add clock widget with dual-color time and next alarm
This commit is contained in:
parent
1dbd96d961
commit
2335e6d926
4 changed files with 183 additions and 0 deletions
|
|
@ -35,5 +35,16 @@
|
|||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/agenda_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widget.ClockWidgetReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/clock_widget_info" />
|
||||
</receiver>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,156 @@
|
|||
package space.darkest.nova.android.widget
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.provider.AlarmClock
|
||||
import android.provider.Settings
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.glance.GlanceId
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.GlanceTheme
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.appwidget.GlanceAppWidget
|
||||
import androidx.glance.appwidget.GlanceAppWidgetReceiver
|
||||
import androidx.glance.appwidget.action.actionStartActivity
|
||||
import androidx.glance.appwidget.provideContent
|
||||
import androidx.glance.background
|
||||
import androidx.glance.color.DynamicThemeColorProviders
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.Column
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.Spacer
|
||||
import androidx.glance.layout.fillMaxSize
|
||||
import androidx.glance.layout.height
|
||||
import androidx.glance.layout.padding
|
||||
import androidx.glance.layout.width
|
||||
import androidx.glance.text.FontWeight
|
||||
import androidx.glance.text.Text
|
||||
import androidx.glance.text.TextStyle
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.TextStyle as DateTextStyle
|
||||
import java.util.Locale
|
||||
|
||||
class ClockWidget : GlanceAppWidget() {
|
||||
|
||||
override suspend fun provideGlance(context: Context, id: GlanceId) {
|
||||
val alarmManager = context.getSystemService(AlarmManager::class.java)
|
||||
val nextAlarm = alarmManager.nextAlarmClock?.let { alarm ->
|
||||
Instant.ofEpochMilli(alarm.triggerTime)
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDateTime()
|
||||
}
|
||||
|
||||
provideContent {
|
||||
GlanceTheme(colors = DynamicThemeColorProviders) {
|
||||
ClockContent(nextAlarm?.toLocalTime(), nextAlarm?.toLocalDate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ClockContent(alarmTime: LocalTime?, alarmDate: LocalDate?) {
|
||||
val now = LocalTime.now()
|
||||
val today = LocalDate.now()
|
||||
val hours = now.format(DateTimeFormatter.ofPattern("HH"))
|
||||
val minutes = now.format(DateTimeFormatter.ofPattern("mm"))
|
||||
val dateStr = today.let {
|
||||
val day = it.dayOfWeek.getDisplayName(DateTextStyle.SHORT, Locale.getDefault())
|
||||
val date = it.format(DateTimeFormatter.ofPattern("d MMM"))
|
||||
"$day, $date"
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.fillMaxSize()
|
||||
.background(GlanceTheme.colors.widgetBackground)
|
||||
.padding(16.dp)
|
||||
.clickable(actionStartActivity(Intent(AlarmClock.ACTION_SHOW_ALARMS))),
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
Column {
|
||||
// time row: hours (primary) : minutes (tertiary)
|
||||
Row(verticalAlignment = Alignment.Bottom) {
|
||||
Text(
|
||||
text = hours,
|
||||
style = TextStyle(
|
||||
color = GlanceTheme.colors.primary,
|
||||
fontSize = 48.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
)
|
||||
Text(
|
||||
text = ":",
|
||||
style = TextStyle(
|
||||
color = GlanceTheme.colors.onSurfaceVariant,
|
||||
fontSize = 48.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
)
|
||||
Text(
|
||||
text = minutes,
|
||||
style = TextStyle(
|
||||
color = GlanceTheme.colors.tertiary,
|
||||
fontSize = 48.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(GlanceModifier.height(2.dp))
|
||||
|
||||
// date
|
||||
Text(
|
||||
text = dateStr,
|
||||
style = TextStyle(
|
||||
color = GlanceTheme.colors.onSurfaceVariant,
|
||||
fontSize = 14.sp,
|
||||
),
|
||||
)
|
||||
|
||||
// next alarm
|
||||
if (alarmTime != null && alarmDate != null) {
|
||||
Spacer(GlanceModifier.height(4.dp))
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = "\u23F0",
|
||||
style = TextStyle(fontSize = 12.sp),
|
||||
)
|
||||
Spacer(GlanceModifier.width(4.dp))
|
||||
Text(
|
||||
text = formatAlarm(alarmTime, alarmDate),
|
||||
style = TextStyle(
|
||||
color = GlanceTheme.colors.secondary,
|
||||
fontSize = 12.sp,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatAlarm(time: LocalTime, date: LocalDate): String {
|
||||
val today = LocalDate.now()
|
||||
val timeStr = time.format(DateTimeFormatter.ofPattern("HH:mm"))
|
||||
return when (date) {
|
||||
today -> timeStr
|
||||
today.plusDays(1) -> "Tomorrow $timeStr"
|
||||
else -> {
|
||||
val dayName = date.dayOfWeek.getDisplayName(DateTextStyle.SHORT, Locale.getDefault())
|
||||
"$dayName $timeStr"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ClockWidgetReceiver : GlanceAppWidgetReceiver() {
|
||||
override val glanceAppWidget: GlanceAppWidget = ClockWidget()
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<resources>
|
||||
<string name="app_name">Nova Shell</string>
|
||||
<string name="widget_description">Calendar agenda showing upcoming events</string>
|
||||
<string name="clock_widget_description">Clock with next alarm</string>
|
||||
<string name="widget_loading">Loading…</string>
|
||||
</resources>
|
||||
|
|
|
|||
15
app/src/main/res/xml/clock_widget_info.xml
Normal file
15
app/src/main/res/xml/clock_widget_info.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/clock_widget_description"
|
||||
android:initialLayout="@layout/glance_default_loading_layout"
|
||||
android:minWidth="180dp"
|
||||
android:minHeight="110dp"
|
||||
android:minResizeWidth="110dp"
|
||||
android:minResizeHeight="80dp"
|
||||
android:maxResizeWidth="530dp"
|
||||
android:maxResizeHeight="200dp"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:targetCellWidth="3"
|
||||
android:targetCellHeight="2"
|
||||
android:updatePeriodMillis="60000"
|
||||
android:widgetCategory="home_screen" />
|
||||
Loading…
Add table
Add a link
Reference in a new issue