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
app
build.gradle
src/main
AndroidManifest.xml
java/code/name/monkey/retromusic
activities
DriveModeActivity.ktLockScreenActivity.ktMainActivity.ktPermissionActivity.ktPurchaseActivity.ktSettingsActivity.ktShareInstagramStory.ktSupportDevelopmentActivity.ktWhatsNewActivity.kt
base
bugreport
tageditor
adapter/album
appwidgets
extensions
fragments
LibraryViewModel.kt
albums
base
other
player
adaptive
blur
card
cardblur
classic
color
fit
flat
full
normal
peak
plain
simple
tiny
playlists
settings
glide
helper
service
MusicService.java
notification
util
res
drawable
layout
menu
values
xml
appthemehelper
build.gradle
build.gradlesrc/main/java/code/name/monkey/appthemehelper
|
@ -15,8 +15,8 @@ android {
|
|||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
applicationId "code.name.monkey.retromusic"
|
||||
versionCode 10544
|
||||
versionName '5.4.1 ' + "_" + getDate()
|
||||
versionCode 10545
|
||||
versionName '5.4.2 ' + "_" + getDate()
|
||||
|
||||
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.annotation:annotation:1.3.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.0-alpha01'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.0-beta01'
|
||||
implementation 'androidx.core:core-ktx:1.7.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-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-ktx:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
|
@ -138,7 +138,7 @@ dependencies {
|
|||
|
||||
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-android:$kotlin_coroutines_version"
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
<activity android:name=".activities.PermissionActivity" />
|
||||
<activity android:name=".activities.LockScreenActivity" />
|
||||
<activity
|
||||
android:name="code.name.monkey.retromusic.fragments.backup.RestoreActivity"
|
||||
android:name=".fragments.backup.RestoreActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
@ -256,13 +256,25 @@
|
|||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/app_widget_card_info" />
|
||||
</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
|
||||
android:name=".service.MusicService"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:foregroundServiceType="mediaPlayback"
|
||||
android:label="@string/app_name"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<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.activities.base.AbsMusicServiceActivity
|
||||
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.glide.BlurTransformation
|
||||
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.activities.base.AbsMusicServiceActivity
|
||||
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.glide.GlideApp
|
||||
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||
|
@ -47,7 +47,7 @@ class LockScreenActivity : AbsMusicServiceActivity() {
|
|||
binding = ActivityLockScreenBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
hideStatusBar()
|
||||
setStatusbarColorAuto()
|
||||
setStatusBarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
|
||||
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.activities.base.AbsCastActivity
|
||||
import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding
|
||||
import code.name.monkey.retromusic.extensions.currentFragment
|
||||
import code.name.monkey.retromusic.extensions.extra
|
||||
import code.name.monkey.retromusic.extensions.findNavController
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewFragment
|
||||
import code.name.monkey.retromusic.fragments.home.HomeFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
|
@ -136,8 +134,8 @@ class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener {
|
|||
PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
|
||||
val expand = extra<Boolean>(EXPAND_PANEL).value ?: false
|
||||
if (expand && PreferenceUtil.isExpandPanel) {
|
||||
setBottomNavVisibility(false)
|
||||
fromNotification = true
|
||||
slidingPanel.bringToFront()
|
||||
expandPanel()
|
||||
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.databinding.ActivityPermissionBinding
|
||||
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.util.RingtoneManager
|
||||
|
||||
|
@ -40,7 +42,7 @@ class PermissionActivity : AbsMusicServiceActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityPermissionBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setStatusbarColorAuto()
|
||||
setStatusBarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
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.activities.base.AbsBaseActivity
|
||||
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.PurchaseInfo
|
||||
|
||||
|
@ -41,8 +44,8 @@ class PurchaseActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
|
|||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityProVersionBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setStatusbarColor(Color.TRANSPARENT)
|
||||
setLightStatusbar(false)
|
||||
setStatusBarColor(Color.TRANSPARENT)
|
||||
setLightStatusBar(false)
|
||||
binding.toolbar.navigationIcon?.setTint(Color.WHITE)
|
||||
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.appshortcuts.DynamicShortcutManager
|
||||
import code.name.monkey.retromusic.databinding.ActivitySettingsBinding
|
||||
import code.name.monkey.retromusic.extensions.applyToolbar
|
||||
import code.name.monkey.retromusic.extensions.extra
|
||||
import code.name.monkey.retromusic.extensions.findNavController
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.color.ColorCallback
|
||||
|
||||
|
@ -38,7 +35,7 @@ class SettingsActivity : AbsThemeActivity(), ColorCallback, OnThemeChangedListen
|
|||
setDrawUnderStatusBar()
|
||||
val mSavedInstanceState = extra<Bundle>(TAG).value ?: savedInstanceState
|
||||
super.onCreate(mSavedInstanceState)
|
||||
setLightStatusbarAuto(surfaceColor())
|
||||
setLightStatusBarAuto(surfaceColor())
|
||||
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setupToolbar()
|
||||
|
|
|
@ -28,6 +28,10 @@ import code.name.monkey.appthemehelper.util.ColorUtil
|
|||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||
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.RetroGlideExtension
|
||||
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
||||
|
@ -60,7 +64,7 @@ class ShareInstagramStory : AbsBaseActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityShareInstagramBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setStatusbarColor(Color.TRANSPARENT)
|
||||
setStatusBarColor(Color.TRANSPARENT)
|
||||
|
||||
binding.toolbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
@ -104,7 +108,7 @@ class ShareInstagramStory : AbsBaseActivity() {
|
|||
}
|
||||
|
||||
private fun setColors(colorLight: Boolean, color: Int) {
|
||||
setLightStatusbar(colorLight)
|
||||
setLightStatusBar(colorLight)
|
||||
binding.toolbar.setTitleTextColor(
|
||||
MaterialValueHelper.getPrimaryTextColor(
|
||||
this@ShareInstagramStory,
|
||||
|
|
|
@ -37,6 +37,8 @@ import code.name.monkey.retromusic.BuildConfig
|
|||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||
import code.name.monkey.retromusic.databinding.ActivityDonationBinding
|
||||
import code.name.monkey.retromusic.extensions.setStatusBarColorAuto
|
||||
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||
import code.name.monkey.retromusic.extensions.textColorPrimary
|
||||
import code.name.monkey.retromusic.extensions.textColorSecondary
|
||||
import com.anjlab.android.iab.v3.BillingProcessor
|
||||
|
@ -73,7 +75,7 @@ class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingH
|
|||
binding = ActivityDonationBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setStatusbarColorAuto()
|
||||
setStatusBarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
|
||||
setupToolbar()
|
||||
|
|
|
@ -17,6 +17,8 @@ import code.name.monkey.retromusic.R
|
|||
import code.name.monkey.retromusic.activities.base.AbsThemeActivity
|
||||
import code.name.monkey.retromusic.databinding.ActivityWhatsNewBinding
|
||||
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.RetroUtil
|
||||
import java.io.BufferedReader
|
||||
|
@ -29,7 +31,7 @@ class WhatsNewActivity : AbsThemeActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
val binding = ActivityWhatsNewBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setLightStatusbarAuto(resolveColor(this, R.attr.colorSurface))
|
||||
setLightStatusBarAuto(resolveColor(this, R.attr.colorSurface))
|
||||
setTaskDescriptionColorAuto()
|
||||
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||
ToolbarContentTintHelper.colorBackButton(binding.toolbar)
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
package code.name.monkey.retromusic.activities.base
|
||||
|
||||
import android.animation.Animator
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
|
@ -25,6 +24,7 @@ import android.widget.FrameLayout
|
|||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.commit
|
||||
|
@ -67,11 +67,10 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
|||
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||
companion object {
|
||||
val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName
|
||||
var fromNotification: Boolean = false
|
||||
}
|
||||
|
||||
var fromNotification = false
|
||||
private var windowInsets: WindowInsetsCompat? = null
|
||||
private var bottomNavAnimator: Animator? = null
|
||||
protected val libraryViewModel by viewModel<LibraryViewModel>()
|
||||
private lateinit var bottomSheetBehavior: RetroBottomSheetBehavior<FrameLayout>
|
||||
private var playerFragment: AbsPlayerFragment? = null
|
||||
|
@ -93,21 +92,19 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
when (newState) {
|
||||
STATE_EXPANDED -> {
|
||||
onPanelExpanded()
|
||||
|
||||
}
|
||||
STATE_COLLAPSED -> {
|
||||
onPanelCollapsed()
|
||||
if (fromNotification) {
|
||||
hideBottomSheet(MusicPlayerRemote.playingQueue.isEmpty())
|
||||
fromNotification = false
|
||||
}
|
||||
}
|
||||
STATE_SETTLING, STATE_DRAGGING -> {
|
||||
if (fromNotification) {
|
||||
bottomNavigationView.isVisible = true
|
||||
binding.bottomNavigationView.bringToFront()
|
||||
fromNotification = false
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
println("Do something")
|
||||
println("Do a flip")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +172,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
if (progress < 0) return
|
||||
val alpha = 1 - progress
|
||||
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.alpha = alpha
|
||||
binding.playerFragmentContainer.alpha = (progress - 0.2F) / 0.2F
|
||||
|
@ -184,9 +181,9 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
open fun onPanelCollapsed() {
|
||||
setMiniPlayerAlphaProgress(0F)
|
||||
// restore values
|
||||
super.setLightStatusbarAuto(surfaceColor())
|
||||
super.setLightNavigationAuto()
|
||||
super.setTaskDescriptionColor(taskColor)
|
||||
setLightStatusBarAuto(surfaceColor())
|
||||
setLightNavigationAuto()
|
||||
setTaskDescriptionColor(taskColor)
|
||||
}
|
||||
|
||||
open fun onPanelExpanded() {
|
||||
|
@ -217,6 +214,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
|
||||
val bottomNavigationView get() = binding.bottomNavigationView
|
||||
|
||||
val slidingPanel get() = binding.slidingPanel
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||
|
@ -251,32 +250,31 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
collapsePanel()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun onPaletteColorChanged() {
|
||||
if (panelState == STATE_EXPANDED) {
|
||||
super.setTaskDescriptionColor(paletteColor)
|
||||
setTaskDescColor(paletteColor)
|
||||
val isColorLight = ColorUtil.isColorLight(paletteColor)
|
||||
if (PreferenceUtil.isAdaptiveColor && (nowPlayingScreen == Normal || nowPlayingScreen == Flat)) {
|
||||
super.setLightNavigationBar(true)
|
||||
super.setLightStatusbar(isColorLight)
|
||||
setLightNavigationBar(true)
|
||||
setLightStatusBar(isColorLight)
|
||||
} else if (nowPlayingScreen == Card || nowPlayingScreen == Blur || nowPlayingScreen == BlurCard) {
|
||||
super.setLightStatusbar(false)
|
||||
super.setLightNavigationBar(true)
|
||||
setLightStatusBar(false)
|
||||
setLightNavigationBar(true)
|
||||
} else if (nowPlayingScreen == Color || nowPlayingScreen == Tiny || nowPlayingScreen == Gradient) {
|
||||
super.setLightNavigationBar(isColorLight)
|
||||
super.setLightStatusbar(isColorLight)
|
||||
setLightNavigationBar(isColorLight)
|
||||
setLightStatusBar(isColorLight)
|
||||
} else if (nowPlayingScreen == Full) {
|
||||
super.setLightNavigationBar(isColorLight)
|
||||
super.setLightStatusbar(false)
|
||||
setLightNavigationBar(isColorLight)
|
||||
setLightStatusBar(false)
|
||||
} else if (nowPlayingScreen == Classic) {
|
||||
super.setLightStatusbar(false)
|
||||
setLightStatusBar(false)
|
||||
} else if (nowPlayingScreen == Fit) {
|
||||
super.setLightStatusbar(false)
|
||||
setLightStatusBar(false)
|
||||
} else {
|
||||
super.setLightStatusbar(
|
||||
setLightStatusBar(
|
||||
ColorUtil.isColorLight(
|
||||
ATHUtil.resolveColor(
|
||||
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
|
||||
if (panelState == STATE_COLLAPSED) {
|
||||
super.setTaskDescriptionColor(color)
|
||||
setTaskDescriptionColor(color)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,53 +317,63 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
}
|
||||
|
||||
fun setBottomNavVisibility(visible: Boolean, animate: Boolean = false) {
|
||||
binding.bottomNavigationView.isVisible = visible
|
||||
hideBottomSheet(MusicPlayerRemote.playingQueue.isEmpty(), animate)
|
||||
val translationY =
|
||||
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 =
|
||||
windowInsets.safeGetBottomInsets() +
|
||||
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 isVisible = binding.bottomNavigationView.isVisible
|
||||
if (hide) {
|
||||
bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets()
|
||||
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.bottomNavigationView, 10f)
|
||||
} else {
|
||||
if (MusicPlayerRemote.playingQueue.isNotEmpty()) {
|
||||
|
||||
ViewCompat.setElevation(binding.slidingPanel, 10f)
|
||||
ViewCompat.setElevation(binding.bottomNavigationView, 10f)
|
||||
if (isVisible) {
|
||||
if (isBottomNavVisible) {
|
||||
println("List")
|
||||
if (animate) {
|
||||
bottomNavAnimator?.end()
|
||||
bottomSheetBehavior.peekHeightAnimate(heightOfBarWithTabs)
|
||||
bottomNavAnimator = binding.bottomNavigationView.translateYAnimate(0F)
|
||||
} else {
|
||||
bottomSheetBehavior.peekHeight = heightOfBarWithTabs
|
||||
binding.bottomNavigationView.translationY = 0F
|
||||
}
|
||||
binding.bottomNavigationView.bringToFront()
|
||||
libraryViewModel.setFabMargin(dip(R.dimen.mini_player_height_expanded))
|
||||
} else {
|
||||
println("Details")
|
||||
if (animate) {
|
||||
bottomSheetBehavior.peekHeightAnimate(heightOfBar)
|
||||
bottomNavAnimator?.end()
|
||||
bottomNavAnimator =
|
||||
bottomNavigationView.translateYAnimate(dip(R.dimen.bottom_nav_height).toFloat())
|
||||
bottomNavAnimator?.doOnEnd {
|
||||
bottomSheetBehavior.peekHeightAnimate(heightOfBar).doOnEnd {
|
||||
binding.slidingPanel.bringToFront()
|
||||
}
|
||||
} else {
|
||||
bottomSheetBehavior.peekHeight = heightOfBar
|
||||
binding.bottomNavigationView.translationY =
|
||||
dip(R.dimen.bottom_nav_height).toFloat()
|
||||
binding.slidingPanel.bringToFront()
|
||||
}
|
||||
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.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
||||
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.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.R
|
||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||
import code.name.monkey.retromusic.extensions.*
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import code.name.monkey.retromusic.util.theme.ThemeManager
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import java.util.*
|
||||
|
@ -53,9 +41,8 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
|||
setImmersiveFullscreen()
|
||||
registerSystemUiVisibility()
|
||||
toggleScreenOn()
|
||||
setDrawUnderNavigationBar()
|
||||
setLightNavigationAuto()
|
||||
setLightStatusbarAuto(surfaceColor())
|
||||
setLightStatusBarAuto(surfaceColor())
|
||||
}
|
||||
|
||||
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) {
|
||||
super.onWindowFocusChanged(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() {
|
||||
val decorView = window.decorView
|
||||
decorView.setOnSystemUiVisibilityChangeListener { visibility ->
|
||||
|
@ -193,23 +83,6 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
|
|||
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() {
|
||||
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.GithubTarget
|
||||
import code.name.monkey.retromusic.databinding.ActivityBugReportBinding
|
||||
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||
import code.name.monkey.retromusic.misc.DialogAsyncTask
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
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.saf.SAFGuideActivity
|
||||
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.AudioTagInfo
|
||||
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.databinding.ActivityAlbumTagEditorBinding
|
||||
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.glide.GlideApp
|
||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||
|
|
|
@ -163,7 +163,7 @@ open class AlbumAdapter(
|
|||
when (PreferenceUtil.albumSortOrder) {
|
||||
SortOrder.AlbumSortOrder.ALBUM_A_Z, SortOrder.AlbumSortOrder.ALBUM_Z_A -> sectionName =
|
||||
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(
|
||||
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
|
||||
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
|
||||
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.shape.ShapeAppearanceModel
|
||||
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T {
|
||||
return LayoutInflater.from(context).inflate(layout, this, false) as T
|
||||
|
@ -67,21 +68,22 @@ fun View.translateYAnimate(value: Float): Animator {
|
|||
.apply {
|
||||
duration = 300
|
||||
doOnStart {
|
||||
if (value == 0f) {
|
||||
show()
|
||||
}
|
||||
show()
|
||||
bringToFront()
|
||||
}
|
||||
doOnEnd {
|
||||
if (value != 0f) {
|
||||
hide()
|
||||
} else {
|
||||
show()
|
||||
}
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int) {
|
||||
ObjectAnimator.ofInt(this, "peekHeight", value)
|
||||
fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int): Animator {
|
||||
return ObjectAnimator.ofInt(this, "peekHeight", value)
|
||||
.apply {
|
||||
duration = 300
|
||||
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.
|
||||
*/
|
||||
fun View.drawAboveSystemBars(onlyPortrait: Boolean = true) {
|
||||
if (PreferenceUtil.isFullScreenMode) return
|
||||
if (onlyPortrait && RetroUtil.isLandscape()) return
|
||||
// Create a snapshot of the view's margin state
|
||||
val initialMargin = recordInitialMarginForView(this)
|
||||
|
@ -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.
|
||||
*/
|
||||
fun View.drawAboveSystemBarsWithPadding(consume: Boolean = false) {
|
||||
if (PreferenceUtil.isFullScreenMode) return
|
||||
val initialPadding = recordInitialPaddingForView(this)
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
|
|
|
@ -29,6 +29,7 @@ import code.name.monkey.retromusic.util.DensityUtil
|
|||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
||||
class LibraryViewModel(
|
||||
|
@ -278,14 +279,16 @@ class LibraryViewModel(
|
|||
}
|
||||
emit(songs)
|
||||
// Cleaning up deleted or moved songs
|
||||
songs.forEach { song ->
|
||||
if (!File(song.data).exists() || song.id == -1L) {
|
||||
repository.deleteSongInPlayCount(song.toPlayCount())
|
||||
withContext(IO) {
|
||||
songs.forEach { song ->
|
||||
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 {
|
||||
|
|
|
@ -196,7 +196,7 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
|
|||
0,
|
||||
R.id.action_album_sort_order_artist,
|
||||
2,
|
||||
R.string.sort_order_artist
|
||||
R.string.sort_order_album_artist
|
||||
).isChecked =
|
||||
currentSortOrder.equals(AlbumSortOrder.ALBUM_ARTIST)
|
||||
sortOrderMenu.add(
|
||||
|
|
|
@ -22,6 +22,8 @@ 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.activities.MainActivity
|
||||
import code.name.monkey.retromusic.extensions.setLightStatusBarAuto
|
||||
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
|
||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
||||
|
||||
|
@ -42,7 +44,7 @@ abstract class AbsMainActivityFragment(@LayoutRes layout: Int) : AbsMusicService
|
|||
if (statusBar != null) {
|
||||
if (VersionUtils.hasMarshmallow()) {
|
||||
statusBar.setBackgroundColor(color)
|
||||
mainActivity.setLightStatusbarAuto(color)
|
||||
mainActivity.setLightStatusBarAuto(color)
|
||||
} else {
|
||||
statusBar.setBackgroundColor(color)
|
||||
}
|
||||
|
|
|
@ -15,21 +15,14 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.navOptions
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||
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.
|
||||
|
@ -103,33 +96,4 @@ open class AbsMusicServiceFragment(@LayoutRes layout: Int) : Fragment(layout),
|
|||
|
||||
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?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
enterTransition = Fade()
|
||||
exitTransition = Fade()
|
||||
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.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.FragmentAdaptivePlayerPlaybackControlsBinding
|
||||
import code.name.monkey.retromusic.extensions.applyColor
|
||||
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.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
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.retromusic.R
|
||||
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.show
|
||||
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.retromusic.R
|
||||
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.ripAlpha
|
||||
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.databinding.FragmentCardBlurPlayerPlaybackControlsBinding
|
||||
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.show
|
||||
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.adapter.song.PlayingQueueAdapter
|
||||
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.show
|
||||
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.databinding.FragmentColorPlayerPlaybackControlsBinding
|
||||
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.show
|
||||
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.retromusic.R
|
||||
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.ripAlpha
|
||||
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.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.FragmentFlatPlayerPlaybackControlsBinding
|
||||
import code.name.monkey.retromusic.extensions.applyColor
|
||||
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.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
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.toSongEntity
|
||||
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.show
|
||||
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.retromusic.R
|
||||
import code.name.monkey.retromusic.databinding.FragmentPlayerPlaybackControlsBinding
|
||||
import code.name.monkey.retromusic.extensions.applyColor
|
||||
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.extensions.*
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||
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.databinding.FragmentPeakPlayerBinding
|
||||
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.show
|
||||
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.databinding.FragmentPlainControlsFragmentBinding
|
||||
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.show
|
||||
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.retromusic.R
|
||||
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.show
|
||||
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.databinding.FragmentTinyPlayerBinding
|
||||
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.show
|
||||
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.db.PlaylistWithSongs
|
||||
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.fragments.base.AbsMainActivityFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
||||
import code.name.monkey.retromusic.interfaces.ICabCallback
|
||||
import code.name.monkey.retromusic.interfaces.ICabHolder
|
||||
|
@ -123,8 +124,12 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
|||
}
|
||||
|
||||
private fun checkForPadding() {
|
||||
val height = dipToPix(52f)
|
||||
binding.recyclerView.setPadding(0, 0, 0, height.toInt())
|
||||
val itemCount: Int = playlistSongAdapter.itemCount
|
||||
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() {
|
||||
|
|
|
@ -19,15 +19,16 @@ import android.graphics.drawable.ColorDrawable
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat
|
||||
import code.name.monkey.retromusic.activities.OnThemeChangedListener
|
||||
import code.name.monkey.retromusic.extensions.safeGetBottomInsets
|
||||
import code.name.monkey.retromusic.preferences.*
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
|
@ -66,16 +67,19 @@ abstract class AbsSettingsFragment : ATEPreferenceFragmentCompat() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setDivider(ColorDrawable(Color.TRANSPARENT))
|
||||
// This is a workaround as CollapsingToolbarLayout consumes insets and
|
||||
// insets are not passed to child views
|
||||
// CollapsingToolbarLayout consumes insets and insets are not passed to child views
|
||||
// So we get insets from root view
|
||||
// https://github.com/material-components/material-components-android/issues/1310
|
||||
if (!RetroUtil.isLandscape()) {
|
||||
listView.updatePadding(bottom = RetroUtil.getNavigationBarHeight())
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
view
|
||||
) { _, insets ->
|
||||
listView.updatePadding(bottom = insets.safeGetBottomInsets())
|
||||
insets
|
||||
}
|
||||
invalidateSettings()
|
||||
}
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference?) {
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
when (preference) {
|
||||
is LibraryPreference -> {
|
||||
val fragment = LibraryPreferenceDialog.newInstance()
|
||||
|
|
|
@ -33,10 +33,10 @@ import java.io.File
|
|||
@GlideExtension
|
||||
object RetroGlideExtension {
|
||||
|
||||
private const val DEFAULT_ERROR_ARTIST_IMAGE =
|
||||
private const val DEFAULT_ARTIST_IMAGE =
|
||||
R.drawable.default_artist_art
|
||||
private const val DEFAULT_ERROR_SONG_IMAGE: Int = R.drawable.default_audio_art
|
||||
private const val DEFAULT_ERROR_ALBUM_IMAGE = R.drawable.default_album_art
|
||||
private const val DEFAULT_SONG_IMAGE: Int = R.drawable.default_audio_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 val DEFAULT_DISK_CACHE_STRATEGY_ARTIST = DiskCacheStrategy.RESOURCE
|
||||
|
@ -99,7 +99,8 @@ object RetroGlideExtension {
|
|||
return baseRequestOptions
|
||||
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY_ARTIST)
|
||||
.priority(Priority.LOW)
|
||||
.error(DEFAULT_ERROR_ARTIST_IMAGE)
|
||||
.error(DEFAULT_ARTIST_IMAGE)
|
||||
.placeholder(DEFAULT_ARTIST_IMAGE)
|
||||
.signature(createSignature(artist))
|
||||
}
|
||||
|
||||
|
@ -110,7 +111,8 @@ object RetroGlideExtension {
|
|||
song: Song
|
||||
): BaseRequestOptions<*> {
|
||||
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||
.error(DEFAULT_ERROR_SONG_IMAGE)
|
||||
.error(DEFAULT_SONG_IMAGE)
|
||||
.placeholder(DEFAULT_SONG_IMAGE)
|
||||
.signature(createSignature(song))
|
||||
}
|
||||
|
||||
|
@ -121,7 +123,8 @@ object RetroGlideExtension {
|
|||
song: Song
|
||||
): BaseRequestOptions<*> {
|
||||
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||
.error(DEFAULT_ERROR_ALBUM_IMAGE)
|
||||
.error(DEFAULT_ALBUM_IMAGE)
|
||||
.placeholder(DEFAULT_ALBUM_IMAGE)
|
||||
.signature(createSignature(song))
|
||||
}
|
||||
|
||||
|
@ -154,7 +157,7 @@ object RetroGlideExtension {
|
|||
baseRequestOptions: BaseRequestOptions<*>
|
||||
): BaseRequestOptions<*> {
|
||||
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||
.error(DEFAULT_ERROR_ALBUM_IMAGE)
|
||||
.error(DEFAULT_ALBUM_IMAGE)
|
||||
}
|
||||
|
||||
private fun createSignature(song: Song): Key {
|
||||
|
|
|
@ -33,8 +33,7 @@ abstract class RetroMusicColoredTarget(view: ImageView) : BitmapPaletteTarget(vi
|
|||
|
||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||
super.onLoadFailed(errorDrawable)
|
||||
val colors = MediaNotificationProcessor(App.getContext(), errorDrawable)
|
||||
onColorReady(colors)
|
||||
onColorReady(MediaNotificationProcessor.errorColor(App.getContext()))
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
|
|
|
@ -54,11 +54,11 @@ class SortOrder {
|
|||
const val ALBUM_Z_A = "$ALBUM_A_Z DESC"
|
||||
|
||||
/* 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 */
|
||||
const val ALBUM_ARTIST = (MediaStore.Audio.Artists.DEFAULT_SORT_ORDER +
|
||||
", " + MediaStore.Audio.Albums.DEFAULT_SORT_ORDER)
|
||||
/* Album Artist sort order artist */
|
||||
const val ALBUM_ARTIST = "case when lower(album_artist) is null then 1 else 0 end, lower(album_artist)"
|
||||
|
||||
/* Album sort order year */
|
||||
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.service.AudioFader.startFadeAnimator;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
@ -34,6 +35,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.Bitmap;
|
||||
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.AppWidgetCard;
|
||||
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.AppWidgetText;
|
||||
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.volume.AudioVolumeObserver;
|
||||
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener;
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* @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 AppWidgetMD3 appWidgetMd3 = AppWidgetMD3.Companion.getInstance();
|
||||
|
||||
private final BroadcastReceiver widgetIntentReceiver =
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
|
@ -226,6 +232,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
appWidgetText.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetMD3.NAME: {
|
||||
appWidgetMd3.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +283,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
updateNotification();
|
||||
playingNotification.updateFavorite(getCurrentSong(), MusicService.this::startForegroundOrNotify);
|
||||
startForegroundOrNotify();
|
||||
}
|
||||
};
|
||||
private final BroadcastReceiver lockScreenReceiver =
|
||||
|
@ -356,6 +367,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
private ThrottledSeekHandler throttledSeekHandler;
|
||||
private Handler uiThreadHandler;
|
||||
private PowerManager.WakeLock wakeLock;
|
||||
private NotificationManager notificationManager;
|
||||
private boolean isForeground = false;
|
||||
|
||||
private static Bitmap copy(Bitmap bitmap) {
|
||||
Bitmap.Config config = bitmap.getConfig();
|
||||
|
@ -417,6 +430,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
registerReceiver(updateFavoriteReceiver, new IntentFilter(FAVORITE_STATE_CHANGED));
|
||||
registerReceiver(lockScreenReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
||||
|
||||
setSessionToken(mediaSession.getSessionToken());
|
||||
if (VersionUtils.INSTANCE.hasMarshmallow()) {
|
||||
notificationManager = getSystemService(NotificationManager.class);
|
||||
}
|
||||
initNotification();
|
||||
|
||||
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
||||
|
@ -467,7 +484,6 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
|
||||
mPackageValidator = new PackageValidator(this, R.xml.allowed_media_browser_callers);
|
||||
mMusicProvider.setMusicService(this);
|
||||
setSessionToken(mediaSession.getSessionToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -765,11 +781,10 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
public void initNotification() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
||||
&& !PreferenceUtil.INSTANCE.isClassicNotification()) {
|
||||
playingNotification = new PlayingNotificationImpl();
|
||||
playingNotification = PlayingNotificationImpl.Companion.from(this, notificationManager, mediaSession);
|
||||
} else {
|
||||
playingNotification = new PlayingNotificationOreo();
|
||||
playingNotification = PlayingNotificationOreo.Companion.from(this, notificationManager);
|
||||
}
|
||||
playingNotification.init(this);
|
||||
}
|
||||
|
||||
public boolean isLastTrack() {
|
||||
|
@ -837,7 +852,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
// Request from an untrusted package: return an empty browser root
|
||||
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_EMPTY_ROOT, null);
|
||||
} 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.
|
||||
*/
|
||||
boolean isRecentRequest = false;
|
||||
|
@ -882,7 +898,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
/* Switch to MultiPlayer if Crossfade duration is 0 and
|
||||
Playback is not an instance of MultiPlayer */
|
||||
if (playback != null)
|
||||
playback.setCrossFadeDuration(PreferenceUtil.INSTANCE.getCrossFadeDuration());
|
||||
playback.setCrossFadeDuration(PreferenceUtil.INSTANCE.getCrossFadeDuration());
|
||||
if (!(playback instanceof MultiPlayer) && PreferenceUtil.INSTANCE.getCrossFadeDuration() == 0) {
|
||||
if (playback != null) {
|
||||
playback.release();
|
||||
|
@ -1042,6 +1058,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
}
|
||||
|
||||
public void pause() {
|
||||
Log.i(TAG, "Paused");
|
||||
pausedByTransientLossOfFocus = false;
|
||||
if (playback != null && playback.isPlaying()) {
|
||||
startFadeAnimator(playback, false, () -> {
|
||||
|
@ -1163,7 +1180,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
|
||||
public void quit() {
|
||||
pause();
|
||||
playingNotification.stop();
|
||||
stopForeground(true);
|
||||
notificationManager.cancel(PlayingNotification.NOTIFICATION_ID);
|
||||
|
||||
closeAudioEffectSession();
|
||||
getAudioManager().abandonAudioFocus(audioFocusListener);
|
||||
|
@ -1326,7 +1344,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
|
||||
public void updateNotification() {
|
||||
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) {
|
||||
switch (what) {
|
||||
case PLAY_STATE_CHANGED:
|
||||
updateNotification();
|
||||
updateMediaSessionPlaybackState();
|
||||
final boolean isPlaying = isPlaying();
|
||||
if (!isPlaying && getSongProgressMillis() > 0) {
|
||||
savePositionInTrack();
|
||||
}
|
||||
songPlayCountHelper.notifyPlayStateChanged(isPlaying);
|
||||
playingNotification.setPlaying(isPlaying);
|
||||
startForegroundOrNotify();
|
||||
break;
|
||||
case FAVORITE_STATE_CHANGED:
|
||||
playingNotification.updateFavorite(getCurrentSong(), this::startForegroundOrNotify);
|
||||
case META_CHANGED:
|
||||
updateNotification();
|
||||
playingNotification.updateMetadata(getCurrentSong(), this::startForegroundOrNotify);
|
||||
updateMediaSessionMetaData();
|
||||
updateMediaSessionPlaybackState();
|
||||
savePosition();
|
||||
|
@ -1428,12 +1449,41 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
if (playingQueue.size() > 0) {
|
||||
prepareNext();
|
||||
} else {
|
||||
playingNotification.stop();
|
||||
stopForegroundAndNotification();
|
||||
}
|
||||
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() {
|
||||
synchronized (this) {
|
||||
try {
|
||||
|
@ -1551,6 +1601,7 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
appWidgetSmall.notifyChange(this, what);
|
||||
appWidgetCard.notifyChange(this, what);
|
||||
appWidgetText.notifyChange(this, what);
|
||||
appWidgetMd3.notifyChange(this, what);
|
||||
}
|
||||
|
||||
private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
|
||||
|
@ -1592,8 +1643,8 @@ public class MusicService extends MediaBrowserServiceCompat
|
|||
mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
|
||||
|
||||
PendingIntent mediaButtonReceiverPendingIntent;
|
||||
mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent,
|
||||
VersionUtils.INSTANCE.hasMarshmallow() ? PendingIntent.FLAG_IMMUTABLE : 0);
|
||||
mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent,
|
||||
VersionUtils.INSTANCE.hasMarshmallow() ? PendingIntent.FLAG_IMMUTABLE : 0);
|
||||
|
||||
mediaSession = new MediaSessionCompat(
|
||||
this,
|
||||
|
|
|
@ -15,95 +15,51 @@
|
|||
package code.name.monkey.retromusic.service.notification
|
||||
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context.NOTIFICATION_SERVICE
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import android.content.Context
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
|
||||
|
||||
abstract class PlayingNotification {
|
||||
protected lateinit var service: MusicService
|
||||
protected var stopped: Boolean = false
|
||||
private var notifyMode = NOTIFY_MODE_BACKGROUND
|
||||
private var notificationManager: NotificationManager? = null
|
||||
abstract class PlayingNotification(context: Context) :
|
||||
NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) {
|
||||
|
||||
abstract fun updateMetadata(song: Song, onUpdate: () -> Unit)
|
||||
|
||||
@Synchronized
|
||||
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 setPlaying(isPlaying: Boolean)
|
||||
|
||||
abstract fun update()
|
||||
|
||||
@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)
|
||||
}
|
||||
}
|
||||
abstract fun updateFavorite(song: Song, onUpdate: () -> Unit)
|
||||
|
||||
companion object {
|
||||
const val NOTIFICATION_CONTROLS_SIZE_MULTIPLIER = 1.0f
|
||||
internal const val NOTIFICATION_CHANNEL_ID = "playing_notification"
|
||||
private const val NOTIFICATION_ID = 1
|
||||
private const val NOTIFY_MODE_FOREGROUND = 1
|
||||
private const val NOTIFY_MODE_BACKGROUND = 0
|
||||
const val NOTIFICATION_ID = 1
|
||||
|
||||
|
||||
@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
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.text.HtmlCompat
|
||||
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.RetroGlideExtension
|
||||
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.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.SimpleTarget
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class PlayingNotificationImpl : PlayingNotification(), KoinComponent {
|
||||
private var target: Target<BitmapPaletteWrapper>? = null
|
||||
@SuppressLint("RestrictedApi")
|
||||
class PlayingNotificationImpl(
|
||||
val context: Context,
|
||||
mediaSessionToken: MediaSessionCompat.Token
|
||||
) : PlayingNotification(context) {
|
||||
|
||||
@Synchronized
|
||||
override fun update() {
|
||||
stopped = false
|
||||
GlobalScope.launch {
|
||||
val song = service.currentSong
|
||||
init {
|
||||
val action = Intent(context, 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(
|
||||
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 isPlaying = service.isPlaying
|
||||
val isFavorite = if (playlist != null) {
|
||||
val songEntity = song.toSongEntity(playlist.playListId)
|
||||
MusicUtil.repository.isFavoriteSong(songEntity).isNotEmpty()
|
||||
} else false
|
||||
|
||||
val playButtonResId =
|
||||
if (isPlaying) R.drawable.ic_pause_white_48dp else R.drawable.ic_play_arrow_white_48dp
|
||||
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())
|
||||
}
|
||||
})
|
||||
withContext(Dispatchers.Main) {
|
||||
mActions[0] = buildFavoriteAction(isFavorite)
|
||||
onUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun retrievePlaybackAction(action: String): PendingIntent {
|
||||
val serviceName = ComponentName(service, MusicService::class.java)
|
||||
val serviceName = ComponentName(context, MusicService::class.java)
|
||||
val intent = Intent(action)
|
||||
intent.component = serviceName
|
||||
return PendingIntent.getService(
|
||||
service, 0, intent,
|
||||
if (VersionUtils.hasMarshmallow()) PendingIntent.FLAG_IMMUTABLE
|
||||
else 0 or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or
|
||||
if (VersionUtils.hasMarshmallow()) PendingIntent.FLAG_IMMUTABLE
|
||||
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
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
|
@ -21,6 +23,7 @@ import android.content.Intent
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.app.NotificationCompat
|
||||
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.retromusic.R
|
||||
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.RetroGlideExtension
|
||||
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.createBitmap
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.SimpleTarget
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
val remoteViews = RemoteViews(
|
||||
service.packageName,
|
||||
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
|
||||
}
|
||||
init {
|
||||
val notificationLayout = getCombinedRemoteViews(true)
|
||||
val notificationLayoutBig = getCombinedRemoteViews(false)
|
||||
|
||||
override fun update() {
|
||||
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)
|
||||
val action = Intent(context, 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,
|
||||
context,
|
||||
0,
|
||||
action,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or if (VersionUtils.hasMarshmallow())
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
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)
|
||||
.setContentIntent(clickIntent)
|
||||
.setDeleteIntent(deleteIntent)
|
||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setCustomContentView(notificationLayout)
|
||||
.setCustomBigContentView(notificationLayoutBig)
|
||||
.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())
|
||||
setSmallIcon(R.drawable.ic_notification)
|
||||
setContentIntent(clickIntent)
|
||||
setDeleteIntent(deleteIntent)
|
||||
setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
priority = NotificationCompat.PRIORITY_MAX
|
||||
setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
setCustomContentView(notificationLayout)
|
||||
setCustomBigContentView(notificationLayoutBig)
|
||||
setOngoing(true)
|
||||
}
|
||||
|
||||
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(
|
||||
context: Context, action: String,
|
||||
|
@ -275,23 +286,34 @@ class PlayingNotificationOreo : PlayingNotification() {
|
|||
private fun linkButtons(notificationLayout: RemoteViews) {
|
||||
var pendingIntent: PendingIntent
|
||||
|
||||
val serviceName = ComponentName(service, MusicService::class.java)
|
||||
val serviceName = ComponentName(context, MusicService::class.java)
|
||||
|
||||
// Previous track
|
||||
pendingIntent = buildPendingIntent(service, ACTION_REWIND, serviceName)
|
||||
pendingIntent = buildPendingIntent(context, ACTION_REWIND, serviceName)
|
||||
notificationLayout.setOnClickPendingIntent(R.id.action_prev, pendingIntent)
|
||||
|
||||
// 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)
|
||||
|
||||
// Next track
|
||||
pendingIntent = buildPendingIntent(service, ACTION_SKIP, serviceName)
|
||||
pendingIntent = buildPendingIntent(context, ACTION_SKIP, serviceName)
|
||||
notificationLayout.setOnClickPendingIntent(R.id.action_next, pendingIntent)
|
||||
|
||||
// Close
|
||||
pendingIntent = buildPendingIntent(service, ACTION_QUIT, serviceName)
|
||||
pendingIntent = buildPendingIntent(context, ACTION_QUIT, serviceName)
|
||||
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
|
||||
return try {
|
||||
if (TextUtils.isEmpty(musicMediaTitle)) {
|
||||
return ""
|
||||
return "-"
|
||||
}
|
||||
musicMediaTitle = musicMediaTitle!!.trim { it <= ' ' }.lowercase()
|
||||
if (musicMediaTitle.startsWith("the ")) {
|
||||
|
@ -526,6 +526,7 @@ object MusicUtil : KoinComponent {
|
|||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
fun deleteTracksR(activity: Activity, songs: List<Song>) {
|
||||
removeFromQueue(songs)
|
||||
val pendingIntent = MediaStore.createDeleteRequest(activity.contentResolver, songs.map {
|
||||
getSongFileUri(it.id)
|
||||
})
|
||||
|
|
|
@ -372,7 +372,7 @@ object PreferenceUtil {
|
|||
|
||||
var artistGridStyle: GridStyle
|
||||
get() {
|
||||
val id: Int = sharedPreferences.getInt(ARTIST_GRID_STYLE, 4)
|
||||
val id: Int = sharedPreferences.getInt(ARTIST_GRID_STYLE, 3)
|
||||
return GridStyle.values().firstOrNull { gridStyle ->
|
||||
gridStyle.id == id
|
||||
} ?: GridStyle.Circular
|
||||
|
|
|
@ -473,4 +473,12 @@ public class MediaNotificationProcessor {
|
|||
public interface OnPaletteLoadedListener {
|
||||
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:icon="@drawable/ic_search"
|
||||
android:title="@string/action_search"
|
||||
app:showAsAction="ifRoom" />
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
|
@ -39,6 +39,9 @@
|
|||
<dimen name="app_widget_card_radius">2dp</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="toolbar_margin_horizontal">8dp</dimen>
|
||||
<dimen name="toolbar_height">48dp</dimen>
|
||||
|
|
|
@ -454,6 +454,7 @@
|
|||
<string name="sort_order_a_z">Ascending</string>
|
||||
<string name="sort_order_album">Album</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_date">Date added</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="title_new_backup">New Backup</string>
|
||||
<string name="backup_restore_settings_summary">Backup and restore your settings, playlists</string>
|
||||
<string name="app_widget_md3_name">MD3</string>
|
||||
</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 'androidx.appcompat:appcompat:1.4.0'
|
||||
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 "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package code.name.monkey.appthemehelper
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.ActivityManager
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorInt
|
||||
|
@ -18,7 +18,6 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
|||
*/
|
||||
object ATH {
|
||||
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
fun didThemeValuesChange(context: Context, since: Long): Boolean {
|
||||
return ThemeStore.isConfigured(context) && ThemeStore.prefs(context).getLong(
|
||||
ThemeStorePrefKeys.VALUES_CHANGED,
|
||||
|
@ -26,7 +25,7 @@ object ATH {
|
|||
) > since
|
||||
}
|
||||
|
||||
fun setLightStatusbar(activity: Activity, enabled: Boolean) {
|
||||
fun setLightStatusBar(activity: Activity, enabled: Boolean) {
|
||||
activity.window.apply {
|
||||
WindowInsetsControllerCompat(
|
||||
this,
|
||||
|
@ -36,29 +35,26 @@ object ATH {
|
|||
}
|
||||
|
||||
fun setLightNavigationbar(activity: Activity, enabled: Boolean) {
|
||||
activity.window?.apply {
|
||||
activity.window.apply {
|
||||
WindowInsetsControllerCompat(
|
||||
this,
|
||||
decorView
|
||||
).isAppearanceLightNavigationBars = enabled
|
||||
navigationBarColor = Color.TRANSPARENT
|
||||
}
|
||||
}
|
||||
|
||||
fun setLightNavigationbarAuto(activity: Activity, bgColor: Int) {
|
||||
fun setLightNavigationBarAuto(activity: Activity, bgColor: Int) {
|
||||
setLightNavigationbar(activity, ColorUtil.isColorLight(bgColor))
|
||||
}
|
||||
|
||||
fun setNavigationbarColorAuto(activity: Activity) {
|
||||
setNavigationbarColor(activity, ThemeStore.navigationBarColor(activity))
|
||||
}
|
||||
|
||||
fun setNavigationbarColor(activity: Activity, color: Int) {
|
||||
fun setNavigationBarColor(activity: Activity, color: Int) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
activity.window.navigationBarColor = color
|
||||
} else {
|
||||
activity.window.navigationBarColor = ColorUtil.darkenColor(color)
|
||||
}
|
||||
setLightNavigationbarAuto(activity, color)
|
||||
setLightNavigationBarAuto(activity, color)
|
||||
}
|
||||
|
||||
fun setActivityToolbarColorAuto(activity: Activity, toolbar: Toolbar?) {
|
||||
|
|
|
@ -43,9 +43,9 @@ class ATEColorPreference @JvmOverloads constructor(
|
|||
invalidateColor()
|
||||
}*/
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder?) {
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
mView = holder?.itemView
|
||||
mView = holder.itemView
|
||||
invalidateColor()
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import androidx.preference.PreferenceViewHolder
|
|||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
|
||||
class ATEPreferenceCategory @JvmOverloads constructor(
|
||||
context: Context?,
|
||||
context: Context,
|
||||
attrs: AttributeSet?,
|
||||
defStyleAttr: Int = -1,
|
||||
defStyleRes: Int = -1
|
||||
|
|
|
@ -9,9 +9,9 @@ buildscript {
|
|||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||
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 "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