Skip to content

Commit

Permalink
Migrate glance app widgets (#1111)
Browse files Browse the repository at this point in the history
  • Loading branch information
TinasheMzondiwa authored Aug 19, 2024
1 parent 0d83f58 commit f1d8a97
Show file tree
Hide file tree
Showing 25 changed files with 611 additions and 250 deletions.
4 changes: 2 additions & 2 deletions features/app-widgets/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<application>
<receiver
android:name=".today.TodayAppWidget"
android:name=".today.TodayAppWidgetProvider"
android:enabled="@bool/legacy_appwidget"
android:exported="true"
android:label="Today's Lesson">
Expand All @@ -16,7 +16,7 @@
android:resource="@xml/today_app_widget_info" />
</receiver>
<receiver
android:name=".today.TodayImgAppWidget"
android:name=".today.TodayImgAppWidgetProvider"
android:enabled="@bool/legacy_appwidget"
android:exported="true"
android:label="Today's Lesson">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ import android.content.Context
import android.content.Intent
import androidx.glance.appwidget.GlanceAppWidgetManager
import androidx.glance.appwidget.updateAll
import app.ss.widgets.glance.today.TodayAppWidget
import app.ss.widgets.glance.today.TodayImageAppWidget
import app.ss.widgets.glance.week.LessonInfoWidget
import app.ss.widgets.today.TodayAppWidget
import app.ss.widgets.today.TodayImgAppWidget
import app.ss.widgets.today.TodayAppWidgetProvider
import app.ss.widgets.today.TodayImgAppWidgetProvider
import app.ss.widgets.week.WeekLessonWidget
import app.ss.widgets.work.WidgetUpdateWorker
import dagger.hilt.android.qualifiers.ApplicationContext
Expand All @@ -49,15 +50,12 @@ interface AppWidgetHelper {

internal class AppWidgetHelperImpl @Inject constructor(
@ApplicationContext private val context: Context,
private val lessonInfoWidget: LessonInfoWidget.Factory,
private val todayWidget: app.ss.widgets.glance.today.TodayAppWidget.Factory,
private val todayImageAppWidget: TodayImageAppWidget.Factory,
private val dispatcherProvider: DispatcherProvider,
) : AppWidgetHelper, Scopable by defaultScopable(dispatcherProvider) {

private val widgets = listOf(
TodayAppWidget::class.java,
TodayImgAppWidget::class.java,
TodayAppWidgetProvider::class.java,
TodayImgAppWidgetProvider::class.java,
WeekLessonWidget::class.java,
)

Expand All @@ -73,9 +71,9 @@ internal class AppWidgetHelperImpl @Inject constructor(
}
}

lessonInfoWidget.create().updateAll(context)
todayWidget.create().updateAll(context)
todayImageAppWidget.create().updateAll(context)
LessonInfoWidget().updateAll(context)
TodayAppWidget().updateAll(context)
TodayImageAppWidget().updateAll(context)

WidgetUpdateWorker.enqueue(context)
} else {
Expand All @@ -89,9 +87,9 @@ internal class AppWidgetHelperImpl @Inject constructor(
val glanceAppWidgetManager = GlanceAppWidgetManager(context)

val glanceWidgetIds = withContext(dispatcherProvider.default) {
glanceAppWidgetManager.getGlanceIds(lessonInfoWidget.create().javaClass) +
glanceAppWidgetManager.getGlanceIds(todayWidget.create().javaClass) +
glanceAppWidgetManager.getGlanceIds(todayImageAppWidget.create().javaClass)
glanceAppWidgetManager.getGlanceIds(LessonInfoWidget().javaClass) +
glanceAppWidgetManager.getGlanceIds(TodayAppWidget().javaClass) +
glanceAppWidgetManager.getGlanceIds(TodayImageAppWidget().javaClass)

}
val legacyWidgetIds = widgets.map { appWidgetManager.getAppWidgetIds(ComponentName(context, it)) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ import android.content.Context
import android.content.Intent
import android.os.Build
import app.ss.widgets.model.WidgetType
import app.ss.widgets.today.TodayAppWidget
import app.ss.widgets.today.TodayImgAppWidget
import app.ss.widgets.today.TodayAppWidgetProvider
import app.ss.widgets.today.TodayImgAppWidgetProvider
import app.ss.widgets.week.WeekLessonWidget
import com.cryart.sabbathschool.core.extensions.sdk.isAtLeastApi
import javax.inject.Inject
Expand Down Expand Up @@ -67,8 +67,8 @@ abstract class BaseWidgetProvider<M> : AppWidgetProvider() {
// Instruct the widget manager to update the widget
val mgr = AppWidgetManager.getInstance(context)
val clazz = when (type) {
WidgetType.TODAY -> TodayAppWidget::class.java
WidgetType.TODAY_IMG -> TodayImgAppWidget::class.java
WidgetType.TODAY -> TodayAppWidgetProvider::class.java
WidgetType.TODAY_IMG -> TodayImgAppWidgetProvider::class.java
WidgetType.WEEK_LESSON -> WeekLessonWidget::class.java
}
val cn = ComponentName(context, clazz)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package app.ss.widgets.glance

import android.content.Context
import androidx.glance.appwidget.GlanceAppWidget
import app.ss.widgets.WidgetDataProvider
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent

@EntryPoint
@InstallIn(SingletonComponent::class)
internal interface AppWidgetDataProviderEntryPoint {
fun widgetDataProvider(): WidgetDataProvider
}

/**
* A base [GlanceAppWidget] class that handles injection.
*/
internal abstract class BaseGlanceAppWidget : GlanceAppWidget() {

fun dataProvider(context: Context): WidgetDataProvider {
val appContext = context.applicationContext ?: throw IllegalStateException()
val hiltEntryPoint =
EntryPointAccessors.fromApplication(appContext, AppWidgetDataProviderEntryPoint::class.java)
return hiltEntryPoint.widgetDataProvider()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,44 +23,10 @@
package app.ss.widgets.glance.extensions

import android.content.Intent
import android.os.Build
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.action.Action
import androidx.glance.action.clickable
import androidx.glance.appwidget.action.actionStartActivity
import androidx.glance.appwidget.appWidgetBackground
import androidx.glance.appwidget.cornerRadius
import androidx.glance.background
import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.height
import com.cryart.sabbathschool.core.extensions.sdk.isAtLeastApi

@Composable
fun GlanceModifier.modifyAppWidgetBackground() = this
.fillMaxSize()
.appWidgetBackground()
.background(GlanceTheme.colors.surface)
.appWidgetBackgroundCornerRadius()

fun GlanceModifier.appWidgetBackgroundCornerRadius(): GlanceModifier {
if (isAtLeastApi(Build.VERSION_CODES.S)) {
cornerRadius(android.R.dimen.system_app_widget_background_radius)
} else {
cornerRadius(16.dp)
}
return this
}

@Composable
fun GlanceModifier.divider(height: Dp = 0.5.dp) = this
.fillMaxWidth()
.height(height)
.background(GlanceTheme.colors.inverseOnSurface)

private const val pkg = "com.cryart.sabbathschool"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.LocalSize
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.SizeMode
import androidx.glance.appwidget.components.Scaffold
import androidx.glance.appwidget.cornerRadius
import androidx.glance.appwidget.provideContent
import androidx.glance.layout.Alignment
Expand All @@ -50,47 +50,44 @@ import androidx.glance.layout.height
import androidx.glance.layout.padding
import androidx.glance.layout.size
import androidx.glance.text.Text
import app.ss.widgets.WidgetDataProvider
import app.ss.widgets.glance.BaseGlanceAppWidget
import app.ss.widgets.glance.extensions.clickable
import app.ss.widgets.glance.extensions.fallbackIntent
import app.ss.widgets.glance.extensions.modifyAppWidgetBackground
import app.ss.widgets.glance.extensions.stringResource
import app.ss.widgets.glance.extensions.toAction
import app.ss.widgets.glance.theme.SsGlanceTheme
import app.ss.widgets.glance.theme.todayBody
import app.ss.widgets.glance.theme.todayTitle
import app.ss.widgets.model.TodayWidgetModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import ss.misc.DateHelper
import app.ss.translations.R as L10nR
import app.ss.widgets.R as WidgetsR

internal class TodayAppWidget @AssistedInject constructor(
private val dataProvider: WidgetDataProvider,
) : GlanceAppWidget() {
internal class TodayAppWidget : BaseGlanceAppWidget() {

override val sizeMode = SizeMode.Responsive(
setOf(smallMode, mediumMode, largeMode)
)

override suspend fun provideGlance(context: Context, id: GlanceId) {
val model = dataProvider.getTodayModel()
val model = dataProvider(context).getTodayModel()

provideContent {
Content(data = model)
SsGlanceTheme {
Content(data = model)
}
}
}

@Composable
private fun Content(data: TodayWidgetModel?) {
private fun Content(data: TodayWidgetModel?, modifier: GlanceModifier = GlanceModifier) {
val isSmallMode = LocalSize.current == smallMode

SsGlanceTheme {
Box(
modifier = GlanceModifier
.modifyAppWidgetBackground()
.clickable(intent = data?.intent)
) {
Scaffold(
modifier = modifier.clickable(intent = data?.intent),
horizontalPadding = 0.dp
) {
Box(modifier = GlanceModifier) {
WidgetAppLogo()

TodayInfo(
Expand All @@ -113,11 +110,6 @@ internal class TodayAppWidget @AssistedInject constructor(
}
}

@AssistedFactory
interface Factory {
fun create(): TodayAppWidget
}

companion object {
private val smallMode = DpSize(180.dp, 55.dp)
private val mediumMode = DpSize(180.dp, 110.dp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,8 @@ package app.ss.widgets.glance.today

import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
internal class TodayAppWidgetReceiver : GlanceAppWidgetReceiver() {

@Inject
lateinit var widgetFactory: TodayAppWidget.Factory

override val glanceAppWidget: GlanceAppWidget get() = widgetFactory.create()
override val glanceAppWidget: GlanceAppWidget get() = TodayAppWidget()
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,22 @@ import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.LocalContext
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.SizeMode
import androidx.glance.appwidget.components.Scaffold
import androidx.glance.appwidget.provideContent
import androidx.glance.background
import androidx.glance.layout.Box
import androidx.glance.layout.ContentScale
import androidx.glance.layout.fillMaxSize
import androidx.glance.unit.ColorProvider
import app.ss.widgets.R
import app.ss.widgets.WidgetDataProvider
import app.ss.widgets.glance.BaseGlanceAppWidget
import app.ss.widgets.glance.extensions.clickable
import app.ss.widgets.glance.extensions.modifyAppWidgetBackground
import app.ss.widgets.glance.theme.SsGlanceTheme
import app.ss.widgets.model.TodayWidgetModel
import com.cryart.sabbathschool.core.extensions.context.fetchBitmap
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject

internal class TodayImageAppWidget @AssistedInject constructor(
private val dataProvider: WidgetDataProvider,
) : GlanceAppWidget() {
internal class TodayImageAppWidget : BaseGlanceAppWidget() {

data class Data(
val model: TodayWidgetModel? = null,
Expand All @@ -69,26 +64,25 @@ internal class TodayImageAppWidget @AssistedInject constructor(
)

override suspend fun provideGlance(context: Context, id: GlanceId) {
val model = dataProvider.getTodayModel()
val model = dataProvider(context).getTodayModel()
val bitmap = context.fetchBitmap(model?.cover)

provideContent {
Content(model = model, cover = bitmap)
SsGlanceTheme {
Content(model = model, cover = bitmap)
}
}
}

@Composable
@SuppressLint("RestrictedApi")
private fun Content(
model: TodayWidgetModel?,
cover: Bitmap?
cover: Bitmap?,
modifier: GlanceModifier = GlanceModifier,
) {
SsGlanceTheme {
Box(
modifier = GlanceModifier
.modifyAppWidgetBackground()
.clickable(intent = model?.intent)
) {
Scaffold(modifier = modifier.clickable(intent = model?.intent), horizontalPadding = 0.dp) {
Box(modifier = GlanceModifier) {
cover?.let { bitmap ->
Image(
provider = BitmapImageProvider(bitmap),
Expand All @@ -98,7 +92,7 @@ internal class TodayImageAppWidget @AssistedInject constructor(
)
}

val (modifier: GlanceModifier, textColor: ColorProvider?) = if (cover != null) {
val (infoModifier: GlanceModifier, textColor: ColorProvider?) = if (cover != null) {
GlanceModifier.background(
ImageProvider(R.drawable.bg_img_foreground)
) to ColorProvider(Color.White)
Expand All @@ -123,14 +117,9 @@ internal class TodayImageAppWidget @AssistedInject constructor(
TodayInfoSpec.ReadOptions.Hidden
}
),
modifier = modifier
modifier = infoModifier,
)
}
}
}

@AssistedFactory
interface Factory {
fun create(): TodayImageAppWidget
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,8 @@ package app.ss.widgets.glance.today

import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
internal class TodayImageAppWidgetReceiver : GlanceAppWidgetReceiver() {

@Inject
lateinit var widgetFactory: TodayImageAppWidget.Factory

override val glanceAppWidget: GlanceAppWidget get() = widgetFactory.create()
override val glanceAppWidget: GlanceAppWidget get() = TodayImageAppWidget()
}
Loading

0 comments on commit f1d8a97

Please sign in to comment.