-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: clean up widgets and restore functionality
Picks refactoring work over the rewrite branch
- Loading branch information
Showing
18 changed files
with
492 additions
and
525 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
app/src/main/java/com/kelsos/mbrc/common/utilities/CustomLoggingTree.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.kelsos.mbrc.common.utilities | ||
|
||
import timber.log.Timber | ||
|
||
class CustomLoggingTree : Timber.DebugTree() { | ||
override fun createStackElementTag(element: StackTraceElement): String = | ||
with(element) { | ||
val thread = with(Thread.currentThread()) { name } | ||
val createStackElementTag = super.createStackElementTag(element) | ||
val className = createStackElementTag?.split("$")?.get(0) | ||
"($className.kt:$lineNumber)#$methodName {$thread}" | ||
} | ||
|
||
companion object { | ||
fun create(): CustomLoggingTree = CustomLoggingTree() | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
app/src/main/java/com/kelsos/mbrc/common/utilities/Helpers.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.kelsos.mbrc.common.utilities | ||
|
||
inline fun <T1 : Any, T2 : Any, R : Any> whenNotNull( | ||
p1: T1?, | ||
p2: T2?, | ||
block: (T1, T2) -> R?, | ||
): R? = if (p1 != null && p2 != null) block(p1, p2) else null |
35 changes: 35 additions & 0 deletions
35
app/src/main/java/com/kelsos/mbrc/features/widgets/BundleData.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.kelsos.mbrc.features.widgets | ||
|
||
import android.os.Bundle | ||
import androidx.core.os.BundleCompat | ||
import com.kelsos.mbrc.annotations.PlayerState | ||
import com.kelsos.mbrc.features.player.TrackInfo | ||
|
||
class BundleData( | ||
private val bundle: Bundle, | ||
) { | ||
fun isState() = bundle.getBoolean(WidgetUpdater.STATE, false) | ||
|
||
fun isInfo() = bundle.getBoolean(WidgetUpdater.INFO, false) | ||
|
||
fun isCover() = bundle.getBoolean(WidgetUpdater.COVER, false) | ||
|
||
fun cover(): String = bundle.getString(WidgetUpdater.COVER_PATH, "") | ||
|
||
fun state(): String = bundle.getString(WidgetUpdater.PLAYER_STATE, PlayerState.UNDEFINED) | ||
|
||
fun playingTrack(): TrackInfo = | ||
BundleCompat.getParcelable( | ||
bundle, | ||
WidgetUpdater.TRACK_INFO, | ||
TrackInfo::class.java, | ||
) ?: TrackInfo() | ||
|
||
override fun toString(): String = | ||
when { | ||
this.isState() -> "State: ${this.state()}" | ||
this.isInfo() -> "Info: ${this.playingTrack()}" | ||
this.isCover() -> "Cover: ${this.cover()}" | ||
else -> "Unknown" | ||
} | ||
} |
167 changes: 167 additions & 0 deletions
167
app/src/main/java/com/kelsos/mbrc/features/widgets/WidgetBase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package com.kelsos.mbrc.features.widgets | ||
|
||
import android.app.PendingIntent | ||
import android.appwidget.AppWidgetManager | ||
import android.appwidget.AppWidgetProvider | ||
import android.content.ComponentName | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.os.Bundle | ||
import android.widget.RemoteViews | ||
import coil3.imageLoader | ||
import coil3.request.ImageRequest | ||
import coil3.size.Precision | ||
import coil3.size.Scale | ||
import com.kelsos.mbrc.R | ||
import com.kelsos.mbrc.annotations.PlayerState | ||
import com.kelsos.mbrc.common.utilities.whenNotNull | ||
import com.kelsos.mbrc.features.player.PlayerActivity | ||
import com.kelsos.mbrc.features.player.TrackInfo | ||
import timber.log.Timber | ||
import java.io.File | ||
|
||
abstract class WidgetBase : AppWidgetProvider() { | ||
abstract val config: WidgetConfig | ||
abstract val type: String | ||
|
||
override fun onReceive( | ||
context: Context?, | ||
intent: Intent?, | ||
) { | ||
super.onReceive(context, intent) | ||
if (intent?.action == AppWidgetManager.ACTION_APPWIDGET_UPDATE) { | ||
whenNotNull(context, intent.extras, this::updateWidget) | ||
} | ||
} | ||
|
||
private fun updateWidget( | ||
context: Context, | ||
extras: Bundle, | ||
) { | ||
val widgetManager = AppWidgetManager.getInstance(context) | ||
val widgets = ComponentName(context.packageName, config.widgetClass.java.name) | ||
val widgetsIds = widgetManager.getAppWidgetIds(widgets) | ||
val data = BundleData(extras) | ||
|
||
if (widgetsIds.isEmpty()) { | ||
Timber.v("No $type widgets found for update") | ||
return | ||
} | ||
|
||
Timber.v("Updating $type widgets ${widgetsIds.joinToString(", ")} with extras: $data") | ||
|
||
when { | ||
data.isCover() -> { | ||
updateCover(context, widgetManager, widgetsIds, data.cover()) | ||
} | ||
data.isInfo() -> | ||
updateInfo( | ||
context, | ||
widgetManager, | ||
widgetsIds, | ||
data.playingTrack(), | ||
) | ||
data.isState() -> | ||
updatePlayState( | ||
context, | ||
widgetManager, | ||
widgetsIds, | ||
data.state(), | ||
) | ||
} | ||
} | ||
|
||
override fun onUpdate( | ||
context: Context, | ||
appWidgetManager: AppWidgetManager, | ||
appWidgetIds: IntArray, | ||
) { | ||
super.onUpdate(context, appWidgetManager, appWidgetIds) | ||
|
||
if (!appWidgetIds.isEmpty()) { | ||
Timber.v("onUpdate called for $type widgets: ${appWidgetIds.joinToString(", ")}") | ||
} | ||
|
||
for (appWidgetId in appWidgetIds) { | ||
val intent = Intent(context, PlayerActivity::class.java) | ||
val pendingIntent = | ||
PendingIntent.getActivity( | ||
context, | ||
0, | ||
intent, | ||
PendingIntent.FLAG_IMMUTABLE, | ||
) | ||
val views = RemoteViews(context.packageName, config.layout) | ||
setupActionIntents(views, pendingIntent, context) | ||
// Tell the AppWidgetManager to perform an set on the current app widget | ||
appWidgetManager.updateAppWidget(appWidgetId, views) | ||
} | ||
} | ||
|
||
abstract fun setupActionIntents( | ||
views: RemoteViews, | ||
pendingIntent: PendingIntent, | ||
context: Context, | ||
) | ||
|
||
abstract fun setupTrackInfo( | ||
views: RemoteViews, | ||
info: TrackInfo, | ||
) | ||
|
||
private fun updateInfo( | ||
context: Context, | ||
widgetManager: AppWidgetManager, | ||
widgetsIds: IntArray, | ||
info: TrackInfo, | ||
) { | ||
val views = RemoteViews(context.packageName, config.layout) | ||
setupTrackInfo(views, info) | ||
widgetManager.updateAppWidget(widgetsIds, views) | ||
} | ||
|
||
private fun updateCover( | ||
context: Context, | ||
widgetManager: AppWidgetManager, | ||
widgetsIds: IntArray, | ||
path: String, | ||
) { | ||
val widget = RemoteViews(context.packageName, config.layout) | ||
val coverFile = File(path) | ||
if (coverFile.exists()) { | ||
val request = | ||
ImageRequest | ||
.Builder(context) | ||
.data(coverFile) | ||
.size(R.dimen.widget_small_height) | ||
.scale(Scale.FILL) | ||
.precision(Precision.INEXACT) | ||
.target(RemoteViewsTarget(widgetManager, widget, widgetsIds, config.imageId)) | ||
.build() | ||
|
||
context.imageLoader.enqueue(request) | ||
} else { | ||
widget.setImageViewResource(config.imageId, R.drawable.ic_image_no_cover) | ||
widgetManager.updateAppWidget(widgetsIds, widget) | ||
} | ||
} | ||
|
||
private fun updatePlayState( | ||
context: Context, | ||
manager: AppWidgetManager, | ||
widgetsIds: IntArray, | ||
state: String, | ||
) { | ||
val widget = RemoteViews(context.packageName, config.layout) | ||
|
||
widget.setImageViewResource( | ||
config.playButtonId, | ||
if (PlayerState.PLAYING == state) { | ||
R.drawable.ic_action_pause | ||
} else { | ||
R.drawable.ic_action_play | ||
}, | ||
) | ||
manager.updateAppWidget(widgetsIds, widget) | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
app/src/main/java/com/kelsos/mbrc/features/widgets/WidgetConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.kelsos.mbrc.features.widgets | ||
|
||
import androidx.annotation.DimenRes | ||
import androidx.annotation.IdRes | ||
import androidx.annotation.LayoutRes | ||
import kotlin.reflect.KClass | ||
|
||
data class WidgetConfig( | ||
@LayoutRes | ||
val layout: Int, | ||
@DimenRes | ||
val imageSize: Int, | ||
@IdRes | ||
val imageId: Int, | ||
@IdRes | ||
val playButtonId: Int, | ||
val widgetClass: KClass<out WidgetBase>, | ||
) |
Oops, something went wrong.