Add weather plugin language parameter

This commit is contained in:
MM20 2023-12-17 19:30:59 +01:00
parent d98fc29fba
commit 1c542f38ba
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
4 changed files with 37 additions and 13 deletions

View File

@ -1,6 +1,10 @@
package de.mm20.launcher2.plugin.config package de.mm20.launcher2.plugin.config
data class WeatherPluginConfig( data class WeatherPluginConfig(
val supportsAutoLocation: Boolean, /**
val supportsCustomLocation: Boolean, * Minimum time (in ms) that needs to pass before the provider can be queried again.
* Note that updates can be triggered sooner if the user manually changes their location
* or weather provider.
*/
val minUpdateInterval: Long = 60 * 60 * 1000L,
) )

View File

@ -11,6 +11,7 @@ object WeatherPluginContract {
const val Lon = "lon" const val Lon = "lon"
const val Id = "id" const val Id = "id"
const val LocationName = "location_name" const val LocationName = "location_name"
const val Language = "lang"
} }
object ForecastColumns { object ForecastColumns {
@ -36,6 +37,7 @@ object WeatherPluginContract {
object LocationParams { object LocationParams {
const val Query = "query" const val Query = "query"
const val Language = "lang"
} }
object LocationColumns { object LocationColumns {

View File

@ -75,7 +75,7 @@ val Double.inch
enum class WeatherIcon { enum class WeatherIcon {
None, Unknown,
Clear, Clear,
Cloudy, Cloudy,
Cold, Cold,

View File

@ -17,6 +17,7 @@ import de.mm20.launcher2.sdk.utils.launchWithCancellationSignal
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.io.IOException import java.io.IOException
import java.util.Locale
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -59,9 +60,11 @@ abstract class WeatherProvider(
?.toDoubleOrNull() ?.toDoubleOrNull()
val id = uri.getQueryParameter(WeatherPluginContract.ForecastParams.Id) val id = uri.getQueryParameter(WeatherPluginContract.ForecastParams.Id)
val name = uri.getQueryParameter(WeatherPluginContract.ForecastParams.LocationName) val name = uri.getQueryParameter(WeatherPluginContract.ForecastParams.LocationName)
val lang = uri.getQueryParameter(WeatherPluginContract.ForecastParams.Language)
?: Locale.getDefault().language
val forecasts = launchWithCancellationSignal(cancellationSignal) { val forecasts = launchWithCancellationSignal(cancellationSignal) {
getWeatherData(lat, lon, id, name) getWeatherData(lat, lon, id, name, lang)
} ?: return null } ?: return null
return createForecastCursor(forecasts) return createForecastCursor(forecasts)
} }
@ -69,10 +72,13 @@ abstract class WeatherProvider(
uri.pathSegments.size == 1 && uri.pathSegments.first() == WeatherPluginContract.Paths.Locations -> { uri.pathSegments.size == 1 && uri.pathSegments.first() == WeatherPluginContract.Paths.Locations -> {
val query = val query =
uri.getQueryParameter(WeatherPluginContract.LocationParams.Query) ?: return null uri.getQueryParameter(WeatherPluginContract.LocationParams.Query) ?: return null
val lang = uri.getQueryParameter(WeatherPluginContract.LocationParams.Language)
?: Locale.getDefault().language
val locations = launchWithCancellationSignal( val locations = launchWithCancellationSignal(
cancellationSignal cancellationSignal
) { ) {
findLocations(query) findLocations(query, lang)
} }
return createLocationsCursor(locations) return createLocationsCursor(locations)
} }
@ -84,16 +90,17 @@ abstract class WeatherProvider(
lat: Double?, lat: Double?,
lon: Double?, lon: Double?,
id: String?, id: String?,
locationName: String? locationName: String?,
lang: String,
): List<Forecast>? { ): List<Forecast>? {
if (lat != null && lon != null && locationName == null) { if (lat != null && lon != null && locationName == null) {
return getWeatherData(lat, lon) return getWeatherData(lat, lon, lang)
} }
if (id != null && locationName != null) { if (id != null && locationName != null) {
return getWeatherData(WeatherLocation.Id(id, locationName)) return getWeatherData(WeatherLocation.Id(id, locationName), lang)
} }
if (locationName != null && lat != null && lon != null) { if (locationName != null && lat != null && lon != null) {
return getWeatherData(WeatherLocation.LatLon(locationName, lat, lon)) return getWeatherData(WeatherLocation.LatLon(locationName, lat, lon), lang)
} }
return null return null
} }
@ -208,8 +215,11 @@ abstract class WeatherProvider(
* Find locations based on a query string. * Find locations based on a query string.
* The default implementation uses the Android Geocoder and returns a list of lat lon locations. * The default implementation uses the Android Geocoder and returns a list of lat lon locations.
* It also supports lat/lon coordinates in the format "[lat] [lon] [name]" or "[lat] [lon]". * It also supports lat/lon coordinates in the format "[lat] [lon] [name]" or "[lat] [lon]".
* @param query the query string
* @param lang the ISO 639 language code of the language that the user has set for the launcher.
* Should be used for location names if supported by the provider.
*/ */
open suspend fun findLocations(query: String): List<WeatherLocation> { open suspend fun findLocations(query: String, lang: String): List<WeatherLocation> {
val context = context ?: return emptyList() val context = context ?: return emptyList()
val parts = query.split(" ", limit = 3) val parts = query.split(" ", limit = 3)
val lat = parts.getOrNull(0)?.toDoubleOrNull() val lat = parts.getOrNull(0)?.toDoubleOrNull()
@ -281,16 +291,24 @@ abstract class WeatherProvider(
/** /**
* Get weather data for the current location. This is called when the user has set * Get weather data for the current location. This is called when the user has set
* the location to "Current location". * the location to "Current location".
* @param lat the latitude of the current location
* @param lon the longitude of the current location
* @param lang the ISO 639 language code of the language that the user has set for the launcher.
* Should be used for weather conditions and location names if supported by the provider.
*/ */
abstract suspend fun getWeatherData(lat: Double, lon: Double): List<Forecast>? abstract suspend fun getWeatherData(lat: Double, lon: Double, lang: String?): List<Forecast>?
/** /**
* Get weather data for a set location. This is called when the user has set * Get weather data for a set location. This is called when the user has set
* the location to a custom location. * the location to a custom location.
* @param location the location that the user has set. This is guaranteed * @param location the location that the user has set. This is guaranteed
* to be one of the locations returned by [findLocations]. * to be one of the locations returned by [findLocations].
* @param lang the ISO 639 language code of the language that the user has set for the launcher.
* Should be used for weather conditions if supported by the provider.
* @return the weather data for the given location * @return the weather data for the given location
* Note that returned forecasts should use the same location name as the location parameter. * Note that returned forecasts should use the name that is set in the [location] parameter as
* the location name, in order to avoid confusion when the user has set the location to a
* custom location.
*/ */
abstract suspend fun getWeatherData(location: WeatherLocation): List<Forecast>? abstract suspend fun getWeatherData(location: WeatherLocation, lang: String?): List<Forecast>?
} }