From e3997334f690fb7a6a2adcb9cb0a2f55ccb2eea1 Mon Sep 17 00:00:00 2001 From: Alex Yermolenko Date: Fri, 5 Jul 2024 15:02:24 +0200 Subject: [PATCH 1/3] feat: refactor ZeWeatherService to use DI --- .../de/berlindroid/zeapp/zedi/ApiModule.kt | 16 +++- .../zeapp/zeservices/ZeWeatherApi.kt | 26 ++++++ .../zeapp/zeservices/ZeWeatherService.kt | 88 ++++++------------- .../zeapp/zeui/ZeWeatherEditorDialog.kt | 5 +- .../zeapp/zeui/zehome/SelectedEditor.kt | 1 + .../berlindroid/zeapp/zeui/zehome/ZeScreen.kt | 5 +- .../zeapp/zevm/ZeBadgeViewModel.kt | 4 + 7 files changed, 76 insertions(+), 69 deletions(-) create mode 100644 zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherApi.kt diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zedi/ApiModule.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zedi/ApiModule.kt index 6e685f1c..1d09440a 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zedi/ApiModule.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zedi/ApiModule.kt @@ -1,6 +1,5 @@ package de.berlindroid.zeapp.zedi -import android.util.Log import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -9,20 +8,19 @@ import de.berlindroid.zeapp.zeservices.ZePassApi import de.berlindroid.zeapp.zeservices.ZePassService import de.berlindroid.zeapp.zeservices.ZeUserApi import de.berlindroid.zeapp.zeservices.ZeUserService +import de.berlindroid.zeapp.zeservices.ZeWeatherApi import kotlinx.serialization.json.Json import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient -import okhttp3.Response -import retrofit2.HttpException import retrofit2.Retrofit import retrofit2.converter.kotlinx.serialization.asConverterFactory -import timber.log.Timber data class ZeServerBaseUrl( val value: String, ) private val BASE_URL = ZeServerBaseUrl("https://zebadge.app/api/") +private val METEO_URL = ZeServerBaseUrl("https://api.open-meteo.com") @InstallIn(ViewModelComponent::class) @Module @@ -79,4 +77,14 @@ object ApiModule { ZeUserService:: class.java, ) + + @Provides + fun provideZeWeatherApi( + json: Json, + ): ZeWeatherApi = + Retrofit.Builder() + .baseUrl(METEO_URL.value) + .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) + .build() + .create(ZeWeatherApi::class.java) } diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherApi.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherApi.kt new file mode 100644 index 00000000..1a6fd642 --- /dev/null +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherApi.kt @@ -0,0 +1,26 @@ +package de.berlindroid.zeapp.zeservices + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import retrofit2.http.GET + +interface ZeWeatherApi { + + @Serializable + data class Weather( + @SerialName(value = "hourly") + val hourly: Hourly, + ) + + @Serializable + data class Hourly( + @SerialName(value = "time") + val time: List, + + @SerialName(value = "temperature_2m") + val temperature: List, + ) + + @GET("v1/forecast?latitude=52.5244&longitude=13.4105&hourly=temperature_2m&forecast_days=16") + suspend fun getWeather(): Weather +} diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt index f7cf4096..7e73f77f 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt @@ -1,69 +1,39 @@ package de.berlindroid.zeapp.zeservices import de.berlindroid.zeapp.zemodels.WeatherData -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import okhttp3.MediaType.Companion.toMediaType -import retrofit2.Retrofit -import retrofit2.converter.kotlinx.serialization.asConverterFactory -import retrofit2.http.GET - -internal suspend fun fetchWeather(date: String): WeatherData { - try { - val weather = weatherApiService.getWeather() - - val tempIndex = weather.hourly.time.indexOfFirst { - it.contains("${date}T12:00") - } - if (tempIndex == -1) { +import javax.inject.Inject + + +/** + * Service to fetch the weather data from the API by the provided date + */ +class ZeWeatherService @Inject constructor(private val zeWeatherApi: ZeWeatherApi) { + + internal suspend fun fetchWeather(date: String): WeatherData { + try { + val weather = zeWeatherApi.getWeather() + + val tempIndex = weather.hourly.time.indexOfFirst { + it.contains("${date}T12:00") + } + if (tempIndex == -1) { + return WeatherData( + day = null, + temperature = -1.0, + ) + } + val temperature = weather.hourly.temperature[tempIndex] + val day = weather.hourly.time[tempIndex] + return WeatherData( + day = day, + temperature = temperature, + ) + } catch (e: Exception) { return WeatherData( day = null, - temperature = -1.0, + temperature = -42.0, ) } - val temperature = weather.hourly.temperature[tempIndex] - val day = weather.hourly.time[tempIndex] - return WeatherData( - day = day, - temperature = temperature, - ) - } catch (e: Exception) { - return WeatherData( - day = null, - temperature = -42.0, - ) } -} - -private val json = Json { - ignoreUnknownKeys = true -} - -private val retrofit = Retrofit.Builder() - .baseUrl("https://api.open-meteo.com") - .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) - .build() - -private val weatherApiService = retrofit.create(WeatherApi::class.java) - -private interface WeatherApi { - - @Serializable - data class Weather( - @SerialName(value = "hourly") - val hourly: Hourly, - ) - - @Serializable - data class Hourly( - @SerialName(value = "time") - val time: List, - - @SerialName(value = "temperature_2m") - val temperature: List, - ) - @GET("v1/forecast?latitude=52.5244&longitude=13.4105&hourly=temperature_2m&forecast_days=16") - suspend fun getWeather(): Weather } diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeWeatherEditorDialog.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeWeatherEditorDialog.kt index c0e89dc0..f1e837ae 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeWeatherEditorDialog.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeWeatherEditorDialog.kt @@ -35,7 +35,6 @@ import de.berlindroid.zeapp.zebits.composableToBitmap import de.berlindroid.zeapp.zebits.isBinary import de.berlindroid.zeapp.zemodels.WeatherData import de.berlindroid.zeapp.zemodels.ZeConfiguration -import de.berlindroid.zeapp.zeservices.fetchWeather import de.berlindroid.zeapp.zeui.zepages.WeatherPage import de.berlindroid.zeapp.zeui.zetheme.ZeBlack import de.berlindroid.zeapp.zeui.zetheme.ZeWhite @@ -59,6 +58,7 @@ fun WeatherEditorDialog( dismissed: () -> Unit = {}, accepted: (config: ZeConfiguration.Weather) -> Unit, updateMessage: (String) -> Unit, + onFetchWeatherClick: suspend (String) -> WeatherData, ) { val activity = LocalContext.current as Activity @@ -200,9 +200,8 @@ fun WeatherEditorDialog( item { Button( onClick = { - // Fix this please :) scope.launch { - weatherData = fetchWeather(date) + weatherData = onFetchWeatherClick(date) redrawComposableImage() } }, diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt index f0c0464a..dcd624ef 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt @@ -74,6 +74,7 @@ internal fun SelectedEditor( dismissed = { vm.slotConfigured(null, null) }, accepted = { newConfig -> vm.slotConfigured(editor.slot, newConfig) }, updateMessage = vm::showMessage, + onFetchWeatherClick = vm::fetchWeather ) is ZeConfiguration.Quote -> RandomQuotesEditorDialog( diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt index 9c73e85e..00d8a14e 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt @@ -3,6 +3,7 @@ package de.berlindroid.zeapp.zeui.zehome import android.content.Intent import android.net.Uri import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.DrawerState import androidx.compose.material3.DrawerValue @@ -134,9 +135,7 @@ internal fun ZeScreen(vm: ZeBadgeViewModel, modifier: Modifier = Modifier) { ) } composable(ROUTE_ZEPASS) { - ZeUserProfile( - - ) + ZeUserProfile(paddingValues = PaddingValues()) } composable(ROUTE_ZEPASS) { ZeUserProfile(paddingValues) diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt index 121fab35..dc17063f 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt @@ -19,6 +19,7 @@ import de.berlindroid.zeapp.zeservices.ZeBadgeManager import de.berlindroid.zeapp.zeservices.ZeClipboardService import de.berlindroid.zeapp.zeservices.ZeImageProviderService import de.berlindroid.zeapp.zeservices.ZePreferencesService +import de.berlindroid.zeapp.zeservices.ZeWeatherService import de.berlindroid.zeapp.zeui.pixelManipulation import de.berlindroid.zeapp.zeui.simulator.ZeSimulatorButtonAction import de.berlindroid.zekompanion.ditherFloydSteinberg @@ -47,6 +48,7 @@ class ZeBadgeViewModel @Inject constructor( private val badgeManager: ZeBadgeManager, private val preferencesService: ZePreferencesService, private val clipboardService: ZeClipboardService, + private val weatherService: ZeWeatherService, private val getTemplateConfigurations: GetTemplateConfigurations, ) : ViewModel() { @@ -533,6 +535,8 @@ class ZeBadgeViewModel @Inject constructor( } } + suspend fun fetchWeather(date: String) = weatherService.fetchWeather(date) + private fun getInitialUIState(): ZeBadgeUiState = ZeBadgeUiState( message = "", From 985da05062dd1e69c02d50753dcbf673086a9faf Mon Sep 17 00:00:00 2001 From: Alex Yermolenko Date: Fri, 5 Jul 2024 15:08:16 +0200 Subject: [PATCH 2/3] feat: merge with dev --- .../main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt index 00d8a14e..56642b87 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/ZeScreen.kt @@ -3,7 +3,6 @@ package de.berlindroid.zeapp.zeui.zehome import android.content.Intent import android.net.Uri import androidx.activity.compose.BackHandler -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.DrawerState import androidx.compose.material3.DrawerValue @@ -134,9 +133,6 @@ internal fun ZeScreen(vm: ZeBadgeViewModel, modifier: Modifier = Modifier) { vm = vm, ) } - composable(ROUTE_ZEPASS) { - ZeUserProfile(paddingValues = PaddingValues()) - } composable(ROUTE_ZEPASS) { ZeUserProfile(paddingValues) } From 9516fd5c18a2a1437a217d535d6509de93548fc2 Mon Sep 17 00:00:00 2001 From: Alex Yermolenko Date: Fri, 5 Jul 2024 15:11:55 +0200 Subject: [PATCH 3/3] feat: lint fix --- .../java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt | 1 - .../java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt index 7e73f77f..b2e751ad 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeservices/ZeWeatherService.kt @@ -35,5 +35,4 @@ class ZeWeatherService @Inject constructor(private val zeWeatherApi: ZeWeatherAp ) } } - } diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt index dcd624ef..f535e30f 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zehome/SelectedEditor.kt @@ -74,7 +74,7 @@ internal fun SelectedEditor( dismissed = { vm.slotConfigured(null, null) }, accepted = { newConfig -> vm.slotConfigured(editor.slot, newConfig) }, updateMessage = vm::showMessage, - onFetchWeatherClick = vm::fetchWeather + onFetchWeatherClick = vm::fetchWeather, ) is ZeConfiguration.Quote -> RandomQuotesEditorDialog(