Add a few more providers and fix multiple bugs

This commit is contained in:
Tommaso Berlose 2020-10-11 21:59:44 +02:00
parent 1644fb7682
commit 6a912ee003
149 changed files with 923 additions and 404 deletions

Binary file not shown.

View File

@ -23,8 +23,8 @@ android {
applicationId "com.tommasoberlose.anotherwidget" applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 29 targetSdkVersion 29
versionCode 105 versionCode 106
versionName "2.0.13" versionName "2.0.14"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY']) buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])

View File

@ -0,0 +1,64 @@
package com.tommasoberlose.anotherwidget.components
import android.content.Context
import android.view.View
import androidx.core.view.isVisible
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.utils.openURI
import kotlinx.android.synthetic.main.weather_provider_settings_layout.view.*
class BottomSheetWeatherProviderSettings(context: Context, callback: () -> Unit) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
init {
val view = View.inflate(context, R.layout.weather_provider_settings_layout, null)
view.api_key_container.isVisible = WeatherHelper.isKeyRequired()
view.action_save_key.isVisible = WeatherHelper.isKeyRequired()
WeatherHelper.getProviderInfoTitle(context).let { title ->
view.info_title.text = title
view.info_title.isVisible = title != ""
}
WeatherHelper.getProviderInfoSubtitle(context).let { subtitle ->
view.info_subtitle.text = subtitle
view.info_subtitle.isVisible = subtitle != ""
}
view.info_provider.text = WeatherHelper.getProviderName(context)
view.api_key.editText?.setText(when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather
Constants.WeatherProvider.WEATHER_GOV,
Constants.WeatherProvider.YR,
null -> ""
})
view.action_open_provider.setOnClickListener {
context.openURI(WeatherHelper.getProviderLink())
}
view.action_save_key.setOnClickListener {
val key = view.api_key.editText?.text.toString()
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen = key
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit = key
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi = key
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere = key
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather = key
else -> {}
}
callback.invoke()
dismiss()
}
setContentView(view)
}
}

View File

@ -3,6 +3,7 @@ package com.tommasoberlose.anotherwidget.helpers
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.util.Log
import com.google.android.gms.location.LocationServices import com.google.android.gms.location.LocationServices
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
@ -12,6 +13,9 @@ import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.isDarkTheme import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
@ -21,7 +25,7 @@ import org.greenrobot.eventbus.EventBus
object WeatherHelper { object WeatherHelper {
fun updateWeather(context: Context) { suspend fun updateWeather(context: Context) {
val networkApi = WeatherNetworkApi(context) val networkApi = WeatherNetworkApi(context)
if (Preferences.customLocationAdd != "") { if (Preferences.customLocationAdd != "") {
networkApi.updateWeather() networkApi.updateWeather()
@ -32,10 +36,17 @@ object WeatherHelper {
if (location != null) { if (location != null) {
Preferences.customLocationLat = location.latitude.toString() Preferences.customLocationLat = location.latitude.toString()
Preferences.customLocationLon = location.longitude.toString() Preferences.customLocationLon = location.longitude.toString()
networkApi.updateWeather()
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
CoroutineScope(Dispatchers.IO).launch {
networkApi.updateWeather()
}
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} else {
CoroutineScope(Dispatchers.IO).launch {
networkApi.updateWeather()
}
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
} }
@ -48,7 +59,7 @@ object WeatherHelper {
MainWidget.updateWidget(context) MainWidget.updateWidget(context)
} }
fun getProviderName(context: Context, provider: Constants.WeatherProvider): String { fun getProviderName(context: Context, provider: Constants.WeatherProvider = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
return context.getString(when(provider) { return context.getString(when(provider) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.settings_weather_provider_open_weather Constants.WeatherProvider.OPEN_WEATHER -> R.string.settings_weather_provider_open_weather
Constants.WeatherProvider.WEATHER_BIT -> R.string.settings_weather_provider_weatherbit Constants.WeatherProvider.WEATHER_BIT -> R.string.settings_weather_provider_weatherbit
@ -60,21 +71,8 @@ object WeatherHelper {
}) })
} }
fun getProviderLinkName(context: Context): String { fun getProviderInfoTitle(context: Context, provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { return context.getString(when(provider) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.action_open_provider_open_weather
Constants.WeatherProvider.WEATHER_BIT -> R.string.action_open_provider_weatherbit
Constants.WeatherProvider.WEATHER_API -> R.string.action_open_provider_weatherapi
Constants.WeatherProvider.HERE -> R.string.action_open_provider_here
Constants.WeatherProvider.ACCUWEATHER -> R.string.action_open_provider_accuweather
Constants.WeatherProvider.WEATHER_GOV -> R.string.action_open_provider_weather_gov
Constants.WeatherProvider.YR -> R.string.action_open_provider_yr
else -> R.string.nothing
})
}
fun getProviderInfoTitle(context: Context): String {
return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_title Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_title
Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_title Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_title
Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_title Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_title
@ -86,8 +84,8 @@ object WeatherHelper {
}) })
} }
fun getProviderInfoSubtitle(context: Context): String { fun getProviderInfoSubtitle(context: Context, provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { return context.getString(when(provider) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_subtitle Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_subtitle
Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_subtitle Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_subtitle
Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_subtitle Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_subtitle
@ -99,20 +97,20 @@ object WeatherHelper {
}) })
} }
fun getProviderLink(): String { fun getProviderLink(provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
return when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { return when(provider) {
Constants.WeatherProvider.OPEN_WEATHER -> "https://home.openweathermap.org/users/sign_up" Constants.WeatherProvider.OPEN_WEATHER -> "https://home.openweathermap.org/users/sign_in"
Constants.WeatherProvider.WEATHER_BIT -> "https://www.weatherbit.io/account/create" Constants.WeatherProvider.WEATHER_BIT -> "https://www.weatherbit.io/account/login"
Constants.WeatherProvider.WEATHER_API -> "https://www.weatherapi.com/signup.aspx" Constants.WeatherProvider.WEATHER_API -> "https://www.weatherapi.com/login.aspx"
Constants.WeatherProvider.HERE -> "https://developer.here.com/sign-up?create=Freemium-Basic&keepState=true&step=account" Constants.WeatherProvider.HERE -> "https://developer.here.com/login"
Constants.WeatherProvider.ACCUWEATHER -> "https://developer.accuweather.com/user/register" Constants.WeatherProvider.ACCUWEATHER -> "https://developer.accuweather.com/user/login"
Constants.WeatherProvider.WEATHER_GOV -> "http://www.weather.gov/" Constants.WeatherProvider.WEATHER_GOV -> "http://www.weather.gov/"
Constants.WeatherProvider.YR -> "https://www.yr.no/" Constants.WeatherProvider.YR -> "https://www.yr.no/"
else -> "" else -> ""
} }
} }
fun isKeyRequired(): Boolean = when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { fun isKeyRequired(provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): Boolean = when (provider) {
Constants.WeatherProvider.OPEN_WEATHER, Constants.WeatherProvider.OPEN_WEATHER,
Constants.WeatherProvider.WEATHER_BIT, Constants.WeatherProvider.WEATHER_BIT,
Constants.WeatherProvider.WEATHER_API, Constants.WeatherProvider.WEATHER_API,
@ -124,6 +122,17 @@ object WeatherHelper {
else -> true else -> true
} }
fun getApiKey(provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String = when (provider) {
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather
Constants.WeatherProvider.WEATHER_GOV -> ""
Constants.WeatherProvider.YR -> ""
else -> ""
}
fun getWeatherIconResource(context: Context, icon: String, style: Int = Preferences.weatherIconPack): Int { fun getWeatherIconResource(context: Context, icon: String, style: Int = Preferences.weatherIconPack): Int {
return when (icon) { return when (icon) {
"01d" -> { "01d" -> {
@ -451,4 +460,50 @@ object WeatherHelper {
1282 -> "13" 1282 -> "13"
else -> "" else -> ""
} + if (isDaytime) "d" else "n" } + if (isDaytime) "d" else "n"
fun getYRIcon(iconCode: String, isDaytime: Boolean): String = when {
iconCode.contains("clearsky") -> "01"
iconCode.contains("cloudy") -> "04"
iconCode.contains("fair") -> "02"
iconCode.contains("fog") -> "82"
iconCode.contains("heavyrain") -> "10"
iconCode.contains("heavyrainandthunder") -> "11"
iconCode.contains("heavyrainshowers") -> "10"
iconCode.contains("heavyrainshowersandthunder") -> "11"
iconCode.contains("heavysleet") -> "10"
iconCode.contains("heavysleetandthunder") -> "11"
iconCode.contains("heavysleetshowers") -> "10"
iconCode.contains("heavysleetshowersandthunder") -> "11"
iconCode.contains("heavysnow") -> "13"
iconCode.contains("heavysnowandthunder") -> "13"
iconCode.contains("heavysnowshowers") -> "13"
iconCode.contains("heavysnowshowersandthunder") -> "13"
iconCode.contains("lightrain") -> "10"
iconCode.contains("lightrainandthunder") -> "11"
iconCode.contains("lightrainshowers") -> "10"
iconCode.contains("lightrainshowersandthunder") -> "11"
iconCode.contains("lightsleet") -> "10"
iconCode.contains("lightsleetandthunder") -> "11"
iconCode.contains("lightsleetshowers") -> "10"
iconCode.contains("lightsnow") -> "13"
iconCode.contains("lightsnowandthunder") -> "13"
iconCode.contains("lightsnowshowers") -> "13"
iconCode.contains("lightssleetshowersandthunder") -> "81"
iconCode.contains("lightssnowshowersandthunder") -> "81"
iconCode.contains("partlycloudy") -> "03"
iconCode.contains("rain") -> "10"
iconCode.contains("rainandthunder") -> "11"
iconCode.contains("rainshowers") -> "10"
iconCode.contains("rainshowersandthunder") -> "11"
iconCode.contains("sleet") -> "10"
iconCode.contains("sleetandthunder") -> "11"
iconCode.contains("sleetshowers") -> "10"
iconCode.contains("sleetshowersandthunder") -> "11"
iconCode.contains("snow") -> "13"
iconCode.contains("snowandthunder") -> "13"
iconCode.contains("snowshowers") -> "13"
iconCode.contains("snowshowersandthunder") -> "13"
else -> ""
} + if (isDaytime) "d" else "n"
} }

View File

@ -21,10 +21,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import java.lang.Exception import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
class WeatherNetworkApi(val context: Context) { class WeatherNetworkApi(val context: Context) {
fun updateWeather() { suspend fun updateWeather() {
Preferences.weatherProviderError = "" Preferences.weatherProviderError = "-"
Preferences.weatherProviderLocationError = "" Preferences.weatherProviderLocationError = ""
if (Preferences.showWeather && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") { if (Preferences.showWeather && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
@ -41,11 +43,13 @@ class WeatherNetworkApi(val context: Context) {
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
context context
) )
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
private fun useOpenWeatherMap(context: Context) { private fun useOpenWeatherMap(context: Context) {
if (Preferences.weatherProviderApiOpen != "" ) { if (Preferences.weatherProviderApiOpen != "") {
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApiOpen) val helper = OpenWeatherMapHelper(Preferences.weatherProviderApiOpen)
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC) helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object : helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
@ -56,14 +60,18 @@ class WeatherNetworkApi(val context: Context) {
Preferences.weatherIcon = currentWeather.weather[0].icon Preferences.weatherIcon = currentWeather.weather[0].icon
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(context) MainWidget.updateWidget(context)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
override fun onFailure(throwable: Throwable?) { override fun onFailure(throwable: Throwable?) {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
}) })
} else { } else {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key) Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
@ -72,95 +80,137 @@ class WeatherNetworkApi(val context: Context) {
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
context context
) )
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
private fun useWeatherGov(context: Context) { private suspend fun useWeatherGov(context: Context) {
CoroutineScope(Dispatchers.IO).launch { val repository = WeatherGovRepository()
val repository = WeatherGovRepository() val pointsResponse = executeWithRetry(times = 5) {
val pointsResponse = executeWithRetry(times = 5) { repository.getGridPoints(
repository.getGridPoints( Preferences.customLocationLat,
Preferences.customLocationLat, Preferences.customLocationLon
Preferences.customLocationLon )
) }
}
when (pointsResponse) { when (pointsResponse) {
is NetworkResponse.Success -> { is NetworkResponse.Success -> {
try { try {
val pp = pointsResponse.body["properties"] as LinkedTreeMap<*, *> val pp = pointsResponse.body["properties"] as LinkedTreeMap<*, *>
val gridId = pp["gridId"] as String val gridId = pp["gridId"] as String
val gridX = pp["gridX"] as Double val gridX = pp["gridX"] as Double
val gridY = pp["gridY"] as Double val gridY = pp["gridY"] as Double
when (val weatherResponse = repository.getWeather( when (val weatherResponse = repository.getWeather(
gridId, gridId,
gridX, gridX,
gridY, gridY,
if (Preferences.weatherTempUnit == "F") "us" else "si" if (Preferences.weatherTempUnit == "F") "us" else "si"
)) { )) {
is NetworkResponse.Success -> { is NetworkResponse.Success -> {
try { try {
val props = val props =
weatherResponse.body["properties"] as LinkedTreeMap<*, *> weatherResponse.body["properties"] as LinkedTreeMap<*, *>
val periods = props["periods"] as List<*> val periods = props["periods"] as List<*>
val now = periods[0] as LinkedTreeMap<*, *> val now = periods[0] as LinkedTreeMap<*, *>
val temp = now["temperature"] as Double val temp = now["temperature"] as Double
val fullIcon = now["icon"] as String val fullIcon = now["icon"] as String
val isDaytime = now["isDaytime"] as Boolean val isDaytime = now["isDaytime"] as Boolean
Preferences.weatherTemp = temp.toFloat() Preferences.weatherTemp = temp.toFloat()
Preferences.weatherIcon = WeatherHelper.getWeatherGovIcon(fullIcon, isDaytime) Preferences.weatherIcon = WeatherHelper.getWeatherGovIcon(fullIcon, isDaytime)
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(context) Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) MainWidget.updateWidget(context)
} catch (ex: Exception) { } catch (ex: Exception) {
} Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
} finally {
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
} catch(ex: Exception) { else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
Preferences.weatherProviderLocationError = ""
}
} }
} } catch(ex: Exception) {
is NetworkResponse.ServerError -> { Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
if (pointsResponse.body?.containsKey("status") == true && (pointsResponse.body?.get("status") as Double).toInt() == 404) { Preferences.weatherProviderLocationError = ""
Preferences.weatherProviderError = "" } finally {
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_wrong_location) EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
WeatherHelper.removeWeather(
context
)
} }
} }
is NetworkResponse.ServerError -> {
if (pointsResponse.body?.containsKey("status") == true && (pointsResponse.body?.get("status") as Double).toInt() == 404) {
Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_wrong_location)
} else {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
}
WeatherHelper.removeWeather(
context
)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
} }
} }
private fun useHereProvider(context: Context) { private suspend fun useHereProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch { if (Preferences.weatherProviderApiHere != "") {
val repository = HereRepository() val repository = HereRepository()
when (val response = repository.getWeather()) { when (val response = repository.getWeather()) {
is NetworkResponse.Success -> { is NetworkResponse.Success -> {
try { try {
Log.d("ciao - here", response.body.toString()) Log.d("ciao - here", response.body.toString())
Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = ""
} catch(ex: Exception) { } catch(ex: Exception) {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
} finally {
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
is NetworkResponse.ServerError -> { is NetworkResponse.ServerError -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
context context
) )
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
} else {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
Preferences.weatherProviderLocationError = ""
WeatherHelper.removeWeather(
context
)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
private fun useWeatherBitProvider(context: Context) { private suspend fun useWeatherBitProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch { if (Preferences.weatherProviderApiWeatherBit != "") {
val repository = WeatherbitRepository() val repository = WeatherbitRepository()
when (val response = repository.getWeather()) { when (val response = repository.getWeather()) {
@ -177,27 +227,53 @@ class WeatherNetworkApi(val context: Context) {
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(context) MainWidget.updateWidget(context)
Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} catch(ex: Exception) { } catch(ex: Exception) {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
} finally {
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
is NetworkResponse.ServerError -> { is NetworkResponse.ServerError -> {
when (response.code) { when (response.code) {
403 -> { 403 -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key) Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
Preferences.weatherProviderLocationError = ""
}
else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
} }
} }
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
context context
) )
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
} else {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
Preferences.weatherProviderLocationError = ""
WeatherHelper.removeWeather(
context
)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
private fun useWeatherApiProvider(context: Context) { private suspend fun useWeatherApiProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch { if (Preferences.weatherProviderApiWeatherApi != "") {
val repository = WeatherApiRepository() val repository = WeatherApiRepository()
when (val response = repository.getWeather()) { when (val response = repository.getWeather()) {
@ -216,68 +292,150 @@ class WeatherNetworkApi(val context: Context) {
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(context) MainWidget.updateWidget(context)
Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} catch(ex: Exception) { } catch(ex: Exception) {
Log.d("ciao", ex.localizedMessage) Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
} finally {
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
is NetworkResponse.ServerError -> { is NetworkResponse.ServerError -> {
when (response.code) { when (response.code) {
401 -> { 401 -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key) Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
Preferences.weatherProviderLocationError = ""
} }
403 -> { 403 -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_expired_key) Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_expired_key)
Preferences.weatherProviderLocationError = ""
}
else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
} }
} }
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
context context
) )
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
} else {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
Preferences.weatherProviderLocationError = ""
WeatherHelper.removeWeather(
context
)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
private fun useAccuweatherProvider(context: Context) { private suspend fun useAccuweatherProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch { if (Preferences.weatherProviderApiAccuweather != "") {
val repository = AccuweatherRepository() val repository = AccuweatherRepository()
// when (val response = repository.getWeather()) { // when (val response = repository.getWeather()) {
// is NetworkResponse.Success -> { // is NetworkResponse.Success -> {
// try { // try {
// Log.d("ciao", response.body.toString()) // Log.d("ciao", response.body.toString())
// } catch(ex: Exception) { // } catch(ex: Exception) {
// //
// } // Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
// } // Preferences.weatherProviderLocationError = ""
// is NetworkResponse.ServerError -> { // }
// WeatherHelper.removeWeather( // }
// context // is NetworkResponse.ServerError -> {
// ) // WeatherHelper.removeWeather(
// } // context
// } // )
// }
// Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
// Preferences.weatherProviderLocationError = ""
// EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
// }
} else {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
Preferences.weatherProviderLocationError = ""
WeatherHelper.removeWeather(
context
)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
private fun useYrProvider(context: Context) { private suspend fun useYrProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch { val repository = YrRepository()
val repository = YrRepository()
when (val response = repository.getWeather()) { when (val response = repository.getWeather()) {
is NetworkResponse.Success -> { is NetworkResponse.Success -> {
try { try {
Log.d("ciao - yr", response.body.toString()) val pp = response.body["properties"] as LinkedTreeMap<*, *>
} catch(ex: Exception) { val data = pp["timeseries"] as List<LinkedTreeMap<String, Any>>?
data?.let {
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
for (item in data) {
val time = Calendar.getInstance().apply { time = format.parse(item["time"] as String)!! }
val now = Calendar.getInstance()
if (time.timeInMillis >= now.timeInMillis) {
val dd = item["data"] as LinkedTreeMap<*, *>
val instant = dd["instant"] as LinkedTreeMap<*, *>
val next = dd["next_1_hours"] as LinkedTreeMap<*, *>
val details = instant["details"] as LinkedTreeMap<*, *>
val temp = details["air_temperature"] as Double
val summary = next["summary"] as LinkedTreeMap<*, *>
val iconCode = summary["symbol_code"] as String
Preferences.weatherTemp = temp.toFloat()
Preferences.weatherIcon = WeatherHelper.getYRIcon(iconCode, now.get(Calendar.HOUR_OF_DAY) >= 22 || now.get(Calendar.HOUR_OF_DAY) <= 8)
Preferences.weatherTempUnit = "C"
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(context)
Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = ""
break
}
}
} }
} catch(ex: Exception) {
ex.printStackTrace()
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
Preferences.weatherProviderLocationError = ""
} finally {
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
is NetworkResponse.ServerError -> { }
WeatherHelper.removeWeather( is NetworkResponse.ServerError -> {
context Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
) Preferences.weatherProviderLocationError = ""
} WeatherHelper.removeWeather(
context
)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
else -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
Preferences.weatherProviderLocationError = ""
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
} }

View File

@ -8,6 +8,9 @@ import android.content.Intent
import com.tommasoberlose.anotherwidget.global.Actions import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.* import java.util.*
@ -22,7 +25,9 @@ class WeatherReceiver : BroadcastReceiver() {
Intent.ACTION_TIME_CHANGED -> setUpdates(context) Intent.ACTION_TIME_CHANGED -> setUpdates(context)
Actions.ACTION_WEATHER_UPDATE -> { Actions.ACTION_WEATHER_UPDATE -> {
WeatherHelper.updateWeather(context) GlobalScope.launch(Dispatchers.IO) {
WeatherHelper.updateWeather(context)
}
} }
} }
} }

View File

@ -4,8 +4,10 @@ import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.pm.ResolveInfo import android.content.pm.ResolveInfo
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -15,37 +17,44 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.material.snackbar.Snackbar
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
import com.tommasoberlose.anotherwidget.components.BottomSheetWeatherProviderSettings
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
import com.tommasoberlose.anotherwidget.databinding.ActivityWeatherProviderBinding import com.tommasoberlose.anotherwidget.databinding.ActivityWeatherProviderBinding
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.ui.viewmodels.WeatherProviderViewModel
import com.tommasoberlose.anotherwidget.utils.collapse
import com.tommasoberlose.anotherwidget.utils.expand
import com.tommasoberlose.anotherwidget.utils.openURI import com.tommasoberlose.anotherwidget.utils.openURI
import kotlinx.android.synthetic.main.activity_choose_application.* import com.tommasoberlose.anotherwidget.utils.reveal
import kotlinx.android.synthetic.main.activity_weather_provider.* import kotlinx.android.synthetic.main.activity_weather_provider.*
import kotlinx.android.synthetic.main.activity_weather_provider.action_back
import kotlinx.android.synthetic.main.activity_weather_provider.list_view
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import net.idik.lib.slimadapter.SlimAdapter import net.idik.lib.slimadapter.SlimAdapter
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class WeatherProviderActivity : AppCompatActivity() { class WeatherProviderActivity : AppCompatActivity() {
private lateinit var adapter: SlimAdapter private lateinit var adapter: SlimAdapter
private lateinit var viewModel: MainViewModel private lateinit var viewModel: WeatherProviderViewModel
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_weather_provider) setContentView(R.layout.activity_weather_provider)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java) viewModel = ViewModelProvider(this).get(WeatherProviderViewModel::class.java)
api_key.editText?.setText(Preferences.weatherProviderApiOpen)
list_view.setHasFixedSize(true) list_view.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(this) val mLayoutManager = LinearLayoutManager(this)
@ -53,91 +62,119 @@ class WeatherProviderActivity : AppCompatActivity() {
adapter = SlimAdapter.create() adapter = SlimAdapter.create()
adapter adapter
.register<Int>(R.layout.list_item) { item, injector -> .register<Constants.WeatherProvider>(R.layout.weather_provider_list_item) { provider, injector ->
val provider = Constants.WeatherProvider.fromInt(item)!!
injector injector
.text(R.id.text, WeatherHelper.getProviderName(this, provider)) .text(R.id.text, WeatherHelper.getProviderName(this, provider))
.clicked(R.id.text) { .clicked(R.id.item) {
Preferences.weatherProvider = item val oldValue = Preferences.weatherProvider
Preferences.weatherProvider = provider.value
updateListItem(oldValue)
updateListItem()
loader.isVisible = true
lifecycleScope.launch {
WeatherHelper.updateWeather(this@WeatherProviderActivity)
}
} }
} .clicked(R.id.radioButton) {
.attachTo(list_view) val oldValue = Preferences.weatherProvider
Preferences.weatherProvider = provider.value
updateListItem(oldValue)
updateListItem()
loader.isVisible = true
lifecycleScope.launch {
WeatherHelper.updateWeather(this@WeatherProviderActivity)
}
}
.checked(R.id.radioButton, provider.value == Preferences.weatherProvider)
.with<TextView>(R.id.text2) {
if (WeatherHelper.isKeyRequired(provider)) {
it.text = getString(R.string.api_key_required_message)
}
if (provider == Constants.WeatherProvider.WEATHER_GOV) {
it.text = getString(R.string.us_only_message)
}
}
.clicked(R.id.action_configure) {
BottomSheetWeatherProviderSettings(this) {
lifecycleScope.launch {
loader.isVisible = true
WeatherHelper.updateWeather(this@WeatherProviderActivity)
}
}.show()
}
.visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.value == Preferences.weatherProvider) View.VISIBLE else View.GONE)
.visibility(R.id.info_container, if (WeatherHelper.isKeyRequired(provider) || provider == Constants.WeatherProvider.WEATHER_GOV) View.VISIBLE else View.GONE)
.with<TextView>(R.id.provider_error) {
if (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") {
it.text = Preferences.weatherProviderError
it.isVisible = provider.value == Preferences.weatherProvider
} else if (Preferences.weatherProviderLocationError != "") {
it.text = Preferences.weatherProviderLocationError
it.isVisible = provider.value == Preferences.weatherProvider
} else {
it.isVisible = false
}
}
.image(R.id.action_configure, ContextCompat.getDrawable(this, if (WeatherHelper.isKeyRequired(provider)) R.drawable.round_settings else R.drawable.outline_info_white))
}.attachTo(list_view)
adapter.updateData(
Constants.WeatherProvider.values().asList()
.filter { it != Constants.WeatherProvider.HERE }
.filter { it != Constants.WeatherProvider.ACCUWEATHER }
)
setupListener() setupListener()
subscribeUi(viewModel) subscribeUi(viewModel)
} }
private fun subscribeUi(viewModel: MainViewModel) { private fun subscribeUi(viewModel: WeatherProviderViewModel) {
adapter.updateData(Constants.WeatherProvider.values().map { it.value }) viewModel.weatherProviderError.observe(this) {
updateListItem()
}
// viewModel.weatherProvider.observe(this, Observer { viewModel.weatherProviderLocationError.observe(this) {
// weather_provider.editText?.setText(WeatherHelper.getProviderName(this, Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!).split("\n").first()) updateListItem()
// }
// api_key_container.isVisible = WeatherHelper.isKeyRequired() }
//
// WeatherHelper.getProviderInfoTitle(this).let { private fun updateListItem(provider: Int = Preferences.weatherProvider) {
// info_title.text = it (adapter.data).forEachIndexed { index, item ->
// info_title.isVisible = it != "" if (item is Constants.WeatherProvider && item.value == provider) {
// } adapter.notifyItemChanged(index)
// }
// WeatherHelper.getProviderInfoSubtitle(this).let { }
// info_subtitle.text = it
// info_subtitle.isVisible = it != ""
// }
//
// action_open_provider.text = WeatherHelper.getProviderLinkName(this)
//
// api_key.editText?.setText(when (Constants.WeatherProvider.fromInt(it)) {
// Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen
// Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit
// Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi
// Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere
// Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather
// Constants.WeatherProvider.WEATHER_GOV,
// Constants.WeatherProvider.YR,
// null -> ""
// })
// })
} }
private fun setupListener() { private fun setupListener() {
action_back.setOnClickListener { action_back.setOnClickListener {
onBackPressed() onBackPressed()
} }
action_open_provider.setOnClickListener {
openURI(WeatherHelper.getProviderLink())
}
weather_provider_inner.setOnClickListener {
if (Preferences.showWeather) {
val dialog = BottomSheetMenu<Int>(this, header = getString(R.string.settings_weather_provider_api)).setSelectedValue(Preferences.weatherProvider)
(0 until 7).forEach {
val item = Constants.WeatherProvider.fromInt(it)
dialog.addItem(WeatherHelper.getProviderName(this, item!!), it)
}
dialog.addOnSelectItemListener { value ->
Preferences.weatherProvider = value
}.show()
}
}
api_key.editText?.addTextChangedListener {
val key = it?.toString() ?: ""
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen = key
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit = key
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi = key
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere = key
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather = key
else -> {}
}
}
} }
override fun onBackPressed() { override fun onBackPressed() {
setResult(Activity.RESULT_OK) setResult(Activity.RESULT_OK)
finish() finish()
} }
override fun onResume() {
super.onResume()
EventBus.getDefault().register(this)
}
override fun onPause() {
EventBus.getDefault().unregister(this)
super.onPause()
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(ignore: MainFragment.UpdateUiMessageEvent?) {
loader.isVisible = Preferences.weatherProviderError == "-"
if (Preferences.weatherProviderError == "" && Preferences.weatherProviderLocationError == "") {
Snackbar.make(list_view, getString(R.string.settings_weather_provider_api_key_subtitle_all_set), Snackbar.LENGTH_LONG).show()
}
}
} }

View File

@ -39,10 +39,7 @@ import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.*
import com.tommasoberlose.anotherwidget.utils.getCurrentWallpaper
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.toPixel
import kotlinx.android.synthetic.main.fragment_app_main.* import kotlinx.android.synthetic.main.fragment_app_main.*
import kotlinx.android.synthetic.main.the_widget_sans.* import kotlinx.android.synthetic.main.the_widget_sans.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -76,6 +73,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
subscribeUi(viewModel) subscribeUi(viewModel)
// Viewpager // Viewpager
@ -352,11 +350,11 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText) backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
badgeGravity = BadgeDrawable.TOP_END badgeGravity = BadgeDrawable.TOP_END
}?.isVisible = if (Preferences.showWeather) { }?.isVisible = if (Preferences.showWeather) {
(WeatherHelper.isKeyRequired() && Preferences.weatherProviderApiOpen == "") (WeatherHelper.isKeyRequired() && WeatherHelper.getApiKey() == "")
|| (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission( || (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
) != true) ) != true)
|| (Preferences.weatherProviderError != "") || (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-")
} else { } else {
false false
} }

View File

@ -193,7 +193,9 @@ class SettingsFragment : Fragment() {
} }
action_refresh_widget.setOnClickListener { action_refresh_widget.setOnClickListener {
WeatherHelper.updateWeather(requireContext()) viewLifecycleOwner.lifecycleScope.launch {
WeatherHelper.updateWeather(requireContext())
}
CalendarHelper.updateEventList(requireContext()) CalendarHelper.updateEventList(requireContext())
MediaPlayerHelper.updatePlayingMediaInfo(requireContext()) MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
} }

View File

@ -188,7 +188,7 @@ class WeatherTabFragment : Fragment() {
} }
private fun checkWeatherProviderConfig() { private fun checkWeatherProviderConfig() {
weather_provider_error.isVisible = Preferences.weatherProviderError != "" weather_provider_error.isVisible = Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-"
weather_provider_error?.text = Preferences.weatherProviderError weather_provider_error?.text = Preferences.weatherProviderError
weather_provider_location_error.isVisible = Preferences.weatherProviderLocationError != "" weather_provider_location_error.isVisible = Preferences.weatherProviderLocationError != ""
@ -233,7 +233,9 @@ class WeatherTabFragment : Fragment() {
.addItem(getString(R.string.celsius), "C") .addItem(getString(R.string.celsius), "C")
.addOnSelectItemListener { value -> .addOnSelectItemListener { value ->
if (value != Preferences.weatherTempUnit) { if (value != Preferences.weatherTempUnit) {
WeatherHelper.updateWeather(requireContext()) viewLifecycleOwner.lifecycleScope.launch {
WeatherHelper.updateWeather(requireContext())
}
} }
Preferences.weatherTempUnit = value Preferences.weatherTempUnit = value
}.show() }.show()

View File

@ -0,0 +1,19 @@
package com.tommasoberlose.anotherwidget.ui.viewmodels
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.chibatching.kotpref.livedata.asLiveData
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
class WeatherProviderViewModel(application: Application) : AndroidViewModel(application) {
val weatherProvider = Preferences.asLiveData(Preferences::weatherProvider)
val weatherProviderError = Preferences.asLiveData(Preferences::weatherProviderError)
val weatherProviderLocationError = Preferences.asLiveData(Preferences::weatherProviderLocationError)
}

View File

@ -32,10 +32,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.* import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.receivers.* import com.tommasoberlose.anotherwidget.receivers.*
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.*
import com.tommasoberlose.anotherwidget.utils.getCapWordString
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.toPixel
import kotlinx.android.synthetic.main.the_widget.view.* import kotlinx.android.synthetic.main.the_widget.view.*
import java.lang.Exception import java.lang.Exception
import java.text.DateFormat import java.text.DateFormat
@ -661,14 +658,11 @@ class MainWidget : AppWidgetProvider() {
if (Preferences.isCharging) { if (Preferences.isCharging) {
v.second_row_icon.isVisible = false v.second_row_icon.isVisible = false
val batteryLevel = BatteryHelper.getBatteryLevel(context) val batteryLevel = BatteryHelper.getBatteryLevel(context)
if (batteryLevel == 100) { if (batteryLevel != 100) {
v.next_event_date.text = "%s - %d%%".format( v.next_event_date.text = context.getString(R.string.charging)
context.getString(R.string.charging),
batteryLevel
)
} else { } else {
v.next_event_date.text = v.next_event_date.text =
context.getString(R.string.charging) context.getString(R.string.charged)
} }
showSomething = true showSomething = true
break@loop break@loop

View File

@ -95,7 +95,7 @@ fun View.expand() {
} }
} }
fun View.collapse() { fun View.collapse(duration: Long = 500L) {
if (visibility != View.GONE) { if (visibility != View.GONE) {
val initialHeight = measuredHeight val initialHeight = measuredHeight
@ -114,7 +114,7 @@ fun View.collapse() {
} }
} }
a.duration = 500L //(initialHeight / v.context.resources.displayMetrics.density).toLong() a.duration = duration //(initialHeight / v.context.resources.displayMetrics.density).toLong()
startAnimation(a) startAnimation(a)
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

Some files were not shown because too many files have changed in this diff Show More