Merge branch 'main' of github.com:MM2-0/Kvaesitso

This commit is contained in:
MM20 2025-06-03 00:13:03 +02:00
commit d81936212d
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
8 changed files with 132 additions and 24 deletions

View File

@ -18,6 +18,8 @@ import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.channelFlow
import de.mm20.launcher2.ktx.foldOrNull
import de.mm20.launcher2.ktx.isBetterThan
import kotlinx.coroutines.flow.combine
class DevicePoseProvider internal constructor(
@ -37,10 +39,16 @@ class DevicePoseProvider internal constructor(
}
fun getLocation(minTimeMs: Long = 1000, minDistanceM: Float = 1f) = channelFlow {
fun updateLocation(update: Location?) {
if (update == null) return
if (!update.isBetterThan(lastLocation)) return
lastLocation = update
updateDeclination(update)
trySend(update)
}
val locationCallback = LocationListenerCompat {
lastLocation = it
updateDeclination(it)
trySend(it)
updateLocation(it)
}
context.getSystemService<LocationManager>()
@ -50,20 +58,14 @@ class DevicePoseProvider internal constructor(
val hasCoarseAccess =
context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
val location =
(if (hasFineAccess) this@runCatching.getLastKnownLocation(LocationManager.GPS_PROVIDER) else null)
?: if (hasCoarseAccess) this@runCatching.getLastKnownLocation(
LocationManager.NETWORK_PROVIDER
) else null
val previousLocation =
hasFineAccess.foldOrNull { getLastKnownLocation(LocationManager.GPS_PROVIDER) } ?:
hasCoarseAccess.foldOrNull { getLastKnownLocation(LocationManager.NETWORK_PROVIDER) }
if (location != null) {
lastLocation = location
updateDeclination(location)
trySend(location)
}
updateLocation(previousLocation)
if (hasFineAccess) {
this@runCatching.requestLocationUpdates(
requestLocationUpdates(
LocationManager.GPS_PROVIDER,
minTimeMs,
minDistanceM,
@ -71,7 +73,7 @@ class DevicePoseProvider internal constructor(
)
}
if (hasCoarseAccess) {
this@runCatching.requestLocationUpdates(
requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
minTimeMs,
minDistanceM,

View File

@ -318,8 +318,8 @@
<string name="search_action_websearch">Internetes keresés</string>
<string name="plugin_state_setup_required">Először be kell állítani ezt a bővítményt</string>
<string name="plugin_action_setup">Beállítás</string>
<string name="plugin_type_weather">Időjárás-előrejelzés szolgáltató</string>
<string name="plugin_weather_provider_enable">Beállítás időjárás-előrejelzési szolgáltatónak</string>
<string name="plugin_type_weather">Időjáráselőrejelzési szolgáltató</string>
<string name="plugin_weather_provider_enable">Beállítás időjáráselőrejelzési szolgáltatónak</string>
<string name="preference_clock_widget_alignment_bottom">Alulra</string>
<string name="preference_clockwidget_battery_part_summary">Az akkumulátor jelenlegi töltöttségi szintjének megjelenítése, amikor az akkumulátor lemerült vagy töltődik</string>
<string name="preference_clockwidget_alarm_part_summary">Azon riasztások megjelenítése, amelyek a következő 8 órán belül megszólalnak</string>
@ -379,7 +379,7 @@
<string name="preference_search_currencyconverter">Valutaváltó</string>
<string name="preference_search_bar_auto_focus_summary">A billentyűzet automatikus megjelenítése az alkalmazásfiók megnyitásakor</string>
<string name="note_widget_link_file_summary">Szinkronizálja a modul tartalmát egy külső fájllal</string>
<string name="plugin_weather_provider_enabled">Jelenleg időjárás-előrejelzés szolgáltatóként van beállítva</string>
<string name="plugin_weather_provider_enabled">Jelenleg időjáráselőrejelzési szolgáltatóként van beállítva</string>
<string name="preference_search_websites">Weboldalak</string>
<string name="preference_search_websites_summary">Egy weboldal előnézetének megjelenítése, ha a keresési lekérdezés egy webcím</string>
<string name="preference_edit_favorites_summary">A kitűzött elemek sorrendjének módosítása</string>
@ -835,4 +835,11 @@
<string name="gesture_action_widgets">Modulok</string>
<string name="bad_configuration_title">Gratulálunk, kizárta saját magát!</string>
<string name="bad_configuration_summary">Felfedezte a beállítások olyan kombinációját, amely a keresést és a beállításokat is elérhetetlenné teszi — gyakorlatilag kizárja Önt az indítóból.</string>
<string name="preference_screen_shapes">Alakzatok</string>
<string name="preference_shapes_default">Alapértelmezett</string>
<string name="preference_shapes_extra_round">További lekerekítés</string>
<string name="preference_shapes_rect">Négyszögletes</string>
<string name="preference_shapes_base">Alap alakzat</string>
<string name="confirmation_delete_shapes_scheme">Biztosan törölni szeretné a(z) %1$s nevű alakzatsémát?</string>
<string name="new_shapes_name">Új alakzatok</string>
</resources>

View File

@ -846,4 +846,11 @@
<string name="gesture_action_widgets">Widget</string>
<string name="bad_configuration_title">Congratulazioni, ti sei chiuso fuori!</string>
<string name="bad_configuration_summary">Hai scoperto una combinazione di impostazioni che rende inaccessibili sia la ricerca sia le impostazioni, impedendoti di fatto di accedere al launcher.</string>
<string name="preference_shapes_default">Predefinito</string>
<string name="preference_screen_shapes">Forme</string>
<string name="preference_shapes_extra_round">Arrotondamento extra</string>
<string name="preference_shapes_rect">Rettangolare</string>
<string name="preference_shapes_base">Forma di base</string>
<string name="confirmation_delete_shapes_scheme">Vuoi davvero eliminare lo schema di forme %1$s?</string>
<string name="new_shapes_name">Nuove forme</string>
</resources>

View File

@ -835,4 +835,11 @@
<string name="preference_widgets_on_home_screen">Widgets op het thuisscherm</string>
<string name="bad_configuration_title">Proficiat, je hebt jezelf buiten gesloten!</string>
<string name="bad_configuration_summary">Je hebt een combinatie van instellingen ontdekt die zowel zoeken als de instellingen onbereikbaar maakt - je bent nu volledig uit de startschermapp gesloten.</string>
<string name="preference_screen_shapes">Vormen</string>
<string name="preference_shapes_default">Standaard</string>
<string name="preference_shapes_extra_round">Extra rond</string>
<string name="preference_shapes_rect">Rechthoekig</string>
<string name="preference_shapes_base">Basisvorm</string>
<string name="confirmation_delete_shapes_scheme">Weet je zeker dat je de vorm %1$s wil verwijderen?</string>
<string name="new_shapes_name">Nieuwe vormen</string>
</resources>

View File

@ -0,0 +1,37 @@
package de.mm20.launcher2.ktx
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.nanoseconds
import android.location.Location as AndroidLocation
/* https://github.com/streetcomplete/StreetComplete/blob/master/app/src/main/java/de/westnordost/streetcomplete/util/location/LocationUtils.kt
* GPL-3.0-or-later
*/
fun AndroidLocation.isBetterThan(previous: AndroidLocation?): Boolean {
if (longitude.isNaN() || latitude.isNaN()) return false
if (previous == null) return true
val locationTimeDiff = elapsedRealtimeNanos.nanoseconds - previous.elapsedRealtimeNanos.nanoseconds
val isMuchNewer = locationTimeDiff > 2.minutes
val isMuchOlder = locationTimeDiff < (-2).minutes
val isNewer = locationTimeDiff.isPositive()
val accuracyDelta = accuracy - previous.accuracy
val isLessAccurate = accuracyDelta > 0f
val isMoreAccurate = accuracyDelta < 0f
val isMuchLessAccurate = accuracyDelta > 200f
val isFromSameProvider = provider == previous.provider
return when {
// the user has likely moved
isMuchNewer -> true
// If the new location is more than two minutes older, it must be worse
isMuchOlder -> false
isMoreAccurate -> true
isNewer && !isLessAccurate -> true
isNewer && !isMuchLessAccurate && isFromSameProvider -> true
else -> false
}
}

View File

@ -1,5 +1,14 @@
package de.mm20.launcher2.ktx
inline fun Boolean.toInt(): Int {
fun Boolean.toInt(): Int {
return if (this) 1 else 0
}
fun <T> Boolean.fold(
whenTrue: () -> T,
otherwise: () -> T
): T = if (this) whenTrue() else otherwise()
fun <T> Boolean.foldOrNull(
whenTrue: () -> T
): T? = fold(whenTrue) { null }

View File

@ -388,6 +388,8 @@ internal fun parseOpeningSchedule(
}
}
}
} else if (!rule.holidays.isNullOrEmpty()) {
continue // skip PH and SH entries
} else if (!rule.times.isNullOrEmpty() || !rule.months.isNullOrEmpty()) {
rulesMap.forEach { _, it ->
it.add(rule)
@ -395,14 +397,12 @@ internal fun parseOpeningSchedule(
}
}
// Filter out rules that are not valid for the current year, month, and week. Hopefully,
// there is only one rule left per weekday. If not, skip that weekday.
val applicableRules = rulesMap.mapNotNull { (day, rules) ->
// Filter out rules that are not valid for the current year, month, and week.
val applicableRules = rulesMap.flatMap { (day, rules) ->
rules.filterYears(localTime)
.filterMonths(localTime)
.filterNthDays(localTime)
.map { it.copy(weekdays = listOf(day)) }
.singleOrNull()
}
val hours = mutableSetOf<OpeningHours>()

View File

@ -302,4 +302,43 @@ class OpeningHoursTest {
LocalDateTime.of(2025, Month.APRIL, 10, 0, 0)
)
}
@Test
fun regressTest0() {
OpeningSchedule.Hours(
setOf(
OpeningHours(dayOfWeek = DayOfWeek.MONDAY, startTime = LocalTime.of(8,30), duration = Duration.ofHours(3) + Duration.ofMinutes(30)),
OpeningHours(dayOfWeek = DayOfWeek.TUESDAY, startTime = LocalTime.of(8,30), duration = Duration.ofHours(3) + Duration.ofMinutes(30)),
OpeningHours(dayOfWeek = DayOfWeek.WEDNESDAY, startTime = LocalTime.of(8,30), duration = Duration.ofHours(3) + Duration.ofMinutes(30)),
OpeningHours(dayOfWeek = DayOfWeek.THURSDAY, startTime = LocalTime.of(8,30), duration = Duration.ofHours(3) + Duration.ofMinutes(30)),
OpeningHours(dayOfWeek = DayOfWeek.FRIDAY, startTime = LocalTime.of(8,30), duration = Duration.ofHours(3) + Duration.ofMinutes(30)),
OpeningHours(dayOfWeek = DayOfWeek.MONDAY, startTime = LocalTime.of(14,0), duration = Duration.ofHours(2)),
OpeningHours(dayOfWeek = DayOfWeek.TUESDAY, startTime = LocalTime.of(14,0), duration = Duration.ofHours(2)),
OpeningHours(dayOfWeek = DayOfWeek.FRIDAY, startTime = LocalTime.of(14,0), duration = Duration.ofHours(2)),
OpeningHours(dayOfWeek = DayOfWeek.THURSDAY, startTime = LocalTime.of(17,0), duration = Duration.ofHours(2)),
)
) assertEqualTo parseOpeningSchedule(
"Mo-Fr 08:30-12:00; Mo,Tu,Fr 14:00-16:00; Th 17:00-19:00"
)
}
@Test
fun regressTest1() {
OpeningSchedule.Hours(
setOf(
OpeningHours(dayOfWeek = DayOfWeek.TUESDAY, startTime = LocalTime.of(11,45), duration = Duration.ofHours(10) + Duration.ofMinutes(45)),
OpeningHours(dayOfWeek = DayOfWeek.WEDNESDAY, startTime = LocalTime.of(11,45), duration = Duration.ofHours(10) + Duration.ofMinutes(45)),
OpeningHours(dayOfWeek = DayOfWeek.THURSDAY, startTime = LocalTime.of(11,45), duration = Duration.ofHours(10) + Duration.ofMinutes(45)),
OpeningHours(dayOfWeek = DayOfWeek.FRIDAY, startTime = LocalTime.of(11,45), duration = Duration.ofHours(10) + Duration.ofMinutes(45)),
OpeningHours(dayOfWeek = DayOfWeek.SATURDAY, startTime = LocalTime.of(11,45), duration = Duration.ofHours(10) + Duration.ofMinutes(45)),
OpeningHours(dayOfWeek = DayOfWeek.SUNDAY, startTime = LocalTime.of(11,30), duration = Duration.ofHours(11)),
// We don't track public holidays. Otherwise, we'd probably go mad!
)
) assertEqualTo parseOpeningSchedule(
"Tu-Sa 11:45-22:30; Su 11:30-22:30; PH 11:30-22:30"
)
}
}