Compare commits
4 Commits
05c7f0f60d
...
6aba977823
| Author | SHA1 | Date | |
|---|---|---|---|
| 6aba977823 | |||
| 229e5d1d32 | |||
| cb07acb577 | |||
| a0f9413d40 |
@@ -34,8 +34,8 @@ android {
|
||||
applicationId = "de.mm20.launcher2"
|
||||
minSdk = libs.versions.minSdk.get().toInt()
|
||||
targetSdk = libs.versions.targetSdk.get().toInt()
|
||||
versionCode = System.getenv("VERSION_CODE_OVERRIDE")?.toIntOrNull() ?: 2026091004
|
||||
versionName = "1.40.2-typing.5"
|
||||
versionCode = System.getenv("VERSION_CODE_OVERRIDE")?.toIntOrNull() ?: 2026091005
|
||||
versionName = "1.40.2-typing.6"
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
|
||||
|
||||
@@ -5,22 +5,26 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.icu.text.DateFormat
|
||||
import android.icu.util.ULocale
|
||||
import android.provider.AlarmClock
|
||||
import android.text.format.DateUtils
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.getSystemService
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.locals.LocalTimeFormat
|
||||
import de.mm20.launcher2.ui.utils.isTwentyFourHours
|
||||
import java.util.Date
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.trySendBlocking
|
||||
import kotlinx.coroutines.flow.*
|
||||
@@ -51,7 +55,8 @@ class AlarmPartProvider : PartProvider {
|
||||
if (alarm > it + AlarmWindow) {
|
||||
send(0)
|
||||
} else {
|
||||
send(60)
|
||||
// Highest ranking, so the alarm always sits directly below the clock.
|
||||
send(100)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,11 +82,15 @@ class AlarmPartProvider : PartProvider {
|
||||
@Composable
|
||||
override fun Component(compactLayout: Boolean) {
|
||||
val context = LocalContext.current
|
||||
val timeFormat = LocalTimeFormat.current
|
||||
|
||||
val alarmTime by nextAlarmTime
|
||||
val time by this.time.collectAsState(System.currentTimeMillis())
|
||||
|
||||
alarmTime?.let {
|
||||
alarmTime?.let { alarm ->
|
||||
|
||||
val skeleton = if (timeFormat.isTwentyFourHours(context)) "HH:mm" else "hh:mm a"
|
||||
val alarmText = DateFormat.getInstanceForSkeleton(skeleton, ULocale.getDefault())
|
||||
.format(Date(alarm))
|
||||
|
||||
if (!compactLayout) {
|
||||
|
||||
@@ -99,12 +108,8 @@ class AlarmPartProvider : PartProvider {
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
text = DateUtils.getRelativeTimeSpanString(
|
||||
it,
|
||||
time,
|
||||
DateUtils.MINUTE_IN_MILLIS
|
||||
)
|
||||
.toString(),
|
||||
text = alarmText,
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -123,13 +128,10 @@ class AlarmPartProvider : PartProvider {
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
text = DateUtils.getRelativeTimeSpanString(
|
||||
it,
|
||||
time,
|
||||
DateUtils.MINUTE_IN_MILLIS
|
||||
text = alarmText,
|
||||
style = MaterialTheme.typography.titleLarge.copy(
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
.toString(),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -69,17 +70,14 @@ import java.util.Date
|
||||
*/
|
||||
private const val MaxRows = 4
|
||||
|
||||
/** An event that starts within this time frame (or is running) raises the ranking. */
|
||||
private const val SoonThreshold = 30 * 60 * 1000L
|
||||
|
||||
/** Re-query interval, so the agenda survives calendar changes that don't notify. */
|
||||
private const val RefreshInterval = 15 * 60 * 1000L
|
||||
|
||||
private const val RankingToday = 30
|
||||
private const val RankingSoon = 70
|
||||
/** Static ranking: the agenda is shown whenever there are events left today. */
|
||||
private const val Ranking = 30
|
||||
|
||||
/** Width of the dot column. Kept fixed so the rows line up with each other. */
|
||||
private val DotColumn = 12.dp
|
||||
private val DotColumn = 24.dp
|
||||
|
||||
/** Width of the time column. Wide enough for "11:59 PM" and "all-day". */
|
||||
private val TimeColumn = 64.dp
|
||||
@@ -100,17 +98,12 @@ class CalendarPartProvider : PartProvider, KoinComponent {
|
||||
private val searchSettings: CalendarSearchSettings by inject()
|
||||
|
||||
private val agenda = MutableStateFlow<List<CalendarEvent>>(emptyList())
|
||||
private val time = MutableStateFlow(System.currentTimeMillis())
|
||||
|
||||
override fun setTime(time: Long) {
|
||||
this.time.value = time
|
||||
}
|
||||
|
||||
override fun getRanking(context: Context): Flow<Int> = channelFlow {
|
||||
// Load the agenda in the background; the ranking itself only depends on the
|
||||
// already known agenda and the current time, so it can be emitted right away.
|
||||
// already known agenda, so it can be emitted right away.
|
||||
launch { observeAgenda(context) }
|
||||
combine(agenda, time) { events, now -> ranking(events, now) }
|
||||
agenda.map { ranking(it) }
|
||||
.distinctUntilChanged()
|
||||
.collect { send(it) }
|
||||
}
|
||||
@@ -167,13 +160,8 @@ class CalendarPartProvider : PartProvider, KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ranking(events: List<CalendarEvent>, now: Long): Int {
|
||||
if (events.isEmpty()) return 0
|
||||
val soon = events.any { event ->
|
||||
val start = event.startTime
|
||||
!event.allDay && start != null && start <= now + SoonThreshold && event.endTime > now
|
||||
}
|
||||
return if (soon) RankingSoon else RankingToday
|
||||
private fun ranking(events: List<CalendarEvent>): Int {
|
||||
return if (events.isEmpty()) 0 else Ranking
|
||||
}
|
||||
|
||||
private fun endOfDay(now: Long): Long {
|
||||
|
||||
@@ -24,7 +24,8 @@ import java.util.*
|
||||
|
||||
class DatePartProvider : PartProvider {
|
||||
override fun getRanking(context: Context): Flow<Int> = flow {
|
||||
emit(1)
|
||||
// Second highest, so the date follows the alarm below the clock.
|
||||
emit(90)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
Reference in New Issue
Block a user