package com.tt.honeyDue.widget import android.content.Context import android.content.Intent import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import androidx.glance.GlanceId import androidx.glance.GlanceModifier import androidx.glance.action.ActionParameters import androidx.glance.action.actionParametersOf import androidx.glance.action.clickable import androidx.glance.appwidget.GlanceAppWidget import androidx.glance.appwidget.GlanceAppWidgetReceiver import androidx.glance.appwidget.SizeMode import androidx.glance.appwidget.action.ActionCallback import androidx.glance.appwidget.action.actionRunCallback import androidx.glance.appwidget.provideContent import androidx.glance.background import androidx.glance.layout.Alignment import androidx.glance.layout.Box import androidx.glance.layout.Column import androidx.glance.layout.Spacer import androidx.glance.layout.fillMaxSize import androidx.glance.layout.height import androidx.glance.layout.padding /** * Small (2x2) widget. * * Mirrors iOS `SmallWidgetView` / `FreeWidgetView` in * `iosApp/HoneyDue/HoneyDue.swift`: * - Free tier → big count + "tasks waiting" label. * - Premium → task count header + single next-task row with * an inline complete button wired to [CompleteTaskAction]. * * Glance restriction: no radial gradients or custom shapes, so the * "organic" glow behind the number is dropped. Cream background and * primary/accent colors match iOS. */ class HoneyDueSmallWidget : GlanceAppWidget() { override val sizeMode: SizeMode = SizeMode.Single override suspend fun provideGlance(context: Context, id: GlanceId) { val repo = WidgetDataRepository.get(context) val tasks = repo.loadTasks() val tier = repo.loadTierState() val isPremium = tier.equals("premium", ignoreCase = true) provideContent { SmallWidgetContent(tasks, isPremium) } } @Composable private fun SmallWidgetContent( tasks: List, isPremium: Boolean ) { val openApp = actionRunCallback() Box( modifier = GlanceModifier .fillMaxSize() .background(WidgetColors.BACKGROUND_PRIMARY) .padding(12.dp) .clickable(openApp), contentAlignment = Alignment.Center ) { if (!isPremium) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalAlignment = Alignment.CenterVertically, modifier = GlanceModifier.fillMaxSize() ) { TaskCountBlock(count = tasks.size, long = true) } } else { Column(modifier = GlanceModifier.fillMaxSize()) { TaskCountBlock(count = tasks.size, long = false) Spacer(modifier = GlanceModifier.height(8.dp)) val nextTask = tasks.firstOrNull() if (nextTask != null) { TaskRow( task = nextTask, compact = true, showResidence = false, onTaskClick = openApp, trailing = { CompleteButton(taskId = nextTask.id) } ) } else { EmptyState(compact = true, onTap = openApp) } } } } } } /** * Launch the main activity when the widget is tapped. * * Shared across all three widget sizes. Task-completion actions live * in Stream M's [CompleteTaskAction]; this receiver handles plain * "open app" taps. */ class OpenAppAction : ActionCallback { override suspend fun onAction( context: Context, glanceId: GlanceId, parameters: ActionParameters ) { val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) intent?.let { it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP context.startActivity(it) } } } /** AppWidget receiver for the small widget. */ class HoneyDueSmallWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = HoneyDueSmallWidget() }