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
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
applicationId "code.name.monkey.retromusic"
|
applicationId "code.name.monkey.retromusic"
|
||||||
versionCode 10557
|
versionCode 10563
|
||||||
versionName '5.6.1'
|
versionName '5.7.0'
|
||||||
|
|
||||||
buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"")
|
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')
|
new Date().format('MMddyyyyss')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':appthemehelper')
|
implementation project(':appthemehelper')
|
||||||
implementation "androidx.gridlayout:gridlayout:1.0.0"
|
implementation "androidx.gridlayout:gridlayout:1.0.0"
|
||||||
implementation "androidx.cardview:cardview: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.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.recyclerview:recyclerview:1.3.0-alpha01'
|
||||||
implementation "androidx.preference:preference-ktx:$preference_version"
|
implementation "androidx.preference:preference-ktx:$preference_version"
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
|
@ -103,7 +102,7 @@ dependencies {
|
||||||
|
|
||||||
//Cast Dependencies
|
//Cast Dependencies
|
||||||
implementation 'androidx.mediarouter:mediarouter:1.2.5'
|
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
|
//WebServer by NanoHttpd
|
||||||
implementation "org.nanohttpd:nanohttpd:2.3.1"
|
implementation "org.nanohttpd:nanohttpd:2.3.1"
|
||||||
|
|
||||||
|
@ -111,7 +110,7 @@ dependencies {
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
||||||
implementation "androidx.navigation:navigation-ui-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-runtime:$room_version"
|
||||||
implementation "androidx.room:room-ktx:$room_version"
|
implementation "androidx.room:room-ktx:$room_version"
|
||||||
kapt "androidx.room:room-compiler:$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-core:$kotlin_coroutines_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$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-core:$koin_version"
|
||||||
implementation "io.insert-koin:koin-android:$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 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC3'
|
||||||
implementation 'com.github.jetradarmobile:android-snowfall:1.2.1'
|
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 'org.eclipse.mylyn.github:org.eclipse.egit.github.core:2.1.5'
|
||||||
implementation 'com.github.Adonai:jaudiotagger:2.3.15'
|
implementation 'com.github.Adonai:jaudiotagger:2.3.15'
|
||||||
implementation 'com.anjlab.android.iab.v3:library:2.0.3'
|
implementation 'com.anjlab.android.iab.v3:library:2.0.3'
|
||||||
|
|
|
@ -292,6 +292,18 @@
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/app_widget_md3_info" />
|
android:resource="@xml/app_widget_md3_info" />
|
||||||
</receiver>
|
</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
|
<service
|
||||||
android:name=".service.MusicService"
|
android:name=".service.MusicService"
|
||||||
|
|
|
@ -70,6 +70,8 @@
|
||||||
title="KeyboardVisibilityEvent">KeyboardVisibilityEvent</a></b> by Yasuhiro SHIMIZU</p>
|
title="KeyboardVisibilityEvent">KeyboardVisibilityEvent</a></b> by Yasuhiro SHIMIZU</p>
|
||||||
<p><b><a href="https://github.com/JetradarMobile/android-snowfall"
|
<p><b><a href="https://github.com/JetradarMobile/android-snowfall"
|
||||||
title="android-snowfall">android-snowfall</a></b> by Jetradar Mobile</p>
|
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://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><b><a href="https://www.techjuice.pk" title="City wallpaper"> Material Design City Wallpaper</a></b>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -58,12 +58,41 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
{style-placeholder}
|
{style-placeholder}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<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>
|
<h2>v5.6.1</h2>
|
||||||
<h3>Fixed</h3>
|
<h3>Fixed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -20,6 +20,7 @@ import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
||||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
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.BillingProcessor
|
||||||
import com.anjlab.android.iab.v3.PurchaseInfo
|
import com.anjlab.android.iab.v3.PurchaseInfo
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
|
@ -28,6 +29,7 @@ import org.koin.core.context.startKoin
|
||||||
class App : Application() {
|
class App : Application() {
|
||||||
|
|
||||||
lateinit var billingProcessor: BillingProcessor
|
lateinit var billingProcessor: BillingProcessor
|
||||||
|
private val wallpaperAccentManager = WallpaperAccentManager(this)
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
@ -44,6 +46,7 @@ class App : Application() {
|
||||||
.coloredNavigationBar(true)
|
.coloredNavigationBar(true)
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
|
wallpaperAccentManager.init()
|
||||||
|
|
||||||
if (VersionUtils.hasNougatMR())
|
if (VersionUtils.hasNougatMR())
|
||||||
DynamicShortcutManager(this).initDynamicShortcuts()
|
DynamicShortcutManager(this).initDynamicShortcuts()
|
||||||
|
@ -71,6 +74,7 @@ class App : Application() {
|
||||||
override fun onTerminate() {
|
override fun onTerminate() {
|
||||||
super.onTerminate()
|
super.onTerminate()
|
||||||
billingProcessor.release()
|
billingProcessor.release()
|
||||||
|
wallpaperAccentManager.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -73,7 +73,7 @@ const val NOW_PLAYING_SCREEN_ID = "now_playing_screen_id"
|
||||||
const val CAROUSEL_EFFECT = "carousel_effect"
|
const val CAROUSEL_EFFECT = "carousel_effect"
|
||||||
const val COLORED_NOTIFICATION = "colored_notification"
|
const val COLORED_NOTIFICATION = "colored_notification"
|
||||||
const val CLASSIC_NOTIFICATION = "classic_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 ALBUM_ART_ON_LOCK_SCREEN = "album_art_on_lock_screen"
|
||||||
const val BLURRED_ALBUM_ART = "blurred_album_art"
|
const val BLURRED_ALBUM_ART = "blurred_album_art"
|
||||||
const val NEW_BLUR_AMOUNT = "new_blur_amount"
|
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 WHITELIST_MUSIC = "whitelist_music"
|
||||||
const val MATERIAL_YOU = "material_you"
|
const val MATERIAL_YOU = "material_you"
|
||||||
const val SNOWFALL = "snowfall"
|
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()) {
|
if (!hasPermissions()) {
|
||||||
findNavController(R.id.fragment_container).navigate(R.id.permissionFragment)
|
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)
|
NavigationUtil.gotoWhatNews(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
|
||||||
currentFragment(R.id.fragment_container)?.enterTransition = null
|
currentFragment(R.id.fragment_container)?.enterTransition = null
|
||||||
}
|
}
|
||||||
when (destination.id) {
|
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
|
// Save the last tab
|
||||||
if (PreferenceUtil.rememberLastTab) {
|
if (PreferenceUtil.rememberLastTab) {
|
||||||
saveTab(destination.id)
|
saveTab(destination.id)
|
||||||
|
@ -147,7 +147,7 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
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()
|
postRecreate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,9 @@ import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.LayoutRes
|
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
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.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||||
import code.name.monkey.retromusic.databinding.ActivityDonationBinding
|
import code.name.monkey.retromusic.databinding.ActivityDonationBinding
|
||||||
|
import code.name.monkey.retromusic.databinding.ItemDonationOptionBinding
|
||||||
import code.name.monkey.retromusic.extensions.*
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import com.anjlab.android.iab.v3.BillingProcessor
|
import com.anjlab.android.iab.v3.BillingProcessor
|
||||||
import com.anjlab.android.iab.v3.PurchaseInfo
|
import com.anjlab.android.iab.v3.PurchaseInfo
|
||||||
|
@ -169,8 +167,8 @@ class SkuDetailsAdapter(
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder {
|
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder {
|
||||||
return ViewHolder(
|
return ViewHolder(
|
||||||
LayoutInflater.from(donationsDialog).inflate(
|
ItemDonationOptionBinding.inflate(
|
||||||
LAYOUT_RES_ID,
|
LayoutInflater.from(donationsDialog),
|
||||||
viewGroup,
|
viewGroup,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
@ -179,12 +177,14 @@ class SkuDetailsAdapter(
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
|
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
|
||||||
val skuDetails = skuDetailsList[i]
|
val skuDetails = skuDetailsList[i]
|
||||||
viewHolder.title.text = skuDetails.title.replace("Music Player - MP3 Player - Retro", "")
|
with(viewHolder.binding) {
|
||||||
.trim { it <= ' ' }
|
itemTitle.text = skuDetails.title.replace("Music Player - MP3 Player - Retro", "")
|
||||||
viewHolder.text.text = skuDetails.description
|
.trim { it <= ' ' }
|
||||||
viewHolder.text.isVisible = false
|
itemText.text = skuDetails.description
|
||||||
viewHolder.price.text = skuDetails.priceText
|
itemText.isVisible = false
|
||||||
viewHolder.image.setImageResource(getIcon(i))
|
itemPrice.text = skuDetails.priceText
|
||||||
|
itemImage.setImageResource(getIcon(i))
|
||||||
|
}
|
||||||
|
|
||||||
val purchased = donationsDialog.billingProcessor!!.isPurchased(skuDetails.productId)
|
val purchased = donationsDialog.billingProcessor!!.isPurchased(skuDetails.productId)
|
||||||
val titleTextColor = if (purchased) ATHUtil.resolveColor(
|
val titleTextColor = if (purchased) ATHUtil.resolveColor(
|
||||||
|
@ -194,13 +194,14 @@ class SkuDetailsAdapter(
|
||||||
val contentTextColor =
|
val contentTextColor =
|
||||||
if (purchased) titleTextColor else donationsDialog.textColorSecondary()
|
if (purchased) titleTextColor else donationsDialog.textColorSecondary()
|
||||||
|
|
||||||
viewHolder.title.setTextColor(titleTextColor)
|
with(viewHolder.binding) {
|
||||||
viewHolder.text.setTextColor(contentTextColor)
|
itemTitle.setTextColor(titleTextColor)
|
||||||
viewHolder.price.setTextColor(titleTextColor)
|
itemText.setTextColor(contentTextColor)
|
||||||
|
itemPrice.setTextColor(titleTextColor)
|
||||||
strikeThrough(viewHolder.title, purchased)
|
strikeThrough(itemTitle, purchased)
|
||||||
strikeThrough(viewHolder.text, purchased)
|
strikeThrough(itemText, purchased)
|
||||||
strikeThrough(viewHolder.price, purchased)
|
strikeThrough(itemPrice, purchased)
|
||||||
|
}
|
||||||
|
|
||||||
viewHolder.itemView.setOnTouchListener { _, _ -> purchased }
|
viewHolder.itemView.setOnTouchListener { _, _ -> purchased }
|
||||||
viewHolder.itemView.setOnClickListener { donationsDialog.donate(i) }
|
viewHolder.itemView.setOnClickListener { donationsDialog.donate(i) }
|
||||||
|
@ -210,17 +211,9 @@ class SkuDetailsAdapter(
|
||||||
return skuDetailsList.size
|
return skuDetailsList.size
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
class ViewHolder(val binding: ItemDonationOptionBinding) : RecyclerView.ViewHolder(binding.root)
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@LayoutRes
|
|
||||||
private val LAYOUT_RES_ID = R.layout.item_donation_option
|
|
||||||
|
|
||||||
private fun strikeThrough(textView: TextView, strikeThrough: Boolean) {
|
private fun strikeThrough(textView: TextView, strikeThrough: Boolean) {
|
||||||
textView.paintFlags =
|
textView.paintFlags =
|
||||||
if (strikeThrough) textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
if (strikeThrough) textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
||||||
|
|
|
@ -27,7 +27,6 @@ class WhatsNewActivity : AbsThemeActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val binding = ActivityWhatsNewBinding.inflate(layoutInflater)
|
val binding = ActivityWhatsNewBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setLightStatusBarAuto(surfaceColor())
|
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||||
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
||||||
|
|
|
@ -31,7 +31,7 @@ import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.commit
|
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.R
|
||||||
import code.name.monkey.retromusic.RetroBottomSheetBehavior
|
import code.name.monkey.retromusic.RetroBottomSheetBehavior
|
||||||
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
|
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
|
||||||
|
@ -110,9 +110,15 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
when (newState) {
|
when (newState) {
|
||||||
STATE_EXPANDED -> {
|
STATE_EXPANDED -> {
|
||||||
onPanelExpanded()
|
onPanelExpanded()
|
||||||
|
if (PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) {
|
||||||
|
keepScreenOn(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
STATE_COLLAPSED -> {
|
STATE_COLLAPSED -> {
|
||||||
onPanelCollapsed()
|
onPanelCollapsed()
|
||||||
|
if ((PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) || !PreferenceUtil.isScreenOnEnabled) {
|
||||||
|
keepScreenOn(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
STATE_SETTLING, STATE_DRAGGING -> {
|
STATE_SETTLING, STATE_DRAGGING -> {
|
||||||
if (fromNotification) {
|
if (fromNotification) {
|
||||||
|
@ -140,7 +146,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
insets
|
insets
|
||||||
}
|
}
|
||||||
if (RetroUtil.isLandscape()) {
|
if (RetroUtil.isLandscape()) {
|
||||||
binding.slidingPanel.drawAboveSystemBarsWithPadding(true)
|
binding.slidingPanel.drawAboveSystemBarsWithPadding()
|
||||||
}
|
}
|
||||||
chooseFragmentForTheme()
|
chooseFragmentForTheme()
|
||||||
setupSlidingUpPanel()
|
setupSlidingUpPanel()
|
||||||
|
@ -199,6 +205,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun animateNavigationBarColor(color: Int) {
|
private fun animateNavigationBarColor(color: Int) {
|
||||||
|
if (VersionUtils.hasOreo()) return
|
||||||
navigationBarColorAnimator?.cancel()
|
navigationBarColorAnimator?.cancel()
|
||||||
navigationBarColorAnimator = ValueAnimator
|
navigationBarColorAnimator = ValueAnimator
|
||||||
.ofArgb(window.navigationBarColor, color).apply {
|
.ofArgb(window.navigationBarColor, color).apply {
|
||||||
|
@ -217,14 +224,16 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
setMiniPlayerAlphaProgress(0F)
|
setMiniPlayerAlphaProgress(0F)
|
||||||
// restore values
|
// restore values
|
||||||
animateNavigationBarColor(surfaceColor())
|
animateNavigationBarColor(surfaceColor())
|
||||||
setLightStatusBarAuto(surfaceColor())
|
setLightStatusBarAuto()
|
||||||
setLightNavigationAuto()
|
setLightNavigationBarAuto()
|
||||||
setTaskDescriptionColor(taskColor)
|
setTaskDescriptionColor(taskColor)
|
||||||
|
playerFragment?.onHide()
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun onPanelExpanded() {
|
open fun onPanelExpanded() {
|
||||||
setMiniPlayerAlphaProgress(1F)
|
setMiniPlayerAlphaProgress(1F)
|
||||||
onPaletteColorChanged()
|
onPaletteColorChanged()
|
||||||
|
playerFragment?.onShow()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupSlidingUpPanel() {
|
private fun setupSlidingUpPanel() {
|
||||||
|
@ -291,7 +300,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
if (panelState == STATE_EXPANDED) {
|
if (panelState == STATE_EXPANDED) {
|
||||||
navigationBarColor = surfaceColor()
|
navigationBarColor = surfaceColor()
|
||||||
setTaskDescColor(paletteColor)
|
setTaskDescColor(paletteColor)
|
||||||
val isColorLight = ColorUtil.isColorLight(paletteColor)
|
val isColorLight = paletteColor.isColorLight
|
||||||
if (PreferenceUtil.isAdaptiveColor && (nowPlayingScreen == Normal || nowPlayingScreen == Flat)) {
|
if (PreferenceUtil.isAdaptiveColor && (nowPlayingScreen == Normal || nowPlayingScreen == Flat)) {
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
setLightStatusBar(isColorLight)
|
setLightStatusBar(isColorLight)
|
||||||
|
@ -314,13 +323,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
setLightStatusBar(false)
|
setLightStatusBar(false)
|
||||||
} else if (nowPlayingScreen == Fit) {
|
} else if (nowPlayingScreen == Fit) {
|
||||||
setLightStatusBar(false)
|
setLightStatusBar(false)
|
||||||
} else {
|
|
||||||
setLightStatusBar(
|
|
||||||
ColorUtil.isColorLight(
|
|
||||||
surfaceColor()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
setLightNavigationBar(true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,12 +403,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets()
|
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets()
|
||||||
bottomSheetBehavior.state = STATE_COLLAPSED
|
bottomSheetBehavior.state = STATE_COLLAPSED
|
||||||
libraryViewModel.setFabMargin(if (isBottomNavVisible) dip(R.dimen.bottom_nav_height) else 0)
|
libraryViewModel.setFabMargin(if (isBottomNavVisible) dip(R.dimen.bottom_nav_height) else 0)
|
||||||
binding.slidingPanel.elevation = 0F
|
|
||||||
binding.bottomNavigationView.elevation = 10F
|
|
||||||
} else {
|
} else {
|
||||||
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||||
binding.slidingPanel.elevation = 0F
|
binding.slidingPanel.elevation = 0F
|
||||||
binding.bottomNavigationView.elevation = 10F
|
binding.bottomNavigationView.elevation = 5F
|
||||||
if (isBottomNavVisible) {
|
if (isBottomNavVisible) {
|
||||||
println("List")
|
println("List")
|
||||||
if (animate) {
|
if (animate) {
|
||||||
|
|
|
@ -23,11 +23,12 @@ import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
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.LanguageContextWrapper
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.extensions.*
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.theme.ThemeManager
|
import code.name.monkey.retromusic.util.theme.ThemeManager
|
||||||
import com.google.android.material.color.DynamicColors
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
|
@ -35,27 +36,28 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
private val handler = Handler()
|
private val handler = Handler()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
setDrawBehindSystemBars()
|
|
||||||
updateTheme()
|
updateTheme()
|
||||||
hideStatusBar()
|
hideStatusBar()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setImmersiveFullscreen()
|
setEdgeToEdgeOrImmersive()
|
||||||
registerSystemUiVisibility()
|
registerSystemUiVisibility()
|
||||||
toggleScreenOn()
|
toggleScreenOn()
|
||||||
setLightNavigationAuto()
|
setLightNavigationBarAuto()
|
||||||
setLightStatusBarAuto(surfaceColor())
|
setLightStatusBarAuto(surfaceColor())
|
||||||
|
if (VersionUtils.hasQ()) {
|
||||||
|
window.decorView.isForceDarkAllowed = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTheme() {
|
private fun updateTheme() {
|
||||||
setTheme(ThemeManager.getThemeResValue(this))
|
setTheme(ThemeManager.getThemeResValue())
|
||||||
setDefaultNightMode(ThemeManager.getNightMode(this))
|
setDefaultNightMode(ThemeManager.getNightMode())
|
||||||
|
|
||||||
// Apply dynamic colors to activity if enabled
|
if (PreferenceUtil.isCustomFont) {
|
||||||
if (PreferenceUtil.materialYou) {
|
setTheme(R.style.FontThemeOverlay)
|
||||||
DynamicColors.applyIfAvailable(
|
}
|
||||||
this,
|
if (PreferenceUtil.circlePlayButton) {
|
||||||
com.google.android.material.R.style.ThemeOverlay_Material3_DynamicColors_DayNight
|
setTheme(R.style.CircleFABOverlay)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.adapter
|
package code.name.monkey.retromusic.adapter
|
||||||
|
|
||||||
import android.os.SystemClock
|
import android.annotation.SuppressLint
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
@ -29,31 +28,22 @@ import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
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.*
|
||||||
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
|
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
|
||||||
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
|
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
|
||||||
import code.name.monkey.retromusic.adapter.song.SongAdapter
|
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.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.IAlbumClickListener
|
||||||
import code.name.monkey.retromusic.interfaces.IArtistClickListener
|
import code.name.monkey.retromusic.interfaces.IArtistClickListener
|
||||||
import code.name.monkey.retromusic.interfaces.IGenreClickListener
|
import code.name.monkey.retromusic.interfaces.IGenreClickListener
|
||||||
import code.name.monkey.retromusic.model.*
|
import code.name.monkey.retromusic.model.*
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import com.google.android.material.card.MaterialCardView
|
|
||||||
|
|
||||||
class HomeAdapter(
|
class HomeAdapter(
|
||||||
private val activity: AppCompatActivity
|
private val activity: AppCompatActivity
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IArtistClickListener, IAlbumClickListener,
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IArtistClickListener, IAlbumClickListener,
|
||||||
IGenreClickListener {
|
IGenreClickListener {
|
||||||
|
|
||||||
private var mLastClickTime: Long = 0
|
|
||||||
|
|
||||||
private var list = listOf<Home>()
|
private var list = listOf<Home>()
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
@ -65,17 +55,10 @@ class HomeAdapter(
|
||||||
LayoutInflater.from(activity).inflate(R.layout.section_recycler_view, parent, false)
|
LayoutInflater.from(activity).inflate(R.layout.section_recycler_view, parent, false)
|
||||||
return when (viewType) {
|
return when (viewType) {
|
||||||
RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(layout)
|
RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(layout)
|
||||||
GENRES -> GenreViewHolder(layout)
|
|
||||||
FAVOURITES -> PlaylistViewHolder(layout)
|
FAVOURITES -> PlaylistViewHolder(layout)
|
||||||
TOP_ALBUMS, RECENT_ALBUMS -> AlbumViewHolder(layout)
|
TOP_ALBUMS, RECENT_ALBUMS -> AlbumViewHolder(layout)
|
||||||
else -> {
|
else -> {
|
||||||
SuggestionsViewHolder(
|
ArtistViewHolder(layout)
|
||||||
LayoutInflater.from(activity).inflate(
|
|
||||||
R.layout.item_suggestions,
|
|
||||||
parent,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,10 +110,6 @@ class HomeAdapter(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SUGGESTIONS -> {
|
|
||||||
val viewHolder = holder as SuggestionsViewHolder
|
|
||||||
viewHolder.bindView(home)
|
|
||||||
}
|
|
||||||
FAVOURITES -> {
|
FAVOURITES -> {
|
||||||
val viewHolder = holder as PlaylistViewHolder
|
val viewHolder = holder as PlaylistViewHolder
|
||||||
viewHolder.bindView(home)
|
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
|
return list.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun swapData(sections: List<Home>) {
|
fun swapData(sections: List<Home>) {
|
||||||
list = sections
|
list = sections
|
||||||
notifyDataSetChanged()
|
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) {
|
private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) {
|
||||||
fun bindView(home: Home) {
|
fun bindView(home: Home) {
|
||||||
title.setText(home.titleRes)
|
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) {
|
open class AbsHomeViewItem(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
val recyclerView: RecyclerView = itemView.findViewById(R.id.recyclerView)
|
val recyclerView: RecyclerView = itemView.findViewById(R.id.recyclerView)
|
||||||
val title: AppCompatTextView = itemView.findViewById(R.id.title)
|
val title: AppCompatTextView = itemView.findViewById(R.id.title)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.adapter
|
package code.name.monkey.retromusic.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -45,6 +46,7 @@ class SearchAdapter(
|
||||||
private var dataSet: List<Any>
|
private var dataSet: List<Any>
|
||||||
) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() {
|
) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun swapDataSet(dataSet: List<Any>) {
|
fun swapDataSet(dataSet: List<Any>) {
|
||||||
this.dataSet = dataSet
|
this.dataSet = dataSet
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
|
@ -148,13 +150,13 @@ class SearchAdapter(
|
||||||
imageTextContainer?.isInvisible = true
|
imageTextContainer?.isInvisible = true
|
||||||
if (itemViewType == SONG) {
|
if (itemViewType == SONG) {
|
||||||
imageTextContainer?.isGone = true
|
imageTextContainer?.isGone = true
|
||||||
menu?.visibility = View.VISIBLE
|
menu?.isVisible = true
|
||||||
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
|
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
|
||||||
override val song: Song
|
override val song: Song
|
||||||
get() = dataSet[layoutPosition] as Song
|
get() = dataSet[layoutPosition] as Song
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
menu?.visibility = View.GONE
|
menu?.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
when (itemViewType) {
|
when (itemViewType) {
|
||||||
|
@ -162,7 +164,7 @@ class SearchAdapter(
|
||||||
ARTIST -> setImageTransitionName(activity.getString(R.string.transition_artist_image))
|
ARTIST -> setImageTransitionName(activity.getString(R.string.transition_artist_image))
|
||||||
else -> {
|
else -> {
|
||||||
val container = itemView.findViewById<View>(R.id.imageContainer)
|
val container = itemView.findViewById<View>(R.id.imageContainer)
|
||||||
container?.visibility = View.GONE
|
container?.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,9 +203,8 @@ class SearchAdapter(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SONG -> {
|
SONG -> {
|
||||||
val playList = mutableListOf<Song>()
|
MusicPlayerRemote.playNext(item as Song)
|
||||||
playList.add(item as Song)
|
MusicPlayerRemote.playNextSong()
|
||||||
MusicPlayerRemote.openQueue(playList, 0, true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
||||||
|
@ -78,7 +79,7 @@ class SongFileAdapter(
|
||||||
if (holder.itemViewType == FILE) {
|
if (holder.itemViewType == FILE) {
|
||||||
holder.text?.text = getFileText(file)
|
holder.text?.text = getFileText(file)
|
||||||
} else {
|
} 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.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
||||||
|
@ -174,7 +175,7 @@ open class AlbumAdapter(
|
||||||
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
menu?.visibility = View.GONE
|
menu?.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View?) {
|
override fun onClick(v: View?) {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.adapter.artist
|
package code.name.monkey.retromusic.adapter.artist
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -21,6 +22,7 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
|
||||||
|
@ -52,13 +54,17 @@ class ArtistAdapter(
|
||||||
activity, ICabHolder, R.menu.menu_media_selection
|
activity, ICabHolder, R.menu.menu_media_selection
|
||||||
), PopupTextProvider {
|
), PopupTextProvider {
|
||||||
|
|
||||||
|
var albumArtistsOnly = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.setHasStableIds(true)
|
this.setHasStableIds(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun swapDataSet(dataSet: List<Artist>) {
|
fun swapDataSet(dataSet: List<Artist>) {
|
||||||
this.dataSet = dataSet
|
this.dataSet = dataSet
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
|
albumArtistsOnly = PreferenceUtil.albumArtistsOnly
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemId(position: Int): Long {
|
override fun getItemId(position: Int): Long {
|
||||||
|
@ -86,7 +92,7 @@ class ArtistAdapter(
|
||||||
holder.title?.text = artist.name
|
holder.title?.text = artist.name
|
||||||
holder.text?.hide()
|
holder.text?.hide()
|
||||||
val transitionName =
|
val transitionName =
|
||||||
if (PreferenceUtil.albumArtistsOnly) artist.name else artist.id.toString()
|
if (albumArtistsOnly) artist.name else artist.id.toString()
|
||||||
if (holder.imageContainer != null) {
|
if (holder.imageContainer != null) {
|
||||||
ViewCompat.setTransitionName(holder.imageContainer!!, transitionName)
|
ViewCompat.setTransitionName(holder.imageContainer!!, transitionName)
|
||||||
} else {
|
} else {
|
||||||
|
@ -158,7 +164,7 @@ class ArtistAdapter(
|
||||||
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
menu?.visibility = View.GONE
|
menu?.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View?) {
|
override fun onClick(v: View?) {
|
||||||
|
@ -168,7 +174,7 @@ class ArtistAdapter(
|
||||||
} else {
|
} else {
|
||||||
val artist = dataSet[layoutPosition]
|
val artist = dataSet[layoutPosition]
|
||||||
image?.let {
|
image?.let {
|
||||||
if (PreferenceUtil.albumArtistsOnly && IAlbumArtistClickListener != null) {
|
if (albumArtistsOnly && IAlbumArtistClickListener != null) {
|
||||||
IAlbumArtistClickListener.onAlbumArtist(artist.name, imageContainer ?: it)
|
IAlbumArtistClickListener.onAlbumArtist(artist.name, imageContainer ?: it)
|
||||||
} else {
|
} else {
|
||||||
IArtistClickListener.onArtist(artist.id, imageContainer ?: it)
|
IArtistClickListener.onArtist(artist.id, imageContainer ?: it)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.view.MenuItem
|
||||||
import androidx.annotation.MenuRes
|
import androidx.annotation.MenuRes
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||||
import code.name.monkey.retromusic.interfaces.ICabCallback
|
import code.name.monkey.retromusic.interfaces.ICabCallback
|
||||||
|
@ -31,7 +32,10 @@ abstract class AbsMultiSelectAdapter<V : RecyclerView.ViewHolder?, I>(
|
||||||
|
|
||||||
override fun onCabFinished(cab: AttachedCab): Boolean {
|
override fun onCabFinished(cab: AttachedCab): Boolean {
|
||||||
clearChecked()
|
clearChecked()
|
||||||
activity.window.statusBarColor = Color.TRANSPARENT
|
activity.window.statusBarColor = when {
|
||||||
|
VersionUtils.hasMarshmallow() -> Color.TRANSPARENT
|
||||||
|
else -> Color.BLACK
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.adapter.song
|
||||||
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
|
@ -129,7 +130,7 @@ class OrderablePlaylistSongAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
dragView?.visibility = View.VISIBLE
|
dragView?.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View?) {
|
override fun onClick(v: View?) {
|
||||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.adapter.song
|
||||||
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.glide.GlideApp
|
import code.name.monkey.retromusic.glide.GlideApp
|
||||||
|
@ -154,7 +155,7 @@ class PlayingQueueAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
dragView?.visibility = View.VISIBLE
|
dragView?.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSongMenuItemClick(item: MenuItem): Boolean {
|
override fun onSongMenuItemClick(item: MenuItem): Boolean {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package code.name.monkey.retromusic.adapter.song
|
package code.name.monkey.retromusic.adapter.song
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
|
@ -61,7 +62,7 @@ class ShuffleButtonSongAdapter(
|
||||||
super.onBindViewHolder(holder, position - 1)
|
super.onBindViewHolder(holder, position - 1)
|
||||||
val landscape = RetroUtil.isLandscape()
|
val landscape = RetroUtil.isLandscape()
|
||||||
if ((PreferenceUtil.songGridSize > 2 && !landscape) || (PreferenceUtil.songGridSizeLand > 5 && landscape)) {
|
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.title?.setTextColor(color.primaryTextColor)
|
||||||
holder.text?.setTextColor(color.secondaryTextColor)
|
holder.text?.setTextColor(color.secondaryTextColor)
|
||||||
holder.paletteColorContainer?.setBackgroundColor(color.backgroundColor)
|
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)
|
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 image = getAlbumArtDrawable(service.resources, bitmap)
|
||||||
val roundedBitmap = createRoundedBitmap(
|
val roundedBitmap = createRoundedBitmap(
|
||||||
image, imageSize, imageSize, cardRadius, cardRadius, cardRadius, cardRadius
|
image,
|
||||||
|
imageSize,
|
||||||
|
imageSize,
|
||||||
|
cardRadius,
|
||||||
|
cardRadius,
|
||||||
|
cardRadius,
|
||||||
|
cardRadius
|
||||||
)
|
)
|
||||||
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ abstract class BaseAppWidget : AppWidgetProvider() {
|
||||||
*/
|
*/
|
||||||
fun notifyChange(service: MusicService, what: String) {
|
fun notifyChange(service: MusicService, what: String) {
|
||||||
if (hasInstances(service)) {
|
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)
|
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
|
package code.name.monkey.retromusic.dialogs
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.AlarmManager
|
import android.app.AlarmManager
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
|
@ -23,7 +22,6 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.widget.CheckBox
|
import android.widget.CheckBox
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -31,6 +29,7 @@ import android.widget.Toast
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.R
|
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.addAccentColor
|
||||||
import code.name.monkey.retromusic.extensions.colorButtons
|
import code.name.monkey.retromusic.extensions.colorButtons
|
||||||
import code.name.monkey.retromusic.extensions.materialDialog
|
import code.name.monkey.retromusic.extensions.materialDialog
|
||||||
|
@ -49,31 +48,27 @@ class SleepTimerDialog : DialogFragment() {
|
||||||
private lateinit var timerUpdater: TimerUpdater
|
private lateinit var timerUpdater: TimerUpdater
|
||||||
private lateinit var dialog: MaterialDialog
|
private lateinit var dialog: MaterialDialog
|
||||||
private lateinit var shouldFinishLastSong: CheckBox
|
private lateinit var shouldFinishLastSong: CheckBox
|
||||||
private lateinit var seekBar: SeekBar
|
|
||||||
private lateinit var timerDisplay: TextView
|
private lateinit var timerDisplay: TextView
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
timerUpdater = TimerUpdater()
|
timerUpdater = TimerUpdater()
|
||||||
val layout =
|
val binding = DialogSleepTimerBinding.inflate(layoutInflater)
|
||||||
LayoutInflater.from(requireContext()).inflate(R.layout.dialog_sleep_timer, null)
|
shouldFinishLastSong = binding.shouldFinishLastSong
|
||||||
shouldFinishLastSong = layout.findViewById(R.id.shouldFinishLastSong)
|
timerDisplay = binding.timerDisplay
|
||||||
seekBar = layout.findViewById(R.id.seekBar)
|
|
||||||
timerDisplay = layout.findViewById(R.id.timerDisplay)
|
|
||||||
|
|
||||||
val finishMusic = PreferenceUtil.isSleepTimerFinishMusic
|
val finishMusic = PreferenceUtil.isSleepTimerFinishMusic
|
||||||
shouldFinishLastSong.apply {
|
shouldFinishLastSong.apply {
|
||||||
addAccentColor()
|
addAccentColor()
|
||||||
isChecked = finishMusic
|
isChecked = finishMusic
|
||||||
}
|
}
|
||||||
seekBar.apply {
|
binding.seekBar.apply {
|
||||||
addAccentColor()
|
addAccentColor()
|
||||||
seekArcProgress = PreferenceUtil.lastSleepTimerValue
|
seekArcProgress = PreferenceUtil.lastSleepTimerValue
|
||||||
updateTimeDisplayTime()
|
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) {
|
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
|
||||||
if (i < 1) {
|
if (i < 1) {
|
||||||
seekBar.progress = 1
|
seekBar.progress = 1
|
||||||
|
@ -91,7 +86,7 @@ class SleepTimerDialog : DialogFragment() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return materialDialog(R.string.action_sleep_timer)
|
return materialDialog(R.string.action_sleep_timer)
|
||||||
.setView(layout)
|
.setView(binding.root)
|
||||||
.setPositiveButton(R.string.action_set) { _, _ ->
|
.setPositiveButton(R.string.action_set) { _, _ ->
|
||||||
PreferenceUtil.isSleepTimerFinishMusic = shouldFinishLastSong.isChecked
|
PreferenceUtil.isSleepTimerFinishMusic = shouldFinishLastSong.isChecked
|
||||||
val minutes = seekArcProgress
|
val minutes = seekArcProgress
|
||||||
|
@ -170,7 +165,6 @@ class SleepTimerDialog : DialogFragment() {
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun onTick(millisUntilFinished: Long) {
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
seekBar.progress = millisUntilFinished.toInt()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFinish() {
|
override fun onFinish() {
|
||||||
|
|
|
@ -4,14 +4,11 @@ import android.app.ActivityManager
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.*
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import code.name.monkey.appthemehelper.ATH
|
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.R
|
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() {
|
fun AppCompatActivity.setImmersiveFullscreen() {
|
||||||
if (PreferenceUtil.isFullScreenMode) {
|
if (PreferenceUtil.isFullScreenMode) {
|
||||||
WindowInsetsControllerCompat(window, window.decorView).apply {
|
WindowInsetsControllerCompat(window, window.decorView).apply {
|
||||||
|
@ -36,6 +49,14 @@ fun AppCompatActivity.setImmersiveFullscreen() {
|
||||||
window.attributes.layoutInDisplayCutoutMode =
|
window.attributes.layoutInDisplayCutoutMode =
|
||||||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
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() {
|
fun AppCompatActivity.setDrawBehindSystemBars() {
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
||||||
if (VersionUtils.hasOreo()) {
|
if (VersionUtils.hasOreo()) {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
window.navigationBarColor = Color.TRANSPARENT
|
||||||
|
window.statusBarColor = Color.TRANSPARENT
|
||||||
if (VersionUtils.hasQ()) {
|
if (VersionUtils.hasQ()) {
|
||||||
window.isNavigationBarContrastEnforced = false
|
window.isNavigationBarContrastEnforced = false
|
||||||
}
|
}
|
||||||
window.navigationBarColor = Color.TRANSPARENT
|
|
||||||
window.statusBarColor = Color.TRANSPARENT
|
|
||||||
} else {
|
} else {
|
||||||
setNavigationBarColorPreOreo(surfaceColor())
|
setNavigationBarColorPreOreo(surfaceColor())
|
||||||
if (VersionUtils.hasMarshmallow()) {
|
if (VersionUtils.hasMarshmallow()) {
|
||||||
setStatusBarColor(Color.TRANSPARENT)
|
setStatusBarColor(Color.TRANSPARENT)
|
||||||
} else {
|
} else {
|
||||||
setStatusBarColor(surfaceColor())
|
setStatusBarColor(Color.BLACK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,24 +117,49 @@ fun AppCompatActivity.setTaskDescriptionColorAuto() {
|
||||||
setTaskDescriptionColor(surfaceColor())
|
setTaskDescriptionColor(surfaceColor())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AppCompatActivity.setLightNavigationAuto() {
|
@Suppress("Deprecation")
|
||||||
ATH.setLightNavigationBarAuto(this, surfaceColor())
|
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) {
|
fun AppCompatActivity.setLightStatusBarAuto() {
|
||||||
ATH.setLightStatusBar(this, enabled)
|
setLightStatusBar(surfaceColor().isColorLight)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AppCompatActivity.setLightStatusBarAuto(bgColor: Int) {
|
fun AppCompatActivity.setLightStatusBarAuto(bgColor: Int) {
|
||||||
setLightStatusBar(ColorUtil.isColorLight(bgColor))
|
setLightStatusBar(bgColor.isColorLight)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("Deprecation")
|
||||||
fun AppCompatActivity.setLightNavigationBar(enabled: Boolean) {
|
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) {
|
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.ExtendedFloatingActionButton
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.android.material.progressindicator.CircularProgressIndicator
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
import com.google.android.material.slider.Slider
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
|
||||||
fun Int.ripAlpha(): Int {
|
fun Int.ripAlpha(): Int {
|
||||||
|
@ -112,6 +113,22 @@ fun SeekBar.addAccentColor() {
|
||||||
thumbTintList = colorState
|
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() {
|
fun Button.accentTextColor() {
|
||||||
if (materialYou) return
|
if (materialYou) return
|
||||||
setTextColor(ThemeStore.accentColor(App.getContext()))
|
setTextColor(ThemeStore.accentColor(App.getContext()))
|
||||||
|
@ -248,15 +265,10 @@ fun Context.getColorCompat(@ColorRes colorRes: Int): Int {
|
||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
fun Context.darkAccentColor(): Int {
|
fun Context.darkAccentColor(): Int {
|
||||||
val colorSurfaceVariant = if (surfaceColor().isColorLight) {
|
|
||||||
surfaceColor()
|
|
||||||
} else {
|
|
||||||
surfaceColor().lighterColor
|
|
||||||
}
|
|
||||||
return ColorUtils.blendARGB(
|
return ColorUtils.blendARGB(
|
||||||
accentColor(),
|
accentColor(),
|
||||||
colorSurfaceVariant,
|
surfaceColor(),
|
||||||
if (surfaceColor().isColorLight) 0.96f else 0.975f
|
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
|
inline val @receiver:ColorInt Int.isColorLight
|
||||||
get() = ColorUtil.isColorLight(this)
|
get() = ColorUtil.isColorLight(this)
|
||||||
|
|
||||||
|
@ -276,4 +297,7 @@ inline val @receiver:ColorInt Int.lighterColor
|
||||||
get() = ColorUtil.lightenColor(this)
|
get() = ColorUtil.lightenColor(this)
|
||||||
|
|
||||||
inline val @receiver:ColorInt Int.darkerColor
|
inline val @receiver:ColorInt Int.darkerColor
|
||||||
get() = ColorUtil.darkenColor(this)
|
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.appcompat.app.AlertDialog
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
|
||||||
fun DialogFragment.materialDialog(title: Int): MaterialAlertDialogBuilder {
|
fun DialogFragment.materialDialog(title: Int): MaterialAlertDialogBuilder {
|
||||||
|
|
|
@ -21,9 +21,9 @@ fun Fragment.createNewFile(
|
||||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult())
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult())
|
||||||
{ result: ActivityResult ->
|
{ result: ActivityResult ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
val outputStream: OutputStream? =
|
context?.contentResolver?.openOutputStream(result.data?.data!!)?.use { os->
|
||||||
context?.contentResolver?.openOutputStream(result.data?.data!!)
|
write(os, result.data?.data)
|
||||||
write(outputStream, 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.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.MarginLayoutParams
|
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import androidx.annotation.LayoutRes
|
import androidx.annotation.LayoutRes
|
||||||
|
import androidx.annotation.Px
|
||||||
import androidx.core.animation.doOnEnd
|
import androidx.core.animation.doOnEnd
|
||||||
import androidx.core.animation.doOnStart
|
import androidx.core.animation.doOnStart
|
||||||
import androidx.core.view.*
|
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.appthemehelper.util.TintHelper
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
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.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import com.google.android.material.shape.ShapeAppearanceModel
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T {
|
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() {
|
fun View.show() {
|
||||||
visibility = View.VISIBLE
|
isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun View.hide() {
|
fun View.hide() {
|
||||||
visibility = View.GONE
|
isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun View.hidden() {
|
fun View.hidden() {
|
||||||
visibility = View.INVISIBLE
|
isInvisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun View.showOrHide(show: Boolean) = if (show) show() else hide()
|
|
||||||
|
|
||||||
fun EditText.appHandleColor(): EditText {
|
fun EditText.appHandleColor(): EditText {
|
||||||
if (PreferenceUtil.materialYou) return this
|
if (PreferenceUtil.materialYou) return this
|
||||||
TintHelper.colorHandles(this, ThemeStore.accentColor(context))
|
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.
|
* This will draw our view above the navigation bar instead of behind it by adding margins.
|
||||||
*/
|
*/
|
||||||
fun View.drawAboveSystemBars(onlyPortrait: Boolean = true) {
|
fun View.drawAboveSystemBars(onlyPortrait: Boolean = true) {
|
||||||
if (PreferenceUtil.isFullScreenMode) return
|
if (PreferenceUtil.isFullScreenMode) return
|
||||||
if (onlyPortrait && RetroUtil.isLandscape()) return
|
if (onlyPortrait && RetroUtil.isLandscape()) return
|
||||||
// Create a snapshot of the view's margin state
|
applyInsetter {
|
||||||
val initialMargin = recordInitialMarginForView(this)
|
type(navigationBars = true) {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
margin()
|
||||||
(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
|
|
||||||
}
|
}
|
||||||
windowInsets
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will draw our view above the navigation bar instead of behind it by adding padding.
|
* 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
|
if (PreferenceUtil.isFullScreenMode) return
|
||||||
val initialPadding = recordInitialPaddingForView(this)
|
val initialPadding = recordInitialPaddingForView(this)
|
||||||
|
|
||||||
|
@ -168,11 +173,9 @@ fun View.drawAboveSystemBarsWithPadding(consume: Boolean = false) {
|
||||||
) { v: View, windowInsets: WindowInsetsCompat ->
|
) { v: View, windowInsets: WindowInsetsCompat ->
|
||||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
v.updatePadding(
|
v.updatePadding(
|
||||||
left = initialPadding.left + insets.left,
|
bottom = initialPadding.bottom + insets.bottom
|
||||||
bottom = initialPadding.bottom + insets.bottom,
|
|
||||||
right = initialPadding.right + insets.right
|
|
||||||
)
|
)
|
||||||
if (consume) WindowInsetsCompat.CONSUMED else windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
requestApplyInsetsWhenAttached()
|
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(
|
data class InitialPadding(
|
||||||
val left: Int, val top: Int,
|
val left: Int, val top: Int,
|
||||||
val right: Int, val bottom: Int
|
val right: Int, val bottom: Int
|
||||||
|
@ -243,4 +205,4 @@ data class InitialPadding(
|
||||||
|
|
||||||
fun recordInitialPaddingForView(view: View) = InitialPadding(
|
fun recordInitialPaddingForView(view: View) = InitialPadding(
|
||||||
view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom
|
view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom
|
||||||
)
|
)
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.fragments
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.core.animation.doOnEnd
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import code.name.monkey.retromusic.*
|
import code.name.monkey.retromusic.*
|
||||||
import code.name.monkey.retromusic.db.*
|
import code.name.monkey.retromusic.db.*
|
||||||
|
@ -39,6 +40,7 @@ class LibraryViewModel(
|
||||||
|
|
||||||
private val _paletteColor = MutableLiveData<Int>()
|
private val _paletteColor = MutableLiveData<Int>()
|
||||||
private val home = MutableLiveData<List<Home>>()
|
private val home = MutableLiveData<List<Home>>()
|
||||||
|
private val suggestions = MutableLiveData<List<Song>>()
|
||||||
private val albums = MutableLiveData<List<Album>>()
|
private val albums = MutableLiveData<List<Album>>()
|
||||||
private val songs = MutableLiveData<List<Song>>()
|
private val songs = MutableLiveData<List<Song>>()
|
||||||
private val artists = MutableLiveData<List<Artist>>()
|
private val artists = MutableLiveData<List<Artist>>()
|
||||||
|
@ -55,6 +57,7 @@ class LibraryViewModel(
|
||||||
|
|
||||||
private fun loadLibraryContent() = viewModelScope.launch(IO) {
|
private fun loadLibraryContent() = viewModelScope.launch(IO) {
|
||||||
fetchHomeSections()
|
fetchHomeSections()
|
||||||
|
fetchSuggestions()
|
||||||
fetchSongs()
|
fetchSongs()
|
||||||
fetchAlbums()
|
fetchAlbums()
|
||||||
fetchArtists()
|
fetchArtists()
|
||||||
|
@ -92,38 +95,33 @@ class LibraryViewModel(
|
||||||
return home
|
return home
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSuggestions(): LiveData<List<Song>> {
|
||||||
|
return suggestions
|
||||||
|
}
|
||||||
|
|
||||||
fun getFabMargin(): LiveData<Int> {
|
fun getFabMargin(): LiveData<Int> {
|
||||||
return fabMargin
|
return fabMargin
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchSongs() {
|
private suspend fun fetchSongs() {
|
||||||
viewModelScope.launch(IO) {
|
songs.postValue(repository.allSongs())
|
||||||
songs.postValue(repository.allSongs())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchAlbums() {
|
private suspend fun fetchAlbums() {
|
||||||
viewModelScope.launch(IO) {
|
albums.postValue(repository.fetchAlbums())
|
||||||
albums.postValue(repository.fetchAlbums())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchArtists() {
|
private suspend fun fetchArtists() {
|
||||||
if (PreferenceUtil.albumArtistsOnly) {
|
if (PreferenceUtil.albumArtistsOnly) {
|
||||||
viewModelScope.launch(IO) {
|
artists.postValue(repository.albumArtists())
|
||||||
artists.postValue(repository.albumArtists())
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
viewModelScope.launch(IO) {
|
artists.postValue(repository.fetchArtists())
|
||||||
artists.postValue(repository.fetchArtists())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchPlaylists() {
|
private suspend fun fetchPlaylists() {
|
||||||
viewModelScope.launch(IO) {
|
playlists.postValue(repository.fetchPlaylistWithSongs())
|
||||||
playlists.postValue(repository.fetchPlaylistWithSongs())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchLegacyPlaylist() {
|
private fun fetchLegacyPlaylist() {
|
||||||
|
@ -132,16 +130,16 @@ class LibraryViewModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchGenres() {
|
private suspend fun fetchGenres() {
|
||||||
viewModelScope.launch(IO) {
|
genres.postValue(repository.fetchGenres())
|
||||||
genres.postValue(repository.fetchGenres())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fetchHomeSections() {
|
private suspend fun fetchHomeSections() {
|
||||||
viewModelScope.launch(IO) {
|
home.postValue(repository.homeSections())
|
||||||
home.postValue(repository.homeSections())
|
}
|
||||||
}
|
|
||||||
|
private suspend fun fetchSuggestions() {
|
||||||
|
suggestions.postValue(repository.suggestions())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(query: String?, filter: Filter) {
|
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) {
|
when (reloadType) {
|
||||||
Songs -> fetchSongs()
|
Songs -> fetchSongs()
|
||||||
Albums -> fetchAlbums()
|
Albums -> fetchAlbums()
|
||||||
|
@ -159,6 +157,7 @@ class LibraryViewModel(
|
||||||
HomeSections -> fetchHomeSections()
|
HomeSections -> fetchHomeSections()
|
||||||
Playlists -> fetchPlaylists()
|
Playlists -> fetchPlaylists()
|
||||||
Genres -> fetchGenres()
|
Genres -> fetchGenres()
|
||||||
|
Suggestions -> fetchSuggestions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +254,7 @@ class LibraryViewModel(
|
||||||
}
|
}
|
||||||
repository.insertSongs(songEntities)
|
repository.insertSongs(songEntities)
|
||||||
} else {
|
} else {
|
||||||
if (playlist != Playlist.empty){
|
if (playlist != Playlist.empty) {
|
||||||
val playListId = createPlaylist(PlaylistEntity(playlistName = playlist.name))
|
val playListId = createPlaylist(PlaylistEntity(playlistName = playlist.name))
|
||||||
val songEntities = playlist.getSongs().map {
|
val songEntities = playlist.getSongs().map {
|
||||||
it.toSongEntity(playListId)
|
it.toSongEntity(playListId)
|
||||||
|
@ -367,7 +366,7 @@ class LibraryViewModel(
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
if (songs.isNotEmpty()) {
|
if (songs.isNotEmpty()) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
App.getContext(),
|
App.getContext(),
|
||||||
"Adding songs to $playlistName",
|
"Adding songs to $playlistName",
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
|
@ -382,15 +381,16 @@ class LibraryViewModel(
|
||||||
fun setFabMargin(bottomMargin: Int) {
|
fun setFabMargin(bottomMargin: Int) {
|
||||||
val currentValue = DensityUtil.dip2px(App.getContext(), 16F) +
|
val currentValue = DensityUtil.dip2px(App.getContext(), 16F) +
|
||||||
bottomMargin
|
bottomMargin
|
||||||
if (currentValue != fabMargin.value) {
|
ValueAnimator.ofInt(fabMargin.value!!, currentValue).apply {
|
||||||
ValueAnimator.ofInt(fabMargin.value!!, currentValue).apply {
|
addUpdateListener {
|
||||||
addUpdateListener {
|
fabMargin.postValue(
|
||||||
fabMargin.postValue(
|
(it.animatedValue as Int)
|
||||||
it.animatedValue as Int
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
start()
|
|
||||||
}
|
}
|
||||||
|
doOnEnd {
|
||||||
|
fabMargin.postValue(currentValue)
|
||||||
|
}
|
||||||
|
start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,4 +402,5 @@ enum class ReloadType {
|
||||||
HomeSections,
|
HomeSections,
|
||||||
Playlists,
|
Playlists,
|
||||||
Genres,
|
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 {
|
sharedElementEnterTransition = MaterialContainerTransform().apply {
|
||||||
drawingViewId = R.id.fragment_container
|
drawingViewId = R.id.fragment_container
|
||||||
scrimColor = Color.TRANSPARENT
|
scrimColor = Color.TRANSPARENT
|
||||||
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
|
setAllContainerColors(surfaceColor())
|
||||||
setPathMotion(MaterialArcMotion())
|
setPathMotion(MaterialArcMotion())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||||
if (!handleBackPress()) {
|
if (!handleBackPress()) {
|
||||||
remove()
|
remove()
|
||||||
mainActivity.finish()
|
requireActivity().onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,6 +346,13 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
|
||||||
libraryViewModel.forceReload(ReloadType.Albums)
|
libraryViewModel.forceReload(ReloadType.Albums)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
if (cab.isActive()) {
|
||||||
|
cab.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleBackPress(): Boolean {
|
private fun handleBackPress(): Boolean {
|
||||||
cab?.let {
|
cab?.let {
|
||||||
if (it.isActive()) {
|
if (it.isActive()) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import androidx.core.os.bundleOf
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
@ -75,7 +76,7 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
sharedElementEnterTransition = MaterialContainerTransform().apply {
|
sharedElementEnterTransition = MaterialContainerTransform().apply {
|
||||||
drawingViewId = R.id.fragment_container
|
drawingViewId = R.id.fragment_container
|
||||||
scrimColor = Color.TRANSPARENT
|
scrimColor = Color.TRANSPARENT
|
||||||
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
|
setAllContainerColors(surfaceColor())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,19 +193,21 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
|
||||||
if (lastFmArtist != null && lastFmArtist.artist != null && lastFmArtist.artist.bio != null) {
|
if (lastFmArtist != null && lastFmArtist.artist != null && lastFmArtist.artist.bio != null) {
|
||||||
val bioContent = lastFmArtist.artist.bio.content
|
val bioContent = lastFmArtist.artist.bio.content
|
||||||
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
|
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
|
||||||
binding.fragmentArtistContent.biographyText.visibility = View.VISIBLE
|
binding.fragmentArtistContent.run {
|
||||||
binding.fragmentArtistContent.biographyTitle.visibility = View.VISIBLE
|
biographyText.isVisible = true
|
||||||
biography = HtmlCompat.fromHtml(bioContent, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
biographyTitle.isVisible = true
|
||||||
binding.fragmentArtistContent.biographyText.text = biography
|
biography = HtmlCompat.fromHtml(bioContent, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||||
if (lastFmArtist.artist.stats.listeners.isNotEmpty()) {
|
biographyText.text = biography
|
||||||
binding.fragmentArtistContent.listeners.show()
|
if (lastFmArtist.artist.stats.listeners.isNotEmpty()) {
|
||||||
binding.fragmentArtistContent.listenersLabel.show()
|
listeners.show()
|
||||||
binding.fragmentArtistContent.scrobbles.show()
|
listenersLabel.show()
|
||||||
binding.fragmentArtistContent.scrobblesLabel.show()
|
scrobbles.show()
|
||||||
binding.fragmentArtistContent.listeners.text =
|
scrobblesLabel.show()
|
||||||
RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat())
|
listeners.text =
|
||||||
binding.fragmentArtistContent.scrobbles.text =
|
RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat())
|
||||||
RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat())
|
scrobbles.text =
|
||||||
|
RetroUtil.formatValue(lastFmArtist.artist.stats.playcount.toFloat())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||||
if (!handleBackPress()) {
|
if (!handleBackPress()) {
|
||||||
remove()
|
remove()
|
||||||
mainActivity.finish()
|
requireActivity().onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,4 +382,11 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
|
||||||
super.onResume()
|
super.onResume()
|
||||||
libraryViewModel.forceReload(ReloadType.Artists)
|
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
|
val backupsLiveData: LiveData<List<File>> = backupsMutableLiveData
|
||||||
|
|
||||||
fun loadBackups(context: Context) {
|
fun loadBackups(context: Context) {
|
||||||
BackupHelper.getBackupRoot(context).listFiles { _, name ->
|
BackupHelper.getBackupRoot().listFiles { _, name ->
|
||||||
return@listFiles name.endsWith(BackupHelper.BACKUP_EXTENSION)
|
return@listFiles name.endsWith(BackupHelper.BACKUP_EXTENSION)
|
||||||
}?.toList()?.let {
|
}?.toList()?.let {
|
||||||
backupsMutableLiveData.value = it
|
backupsMutableLiveData.value = it
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package code.name.monkey.retromusic.fragments.backup
|
package code.name.monkey.retromusic.fragments.backup
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
|
@ -52,7 +53,7 @@ class RestoreActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTheme() {
|
private fun updateTheme() {
|
||||||
AppCompatDelegate.setDefaultNightMode(ThemeManager.getNightMode(this))
|
AppCompatDelegate.setDefaultNightMode(ThemeManager.getNightMode())
|
||||||
|
|
||||||
// Apply dynamic colors to activity if enabled
|
// Apply dynamic colors to activity if enabled
|
||||||
if (PreferenceUtil.materialYou) {
|
if (PreferenceUtil.materialYou) {
|
||||||
|
@ -65,10 +66,10 @@ class RestoreActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private fun getFileName(uri: Uri?): String? {
|
private fun getFileName(uri: Uri?): String? {
|
||||||
when (uri?.scheme) {
|
when (uri?.scheme) {
|
||||||
"file" -> {
|
ContentResolver.SCHEME_FILE -> {
|
||||||
return uri.lastPathSegment
|
return uri.lastPathSegment
|
||||||
}
|
}
|
||||||
"content" -> {
|
ContentResolver.SCHEME_CONTENT -> {
|
||||||
val proj = arrayOf(MediaStore.Files.FileColumns.DISPLAY_NAME)
|
val proj = arrayOf(MediaStore.Files.FileColumns.DISPLAY_NAME)
|
||||||
contentResolver.query(
|
contentResolver.query(
|
||||||
uri, proj, null, null, null
|
uri, proj, null, null, null
|
||||||
|
|
|
@ -14,14 +14,27 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.fragments.base
|
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.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.AccelerateInterpolator
|
import android.view.animation.AccelerateInterpolator
|
||||||
import android.view.animation.DecelerateInterpolator
|
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.annotation.LayoutRes
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import code.name.monkey.retromusic.R
|
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.fragments.other.VolumeFragment
|
||||||
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
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.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
|
||||||
|
@ -36,37 +49,101 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
|
||||||
|
|
||||||
protected abstract fun hide()
|
protected abstract fun hide()
|
||||||
|
|
||||||
protected abstract fun updateShuffleState()
|
|
||||||
|
|
||||||
protected abstract fun updateRepeatState()
|
|
||||||
|
|
||||||
protected abstract fun setUpProgressSlider()
|
|
||||||
|
|
||||||
abstract fun setColor(color: MediaNotificationProcessor)
|
abstract fun setColor(color: MediaNotificationProcessor)
|
||||||
|
|
||||||
fun showBounceAnimation(view: View) {
|
var lastPlaybackControlsColor: Int = 0
|
||||||
view.apply {
|
|
||||||
clearAnimation()
|
var lastDisabledPlaybackControlsColor: Int = 0
|
||||||
scaleX = 0.9f
|
|
||||||
scaleY = 0.9f
|
var isSeeking = false
|
||||||
visibility = View.VISIBLE
|
private set
|
||||||
pivotX = (view.width / 2).toFloat()
|
|
||||||
pivotY = (view.height / 2).toFloat()
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
isVisible = true
|
||||||
|
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 onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -74,6 +151,68 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
|
||||||
hideVolumeIfAvailable()
|
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
|
protected var volumeFragment: VolumeFragment? = null
|
||||||
|
|
||||||
private fun hideVolumeIfAvailable() {
|
private fun hideVolumeIfAvailable() {
|
||||||
|
@ -82,10 +221,20 @@ abstract class AbsPlayerControlsFragment(@LayoutRes layout: Int) : AbsMusicServi
|
||||||
.replace(R.id.volumeFragmentContainer, VolumeFragment()).commit()
|
.replace(R.id.volumeFragmentContainer, VolumeFragment()).commit()
|
||||||
childFragmentManager.executePendingTransactions()
|
childFragmentManager.executePendingTransactions()
|
||||||
volumeFragment =
|
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 {
|
companion object {
|
||||||
const val SLIDER_ANIMATION_TIME: Long = 400
|
const val SLIDER_ANIMATION_TIME: Long = 400
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,14 @@ import android.view.View
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.LayoutRes
|
import androidx.annotation.LayoutRes
|
||||||
import androidx.appcompat.graphics.drawable.DrawableWrapper
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.navOptions
|
import androidx.navigation.navOptions
|
||||||
import androidx.viewpager.widget.ViewPager
|
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_ALBUM_ID
|
||||||
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
|
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
|
||||||
import code.name.monkey.retromusic.R
|
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.dialogs.*
|
||||||
import code.name.monkey.retromusic.extensions.currentFragment
|
import code.name.monkey.retromusic.extensions.currentFragment
|
||||||
import code.name.monkey.retromusic.extensions.hide
|
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.extensions.whichFragment
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
||||||
import code.name.monkey.retromusic.fragments.ReloadType
|
import code.name.monkey.retromusic.fragments.ReloadType
|
||||||
|
@ -78,9 +80,18 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val song = MusicPlayerRemote.currentSong
|
val song = MusicPlayerRemote.currentSong
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
|
R.id.action_playback_speed -> {
|
||||||
|
PlaybackSpeedDialog.newInstance().show(childFragmentManager, "PLAYBACK_SETTINGS")
|
||||||
|
return true
|
||||||
|
}
|
||||||
R.id.action_toggle_lyrics -> {
|
R.id.action_toggle_lyrics -> {
|
||||||
PreferenceUtil.showLyrics = !item.isChecked
|
PreferenceUtil.showLyrics = !PreferenceUtil.showLyrics
|
||||||
item.isChecked = !item.isChecked
|
showLyricsIcon(item)
|
||||||
|
if (PreferenceUtil.lyricsScreenOn && PreferenceUtil.showLyrics) {
|
||||||
|
mainActivity.keepScreenOn(true)
|
||||||
|
} else if (!PreferenceUtil.isScreenOnEnabled && !PreferenceUtil.showLyrics) {
|
||||||
|
mainActivity.keepScreenOn(false)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.action_go_to_lyrics -> {
|
R.id.action_go_to_lyrics -> {
|
||||||
|
@ -162,7 +173,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.action_sleep_timer -> {
|
R.id.action_sleep_timer -> {
|
||||||
SleepTimerDialog().show(parentFragmentManager, TAG)
|
SleepTimerDialog().show(parentFragmentManager, "SLEEP_TIMER")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.action_set_as_ringtone -> {
|
R.id.action_set_as_ringtone -> {
|
||||||
|
@ -193,6 +204,18 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
return false
|
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 playerToolbar(): Toolbar?
|
||||||
|
|
||||||
abstract fun onShow()
|
abstract fun onShow()
|
||||||
|
@ -237,7 +260,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
val isFavorite: Boolean =
|
val isFavorite: Boolean =
|
||||||
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
||||||
withContext(Main) {
|
withContext(Main) {
|
||||||
val icon = if (animate) {
|
val icon = if (animate && VersionUtils.hasMarshmallow()) {
|
||||||
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
||||||
} else {
|
} else {
|
||||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
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 &&
|
if (PreferenceUtil.isFullScreenMode &&
|
||||||
view.findViewById<View>(R.id.status_bar) != null
|
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 = whichFragment(R.id.playerAlbumCoverFragment)
|
||||||
playerAlbumCoverFragment?.setCallbacks(this)
|
playerAlbumCoverFragment?.setCallbacks(this)
|
||||||
|
@ -287,9 +310,8 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
playerToolbar()?.menu?.removeItem(R.id.action_toggle_lyrics)
|
playerToolbar()?.menu?.removeItem(R.id.action_toggle_lyrics)
|
||||||
} else {
|
} else {
|
||||||
playerToolbar()?.menu?.findItem(R.id.action_toggle_lyrics)?.apply {
|
playerToolbar()?.menu?.findItem(R.id.action_toggle_lyrics)?.apply {
|
||||||
fixCheckStateOnIcon()
|
|
||||||
isCheckable = true
|
|
||||||
isChecked = PreferenceUtil.showLyrics
|
isChecked = PreferenceUtil.showLyrics
|
||||||
|
showLyricsIcon(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requireView().setOnTouchListener(
|
requireView().setOnTouchListener(
|
||||||
|
@ -412,15 +434,4 @@ fun goToLyrics(activity: Activity) {
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 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.dialogs.ImportPlaylistDialog
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
import code.name.monkey.retromusic.extensions.dip
|
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.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.interfaces.IScrollHelper
|
import code.name.monkey.retromusic.interfaces.IScrollHelper
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.ThemedFastScroller.create
|
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.MaterialFadeThrough
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
|
||||||
import me.zhanghai.android.fastscroll.FastScroller
|
import me.zhanghai.android.fastscroll.FastScroller
|
||||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||||
|
|
||||||
|
@ -60,7 +57,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
||||||
view.doOnPreDraw { startPostponedEnterTransition() }
|
view.doOnPreDraw { startPostponedEnterTransition() }
|
||||||
enterTransition = MaterialFadeThrough().addTarget(binding.recyclerView)
|
enterTransition = MaterialFadeThrough().addTarget(binding.recyclerView)
|
||||||
reenterTransition = MaterialFadeThrough().addTarget(binding.recyclerView)
|
reenterTransition = MaterialFadeThrough().addTarget(binding.recyclerView)
|
||||||
mainActivity.setSupportActionBar(binding.toolbar)
|
mainActivity.setSupportActionBar(toolbar)
|
||||||
mainActivity.supportActionBar?.title = null
|
mainActivity.supportActionBar?.title = null
|
||||||
initLayoutManager()
|
initLayoutManager()
|
||||||
initAdapter()
|
initAdapter()
|
||||||
|
@ -99,25 +96,18 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
||||||
open fun onShuffleClicked() {
|
open fun onShuffleClicked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toolbar(): Toolbar {
|
val toolbar: Toolbar get() = binding.appBarLayout.toolbar
|
||||||
return binding.toolbar
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
binding.toolbar.setNavigationOnClickListener {
|
toolbar.setNavigationOnClickListener {
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(requireView())
|
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
R.id.searchFragment,
|
R.id.action_search,
|
||||||
null,
|
null,
|
||||||
navOptions
|
navOptions
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val appName = resources.getString(titleRes)
|
val appName = resources.getString(titleRes)
|
||||||
binding.appNameText.text = appName
|
binding.appBarLayout.title = appName
|
||||||
binding.toolbarContainer.drawNextToNavbar()
|
|
||||||
binding.appBarLayout.statusBarForeground =
|
|
||||||
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract val titleRes: Int
|
abstract val titleRes: Int
|
||||||
|
@ -155,17 +145,19 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
||||||
|
|
||||||
private fun checkIsEmpty() {
|
private fun checkIsEmpty() {
|
||||||
binding.emptyText.setText(emptyMessage)
|
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() {
|
private fun checkForPadding() {
|
||||||
val itemCount: Int = adapter?.itemCount ?: 0
|
val itemCount: Int = adapter?.itemCount ?: 0
|
||||||
|
|
||||||
if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
binding.recyclerView.updatePadding(
|
||||||
binding.recyclerView.updatePadding(bottom = dip(R.dimen.mini_player_height_expanded))
|
bottom = if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||||
} else {
|
dip(R.dimen.mini_player_height_expanded)
|
||||||
binding.recyclerView.updatePadding(bottom = dip(R.dimen.bottom_nav_height))
|
} else {
|
||||||
}
|
dip(R.dimen.bottom_nav_height)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initLayoutManager() {
|
private fun initLayoutManager() {
|
||||||
|
@ -209,7 +201,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
super.onPrepareOptionsMenu(menu)
|
super.onPrepareOptionsMenu(menu)
|
||||||
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(requireActivity(), binding.toolbar)
|
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(requireActivity(), toolbar)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
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)
|
inflater.inflate(R.menu.menu_main, menu)
|
||||||
ToolbarContentTintHelper.handleOnCreateOptionsMenu(
|
ToolbarContentTintHelper.handleOnCreateOptionsMenu(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
binding.toolbar,
|
toolbar,
|
||||||
menu,
|
menu,
|
||||||
ATHToolbarActivity.getToolbarBackgroundColor(binding.toolbar)
|
ATHToolbarActivity.getToolbarBackgroundColor(toolbar)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,10 @@ import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.loader.app.LoaderManager
|
import androidx.loader.app.LoaderManager
|
||||||
import androidx.loader.content.Loader
|
import androidx.loader.content.Loader
|
||||||
import androidx.navigation.Navigation.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
|
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.model.Song
|
||||||
import code.name.monkey.retromusic.providers.BlacklistStore
|
import code.name.monkey.retromusic.providers.BlacklistStore
|
||||||
import code.name.monkey.retromusic.util.*
|
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.PreferenceUtil.startDirectory
|
||||||
import code.name.monkey.retromusic.util.ThemedFastScroller.create
|
import code.name.monkey.retromusic.util.ThemedFastScroller.create
|
||||||
import code.name.monkey.retromusic.views.BreadCrumbLayout.Crumb
|
import code.name.monkey.retromusic.views.BreadCrumbLayout.Crumb
|
||||||
import code.name.monkey.retromusic.views.BreadCrumbLayout.SelectionCallback
|
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.AttachedCab
|
||||||
import com.afollestad.materialcab.attached.destroy
|
import com.afollestad.materialcab.attached.destroy
|
||||||
import com.afollestad.materialcab.attached.isActive
|
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.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.transition.MaterialFadeThrough
|
import com.google.android.material.transition.MaterialFadeThrough
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -94,14 +92,10 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var storageItems = ArrayList<Storage>()
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
_binding = FragmentFolderBinding.bind(view)
|
||||||
|
|
||||||
mainActivity.addMusicServiceEventListener(libraryViewModel)
|
mainActivity.addMusicServiceEventListener(libraryViewModel)
|
||||||
mainActivity.setSupportActionBar(binding.toolbar)
|
mainActivity.setSupportActionBar(binding.toolbar)
|
||||||
mainActivity.supportActionBar?.title = null
|
mainActivity.supportActionBar?.title = null
|
||||||
|
@ -118,7 +112,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
if (!handleBackPress()) {
|
if (!handleBackPress()) {
|
||||||
remove()
|
remove()
|
||||||
mainActivity.finish()
|
requireActivity().onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -128,10 +122,8 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpTitle() {
|
private fun setUpTitle() {
|
||||||
binding.toolbar.setNavigationOnClickListener { v: View? ->
|
binding.toolbar.setNavigationOnClickListener {
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).setDuration(300)
|
findNavController().navigate(R.id.action_search, null, navOptions)
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).setDuration(300)
|
|
||||||
findNavController(v!!).navigate(R.id.searchFragment, null, navOptions)
|
|
||||||
}
|
}
|
||||||
binding.appNameText.text = resources.getString(R.string.folders)
|
binding.appNameText.text = resources.getString(R.string.folders)
|
||||||
}
|
}
|
||||||
|
@ -156,12 +148,8 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
saveScrollPosition()
|
saveScrollPosition()
|
||||||
}
|
if (cab.isActive()) {
|
||||||
|
cab.destroy()
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
if (_binding != null) {
|
|
||||||
outState.putParcelable(CRUMBS, binding.breadCrumbs.stateWrapper)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +296,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
openQueue(songs, startIndex, true)
|
openQueue(songs, startIndex, true)
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(
|
Snackbar.make(
|
||||||
binding.root,
|
mainActivity.slidingPanel,
|
||||||
Html.fromHtml(
|
Html.fromHtml(
|
||||||
String.format(
|
String.format(
|
||||||
getString(R.string.not_listed_in_media_store), file1.name
|
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)
|
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||||
menu.add(0, R.id.action_go_to_start_directory, 1, R.string.action_go_to_start_directory)
|
menu.add(0, R.id.action_go_to_start_directory, 1, R.string.action_go_to_start_directory)
|
||||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
.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_grid_size)
|
||||||
menu.removeItem(R.id.action_layout_type)
|
menu.removeItem(R.id.action_layout_type)
|
||||||
menu.removeItem(R.id.action_sort_order)
|
menu.removeItem(R.id.action_sort_order)
|
||||||
|
@ -416,6 +406,14 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.action_settings -> {
|
||||||
|
findNavController().navigate(
|
||||||
|
R.id.settingsActivity,
|
||||||
|
null,
|
||||||
|
navOptions
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
@ -461,8 +459,7 @@ class FoldersFragment : AbsMainActivityFragment(R.layout.fragment_folder),
|
||||||
private fun checkIsEmpty() {
|
private fun checkIsEmpty() {
|
||||||
if (_binding != null) {
|
if (_binding != null) {
|
||||||
binding.emptyEmoji.text = getEmojiByUnicode(0x1F631)
|
binding.emptyEmoji.text = getEmojiByUnicode(0x1F631)
|
||||||
binding.empty.visibility =
|
binding.empty.isVisible = adapter?.itemCount == 0
|
||||||
if (adapter == null || adapter!!.itemCount == 0) View.VISIBLE else View.GONE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -100,7 +101,7 @@ class GenreDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_
|
||||||
private fun checkIsEmpty() {
|
private fun checkIsEmpty() {
|
||||||
checkForPadding()
|
checkForPadding()
|
||||||
binding.emptyEmoji.text = getEmojiByUnicode(0x1F631)
|
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() {
|
private fun checkForPadding() {
|
||||||
|
|
|
@ -48,7 +48,7 @@ GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(),
|
||||||
})
|
})
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||||
remove()
|
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.text.HtmlCompat
|
||||||
import androidx.core.view.doOnLayout
|
import androidx.core.view.doOnLayout
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
|
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.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.*
|
import code.name.monkey.retromusic.*
|
||||||
import code.name.monkey.retromusic.adapter.HomeAdapter
|
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.databinding.FragmentHomeBinding
|
||||||
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
|
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
|
||||||
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
|
import code.name.monkey.retromusic.dialogs.ImportPlaylistDialog
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
import code.name.monkey.retromusic.extensions.drawNextToNavbar
|
import code.name.monkey.retromusic.extensions.drawNextToNavbar
|
||||||
import code.name.monkey.retromusic.extensions.elevatedAccentColor
|
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.fragments.base.AbsMainActivityFragment
|
||||||
import code.name.monkey.retromusic.glide.GlideApp
|
import code.name.monkey.retromusic.glide.GlideApp
|
||||||
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
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.interfaces.IScrollHelper
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
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
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
|
||||||
class HomeFragment :
|
class HomeFragment :
|
||||||
AbsMainActivityFragment(if (PreferenceUtil.isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home),
|
AbsMainActivityFragment(R.layout.fragment_home), IScrollHelper {
|
||||||
IScrollHelper {
|
|
||||||
|
|
||||||
private var _binding: HomeBindingAdapter? = null
|
private var _binding: HomeBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = getBinding(PreferenceUtil.isHomeBanner, view)
|
val homeBinding = FragmentHomeBinding.bind(view)
|
||||||
|
_binding = HomeBinding(homeBinding)
|
||||||
mainActivity.setSupportActionBar(binding.toolbar)
|
mainActivity.setSupportActionBar(binding.toolbar)
|
||||||
mainActivity.supportActionBar?.title = null
|
mainActivity.supportActionBar?.title = null
|
||||||
setupListeners()
|
setupListeners()
|
||||||
|
@ -75,6 +80,9 @@ class HomeFragment :
|
||||||
libraryViewModel.getHome().observe(viewLifecycleOwner, {
|
libraryViewModel.getHome().observe(viewLifecycleOwner, {
|
||||||
homeAdapter.swapData(it)
|
homeAdapter.swapData(it)
|
||||||
})
|
})
|
||||||
|
libraryViewModel.getSuggestions().observe(viewLifecycleOwner, {
|
||||||
|
loadSuggestions(it)
|
||||||
|
})
|
||||||
|
|
||||||
loadProfile()
|
loadProfile()
|
||||||
setupTitle()
|
setupTitle()
|
||||||
|
@ -86,7 +94,7 @@ class HomeFragment :
|
||||||
binding.toolbar.drawNextToNavbar()
|
binding.toolbar.drawNextToNavbar()
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||||
remove()
|
remove()
|
||||||
mainActivity.finish()
|
requireActivity().onBackPressed()
|
||||||
}
|
}
|
||||||
view.doOnLayout {
|
view.doOnLayout {
|
||||||
adjustPlaylistButtons()
|
adjustPlaylistButtons()
|
||||||
|
@ -96,7 +104,7 @@ class HomeFragment :
|
||||||
private fun adjustPlaylistButtons() {
|
private fun adjustPlaylistButtons() {
|
||||||
val buttons =
|
val buttons =
|
||||||
listOf(binding.history, binding.lastAdded, binding.topPlayed, binding.actionShuffle)
|
listOf(binding.history, binding.lastAdded, binding.topPlayed, binding.actionShuffle)
|
||||||
buttons.maxOf { it.lineCount }.let { maxLineCount->
|
buttons.maxOf { it.lineCount }.let { maxLineCount ->
|
||||||
buttons.forEach { button ->
|
buttons.forEach { button ->
|
||||||
// Set the highest line count to every button for consistency
|
// Set the highest line count to every button for consistency
|
||||||
button.setLines(maxLineCount)
|
button.setLines(maxLineCount)
|
||||||
|
@ -150,24 +158,17 @@ class HomeFragment :
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
// Reload suggestions
|
||||||
|
binding.suggestions.refreshButton.setOnClickListener {
|
||||||
private fun getBinding(homeBanner: Boolean, view: View): HomeBindingAdapter {
|
libraryViewModel.forceReload(
|
||||||
return if (homeBanner) {
|
ReloadType.Suggestions
|
||||||
val homeBannerBinding = FragmentBannerHomeBinding.bind(view)
|
)
|
||||||
HomeBindingAdapter(null, homeBannerBinding)
|
|
||||||
} else {
|
|
||||||
val homeBinding = FragmentHomeBinding.bind(view)
|
|
||||||
HomeBindingAdapter(homeBinding, null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTitle() {
|
private fun setupTitle() {
|
||||||
binding.toolbar.setNavigationOnClickListener {
|
binding.toolbar.setNavigationOnClickListener {
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(binding.root)
|
findNavController().navigate(R.id.action_search, null, navOptions)
|
||||||
reenterTransition =
|
|
||||||
MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
|
||||||
findNavController().navigate(R.id.searchFragment, null, navOptions)
|
|
||||||
}
|
}
|
||||||
val hexColor = String.format("#%06X", 0xFFFFFF and accentColor())
|
val hexColor = String.format("#%06X", 0xFFFFFF and accentColor())
|
||||||
val appName = HtmlCompat.fromHtml(
|
val appName = HtmlCompat.fromHtml(
|
||||||
|
@ -234,6 +235,51 @@ class HomeFragment :
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
|
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 {
|
companion object {
|
||||||
|
|
||||||
const val TAG: String = "BannerHomeFragment"
|
const val TAG: String = "BannerHomeFragment"
|
||||||
|
@ -270,7 +316,7 @@ class HomeFragment :
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
libraryViewModel.fetchHomeSections()
|
libraryViewModel.forceReload(ReloadType.HomeSections)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -54,7 +54,7 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
|
||||||
mainActivity.supportActionBar?.title = null
|
mainActivity.supportActionBar?.title = null
|
||||||
binding.toolbar.setNavigationOnClickListener {
|
binding.toolbar.setNavigationOnClickListener {
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
R.id.searchFragment,
|
R.id.action_search,
|
||||||
null,
|
null,
|
||||||
navOptions
|
navOptions
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,8 +12,10 @@ import androidx.preference.PreferenceManager
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.SHOW_LYRICS
|
import code.name.monkey.retromusic.SHOW_LYRICS
|
||||||
import code.name.monkey.retromusic.databinding.FragmentCoverLyricsBinding
|
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.AbsMusicServiceFragment
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
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.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||||
import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics
|
import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics
|
||||||
|
@ -45,6 +47,14 @@ class CoverLyricsFragment : AbsMusicServiceFragment(R.layout.fragment_cover_lyri
|
||||||
if (PreferenceUtil.showLyrics) {
|
if (PreferenceUtil.showLyrics) {
|
||||||
progressViewUpdateHelper?.start()
|
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?) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
|
@ -110,7 +120,7 @@ class CoverLyricsFragment : AbsMusicServiceFragment(R.layout.fragment_cover_lyri
|
||||||
if (lyrics !is AbsSynchronizedLyrics) return
|
if (lyrics !is AbsSynchronizedLyrics) return
|
||||||
val synchronizedLyrics = lyrics as AbsSynchronizedLyrics
|
val synchronizedLyrics = lyrics as AbsSynchronizedLyrics
|
||||||
|
|
||||||
lyricsLayout.visibility = View.VISIBLE
|
lyricsLayout.isVisible = true
|
||||||
lyricsLayout.alpha = 1f
|
lyricsLayout.alpha = 1f
|
||||||
|
|
||||||
val oldLine = lyricsLine2.text.toString()
|
val oldLine = lyricsLine2.text.toString()
|
||||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.fragments.other
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
import androidx.navigation.fragment.FragmentNavigatorExtras
|
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.databinding.FragmentPlaylistDetailBinding
|
||||||
import code.name.monkey.retromusic.db.toSong
|
import code.name.monkey.retromusic.db.toSong
|
||||||
import code.name.monkey.retromusic.extensions.dipToPix
|
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.fragments.base.AbsMainActivityFragment
|
||||||
import code.name.monkey.retromusic.interfaces.IAlbumClickListener
|
import code.name.monkey.retromusic.interfaces.IAlbumClickListener
|
||||||
import code.name.monkey.retromusic.interfaces.IArtistClickListener
|
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.Album
|
||||||
import code.name.monkey.retromusic.model.Artist
|
import code.name.monkey.retromusic.model.Artist
|
||||||
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
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.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
|
||||||
class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail),
|
class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail),
|
||||||
IArtistClickListener, IAlbumClickListener {
|
IArtistClickListener, IAlbumClickListener, ICabHolder {
|
||||||
private val args by navArgs<DetailListFragmentArgs>()
|
private val args by navArgs<DetailListFragmentArgs>()
|
||||||
private var _binding: FragmentPlaylistDetailBinding? = null
|
private var _binding: FragmentPlaylistDetailBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
@ -88,6 +97,12 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
|
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
|
||||||
postponeEnterTransition()
|
postponeEnterTransition()
|
||||||
view.doOnPreDraw { startPostponedEnterTransition() }
|
view.doOnPreDraw { startPostponedEnterTransition() }
|
||||||
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||||
|
if (!handleBackPress()) {
|
||||||
|
remove()
|
||||||
|
findNavController().navigateUp()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lastAddedSongs() {
|
private fun lastAddedSongs() {
|
||||||
|
@ -95,16 +110,16 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
val songAdapter = ShuffleButtonSongAdapter(
|
val songAdapter = ShuffleButtonSongAdapter(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
mutableListOf(),
|
mutableListOf(),
|
||||||
R.layout.item_list, null
|
R.layout.item_list, this
|
||||||
)
|
)
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
adapter = songAdapter
|
adapter = songAdapter
|
||||||
layoutManager = linearLayoutManager()
|
layoutManager = linearLayoutManager()
|
||||||
scheduleLayoutAnimation()
|
scheduleLayoutAnimation()
|
||||||
}
|
}
|
||||||
libraryViewModel.recentSongs().observe(viewLifecycleOwner, { songs ->
|
libraryViewModel.recentSongs().observe(viewLifecycleOwner) { songs ->
|
||||||
songAdapter.swapDataSet(songs)
|
songAdapter.swapDataSet(songs)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun topPlayed() {
|
private fun topPlayed() {
|
||||||
|
@ -112,15 +127,15 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
val songAdapter = ShuffleButtonSongAdapter(
|
val songAdapter = ShuffleButtonSongAdapter(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
mutableListOf(),
|
mutableListOf(),
|
||||||
R.layout.item_list, null
|
R.layout.item_list, this
|
||||||
)
|
)
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
adapter = songAdapter
|
adapter = songAdapter
|
||||||
layoutManager = linearLayoutManager()
|
layoutManager = linearLayoutManager()
|
||||||
}
|
}
|
||||||
libraryViewModel.playCountSongs().observe(viewLifecycleOwner, { songs ->
|
libraryViewModel.playCountSongs().observe(viewLifecycleOwner) { songs ->
|
||||||
songAdapter.swapDataSet(songs)
|
songAdapter.swapDataSet(songs)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadHistory() {
|
private fun loadHistory() {
|
||||||
|
@ -129,15 +144,15 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
val songAdapter = ShuffleButtonSongAdapter(
|
val songAdapter = ShuffleButtonSongAdapter(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
mutableListOf(),
|
mutableListOf(),
|
||||||
R.layout.item_list, null
|
R.layout.item_list, this
|
||||||
)
|
)
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
adapter = songAdapter
|
adapter = songAdapter
|
||||||
layoutManager = linearLayoutManager()
|
layoutManager = linearLayoutManager()
|
||||||
}
|
}
|
||||||
libraryViewModel.observableHistorySongs().observe(viewLifecycleOwner, {
|
libraryViewModel.observableHistorySongs().observe(viewLifecycleOwner) {
|
||||||
songAdapter.swapDataSet(it)
|
songAdapter.swapDataSet(it)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFavorite() {
|
private fun loadFavorite() {
|
||||||
|
@ -145,50 +160,55 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
val songAdapter = SongAdapter(
|
val songAdapter = SongAdapter(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
mutableListOf(),
|
mutableListOf(),
|
||||||
R.layout.item_list, null
|
R.layout.item_list, this
|
||||||
)
|
)
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
adapter = songAdapter
|
adapter = songAdapter
|
||||||
layoutManager = linearLayoutManager()
|
layoutManager = linearLayoutManager()
|
||||||
}
|
}
|
||||||
libraryViewModel.favorites().observe(viewLifecycleOwner, { songEntities ->
|
libraryViewModel.favorites().observe(viewLifecycleOwner) { songEntities ->
|
||||||
val songs = songEntities.map { songEntity -> songEntity.toSong() }
|
val songs = songEntities.map { songEntity -> songEntity.toSong() }
|
||||||
songAdapter.swapDataSet(songs)
|
songAdapter.swapDataSet(songs)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun loadArtists(title: Int, type: Int) {
|
private fun loadArtists(title: Int, type: Int) {
|
||||||
binding.toolbar.setTitle(title)
|
binding.toolbar.setTitle(title)
|
||||||
libraryViewModel.artists(type).observe(viewLifecycleOwner, { artists ->
|
val artistAdapter = artistAdapter(listOf())
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
adapter = artistAdapter(artists)
|
adapter = artistAdapter
|
||||||
layoutManager = gridLayoutManager()
|
layoutManager = gridLayoutManager()
|
||||||
}
|
}
|
||||||
})
|
libraryViewModel.artists(type).observe(viewLifecycleOwner) { artists ->
|
||||||
|
artistAdapter.swapDataSet(artists)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAlbums(title: Int, type: Int) {
|
private fun loadAlbums(title: Int, type: Int) {
|
||||||
binding.toolbar.setTitle(title)
|
binding.toolbar.setTitle(title)
|
||||||
libraryViewModel.albums(type).observe(viewLifecycleOwner, { albums ->
|
val albumAdapter = albumAdapter(listOf())
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
adapter = albumAdapter(albums)
|
adapter = albumAdapter
|
||||||
layoutManager = gridLayoutManager()
|
layoutManager = gridLayoutManager()
|
||||||
}
|
}
|
||||||
})
|
libraryViewModel.albums(type).observe(viewLifecycleOwner) { albums ->
|
||||||
|
albumAdapter.swapDataSet(albums)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun artistAdapter(artists: List<Artist>): ArtistAdapter = ArtistAdapter(
|
private fun artistAdapter(artists: List<Artist>): ArtistAdapter = ArtistAdapter(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
artists,
|
artists,
|
||||||
R.layout.item_grid_circle,
|
R.layout.item_grid_circle,
|
||||||
null, this@DetailListFragment
|
this, this@DetailListFragment
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun albumAdapter(albums: List<Album>): AlbumAdapter = AlbumAdapter(
|
private fun albumAdapter(albums: List<Album>): AlbumAdapter = AlbumAdapter(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
albums,
|
albums,
|
||||||
R.layout.item_grid,
|
R.layout.item_grid,
|
||||||
null, this@DetailListFragment
|
this, this@DetailListFragment
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun linearLayoutManager(): LinearLayoutManager =
|
private fun linearLayoutManager(): LinearLayoutManager =
|
||||||
|
@ -228,4 +248,37 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_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
|
package code.name.monkey.retromusic.fragments.other
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.provider.MediaStore
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.view.*
|
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.ViewCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
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.FragmentNormalLyricsBinding
|
||||||
import code.name.monkey.retromusic.databinding.FragmentSyncedLyricsBinding
|
import code.name.monkey.retromusic.databinding.FragmentSyncedLyricsBinding
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
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.textColorSecondary
|
||||||
|
import code.name.monkey.retromusic.extensions.uri
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
|
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||||
import code.name.monkey.retromusic.lyrics.LrcView
|
import code.name.monkey.retromusic.lyrics.LrcView
|
||||||
import code.name.monkey.retromusic.model.AudioTagInfo
|
import code.name.monkey.retromusic.model.AudioTagInfo
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.util.LyricUtil
|
import code.name.monkey.retromusic.util.*
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
|
||||||
import com.afollestad.materialdialogs.LayoutMode
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
|
||||||
import com.afollestad.materialdialogs.input.input
|
import com.afollestad.materialdialogs.input.input
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
@ -55,6 +59,7 @@ import kotlinx.coroutines.*
|
||||||
import org.jaudiotagger.audio.AudioFileIO
|
import org.jaudiotagger.audio.AudioFileIO
|
||||||
import org.jaudiotagger.tag.FieldKey
|
import org.jaudiotagger.tag.FieldKey
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
|
@ -95,6 +100,43 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
return transform
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
|
@ -105,15 +147,9 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
ViewCompat.setTransitionName(binding.container, "lyrics")
|
ViewCompat.setTransitionName(binding.container, "lyrics")
|
||||||
|
|
||||||
setupWakelock()
|
setupWakelock()
|
||||||
|
|
||||||
binding.tabLyrics.setBackgroundColor(surfaceColor())
|
|
||||||
binding.container.setBackgroundColor(surfaceColor())
|
|
||||||
setupViews()
|
setupViews()
|
||||||
setupToolbar()
|
setupToolbar()
|
||||||
updateTitleSong()
|
updateTitleSong()
|
||||||
if (VersionUtils.hasR()) {
|
|
||||||
binding.editButton.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
|
@ -144,7 +180,6 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
mainActivity.setSupportActionBar(binding.toolbar)
|
mainActivity.setSupportActionBar(binding.toolbar)
|
||||||
binding.toolbar.setBackgroundColor(surfaceColor())
|
|
||||||
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
||||||
binding.toolbar.setNavigationOnClickListener {
|
binding.toolbar.setNavigationOnClickListener {
|
||||||
findNavController().navigateUp()
|
findNavController().navigateUp()
|
||||||
|
@ -204,7 +239,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialDialog(requireContext(), BottomSheet(LayoutMode.WRAP_CONTENT)).show {
|
MaterialDialog(requireContext()).show {
|
||||||
title(res = R.string.edit_normal_lyrics)
|
title(res = R.string.edit_normal_lyrics)
|
||||||
input(
|
input(
|
||||||
hintRes = R.string.paste_lyrics_here,
|
hintRes = R.string.paste_lyrics_here,
|
||||||
|
@ -213,12 +248,30 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
) { _, input ->
|
) { _, input ->
|
||||||
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
|
||||||
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
|
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
|
||||||
|
syncedLyrics = input.toString()
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
TagWriter.writeTagsToFiles(
|
if (VersionUtils.hasR()) {
|
||||||
requireContext(), AudioTagInfo(
|
cacheFile = TagWriter.writeTagsToFilesR(
|
||||||
listOf(song.data), fieldKeyValueMap, null
|
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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
positiveButton(res = R.string.save) {
|
positiveButton(res = R.string.save) {
|
||||||
|
@ -233,14 +286,40 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
private fun editSyncedLyrics() {
|
private fun editSyncedLyrics() {
|
||||||
val content: String = LyricUtil.getStringFromLrc(LyricUtil.getSyncedLyricsFile(song))
|
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)
|
title(res = R.string.edit_synced_lyrics)
|
||||||
input(
|
input(
|
||||||
hintRes = R.string.paste_timeframe_lyrics_here,
|
hintRes = R.string.paste_timeframe_lyrics_here,
|
||||||
prefill = content,
|
prefill = content,
|
||||||
inputType = InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_CLASS_TEXT
|
inputType = InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_CLASS_TEXT
|
||||||
) { _, input ->
|
) { _, input ->
|
||||||
LyricUtil.writeLrc(song, input.toString())
|
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) {
|
positiveButton(res = R.string.save) {
|
||||||
(lyricsSectionsAdapter.fragments[0].first as SyncedLyrics).loadLRCLyrics()
|
(lyricsSectionsAdapter.fragments[0].first as SyncedLyrics).loadLRCLyrics()
|
||||||
|
@ -285,11 +364,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
if (lyrics.isNullOrEmpty()) {
|
binding.noLyricsFound.isVisible = lyrics.isNullOrEmpty()
|
||||||
binding.noLyricsFound.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
binding.noLyricsFound.visibility = View.GONE
|
|
||||||
}
|
|
||||||
binding.normalLyrics.text = lyrics
|
binding.normalLyrics.text = lyrics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ class PlayingQueueRVFragment : AbsRecyclerViewFragment<PlayingQueueAdapter, Line
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
toolbar().apply {
|
toolbar.apply {
|
||||||
setNavigationOnClickListener {
|
setNavigationOnClickListener {
|
||||||
findNavController().navigateUp()
|
findNavController().navigateUp()
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
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.R
|
||||||
import code.name.monkey.retromusic.SHOW_LYRICS
|
import code.name.monkey.retromusic.SHOW_LYRICS
|
||||||
import code.name.monkey.retromusic.adapter.album.AlbumCoverPagerAdapter
|
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.CarousalPagerTransformer
|
||||||
import code.name.monkey.retromusic.transform.ParallaxPagerTransformer
|
import code.name.monkey.retromusic.transform.ParallaxPagerTransformer
|
||||||
import code.name.monkey.retromusic.util.LyricUtil
|
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.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -145,21 +147,6 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
goToLyrics(requireActivity())
|
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)
|
showLyrics(false)
|
||||||
progressViewUpdateHelper?.stop()
|
progressViewUpdateHelper?.stop()
|
||||||
}
|
}
|
||||||
|
} else if (key == LYRICS_TYPE) {
|
||||||
|
maybeInitLyrics()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,13 +212,22 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showLyrics(visible: Boolean) {
|
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 {
|
doOnEnd {
|
||||||
_binding?.lyricsView?.isVisible = visible
|
lyrics.isVisible = visible
|
||||||
}
|
}
|
||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
ObjectAnimator.ofFloat(viewPager, View.ALPHA, if (visible) 0F else 1F).start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun maybeInitLyrics() {
|
private fun maybeInitLyrics() {
|
||||||
|
@ -237,7 +235,9 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
||||||
// Don't show lyrics container for below conditions
|
// Don't show lyrics container for below conditions
|
||||||
if (lyricViewNpsList.contains(nps) && PreferenceUtil.showLyrics) {
|
if (lyricViewNpsList.contains(nps) && PreferenceUtil.showLyrics) {
|
||||||
showLyrics(true)
|
showLyrics(true)
|
||||||
progressViewUpdateHelper?.start()
|
if (PreferenceUtil.lyricsType == LyricsType.REPLACE_COVER) {
|
||||||
|
progressViewUpdateHelper?.start()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
showLyrics(false)
|
showLyrics(false)
|
||||||
progressViewUpdateHelper?.stop()
|
progressViewUpdateHelper?.stop()
|
||||||
|
@ -283,9 +283,9 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
|
||||||
} else {
|
} else {
|
||||||
surfaceColor()
|
surfaceColor()
|
||||||
}
|
}
|
||||||
Color -> color.backgroundColor
|
Color ,Classic -> color.backgroundColor
|
||||||
Blur -> Color.BLACK
|
Blur -> Color.BLACK
|
||||||
else -> color.backgroundColor
|
else -> surfaceColor()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,12 @@
|
||||||
package code.name.monkey.retromusic.fragments.player.adaptive
|
package code.name.monkey.retromusic.fragments.player.adaptive
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
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.extensions.*
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -43,38 +38,35 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
class AdaptivePlaybackControlsFragment :
|
class AdaptivePlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_adaptive_player_playback_controls) {
|
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 var _binding: FragmentAdaptivePlayerPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val progressSlider: SeekBar
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.progressSlider
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override val shuffleButton: ImageButton
|
||||||
inflater: LayoutInflater,
|
get() = binding.shuffleButton
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
override val repeatButton: ImageButton
|
||||||
): View {
|
get() = binding.repeatButton
|
||||||
_binding = FragmentAdaptivePlayerPlaybackControlsBinding.inflate(inflater, container, false)
|
|
||||||
return binding.root
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
setUpMusicControllers()
|
_binding = FragmentAdaptivePlayerPlaybackControlsBinding.bind(view)
|
||||||
|
|
||||||
binding.playPauseButton.setOnClickListener {
|
setUpPlayPauseFab()
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
|
||||||
MusicPlayerRemote.pauseSong()
|
|
||||||
} else {
|
|
||||||
MusicPlayerRemote.resumePlaying()
|
|
||||||
}
|
|
||||||
showBounceAnimation(binding.playPauseButton)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSong() {
|
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() {
|
override fun onPlayingMetaChanged() {
|
||||||
super.onPlayingMetaChanged()
|
super.onPlayingMetaChanged()
|
||||||
updateSong()
|
updateSong()
|
||||||
|
@ -163,7 +145,14 @@ class AdaptivePlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayPauseFab() {
|
private fun setUpPlayPauseFab() {
|
||||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
binding.playPauseButton.setOnClickListener {
|
||||||
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
|
MusicPlayerRemote.pauseSong()
|
||||||
|
} else {
|
||||||
|
MusicPlayerRemote.resumePlaying()
|
||||||
|
}
|
||||||
|
it.showBounceAnimation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseDrawableState() {
|
private fun updatePlayPauseDrawableState() {
|
||||||
|
@ -174,103 +163,9 @@ class AdaptivePlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpMusicControllers() {
|
override fun show() {}
|
||||||
setUpPlayPauseFab()
|
|
||||||
setUpPrevNext()
|
|
||||||
setUpRepeatButton()
|
|
||||||
setUpShuffleButton()
|
|
||||||
setUpProgressSlider()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpPrevNext() {
|
override fun hide() {}
|
||||||
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 onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
|
|
@ -16,13 +16,13 @@ package code.name.monkey.retromusic.fragments.player.blur
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.AccelerateInterpolator
|
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -48,28 +44,32 @@ class BlurPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_blur_player_playback_controls) {
|
AbsPlayerControlsFragment(R.layout.fragment_blur_player_playback_controls) {
|
||||||
private var _binding: FragmentBlurPlayerPlaybackControlsBinding? = null
|
private var _binding: FragmentBlurPlayerPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
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?) {
|
override val progressSlider: SeekBar
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.progressSlider
|
||||||
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentBlurPlayerPlaybackControlsBinding.bind(view)
|
_binding = FragmentBlurPlayerPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
|
|
||||||
binding.playPauseButton.setOnClickListener {
|
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
|
||||||
MusicPlayerRemote.pauseSong()
|
|
||||||
} else {
|
|
||||||
MusicPlayerRemote.resumePlaying()
|
|
||||||
}
|
|
||||||
showBounceAnimation()
|
|
||||||
}
|
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.isSelected = true
|
binding.text.isSelected = true
|
||||||
binding.title.setOnClickListener {
|
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() {
|
override fun onServiceConnected() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
updateRepeatState()
|
updateRepeatState()
|
||||||
|
@ -159,7 +149,14 @@ class BlurPlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayPauseFab() {
|
private fun setUpPlayPauseFab() {
|
||||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
binding.playPauseButton.setOnClickListener {
|
||||||
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
|
MusicPlayerRemote.pauseSong()
|
||||||
|
} else {
|
||||||
|
MusicPlayerRemote.resumePlaying()
|
||||||
|
}
|
||||||
|
it.showBounceAnimation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseDrawableState() {
|
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() {
|
public override fun show() {
|
||||||
binding.playPauseButton.animate()
|
binding.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
|
@ -96,11 +96,13 @@ class CardFragment : AbsPlayerFragment(R.layout.fragment_card_player) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayerToolbar() {
|
private fun setUpPlayerToolbar() {
|
||||||
binding.playerToolbar.inflateMenu(R.menu.menu_player)
|
binding.playerToolbar.apply {
|
||||||
binding.playerToolbar.setNavigationOnClickListener { requireActivity().onBackPressed() }
|
inflateMenu(R.menu.menu_player)
|
||||||
binding.playerToolbar.setOnMenuItemClickListener(this)
|
setNavigationOnClickListener { requireActivity().onBackPressed() }
|
||||||
|
setOnMenuItemClickListener(this@CardFragment)
|
||||||
|
|
||||||
ToolbarContentTintHelper.colorizeToolbar(binding.playerToolbar, Color.WHITE, activity)
|
ToolbarContentTintHelper.colorizeToolbar(this, Color.WHITE, activity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
override fun onServiceConnected() {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import android.graphics.PorterDuff
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -46,31 +43,29 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
class CardPlaybackControlsFragment :
|
class CardPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_card_player_playback_controls) {
|
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 var _binding: FragmentCardPlayerPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val shuffleButton: ImageButton
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.mediaButton.shuffleButton
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
|
||||||
}
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentCardPlayerPlaybackControlsBinding.bind(view)
|
_binding = FragmentCardPlayerPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
|
|
||||||
binding.mediaButton.playPauseButton.setOnClickListener {
|
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
|
||||||
MusicPlayerRemote.pauseSong()
|
|
||||||
} else {
|
|
||||||
MusicPlayerRemote.resumePlaying()
|
|
||||||
}
|
|
||||||
showBounceAnimation(binding.mediaButton.playPauseButton)
|
|
||||||
}
|
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.isSelected = true
|
binding.text.isSelected = true
|
||||||
binding.title.setOnClickListener {
|
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() {
|
override fun onServiceConnected() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
updateRepeatState()
|
updateRepeatState()
|
||||||
|
@ -167,7 +152,14 @@ class CardPlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayPauseFab() {
|
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() {
|
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() {
|
private fun updateProgressTextColor() {
|
||||||
val color = MaterialValueHelper.getPrimaryTextColor(context, false)
|
val color = MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||||
binding.songTotalTime.setTextColor(color)
|
binding.songTotalTime.setTextColor(color)
|
||||||
binding.songCurrentProgress.setTextColor(color)
|
binding.songCurrentProgress.setTextColor(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun show() {
|
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 hide() {}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
|
|
@ -111,7 +111,8 @@ class CardBlurFragment : AbsPlayerFragment(R.layout.fragment_card_blur_player),
|
||||||
setTitleTextColor(Color.WHITE)
|
setTitleTextColor(Color.WHITE)
|
||||||
setSubtitleTextColor(Color.WHITE)
|
setSubtitleTextColor(Color.WHITE)
|
||||||
ToolbarContentTintHelper.colorizeToolbar(binding.playerToolbar, Color.WHITE, activity)
|
ToolbarContentTintHelper.colorizeToolbar(binding.playerToolbar, Color.WHITE, activity)
|
||||||
}.setOnMenuItemClickListener(this)
|
setOnMenuItemClickListener(this@CardBlurFragment)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
override fun onServiceConnected() {
|
||||||
|
|
|
@ -16,11 +16,11 @@ package code.name.monkey.retromusic.fragments.player.cardblur
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.TintHelper
|
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.extensions.show
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -43,23 +40,29 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
class CardBlurPlaybackControlsFragment :
|
class CardBlurPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_card_blur_player_playback_controls) {
|
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 var _binding: FragmentCardBlurPlayerPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val shuffleButton: ImageButton
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.mediaButton.shuffleButton
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
|
||||||
}
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentCardBlurPlayerPlaybackControlsBinding.bind(view)
|
_binding = FragmentCardBlurPlayerPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
|
binding.progressSlider.applyColor(Color.WHITE)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setColor(color: MediaNotificationProcessor) {
|
override fun setColor(color: MediaNotificationProcessor) {
|
||||||
|
@ -96,16 +99,6 @@ class CardBlurPlaybackControlsFragment :
|
||||||
binding.songInfo.setTextColor(color)
|
binding.songInfo.setTextColor(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
progressViewUpdateHelper.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
progressViewUpdateHelper.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
override fun onServiceConnected() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
updateRepeatState()
|
updateRepeatState()
|
||||||
|
@ -139,78 +132,6 @@ class CardBlurPlaybackControlsFragment :
|
||||||
updateShuffleState()
|
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() {
|
public override fun show() {
|
||||||
binding.mediaButton.playPauseButton.animate()
|
binding.mediaButton.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package code.name.monkey.retromusic.fragments.player.circle
|
package code.name.monkey.retromusic.fragments.player.circle
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.PorterDuff
|
import android.graphics.PorterDuff
|
||||||
|
@ -22,9 +23,7 @@ import android.graphics.drawable.ColorDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.animation.Animation
|
import android.view.animation.Animation
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
import android.widget.SeekBar
|
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.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentCirclePlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentCirclePlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.*
|
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.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||||
|
@ -77,17 +77,10 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
_binding = FragmentCirclePlayerBinding.bind(view)
|
||||||
|
|
||||||
setupViews()
|
setupViews()
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.title.setOnClickListener {
|
binding.title.setOnClickListener {
|
||||||
|
@ -132,10 +125,11 @@ class CirclePlayerFragment : AbsPlayerFragment(R.layout.fragment_circle_player),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private fun setUpPrevNext() {
|
private fun setUpPrevNext() {
|
||||||
updatePrevNextColor()
|
updatePrevNextColor()
|
||||||
binding.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
binding.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true))
|
||||||
binding.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
binding.previousButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), false))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePrevNextColor() {
|
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.hide
|
||||||
import code.name.monkey.retromusic.extensions.show
|
import code.name.monkey.retromusic.extensions.show
|
||||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
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.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||||
|
@ -455,10 +456,21 @@ class ClassicPlayerFragment : AbsPlayerFragment(R.layout.fragment_classic_player
|
||||||
setUpProgressSlider()
|
setUpProgressSlider()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private fun setUpPrevNext() {
|
private fun setUpPrevNext() {
|
||||||
updatePrevNextColor()
|
updatePrevNextColor()
|
||||||
binding.playerControlsContainer.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
binding.playerControlsContainer.nextButton.setOnTouchListener(
|
||||||
binding.playerControlsContainer.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
MusicSeekSkipTouchListener(
|
||||||
|
requireActivity(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
binding.playerControlsContainer.previousButton.setOnTouchListener(
|
||||||
|
MusicSeekSkipTouchListener(
|
||||||
|
requireActivity(),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePrevNextColor() {
|
private fun updatePrevNextColor() {
|
||||||
|
|
|
@ -16,7 +16,6 @@ package code.name.monkey.retromusic.fragments.player.color
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.animation.doOnEnd
|
import androidx.core.animation.doOnEnd
|
||||||
|
@ -61,7 +60,7 @@ class ColorFragment : AbsPlayerFragment(R.layout.fragment_color_player) {
|
||||||
_binding?.root?.setBackgroundColor(color.backgroundColor)
|
_binding?.root?.setBackgroundColor(color.backgroundColor)
|
||||||
}
|
}
|
||||||
animator.start()
|
animator.start()
|
||||||
Handler().post {
|
binding.playerToolbar.post {
|
||||||
ToolbarContentTintHelper.colorizeToolbar(
|
ToolbarContentTintHelper.colorizeToolbar(
|
||||||
binding.playerToolbar,
|
binding.playerToolbar,
|
||||||
color.secondaryTextColor,
|
color.secondaryTextColor,
|
||||||
|
|
|
@ -17,16 +17,15 @@ package code.name.monkey.retromusic.fragments.player.color
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewAnimationUtils
|
import android.view.ViewAnimationUtils
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.animation.AccelerateInterpolator
|
import android.view.animation.AccelerateInterpolator
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.TintHelper
|
import code.name.monkey.appthemehelper.util.TintHelper
|
||||||
import code.name.monkey.retromusic.R
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
class ColorPlaybackControlsFragment :
|
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 var _binding: FragmentColorPlayerPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val shuffleButton: ImageButton
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.shuffleButton
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override val repeatButton: ImageButton
|
||||||
inflater: LayoutInflater,
|
get() = binding.repeatButton
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View {
|
|
||||||
_binding = FragmentColorPlayerPlaybackControlsBinding.inflate(inflater, container, false)
|
|
||||||
return binding.root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
override val nextButton: ImageButton
|
||||||
super.onResume()
|
get() = binding.nextButton
|
||||||
progressViewUpdateHelper.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
override val previousButton: ImageButton
|
||||||
super.onPause()
|
get() = binding.previousButton
|
||||||
progressViewUpdateHelper.stop()
|
|
||||||
}
|
override val songTotalTime: TextView
|
||||||
|
get() = binding.songTotalTime
|
||||||
|
|
||||||
|
override val songCurrentProgress: TextView
|
||||||
|
get() = binding.songCurrentProgress
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
setUpMusicControllers()
|
_binding = FragmentColorPlayerPlaybackControlsBinding.bind(view)
|
||||||
|
|
||||||
|
setUpPlayPauseFab()
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.isSelected = true
|
binding.text.isSelected = true
|
||||||
binding.title.setOnClickListener {
|
binding.title.setOnClickListener {
|
||||||
|
@ -155,80 +145,23 @@ class ColorPlaybackControlsFragment :
|
||||||
private fun setUpPlayPauseFab() {
|
private fun setUpPlayPauseFab() {
|
||||||
TintHelper.setTintAuto(binding.playPauseButton, Color.WHITE, true)
|
TintHelper.setTintAuto(binding.playPauseButton, Color.WHITE, true)
|
||||||
TintHelper.setTintAuto(binding.playPauseButton, Color.BLACK, false)
|
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() {
|
private fun updatePlayPauseDrawableState() {
|
||||||
when {
|
binding.playPauseButton.setImageResource(
|
||||||
MusicPlayerRemote.isPlaying -> binding.playPauseButton.setImageResource(R.drawable.ic_pause)
|
when {
|
||||||
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() {
|
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 {
|
fun createRevealAnimator(view: View): Animator {
|
||||||
val location = IntArray(2)
|
val location = IntArray(2)
|
||||||
binding.playPauseButton.getLocationOnScreen(location)
|
binding.playPauseButton.getLocationOnScreen(location)
|
||||||
|
|
|
@ -15,13 +15,13 @@
|
||||||
package code.name.monkey.retromusic.fragments.player.fit
|
package code.name.monkey.retromusic.fragments.player.fit
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.AccelerateInterpolator
|
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
|
||||||
class FitPlaybackControlsFragment :
|
class FitPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_fit_playback_controls) {
|
AbsPlayerControlsFragment(R.layout.fragment_fit_playback_controls) {
|
||||||
|
|
||||||
private var _binding: FragmentFitPlaybackControlsBinding? = null
|
private var _binding: FragmentFitPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
private var lastPlaybackControlsColor: Int = 0
|
override val shuffleButton: ImageButton
|
||||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
get() = binding.shuffleButton
|
||||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val repeatButton: ImageButton
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.repeatButton
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
|
||||||
}
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentFitPlaybackControlsBinding.bind(view)
|
_binding = FragmentFitPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
|
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.isSelected = true
|
binding.text.isSelected = true
|
||||||
|
@ -70,15 +78,6 @@ class FitPlaybackControlsFragment :
|
||||||
binding.text.setOnClickListener {
|
binding.text.setOnClickListener {
|
||||||
goToArtist(requireActivity())
|
goToArtist(requireActivity())
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playPauseButton.setOnClickListener {
|
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
|
||||||
MusicPlayerRemote.pauseSong()
|
|
||||||
} else {
|
|
||||||
MusicPlayerRemote.resumePlaying()
|
|
||||||
}
|
|
||||||
showBounceAnimation()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSong() {
|
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() {
|
override fun onServiceConnected() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
updateRepeatState()
|
updateRepeatState()
|
||||||
|
@ -163,7 +152,14 @@ class FitPlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayPauseFab() {
|
private fun setUpPlayPauseFab() {
|
||||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
binding.playPauseButton.setOnClickListener {
|
||||||
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
|
MusicPlayerRemote.pauseSong()
|
||||||
|
} else {
|
||||||
|
MusicPlayerRemote.resumePlaying()
|
||||||
|
}
|
||||||
|
it.showBounceAnimation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseDrawableState() {
|
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() {
|
public override fun show() {
|
||||||
binding.playPauseButton.animate()
|
binding.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
package code.name.monkey.retromusic.fragments.player.flat
|
package code.name.monkey.retromusic.fragments.player.flat
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicProgressViewUpdateHelper.Callback
|
||||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -45,22 +42,28 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
class FlatPlaybackControlsFragment :
|
class FlatPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_flat_player_playback_controls), Callback {
|
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 var _binding: FragmentFlatPlayerPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val shuffleButton: ImageButton
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.shuffleButton
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
|
||||||
}
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentFlatPlayerPlaybackControlsBinding.bind(view)
|
_binding = FragmentFlatPlayerPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.isSelected = true
|
binding.text.isSelected = true
|
||||||
binding.title.setOnClickListener {
|
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() {
|
public override fun show() {
|
||||||
binding.playPauseButton.animate()
|
binding.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.scaleX(1f)
|
||||||
|
@ -157,10 +150,6 @@ class FlatPlaybackControlsFragment :
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayPauseFab() {
|
|
||||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updatePlayPauseDrawableState() {
|
private fun updatePlayPauseDrawableState() {
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
binding.playPauseButton.setImageResource(R.drawable.ic_pause)
|
binding.playPauseButton.setImageResource(R.drawable.ic_pause)
|
||||||
|
@ -169,13 +158,6 @@ class FlatPlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpMusicControllers() {
|
|
||||||
setUpPlayPauseFab()
|
|
||||||
setUpRepeatButton()
|
|
||||||
setUpShuffleButton()
|
|
||||||
setUpProgressSlider()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateSong() {
|
private fun updateSong() {
|
||||||
val song = MusicPlayerRemote.currentSong
|
val song = MusicPlayerRemote.currentSong
|
||||||
binding.title.text = song.title
|
binding.title.text = song.title
|
||||||
|
@ -196,81 +178,8 @@ class FlatPlaybackControlsFragment :
|
||||||
updateShuffleState()
|
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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,7 +18,6 @@ import android.animation.ObjectAnimator
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.graphics.drawable.AnimatedVectorDrawable
|
import android.graphics.drawable.AnimatedVectorDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -26,10 +25,13 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
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.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentFullPlayerControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentFullPlayerControlsBinding
|
||||||
import code.name.monkey.retromusic.db.PlaylistEntity
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.helper.PlayPauseButtonOnClickHandler
|
||||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.service.MusicService
|
import code.name.monkey.retromusic.service.MusicService
|
||||||
import code.name.monkey.retromusic.util.MusicUtil
|
import code.name.monkey.retromusic.util.MusicUtil
|
||||||
|
@ -66,17 +66,30 @@ class FullPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_full_player_controls),
|
AbsPlayerControlsFragment(R.layout.fragment_full_player_controls),
|
||||||
PopupMenu.OnMenuItemClickListener {
|
PopupMenu.OnMenuItemClickListener {
|
||||||
|
|
||||||
private var lastPlaybackControlsColor: Int = 0
|
|
||||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
|
||||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
|
||||||
private val libraryViewModel: LibraryViewModel by sharedViewModel()
|
private val libraryViewModel: LibraryViewModel by sharedViewModel()
|
||||||
private var _binding: FragmentFullPlayerControlsBinding? = null
|
private var _binding: FragmentFullPlayerControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val progressSlider: SeekBar
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.progressSlider
|
||||||
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
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() {
|
public override fun show() {
|
||||||
binding.playPauseButton.animate()
|
binding.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.scaleX(1f)
|
||||||
|
@ -190,10 +193,6 @@ class FullPlaybackControlsFragment :
|
||||||
|
|
||||||
private fun setUpMusicControllers() {
|
private fun setUpMusicControllers() {
|
||||||
setUpPlayPauseFab()
|
setUpPlayPauseFab()
|
||||||
setUpPrevNext()
|
|
||||||
setUpRepeatButton()
|
|
||||||
setUpShuffleButton()
|
|
||||||
setUpProgressSlider()
|
|
||||||
setupFavourite()
|
setupFavourite()
|
||||||
setupMenu()
|
setupMenu()
|
||||||
}
|
}
|
||||||
|
@ -213,43 +212,6 @@ class FullPlaybackControlsFragment :
|
||||||
return (parentFragment as FullPlayerFragment).onMenuItemClick(item!!)
|
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() {
|
override fun onRepeatModeChanged() {
|
||||||
updateRepeatState()
|
updateRepeatState()
|
||||||
}
|
}
|
||||||
|
@ -258,53 +220,6 @@ class FullPlaybackControlsFragment :
|
||||||
updateShuffleState()
|
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() {
|
private fun setupFavourite() {
|
||||||
binding.songFavourite.setOnClickListener {
|
binding.songFavourite.setOnClickListener {
|
||||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||||
|
@ -320,7 +235,7 @@ class FullPlaybackControlsFragment :
|
||||||
val isFavorite: Boolean =
|
val isFavorite: Boolean =
|
||||||
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
val icon = if (animate) {
|
val icon = if (animate && VersionUtils.hasMarshmallow()) {
|
||||||
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
||||||
} else {
|
} else {
|
||||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
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.PopupMenu
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
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.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
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.R
|
||||||
import code.name.monkey.retromusic.RetroBottomSheetBehavior
|
import code.name.monkey.retromusic.RetroBottomSheetBehavior
|
||||||
import code.name.monkey.retromusic.adapter.song.PlayingQueueAdapter
|
import code.name.monkey.retromusic.adapter.song.PlayingQueueAdapter
|
||||||
import code.name.monkey.retromusic.databinding.FragmentGradientPlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentGradientPlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.*
|
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.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||||
|
@ -63,7 +67,8 @@ import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_player),
|
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 lastColor: Int = 0
|
||||||
private var lastPlaybackControlsColor: Int = 0
|
private var lastPlaybackControlsColor: Int = 0
|
||||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||||
|
@ -126,9 +131,9 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupPanel() {
|
private fun setupPanel() {
|
||||||
binding.colorBackground.doOnLayout {
|
if (!ViewCompat.isLaidOut(binding.colorBackground) || binding.colorBackground.isLayoutRequested) {
|
||||||
val panel = getQueuePanel()
|
binding.colorBackground.addOnLayoutChangeListener(this)
|
||||||
panel.peekHeight = binding.container.height
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +284,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
val isFavorite: Boolean =
|
val isFavorite: Boolean =
|
||||||
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
val icon = if (animate) {
|
val icon = if (animate && VersionUtils.hasMarshmallow()) {
|
||||||
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
|
||||||
} else {
|
} else {
|
||||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
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() {
|
private fun setUpPrevNext() {
|
||||||
updatePrevNextColor()
|
updatePrevNextColor()
|
||||||
binding.playbackControlsFragment.nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
binding.playbackControlsFragment.nextButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), true))
|
||||||
binding.playbackControlsFragment.previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
binding.playbackControlsFragment.previousButton.setOnTouchListener(MusicSeekSkipTouchListener(requireActivity(), false))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePrevNextColor() {
|
private fun updatePrevNextColor() {
|
||||||
|
@ -450,7 +456,7 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
|
||||||
private fun updateLabel() {
|
private fun updateLabel() {
|
||||||
(MusicPlayerRemote.playingQueue.size - 1).apply {
|
(MusicPlayerRemote.playingQueue.size - 1).apply {
|
||||||
if (this == (MusicPlayerRemote.position)) {
|
if (this == (MusicPlayerRemote.position)) {
|
||||||
binding.nextSong.text = "Last song"
|
binding.nextSong.text = context?.resources?.getString(R.string.last_song)
|
||||||
} else {
|
} else {
|
||||||
val title = MusicPlayerRemote.playingQueue[MusicPlayerRemote.position + 1].title
|
val title = MusicPlayerRemote.playingQueue[MusicPlayerRemote.position + 1].title
|
||||||
binding.nextSong.text = 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() {
|
private fun setupRecyclerView() {
|
||||||
playingQueueAdapter = PlayingQueueAdapter(
|
playingQueueAdapter = PlayingQueueAdapter(
|
||||||
requireActivity() as AppCompatActivity,
|
requireActivity() as AppCompatActivity,
|
||||||
|
|
|
@ -37,7 +37,6 @@ class HomePlayerFragment : AbsPlayerFragment(R.layout.fragment_home_player),
|
||||||
private var _binding: FragmentHomePlayerBinding? = null
|
private var _binding: FragmentHomePlayerBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
package code.name.monkey.retromusic.fragments.player.lockscreen
|
package code.name.monkey.retromusic.fragments.player.lockscreen
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
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.extensions.textColorSecondary
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -46,23 +44,34 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
class LockScreenControlsFragment :
|
class LockScreenControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_lock_screen_playback_controls) {
|
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 var _binding: FragmentLockScreenPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val shuffleButton: ImageButton
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.shuffleButton
|
||||||
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentLockScreenPlaybackControlsBinding.bind(view)
|
_binding = FragmentLockScreenPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,16 +81,6 @@ class LockScreenControlsFragment :
|
||||||
binding.text.text = String.format("%s - %s", song.artistName, song.albumName)
|
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() {
|
override fun onServiceConnected() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
updateRepeatState()
|
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() {
|
public override fun show() {
|
||||||
binding.playPauseButton.animate()
|
binding.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
|
@ -19,7 +19,9 @@ import android.graphics.PorterDuff
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -44,22 +43,35 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
class MaterialControlsFragment :
|
class MaterialControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_material_playback_controls) {
|
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 var _binding: FragmentMaterialPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val shuffleButton: ImageButton
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.shuffleButton
|
||||||
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentMaterialPlaybackControlsBinding.bind(view)
|
_binding = FragmentMaterialPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.isSelected = true
|
binding.text.isSelected = true
|
||||||
binding.title.setOnClickListener {
|
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() {
|
override fun onServiceConnected() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
updateRepeatState()
|
updateRepeatState()
|
||||||
|
@ -175,103 +177,9 @@ class MaterialControlsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpMusicControllers() {
|
public override fun show() {}
|
||||||
setUpPlayPauseFab()
|
|
||||||
setUpPrevNext()
|
|
||||||
setUpRepeatButton()
|
|
||||||
setUpShuffleButton()
|
|
||||||
setUpProgressSlider()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpPrevNext() {
|
public override fun hide() {}
|
||||||
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())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.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.databinding.FragmentPlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
import code.name.monkey.retromusic.extensions.colorControlNormal
|
||||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
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.extensions.surfaceColor
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||||
|
@ -167,7 +168,7 @@ class PlayerFragment : AbsPlayerFragment(R.layout.fragment_player),
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startOrStopSnow(isSnowFalling: Boolean) {
|
private fun startOrStopSnow(isSnowFalling: Boolean) {
|
||||||
if (isSnowFalling) {
|
if (isSnowFalling && !surfaceColor().isColorLight) {
|
||||||
binding.snowfallView.isVisible = true
|
binding.snowfallView.isVisible = true
|
||||||
binding.snowfallView.restartFalling()
|
binding.snowfallView.restartFalling()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,13 +14,12 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.fragments.player.normal
|
package code.name.monkey.retromusic.fragments.player.normal
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
|
||||||
class PlayerPlaybackControlsFragment :
|
class PlayerPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_player_playback_controls) {
|
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 var _binding: FragmentPlayerPlaybackControlsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val progressSlider: SeekBar
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.progressSlider
|
||||||
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentPlayerPlaybackControlsBinding.bind(view)
|
_binding = FragmentPlayerPlaybackControlsBinding.bind(view)
|
||||||
setUpMusicControllers()
|
|
||||||
binding.playPauseButton.setOnClickListener {
|
setUpPlayPauseFab()
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
|
||||||
MusicPlayerRemote.pauseSong()
|
|
||||||
} else {
|
|
||||||
MusicPlayerRemote.resumePlaying()
|
|
||||||
}
|
|
||||||
showBounceAnimation(binding.playPauseButton)
|
|
||||||
}
|
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.isSelected = true
|
binding.text.isSelected = true
|
||||||
binding.title.setOnClickListener {
|
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() {
|
override fun onServiceConnected() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
|
@ -161,7 +152,14 @@ class PlayerPlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayPauseFab() {
|
private fun setUpPlayPauseFab() {
|
||||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
binding.playPauseButton.setOnClickListener {
|
||||||
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
|
MusicPlayerRemote.pauseSong()
|
||||||
|
} else {
|
||||||
|
MusicPlayerRemote.resumePlaying()
|
||||||
|
}
|
||||||
|
it.showBounceAnimation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseDrawableState() {
|
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() {
|
public override fun show() {
|
||||||
binding.playPauseButton.animate()
|
binding.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
|
@ -20,7 +20,9 @@ import android.graphics.PorterDuff
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
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.extensions.applyColor
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
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) {
|
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 var _binding: FragmentPeakControlPlayerBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override val progressSlider: SeekBar
|
||||||
super.onCreate(savedInstanceState)
|
get() = binding.progressSlider
|
||||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
override val shuffleButton: ImageButton
|
||||||
super.onResume()
|
get() = binding.shuffleButton
|
||||||
progressViewUpdateHelper.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
override val repeatButton: ImageButton
|
||||||
super.onPause()
|
get() = binding.repeatButton
|
||||||
progressViewUpdateHelper.stop()
|
|
||||||
}
|
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(
|
override fun onViewCreated(
|
||||||
view: View,
|
view: View,
|
||||||
|
@ -71,14 +73,12 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment(R.layout.fragment_pe
|
||||||
) {
|
) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentPeakControlPlayerBinding.bind(view)
|
_binding = FragmentPeakControlPlayerBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {}
|
||||||
}
|
|
||||||
|
|
||||||
override fun hide() {
|
override fun hide() {}
|
||||||
}
|
|
||||||
|
|
||||||
override fun setColor(color: MediaNotificationProcessor) {
|
override fun setColor(color: MediaNotificationProcessor) {
|
||||||
val controlsColor =
|
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() {
|
private fun setUpPlayPauseFab() {
|
||||||
TintHelper.setTintAuto(binding.playPauseButton, Color.WHITE, true)
|
TintHelper.setTintAuto(binding.playPauseButton, Color.WHITE, true)
|
||||||
TintHelper.setTintAuto(binding.playPauseButton, Color.BLACK, false)
|
TintHelper.setTintAuto(binding.playPauseButton, Color.BLACK, false)
|
||||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
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() {
|
override fun onPlayStateChanged() {
|
||||||
super.onPlayStateChanged()
|
super.onPlayStateChanged()
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
|
|
|
@ -15,13 +15,13 @@
|
||||||
package code.name.monkey.retromusic.fragments.player.plain
|
package code.name.monkey.retromusic.fragments.player.plain
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.AccelerateInterpolator
|
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
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.extensions.show
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -50,12 +46,30 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
class PlainPlaybackControlsFragment :
|
class PlainPlaybackControlsFragment :
|
||||||
AbsPlayerControlsFragment(R.layout.fragment_plain_controls_fragment) {
|
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 var _binding: FragmentPlainControlsFragmentBinding? = null
|
||||||
private val binding get() = _binding!!
|
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() {
|
override fun onPlayStateChanged() {
|
||||||
updatePlayPauseDrawableState()
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentPlainControlsFragmentBinding.bind(view)
|
_binding = FragmentPlainControlsFragmentBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUpPlayPauseFab() {
|
||||||
binding.playPauseButton.setOnClickListener {
|
binding.playPauseButton.setOnClickListener {
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
MusicPlayerRemote.pauseSong()
|
MusicPlayerRemote.pauseSong()
|
||||||
} else {
|
} else {
|
||||||
MusicPlayerRemote.resumePlaying()
|
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) {
|
override fun setColor(color: MediaNotificationProcessor) {
|
||||||
val colorBg = ATHUtil.resolveColor(requireContext(), android.R.attr.colorBackground)
|
val colorBg = ATHUtil.resolveColor(requireContext(), android.R.attr.colorBackground)
|
||||||
if (ColorUtil.isColorLight(colorBg)) {
|
if (ColorUtil.isColorLight(colorBg)) {
|
||||||
|
@ -179,53 +157,6 @@ class PlainPlaybackControlsFragment :
|
||||||
updatePrevNextColor()
|
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() {
|
public override fun show() {
|
||||||
binding.playPauseButton.animate()
|
binding.playPauseButton.animate()
|
||||||
.scaleX(1f)
|
.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() {
|
private fun updatePlayPauseDrawableState() {
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
binding.playPauseButton.setImageResource(R.drawable.ic_pause)
|
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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.fragments.player.simple
|
package code.name.monkey.retromusic.fragments.player.simple
|
||||||
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
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.goToAlbum
|
||||||
import code.name.monkey.retromusic.fragments.base.goToArtist
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
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.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -49,10 +46,17 @@ class SimplePlaybackControlsFragment :
|
||||||
private var _binding: FragmentSimpleControlsFragmentBinding? = null
|
private var _binding: FragmentSimpleControlsFragmentBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val shuffleButton: ImageButton
|
||||||
|
get() = binding.shuffleButton
|
||||||
|
|
||||||
private var lastPlaybackControlsColor: Int = 0
|
override val repeatButton: ImageButton
|
||||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
get() = binding.repeatButton
|
||||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
|
||||||
|
override val nextButton: ImageButton
|
||||||
|
get() = binding.nextButton
|
||||||
|
|
||||||
|
override val previousButton: ImageButton
|
||||||
|
get() = binding.previousButton
|
||||||
|
|
||||||
override fun onPlayStateChanged() {
|
override fun onPlayStateChanged() {
|
||||||
updatePlayPauseDrawableState()
|
updatePlayPauseDrawableState()
|
||||||
|
@ -73,37 +77,15 @@ class SimplePlaybackControlsFragment :
|
||||||
updateSong()
|
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?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentSimpleControlsFragmentBinding.bind(view)
|
_binding = FragmentSimpleControlsFragmentBinding.bind(view)
|
||||||
setUpMusicControllers()
|
setUpPlayPauseFab()
|
||||||
binding.title.isSelected = true
|
binding.title.isSelected = true
|
||||||
binding.text.setOnClickListener {
|
binding.text.setOnClickListener {
|
||||||
goToArtist(requireActivity())
|
goToArtist(requireActivity())
|
||||||
}
|
}
|
||||||
binding.playPauseButton.setOnClickListener {
|
|
||||||
if (MusicPlayerRemote.isPlaying) {
|
|
||||||
MusicPlayerRemote.pauseSong()
|
|
||||||
} else {
|
|
||||||
MusicPlayerRemote.resumePlaying()
|
|
||||||
}
|
|
||||||
showBounceAnimation(binding.playPauseButton)
|
|
||||||
}
|
|
||||||
binding.title.setOnClickListener {
|
binding.title.setOnClickListener {
|
||||||
goToAlbum(requireActivity())
|
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() {
|
private fun updateSong() {
|
||||||
val song = MusicPlayerRemote.currentSong
|
val song = MusicPlayerRemote.currentSong
|
||||||
binding.title.text = song.title
|
binding.title.text = song.title
|
||||||
|
@ -213,9 +129,6 @@ class SimplePlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setUpProgressSlider() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||||
binding.songCurrentProgress.text = String.format(
|
binding.songCurrentProgress.text = String.format(
|
||||||
"%s / %s",
|
"%s / %s",
|
||||||
|
@ -263,7 +176,14 @@ class SimplePlaybackControlsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpPlayPauseFab() {
|
private fun setUpPlayPauseFab() {
|
||||||
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
binding.playPauseButton.setOnClickListener {
|
||||||
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
|
MusicPlayerRemote.pauseSong()
|
||||||
|
} else {
|
||||||
|
MusicPlayerRemote.resumePlaying()
|
||||||
|
}
|
||||||
|
it.showBounceAnimation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePlayPauseDrawableState() {
|
private fun updatePlayPauseDrawableState() {
|
||||||
|
|
|
@ -14,15 +14,13 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.fragments.player.tiny
|
package code.name.monkey.retromusic.fragments.player.tiny
|
||||||
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageButton
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentTinyControlsFragmentBinding
|
import code.name.monkey.retromusic.databinding.FragmentTinyControlsFragmentBinding
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
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
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
|
||||||
class TinyPlaybackControlsFragment :
|
class TinyPlaybackControlsFragment :
|
||||||
|
@ -30,14 +28,15 @@ class TinyPlaybackControlsFragment :
|
||||||
private var _binding: FragmentTinyControlsFragmentBinding? = null
|
private var _binding: FragmentTinyControlsFragmentBinding? = null
|
||||||
private val binding get() = _binding!!
|
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) {
|
override fun setColor(color: MediaNotificationProcessor) {
|
||||||
lastPlaybackControlsColor = color.secondaryTextColor
|
lastPlaybackControlsColor = color.secondaryTextColor
|
||||||
|
@ -50,66 +49,9 @@ class TinyPlaybackControlsFragment :
|
||||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private var lastPlaybackControlsColor: Int = 0
|
|
||||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentTinyControlsFragmentBinding.bind(view)
|
_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() {
|
override fun onServiceConnected() {
|
||||||
|
|
|
@ -59,11 +59,9 @@ class TinyPlayerFragment : AbsPlayerFragment(R.layout.fragment_tiny_player),
|
||||||
return binding.playerToolbar
|
return binding.playerToolbar
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onShow() {
|
override fun onShow() {}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
override fun onBackPressed(): Boolean {
|
||||||
return false
|
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.db.toSongs
|
||||||
import code.name.monkey.retromusic.extensions.dip
|
import code.name.monkey.retromusic.extensions.dip
|
||||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
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.fragments.base.AbsMainActivityFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
||||||
|
@ -149,8 +150,8 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showEmptyView() {
|
private fun showEmptyView() {
|
||||||
binding.empty.visibility = View.VISIBLE
|
binding.empty.isVisible = true
|
||||||
binding.emptyText.visibility = View.VISIBLE
|
binding.emptyText.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun songs(songs: List<Song>) {
|
fun songs(songs: List<Song>) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ class PlaylistsFragment :
|
||||||
})
|
})
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||||
remove()
|
remove()
|
||||||
mainActivity.finish()
|
requireActivity().onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCurrentSong() {
|
private fun updateCurrentSong() {
|
||||||
binding.toolbar.subtitle = getUpNextAndQueueTime()
|
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayingMetaChanged() {
|
override fun onPlayingMetaChanged() {
|
||||||
|
@ -140,7 +140,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
||||||
private fun updateQueuePosition() {
|
private fun updateQueuePosition() {
|
||||||
playingQueueAdapter?.setCurrent(MusicPlayerRemote.position)
|
playingQueueAdapter?.setCurrent(MusicPlayerRemote.position)
|
||||||
resetToCurrentPosition()
|
resetToCurrentPosition()
|
||||||
binding.toolbar.subtitle = getUpNextAndQueueTime()
|
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateQueue() {
|
private fun updateQueue() {
|
||||||
|
@ -179,7 +179,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
binding.toolbar.subtitle = getUpNextAndQueueTime()
|
binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime()
|
||||||
binding.clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor())
|
binding.clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor())
|
||||||
ColorStateList.valueOf(
|
ColorStateList.valueOf(
|
||||||
MaterialValueHelper.getPrimaryTextColor(
|
MaterialValueHelper.getPrimaryTextColor(
|
||||||
|
@ -190,10 +190,13 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q
|
||||||
binding.clearQueue.setTextColor(this)
|
binding.clearQueue.setTextColor(this)
|
||||||
binding.clearQueue.iconTint = this
|
binding.clearQueue.iconTint = this
|
||||||
}
|
}
|
||||||
binding.toolbar.apply {
|
binding.appBarLayout.pinWhenScrolled()
|
||||||
|
binding.appBarLayout.toolbar.apply {
|
||||||
setNavigationOnClickListener {
|
setNavigationOnClickListener {
|
||||||
findNavController().navigateUp()
|
findNavController().navigateUp()
|
||||||
}
|
}
|
||||||
|
setTitle(R.string.now_playing_queue)
|
||||||
|
setTitleTextAppearance(context, R.style.ToolbarTextAppearanceNormal)
|
||||||
setNavigationIcon(R.drawable.ic_keyboard_backspace_black)
|
setNavigationIcon(R.drawable.ic_keyboard_backspace_black)
|
||||||
ToolbarContentTintHelper.colorBackButton(this)
|
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.chip.ChipGroup
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
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 net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
@ -63,8 +63,8 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(view)
|
enterTransition = MaterialFadeThrough().addTarget(view)
|
||||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
reenterTransition = MaterialFadeThrough().addTarget(view)
|
||||||
_binding = FragmentSearchBinding.bind(view)
|
_binding = FragmentSearchBinding.bind(view)
|
||||||
mainActivity.setSupportActionBar(binding.toolbar)
|
mainActivity.setSupportActionBar(binding.toolbar)
|
||||||
libraryViewModel.clearSearchResult()
|
libraryViewModel.clearSearchResult()
|
||||||
|
@ -147,7 +147,7 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
||||||
super.onChanged()
|
super.onChanged()
|
||||||
binding.empty.isVisible = searchAdapter.itemCount < 1
|
binding.empty.isVisible = searchAdapter.itemCount < 1
|
||||||
val height = dipToPix(52f)
|
val height = dipToPix(52f)
|
||||||
binding.recyclerView.setPadding(0, 0, 0, height.toInt())
|
binding.recyclerView.updatePadding(bottom = height.toInt())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
|
@ -226,11 +226,6 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
||||||
hideKeyboard(view)
|
hideKeyboard(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
mainActivity.setBottomNavVisibility(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hideKeyboard(view: View?) {
|
private fun hideKeyboard(view: View?) {
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
val imm: InputMethodManager =
|
val imm: InputMethodManager =
|
||||||
|
|
|
@ -20,18 +20,14 @@ import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
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.ListPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat
|
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat
|
||||||
import code.name.monkey.retromusic.activities.OnThemeChangedListener
|
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.preferences.*
|
||||||
import code.name.monkey.retromusic.util.NavigationUtil
|
import code.name.monkey.retromusic.util.NavigationUtil
|
||||||
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hemanth S (h4h13).
|
* @author Hemanth S (h4h13).
|
||||||
|
@ -74,19 +70,10 @@ abstract class AbsSettingsFragment : ATEPreferenceFragmentCompat() {
|
||||||
listView.overScrollMode = View.OVER_SCROLL_NEVER
|
listView.overScrollMode = View.OVER_SCROLL_NEVER
|
||||||
}
|
}
|
||||||
|
|
||||||
// CollapsingToolbarLayout consumes insets and insets are not passed to child views
|
listView.applyInsetter {
|
||||||
// So we get insets from decor view
|
type(navigationBars = true) {
|
||||||
// https://github.com/material-components/material-components-android/issues/1310
|
padding()
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
}
|
||||||
requireActivity().rootView
|
|
||||||
) { _, windowInsets ->
|
|
||||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
||||||
listView.updatePadding(
|
|
||||||
left = insets.left,
|
|
||||||
bottom = insets.bottom,
|
|
||||||
right = insets.right,
|
|
||||||
)
|
|
||||||
windowInsets
|
|
||||||
}
|
}
|
||||||
invalidateSettings()
|
invalidateSettings()
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,14 @@ import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
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.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.retromusic.App
|
import code.name.monkey.retromusic.App
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentMainSettingsBinding
|
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.hide
|
||||||
import code.name.monkey.retromusic.extensions.rootView
|
|
||||||
import code.name.monkey.retromusic.extensions.show
|
import code.name.monkey.retromusic.extensions.show
|
||||||
import code.name.monkey.retromusic.util.NavigationUtil
|
import code.name.monkey.retromusic.util.NavigationUtil
|
||||||
|
|
||||||
|
@ -40,17 +37,20 @@ class MainSettingsFragment : Fragment(), View.OnClickListener {
|
||||||
|
|
||||||
|
|
||||||
override fun onClick(view: View) {
|
override fun onClick(view: View) {
|
||||||
when (view.id) {
|
findNavController().navigate(
|
||||||
R.id.generalSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_themeSettingsFragment)
|
when (view.id) {
|
||||||
R.id.audioSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_audioSettings)
|
R.id.generalSettings -> R.id.action_mainSettingsFragment_to_themeSettingsFragment
|
||||||
R.id.personalizeSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_personalizeSettingsFragment)
|
R.id.audioSettings -> R.id.action_mainSettingsFragment_to_audioSettings
|
||||||
R.id.imageSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_imageSettingFragment)
|
R.id.personalizeSettings -> R.id.action_mainSettingsFragment_to_personalizeSettingsFragment
|
||||||
R.id.notificationSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_notificationSettingsFragment)
|
R.id.imageSettings -> R.id.action_mainSettingsFragment_to_imageSettingFragment
|
||||||
R.id.otherSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_otherSettingsFragment)
|
R.id.notificationSettings -> R.id.action_mainSettingsFragment_to_notificationSettingsFragment
|
||||||
R.id.aboutSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_aboutActivity)
|
R.id.otherSettings -> R.id.action_mainSettingsFragment_to_otherSettingsFragment
|
||||||
R.id.nowPlayingSettings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_nowPlayingSettingsFragment)
|
R.id.aboutSettings -> R.id.action_mainSettingsFragment_to_aboutActivity
|
||||||
R.id.backup_restore_settings -> findNavController().navigate(R.id.action_mainSettingsFragment_to_backupFragment)
|
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(
|
override fun onCreateView(
|
||||||
|
@ -89,17 +89,7 @@ class MainSettingsFragment : Fragment(), View.OnClickListener {
|
||||||
binding.diamondIcon.imageTintList = ColorStateList.valueOf(it)
|
binding.diamondIcon.imageTintList = ColorStateList.valueOf(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
binding.container.drawAboveSystemBarsWithPadding()
|
||||||
requireActivity().rootView
|
|
||||||
) { _, windowInsets ->
|
|
||||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
||||||
_binding?.container?.updatePadding(
|
|
||||||
left = insets.left,
|
|
||||||
bottom = insets.bottom,
|
|
||||||
right = insets.right,
|
|
||||||
)
|
|
||||||
windowInsets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.fragments.settings
|
package code.name.monkey.retromusic.fragments.settings
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
|
@ -37,6 +38,7 @@ import com.google.android.material.color.DynamicColors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ThemeSettingsFragment : AbsSettingsFragment() {
|
class ThemeSettingsFragment : AbsSettingsFragment() {
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
override fun invalidateSettings() {
|
override fun invalidateSettings() {
|
||||||
val generalTheme: Preference? = findPreference(GENERAL_THEME)
|
val generalTheme: Preference? = findPreference(GENERAL_THEME)
|
||||||
generalTheme?.let {
|
generalTheme?.let {
|
||||||
|
@ -121,6 +123,16 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
|
||||||
restartActivity()
|
restartActivity()
|
||||||
true
|
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?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
|
|
@ -51,12 +51,11 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
|
||||||
if (!handleBackPress()) {
|
if (!handleBackPress()) {
|
||||||
remove()
|
remove()
|
||||||
mainActivity.finish()
|
requireActivity().onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override val titleRes: Int
|
override val titleRes: Int
|
||||||
get() = R.string.songs
|
get() = R.string.songs
|
||||||
|
|
||||||
|
@ -346,6 +345,13 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
|
||||||
libraryViewModel.forceReload(ReloadType.Songs)
|
libraryViewModel.forceReload(ReloadType.Songs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
if (cab.isActive()) {
|
||||||
|
cab.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
var TAG: String = SongsFragment::class.java.simpleName
|
var TAG: String = SongsFragment::class.java.simpleName
|
||||||
|
|
|
@ -28,7 +28,7 @@ object BackupHelper : KoinComponent {
|
||||||
|
|
||||||
suspend fun createBackup(context: Context, name: String) {
|
suspend fun createBackup(context: Context, name: String) {
|
||||||
val backupFile =
|
val backupFile =
|
||||||
File(getBackupRoot(context), name + APPEND_EXTENSION)
|
File(getBackupRoot(), name + APPEND_EXTENSION)
|
||||||
if (backupFile.parentFile?.exists() != true) {
|
if (backupFile.parentFile?.exists() != true) {
|
||||||
backupFile.parentFile?.mkdirs()
|
backupFile.parentFile?.mkdirs()
|
||||||
}
|
}
|
||||||
|
@ -257,9 +257,9 @@ object BackupHelper : KoinComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBackupRoot(context: Context): File {
|
fun getBackupRoot(): File {
|
||||||
return File(
|
return File(
|
||||||
context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
|
||||||
"RetroMusic/Backups"
|
"RetroMusic/Backups"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,10 @@
|
||||||
package code.name.monkey.retromusic.helper
|
package code.name.monkey.retromusic.helper
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
|
@ -440,12 +438,14 @@ object MusicPlayerRemote : KoinComponent {
|
||||||
} else if (uri.authority == "media") {
|
} else if (uri.authority == "media") {
|
||||||
songId = uri.lastPathSegment
|
songId = uri.lastPathSegment
|
||||||
}
|
}
|
||||||
if (songId != null) {
|
songs = if (songId != null) {
|
||||||
songs = songRepository.songs(songId)
|
songRepository.songs(songId)
|
||||||
|
} else {
|
||||||
|
songRepository.songsIgnoreBlacklist(uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (songs == null) {
|
if (songs == null || songs.isEmpty()) {
|
||||||
var songFile: File? = null
|
var songFile: File? = null
|
||||||
if (uri.authority != null && uri.authority == "com.android.externalstorage.documents") {
|
if (uri.authority != null && uri.authority == "com.android.externalstorage.documents") {
|
||||||
songFile = File(
|
songFile = File(
|
||||||
|
@ -462,7 +462,7 @@ object MusicPlayerRemote : KoinComponent {
|
||||||
songFile = File(uri.path!!)
|
songFile = File(uri.path!!)
|
||||||
}
|
}
|
||||||
if (songFile != null) {
|
if (songFile != null) {
|
||||||
songs = songRepository.songsByFilePath(songFile.absolutePath)
|
songs = songRepository.songsByFilePath(songFile.absolutePath, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (songs != null && songs.isNotEmpty()) {
|
if (songs != null && songs.isNotEmpty()) {
|
||||||
|
@ -474,7 +474,6 @@ object MusicPlayerRemote : KoinComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
|
||||||
private fun getSongIdFromMediaProvider(uri: Uri): String {
|
private fun getSongIdFromMediaProvider(uri: Uri): String {
|
||||||
return DocumentsContract.getDocumentId(uri).split(":".toRegex())
|
return DocumentsContract.getDocumentId(uri).split(":".toRegex())
|
||||||
.dropLastWhile { it.isEmpty() }.toTypedArray()[1]
|
.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 mDefaultLabel: String? = null
|
||||||
private var mLrcPadding = 0f
|
private var mLrcPadding = 0f
|
||||||
private var mOnPlayClickListener: OnPlayClickListener? = null
|
private var mOnPlayClickListener: OnPlayClickListener? = null
|
||||||
private var mOnFlingXListener: OnFlingXListener? = null
|
|
||||||
private var mAnimator: ValueAnimator? = null
|
private var mAnimator: ValueAnimator? = null
|
||||||
private var mGestureDetector: GestureDetector? = null
|
private var mGestureDetector: GestureDetector? = null
|
||||||
private var mScroller: Scroller? = null
|
private var mScroller: Scroller? = null
|
||||||
|
@ -132,9 +131,6 @@ class CoverLrcView @JvmOverloads constructor(
|
||||||
velocityX: Float,
|
velocityX: Float,
|
||||||
velocityY: Float
|
velocityY: Float
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (mOnFlingXListener != null && abs(velocityX) > abs(velocityY)) {
|
|
||||||
return mOnFlingXListener!!.onFlingX(velocityX)
|
|
||||||
}
|
|
||||||
if (hasLrc()) {
|
if (hasLrc()) {
|
||||||
mScroller!!.fling(
|
mScroller!!.fling(
|
||||||
0,
|
0,
|
||||||
|
@ -167,7 +163,7 @@ class CoverLrcView @JvmOverloads constructor(
|
||||||
isShowTimeline = false
|
isShowTimeline = false
|
||||||
removeCallbacks(hideTimelineRunnable)
|
removeCallbacks(hideTimelineRunnable)
|
||||||
mCurrentLine = centerLine
|
mCurrentLine = centerLine
|
||||||
invalidate()
|
animateCurrentTextSize()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -320,10 +316,6 @@ class CoverLrcView @JvmOverloads constructor(
|
||||||
mOnPlayClickListener = onPlayClickListener
|
mOnPlayClickListener = onPlayClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOnFlingXListener(onFlingXListener: OnFlingXListener) {
|
|
||||||
mOnFlingXListener = onFlingXListener
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 设置歌词为空时屏幕中央显示的文字,如“暂无歌词” */
|
/** 设置歌词为空时屏幕中央显示的文字,如“暂无歌词” */
|
||||||
fun setLabel(label: String?) {
|
fun setLabel(label: String?) {
|
||||||
runOnUi {
|
runOnUi {
|
||||||
|
@ -458,6 +450,7 @@ class CoverLrcView @JvmOverloads constructor(
|
||||||
mCurrentLine = line
|
mCurrentLine = line
|
||||||
if (!isShowTimeline) {
|
if (!isShowTimeline) {
|
||||||
smoothScrollTo(line)
|
smoothScrollTo(line)
|
||||||
|
animateCurrentTextSize()
|
||||||
} else {
|
} else {
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
|
@ -536,6 +529,18 @@ class CoverLrcView @JvmOverloads constructor(
|
||||||
canvas.restore()
|
canvas.restore()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun animateCurrentTextSize() {
|
||||||
|
val currentTextSize = mCurrentTextSize
|
||||||
|
ValueAnimator.ofFloat(mNormalTextSize, currentTextSize).apply {
|
||||||
|
addUpdateListener {
|
||||||
|
mCurrentTextSize = it.animatedValue as Float
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
duration = 300L
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
if (event.action == MotionEvent.ACTION_UP
|
if (event.action == MotionEvent.ACTION_UP
|
||||||
|
@ -613,7 +618,7 @@ class CoverLrcView @JvmOverloads constructor(
|
||||||
private fun adjustCenter() {
|
private fun adjustCenter() {
|
||||||
smoothScrollTo(centerLine, ADJUST_DURATION)
|
smoothScrollTo(centerLine, ADJUST_DURATION)
|
||||||
}
|
}
|
||||||
/** 滚动到某一行 */
|
|
||||||
/** 滚动到某一行 */
|
/** 滚动到某一行 */
|
||||||
private fun smoothScrollTo(line: Int, duration: Long = mAnimationDuration) {
|
private fun smoothScrollTo(line: Int, duration: Long = mAnimationDuration) {
|
||||||
val offset = getOffset(line)
|
val offset = getOffset(line)
|
||||||
|
|
|
@ -37,6 +37,7 @@ data class CategoryInfo(
|
||||||
Artists(R.id.action_artist, R.string.artists, R.drawable.asld_artist),
|
Artists(R.id.action_artist, R.string.artists, R.drawable.asld_artist),
|
||||||
Playlists(R.id.action_playlist, R.string.playlists, R.drawable.asld_playlist),
|
Playlists(R.id.action_playlist, R.string.playlists, R.drawable.asld_playlist),
|
||||||
Genres(R.id.action_genre, R.string.genres, R.drawable.asld_guitar),
|
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
|
package code.name.monkey.retromusic.preferences
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -22,8 +21,6 @@ import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
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.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||||
import code.name.monkey.retromusic.App
|
import code.name.monkey.retromusic.App
|
||||||
import code.name.monkey.retromusic.R
|
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.extensions.*
|
||||||
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
|
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
|
||||||
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
|
private var viewPagerPosition: Int = 0
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
@SuppressLint("InflateParams") val view =
|
val binding = PreferenceDialogNowPlayingScreenBinding.inflate(layoutInflater)
|
||||||
layoutInflater
|
binding.nowPlayingScreenViewPager.apply {
|
||||||
.inflate(R.layout.preference_dialog_now_playing_screen, null)
|
adapter = AlbumCoverStyleAdapter(requireContext())
|
||||||
val viewPager = view.findViewById<ViewPager>(R.id.now_playing_screen_view_pager)
|
addOnPageChangeListener(this@AlbumCoverStylePreferenceDialog)
|
||||||
viewPager.adapter = AlbumCoverStyleAdapter(requireContext())
|
pageMargin = ViewUtil.convertDpToPixel(32f, resources).toInt()
|
||||||
viewPager.addOnPageChangeListener(this)
|
currentItem = PreferenceUtil.albumCoverStyle.ordinal
|
||||||
viewPager.pageMargin = ViewUtil.convertDpToPixel(32f, resources).toInt()
|
}
|
||||||
viewPager.currentItem = PreferenceUtil.albumCoverStyle.ordinal
|
|
||||||
|
|
||||||
return materialDialog(R.string.pref_title_album_cover_style)
|
return materialDialog(R.string.pref_title_album_cover_style)
|
||||||
.setPositiveButton(R.string.set) { _, _ ->
|
.setPositiveButton(R.string.set) { _, _ ->
|
||||||
|
@ -89,7 +87,7 @@ class AlbumCoverStylePreferenceDialog : DialogFragment(),
|
||||||
PreferenceUtil.albumCoverStyle = coverStyle
|
PreferenceUtil.albumCoverStyle = coverStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setView(view)
|
.setView(binding.root)
|
||||||
.create()
|
.create()
|
||||||
.colorButtons()
|
.colorButtons()
|
||||||
}
|
}
|
||||||
|
@ -111,25 +109,17 @@ class AlbumCoverStylePreferenceDialog : DialogFragment(),
|
||||||
val albumCoverStyle = values()[position]
|
val albumCoverStyle = values()[position]
|
||||||
|
|
||||||
val inflater = LayoutInflater.from(context)
|
val inflater = LayoutInflater.from(context)
|
||||||
val layout = inflater.inflate(
|
val binding = PreferenceNowPlayingScreenItemBinding.inflate(inflater, collection, true)
|
||||||
R.layout.preference_now_playing_screen_item,
|
|
||||||
collection,
|
|
||||||
false
|
|
||||||
) as ViewGroup
|
|
||||||
collection.addView(layout)
|
|
||||||
|
|
||||||
val image = layout.findViewById<ImageView>(R.id.image)
|
Glide.with(context).load(albumCoverStyle.drawableResId).into(binding.image)
|
||||||
val title = layout.findViewById<TextView>(R.id.title)
|
binding.title.setText(albumCoverStyle.titleRes)
|
||||||
val proText = layout.findViewById<TextView>(R.id.proText)
|
|
||||||
Glide.with(context).load(albumCoverStyle.drawableResId).into(image)
|
|
||||||
title.setText(albumCoverStyle.titleRes)
|
|
||||||
if (isAlbumCoverStyle(albumCoverStyle)) {
|
if (isAlbumCoverStyle(albumCoverStyle)) {
|
||||||
proText.show()
|
binding.proText.show()
|
||||||
proText.setText(R.string.pro)
|
binding.proText.setText(R.string.pro)
|
||||||
} else {
|
} else {
|
||||||
proText.hide()
|
binding.proText.hide()
|
||||||
}
|
}
|
||||||
return layout
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun destroyItem(
|
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
|
package code.name.monkey.retromusic.preferences
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
|
||||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||||
import code.name.monkey.retromusic.R
|
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.colorButtons
|
||||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
import code.name.monkey.retromusic.extensions.colorControlNormal
|
||||||
import code.name.monkey.retromusic.extensions.materialDialog
|
import code.name.monkey.retromusic.extensions.materialDialog
|
||||||
|
@ -50,29 +36,24 @@ class DurationPreference @JvmOverloads constructor(
|
||||||
class DurationPreferenceDialog : DialogFragment() {
|
class DurationPreferenceDialog : DialogFragment() {
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val view = layoutInflater
|
val binding = PreferenceDialogAudioFadeBinding.inflate(layoutInflater)
|
||||||
.inflate(R.layout.preference_dialog_audio_fade, null)
|
|
||||||
|
|
||||||
|
binding.slider.apply {
|
||||||
val slider = view.findViewById<Slider>(R.id.slider)
|
addAccentColor()
|
||||||
val duration = view.findViewById<TextView>(R.id.duration)
|
value = PreferenceUtil.audioFadeDuration.toFloat()
|
||||||
ColorStateList.valueOf(ThemeStore.accentColor(requireContext())).let {
|
updateText(value.toInt(), binding.duration)
|
||||||
slider.trackTintList = it
|
addOnChangeListener(Slider.OnChangeListener { _, value, fromUser ->
|
||||||
slider.thumbTintList = it
|
if (fromUser) {
|
||||||
|
updateText(value.toInt(), binding.duration)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
slider.value = PreferenceUtil.audioFadeDuration.toFloat()
|
|
||||||
updateText(slider.value.toInt(), duration)
|
|
||||||
slider.addOnChangeListener(Slider.OnChangeListener { _, value, fromUser ->
|
|
||||||
if (fromUser) {
|
|
||||||
updateText(value.toInt(), duration)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
return materialDialog(R.string.audio_fade_duration)
|
return materialDialog(R.string.audio_fade_duration)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.save) { _, _ -> updateDuration(slider.value.toInt()) }
|
.setPositiveButton(R.string.save) { _, _ -> updateDuration(binding.slider.value.toInt()) }
|
||||||
.setView(view)
|
.setView(binding.root)
|
||||||
.create()
|
.create()
|
||||||
.colorButtons()
|
.colorButtons()
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,10 @@ import androidx.core.graphics.BlendModeColorFilterCompat
|
||||||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.CategoryInfoAdapter
|
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.colorButtons
|
||||||
import code.name.monkey.retromusic.extensions.colorControlNormal
|
import code.name.monkey.retromusic.extensions.colorControlNormal
|
||||||
import code.name.monkey.retromusic.extensions.materialDialog
|
import code.name.monkey.retromusic.extensions.materialDialog
|
||||||
|
@ -51,15 +51,14 @@ class LibraryPreference @JvmOverloads constructor(
|
||||||
class LibraryPreferenceDialog : DialogFragment() {
|
class LibraryPreferenceDialog : DialogFragment() {
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val view = layoutInflater
|
val binding = PreferenceDialogLibraryCategoriesBinding.inflate(layoutInflater)
|
||||||
.inflate(R.layout.preference_dialog_library_categories, null)
|
|
||||||
|
|
||||||
val categoryAdapter = CategoryInfoAdapter()
|
val categoryAdapter = CategoryInfoAdapter()
|
||||||
val recyclerView = view.findViewById<RecyclerView>(R.id.recycler_view)
|
binding.recyclerView.apply {
|
||||||
recyclerView.layoutManager = LinearLayoutManager(activity)
|
layoutManager = LinearLayoutManager(activity)
|
||||||
recyclerView.adapter = categoryAdapter
|
adapter = categoryAdapter
|
||||||
categoryAdapter.attachToRecyclerView(recyclerView)
|
categoryAdapter.attachToRecyclerView(this)
|
||||||
|
}
|
||||||
|
|
||||||
return materialDialog(R.string.library_categories)
|
return materialDialog(R.string.library_categories)
|
||||||
.setNeutralButton(
|
.setNeutralButton(
|
||||||
|
@ -68,8 +67,8 @@ class LibraryPreferenceDialog : DialogFragment() {
|
||||||
updateCategories(PreferenceUtil.defaultCategories)
|
updateCategories(PreferenceUtil.defaultCategories)
|
||||||
}
|
}
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton( R.string.done) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
|
.setPositiveButton(R.string.done) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
|
||||||
.setView(view)
|
.setView(binding.root)
|
||||||
.create()
|
.create()
|
||||||
.colorButtons()
|
.colorButtons()
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,6 @@ import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||||
import androidx.core.graphics.BlendModeCompat.SRC_IN
|
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.appthemehelper.common.prefs.supportv7.ATEDialogPreference
|
||||||
import code.name.monkey.retromusic.App
|
import code.name.monkey.retromusic.App
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.databinding.PreferenceNowPlayingScreenItemBinding
|
||||||
import code.name.monkey.retromusic.extensions.*
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
||||||
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 nowPlayingScreen = values()[position]
|
||||||
|
|
||||||
val inflater = LayoutInflater.from(context)
|
val inflater = LayoutInflater.from(context)
|
||||||
val layout = inflater.inflate(
|
val binding = PreferenceNowPlayingScreenItemBinding.inflate(inflater, collection, true)
|
||||||
R.layout.preference_now_playing_screen_item,
|
Glide.with(context).load(nowPlayingScreen.drawableResId).into(binding.image)
|
||||||
collection,
|
binding.title.setText(nowPlayingScreen.titleRes)
|
||||||
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)
|
|
||||||
if (isNowPlayingThemes(nowPlayingScreen)) {
|
if (isNowPlayingThemes(nowPlayingScreen)) {
|
||||||
proText.show()
|
binding.proText.show()
|
||||||
proText.setText(R.string.pro)
|
binding.proText.setText(R.string.pro)
|
||||||
}else{
|
} else {
|
||||||
proText.hide()
|
binding.proText.hide()
|
||||||
}
|
}
|
||||||
return layout
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun destroyItem(
|
override fun destroyItem(
|
||||||
|
|
|
@ -69,6 +69,7 @@ interface Repository {
|
||||||
suspend fun recentAlbumsHome(): Home
|
suspend fun recentAlbumsHome(): Home
|
||||||
suspend fun favoritePlaylistHome(): Home
|
suspend fun favoritePlaylistHome(): Home
|
||||||
suspend fun suggestionsHome(): Home
|
suspend fun suggestionsHome(): Home
|
||||||
|
suspend fun suggestions(): List<Song>
|
||||||
suspend fun genresHome(): Home
|
suspend fun genresHome(): Home
|
||||||
suspend fun playlists(): Home
|
suspend fun playlists(): Home
|
||||||
suspend fun homeSections(): List<Home>
|
suspend fun homeSections(): List<Home>
|
||||||
|
@ -240,19 +241,15 @@ class RealRepository(
|
||||||
override suspend fun homeSections(): List<Home> {
|
override suspend fun homeSections(): List<Home> {
|
||||||
val homeSections = mutableListOf<Home>()
|
val homeSections = mutableListOf<Home>()
|
||||||
val sections: List<Home> = listOf(
|
val sections: List<Home> = listOf(
|
||||||
suggestionsHome(),
|
|
||||||
topArtistsHome(),
|
topArtistsHome(),
|
||||||
topAlbumsHome(),
|
topAlbumsHome(),
|
||||||
recentArtistsHome(),
|
recentArtistsHome(),
|
||||||
recentAlbumsHome(),
|
recentAlbumsHome(),
|
||||||
favoritePlaylistHome()
|
favoritePlaylistHome()
|
||||||
// genresHome()
|
|
||||||
)
|
)
|
||||||
for (section in sections) {
|
for (section in sections) {
|
||||||
if (section.arrayList.isNotEmpty()) {
|
if (section.arrayList.isNotEmpty()) {
|
||||||
if (section.homeSection != SUGGESTIONS || PreferenceUtil.homeSuggestions) {
|
homeSections.add(section)
|
||||||
homeSections.add(section)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return homeSections
|
return homeSections
|
||||||
|
@ -374,6 +371,13 @@ class RealRepository(
|
||||||
return suggestions
|
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 {
|
override suspend fun genresHome(): Home {
|
||||||
val genres = genreRepository.genres().shuffled()
|
val genres = genreRepository.genres().shuffled()
|
||||||
return Home(genres, GENRES, R.string.genres)
|
return Home(genres, GENRES, R.string.genres)
|
||||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.repository
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.provider.MediaStore.Audio.AudioColumns
|
import android.provider.MediaStore.Audio.AudioColumns
|
||||||
|
@ -42,11 +43,13 @@ interface SongRepository {
|
||||||
|
|
||||||
fun songs(query: String): List<Song>
|
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(cursor: Cursor?): Song
|
||||||
|
|
||||||
fun song(songId: Long): Song
|
fun song(songId: Long): Song
|
||||||
|
|
||||||
|
fun songsIgnoreBlacklist(uri: Uri): List<Song>
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealSongRepository(private val context: Context) : SongRepository {
|
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())))
|
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(
|
return songs(
|
||||||
makeSongCursor(
|
makeSongCursor(
|
||||||
AudioColumns.DATA + "=?",
|
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(
|
private fun getSongFromCursorImpl(
|
||||||
cursor: Cursor
|
cursor: Cursor
|
||||||
): Song {
|
): Song {
|
||||||
|
@ -128,40 +154,41 @@ class RealSongRepository(private val context: Context) : SongRepository {
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun makeSongCursor(
|
fun makeSongCursor(
|
||||||
|
|
||||||
selection: String?,
|
selection: String?,
|
||||||
selectionValues: Array<String>?,
|
selectionValues: Array<String>?,
|
||||||
sortOrder: String = PreferenceUtil.songSortOrder
|
sortOrder: String = PreferenceUtil.songSortOrder,
|
||||||
|
ignoreBlacklist: Boolean = false
|
||||||
): Cursor? {
|
): Cursor? {
|
||||||
var selectionFinal = selection
|
var selectionFinal = selection
|
||||||
var selectionValuesFinal = selectionValues
|
var selectionValuesFinal = selectionValues
|
||||||
selectionFinal = if (selection != null && selection.trim { it <= ' ' } != "") {
|
if (!ignoreBlacklist) {
|
||||||
"$IS_MUSIC AND $selectionFinal"
|
selectionFinal = if (selection != null && selection.trim { it <= ' ' } != "") {
|
||||||
} else {
|
"$IS_MUSIC AND $selectionFinal"
|
||||||
IS_MUSIC
|
} else {
|
||||||
}
|
IS_MUSIC
|
||||||
|
|
||||||
// Whitelist
|
|
||||||
if (PreferenceUtil.isWhiteList) {
|
|
||||||
selectionFinal =
|
|
||||||
selectionFinal + " AND " + AudioColumns.DATA + " LIKE ?"
|
|
||||||
selectionValuesFinal = addSelectionValues(
|
|
||||||
selectionValuesFinal, arrayListOf(
|
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).canonicalPath
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Blacklist
|
|
||||||
val paths = BlacklistStore.getInstance(context).paths
|
|
||||||
if (paths.isNotEmpty()) {
|
|
||||||
selectionFinal = generateBlacklistSelection(selectionFinal, paths.size)
|
|
||||||
selectionValuesFinal = addSelectionValues(selectionValuesFinal, paths)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whitelist
|
||||||
|
if (PreferenceUtil.isWhiteList) {
|
||||||
|
selectionFinal =
|
||||||
|
selectionFinal + " AND " + AudioColumns.DATA + " LIKE ?"
|
||||||
|
selectionValuesFinal = addSelectionValues(
|
||||||
|
selectionValuesFinal, arrayListOf(
|
||||||
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).canonicalPath
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Blacklist
|
||||||
|
val paths = BlacklistStore.getInstance(context).paths
|
||||||
|
if (paths.isNotEmpty()) {
|
||||||
|
selectionFinal = generateBlacklistSelection(selectionFinal, paths.size)
|
||||||
|
selectionValuesFinal = addSelectionValues(selectionValuesFinal, paths)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectionFinal =
|
||||||
|
selectionFinal + " AND " + Media.DURATION + ">= " + (PreferenceUtil.filterLength * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
selectionFinal =
|
|
||||||
selectionFinal + " AND " + Media.DURATION + ">= " + (PreferenceUtil.filterLength * 1000)
|
|
||||||
|
|
||||||
val uri = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
val uri = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||||
Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,8 +16,10 @@ package code.name.monkey.retromusic.service;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
|
import android.media.PlaybackParams;
|
||||||
import android.media.audiofx.AudioEffect;
|
import android.media.audiofx.AudioEffect;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
@ -26,29 +28,37 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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.R;
|
||||||
import code.name.monkey.retromusic.service.playback.Playback;
|
import code.name.monkey.retromusic.service.playback.Playback;
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||||
|
|
||||||
/** @author Andrew Neal, Karim Abou Zeid (kabouzeid) */
|
/**
|
||||||
|
* @author Andrew Neal, Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
public class MultiPlayer
|
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();
|
public static final String TAG = MultiPlayer.class.getSimpleName();
|
||||||
|
|
||||||
private MediaPlayer mCurrentMediaPlayer = new MediaPlayer();
|
private MediaPlayer mCurrentMediaPlayer = new MediaPlayer();
|
||||||
private MediaPlayer mNextMediaPlayer;
|
private MediaPlayer mNextMediaPlayer;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@Nullable
|
@Nullable
|
||||||
private Playback.PlaybackCallbacks callbacks;
|
private Playback.PlaybackCallbacks callbacks;
|
||||||
|
|
||||||
private boolean mIsInitialized = false;
|
private boolean mIsInitialized = false;
|
||||||
|
|
||||||
/** Constructor of <code>MultiPlayer</code> */
|
/**
|
||||||
|
* Constructor of <code>MultiPlayer</code>
|
||||||
|
*/
|
||||||
MultiPlayer(final Context context) {
|
MultiPlayer(final Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +77,7 @@ public class MultiPlayer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param player The {@link MediaPlayer} to use
|
* @param player The {@link MediaPlayer} to use
|
||||||
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
|
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
|
||||||
* @return True if the <code>player</code> has been prepared and is ready to play, false otherwise
|
* @return True if the <code>player</code> has been prepared and is ready to play, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean setDataSourceImpl(@NonNull final MediaPlayer player, @NonNull final String path) {
|
private boolean setDataSourceImpl(@NonNull final MediaPlayer player, @NonNull final String path) {
|
||||||
|
@ -82,6 +92,7 @@ public class MultiPlayer
|
||||||
} else {
|
} else {
|
||||||
player.setDataSource(path);
|
player.setDataSource(path);
|
||||||
}
|
}
|
||||||
|
setPlaybackSpeedPitch(player);
|
||||||
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||||
player.prepare();
|
player.prepare();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -155,13 +166,17 @@ public class MultiPlayer
|
||||||
this.callbacks = callbacks;
|
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
|
@Override
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return mIsInitialized;
|
return mIsInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Starts or resumes playback. */
|
/**
|
||||||
|
* Starts or resumes playback.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean start() {
|
public boolean start() {
|
||||||
try {
|
try {
|
||||||
|
@ -172,14 +187,18 @@ public class MultiPlayer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resets the MediaPlayer to its uninitialized state. */
|
/**
|
||||||
|
* Resets the MediaPlayer to its uninitialized state.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
mCurrentMediaPlayer.reset();
|
mCurrentMediaPlayer.reset();
|
||||||
mIsInitialized = false;
|
mIsInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Releases resources associated with this MediaPlayer object. */
|
/**
|
||||||
|
* Releases resources associated with this MediaPlayer object.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
stop();
|
stop();
|
||||||
|
@ -187,9 +206,12 @@ public class MultiPlayer
|
||||||
if (mNextMediaPlayer != null) {
|
if (mNextMediaPlayer != null) {
|
||||||
mNextMediaPlayer.release();
|
mNextMediaPlayer.release();
|
||||||
}
|
}
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context).unregisterOnSharedPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pauses playback. Call start() to resume. */
|
/**
|
||||||
|
* Pauses playback. Call start() to resume.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean pause() {
|
public boolean pause() {
|
||||||
try {
|
try {
|
||||||
|
@ -200,7 +222,9 @@ public class MultiPlayer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks whether the MultiPlayer is playing. */
|
/**
|
||||||
|
* Checks whether the MultiPlayer is playing.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
return mIsInitialized && mCurrentMediaPlayer.isPlaying();
|
return mIsInitialized && mCurrentMediaPlayer.isPlaying();
|
||||||
|
@ -291,7 +315,9 @@ public class MultiPlayer
|
||||||
return mCurrentMediaPlayer.getAudioSessionId();
|
return mCurrentMediaPlayer.getAudioSessionId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
|
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
|
||||||
mIsInitialized = false;
|
mIsInitialized = false;
|
||||||
|
@ -308,7 +334,9 @@ public class MultiPlayer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCompletion(final MediaPlayer mp) {
|
public void onCompletion(final MediaPlayer mp) {
|
||||||
if (mp.equals(mCurrentMediaPlayer) && mNextMediaPlayer != null) {
|
if (mp.equals(mCurrentMediaPlayer) && mNextMediaPlayer != null) {
|
||||||
|
@ -323,6 +351,26 @@ public class MultiPlayer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.CLASSIC_NOTIFICATION;
|
||||||
import static code.name.monkey.retromusic.ConstantsKt.COLORED_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.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.ConstantsKt.TOGGLE_HEADSET;
|
||||||
import static code.name.monkey.retromusic.service.AudioFader.startFadeAnimator;
|
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.activities.LockScreenActivity;
|
||||||
import code.name.monkey.retromusic.appwidgets.AppWidgetBig;
|
import code.name.monkey.retromusic.appwidgets.AppWidgetBig;
|
||||||
import code.name.monkey.retromusic.appwidgets.AppWidgetCard;
|
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.AppWidgetClassic;
|
||||||
import code.name.monkey.retromusic.appwidgets.AppWidgetMD3;
|
import code.name.monkey.retromusic.appwidgets.AppWidgetMD3;
|
||||||
import code.name.monkey.retromusic.appwidgets.AppWidgetSmall;
|
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 META_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".metachanged";
|
||||||
public static final String QUEUE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".queuechanged";
|
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 PLAY_STATE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".playstatechanged";
|
||||||
|
|
||||||
public static final String FAVORITE_STATE_CHANGED =
|
public static final String FAVORITE_STATE_CHANGED =
|
||||||
RETRO_MUSIC_PACKAGE_NAME + "favoritestatechanged";
|
RETRO_MUSIC_PACKAGE_NAME + "favoritestatechanged";
|
||||||
public static final String REPEAT_MODE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".repeatmodechanged";
|
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 AppWidgetMD3 appWidgetMd3 = AppWidgetMD3.Companion.getInstance();
|
||||||
|
|
||||||
|
private final AppWidgetCircle appWidgetCircle = AppWidgetCircle.Companion.getInstance();
|
||||||
|
|
||||||
private final BroadcastReceiver widgetIntentReceiver =
|
private final BroadcastReceiver widgetIntentReceiver =
|
||||||
new BroadcastReceiver() {
|
new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -236,6 +241,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
appWidgetMd3.performUpdate(MusicService.this, ids);
|
appWidgetMd3.performUpdate(MusicService.this, ids);
|
||||||
break;
|
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) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
playingNotification.updateFavorite(getCurrentSong(), MusicService.this::startForegroundOrNotify);
|
playingNotification.updateFavorite(getCurrentSong(), MusicService.this::startForegroundOrNotify);
|
||||||
startForegroundOrNotify();
|
startForegroundOrNotify();
|
||||||
|
appWidgetCircle.notifyChange(MusicService.this, FAVORITE_STATE_CHANGED);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final BroadcastReceiver lockScreenReceiver =
|
private final BroadcastReceiver lockScreenReceiver =
|
||||||
|
@ -431,9 +441,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
registerReceiver(lockScreenReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
registerReceiver(lockScreenReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
||||||
|
|
||||||
setSessionToken(mediaSession.getSessionToken());
|
setSessionToken(mediaSession.getSessionToken());
|
||||||
if (VersionUtils.INSTANCE.hasMarshmallow()) {
|
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
notificationManager = getSystemService(NotificationManager.class);
|
|
||||||
}
|
|
||||||
initNotification();
|
initNotification();
|
||||||
|
|
||||||
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
||||||
|
@ -939,8 +947,11 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
break;
|
break;
|
||||||
case CLASSIC_NOTIFICATION:
|
case CLASSIC_NOTIFICATION:
|
||||||
updateNotification();
|
updateNotification();
|
||||||
playingNotification.setPlaying(isPlaying());
|
|
||||||
playingNotification.updateMetadata(getCurrentSong(), this::startForegroundOrNotify);
|
playingNotification.updateMetadata(getCurrentSong(), this::startForegroundOrNotify);
|
||||||
|
playingNotification.setPlaying(isPlaying(),this::startForegroundOrNotify);
|
||||||
|
break;
|
||||||
|
case PLAYBACK_SPEED:
|
||||||
|
updateMediaSessionPlaybackState();
|
||||||
break;
|
break;
|
||||||
case TOGGLE_HEADSET:
|
case TOGGLE_HEADSET:
|
||||||
registerHeadsetEvents();
|
registerHeadsetEvents();
|
||||||
|
@ -1336,7 +1347,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
.setState(
|
.setState(
|
||||||
isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||||
getSongProgressMillis(),
|
getSongProgressMillis(),
|
||||||
1);
|
PreferenceUtil.INSTANCE.getPlaybackSpeed());
|
||||||
|
|
||||||
setCustomAction(stateBuilder);
|
setCustomAction(stateBuilder);
|
||||||
|
|
||||||
|
@ -1426,7 +1437,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
savePositionInTrack();
|
savePositionInTrack();
|
||||||
}
|
}
|
||||||
songPlayCountHelper.notifyPlayStateChanged(isPlaying);
|
songPlayCountHelper.notifyPlayStateChanged(isPlaying);
|
||||||
playingNotification.setPlaying(isPlaying);
|
playingNotification.setPlaying(isPlaying, this::startForegroundOrNotify);
|
||||||
startForegroundOrNotify();
|
startForegroundOrNotify();
|
||||||
break;
|
break;
|
||||||
case FAVORITE_STATE_CHANGED:
|
case FAVORITE_STATE_CHANGED:
|
||||||
|
@ -1617,6 +1628,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
appWidgetCard.notifyChange(this, what);
|
appWidgetCard.notifyChange(this, what);
|
||||||
appWidgetText.notifyChange(this, what);
|
appWidgetText.notifyChange(this, what);
|
||||||
appWidgetMd3.notifyChange(this, what);
|
appWidgetMd3.notifyChange(this, what);
|
||||||
|
appWidgetCircle.notifyChange(this, what);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
|
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