Add OSM search provider (#611)
* add openstreetmaps module in data * fix injection * retrofit2 implementation * tokenization * partial rewrite of OpeningTime.fromOverpassElement * finish rewrite of OpeningTime.fromOverpassElement * fix merge x) * configurable search radius * add settings section and disable setting explicit timeout values for http-client to alleviate issues during debugging * settings screen localization * enable radius slider only when locations are enabled * fix dayRange parsing, add barebones UI * add files to git * add location listener in SearchableItemVM that gets activated by LocationItem * add heading listener * Calculations, UI additions * rename settings to LocationsSettings * use android location library for bearing calculations * location fix * rotation fix, demo UI * working buttons for launching map and website (if available) * finish botched UI * improve overpass query by utilizing regex for fuzzy search results * add link to documentation for further reference * localization comments * remove wikipedia minification setting * schema version, default radius 1.5km * move osm-specific opening-time parsing to OsmLocation * refactor with callbackFlow * remember flow and set minimum distance update to 1m * refactor for replacementIcon, add imperial unit option * 'open until' UI fix * implement serializers * catch errors in deserializer * hacky live sorting by distance * give max priority to bestmatch determined by SearchVM * add yards as additional step to metersToLocalizzedString * move http-client from serializers of osmlocation to companion object for cache updating * add setting for custom URL * round yards to int * add botched map preview * unbotch map tiles, draw user location in map (proof of concept) * - create MapTiles Composable - add border around map - add indicators for location and userlocation, when on map * fix default imperial units setting * fix tint color * add OSM attribution string * display loading animation when tiles can't be shown yet * create compose preview of maptiles * UI work * being glad that API's just return null instead of throwing information * tryStartActivity * aniimate card row placement * Text alignment, padding * Rotation -PI/PI wrap fix * fix direction arrow rotation when screen is upside down * more icons * icons, settings, localization - consider other tags than "amenity" when determining location category - add many more location categories with corresponding icons - add settings to disable map theming and hide search results with LocationCategory.OTHER - add default localizations for settings * catch errors when deserializing location category * move location and heading functions to Context.kt in extensions * fix hideUncategorized criterion * add pre-sorting by distance for location results in SearchVM by injecting Context into search() * specify receiver parameters in ktx.Context lambdas * move pose logic and context dependency to new module devicepose with DevicePoseProvider * git, add the frickin' module * search overpass for nodes and ways include category for parcel_locker already start searching for queries extending length 2 * make openingTimes immutable * OsmRepository changes - include telephone number - don't try to repeatedly update cache if there is no value to be updated to - deduplicate results with same label by category and distance (100m) - include fixmeurl to point to openstreetmaps.org/fixthemap * ask for center in overpass API to compute center coordinates of ways * search for brand * add chemist location category * restaurant / fastfood icon shenanigans * actually add the icons :| * add leisure tag for leisure:fitness_centre * return to 'open until'/'opens in'/'open next' * adding missing UI features - bug report dialog - call button if phone number exists - grid item popup * refactor to handle 24/7 locations more comfortably * hide hours in 'opens_in' when they are zero * show maptiles such that user is always in view * drawing adjustments * cache previous zoom level to speed up tile coordinate calculations * using remember * using MutableIntState * fix logic that determines whether tiles are loading * fix for numTiles == 9 * one plus one is two plus one makes three quick maths * animate user location indicator, remember calculations * fix off by one when determining next opening hour * second attempt to fix upside down arrow rotation (probably fine now) * logging * reconsider declination, inject samplingPeriod * undoing the merge undo * move localization string to i18n * revert reordering by distance * refactor .distanceTo * make Location abstract class to override compareTo with cached distance to correct sort order in search results * when it is if when you could use when * replace Pair with dataclass * condition check order * not creating objects with undefined locations, removing suspend from getCategory() * inject permissionsmanager as constructor parameter * Store OSM settings in decentralized datastore * Update searchable content in database on launch * Refactor, add mechanism to load updated searchable data lazily * Cache all OSM data in launcher database * Add pin to favorites button to location results * Add sealed class UpdateResult that is returned by awaiting updatedSelf of DeferredSearchable - update on success - set flag on temporarily unavailable (TODO add some UI indication) - delete and invalidate VM on permanently unavailable (Display some message window to user?) * Move sorting of Locations from OsmRepository to SearchVM using cached location in DevicePoseProvider, if available * make use of cached location in code * make use of DevicePoseProvider in WeatherRepository * inject via koin * increase getLocation().timeout() to 10 minutes since we are asking for locations only every hour, so 10 minutes seem reasonable (?) * poll new location every time * add icon for cached results where results are temporarily unavailable * Refactor DeferredSearchable to UpdatableSearchable that receives a closure to retrieve an updated self. - moved timestamp (formerly `updatedAt`) to UpdatableSearchable - moved logic whether to update searchable to `requestUpdatedSearchable` in SearchableItemVM, which gets triggered every time the details of the item are shown - keep track in SearchableVM whether we should retry updating, possibly bypassing a timestamp value that is not old enough - show toast upon permanently unavailable - animate "cached_searchable" icon - make "cached_searchable" icon clickable to show toast explaining the situation * logging on PermanentlyUnavailable * refactor OsmRepository.update() * MapTheming adjustments. There is now darkmode, hooray! * remove outdated comment * code tidying * remove unnecessary LaunchedEffect * make outdated badge only clickable when actually outdated * deserialize opening schedule * set deserialized props to null if strings are blank * also consider contact:* tagging scheme for website & phone * tweaks * git add Result.kt * don't search for locations if network is not allowed * merge fixes * Move location search settings to preferences module * Change wording and order of location search preferences * Limit location search results * Order location search results by distance * Use a sequence * Android Studio's suggestion wasn't as fleshed out as one would hope * Add proguard rules * Rename TileMapRepository to MapTileLoader --------- Co-authored-by: MM20 <15646950+MM2-0@users.noreply.github.com>
This commit is contained in:
parent
4b30b13266
commit
cba387c832
9
.idea/inspectionProfiles/Project_Default.xml
generated
9
.idea/inspectionProfiles/Project_Default.xml
generated
@ -4,30 +4,39 @@
|
||||
<inspection_tool class="AndroidLintNewerVersionAvailable" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
@ -13,7 +13,7 @@ android {
|
||||
}
|
||||
|
||||
packaging {
|
||||
//resources.excludes.add("META-INF/DEPENDENCIES")
|
||||
resources.excludes.add("META-INF/DEPENDENCIES")
|
||||
resources.excludes.add("META-INF/LICENSE")
|
||||
resources.excludes.add("META-INF/LICENSE.txt")
|
||||
resources.excludes.add("META-INF/license.txt")
|
||||
@ -166,7 +166,9 @@ dependencies {
|
||||
implementation(project(":services:global-actions"))
|
||||
implementation(project(":services:widgets"))
|
||||
implementation(project(":services:favorites"))
|
||||
implementation(project(":data:openstreetmaps"))
|
||||
implementation(project(":services:plugins"))
|
||||
implementation(project(":core:devicepose"))
|
||||
|
||||
// Uncomment this if you want annoying notifications in your debug builds yelling at you how terrible your code is
|
||||
//debugImplementation(libs.leakcanary)
|
||||
|
||||
@ -26,8 +26,10 @@ import de.mm20.launcher2.database.databaseModule
|
||||
import de.mm20.launcher2.debug.initDebugMode
|
||||
import de.mm20.launcher2.globalactions.globalActionsModule
|
||||
import de.mm20.launcher2.notifications.notificationsModule
|
||||
import de.mm20.launcher2.openstreetmaps.openStreetMapsModule
|
||||
import de.mm20.launcher2.permissions.permissionsModule
|
||||
import de.mm20.launcher2.data.plugins.dataPluginsModule
|
||||
import de.mm20.launcher2.devicepose.devicePoseModule
|
||||
import de.mm20.launcher2.plugins.servicesPluginsModule
|
||||
import de.mm20.launcher2.preferences.preferencesModule
|
||||
import de.mm20.launcher2.searchactions.searchActionsModule
|
||||
@ -86,11 +88,13 @@ class LauncherApplication : Application(), CoroutineScope, ImageLoaderFactory {
|
||||
websitesModule,
|
||||
widgetsModule,
|
||||
wikipediaModule,
|
||||
openStreetMapsModule,
|
||||
servicesTagsModule,
|
||||
widgetsServiceModule,
|
||||
dataPluginsModule,
|
||||
servicesPluginsModule,
|
||||
backupModule,
|
||||
devicePoseModule,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -6,6 +6,10 @@ plugins {
|
||||
android {
|
||||
compileSdk = libs.versions.compileSdk.get().toInt()
|
||||
|
||||
packaging {
|
||||
resources.excludes.add("META-INF/DEPENDENCIES")
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdk = libs.versions.minSdk.get().toInt()
|
||||
|
||||
@ -136,6 +140,7 @@ dependencies {
|
||||
implementation(project(":core:crashreporter"))
|
||||
implementation(project(":data:notifications"))
|
||||
implementation(project(":data:contacts"))
|
||||
implementation(project(":data:openstreetmaps"))
|
||||
implementation(project(":core:permissions"))
|
||||
implementation(project(":data:websites"))
|
||||
implementation(project(":data:unitconverter"))
|
||||
@ -149,4 +154,5 @@ dependencies {
|
||||
implementation(project(":services:global-actions"))
|
||||
implementation(project(":services:widgets"))
|
||||
implementation(project(":services:favorites"))
|
||||
implementation(project(":core:devicepose"))
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<application>
|
||||
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
package de.mm20.launcher2.ui.animation
|
||||
|
||||
import androidx.compose.animation.core.AnimationSpec
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.BiasAlignment
|
||||
|
||||
@Composable
|
||||
fun animateHorizontalAlignmentAsState(
|
||||
targetAlignment: Alignment.Horizontal,
|
||||
animationSpec: AnimationSpec<Float> = tween()
|
||||
): State<BiasAlignment.Horizontal> {
|
||||
val bias by animateFloatAsState(
|
||||
targetValue = when (targetAlignment) {
|
||||
Alignment.Start -> -1f
|
||||
Alignment.End -> 1f
|
||||
else -> 0f
|
||||
},
|
||||
animationSpec = animationSpec
|
||||
)
|
||||
return remember { derivedStateOf { BiasAlignment.Horizontal(bias) } }
|
||||
}
|
||||
@ -2,6 +2,7 @@ package de.mm20.launcher2.ui.ktx
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import hct.Hct
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
fun Color.toHexString(): String {
|
||||
@ -17,4 +18,13 @@ fun Color.toHexString(): String {
|
||||
fun Color.Companion.hct(hue: Float, chroma: Float, tone: Float): Color {
|
||||
val hct = Hct.from(hue.toDouble(), chroma.toDouble(), tone.toDouble())
|
||||
return Color(hct.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
val Color.hue: Float
|
||||
get() {
|
||||
val r = this.red / 255f
|
||||
val g = this.green / 255f
|
||||
val b = this.blue / 255f
|
||||
// sqrt(3)
|
||||
return atan2(1.7320508f * (g - b), 2f * r - g - b)
|
||||
}
|
||||
|
||||
78
app/ui/src/main/java/de/mm20/launcher2/ui/ktx/ColorMatrix.kt
Normal file
78
app/ui/src/main/java/de/mm20/launcher2/ui/ktx/ColorMatrix.kt
Normal file
@ -0,0 +1,78 @@
|
||||
package de.mm20.launcher2.ui.ktx
|
||||
|
||||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import de.mm20.launcher2.ktx.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
fun ColorMatrix.invert(fraction: Float, withAlpha: Boolean = false): ColorMatrix {
|
||||
assert(fraction in 0f..1f)
|
||||
val scale = -2f * fraction + 1f
|
||||
this *= ColorMatrix().apply {
|
||||
setToScale(scale, scale, scale, if (withAlpha) scale else 1f)
|
||||
this[0, 4] = 255f
|
||||
this[1, 4] = 255f
|
||||
this[2, 4] = 255f
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
// https://chromium.googlesource.com/chromium/blink/+/master/Source/platform/graphics/filters/FEColorMatrix.cpp#93
|
||||
fun ColorMatrix.hueRotate(deg: Float): ColorMatrix {
|
||||
val cosHue = cos(deg * Float.PI / 180f)
|
||||
val sinHue = sin(deg * Float.PI / 180f)
|
||||
val mat = FloatArray(20)
|
||||
mat[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f
|
||||
mat[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f
|
||||
mat[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f
|
||||
mat[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f
|
||||
mat[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f
|
||||
mat[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f
|
||||
mat[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f
|
||||
mat[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f
|
||||
mat[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f
|
||||
mat[18] = 1f
|
||||
this *= ColorMatrix(mat)
|
||||
return this
|
||||
}
|
||||
|
||||
fun ColorMatrix.contrast(contrast: Float): ColorMatrix {
|
||||
this *= ColorMatrix(
|
||||
floatArrayOf(
|
||||
contrast, 0f, 0f, 0f, 0f,
|
||||
0f, contrast, 0f, 0f, 0f,
|
||||
0f, 0f, contrast, 0f, 0f,
|
||||
0f, 0f, 0f, 1f, 0f
|
||||
)
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
// https://github.com/darkreader/darkreader/blob/b1bbaa74b6bd460556ab0c2a8d8e20c562e05e9b/src/generators/utils/matrix.ts#L75
|
||||
fun ColorMatrix.sepia(amount: Float): ColorMatrix {
|
||||
this *= ColorMatrix(
|
||||
floatArrayOf(
|
||||
0.393f + 0.607f * (1f - amount),
|
||||
0.769f - 0.769f * (1f - amount),
|
||||
0.189f - 0.189f * (1f - amount),
|
||||
0f,
|
||||
0f,
|
||||
0.349f - 0.349f * (1f - amount),
|
||||
0.686f + 0.314f * (1 - amount),
|
||||
0.168f - 0.168f * (1f - amount),
|
||||
0f,
|
||||
0f,
|
||||
0.272f - 0.272f * (1f - amount),
|
||||
0.534f - 0.534f * (1 - amount),
|
||||
0.131f + 0.869f * (1f - amount),
|
||||
0f,
|
||||
0f,
|
||||
0f,
|
||||
0f,
|
||||
0f,
|
||||
1f,
|
||||
0f,
|
||||
)
|
||||
)
|
||||
return this
|
||||
}
|
||||
15
app/ui/src/main/java/de/mm20/launcher2/ui/ktx/Deferred.kt
Normal file
15
app/ui/src/main/java/de/mm20/launcher2/ui/ktx/Deferred.kt
Normal file
@ -0,0 +1,15 @@
|
||||
package de.mm20.launcher2.ui.ktx
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.produceState
|
||||
import kotlinx.coroutines.Deferred
|
||||
|
||||
@Composable
|
||||
fun <T> Deferred<T>?.asState(initialValue: T): State<T> {
|
||||
return produceState(initialValue) {
|
||||
if (this@asState != null) {
|
||||
value = await()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,19 @@
|
||||
package de.mm20.launcher2.ui.ktx
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.animation.core.AnimationVector2D
|
||||
import androidx.compose.animation.core.TwoWayConverter
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlin.math.PI
|
||||
import de.mm20.launcher2.ktx.PI
|
||||
import de.mm20.launcher2.ui.R
|
||||
import java.text.DecimalFormat
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* Converts the given pixel size to a Dp value based on the current density
|
||||
@ -13,3 +22,52 @@ import kotlin.math.PI
|
||||
fun Float.toDp(): Dp {
|
||||
return (this / LocalDensity.current.density).dp
|
||||
}
|
||||
|
||||
fun Float.roundToString(): String = this.roundToInt().toString()
|
||||
|
||||
fun Float.metersToLocalizedString(context: Context, imperialUnits: Boolean): String {
|
||||
val decimalFormat =
|
||||
DecimalFormat().apply { maximumFractionDigits = 1; minimumFractionDigits = 0 }
|
||||
|
||||
val (value, unit) = if (imperialUnits) {
|
||||
// yee haw
|
||||
val asFeet = this * 3.28084f
|
||||
val isYards = asFeet >= 3f
|
||||
val isMiles = asFeet >= 5280f
|
||||
val value =
|
||||
if (isMiles) decimalFormat.format(asFeet / 5280f)
|
||||
else if (isYards) (asFeet / 3f).roundToString()
|
||||
else asFeet.roundToString()
|
||||
|
||||
val unit = context.getString(
|
||||
if (isMiles) R.string.unit_mile_symbol
|
||||
else if (isYards) R.string.unit_yard_symbol
|
||||
else R.string.unit_foot_symbol
|
||||
)
|
||||
|
||||
value to unit
|
||||
} else {
|
||||
val isKm = this >= 1000f
|
||||
val value =
|
||||
if (isKm) decimalFormat.format(this / 1000f)
|
||||
else this.roundToString()
|
||||
|
||||
val unit = context.getString(
|
||||
if (isKm) R.string.unit_kilometer_symbol
|
||||
else R.string.unit_meter_symbol
|
||||
)
|
||||
|
||||
value to unit
|
||||
}
|
||||
|
||||
return "$value $unit"
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/68651222
|
||||
val Float.Companion.DegreesConverter
|
||||
get() = TwoWayConverter<Float, AnimationVector2D>({
|
||||
val rad = it * Float.PI / 180f
|
||||
AnimationVector2D(sin(rad), cos(rad))
|
||||
}, {
|
||||
(atan2(it.v1, it.v2) * 180f / Float.PI + 360f) % 360f
|
||||
})
|
||||
|
||||
@ -2,10 +2,9 @@ package de.mm20.launcher2.ui.ktx
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
|
||||
fun Modifier.conditional(condition: Boolean, other: Modifier): Modifier {
|
||||
if (condition) {
|
||||
return this then other
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
@ -38,6 +39,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.search.Location
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.common.FavoritesTagSelector
|
||||
@ -60,6 +62,9 @@ import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlin.math.ceil
|
||||
|
||||
private const val PRIORITY_MIN = Int.MAX_VALUE
|
||||
private const val PRIORITY_MAX = Int.MIN_VALUE
|
||||
|
||||
@Composable
|
||||
fun SearchColumn(
|
||||
modifier: Modifier = Modifier,
|
||||
@ -90,6 +95,7 @@ fun SearchColumn(
|
||||
val unitConverter by viewModel.unitConverterResults
|
||||
val calculator by viewModel.calculatorResults
|
||||
val wikipedia by viewModel.articleResults
|
||||
val locations by viewModel.locationResults
|
||||
val website by viewModel.websiteResults
|
||||
val hiddenResults by viewModel.hiddenResults
|
||||
|
||||
@ -100,6 +106,7 @@ fun SearchColumn(
|
||||
val missingCalendarPermission by viewModel.missingCalendarPermission.collectAsState(false)
|
||||
val missingShortcutsPermission by viewModel.missingAppShortcutPermission.collectAsState(false)
|
||||
val missingContactsPermission by viewModel.missingContactsPermission.collectAsState(false)
|
||||
val missingLocationPermission by viewModel.missingLocationPermission.collectAsState(false)
|
||||
val missingFilesPermission by viewModel.missingFilesPermission.collectAsState(false)
|
||||
|
||||
val pinnedTags by favoritesVM.pinnedTags.collectAsState(emptyList())
|
||||
@ -295,6 +302,30 @@ fun SearchColumn(
|
||||
key = "contacts",
|
||||
highlightedItem = bestMatch as? SavableSearchable
|
||||
)
|
||||
ListResults(
|
||||
before = if (missingLocationPermission && !isSearchEmpty) {
|
||||
{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_location_search),
|
||||
onClick = { viewModel.requestLocationPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableLocationSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
items = locations.toImmutableList(),
|
||||
reverse = reverse,
|
||||
key = "locations",
|
||||
highlightedItem = bestMatch as? SavableSearchable
|
||||
)
|
||||
for (wiki in wikipedia) {
|
||||
SingleResult(highlight = bestMatch == wiki) {
|
||||
ArticleItem(article = wiki)
|
||||
@ -436,7 +467,7 @@ fun LazyListScope.ListResults(
|
||||
key: String,
|
||||
before: (@Composable () -> Unit)? = null,
|
||||
after: (@Composable () -> Unit)? = null,
|
||||
highlightedItem: SavableSearchable?
|
||||
highlightedItem: SavableSearchable?,
|
||||
) {
|
||||
if (before != null) {
|
||||
item(key = "$key-before") {
|
||||
|
||||
@ -5,14 +5,15 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.devicepose.DevicePoseProvider
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.preferences.LegacySettings.SearchResultOrderingSettings.Ordering
|
||||
import de.mm20.launcher2.preferences.SearchResultOrder
|
||||
import de.mm20.launcher2.preferences.search.CalendarSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.ContactSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.FavoritesSettings
|
||||
import de.mm20.launcher2.preferences.search.FileSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.LocationSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.ShortcutSearchSettings
|
||||
import de.mm20.launcher2.preferences.ui.SearchUiSettings
|
||||
import de.mm20.launcher2.search.AppProfile
|
||||
@ -25,6 +26,7 @@ import de.mm20.launcher2.search.File
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.SearchService
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.search.Location
|
||||
import de.mm20.launcher2.search.Website
|
||||
import de.mm20.launcher2.search.data.Calculator
|
||||
import de.mm20.launcher2.search.data.UnitConverter
|
||||
@ -37,6 +39,7 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
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.flow.shareIn
|
||||
@ -57,6 +60,8 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
private val calendarSearchSettings: CalendarSearchSettings by inject()
|
||||
private val shortcutSearchSettings: ShortcutSearchSettings by inject()
|
||||
private val searchUiSettings: SearchUiSettings by inject()
|
||||
private val locationSearchSettings: LocationSearchSettings by inject()
|
||||
private val devicePoseProvider: DevicePoseProvider by inject()
|
||||
|
||||
val launchOnEnter = searchUiSettings.launchOnEnter
|
||||
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
|
||||
@ -66,6 +71,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
val searchQuery = mutableStateOf("")
|
||||
val isSearchEmpty = mutableStateOf(true)
|
||||
|
||||
val locationResults = mutableStateOf<List<Location>>(emptyList())
|
||||
val appResults = mutableStateOf<List<Application>>(emptyList())
|
||||
val workAppResults = mutableStateOf<List<Application>>(emptyList())
|
||||
val appShortcutResults = mutableStateOf<List<AppShortcut>>(emptyList())
|
||||
@ -94,7 +100,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
val bestMatch = mutableStateOf<Searchable?>(null)
|
||||
|
||||
init {
|
||||
search("", true)
|
||||
search("", forceRestart = true)
|
||||
}
|
||||
|
||||
fun launchBestMatchOrAction(context: Context) {
|
||||
@ -138,6 +144,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
results.files,
|
||||
results.contacts,
|
||||
results.calendars,
|
||||
results.locations,
|
||||
results.wikipedia,
|
||||
results.websites,
|
||||
results.calculators,
|
||||
@ -169,6 +176,11 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
|
||||
resultsList = resultsList.sortedWith { a, b ->
|
||||
when {
|
||||
a is Location && b is Location && devicePoseProvider.lastLocation != null -> {
|
||||
a.distanceTo(devicePoseProvider.lastLocation!!)
|
||||
.compareTo(b.distanceTo(devicePoseProvider.lastLocation!!))
|
||||
}
|
||||
|
||||
a is SavableSearchable && b !is SavableSearchable -> -1
|
||||
a !is SavableSearchable && b is SavableSearchable -> 1
|
||||
a is SavableSearchable && b is SavableSearchable -> {
|
||||
@ -200,6 +212,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
val unitConv = mutableListOf<UnitConverter>()
|
||||
val calc = mutableListOf<Calculator>()
|
||||
val articles = mutableListOf<Article>()
|
||||
val locations = mutableListOf<Location>()
|
||||
val website = mutableListOf<Website>()
|
||||
val actions = mutableListOf<SearchAction>()
|
||||
for (r in resultsList) {
|
||||
@ -218,6 +231,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
r is Calculator -> calc.add(r)
|
||||
r is Website -> website.add(r)
|
||||
r is Article -> articles.add(r)
|
||||
r is Location -> locations.add(r)
|
||||
r is SearchAction -> actions.add(r)
|
||||
}
|
||||
}
|
||||
@ -230,6 +244,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
unitConv,
|
||||
calc,
|
||||
events,
|
||||
locations,
|
||||
contacts,
|
||||
articles,
|
||||
website,
|
||||
@ -245,6 +260,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
contactResults.value = contacts
|
||||
calendarResults.value = events
|
||||
articleResults.value = articles
|
||||
locationResults.value = locations
|
||||
websiteResults.value = website
|
||||
calculatorResults.value = calc
|
||||
unitConverterResults.value = unitConv
|
||||
@ -282,6 +298,19 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
contactSearchSettings.setEnabled(false)
|
||||
}
|
||||
|
||||
val missingLocationPermission = combine(
|
||||
permissionsManager.hasPermission(PermissionGroup.Location),
|
||||
locationSearchSettings.enabled.distinctUntilChanged()
|
||||
) { perm, enabled -> !perm && enabled }
|
||||
|
||||
fun requestLocationPermission(context: AppCompatActivity) {
|
||||
permissionsManager.requestPermission(context, PermissionGroup.Location)
|
||||
}
|
||||
|
||||
fun disableLocationSearch() {
|
||||
locationSearchSettings.setEnabled(false)
|
||||
}
|
||||
|
||||
val missingFilesPermission = combine(
|
||||
permissionsManager.hasPermission(PermissionGroup.ExternalStorage),
|
||||
fileSearchSettings.localFiles
|
||||
|
||||
@ -1,28 +1,32 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.common
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.LauncherApps
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import de.mm20.launcher2.appshortcuts.AppShortcutRepository
|
||||
import de.mm20.launcher2.badges.BadgeService
|
||||
import de.mm20.launcher2.devicepose.DevicePoseProvider
|
||||
import de.mm20.launcher2.icons.IconService
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.notifications.Notification
|
||||
import de.mm20.launcher2.notifications.NotificationRepository
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.search.File
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.preferences.search.LocationSearchSettings
|
||||
import de.mm20.launcher2.search.AppShortcut
|
||||
import de.mm20.launcher2.search.Application
|
||||
import de.mm20.launcher2.search.File
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.UpdatableSearchable
|
||||
import de.mm20.launcher2.search.UpdateResult
|
||||
import de.mm20.launcher2.services.favorites.FavoritesService
|
||||
import de.mm20.launcher2.services.tags.TagsService
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.launcher.search.ListItemViewModel
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@ -35,7 +39,9 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class SearchableItemVM : ListItemViewModel(), KoinComponent {
|
||||
private val favoritesService: FavoritesService by inject()
|
||||
private val badgeService: BadgeService by inject()
|
||||
@ -44,9 +50,14 @@ class SearchableItemVM : ListItemViewModel(), KoinComponent {
|
||||
private val notificationRepository: NotificationRepository by inject()
|
||||
private val appShortcutRepository: AppShortcutRepository by inject()
|
||||
private val permissionsManager: PermissionsManager by inject()
|
||||
private val locationSearchSettings: LocationSearchSettings by inject()
|
||||
|
||||
private val searchable = MutableStateFlow<SavableSearchable?>(null)
|
||||
private val iconSize = MutableStateFlow<Int>(0)
|
||||
val isUpToDate = MutableStateFlow(true)
|
||||
|
||||
val devicePoseProvider: DevicePoseProvider by inject()
|
||||
|
||||
val searchable = MutableStateFlow<SavableSearchable?>(null)
|
||||
private val iconSize = MutableStateFlow(0)
|
||||
fun init(searchable: SavableSearchable, iconSize: Int) {
|
||||
this.searchable.value = searchable
|
||||
this.iconSize.value = iconSize
|
||||
@ -104,7 +115,7 @@ class SearchableItemVM : ListItemViewModel(), KoinComponent {
|
||||
).first()
|
||||
}
|
||||
|
||||
open fun launch(context: Context, bounds: Rect? = null): Boolean {
|
||||
fun launch(context: Context, bounds: Rect? = null): Boolean {
|
||||
val searchable = searchable.value ?: return false
|
||||
val view = (context as? AppCompatActivity)?.window?.decorView
|
||||
val options = if (bounds != null && view != null) {
|
||||
@ -167,7 +178,63 @@ class SearchableItemVM : ListItemViewModel(), KoinComponent {
|
||||
favoritesService.reset(searchable)
|
||||
}
|
||||
|
||||
private var shouldRetryUpdate = false
|
||||
|
||||
fun requestUpdatedSearchable(context: Context) {
|
||||
val searchable = searchable.value ?: return
|
||||
if (searchable is UpdatableSearchable<*>) {
|
||||
val updatedSelf = searchable.updatedSelf ?: return
|
||||
if (!shouldRetryUpdate && System.currentTimeMillis() < searchable.timestamp + 1.hours.inWholeMilliseconds) return
|
||||
viewModelScope.launch {
|
||||
this@SearchableItemVM.searchable.value = with(updatedSelf()) {
|
||||
when (this) {
|
||||
is UpdateResult.Success -> {
|
||||
isUpToDate.value = true
|
||||
shouldRetryUpdate = false
|
||||
favoritesService.upsert(this.result)
|
||||
this.result
|
||||
}
|
||||
|
||||
is UpdateResult.TemporarilyUnavailable -> {
|
||||
isUpToDate.value = false
|
||||
shouldRetryUpdate = true
|
||||
return@launch
|
||||
}
|
||||
|
||||
is UpdateResult.PermanentlyUnavailable -> {
|
||||
isUpToDate.value = false
|
||||
shouldRetryUpdate = false
|
||||
favoritesService.delete(searchable)
|
||||
Toast.makeText(
|
||||
context,
|
||||
R.string.unavailable_searchable,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
Log.d("requestUpdatedSearchable", "PermanentlyUnavailable", this.cause)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun requestShortcutPermission(activity: AppCompatActivity) {
|
||||
permissionsManager.requestPermission(activity, PermissionGroup.AppShortcuts)
|
||||
}
|
||||
|
||||
val useInsaneUnits = locationSearchSettings.imperialUnits
|
||||
.stateIn(viewModelScope, SharingStarted.Lazily, false)
|
||||
|
||||
val showMap = locationSearchSettings.showMap
|
||||
.stateIn(viewModelScope, SharingStarted.Lazily, false)
|
||||
|
||||
val applyMapTheming = locationSearchSettings.themeMap
|
||||
.stateIn(viewModelScope, SharingStarted.Lazily, false)
|
||||
|
||||
val showPositionOnMap = locationSearchSettings.showPositionOnMap
|
||||
.stateIn(viewModelScope, SharingStarted.Lazily, false)
|
||||
|
||||
val mapTileServerUrl = locationSearchSettings.tileServer
|
||||
.stateIn(viewModelScope, SharingStarted.Lazily, "")
|
||||
}
|
||||
@ -23,6 +23,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@ -50,6 +51,7 @@ import de.mm20.launcher2.search.AppShortcut
|
||||
import de.mm20.launcher2.search.Application
|
||||
import de.mm20.launcher2.search.Article
|
||||
import de.mm20.launcher2.search.CalendarEvent
|
||||
import de.mm20.launcher2.search.Location
|
||||
import de.mm20.launcher2.search.Website
|
||||
import de.mm20.launcher2.ui.component.LauncherCard
|
||||
import de.mm20.launcher2.ui.component.LocalIconShape
|
||||
@ -61,6 +63,7 @@ import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
||||
import de.mm20.launcher2.ui.launcher.search.contacts.ContactItemGridPopup
|
||||
import de.mm20.launcher2.ui.launcher.search.files.FileItemGridPopup
|
||||
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
|
||||
import de.mm20.launcher2.ui.launcher.search.location.LocationItemGridPopup
|
||||
import de.mm20.launcher2.ui.launcher.search.shortcut.ShortcutItemGridPopup
|
||||
import de.mm20.launcher2.ui.launcher.search.website.WebsiteItemGridPopup
|
||||
import de.mm20.launcher2.ui.launcher.search.wikipedia.ArticleItemGridPopup
|
||||
@ -86,6 +89,8 @@ fun GridItem(
|
||||
viewModel.init(item, iconSize.toInt())
|
||||
}
|
||||
|
||||
val item = viewModel.searchable.collectAsState().value ?: item
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
var showPopup by remember(item.key) { mutableStateOf(false) }
|
||||
@ -94,6 +99,10 @@ fun GridItem(
|
||||
val launchOnPress = !item.preferDetailsOverLaunch
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
|
||||
LaunchedEffect(showPopup) {
|
||||
if (showPopup) viewModel.requestUpdatedSearchable(context)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.combinedClickable(
|
||||
@ -212,7 +221,7 @@ fun ItemPopup(origin: Rect, searchable: Searchable, onDismissRequest: () -> Unit
|
||||
.imePadding()
|
||||
.padding(horizontal = 16.dp)
|
||||
.then(
|
||||
if (show.targetState ) {
|
||||
if (show.targetState) {
|
||||
Modifier.pointerInput(Unit) {
|
||||
detectTapGestures(onPress = {
|
||||
show.targetState = false
|
||||
@ -319,6 +328,18 @@ fun ItemPopup(origin: Rect, searchable: Searchable, onDismissRequest: () -> Unit
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is Location -> {
|
||||
LocationItemGridPopup(
|
||||
location = searchable,
|
||||
show = show,
|
||||
animationProgress = animationProgress.value,
|
||||
origin = origin,
|
||||
onDismiss = {
|
||||
show.targetState = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import de.mm20.launcher2.search.AppShortcut
|
||||
import de.mm20.launcher2.search.CalendarEvent
|
||||
import de.mm20.launcher2.search.Contact
|
||||
import de.mm20.launcher2.search.File
|
||||
import de.mm20.launcher2.search.Location
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.ui.component.InnerCard
|
||||
import de.mm20.launcher2.ui.ktx.toPixels
|
||||
@ -21,6 +22,7 @@ import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
||||
import de.mm20.launcher2.ui.launcher.search.contacts.ContactItem
|
||||
import de.mm20.launcher2.ui.launcher.search.files.FileItem
|
||||
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
|
||||
import de.mm20.launcher2.ui.launcher.search.location.LocationItem
|
||||
import de.mm20.launcher2.ui.launcher.search.shortcut.AppShortcutItem
|
||||
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
||||
|
||||
@ -39,6 +41,12 @@ fun ListItem(
|
||||
LaunchedEffect(item, iconSize) {
|
||||
viewModel.init(item, iconSize.toInt())
|
||||
}
|
||||
|
||||
LaunchedEffect(showDetails) {
|
||||
if (showDetails) viewModel.requestUpdatedSearchable(context)
|
||||
}
|
||||
|
||||
val item = viewModel.searchable.collectAsState().value ?: item
|
||||
|
||||
var bounds by remember { mutableStateOf(Rect.Zero) }
|
||||
InnerCard(
|
||||
@ -64,52 +72,69 @@ fun ListItem(
|
||||
onBack = { showDetails = false }
|
||||
)
|
||||
}
|
||||
|
||||
is File -> {
|
||||
FileItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.combinedClickable(
|
||||
enabled = !showDetails,
|
||||
onClick = {
|
||||
if (!viewModel.launch(context, bounds)) {
|
||||
showDetails = true
|
||||
}
|
||||
},
|
||||
onLongClick = { showDetails = true }
|
||||
),
|
||||
enabled = !showDetails,
|
||||
onClick = {
|
||||
if (!viewModel.launch(context, bounds)) {
|
||||
showDetails = true
|
||||
}
|
||||
},
|
||||
onLongClick = { showDetails = true }
|
||||
),
|
||||
file = item,
|
||||
showDetails = showDetails,
|
||||
onBack = { showDetails = false }
|
||||
)
|
||||
}
|
||||
|
||||
is CalendarEvent -> {
|
||||
CalendarItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.combinedClickable(
|
||||
enabled = !showDetails,
|
||||
onClick = { showDetails = true },
|
||||
onLongClick = { showDetails = true }
|
||||
),
|
||||
enabled = !showDetails,
|
||||
onClick = { showDetails = true },
|
||||
onLongClick = { showDetails = true }
|
||||
),
|
||||
calendar = item,
|
||||
showDetails = showDetails,
|
||||
onBack = { showDetails = false }
|
||||
)
|
||||
}
|
||||
|
||||
is Location -> {
|
||||
LocationItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.combinedClickable(
|
||||
enabled = !showDetails,
|
||||
onClick = { showDetails = true },
|
||||
onLongClick = { showDetails = true }),
|
||||
location = item,
|
||||
showDetails = showDetails,
|
||||
onBack = { showDetails = false }
|
||||
)
|
||||
}
|
||||
|
||||
is AppShortcut -> {
|
||||
AppShortcutItem(
|
||||
shortcut = item,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.combinedClickable(
|
||||
enabled = !showDetails,
|
||||
onClick = {
|
||||
if (!viewModel.launch(context, bounds)) {
|
||||
showDetails = true
|
||||
}
|
||||
},
|
||||
onLongClick = { showDetails = true }
|
||||
),
|
||||
enabled = !showDetails,
|
||||
onClick = {
|
||||
if (!viewModel.launch(context, bounds)) {
|
||||
showDetails = true
|
||||
}
|
||||
},
|
||||
onLongClick = { showDetails = true }
|
||||
),
|
||||
showDetails = showDetails,
|
||||
onBack = { showDetails = false }
|
||||
)
|
||||
|
||||
@ -0,0 +1,569 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.location
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.EaseOutBack
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.animateValueAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.expandIn
|
||||
import androidx.compose.animation.shrinkOut
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
||||
import androidx.compose.material.icons.rounded.ArrowUpward
|
||||
import androidx.compose.material.icons.rounded.BugReport
|
||||
import androidx.compose.material.icons.rounded.Map
|
||||
import androidx.compose.material.icons.rounded.Phone
|
||||
import androidx.compose.material.icons.rounded.Star
|
||||
import androidx.compose.material.icons.rounded.StarOutline
|
||||
import androidx.compose.material.icons.rounded.TravelExplore
|
||||
import androidx.compose.material.icons.twotone.CloudOff
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.roundToIntRect
|
||||
import androidx.compose.ui.unit.times
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import de.mm20.launcher2.i18n.R
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.search.Location
|
||||
import de.mm20.launcher2.ui.animation.animateHorizontalAlignmentAsState
|
||||
import de.mm20.launcher2.ui.animation.animateTextStyleAsState
|
||||
import de.mm20.launcher2.ui.component.DefaultToolbarAction
|
||||
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
|
||||
import de.mm20.launcher2.ui.component.Toolbar
|
||||
import de.mm20.launcher2.ui.component.ToolbarAction
|
||||
import de.mm20.launcher2.ui.ktx.DegreesConverter
|
||||
import de.mm20.launcher2.ui.ktx.metersToLocalizedString
|
||||
import de.mm20.launcher2.ui.ktx.toPixels
|
||||
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
||||
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
||||
import de.mm20.launcher2.ui.modifier.scale
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.DayOfWeek
|
||||
import java.time.Duration
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.time.format.TextStyle
|
||||
import kotlin.math.pow
|
||||
|
||||
@Composable
|
||||
fun LocationItem(
|
||||
modifier: Modifier = Modifier,
|
||||
location: Location,
|
||||
showDetails: Boolean,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val viewModel: SearchableItemVM = listItemViewModel(key = "search-${location.key}")
|
||||
val iconSize = LocalGridSettings.current.iconSize.dp.toPixels()
|
||||
|
||||
val userLocation by remember {
|
||||
viewModel.devicePoseProvider.getLocation()
|
||||
}.collectAsStateWithLifecycle(viewModel.devicePoseProvider.lastLocation)
|
||||
val insaneUnits by viewModel.useInsaneUnits.collectAsState()
|
||||
|
||||
val isUpToDate by viewModel.isUpToDate.collectAsState()
|
||||
|
||||
val distance = userLocation?.distanceTo(location.toAndroidLocation())
|
||||
|
||||
var showBugreportDialog by remember { mutableStateOf(false) }
|
||||
|
||||
Row(modifier = modifier) {
|
||||
Column {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp, bottom = 8.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
val icon by viewModel.icon.collectAsStateWithLifecycle()
|
||||
val badge by viewModel.badge.collectAsState(null)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(52.dp)
|
||||
.aspectRatio(1f)
|
||||
) {
|
||||
ShapedLauncherIcon(
|
||||
size = 48.dp,
|
||||
icon = { icon },
|
||||
badge = { badge },
|
||||
)
|
||||
val targetIconAnimationValue = if (isUpToDate) 0f else 1f
|
||||
val animatedIconAlpha by animateFloatAsState(
|
||||
targetValue = targetIconAnimationValue,
|
||||
animationSpec = tween(delayMillis = 275)
|
||||
)
|
||||
val animatedIconSize by animateDpAsState(
|
||||
targetValue = targetIconAnimationValue * 20.dp,
|
||||
animationSpec = tween(delayMillis = 275, easing = EaseOutBack)
|
||||
)
|
||||
Box(
|
||||
Modifier
|
||||
.size(22.dp)
|
||||
.align(Alignment.BottomEnd)
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.size(animatedIconSize)
|
||||
.alpha(animatedIconAlpha)
|
||||
.align(Alignment.Center)
|
||||
.clickable(!isUpToDate) {
|
||||
Toast
|
||||
.makeText(
|
||||
context,
|
||||
R.string.cached_searchable,
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
},
|
||||
imageVector = Icons.TwoTone.CloudOff,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(.75f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
val textStyle by animateTextStyleAsState(
|
||||
if (showDetails) MaterialTheme.typography.titleMedium
|
||||
else MaterialTheme.typography.titleSmall
|
||||
)
|
||||
val titleAlignment by animateHorizontalAlignmentAsState(
|
||||
targetAlignment = if (showDetails) Alignment.CenterHorizontally else Alignment.Start
|
||||
)
|
||||
Text(
|
||||
text = location.labelOverride ?: location.label,
|
||||
modifier = Modifier.align(titleAlignment),
|
||||
style = textStyle,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = true,
|
||||
)
|
||||
if (!location.openingSchedule?.openingHours.isNullOrEmpty()) {
|
||||
val isOpen = location.openingSchedule!!.isOpen
|
||||
AnimatedVisibility(!showDetails) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
text = context.getString(if (isOpen) R.string.location_open else R.string.location_closed),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = if (isOpen) MaterialTheme.colorScheme.tertiary else MaterialTheme.colorScheme.secondary,
|
||||
textAlign = TextAlign.Start,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.padding(end = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.SpaceAround,
|
||||
) {
|
||||
val targetHeading by remember(userLocation, location) {
|
||||
if (userLocation != null)
|
||||
viewModel.devicePoseProvider.getHeadingToDegrees(
|
||||
userLocation!!.bearingTo(
|
||||
location.toAndroidLocation()
|
||||
)
|
||||
)
|
||||
else
|
||||
emptyFlow()
|
||||
}.collectAsStateWithLifecycle(null)
|
||||
|
||||
if (targetHeading != null) {
|
||||
val directionArrowAngle by animateValueAsState(
|
||||
targetValue = targetHeading!!,
|
||||
typeConverter = Float.DegreesConverter
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.rotate(directionArrowAngle),
|
||||
imageVector = Icons.Rounded.ArrowUpward,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
if (distance != null) {
|
||||
Text(
|
||||
text = distance.metersToLocalizedString(
|
||||
context, insaneUnits
|
||||
), style = MaterialTheme.typography.labelSmall
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(showDetails) {
|
||||
Column {
|
||||
val isTwentyFourSeven = location.openingSchedule?.isTwentyFourSeven ?: false
|
||||
val hasOpeningHours = !location.openingSchedule?.openingHours.isNullOrEmpty()
|
||||
val daysOfWeek = enumValues<DayOfWeek>()
|
||||
|
||||
val javaLocale = java.util.Locale.forLanguageTag(Locale.current.toLanguageTag())
|
||||
val timeFormatter = DateTimeFormatter
|
||||
.ofLocalizedTime(FormatStyle.SHORT)
|
||||
.withLocale(javaLocale)
|
||||
|
||||
if (isTwentyFourSeven) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(bottom = 8.dp),
|
||||
text = stringResource(id = R.string.location_open_24_7),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.tertiary,
|
||||
)
|
||||
} else if (hasOpeningHours) {
|
||||
val oh = location.openingSchedule!!.openingHours
|
||||
val openIndex = oh.indexOfFirst { it.isOpen }
|
||||
if (openIndex != -1) {
|
||||
val todaySchedule = oh[openIndex]
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(bottom = 8.dp),
|
||||
text = stringResource(
|
||||
R.string.location_open_until,
|
||||
(todaySchedule.startTime + todaySchedule.duration).format(
|
||||
timeFormatter
|
||||
)
|
||||
),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val showMap by viewModel.showMap.collectAsState()
|
||||
if (showMap) {
|
||||
val zoomLevel = 19
|
||||
val nTiles = 4
|
||||
|
||||
val tileServerUrl by viewModel.mapTileServerUrl.collectAsState()
|
||||
val shape = MaterialTheme.shapes.small
|
||||
|
||||
val applyTheming by viewModel.applyMapTheming.collectAsState()
|
||||
val showPositionOnMap by viewModel.showPositionOnMap.collectAsState()
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
MapTiles(
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp, bottom = 8.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.fillMaxWidth(.9125f)
|
||||
.aspectRatio(1f)
|
||||
.border(1.dp, MaterialTheme.colorScheme.outline, shape)
|
||||
.clip(shape)
|
||||
.clickable {
|
||||
viewModel.launch(context)
|
||||
},
|
||||
tileServerUrl = tileServerUrl,
|
||||
location = location,
|
||||
initialZoomLevel = zoomLevel,
|
||||
numberOfTiles = nTiles,
|
||||
applyTheming = applyTheming,
|
||||
userLocation = if (showPositionOnMap) userLocation?.let {
|
||||
UserLocation(
|
||||
it.latitude,
|
||||
it.longitude
|
||||
)
|
||||
} else null,
|
||||
)
|
||||
|
||||
val address = buildAddress(location.street, location.houseNumber)
|
||||
if (address != null) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(bottom = 8.dp),
|
||||
text = address,
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.secondary
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider(Modifier.padding(top = 8.dp))
|
||||
|
||||
if (!isTwentyFourSeven && hasOpeningHours) {
|
||||
val today = LocalDateTime.now().dayOfWeek
|
||||
val oh = location.openingSchedule!!.openingHours
|
||||
val nextOpeningTime =
|
||||
(0..DayOfWeek.SUNDAY.ordinal)
|
||||
.firstNotNullOfOrNull {
|
||||
val dow =
|
||||
daysOfWeek[(today.ordinal + it) % (DayOfWeek.SUNDAY.ordinal + 1)]
|
||||
oh.filter {
|
||||
it.dayOfWeek == dow
|
||||
}.firstOrNull {
|
||||
it.dayOfWeek != today || it.startTime.isAfter(LocalTime.now())
|
||||
}
|
||||
} ?: oh.first()
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(top = 8.dp),
|
||||
text = stringResource(
|
||||
if (nextOpeningTime.dayOfWeek == today) R.string.location_open_next
|
||||
else R.string.location_open_next_day,
|
||||
if (nextOpeningTime.dayOfWeek == today) {
|
||||
val untilOpenToday = Duration.between(
|
||||
LocalTime.now(),
|
||||
nextOpeningTime.startTime,
|
||||
)
|
||||
val hours = untilOpenToday.toHours()
|
||||
val minutes = untilOpenToday.toMinutes() % 60L
|
||||
if (hours > 0L) "${hours}h ${minutes}m"
|
||||
else "${minutes}m"
|
||||
} else "${
|
||||
nextOpeningTime.dayOfWeek.getDisplayName(
|
||||
TextStyle.FULL_STANDALONE,
|
||||
javaLocale
|
||||
)
|
||||
} ${nextOpeningTime.startTime.format(timeFormatter)}"
|
||||
),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
|
||||
val toolbarActions = mutableListOf<ToolbarAction>()
|
||||
|
||||
if (LocalFavoritesEnabled.current) {
|
||||
val isPinned by viewModel.isPinned.collectAsState(false)
|
||||
val favAction = if (isPinned) {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_favorites_unpin),
|
||||
icon = Icons.Rounded.Star,
|
||||
action = {
|
||||
viewModel.unpin()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_favorites_pin),
|
||||
icon = Icons.Rounded.StarOutline,
|
||||
action = {
|
||||
viewModel.pin()
|
||||
})
|
||||
}
|
||||
toolbarActions.add(favAction)
|
||||
}
|
||||
|
||||
if (!showMap) {
|
||||
toolbarActions += DefaultToolbarAction(
|
||||
label = stringResource(id = R.string.menu_map),
|
||||
icon = Icons.Rounded.Map
|
||||
) {
|
||||
viewModel.launch(context)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
location.phoneNumber?.let {
|
||||
toolbarActions += DefaultToolbarAction(
|
||||
label = stringResource(id = R.string.menu_dial),
|
||||
icon = Icons.Rounded.Phone
|
||||
) {
|
||||
viewModel.viewModelScope.launch {
|
||||
context.tryStartActivity(
|
||||
Intent(
|
||||
Intent.ACTION_DIAL, Uri.parse("tel:$it")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
location.websiteUrl?.let {
|
||||
toolbarActions += DefaultToolbarAction(
|
||||
label = stringResource(id = R.string.menu_website),
|
||||
icon = Icons.Rounded.TravelExplore
|
||||
) {
|
||||
viewModel.viewModelScope.launch {
|
||||
context.tryStartActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW, Uri.parse(it)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
location.fixMeUrl?.let {
|
||||
toolbarActions += DefaultToolbarAction(
|
||||
label = stringResource(id = R.string.menu_bugreport),
|
||||
icon = Icons.Rounded.BugReport,
|
||||
) {
|
||||
showBugreportDialog = true
|
||||
}
|
||||
}
|
||||
|
||||
Toolbar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
leftActions = listOf(DefaultToolbarAction(
|
||||
label = stringResource(id = R.string.menu_back),
|
||||
icon = Icons.AutoMirrored.Rounded.ArrowBack
|
||||
) {
|
||||
onBack()
|
||||
}),
|
||||
rightActions = toolbarActions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showBugreportDialog && location.fixMeUrl != null) {
|
||||
AlertDialog(
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
tonalElevation = 35.dp,
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = { showBugreportDialog = false },
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = android.R.string.ok),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
)
|
||||
}
|
||||
},
|
||||
onDismissRequest = {
|
||||
showBugreportDialog = false
|
||||
},
|
||||
text = {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.alert_bugreport),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
softWrap = true,
|
||||
textAlign = TextAlign.Justify
|
||||
)
|
||||
HorizontalDivider(Modifier.padding(vertical = 8.dp))
|
||||
Text(
|
||||
modifier = modifier.clickable {
|
||||
showBugreportDialog = false
|
||||
viewModel.viewModelScope.launch {
|
||||
context.tryStartActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW, Uri.parse(location.fixMeUrl)
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
text = location.fixMeUrl!!,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LocationItemGridPopup(
|
||||
location: Location,
|
||||
show: MutableTransitionState<Boolean>,
|
||||
animationProgress: Float,
|
||||
origin: Rect,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
show,
|
||||
enter = expandIn(
|
||||
animationSpec = tween(300),
|
||||
expandFrom = Alignment.TopEnd,
|
||||
) { origin.roundToIntRect().size },
|
||||
exit = shrinkOut(
|
||||
animationSpec = tween(300),
|
||||
shrinkTowards = Alignment.TopEnd,
|
||||
) { origin.roundToIntRect().size },
|
||||
) {
|
||||
LocationItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.scale(
|
||||
1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress),
|
||||
transformOrigin = TransformOrigin(1f, 0f)
|
||||
)
|
||||
.offset(
|
||||
x = 16.dp * (1 - animationProgress).pow(10),
|
||||
y = (-16).dp * (1 - animationProgress),
|
||||
),
|
||||
location = location,
|
||||
showDetails = true,
|
||||
onBack = onDismiss,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildAddress(
|
||||
street: String?,
|
||||
houseNumber: String?,
|
||||
): String? {
|
||||
val summary = StringBuilder()
|
||||
if (street != null) {
|
||||
summary.append(street, ' ')
|
||||
if (houseNumber != null) {
|
||||
summary.append(houseNumber, ' ')
|
||||
}
|
||||
}
|
||||
return if (summary.isEmpty()) null else summary.toString()
|
||||
}
|
||||
@ -0,0 +1,582 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.location
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.core.EaseInOutCirc
|
||||
import androidx.compose.animation.core.EaseInOutSine
|
||||
import androidx.compose.animation.core.RepeatMode
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.animateOffsetAsState
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableIntState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import androidx.compose.ui.graphics.FilterQuality
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.drawText
|
||||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.minus
|
||||
import coil.ImageLoader
|
||||
import coil.compose.AsyncImage
|
||||
import coil.compose.AsyncImagePainter
|
||||
import coil.disk.DiskCache
|
||||
import coil.memory.MemoryCache
|
||||
import coil.request.CachePolicy
|
||||
import coil.request.ImageRequest
|
||||
import de.mm20.launcher2.ktx.PI
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.search.Location
|
||||
import de.mm20.launcher2.search.LocationCategory
|
||||
import de.mm20.launcher2.search.OpeningHours
|
||||
import de.mm20.launcher2.search.OpeningSchedule
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.SearchableSerializer
|
||||
import de.mm20.launcher2.ui.ktx.contrast
|
||||
import de.mm20.launcher2.ui.ktx.hue
|
||||
import de.mm20.launcher2.ui.ktx.hueRotate
|
||||
import de.mm20.launcher2.ui.ktx.invert
|
||||
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koin.core.context.GlobalContext
|
||||
import org.koin.core.context.startKoin
|
||||
import kotlin.math.asinh
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sqrt
|
||||
import kotlin.math.tan
|
||||
|
||||
data class UserLocation(val lat: Double, val lon: Double)
|
||||
|
||||
@Composable
|
||||
fun MapTiles(
|
||||
tileServerUrl: String,
|
||||
location: Location,
|
||||
initialZoomLevel: Int,
|
||||
numberOfTiles: Int,
|
||||
userLocation: UserLocation?,
|
||||
applyTheming: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
// https://wiki.openstreetmap.org/wiki/Attribution_guidelines/2021-06-04_draft#Attribution_text
|
||||
osmAttribution: String? = "© OpenStreetMap",
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val tintColor = MaterialTheme.colorScheme.surface
|
||||
val darkMode = LocalDarkTheme.current
|
||||
|
||||
val previousZoomLevel = remember { mutableIntStateOf(-1) }
|
||||
val (start, stop, zoom) = remember(userLocation) {
|
||||
userLocation
|
||||
?.runCatching {
|
||||
getEnclosingTiles(
|
||||
location,
|
||||
numberOfTiles,
|
||||
this,
|
||||
previousZoomLevel
|
||||
)
|
||||
}
|
||||
?.onFailure {
|
||||
Log.e("MapTiles", "Enclosing calculation failed", it)
|
||||
}
|
||||
?.getOrNull()
|
||||
?: getTilesAround(location, initialZoomLevel, numberOfTiles)
|
||||
}
|
||||
|
||||
val sideLength = stop.x - start.x + 1
|
||||
|
||||
val imageStates = remember { (0 until numberOfTiles).map { false }.toMutableStateList() }
|
||||
|
||||
val colorMatrix = remember(applyTheming, darkMode, tintColor) {
|
||||
// darkreader css for openstreetmap tiles
|
||||
// invert(93.7%) hue-rotate(180deg) contrast(90.6%)
|
||||
val tintHueDeg = tintColor.hue * 180f / Float.PI
|
||||
|
||||
if (!darkMode && applyTheming) {
|
||||
ColorMatrix()
|
||||
.hueRotate(tintHueDeg)
|
||||
} else if (darkMode) {
|
||||
ColorMatrix()
|
||||
.invert(0.937f)
|
||||
.hueRotate(180f + if (applyTheming) tintHueDeg else 0f)
|
||||
.contrast(0.906f)
|
||||
} else null
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = modifier,
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Column(modifier = Modifier.matchParentSize()) {
|
||||
for (y in start.y..stop.y) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f / sideLength)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
for (x in start.x..stop.x) {
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.weight(1f / sideLength)
|
||||
.fillMaxSize(),
|
||||
imageLoader = MapTileLoader.loader,
|
||||
model = MapTileLoader.getTileRequest(tileServerUrl, x, y, zoom),
|
||||
contentDescription = null,
|
||||
colorFilter = colorMatrix?.let { ColorFilter.colorMatrix(it) },
|
||||
filterQuality = FilterQuality.High,
|
||||
onState = {
|
||||
val stateIndex =
|
||||
(y - start.y) * (stop.y - start.y + 1) + (x - start.x)
|
||||
when (it) {
|
||||
is AsyncImagePainter.State.Loading -> imageStates[stateIndex] =
|
||||
false
|
||||
|
||||
is AsyncImagePainter.State.Success -> imageStates[stateIndex] =
|
||||
true
|
||||
|
||||
is AsyncImagePainter.State.Error -> {
|
||||
imageStates[stateIndex] = false
|
||||
Log.e(
|
||||
"MapTiles",
|
||||
"Error loading tile: $x, $y @$zoom",
|
||||
it.result.throwable
|
||||
)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageStates.all { it }) {
|
||||
val locationBorderColor =
|
||||
if (applyTheming) MaterialTheme.colorScheme.error else Color(0xFFEFA521) // orange-ish
|
||||
val userLocationColor =
|
||||
if (applyTheming) MaterialTheme.colorScheme.onErrorContainer else Color(0xFF35A82C) // darkish green
|
||||
val userLocationBorderColor =
|
||||
if (applyTheming) {
|
||||
MaterialTheme.colorScheme.errorContainer
|
||||
} else if (darkMode) {
|
||||
Color(0xFF777777)
|
||||
} else {
|
||||
Color(0xFFE5E5E5)
|
||||
}
|
||||
|
||||
val infiniteTransition = rememberInfiniteTransition("infiniteTransition")
|
||||
val userLocAnimation by infiniteTransition.animateFloat(
|
||||
initialValue = 0.8f,
|
||||
targetValue = 1f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(2000, easing = EaseInOutSine),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
),
|
||||
label = "userLocAnimation"
|
||||
)
|
||||
val poiLocAnimation by infiniteTransition.animateFloat(
|
||||
initialValue = 30f,
|
||||
targetValue = 20f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(750, easing = EaseInOutCirc),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
),
|
||||
label = "poiLocAnimation"
|
||||
)
|
||||
|
||||
val textMeasurer = rememberTextMeasurer()
|
||||
val osmAttributionTextStyle = MaterialTheme.typography.labelSmall
|
||||
val osmAttributionTextColor = MaterialTheme.colorScheme.onSurface
|
||||
val osmAttributionSurface =
|
||||
MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = .5f)
|
||||
|
||||
val (yLocation, xLocation) = remember(location, zoom) {
|
||||
getDoubleTileCoordinates(
|
||||
latitude = location.latitude,
|
||||
longitude = location.longitude,
|
||||
zoom
|
||||
)
|
||||
}
|
||||
val (yUser, xUser) = remember(userLocation, zoom) {
|
||||
if (userLocation != null) {
|
||||
getDoubleTileCoordinates(
|
||||
latitude = userLocation.lat,
|
||||
longitude = userLocation.lon,
|
||||
zoom
|
||||
)
|
||||
} else {
|
||||
-1.0 to -1.0
|
||||
}
|
||||
}
|
||||
val animatedUserIndicatorOffset by animateOffsetAsState(
|
||||
targetValue = (Offset(
|
||||
xUser.toFloat(),
|
||||
yUser.toFloat()
|
||||
) - start) / sideLength.toFloat(),
|
||||
animationSpec = tween(
|
||||
1000,
|
||||
250
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Canvas(modifier = Modifier.matchParentSize()) {
|
||||
assert(size.width == size.height)
|
||||
|
||||
if (userLocation != null) {
|
||||
if (start.y < yUser && yUser < stop.y + 1 &&
|
||||
start.x < xUser && xUser < stop.x + 1
|
||||
) {
|
||||
val userIndicatorOffset = animatedUserIndicatorOffset * size.width
|
||||
drawCircle(
|
||||
color = userLocationBorderColor,
|
||||
radius = 18.5f * userLocAnimation,
|
||||
center = userIndicatorOffset,
|
||||
alpha = (userLocAnimation - 0.8f) * 5f
|
||||
)
|
||||
drawCircle(
|
||||
color = userLocationColor,
|
||||
radius = 13.5f * userLocAnimation,
|
||||
center = userIndicatorOffset,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val locationIndicatorOffset =
|
||||
(Offset(
|
||||
xLocation.toFloat(),
|
||||
yLocation.toFloat()
|
||||
) - start) / sideLength.toFloat() * size.width
|
||||
drawCircle(
|
||||
color = locationBorderColor,
|
||||
radius = poiLocAnimation,
|
||||
center = locationIndicatorOffset,
|
||||
style = Stroke(width = 4f)
|
||||
)
|
||||
if (osmAttribution != null) {
|
||||
val measureResult = textMeasurer.measure(
|
||||
osmAttribution,
|
||||
maxLines = 1,
|
||||
style = osmAttributionTextStyle
|
||||
)
|
||||
val osmLabelPadding = 6f
|
||||
val textOffset = Offset(
|
||||
x = size.width - measureResult.size.width - osmLabelPadding,
|
||||
y = size.height - measureResult.size.height - osmLabelPadding
|
||||
)
|
||||
drawRoundRect(
|
||||
color = osmAttributionSurface,
|
||||
topLeft = textOffset - Offset(osmLabelPadding, 0f),
|
||||
size = Size(
|
||||
width = measureResult.size.width + 2 * osmLabelPadding,
|
||||
height = measureResult.size.height + osmLabelPadding
|
||||
),
|
||||
cornerRadius = CornerRadius(8f, 8f)
|
||||
)
|
||||
drawText(
|
||||
measureResult,
|
||||
color = osmAttributionTextColor,
|
||||
topLeft = textOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val loadingColor = MaterialTheme.colorScheme.secondary
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.fillMaxSize(.15f),
|
||||
color = loadingColor,
|
||||
strokeCap = StrokeCap.Round,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDoubleTileCoordinates(
|
||||
latitude: Double,
|
||||
longitude: Double,
|
||||
zoomLevel: Int
|
||||
): Pair<Double, Double> {
|
||||
// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Mathematics
|
||||
val latRadians = Math.toRadians(latitude)
|
||||
val xCoordinate = (longitude + 180.0) / 360.0 * (1 shl zoomLevel)
|
||||
val yCoordinate = (1.0 - asinh(tan(latRadians)) / Math.PI) * (1 shl (zoomLevel - 1))
|
||||
|
||||
return yCoordinate to xCoordinate
|
||||
}
|
||||
|
||||
data class TileCoordinateRange(val start: IntOffset, val stop: IntOffset, val zoomLevel: Int)
|
||||
|
||||
private fun getTilesAround(
|
||||
location: Location,
|
||||
zoomLevel: Int,
|
||||
nTiles: Int
|
||||
): TileCoordinateRange {
|
||||
if (sqrt(nTiles.toDouble()) % 1.0 != 0.0)
|
||||
throw IllegalArgumentException("nTiles must be a square number")
|
||||
|
||||
val sideLen = sqrt(nTiles.toDouble()).toInt()
|
||||
val sideLenHalf = sideLen / 2
|
||||
|
||||
val (yCoordinate, xCoordinate) = getDoubleTileCoordinates(
|
||||
location.latitude,
|
||||
location.longitude,
|
||||
zoomLevel
|
||||
)
|
||||
val xTile = xCoordinate.toInt()
|
||||
val yTile = yCoordinate.toInt()
|
||||
|
||||
val yStart: Int
|
||||
val yStop: Int
|
||||
val xStart: Int
|
||||
val xStop: Int
|
||||
|
||||
if (sideLen % 2 == 1) {
|
||||
// center tile is defined
|
||||
yStart = yTile - sideLenHalf
|
||||
yStop = yTile + sideLenHalf
|
||||
xStart = xTile - sideLenHalf
|
||||
xStop = xTile + sideLenHalf
|
||||
} else {
|
||||
// center tile is not defined; take adjacent tiles closest to coordinate of interest
|
||||
val leftOfCenter = (xCoordinate % 1.0) < 0.5
|
||||
val topOfCenter = (yCoordinate % 1.0) < 0.5
|
||||
|
||||
yStart = if (topOfCenter) yTile - sideLenHalf else yTile - sideLenHalf + 1
|
||||
yStop = if (topOfCenter) yTile + sideLenHalf - 1 else yTile + sideLenHalf
|
||||
xStart = if (leftOfCenter) xTile - sideLenHalf else xTile - sideLenHalf + 1
|
||||
xStop = if (leftOfCenter) xTile + sideLenHalf - 1 else xTile + sideLenHalf
|
||||
}
|
||||
|
||||
return TileCoordinateRange(IntOffset(xStart, yStart), IntOffset(xStop, yStop), zoomLevel)
|
||||
}
|
||||
|
||||
const val ZOOM_MAX = 19
|
||||
const val ZOOM_MIN = 0
|
||||
|
||||
private fun getEnclosingTiles(
|
||||
location: Location,
|
||||
nTiles: Int,
|
||||
userLocation: UserLocation,
|
||||
previousZoomLevel: MutableIntState,
|
||||
): TileCoordinateRange {
|
||||
if (sqrt(nTiles.toDouble()) % 1.0 != 0.0)
|
||||
throw IllegalArgumentException("nTiles must be a square number")
|
||||
|
||||
val sideLen = sqrt(nTiles.toDouble()).toInt()
|
||||
val sideLenHalf = sideLen / 2
|
||||
|
||||
// start at previous zoom (+1) to do less calculations, because if
|
||||
// - user comes closer to location:
|
||||
// we might be able to increase the zoom level by one
|
||||
// - user moves further away from location:
|
||||
// we still iterate down to minimum zoom and there is no need to start with ZOOM_MAX for that
|
||||
for (zoomLevel in previousZoomLevel
|
||||
.intValue
|
||||
.let { if (it == -1) ZOOM_MAX else min(it + 1, ZOOM_MAX) } downTo ZOOM_MIN
|
||||
) {
|
||||
|
||||
val (locationY, locationX) = getDoubleTileCoordinates(
|
||||
location.latitude,
|
||||
location.longitude,
|
||||
zoomLevel
|
||||
)
|
||||
val (userY, userX) = getDoubleTileCoordinates(
|
||||
userLocation.lat,
|
||||
userLocation.lon,
|
||||
zoomLevel
|
||||
)
|
||||
|
||||
val (locationTileY, locationTileX) = locationY.toInt() to locationX.toInt()
|
||||
val (userTileY, userTileX) = userY.toInt() to userX.toInt()
|
||||
|
||||
if (locationTileY - sideLenHalf <= userTileY && userTileY <= locationTileY + sideLenHalf &&
|
||||
locationTileX - sideLenHalf <= userTileX && userTileX <= locationTileX + sideLenHalf
|
||||
) {
|
||||
var xStart = min(locationTileX, userTileX)
|
||||
var yStart = min(locationTileY, userTileY)
|
||||
var xStop = max(locationTileX, userTileX)
|
||||
var yStop = max(locationTileY, userTileY)
|
||||
|
||||
val xRem = sideLen - xStop + xStart - 1
|
||||
if (0 < xRem) {
|
||||
val leftOfCenter = (locationX % 1.0) < 0.5
|
||||
val ceil = ceil(xRem / 2.0).toInt()
|
||||
val floor = floor(xRem / 2.0).toInt()
|
||||
|
||||
if (leftOfCenter) {
|
||||
xStart -= ceil
|
||||
xStop += floor
|
||||
} else {
|
||||
xStart -= floor
|
||||
xStop += ceil
|
||||
}
|
||||
}
|
||||
val yRem = sideLen - yStop + yStart - 1
|
||||
if (0 < yRem) {
|
||||
val topOfCenter = (locationY % 1.0) < 0.5
|
||||
val ceil = ceil(yRem / 2.0).toInt()
|
||||
val floor = floor(yRem / 2.0).toInt()
|
||||
|
||||
if (topOfCenter) {
|
||||
yStart -= ceil
|
||||
yStop += floor
|
||||
} else {
|
||||
yStart -= floor
|
||||
yStop += ceil
|
||||
}
|
||||
}
|
||||
|
||||
previousZoomLevel.intValue = zoomLevel
|
||||
|
||||
return TileCoordinateRange(
|
||||
IntOffset(xStart, yStart),
|
||||
IntOffset(xStop, yStop),
|
||||
zoomLevel
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
throw IllegalStateException("Unreachable (right?) | lat: ${location.latitude} | lon: ${location.longitude} | user: $userLocation | nTiles: $nTiles")
|
||||
}
|
||||
|
||||
private object MapTileLoader : KoinComponent {
|
||||
private val context: Context by inject()
|
||||
|
||||
private val userAgent = "${context.packageName}/${
|
||||
context.packageManager.getPackageInfo(
|
||||
context.packageName,
|
||||
0
|
||||
)?.versionName ?: "dev"
|
||||
}"
|
||||
fun getTileRequest(tileServerUrl: String, x: Int, y: Int, zoom: Int): ImageRequest {
|
||||
return ImageRequest.Builder(context)
|
||||
.data("$tileServerUrl/$zoom/$x/$y.png")
|
||||
.addHeader(
|
||||
"User-Agent",
|
||||
userAgent
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
val loader = ImageLoader
|
||||
.Builder(context)
|
||||
.memoryCache {
|
||||
MemoryCache.Builder(context)
|
||||
.maxSizePercent(0.05)
|
||||
.build()
|
||||
}
|
||||
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||
.diskCache {
|
||||
DiskCache.Builder()
|
||||
.directory(context.cacheDir.resolve("osm_tiles"))
|
||||
.maxSizePercent(0.01)
|
||||
.build()
|
||||
}
|
||||
.diskCachePolicy(CachePolicy.ENABLED)
|
||||
.respectCacheHeaders(true)
|
||||
.networkCachePolicy(CachePolicy.ENABLED)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun MapTilesPreview() {
|
||||
val context = LocalContext.current
|
||||
|
||||
if (GlobalContext.getKoinApplicationOrNull() == null) {
|
||||
startKoin {
|
||||
androidContext(context)
|
||||
}
|
||||
}
|
||||
|
||||
val borderShape = MaterialTheme.shapes.medium
|
||||
|
||||
MapTiles(
|
||||
modifier = Modifier
|
||||
.size(300.dp)
|
||||
.border(
|
||||
BorderStroke(1.dp, MaterialTheme.colorScheme.outline),
|
||||
borderShape
|
||||
)
|
||||
.clip(borderShape),
|
||||
tileServerUrl = "http://tile.openstreetmap.org",
|
||||
location = MockLocation,
|
||||
initialZoomLevel = 19,
|
||||
numberOfTiles = 9,
|
||||
applyTheming = false,
|
||||
userLocation = UserLocation(52.51623, 13.4048)
|
||||
)
|
||||
}
|
||||
|
||||
internal object MockLocation : Location {
|
||||
|
||||
override val domain: String = "MOCKLOCATION"
|
||||
override val key: String = "MOCKLOCATION"
|
||||
override val label: String = "Brandenburger Tor"
|
||||
override val fixMeUrl: String = "https://www.openstreetmap.org/fixthemap"
|
||||
|
||||
override val latitude = 52.5162700
|
||||
override val longitude = 13.3777021
|
||||
|
||||
override var category: LocationCategory? = LocationCategory.OTHER
|
||||
|
||||
override val street: String = "Pariser Platz"
|
||||
|
||||
override val houseNumber: String = "1"
|
||||
|
||||
override val openingSchedule: OpeningSchedule =
|
||||
OpeningSchedule(true, emptyList<OpeningHours>().toImmutableList())
|
||||
|
||||
override val websiteUrl: String = "https://en.wikipedia.org/wiki/Brandenburg_Gate"
|
||||
|
||||
override val phoneNumber: String = "+49 1234567"
|
||||
|
||||
override fun overrideLabel(label: String): SavableSearchable = TODO()
|
||||
|
||||
override fun launch(context: Context, options: Bundle?): Boolean =
|
||||
context.tryStartActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("https://en.wikipedia.org/wiki/Brandenburg_Gate")
|
||||
)
|
||||
)
|
||||
|
||||
override fun getSerializer(): SearchableSerializer = TODO()
|
||||
}
|
||||
@ -48,6 +48,7 @@ import de.mm20.launcher2.ui.settings.homescreen.HomescreenSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.icons.IconsSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.integrations.IntegrationsSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.license.LicenseScreen
|
||||
import de.mm20.launcher2.ui.settings.locations.LocationsSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.log.LogScreen
|
||||
import de.mm20.launcher2.ui.settings.main.MainSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.media.MediaIntegrationSettingsScreen
|
||||
@ -151,6 +152,9 @@ class SettingsActivity : BaseActivity() {
|
||||
composable("settings/search/wikipedia") {
|
||||
WikipediaSettingsScreen()
|
||||
}
|
||||
composable("settings/search/locations") {
|
||||
LocationsSettingsScreen()
|
||||
}
|
||||
composable("settings/search/files") {
|
||||
FileSearchSettingsScreen()
|
||||
}
|
||||
|
||||
@ -0,0 +1,158 @@
|
||||
package de.mm20.launcher2.ui.settings.locations
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.preferences.search.LocationSearchSettings
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.preferences.ListPreference
|
||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||
import de.mm20.launcher2.ui.component.preferences.SliderPreference
|
||||
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||
import de.mm20.launcher2.ui.component.preferences.TextPreference
|
||||
import de.mm20.launcher2.ui.ktx.metersToLocalizedString
|
||||
|
||||
@Composable
|
||||
fun LocationsSettingsScreen() {
|
||||
val viewModel: LocationsSettingsScreenVM = viewModel()
|
||||
|
||||
val locations by viewModel.locations.collectAsState()
|
||||
val imperialUnits by viewModel.imperialUnits.collectAsState()
|
||||
val hideUncategorized by viewModel.hideUncategorized.collectAsState()
|
||||
val radius by viewModel.radius.collectAsState()
|
||||
val customOverpassUrl by viewModel.customOverpassUrl.collectAsState()
|
||||
val showMap by viewModel.showMap.collectAsState()
|
||||
val themeMap by viewModel.themeMap.collectAsState()
|
||||
val showPositionOnMap by viewModel.showPositionOnMap.collectAsState()
|
||||
val customTileServerUrl by viewModel.customTileServerUrl.collectAsState()
|
||||
|
||||
|
||||
PreferenceScreen(title = stringResource(R.string.preference_search_locations)) {
|
||||
item {
|
||||
PreferenceCategory {
|
||||
SwitchPreference(
|
||||
title = stringResource(R.string.preference_search_locations),
|
||||
summary = stringResource(R.string.preference_search_locations_summary),
|
||||
value = locations == true,
|
||||
onValueChanged = {
|
||||
viewModel.setLocations(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
PreferenceCategory {
|
||||
ListPreference(
|
||||
title = stringResource(R.string.length_unit),
|
||||
items = listOf(
|
||||
stringResource(R.string.imperial) to true,
|
||||
stringResource(R.string.metric) to false
|
||||
),
|
||||
enabled = locations == true,
|
||||
value = imperialUnits,
|
||||
onValueChanged = {
|
||||
viewModel.setImperialUnits(it)
|
||||
}
|
||||
)
|
||||
SliderPreference(
|
||||
title = stringResource(R.string.preference_search_locations_radius),
|
||||
value = radius,
|
||||
min = 500,
|
||||
max = 10000,
|
||||
step = 500,
|
||||
enabled = locations == true,
|
||||
onValueChanged = {
|
||||
viewModel.setRadius(it)
|
||||
},
|
||||
label = {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.width(64.dp)
|
||||
.padding(start = 16.dp),
|
||||
text = it.toFloat()
|
||||
.metersToLocalizedString(LocalContext.current, imperialUnits),
|
||||
style = MaterialTheme.typography.titleSmall
|
||||
)
|
||||
it.toFloat()
|
||||
.metersToLocalizedString(LocalContext.current, imperialUnits)
|
||||
}
|
||||
)
|
||||
SwitchPreference(
|
||||
title = stringResource(R.string.preference_search_locations_hide_uncategorized),
|
||||
summary = stringResource(R.string.preference_search_locations_hide_uncategorized_summary),
|
||||
value = hideUncategorized == true,
|
||||
enabled = locations == true,
|
||||
onValueChanged = {
|
||||
viewModel.setHideUncategorized(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
PreferenceCategory {
|
||||
SwitchPreference(
|
||||
title = stringResource(R.string.preference_search_locations_show_map),
|
||||
summary = stringResource(R.string.preference_search_locations_show_map_summary),
|
||||
enabled = locations == true,
|
||||
value = showMap == true,
|
||||
onValueChanged = {
|
||||
viewModel.setShowMap(it)
|
||||
}
|
||||
)
|
||||
SwitchPreference(
|
||||
title = stringResource(R.string.preference_search_locations_theme_map),
|
||||
summary = stringResource(R.string.preference_search_locations_theme_map_summary),
|
||||
value = themeMap == true,
|
||||
enabled = locations == true && showMap == true,
|
||||
onValueChanged = {
|
||||
viewModel.setThemeMap(it)
|
||||
}
|
||||
)
|
||||
SwitchPreference(
|
||||
title = stringResource(R.string.preference_search_locations_show_position_on_map),
|
||||
summary = stringResource(R.string.preference_search_locations_show_position_on_map_summary),
|
||||
value = showPositionOnMap == true,
|
||||
enabled = locations == true && showMap == true,
|
||||
onValueChanged = {
|
||||
viewModel.setShowPositionOnMap(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
item {
|
||||
PreferenceCategory(stringResource(R.string.preference_category_advanced)) {
|
||||
TextPreference(
|
||||
title = stringResource(R.string.preference_search_location_custom_overpass_url),
|
||||
value = customOverpassUrl,
|
||||
placeholder = stringResource(id = R.string.overpass_url),
|
||||
summary = customOverpassUrl.takeIf { !it.isNullOrBlank() }
|
||||
?: stringResource(id = R.string.overpass_url),
|
||||
onValueChanged = {
|
||||
viewModel.setCustomOverpassUrl(it)
|
||||
}
|
||||
)
|
||||
TextPreference(
|
||||
title = stringResource(R.string.preference_search_location_custom_tile_server_url),
|
||||
value = customTileServerUrl ?: "",
|
||||
placeholder = LocationSearchSettings.DefaultTileServerUrl,
|
||||
summary = customTileServerUrl.takeIf { !it.isNullOrBlank() }
|
||||
?: LocationSearchSettings.DefaultTileServerUrl,
|
||||
onValueChanged = {
|
||||
viewModel.setCustomTileServerUrl(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package de.mm20.launcher2.ui.settings.locations
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.preferences.search.LocationSearchSettings
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class LocationsSettingsScreenVM: ViewModel(), KoinComponent {
|
||||
private val settings: LocationSearchSettings by inject()
|
||||
|
||||
val locations = settings.enabled
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
fun setLocations(openStreetMaps: Boolean) {
|
||||
settings.setEnabled(openStreetMaps)
|
||||
}
|
||||
|
||||
val imperialUnits = settings.imperialUnits
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), false)
|
||||
fun setImperialUnits(imperialUnits: Boolean) {
|
||||
settings.setImperialUnits(imperialUnits)
|
||||
}
|
||||
|
||||
val radius = settings.searchRadius
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), 1500)
|
||||
fun setRadius(radius: Int) {
|
||||
settings.setSearchRadius(radius)
|
||||
}
|
||||
|
||||
val customOverpassUrl = settings.overpassUrl
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), "")
|
||||
fun setCustomOverpassUrl(customUrl: String) {
|
||||
var url = customUrl
|
||||
if (url.endsWith('/')){
|
||||
url = url.substringBeforeLast('/')
|
||||
}
|
||||
if (url.endsWith("/api/interpreter")) {
|
||||
url = url.substringBeforeLast("/api/interpreter")
|
||||
}
|
||||
|
||||
settings.setOverpassUrl(url)
|
||||
}
|
||||
|
||||
val showMap = settings.showMap
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
fun setShowMap(showMap: Boolean) {
|
||||
settings.setShowMap(showMap)
|
||||
}
|
||||
|
||||
val showPositionOnMap = settings.showPositionOnMap
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
fun setShowPositionOnMap(showPositionOnMap: Boolean) {
|
||||
settings.setShowPositionOnMap(showPositionOnMap)
|
||||
}
|
||||
|
||||
val customTileServerUrl = settings.tileServer
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
fun setCustomTileServerUrl(customTileServerUrl: String) {
|
||||
settings.setTileServer(customTileServerUrl)
|
||||
}
|
||||
|
||||
val hideUncategorized = settings.hideUncategorized
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
fun setHideUncategorized(hideUncategorized: Boolean) {
|
||||
settings.setHideUncategorized(hideUncategorized)
|
||||
}
|
||||
|
||||
val themeMap = settings.themeMap
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
fun setThemeMap(themeMap: Boolean) {
|
||||
settings.setThemeMap(themeMap)
|
||||
}
|
||||
}
|
||||
@ -174,6 +174,20 @@ fun SearchSettingsScreen() {
|
||||
}
|
||||
)
|
||||
|
||||
val locations by viewModel.locations.collectAsStateWithLifecycle(null)
|
||||
PreferenceWithSwitch(
|
||||
title= stringResource(R.string.preference_search_locations),
|
||||
summary = stringResource(R.string.preference_search_locations_summary),
|
||||
icon = Icons.Rounded.Place,
|
||||
switchValue = locations == true,
|
||||
onSwitchChanged = {
|
||||
viewModel.setLocations(it)
|
||||
},
|
||||
onClick = {
|
||||
navController?.navigate("settings/search/locations")
|
||||
}
|
||||
)
|
||||
|
||||
Preference(
|
||||
title = stringResource(R.string.preference_screen_search_actions),
|
||||
summary = stringResource(R.string.preference_search_search_actions_summary),
|
||||
|
||||
@ -9,15 +9,14 @@ import de.mm20.launcher2.preferences.SearchResultOrder
|
||||
import de.mm20.launcher2.preferences.search.CalculatorSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.CalendarSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.ContactSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.LocationSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.ShortcutSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.UnitConverterSettings
|
||||
import de.mm20.launcher2.preferences.search.WebsiteSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.WikipediaSearchSettings
|
||||
import de.mm20.launcher2.preferences.ui.SearchUiSettings
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
@ -32,6 +31,7 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
private val calculatorSearchSettings: CalculatorSearchSettings by inject()
|
||||
|
||||
private val permissionsManager: PermissionsManager by inject()
|
||||
private val locationSearchSettings: LocationSearchSettings by inject()
|
||||
|
||||
val favorites = searchUiSettings.favorites
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
@ -95,9 +95,15 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
websiteSearchSettings.setEnabled(websites)
|
||||
}
|
||||
|
||||
val autoFocus = searchUiSettings.openKeyboard
|
||||
val locations = locationSearchSettings.enabled
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
|
||||
fun setLocations(locations: Boolean) {
|
||||
locationSearchSettings.setEnabled(locations)
|
||||
}
|
||||
|
||||
val autoFocus = searchUiSettings.openKeyboard
|
||||
|
||||
fun setAutoFocus(autoFocus: Boolean) {
|
||||
searchUiSettings.setOpenKeyboard(autoFocus)
|
||||
}
|
||||
|
||||
@ -46,7 +46,6 @@ dependencies {
|
||||
implementation(libs.materialcomponents.core)
|
||||
|
||||
implementation(libs.koin.android)
|
||||
|
||||
implementation(libs.androidx.palette)
|
||||
|
||||
implementation(project(":core:ktx"))
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
package de.mm20.launcher2.coroutines
|
||||
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
|
||||
fun <T> deferred(block: suspend () -> T): Deferred<T> {
|
||||
val deferred = CompletableDeferred<T>()
|
||||
return object : Deferred<T> by deferred {
|
||||
private val mutex = Mutex()
|
||||
override suspend fun await(): T {
|
||||
mutex.withLock {
|
||||
if (!deferred.isCompleted) {
|
||||
block().also { deferred.complete(it) }
|
||||
}
|
||||
}
|
||||
return deferred.await()
|
||||
}
|
||||
}
|
||||
}
|
||||
250
core/base/src/main/java/de/mm20/launcher2/search/Location.kt
Normal file
250
core/base/src/main/java/de/mm20/launcher2/search/Location.kt
Normal file
@ -0,0 +1,250 @@
|
||||
package de.mm20.launcher2.search
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import de.mm20.launcher2.base.R
|
||||
import de.mm20.launcher2.icons.ColorLayer
|
||||
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 java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
import android.location.Location as AndroidLocation
|
||||
|
||||
interface Location : SavableSearchable {
|
||||
|
||||
val latitude: Double
|
||||
val longitude: Double
|
||||
val fixMeUrl: String?
|
||||
|
||||
val category: LocationCategory?
|
||||
|
||||
val street: String?
|
||||
val houseNumber: String?
|
||||
val openingSchedule: OpeningSchedule?
|
||||
val websiteUrl: String?
|
||||
val phoneNumber: String?
|
||||
|
||||
override val preferDetailsOverLaunch: Boolean
|
||||
get() = true
|
||||
|
||||
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
|
||||
|
||||
contains(
|
||||
"ramen",
|
||||
ignoreCase = true
|
||||
) -> R.drawable.ic_location_ramen to R.color.orange
|
||||
|
||||
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_STOP -> 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
|
||||
}
|
||||
return StaticLauncherIcon(
|
||||
foregroundLayer = TintedIconLayer(
|
||||
icon = ContextCompat.getDrawable(context, resId)!!,
|
||||
scale = 0.5f,
|
||||
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 distanceTo(androidLocation: AndroidLocation): Float {
|
||||
return androidLocation.distanceTo(this.toAndroidLocation())
|
||||
}
|
||||
|
||||
fun distanceTo(otherLocation: Location): Float =
|
||||
this.distanceTo(otherLocation.toAndroidLocation())
|
||||
}
|
||||
|
||||
// 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_STOP,
|
||||
BUS_STATION,
|
||||
ATM,
|
||||
ART,
|
||||
KIOSK,
|
||||
BUS_STOP,
|
||||
MUSEUM,
|
||||
PARCEL_LOCKER,
|
||||
CHEMIST,
|
||||
TRAVEL_AGENCY,
|
||||
FITNESS_CENTRE
|
||||
}
|
||||
|
||||
data class OpeningHours(
|
||||
val dayOfWeek: DayOfWeek,
|
||||
val startTime: LocalTime,
|
||||
val duration: Duration
|
||||
) {
|
||||
val isOpen: Boolean
|
||||
get() = LocalDate.now().dayOfWeek == dayOfWeek &&
|
||||
LocalTime.now().isAfter(startTime) &&
|
||||
LocalTime.now().isBefore(startTime.plus(duration))
|
||||
|
||||
override fun toString(): String = "$dayOfWeek $startTime-${startTime.plus(duration)}"
|
||||
}
|
||||
|
||||
data class OpeningSchedule(
|
||||
val isTwentyFourSeven: Boolean,
|
||||
val openingHours: ImmutableList<OpeningHours>
|
||||
) {
|
||||
val isOpen: Boolean
|
||||
get() = isTwentyFourSeven || openingHours.any { it.isOpen }
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
package de.mm20.launcher2.search
|
||||
|
||||
import kotlinx.coroutines.Deferred
|
||||
|
||||
interface Searchable
|
||||
@ -0,0 +1,18 @@
|
||||
package de.mm20.launcher2.search
|
||||
|
||||
/**
|
||||
* Interface that can be implemented by [SavableSearchable]s to provide a way to update itself.
|
||||
* Consumers of [SavableSearchable]s can check if the [SavableSearchable] implements this interface
|
||||
* and decide to get an updated version of the [SavableSearchable] by calling [updatedSelf], which
|
||||
* returns an [UpdateResult] that contains either an up-to-date value or specifies unavailability.
|
||||
*/
|
||||
interface UpdatableSearchable<T : SavableSearchable> {
|
||||
val timestamp: Long
|
||||
val updatedSelf: (suspend () -> UpdateResult<T>)?
|
||||
}
|
||||
|
||||
sealed class UpdateResult<out T> {
|
||||
data class Success<out T>(val result: T) : UpdateResult<T>()
|
||||
data class TemporarilyUnavailable<T>(val cause: Throwable? = null) : UpdateResult<T>()
|
||||
data class PermanentlyUnavailable<T>(val cause: Throwable? = null) : UpdateResult<T>()
|
||||
}
|
||||
10
core/base/src/main/res/drawable/ic_location_alcohol.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_alcohol.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,800L200,672Q165,660 142.5,629.5Q120,599 120,560L120,280Q120,263 131.5,251.5Q143,240 160,240L320,240Q337,240 348.5,251.5Q360,263 360,280L360,560Q360,599 337.5,629.5Q315,660 280,672L280,800L320,800Q337,800 348.5,811.5Q360,823 360,840Q360,857 348.5,868.5Q337,880 320,880L160,880Q143,880 131.5,868.5Q120,857 120,840Q120,823 131.5,811.5Q143,800 160,800L200,800ZM200,440L280,440L280,320L200,320L200,440ZM240,600Q257,600 268.5,588.5Q280,577 280,560L280,520L200,520L200,560Q200,577 211.5,588.5Q223,600 240,600ZM520,880Q487,880 463.5,856.5Q440,833 440,800L440,418Q440,392 455,371.5Q470,351 494,342L532,328Q546,323 553,313.5Q560,304 560,290L560,120Q560,103 571.5,91.5Q583,80 600,80L720,80Q737,80 748.5,91.5Q760,103 760,120L760,290Q760,304 767,313.5Q774,323 788,328L826,342Q850,351 865,371.5Q880,392 880,418L880,800Q880,833 856.5,856.5Q833,880 800,880L520,880ZM640,200L680,200L680,160L640,160L640,200ZM520,480L800,480L800,418L762,404Q724,390 702,360Q680,330 680,292L680,280L640,280L640,292Q640,330 618,360Q596,390 558,404L520,418L520,480ZM520,800L800,800L800,720L520,720L520,800ZM520,640L800,640L800,560L520,560L520,640ZM240,520Q240,520 240,520Q240,520 240,520L240,520L240,520L240,520Q240,520 240,520Q240,520 240,520ZM520,640L520,560L520,560L520,640L520,640Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_art.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_art.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,880Q398,880 325,848.5Q252,817 197.5,762.5Q143,708 111.5,635Q80,562 80,480Q80,397 112.5,324Q145,251 200.5,197Q256,143 330,111.5Q404,80 488,80Q568,80 639,107.5Q710,135 763.5,183.5Q817,232 848.5,298.5Q880,365 880,442Q880,557 810,618.5Q740,680 640,680L566,680Q557,680 553.5,685Q550,690 550,696Q550,708 565,730.5Q580,753 580,782Q580,832 552.5,856Q525,880 480,880ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM260,520Q286,520 303,503Q320,486 320,460Q320,434 303,417Q286,400 260,400Q234,400 217,417Q200,434 200,460Q200,486 217,503Q234,520 260,520ZM380,360Q406,360 423,343Q440,326 440,300Q440,274 423,257Q406,240 380,240Q354,240 337,257Q320,274 320,300Q320,326 337,343Q354,360 380,360ZM580,360Q606,360 623,343Q640,326 640,300Q640,274 623,257Q606,240 580,240Q554,240 537,257Q520,274 520,300Q520,326 537,343Q554,360 580,360ZM700,520Q726,520 743,503Q760,486 760,460Q760,434 743,417Q726,400 700,400Q674,400 657,417Q640,434 640,460Q640,486 657,503Q674,520 700,520ZM480,800Q489,800 494.5,795Q500,790 500,782Q500,768 485,749Q470,730 470,692Q470,650 499,625Q528,600 570,600L640,600Q706,600 753,561.5Q800,523 800,442Q800,321 707.5,240.5Q615,160 488,160Q352,160 256,253Q160,346 160,480Q160,613 253.5,706.5Q347,800 480,800Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_atm.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_atm.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M520,560L400,560Q383,560 371.5,571.5Q360,583 360,600Q360,617 371.5,628.5Q383,640 400,640L440,640L440,640Q440,657 451.5,668.5Q463,680 480,680Q497,680 508.5,668.5Q520,657 520,640L520,640L560,640Q577,640 588.5,628.5Q600,617 600,600L600,480Q600,463 588.5,451.5Q577,440 560,440L440,440L440,400L560,400Q577,400 588.5,388.5Q600,377 600,360Q600,343 588.5,331.5Q577,320 560,320L520,320L520,320Q520,303 508.5,291.5Q497,280 480,280Q463,280 451.5,291.5Q440,303 440,320L440,320L400,320Q383,320 371.5,331.5Q360,343 360,360L360,480Q360,497 371.5,508.5Q383,520 400,520L520,520L520,560ZM160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM160,720L800,720Q800,720 800,720Q800,720 800,720L800,240Q800,240 800,240Q800,240 800,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720ZM160,720Q160,720 160,720Q160,720 160,720L160,240Q160,240 160,240Q160,240 160,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720L160,720Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_bakery.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_bakery.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M804,678Q821,687 834,674Q847,661 838,644L780,536L738,644L804,678ZM604,640L652,640L748,402Q751,394 746.5,388.5Q742,383 736,380L656,348Q647,345 638.5,350Q630,355 628,364L604,640ZM308,640L356,640L332,364Q330,353 321.5,349Q313,345 304,348L224,380Q216,383 212.5,388.5Q209,394 212,402L308,640ZM156,678L222,644L180,536L122,644Q113,661 126,674Q139,687 156,678ZM436,640L524,640L554,302Q556,293 549.5,286.5Q543,280 534,280L426,280Q418,280 411.5,286.5Q405,293 406,302L436,640ZM138,760Q96,760 68,728.5Q40,697 40,654Q40,642 43.5,630.5Q47,619 52,608L140,440Q126,400 141,361Q156,322 194,306L274,274Q288,269 302,267Q316,265 330,268Q344,239 369,219.5Q394,200 426,200L534,200Q566,200 591,219.5Q616,239 630,268Q644,266 658,267.5Q672,269 686,274L766,306Q806,322 822,361Q838,400 820,438L908,606Q914,617 917,629Q920,641 920,654Q920,699 889.5,729.5Q859,760 814,760Q803,760 792,757.5Q781,755 770,750L708,720L250,720L194,750Q181,757 166.5,758.5Q152,760 138,760ZM480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_bank.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_bank.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M237,840Q214,840 192.5,824Q171,808 164,785Q139,701 123,639.5Q107,578 97.5,531.5Q88,485 84,449Q80,413 80,380Q80,288 144,224Q208,160 300,160L500,160Q527,124 568.5,102Q610,80 660,80Q685,80 702.5,97.5Q720,115 720,140Q720,146 718.5,152Q717,158 715,163Q711,174 707.5,185Q704,196 702,209L793,300L840,300Q857,300 868.5,311.5Q880,323 880,340L880,550Q880,563 872.5,573Q865,583 852,588L767,616L717,783Q709,809 688,824.5Q667,840 640,840L560,840Q527,840 503.5,816.5Q480,793 480,760L480,760L400,760L400,760Q400,793 376.5,816.5Q353,840 320,840L237,840ZM240,760L320,760Q320,760 320,760Q320,760 320,760L320,680L560,680L560,760Q560,760 560,760Q560,760 560,760L640,760Q640,760 640,760Q640,760 640,760L702,554L800,521L800,380L760,380L620,240Q620,220 622.5,201Q625,182 630,164Q601,172 579,191.5Q557,211 547,240L300,240Q242,240 201,281Q160,322 160,380Q160,421 181,520.5Q202,620 240,760Q240,760 240,760Q240,760 240,760ZM640,440Q657,440 668.5,428.5Q680,417 680,400Q680,383 668.5,371.5Q657,360 640,360Q623,360 611.5,371.5Q600,383 600,400Q600,417 611.5,428.5Q623,440 640,440ZM480,360Q497,360 508.5,348.5Q520,337 520,320Q520,303 508.5,291.5Q497,280 480,280L360,280Q343,280 331.5,291.5Q320,303 320,320Q320,337 331.5,348.5Q343,360 360,360L480,360ZM480,462Q480,462 480,462Q480,462 480,462Q480,462 480,462Q480,462 480,462Q480,462 480,462Q480,462 480,462L480,462Q480,462 480,462Q480,462 480,462Q480,462 480,462Q480,462 480,462L480,462L480,462L480,462L480,462L480,462Q480,462 480,462Q480,462 480,462L480,462Q480,462 480,462Q480,462 480,462L480,462L480,462L480,462Q480,462 480,462Q480,462 480,462L480,462Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_bar.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_bar.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M440,760L440,560L138,220Q130,212 125,201.5Q120,191 120,180Q120,154 138,137Q156,120 182,120L778,120Q804,120 822,137Q840,154 840,180Q840,191 835,201.5Q830,212 822,220L520,560L520,760L680,760Q697,760 708.5,771.5Q720,783 720,800Q720,817 708.5,828.5Q697,840 680,840L280,840Q263,840 251.5,828.5Q240,817 240,800Q240,783 251.5,771.5Q263,760 280,760L440,760ZM298,280L662,280L734,200L226,200L298,280ZM480,484L591,360L369,360L480,484ZM480,484L480,484L480,484L480,484Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_basketball.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_basketball.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M162,440L276,440Q270,402 253,369Q236,336 210,310Q192,339 179.5,371.5Q167,404 162,440ZM684,440L798,440Q793,404 780.5,371.5Q768,339 750,310Q724,336 707,369Q690,402 684,440ZM210,650Q236,624 253,591Q270,558 276,520L162,520Q167,556 179.5,588.5Q192,621 210,650ZM750,650Q768,621 780.5,588.5Q793,556 798,520L684,520Q690,558 707,591Q724,624 750,650ZM358,440L440,440L440,162Q387,170 341.5,191.5Q296,213 260,248Q299,286 324.5,334.5Q350,383 358,440ZM520,440L602,440Q610,383 635.5,334.5Q661,286 700,248Q664,213 618.5,191.5Q573,170 520,162L520,440ZM440,798L440,520L358,520Q350,577 324.5,625.5Q299,674 260,712Q296,747 341.5,768.5Q387,790 440,798ZM520,798Q573,790 618.5,768.5Q664,747 700,712Q661,674 635.5,625.5Q610,577 602,520L520,520L520,798ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880Z"/>
|
||||
</vector>
|
||||
11
core/base/src/main/res/drawable/ic_location_bicycle.xml
Normal file
11
core/base/src/main/res/drawable/ic_location_bicycle.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,800Q115,800 57.5,742.5Q0,685 0,600Q0,515 58.5,457.5Q117,400 200,400Q277,400 329.5,446Q382,492 396,560L422,560L350,360L320,360Q303,360 291.5,348.5Q280,337 280,320Q280,303 291.5,291.5Q303,280 320,280L440,280Q457,280 468.5,291.5Q480,303 480,320Q480,337 468.5,348.5Q457,360 440,360L436,360L450,400L642,400L584,240Q584,240 584,240Q584,240 584,240L520,240Q503,240 491.5,228.5Q480,217 480,200Q480,183 491.5,171.5Q503,160 520,160L584,160Q610,160 630.5,174Q651,188 660,212L728,398L760,398Q843,398 901.5,456.5Q960,515 960,598Q960,682 902,741Q844,800 760,800Q688,800 633.5,755Q579,710 564,640L396,640Q382,709 328,754.5Q274,800 200,800ZM200,720Q241,720 270.5,697.5Q300,675 312,640L240,640Q223,640 211.5,628.5Q200,617 200,600Q200,583 211.5,571.5Q223,560 240,560L312,560Q300,524 270.5,502Q241,480 200,480Q149,480 114.5,514.5Q80,549 80,600Q80,650 114.5,685Q149,720 200,720ZM508,560L564,560Q569,537 577.5,517Q586,497 600,480L478,480L508,560ZM760,720Q811,720 845.5,685Q880,650 880,600Q880,549 845.5,514.5Q811,480 760,480Q758,480 758,480Q758,480 756,480L782,549Q788,565 781,579.5Q774,594 758,600Q742,606 727,599Q712,592 706,576L682,508Q662,525 651,548Q640,571 640,600Q640,650 674.5,685Q709,720 760,720ZM196,600Q196,600 196,600Q196,600 196,600Q196,600 196,600Q196,600 196,600Q196,600 196,600Q196,600 196,600L196,600Q196,600 196,600Q196,600 196,600ZM760,600Q760,600 760,600Q760,600 760,600Q760,600 760,600Q760,600 760,600Q760,600 760,600Q760,600 760,600L760,600Q760,600 760,600Q760,600 760,600Q760,600 760,600Q760,600 760,600Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_bus_station.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_bus_station.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M320,760L320,780Q320,805 302.5,822.5Q285,840 260,840Q235,840 217.5,822.5Q200,805 200,780L200,718Q182,698 171,673.5Q160,649 160,620L160,240Q160,157 237,118.5Q314,80 480,80Q652,80 726,117Q800,154 800,240L800,620Q800,649 789,673.5Q778,698 760,718L760,780Q760,805 742.5,822.5Q725,840 700,840Q675,840 657.5,822.5Q640,805 640,780L640,760L320,760ZM482,200Q592,200 641.5,200Q691,200 706,200L258,200Q276,200 325.5,200Q375,200 482,200ZM640,480L320,480Q287,480 263.5,480Q240,480 240,480L240,480L720,480L720,480Q720,480 696.5,480Q673,480 640,480ZM240,400L720,400L720,280L240,280L240,400ZM340,640Q365,640 382.5,622.5Q400,605 400,580Q400,555 382.5,537.5Q365,520 340,520Q315,520 297.5,537.5Q280,555 280,580Q280,605 297.5,622.5Q315,640 340,640ZM620,640Q645,640 662.5,622.5Q680,605 680,580Q680,555 662.5,537.5Q645,520 620,520Q595,520 577.5,537.5Q560,555 560,580Q560,605 577.5,622.5Q595,640 620,640ZM258,200L706,200Q691,183 641.5,171.5Q592,160 482,160Q375,160 325.5,172.5Q276,185 258,200ZM320,680L640,680Q673,680 696.5,656.5Q720,633 720,600L720,480L240,480L240,600Q240,633 263.5,656.5Q287,680 320,680Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_cafe.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_cafe.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,840Q183,840 171.5,828.5Q160,817 160,800Q160,783 171.5,771.5Q183,760 200,760L760,760Q777,760 788.5,771.5Q800,783 800,800Q800,817 788.5,828.5Q777,840 760,840L200,840ZM320,680Q254,680 207,633Q160,586 160,520L160,200Q160,167 183.5,143.5Q207,120 240,120L800,120Q833,120 856.5,143.5Q880,167 880,200L880,320Q880,353 856.5,376.5Q833,400 800,400L720,400L720,520Q720,586 673,633Q626,680 560,680L320,680ZM320,600L560,600Q593,600 616.5,576.5Q640,553 640,520L640,200L240,200L240,520Q240,553 263.5,576.5Q287,600 320,600ZM720,320L800,320Q800,320 800,320Q800,320 800,320L800,200Q800,200 800,200Q800,200 800,200L720,200L720,320ZM320,600Q287,600 263.5,600Q240,600 240,600L240,600L640,600L640,600Q640,600 616.5,600Q593,600 560,600L320,600Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_car.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_car.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,760L240,780Q240,805 222.5,822.5Q205,840 180,840Q155,840 137.5,822.5Q120,805 120,780L120,494Q120,487 121,480Q122,473 124,467L199,254Q207,230 228,215Q249,200 275,200L685,200Q711,200 732,215Q753,230 761,254L836,467Q838,473 839,480Q840,487 840,494L840,780Q840,805 822.5,822.5Q805,840 780,840Q755,840 737.5,822.5Q720,805 720,780L720,760L240,760ZM232,400L728,400L686,280Q686,280 686,280Q686,280 686,280L274,280Q274,280 274,280Q274,280 274,280L232,400ZM200,480L200,480L200,680L200,680L200,480ZM300,640Q325,640 342.5,622.5Q360,605 360,580Q360,555 342.5,537.5Q325,520 300,520Q275,520 257.5,537.5Q240,555 240,580Q240,605 257.5,622.5Q275,640 300,640ZM660,640Q685,640 702.5,622.5Q720,605 720,580Q720,555 702.5,537.5Q685,520 660,520Q635,520 617.5,537.5Q600,555 600,580Q600,605 617.5,622.5Q635,640 660,640ZM200,680L760,680L760,480L200,480L200,680Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_car_repair.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_car_repair.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,880Q463,880 451.5,868.5Q440,857 440,840L440,760L200,760Q183,760 171.5,748.5Q160,737 160,720Q160,703 171.5,691.5Q183,680 200,680L760,680Q777,680 788.5,691.5Q800,703 800,720Q800,737 788.5,748.5Q777,760 760,760L520,760L520,840Q520,857 508.5,868.5Q497,880 480,880ZM360,460Q377,460 388.5,448.5Q400,437 400,420Q400,403 388.5,391.5Q377,380 360,380Q343,380 331.5,391.5Q320,403 320,420Q320,437 331.5,448.5Q343,460 360,460ZM600,460Q617,460 628.5,448.5Q640,437 640,420Q640,403 628.5,391.5Q617,380 600,380Q583,380 571.5,391.5Q560,403 560,420Q560,437 571.5,448.5Q583,460 600,460ZM240,640Q223,640 211.5,628.5Q200,617 200,600L200,357Q200,350 201,343.5Q202,337 204,331L258,174Q266,150 287,135Q308,120 334,120L626,120Q652,120 673,135Q694,150 702,174L756,331Q758,337 759,343.5Q760,350 760,357L760,600Q760,617 748.5,628.5Q737,640 720,640Q703,640 691.5,628.5Q680,617 680,600L680,560L280,560L280,600Q280,617 268.5,628.5Q257,640 240,640ZM306,280L654,280L626,200Q626,200 626,200Q626,200 626,200L334,200Q334,200 334,200Q334,200 334,200L306,280ZM280,360L280,360L280,480L280,480L280,360ZM280,480L680,480L680,360L280,360L280,480Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_cinema.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_cinema.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,760L240,800Q240,817 228.5,828.5Q217,840 200,840Q183,840 171.5,828.5Q160,817 160,800L160,160Q160,143 171.5,131.5Q183,120 200,120Q217,120 228.5,131.5Q240,143 240,160L240,200L320,200L320,160Q320,143 331.5,131.5Q343,120 360,120L600,120Q617,120 628.5,131.5Q640,143 640,160L640,200L720,200L720,160Q720,143 731.5,131.5Q743,120 760,120Q777,120 788.5,131.5Q800,143 800,160L800,800Q800,817 788.5,828.5Q777,840 760,840Q743,840 731.5,828.5Q720,817 720,800L720,760L640,760L640,800Q640,817 628.5,828.5Q617,840 600,840L360,840Q343,840 331.5,828.5Q320,817 320,800L320,760L240,760ZM240,680L320,680L320,600L240,600L240,680ZM240,520L320,520L320,440L240,440L240,520ZM240,360L320,360L320,280L240,280L240,360ZM640,680L720,680L720,600L640,600L640,680ZM640,520L720,520L720,440L640,440L640,520ZM640,360L720,360L720,280L640,280L640,360ZM400,760L560,760L560,200L400,200L400,760ZM400,200L400,200L560,200L560,200L400,200Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_clothes.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_clothes.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,438L200,460Q186,468 170,464Q154,460 146,446L66,306Q58,292 62,276Q66,260 80,252L310,120L380,120Q389,120 394.5,125.5Q400,131 400,140L400,160Q400,193 423.5,216.5Q447,240 480,240Q513,240 536.5,216.5Q560,193 560,160L560,140Q560,131 565.5,125.5Q571,120 580,120L650,120L880,252Q894,260 898,276Q902,292 894,306L814,446Q806,460 790.5,463.5Q775,467 760,459L720,439L720,800Q720,817 708.5,828.5Q697,840 680,840L280,840Q263,840 251.5,828.5Q240,817 240,800L240,438ZM320,304L320,760L640,760L640,304L764,372L806,302L634,202L634,202Q619,253 577.5,286.5Q536,320 480,320Q424,320 382.5,286.5Q341,253 326,202L326,202L154,302L196,372L320,304ZM480,481L480,481L480,481L480,481L480,481Q480,481 480,481Q480,481 480,481Q480,481 480,481Q480,481 480,481L480,481L480,481L480,481L480,481L480,481L480,481L480,481Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_college.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_college.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M242,711Q222,700 211,681.5Q200,663 200,640L200,448L104,395Q93,389 88,380Q83,371 83,360Q83,349 88,340Q93,331 104,325L442,141Q451,136 460.5,133.5Q470,131 480,131Q490,131 499.5,133.5Q509,136 518,141L899,349Q909,354 914.5,363.5Q920,373 920,384L920,640Q920,657 908.5,668.5Q897,680 880,680Q863,680 851.5,668.5Q840,657 840,640L840,404L760,448L760,640Q760,663 749,681.5Q738,700 718,711L518,819Q509,824 499.5,826.5Q490,829 480,829Q470,829 460.5,826.5Q451,824 442,819L242,711ZM480,508Q480,508 480,508Q480,508 480,508L754,360L480,212Q480,212 480,212Q480,212 480,212L206,360L480,508ZM480,749Q480,749 480,749Q480,749 480,749L680,641Q680,641 680,641Q680,641 680,641L680,490L519,579Q510,584 500,586.5Q490,589 480,589Q470,589 460,586.5Q450,584 441,579L280,490L280,641Q280,641 280,641Q280,641 280,641L480,749ZM480,508L480,508L480,508Q480,508 480,508Q480,508 480,508L480,508L480,508Q480,508 480,508Q480,508 480,508ZM480,629Q480,629 480,629Q480,629 480,629L480,629L480,629L480,629L480,629L480,629L480,629L480,629Q480,629 480,629Q480,629 480,629L480,629ZM480,629L480,629Q480,629 480,629Q480,629 480,629L480,629L480,629L480,629L480,629L480,629L480,629L480,629Q480,629 480,629Q480,629 480,629Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_computer.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_computer.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M80,840Q63,840 51.5,828.5Q40,817 40,800Q40,783 51.5,771.5Q63,760 80,760L880,760Q897,760 908.5,771.5Q920,783 920,800Q920,817 908.5,828.5Q897,840 880,840L80,840ZM160,720Q127,720 103.5,696.5Q80,673 80,640L80,200Q80,167 103.5,143.5Q127,120 160,120L800,120Q833,120 856.5,143.5Q880,167 880,200L880,640Q880,673 856.5,696.5Q833,720 800,720L160,720ZM160,640L800,640Q800,640 800,640Q800,640 800,640L800,200Q800,200 800,200Q800,200 800,200L160,200Q160,200 160,200Q160,200 160,200L160,640Q160,640 160,640Q160,640 160,640ZM160,640Q160,640 160,640Q160,640 160,640L160,200Q160,200 160,200Q160,200 160,200L160,200Q160,200 160,200Q160,200 160,200L160,640Q160,640 160,640Q160,640 160,640L160,640Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_convenience.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_convenience.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M841,442L841,760Q841,793 817.5,816.5Q794,840 761,840L201,840Q168,840 144.5,816.5Q121,793 121,760L121,442Q98,421 85.5,388Q73,355 85,316L127,180Q135,154 155.5,137Q176,120 203,120L759,120Q786,120 806,136.5Q826,153 835,180L877,316Q889,355 876.5,387Q864,419 841,442ZM569,400Q596,400 610,381.5Q624,363 621,340L599,200L521,200L521,348Q521,369 535,384.5Q549,400 569,400ZM389,400Q412,400 426.5,384.5Q441,369 441,348L441,200L363,200L341,340Q337,364 351.5,382Q366,400 389,400ZM211,400Q229,400 242.5,387Q256,374 259,354L281,200L203,200Q203,200 203,200Q203,200 203,200L163,334Q157,354 169.5,377Q182,400 211,400ZM751,400Q780,400 793,377Q806,354 799,334L757,200Q757,200 757,200Q757,200 757,200L681,200L703,354Q706,374 719.5,387Q733,400 751,400ZM201,760L761,760Q761,760 761,760Q761,760 761,760L761,478Q756,480 754.5,480Q753,480 751,480Q724,480 703.5,471Q683,462 663,442Q645,460 622,470Q599,480 573,480Q546,480 522.5,470Q499,460 481,442Q464,460 441.5,470Q419,480 393,480Q364,480 340.5,470Q317,460 299,442Q278,463 257.5,471.5Q237,480 211,480Q209,480 206.5,480Q204,480 201,478L201,760Q201,760 201,760Q201,760 201,760ZM761,760L201,760Q201,760 201,760Q201,760 201,760L201,760Q204,760 206.5,760Q209,760 211,760Q237,760 257.5,760Q278,760 299,760Q308,760 318.5,760Q329,760 341,760Q353,760 366,760Q379,760 393,760Q406,760 418,760Q430,760 441.5,760Q453,760 463,760Q473,760 481,760Q499,760 522.5,760Q546,760 573,760Q586,760 598,760Q610,760 621.5,760Q633,760 643.5,760Q654,760 663,760Q683,760 703.5,760Q724,760 751,760Q753,760 754.5,760Q756,760 761,760L761,760Q761,760 761,760Q761,760 761,760ZM341,720L421,720Q429,720 435,714Q441,708 441,700Q441,692 435,686Q429,680 421,680L361,680L361,640L421,640Q429,640 435,634Q441,628 441,620L441,540Q441,532 435,526Q429,520 421,520L341,520Q333,520 327,526Q321,532 321,540Q321,548 327,554Q333,560 341,560L401,560L401,600L341,600Q333,600 327,606Q321,612 321,620L321,700Q321,708 327,714Q333,720 341,720ZM601,640L601,700Q601,708 607,714Q613,720 621,720Q629,720 635,714Q641,708 641,700L641,540Q641,532 635,526Q629,520 621,520Q613,520 607,526Q601,532 601,540L601,600L561,600L561,540Q561,532 555,526Q549,520 541,520Q533,520 527,526Q521,532 521,540L521,620Q521,628 527,634Q533,640 541,640L601,640Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_dentist.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_dentist.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M680,85Q746,85 793,132Q840,179 840,245Q840,256 838.5,274.5Q837,293 834,317L779,720Q774,758 744.5,782Q715,806 677,806Q654,806 634.5,796Q615,786 602,768L495,612Q493,608 488.5,606.5Q484,605 479,605Q475,605 463,614L359,765Q345,785 324.5,795.5Q304,806 281,806Q243,806 214,781.5Q185,757 180,719L126,317Q123,293 121.5,274.5Q120,256 120,245Q120,179 167,132Q214,85 280,85Q316,85 337.5,94.5Q359,104 379,115Q399,126 421.5,135.5Q444,145 480,145Q516,145 538.5,135.5Q561,126 581,115Q601,104 623,94.5Q645,85 680,85ZM680,165Q657,165 639.5,174.5Q622,184 601,195Q580,206 552,215.5Q524,225 480,225Q436,225 408,215.5Q380,206 359,195Q338,184 320.5,174.5Q303,165 280,165Q247,165 223.5,188.5Q200,212 200,245Q200,253 201,268Q202,283 205,303L260,708Q261,716 267,720.5Q273,725 281,725Q286,725 290,723Q294,721 296,717L397,569Q411,549 433,537Q455,525 480,525Q505,525 527,537Q549,549 563,569L666,720Q668,723 671,724.5Q674,726 678,726Q686,726 692.5,721.5Q699,717 700,709L755,303Q758,283 759,268Q760,253 760,245Q760,212 736.5,188.5Q713,165 680,165ZM480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445L480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445L480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445L480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445L480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Q480,445 480,445Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_doctors.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_doctors.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M540,880Q432,880 356,804Q280,728 280,620L280,597Q194,583 137,516.5Q80,450 80,360L80,160Q80,143 91.5,131.5Q103,120 120,120L200,120L200,120Q200,103 211.5,91.5Q223,80 240,80Q257,80 268.5,91.5Q280,103 280,120L280,200Q280,217 268.5,228.5Q257,240 240,240Q223,240 211.5,228.5Q200,217 200,200L200,200L160,200L160,360Q160,426 207,473Q254,520 320,520Q386,520 433,473Q480,426 480,360L480,200L440,200L440,200Q440,217 428.5,228.5Q417,240 400,240Q383,240 371.5,228.5Q360,217 360,200L360,120Q360,103 371.5,91.5Q383,80 400,80Q417,80 428.5,91.5Q440,103 440,120L440,120L520,120Q537,120 548.5,131.5Q560,143 560,160L560,360Q560,450 503,516.5Q446,583 360,597L360,620Q360,695 412.5,747.5Q465,800 540,800Q615,800 667.5,747.5Q720,695 720,620L720,553Q685,540 662.5,509.5Q640,479 640,440Q640,390 675,355Q710,320 760,320Q810,320 845,355Q880,390 880,440Q880,479 857.5,509.5Q835,540 800,553L800,620Q800,728 724,804Q648,880 540,880ZM760,480Q777,480 788.5,468.5Q800,457 800,440Q800,423 788.5,411.5Q777,400 760,400Q743,400 731.5,411.5Q720,423 720,440Q720,457 731.5,468.5Q743,480 760,480ZM760,440Q760,440 760,440Q760,440 760,440Q760,440 760,440Q760,440 760,440Q760,440 760,440Q760,440 760,440Q760,440 760,440Q760,440 760,440Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_electronics.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_electronics.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M360,560L360,400Q360,383 371.5,371.5Q383,360 400,360L560,360Q577,360 588.5,371.5Q600,383 600,400L600,560Q600,577 588.5,588.5Q577,600 560,600L400,600Q383,600 371.5,588.5Q360,577 360,560ZM440,520L520,520L520,440L440,440L440,520ZM360,800L360,760L280,760Q247,760 223.5,736.5Q200,713 200,680L200,600L160,600Q143,600 131.5,588.5Q120,577 120,560Q120,543 131.5,531.5Q143,520 160,520L200,520L200,440L160,440Q143,440 131.5,428.5Q120,417 120,400Q120,383 131.5,371.5Q143,360 160,360L200,360L200,280Q200,247 223.5,223.5Q247,200 280,200L360,200L360,160Q360,143 371.5,131.5Q383,120 400,120Q417,120 428.5,131.5Q440,143 440,160L440,200L520,200L520,160Q520,143 531.5,131.5Q543,120 560,120Q577,120 588.5,131.5Q600,143 600,160L600,200L680,200Q713,200 736.5,223.5Q760,247 760,280L760,360L800,360Q817,360 828.5,371.5Q840,383 840,400Q840,417 828.5,428.5Q817,440 800,440L760,440L760,520L800,520Q817,520 828.5,531.5Q840,543 840,560Q840,577 828.5,588.5Q817,600 800,600L760,600L760,680Q760,713 736.5,736.5Q713,760 680,760L600,760L600,800Q600,817 588.5,828.5Q577,840 560,840Q543,840 531.5,828.5Q520,817 520,800L520,760L440,760L440,800Q440,817 428.5,828.5Q417,840 400,840Q383,840 371.5,828.5Q360,817 360,800ZM680,680Q680,680 680,680Q680,680 680,680L680,280Q680,280 680,280Q680,280 680,280L280,280Q280,280 280,280Q280,280 280,280L280,680Q280,680 280,680Q280,680 280,680L680,680ZM480,480L480,480L480,480L480,480L480,480Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_fastfood.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_fastfood.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M533,520Q501,475 448.5,457.5Q396,440 340,440Q284,440 231.5,457.5Q179,475 147,520L533,520ZM340,360Q386,360 433.5,371.5Q481,383 521.5,407Q562,431 591,467Q620,503 630,552Q634,571 622,585.5Q610,600 591,600L89,600Q70,600 58,585.5Q46,571 50,552Q60,503 89.5,467Q119,431 159.5,407Q200,383 247,371.5Q294,360 340,360ZM80,760Q63,760 51.5,748.5Q40,737 40,720Q40,703 51.5,691.5Q63,680 80,680L600,680Q617,680 628.5,691.5Q640,703 640,720Q640,737 628.5,748.5Q617,760 600,760L80,760ZM788,920L720,920L720,840L776,840L832,280L450,280L446,245Q444,227 455.5,213.5Q467,200 485,200L640,200L640,80Q640,63 651.5,51.5Q663,40 680,40Q697,40 708.5,51.5Q720,63 720,80L720,200L876,200Q894,200 906,213Q918,226 916,244L854,862Q851,887 832,903.5Q813,920 788,920ZM720,840L776,840L776,840L720,840L720,840Q720,840 720,840Q720,840 720,840L720,840ZM80,920Q63,920 51.5,908.5Q40,897 40,880Q40,863 51.5,851.5Q63,840 80,840L600,840Q617,840 628.5,851.5Q640,863 640,880Q640,897 628.5,908.5Q617,920 600,920L80,920ZM340,520Q340,520 340,520Q340,520 340,520Q340,520 340,520Q340,520 340,520L340,520Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_fitness.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_fitness.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M282,338L168,452Q157,463 140.5,463.5Q124,464 112,452Q101,441 100.5,424.5Q100,408 111,396L140,366L112,338Q100,326 100,310Q100,294 112,282L168,226L139,196Q128,185 128,168.5Q128,152 140,140Q151,129 167.5,128.5Q184,128 196,139L226,168L282,112Q294,100 310,100Q326,100 338,112L366,140L396,111Q407,100 423.5,100Q440,100 452,112Q463,123 463,140Q463,157 452,168L338,282L678,622L792,508Q803,497 819.5,496.5Q836,496 848,508Q859,519 859.5,535.5Q860,552 849,564L820,594L848,622Q860,634 860,650Q860,666 848,678L792,734L821,764Q832,775 832,791.5Q832,808 820,820Q809,831 792.5,831.5Q776,832 764,821L734,792L678,848Q666,860 650,860Q634,860 622,848L594,820L564,849Q553,860 536.5,860Q520,860 508,848Q497,837 497,820Q497,803 508,792L622,678L282,338Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_florist.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_florist.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,879Q480,753 556,656Q632,559 749,530Q768,525 786.5,526.5Q805,528 819,542Q831,555 832.5,573Q834,591 829,608Q801,726 703.5,802.5Q606,879 480,879ZM578,782Q635,761 678,718Q721,675 742,618Q685,639 642,682Q599,725 578,782ZM480,880Q480,754 404,657Q328,560 211,531Q192,526 173.5,527.5Q155,529 141,543Q129,556 127.5,574Q126,592 131,609Q159,727 256.5,803.5Q354,880 480,880ZM382,782Q325,761 282,718Q239,675 218,618Q275,639 318,682Q361,725 382,782ZM578,782Q578,782 578,782Q578,782 578,782Q578,782 578,782Q578,782 578,782ZM382,782Q382,782 382,782Q382,782 382,782Q382,782 382,782Q382,782 382,782ZM480,360Q497,360 508.5,348.5Q520,337 520,320Q520,303 508.5,291.5Q497,280 480,280Q463,280 451.5,291.5Q440,303 440,320Q440,337 451.5,348.5Q463,360 480,360ZM480,600Q441,600 409.5,578.5Q378,557 364,522Q359,522 355,522.5Q351,523 346,523Q294,523 257,486Q220,449 220,397Q220,376 227,356.5Q234,337 248,320Q235,303 228,283.5Q221,264 221,243Q221,191 257.5,154Q294,117 346,117Q351,117 355,117.5Q359,118 364,118Q378,83 409.5,61.5Q441,40 480,40Q519,40 550.5,61.5Q582,83 596,118Q601,118 605,117.5Q609,117 614,117Q666,117 702.5,154Q739,191 739,243Q739,264 732.5,283.5Q726,303 712,320Q725,337 732,356.5Q739,376 739,397Q739,449 702.5,486Q666,523 614,523Q609,523 605,522.5Q601,522 596,522Q582,557 550.5,578.5Q519,600 480,600ZM614,443Q633,443 646.5,429.5Q660,416 660,397Q660,383 652.5,372.5Q645,362 633,356L598,339Q596,350 592,360.5Q588,371 583,380Q578,389 571,397Q564,405 556,412L588,435Q593,439 599.5,441Q606,443 614,443ZM598,301L633,284Q645,278 652,267Q659,256 659,243Q659,224 646,210.5Q633,197 614,197Q606,197 600,199Q594,201 588,205L555,228Q563,235 570.5,243Q578,251 583,260Q588,269 592,279.5Q596,290 598,301ZM439,208Q449,204 459,202Q469,200 480,200Q491,200 501,202Q511,204 521,208L526,164Q528,146 513.5,133Q499,120 480,120Q461,120 446.5,133Q432,146 434,164L439,208ZM480,520Q499,520 513.5,507Q528,494 526,476L521,432Q511,436 501,438Q491,440 480,440Q469,440 459,438Q449,436 439,432L434,476Q432,494 446.5,507Q461,520 480,520ZM362,301Q364,290 368,279.5Q372,269 377,260Q382,251 389,243Q396,235 404,228L372,205Q367,201 360.5,199Q354,197 346,197Q327,197 313.5,210.5Q300,224 300,243Q300,256 307.5,267Q315,278 327,284L362,301ZM346,442Q354,442 360,440.5Q366,439 372,434L405,412Q397,405 389.5,397Q382,389 377,380Q372,371 368,360.5Q364,350 362,339L327,356Q315,362 308,373Q301,384 301,397Q302,416 314.5,429Q327,442 346,442ZM583,380Q583,380 583,380Q583,380 583,380L583,380Q583,380 583,380Q583,380 583,380Q583,380 583,380Q583,380 583,380L583,380Q583,380 583,380Q583,380 583,380Q583,380 583,380Q583,380 583,380ZM583,260Q583,260 583,260Q583,260 583,260Q583,260 583,260Q583,260 583,260L583,260Q583,260 583,260Q583,260 583,260Q583,260 583,260Q583,260 583,260Q583,260 583,260Q583,260 583,260L583,260ZM480,200L480,200Q480,200 480,200Q480,200 480,200Q480,200 480,200Q480,200 480,200L480,200Q480,200 480,200Q480,200 480,200Q480,200 480,200Q480,200 480,200ZM480,440Q480,440 480,440Q480,440 480,440L480,440Q480,440 480,440Q480,440 480,440Q480,440 480,440Q480,440 480,440L480,440Q480,440 480,440Q480,440 480,440ZM377,260L377,260Q377,260 377,260Q377,260 377,260Q377,260 377,260Q377,260 377,260Q377,260 377,260Q377,260 377,260L377,260Q377,260 377,260Q377,260 377,260Q377,260 377,260Q377,260 377,260ZM377,380Q377,380 377,380Q377,380 377,380Q377,380 377,380Q377,380 377,380L377,380Q377,380 377,380Q377,380 377,380Q377,380 377,380Q377,380 377,380L377,380Q377,380 377,380Q377,380 377,380Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_fuel.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_fuel.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,800L160,200Q160,167 183.5,143.5Q207,120 240,120L480,120Q513,120 536.5,143.5Q560,167 560,200L560,480L600,480Q633,480 656.5,503.5Q680,527 680,560L680,740Q680,757 691.5,768.5Q703,780 720,780Q737,780 748.5,768.5Q760,757 760,740L760,452Q751,457 741,458.5Q731,460 720,460Q678,460 649,431Q620,402 620,360Q620,328 637.5,302.5Q655,277 684,266L621,203Q612,194 612,182Q612,170 621,161Q629,153 641.5,152.5Q654,152 663,160L790,284Q805,299 812.5,319Q820,339 820,360L820,740Q820,782 791,811Q762,840 720,840Q678,840 649,811Q620,782 620,740L620,540Q620,540 620,540Q620,540 620,540L560,540L560,800Q560,817 548.5,828.5Q537,840 520,840L200,840Q183,840 171.5,828.5Q160,817 160,800ZM240,400L480,400L480,200Q480,200 480,200Q480,200 480,200L240,200Q240,200 240,200Q240,200 240,200L240,400ZM720,400Q737,400 748.5,388.5Q760,377 760,360Q760,343 748.5,331.5Q737,320 720,320Q703,320 691.5,331.5Q680,343 680,360Q680,377 691.5,388.5Q703,400 720,400ZM240,760L480,760L480,480L240,480L240,760ZM480,760L240,760L240,760L480,760L480,760Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_furniture.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_furniture.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,840Q183,840 171.5,828.5Q160,817 160,800L160,760L160,760Q110,760 75,725Q40,690 40,640L40,440Q40,390 75,355Q110,320 160,320L160,320L160,240Q160,190 195,155Q230,120 280,120L680,120Q730,120 765,155Q800,190 800,240L800,320L800,320Q850,320 885,355Q920,390 920,440L920,640Q920,690 885,725Q850,760 800,760L800,760L800,800Q800,817 788.5,828.5Q777,840 760,840Q743,840 731.5,828.5Q720,817 720,800L720,760L240,760L240,800Q240,817 228.5,828.5Q217,840 200,840ZM160,680L800,680Q817,680 828.5,668.5Q840,657 840,640L840,440Q840,423 828.5,411.5Q817,400 800,400Q783,400 771.5,411.5Q760,423 760,440L760,600L200,600L200,440Q200,423 188.5,411.5Q177,400 160,400Q143,400 131.5,411.5Q120,423 120,440L120,640Q120,657 131.5,668.5Q143,680 160,680ZM280,520L680,520L680,440Q680,413 691,391Q702,369 720,352L720,240Q720,223 708.5,211.5Q697,200 680,200L280,200Q263,200 251.5,211.5Q240,223 240,240L240,352Q258,369 269,391Q280,413 280,440L280,520ZM480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520L480,520ZM480,680Q480,680 480,680Q480,680 480,680L480,680Q480,680 480,680Q480,680 480,680Q480,680 480,680Q480,680 480,680L480,680L480,680L480,680Q480,680 480,680Q480,680 480,680Q480,680 480,680Q480,680 480,680L480,680Q480,680 480,680Q480,680 480,680L480,680ZM480,600Q480,600 480,600Q480,600 480,600L480,600L480,600L480,600Q480,600 480,600Q480,600 480,600L480,600L480,600Q480,600 480,600Q480,600 480,600L480,600L480,600L480,600Q480,600 480,600Q480,600 480,600L480,600L480,600Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_gift.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_gift.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,800L160,440L160,440Q127,440 103.5,416.5Q80,393 80,360L80,280Q80,247 103.5,223.5Q127,200 160,200L288,200Q283,191 281.5,181Q280,171 280,160Q280,110 315,75Q350,40 400,40Q423,40 443,48.5Q463,57 480,72Q497,56 517,48Q537,40 560,40Q610,40 645,75Q680,110 680,160Q680,171 678,180.5Q676,190 672,200L800,200Q833,200 856.5,223.5Q880,247 880,280L880,360Q880,393 856.5,416.5Q833,440 800,440L800,440L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880Q207,880 183.5,856.5Q160,833 160,800ZM560,120Q543,120 531.5,131.5Q520,143 520,160Q520,177 531.5,188.5Q543,200 560,200Q577,200 588.5,188.5Q600,177 600,160Q600,143 588.5,131.5Q577,120 560,120ZM360,160Q360,177 371.5,188.5Q383,200 400,200Q417,200 428.5,188.5Q440,177 440,160Q440,143 428.5,131.5Q417,120 400,120Q383,120 371.5,131.5Q360,143 360,160ZM160,280L160,360L440,360L440,280L160,280ZM440,800L440,440L240,440L240,800Q240,800 240,800Q240,800 240,800L440,800ZM520,800L720,800Q720,800 720,800Q720,800 720,800L720,440L520,440L520,800ZM800,360L800,280L520,280L520,360L800,360Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_grave_yard.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_grave_yard.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M426,800Q417,774 403,752Q389,730 370,711Q351,692 329,677.5Q307,663 281,654Q283,683 295,708Q307,733 327,753Q347,773 372,785.5Q397,798 426,800ZM534,800Q563,797 588,785Q613,773 633,753Q653,733 665,708Q677,683 680,654Q654,663 631.5,677Q609,691 590,710Q571,729 557,751.5Q543,774 534,800ZM480,440Q546,440 593,393Q640,346 640,280L640,232L570,291L480,182L390,291L320,232L320,280Q320,346 367,393Q414,440 480,440ZM440,880Q340,880 270,810Q200,740 200,640L200,560Q271,559 334,589Q397,619 440,670L440,517Q354,503 297,436.5Q240,370 240,280L240,144Q240,118 263,107.5Q286,97 306,114L380,178L449,94Q461,80 480,80Q499,80 511,94L580,178L654,114Q674,97 697,107.5Q720,118 720,144L720,280Q720,370 663,436.5Q606,503 520,517L520,670Q563,619 626,589Q689,559 760,560L760,640Q760,740 690,810Q620,880 520,880L440,880ZM480,311Q480,311 480,311Q480,311 480,311L480,311L480,311L480,311L480,311L480,311L480,311Q480,311 480,311Q480,311 480,311ZM607,727Q607,727 607,727Q607,727 607,727Q607,727 607,727Q607,727 607,727Q607,727 607,727Q607,727 607,727Q607,727 607,727Q607,727 607,727ZM354,727Q354,727 354,727Q354,727 354,727Q354,727 354,727Q354,727 354,727Q354,727 354,727Q354,727 354,727Q354,727 354,727Q354,727 354,727Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_hairdresser.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_hairdresser.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M680,880Q663,880 651.5,868.5Q640,857 640,840Q640,823 651.5,811.5Q663,800 680,800L800,800L800,720L680,720Q663,720 651.5,708.5Q640,697 640,680Q640,663 651.5,651.5Q663,640 680,640L800,640L800,560L680,560Q663,560 651.5,548.5Q640,537 640,520Q640,503 651.5,491.5Q663,480 680,480L800,480L800,400L680,400Q663,400 651.5,388.5Q640,377 640,360Q640,343 651.5,331.5Q663,320 680,320L800,320L800,240L680,240Q663,240 651.5,228.5Q640,217 640,200Q640,183 651.5,171.5Q663,160 680,160L840,160Q873,160 896.5,183.5Q920,207 920,240L920,800Q920,833 896.5,856.5Q873,880 840,880L680,880ZM256,800L384,800Q384,800 384,800Q384,800 384,800L502,474Q502,474 502,474Q502,474 502,474L378,400L262,400L138,474Q138,474 138,474Q138,474 138,474L256,800Q256,800 256,800Q256,800 256,800ZM320,600Q320,600 320,600Q320,600 320,600L320,600Q320,600 320,600Q320,600 320,600L320,600L320,600L320,600Q320,600 320,600Q320,600 320,600L320,600Q320,600 320,600Q320,600 320,600L320,600ZM181,827L63,502Q53,475 62.5,448Q72,421 97,406L240,320L240,120Q240,103 251.5,91.5Q263,80 280,80L360,80Q377,80 388.5,91.5Q400,103 400,120L400,320L543,406Q568,421 577.5,448Q587,475 577,502L459,827Q451,851 430.5,865.5Q410,880 384,880L256,880Q230,880 209.5,865.5Q189,851 181,827Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_hardware.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_hardware.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M400,840Q383,840 371.5,828.5Q360,817 360,800L360,320L208,320Q189,320 177,306Q165,292 169,273Q182,205 236.5,162.5Q291,120 360,120L560,120Q577,120 588.5,131.5Q600,143 600,160L600,240L702,138Q710,130 721.5,125Q733,120 745,120L760,120Q777,120 788.5,131.5Q800,143 800,160L800,400Q800,417 788.5,428.5Q777,440 760,440L745,440Q733,440 721.5,435Q710,430 702,422L600,320L600,800Q600,817 588.5,828.5Q577,840 560,840L400,840ZM440,760L520,760L520,520L480,520L440,520L440,760ZM440,440L520,440L520,200L360,200Q334,200 311,210.5Q288,221 271,240L440,240L440,440ZM480,480L480,480L480,480L480,480L480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480L480,480L480,480L480,480Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_hospital.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_hospital.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M420,540L420,620Q420,645 437.5,662.5Q455,680 480,680Q505,680 522.5,662.5Q540,645 540,620L540,540L620,540Q645,540 662.5,522.5Q680,505 680,480Q680,455 662.5,437.5Q645,420 620,420L540,420L540,340Q540,315 522.5,297.5Q505,280 480,280Q455,280 437.5,297.5Q420,315 420,340L420,420L340,420Q315,420 297.5,437.5Q280,455 280,480Q280,505 297.5,522.5Q315,540 340,540L420,540ZM200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L760,120Q793,120 816.5,143.5Q840,167 840,200L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM200,760L760,760Q760,760 760,760Q760,760 760,760L760,200Q760,200 760,200Q760,200 760,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760ZM200,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760L200,760Q200,760 200,760Q200,760 200,760L200,200Q200,200 200,200Q200,200 200,200Z"/>
|
||||
</vector>
|
||||
11
core/base/src/main/res/drawable/ic_location_hotel.xml
Normal file
11
core/base/src/main/res/drawable/ic_location_hotel.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M80,760Q63,760 51.5,748.5Q40,737 40,720L40,200Q40,183 51.5,171.5Q63,160 80,160Q97,160 108.5,171.5Q120,183 120,200L120,560L440,560L440,320Q440,287 463.5,263.5Q487,240 520,240L760,240Q826,240 873,287Q920,334 920,400L920,720Q920,737 908.5,748.5Q897,760 880,760Q863,760 851.5,748.5Q840,737 840,720L840,640L120,640L120,720Q120,737 108.5,748.5Q97,760 80,760ZM280,520Q230,520 195,485Q160,450 160,400Q160,350 195,315Q230,280 280,280Q330,280 365,315Q400,350 400,400Q400,450 365,485Q330,520 280,520ZM520,560L840,560L840,400Q840,367 816.5,343.5Q793,320 760,320L520,320L520,560ZM280,440Q297,440 308.5,428.5Q320,417 320,400Q320,383 308.5,371.5Q297,360 280,360Q263,360 251.5,371.5Q240,383 240,400Q240,417 251.5,428.5Q263,440 280,440ZM280,400Q280,400 280,400Q280,400 280,400Q280,400 280,400Q280,400 280,400Q280,400 280,400Q280,400 280,400Q280,400 280,400Q280,400 280,400ZM520,320L520,320Q520,320 520,320Q520,320 520,320L520,560L520,560L520,320Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_ice_cream.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_ice_cream.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M120,400Q120,349 149.5,308Q179,267 224,250Q242,159 313.5,99.5Q385,40 480,40Q575,40 646.5,99.5Q718,159 736,250Q781,267 810.5,308Q840,349 840,400Q840,475 787,519Q734,563 668,560L517,852Q512,863 502.5,868Q493,873 482,873Q471,873 461,868Q451,863 446,852L294,560Q223,563 171.5,519Q120,475 120,400ZM280,480Q295,480 309.5,475Q324,470 336,458L358,436L384,452Q405,466 429.5,473Q454,480 480,480Q506,480 530.5,473Q555,466 576,452L602,436L624,458Q636,470 650.5,475Q665,480 680,480Q713,480 736.5,456.5Q760,433 760,400Q760,370 741,347.5Q722,325 692,320L662,316L660,284Q655,215 603,167.5Q551,120 480,120Q409,120 357,167.5Q305,215 300,284L298,316L268,322Q238,328 219,349Q200,370 200,400Q200,433 223.5,456.5Q247,480 280,480ZM482,746L590,536L590,536Q566,548 538,554Q510,560 480,560Q453,560 425.5,554Q398,548 372,536L372,536L482,746ZM480,300L480,300L480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300L480,300L480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300L480,300L480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300L480,300L480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Q480,300 480,300Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_jewelry.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_jewelry.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,795Q463,795 447,787.5Q431,780 419,766L113,400Q104,389 99.5,376Q95,363 95,349Q95,340 96.5,330.5Q98,321 103,313L178,164Q189,144 207.5,132Q226,120 249,120L711,120Q734,120 752.5,132Q771,144 782,164L857,313Q862,321 863.5,330.5Q865,340 865,349Q865,363 860.5,376Q856,389 847,400L541,766Q529,780 513,787.5Q497,795 480,795ZM385,320L575,320L515,200L445,200L385,320ZM440,667L440,400L218,400L440,667ZM520,667L742,400L520,400L520,667ZM664,320L770,320L710,200Q710,200 710,200Q710,200 710,200L604,200L664,320ZM190,320L296,320L356,200L250,200Q250,200 250,200Q250,200 250,200L190,320Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_kebab.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_kebab.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,920Q267,920 258.5,911.5Q250,903 250,890L250,760L220,760Q178,760 149,731Q120,702 120,660Q120,618 149,589Q178,560 220,560L250,560L250,520L160,520Q143,520 131.5,508.5Q120,497 120,480L120,360Q120,343 131.5,331.5Q143,320 160,320L250,320L250,280L220,280Q178,280 149,251Q120,222 120,180Q120,138 149,109Q178,80 220,80L250,80L250,70Q250,57 258.5,48.5Q267,40 280,40Q293,40 301.5,48.5Q310,57 310,70L310,80L340,80Q382,80 411,109Q440,138 440,180Q440,222 411,251Q382,280 340,280L310,280L310,320L400,320Q417,320 428.5,331.5Q440,343 440,360L440,480Q440,497 428.5,508.5Q417,520 400,520L310,520L310,560L340,560Q382,560 411,589Q440,618 440,660Q440,702 411,731Q382,760 340,760L310,760L310,890Q310,903 301.5,911.5Q293,920 280,920ZM680,920Q667,920 658.5,911.5Q650,903 650,890L650,760L620,760Q578,760 549,731Q520,702 520,660Q520,618 549,589Q578,560 620,560L650,560L650,520L560,520Q543,520 531.5,508.5Q520,497 520,480L520,360Q520,343 531.5,331.5Q543,320 560,320L650,320L650,280L620,280Q578,280 549,251Q520,222 520,180Q520,138 549,109Q578,80 620,80L650,80L650,70Q650,57 658.5,48.5Q667,40 680,40Q693,40 701.5,48.5Q710,57 710,70L710,80L740,80Q782,80 811,109Q840,138 840,180Q840,222 811,251Q782,280 740,280L710,280L710,320L800,320Q817,320 828.5,331.5Q840,343 840,360L840,480Q840,497 828.5,508.5Q817,520 800,520L710,520L710,560L740,560Q782,560 811,589Q840,618 840,660Q840,702 811,731Q782,760 740,760L710,760L710,890Q710,903 701.5,911.5Q693,920 680,920ZM220,200L340,200Q348,200 354,194Q360,188 360,180Q360,172 354,166Q348,160 340,160L220,160Q212,160 206,166Q200,172 200,180Q200,188 206,194Q212,200 220,200ZM620,200L740,200Q748,200 754,194Q760,188 760,180Q760,172 754,166Q748,160 740,160L620,160Q612,160 606,166Q600,172 600,180Q600,188 606,194Q612,200 620,200ZM200,440L360,440L360,400L200,400L200,440ZM600,440L760,440L760,400L600,400L600,440ZM220,680L340,680Q348,680 354,674Q360,668 360,660Q360,652 354,646Q348,640 340,640L220,640Q212,640 206,646Q200,652 200,660Q200,668 206,674Q212,680 220,680ZM620,680L740,680Q748,680 754,674Q760,668 760,660Q760,652 754,646Q748,640 740,640L620,640Q612,640 606,646Q600,652 600,660Q600,668 606,674Q612,680 620,680ZM200,200L200,200Q200,200 200,194Q200,188 200,180Q200,172 200,166Q200,160 200,160L200,160Q200,160 200,166Q200,172 200,180Q200,188 200,194Q200,200 200,200ZM600,200L600,200Q600,200 600,194Q600,188 600,180Q600,172 600,166Q600,160 600,160L600,160Q600,160 600,166Q600,172 600,180Q600,188 600,194Q600,200 600,200ZM200,440L200,440L200,400L200,400L200,440ZM600,440L600,440L600,400L600,400L600,440ZM200,680L200,680Q200,680 200,674Q200,668 200,660Q200,652 200,646Q200,640 200,640L200,640Q200,640 200,646Q200,652 200,660Q200,668 200,674Q200,680 200,680ZM600,680L600,680Q600,680 600,674Q600,668 600,660Q600,652 600,646Q600,640 600,640L600,640Q600,640 600,646Q600,652 600,660Q600,668 600,674Q600,680 600,680Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_kiosk.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_kiosk.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,840Q127,840 103.5,816.5Q80,793 80,760L80,144Q80,137 86,134.5Q92,132 97,137L133,173Q139,179 147,179Q155,179 161,173L199,134Q205,128 213,128Q221,128 227,134L266,173Q272,179 280,179Q288,179 294,173L333,134Q339,128 347,128Q355,128 361,134L399,173Q405,179 413,179Q421,179 427,173L466,134Q472,128 480,128Q488,128 494,134L533,173Q539,179 547,179Q555,179 561,173L599,134Q605,128 613,128Q621,128 627,134L666,173Q672,179 680,179Q688,179 694,173L733,134Q739,128 747,128Q755,128 761,134L799,173Q805,179 813,179Q821,179 827,173L863,137Q868,132 874,134.5Q880,137 880,144L880,760Q880,793 856.5,816.5Q833,840 800,840L160,840ZM160,760L440,760L440,520L160,520L160,760Q160,760 160,760Q160,760 160,760ZM520,760L800,760Q800,760 800,760Q800,760 800,760L800,680L520,680L520,760ZM520,600L800,600L800,520L520,520L520,600ZM160,440L800,440L800,320L160,320L160,440Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_laundry.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_laundry.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,160Q160,127 183.5,103.5Q207,80 240,80L720,80Q753,80 776.5,103.5Q800,127 800,160L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM240,800L720,800Q720,800 720,800Q720,800 720,800L720,160Q720,160 720,160Q720,160 720,160L240,160Q240,160 240,160Q240,160 240,160L240,800Q240,800 240,800Q240,800 240,800ZM480,760Q563,760 621.5,701.5Q680,643 680,560Q680,477 621.5,418.5Q563,360 480,360Q397,360 338.5,418.5Q280,477 280,560Q280,643 338.5,701.5Q397,760 480,760ZM480,692Q454,692 429.5,682.5Q405,673 386,654L574,466Q593,485 602.5,509.5Q612,534 612,560Q612,615 573.5,653.5Q535,692 480,692ZM320,280Q337,280 348.5,268.5Q360,257 360,240Q360,223 348.5,211.5Q337,200 320,200Q303,200 291.5,211.5Q280,223 280,240Q280,257 291.5,268.5Q303,280 320,280ZM440,280Q457,280 468.5,268.5Q480,257 480,240Q480,223 468.5,211.5Q457,200 440,200Q423,200 411.5,211.5Q400,223 400,240Q400,257 411.5,268.5Q423,280 440,280ZM240,800Q240,800 240,800Q240,800 240,800L240,160Q240,160 240,160Q240,160 240,160L240,160Q240,160 240,160Q240,160 240,160L240,800Q240,800 240,800Q240,800 240,800L240,800Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_library.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_library.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,613Q254,606 269,603Q284,600 300,600L320,600L320,160L300,160Q275,160 257.5,177.5Q240,195 240,220L240,613ZM400,600L720,600L720,160Q720,160 720,160Q720,160 720,160L400,160L400,600ZM240,613Q240,613 240,613Q240,613 240,613L240,613L240,160L240,160Q240,160 240,160Q240,160 240,160L240,613ZM300,880Q242,880 201,839Q160,798 160,740L160,220Q160,162 201,121Q242,80 300,80L720,80Q753,80 776.5,103.5Q800,127 800,160L800,661Q800,669 793.5,675.5Q787,682 770,690Q756,697 748,710Q740,723 740,740Q740,757 748,770.5Q756,784 770,790Q784,796 792,806.5Q800,817 800,829L800,839Q800,856 788.5,868Q777,880 760,880L300,880ZM300,800L673,800Q667,786 663.5,771.5Q660,757 660,740Q660,724 663,709Q666,694 673,680L300,680Q274,680 257,697.5Q240,715 240,740Q240,766 257,783Q274,800 300,800Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_mall.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_mall.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,880Q167,880 143.5,856.5Q120,833 120,800L120,320Q120,287 143.5,263.5Q167,240 200,240L280,240Q280,157 338.5,98.5Q397,40 480,40Q563,40 621.5,98.5Q680,157 680,240L760,240Q793,240 816.5,263.5Q840,287 840,320L840,800Q840,833 816.5,856.5Q793,880 760,880L200,880ZM200,800L760,800Q760,800 760,800Q760,800 760,800L760,320Q760,320 760,320Q760,320 760,320L200,320Q200,320 200,320Q200,320 200,320L200,800Q200,800 200,800Q200,800 200,800ZM360,240L600,240Q600,190 565,155Q530,120 480,120Q430,120 395,155Q360,190 360,240ZM200,800Q200,800 200,800Q200,800 200,800L200,320Q200,320 200,320Q200,320 200,320L200,320Q200,320 200,320Q200,320 200,320L200,800Q200,800 200,800Q200,800 200,800L200,800ZM479,560Q553,560 613,511Q673,462 672,401Q672,384 661,372Q650,360 633,360Q619,360 608,369Q597,378 592,396Q581,434 549,457Q517,480 479,480Q441,480 408.5,457Q376,434 366,396Q361,377 351,368.5Q341,360 327,360Q310,360 298.5,372Q287,384 287,401Q287,462 346,511Q405,560 479,560Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_mobile_phone.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_mobile_phone.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M420,800L540,800Q548,800 554,794Q560,788 560,780Q560,772 554,766Q548,760 540,760L420,760Q412,760 406,766Q400,772 400,780Q400,788 406,794Q412,800 420,800ZM280,920Q247,920 223.5,896.5Q200,873 200,840L200,120Q200,87 223.5,63.5Q247,40 280,40L680,40Q713,40 736.5,63.5Q760,87 760,120L760,840Q760,873 736.5,896.5Q713,920 680,920L280,920ZM280,720L280,840Q280,840 280,840Q280,840 280,840L680,840Q680,840 680,840Q680,840 680,840L680,720L280,720ZM280,640L680,640L680,240L280,240L280,640ZM280,160L680,160L680,120Q680,120 680,120Q680,120 680,120L280,120Q280,120 280,120Q280,120 280,120L280,160ZM280,720L280,720L280,840Q280,840 280,840Q280,840 280,840L280,840Q280,840 280,840Q280,840 280,840L280,720ZM280,160L280,120Q280,120 280,120Q280,120 280,120L280,120Q280,120 280,120Q280,120 280,120L280,160L280,160Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_museum.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_museum.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M80,880L80,800L160,800L160,440L134,440Q111,440 95.5,424Q80,408 80,385Q80,373 85.5,363Q91,353 101,346L434,112Q445,104 456.5,100.5Q468,97 480,97Q492,97 503.5,100.5Q515,104 526,112L859,346Q869,353 874.5,363.5Q880,374 880,386Q880,409 864.5,424.5Q849,440 826,440L800,440L800,800L880,800L880,880L80,880ZM720,800L720,346L480,178Q480,178 480,178Q480,178 480,178L240,346L240,800L720,800ZM480,648Q490,648 498.5,643.5Q507,639 513,630L560,560L560,680Q560,697 571.5,708.5Q583,720 600,720Q617,720 628.5,708.5Q640,697 640,680L640,473Q640,459 630.5,449.5Q621,440 607,440L578,440Q570,440 562.5,444Q555,448 550,455L480,560L412,458Q407,450 398,445Q389,440 379,440L360,440Q343,440 331.5,451.5Q320,463 320,480L320,680Q320,697 331.5,708.5Q343,720 360,720Q377,720 388.5,708.5Q400,697 400,680L400,560L447,630Q453,639 461.5,643.5Q470,648 480,648ZM720,800L240,800L240,800L480,800Q480,800 480,800Q480,800 480,800L720,800L720,800Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_nightclub.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_nightclub.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,720L280,560L81,262Q67,242 79,221Q91,200 115,200L525,200Q549,200 561,221Q573,242 559,262L360,560L360,720L400,720Q417,720 428.5,731.5Q440,743 440,760Q440,777 428.5,788.5Q417,800 400,800L240,800Q223,800 211.5,788.5Q200,777 200,760Q200,743 211.5,731.5Q223,720 240,720L280,720ZM236,360L404,360L460,280L180,280L236,360ZM640,800Q590,800 555,765Q520,730 520,680Q520,630 555,595Q590,560 640,560Q651,560 661,561.5Q671,563 680,568L680,240Q680,223 691.5,211.5Q703,200 720,200L820,200Q845,200 862.5,217.5Q880,235 880,260Q880,285 862.5,302.5Q845,320 820,320L760,320L760,680Q760,730 725,765Q690,800 640,800Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_optician.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_optician.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M274,600Q305,600 329.5,582Q354,564 364,535L379,489Q395,441 371,400.5Q347,360 302,360L161,360L180,517Q185,552 211.5,576Q238,600 274,600ZM686,600Q722,600 748.5,576Q775,552 780,517L799,360L659,360Q614,360 590,401Q566,442 582,490L596,535Q606,564 630.5,582Q655,600 686,600ZM274,680Q208,680 158.5,636.5Q109,593 101,527L80,360L80,360Q63,360 51.5,348.5Q40,337 40,320Q40,303 51.5,291.5Q63,280 80,280L302,280Q346,280 382.5,301.5Q419,323 440,360L521,360Q542,323 578.5,301.5Q615,280 659,280L880,280Q897,280 908.5,291.5Q920,303 920,320Q920,337 908.5,348.5Q897,360 880,360L880,360L859,527Q851,593 801.5,636.5Q752,680 686,680Q629,680 583.5,647.5Q538,615 520,561L505,516Q503,509 501,501.5Q499,494 497,480L463,480Q461,492 459,499.5Q457,507 455,514L440,560Q422,614 376.5,647Q331,680 274,680Z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M440,777L440,503L200,364L200,638Q200,638 200,638Q200,638 200,638L440,777ZM520,777L760,638Q760,638 760,638Q760,638 760,638L760,364L520,503L520,777ZM440,869L160,708Q141,697 130.5,679Q120,661 120,639L120,321Q120,299 130.5,281Q141,263 160,252L440,91Q459,80 480,80Q501,80 520,91L800,252Q819,263 829.5,281Q840,299 840,321L840,639Q840,661 829.5,679Q819,697 800,708L520,869Q501,880 480,880Q459,880 440,869ZM640,341L717,297L480,160Q480,160 480,160Q480,160 480,160L402,205L640,341ZM480,434L558,389L321,252L243,297L480,434Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_parking.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_parking.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M400,600L400,760Q400,793 376.5,816.5Q353,840 320,840Q287,840 263.5,816.5Q240,793 240,760L240,200Q240,167 263.5,143.5Q287,120 320,120L520,120Q620,120 690,190Q760,260 760,360Q760,460 690,530Q620,600 520,600L400,600ZM400,440L528,440Q561,440 584.5,416.5Q608,393 608,360Q608,327 584.5,303.5Q561,280 528,280L400,280L400,440Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_pharmacy.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_pharmacy.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M204,840Q162,840 138.5,807Q115,774 128,735L200,520L128,305Q115,266 138.5,233Q162,200 204,200L628,200L669,87Q676,67 694.5,58.5Q713,50 733,57Q753,64 761.5,82.5Q770,101 763,121L734,200L756,200Q798,200 821.5,233Q845,266 832,305L760,520L832,735Q845,774 821.5,807Q798,840 756,840L204,840ZM440,680L520,680L520,560L640,560L640,480L520,480L520,360L440,360L440,480L320,480L320,560L440,560L440,680ZM204,760L756,760Q756,760 756,760Q756,760 756,760L676,520L756,280Q756,280 756,280Q756,280 756,280L204,280Q204,280 204,280Q204,280 204,280L284,520L204,760Q204,760 204,760Q204,760 204,760ZM480,520Q480,520 480,520Q480,520 480,520L480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_photo.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_photo.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,700Q555,700 607.5,647.5Q660,595 660,520Q660,445 607.5,392.5Q555,340 480,340Q405,340 352.5,392.5Q300,445 300,520Q300,595 352.5,647.5Q405,700 480,700ZM480,620Q438,620 409,591Q380,562 380,520Q380,478 409,449Q438,420 480,420Q522,420 551,449Q580,478 580,520Q580,562 551,591Q522,620 480,620ZM160,840Q127,840 103.5,816.5Q80,793 80,760L80,280Q80,247 103.5,223.5Q127,200 160,200L286,200L336,146Q347,134 362.5,127Q378,120 395,120L565,120Q582,120 597.5,127Q613,134 624,146L674,200L800,200Q833,200 856.5,223.5Q880,247 880,280L880,760Q880,793 856.5,816.5Q833,840 800,840L160,840ZM160,760L800,760Q800,760 800,760Q800,760 800,760L800,280Q800,280 800,280Q800,280 800,280L638,280L565,200L395,200L322,280L160,280Q160,280 160,280Q160,280 160,280L160,760Q160,760 160,760Q160,760 160,760ZM480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520L480,520L480,520L480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_pizza.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_pizza.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,120Q568,120 659,150Q750,180 820,234Q836,246 844,263Q852,280 852,298Q852,309 848.5,320.5Q845,332 838,343L547,780Q535,798 517,807Q499,816 480,816Q461,816 443,807Q425,798 413,780L122,343Q115,332 112,321Q109,310 109,299Q109,281 117,264Q125,247 141,235Q211,182 301.5,151Q392,120 480,120ZM480,200Q397,200 327,228Q257,256 188,298Q188,298 188,298Q188,298 188,298Q188,298 188,298Q188,298 188,298L480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736L772,298Q772,298 772,298Q772,298 772,298Q772,298 772,298Q772,298 772,298Q703,255 633.5,227.5Q564,200 480,200ZM380,400Q405,400 422.5,382.5Q440,365 440,340Q440,315 422.5,297.5Q405,280 380,280Q355,280 337.5,297.5Q320,315 320,340Q320,365 337.5,382.5Q355,400 380,400ZM480,600Q505,600 522.5,582.5Q540,565 540,540Q540,515 522.5,497.5Q505,480 480,480Q455,480 437.5,497.5Q420,515 420,540Q420,565 437.5,582.5Q455,600 480,600ZM480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736L480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736L480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Q480,736 480,736Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_place.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_place.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,659Q579,579 629.5,505Q680,431 680,366Q680,310 659.5,270.5Q639,231 609,206.5Q579,182 544,171Q509,160 480,160Q451,160 416,171Q381,182 351,206.5Q321,231 300.5,270.5Q280,310 280,366Q280,431 330.5,505Q381,579 480,659ZM480,744Q470,744 460.5,741Q451,738 443,732Q362,669 281,573.5Q200,478 200,366Q200,295 225.5,241.5Q251,188 291,152Q331,116 381,98Q431,80 480,80Q529,80 579,98Q629,116 669,152Q709,188 734.5,241.5Q760,295 760,366Q760,478 679,573.5Q598,669 517,732Q509,738 499.5,741Q490,744 480,744ZM480,440Q513,440 536.5,416.5Q560,393 560,360Q560,327 536.5,303.5Q513,280 480,280Q447,280 423.5,303.5Q400,327 400,360Q400,393 423.5,416.5Q447,440 480,440ZM240,880Q223,880 211.5,868.5Q200,857 200,840Q200,823 211.5,811.5Q223,800 240,800L720,800Q737,800 748.5,811.5Q760,823 760,840Q760,857 748.5,868.5Q737,880 720,880L240,880ZM480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Q480,366 480,366Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_police.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_police.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,540L565,605Q571,610 577,605.5Q583,601 581,594L548,488L637,418Q642,413 640,406.5Q638,400 631,400L524,400L490,293Q488,286 480,286Q472,286 470,293L436,400L329,400Q322,400 319.5,406.5Q317,413 322,418L410,488L377,595Q375,602 381,606.5Q387,611 393,606L480,540ZM480,876Q473,876 467,875Q461,874 455,872Q320,827 240,705.5Q160,584 160,444L160,255Q160,230 174.5,210Q189,190 212,181L452,91Q466,86 480,86Q494,86 508,91L748,181Q771,190 785.5,210Q800,230 800,255L800,444Q800,584 720,705.5Q640,827 505,872Q499,874 493,875Q487,876 480,876ZM480,796Q584,763 652,664Q720,565 720,444L720,255Q720,255 720,255Q720,255 720,255L480,165Q480,165 480,165Q480,165 480,165L240,255Q240,255 240,255Q240,255 240,255L240,444Q240,565 308,664Q376,763 480,796ZM480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_post_office.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_post_office.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M120,880Q103,880 91.5,868.5Q80,857 80,840L80,520Q80,503 91.5,491.5Q103,480 120,480L240,480L240,320Q240,220 310,150Q380,80 480,80L640,80Q740,80 810,150Q880,220 880,320L880,840Q880,857 868.5,868.5Q857,880 840,880Q823,880 811.5,868.5Q800,857 800,840L800,760L640,760L640,840Q640,857 628.5,868.5Q617,880 600,880L120,880ZM640,680L800,680L800,320Q800,254 753,207Q706,160 640,160L480,160Q414,160 367,207Q320,254 320,320L320,480L600,480Q617,480 628.5,491.5Q640,503 640,520L640,680ZM360,674Q360,674 360,674Q360,674 360,674L560,560L160,560L360,674ZM160,800L560,800L560,630L400,721Q391,726 381,729Q371,732 360,732Q349,732 339,729Q329,726 320,721L160,630L160,800ZM160,560L160,586Q160,569 160,585Q160,601 160,612Q160,619 160,625.5Q160,632 160,639L160,630L160,800L160,800L160,630L160,639Q160,632 160,625.5Q160,619 160,612Q160,601 160,585Q160,569 160,586L160,560L160,560ZM440,400Q423,400 411.5,388.5Q400,377 400,360Q400,343 411.5,331.5Q423,320 440,320L680,320Q697,320 708.5,331.5Q720,343 720,360Q720,377 708.5,388.5Q697,400 680,400L440,400Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_pub.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_pub.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M320,760L600,760Q600,760 600,760Q600,760 600,760L600,360L520,360Q492,360 474,374Q456,388 431,415Q411,437 384.5,460.5Q358,484 320,495L320,760Q320,760 320,760Q320,760 320,760ZM240,760L240,494Q188,480 154,438Q120,396 120,340Q120,287 150.5,246Q181,205 229,189Q252,141 297.5,111Q343,81 400,81Q435,81 465.5,93Q496,105 521,125Q531,123 540,121.5Q549,120 560,120Q626,120 673,167Q720,214 720,280Q720,302 714.5,322Q709,342 698,360L760,360Q793,360 816.5,383.5Q840,407 840,440L840,680Q840,713 816.5,736.5Q793,760 760,760L680,760L680,760Q680,793 656.5,816.5Q633,840 600,840L320,840Q287,840 263.5,816.5Q240,793 240,760ZM200,340Q200,373 223.5,396.5Q247,420 280,420Q312,420 334.5,399Q357,378 381,352Q406,325 437.5,302.5Q469,280 520,280L640,280Q640,247 616.5,223.5Q593,200 560,200Q535,200 518,206.5Q501,213 501,213L470,187Q459,178 441.5,169.5Q424,161 400,161Q368,161 341.5,178Q315,195 301,224L287,254L255,265Q230,273 215,293.5Q200,314 200,340ZM680,680L760,680Q760,680 760,680Q760,680 760,680L760,440Q760,440 760,440Q760,440 760,440L680,440L680,680ZM320,760Q320,760 320,760Q320,760 320,760L320,760Q358,760 384.5,760Q411,760 431,760Q456,760 474,760Q492,760 520,760L600,760L600,760Q600,760 600,760Q600,760 600,760L320,760Z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,760L240,600L200,600Q183,600 171.5,588.5Q160,577 160,560Q160,543 171.5,531.5Q183,520 200,520L244,520Q256,445 310.5,390.5Q365,336 440,324L440,160Q440,143 451.5,131.5Q463,120 480,120L680,120Q697,120 708.5,131.5Q720,143 720,160L720,240Q720,257 708.5,268.5Q697,280 680,280L520,280L520,324Q595,336 649.5,390.5Q704,445 716,520L760,520Q777,520 788.5,531.5Q800,543 800,560Q800,577 788.5,588.5Q777,600 760,600L720,600L720,760L840,760Q857,760 868.5,771.5Q880,783 880,800Q880,817 868.5,828.5Q857,840 840,840L120,840Q103,840 91.5,828.5Q80,817 80,800Q80,783 91.5,771.5Q103,760 120,760L240,760ZM320,760L440,760L440,600L320,600L320,760ZM520,760L640,760L640,600L520,600L520,760ZM326,520L634,520Q620,467 577,433.5Q534,400 480,400Q426,400 383,433.5Q340,467 326,520ZM480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520Q480,520 480,520L480,520Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_railway_stop.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_railway_stop.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,620L160,240Q160,187 187.5,155.5Q215,124 260,107.5Q305,91 362.5,85.5Q420,80 480,80Q546,80 604.5,85.5Q663,91 706.5,107.5Q750,124 775,155.5Q800,187 800,240L800,620Q800,679 759.5,719.5Q719,760 660,760L680,780Q697,797 688,818.5Q679,840 655,840Q648,840 641.5,837.5Q635,835 630,830L560,760L400,760L330,830Q325,835 318.5,837.5Q312,840 305,840Q282,840 272.5,818.5Q263,797 280,780L300,760Q241,760 200.5,719.5Q160,679 160,620ZM480,160Q374,160 325,172.5Q276,185 258,200L706,200Q691,183 641.5,171.5Q592,160 480,160ZM240,400L440,400L440,280L240,280L240,400ZM660,480L300,480Q274,480 257,480Q240,480 240,480L240,480L720,480L720,480Q720,480 703,480Q686,480 660,480ZM520,400L720,400L720,280L520,280L520,400ZM340,640Q366,640 383,623Q400,606 400,580Q400,554 383,537Q366,520 340,520Q314,520 297,537Q280,554 280,580Q280,606 297,623Q314,640 340,640ZM620,640Q646,640 663,623Q680,606 680,580Q680,554 663,537Q646,520 620,520Q594,520 577,537Q560,554 560,580Q560,606 577,623Q594,640 620,640ZM300,680L660,680Q686,680 703,663Q720,646 720,620L720,480L240,480L240,620Q240,646 257,663Q274,680 300,680ZM480,200Q592,200 641.5,200Q691,200 706,200L258,200Q276,200 325,200Q374,200 480,200Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_ramen.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_ramen.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M320,810Q222,772 151,697.5Q80,623 80,520Q80,503 91.5,491.5Q103,480 120,480L160,480L160,196Q160,181 170,170Q180,159 195,157L847,84Q861,82 870.5,91Q880,100 880,114Q880,125 872,133.5Q864,142 853,143L420,192L420,260L850,260Q863,260 871.5,268.5Q880,277 880,290Q880,303 871.5,311.5Q863,320 850,320L420,320L420,480L840,480Q857,480 868.5,491.5Q880,503 880,520Q880,623 809,697.5Q738,772 640,810L640,840Q640,857 628.5,868.5Q617,880 600,880L360,880Q343,880 331.5,868.5Q320,857 320,840L320,810ZM320,260L360,260L360,199L320,203L320,260ZM220,260L260,260L260,210L220,214L220,260ZM320,480L360,480L360,320L320,320L320,480ZM220,480L260,480L260,320L220,320L220,480ZM400,800L560,800L560,756L610,736Q671,712 718,667Q765,622 786,560L174,560Q195,622 242,667.5Q289,713 350,736L400,756L400,800ZM480,560L480,560L480,560Q480,560 480,560Q480,560 480,560L480,560Q480,560 480,560Q480,560 480,560L480,560L480,560L480,560Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_restaurant.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_restaurant.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,360L280,120Q280,103 291.5,91.5Q303,80 320,80Q337,80 348.5,91.5Q360,103 360,120L360,360L400,360L400,120Q400,103 411.5,91.5Q423,80 440,80Q457,80 468.5,91.5Q480,103 480,120L480,360Q480,416 445.5,458Q411,500 360,514L360,840Q360,857 348.5,868.5Q337,880 320,880Q303,880 291.5,868.5Q280,857 280,840L280,514Q229,500 194.5,458Q160,416 160,360L160,120Q160,103 171.5,91.5Q183,80 200,80Q217,80 228.5,91.5Q240,103 240,120L240,360L280,360ZM680,560L600,560Q583,560 571.5,548.5Q560,537 560,520L560,280Q560,210 611.5,145Q663,80 718,80Q736,80 748,94Q760,108 760,127L760,840Q760,857 748.5,868.5Q737,880 720,880Q703,880 691.5,868.5Q680,857 680,840L680,560Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_school.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_school.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,320Q160,264 194,222Q228,180 280,166L280,120Q280,103 291.5,91.5Q303,80 320,80L360,80Q377,80 388.5,91.5Q400,103 400,120L400,160L560,160L560,120Q560,103 571.5,91.5Q583,80 600,80L640,80Q657,80 668.5,91.5Q680,103 680,120L680,166Q732,180 766,222Q800,264 800,320L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM240,800L720,800Q720,800 720,800Q720,800 720,800L720,320Q720,287 696.5,263.5Q673,240 640,240L320,240Q287,240 263.5,263.5Q240,287 240,320L240,800Q240,800 240,800Q240,800 240,800ZM580,560L580,600Q580,617 591.5,628.5Q603,640 620,640Q637,640 648.5,628.5Q660,617 660,600L660,520Q660,503 648.5,491.5Q637,480 620,480L340,480Q323,480 311.5,491.5Q300,503 300,520Q300,537 311.5,548.5Q323,560 340,560L580,560ZM480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520L480,520Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_shoes.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_shoes.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M216,380Q255,380 290,394Q325,408 354,435L736,800L760,800Q777,800 788.5,788.5Q800,777 800,760Q800,752 798.5,743Q797,734 788,725L605,542L534,328Q534,328 534,328Q534,328 534,328L460,346Q422,356 391,332Q360,308 360,269L360,185Q360,185 360,185Q360,185 360,185L332,171Q332,171 332,171Q332,171 332,171L178,377Q177,378 177,378.5Q177,379 176,380L216,380ZM216,460L170,460Q173,467 177.5,473Q182,479 188,484L512,779Q523,790 537,795Q551,800 566,800L620,800L299,493Q282,476 260.5,468Q239,460 216,460ZM566,880Q536,880 509,869Q482,858 459,838L134,543Q88,501 82.5,440Q77,379 114,329L268,123Q285,100 313.5,92.5Q342,85 368,99L396,113Q417,124 428.5,143Q440,162 440,185L440,269L514,250Q544,242 572,257.5Q600,273 610,302L675,498L845,668Q865,688 872.5,711Q880,734 880,760Q880,810 845,845Q810,880 760,880L566,880Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_soccer.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_soccer.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM680,380L734,362L750,308Q718,260 673,225.5Q628,191 574,174L520,212L520,268L680,380ZM280,380L440,268L440,212L386,174Q332,191 287,225.5Q242,260 210,308L226,362L280,380ZM238,688L284,684L314,630L256,456L200,436L160,466Q160,531 178,584.5Q196,638 238,688ZM480,800Q506,800 531,796Q556,792 580,784L608,724L582,680L378,680L352,724L380,784Q404,792 429,796Q454,800 480,800ZM390,600L570,600L626,440L480,338L336,440L390,600ZM722,688Q764,638 782,584.5Q800,531 800,466L760,438L704,456L646,630L676,684L722,688Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_supermarket.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_supermarket.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M640,880Q540,880 470,810Q400,740 400,640Q400,540 470,470Q540,400 640,400Q740,400 810,470Q880,540 880,640Q880,740 810,810Q740,880 640,880ZM640,800Q706,800 753,753Q800,706 800,640Q800,574 753,527Q706,480 640,480Q574,480 527,527Q480,574 480,640Q480,706 527,753Q574,800 640,800ZM160,800Q127,800 103.5,776.5Q80,753 80,720L80,416Q80,408 81.5,400Q83,392 86,384L166,200L160,200Q143,200 131.5,188.5Q120,177 120,160L120,120Q120,103 131.5,91.5Q143,80 160,80L440,80Q457,80 468.5,91.5Q480,103 480,120L480,160Q480,177 468.5,188.5Q457,200 440,200L434,200L500,352Q481,362 464,373Q447,384 432,398L348,200L252,200L160,416L160,720Q160,720 160,720Q160,720 160,720L330,720Q335,741 343.5,761.5Q352,782 364,800L160,800ZM640,360Q598,360 569,331Q540,302 540,260Q540,218 569,189Q598,160 640,160L640,360Q640,318 669,289Q698,260 740,260Q782,260 811,289Q840,318 840,360L640,360Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_tapas.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_tapas.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,920Q263,920 251.5,908.5Q240,897 240,880L240,560L160,560Q118,560 89,531Q60,502 60,460Q60,418 89,389Q118,360 160,360L240,360L240,320L160,320Q118,320 89,291Q60,262 60,220Q60,178 89,149Q118,120 160,120L240,120L240,80Q240,63 251.5,51.5Q263,40 280,40Q297,40 308.5,51.5Q320,63 320,80L320,120L400,120Q442,120 471,149Q500,178 500,220Q500,262 471,291Q442,320 400,320L320,320L320,360L400,360Q442,360 471,389Q500,418 500,460Q500,502 471,531Q442,560 400,560L320,560L320,880Q320,897 308.5,908.5Q297,920 280,920ZM160,480L400,480Q408,480 414,474Q420,468 420,460Q420,452 414,446Q408,440 400,440L160,440Q152,440 146,446Q140,452 140,460Q140,468 146,474Q152,480 160,480ZM160,240L400,240Q408,240 414,234Q420,228 420,220Q420,212 414,206Q408,200 400,200L160,200Q152,200 146,206Q140,212 140,220Q140,228 146,234Q152,240 160,240ZM680,840L680,554Q627,540 593.5,497.5Q560,455 560,400L560,80Q560,63 571.5,51.5Q583,40 600,40L840,40Q857,40 868.5,51.5Q880,63 880,80L880,400Q880,455 846.5,497.5Q813,540 760,554L760,840L800,840Q817,840 828.5,851.5Q840,863 840,880Q840,897 828.5,908.5Q817,920 800,920L640,920Q623,920 611.5,908.5Q600,897 600,880Q600,863 611.5,851.5Q623,840 640,840L680,840ZM720,480Q753,480 776.5,456.5Q800,433 800,400L800,320L640,320L640,400Q640,433 663.5,456.5Q687,480 720,480ZM640,240L800,240L800,120L640,120L640,240ZM140,480L140,480Q140,480 140,474Q140,468 140,460Q140,452 140,446Q140,440 140,440L140,440Q140,440 140,446Q140,452 140,460Q140,468 140,474Q140,480 140,480ZM140,240L140,240Q140,240 140,234Q140,228 140,220Q140,212 140,206Q140,200 140,200L140,200Q140,200 140,206Q140,212 140,220Q140,228 140,234Q140,240 140,240ZM720,320Q720,320 720,320Q720,320 720,320L720,320L720,320L720,320Q720,320 720,320Q720,320 720,320Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_tennis.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_tennis.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M520,582Q423,582 378,593Q333,604 301,636L165,772Q154,783 137.5,783Q121,783 109,772Q97,760 97,743.5Q97,727 109,715L244,580Q275,549 286.5,502.5Q298,456 298,360Q298,302 324,246Q350,190 398,142Q489,51 599,39Q709,27 780,100Q852,172 840,282Q828,392 738,482Q690,530 634,556Q578,582 520,582ZM412,466Q459,512 539,500Q619,488 682,425Q746,361 758.5,281.5Q771,202 724,157Q676,109 598.5,121Q521,133 456,197Q393,260 379.5,339.5Q366,419 412,466ZM720,920Q654,920 607,873Q560,826 560,760Q560,694 607,647Q654,600 720,600Q786,600 833,647Q880,694 880,760Q880,826 833,873Q786,920 720,920ZM720,840Q753,840 776.5,816.5Q800,793 800,760Q800,727 776.5,703.5Q753,680 720,680Q687,680 663.5,703.5Q640,727 640,760Q640,793 663.5,816.5Q687,840 720,840ZM720,760Q720,760 720,760Q720,760 720,760Q720,760 720,760Q720,760 720,760Q720,760 720,760Q720,760 720,760Q720,760 720,760Q720,760 720,760Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_theatre.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_theatre.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M760,300Q777,300 788.5,288.5Q800,277 800,260Q800,243 788.5,231.5Q777,220 760,220Q743,220 731.5,231.5Q720,243 720,260Q720,277 731.5,288.5Q743,300 760,300ZM600,300Q617,300 628.5,288.5Q640,277 640,260Q640,243 628.5,231.5Q617,220 600,220Q583,220 571.5,231.5Q560,243 560,260Q560,277 571.5,288.5Q583,300 600,300ZM680,360Q651,360 624.5,371.5Q598,383 586,409Q581,419 588.5,427.5Q596,436 608,436L752,436Q764,436 771.5,427.5Q779,419 774,409Q762,383 735.5,371.5Q709,360 680,360ZM280,880Q180,880 110,810Q40,740 40,640L40,440Q40,407 63.5,383.5Q87,360 120,360L440,360Q473,360 496.5,383.5Q520,407 520,440L520,640Q520,740 450,810Q380,880 280,880ZM280,800Q346,800 393,753Q440,706 440,640L440,440Q440,440 440,440Q440,440 440,440L120,440Q120,440 120,440Q120,440 120,440L120,640Q120,706 167,753Q214,800 280,800ZM680,600Q654,600 628.5,594.5Q603,589 580,578L580,484Q602,501 627.5,510.5Q653,520 680,520Q746,520 793,473Q840,426 840,360L840,160Q840,160 840,160Q840,160 840,160L520,160Q520,160 520,160Q520,160 520,160L520,300L440,300L440,160Q440,127 463.5,103.5Q487,80 520,80L840,80Q873,80 896.5,103.5Q920,127 920,160L920,360Q920,460 850,530Q780,600 680,600ZM200,580Q217,580 228.5,568.5Q240,557 240,540Q240,523 228.5,511.5Q217,500 200,500Q183,500 171.5,511.5Q160,523 160,540Q160,557 171.5,568.5Q183,580 200,580ZM360,580Q377,580 388.5,568.5Q400,557 400,540Q400,523 388.5,511.5Q377,500 360,500Q343,500 331.5,511.5Q320,523 320,540Q320,557 331.5,568.5Q343,580 360,580ZM280,716Q308,716 333,705Q358,694 372,670Q377,659 371,649.5Q365,640 354,640L206,640Q195,640 189,649.5Q183,659 188,670Q202,694 227,705Q252,716 280,716ZM280,620Q280,620 280,620Q280,620 280,620L280,620Q280,620 280,620Q280,620 280,620L280,620Q280,620 280,620Q280,620 280,620L280,620Q280,620 280,620Q280,620 280,620ZM670,340L670,340Q670,340 670,340Q670,340 670,340L670,340Q670,340 670,340Q670,340 670,340L670,340Q670,340 670,340Q670,340 670,340Q670,340 670,340Q670,340 670,340L670,340Q670,340 670,340Q670,340 670,340Q670,340 670,340Q670,340 670,340L670,340Q670,340 670,340Q670,340 670,340L670,340Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_tobacco.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_tobacco.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M140,760Q115,760 97.5,742.5Q80,725 80,700Q80,675 97.5,657.5Q115,640 140,640L650,640Q663,640 671.5,648.5Q680,657 680,670L680,730Q680,743 671.5,751.5Q663,760 650,760L140,760ZM750,760Q737,760 728.5,751.5Q720,743 720,730L720,670Q720,657 728.5,648.5Q737,640 750,640Q763,640 771.5,648.5Q780,657 780,670L780,730Q780,743 771.5,751.5Q763,760 750,760ZM850,760Q837,760 828.5,751.5Q820,743 820,730L820,670Q820,657 828.5,648.5Q837,640 850,640Q863,640 871.5,648.5Q880,657 880,670L880,730Q880,743 871.5,751.5Q863,760 850,760ZM750,600Q737,600 728.5,591.5Q720,583 720,570L720,548Q720,509 697,488.5Q674,468 642,468L580,468Q524,468 485,429Q446,390 446,334Q446,278 485,239Q524,200 580,200Q593,200 601.5,208.5Q610,217 610,230Q610,243 601.5,251.5Q593,260 580,260Q550,260 528,281Q506,302 506,334Q506,366 528,387Q550,408 580,408L642,408Q698,408 739,444Q780,480 780,534L780,570Q780,583 771.5,591.5Q763,600 750,600ZM850,600Q837,600 828.5,591.5Q820,583 820,570L820,510Q820,444 774,396Q728,348 660,348Q647,348 638.5,339.5Q630,331 630,318Q630,305 638.5,296.5Q647,288 660,288Q690,288 712,266Q734,244 734,214Q734,184 712,162Q690,140 660,140Q647,140 638.5,131.5Q630,123 630,110Q630,97 638.5,88.5Q647,80 660,80Q716,80 755,119Q794,158 794,214Q794,243 783,266.5Q772,290 754,310Q810,336 845,390Q880,444 880,510L880,570Q880,583 871.5,591.5Q863,600 850,600Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_toilets.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_toilets.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M220,840L220,580L200,580Q183,580 171.5,568.5Q160,557 160,540L160,360Q160,327 183.5,303.5Q207,280 240,280L360,280Q393,280 416.5,303.5Q440,327 440,360L440,540Q440,557 428.5,568.5Q417,580 400,580L380,580L380,840Q380,857 368.5,868.5Q357,880 340,880L260,880Q243,880 231.5,868.5Q220,857 220,840ZM300,240Q267,240 243.5,216.5Q220,193 220,160Q220,127 243.5,103.5Q267,80 300,80Q333,80 356.5,103.5Q380,127 380,160Q380,193 356.5,216.5Q333,240 300,240ZM600,840L600,640L535,640Q515,640 503,623.5Q491,607 498,587L582,334Q590,308 611.5,294Q633,280 660,280Q687,280 708.5,294Q730,308 738,334L822,587Q829,607 817,623.5Q805,640 785,640L720,640L720,840Q720,857 708.5,868.5Q697,880 680,880L640,880Q623,880 611.5,868.5Q600,857 600,840ZM660,240Q627,240 603.5,216.5Q580,193 580,160Q580,127 603.5,103.5Q627,80 660,80Q693,80 716.5,103.5Q740,127 740,160Q740,193 716.5,216.5Q693,240 660,240Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_tram_stop.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_tram_stop.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,700L160,320Q160,223 245,193Q330,163 440,160L470,100L310,100Q297,100 288.5,91.5Q280,83 280,70Q280,57 288.5,48.5Q297,40 310,40L650,40Q663,40 671.5,48.5Q680,57 680,70Q680,83 671.5,91.5Q663,100 650,100L550,100L520,160Q639,163 719.5,192.5Q800,222 800,320L800,700Q800,759 759.5,799.5Q719,840 660,840L680,860Q697,877 688,898.5Q679,920 655,920Q648,920 641.5,917.5Q635,915 630,910L560,840L400,840L330,910Q325,915 318.5,917.5Q312,920 305,920Q282,920 272.5,898.5Q263,877 280,860L300,840Q241,840 200.5,799.5Q160,759 160,700ZM660,560L300,560Q274,560 257,560Q240,560 240,560L240,560L720,560L720,560Q720,560 703,560Q686,560 660,560ZM480,720Q505,720 522.5,702.5Q540,685 540,660Q540,635 522.5,617.5Q505,600 480,600Q455,600 437.5,617.5Q420,635 420,660Q420,685 437.5,702.5Q455,720 480,720ZM478,280Q614,280 654,280Q694,280 706,280L256,280Q268,280 306,280Q344,280 478,280ZM240,480L720,480L720,360L240,360L240,480ZM300,760L660,760Q686,760 703,743Q720,726 720,700L720,560L240,560L240,700Q240,726 257,743Q274,760 300,760ZM478,240Q344,240 306,254.5Q268,269 256,280L706,280Q694,266 654,253Q614,240 478,240Z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,640Q280,607 303.5,583.5Q327,560 360,560Q393,560 416.5,583.5Q440,607 440,640Q440,673 416.5,696.5Q393,720 360,720Q327,720 303.5,696.5Q280,673 280,640ZM200,920Q183,920 171.5,908.5Q160,897 160,880L160,560Q160,543 171.5,531.5Q183,520 200,520Q217,520 228.5,531.5Q240,543 240,560L240,760L480,760L480,600Q480,583 491.5,571.5Q503,560 520,560L720,560Q753,560 776.5,583.5Q800,607 800,640L800,880Q800,897 788.5,908.5Q777,920 760,920Q743,920 731.5,908.5Q720,897 720,880L720,840L240,840L240,880Q240,897 228.5,908.5Q217,920 200,920ZM512,306L406,412L415,470Q416,475 414.5,479Q413,483 409,487L405,491Q397,499 387.5,497Q378,495 373,486L339,422L271,385Q263,381 262,372.5Q261,364 267,358L275,350Q277,348 289,345L349,353L455,247L267,145Q256,140 255,128Q254,116 262,108L269,101Q274,96 279.5,94.5Q285,93 291,95L542,160L650,52Q662,40 679,40Q696,40 708,52Q720,64 720,81Q720,98 708,110L600,218L664,468Q666,475 664.5,481Q663,487 658,492L654,496Q645,505 632,503Q619,501 613,490L512,306ZM720,760L720,640Q720,640 720,640Q720,640 720,640L560,640L560,760L720,760ZM560,760L560,760L560,640L560,640Q560,640 560,640Q560,640 560,640L560,760Z"/>
|
||||
</vector>
|
||||
10
core/base/src/main/res/drawable/ic_location_wine.xml
Normal file
10
core/base/src/main/res/drawable/ic_location_wine.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M440,760L440,596Q354,582 297,516Q240,450 240,360L240,160Q240,143 251.5,131.5Q263,120 280,120L680,120Q697,120 708.5,131.5Q720,143 720,160L720,360Q720,450 663,516Q606,582 520,596L520,760L600,760Q617,760 628.5,771.5Q640,783 640,800Q640,817 628.5,828.5Q617,840 600,840L360,840Q343,840 331.5,828.5Q320,817 320,800Q320,783 331.5,771.5Q343,760 360,760L440,760ZM480,520Q536,520 578,486Q620,452 634,400L326,400Q340,452 382,486Q424,520 480,520ZM320,320L640,320L640,200L320,200L320,320ZM480,520Q480,520 480,520Q480,520 480,520L480,520Q480,520 480,520Q480,520 480,520Z"/>
|
||||
</vector>
|
||||
@ -14,7 +14,7 @@ import java.io.File
|
||||
object CrashReporter {
|
||||
fun logException(e: Exception) {
|
||||
if (e !is CancellationException) {
|
||||
com.balsikandar.crashreporter.CrashReporter.logException(e)
|
||||
CrashReporter.logException(e)
|
||||
}
|
||||
Log.e("MM20", Log.getStackTraceString(e))
|
||||
}
|
||||
|
||||
1
core/devicepose/.gitignore
vendored
Normal file
1
core/devicepose/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
48
core/devicepose/build.gradle.kts
Normal file
48
core/devicepose/build.gradle.kts
Normal file
@ -0,0 +1,48 @@
|
||||
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
|
||||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "de.mm20.launcher2.location"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.materialcomponents.core)
|
||||
|
||||
implementation(libs.koin.android)
|
||||
|
||||
implementation(project(":core:ktx"))
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
}
|
||||
0
core/devicepose/consumer-rules.pro
Normal file
0
core/devicepose/consumer-rules.pro
Normal file
21
core/devicepose/proguard-rules.pro
vendored
Normal file
21
core/devicepose/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user