Add support for location plugins (#772)
* Cherry pick location refactor * Refactor :data:openstreetmaps to :data:locations * contract, plugin sdk * Implement serialization, module tweaks * Include check for out-of-date departures in SearchableItemVM.requestUpdatedSearchable() * settings for location plugins * Try not to be too lazy * more fiddling with the plugin SDK * add departures in MapView with mock data for debug builds * change icons * add boats * animate departure lazycolumn * Add MarqueeText for text overflow handling * Define height for Departures in case there is no map to display * Don't inclure railway / highway tags for OSM since there will be location plugins for that * sort by time * - Apply pre-merge changes to LocationSettings - Add banner warning about slowed down location search for large search radii * ditch `showLocationOnMap` * LocationItem: make `showOpeningSchedule` toggleable * LocationItem: make Navigation AssistChip work for people that don't have google maps installed * LocationItem: resolve TODOs * MapTiles: ditch unused code, animate userIndicator * Reintroduce departure list * Add LineColor * Add osm tag `stars` as `userRating` https://taginfo.openstreetmap.org/keys/stars#overview * typealias -> import * Don't add Navigation Chip when there is no way to resolve navigation intents * Add settings migration * Set plugin SDK version to 1.2.0-SNAPSHOT * Deduplicate shared plugin classes, use kotlinx.serialization * Fix imports * Use ZonedDateTime for depature times * Add more line types * Rewrite location serialization * Replace street/houseNumber with address * Add attribution field * Add plugin config * Reject location search requests without lat lon parameters * Add default values to plugin location class * Don't crash if column value is null * Add docs comments to LocationCategory values * Refactor OpeningSchedule as polymorphic * remove dead corpse *ahem* code * Split LocationCategory into category and icon (Also update to Kotlin 2.0, please don't do this at home) * Add more location icons * Fix (?) location deserializer * Add more location icons * More icons * Meh * Add Pub * Disable Github Maven repo if credentials are missing * Add location search specific settings to plugin details screen * Add language parameter * Unbreak the build * Refactor plugin SDK (with breaking changes) * Set plugin SDK version to 2.0.0-SNAPSHOT * Document SDK breaking changes * Implement LocationProvider.getQuery * Add a typesafe cursor API * Oops I did it again next time maybe check if the code is actually compiling before pushing * Add missing return statement * Fix list serialization * Departure time UI adjustment * Use typesafe cursor for weather plugins * Add userRatingCount and emailAddress fields * grrr * Rename and extend LineTypes * Add default lineType to Departure to fix serialization errors * Fix refreshing stored plugin locations * Adapt line name column width to available departures * Fix plugin settings screen category overlap * add LocationItem.GenericTransit * Fix crash during deserialization of locations * Update SDK docs * Replace plugin "official" mark with "verified developer" mark before anyone gets sued * show 'now' when departure is in less than one minute * Add typesafe Bundle API * Implement plugin API changes * Plugin SDK: Fix refresh result not being returned * Update docs * apply alpha to departures that have departured * better (maybe): reduce saturation instead of alpha * Add default values for Attribution * Display attribution * Rearrange location result layout * Reduce searchable update interval to 1 minute * Pass last update time to refresh function * Change refresh path and ensure that timestamp is only update when the item was updated * categorize osm location * Update docs * Optimize location search - run providers in parallel - flatten code * add experimental address parsing for OSM * add poi_category_townhall * Fix popup closing when favorites items are updated * Revert "Fix popup closing when favorites items are updated" This reverts commit fc517fd066c7f8109b6d6df2d4f536af66398207. * Fork AndroidAddressFormatter to `:libs:address-formatter` * migrate `:libs:address-formatter` dependencies to version catalog and update them * also consider addr:{suburb,hamlet} for `Address.city` if city tag is missing * Move poi strings back to strings.xml * Update Jetpack Compose * Move address-formatter back to its original package, add license and readme * Move address-formatter back to its original package --------- Co-authored-by: MM20 <15646950+MM2-0@users.noreply.github.com>
This commit is contained in:
@@ -48,6 +48,9 @@ dependencies {
|
||||
|
||||
implementation(libs.koin.android)
|
||||
implementation(libs.androidx.palette)
|
||||
runtimeOnly(libs.androidx.compose.ui)
|
||||
runtimeOnly(libs.androidx.compose.runtime)
|
||||
implementation(libs.androidx.compose.materialicons)
|
||||
|
||||
implementation(project(":core:ktx"))
|
||||
implementation(project(":core:i18n"))
|
||||
|
||||
@@ -0,0 +1,538 @@
|
||||
package de.mm20.launcher2.icons
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.materialIcon
|
||||
import androidx.compose.material.icons.materialPath
|
||||
import androidx.compose.ui.graphics.vector.group
|
||||
|
||||
val Icons.Rounded.Battery0Bar
|
||||
get() = materialIcon("Icons.Rounded.Battery0Bar") {
|
||||
materialPath {
|
||||
moveTo(17f, 5f)
|
||||
verticalLineToRelative(16f)
|
||||
curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f)
|
||||
horizontalLineTo(8f)
|
||||
curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f)
|
||||
verticalLineTo(5f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
verticalLineTo(3f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f)
|
||||
verticalLineToRelative(1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f)
|
||||
close()
|
||||
moveTo(15f, 6f)
|
||||
horizontalLineTo(9f)
|
||||
verticalLineToRelative(14f)
|
||||
horizontalLineToRelative(6f)
|
||||
verticalLineTo(6f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.Battery1Bar
|
||||
get() = materialIcon("Icons.Rounded.Battery1Bar") {
|
||||
materialPath {
|
||||
moveTo(17f, 5f)
|
||||
verticalLineToRelative(16f)
|
||||
curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f)
|
||||
horizontalLineTo(8f)
|
||||
curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f)
|
||||
verticalLineTo(5f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
verticalLineTo(3f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f)
|
||||
verticalLineToRelative(1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f)
|
||||
close()
|
||||
moveTo(15f, 6f)
|
||||
horizontalLineTo(9f)
|
||||
verticalLineToRelative(12f)
|
||||
horizontalLineToRelative(6f)
|
||||
verticalLineTo(6f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.Battery2Bar
|
||||
get() = materialIcon("Icons.Rounded.Battery2Bar") {
|
||||
materialPath {
|
||||
moveTo(17f, 5f)
|
||||
verticalLineToRelative(16f)
|
||||
curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f)
|
||||
horizontalLineTo(8f)
|
||||
curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f)
|
||||
verticalLineTo(5f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
verticalLineTo(3f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f)
|
||||
verticalLineToRelative(1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f)
|
||||
close()
|
||||
moveTo(15f, 6f)
|
||||
horizontalLineTo(9f)
|
||||
verticalLineToRelative(10f)
|
||||
horizontalLineToRelative(6f)
|
||||
verticalLineTo(6f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.Battery3Bar
|
||||
get() = materialIcon("Icons.Rounded.Battery3Bar") {
|
||||
materialPath {
|
||||
moveTo(17f, 5f)
|
||||
verticalLineToRelative(16f)
|
||||
curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f)
|
||||
horizontalLineTo(8f)
|
||||
curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f)
|
||||
verticalLineTo(5f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
verticalLineTo(3f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f)
|
||||
verticalLineToRelative(1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f)
|
||||
close()
|
||||
moveTo(15f, 6f)
|
||||
horizontalLineTo(9f)
|
||||
verticalLineToRelative(8f)
|
||||
horizontalLineToRelative(6f)
|
||||
verticalLineTo(6f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.Battery4Bar
|
||||
get() = materialIcon("Icons.Rounded.Battery4Bar") {
|
||||
materialPath {
|
||||
moveTo(17f, 5f)
|
||||
verticalLineToRelative(16f)
|
||||
curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f)
|
||||
horizontalLineTo(8f)
|
||||
curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f)
|
||||
verticalLineTo(5f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
verticalLineTo(3f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f)
|
||||
verticalLineToRelative(1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f)
|
||||
close()
|
||||
moveTo(15f, 6f)
|
||||
horizontalLineTo(9f)
|
||||
verticalLineToRelative(6f)
|
||||
horizontalLineToRelative(6f)
|
||||
verticalLineTo(6f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.Battery5Bar
|
||||
get() = materialIcon("Icons.Rounded.Battery5Bar") {
|
||||
materialPath {
|
||||
moveTo(17f, 5f)
|
||||
verticalLineToRelative(16f)
|
||||
curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f)
|
||||
horizontalLineTo(8f)
|
||||
curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f)
|
||||
verticalLineTo(5f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
verticalLineTo(3f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f)
|
||||
verticalLineToRelative(1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f)
|
||||
close()
|
||||
moveTo(15f, 6f)
|
||||
horizontalLineTo(9f)
|
||||
verticalLineToRelative(4f)
|
||||
horizontalLineToRelative(6f)
|
||||
verticalLineTo(6f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.Battery6Bar
|
||||
get() = materialIcon("Icons.Rounded.Battery6Bar") {
|
||||
materialPath {
|
||||
moveTo(17f, 5f)
|
||||
verticalLineToRelative(16f)
|
||||
curveToRelative(0f, 0.55f, -0.45f, 1f, -1f, 1f)
|
||||
horizontalLineTo(8f)
|
||||
curveToRelative(-0.55f, 0f, -1f, -0.45f, -1f, -1f)
|
||||
verticalLineTo(5f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
verticalLineTo(3f)
|
||||
curveToRelative(0f, -0.55f, 0.45f, -1f, 1f, -1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveToRelative(0.55f, 0f, 1f, 0.45f, 1f, 1f)
|
||||
verticalLineToRelative(1f)
|
||||
horizontalLineToRelative(2f)
|
||||
curveTo(16.55f, 4f, 17f, 4.45f, 17f, 5f)
|
||||
close()
|
||||
moveTo(15f, 6f)
|
||||
horizontalLineTo(9f)
|
||||
verticalLineToRelative(2f)
|
||||
horizontalLineToRelative(6f)
|
||||
verticalLineTo(6f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.BatteryCharging0Bar
|
||||
get() = materialIcon("Icons.Rounded.BatteryCharging0Bar") {
|
||||
group(
|
||||
scaleX = 0.26458333f,
|
||||
scaleY = 0.26458333f,
|
||||
) {
|
||||
materialPath {
|
||||
moveTo(41.574219f, 7.5585938f)
|
||||
curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f)
|
||||
lineTo(37.794922f, 15.117188f)
|
||||
lineTo(30.236328f, 15.117188f)
|
||||
curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f)
|
||||
lineTo(26.457031f, 79.369141f)
|
||||
curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f)
|
||||
lineTo(60.472656f, 83.150391f)
|
||||
curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f)
|
||||
lineTo(64.251953f, 18.898438f)
|
||||
curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f)
|
||||
lineTo(52.914062f, 15.117188f)
|
||||
lineTo(52.914062f, 11.337891f)
|
||||
curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f)
|
||||
lineTo(41.574219f, 7.5585938f)
|
||||
close()
|
||||
moveTo(34.015625f, 22.677734f)
|
||||
lineTo(56.693359f, 22.677734f)
|
||||
lineTo(56.693359f, 75.589844f)
|
||||
lineTo(34.015625f, 75.589844f)
|
||||
lineTo(34.015625f, 22.677734f)
|
||||
close()
|
||||
moveTo(47.253906f, 32.126953f)
|
||||
curveTo(46.605486f, 32.112843f, 45.950535f, 32.41843f, 45.582031f, 33.109375f)
|
||||
lineTo(35.490234f, 52.005859f)
|
||||
curveTo(34.809919f, 53.290899f, 35.716123f, 54.802734f, 37.152344f, 54.802734f)
|
||||
lineTo(41.574219f, 54.802734f)
|
||||
lineTo(41.574219f, 68.03125f)
|
||||
curveTo(41.574219f, 69.996604f, 44.219867f, 70.640241f, 45.126953f, 68.939453f)
|
||||
lineTo(55.21875f, 50.041016f)
|
||||
curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f)
|
||||
lineTo(49.134766f, 47.244141f)
|
||||
lineTo(49.134766f, 34.015625f)
|
||||
curveTo(49.134766f, 32.848696f, 48.201598f, 32.147575f, 47.253906f, 32.126953f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.BatteryCharging1Bar
|
||||
get() = materialIcon("Icons.Rounded.BatteryCharging1Bar") {
|
||||
group(
|
||||
scaleX = 0.26458333f,
|
||||
scaleY = 0.26458333f,
|
||||
) {
|
||||
materialPath {
|
||||
moveTo(41.574219f, 7.5585938f)
|
||||
curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f)
|
||||
lineTo(37.794922f, 15.117188f)
|
||||
lineTo(30.236328f, 15.117188f)
|
||||
curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f)
|
||||
lineTo(26.457031f, 79.369141f)
|
||||
curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f)
|
||||
lineTo(60.472656f, 83.150391f)
|
||||
curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f)
|
||||
lineTo(64.251953f, 18.898438f)
|
||||
curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f)
|
||||
lineTo(52.914062f, 15.117188f)
|
||||
lineTo(52.914062f, 11.337891f)
|
||||
curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f)
|
||||
lineTo(41.574219f, 7.5585938f)
|
||||
close()
|
||||
moveTo(34.015625f, 22.677734f)
|
||||
lineTo(56.693359f, 22.677734f)
|
||||
lineTo(56.693359f, 68.03125f)
|
||||
lineTo(45.611328f, 68.03125f)
|
||||
lineTo(45.126953f, 68.939453f)
|
||||
curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f)
|
||||
lineTo(34.015625f, 68.03125f)
|
||||
lineTo(34.015625f, 22.677734f)
|
||||
close()
|
||||
moveTo(41.574219f, 68.03125f)
|
||||
lineTo(45.611328f, 68.03125f)
|
||||
lineTo(55.21875f, 50.041016f)
|
||||
curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f)
|
||||
lineTo(49.134766f, 47.244141f)
|
||||
lineTo(49.134766f, 34.015625f)
|
||||
curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f)
|
||||
lineTo(35.490234f, 52.005859f)
|
||||
curveTo(34.809919f, 53.290899f, 35.716123f, 54.802734f, 37.152344f, 54.802734f)
|
||||
lineTo(41.574219f, 54.802734f)
|
||||
lineTo(41.574219f, 68.03125f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.BatteryCharging2Bar
|
||||
get() = materialIcon("Icons.Rounded.BatteryCharging2Bar") {
|
||||
group(
|
||||
scaleX = 0.26458333f,
|
||||
scaleY = 0.26458333f,
|
||||
) {
|
||||
materialPath {
|
||||
moveTo(41.574219f, 7.5585938f)
|
||||
curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f)
|
||||
lineTo(37.794922f, 15.117188f)
|
||||
lineTo(30.236328f, 15.117188f)
|
||||
curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f)
|
||||
lineTo(26.457031f, 79.369141f)
|
||||
curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f)
|
||||
lineTo(60.472656f, 83.150391f)
|
||||
curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f)
|
||||
lineTo(64.251953f, 18.898438f)
|
||||
curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f)
|
||||
lineTo(52.914062f, 15.117188f)
|
||||
lineTo(52.914062f, 11.337891f)
|
||||
curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f)
|
||||
lineTo(41.574219f, 7.5585938f)
|
||||
close()
|
||||
moveTo(34.015625f, 22.677734f)
|
||||
lineTo(56.693359f, 22.677734f)
|
||||
lineTo(56.693359f, 60.472656f)
|
||||
lineTo(49.648438f, 60.472656f)
|
||||
lineTo(45.126953f, 68.939453f)
|
||||
curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f)
|
||||
lineTo(41.574219f, 60.472656f)
|
||||
lineTo(34.015625f, 60.472656f)
|
||||
lineTo(34.015625f, 22.677734f)
|
||||
close()
|
||||
moveTo(41.574219f, 60.472656f)
|
||||
lineTo(49.648438f, 60.472656f)
|
||||
lineTo(55.21875f, 50.041016f)
|
||||
curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f)
|
||||
lineTo(49.134766f, 47.244141f)
|
||||
lineTo(49.134766f, 34.015625f)
|
||||
curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f)
|
||||
lineTo(35.490234f, 52.005859f)
|
||||
curveTo(34.809919f, 53.290899f, 35.716123f, 54.802734f, 37.152344f, 54.802734f)
|
||||
lineTo(41.574219f, 54.802734f)
|
||||
lineTo(41.574219f, 60.472656f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.BatteryCharging3Bar
|
||||
get() = materialIcon("Icons.Rounded.BatteryCharging3Bar") {
|
||||
group(
|
||||
scaleX = 0.26458333f,
|
||||
scaleY = 0.26458333f,
|
||||
) {
|
||||
materialPath {
|
||||
moveTo(41.574219f, 7.5585938f)
|
||||
curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f)
|
||||
lineTo(37.794922f, 15.117188f)
|
||||
lineTo(30.236328f, 15.117188f)
|
||||
curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f)
|
||||
lineTo(26.457031f, 79.369141f)
|
||||
curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f)
|
||||
lineTo(60.472656f, 83.150391f)
|
||||
curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f)
|
||||
lineTo(64.251953f, 18.898438f)
|
||||
curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f)
|
||||
lineTo(52.914062f, 15.117188f)
|
||||
lineTo(52.914062f, 11.337891f)
|
||||
curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f)
|
||||
lineTo(41.574219f, 7.5585938f)
|
||||
close()
|
||||
moveTo(34.015625f, 22.677734f)
|
||||
lineTo(56.693359f, 22.677734f)
|
||||
lineTo(56.693359f, 52.914062f)
|
||||
lineTo(53.683594f, 52.914062f)
|
||||
lineTo(45.126953f, 68.939453f)
|
||||
curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f)
|
||||
lineTo(41.574219f, 54.802734f)
|
||||
lineTo(37.152344f, 54.802734f)
|
||||
curveTo(36.048819f, 54.802734f, 35.258483f, 53.910469f, 35.259766f, 52.914062f)
|
||||
lineTo(34.015625f, 52.914062f)
|
||||
lineTo(34.015625f, 22.677734f)
|
||||
close()
|
||||
moveTo(35.259766f, 52.914062f)
|
||||
lineTo(53.683594f, 52.914062f)
|
||||
lineTo(55.21875f, 50.041016f)
|
||||
curveTo(55.899065f, 48.755976f, 54.955066f, 47.244141f, 53.556641f, 47.244141f)
|
||||
lineTo(49.134766f, 47.244141f)
|
||||
lineTo(49.134766f, 34.015625f)
|
||||
curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f)
|
||||
lineTo(35.490234f, 52.005859f)
|
||||
curveTo(35.332642f, 52.303535f, 35.260152f, 52.613661f, 35.259766f, 52.914062f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.BatteryCharging4Bar
|
||||
get() = materialIcon("Icons.Rounded.BatteryCharging4Bar") {
|
||||
group(
|
||||
scaleX = 0.26458333f,
|
||||
scaleY = 0.26458333f,
|
||||
) {
|
||||
materialPath {
|
||||
moveTo(41.574219f, 7.5585938f)
|
||||
curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f)
|
||||
lineTo(37.794922f, 15.117188f)
|
||||
lineTo(30.236328f, 15.117188f)
|
||||
curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f)
|
||||
lineTo(26.457031f, 79.369141f)
|
||||
curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f)
|
||||
lineTo(60.472656f, 83.150391f)
|
||||
curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f)
|
||||
lineTo(64.251953f, 18.898438f)
|
||||
curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f)
|
||||
lineTo(52.914062f, 15.117188f)
|
||||
lineTo(52.914062f, 11.337891f)
|
||||
curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f)
|
||||
lineTo(41.574219f, 7.5585938f)
|
||||
close()
|
||||
moveTo(34.015625f, 22.677734f)
|
||||
lineTo(56.693359f, 22.677734f)
|
||||
lineTo(56.693359f, 45.353516f)
|
||||
lineTo(49.134766f, 45.353516f)
|
||||
lineTo(49.134766f, 47.244141f)
|
||||
lineTo(53.556641f, 47.244141f)
|
||||
curveTo(54.955066f, 47.244141f, 55.899065f, 48.755976f, 55.21875f, 50.041016f)
|
||||
lineTo(45.126953f, 68.939453f)
|
||||
curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f)
|
||||
lineTo(41.574219f, 54.802734f)
|
||||
lineTo(37.152344f, 54.802734f)
|
||||
curveTo(35.716123f, 54.802734f, 34.809919f, 53.290899f, 35.490234f, 52.005859f)
|
||||
lineTo(39.042969f, 45.353516f)
|
||||
lineTo(34.015625f, 45.353516f)
|
||||
lineTo(34.015625f, 22.677734f)
|
||||
close()
|
||||
moveTo(39.042969f, 45.353516f)
|
||||
lineTo(49.134766f, 45.353516f)
|
||||
lineTo(49.134766f, 34.015625f)
|
||||
curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f)
|
||||
lineTo(39.042969f, 45.353516f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.BatteryCharging5Bar
|
||||
get() = materialIcon("Icons.Rounded.BatteryCharging5Bar") {
|
||||
group(
|
||||
scaleX = 0.26458333f,
|
||||
scaleY = 0.26458333f,
|
||||
) {
|
||||
materialPath {
|
||||
moveTo(41.574219f, 7.5585938f)
|
||||
curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f)
|
||||
lineTo(37.794922f, 15.117188f)
|
||||
lineTo(30.236328f, 15.117188f)
|
||||
curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f)
|
||||
lineTo(26.457031f, 79.369141f)
|
||||
curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f)
|
||||
lineTo(60.472656f, 83.150391f)
|
||||
curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f)
|
||||
lineTo(64.251953f, 18.898438f)
|
||||
curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f)
|
||||
lineTo(52.914062f, 15.117188f)
|
||||
lineTo(52.914062f, 11.337891f)
|
||||
curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f)
|
||||
lineTo(41.574219f, 7.5585938f)
|
||||
close()
|
||||
moveTo(34.015625f, 22.677734f)
|
||||
lineTo(56.693359f, 22.677734f)
|
||||
lineTo(56.693359f, 37.794922f)
|
||||
lineTo(49.134766f, 37.794922f)
|
||||
lineTo(49.134766f, 47.244141f)
|
||||
lineTo(53.556641f, 47.244141f)
|
||||
curveTo(54.955066f, 47.244141f, 55.899065f, 48.755976f, 55.21875f, 50.041016f)
|
||||
lineTo(45.126953f, 68.939453f)
|
||||
curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f)
|
||||
lineTo(41.574219f, 54.802734f)
|
||||
lineTo(37.152344f, 54.802734f)
|
||||
curveTo(35.716123f, 54.802734f, 34.809919f, 53.290899f, 35.490234f, 52.005859f)
|
||||
lineTo(43.080078f, 37.794922f)
|
||||
lineTo(34.015625f, 37.794922f)
|
||||
lineTo(34.015625f, 22.677734f)
|
||||
close()
|
||||
moveTo(43.080078f, 37.794922f)
|
||||
lineTo(49.134766f, 37.794922f)
|
||||
lineTo(49.134766f, 34.015625f)
|
||||
curveTo(49.134766f, 32.050271f, 46.489118f, 31.408588f, 45.582031f, 33.109375f)
|
||||
lineTo(43.080078f, 37.794922f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Icons.Rounded.BatteryCharging6Bar
|
||||
get() = materialIcon("Icons.Rounded.BatteryCharging6Bar") {
|
||||
group(
|
||||
scaleX = 0.26458333f,
|
||||
scaleY = 0.26458333f,
|
||||
) {
|
||||
materialPath {
|
||||
moveTo(41.574219f, 7.5585938f)
|
||||
curveTo(39.495479f, 7.5585937f, 37.794922f, 9.2591505f, 37.794922f, 11.337891f)
|
||||
lineTo(37.794922f, 15.117188f)
|
||||
lineTo(30.236328f, 15.117188f)
|
||||
curveTo(28.157588f, 15.117187f, 26.457031f, 16.819697f, 26.457031f, 18.898438f)
|
||||
lineTo(26.457031f, 79.369141f)
|
||||
curveTo(26.457031f, 81.447881f, 28.157588f, 83.150391f, 30.236328f, 83.150391f)
|
||||
lineTo(60.472656f, 83.150391f)
|
||||
curveTo(62.551396f, 83.150391f, 64.251953f, 81.447881f, 64.251953f, 79.369141f)
|
||||
lineTo(64.251953f, 18.898438f)
|
||||
curveTo(64.251953f, 16.819697f, 62.551396f, 15.117188f, 60.472656f, 15.117188f)
|
||||
lineTo(52.914062f, 15.117188f)
|
||||
lineTo(52.914062f, 11.337891f)
|
||||
curveTo(52.914063f, 9.2591505f, 51.213506f, 7.5585938f, 49.134766f, 7.5585938f)
|
||||
lineTo(41.574219f, 7.5585938f)
|
||||
close()
|
||||
moveTo(34.015625f, 22.677734f)
|
||||
lineTo(56.693359f, 22.677734f)
|
||||
lineTo(56.693359f, 30.236328f)
|
||||
lineTo(34.015625f, 30.236328f)
|
||||
lineTo(34.015625f, 22.677734f)
|
||||
close()
|
||||
moveTo(47.253906f, 32.126953f)
|
||||
curveTo(48.201598f, 32.147575f, 49.134766f, 32.848696f, 49.134766f, 34.015625f)
|
||||
lineTo(49.134766f, 47.244141f)
|
||||
lineTo(53.556641f, 47.244141f)
|
||||
curveTo(54.955066f, 47.244141f, 55.899065f, 48.755976f, 55.21875f, 50.041016f)
|
||||
lineTo(45.126953f, 68.939453f)
|
||||
curveTo(44.219867f, 70.640241f, 41.574219f, 69.996604f, 41.574219f, 68.03125f)
|
||||
lineTo(41.574219f, 54.802734f)
|
||||
lineTo(37.152344f, 54.802734f)
|
||||
curveTo(35.716123f, 54.802734f, 34.809919f, 53.290899f, 35.490234f, 52.005859f)
|
||||
lineTo(45.582031f, 33.109375f)
|
||||
curveTo(45.950535f, 32.41843f, 46.605486f, 32.112843f, 47.253906f, 32.126953f)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
package de.mm20.launcher2.icons
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
sealed interface LauncherIconLayer
|
||||
|
||||
@@ -53,4 +54,9 @@ data class TextLayer(
|
||||
val color: Int = 0,
|
||||
) : LauncherIconLayer
|
||||
|
||||
data class VectorLayer(
|
||||
val vector: ImageVector,
|
||||
val color: Int = 0,
|
||||
) : LauncherIconLayer
|
||||
|
||||
object TransparentLayer: LauncherIconLayer
|
||||
@@ -1,9 +1,11 @@
|
||||
package de.mm20.launcher2.plugin
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import de.mm20.launcher2.plugin.config.SearchPluginConfig
|
||||
import de.mm20.launcher2.plugin.config.QueryPluginConfig
|
||||
import de.mm20.launcher2.plugin.config.WeatherPluginConfig
|
||||
import de.mm20.launcher2.plugin.contracts.PluginContract
|
||||
|
||||
@@ -11,7 +13,25 @@ class PluginApi(
|
||||
private val pluginAuthority: String,
|
||||
private val contentResolver: ContentResolver,
|
||||
) {
|
||||
fun getSearchPluginConfig(): SearchPluginConfig? {
|
||||
fun getConfig(): Bundle? {
|
||||
val configBundle = try {
|
||||
contentResolver.call(
|
||||
Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(pluginAuthority)
|
||||
.build(),
|
||||
PluginContract.Methods.GetConfig,
|
||||
null,
|
||||
null
|
||||
) ?: return null
|
||||
} catch (e: Exception) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority threw exception", e)
|
||||
return null
|
||||
}
|
||||
return configBundle
|
||||
}
|
||||
|
||||
fun getSearchPluginConfig(): QueryPluginConfig? {
|
||||
val configBundle = try {
|
||||
contentResolver.call(
|
||||
Uri.Builder()
|
||||
@@ -27,7 +47,7 @@ class PluginApi(
|
||||
return null
|
||||
}
|
||||
|
||||
return SearchPluginConfig(configBundle)
|
||||
return QueryPluginConfig(configBundle)
|
||||
}
|
||||
|
||||
fun getWeatherPluginConfig(): WeatherPluginConfig? {
|
||||
|
||||
@@ -10,7 +10,7 @@ data class PluginPackage(
|
||||
val author: String? = null,
|
||||
val settings: Intent? = null,
|
||||
val plugins: List<Plugin>,
|
||||
val isOfficial: Boolean = false,
|
||||
val isVerified: Boolean = false,
|
||||
) {
|
||||
val enabled: Boolean = plugins.all { it.enabled }
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package de.mm20.launcher2.plugin
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.CancellationSignal
|
||||
import android.util.Log
|
||||
import de.mm20.launcher2.plugin.config.QueryPluginConfig
|
||||
import de.mm20.launcher2.plugin.contracts.LocationPluginContract
|
||||
import de.mm20.launcher2.plugin.contracts.PluginContract
|
||||
import de.mm20.launcher2.plugin.contracts.SearchPluginContract
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
private class NotUpdated : Exception("Not updated")
|
||||
|
||||
abstract class QueryPluginApi<TQuery, TResult>(
|
||||
private val context: Context,
|
||||
private val pluginAuthority: String,
|
||||
) {
|
||||
private fun getLanguage() = context.resources.configuration.locales[0].language
|
||||
|
||||
fun getConfig(): QueryPluginConfig? {
|
||||
val configBundle = try {
|
||||
context.contentResolver.call(
|
||||
Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(pluginAuthority)
|
||||
.build(),
|
||||
PluginContract.Methods.GetConfig,
|
||||
null,
|
||||
null
|
||||
) ?: return null
|
||||
} catch (e: Exception) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority threw exception", e)
|
||||
return null
|
||||
}
|
||||
return QueryPluginConfig(configBundle)
|
||||
}
|
||||
|
||||
suspend fun search(query: TQuery, allowNetwork: Boolean): List<TResult> = withContext(Dispatchers.IO) {
|
||||
val lang = getLanguage()
|
||||
val uri = Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(pluginAuthority)
|
||||
.path(LocationPluginContract.Paths.Search)
|
||||
.appendQueryParameters(query)
|
||||
.appendQueryParameter(
|
||||
SearchPluginContract.Params.AllowNetwork,
|
||||
allowNetwork.toString()
|
||||
)
|
||||
.appendQueryParameter(
|
||||
SearchPluginContract.Params.Lang,
|
||||
lang
|
||||
)
|
||||
.build()
|
||||
val cancellationSignal = CancellationSignal()
|
||||
|
||||
return@withContext suspendCancellableCoroutine {
|
||||
it.invokeOnCancellation {
|
||||
cancellationSignal.cancel()
|
||||
}
|
||||
val cursor = try {
|
||||
context.contentResolver.query(
|
||||
uri,
|
||||
null,
|
||||
null,
|
||||
cancellationSignal
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority threw exception", e)
|
||||
it.resume(emptyList())
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
if (cursor == null) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority returned null cursor")
|
||||
it.resume(emptyList())
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
val results = cursor.getData() ?: emptyList()
|
||||
it.resume(results)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun get(id: String): Result<TResult?> = withContext(Dispatchers.IO) {
|
||||
val uri = Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(pluginAuthority)
|
||||
.path(SearchPluginContract.Paths.Root)
|
||||
.appendPath(id)
|
||||
.appendQueryParameter(SearchPluginContract.Params.Lang, getLanguage())
|
||||
.build()
|
||||
|
||||
val cancellationSignal = CancellationSignal()
|
||||
|
||||
return@withContext suspendCancellableCoroutine {
|
||||
it.invokeOnCancellation {
|
||||
cancellationSignal.cancel()
|
||||
}
|
||||
val cursor = try {
|
||||
context.contentResolver.query(
|
||||
uri,
|
||||
null,
|
||||
null,
|
||||
cancellationSignal
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority threw exception", e)
|
||||
it.resume(Result.failure(e))
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
if (cursor == null) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority returned null cursor")
|
||||
it.resume(Result.success(null))
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
val result = cursor.getData()?.firstOrNull()
|
||||
|
||||
if (result == null) {
|
||||
it.resume(Result.success(null))
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
it.resume(Result.success(result))
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun refresh(item: TResult, lastUpdate: Long): Result<TResult?> = withContext(Dispatchers.IO) {
|
||||
val uri = Uri.Builder()
|
||||
.scheme("content")
|
||||
.authority(pluginAuthority)
|
||||
.path(SearchPluginContract.Paths.Refresh)
|
||||
.appendQueryParameter(SearchPluginContract.Params.Lang, getLanguage())
|
||||
.appendQueryParameter(SearchPluginContract.Params.UpdatedAt, lastUpdate.toString())
|
||||
.build()
|
||||
|
||||
val cancellationSignal = CancellationSignal()
|
||||
|
||||
return@withContext suspendCancellableCoroutine {
|
||||
it.invokeOnCancellation {
|
||||
cancellationSignal.cancel()
|
||||
}
|
||||
val cursor = try {
|
||||
context.contentResolver.query(
|
||||
uri,
|
||||
null,
|
||||
item.toBundle(),
|
||||
cancellationSignal
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority threw exception", e)
|
||||
it.resume(Result.failure(e))
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
if (cursor == null) {
|
||||
Log.e("MM20", "Plugin $pluginAuthority returned null cursor")
|
||||
it.resume(Result.failure(IllegalArgumentException()))
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
if (cursor.extras?.getBoolean(SearchPluginContract.Extras.NotUpdated) == true) {
|
||||
it.resume(Result.failure(NotUpdated()))
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
val result = cursor.getData()?.firstOrNull()
|
||||
|
||||
if (result == null) {
|
||||
it.resume(Result.success(null))
|
||||
return@suspendCancellableCoroutine
|
||||
}
|
||||
|
||||
it.resume(Result.success(result))
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun Uri.Builder.appendQueryParameters(query: TQuery): Uri.Builder
|
||||
|
||||
protected abstract fun Cursor.getData(): List<TResult>?
|
||||
|
||||
protected abstract fun TResult.toBundle(): Bundle
|
||||
}
|
||||
@@ -2,8 +2,8 @@ package de.mm20.launcher2.plugin.config
|
||||
|
||||
import android.os.Bundle
|
||||
|
||||
fun SearchPluginConfig(bundle: Bundle): SearchPluginConfig? {
|
||||
return SearchPluginConfig(
|
||||
fun QueryPluginConfig(bundle: Bundle): QueryPluginConfig {
|
||||
return QueryPluginConfig(
|
||||
storageStrategy = valueOfOrElse(
|
||||
bundle.getString(
|
||||
"storageStrategy",
|
||||
|
||||
@@ -1,16 +1,135 @@
|
||||
package de.mm20.launcher2.search
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.rounded.DirectionsBike
|
||||
import androidx.compose.material.icons.rounded.AccountBalance
|
||||
import androidx.compose.material.icons.rounded.AttachMoney
|
||||
import androidx.compose.material.icons.rounded.Attractions
|
||||
import androidx.compose.material.icons.rounded.BakeryDining
|
||||
import androidx.compose.material.icons.rounded.Bed
|
||||
import androidx.compose.material.icons.rounded.Bento
|
||||
import androidx.compose.material.icons.rounded.Book
|
||||
import androidx.compose.material.icons.rounded.BreakfastDining
|
||||
import androidx.compose.material.icons.rounded.BrunchDining
|
||||
import androidx.compose.material.icons.rounded.CarRental
|
||||
import androidx.compose.material.icons.rounded.CarRepair
|
||||
import androidx.compose.material.icons.rounded.Casino
|
||||
import androidx.compose.material.icons.rounded.Checkroom
|
||||
import androidx.compose.material.icons.rounded.Church
|
||||
import androidx.compose.material.icons.rounded.ContentCut
|
||||
import androidx.compose.material.icons.rounded.Diamond
|
||||
import androidx.compose.material.icons.rounded.DirectionsBoat
|
||||
import androidx.compose.material.icons.rounded.DirectionsBus
|
||||
import androidx.compose.material.icons.rounded.DirectionsCar
|
||||
import androidx.compose.material.icons.rounded.DirectionsTransit
|
||||
import androidx.compose.material.icons.rounded.Discount
|
||||
import androidx.compose.material.icons.rounded.DownhillSkiing
|
||||
import androidx.compose.material.icons.rounded.ElectricScooter
|
||||
import androidx.compose.material.icons.rounded.EvStation
|
||||
import androidx.compose.material.icons.rounded.Fastfood
|
||||
import androidx.compose.material.icons.rounded.Festival
|
||||
import androidx.compose.material.icons.rounded.FitnessCenter
|
||||
import androidx.compose.material.icons.rounded.Flight
|
||||
import androidx.compose.material.icons.rounded.Forest
|
||||
import androidx.compose.material.icons.rounded.Gavel
|
||||
import androidx.compose.material.icons.rounded.Hiking
|
||||
import androidx.compose.material.icons.rounded.Hotel
|
||||
import androidx.compose.material.icons.rounded.Icecream
|
||||
import androidx.compose.material.icons.rounded.Kayaking
|
||||
import androidx.compose.material.icons.rounded.KebabDining
|
||||
import androidx.compose.material.icons.rounded.Liquor
|
||||
import androidx.compose.material.icons.rounded.LocalAtm
|
||||
import androidx.compose.material.icons.rounded.LocalBar
|
||||
import androidx.compose.material.icons.rounded.LocalCafe
|
||||
import androidx.compose.material.icons.rounded.LocalCarWash
|
||||
import androidx.compose.material.icons.rounded.LocalConvenienceStore
|
||||
import androidx.compose.material.icons.rounded.LocalFireDepartment
|
||||
import androidx.compose.material.icons.rounded.LocalFlorist
|
||||
import androidx.compose.material.icons.rounded.LocalGasStation
|
||||
import androidx.compose.material.icons.rounded.LocalGroceryStore
|
||||
import androidx.compose.material.icons.rounded.LocalHospital
|
||||
import androidx.compose.material.icons.rounded.LocalLaundryService
|
||||
import androidx.compose.material.icons.rounded.LocalMall
|
||||
import androidx.compose.material.icons.rounded.LocalParking
|
||||
import androidx.compose.material.icons.rounded.LocalPharmacy
|
||||
import androidx.compose.material.icons.rounded.LocalPizza
|
||||
import androidx.compose.material.icons.rounded.LocalPolice
|
||||
import androidx.compose.material.icons.rounded.LocalPostOffice
|
||||
import androidx.compose.material.icons.rounded.LocalTaxi
|
||||
import androidx.compose.material.icons.rounded.LunchDining
|
||||
import androidx.compose.material.icons.rounded.Moped
|
||||
import androidx.compose.material.icons.rounded.Mosque
|
||||
import androidx.compose.material.icons.rounded.Motorcycle
|
||||
import androidx.compose.material.icons.rounded.Museum
|
||||
import androidx.compose.material.icons.rounded.MusicNote
|
||||
import androidx.compose.material.icons.rounded.Newspaper
|
||||
import androidx.compose.material.icons.rounded.Nightlife
|
||||
import androidx.compose.material.icons.rounded.NordicWalking
|
||||
import androidx.compose.material.icons.rounded.Palette
|
||||
import androidx.compose.material.icons.rounded.Paragliding
|
||||
import androidx.compose.material.icons.rounded.Park
|
||||
import androidx.compose.material.icons.rounded.Pets
|
||||
import androidx.compose.material.icons.rounded.Phone
|
||||
import androidx.compose.material.icons.rounded.Place
|
||||
import androidx.compose.material.icons.rounded.Pool
|
||||
import androidx.compose.material.icons.rounded.RamenDining
|
||||
import androidx.compose.material.icons.rounded.Restaurant
|
||||
import androidx.compose.material.icons.rounded.School
|
||||
import androidx.compose.material.icons.rounded.ShoppingBag
|
||||
import androidx.compose.material.icons.rounded.Skateboarding
|
||||
import androidx.compose.material.icons.rounded.Snowboarding
|
||||
import androidx.compose.material.icons.rounded.SoupKitchen
|
||||
import androidx.compose.material.icons.rounded.Sports
|
||||
import androidx.compose.material.icons.rounded.SportsBar
|
||||
import androidx.compose.material.icons.rounded.SportsBaseball
|
||||
import androidx.compose.material.icons.rounded.SportsBasketball
|
||||
import androidx.compose.material.icons.rounded.SportsCricket
|
||||
import androidx.compose.material.icons.rounded.SportsFootball
|
||||
import androidx.compose.material.icons.rounded.SportsGolf
|
||||
import androidx.compose.material.icons.rounded.SportsGymnastics
|
||||
import androidx.compose.material.icons.rounded.SportsHandball
|
||||
import androidx.compose.material.icons.rounded.SportsHockey
|
||||
import androidx.compose.material.icons.rounded.SportsMartialArts
|
||||
import androidx.compose.material.icons.rounded.SportsMotorsports
|
||||
import androidx.compose.material.icons.rounded.SportsRugby
|
||||
import androidx.compose.material.icons.rounded.SportsSoccer
|
||||
import androidx.compose.material.icons.rounded.SportsTennis
|
||||
import androidx.compose.material.icons.rounded.SportsVolleyball
|
||||
import androidx.compose.material.icons.rounded.Stadium
|
||||
import androidx.compose.material.icons.rounded.Subway
|
||||
import androidx.compose.material.icons.rounded.Surfing
|
||||
import androidx.compose.material.icons.rounded.Synagogue
|
||||
import androidx.compose.material.icons.rounded.TakeoutDining
|
||||
import androidx.compose.material.icons.rounded.TempleBuddhist
|
||||
import androidx.compose.material.icons.rounded.TempleHindu
|
||||
import androidx.compose.material.icons.rounded.TheaterComedy
|
||||
import androidx.compose.material.icons.rounded.Theaters
|
||||
import androidx.compose.material.icons.rounded.Train
|
||||
import androidx.compose.material.icons.rounded.Tram
|
||||
import androidx.compose.material.icons.rounded.Wc
|
||||
import androidx.core.content.ContextCompat
|
||||
import de.mm20.launcher2.base.R
|
||||
import de.mm20.launcher2.icons.CableCar
|
||||
import de.mm20.launcher2.icons.Candle
|
||||
import de.mm20.launcher2.icons.ColorLayer
|
||||
import de.mm20.launcher2.icons.Dentistry
|
||||
import de.mm20.launcher2.icons.Eyeglasses
|
||||
import de.mm20.launcher2.icons.Monument
|
||||
import de.mm20.launcher2.icons.StaticLauncherIcon
|
||||
import de.mm20.launcher2.icons.TintedIconLayer
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import java.time.DayOfWeek
|
||||
import java.time.Duration
|
||||
import de.mm20.launcher2.icons.Stethoscope
|
||||
import de.mm20.launcher2.icons.VectorLayer
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.search.location.Address
|
||||
import de.mm20.launcher2.search.location.Attribution
|
||||
import de.mm20.launcher2.search.location.Departure
|
||||
import de.mm20.launcher2.search.location.LocationIcon
|
||||
import de.mm20.launcher2.search.location.OpeningHours
|
||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.temporal.TemporalAdjusters
|
||||
import android.location.Location as AndroidLocation
|
||||
|
||||
@@ -20,128 +139,182 @@ interface Location : SavableSearchable {
|
||||
val longitude: Double
|
||||
val fixMeUrl: String?
|
||||
|
||||
val category: LocationCategory?
|
||||
val icon: LocationIcon?
|
||||
val category: String?
|
||||
|
||||
val address: Address?
|
||||
|
||||
val street: String?
|
||||
val houseNumber: String?
|
||||
val openingSchedule: OpeningSchedule?
|
||||
val websiteUrl: String?
|
||||
val phoneNumber: String?
|
||||
val emailAddress: String?
|
||||
|
||||
val userRating: Float?
|
||||
val userRatingCount: Int?
|
||||
|
||||
val openingSchedule: OpeningSchedule?
|
||||
val departures: List<Departure>?
|
||||
|
||||
val attribution: Attribution?
|
||||
get() = null
|
||||
|
||||
override val preferDetailsOverLaunch: Boolean
|
||||
get() = true
|
||||
|
||||
override fun launch(context: Context, options: Bundle?): Boolean {
|
||||
return context.tryStartActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("geo:$latitude,$longitude?q=${Uri.encode(label)}")
|
||||
),
|
||||
options
|
||||
)
|
||||
}
|
||||
|
||||
override fun getPlaceholderIcon(context: Context): StaticLauncherIcon {
|
||||
val (resId, bgColor) = when (category) {
|
||||
LocationCategory.FAST_FOOD, LocationCategory.RESTAURANT -> with(
|
||||
labelOverride ?: label
|
||||
) {
|
||||
when {
|
||||
contains(
|
||||
"pizza",
|
||||
ignoreCase = true
|
||||
) -> R.drawable.ic_location_pizza to R.color.red
|
||||
val (vector, bgColor) = when (icon) {
|
||||
// blue: transportation
|
||||
LocationIcon.Car -> Icons.Rounded.DirectionsCar to R.color.blue
|
||||
LocationIcon.CarRental -> Icons.Rounded.CarRental to R.color.blue
|
||||
LocationIcon.CarRepair -> Icons.Rounded.CarRepair to R.color.blue
|
||||
LocationIcon.CarWash -> Icons.Rounded.LocalCarWash to R.color.blue
|
||||
LocationIcon.ChargingStation -> Icons.Rounded.EvStation to R.color.blue
|
||||
LocationIcon.GasStation -> Icons.Rounded.LocalGasStation to R.color.blue
|
||||
LocationIcon.Parking -> Icons.Rounded.LocalParking to R.color.blue
|
||||
LocationIcon.Bus -> Icons.Rounded.DirectionsBus to R.color.blue
|
||||
LocationIcon.Tram -> Icons.Rounded.Tram to R.color.blue
|
||||
LocationIcon.Subway -> Icons.Rounded.Subway to R.color.blue
|
||||
LocationIcon.Train -> Icons.Rounded.Train to R.color.blue
|
||||
LocationIcon.CableCar -> Icons.Rounded.CableCar to R.color.blue
|
||||
LocationIcon.Airport -> Icons.Rounded.Flight to R.color.blue
|
||||
LocationIcon.Boat -> Icons.Rounded.DirectionsBoat to R.color.blue
|
||||
LocationIcon.Moped -> Icons.Rounded.Moped to R.color.blue
|
||||
LocationIcon.Bike -> Icons.AutoMirrored.Rounded.DirectionsBike to R.color.blue
|
||||
LocationIcon.Motorcycle -> Icons.Rounded.Motorcycle to R.color.blue
|
||||
LocationIcon.ElectricScooter -> Icons.Rounded.ElectricScooter to R.color.blue
|
||||
LocationIcon.Taxi -> Icons.Rounded.LocalTaxi to R.color.blue
|
||||
LocationIcon.GenericTransit -> Icons.Rounded.DirectionsTransit to R.color.blue
|
||||
|
||||
contains(
|
||||
"ramen",
|
||||
ignoreCase = true
|
||||
) -> R.drawable.ic_location_ramen to R.color.orange
|
||||
// cyan: art, culture, entertainment
|
||||
LocationIcon.ArtGallery -> Icons.Rounded.Palette to R.color.cyan
|
||||
LocationIcon.Museum -> Icons.Rounded.Museum to R.color.cyan
|
||||
LocationIcon.Theater -> Icons.Rounded.TheaterComedy to R.color.cyan
|
||||
LocationIcon.MovieTheater -> Icons.Rounded.Theaters to R.color.cyan
|
||||
LocationIcon.AmusementPark -> Icons.Rounded.Attractions to R.color.cyan
|
||||
LocationIcon.NightClub -> Icons.Rounded.Nightlife to R.color.cyan
|
||||
LocationIcon.ConcertHall -> Icons.Rounded.MusicNote to R.color.cyan
|
||||
LocationIcon.Stadium -> Icons.Rounded.Stadium to R.color.cyan
|
||||
LocationIcon.Casino -> Icons.Rounded.Casino to R.color.cyan
|
||||
LocationIcon.Circus -> Icons.Rounded.Festival to R.color.cyan
|
||||
// pink: hotels
|
||||
LocationIcon.Hotel -> Icons.Rounded.Hotel to R.color.pink
|
||||
// orange: food and drink
|
||||
LocationIcon.Restaurant -> Icons.Rounded.Restaurant to R.color.orange
|
||||
LocationIcon.Cafe -> Icons.Rounded.LocalCafe to R.color.orange
|
||||
LocationIcon.FastFood -> Icons.Rounded.Fastfood to R.color.orange
|
||||
LocationIcon.Pizza -> Icons.Rounded.LocalPizza to R.color.orange
|
||||
LocationIcon.Burger -> Icons.Rounded.LunchDining to R.color.orange
|
||||
LocationIcon.Kebab -> Icons.Rounded.KebabDining to R.color.orange
|
||||
LocationIcon.IceCream -> Icons.Rounded.Icecream to R.color.orange
|
||||
LocationIcon.Ramen -> Icons.Rounded.RamenDining to R.color.orange
|
||||
LocationIcon.Soup -> Icons.Rounded.SoupKitchen to R.color.orange
|
||||
LocationIcon.Bar -> Icons.Rounded.LocalBar to R.color.orange
|
||||
LocationIcon.Brunch -> Icons.Rounded.BrunchDining to R.color.orange
|
||||
LocationIcon.Breakfast -> Icons.Rounded.BreakfastDining to R.color.orange
|
||||
LocationIcon.Pub -> Icons.Rounded.SportsBar to R.color.orange
|
||||
LocationIcon.JapaneseCuisine -> Icons.Rounded.Bento to R.color.orange
|
||||
LocationIcon.AsianCuisine -> Icons.Rounded.TakeoutDining to R.color.orange
|
||||
// indigo: business and shopping
|
||||
LocationIcon.Shopping -> Icons.Rounded.ShoppingBag to R.color.indigo
|
||||
LocationIcon.Supermarket -> Icons.Rounded.LocalGroceryStore to R.color.indigo
|
||||
LocationIcon.Florist -> Icons.Rounded.LocalFlorist to R.color.indigo
|
||||
LocationIcon.Kiosk -> Icons.Rounded.Newspaper to R.color.indigo
|
||||
LocationIcon.FurnitureStore -> Icons.Rounded.Bed to R.color.indigo
|
||||
LocationIcon.CellPhoneStore -> Icons.Rounded.Phone to R.color.indigo
|
||||
LocationIcon.BookStore -> Icons.Rounded.Book to R.color.indigo
|
||||
LocationIcon.ClothingStore -> Icons.Rounded.Checkroom to R.color.indigo
|
||||
LocationIcon.ConvenienceStore -> Icons.Rounded.LocalConvenienceStore to R.color.indigo
|
||||
LocationIcon.DiscountStore -> Icons.Rounded.Discount to R.color.indigo
|
||||
LocationIcon.JewelryStore -> Icons.Rounded.Diamond to R.color.indigo
|
||||
LocationIcon.ShoppingMall -> Icons.Rounded.LocalMall to R.color.indigo
|
||||
LocationIcon.LiquorStore -> Icons.Rounded.Liquor to R.color.indigo
|
||||
LocationIcon.PetStore -> Icons.Rounded.Pets to R.color.indigo
|
||||
LocationIcon.Bakery -> Icons.Rounded.BakeryDining to R.color.indigo
|
||||
LocationIcon.Optician -> Icons.Rounded.Eyeglasses to R.color.indigo
|
||||
LocationIcon.Pharmacy -> Icons.Rounded.LocalPharmacy to R.color.indigo
|
||||
LocationIcon.HairSalon -> Icons.Rounded.ContentCut to R.color.indigo
|
||||
LocationIcon.Laundromat -> Icons.Rounded.LocalLaundryService to R.color.indigo
|
||||
// purple: sports and recreation
|
||||
LocationIcon.Sports -> Icons.Rounded.Sports to R.color.purple
|
||||
LocationIcon.FitnessCenter -> Icons.Rounded.FitnessCenter to R.color.purple
|
||||
LocationIcon.Soccer -> Icons.Rounded.SportsSoccer to R.color.purple
|
||||
LocationIcon.Basketball -> Icons.Rounded.SportsBasketball to R.color.purple
|
||||
LocationIcon.Golf -> Icons.Rounded.SportsGolf to R.color.purple
|
||||
LocationIcon.Tennis -> Icons.Rounded.SportsTennis to R.color.purple
|
||||
LocationIcon.Baseball -> Icons.Rounded.SportsBaseball to R.color.purple
|
||||
LocationIcon.Rugby -> Icons.Rounded.SportsRugby to R.color.purple
|
||||
LocationIcon.AmericanFootball -> Icons.Rounded.SportsFootball to R.color.purple
|
||||
LocationIcon.Hiking -> Icons.Rounded.Hiking to R.color.purple
|
||||
LocationIcon.Swimming -> Icons.Rounded.Pool to R.color.purple
|
||||
LocationIcon.Surfing -> Icons.Rounded.Surfing to R.color.purple
|
||||
LocationIcon.Motorsports -> Icons.Rounded.SportsMotorsports to R.color.purple
|
||||
LocationIcon.Handball -> Icons.Rounded.SportsHandball to R.color.purple
|
||||
LocationIcon.Volleyball -> Icons.Rounded.SportsVolleyball to R.color.purple
|
||||
LocationIcon.Skiing -> Icons.Rounded.DownhillSkiing to R.color.purple
|
||||
LocationIcon.Kayaking -> Icons.Rounded.Kayaking to R.color.purple
|
||||
LocationIcon.Skateboarding -> Icons.Rounded.Skateboarding to R.color.purple
|
||||
LocationIcon.Cricket -> Icons.Rounded.SportsCricket to R.color.purple
|
||||
LocationIcon.MartialArts -> Icons.Rounded.SportsMartialArts to R.color.purple
|
||||
LocationIcon.NordicWalking -> Icons.Rounded.NordicWalking to R.color.purple
|
||||
LocationIcon.Paragliding -> Icons.Rounded.Paragliding to R.color.purple
|
||||
LocationIcon.Gymnastics -> Icons.Rounded.SportsGymnastics to R.color.purple
|
||||
LocationIcon.Snowboarding -> Icons.Rounded.Snowboarding to R.color.purple
|
||||
LocationIcon.Hockey -> Icons.Rounded.SportsHockey to R.color.purple
|
||||
// green: finances
|
||||
LocationIcon.Bank -> Icons.Rounded.AttachMoney to R.color.green
|
||||
LocationIcon.Atm -> Icons.Rounded.LocalAtm to R.color.green
|
||||
// red: health
|
||||
LocationIcon.Hospital -> Icons.Rounded.LocalHospital to R.color.red
|
||||
LocationIcon.Clinic -> Icons.Rounded.LocalHospital to R.color.red
|
||||
LocationIcon.Dentist -> Icons.Rounded.Dentistry to R.color.red
|
||||
LocationIcon.Physician -> Icons.Rounded.Stethoscope to R.color.red
|
||||
// light green: nature
|
||||
LocationIcon.Park -> Icons.Rounded.Park to R.color.lightgreen
|
||||
LocationIcon.Forest -> Icons.Rounded.Forest to R.color.lightgreen
|
||||
// brown: places of worship and remembrance
|
||||
LocationIcon.Monument -> Icons.Rounded.Monument to R.color.brown
|
||||
LocationIcon.Church -> Icons.Rounded.Church to R.color.brown
|
||||
LocationIcon.Mosque -> Icons.Rounded.Mosque to R.color.brown
|
||||
LocationIcon.Synagogue -> Icons.Rounded.Synagogue to R.color.brown
|
||||
LocationIcon.HinduTemple -> Icons.Rounded.TempleHindu to R.color.brown
|
||||
LocationIcon.BuddhistTemple -> Icons.Rounded.TempleBuddhist to R.color.brown
|
||||
LocationIcon.Candle -> Icons.Rounded.Candle to R.color.brown
|
||||
// bluegrey: public services
|
||||
LocationIcon.GovernmentBuilding -> Icons.Rounded.AccountBalance to R.color.bluegrey
|
||||
LocationIcon.Police -> Icons.Rounded.LocalPolice to R.color.bluegrey
|
||||
LocationIcon.FireDepartment -> Icons.Rounded.LocalFireDepartment to R.color.bluegrey
|
||||
LocationIcon.Courthouse -> Icons.Rounded.Gavel to R.color.bluegrey
|
||||
LocationIcon.PostOffice -> Icons.Rounded.LocalPostOffice to R.color.bluegrey
|
||||
LocationIcon.Library -> Icons.Rounded.Book to R.color.bluegrey
|
||||
LocationIcon.School -> Icons.Rounded.School to R.color.bluegrey
|
||||
LocationIcon.University -> Icons.Rounded.School to R.color.bluegrey
|
||||
LocationIcon.PublicBathroom -> Icons.Rounded.Wc to R.color.bluegrey
|
||||
|
||||
contains(
|
||||
"tapas",
|
||||
ignoreCase = true
|
||||
) -> R.drawable.ic_location_tapas to R.color.orange
|
||||
|
||||
contains(
|
||||
"keba" /* b or p, depending on locale */,
|
||||
ignoreCase = true
|
||||
) -> R.drawable.ic_location_kebab to R.color.orange
|
||||
|
||||
category == LocationCategory.FAST_FOOD -> R.drawable.ic_location_fastfood to R.color.orange
|
||||
else -> R.drawable.ic_location_restaurant to R.color.red
|
||||
}
|
||||
}
|
||||
|
||||
LocationCategory.BAR -> R.drawable.ic_location_bar to R.color.amber
|
||||
LocationCategory.CAFE, LocationCategory.COFFEE_SHOP -> R.drawable.ic_location_cafe to R.color.brown
|
||||
LocationCategory.HOTEL -> R.drawable.ic_location_hotel to R.color.green
|
||||
LocationCategory.SUPERMARKET -> R.drawable.ic_location_supermarket to R.color.lightblue
|
||||
LocationCategory.SCHOOL -> R.drawable.ic_location_school to R.color.purple
|
||||
LocationCategory.PARKING -> R.drawable.ic_location_parking to R.color.blue
|
||||
LocationCategory.FUEL -> R.drawable.ic_location_fuel to R.color.teal
|
||||
LocationCategory.TOILETS -> R.drawable.ic_location_toilets to R.color.blue
|
||||
LocationCategory.PHARMACY -> R.drawable.ic_location_pharmacy to R.color.pink
|
||||
LocationCategory.HOSPITAL, LocationCategory.CLINIC -> R.drawable.ic_location_hospital to R.color.red
|
||||
LocationCategory.POST_OFFICE -> R.drawable.ic_location_post_office to R.color.yellow
|
||||
LocationCategory.PUB, LocationCategory.BIERGARTEN -> R.drawable.ic_location_pub to R.color.amber
|
||||
LocationCategory.GRAVE_YARD -> R.drawable.ic_location_grave_yard to R.color.grey
|
||||
LocationCategory.DOCTORS -> R.drawable.ic_location_doctors to R.color.red
|
||||
LocationCategory.POLICE -> R.drawable.ic_location_police to R.color.blue
|
||||
LocationCategory.DENTIST -> R.drawable.ic_location_dentist to R.color.lightblue
|
||||
LocationCategory.LIBRARY, LocationCategory.BOOKS -> R.drawable.ic_location_library to R.color.brown
|
||||
LocationCategory.COLLEGE, LocationCategory.UNIVERSITY -> R.drawable.ic_location_college to R.color.purple
|
||||
LocationCategory.ICE_CREAM -> R.drawable.ic_location_ice_cream to R.color.pink
|
||||
LocationCategory.THEATRE -> R.drawable.ic_location_theatre to R.color.purple
|
||||
LocationCategory.PUBLIC_BUILDING -> R.drawable.ic_location_public_building to R.color.bluegrey
|
||||
LocationCategory.CINEMA -> R.drawable.ic_location_cinema to R.color.purple
|
||||
LocationCategory.NIGHTCLUB -> R.drawable.ic_location_nightclub to R.color.purple
|
||||
LocationCategory.CONVENIENCE -> R.drawable.ic_location_convenience to R.color.lightblue
|
||||
LocationCategory.CLOTHES -> R.drawable.ic_location_clothes to R.color.pink
|
||||
LocationCategory.HAIRDRESSER, LocationCategory.BEAUTY -> R.drawable.ic_location_hairdresser to R.color.pink
|
||||
LocationCategory.CAR_REPAIR -> R.drawable.ic_location_car_repair to R.color.blue
|
||||
LocationCategory.BAKERY -> R.drawable.ic_location_bakery to R.color.brown
|
||||
LocationCategory.CAR -> R.drawable.ic_location_car to R.color.blue
|
||||
LocationCategory.MOBILE_PHONE -> R.drawable.ic_location_mobile_phone to R.color.blue
|
||||
LocationCategory.FURNITURE -> R.drawable.ic_location_furniture to R.color.brown
|
||||
LocationCategory.ALCOHOL -> R.drawable.ic_location_alcohol to R.color.amber
|
||||
LocationCategory.FLORIST -> R.drawable.ic_location_florist to R.color.green
|
||||
LocationCategory.HARDWARE -> R.drawable.ic_location_hardware to R.color.brown
|
||||
LocationCategory.ELECTRONICS -> R.drawable.ic_location_electronics to R.color.blue
|
||||
LocationCategory.SHOES -> R.drawable.ic_location_shoes to R.color.pink
|
||||
LocationCategory.MALL, LocationCategory.DEPARTMENT_STORE, LocationCategory.CHEMIST -> R.drawable.ic_location_mall to R.color.blue
|
||||
LocationCategory.OPTICIAN -> R.drawable.ic_location_optician to R.color.blue
|
||||
LocationCategory.JEWELRY -> R.drawable.ic_location_jewelry to R.color.pink
|
||||
LocationCategory.GIFT -> R.drawable.ic_location_gift to R.color.pink
|
||||
LocationCategory.BICYCLE -> R.drawable.ic_location_bicycle to R.color.blue
|
||||
LocationCategory.LAUNDRY -> R.drawable.ic_location_laundry to R.color.blue
|
||||
LocationCategory.COMPUTER -> R.drawable.ic_location_computer to R.color.blue
|
||||
LocationCategory.TOBACCO -> R.drawable.ic_location_tobacco to R.color.amber
|
||||
LocationCategory.WINE -> R.drawable.ic_location_wine to R.color.amber
|
||||
LocationCategory.PHOTO -> R.drawable.ic_location_photo to R.color.blue
|
||||
LocationCategory.BANK -> R.drawable.ic_location_bank to R.color.blue
|
||||
LocationCategory.SOCCER -> R.drawable.ic_location_soccer to R.color.green
|
||||
LocationCategory.BASKETBALL -> R.drawable.ic_location_basketball to R.color.orange
|
||||
LocationCategory.TENNIS -> R.drawable.ic_location_tennis to R.color.orange
|
||||
LocationCategory.FITNESS, LocationCategory.FITNESS_CENTRE -> R.drawable.ic_location_fitness to R.color.orange
|
||||
LocationCategory.TRAM_STOP -> R.drawable.ic_location_tram_stop to R.color.blue
|
||||
LocationCategory.RAILWAY_STATION -> R.drawable.ic_location_railway_stop to R.color.lightblue
|
||||
LocationCategory.BUS_STATION, LocationCategory.BUS_STOP -> R.drawable.ic_location_bus_station to R.color.blue
|
||||
LocationCategory.ATM -> R.drawable.ic_location_atm to R.color.green
|
||||
LocationCategory.ART -> R.drawable.ic_location_art to R.color.deeporange
|
||||
LocationCategory.KIOSK -> R.drawable.ic_location_kiosk to R.color.bluegrey
|
||||
LocationCategory.MUSEUM -> R.drawable.ic_location_museum to R.color.deeporange
|
||||
LocationCategory.PARCEL_LOCKER -> R.drawable.ic_location_parcel_locker to R.color.bluegrey
|
||||
LocationCategory.TRAVEL_AGENCY -> R.drawable.ic_location_travel_agency to R.color.lightblue
|
||||
else -> R.drawable.ic_location_place to R.color.bluegrey
|
||||
null -> Icons.Rounded.Place to R.color.bluegrey
|
||||
}
|
||||
return StaticLauncherIcon(
|
||||
foregroundLayer = TintedIconLayer(
|
||||
icon = ContextCompat.getDrawable(context, resId)!!,
|
||||
scale = 0.5f,
|
||||
foregroundLayer = VectorLayer(
|
||||
vector = vector,
|
||||
color = ContextCompat.getColor(context, bgColor)
|
||||
),
|
||||
backgroundLayer = ColorLayer(ContextCompat.getColor(context, bgColor))
|
||||
)
|
||||
}
|
||||
|
||||
fun toAndroidLocation(): AndroidLocation {
|
||||
val location = AndroidLocation("KvaesitsoLocationProvider")
|
||||
|
||||
location.latitude = latitude
|
||||
location.longitude = longitude
|
||||
|
||||
return location
|
||||
}
|
||||
fun toAndroidLocation(): AndroidLocation =
|
||||
AndroidLocation("KvaesitsoLocationProvider").apply {
|
||||
this.latitude = this@Location.latitude
|
||||
this.longitude = this@Location.longitude
|
||||
}
|
||||
|
||||
fun distanceTo(androidLocation: AndroidLocation): Float {
|
||||
return androidLocation.distanceTo(this.toAndroidLocation())
|
||||
@@ -149,107 +322,25 @@ interface Location : SavableSearchable {
|
||||
|
||||
fun distanceTo(otherLocation: Location): Float =
|
||||
this.distanceTo(otherLocation.toAndroidLocation())
|
||||
|
||||
fun distanceTo(
|
||||
latitude: Double,
|
||||
longitude: Double,
|
||||
locationProvider: String = "KvaesitsoLocationProvider"
|
||||
): Float =
|
||||
this.distanceTo(AndroidLocation(locationProvider).apply {
|
||||
this.latitude = latitude
|
||||
this.longitude = longitude
|
||||
})
|
||||
}
|
||||
|
||||
// https://taginfo.openstreetmap.org/tags
|
||||
// 'amenity', 'shop', 'sport' of which the most important
|
||||
enum class LocationCategory {
|
||||
RESTAURANT,
|
||||
FAST_FOOD,
|
||||
BAR,
|
||||
CAFE,
|
||||
HOTEL,
|
||||
SUPERMARKET,
|
||||
OTHER,
|
||||
SCHOOL,
|
||||
PARKING,
|
||||
FUEL,
|
||||
TOILETS,
|
||||
PHARMACY,
|
||||
HOSPITAL,
|
||||
POST_OFFICE,
|
||||
PUB,
|
||||
GRAVE_YARD,
|
||||
DOCTORS,
|
||||
POLICE,
|
||||
DENTIST,
|
||||
LIBRARY,
|
||||
COLLEGE,
|
||||
ICE_CREAM,
|
||||
THEATRE,
|
||||
PUBLIC_BUILDING,
|
||||
CINEMA,
|
||||
NIGHTCLUB,
|
||||
BIERGARTEN,
|
||||
CLINIC,
|
||||
UNIVERSITY,
|
||||
DEPARTMENT_STORE,
|
||||
CLOTHES,
|
||||
CONVENIENCE,
|
||||
HAIRDRESSER,
|
||||
CAR_REPAIR,
|
||||
BEAUTY,
|
||||
BOOKS,
|
||||
BAKERY,
|
||||
CAR,
|
||||
MOBILE_PHONE,
|
||||
FURNITURE,
|
||||
ALCOHOL,
|
||||
FLORIST,
|
||||
HARDWARE,
|
||||
ELECTRONICS,
|
||||
SHOES,
|
||||
MALL,
|
||||
OPTICIAN,
|
||||
JEWELRY,
|
||||
GIFT,
|
||||
BICYCLE,
|
||||
LAUNDRY,
|
||||
COMPUTER,
|
||||
TOBACCO,
|
||||
WINE,
|
||||
PHOTO,
|
||||
COFFEE_SHOP,
|
||||
BANK,
|
||||
SOCCER,
|
||||
BASKETBALL,
|
||||
TENNIS,
|
||||
FITNESS,
|
||||
TRAM_STOP,
|
||||
RAILWAY_STATION,
|
||||
RAILWAY_STOP,
|
||||
BUS_STATION,
|
||||
ATM,
|
||||
ART,
|
||||
KIOSK,
|
||||
BUS_STOP,
|
||||
MUSEUM,
|
||||
PARCEL_LOCKER,
|
||||
CHEMIST,
|
||||
TRAVEL_AGENCY,
|
||||
FITNESS_CENTRE
|
||||
fun OpeningSchedule.isOpen(date: LocalDateTime = LocalDateTime.now()): Boolean = when (this) {
|
||||
is OpeningSchedule.TwentyFourSeven -> true
|
||||
is OpeningSchedule.Hours -> openingHours.any { it.isOpen(date) }
|
||||
}
|
||||
|
||||
data class OpeningHours(
|
||||
val dayOfWeek: DayOfWeek,
|
||||
val startTime: LocalTime,
|
||||
val duration: Duration
|
||||
) {
|
||||
|
||||
fun isOpen(date: LocalDateTime = LocalDateTime.now()): Boolean {
|
||||
val startTime = date.with(TemporalAdjusters.previousOrSame(dayOfWeek)).with(startTime)
|
||||
val endTime = startTime.plus(duration)
|
||||
return date in startTime..<endTime
|
||||
}
|
||||
|
||||
override fun toString(): String = "$dayOfWeek $startTime-${startTime.plus(duration)}"
|
||||
}
|
||||
|
||||
data class OpeningSchedule(
|
||||
val isTwentyFourSeven: Boolean,
|
||||
val openingHours: ImmutableList<OpeningHours>
|
||||
) {
|
||||
fun isOpen(date: LocalDateTime = LocalDateTime.now()): Boolean {
|
||||
return isTwentyFourSeven || openingHours.any { it.isOpen(date) }
|
||||
}
|
||||
fun OpeningHours.isOpen(date: LocalDateTime = LocalDateTime.now()): Boolean {
|
||||
val startTime = date.with(TemporalAdjusters.previousOrSame(dayOfWeek)).with(startTime)
|
||||
val endTime = startTime.plus(duration)
|
||||
return date in startTime..<endTime
|
||||
}
|
||||
@@ -8,7 +8,7 @@ package de.mm20.launcher2.search
|
||||
*/
|
||||
interface UpdatableSearchable<T : SavableSearchable> {
|
||||
val timestamp: Long
|
||||
val updatedSelf: (suspend () -> UpdateResult<T>)?
|
||||
val updatedSelf: (suspend (SavableSearchable) -> UpdateResult<T>)?
|
||||
}
|
||||
|
||||
sealed class UpdateResult<out T> {
|
||||
@@ -16,3 +16,16 @@ sealed class UpdateResult<out T> {
|
||||
data class TemporarilyUnavailable<T>(val cause: Throwable? = null) : UpdateResult<T>()
|
||||
data class PermanentlyUnavailable<T>(val cause: Throwable? = null) : UpdateResult<T>()
|
||||
}
|
||||
|
||||
fun <T>Result<T?>.asUpdateResult(): UpdateResult<T> {
|
||||
return if (isSuccess) {
|
||||
val refreshed = getOrNull()
|
||||
if (refreshed == null) {
|
||||
UpdateResult.PermanentlyUnavailable()
|
||||
} else {
|
||||
UpdateResult.Success(refreshed)
|
||||
}
|
||||
} else {
|
||||
UpdateResult.TemporarilyUnavailable(exceptionOrNull())
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package de.mm20.launcher2.search
|
||||
|
||||
import de.mm20.launcher2.search.location.OpeningHours
|
||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
Reference in New Issue
Block a user