Merge pull request #1178 from prathameshmm02/dev
Bug Fixes & Improvements
This commit is contained in:
commit
350cba2042
64 changed files with 1275 additions and 749 deletions
|
@ -15,8 +15,8 @@ android {
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
applicationId "code.name.monkey.retromusic"
|
applicationId "code.name.monkey.retromusic"
|
||||||
versionCode 10544
|
versionCode 10545
|
||||||
versionName '5.4.1 ' + "_" + getDate()
|
versionName '5.4.2 ' + "_" + getDate()
|
||||||
|
|
||||||
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')}\"")
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,8 @@ dependencies {
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||||
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.2'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
implementation 'androidx.recyclerview:recyclerview:1.3.0-alpha01'
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.2.0-beta01'
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
implementation 'androidx.palette:palette-ktx:1.0.0'
|
implementation 'androidx.palette:palette-ktx:1.0.0'
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ dependencies {
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
||||||
|
|
||||||
def room_version = '2.4.0-beta02'
|
def room_version = '2.4.0-rc01'
|
||||||
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"
|
||||||
|
@ -138,7 +138,7 @@ dependencies {
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
||||||
def kotlin_coroutines_version = '1.5.2'
|
def kotlin_coroutines_version = '1.6.0-RC'
|
||||||
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"
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
<activity android:name=".activities.PermissionActivity" />
|
<activity android:name=".activities.PermissionActivity" />
|
||||||
<activity android:name=".activities.LockScreenActivity" />
|
<activity android:name=".activities.LockScreenActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name="code.name.monkey.retromusic.fragments.backup.RestoreActivity"
|
android:name=".fragments.backup.RestoreActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
@ -256,13 +256,25 @@
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/app_widget_card_info" />
|
android:resource="@xml/app_widget_card_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
<receiver
|
||||||
|
android:name=".appwidgets.AppWidgetMD3"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/app_widget_md3_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_md3_info" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.MusicService"
|
android:name=".service.MusicService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
|
||||||
android:foregroundServiceType="mediaPlayback"
|
android:foregroundServiceType="mediaPlayback"
|
||||||
|
android:label="@string/app_name"
|
||||||
tools:ignore="ExportedService">
|
tools:ignore="ExportedService">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.media.browse.MediaBrowserService" />
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
|
|
|
@ -24,6 +24,7 @@ import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||||
import code.name.monkey.retromusic.databinding.ActivityDriveModeBinding
|
import code.name.monkey.retromusic.databinding.ActivityDriveModeBinding
|
||||||
|
import code.name.monkey.retromusic.extensions.setDrawUnderStatusBar
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
import code.name.monkey.retromusic.glide.BlurTransformation
|
import code.name.monkey.retromusic.glide.BlurTransformation
|
||||||
import code.name.monkey.retromusic.glide.GlideApp
|
import code.name.monkey.retromusic.glide.GlideApp
|
||||||
|
|
|
@ -24,7 +24,7 @@ import androidx.core.view.ViewCompat
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||||
import code.name.monkey.retromusic.databinding.ActivityLockScreenBinding
|
import code.name.monkey.retromusic.databinding.ActivityLockScreenBinding
|
||||||
import code.name.monkey.retromusic.extensions.whichFragment
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.fragments.player.lockscreen.LockScreenControlsFragment
|
import code.name.monkey.retromusic.fragments.player.lockscreen.LockScreenControlsFragment
|
||||||
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
|
||||||
|
@ -47,7 +47,7 @@ class LockScreenActivity : AbsMusicServiceActivity() {
|
||||||
binding = ActivityLockScreenBinding.inflate(layoutInflater)
|
binding = ActivityLockScreenBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
hideStatusBar()
|
hideStatusBar()
|
||||||
setStatusbarColorAuto()
|
setStatusBarColorAuto()
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
|
|
||||||
val config = SlidrConfig.Builder().listener(object : SlidrListener {
|
val config = SlidrConfig.Builder().listener(object : SlidrListener {
|
||||||
|
|
|
@ -26,9 +26,7 @@ import androidx.navigation.ui.setupWithNavController
|
||||||
import code.name.monkey.retromusic.*
|
import code.name.monkey.retromusic.*
|
||||||
import code.name.monkey.retromusic.activities.base.AbsCastActivity
|
import code.name.monkey.retromusic.activities.base.AbsCastActivity
|
||||||
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
|
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
|
||||||
import code.name.monkey.retromusic.extensions.currentFragment
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.extra
|
|
||||||
import code.name.monkey.retromusic.extensions.findNavController
|
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewFragment
|
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewFragment
|
||||||
import code.name.monkey.retromusic.fragments.home.HomeFragment
|
import code.name.monkey.retromusic.fragments.home.HomeFragment
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
|
@ -136,8 +134,8 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
|
||||||
PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
|
PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
|
||||||
val expand = extra<Boolean>(EXPAND_PANEL).value ?: false
|
val expand = extra<Boolean>(EXPAND_PANEL).value ?: false
|
||||||
if (expand && PreferenceUtil.isExpandPanel) {
|
if (expand && PreferenceUtil.isExpandPanel) {
|
||||||
setBottomNavVisibility(false)
|
|
||||||
fromNotification = true
|
fromNotification = true
|
||||||
|
slidingPanel.bringToFront()
|
||||||
expandPanel()
|
expandPanel()
|
||||||
intent.removeExtra(EXPAND_PANEL)
|
intent.removeExtra(EXPAND_PANEL)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||||
import code.name.monkey.retromusic.databinding.ActivityPermissionBinding
|
import code.name.monkey.retromusic.databinding.ActivityPermissionBinding
|
||||||
import code.name.monkey.retromusic.extensions.accentBackgroundColor
|
import code.name.monkey.retromusic.extensions.accentBackgroundColor
|
||||||
|
import code.name.monkey.retromusic.extensions.setStatusBarColorAuto
|
||||||
|
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||||
import code.name.monkey.retromusic.extensions.show
|
import code.name.monkey.retromusic.extensions.show
|
||||||
import code.name.monkey.retromusic.util.RingtoneManager
|
import code.name.monkey.retromusic.util.RingtoneManager
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ class PermissionActivity : AbsMusicServiceActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityPermissionBinding.inflate(layoutInflater)
|
binding = ActivityPermissionBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setStatusbarColorAuto()
|
setStatusBarColorAuto()
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
setupTitle()
|
setupTitle()
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
||||||
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.ActivityProVersionBinding
|
import code.name.monkey.retromusic.databinding.ActivityProVersionBinding
|
||||||
|
import code.name.monkey.retromusic.extensions.setDrawUnderStatusBar
|
||||||
|
import code.name.monkey.retromusic.extensions.setLightStatusBar
|
||||||
|
import code.name.monkey.retromusic.extensions.setStatusBarColor
|
||||||
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
|
||||||
|
|
||||||
|
@ -41,8 +44,8 @@ class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityProVersionBinding.inflate(layoutInflater)
|
binding = ActivityProVersionBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setStatusbarColor(Color.TRANSPARENT)
|
setStatusBarColor(Color.TRANSPARENT)
|
||||||
setLightStatusbar(false)
|
setLightStatusBar(false)
|
||||||
binding.toolbar.navigationIcon?.setTint(Color.WHITE)
|
binding.toolbar.navigationIcon?.setTint(Color.WHITE)
|
||||||
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,7 @@ import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsThemeActivity
|
import code.name.monkey.retromusic.activities.base.AbsThemeActivity
|
||||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
||||||
import code.name.monkey.retromusic.databinding.ActivitySettingsBinding
|
import code.name.monkey.retromusic.databinding.ActivitySettingsBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyToolbar
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.extra
|
|
||||||
import code.name.monkey.retromusic.extensions.findNavController
|
|
||||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.color.ColorCallback
|
import com.afollestad.materialdialogs.color.ColorCallback
|
||||||
|
|
||||||
|
@ -38,7 +35,7 @@ class SettingsActivity : AbsThemeActivity(), ColorCallback, OnThemeChangedListen
|
||||||
setDrawUnderStatusBar()
|
setDrawUnderStatusBar()
|
||||||
val mSavedInstanceState = extra<Bundle>(TAG).value ?: savedInstanceState
|
val mSavedInstanceState = extra<Bundle>(TAG).value ?: savedInstanceState
|
||||||
super.onCreate(mSavedInstanceState)
|
super.onCreate(mSavedInstanceState)
|
||||||
setLightStatusbarAuto(surfaceColor())
|
setLightStatusBarAuto(surfaceColor())
|
||||||
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupToolbar()
|
setupToolbar()
|
||||||
|
|
|
@ -28,6 +28,10 @@ import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||||
import code.name.monkey.retromusic.databinding.ActivityShareInstagramBinding
|
import code.name.monkey.retromusic.databinding.ActivityShareInstagramBinding
|
||||||
|
import code.name.monkey.retromusic.extensions.applyToolbar
|
||||||
|
import code.name.monkey.retromusic.extensions.setDrawUnderStatusBar
|
||||||
|
import code.name.monkey.retromusic.extensions.setLightStatusBar
|
||||||
|
import code.name.monkey.retromusic.extensions.setStatusBarColor
|
||||||
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.glide.RetroMusicColoredTarget
|
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
||||||
|
@ -60,7 +64,7 @@ class ShareInstagramStory : AbsBaseActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityShareInstagramBinding.inflate(layoutInflater)
|
binding = ActivityShareInstagramBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setStatusbarColor(Color.TRANSPARENT)
|
setStatusBarColor(Color.TRANSPARENT)
|
||||||
|
|
||||||
binding.toolbar.setBackgroundColor(Color.TRANSPARENT)
|
binding.toolbar.setBackgroundColor(Color.TRANSPARENT)
|
||||||
setSupportActionBar(binding.toolbar)
|
setSupportActionBar(binding.toolbar)
|
||||||
|
@ -104,7 +108,7 @@ class ShareInstagramStory : AbsBaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColors(colorLight: Boolean, color: Int) {
|
private fun setColors(colorLight: Boolean, color: Int) {
|
||||||
setLightStatusbar(colorLight)
|
setLightStatusBar(colorLight)
|
||||||
binding.toolbar.setTitleTextColor(
|
binding.toolbar.setTitleTextColor(
|
||||||
MaterialValueHelper.getPrimaryTextColor(
|
MaterialValueHelper.getPrimaryTextColor(
|
||||||
this@ShareInstagramStory,
|
this@ShareInstagramStory,
|
||||||
|
|
|
@ -37,6 +37,8 @@ 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.extensions.setStatusBarColorAuto
|
||||||
|
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||||
import code.name.monkey.retromusic.extensions.textColorPrimary
|
import code.name.monkey.retromusic.extensions.textColorPrimary
|
||||||
import code.name.monkey.retromusic.extensions.textColorSecondary
|
import code.name.monkey.retromusic.extensions.textColorSecondary
|
||||||
import com.anjlab.android.iab.v3.BillingProcessor
|
import com.anjlab.android.iab.v3.BillingProcessor
|
||||||
|
@ -73,7 +75,7 @@ class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingH
|
||||||
binding = ActivityDonationBinding.inflate(layoutInflater)
|
binding = ActivityDonationBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
setStatusbarColorAuto()
|
setStatusBarColorAuto()
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
|
|
||||||
setupToolbar()
|
setupToolbar()
|
||||||
|
|
|
@ -17,6 +17,8 @@ import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsThemeActivity
|
import code.name.monkey.retromusic.activities.base.AbsThemeActivity
|
||||||
import code.name.monkey.retromusic.databinding.ActivityWhatsNewBinding
|
import code.name.monkey.retromusic.databinding.ActivityWhatsNewBinding
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
|
import code.name.monkey.retromusic.extensions.setLightStatusBarAuto
|
||||||
|
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.lastVersion
|
import code.name.monkey.retromusic.util.PreferenceUtil.lastVersion
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
|
@ -29,7 +31,7 @@ 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(resolveColor(this, R.attr.colorSurface))
|
setLightStatusBarAuto(resolveColor(this, R.attr.colorSurface))
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||||
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.activities.base
|
package code.name.monkey.retromusic.activities.base
|
||||||
|
|
||||||
import android.animation.Animator
|
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -25,6 +24,7 @@ import android.widget.FrameLayout
|
||||||
import androidx.core.animation.doOnEnd
|
import androidx.core.animation.doOnEnd
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
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
|
||||||
|
@ -67,11 +67,10 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
companion object {
|
companion object {
|
||||||
val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName
|
val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName
|
||||||
var fromNotification: Boolean = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fromNotification = false
|
||||||
private var windowInsets: WindowInsetsCompat? = null
|
private var windowInsets: WindowInsetsCompat? = null
|
||||||
private var bottomNavAnimator: Animator? = null
|
|
||||||
protected val libraryViewModel by viewModel<LibraryViewModel>()
|
protected val libraryViewModel by viewModel<LibraryViewModel>()
|
||||||
private lateinit var bottomSheetBehavior: RetroBottomSheetBehavior<FrameLayout>
|
private lateinit var bottomSheetBehavior: RetroBottomSheetBehavior<FrameLayout>
|
||||||
private var playerFragment: AbsPlayerFragment? = null
|
private var playerFragment: AbsPlayerFragment? = null
|
||||||
|
@ -93,21 +92,19 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
when (newState) {
|
when (newState) {
|
||||||
STATE_EXPANDED -> {
|
STATE_EXPANDED -> {
|
||||||
onPanelExpanded()
|
onPanelExpanded()
|
||||||
|
|
||||||
}
|
}
|
||||||
STATE_COLLAPSED -> {
|
STATE_COLLAPSED -> {
|
||||||
onPanelCollapsed()
|
onPanelCollapsed()
|
||||||
if (fromNotification) {
|
|
||||||
hideBottomSheet(MusicPlayerRemote.playingQueue.isEmpty())
|
|
||||||
fromNotification = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
STATE_SETTLING, STATE_DRAGGING -> {
|
STATE_SETTLING, STATE_DRAGGING -> {
|
||||||
if (fromNotification) {
|
if (fromNotification) {
|
||||||
bottomNavigationView.isVisible = true
|
binding.bottomNavigationView.bringToFront()
|
||||||
|
fromNotification = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
println("Do something")
|
println("Do a flip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +172,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
if (progress < 0) return
|
if (progress < 0) return
|
||||||
val alpha = 1 - progress
|
val alpha = 1 - progress
|
||||||
miniPlayerFragment?.view?.alpha = 1 - (progress / 0.2F)
|
miniPlayerFragment?.view?.alpha = 1 - (progress / 0.2F)
|
||||||
miniPlayerFragment?.view?.visibility = if (alpha == 0f) View.GONE else View.VISIBLE
|
miniPlayerFragment?.view?.isGone = alpha == 0f
|
||||||
binding.bottomNavigationView.translationY = progress * 500
|
binding.bottomNavigationView.translationY = progress * 500
|
||||||
binding.bottomNavigationView.alpha = alpha
|
binding.bottomNavigationView.alpha = alpha
|
||||||
binding.playerFragmentContainer.alpha = (progress - 0.2F) / 0.2F
|
binding.playerFragmentContainer.alpha = (progress - 0.2F) / 0.2F
|
||||||
|
@ -184,9 +181,9 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
open fun onPanelCollapsed() {
|
open fun onPanelCollapsed() {
|
||||||
setMiniPlayerAlphaProgress(0F)
|
setMiniPlayerAlphaProgress(0F)
|
||||||
// restore values
|
// restore values
|
||||||
super.setLightStatusbarAuto(surfaceColor())
|
setLightStatusBarAuto(surfaceColor())
|
||||||
super.setLightNavigationAuto()
|
setLightNavigationAuto()
|
||||||
super.setTaskDescriptionColor(taskColor)
|
setTaskDescriptionColor(taskColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun onPanelExpanded() {
|
open fun onPanelExpanded() {
|
||||||
|
@ -217,6 +214,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
|
|
||||||
val bottomNavigationView get() = binding.bottomNavigationView
|
val bottomNavigationView get() = binding.bottomNavigationView
|
||||||
|
|
||||||
|
val slidingPanel get() = binding.slidingPanel
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
override fun onServiceConnected() {
|
||||||
super.onServiceConnected()
|
super.onServiceConnected()
|
||||||
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||||
|
@ -251,32 +250,31 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
collapsePanel()
|
collapsePanel()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onPaletteColorChanged() {
|
private fun onPaletteColorChanged() {
|
||||||
if (panelState == STATE_EXPANDED) {
|
if (panelState == STATE_EXPANDED) {
|
||||||
super.setTaskDescriptionColor(paletteColor)
|
setTaskDescColor(paletteColor)
|
||||||
val isColorLight = ColorUtil.isColorLight(paletteColor)
|
val isColorLight = ColorUtil.isColorLight(paletteColor)
|
||||||
if (PreferenceUtil.isAdaptiveColor && (nowPlayingScreen == Normal || nowPlayingScreen == Flat)) {
|
if (PreferenceUtil.isAdaptiveColor && (nowPlayingScreen == Normal || nowPlayingScreen == Flat)) {
|
||||||
super.setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
super.setLightStatusbar(isColorLight)
|
setLightStatusBar(isColorLight)
|
||||||
} else if (nowPlayingScreen == Card || nowPlayingScreen == Blur || nowPlayingScreen == BlurCard) {
|
} else if (nowPlayingScreen == Card || nowPlayingScreen == Blur || nowPlayingScreen == BlurCard) {
|
||||||
super.setLightStatusbar(false)
|
setLightStatusBar(false)
|
||||||
super.setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
} else if (nowPlayingScreen == Color || nowPlayingScreen == Tiny || nowPlayingScreen == Gradient) {
|
} else if (nowPlayingScreen == Color || nowPlayingScreen == Tiny || nowPlayingScreen == Gradient) {
|
||||||
super.setLightNavigationBar(isColorLight)
|
setLightNavigationBar(isColorLight)
|
||||||
super.setLightStatusbar(isColorLight)
|
setLightStatusBar(isColorLight)
|
||||||
} else if (nowPlayingScreen == Full) {
|
} else if (nowPlayingScreen == Full) {
|
||||||
super.setLightNavigationBar(isColorLight)
|
setLightNavigationBar(isColorLight)
|
||||||
super.setLightStatusbar(false)
|
setLightStatusBar(false)
|
||||||
} else if (nowPlayingScreen == Classic) {
|
} else if (nowPlayingScreen == Classic) {
|
||||||
super.setLightStatusbar(false)
|
setLightStatusBar(false)
|
||||||
} else if (nowPlayingScreen == Fit) {
|
} else if (nowPlayingScreen == Fit) {
|
||||||
super.setLightStatusbar(false)
|
setLightStatusBar(false)
|
||||||
} else {
|
} else {
|
||||||
super.setLightStatusbar(
|
setLightStatusBar(
|
||||||
ColorUtil.isColorLight(
|
ColorUtil.isColorLight(
|
||||||
ATHUtil.resolveColor(
|
ATHUtil.resolveColor(
|
||||||
this,
|
this,
|
||||||
|
@ -284,15 +282,15 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
super.setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTaskDescriptionColor(color: Int) {
|
private fun setTaskDescColor(color: Int) {
|
||||||
taskColor = color
|
taskColor = color
|
||||||
if (panelState == STATE_COLLAPSED) {
|
if (panelState == STATE_COLLAPSED) {
|
||||||
super.setTaskDescriptionColor(color)
|
setTaskDescriptionColor(color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,53 +317,63 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setBottomNavVisibility(visible: Boolean, animate: Boolean = false) {
|
fun setBottomNavVisibility(visible: Boolean, animate: Boolean = false) {
|
||||||
binding.bottomNavigationView.isVisible = visible
|
val translationY =
|
||||||
hideBottomSheet(MusicPlayerRemote.playingQueue.isEmpty(), animate)
|
if (visible) 0F else dip(R.dimen.bottom_nav_height).toFloat() + windowInsets.safeGetBottomInsets()
|
||||||
|
if (animate) {
|
||||||
|
binding.bottomNavigationView.translateYAnimate(translationY).doOnEnd {
|
||||||
|
if (visible && bottomSheetBehavior.state != STATE_EXPANDED) {
|
||||||
|
binding.bottomNavigationView.bringToFront()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.bottomNavigationView.translationY =
|
||||||
|
translationY
|
||||||
|
if (visible && bottomSheetBehavior.state != STATE_EXPANDED) {
|
||||||
|
binding.bottomNavigationView.bringToFront()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideBottomSheet(
|
||||||
|
hide = MusicPlayerRemote.playingQueue.isEmpty(),
|
||||||
|
animate = animate,
|
||||||
|
isBottomNavVisible = visible
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideBottomSheet(hide: Boolean, animate: Boolean = false) {
|
fun hideBottomSheet(
|
||||||
|
hide: Boolean,
|
||||||
|
animate: Boolean = false,
|
||||||
|
isBottomNavVisible: Boolean = bottomNavigationView.isVisible
|
||||||
|
) {
|
||||||
val heightOfBar =
|
val heightOfBar =
|
||||||
windowInsets.safeGetBottomInsets() +
|
windowInsets.safeGetBottomInsets() +
|
||||||
if (MusicPlayerRemote.isCasting) dip(R.dimen.cast_mini_player_height) else dip(R.dimen.mini_player_height)
|
if (MusicPlayerRemote.isCasting) dip(R.dimen.cast_mini_player_height) else dip(R.dimen.mini_player_height)
|
||||||
val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height)
|
val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height)
|
||||||
val isVisible = binding.bottomNavigationView.isVisible
|
|
||||||
if (hide) {
|
if (hide) {
|
||||||
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets()
|
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets()
|
||||||
bottomSheetBehavior.state = STATE_COLLAPSED
|
bottomSheetBehavior.state = STATE_COLLAPSED
|
||||||
libraryViewModel.setFabMargin(if (isVisible) dip(R.dimen.bottom_nav_height) else 0)
|
libraryViewModel.setFabMargin(if (isBottomNavVisible) dip(R.dimen.bottom_nav_height) else 0)
|
||||||
ViewCompat.setElevation(binding.slidingPanel, 0f)
|
ViewCompat.setElevation(binding.slidingPanel, 0f)
|
||||||
ViewCompat.setElevation(binding.bottomNavigationView, 10f)
|
ViewCompat.setElevation(binding.bottomNavigationView, 10f)
|
||||||
} else {
|
} else {
|
||||||
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||||
|
|
||||||
ViewCompat.setElevation(binding.slidingPanel, 10f)
|
ViewCompat.setElevation(binding.slidingPanel, 10f)
|
||||||
ViewCompat.setElevation(binding.bottomNavigationView, 10f)
|
ViewCompat.setElevation(binding.bottomNavigationView, 10f)
|
||||||
if (isVisible) {
|
if (isBottomNavVisible) {
|
||||||
println("List")
|
println("List")
|
||||||
if (animate) {
|
if (animate) {
|
||||||
bottomNavAnimator?.end()
|
|
||||||
bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs)
|
bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs)
|
||||||
bottomNavAnimator = binding.bottomNavigationView.translateYAnimate(0F)
|
|
||||||
} else {
|
} else {
|
||||||
bottomSheetBehavior.peekHeight = heightOfBarWithTabs
|
bottomSheetBehavior.peekHeight = heightOfBarWithTabs
|
||||||
binding.bottomNavigationView.translationY = 0F
|
|
||||||
}
|
}
|
||||||
binding.bottomNavigationView.bringToFront()
|
|
||||||
libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height_expanded))
|
libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height_expanded))
|
||||||
} else {
|
} else {
|
||||||
println("Details")
|
println("Details")
|
||||||
if (animate) {
|
if (animate) {
|
||||||
bottomSheetBehavior.peekHeightAnimate(heightOfBar)
|
bottomSheetBehavior.peekHeightAnimate(heightOfBar).doOnEnd {
|
||||||
bottomNavAnimator?.end()
|
|
||||||
bottomNavAnimator =
|
|
||||||
bottomNavigationView.translateYAnimate(dip(R.dimen.bottom_nav_height).toFloat())
|
|
||||||
bottomNavAnimator?.doOnEnd {
|
|
||||||
binding.slidingPanel.bringToFront()
|
binding.slidingPanel.bringToFront()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bottomSheetBehavior.peekHeight = heightOfBar
|
bottomSheetBehavior.peekHeight = heightOfBar
|
||||||
binding.bottomNavigationView.translationY =
|
|
||||||
dip(R.dimen.bottom_nav_height).toFloat()
|
|
||||||
binding.slidingPanel.bringToFront()
|
binding.slidingPanel.bringToFront()
|
||||||
}
|
}
|
||||||
libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height))
|
libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height))
|
||||||
|
|
|
@ -16,28 +16,16 @@ package code.name.monkey.retromusic.activities.base
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
|
||||||
import code.name.monkey.appthemehelper.ATH
|
|
||||||
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.ATHUtil
|
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
|
||||||
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.surfaceColor
|
|
||||||
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.theme.ThemeManager
|
import code.name.monkey.retromusic.util.theme.ThemeManager
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -53,9 +41,8 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
setImmersiveFullscreen()
|
setImmersiveFullscreen()
|
||||||
registerSystemUiVisibility()
|
registerSystemUiVisibility()
|
||||||
toggleScreenOn()
|
toggleScreenOn()
|
||||||
setDrawUnderNavigationBar()
|
|
||||||
setLightNavigationAuto()
|
setLightNavigationAuto()
|
||||||
setLightStatusbarAuto(surfaceColor())
|
setLightStatusBarAuto(surfaceColor())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTheme() {
|
private fun updateTheme() {
|
||||||
|
@ -71,14 +58,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleScreenOn() {
|
|
||||||
if (PreferenceUtil.isScreenOnEnabled) {
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
||||||
} else {
|
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
super.onWindowFocusChanged(hasFocus)
|
super.onWindowFocusChanged(hasFocus)
|
||||||
if (hasFocus) {
|
if (hasFocus) {
|
||||||
|
@ -90,95 +69,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideStatusBar() {
|
|
||||||
hideStatusBar(PreferenceUtil.isFullScreenMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hideStatusBar(fullscreen: Boolean) {
|
|
||||||
val statusBar = window.decorView.rootView.findViewById<View>(R.id.status_bar)
|
|
||||||
if (statusBar != null) {
|
|
||||||
statusBar.visibility = if (fullscreen) View.GONE else View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDrawUnderStatusBar() {
|
|
||||||
RetroUtil.setAllowDrawUnderStatusBar(window)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setDrawUnderNavigationBar() {
|
|
||||||
RetroUtil.setAllowDrawUnderNavigationBar(window)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This will set the color of the view with the id "status_bar" on KitKat and Lollipop. On
|
|
||||||
* Lollipop if no such view is found it will set the statusbar color using the native method.
|
|
||||||
*
|
|
||||||
* @param color the new statusbar color (will be shifted down on Lollipop and above)
|
|
||||||
*/
|
|
||||||
fun setStatusbarColor(color: Int) {
|
|
||||||
val statusBar = window.decorView.rootView.findViewById<View>(R.id.status_bar)
|
|
||||||
if (statusBar != null) {
|
|
||||||
when {
|
|
||||||
VersionUtils.hasMarshmallow() -> statusBar.setBackgroundColor(color)
|
|
||||||
else -> statusBar.setBackgroundColor(
|
|
||||||
ColorUtil.darkenColor(
|
|
||||||
color
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when {
|
|
||||||
VersionUtils.hasMarshmallow() -> window.statusBarColor = color
|
|
||||||
else -> window.statusBarColor = ColorUtil.darkenColor(color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setLightStatusbarAuto(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setStatusbarColorAuto() {
|
|
||||||
// we don't want to use statusbar color because we are doing the color darkening on our own to support KitKat
|
|
||||||
setStatusbarColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
|
||||||
setLightStatusbarAuto(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setTaskDescriptionColor(@ColorInt color: Int) {
|
|
||||||
ATH.setTaskDescriptionColor(this, color)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTaskDescriptionColorAuto() {
|
|
||||||
setTaskDescriptionColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setNavigationbarColor(color: Int) {
|
|
||||||
if (ThemeStore.coloredNavigationBar(this)) {
|
|
||||||
ATH.setNavigationbarColor(this, color)
|
|
||||||
} else {
|
|
||||||
ATH.setNavigationbarColor(this, Color.BLACK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setNavigationbarColorAuto() {
|
|
||||||
setNavigationbarColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setLightNavigationAuto() {
|
|
||||||
ATH.setLightNavigationbarAuto(this, surfaceColor())
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setLightStatusbar(enabled: Boolean) {
|
|
||||||
ATH.setLightStatusbar(this, enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setLightStatusbarAuto(bgColor: Int) {
|
|
||||||
setLightStatusbar(ColorUtil.isColorLight(bgColor))
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setLightNavigationBar(enabled: Boolean) {
|
|
||||||
if (!ATHUtil.isWindowBackgroundDark(this) and ThemeStore.coloredNavigationBar(this)) {
|
|
||||||
ATH.setLightNavigationbar(this, enabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun registerSystemUiVisibility() {
|
private fun registerSystemUiVisibility() {
|
||||||
val decorView = window.decorView
|
val decorView = window.decorView
|
||||||
decorView.setOnSystemUiVisibilityChangeListener { visibility ->
|
decorView.setOnSystemUiVisibilityChangeListener { visibility ->
|
||||||
|
@ -193,23 +83,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
||||||
decorView.setOnSystemUiVisibilityChangeListener(null)
|
decorView.setOnSystemUiVisibilityChangeListener(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setImmersiveFullscreen() {
|
|
||||||
if (PreferenceUtil.isFullScreenMode) {
|
|
||||||
WindowInsetsControllerCompat(window, window.decorView).apply {
|
|
||||||
systemBarsBehavior =
|
|
||||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
|
||||||
hide(WindowInsetsCompat.Type.systemBars())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun exitFullscreen() {
|
|
||||||
WindowInsetsControllerCompat(window, window.decorView).apply {
|
|
||||||
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
|
||||||
show(WindowInsetsCompat.Type.systemBars())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
setImmersiveFullscreen()
|
setImmersiveFullscreen()
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import code.name.monkey.retromusic.activities.bugreport.model.github.ExtraInfo
|
||||||
import code.name.monkey.retromusic.activities.bugreport.model.github.GithubLogin
|
import code.name.monkey.retromusic.activities.bugreport.model.github.GithubLogin
|
||||||
import code.name.monkey.retromusic.activities.bugreport.model.github.GithubTarget
|
import code.name.monkey.retromusic.activities.bugreport.model.github.GithubTarget
|
||||||
import code.name.monkey.retromusic.databinding.ActivityBugReportBinding
|
import code.name.monkey.retromusic.databinding.ActivityBugReportBinding
|
||||||
|
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||||
import code.name.monkey.retromusic.misc.DialogAsyncTask
|
import code.name.monkey.retromusic.misc.DialogAsyncTask
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
|
|
@ -42,6 +42,7 @@ import code.name.monkey.retromusic.R.drawable
|
||||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||||
import code.name.monkey.retromusic.activities.saf.SAFGuideActivity
|
import code.name.monkey.retromusic.activities.saf.SAFGuideActivity
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
|
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||||
import code.name.monkey.retromusic.model.ArtworkInfo
|
import code.name.monkey.retromusic.model.ArtworkInfo
|
||||||
import code.name.monkey.retromusic.model.AudioTagInfo
|
import code.name.monkey.retromusic.model.AudioTagInfo
|
||||||
import code.name.monkey.retromusic.repository.Repository
|
import code.name.monkey.retromusic.repository.Repository
|
||||||
|
|
|
@ -32,6 +32,7 @@ import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.ActivityAlbumTagEditorBinding
|
import code.name.monkey.retromusic.databinding.ActivityAlbumTagEditorBinding
|
||||||
import code.name.monkey.retromusic.extensions.appHandleColor
|
import code.name.monkey.retromusic.extensions.appHandleColor
|
||||||
|
import code.name.monkey.retromusic.extensions.setDrawUnderStatusBar
|
||||||
import code.name.monkey.retromusic.extensions.setTint
|
import code.name.monkey.retromusic.extensions.setTint
|
||||||
import code.name.monkey.retromusic.glide.GlideApp
|
import code.name.monkey.retromusic.glide.GlideApp
|
||||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||||
|
|
|
@ -163,7 +163,7 @@ open class AlbumAdapter(
|
||||||
when (PreferenceUtil.albumSortOrder) {
|
when (PreferenceUtil.albumSortOrder) {
|
||||||
SortOrder.AlbumSortOrder.ALBUM_A_Z, SortOrder.AlbumSortOrder.ALBUM_Z_A -> sectionName =
|
SortOrder.AlbumSortOrder.ALBUM_A_Z, SortOrder.AlbumSortOrder.ALBUM_Z_A -> sectionName =
|
||||||
dataSet[position].title
|
dataSet[position].title
|
||||||
SortOrder.AlbumSortOrder.ALBUM_ARTIST -> sectionName = dataSet[position].artistName
|
SortOrder.AlbumSortOrder.ALBUM_ARTIST -> sectionName = dataSet[position].albumArtist
|
||||||
SortOrder.AlbumSortOrder.ALBUM_YEAR -> return MusicUtil.getYearString(
|
SortOrder.AlbumSortOrder.ALBUM_YEAR -> return MusicUtil.getYearString(
|
||||||
dataSet[position].year
|
dataSet[position].year
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,273 @@
|
||||||
|
/*
|
||||||
|
* 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.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
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.*
|
||||||
|
import code.name.monkey.retromusic.util.DensityUtil
|
||||||
|
import code.name.monkey.retromusic.util.ImageUtil
|
||||||
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.target.SimpleTarget
|
||||||
|
import com.bumptech.glide.request.target.Target
|
||||||
|
import com.bumptech.glide.request.transition.Transition
|
||||||
|
|
||||||
|
class AppWidgetMD3 : 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_md3)
|
||||||
|
|
||||||
|
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
||||||
|
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_audio_art)
|
||||||
|
val secondaryColor = MaterialValueHelper.getSecondaryTextColor(context, true)
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_next, createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_skip_next,
|
||||||
|
secondaryColor
|
||||||
|
), 1f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_prev, createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_skip_previous,
|
||||||
|
secondaryColor
|
||||||
|
), 1f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_toggle_play_pause, createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_play_arrow_white_32dp,
|
||||||
|
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_md3)
|
||||||
|
|
||||||
|
val isPlaying = service.isPlaying
|
||||||
|
val song = service.currentSong
|
||||||
|
|
||||||
|
// Set the titles and artwork
|
||||||
|
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
|
||||||
|
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
|
||||||
|
} else {
|
||||||
|
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
|
||||||
|
appWidgetView.setTextViewText(R.id.title, song.title)
|
||||||
|
appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set correct drawable for pause state
|
||||||
|
val playPauseRes =
|
||||||
|
if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play_arrow_white_32dp
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_toggle_play_pause, createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
service,
|
||||||
|
playPauseRes,
|
||||||
|
MaterialValueHelper.getSecondaryTextColor(service, true)
|
||||||
|
), 1f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set prev/next button drawables
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_next, createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
service,
|
||||||
|
R.drawable.ic_skip_next,
|
||||||
|
MaterialValueHelper.getSecondaryTextColor(service, true)
|
||||||
|
), 1f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_prev, createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
service,
|
||||||
|
R.drawable.ic_skip_previous,
|
||||||
|
MaterialValueHelper.getSecondaryTextColor(service, true)
|
||||||
|
), 1f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Link actions buttons to intents
|
||||||
|
linkButtons(service, appWidgetView)
|
||||||
|
|
||||||
|
if (imageSize == 0) {
|
||||||
|
imageSize =
|
||||||
|
service.resources.getDimensionPixelSize(R.dimen.app_widget_card_image_size)
|
||||||
|
}
|
||||||
|
if (cardRadius == 0f) {
|
||||||
|
cardRadius =
|
||||||
|
DensityUtil.dip2px(service, 8F).toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
.centerCrop()
|
||||||
|
.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 prev/next button drawables
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_next, ImageUtil.createBitmap(
|
||||||
|
ImageUtil.getTintedVectorDrawable(
|
||||||
|
service, R.drawable.ic_skip_next, color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appWidgetView.setImageViewBitmap(
|
||||||
|
R.id.button_prev, ImageUtil.createBitmap(
|
||||||
|
ImageUtil.getTintedVectorDrawable(
|
||||||
|
service, R.drawable.ic_skip_previous, color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val image = getAlbumArtDrawable(service.resources, bitmap)
|
||||||
|
val roundedBitmap = createRoundedBitmap(
|
||||||
|
image, imageSize, imageSize, cardRadius, cardRadius, cardRadius, cardRadius
|
||||||
|
)
|
||||||
|
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
|
||||||
|
|
||||||
|
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)
|
||||||
|
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
|
||||||
|
|
||||||
|
// Previous track
|
||||||
|
pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName)
|
||||||
|
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
|
||||||
|
|
||||||
|
// Play and pause
|
||||||
|
pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName)
|
||||||
|
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
|
||||||
|
|
||||||
|
// Next track
|
||||||
|
pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName)
|
||||||
|
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val NAME = "app_widget_md3"
|
||||||
|
|
||||||
|
private var mInstance: AppWidgetMD3? = null
|
||||||
|
private var imageSize = 0
|
||||||
|
private var cardRadius = 0F
|
||||||
|
|
||||||
|
val instance: AppWidgetMD3
|
||||||
|
@Synchronized get() {
|
||||||
|
if (mInstance == null) {
|
||||||
|
mInstance = AppWidgetMD3()
|
||||||
|
}
|
||||||
|
return mInstance!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
package code.name.monkey.retromusic.extensions
|
||||||
|
|
||||||
|
import android.app.ActivityManager
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import code.name.monkey.appthemehelper.ATH
|
||||||
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
|
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.util.PreferenceUtil
|
||||||
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
|
|
||||||
|
fun AppCompatActivity.toggleScreenOn() {
|
||||||
|
if (PreferenceUtil.isScreenOnEnabled) {
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
} else {
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setImmersiveFullscreen() {
|
||||||
|
if (PreferenceUtil.isFullScreenMode) {
|
||||||
|
WindowInsetsControllerCompat(window, window.decorView).apply {
|
||||||
|
systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
hide(WindowInsetsCompat.Type.systemBars())
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
window.attributes.layoutInDisplayCutoutMode =
|
||||||
|
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.exitFullscreen() {
|
||||||
|
WindowInsetsControllerCompat(window, window.decorView).apply {
|
||||||
|
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun AppCompatActivity.hideStatusBar() {
|
||||||
|
hideStatusBar(PreferenceUtil.isFullScreenMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun AppCompatActivity.hideStatusBar(fullscreen: Boolean) {
|
||||||
|
val statusBar = window.decorView.rootView.findViewById<View>(R.id.status_bar)
|
||||||
|
if (statusBar != null) {
|
||||||
|
statusBar.visibility = if (fullscreen) View.GONE else View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setDrawUnderStatusBar() {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
window.statusBarColor = Color.TRANSPARENT
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FragmentActivity.setTaskDescriptionColor(color: Int) {
|
||||||
|
var colorFinal = color
|
||||||
|
// Task description requires fully opaque color
|
||||||
|
colorFinal = ColorUtil.stripAlpha(colorFinal)
|
||||||
|
// Sets color of entry in the system recents page
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
setTaskDescription(
|
||||||
|
ActivityManager.TaskDescription(
|
||||||
|
title as String?,
|
||||||
|
-1,
|
||||||
|
colorFinal
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
setTaskDescription(ActivityManager.TaskDescription(title as String?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setTaskDescriptionColorAuto() {
|
||||||
|
setTaskDescriptionColor(surfaceColor())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setLightNavigationAuto() {
|
||||||
|
ATH.setLightNavigationBarAuto(this, surfaceColor())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setLightStatusBar(enabled: Boolean) {
|
||||||
|
ATH.setLightStatusBar(this, enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setLightStatusBarAuto(bgColor: Int) {
|
||||||
|
setLightStatusBar(ColorUtil.isColorLight(bgColor))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setLightNavigationBar(enabled: Boolean) {
|
||||||
|
if (!ATHUtil.isWindowBackgroundDark(this) and ThemeStore.coloredNavigationBar(this)) {
|
||||||
|
ATH.setLightNavigationbar(this, enabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will set the color of the view with the id "status_bar" on KitKat and Lollipop. On
|
||||||
|
* Lollipop if no such view is found it will set the statusbar color using the native method.
|
||||||
|
*
|
||||||
|
* @param color the new statusbar color (will be shifted down on Lollipop and above)
|
||||||
|
*/
|
||||||
|
fun AppCompatActivity.setStatusBarColor(color: Int) {
|
||||||
|
val statusBar = window.decorView.rootView.findViewById<View>(R.id.status_bar)
|
||||||
|
if (statusBar != null) {
|
||||||
|
when {
|
||||||
|
VersionUtils.hasMarshmallow() -> statusBar.setBackgroundColor(color)
|
||||||
|
else -> statusBar.setBackgroundColor(
|
||||||
|
ColorUtil.darkenColor(
|
||||||
|
color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
when {
|
||||||
|
VersionUtils.hasMarshmallow() -> window.statusBarColor = color
|
||||||
|
else -> window.statusBarColor = ColorUtil.darkenColor(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setLightStatusBarAuto(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatActivity.setStatusBarColorAuto() {
|
||||||
|
// we don't want to use statusbar color because we are doing the color darkening on our own to support KitKat
|
||||||
|
setStatusBarColor(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
||||||
|
setLightStatusBarAuto(ATHUtil.resolveColor(this, R.attr.colorSurface))
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package code.name.monkey.retromusic.extensions
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
|
import org.jaudiotagger.audio.AudioFileIO
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URLEncoder
|
||||||
|
|
||||||
|
fun getSongInfo(song: Song): String {
|
||||||
|
val file = File(song.data)
|
||||||
|
if (file.exists()) {
|
||||||
|
return try {
|
||||||
|
val audioHeader = AudioFileIO.read(File(song.data)).audioHeader
|
||||||
|
val string: StringBuilder = StringBuilder()
|
||||||
|
val uriFile = Uri.fromFile(file)
|
||||||
|
string.append(getMimeType(uriFile.toString())).append(" • ")
|
||||||
|
string.append(audioHeader.bitRate).append(" kb/s").append(" • ")
|
||||||
|
string.append(RetroUtil.frequencyCount(audioHeader.sampleRate.toInt()))
|
||||||
|
.append(" kHz")
|
||||||
|
string.toString()
|
||||||
|
} catch (er: Exception) {
|
||||||
|
" - "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMimeType(url: String): String {
|
||||||
|
var type: String? = MimeTypeMap.getFileExtensionFromUrl(
|
||||||
|
URLEncoder.encode(url, "utf-8")
|
||||||
|
).uppercase()
|
||||||
|
if (type == null) {
|
||||||
|
type = url.substring(url.lastIndexOf(".") + 1)
|
||||||
|
}
|
||||||
|
return type
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package code.name.monkey.retromusic.extensions
|
package code.name.monkey.retromusic.extensions
|
||||||
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
|
|
||||||
fun WindowInsetsCompat?.safeGetBottomInsets(): Int {
|
fun WindowInsetsCompat?.safeGetBottomInsets(): Int {
|
||||||
return this?.getInsets(WindowInsetsCompat.Type.systemBars())?.bottom ?: 0
|
// Get Navbar heights if insets are null
|
||||||
|
return (this?.getInsets(WindowInsetsCompat.Type.systemBars())?.bottom ?: RetroUtil.getNavigationBarHeight())
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
import com.google.android.material.shape.ShapeAppearanceModel
|
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 {
|
||||||
return LayoutInflater.from(context).inflate(layout, this, false) as T
|
return LayoutInflater.from(context).inflate(layout, this, false) as T
|
||||||
|
@ -67,21 +68,22 @@ fun View.translateYAnimate(value: Float): Animator {
|
||||||
.apply {
|
.apply {
|
||||||
duration = 300
|
duration = 300
|
||||||
doOnStart {
|
doOnStart {
|
||||||
if (value == 0f) {
|
show()
|
||||||
show()
|
bringToFront()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
doOnEnd {
|
doOnEnd {
|
||||||
if (value != 0f) {
|
if (value != 0f) {
|
||||||
hide()
|
hide()
|
||||||
|
} else {
|
||||||
|
show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int) {
|
fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int): Animator {
|
||||||
ObjectAnimator.ofInt(this, "peekHeight", value)
|
return ObjectAnimator.ofInt(this, "peekHeight", value)
|
||||||
.apply {
|
.apply {
|
||||||
duration = 300
|
duration = 300
|
||||||
start()
|
start()
|
||||||
|
@ -136,6 +138,7 @@ fun ShapeableImageView.setCircleShape(boolean: Boolean) {
|
||||||
* 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 (onlyPortrait && RetroUtil.isLandscape()) return
|
if (onlyPortrait && RetroUtil.isLandscape()) return
|
||||||
// Create a snapshot of the view's margin state
|
// Create a snapshot of the view's margin state
|
||||||
val initialMargin = recordInitialMarginForView(this)
|
val initialMargin = recordInitialMarginForView(this)
|
||||||
|
@ -157,6 +160,7 @@ fun View.drawAboveSystemBars(onlyPortrait: Boolean = true) {
|
||||||
* 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(consume: Boolean = false) {
|
||||||
|
if (PreferenceUtil.isFullScreenMode) return
|
||||||
val initialPadding = recordInitialPaddingForView(this)
|
val initialPadding = recordInitialPaddingForView(this)
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
|
|
|
@ -29,6 +29,7 @@ import code.name.monkey.retromusic.util.DensityUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class LibraryViewModel(
|
class LibraryViewModel(
|
||||||
|
@ -278,14 +279,16 @@ class LibraryViewModel(
|
||||||
}
|
}
|
||||||
emit(songs)
|
emit(songs)
|
||||||
// Cleaning up deleted or moved songs
|
// Cleaning up deleted or moved songs
|
||||||
songs.forEach { song ->
|
withContext(IO) {
|
||||||
if (!File(song.data).exists() || song.id == -1L) {
|
songs.forEach { song ->
|
||||||
repository.deleteSongInPlayCount(song.toPlayCount())
|
if (!File(song.data).exists() || song.id == -1L) {
|
||||||
|
repository.deleteSongInPlayCount(song.toPlayCount())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
emit(repository.playCountSongs().map {
|
||||||
|
it.toSong()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
emit(repository.playCountSongs().map {
|
|
||||||
it.toSong()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun artists(type: Int): LiveData<List<Artist>> = liveData {
|
fun artists(type: Int): LiveData<List<Artist>> = liveData {
|
||||||
|
|
|
@ -196,7 +196,7 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
|
||||||
0,
|
0,
|
||||||
R.id.action_album_sort_order_artist,
|
R.id.action_album_sort_order_artist,
|
||||||
2,
|
2,
|
||||||
R.string.sort_order_artist
|
R.string.sort_order_album_artist
|
||||||
).isChecked =
|
).isChecked =
|
||||||
currentSortOrder.equals(AlbumSortOrder.ALBUM_ARTIST)
|
currentSortOrder.equals(AlbumSortOrder.ALBUM_ARTIST)
|
||||||
sortOrderMenu.add(
|
sortOrderMenu.add(
|
||||||
|
|
|
@ -22,6 +22,8 @@ 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
|
||||||
import code.name.monkey.retromusic.activities.MainActivity
|
import code.name.monkey.retromusic.activities.MainActivity
|
||||||
|
import code.name.monkey.retromusic.extensions.setLightStatusBarAuto
|
||||||
|
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ abstract class AbsMainActivityFragment(@LayoutRes layout: Int) : AbsMusicService
|
||||||
if (statusBar != null) {
|
if (statusBar != null) {
|
||||||
if (VersionUtils.hasMarshmallow()) {
|
if (VersionUtils.hasMarshmallow()) {
|
||||||
statusBar.setBackgroundColor(color)
|
statusBar.setBackgroundColor(color)
|
||||||
mainActivity.setLightStatusbarAuto(color)
|
mainActivity.setLightStatusBarAuto(color)
|
||||||
} else {
|
} else {
|
||||||
statusBar.setBackgroundColor(color)
|
statusBar.setBackgroundColor(color)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,21 +15,14 @@
|
||||||
package code.name.monkey.retromusic.fragments.base
|
package code.name.monkey.retromusic.fragments.base
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.webkit.MimeTypeMap
|
|
||||||
import androidx.annotation.LayoutRes
|
import androidx.annotation.LayoutRes
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.navOptions
|
import androidx.navigation.navOptions
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||||
import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
|
||||||
import code.name.monkey.retromusic.model.Song
|
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
|
||||||
import org.jaudiotagger.audio.AudioFileIO
|
|
||||||
import java.io.File
|
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hemanths on 18/08/17.
|
* Created by hemanths on 18/08/17.
|
||||||
|
@ -103,33 +96,4 @@ open class AbsMusicServiceFragment(@LayoutRes layout: Int) : Fragment(layout),
|
||||||
|
|
||||||
override fun onMediaStoreChanged() {
|
override fun onMediaStoreChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSongInfo(song: Song): String {
|
|
||||||
val file = File(song.data)
|
|
||||||
if (file.exists()) {
|
|
||||||
return try {
|
|
||||||
val audioHeader = AudioFileIO.read(File(song.data)).audioHeader
|
|
||||||
val string: StringBuilder = StringBuilder()
|
|
||||||
val uriFile = Uri.fromFile(file)
|
|
||||||
string.append(getMimeType(uriFile.toString())).append(" • ")
|
|
||||||
string.append(audioHeader.bitRate).append(" kb/s").append(" • ")
|
|
||||||
string.append(RetroUtil.frequencyCount(audioHeader.sampleRate.toInt()))
|
|
||||||
.append(" kHz")
|
|
||||||
string.toString()
|
|
||||||
} catch (er: Exception) {
|
|
||||||
" - "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "-"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMimeType(url: String): String {
|
|
||||||
var type: String? = MimeTypeMap.getFileExtensionFromUrl(
|
|
||||||
URLEncoder.encode(url, "utf-8")
|
|
||||||
).uppercase()
|
|
||||||
if (type == null) {
|
|
||||||
type = url.substring(url.lastIndexOf(".") + 1)
|
|
||||||
}
|
|
||||||
return type
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
enterTransition = Fade()
|
enterTransition = Fade()
|
||||||
exitTransition = Fade()
|
exitTransition = Fade()
|
||||||
lyricsSectionsAdapter = LyricsSectionsAdapter(requireActivity())
|
lyricsSectionsAdapter = LyricsSectionsAdapter(requireActivity())
|
||||||
|
|
|
@ -29,10 +29,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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
|
||||||
import code.name.monkey.retromusic.databinding.FragmentAdaptivePlayerPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentAdaptivePlayerPlaybackControlsBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.hide
|
|
||||||
import code.name.monkey.retromusic.extensions.ripAlpha
|
|
||||||
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.MusicProgressViewUpdateHelper
|
||||||
|
|
|
@ -29,6 +29,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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
|
||||||
import code.name.monkey.retromusic.databinding.FragmentBlurPlayerPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentBlurPlayerPlaybackControlsBinding
|
||||||
|
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.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
|
|
@ -27,6 +27,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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
|
||||||
import code.name.monkey.retromusic.databinding.FragmentCardPlayerPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentCardPlayerPlaybackControlsBinding
|
||||||
|
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.ripAlpha
|
import code.name.monkey.retromusic.extensions.ripAlpha
|
||||||
import code.name.monkey.retromusic.extensions.show
|
import code.name.monkey.retromusic.extensions.show
|
||||||
|
|
|
@ -27,6 +27,7 @@ import code.name.monkey.appthemehelper.util.TintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentCardBlurPlayerPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentCardBlurPlayerPlaybackControlsBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.applyColor
|
||||||
|
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.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
|
|
@ -36,6 +36,7 @@ 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.FragmentClassicPlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentClassicPlayerBinding
|
||||||
|
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.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
|
|
@ -32,6 +32,7 @@ import code.name.monkey.appthemehelper.util.TintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentColorPlayerPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentColorPlayerPlaybackControlsBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.applyColor
|
||||||
|
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.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
|
|
@ -29,6 +29,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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
|
||||||
import code.name.monkey.retromusic.databinding.FragmentFitPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentFitPlaybackControlsBinding
|
||||||
|
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.ripAlpha
|
import code.name.monkey.retromusic.extensions.ripAlpha
|
||||||
import code.name.monkey.retromusic.extensions.show
|
import code.name.monkey.retromusic.extensions.show
|
||||||
|
|
|
@ -28,10 +28,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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
|
||||||
import code.name.monkey.retromusic.databinding.FragmentFlatPlayerPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentFlatPlayerPlaybackControlsBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.hide
|
|
||||||
import code.name.monkey.retromusic.extensions.ripAlpha
|
|
||||||
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.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
|
||||||
|
|
|
@ -36,6 +36,7 @@ import code.name.monkey.retromusic.db.PlaylistEntity
|
||||||
import code.name.monkey.retromusic.db.SongEntity
|
import code.name.monkey.retromusic.db.SongEntity
|
||||||
import code.name.monkey.retromusic.db.toSongEntity
|
import code.name.monkey.retromusic.db.toSongEntity
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.applyColor
|
||||||
|
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.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
|
|
|
@ -28,10 +28,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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
|
||||||
import code.name.monkey.retromusic.databinding.FragmentPlayerPlaybackControlsBinding
|
import code.name.monkey.retromusic.databinding.FragmentPlayerPlaybackControlsBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.*
|
||||||
import code.name.monkey.retromusic.extensions.hide
|
|
||||||
import code.name.monkey.retromusic.extensions.ripAlpha
|
|
||||||
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.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
|
||||||
|
|
|
@ -22,6 +22,7 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentPeakPlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentPeakPlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
||||||
|
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.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
|
|
|
@ -30,6 +30,7 @@ import code.name.monkey.appthemehelper.util.TintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentPlainControlsFragmentBinding
|
import code.name.monkey.retromusic.databinding.FragmentPlainControlsFragmentBinding
|
||||||
import code.name.monkey.retromusic.extensions.applyColor
|
import code.name.monkey.retromusic.extensions.applyColor
|
||||||
|
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.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
|
|
@ -25,6 +25,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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
|
||||||
import code.name.monkey.retromusic.databinding.FragmentSimpleControlsFragmentBinding
|
import code.name.monkey.retromusic.databinding.FragmentSimpleControlsFragmentBinding
|
||||||
|
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.fragments.base.AbsPlayerControlsFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
|
|
@ -28,6 +28,7 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.databinding.FragmentTinyPlayerBinding
|
import code.name.monkey.retromusic.databinding.FragmentTinyPlayerBinding
|
||||||
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
||||||
|
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.fragments.base.AbsPlayerFragment
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
|
|
|
@ -18,9 +18,10 @@ import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter
|
||||||
import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding
|
import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding
|
||||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
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.dipToPix
|
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.fragments.base.AbsMainActivityFragment
|
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||||
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
||||||
import code.name.monkey.retromusic.interfaces.ICabCallback
|
import code.name.monkey.retromusic.interfaces.ICabCallback
|
||||||
import code.name.monkey.retromusic.interfaces.ICabHolder
|
import code.name.monkey.retromusic.interfaces.ICabHolder
|
||||||
|
@ -123,8 +124,12 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkForPadding() {
|
private fun checkForPadding() {
|
||||||
val height = dipToPix(52f)
|
val itemCount: Int = playlistSongAdapter.itemCount
|
||||||
binding.recyclerView.setPadding(0, 0, 0, height.toInt())
|
if (itemCount > 0 && MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||||
|
binding.recyclerView.updatePadding(bottom = dip(R.dimen.mini_player_height))
|
||||||
|
} else {
|
||||||
|
binding.recyclerView.updatePadding(bottom = 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIsEmpty() {
|
private fun checkIsEmpty() {
|
||||||
|
|
|
@ -19,15 +19,16 @@ import android.graphics.drawable.ColorDrawable
|
||||||
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.updatePadding
|
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.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 code.name.monkey.retromusic.util.RetroUtil
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hemanth S (h4h13).
|
* @author Hemanth S (h4h13).
|
||||||
|
@ -66,16 +67,19 @@ abstract class AbsSettingsFragment : ATEPreferenceFragmentCompat() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
setDivider(ColorDrawable(Color.TRANSPARENT))
|
setDivider(ColorDrawable(Color.TRANSPARENT))
|
||||||
// This is a workaround as CollapsingToolbarLayout consumes insets and
|
// CollapsingToolbarLayout consumes insets and insets are not passed to child views
|
||||||
// insets are not passed to child views
|
// So we get insets from root view
|
||||||
// https://github.com/material-components/material-components-android/issues/1310
|
// https://github.com/material-components/material-components-android/issues/1310
|
||||||
if (!RetroUtil.isLandscape()) {
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
listView.updatePadding(bottom = RetroUtil.getNavigationBarHeight())
|
view
|
||||||
|
) { _, insets ->
|
||||||
|
listView.updatePadding(bottom = insets.safeGetBottomInsets())
|
||||||
|
insets
|
||||||
}
|
}
|
||||||
invalidateSettings()
|
invalidateSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisplayPreferenceDialog(preference: Preference?) {
|
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||||
when (preference) {
|
when (preference) {
|
||||||
is LibraryPreference -> {
|
is LibraryPreference -> {
|
||||||
val fragment = LibraryPreferenceDialog.newInstance()
|
val fragment = LibraryPreferenceDialog.newInstance()
|
||||||
|
|
|
@ -33,10 +33,10 @@ import java.io.File
|
||||||
@GlideExtension
|
@GlideExtension
|
||||||
object RetroGlideExtension {
|
object RetroGlideExtension {
|
||||||
|
|
||||||
private const val DEFAULT_ERROR_ARTIST_IMAGE =
|
private const val DEFAULT_ARTIST_IMAGE =
|
||||||
R.drawable.default_artist_art
|
R.drawable.default_artist_art
|
||||||
private const val DEFAULT_ERROR_SONG_IMAGE: Int = R.drawable.default_audio_art
|
private const val DEFAULT_SONG_IMAGE: Int = R.drawable.default_audio_art
|
||||||
private const val DEFAULT_ERROR_ALBUM_IMAGE = R.drawable.default_album_art
|
private const val DEFAULT_ALBUM_IMAGE = R.drawable.default_album_art
|
||||||
private const val DEFAULT_ERROR_IMAGE_BANNER = R.drawable.material_design_default
|
private const val DEFAULT_ERROR_IMAGE_BANNER = R.drawable.material_design_default
|
||||||
|
|
||||||
private val DEFAULT_DISK_CACHE_STRATEGY_ARTIST = DiskCacheStrategy.RESOURCE
|
private val DEFAULT_DISK_CACHE_STRATEGY_ARTIST = DiskCacheStrategy.RESOURCE
|
||||||
|
@ -99,7 +99,8 @@ object RetroGlideExtension {
|
||||||
return baseRequestOptions
|
return baseRequestOptions
|
||||||
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY_ARTIST)
|
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY_ARTIST)
|
||||||
.priority(Priority.LOW)
|
.priority(Priority.LOW)
|
||||||
.error(DEFAULT_ERROR_ARTIST_IMAGE)
|
.error(DEFAULT_ARTIST_IMAGE)
|
||||||
|
.placeholder(DEFAULT_ARTIST_IMAGE)
|
||||||
.signature(createSignature(artist))
|
.signature(createSignature(artist))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +111,8 @@ object RetroGlideExtension {
|
||||||
song: Song
|
song: Song
|
||||||
): BaseRequestOptions<*> {
|
): BaseRequestOptions<*> {
|
||||||
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
.error(DEFAULT_ERROR_SONG_IMAGE)
|
.error(DEFAULT_SONG_IMAGE)
|
||||||
|
.placeholder(DEFAULT_SONG_IMAGE)
|
||||||
.signature(createSignature(song))
|
.signature(createSignature(song))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +123,8 @@ object RetroGlideExtension {
|
||||||
song: Song
|
song: Song
|
||||||
): BaseRequestOptions<*> {
|
): BaseRequestOptions<*> {
|
||||||
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
.error(DEFAULT_ERROR_ALBUM_IMAGE)
|
.error(DEFAULT_ALBUM_IMAGE)
|
||||||
|
.placeholder(DEFAULT_ALBUM_IMAGE)
|
||||||
.signature(createSignature(song))
|
.signature(createSignature(song))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +157,7 @@ object RetroGlideExtension {
|
||||||
baseRequestOptions: BaseRequestOptions<*>
|
baseRequestOptions: BaseRequestOptions<*>
|
||||||
): BaseRequestOptions<*> {
|
): BaseRequestOptions<*> {
|
||||||
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
.error(DEFAULT_ERROR_ALBUM_IMAGE)
|
.error(DEFAULT_ALBUM_IMAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSignature(song: Song): Key {
|
private fun createSignature(song: Song): Key {
|
||||||
|
|
|
@ -33,8 +33,7 @@ abstract class RetroMusicColoredTarget(view: ImageView) : BitmapPaletteTarget(vi
|
||||||
|
|
||||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
super.onLoadFailed(errorDrawable)
|
super.onLoadFailed(errorDrawable)
|
||||||
val colors = MediaNotificationProcessor(App.getContext(), errorDrawable)
|
onColorReady(MediaNotificationProcessor.errorColor(App.getContext()))
|
||||||
onColorReady(colors)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceReady(
|
override fun onResourceReady(
|
||||||
|
|
|
@ -54,11 +54,11 @@ class SortOrder {
|
||||||
const val ALBUM_Z_A = "$ALBUM_A_Z DESC"
|
const val ALBUM_Z_A = "$ALBUM_A_Z DESC"
|
||||||
|
|
||||||
/* Album sort order songs */
|
/* Album sort order songs */
|
||||||
const val ALBUM_NUMBER_OF_SONGS = MediaStore.Audio.AlbumColumns.NUMBER_OF_SONGS + " DESC"
|
const val ALBUM_NUMBER_OF_SONGS =
|
||||||
|
MediaStore.Audio.AlbumColumns.NUMBER_OF_SONGS + " DESC"
|
||||||
|
|
||||||
/* Album sort order artist */
|
/* Album Artist sort order artist */
|
||||||
const val ALBUM_ARTIST = (MediaStore.Audio.Artists.DEFAULT_SORT_ORDER +
|
const val ALBUM_ARTIST = "case when lower(album_artist) is null then 1 else 0 end, lower(album_artist)"
|
||||||
", " + MediaStore.Audio.Albums.DEFAULT_SORT_ORDER)
|
|
||||||
|
|
||||||
/* Album sort order year */
|
/* Album sort order year */
|
||||||
const val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
|
const val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
|
||||||
|
|
|
@ -25,6 +25,7 @@ import static code.name.monkey.retromusic.ConstantsKt.CROSS_FADE_DURATION;
|
||||||
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;
|
||||||
|
|
||||||
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.appwidget.AppWidgetManager;
|
import android.appwidget.AppWidgetManager;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
@ -34,6 +35,7 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ServiceInfo;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
|
@ -81,6 +83,7 @@ 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.AppWidgetClassic;
|
import code.name.monkey.retromusic.appwidgets.AppWidgetClassic;
|
||||||
|
import code.name.monkey.retromusic.appwidgets.AppWidgetMD3;
|
||||||
import code.name.monkey.retromusic.appwidgets.AppWidgetSmall;
|
import code.name.monkey.retromusic.appwidgets.AppWidgetSmall;
|
||||||
import code.name.monkey.retromusic.appwidgets.AppWidgetText;
|
import code.name.monkey.retromusic.appwidgets.AppWidgetText;
|
||||||
import code.name.monkey.retromusic.auto.AutoMediaIDHelper;
|
import code.name.monkey.retromusic.auto.AutoMediaIDHelper;
|
||||||
|
@ -105,6 +108,7 @@ import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||||
import code.name.monkey.retromusic.util.RetroUtil;
|
import code.name.monkey.retromusic.util.RetroUtil;
|
||||||
import code.name.monkey.retromusic.volume.AudioVolumeObserver;
|
import code.name.monkey.retromusic.volume.AudioVolumeObserver;
|
||||||
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener;
|
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener;
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid), Andrew Neal
|
* @author Karim Abou Zeid (kabouzeid), Andrew Neal
|
||||||
|
@ -198,6 +202,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
|
|
||||||
private final AppWidgetText appWidgetText = AppWidgetText.Companion.getInstance();
|
private final AppWidgetText appWidgetText = AppWidgetText.Companion.getInstance();
|
||||||
|
|
||||||
|
private final AppWidgetMD3 appWidgetMd3 = AppWidgetMD3.Companion.getInstance();
|
||||||
|
|
||||||
private final BroadcastReceiver widgetIntentReceiver =
|
private final BroadcastReceiver widgetIntentReceiver =
|
||||||
new BroadcastReceiver() {
|
new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -226,6 +232,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
appWidgetText.performUpdate(MusicService.this, ids);
|
appWidgetText.performUpdate(MusicService.this, ids);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case AppWidgetMD3.NAME: {
|
||||||
|
appWidgetMd3.performUpdate(MusicService.this, ids);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,7 +283,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
new BroadcastReceiver() {
|
new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
updateNotification();
|
playingNotification.updateFavorite(getCurrentSong(), MusicService.this::startForegroundOrNotify);
|
||||||
|
startForegroundOrNotify();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final BroadcastReceiver lockScreenReceiver =
|
private final BroadcastReceiver lockScreenReceiver =
|
||||||
|
@ -356,6 +367,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
private ThrottledSeekHandler throttledSeekHandler;
|
private ThrottledSeekHandler throttledSeekHandler;
|
||||||
private Handler uiThreadHandler;
|
private Handler uiThreadHandler;
|
||||||
private PowerManager.WakeLock wakeLock;
|
private PowerManager.WakeLock wakeLock;
|
||||||
|
private NotificationManager notificationManager;
|
||||||
|
private boolean isForeground = false;
|
||||||
|
|
||||||
private static Bitmap copy(Bitmap bitmap) {
|
private static Bitmap copy(Bitmap bitmap) {
|
||||||
Bitmap.Config config = bitmap.getConfig();
|
Bitmap.Config config = bitmap.getConfig();
|
||||||
|
@ -417,6 +430,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
registerReceiver(updateFavoriteReceiver, new IntentFilter(FAVORITE_STATE_CHANGED));
|
registerReceiver(updateFavoriteReceiver, new IntentFilter(FAVORITE_STATE_CHANGED));
|
||||||
registerReceiver(lockScreenReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
registerReceiver(lockScreenReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
||||||
|
|
||||||
|
setSessionToken(mediaSession.getSessionToken());
|
||||||
|
if (VersionUtils.INSTANCE.hasMarshmallow()) {
|
||||||
|
notificationManager = getSystemService(NotificationManager.class);
|
||||||
|
}
|
||||||
initNotification();
|
initNotification();
|
||||||
|
|
||||||
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
||||||
|
@ -467,7 +484,6 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
|
|
||||||
mPackageValidator = new PackageValidator(this, R.xml.allowed_media_browser_callers);
|
mPackageValidator = new PackageValidator(this, R.xml.allowed_media_browser_callers);
|
||||||
mMusicProvider.setMusicService(this);
|
mMusicProvider.setMusicService(this);
|
||||||
setSessionToken(mediaSession.getSessionToken());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -765,11 +781,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
public void initNotification() {
|
public void initNotification() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
||||||
&& !PreferenceUtil.INSTANCE.isClassicNotification()) {
|
&& !PreferenceUtil.INSTANCE.isClassicNotification()) {
|
||||||
playingNotification = new PlayingNotificationImpl();
|
playingNotification = PlayingNotificationImpl.Companion.from(this, notificationManager, mediaSession);
|
||||||
} else {
|
} else {
|
||||||
playingNotification = new PlayingNotificationOreo();
|
playingNotification = PlayingNotificationOreo.Companion.from(this, notificationManager);
|
||||||
}
|
}
|
||||||
playingNotification.init(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLastTrack() {
|
public boolean isLastTrack() {
|
||||||
|
@ -837,7 +852,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
// Request from an untrusted package: return an empty browser root
|
// Request from an untrusted package: return an empty browser root
|
||||||
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_EMPTY_ROOT, null);
|
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_EMPTY_ROOT, null);
|
||||||
} else {
|
} else {
|
||||||
/** By default return the browsable root. Treat the EXTRA_RECENT flag as a special case
|
/**
|
||||||
|
* By default return the browsable root. Treat the EXTRA_RECENT flag as a special case
|
||||||
* and return the recent root instead.
|
* and return the recent root instead.
|
||||||
*/
|
*/
|
||||||
boolean isRecentRequest = false;
|
boolean isRecentRequest = false;
|
||||||
|
@ -882,7 +898,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
/* Switch to MultiPlayer if Crossfade duration is 0 and
|
/* Switch to MultiPlayer if Crossfade duration is 0 and
|
||||||
Playback is not an instance of MultiPlayer */
|
Playback is not an instance of MultiPlayer */
|
||||||
if (playback != null)
|
if (playback != null)
|
||||||
playback.setCrossFadeDuration(PreferenceUtil.INSTANCE.getCrossFadeDuration());
|
playback.setCrossFadeDuration(PreferenceUtil.INSTANCE.getCrossFadeDuration());
|
||||||
if (!(playback instanceof MultiPlayer) && PreferenceUtil.INSTANCE.getCrossFadeDuration() == 0) {
|
if (!(playback instanceof MultiPlayer) && PreferenceUtil.INSTANCE.getCrossFadeDuration() == 0) {
|
||||||
if (playback != null) {
|
if (playback != null) {
|
||||||
playback.release();
|
playback.release();
|
||||||
|
@ -1042,6 +1058,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pause() {
|
public void pause() {
|
||||||
|
Log.i(TAG, "Paused");
|
||||||
pausedByTransientLossOfFocus = false;
|
pausedByTransientLossOfFocus = false;
|
||||||
if (playback != null && playback.isPlaying()) {
|
if (playback != null && playback.isPlaying()) {
|
||||||
startFadeAnimator(playback, false, () -> {
|
startFadeAnimator(playback, false, () -> {
|
||||||
|
@ -1163,7 +1180,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
|
|
||||||
public void quit() {
|
public void quit() {
|
||||||
pause();
|
pause();
|
||||||
playingNotification.stop();
|
stopForeground(true);
|
||||||
|
notificationManager.cancel(PlayingNotification.NOTIFICATION_ID);
|
||||||
|
|
||||||
closeAudioEffectSession();
|
closeAudioEffectSession();
|
||||||
getAudioManager().abandonAudioFocus(audioFocusListener);
|
getAudioManager().abandonAudioFocus(audioFocusListener);
|
||||||
|
@ -1326,7 +1344,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
|
|
||||||
public void updateNotification() {
|
public void updateNotification() {
|
||||||
if (playingNotification != null && getCurrentSong().getId() != -1) {
|
if (playingNotification != null && getCurrentSong().getId() != -1) {
|
||||||
playingNotification.update();
|
stopForegroundAndNotification();
|
||||||
|
initNotification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,17 +1419,19 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
private void handleChangeInternal(@NonNull final String what) {
|
private void handleChangeInternal(@NonNull final String what) {
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case PLAY_STATE_CHANGED:
|
case PLAY_STATE_CHANGED:
|
||||||
updateNotification();
|
|
||||||
updateMediaSessionPlaybackState();
|
updateMediaSessionPlaybackState();
|
||||||
final boolean isPlaying = isPlaying();
|
final boolean isPlaying = isPlaying();
|
||||||
if (!isPlaying && getSongProgressMillis() > 0) {
|
if (!isPlaying && getSongProgressMillis() > 0) {
|
||||||
savePositionInTrack();
|
savePositionInTrack();
|
||||||
}
|
}
|
||||||
songPlayCountHelper.notifyPlayStateChanged(isPlaying);
|
songPlayCountHelper.notifyPlayStateChanged(isPlaying);
|
||||||
|
playingNotification.setPlaying(isPlaying);
|
||||||
|
startForegroundOrNotify();
|
||||||
break;
|
break;
|
||||||
case FAVORITE_STATE_CHANGED:
|
case FAVORITE_STATE_CHANGED:
|
||||||
|
playingNotification.updateFavorite(getCurrentSong(), this::startForegroundOrNotify);
|
||||||
case META_CHANGED:
|
case META_CHANGED:
|
||||||
updateNotification();
|
playingNotification.updateMetadata(getCurrentSong(), this::startForegroundOrNotify);
|
||||||
updateMediaSessionMetaData();
|
updateMediaSessionMetaData();
|
||||||
updateMediaSessionPlaybackState();
|
updateMediaSessionPlaybackState();
|
||||||
savePosition();
|
savePosition();
|
||||||
|
@ -1428,12 +1449,41 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
if (playingQueue.size() > 0) {
|
if (playingQueue.size() > 0) {
|
||||||
prepareNext();
|
prepareNext();
|
||||||
} else {
|
} else {
|
||||||
playingNotification.stop();
|
stopForegroundAndNotification();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Unit startForegroundOrNotify() {
|
||||||
|
if (!isForeground) {
|
||||||
|
// Specify that this is a media service, if supported.
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
startForeground(
|
||||||
|
PlayingNotification.NOTIFICATION_ID, playingNotification.build(),
|
||||||
|
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
startForeground(PlayingNotification.NOTIFICATION_ID, playingNotification.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
isForeground = true;
|
||||||
|
} else {
|
||||||
|
// If we are already in foreground just update the notification
|
||||||
|
notificationManager.notify(
|
||||||
|
PlayingNotification.NOTIFICATION_ID, playingNotification.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopForegroundAndNotification() {
|
||||||
|
stopForeground(true);
|
||||||
|
notificationManager.cancel(PlayingNotification.NOTIFICATION_ID);
|
||||||
|
|
||||||
|
isForeground = false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean openCurrent() {
|
private boolean openCurrent() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
try {
|
try {
|
||||||
|
@ -1551,6 +1601,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
appWidgetSmall.notifyChange(this, what);
|
appWidgetSmall.notifyChange(this, what);
|
||||||
appWidgetCard.notifyChange(this, what);
|
appWidgetCard.notifyChange(this, what);
|
||||||
appWidgetText.notifyChange(this, what);
|
appWidgetText.notifyChange(this, what);
|
||||||
|
appWidgetMd3.notifyChange(this, what);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
|
private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
|
||||||
|
@ -1592,8 +1643,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
||||||
mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
|
mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
|
||||||
|
|
||||||
PendingIntent mediaButtonReceiverPendingIntent;
|
PendingIntent mediaButtonReceiverPendingIntent;
|
||||||
mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent,
|
mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent,
|
||||||
VersionUtils.INSTANCE.hasMarshmallow() ? PendingIntent.FLAG_IMMUTABLE : 0);
|
VersionUtils.INSTANCE.hasMarshmallow() ? PendingIntent.FLAG_IMMUTABLE : 0);
|
||||||
|
|
||||||
mediaSession = new MediaSessionCompat(
|
mediaSession = new MediaSessionCompat(
|
||||||
this,
|
this,
|
||||||
|
|
|
@ -15,95 +15,51 @@
|
||||||
package code.name.monkey.retromusic.service.notification
|
package code.name.monkey.retromusic.service.notification
|
||||||
|
|
||||||
|
|
||||||
import android.app.Notification
|
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context.NOTIFICATION_SERVICE
|
import android.content.Context
|
||||||
import android.content.pm.ServiceInfo
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.service.MusicService
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
|
||||||
|
|
||||||
abstract class PlayingNotification {
|
abstract class PlayingNotification(context: Context) :
|
||||||
protected lateinit var service: MusicService
|
NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) {
|
||||||
protected var stopped: Boolean = false
|
|
||||||
private var notifyMode = NOTIFY_MODE_BACKGROUND
|
|
||||||
private var notificationManager: NotificationManager? = null
|
|
||||||
|
|
||||||
|
abstract fun updateMetadata(song: Song, onUpdate: () -> Unit)
|
||||||
|
|
||||||
@Synchronized
|
abstract fun setPlaying(isPlaying: Boolean)
|
||||||
fun init(service: MusicService) {
|
|
||||||
this.service = service
|
|
||||||
notificationManager = service.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
createNotificationChannel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun update()
|
abstract fun updateFavorite(song: Song, onUpdate: () -> Unit)
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
fun stop() {
|
|
||||||
stopped = true
|
|
||||||
service.stopForeground(true)
|
|
||||||
notificationManager!!.cancel(NOTIFICATION_ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun updateNotifyModeAndPostNotification(notification: Notification) {
|
|
||||||
val newNotifyMode: Int = if (service.isPlaying) {
|
|
||||||
NOTIFY_MODE_FOREGROUND
|
|
||||||
} else {
|
|
||||||
NOTIFY_MODE_BACKGROUND
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notifyMode != newNotifyMode && newNotifyMode == NOTIFY_MODE_BACKGROUND) {
|
|
||||||
service.stopForeground(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newNotifyMode == NOTIFY_MODE_FOREGROUND) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
||||||
service.startForeground(
|
|
||||||
NOTIFICATION_ID,
|
|
||||||
notification,
|
|
||||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
service.startForeground(NOTIFICATION_ID,notification)
|
|
||||||
}
|
|
||||||
} else if (newNotifyMode == NOTIFY_MODE_BACKGROUND) {
|
|
||||||
notificationManager!!.notify(NOTIFICATION_ID, notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyMode = newNotifyMode
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(26)
|
|
||||||
private fun createNotificationChannel() {
|
|
||||||
var notificationChannel: NotificationChannel? = notificationManager!!
|
|
||||||
.getNotificationChannel(NOTIFICATION_CHANNEL_ID)
|
|
||||||
if (notificationChannel == null) {
|
|
||||||
notificationChannel = NotificationChannel(
|
|
||||||
NOTIFICATION_CHANNEL_ID,
|
|
||||||
service.getString(R.string.playing_notification_name),
|
|
||||||
NotificationManager.IMPORTANCE_LOW
|
|
||||||
)
|
|
||||||
notificationChannel.description =
|
|
||||||
service.getString(R.string.playing_notification_description)
|
|
||||||
notificationChannel.enableLights(false)
|
|
||||||
notificationChannel.enableVibration(false)
|
|
||||||
notificationChannel.setShowBadge(false)
|
|
||||||
|
|
||||||
notificationManager!!.createNotificationChannel(notificationChannel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val NOTIFICATION_CONTROLS_SIZE_MULTIPLIER = 1.0f
|
const val NOTIFICATION_CONTROLS_SIZE_MULTIPLIER = 1.0f
|
||||||
internal const val NOTIFICATION_CHANNEL_ID = "playing_notification"
|
internal const val NOTIFICATION_CHANNEL_ID = "playing_notification"
|
||||||
private const val NOTIFICATION_ID = 1
|
const val NOTIFICATION_ID = 1
|
||||||
private const val NOTIFY_MODE_FOREGROUND = 1
|
|
||||||
private const val NOTIFY_MODE_BACKGROUND = 0
|
|
||||||
|
@RequiresApi(26)
|
||||||
|
fun createNotificationChannel(
|
||||||
|
context: Context,
|
||||||
|
notificationManager: NotificationManager
|
||||||
|
) {
|
||||||
|
var notificationChannel: NotificationChannel? = notificationManager
|
||||||
|
.getNotificationChannel(NOTIFICATION_CHANNEL_ID)
|
||||||
|
if (notificationChannel == null) {
|
||||||
|
notificationChannel = NotificationChannel(
|
||||||
|
NOTIFICATION_CHANNEL_ID,
|
||||||
|
context.getString(R.string.playing_notification_name),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
)
|
||||||
|
notificationChannel.description =
|
||||||
|
context.getString(R.string.playing_notification_description)
|
||||||
|
notificationChannel.enableLights(false)
|
||||||
|
notificationChannel.enableVibration(false)
|
||||||
|
notificationChannel.setShowBadge(false)
|
||||||
|
|
||||||
|
notificationManager.createNotificationChannel(notificationChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,14 +14,16 @@
|
||||||
|
|
||||||
package code.name.monkey.retromusic.service.notification
|
package code.name.monkey.retromusic.service.notification
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.support.v4.media.session.MediaSessionCompat
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.media.app.NotificationCompat.MediaStyle
|
import androidx.media.app.NotificationCompat.MediaStyle
|
||||||
|
@ -33,177 +35,196 @@ import code.name.monkey.retromusic.db.toSongEntity
|
||||||
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.glide.palette.BitmapPaletteWrapper
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||||
|
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.service.MusicService.*
|
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.RetroColorUtil
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.request.target.CustomTarget
|
||||||
import com.bumptech.glide.request.target.SimpleTarget
|
|
||||||
import com.bumptech.glide.request.target.Target
|
|
||||||
import com.bumptech.glide.request.transition.Transition
|
import com.bumptech.glide.request.transition.Transition
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.core.component.KoinComponent
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class PlayingNotificationImpl : PlayingNotification(), KoinComponent {
|
@SuppressLint("RestrictedApi")
|
||||||
private var target: Target<BitmapPaletteWrapper>? = null
|
class PlayingNotificationImpl(
|
||||||
|
val context: Context,
|
||||||
|
mediaSessionToken: MediaSessionCompat.Token
|
||||||
|
) : PlayingNotification(context) {
|
||||||
|
|
||||||
@Synchronized
|
init {
|
||||||
override fun update() {
|
val action = Intent(context, MainActivity::class.java)
|
||||||
stopped = false
|
action.putExtra(MainActivity.EXPAND_PANEL, PreferenceUtil.isExpandPanel)
|
||||||
GlobalScope.launch {
|
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
val song = service.currentSong
|
val clickIntent =
|
||||||
|
PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
0,
|
||||||
|
action,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or if (VersionUtils.hasMarshmallow())
|
||||||
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
|
else 0
|
||||||
|
)
|
||||||
|
|
||||||
|
val serviceName = ComponentName(context, MusicService::class.java)
|
||||||
|
val intent = Intent(ACTION_QUIT)
|
||||||
|
intent.component = serviceName
|
||||||
|
val deleteIntent = PendingIntent.getService(
|
||||||
|
context,
|
||||||
|
0,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or (if (VersionUtils.hasMarshmallow())
|
||||||
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
|
else 0)
|
||||||
|
)
|
||||||
|
val toggleFavorite = buildFavoriteAction(false)
|
||||||
|
val playPauseAction = buildPlayAction(true)
|
||||||
|
val previousAction = NotificationCompat.Action(
|
||||||
|
R.drawable.ic_skip_previous_round_white_32dp,
|
||||||
|
context.getString(R.string.action_previous),
|
||||||
|
retrievePlaybackAction(ACTION_REWIND)
|
||||||
|
)
|
||||||
|
val nextAction = NotificationCompat.Action(
|
||||||
|
R.drawable.ic_skip_next_round_white_32dp,
|
||||||
|
context.getString(R.string.action_next),
|
||||||
|
retrievePlaybackAction(ACTION_SKIP)
|
||||||
|
)
|
||||||
|
val dismissAction = NotificationCompat.Action(
|
||||||
|
R.drawable.ic_close,
|
||||||
|
context.getString(R.string.customactivityoncrash_error_activity_error_details_close),
|
||||||
|
retrievePlaybackAction(ACTION_QUIT)
|
||||||
|
)
|
||||||
|
setSmallIcon(R.drawable.ic_notification)
|
||||||
|
setContentIntent(clickIntent)
|
||||||
|
setDeleteIntent(deleteIntent)
|
||||||
|
setShowWhen(false)
|
||||||
|
addAction(toggleFavorite)
|
||||||
|
addAction(previousAction)
|
||||||
|
addAction(playPauseAction)
|
||||||
|
addAction(nextAction)
|
||||||
|
addAction(dismissAction)
|
||||||
|
|
||||||
|
setStyle(
|
||||||
|
MediaStyle()
|
||||||
|
.setMediaSession(mediaSessionToken)
|
||||||
|
.setShowActionsInCompactView(1, 2, 3)
|
||||||
|
)
|
||||||
|
setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
|
if (Build.VERSION.SDK_INT <=
|
||||||
|
Build.VERSION_CODES.O && PreferenceUtil.isColoredNotification
|
||||||
|
) {
|
||||||
|
this.color = color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateMetadata(song: Song, onUpdate: () -> Unit) {
|
||||||
|
setContentTitle(song.title)
|
||||||
|
setContentText(
|
||||||
|
HtmlCompat.fromHtml(
|
||||||
|
"<b>" + song.albumName + "</b>",
|
||||||
|
HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val bigNotificationImageSize = context.resources
|
||||||
|
.getDimensionPixelSize(R.dimen.notification_big_image_size)
|
||||||
|
GlideApp.with(context).asBitmapPalette().songCoverOptions(song)
|
||||||
|
.load(RetroGlideExtension.getSongModel(song))
|
||||||
|
//.checkIgnoreMediaStore()
|
||||||
|
.centerCrop()
|
||||||
|
.into(object : CustomTarget<BitmapPaletteWrapper>(
|
||||||
|
bigNotificationImageSize,
|
||||||
|
bigNotificationImageSize
|
||||||
|
) {
|
||||||
|
override fun onResourceReady(
|
||||||
|
resource: BitmapPaletteWrapper,
|
||||||
|
transition: Transition<in BitmapPaletteWrapper>?
|
||||||
|
) {
|
||||||
|
setLargeIcon(
|
||||||
|
resource.bitmap
|
||||||
|
)
|
||||||
|
if (Build.VERSION.SDK_INT <=
|
||||||
|
Build.VERSION_CODES.O && PreferenceUtil.isColoredNotification
|
||||||
|
) {
|
||||||
|
color = RetroColorUtil.getColor(resource.palette, Color.TRANSPARENT)
|
||||||
|
}
|
||||||
|
onUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
|
super.onLoadFailed(errorDrawable)
|
||||||
|
setLargeIcon(null)
|
||||||
|
onUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadCleared(placeholder: Drawable?) {
|
||||||
|
setLargeIcon(null)
|
||||||
|
onUpdate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPlayAction(isPlaying: Boolean): NotificationCompat.Action {
|
||||||
|
val playButtonResId =
|
||||||
|
if (isPlaying) R.drawable.ic_pause_white_48dp else R.drawable.ic_play_arrow_white_48dp
|
||||||
|
return NotificationCompat.Action.Builder(
|
||||||
|
playButtonResId,
|
||||||
|
context.getString(R.string.action_play_pause),
|
||||||
|
retrievePlaybackAction(ACTION_TOGGLE_PAUSE)
|
||||||
|
).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildFavoriteAction(isFavorite: Boolean): NotificationCompat.Action {
|
||||||
|
val favoriteResId =
|
||||||
|
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
||||||
|
return NotificationCompat.Action.Builder(
|
||||||
|
favoriteResId,
|
||||||
|
context.getString(R.string.action_toggle_favorite),
|
||||||
|
retrievePlaybackAction(TOGGLE_FAVORITE)
|
||||||
|
).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setPlaying(isPlaying: Boolean) {
|
||||||
|
mActions[2] = buildPlayAction(isPlaying)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateFavorite(song: Song, onUpdate: () -> Unit) {
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
val playlist: PlaylistEntity = MusicUtil.repository.favoritePlaylist()
|
val playlist: PlaylistEntity = MusicUtil.repository.favoritePlaylist()
|
||||||
val isPlaying = service.isPlaying
|
|
||||||
val isFavorite = if (playlist != null) {
|
val isFavorite = if (playlist != null) {
|
||||||
val songEntity = song.toSongEntity(playlist.playListId)
|
val songEntity = song.toSongEntity(playlist.playListId)
|
||||||
MusicUtil.repository.isFavoriteSong(songEntity).isNotEmpty()
|
MusicUtil.repository.isFavoriteSong(songEntity).isNotEmpty()
|
||||||
} else false
|
} else false
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
val playButtonResId =
|
mActions[0] = buildFavoriteAction(isFavorite)
|
||||||
if (isPlaying) R.drawable.ic_pause_white_48dp else R.drawable.ic_play_arrow_white_48dp
|
onUpdate()
|
||||||
val favoriteResId =
|
|
||||||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
|
||||||
|
|
||||||
val action = Intent(service, MainActivity::class.java)
|
|
||||||
action.putExtra(MainActivity.EXPAND_PANEL, PreferenceUtil.isExpandPanel)
|
|
||||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
|
||||||
val clickIntent =
|
|
||||||
PendingIntent.getActivity(
|
|
||||||
service, 0, action, if (VersionUtils.hasMarshmallow())
|
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
|
||||||
else 0 or PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
|
|
||||||
val serviceName = ComponentName(service, MusicService::class.java)
|
|
||||||
val intent = Intent(ACTION_QUIT)
|
|
||||||
intent.component = serviceName
|
|
||||||
val deleteIntent = PendingIntent.getService(
|
|
||||||
service,
|
|
||||||
0,
|
|
||||||
intent,
|
|
||||||
if (VersionUtils.hasMarshmallow())
|
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
|
||||||
else 0 or PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
val bigNotificationImageSize = service.resources
|
|
||||||
.getDimensionPixelSize(R.dimen.notification_big_image_size)
|
|
||||||
service.runOnUiThread {
|
|
||||||
if (target != null) {
|
|
||||||
Glide.with(service).clear(target)
|
|
||||||
}
|
|
||||||
target = GlideApp.with(service).asBitmapPalette().songCoverOptions(song)
|
|
||||||
.load(RetroGlideExtension.getSongModel(song))
|
|
||||||
//.checkIgnoreMediaStore()
|
|
||||||
.centerCrop()
|
|
||||||
.into(object : SimpleTarget<BitmapPaletteWrapper>(
|
|
||||||
bigNotificationImageSize,
|
|
||||||
bigNotificationImageSize
|
|
||||||
) {
|
|
||||||
override fun onResourceReady(
|
|
||||||
resource: BitmapPaletteWrapper,
|
|
||||||
transition: Transition<in BitmapPaletteWrapper>?
|
|
||||||
) {
|
|
||||||
update(
|
|
||||||
resource.bitmap,
|
|
||||||
RetroColorUtil.getColor(resource.palette, Color.TRANSPARENT)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
|
||||||
super.onLoadFailed(errorDrawable)
|
|
||||||
update(null, Color.TRANSPARENT)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun update(bitmap: Bitmap?, color: Int) {
|
|
||||||
var bitmapFinal = bitmap
|
|
||||||
if (bitmapFinal == null) {
|
|
||||||
bitmapFinal = BitmapFactory.decodeResource(
|
|
||||||
service.resources,
|
|
||||||
R.drawable.default_audio_art
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val toggleFavorite = NotificationCompat.Action(
|
|
||||||
favoriteResId,
|
|
||||||
service.getString(R.string.action_toggle_favorite),
|
|
||||||
retrievePlaybackAction(TOGGLE_FAVORITE)
|
|
||||||
)
|
|
||||||
val playPauseAction = NotificationCompat.Action(
|
|
||||||
playButtonResId,
|
|
||||||
service.getString(R.string.action_play_pause),
|
|
||||||
retrievePlaybackAction(ACTION_TOGGLE_PAUSE)
|
|
||||||
)
|
|
||||||
val previousAction = NotificationCompat.Action(
|
|
||||||
R.drawable.ic_skip_previous_round_white_32dp,
|
|
||||||
service.getString(R.string.action_previous),
|
|
||||||
retrievePlaybackAction(ACTION_REWIND)
|
|
||||||
)
|
|
||||||
val nextAction = NotificationCompat.Action(
|
|
||||||
R.drawable.ic_skip_next_round_white_32dp,
|
|
||||||
service.getString(R.string.action_next),
|
|
||||||
retrievePlaybackAction(ACTION_SKIP)
|
|
||||||
)
|
|
||||||
|
|
||||||
val builder = NotificationCompat.Builder(
|
|
||||||
service,
|
|
||||||
NOTIFICATION_CHANNEL_ID
|
|
||||||
)
|
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
|
||||||
.setLargeIcon(bitmapFinal)
|
|
||||||
.setContentIntent(clickIntent)
|
|
||||||
.setDeleteIntent(deleteIntent)
|
|
||||||
.setContentTitle(
|
|
||||||
HtmlCompat.fromHtml(
|
|
||||||
"<b>" + song.title + "</b>",
|
|
||||||
HtmlCompat.FROM_HTML_MODE_LEGACY
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.setContentText(song.artistName)
|
|
||||||
.setSubText(
|
|
||||||
HtmlCompat.fromHtml(
|
|
||||||
"<b>" + song.albumName + "</b>",
|
|
||||||
HtmlCompat.FROM_HTML_MODE_LEGACY
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.setOngoing(isPlaying)
|
|
||||||
.setShowWhen(false)
|
|
||||||
.addAction(toggleFavorite)
|
|
||||||
.addAction(previousAction)
|
|
||||||
.addAction(playPauseAction)
|
|
||||||
.addAction(nextAction)
|
|
||||||
|
|
||||||
builder.setStyle(
|
|
||||||
MediaStyle()
|
|
||||||
.setMediaSession(service.mediaSession.sessionToken)
|
|
||||||
.setShowActionsInCompactView(1, 2, 3)
|
|
||||||
)
|
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
||||||
if (Build.VERSION.SDK_INT <=
|
|
||||||
Build.VERSION_CODES.O && PreferenceUtil.isColoredNotification
|
|
||||||
) {
|
|
||||||
builder.color = color
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stopped) {
|
|
||||||
return // notification has been stopped before loading was finished
|
|
||||||
}
|
|
||||||
updateNotifyModeAndPostNotification(builder.build())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun retrievePlaybackAction(action: String): PendingIntent {
|
private fun retrievePlaybackAction(action: String): PendingIntent {
|
||||||
val serviceName = ComponentName(service, MusicService::class.java)
|
val serviceName = ComponentName(context, MusicService::class.java)
|
||||||
val intent = Intent(action)
|
val intent = Intent(action)
|
||||||
intent.component = serviceName
|
intent.component = serviceName
|
||||||
return PendingIntent.getService(
|
return PendingIntent.getService(
|
||||||
service, 0, intent,
|
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or
|
||||||
if (VersionUtils.hasMarshmallow()) PendingIntent.FLAG_IMMUTABLE
|
if (VersionUtils.hasMarshmallow()) PendingIntent.FLAG_IMMUTABLE
|
||||||
else 0 or PendingIntent.FLAG_UPDATE_CURRENT
|
else 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun from(
|
||||||
|
context: Context,
|
||||||
|
notificationManager: NotificationManager,
|
||||||
|
mediaSession: MediaSessionCompat
|
||||||
|
): PlayingNotification {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
createNotificationChannel(context, notificationManager)
|
||||||
|
}
|
||||||
|
return PlayingNotificationImpl(context, mediaSession.sessionToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
package code.name.monkey.retromusic.service.notification
|
package code.name.monkey.retromusic.service.notification
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
@ -21,6 +23,7 @@ import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.os.Build
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor
|
import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor
|
||||||
|
@ -29,6 +32,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
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.activities.MainActivity
|
import code.name.monkey.retromusic.activities.MainActivity
|
||||||
|
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||||
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.glide.palette.BitmapPaletteWrapper
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||||
|
@ -39,224 +43,231 @@ import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import code.name.monkey.retromusic.util.RetroUtil.createBitmap
|
import code.name.monkey.retromusic.util.RetroUtil.createBitmap
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.request.target.CustomTarget
|
||||||
import com.bumptech.glide.request.target.SimpleTarget
|
|
||||||
import com.bumptech.glide.request.target.Target
|
|
||||||
import com.bumptech.glide.request.transition.Transition
|
import com.bumptech.glide.request.transition.Transition
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hemanth S (h4h13).
|
* @author Hemanth S (h4h13).
|
||||||
*/
|
*/
|
||||||
class PlayingNotificationOreo : PlayingNotification() {
|
@SuppressLint("RestrictedApi")
|
||||||
|
class PlayingNotificationOreo(
|
||||||
|
val context: Context
|
||||||
|
) : PlayingNotification(context) {
|
||||||
|
|
||||||
private var target: Target<BitmapPaletteWrapper>? = null
|
private var primaryColor: Int = 0
|
||||||
|
|
||||||
private fun getCombinedRemoteViews(collapsed: Boolean, song: Song): RemoteViews {
|
init {
|
||||||
val remoteViews = RemoteViews(
|
val notificationLayout = getCombinedRemoteViews(true)
|
||||||
service.packageName,
|
val notificationLayoutBig = getCombinedRemoteViews(false)
|
||||||
if (collapsed) R.layout.layout_notification_collapsed else R.layout.layout_notification_expanded
|
|
||||||
)
|
|
||||||
remoteViews.setTextViewText(
|
|
||||||
R.id.appName,
|
|
||||||
service.getString(R.string.app_name) + " • " + song.albumName
|
|
||||||
)
|
|
||||||
remoteViews.setTextViewText(R.id.title, song.title)
|
|
||||||
remoteViews.setTextViewText(R.id.subtitle, song.artistName)
|
|
||||||
linkButtons(remoteViews)
|
|
||||||
return remoteViews
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update() {
|
val action = Intent(context, MainActivity::class.java)
|
||||||
stopped = false
|
|
||||||
val song = service.currentSong
|
|
||||||
val isPlaying = service.isPlaying
|
|
||||||
|
|
||||||
val notificationLayout = getCombinedRemoteViews(true, song)
|
|
||||||
val notificationLayoutBig = getCombinedRemoteViews(false, song)
|
|
||||||
|
|
||||||
val action = Intent(service, MainActivity::class.java)
|
|
||||||
action.putExtra(MainActivity.EXPAND_PANEL, PreferenceUtil.isExpandPanel)
|
action.putExtra(MainActivity.EXPAND_PANEL, PreferenceUtil.isExpandPanel)
|
||||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
|
|
||||||
val clickIntent = PendingIntent
|
val clickIntent = PendingIntent
|
||||||
.getActivity(
|
.getActivity(
|
||||||
service,
|
context,
|
||||||
0,
|
0,
|
||||||
action,
|
action,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or if (VersionUtils.hasMarshmallow())
|
PendingIntent.FLAG_UPDATE_CURRENT or if (VersionUtils.hasMarshmallow())
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
else 0
|
else 0
|
||||||
)
|
)
|
||||||
val deleteIntent = buildPendingIntent(service, ACTION_QUIT, null)
|
val deleteIntent = buildPendingIntent(context, ACTION_QUIT, null)
|
||||||
|
|
||||||
val builder = NotificationCompat.Builder(service, NOTIFICATION_CHANNEL_ID)
|
setSmallIcon(R.drawable.ic_notification)
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
setContentIntent(clickIntent)
|
||||||
.setContentIntent(clickIntent)
|
setDeleteIntent(deleteIntent)
|
||||||
.setDeleteIntent(deleteIntent)
|
setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
priority = NotificationCompat.PRIORITY_MAX
|
||||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
setCustomContentView(notificationLayout)
|
||||||
.setCustomContentView(notificationLayout)
|
setCustomBigContentView(notificationLayoutBig)
|
||||||
.setCustomBigContentView(notificationLayoutBig)
|
setOngoing(true)
|
||||||
.setOngoing(isPlaying)
|
|
||||||
|
|
||||||
val bigNotificationImageSize = service.resources
|
|
||||||
.getDimensionPixelSize(R.dimen.notification_big_image_size)
|
|
||||||
service.runOnUiThread {
|
|
||||||
if (target != null) {
|
|
||||||
Glide.with(service).clear(target)
|
|
||||||
}
|
|
||||||
target = GlideApp.with(service).asBitmapPalette().songCoverOptions(song)
|
|
||||||
.load(RetroGlideExtension.getSongModel(song))
|
|
||||||
.centerCrop()
|
|
||||||
.into(object : SimpleTarget<BitmapPaletteWrapper>(
|
|
||||||
bigNotificationImageSize,
|
|
||||||
bigNotificationImageSize
|
|
||||||
) {
|
|
||||||
override fun onResourceReady(
|
|
||||||
resource: BitmapPaletteWrapper,
|
|
||||||
transition: Transition<in BitmapPaletteWrapper>?
|
|
||||||
) {
|
|
||||||
/* val mediaNotificationProcessor = MediaNotificationProcessor(
|
|
||||||
service,
|
|
||||||
service
|
|
||||||
) { i, _ -> update(resource.bitmap, i) }
|
|
||||||
mediaNotificationProcessor.processNotification(resource.bitmap)*/
|
|
||||||
|
|
||||||
val colors = MediaNotificationProcessor(service, resource.bitmap)
|
|
||||||
update(resource.bitmap, colors.backgroundColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
|
||||||
super.onLoadFailed(errorDrawable)
|
|
||||||
update(
|
|
||||||
null,
|
|
||||||
resolveColor(service, R.attr.colorSurface, Color.WHITE)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun update(bitmap: Bitmap?, bgColor: Int) {
|
|
||||||
var bgColorFinal = bgColor
|
|
||||||
if (bitmap != null) {
|
|
||||||
notificationLayout.setImageViewBitmap(R.id.largeIcon, bitmap)
|
|
||||||
notificationLayoutBig.setImageViewBitmap(R.id.largeIcon, bitmap)
|
|
||||||
} else {
|
|
||||||
notificationLayout.setImageViewResource(
|
|
||||||
R.id.largeIcon,
|
|
||||||
R.drawable.default_audio_art
|
|
||||||
)
|
|
||||||
notificationLayoutBig.setImageViewResource(
|
|
||||||
R.id.largeIcon,
|
|
||||||
R.drawable.default_audio_art
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Android 12 applies a standard Notification template to every notification
|
|
||||||
// which will in turn have a default background so setting a different background
|
|
||||||
// than that, looks weird
|
|
||||||
if (!VersionUtils.hasS()) {
|
|
||||||
if (!PreferenceUtil.isColoredNotification) {
|
|
||||||
bgColorFinal =
|
|
||||||
resolveColor(service, R.attr.colorPrimary, Color.WHITE)
|
|
||||||
}
|
|
||||||
setBackgroundColor(bgColorFinal)
|
|
||||||
}
|
|
||||||
setNotificationContent(ColorUtil.isColorLight(bgColorFinal))
|
|
||||||
|
|
||||||
if (stopped) {
|
|
||||||
return // notification has been stopped before loading was finished
|
|
||||||
}
|
|
||||||
updateNotifyModeAndPostNotification(builder.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setBackgroundColor(color: Int) {
|
|
||||||
notificationLayout.setInt(R.id.image, "setBackgroundColor", color)
|
|
||||||
notificationLayoutBig.setInt(R.id.image, "setBackgroundColor", color)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setNotificationContent(dark: Boolean) {
|
|
||||||
val primary = MaterialValueHelper.getPrimaryTextColor(service, dark)
|
|
||||||
val secondary = MaterialValueHelper.getSecondaryTextColor(service, dark)
|
|
||||||
|
|
||||||
val close = createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
service,
|
|
||||||
R.drawable.ic_close,
|
|
||||||
primary
|
|
||||||
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
|
|
||||||
)
|
|
||||||
val prev = createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
service,
|
|
||||||
R.drawable.ic_skip_previous_round_white_32dp,
|
|
||||||
primary
|
|
||||||
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
|
|
||||||
)
|
|
||||||
val next = createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
service,
|
|
||||||
R.drawable.ic_skip_next_round_white_32dp,
|
|
||||||
primary
|
|
||||||
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
|
|
||||||
)
|
|
||||||
val playPause = createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
service,
|
|
||||||
if (isPlaying)
|
|
||||||
R.drawable.ic_pause_white_48dp
|
|
||||||
else
|
|
||||||
R.drawable.ic_play_arrow_white_48dp, primary
|
|
||||||
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
|
|
||||||
)
|
|
||||||
|
|
||||||
notificationLayout.setTextColor(R.id.title, primary)
|
|
||||||
notificationLayout.setTextColor(R.id.subtitle, secondary)
|
|
||||||
notificationLayout.setTextColor(R.id.appName, secondary)
|
|
||||||
|
|
||||||
notificationLayout.setImageViewBitmap(R.id.action_prev, prev)
|
|
||||||
notificationLayout.setImageViewBitmap(R.id.action_next, next)
|
|
||||||
notificationLayout.setImageViewBitmap(R.id.action_play_pause, playPause)
|
|
||||||
|
|
||||||
notificationLayoutBig.setTextColor(R.id.title, primary)
|
|
||||||
notificationLayoutBig.setTextColor(R.id.subtitle, secondary)
|
|
||||||
notificationLayoutBig.setTextColor(R.id.appName, secondary)
|
|
||||||
|
|
||||||
notificationLayoutBig.setImageViewBitmap(R.id.action_quit, close)
|
|
||||||
notificationLayoutBig.setImageViewBitmap(R.id.action_prev, prev)
|
|
||||||
notificationLayoutBig.setImageViewBitmap(R.id.action_next, next)
|
|
||||||
notificationLayoutBig.setImageViewBitmap(R.id.action_play_pause, playPause)
|
|
||||||
|
|
||||||
notificationLayout.setImageViewBitmap(
|
|
||||||
R.id.smallIcon,
|
|
||||||
createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
service,
|
|
||||||
R.drawable.ic_notification,
|
|
||||||
secondary
|
|
||||||
), 0.6f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
notificationLayoutBig.setImageViewBitmap(
|
|
||||||
R.id.smallIcon,
|
|
||||||
createBitmap(
|
|
||||||
RetroUtil.getTintedVectorDrawable(
|
|
||||||
service,
|
|
||||||
R.drawable.ic_notification,
|
|
||||||
secondary
|
|
||||||
), 0.6f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stopped) {
|
|
||||||
return // notification has been stopped before loading was finished
|
|
||||||
}
|
|
||||||
updateNotifyModeAndPostNotification(builder.build())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getCombinedRemoteViews(collapsed: Boolean): RemoteViews {
|
||||||
|
val remoteViews = RemoteViews(
|
||||||
|
context.packageName,
|
||||||
|
if (collapsed) R.layout.layout_notification_collapsed else R.layout.layout_notification_expanded
|
||||||
|
)
|
||||||
|
linkButtons(remoteViews)
|
||||||
|
return remoteViews
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
override fun updateMetadata(song: Song, onUpdate: () -> Unit) {
|
||||||
|
val bigNotificationImageSize = context.resources
|
||||||
|
.getDimensionPixelSize(R.dimen.notification_big_image_size)
|
||||||
|
GlideApp.with(context).asBitmapPalette().songCoverOptions(song)
|
||||||
|
.load(RetroGlideExtension.getSongModel(song))
|
||||||
|
.centerCrop()
|
||||||
|
.into(object : CustomTarget<BitmapPaletteWrapper>(
|
||||||
|
bigNotificationImageSize,
|
||||||
|
bigNotificationImageSize
|
||||||
|
) {
|
||||||
|
override fun onResourceReady(
|
||||||
|
resource: BitmapPaletteWrapper,
|
||||||
|
transition: Transition<in BitmapPaletteWrapper>?
|
||||||
|
) {
|
||||||
|
val colors = MediaNotificationProcessor(context, resource.bitmap)
|
||||||
|
update(resource.bitmap, colors.backgroundColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
|
super.onLoadFailed(errorDrawable)
|
||||||
|
update(
|
||||||
|
null,
|
||||||
|
resolveColor(context, R.attr.colorSurface, Color.WHITE)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadCleared(placeholder: Drawable?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun update(bitmap: Bitmap?, bgColor: Int) {
|
||||||
|
var bgColorFinal = bgColor
|
||||||
|
if (bitmap != null) {
|
||||||
|
contentView.setImageViewBitmap(R.id.largeIcon, bitmap)
|
||||||
|
bigContentView.setImageViewBitmap(R.id.largeIcon, bitmap)
|
||||||
|
} else {
|
||||||
|
contentView.setImageViewResource(
|
||||||
|
R.id.largeIcon,
|
||||||
|
R.drawable.default_audio_art
|
||||||
|
)
|
||||||
|
bigContentView.setImageViewResource(
|
||||||
|
R.id.largeIcon,
|
||||||
|
R.drawable.default_audio_art
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Android 12 applies a standard Notification template to every notification
|
||||||
|
// which will in turn have a default background so setting a different background
|
||||||
|
// than that, looks weird
|
||||||
|
if (!VersionUtils.hasS()) {
|
||||||
|
if (!PreferenceUtil.isColoredNotification) {
|
||||||
|
bgColorFinal =
|
||||||
|
resolveColor(context, R.attr.colorSurface, Color.WHITE)
|
||||||
|
}
|
||||||
|
setBackgroundColor(bgColorFinal)
|
||||||
|
setNotificationContent(ColorUtil.isColorLight(bgColorFinal))
|
||||||
|
}else {
|
||||||
|
setNotificationContent(!ColorUtil.isColorLight(context.surfaceColor()))
|
||||||
|
}
|
||||||
|
onUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setBackgroundColor(color: Int) {
|
||||||
|
contentView.setInt(R.id.image, "setBackgroundColor", color)
|
||||||
|
bigContentView.setInt(R.id.image, "setBackgroundColor", color)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setNotificationContent(dark: Boolean) {
|
||||||
|
val primary = MaterialValueHelper.getPrimaryTextColor(context, dark)
|
||||||
|
val secondary = MaterialValueHelper.getSecondaryTextColor(context, dark)
|
||||||
|
primaryColor = primary
|
||||||
|
|
||||||
|
val close = createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_close,
|
||||||
|
primary
|
||||||
|
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
|
||||||
|
)
|
||||||
|
val prev = createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_skip_previous_round_white_32dp,
|
||||||
|
primary
|
||||||
|
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
|
||||||
|
)
|
||||||
|
val next = createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_skip_next_round_white_32dp,
|
||||||
|
primary
|
||||||
|
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
|
||||||
|
)
|
||||||
|
val playPause = getPlayPauseBitmap(true)
|
||||||
|
|
||||||
|
contentView.setTextColor(R.id.title, primary)
|
||||||
|
contentView.setTextColor(R.id.subtitle, secondary)
|
||||||
|
contentView.setTextColor(R.id.appName, secondary)
|
||||||
|
|
||||||
|
contentView.setImageViewBitmap(R.id.action_prev, prev)
|
||||||
|
contentView.setImageViewBitmap(R.id.action_next, next)
|
||||||
|
contentView.setImageViewBitmap(R.id.action_play_pause, playPause)
|
||||||
|
|
||||||
|
contentView.setTextViewText(
|
||||||
|
R.id.appName,
|
||||||
|
context.getString(R.string.app_name) + " • " + song.albumName
|
||||||
|
)
|
||||||
|
contentView.setTextViewText(R.id.title, song.title)
|
||||||
|
contentView.setTextViewText(R.id.subtitle, song.artistName)
|
||||||
|
|
||||||
|
|
||||||
|
bigContentView.setTextColor(R.id.title, primary)
|
||||||
|
bigContentView.setTextColor(R.id.subtitle, secondary)
|
||||||
|
bigContentView.setTextColor(R.id.appName, secondary)
|
||||||
|
|
||||||
|
bigContentView.setImageViewBitmap(R.id.action_quit, close)
|
||||||
|
bigContentView.setImageViewBitmap(R.id.action_prev, prev)
|
||||||
|
bigContentView.setImageViewBitmap(R.id.action_next, next)
|
||||||
|
bigContentView.setImageViewBitmap(R.id.action_play_pause, playPause)
|
||||||
|
|
||||||
|
bigContentView.setTextViewText(
|
||||||
|
R.id.appName,
|
||||||
|
context.getString(R.string.app_name) + " • " + song.albumName
|
||||||
|
)
|
||||||
|
bigContentView.setTextViewText(R.id.title, song.title)
|
||||||
|
bigContentView.setTextViewText(R.id.subtitle, song.artistName)
|
||||||
|
|
||||||
|
|
||||||
|
contentView.setImageViewBitmap(
|
||||||
|
R.id.smallIcon,
|
||||||
|
createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_notification,
|
||||||
|
secondary
|
||||||
|
), 0.6f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
bigContentView.setImageViewBitmap(
|
||||||
|
R.id.smallIcon,
|
||||||
|
createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_notification,
|
||||||
|
secondary
|
||||||
|
), 0.6f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPlayPauseBitmap(isPlaying: Boolean): Bitmap {
|
||||||
|
return createBitmap(
|
||||||
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
context,
|
||||||
|
if (isPlaying)
|
||||||
|
R.drawable.ic_pause_white_48dp
|
||||||
|
else
|
||||||
|
R.drawable.ic_play_arrow_white_48dp, primaryColor
|
||||||
|
), NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setPlaying(isPlaying: Boolean) {
|
||||||
|
getPlayPauseBitmap(isPlaying).also {
|
||||||
|
contentView.setImageViewBitmap(R.id.action_play_pause, it)
|
||||||
|
bigContentView.setImageViewBitmap(R.id.action_play_pause, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateFavorite(song: Song, onUpdate: () -> Unit) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildPendingIntent(
|
private fun buildPendingIntent(
|
||||||
context: Context, action: String,
|
context: Context, action: String,
|
||||||
|
@ -275,23 +286,34 @@ class PlayingNotificationOreo : PlayingNotification() {
|
||||||
private fun linkButtons(notificationLayout: RemoteViews) {
|
private fun linkButtons(notificationLayout: RemoteViews) {
|
||||||
var pendingIntent: PendingIntent
|
var pendingIntent: PendingIntent
|
||||||
|
|
||||||
val serviceName = ComponentName(service, MusicService::class.java)
|
val serviceName = ComponentName(context, MusicService::class.java)
|
||||||
|
|
||||||
// Previous track
|
// Previous track
|
||||||
pendingIntent = buildPendingIntent(service, ACTION_REWIND, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName)
|
||||||
notificationLayout.setOnClickPendingIntent(R.id.action_prev, pendingIntent)
|
notificationLayout.setOnClickPendingIntent(R.id.action_prev, pendingIntent)
|
||||||
|
|
||||||
// Play and pause
|
// Play and pause
|
||||||
pendingIntent = buildPendingIntent(service, ACTION_TOGGLE_PAUSE, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName)
|
||||||
notificationLayout.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent)
|
notificationLayout.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent)
|
||||||
|
|
||||||
// Next track
|
// Next track
|
||||||
pendingIntent = buildPendingIntent(service, ACTION_SKIP, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName)
|
||||||
notificationLayout.setOnClickPendingIntent(R.id.action_next, pendingIntent)
|
notificationLayout.setOnClickPendingIntent(R.id.action_next, pendingIntent)
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
pendingIntent = buildPendingIntent(service, ACTION_QUIT, serviceName)
|
pendingIntent = buildPendingIntent(context, ACTION_QUIT, serviceName)
|
||||||
notificationLayout.setOnClickPendingIntent(R.id.action_quit, pendingIntent)
|
notificationLayout.setOnClickPendingIntent(R.id.action_quit, pendingIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(
|
||||||
|
context: Context,
|
||||||
|
notificationManager: NotificationManager
|
||||||
|
): PlayingNotification {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
createNotificationChannel(context, notificationManager)
|
||||||
|
}
|
||||||
|
return PlayingNotificationOreo(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,7 @@ object MusicUtil : KoinComponent {
|
||||||
var musicMediaTitle = mediaTitle
|
var musicMediaTitle = mediaTitle
|
||||||
return try {
|
return try {
|
||||||
if (TextUtils.isEmpty(musicMediaTitle)) {
|
if (TextUtils.isEmpty(musicMediaTitle)) {
|
||||||
return ""
|
return "-"
|
||||||
}
|
}
|
||||||
musicMediaTitle = musicMediaTitle!!.trim { it <= ' ' }.lowercase()
|
musicMediaTitle = musicMediaTitle!!.trim { it <= ' ' }.lowercase()
|
||||||
if (musicMediaTitle.startsWith("the ")) {
|
if (musicMediaTitle.startsWith("the ")) {
|
||||||
|
@ -526,6 +526,7 @@ object MusicUtil : KoinComponent {
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
fun deleteTracksR(activity: Activity, songs: List<Song>) {
|
fun deleteTracksR(activity: Activity, songs: List<Song>) {
|
||||||
|
removeFromQueue(songs)
|
||||||
val pendingIntent = MediaStore.createDeleteRequest(activity.contentResolver, songs.map {
|
val pendingIntent = MediaStore.createDeleteRequest(activity.contentResolver, songs.map {
|
||||||
getSongFileUri(it.id)
|
getSongFileUri(it.id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -372,7 +372,7 @@ object PreferenceUtil {
|
||||||
|
|
||||||
var artistGridStyle: GridStyle
|
var artistGridStyle: GridStyle
|
||||||
get() {
|
get() {
|
||||||
val id: Int = sharedPreferences.getInt(ARTIST_GRID_STYLE, 4)
|
val id: Int = sharedPreferences.getInt(ARTIST_GRID_STYLE, 3)
|
||||||
return GridStyle.values().firstOrNull { gridStyle ->
|
return GridStyle.values().firstOrNull { gridStyle ->
|
||||||
gridStyle.id == id
|
gridStyle.id == id
|
||||||
} ?: GridStyle.Circular
|
} ?: GridStyle.Circular
|
||||||
|
|
|
@ -473,4 +473,12 @@ public class MediaNotificationProcessor {
|
||||||
public interface OnPaletteLoadedListener {
|
public interface OnPaletteLoadedListener {
|
||||||
void onPaletteLoaded(MediaNotificationProcessor mediaNotificationProcessor);
|
void onPaletteLoaded(MediaNotificationProcessor mediaNotificationProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MediaNotificationProcessor errorColor(Context context) {
|
||||||
|
MediaNotificationProcessor errorColors = new MediaNotificationProcessor(context);
|
||||||
|
errorColors.backgroundColor = 0x15724528;
|
||||||
|
errorColors.primaryTextColor = 0x6974059;
|
||||||
|
errorColors.secondaryTextColor = 0x8684677;
|
||||||
|
return errorColors;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
10
app/src/main/res/drawable/app_widget_background.xml
Normal file
10
app/src/main/res/drawable/app_widget_background.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Background for widgets to make the rounded corners based on the
|
||||||
|
appWidgetRadius attribute value
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<corners android:radius="16dp" />
|
||||||
|
<solid android:color="?android:attr/colorBackground" />
|
||||||
|
</shape>
|
100
app/src/main/res/layout/app_widget_md3.xml
Normal file
100
app/src/main/res/layout/app_widget_md3.xml
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/app_widget_md3_height"
|
||||||
|
android:background="@drawable/app_widget_background"
|
||||||
|
android:backgroundTint="?android:attr/colorBackground"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="ContentDescription">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="@dimen/app_widget_md3_image_size"
|
||||||
|
android:layout_height="@dimen/app_widget_md3_image_size"
|
||||||
|
android:background="@drawable/app_widget_background"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/media_actions"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layoutDirection="ltr"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/button_prev"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/widget_selector"
|
||||||
|
tools:src="@drawable/ic_skip_previous"
|
||||||
|
tools:tint="@color/ate_secondary_text_dark" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/button_toggle_play_pause"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/widget_selector"
|
||||||
|
tools:src="@drawable/ic_play_arrow_white_32dp"
|
||||||
|
tools:tint="@color/ate_secondary_text_dark" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/button_next"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/widget_selector"
|
||||||
|
tools:src="@drawable/ic_skip_next"
|
||||||
|
tools:tint="@color/ate_secondary_text_dark" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/media_titles"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@+id/media_actions"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:paddingEnd="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextViewSubtitle1"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
tools:text="Title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextViewNormal"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
tools:text="Text" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
|
@ -5,5 +5,5 @@
|
||||||
android:id="@+id/action_search"
|
android:id="@+id/action_search"
|
||||||
android:icon="@drawable/ic_search"
|
android:icon="@drawable/ic_search"
|
||||||
android:title="@string/action_search"
|
android:title="@string/action_search"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="always" />
|
||||||
</menu>
|
</menu>
|
|
@ -39,6 +39,9 @@
|
||||||
<dimen name="app_widget_card_radius">2dp</dimen>
|
<dimen name="app_widget_card_radius">2dp</dimen>
|
||||||
<dimen name="now_playing_top_margin">12dp</dimen>
|
<dimen name="now_playing_top_margin">12dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="app_widget_md3_height">96dp</dimen>
|
||||||
|
<dimen name="app_widget_md3_image_size">80dp</dimen>
|
||||||
|
|
||||||
<dimen name="icon_notification_dimen">32dp</dimen>
|
<dimen name="icon_notification_dimen">32dp</dimen>
|
||||||
<dimen name="toolbar_margin_horizontal">8dp</dimen>
|
<dimen name="toolbar_margin_horizontal">8dp</dimen>
|
||||||
<dimen name="toolbar_height">48dp</dimen>
|
<dimen name="toolbar_height">48dp</dimen>
|
||||||
|
|
|
@ -454,6 +454,7 @@
|
||||||
<string name="sort_order_a_z">Ascending</string>
|
<string name="sort_order_a_z">Ascending</string>
|
||||||
<string name="sort_order_album">Album</string>
|
<string name="sort_order_album">Album</string>
|
||||||
<string name="sort_order_artist">Artist</string>
|
<string name="sort_order_artist">Artist</string>
|
||||||
|
<string name="sort_order_album_artist">@string/album_artist</string>
|
||||||
<string name="sort_order_composer">Composer</string>
|
<string name="sort_order_composer">Composer</string>
|
||||||
<string name="sort_order_date">Date added</string>
|
<string name="sort_order_date">Date added</string>
|
||||||
<string name="sort_order_date_modified">Date modified</string>
|
<string name="sort_order_date_modified">Date modified</string>
|
||||||
|
@ -517,4 +518,5 @@
|
||||||
<string name="restore_message">Do you want to restore backup?</string>
|
<string name="restore_message">Do you want to restore backup?</string>
|
||||||
<string name="title_new_backup">New Backup</string>
|
<string name="title_new_backup">New Backup</string>
|
||||||
<string name="backup_restore_settings_summary">Backup and restore your settings, playlists</string>
|
<string name="backup_restore_settings_summary">Backup and restore your settings, playlists</string>
|
||||||
|
<string name="app_widget_md3_name">MD3</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
11
app/src/main/res/xml/app_widget_md3_info.xml
Normal file
11
app/src/main/res/xml/app_widget_md3_info.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:initialLayout="@layout/app_widget_classic"
|
||||||
|
android:minWidth="@dimen/app_widget_classic_min_width"
|
||||||
|
android:minHeight="@dimen/app_widget_classic_min_height"
|
||||||
|
android:previewImage="@drawable/widget_classic"
|
||||||
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:updatePeriodMillis="0"
|
||||||
|
android:widgetCategory="keyguard|home_screen"
|
||||||
|
tools:ignore="UnusedAttribute" />
|
|
@ -25,7 +25,7 @@ dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||||
implementation 'com.google.android.material:material:1.5.0-beta01'
|
implementation 'com.google.android.material:material:1.5.0-beta01'
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.2.0-beta01'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package code.name.monkey.appthemehelper
|
package code.name.monkey.appthemehelper
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
|
@ -18,7 +18,6 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
*/
|
*/
|
||||||
object ATH {
|
object ATH {
|
||||||
|
|
||||||
@SuppressLint("CommitPrefEdits")
|
|
||||||
fun didThemeValuesChange(context: Context, since: Long): Boolean {
|
fun didThemeValuesChange(context: Context, since: Long): Boolean {
|
||||||
return ThemeStore.isConfigured(context) && ThemeStore.prefs(context).getLong(
|
return ThemeStore.isConfigured(context) && ThemeStore.prefs(context).getLong(
|
||||||
ThemeStorePrefKeys.VALUES_CHANGED,
|
ThemeStorePrefKeys.VALUES_CHANGED,
|
||||||
|
@ -26,7 +25,7 @@ object ATH {
|
||||||
) > since
|
) > since
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLightStatusbar(activity: Activity, enabled: Boolean) {
|
fun setLightStatusBar(activity: Activity, enabled: Boolean) {
|
||||||
activity.window.apply {
|
activity.window.apply {
|
||||||
WindowInsetsControllerCompat(
|
WindowInsetsControllerCompat(
|
||||||
this,
|
this,
|
||||||
|
@ -36,29 +35,26 @@ object ATH {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLightNavigationbar(activity: Activity, enabled: Boolean) {
|
fun setLightNavigationbar(activity: Activity, enabled: Boolean) {
|
||||||
activity.window?.apply {
|
activity.window.apply {
|
||||||
WindowInsetsControllerCompat(
|
WindowInsetsControllerCompat(
|
||||||
this,
|
this,
|
||||||
decorView
|
decorView
|
||||||
).isAppearanceLightNavigationBars = enabled
|
).isAppearanceLightNavigationBars = enabled
|
||||||
|
navigationBarColor = Color.TRANSPARENT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLightNavigationbarAuto(activity: Activity, bgColor: Int) {
|
fun setLightNavigationBarAuto(activity: Activity, bgColor: Int) {
|
||||||
setLightNavigationbar(activity, ColorUtil.isColorLight(bgColor))
|
setLightNavigationbar(activity, ColorUtil.isColorLight(bgColor))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setNavigationbarColorAuto(activity: Activity) {
|
fun setNavigationBarColor(activity: Activity, color: Int) {
|
||||||
setNavigationbarColor(activity, ThemeStore.navigationBarColor(activity))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setNavigationbarColor(activity: Activity, color: Int) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
activity.window.navigationBarColor = color
|
activity.window.navigationBarColor = color
|
||||||
} else {
|
} else {
|
||||||
activity.window.navigationBarColor = ColorUtil.darkenColor(color)
|
activity.window.navigationBarColor = ColorUtil.darkenColor(color)
|
||||||
}
|
}
|
||||||
setLightNavigationbarAuto(activity, color)
|
setLightNavigationBarAuto(activity, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setActivityToolbarColorAuto(activity: Activity, toolbar: Toolbar?) {
|
fun setActivityToolbarColorAuto(activity: Activity, toolbar: Toolbar?) {
|
||||||
|
|
|
@ -43,9 +43,9 @@ class ATEColorPreference @JvmOverloads constructor(
|
||||||
invalidateColor()
|
invalidateColor()
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: PreferenceViewHolder?) {
|
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||||
super.onBindViewHolder(holder)
|
super.onBindViewHolder(holder)
|
||||||
mView = holder?.itemView
|
mView = holder.itemView
|
||||||
invalidateColor()
|
invalidateColor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import androidx.preference.PreferenceViewHolder
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
|
|
||||||
class ATEPreferenceCategory @JvmOverloads constructor(
|
class ATEPreferenceCategory @JvmOverloads constructor(
|
||||||
context: Context?,
|
context: Context,
|
||||||
attrs: AttributeSet?,
|
attrs: AttributeSet?,
|
||||||
defStyleAttr: Int = -1,
|
defStyleAttr: Int = -1,
|
||||||
defStyleRes: Int = -1
|
defStyleRes: Int = -1
|
||||||
|
|
|
@ -9,9 +9,9 @@ buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
def nav_version = "2.3.5"
|
def nav_version = "2.4.0-beta02"
|
||||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
|
||||||
classpath "com.diffplug.spotless:spotless-plugin-gradle:5.16.0"
|
classpath "com.diffplug.spotless:spotless-plugin-gradle:6.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue