codeskraps 2 months ago
parent
commit
9f808119a6
40 changed files with 196 additions and 90 deletions
  1. 1 1
      .idea/compiler.xml
  2. 10 0
      .idea/deploymentTargetSelector.xml
  3. 2 1
      .idea/gradle.xml
  4. 1 1
      .idea/kotlinc.xml
  5. 1 1
      .idea/misc.xml
  6. 17 0
      .idea/runConfigurations.xml
  7. 32 18
      README.md
  8. 3 4
      app/build.gradle.kts
  9. 1 1
      app/src/main/java/com/codeskraps/weather/ui/MainActivity.kt
  10. BIN
      app/src/main/web_hi_res_1024.png
  11. BIN
      app/src/main/web_hi_res_128.png
  12. BIN
      app/src/main/web_hi_res_16.png
  13. BIN
      app/src/main/web_hi_res_256.png
  14. BIN
      app/src/main/web_hi_res_32.png
  15. BIN
      app/src/main/web_hi_res_64.png
  16. 3 4
      core/local/build.gradle.kts
  17. 2 1
      core/local/src/main/java/com/codeskraps/core/local/data/repository/LocalGeocodingRepositoryImpl.kt
  18. 3 4
      core/location/build.gradle.kts
  19. 3 4
      feature/common/build.gradle.kts
  20. 4 0
      feature/common/src/main/java/com/codeskraps/feature/common/navigation/Screen.kt
  21. 4 4
      feature/geocoding/build.gradle.kts
  22. 2 2
      feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/data/mappers/GeocodingMappers.kt
  23. 3 0
      feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/data/remote/GeoLocationDto.kt
  24. 3 0
      feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/data/remote/GeocodingDto.kt
  25. 7 1
      feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/di/FeatureModule.kt
  26. 2 5
      feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/presentation/components/GeocodingScreen.kt
  27. 3 4
      feature/maps/build.gradle.kts
  28. 1 1
      feature/maps/src/main/java/com/codeskraps/maps/presentation/components/MapScreen.kt
  29. 4 4
      feature/weather/build.gradle.kts
  30. 3 0
      feature/weather/src/main/java/com/codeskraps/feature/weather/data/remote/SunDataDto.kt
  31. 2 0
      feature/weather/src/main/java/com/codeskraps/feature/weather/data/remote/WeatherDataDto.kt
  32. 4 0
      feature/weather/src/main/java/com/codeskraps/feature/weather/data/remote/WeatherDto.kt
  33. 7 1
      feature/weather/src/main/java/com/codeskraps/feature/weather/di/FeatureModule.kt
  34. 6 6
      feature/weather/src/main/java/com/codeskraps/feature/weather/domain/model/WeatherData.kt
  35. 1 1
      feature/weather/src/main/java/com/codeskraps/feature/weather/domain/model/WeatherInfo.kt
  36. 6 0
      feature/weather/src/main/java/com/codeskraps/feature/weather/presentation/WeatherViewModel.kt
  37. 24 0
      feature/weather/src/main/java/com/codeskraps/feature/weather/presentation/components/HourlyWeatherDisplay.kt
  38. 8 0
      feature/weather/src/main/java/com/codeskraps/feature/weather/presentation/mvi/WeatherState.kt
  39. 22 20
      gradle/libs.versions.toml
  40. 1 1
      gradle/wrapper/gradle-wrapper.properties

+ 1 - 1
.idea/compiler.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="CompilerConfiguration">
-    <bytecodeTargetLevel target="17" />
+    <bytecodeTargetLevel target="19" />
   </component>
 </project>

+ 10 - 0
.idea/deploymentTargetSelector.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="deploymentTargetSelector">
+    <selectionStates>
+      <SelectionState runConfigName="app">
+        <option name="selectionMode" value="DROPDOWN" />
+      </SelectionState>
+    </selectionStates>
+  </component>
+</project>

+ 2 - 1
.idea/gradle.xml

@@ -15,8 +15,9 @@
             </builds>
           </compositeBuild>
         </compositeConfiguration>
+        <option name="testRunner" value="CHOOSE_PER_TEST" />
         <option name="externalProjectPath" value="$PROJECT_DIR$" />
-        <option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
+        <option name="gradleJvm" value="corretto-19" />
         <option name="modules">
           <set>
             <option value="$PROJECT_DIR$" />

+ 1 - 1
.idea/kotlinc.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="KotlinJpsPluginSettings">
-    <option name="version" value="1.9.22" />
+    <option name="version" value="1.9.24" />
   </component>
 </project>

+ 1 - 1
.idea/misc.xml

@@ -1,6 +1,6 @@
 <project version="4">
   <component name="ExternalStorageConfigurationManager" enabled="true" />
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="corretto-19" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
   <component name="ProjectType">

+ 17 - 0
.idea/runConfigurations.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
+        <option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
+        <option value="com.intellij.execution.junit.PatternConfigurationProducer" />
+        <option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
+        <option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
+        <option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
+        <option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
+        <option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

+ 32 - 18
README.md

@@ -1,27 +1,41 @@
 ![logo](app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp)
 
-# Weekly-Weather
+# Weekly Weather
 
-A quick view of your weekly weather
+## Overview
 
-A quick overview of you weekly weather of your current location or search and save your favourite locations for easy access.
+Weekly Weather provides a clean, intuitive interface for viewing weather forecasts for your current location and saved favorite places. The app is designed to be straightforward and user-friendly while providing accurate weather information.
 
-Save a GPS weather location with a custom name.
+## Features
 
-App translated into 37 languages.
+- View detailed weekly weather forecasts
+- Automatically detect current location
+- Search and save favorite locations for quick access
+- Custom naming for GPS locations
+- Available in 37 languages
+- Lightweight and battery-efficient
 
-![screenshot_one][screenshot_one]
-![screenshot_two][screenshot_two]
-![screenshot_three][screenshot_three]
-![screenshot_four][screenshot_four]
-![screenshot_five][screenshot_five]
+## Screenshots
 
-[screenshot_one]: store_assets/Screenshot_20240109_145100.png
-[screenshot_two]: store_assets/Screenshot_20240109_145124.png
-[screenshot_three]: store_assets/Screenshot_20240109_145438.png
-[screenshot_four]: store_assets/Screenshot_20240109_145033.png
-[screenshot_five]: store_assets/Screenshot_20240109_145421.png
+<p align="center">
+  <img src="store_assets/Screenshot_20240109_145100.png" width="200" />
+  <img src="store_assets/Screenshot_20240109_145124.png" width="200" /> 
+  <img src="store_assets/Screenshot_20240109_145438.png" width="200" />
+  <img src="store_assets/Screenshot_20240109_145033.png" width="200" />
+  <img src="store_assets/Screenshot_20240109_145421.png" width="200" />
+</p>
 
-Weather data API -> https://open-meteo.com/
-Open Sourced -> https://github.com/codeskraps/Weekly-Weather
-Assets -> https://github.com/Makin-Things/weather-icons
+## Download
+
+<a href="https://play.google.com/store/apps/details?id=com.arklan.weather">
+  <img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" width="200"/>
+</a>
+
+## Credits
+
+- Weather data provided by [Open-Meteo](https://open-meteo.com/)
+- Weather icons from [Makin-Things/weather-icons](https://github.com/Makin-Things/weather-icons)
+
+## Source
+
+This application is open source and available on [GitHub](https://github.com/codeskraps/Weekly-Weather).

+ 3 - 4
app/build.gradle.kts

@@ -1,6 +1,5 @@
 import com.codeskraps.weather.ConfigData
 
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
 plugins {
     alias(libs.plugins.android.application)
     alias(libs.plugins.org.jetbrains.kotlin.android)
@@ -43,11 +42,11 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = ConfigData.javaVersion
-        targetCompatibility = ConfigData.javaVersion
+        sourceCompatibility = ConfigData.JAVA_VERSION
+        targetCompatibility = ConfigData.JAVA_VERSION
     }
     kotlinOptions {
-        jvmTarget = ConfigData.javaTarget
+        jvmTarget = ConfigData.JAVA_TARGET
     }
     buildFeatures {
         compose = true

+ 1 - 1
app/src/main/java/com/codeskraps/weather/ui/MainActivity.kt

@@ -36,7 +36,7 @@ class MainActivity : ComponentActivity() {
             WeatherTheme {
                 val navController = rememberNavController()
 
-                NavHost(navController = navController, startDestination = Screen.Weather.route) {
+                NavHost(navController = navController, startDestination = Screen.Weather.createEmptyRoute()) {
                     composable(
                         route = Screen.Weather.route,
                         arguments = listOf(

BIN
app/src/main/web_hi_res_1024.png


BIN
app/src/main/web_hi_res_128.png


BIN
app/src/main/web_hi_res_16.png


BIN
app/src/main/web_hi_res_256.png


BIN
app/src/main/web_hi_res_32.png


BIN
app/src/main/web_hi_res_64.png


+ 3 - 4
core/local/build.gradle.kts

@@ -1,6 +1,5 @@
 import com.codeskraps.weather.ConfigData
 
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
 plugins {
     alias(libs.plugins.android.library)
     alias(libs.plugins.org.jetbrains.kotlin.android)
@@ -32,11 +31,11 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = ConfigData.javaVersion
-        targetCompatibility = ConfigData.javaVersion
+        sourceCompatibility = ConfigData.JAVA_VERSION
+        targetCompatibility = ConfigData.JAVA_VERSION
     }
     kotlinOptions {
-        jvmTarget = ConfigData.javaTarget
+        jvmTarget = ConfigData.JAVA_TARGET
     }
 }
 

+ 2 - 1
core/local/src/main/java/com/codeskraps/core/local/data/repository/LocalGeocodingRepositoryImpl.kt

@@ -1,5 +1,6 @@
 package com.codeskraps.core.local.data.repository
 
+import com.codeskraps.core.local.data.db.GeocodingDB
 import com.codeskraps.core.local.domain.model.GeoLocation
 import com.codeskraps.core.local.domain.repository.LocalGeocodingRepository
 import com.codeskraps.core.local.data.mappers.toGeoLocationEntity
@@ -9,7 +10,7 @@ import com.codeskraps.feature.common.util.Resource
 import javax.inject.Inject
 
 class LocalGeocodingRepositoryImpl @Inject constructor(
-    private val geocodingDB: com.codeskraps.core.local.data.db.GeocodingDB,
+    private val geocodingDB: GeocodingDB,
     private val localResource: LocalResourceRepository
 ) : LocalGeocodingRepository {
 

+ 3 - 4
core/location/build.gradle.kts

@@ -1,6 +1,5 @@
 import com.codeskraps.weather.ConfigData
 
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
 plugins {
     alias(libs.plugins.android.library)
     alias(libs.plugins.org.jetbrains.kotlin.android)
@@ -32,11 +31,11 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = ConfigData.javaVersion
-        targetCompatibility = ConfigData.javaVersion
+        sourceCompatibility = ConfigData.JAVA_VERSION
+        targetCompatibility = ConfigData.JAVA_VERSION
     }
     kotlinOptions {
-        jvmTarget = ConfigData.javaTarget
+        jvmTarget = ConfigData.JAVA_TARGET
     }
 }
 

+ 3 - 4
feature/common/build.gradle.kts

@@ -1,6 +1,5 @@
 import com.codeskraps.weather.ConfigData
 
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
 plugins {
     alias(libs.plugins.android.library)
     alias(libs.plugins.org.jetbrains.kotlin.android)
@@ -31,11 +30,11 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = ConfigData.javaVersion
-        targetCompatibility = ConfigData.javaVersion
+        sourceCompatibility = ConfigData.JAVA_VERSION
+        targetCompatibility = ConfigData.JAVA_VERSION
     }
     kotlinOptions {
-        jvmTarget = ConfigData.javaTarget
+        jvmTarget = ConfigData.JAVA_TARGET
     }
     buildFeatures {
         compose = true

+ 4 - 0
feature/common/src/main/java/com/codeskraps/feature/common/navigation/Screen.kt

@@ -7,6 +7,10 @@ sealed class Screen(val route: String) {
                 long.toBigDecimal().toPlainString()
             }"
         }
+
+        fun createEmptyRoute(): String {
+            return "weather/nowhere/0/0"
+        }
     }
 
     data object Geocoding : Screen("geocoding")

+ 4 - 4
feature/geocoding/build.gradle.kts

@@ -1,6 +1,5 @@
 import com.codeskraps.weather.ConfigData
 
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
 plugins {
     alias(libs.plugins.android.library)
     alias(libs.plugins.org.jetbrains.kotlin.android)
@@ -34,11 +33,11 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = ConfigData.javaVersion
-        targetCompatibility = ConfigData.javaVersion
+        sourceCompatibility = ConfigData.JAVA_VERSION
+        targetCompatibility = ConfigData.JAVA_VERSION
     }
     kotlinOptions {
-        jvmTarget = ConfigData.javaTarget
+        jvmTarget = ConfigData.JAVA_TARGET
     }
     buildFeatures {
         compose = true
@@ -79,6 +78,7 @@ dependencies {
     // Retrofit
     implementation(libs.retrofit.retrofit)
     implementation(libs.retrofit.converter.moshi)
+    implementation(libs.retrofit.moshi.kotlin)
 
     testImplementation(libs.junit.junit)
     androidTestImplementation(libs.androidx.junit)

+ 2 - 2
feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/data/mappers/GeocodingMappers.kt

@@ -3,9 +3,9 @@ package com.codeskraps.feature.geocoding.data.mappers
 import com.codeskraps.core.local.domain.model.GeoLocation
 import com.codeskraps.feature.geocoding.data.remote.GeocodingDto
 
-fun GeocodingDto.toGeocoding(): List<com.codeskraps.core.local.domain.model.GeoLocation> {
+fun GeocodingDto.toGeocoding(): List<GeoLocation> {
     return results.map {
-        com.codeskraps.core.local.domain.model.GeoLocation(
+        GeoLocation(
             name = it.name,
             latitude = it.latitude,
             longitude = it.longitude,

+ 3 - 0
feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/data/remote/GeoLocationDto.kt

@@ -1,5 +1,8 @@
 package com.codeskraps.feature.geocoding.data.remote
 
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
 data class GeoLocationDto(
     val name: String,
     val latitude: Double,

+ 3 - 0
feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/data/remote/GeocodingDto.kt

@@ -1,5 +1,8 @@
 package com.codeskraps.feature.geocoding.data.remote
 
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
 data class GeocodingDto(
     val results: List<GeoLocationDto>
 )

+ 7 - 1
feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/di/FeatureModule.kt

@@ -1,6 +1,8 @@
 package com.codeskraps.feature.geocoding.di
 
 import com.codeskraps.feature.geocoding.data.remote.GeocodingApi
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
 import dagger.Module
 import dagger.Provides
 import dagger.hilt.InstallIn
@@ -15,9 +17,13 @@ object FeatureModule {
 
     @Provides
     fun providesGeocodingApi(): GeocodingApi {
+        val moshi = Moshi.Builder()
+            .add(KotlinJsonAdapterFactory())
+            .build()
+
         return Retrofit.Builder()
             .baseUrl("https://geocoding-api.open-meteo.com/")
-            .addConverterFactory(MoshiConverterFactory.create())
+            .addConverterFactory(MoshiConverterFactory.create(moshi))
             .build()
             .create()
     }

+ 2 - 5
feature/geocoding/src/main/java/com/codeskraps/feature/geocoding/presentation/components/GeocodingScreen.kt

@@ -19,11 +19,9 @@ import androidx.compose.foundation.text.KeyboardActions
 import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.automirrored.filled.ArrowBack
-import androidx.compose.material.icons.filled.ArrowBack
 import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.material.icons.filled.FavoriteBorder
 import androidx.compose.material3.CircularProgressIndicator
-import androidx.compose.material3.Divider
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
@@ -36,7 +34,6 @@ import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Alignment.Companion.CenterVertically
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.platform.LocalContext
@@ -56,7 +53,7 @@ import com.codeskraps.feature.geocoding.presentation.mvi.GeoEvent
 import com.codeskraps.feature.geocoding.presentation.mvi.GeoState
 import kotlinx.coroutines.flow.Flow
 
-@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
+@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun GeocodingScreen(
     state: GeoState,
@@ -68,7 +65,7 @@ fun GeocodingScreen(
     val context = LocalContext.current
     val resources = context.resources
 
-    LifecycleResumeEffect {
+    LifecycleResumeEffect(Unit) {
         handleEvent(GeoEvent.LoadCache)
         onPauseOrDispose { }
     }

+ 3 - 4
feature/maps/build.gradle.kts

@@ -1,6 +1,5 @@
 import com.codeskraps.weather.ConfigData
 
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
 plugins {
     alias(libs.plugins.android.library)
     alias(libs.plugins.org.jetbrains.kotlin.android)
@@ -33,11 +32,11 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = ConfigData.javaVersion
-        targetCompatibility = ConfigData.javaVersion
+        sourceCompatibility = ConfigData.JAVA_VERSION
+        targetCompatibility = ConfigData.JAVA_VERSION
     }
     kotlinOptions {
-        jvmTarget = ConfigData.javaTarget
+        jvmTarget = ConfigData.JAVA_TARGET
     }
     buildFeatures {
         compose = true

+ 1 - 1
feature/maps/src/main/java/com/codeskraps/maps/presentation/components/MapScreen.kt

@@ -68,7 +68,7 @@ fun MapScreen(
     }
 
     BackHandler {
-        navRoute(Screen.Weather.route)
+        navRoute(Screen.Weather.createEmptyRoute())
     }
 
     Scaffold(

+ 4 - 4
feature/weather/build.gradle.kts

@@ -1,6 +1,5 @@
 import com.codeskraps.weather.ConfigData
 
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
 plugins {
     alias(libs.plugins.android.library)
     alias(libs.plugins.org.jetbrains.kotlin.android)
@@ -34,11 +33,11 @@ android {
         }
     }
     compileOptions {
-        sourceCompatibility = ConfigData.javaVersion
-        targetCompatibility = ConfigData.javaVersion
+        sourceCompatibility = ConfigData.JAVA_VERSION
+        targetCompatibility = ConfigData.JAVA_VERSION
     }
     kotlinOptions {
-        jvmTarget = ConfigData.javaTarget
+        jvmTarget = ConfigData.JAVA_TARGET
     }
     buildFeatures {
         compose = true
@@ -85,6 +84,7 @@ dependencies {
     // Retrofit
     implementation(libs.retrofit.retrofit)
     implementation(libs.retrofit.converter.moshi)
+    implementation(libs.retrofit.moshi.kotlin)
 
     implementation(libs.coroutines.test)
     testImplementation(libs.junit.junit)

+ 3 - 0
feature/weather/src/main/java/com/codeskraps/feature/weather/data/remote/SunDataDto.kt

@@ -1,5 +1,8 @@
 package com.codeskraps.feature.weather.data.remote
 
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
 data class SunDataDto(
     val sunrise: List<String>,
     val sunset: List<String>

+ 2 - 0
feature/weather/src/main/java/com/codeskraps/feature/weather/data/remote/WeatherDataDto.kt

@@ -1,7 +1,9 @@
 package com.codeskraps.feature.weather.data.remote
 
 import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
 
+@JsonClass(generateAdapter = true)
 data class WeatherDataDto(
     val time: List<String>,
     @field:Json(name = "temperature_2m")

+ 4 - 0
feature/weather/src/main/java/com/codeskraps/feature/weather/data/remote/WeatherDto.kt

@@ -1,10 +1,14 @@
 package com.codeskraps.feature.weather.data.remote
 
 import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
 
+@JsonClass(generateAdapter = true)
 data class WeatherDto(
+    @Json(name = "hourly")
     @field:Json(name = "hourly")
     val weatherData: WeatherDataDto,
+    @Json(name = "daily")
     @field:Json(name = "daily")
     val sunData: SunDataDto
 )

+ 7 - 1
feature/weather/src/main/java/com/codeskraps/feature/weather/di/FeatureModule.kt

@@ -1,6 +1,8 @@
 package com.codeskraps.feature.weather.di
 
 import com.codeskraps.feature.weather.data.remote.WeatherApi
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
 import dagger.Module
 import dagger.Provides
 import dagger.hilt.InstallIn
@@ -15,9 +17,13 @@ object FeatureModule {
 
     @Provides
     fun providesWeatherApi(): WeatherApi {
+        val moshi = Moshi.Builder()
+            .add(KotlinJsonAdapterFactory())
+            .build()
+
         return Retrofit.Builder()
             .baseUrl("https://api.open-meteo.com/")
-            .addConverterFactory(MoshiConverterFactory.create())
+            .addConverterFactory(MoshiConverterFactory.create(moshi))
             .build()
             .create()
     }

+ 6 - 6
feature/weather/src/main/java/com/codeskraps/feature/weather/domain/model/WeatherData.kt

@@ -4,11 +4,11 @@ import java.time.LocalDateTime
 
 data class WeatherData(
     val time: LocalDateTime,
-    val temperatureCelsius:Double,
-    val pressure:Double,
-    val windSpeed:Double,
-    val humidity:Double,
+    val temperatureCelsius: Double,
+    val pressure: Double,
+    val windSpeed: Double,
+    val humidity: Double,
     val weatherType: WeatherType,
-    val sunrise:LocalDateTime,
-    val sunset:LocalDateTime
+    val sunrise: LocalDateTime,
+    val sunset: LocalDateTime
 )

+ 1 - 1
feature/weather/src/main/java/com/codeskraps/feature/weather/domain/model/WeatherInfo.kt

@@ -8,5 +8,5 @@ data class WeatherInfo(
     val latitude: Double = .0,
     val longitude: Double = .0,
     val weatherDataPerDay: ImmutableMap<Int, ImmutableList<WeatherData>>,
-    val currentWeatherData: WeatherData?,
+    val currentWeatherData: WeatherData?
 )

+ 6 - 0
feature/weather/src/main/java/com/codeskraps/feature/weather/presentation/WeatherViewModel.kt

@@ -1,5 +1,6 @@
 package com.codeskraps.feature.weather.presentation
 
+import android.util.Log
 import androidx.lifecycle.SavedStateHandle
 import androidx.lifecycle.viewModelScope
 import com.codeskraps.feature.common.dispatcher.DispatcherProvider
@@ -82,6 +83,8 @@ class WeatherViewModel @Inject constructor(
                 geoLocation
             }
 
+            Log.d("WeatherViewModel", "onLoadWeatherInfo: $location")
+
             location?.let { intLocation ->
                 when (val result =
                     weatherRepository.getWeatherData(intLocation.lat, intLocation.long)) {
@@ -144,6 +147,7 @@ class WeatherViewModel @Inject constructor(
                 }
             }
         }
+
         return currentState.copy(
             isLoading = true,
             error = null,
@@ -183,6 +187,8 @@ class WeatherViewModel @Inject constructor(
                 long = long.toDouble()
             )
 
+            Log.d("WeatherViewModel", "onResume: $weatherLocation")
+
             state.handleEvent(WeatherEvent.LoadWeatherInfo(weatherLocation))
         } catch (e: Exception) {
             state.handleEvent(WeatherEvent.LoadWeatherInfo(WeatherLocation()))

+ 24 - 0
feature/weather/src/main/java/com/codeskraps/feature/weather/presentation/components/HourlyWeatherDisplay.kt

@@ -13,10 +13,34 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import com.codeskraps.feature.weather.domain.model.WeatherData
+import com.codeskraps.feature.weather.domain.model.WeatherType
+import java.time.LocalDateTime
 import java.time.format.DateTimeFormatter
 
+@Preview
+@Composable
+private fun HourlyWeatherDisplayPreview() {
+    HourlyWeatherDisplay(
+        weatherData = WeatherData(
+            time = LocalDateTime.now(),
+            temperatureCelsius = 24.2,
+            pressure = 1022.toDouble(),
+            windSpeed = 6.toDouble(),
+            humidity = 62.toDouble(),
+            weatherType = WeatherType.fromWMO(
+                code = 0,
+                isDay = true,
+                isFreezing = false
+            ),
+            sunrise = LocalDateTime.now(),
+            sunset = LocalDateTime.now()
+        )
+    )
+}
+
 @Composable
 fun HourlyWeatherDisplay(
     weatherData: WeatherData,

+ 8 - 0
feature/weather/src/main/java/com/codeskraps/feature/weather/presentation/mvi/WeatherState.kt

@@ -18,3 +18,11 @@ data class WeatherState(
     }
 }
 
+sealed interface State {
+    data class Success(val weatherInfo: WeatherInfo) : State
+    data class Error(val message: String) : State
+    object Loading : State
+    object About : State
+    data class IsCached(val isCached: Boolean) : State
+}
+

+ 22 - 20
gradle/libs.versions.toml

@@ -1,29 +1,30 @@
 [versions]
-androidxComposeBom = "2024.02.02"
-androidGradlePlugin = "8.3.0"
-ktx = "1.12.0"
-compose = "1.8.2"
+androidxComposeBom = "2024.09.03"
+androidGradlePlugin = "8.7.1"
+ktx = "1.13.1"
+compose = "1.9.2"
 immutable = "0.3.7"
-location = "21.2.0"
+location = "21.3.0"
 hilt = "2.51"
 hilt-navigation = "1.2.0"
-navigationCompose = "2.7.7"
-lyfecyleCompose = "2.7.0"
-retrofit = "2.9.0"
+navigationCompose = "2.8.2"
+lyfecyleCompose = "2.8.6"
+retrofit = "2.11.0"
+moshiVersion = "1.12.0"
 junit = "4.13.2"
-junittest = "1.1.5"
-espresso = "3.5.1"
-coroutines = "1.7.3"
+junittest = "1.2.1"
+espresso = "3.6.1"
+coroutines = "1.8.1"
 room = "2.6.1"
-material = "1.6.3"
-material3 = "1.2.1"
-org-jetbrains-kotlin-android = "1.9.22"
-appcompat = "1.6.1"
-com-google-android-material-material = "1.11.0"
-ksp = "1.9.22-1.0.17"
-animationGraphicsAndroid = "1.6.3"
-play-services-maps = "18.2.0"
-maps-compose = "4.3.0"
+material = "1.7.3"
+material3 = "1.3.0"
+appcompat = "1.7.0"
+com-google-android-material-material = "1.12.0"
+org-jetbrains-kotlin-android = "1.9.24"
+ksp = "1.9.24-1.0.20"
+animationGraphicsAndroid = "1.7.3"
+play-services-maps = "19.0.0"
+maps-compose = "4.4.1"
 secretsGradlePlugin = "2.0.1"
 
 
@@ -56,6 +57,7 @@ hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-com
 # Retrofit
 retrofit-retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
 retrofit-converter-moshi = { group = "com.squareup.retrofit2", name = "converter-moshi", version.ref = "retrofit" }
+retrofit-moshi-kotlin = { group = "com.squareup.moshi", name = "moshi-kotlin", version.ref = "moshiVersion" }
 
 # Room
 room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }

+ 1 - 1
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
 #Fri Oct 06 11:44:37 CEST 2023
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists