diff --git a/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetCircle.kt b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetCircle.kt new file mode 100644 index 000000000..98e3da57a --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/appwidgets/AppWidgetCircle.kt @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2020 Hemanth Savarla. + * + * Licensed under the GNU General Public License v3 + * + * This is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + */ +package code.name.monkey.retromusic.appwidgets + +import android.app.PendingIntent +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import android.widget.RemoteViews +import code.name.monkey.appthemehelper.util.MaterialValueHelper +import code.name.monkey.appthemehelper.util.VersionUtils +import code.name.monkey.retromusic.R +import code.name.monkey.retromusic.activities.MainActivity +import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget +import code.name.monkey.retromusic.glide.GlideApp +import code.name.monkey.retromusic.glide.RetroGlideExtension +import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper +import code.name.monkey.retromusic.service.MusicService +import code.name.monkey.retromusic.service.MusicService.ACTION_TOGGLE_PAUSE +import code.name.monkey.retromusic.service.MusicService.TOGGLE_FAVORITE +import code.name.monkey.retromusic.util.ImageUtil +import code.name.monkey.retromusic.util.PreferenceUtil +import code.name.monkey.retromusic.util.RetroUtil +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.SimpleTarget +import com.bumptech.glide.request.target.Target +import com.bumptech.glide.request.transition.Transition + +class AppWidgetCircle : BaseAppWidget() { + private var target: Target? = null // for cancellation + + /** + * Initialize given widgets to default state, where we launch Music on default click and hide + * actions if service not running. + */ + override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) { + val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_circle) + + appWidgetView.setImageViewResource(R.id.image, R.drawable.default_audio_art) + val secondaryColor = MaterialValueHelper.getSecondaryTextColor(context, true) + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, createBitmap( + RetroUtil.getTintedVectorDrawable( + context, + R.drawable.ic_play_arrow, + secondaryColor + ), 1f + ) + ) + + linkButtons(context, appWidgetView) + pushUpdate(context, appWidgetIds, appWidgetView) + } + + /** + * Update all active widget instances by pushing changes + */ + override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) { + val appWidgetView = RemoteViews(service.packageName, R.layout.app_widget_circle) + + val isPlaying = service.isPlaying + val song = service.currentSong + + // Set correct drawable for pause state + val playPauseRes = + if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play_arrow + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + playPauseRes, + MaterialValueHelper.getSecondaryTextColor(service, true) + ), 1f + ) + ) + val isFavorite = true + val favoriteRes = + if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border + appWidgetView.setImageViewBitmap( + R.id.button_toggle_favorite, createBitmap( + RetroUtil.getTintedVectorDrawable( + service, + favoriteRes, + MaterialValueHelper.getSecondaryTextColor(service, true) + ), 1f + ) + ) + + // Link actions buttons to intents + linkButtons(service, appWidgetView) + + if (imageSize == 0) { + val p = RetroUtil.getScreenSize(service) + imageSize = p.x.coerceAtMost(p.y) + } + + // Load the album cover async and push the update on completion + service.runOnUiThread { + if (target != null) { + Glide.with(service).clear(target) + } + target = GlideApp.with(service).asBitmapPalette().songCoverOptions(song) + .load(RetroGlideExtension.getSongModel(song)) + .apply( + RequestOptions().transform(RoundedCorners(imageSize / 2)) + ) + .into(object : SimpleTarget(imageSize, imageSize) { + override fun onResourceReady( + resource: BitmapPaletteWrapper, + transition: Transition? + ) { + val palette = resource.palette + update( + resource.bitmap, palette.getVibrantColor( + palette.getMutedColor( + MaterialValueHelper.getSecondaryTextColor( + service, true + ) + ) + ) + ) + } + + override fun onLoadFailed(errorDrawable: Drawable?) { + super.onLoadFailed(errorDrawable) + update(null, MaterialValueHelper.getSecondaryTextColor(service, true)) + } + + private fun update(bitmap: Bitmap?, color: Int) { + // Set correct drawable for pause state + appWidgetView.setImageViewBitmap( + R.id.button_toggle_play_pause, ImageUtil.createBitmap( + ImageUtil.getTintedVectorDrawable( + service, playPauseRes, color + ) + ) + ) + + // Set favorite button drawables + appWidgetView.setImageViewBitmap( + R.id.button_toggle_favorite, ImageUtil.createBitmap( + ImageUtil.getTintedVectorDrawable( + service, favoriteRes, color + ) + ) + ) + appWidgetView.setImageViewBitmap(R.id.image, bitmap) + + pushUpdate(service, appWidgetIds, appWidgetView) + } + }) + } + } + + /** + * Link up various button actions using [PendingIntent]. + */ + private fun linkButtons(context: Context, views: RemoteViews) { + val action = Intent(context, MainActivity::class.java) + .putExtra( + MainActivity.EXPAND_PANEL, + PreferenceUtil.isExpandPanel + ) + + val serviceName = ComponentName(context, MusicService::class.java) + + // Home + action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + var pendingIntent = + PendingIntent.getActivity( + context, 0, action, if (VersionUtils.hasMarshmallow()) + PendingIntent.FLAG_IMMUTABLE + else 0 + ) + views.setOnClickPendingIntent(R.id.image, pendingIntent) + // Favorite track + pendingIntent = buildPendingIntent(context, TOGGLE_FAVORITE, serviceName) + views.setOnClickPendingIntent(R.id.button_toggle_favorite, pendingIntent) + + // Play and pause + pendingIntent = buildPendingIntent(context, ACTION_TOGGLE_PAUSE, serviceName) + views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent) + } + + companion object { + + const val NAME = "app_widget_circle" + + private var mInstance: AppWidgetCircle? = null + private var imageSize = 0 + + val instance: AppWidgetCircle + @Synchronized get() { + if (mInstance == null) { + mInstance = AppWidgetCircle() + } + return mInstance!! + } + } +} diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java index 9cd954f80..44a479f1d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java +++ b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java @@ -83,6 +83,7 @@ import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.activities.LockScreenActivity; import code.name.monkey.retromusic.appwidgets.AppWidgetBig; import code.name.monkey.retromusic.appwidgets.AppWidgetCard; +import code.name.monkey.retromusic.appwidgets.AppWidgetCircle; import code.name.monkey.retromusic.appwidgets.AppWidgetClassic; import code.name.monkey.retromusic.appwidgets.AppWidgetMD3; import code.name.monkey.retromusic.appwidgets.AppWidgetSmall; @@ -205,6 +206,8 @@ public class MusicService extends MediaBrowserServiceCompat private final AppWidgetMD3 appWidgetMd3 = AppWidgetMD3.Companion.getInstance(); + private final AppWidgetCircle appWidgetCircle = AppWidgetCircle.Companion.getInstance(); + private final BroadcastReceiver widgetIntentReceiver = new BroadcastReceiver() { @Override @@ -237,6 +240,10 @@ public class MusicService extends MediaBrowserServiceCompat appWidgetMd3.performUpdate(MusicService.this, ids); break; } + case AppWidgetCircle.NAME: { + appWidgetCircle.performUpdate(MusicService.this, ids); + break; + } } } } @@ -1619,6 +1626,7 @@ public class MusicService extends MediaBrowserServiceCompat appWidgetCard.notifyChange(this, what); appWidgetText.notifyChange(this, what); appWidgetMd3.notifyChange(this, what); + appWidgetCircle.notifyChange(this, what); } private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) { diff --git a/app/src/main/res/drawable/app_widget_background.xml b/app/src/main/res/drawable/app_widget_background.xml index e845d20cb..4d5263f56 100644 --- a/app/src/main/res/drawable/app_widget_background.xml +++ b/app/src/main/res/drawable/app_widget_background.xml @@ -4,7 +4,6 @@ appWidgetRadius attribute value --> - \ No newline at end of file diff --git a/app/src/main/res/drawable/circle_widget_background.xml b/app/src/main/res/drawable/circle_widget_background.xml new file mode 100644 index 000000000..401d24d88 --- /dev/null +++ b/app/src/main/res/drawable/circle_widget_background.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rounded_drawable.xml b/app/src/main/res/drawable/rounded_drawable.xml index 6d498dbf2..1535a3f46 100644 --- a/app/src/main/res/drawable/rounded_drawable.xml +++ b/app/src/main/res/drawable/rounded_drawable.xml @@ -1,6 +1,5 @@ - \ No newline at end of file diff --git a/app/src/main/res/drawable/widget_button_background.xml b/app/src/main/res/drawable/widget_button_background.xml new file mode 100644 index 000000000..0508710b0 --- /dev/null +++ b/app/src/main/res/drawable/widget_button_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_widget_circle.xml b/app/src/main/res/layout/app_widget_circle.xml new file mode 100644 index 000000000..1f0b73d6b --- /dev/null +++ b/app/src/main/res/layout/app_widget_circle.xml @@ -0,0 +1,43 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-night-v31/colors.xml b/app/src/main/res/values-night-v31/colors.xml index 12a321b43..b19bfab86 100644 --- a/app/src/main/res/values-night-v31/colors.xml +++ b/app/src/main/res/values-night-v31/colors.xml @@ -1,4 +1,4 @@ - @android:color/system_accent1_800 + @android:color/system_accent1_600 \ No newline at end of file diff --git a/app/src/main/res/values-v31/colors.xml b/app/src/main/res/values-v31/colors.xml index 292e53073..8c94d0f0c 100644 --- a/app/src/main/res/values-v31/colors.xml +++ b/app/src/main/res/values-v31/colors.xml @@ -1,4 +1,6 @@ @android:color/system_accent1_50 + @android:color/system_accent1_900 + @android:color/system_accent1_50 \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 3f7a24e3b..2615a4a29 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -36,4 +36,6 @@ #FFFFFF @color/lighterColorSurface + @color/md_indigo_A400 + @color/lighterColorSurface diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index a835130d6..e9fb9f717 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -42,6 +42,11 @@ 90dp 70dp + 180dp + 100dp + 250dp + 250dp + 32dp 8dp 48dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0725a5801..6ec17cf94 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -76,6 +76,7 @@ Classic MD3 Small + @string/circle Minimal Text Artist Artists diff --git a/app/src/main/res/xml/app_widget_big_info.xml b/app/src/main/res/xml/app_widget_big_info.xml index eff87d315..3f37d6309 100755 --- a/app/src/main/res/xml/app_widget_big_info.xml +++ b/app/src/main/res/xml/app_widget_big_info.xml @@ -1,11 +1,9 @@ \ No newline at end of file + android:widgetCategory="keyguard|home_screen" /> \ No newline at end of file diff --git a/app/src/main/res/xml/app_widget_card_info.xml b/app/src/main/res/xml/app_widget_card_info.xml index fc47e387d..7298e5eac 100755 --- a/app/src/main/res/xml/app_widget_card_info.xml +++ b/app/src/main/res/xml/app_widget_card_info.xml @@ -1,11 +1,9 @@ \ No newline at end of file + android:widgetCategory="keyguard|home_screen" /> \ No newline at end of file diff --git a/app/src/main/res/xml/app_widget_circle_info.xml b/app/src/main/res/xml/app_widget_circle_info.xml new file mode 100644 index 000000000..e1b5cf6ed --- /dev/null +++ b/app/src/main/res/xml/app_widget_circle_info.xml @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/app/src/main/res/xml/app_widget_classic_info.xml b/app/src/main/res/xml/app_widget_classic_info.xml index 6aff4feba..70eb5376f 100755 --- a/app/src/main/res/xml/app_widget_classic_info.xml +++ b/app/src/main/res/xml/app_widget_classic_info.xml @@ -1,11 +1,9 @@ \ No newline at end of file + android:widgetCategory="keyguard|home_screen" /> \ No newline at end of file diff --git a/app/src/main/res/xml/app_widget_md3_info.xml b/app/src/main/res/xml/app_widget_md3_info.xml index 6aff4feba..70eb5376f 100644 --- a/app/src/main/res/xml/app_widget_md3_info.xml +++ b/app/src/main/res/xml/app_widget_md3_info.xml @@ -1,11 +1,9 @@ \ No newline at end of file + android:widgetCategory="keyguard|home_screen" /> \ No newline at end of file diff --git a/app/src/main/res/xml/app_widget_small_info.xml b/app/src/main/res/xml/app_widget_small_info.xml index e89998319..0665451f5 100644 --- a/app/src/main/res/xml/app_widget_small_info.xml +++ b/app/src/main/res/xml/app_widget_small_info.xml @@ -1,11 +1,9 @@ \ No newline at end of file + android:widgetCategory="keyguard|home_screen" /> \ No newline at end of file diff --git a/appthemehelper/build.gradle b/appthemehelper/build.gradle index 8316db478..a2437f9b8 100644 --- a/appthemehelper/build.gradle +++ b/appthemehelper/build.gradle @@ -26,7 +26,6 @@ dependencies { implementation "androidx.appcompat:appcompat:$appcompat_version" implementation "com.google.android.material:material:$mdc_version" implementation "androidx.preference:preference-ktx:$preference_version" - implementation 'androidx.cardview:cardview:1.0.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" }