Skip to content

Commit

Permalink
Play Recently Widget.
Browse files Browse the repository at this point in the history
  • Loading branch information
oxyroid committed Jun 15, 2024
1 parent 8b2110f commit 06ab248
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 0 deletions.
3 changes: 3 additions & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -149,5 +149,8 @@ dependencies {
ksp(libs.androidx.hilt.compiler)
implementation(libs.androidx.hilt.work)

implementation("androidx.glance:glance-appwidget:1.0.0")
implementation("androidx.glance:glance-material3:1.0.0")

debugImplementation(libs.squareup.leakcanary)
}
11 changes: 11 additions & 0 deletions androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@
android:resource="@xml/filepaths" />
</provider>

<receiver
android:name=".glance.GlanceReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>

<profileable
android:shell="true"
tools:targetApi="29" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.m3u.androidApp.glance

import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import com.m3u.data.repository.channel.ChannelRepository
import com.m3u.data.repository.media.MediaRepository
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

class GlanceReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = PlayRandomlyWidget()

}

@EntryPoint
@InstallIn(SingletonComponent::class)
interface GlanceAccessor {
val channelRepository: ChannelRepository
val mediaRepository: MediaRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.m3u.androidApp.glance

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.graphics.drawable.toBitmap
import androidx.glance.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.action.clickable
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.action.actionStartActivity
import androidx.glance.appwidget.cornerRadius
import androidx.glance.appwidget.provideContent
import androidx.glance.background
import androidx.glance.layout.Alignment
import androidx.glance.layout.Box
import androidx.glance.layout.ContentScale
import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.padding
import androidx.glance.text.FontWeight
import androidx.glance.text.Text
import androidx.glance.text.TextDefaults
import androidx.glance.unit.ColorProvider
import com.m3u.core.Contracts
import dagger.hilt.android.EntryPointAccessors

class PlayRandomlyWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
val accessor: GlanceAccessor by lazy {
EntryPointAccessors.fromApplication(context.applicationContext)
}
val playedRecently = accessor.channelRepository.observePlayedRecently()
provideContent {
val channel by playedRecently.collectAsState(initial = null)
GlanceTheme {
val bitmap: Bitmap? by produceState<Bitmap?>(
initialValue = null,
key1 = channel?.cover
) {
value = accessor.mediaRepository
.loadDrawable(channel?.cover.orEmpty())
?.toBitmap()
}
Box(
contentAlignment = Alignment.BottomStart,
modifier = GlanceModifier
.fillMaxSize()
.cornerRadius(16.dp)
.clickable(
actionStartActivity(
Intent(Intent.ACTION_VIEW).apply {
component = ComponentName.createRelative(
context,
Contracts.PLAYER_ACTIVITY
)
putExtra(
Contracts.PLAYER_SHORTCUT_CHANNEL_RECENTLY,
true
)
}
)
)
.background(GlanceTheme.colors.background)
.padding(4.dp)
) {
val currentBitmap = bitmap
if (currentBitmap != null) {
Image(
provider = ImageProvider(currentBitmap),
contentDescription = channel?.title,
contentScale = ContentScale.Crop,
modifier = GlanceModifier
.fillMaxSize()
.cornerRadius(16.dp)
)
}
Text(
text = channel?.title.orEmpty(),
style = TextDefaults.defaultTextStyle.copy(
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = ColorProvider(Color.White)
),
maxLines = 1,
modifier = GlanceModifier.padding(12.dp)
)
}
}
}
}
}
9 changes: 9 additions & 0 deletions androidApp/src/main/res/xml/widget_info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout"
android:targetCellWidth="2"
android:targetCellHeight="1"
android:updatePeriodMillis="86400000"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
3 changes: 3 additions & 0 deletions data/src/main/java/com/m3u/data/database/dao/ChannelDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ internal interface ChannelDao {
@Query("SELECT * FROM streams WHERE seen != 0 ORDER BY seen DESC LIMIT 1")
suspend fun getPlayedRecently(): Channel?

@Query("SELECT * FROM streams WHERE seen != 0 ORDER BY seen DESC LIMIT 1")
fun observePlayedRecently(): Flow<Channel?>

@Query("SELECT * FROM streams WHERE id = :id")
suspend fun get(id: Int): Channel?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface ChannelRepository {
suspend fun hide(id: Int, target: Boolean)
suspend fun reportPlayed(id: Int)
suspend fun getPlayedRecently(): Channel?
fun observePlayedRecently(): Flow<Channel?>
fun observeAllUnseenFavourites(limit: Duration): Flow<List<Channel>>
fun observeAllFavourite(): Flow<List<Channel>>
fun observeAllHidden(): Flow<List<Channel>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ internal class ChannelRepositoryImpl @Inject constructor(
channelDao.getPlayedRecently()
}

override fun observePlayedRecently(): Flow<Channel?> = channelDao.observePlayedRecently()

override fun observeAllUnseenFavourites(limit: Duration): Flow<List<Channel>> =
channelDao.observeAllUnseenFavourites(
limit = limit.inWholeMilliseconds,
Expand Down

0 comments on commit 06ab248

Please sign in to comment.