mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-03-30 12:36:00 +02:00
Improves the speed of Location services.
This commit is contained in:
parent
c686e775bf
commit
0084c2b532
@ -27,6 +27,7 @@ import android.location.Location
|
||||
import android.location.LocationListener
|
||||
import android.location.LocationManager
|
||||
import android.os.HandlerThread
|
||||
import android.util.LruCache
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@ -92,7 +93,33 @@ class LocationUtil(context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
class ReverseGeoLocationUtil {
|
||||
object CachedGeoLocations {
|
||||
val locationNames = LruCache<String, String>(20)
|
||||
|
||||
fun cached(geoHashStr: String): String? {
|
||||
return locationNames[geoHashStr]
|
||||
}
|
||||
|
||||
suspend fun geoLocate(
|
||||
geoHashStr: String,
|
||||
location: Location,
|
||||
context: Context,
|
||||
): String? {
|
||||
locationNames[geoHashStr]?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
val name = ReverseGeoLocationUtil().execute(location, context)?.ifBlank { null }
|
||||
|
||||
if (name != null) {
|
||||
locationNames.put(geoHashStr, name)
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
private class ReverseGeoLocationUtil {
|
||||
suspend fun execute(
|
||||
location: Location,
|
||||
context: Context,
|
||||
|
@ -124,7 +124,6 @@ import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import com.fonfon.kgeohash.toGeoHash
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
@ -134,7 +133,6 @@ import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.Nip96MediaServers
|
||||
import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
|
||||
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
|
||||
import com.vitorpamplona.amethyst.ui.components.BechLink
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||
import com.vitorpamplona.amethyst.ui.components.InvoiceRequest
|
||||
@ -144,6 +142,7 @@ import com.vitorpamplona.amethyst.ui.components.ZapRaiserRequest
|
||||
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.CancelIcon
|
||||
import com.vitorpamplona.amethyst.ui.note.CloseIcon
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadCityName
|
||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||
import com.vitorpamplona.amethyst.ui.note.PollIcon
|
||||
import com.vitorpamplona.amethyst.ui.note.RegularPostIcon
|
||||
@ -1172,23 +1171,12 @@ fun FowardZapTo(
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun LocationAsHash(postViewModel: NewPostViewModel) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val locationPermissionState =
|
||||
rememberPermissionState(
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||
)
|
||||
|
||||
if (locationPermissionState.status.isGranted) {
|
||||
var locationDescriptionFlow by remember(postViewModel) { mutableStateOf<Flow<String>?>(null) }
|
||||
|
||||
DisposableEffect(key1 = Unit) {
|
||||
postViewModel.startLocation(context = context)
|
||||
locationDescriptionFlow = postViewModel.location
|
||||
|
||||
onDispose { postViewModel.stopLocation() }
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
@ -1219,7 +1207,7 @@ fun LocationAsHash(postViewModel: NewPostViewModel) {
|
||||
modifier = Modifier.padding(start = 10.dp),
|
||||
)
|
||||
|
||||
locationDescriptionFlow?.let { geoLocation -> DisplayLocationObserver(geoLocation) }
|
||||
DisplayLocationObserver(postViewModel)
|
||||
}
|
||||
|
||||
Divider()
|
||||
@ -1236,41 +1224,39 @@ fun LocationAsHash(postViewModel: NewPostViewModel) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DisplayLocationObserver(geoLocation: Flow<String>) {
|
||||
val location by geoLocation.collectAsStateWithLifecycle(null)
|
||||
fun DisplayLocationObserver(postViewModel: NewPostViewModel) {
|
||||
val context = LocalContext.current
|
||||
var locationDescriptionFlow by remember(postViewModel) { mutableStateOf<Flow<String>?>(null) }
|
||||
|
||||
location?.let { DisplayLocationInTitle(geohash = it) }
|
||||
DisposableEffect(key1 = context) {
|
||||
postViewModel.startLocation(context = context)
|
||||
locationDescriptionFlow = postViewModel.location
|
||||
|
||||
onDispose { postViewModel.stopLocation() }
|
||||
}
|
||||
|
||||
locationDescriptionFlow?.let {
|
||||
val location by it.collectAsStateWithLifecycle(null)
|
||||
|
||||
location?.let { DisplayLocationInTitle(geohash = it) }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DisplayLocationInTitle(geohash: String) {
|
||||
val context = LocalContext.current
|
||||
|
||||
var cityName by remember(geohash) { mutableStateOf<String>(geohash) }
|
||||
|
||||
LaunchedEffect(key1 = geohash) {
|
||||
launch(Dispatchers.IO) {
|
||||
val newCityName =
|
||||
ReverseGeoLocationUtil().execute(geohash.toGeoHash().toLocation(), context)?.ifBlank {
|
||||
null
|
||||
}
|
||||
|
||||
if (newCityName != null && newCityName != cityName) {
|
||||
cityName = newCityName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (geohash != "s0000") {
|
||||
LoadCityName(
|
||||
geohashStr = geohash,
|
||||
onLoading = {
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
LoadingAnimation()
|
||||
},
|
||||
) { cityName ->
|
||||
Text(
|
||||
text = cityName,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.W500,
|
||||
modifier = Modifier.padding(start = Size5dp),
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
LoadingAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,6 @@ import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import coil.Coil
|
||||
import com.fonfon.kgeohash.toGeoHash
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
@ -817,15 +816,12 @@ fun SimpleTextSpinner(
|
||||
fun RenderOption(option: Name) {
|
||||
when (option) {
|
||||
is GeoHashName -> {
|
||||
val geohash = runCatching { option.geoHashTag.toGeoHash() }.getOrNull()
|
||||
if (geohash != null) {
|
||||
LoadCityName(geohash) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(text = "/g/$it", color = MaterialTheme.colorScheme.onSurface)
|
||||
}
|
||||
LoadCityName(option.geoHashTag) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(text = "/g/$it", color = MaterialTheme.colorScheme.onSurface)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.navigation
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
@ -32,7 +31,6 @@ import androidx.navigation.NavBackStackEntry
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.navArgument
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
|
@ -101,7 +101,6 @@ import coil.compose.AsyncImagePainter
|
||||
import coil.request.SuccessResult
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fonfon.kgeohash.GeoHash
|
||||
import com.fonfon.kgeohash.toGeoHash
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.BaseMediaContent
|
||||
@ -115,7 +114,7 @@ import com.vitorpamplona.amethyst.model.Channel
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
|
||||
import com.vitorpamplona.amethyst.service.CachedGeoLocations
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
|
||||
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
|
||||
@ -2768,23 +2767,34 @@ fun LoadOts(
|
||||
|
||||
@Composable
|
||||
fun LoadCityName(
|
||||
geohash: GeoHash,
|
||||
geohashStr: String,
|
||||
onLoading: (@Composable () -> Unit)? = null,
|
||||
content: @Composable (String) -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var cityName by remember(geohash) { mutableStateOf<String>(geohash.toString()) }
|
||||
var cityName by remember(geohashStr) { mutableStateOf(CachedGeoLocations.cached(geohashStr)) }
|
||||
|
||||
LaunchedEffect(key1 = geohash) {
|
||||
launch(Dispatchers.IO) {
|
||||
val newCityName =
|
||||
ReverseGeoLocationUtil().execute(geohash.toLocation(), context)?.ifBlank { null }
|
||||
if (newCityName != null && newCityName != cityName) {
|
||||
cityName = newCityName
|
||||
if (cityName == null) {
|
||||
if (onLoading != null) {
|
||||
onLoading()
|
||||
}
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
LaunchedEffect(key1 = geohashStr, context) {
|
||||
launch(Dispatchers.IO) {
|
||||
val geoHash = runCatching { geohashStr.toGeoHash() }.getOrNull()
|
||||
if (geoHash != null) {
|
||||
val newCityName =
|
||||
CachedGeoLocations.geoLocate(geohashStr, geoHash.toLocation(), context)?.ifBlank { null }
|
||||
if (newCityName != null && newCityName != cityName) {
|
||||
cityName = newCityName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cityName?.let { content(it) }
|
||||
}
|
||||
|
||||
content(cityName)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ -2792,24 +2802,21 @@ fun DisplayLocation(
|
||||
geohashStr: String,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val geoHash = runCatching { geohashStr.toGeoHash() }.getOrNull()
|
||||
if (geoHash != null) {
|
||||
LoadCityName(geoHash) { cityName ->
|
||||
ClickableText(
|
||||
text = AnnotatedString(cityName),
|
||||
onClick = { nav("Geohash/$geoHash") },
|
||||
style =
|
||||
LocalTextStyle.current.copy(
|
||||
color =
|
||||
MaterialTheme.colorScheme.primary.copy(
|
||||
alpha = 0.52f,
|
||||
),
|
||||
fontSize = Font14SP,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
LoadCityName(geohashStr) { cityName ->
|
||||
ClickableText(
|
||||
text = AnnotatedString(cityName),
|
||||
onClick = { nav("Geohash/$geohashStr") },
|
||||
style =
|
||||
LocalTextStyle.current.copy(
|
||||
color =
|
||||
MaterialTheme.colorScheme.primary.copy(
|
||||
alpha = 0.52f,
|
||||
),
|
||||
fontSize = Font14SP,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,32 +31,26 @@ import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
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.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.fonfon.kgeohash.toGeoHash
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.service.NostrGeohashDataSource
|
||||
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadCityName
|
||||
import com.vitorpamplona.amethyst.ui.screen.NostrGeoHashFeedViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.RefresheableFeedView
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdPadding
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun GeoHashScreen(
|
||||
@ -174,27 +168,13 @@ fun DislayGeoTagHeader(
|
||||
geohash: String,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
var cityName by remember(geohash) { mutableStateOf<String>(geohash) }
|
||||
|
||||
LaunchedEffect(key1 = geohash) {
|
||||
launch(Dispatchers.IO) {
|
||||
val newCityName =
|
||||
ReverseGeoLocationUtil().execute(geohash.toGeoHash().toLocation(), context)?.ifBlank {
|
||||
null
|
||||
}
|
||||
if (newCityName != null && newCityName != cityName) {
|
||||
cityName = "$newCityName ($geohash)"
|
||||
}
|
||||
}
|
||||
LoadCityName(geohashStr = geohash) { cityName ->
|
||||
Text(
|
||||
cityName,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
cityName,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
Loading…
x
Reference in New Issue
Block a user