diff --git a/i18n/src/main/res/values-de/strings.xml b/i18n/src/main/res/values-de/strings.xml index 4f49e5ca..e6cfa307 100644 --- a/i18n/src/main/res/values-de/strings.xml +++ b/i18n/src/main/res/values-de/strings.xml @@ -420,4 +420,7 @@ Raster Spaltenanzahl + + Gewähren + Standortzugriff wird benötigt, um den Standort automatisch zu ermitteln \ No newline at end of file diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index d4be9850..b36cd965 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -458,4 +458,7 @@ Grid Number of columns + + Grant + Location access is required to determine the location automatically diff --git a/ui/src/main/java/de/mm20/launcher2/ui/component/MissingPermissionBanner.kt b/ui/src/main/java/de/mm20/launcher2/ui/component/MissingPermissionBanner.kt index b184e859..1187a36c 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/component/MissingPermissionBanner.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/component/MissingPermissionBanner.kt @@ -11,7 +11,9 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import de.mm20.launcher2.ui.R @Composable fun MissingPermissionBanner( @@ -53,7 +55,7 @@ fun MissingPermissionBanner( TextButton( modifier = Modifier.padding(start = 8.dp), onClick = onClick) { - Text("Grant", style = MaterialTheme.typography.labelLarge) + Text(stringResource(R.string.grant_permission), style = MaterialTheme.typography.labelLarge) } } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreen.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreen.kt index 63721785..df885d72 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreen.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreen.kt @@ -1,5 +1,7 @@ package de.mm20.launcher2.ui.settings.weather +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize @@ -18,12 +20,14 @@ import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment 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.compose.ui.window.Dialog import androidx.lifecycle.viewmodel.compose.viewModel import de.mm20.launcher2.preferences.Settings.WeatherSettings.WeatherProvider import de.mm20.launcher2.ui.R +import de.mm20.launcher2.ui.component.MissingPermissionBanner import de.mm20.launcher2.ui.component.preferences.* import de.mm20.launcher2.weather.WeatherLocation import kotlinx.coroutines.launch @@ -31,6 +35,7 @@ import kotlinx.coroutines.launch @Composable fun WeatherScreen() { val viewModel: WeatherScreenVM = viewModel() + val context = LocalContext.current PreferenceScreen(title = stringResource(R.string.preference_screen_weather)) { item { @@ -62,6 +67,16 @@ fun WeatherScreen() { } item { PreferenceCategory(title = stringResource(R.string.preference_category_location)) { + val hasPermission by viewModel.hasLocationPermission.observeAsState() + AnimatedVisibility(hasPermission == false) { + MissingPermissionBanner( + text = stringResource(R.string.missing_permission_auto_location), + onClick = { + viewModel.requestLocationPermission(context as AppCompatActivity) + }, + modifier = Modifier.padding(16.dp) + ) + } val autoLocation by viewModel.autoLocation.observeAsState(false) SwitchPreference( title = stringResource(R.string.preference_automatic_location), @@ -181,7 +196,9 @@ fun LocationPreference( } TextButton( onClick = { showDialog = false }, - modifier = Modifier.align(Alignment.End).padding(24.dp) + modifier = Modifier + .align(Alignment.End) + .padding(24.dp) ) { Text( text = stringResource(R.string.close), diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreenVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreenVM.kt index c286fe6e..af52e0e6 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreenVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/weather/WeatherScreenVM.kt @@ -1,9 +1,12 @@ package de.mm20.launcher2.ui.settings.weather +import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope +import de.mm20.launcher2.permissions.PermissionGroup +import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.preferences.LauncherDataStore import de.mm20.launcher2.preferences.Settings.WeatherSettings import de.mm20.launcher2.weather.WeatherLocation @@ -19,6 +22,7 @@ import kotlin.coroutines.coroutineContext class WeatherScreenVM : ViewModel(), KoinComponent { private val repository: WeatherRepository by inject() private val dataStore: LauncherDataStore by inject() + private val permissionsManager: PermissionsManager by inject() val imperialUnits = dataStore.data.map { it.weather.imperialUnits }.asLiveData() fun setImperialUnits(imperialUnits: Boolean) { @@ -65,6 +69,12 @@ class WeatherScreenVM : ViewModel(), KoinComponent { } } + val hasLocationPermission = permissionsManager.hasPermission(PermissionGroup.Location).asLiveData() + + fun requestLocationPermission(activity: AppCompatActivity) { + permissionsManager.requestPermission(activity, PermissionGroup.Location) + } + val isSearchingLocation = MutableLiveData(false) val locationResults = MutableLiveData>(emptyList())