Compare commits
	
		
			No commits in common. "d88bb723786e6074e05d540b9b28bccbc8e58234" and "16c9fdba515e15dd096d1666398bd8d1bc6132bd" have entirely different histories.
		
	
	
		
			d88bb72378
			...
			16c9fdba51
		
	
		|  | @ -1,15 +0,0 @@ | ||||||
| root = true |  | ||||||
| 
 |  | ||||||
| [*] |  | ||||||
| charset = utf-8 |  | ||||||
| indent_size = 2 |  | ||||||
| indent_style = space |  | ||||||
| insert_final_newline = true |  | ||||||
| 
 |  | ||||||
| [*.{kt,kts}] |  | ||||||
| ij_kotlin_packages_to_use_import_on_demand = unset |  | ||||||
| ij_kotlin_name_count_to_use_star_import = 999 |  | ||||||
| ij_kotlin_name_count_to_use_star_import_for_members = 999 |  | ||||||
| ij_kotlin_allow_trailing_comma = true |  | ||||||
| ij_kotlin_allow_trailing_comma_on_call_site = true |  | ||||||
| ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL |  | ||||||
|  | @ -3,7 +3,6 @@ plugins { | ||||||
|     alias(libs.plugins.kotlin.android) |     alias(libs.plugins.kotlin.android) | ||||||
|     alias(libs.plugins.kotlin.compose) |     alias(libs.plugins.kotlin.compose) | ||||||
|     id("kotlin-parcelize") |     id("kotlin-parcelize") | ||||||
|   id("org.jlleitschuh.gradle.ktlint") version "11.5.1" |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| android { | android { | ||||||
|  | @ -25,7 +24,7 @@ android { | ||||||
|             isMinifyEnabled = false |             isMinifyEnabled = false | ||||||
|             proguardFiles( |             proguardFiles( | ||||||
|                 getDefaultProguardFile("proguard-android-optimize.txt"), |                 getDefaultProguardFile("proguard-android-optimize.txt"), | ||||||
|         "proguard-rules.pro", |                 "proguard-rules.pro" | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -71,4 +70,5 @@ dependencies { | ||||||
|     implementation("com.squareup.retrofit2:converter-gson:2.9.0") |     implementation("com.squareup.retrofit2:converter-gson:2.9.0") | ||||||
|     implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") |     implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") | ||||||
|     implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2") |     implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2") | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | package com.module.breeze | ||||||
|  | 
 | ||||||
|  | import androidx.test.platform.app.InstrumentationRegistry | ||||||
|  | import androidx.test.ext.junit.runners.AndroidJUnit4 | ||||||
|  | 
 | ||||||
|  | import org.junit.Test | ||||||
|  | import org.junit.runner.RunWith | ||||||
|  | 
 | ||||||
|  | import org.junit.Assert.* | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Instrumented test, which will execute on an Android device. | ||||||
|  |  * | ||||||
|  |  * See [testing documentation](http://d.android.com/tools/testing). | ||||||
|  |  */ | ||||||
|  | @RunWith(AndroidJUnit4::class) | ||||||
|  | class ExampleInstrumentedTest { | ||||||
|  |     @Test | ||||||
|  |     fun useAppContext() { | ||||||
|  |         // Context of the app under test. | ||||||
|  |         val appContext = InstrumentationRegistry.getInstrumentation().targetContext | ||||||
|  |         assertEquals("com.module.breeze", appContext.packageName) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -18,16 +18,15 @@ class GpsRepository(private val context: Context) : LocationListener { | ||||||
|         this.onLocationChanged = onLocationChanged |         this.onLocationChanged = onLocationChanged | ||||||
|         locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager |         locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager | ||||||
| 
 | 
 | ||||||
|     if (ContextCompat.checkSelfPermission( |         if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) | ||||||
|         context, |             == | ||||||
|         Manifest.permission.ACCESS_FINE_LOCATION, |             PackageManager.PERMISSION_GRANTED | ||||||
|       ) == PackageManager.PERMISSION_GRANTED |  | ||||||
|         ) { |         ) { | ||||||
|             locationManager?.requestLocationUpdates( |             locationManager?.requestLocationUpdates( | ||||||
|                 LocationManager.GPS_PROVIDER, |                 LocationManager.GPS_PROVIDER, | ||||||
|                 1000L, |                 1000L, | ||||||
|                 1f, |                 1f, | ||||||
|         this, |                 this | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1,17 +1,12 @@ | ||||||
| package com.module.breeze | package com.module.breeze | ||||||
| 
 | 
 | ||||||
| import android.Manifest |  | ||||||
| import android.content.Context | import android.content.Context | ||||||
| import android.content.Intent | import android.content.Intent | ||||||
| import android.content.pm.PackageManager |  | ||||||
| import android.location.Location |  | ||||||
| import android.os.Build | import android.os.Build | ||||||
| import android.os.Bundle | import android.os.Bundle | ||||||
| import androidx.activity.ComponentActivity | import androidx.activity.ComponentActivity | ||||||
| import androidx.activity.compose.rememberLauncherForActivityResult |  | ||||||
| import androidx.activity.compose.setContent | import androidx.activity.compose.setContent | ||||||
| import androidx.activity.enableEdgeToEdge | import androidx.activity.enableEdgeToEdge | ||||||
| import androidx.activity.result.contract.ActivityResultContracts |  | ||||||
| import androidx.annotation.RequiresApi | import androidx.annotation.RequiresApi | ||||||
| import androidx.compose.foundation.layout.Arrangement | import androidx.compose.foundation.layout.Arrangement | ||||||
| import androidx.compose.foundation.layout.Column | import androidx.compose.foundation.layout.Column | ||||||
|  | @ -36,7 +31,6 @@ import androidx.compose.material3.Icon | ||||||
| import androidx.compose.material3.Scaffold | import androidx.compose.material3.Scaffold | ||||||
| import androidx.compose.material3.Text | import androidx.compose.material3.Text | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.runtime.Composable | ||||||
| import androidx.compose.runtime.DisposableEffect |  | ||||||
| import androidx.compose.runtime.getValue | import androidx.compose.runtime.getValue | ||||||
| import androidx.compose.runtime.mutableStateOf | import androidx.compose.runtime.mutableStateOf | ||||||
| import androidx.compose.runtime.remember | import androidx.compose.runtime.remember | ||||||
|  | @ -51,18 +45,33 @@ import androidx.compose.ui.text.font.FontWeight | ||||||
| import androidx.compose.ui.tooling.preview.Preview | import androidx.compose.ui.tooling.preview.Preview | ||||||
| import androidx.compose.ui.unit.dp | import androidx.compose.ui.unit.dp | ||||||
| import androidx.compose.ui.unit.sp | import androidx.compose.ui.unit.sp | ||||||
| import androidx.core.content.ContextCompat |  | ||||||
| import com.module.breeze.ui.theme.BreezeTheme | import com.module.breeze.ui.theme.BreezeTheme | ||||||
| import kotlinx.coroutines.runBlocking | import kotlinx.coroutines.runBlocking | ||||||
| import java.text.DecimalFormat | import java.text.DecimalFormat | ||||||
| import java.time.LocalDate | import java.time.LocalDate | ||||||
| import kotlin.math.roundToInt | import kotlin.math.roundToInt | ||||||
|  | import android.Manifest | ||||||
|  | import android.content.pm.PackageManager | ||||||
|  | import android.location.Location | ||||||
|  | import androidx.activity.compose.rememberLauncherForActivityResult | ||||||
|  | import androidx.activity.result.contract.ActivityResultContracts | ||||||
|  | import androidx.compose.foundation.layout.Column | ||||||
|  | import androidx.compose.material3.Button | ||||||
|  | import androidx.compose.material3.Text | ||||||
|  | import androidx.compose.runtime.DisposableEffect | ||||||
|  | import androidx.compose.runtime.getValue | ||||||
|  | import androidx.compose.runtime.mutableStateOf | ||||||
|  | import androidx.compose.runtime.remember | ||||||
|  | import androidx.compose.runtime.setValue | ||||||
|  | import androidx.compose.ui.platform.LocalContext | ||||||
|  | import androidx.core.content.ContextCompat | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| val fontSizeCurrentTemp = 48.sp | val fontSizeCurrentTemp = 48.sp | ||||||
| val fontSizeUpper = 16.sp | val fontSizeUpper = 16.sp | ||||||
| val fontSizeTitle = 22.sp | val fontSizeTitle = 22.sp | ||||||
| val breezeFontWeight = FontWeight.Bold | val breezeFontWeight = FontWeight.Bold | ||||||
| val iconStyle = Icons.Outlined | val iconStyle = Icons.Outlined; | ||||||
| val textColor = Color(0, 0, 0) | val textColor = Color(0, 0, 0) | ||||||
| val numberFormat = DecimalFormat("00") | val numberFormat = DecimalFormat("00") | ||||||
| val apiKey = "8a6090c4308455152cd8c677b802883b" | val apiKey = "8a6090c4308455152cd8c677b802883b" | ||||||
|  | @ -75,7 +84,7 @@ class MainActivity : ComponentActivity() { | ||||||
|             BreezeTheme { |             BreezeTheme { | ||||||
|                 Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> |                 Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> | ||||||
|                     WeatherInfo( |                     WeatherInfo( | ||||||
|             modifier = Modifier.padding(innerPadding), |                         modifier = Modifier.padding(innerPadding) | ||||||
|                     ) |                     ) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -106,10 +115,16 @@ fun fetchWeather(ctx: Context): ForecastSummary { | ||||||
| 
 | 
 | ||||||
|     var data: ForecastSummary |     var data: ForecastSummary | ||||||
|     runBlocking { |     runBlocking { | ||||||
|     val forecastResponse = RetrofitClient.instance.getWeatherForecast("$todayPlz,ch", apiKey) |         val forecastResponse = RetrofitClient.instance.getWeatherForecast("${todayPlz},ch", apiKey) | ||||||
|         val todaysForecast = getTodaysForecast(forecastResponse) |         val todaysForecast = getTodaysForecast(forecastResponse) | ||||||
| 
 | 
 | ||||||
|         data = todaysForecast |         data = todaysForecast | ||||||
|  |         println("Today's Forecast for ${todayPlz}:") | ||||||
|  |         println("Min Temperature: ${todaysForecast.minTemp}°C") | ||||||
|  |         println("Max Temperature: ${todaysForecast.maxTemp}°C") | ||||||
|  |         println("Rain: ${if (todaysForecast.hasRain) "Yes" else "No"}") | ||||||
|  |         println("Snow: ${if (todaysForecast.hasSnow) "Yes" else "No"}") | ||||||
|  |         println("Strong Winds: ${if (todaysForecast.hasStrongWinds) "Yes" else "No"}") | ||||||
|     } |     } | ||||||
|     return data |     return data | ||||||
| } | } | ||||||
|  | @ -122,13 +137,14 @@ fun fetchCurrentTemp(ctx: Context, lat: Double, lon: Double): WeatherResponse { | ||||||
|     return data |     return data | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @Composable | @Composable | ||||||
| fun WeatherInfo(modifier: Modifier = Modifier) { | fun WeatherInfo(modifier: Modifier = Modifier) { | ||||||
|     val ctx = LocalContext.current |     val ctx = LocalContext.current | ||||||
|     var forecast by remember { mutableStateOf(ForecastSummary(0.0, 0.0, false, false, false)) } |     var forecast by remember { mutableStateOf(ForecastSummary(0.0, 0.0, false, false, false)) } | ||||||
|     var currentTemp by remember { |     var currentTemp by remember { | ||||||
|         mutableStateOf( |         mutableStateOf( | ||||||
|       WeatherResponse(Main(0.0, 0.0, 0.0, 0.0, 0, 0), emptyList(), 0L), |             WeatherResponse(Main(0.0, 0.0, 0.0, 0.0, 0, 0), emptyList(), 0L) | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|     val locationHelper = remember { GpsRepository(ctx) } |     val locationHelper = remember { GpsRepository(ctx) } | ||||||
|  | @ -136,17 +152,17 @@ fun WeatherInfo(modifier: Modifier = Modifier) { | ||||||
|     var location by remember { mutableStateOf<Location?>(null) } |     var location by remember { mutableStateOf<Location?>(null) } | ||||||
| 
 | 
 | ||||||
|     val locationPermission = ContextCompat.checkSelfPermission( |     val locationPermission = ContextCompat.checkSelfPermission( | ||||||
|     ctx, |         ctx, Manifest.permission.ACCESS_FINE_LOCATION | ||||||
|     Manifest.permission.ACCESS_FINE_LOCATION, |  | ||||||
|     ) |     ) | ||||||
|     var hasLocationPermission by remember { |     var hasLocationPermission by remember { | ||||||
|         mutableStateOf(locationPermission == PackageManager.PERMISSION_GRANTED) |         mutableStateOf(locationPermission == PackageManager.PERMISSION_GRANTED) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     val permissionLauncher = rememberLauncherForActivityResult( |     val permissionLauncher = rememberLauncherForActivityResult( | ||||||
|     ActivityResultContracts.RequestPermission(), |         ActivityResultContracts.RequestPermission() | ||||||
|     ) { isGranted -> hasLocationPermission = isGranted } |     ) { isGranted -> hasLocationPermission = isGranted } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     DisposableEffect(key1 = locationHelper, key2 = hasLocationPermission) { |     DisposableEffect(key1 = locationHelper, key2 = hasLocationPermission) { | ||||||
|         if (hasLocationPermission) { |         if (hasLocationPermission) { | ||||||
|             locationHelper.startListening { newLocation -> |             locationHelper.startListening { newLocation -> | ||||||
|  | @ -163,11 +179,9 @@ fun WeatherInfo(modifier: Modifier = Modifier) { | ||||||
|         forecast = fetchWeather(ctx) |         forecast = fetchWeather(ctx) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     Navigation( |     Navigation( | ||||||
|     iconStyle.Settings, |         iconStyle.Settings, "Settings Icon", onClick = { MainActivity.openSettings(ctx) }) | ||||||
|     "Settings Icon", |  | ||||||
|     onClick = { MainActivity.openSettings(ctx) }, |  | ||||||
|   ) |  | ||||||
| 
 | 
 | ||||||
|     Column( |     Column( | ||||||
|         modifier = Modifier.fillMaxSize(), |         modifier = Modifier.fillMaxSize(), | ||||||
|  | @ -180,43 +194,41 @@ fun WeatherInfo(modifier: Modifier = Modifier) { | ||||||
|                 contentDescription = "Location Icon", |                 contentDescription = "Location Icon", | ||||||
|                 modifier = Modifier |                 modifier = Modifier | ||||||
|                     .padding(end = 16.dp) |                     .padding(end = 16.dp) | ||||||
|           .size(32.dp), |                     .size(32.dp) | ||||||
|             ) |             ) | ||||||
|             Icon( |             Icon( | ||||||
|                 imageVector = iconStyle.WaterDrop, |                 imageVector = iconStyle.WaterDrop, | ||||||
|                 contentDescription = "Rain Icon", |                 contentDescription = "Rain Icon", | ||||||
|         modifier = Modifier.alpha(if (forecast.hasRain) 1F else 0.2F), |                 modifier = Modifier.alpha(if (forecast.hasRain) 1F else 0.2F) | ||||||
|             ) |             ) | ||||||
|             Icon( |             Icon( | ||||||
|                 imageVector = iconStyle.AcUnit, |                 imageVector = iconStyle.AcUnit, | ||||||
|                 contentDescription = "Snow Icon", |                 contentDescription = "Snow Icon", | ||||||
|         modifier = Modifier.alpha(if (forecast.hasSnow) 1F else 0.2F), |                 modifier = Modifier.alpha(if (forecast.hasSnow) 1F else 0.2F) | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             Icon( |             Icon( | ||||||
|                 imageVector = iconStyle.Air, |                 imageVector = iconStyle.Air, | ||||||
|                 contentDescription = "Wind Icon", |                 contentDescription = "Wind Icon", | ||||||
|         modifier = Modifier.alpha(if (forecast.hasStrongWinds) 1F else 0.2F), |                 modifier = Modifier.alpha(if (forecast.hasStrongWinds) 1F else 0.2F) | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|         Row { |         Row { | ||||||
|             Icon( |             Icon( | ||||||
|         imageVector = iconStyle.ArrowDownward, |                 imageVector = iconStyle.ArrowDownward, contentDescription = "Arrow down Icon" | ||||||
|         contentDescription = "Arrow down Icon", |  | ||||||
|             ) |             ) | ||||||
|             Text( |             Text( | ||||||
|                 text = numberFormat.format(forecast.minTemp.roundToInt()) + "°", |                 text = numberFormat.format(forecast.minTemp.roundToInt()) + "°", | ||||||
|                 fontSize = fontSizeUpper, |                 fontSize = fontSizeUpper, | ||||||
|         fontWeight = breezeFontWeight, |                 fontWeight = breezeFontWeight | ||||||
|             ) |             ) | ||||||
|             Icon( |             Icon( | ||||||
|         imageVector = iconStyle.ArrowUpward, |                 imageVector = iconStyle.ArrowUpward, contentDescription = "Arrow up Icon" | ||||||
|         contentDescription = "Arrow up Icon", |  | ||||||
|             ) |             ) | ||||||
|             Text( |             Text( | ||||||
|                 text = numberFormat.format(forecast.maxTemp.roundToInt()) + "°", |                 text = numberFormat.format(forecast.maxTemp.roundToInt()) + "°", | ||||||
|                 fontSize = fontSizeUpper, |                 fontSize = fontSizeUpper, | ||||||
|         fontWeight = breezeFontWeight, |                 fontWeight = breezeFontWeight | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|         if (hasLocationPermission) { |         if (hasLocationPermission) { | ||||||
|  | @ -234,8 +246,7 @@ fun WeatherInfo(modifier: Modifier = Modifier) { | ||||||
|                     permissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) |                     permissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) | ||||||
|                 }, |                 }, | ||||||
|                 colors = ButtonDefaults.buttonColors( |                 colors = ButtonDefaults.buttonColors( | ||||||
|           containerColor = Color(0, 0, 0, 20), |                     containerColor = Color(0, 0, 0, 20), contentColor = textColor | ||||||
|           contentColor = textColor, |  | ||||||
|                 ), |                 ), | ||||||
|             ) { |             ) { | ||||||
|                 Text( |                 Text( | ||||||
|  | @ -255,26 +266,25 @@ fun GreetingPreview() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @Composable | @Composable | ||||||
| fun Navigation(icon: ImageVector, iconDescription: String, onClick: () -> Unit = {}) { | fun Navigation(icon: ImageVector, iconDescription: String, onClick: () -> Unit = {}) { | ||||||
|     Row( |     Row( | ||||||
|     horizontalArrangement = Arrangement.End, |         horizontalArrangement = Arrangement.End, modifier = Modifier.fillMaxWidth() | ||||||
|     modifier = Modifier.fillMaxWidth(), |  | ||||||
|     ) { |     ) { | ||||||
|         Button( |         Button( | ||||||
|             onClick = onClick, |             onClick = onClick, | ||||||
|             colors = ButtonDefaults.buttonColors( |             colors = ButtonDefaults.buttonColors( | ||||||
|         containerColor = Color(255, 0, 0, 0), |                 containerColor = Color(255, 0, 0, 0), contentColor = textColor | ||||||
|         contentColor = textColor, |  | ||||||
|             ), |             ), | ||||||
|             shape = CircleShape, |             shape = CircleShape, | ||||||
|             contentPadding = PaddingValues(0.dp), |             contentPadding = PaddingValues(0.dp), | ||||||
|       modifier = Modifier.padding(0.dp, 40.dp, 28.dp, 0.dp), |             modifier = Modifier.padding(0.dp, 40.dp, 28.dp, 0.dp) | ||||||
|         ) { |         ) { | ||||||
|             Icon( |             Icon( | ||||||
|                 imageVector = icon, |                 imageVector = icon, | ||||||
|                 contentDescription = iconDescription, |                 contentDescription = iconDescription, | ||||||
|         modifier = Modifier.size(40.dp), |                 modifier = Modifier.size(40.dp) | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| package com.module.breeze | package com.module.breeze | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| import android.content.Context | import android.content.Context | ||||||
| import android.content.Intent | import android.content.Intent | ||||||
| import android.os.Bundle | import android.os.Bundle | ||||||
|  | @ -53,6 +54,7 @@ var plzArrayStatus: List<String> = listOf( | ||||||
|     "Loading...", |     "Loading...", | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| // ### Start ChatGPT + Fixing | // ### Start ChatGPT + Fixing | ||||||
| val SHARED_PLZ_KEY = stringPreferencesKey("shared-plz") | val SHARED_PLZ_KEY = stringPreferencesKey("shared-plz") | ||||||
| val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings") | val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings") | ||||||
|  | @ -84,6 +86,7 @@ suspend fun setPLZ(index: Int, value: String, ctx: Context) { | ||||||
|     setLocations(ctx, arr) |     setLocations(ctx, arr) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class SettingsActivity : ComponentActivity() { | class SettingsActivity : ComponentActivity() { | ||||||
|     override fun onCreate(savedInstanceState: Bundle?) { |     override fun onCreate(savedInstanceState: Bundle?) { | ||||||
|         super.onCreate(savedInstanceState) |         super.onCreate(savedInstanceState) | ||||||
|  | @ -92,7 +95,7 @@ class SettingsActivity : ComponentActivity() { | ||||||
|             BreezeTheme { |             BreezeTheme { | ||||||
|                 Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> |                 Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> | ||||||
|                     Settings( |                     Settings( | ||||||
|             modifier = Modifier.padding(innerPadding), |                         modifier = Modifier.padding(innerPadding) | ||||||
|                     ) |                     ) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -104,6 +107,8 @@ class SettingsActivity : ComponentActivity() { | ||||||
|             var intent = Intent(ctx, MainActivity::class.java) |             var intent = Intent(ctx, MainActivity::class.java) | ||||||
|             ctx.startActivity(intent) |             ctx.startActivity(intent) | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -111,29 +116,29 @@ class SettingsActivity : ComponentActivity() { | ||||||
| fun Settings(modifier: Modifier = Modifier) { | fun Settings(modifier: Modifier = Modifier) { | ||||||
|     val ctx = LocalContext.current |     val ctx = LocalContext.current | ||||||
| 
 | 
 | ||||||
|   Navigation( |     Navigation(iconStyle.Home, "Home Icon", onClick = { | ||||||
|     iconStyle.Home, |         SettingsActivity.openHome(ctx) | ||||||
|     "Home Icon", |     }) | ||||||
|     onClick = { SettingsActivity.openHome(ctx) }, |  | ||||||
|   ) |  | ||||||
|     Column( |     Column( | ||||||
|         modifier = Modifier.fillMaxSize(), |         modifier = Modifier.fillMaxSize(), | ||||||
|         verticalArrangement = Arrangement.Center, |         verticalArrangement = Arrangement.Center, | ||||||
|     horizontalAlignment = Alignment.CenterHorizontally, |         horizontalAlignment = Alignment.CenterHorizontally | ||||||
|   ) { |     ) | ||||||
|  |     { | ||||||
|         Row( |         Row( | ||||||
|             verticalAlignment = Alignment.CenterVertically, |             verticalAlignment = Alignment.CenterVertically, | ||||||
|       modifier = Modifier.padding(16.dp), |             modifier = Modifier.padding(16.dp) | ||||||
|     ) { |         ) | ||||||
|  |         { | ||||||
|             Icon( |             Icon( | ||||||
|                 imageVector = iconStyle.Map, |                 imageVector = iconStyle.Map, | ||||||
|                 contentDescription = "Configured Locations Icon", |                 contentDescription = "Configured Locations Icon", | ||||||
|         modifier = Modifier.size(40.dp), |                 modifier = Modifier.size(40.dp) | ||||||
|             ) |             ) | ||||||
|             Text( |             Text( | ||||||
|                 text = "Configured Locations", |                 text = "Configured Locations", | ||||||
|                 fontWeight = breezeFontWeight, |                 fontWeight = breezeFontWeight, | ||||||
|         fontSize = fontSizeTitle, |                 fontSize = fontSizeTitle | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|         ConfiguredLocationDay("Monday", 0, ctx) |         ConfiguredLocationDay("Monday", 0, ctx) | ||||||
|  | @ -179,12 +184,12 @@ fun ConfiguredLocationDay(dayName: String = "day", index: Int, ctx: Context) { | ||||||
|     } else { |     } else { | ||||||
|         Row( |         Row( | ||||||
|             verticalAlignment = Alignment.CenterVertically, |             verticalAlignment = Alignment.CenterVertically, | ||||||
|       modifier = Modifier.padding(0.dp, 4.dp), |             modifier = Modifier.padding(0.dp, 4.dp) | ||||||
|         ) { |         ) { | ||||||
|             Text( |             Text( | ||||||
|                 text = dayName, |                 text = dayName, | ||||||
|                 fontWeight = breezeFontWeight, |                 fontWeight = breezeFontWeight, | ||||||
|         modifier = Modifier.width(100.dp), |                 modifier = Modifier.width(100.dp) | ||||||
|             ) |             ) | ||||||
|             TextField( |             TextField( | ||||||
|                 value = plz, |                 value = plz, | ||||||
|  | @ -197,7 +202,7 @@ fun ConfiguredLocationDay(dayName: String = "day", index: Int, ctx: Context) { | ||||||
|                 }, |                 }, | ||||||
|                 label = { Text("PLZ") }, |                 label = { Text("PLZ") }, | ||||||
|                 keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), |                 keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), | ||||||
|         modifier = Modifier.width(110.dp), |                 modifier = Modifier.width(110.dp) | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| package com.module.breeze | package com.module.breeze | ||||||
| 
 | 
 | ||||||
| import okhttp3.OkHttpClient |  | ||||||
| import okhttp3.logging.HttpLoggingInterceptor |  | ||||||
| import retrofit2.Retrofit | import retrofit2.Retrofit | ||||||
| import retrofit2.converter.gson.GsonConverterFactory | import retrofit2.converter.gson.GsonConverterFactory | ||||||
| import retrofit2.http.GET | import retrofit2.http.GET | ||||||
| import retrofit2.http.Query | import retrofit2.http.Query | ||||||
|  | import okhttp3.OkHttpClient | ||||||
|  | import okhttp3.logging.HttpLoggingInterceptor | ||||||
| import java.util.Date | import java.util.Date | ||||||
| 
 | 
 | ||||||
| // Whole File DeepSeek | // Whole File DeepSeek | ||||||
|  | @ -13,7 +13,7 @@ import java.util.Date | ||||||
| data class WeatherResponse( | data class WeatherResponse( | ||||||
|     val main: Main, |     val main: Main, | ||||||
|     val weather: List<Weather>, |     val weather: List<Weather>, | ||||||
|   val dt: Long, |     val dt: Long | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class Main( | data class Main( | ||||||
|  | @ -22,18 +22,18 @@ data class Main( | ||||||
|     val temp_min: Double, |     val temp_min: Double, | ||||||
|     val temp_max: Double, |     val temp_max: Double, | ||||||
|     val pressure: Int, |     val pressure: Int, | ||||||
|   val humidity: Int, |     val humidity: Int | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class Weather( | data class Weather( | ||||||
|     val id: Int, |     val id: Int, | ||||||
|     val main: String, |     val main: String, | ||||||
|     val description: String, |     val description: String, | ||||||
|   val icon: String, |     val icon: String | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class ForecastResponse( | data class ForecastResponse( | ||||||
|   val list: List<Forecast>, |     val list: List<Forecast> | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class Forecast( | data class Forecast( | ||||||
|  | @ -42,20 +42,20 @@ data class Forecast( | ||||||
|     val weather: List<Weather>, |     val weather: List<Weather>, | ||||||
|     val wind: Wind, |     val wind: Wind, | ||||||
|     val rain: Rain?, |     val rain: Rain?, | ||||||
|   val snow: Snow?, |     val snow: Snow? | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class Wind( | data class Wind( | ||||||
|     val speed: Double, |     val speed: Double, | ||||||
|   val deg: Int, |     val deg: Int | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class Rain( | data class Rain( | ||||||
|   val `3h`: Double?, |     val `3h`: Double? | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| data class Snow( | data class Snow( | ||||||
|   val `3h`: Double?, |     val `3h`: Double? | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Retrofit API interface | // Retrofit API interface | ||||||
|  | @ -65,14 +65,14 @@ interface WeatherApiService { | ||||||
|         @Query("lat") lat: Double, |         @Query("lat") lat: Double, | ||||||
|         @Query("lon") lon: Double, |         @Query("lon") lon: Double, | ||||||
|         @Query("appid") apiKey: String, |         @Query("appid") apiKey: String, | ||||||
|     @Query("units") units: String = "metric", |         @Query("units") units: String = "metric" | ||||||
|     ): WeatherResponse |     ): WeatherResponse | ||||||
| 
 | 
 | ||||||
|     @GET("forecast") |     @GET("forecast") | ||||||
|     suspend fun getWeatherForecast( |     suspend fun getWeatherForecast( | ||||||
|         @Query("zip") zip: String, |         @Query("zip") zip: String, | ||||||
|         @Query("appid") apiKey: String, |         @Query("appid") apiKey: String, | ||||||
|     @Query("units") units: String = "metric", |         @Query("units") units: String = "metric" | ||||||
|     ): ForecastResponse |     ): ForecastResponse | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -84,11 +84,16 @@ object RetrofitClient { | ||||||
|         level = HttpLoggingInterceptor.Level.BODY |         level = HttpLoggingInterceptor.Level.BODY | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   private val httpClient = OkHttpClient.Builder().addInterceptor(logging).build() |     private val httpClient = OkHttpClient.Builder() | ||||||
|  |         .addInterceptor(logging) | ||||||
|  |         .build() | ||||||
| 
 | 
 | ||||||
|     val instance: WeatherApiService by lazy { |     val instance: WeatherApiService by lazy { | ||||||
|     Retrofit.Builder().baseUrl(BASE_URL).client(httpClient) |         Retrofit.Builder() | ||||||
|       .addConverterFactory(GsonConverterFactory.create()).build() |             .baseUrl(BASE_URL) | ||||||
|  |             .client(httpClient) | ||||||
|  |             .addConverterFactory(GsonConverterFactory.create()) | ||||||
|  |             .build() | ||||||
|             .create(WeatherApiService::class.java) |             .create(WeatherApiService::class.java) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -115,7 +120,7 @@ fun getTodaysForecast(forecastResponse: ForecastResponse): ForecastSummary { | ||||||
|         maxTemp = maxTemp, |         maxTemp = maxTemp, | ||||||
|         hasRain = hasRain, |         hasRain = hasRain, | ||||||
|         hasSnow = hasSnow, |         hasSnow = hasSnow, | ||||||
|     hasStrongWinds = hasStrongWinds, |         hasStrongWinds = hasStrongWinds | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -125,5 +130,5 @@ data class ForecastSummary( | ||||||
|     val maxTemp: Double, |     val maxTemp: Double, | ||||||
|     val hasRain: Boolean, |     val hasRain: Boolean, | ||||||
|     val hasSnow: Boolean, |     val hasSnow: Boolean, | ||||||
|   val hasStrongWinds: Boolean, |     val hasStrongWinds: Boolean | ||||||
| ) | ) | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| package com.module.breeze.ui.theme | package com.module.breeze.ui.theme | ||||||
| 
 | 
 | ||||||
|  | import android.app.Activity | ||||||
| import android.os.Build | import android.os.Build | ||||||
| import androidx.compose.foundation.isSystemInDarkTheme | import androidx.compose.foundation.isSystemInDarkTheme | ||||||
| import androidx.compose.material3.MaterialTheme | import androidx.compose.material3.MaterialTheme | ||||||
|  | @ -13,13 +14,13 @@ import androidx.compose.ui.platform.LocalContext | ||||||
| private val DarkColorScheme = darkColorScheme( | private val DarkColorScheme = darkColorScheme( | ||||||
|     primary = Purple80, |     primary = Purple80, | ||||||
|     secondary = PurpleGrey80, |     secondary = PurpleGrey80, | ||||||
|   tertiary = Pink80, |     tertiary = Pink80 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| private val LightColorScheme = lightColorScheme( | private val LightColorScheme = lightColorScheme( | ||||||
|     primary = Purple40, |     primary = Purple40, | ||||||
|     secondary = PurpleGrey40, |     secondary = PurpleGrey40, | ||||||
|   tertiary = Pink40, |     tertiary = Pink40 | ||||||
| 
 | 
 | ||||||
|     /* Other default colors to override |     /* Other default colors to override | ||||||
|     background = Color(0xFFFFFBFE), |     background = Color(0xFFFFFBFE), | ||||||
|  | @ -37,7 +38,7 @@ fun BreezeTheme( | ||||||
|     darkTheme: Boolean = isSystemInDarkTheme(), |     darkTheme: Boolean = isSystemInDarkTheme(), | ||||||
|     // Dynamic color is available on Android 12+ |     // Dynamic color is available on Android 12+ | ||||||
|     dynamicColor: Boolean = true, |     dynamicColor: Boolean = true, | ||||||
|   content: @Composable () -> Unit, |     content: @Composable () -> Unit | ||||||
| ) { | ) { | ||||||
|     val colorScheme = when { |     val colorScheme = when { | ||||||
|         dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { |         dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { | ||||||
|  | @ -52,6 +53,6 @@ fun BreezeTheme( | ||||||
|     MaterialTheme( |     MaterialTheme( | ||||||
|         colorScheme = colorScheme, |         colorScheme = colorScheme, | ||||||
|         typography = Typography, |         typography = Typography, | ||||||
|     content = content, |         content = content | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  | @ -13,8 +13,8 @@ val Typography = Typography( | ||||||
|         fontWeight = FontWeight.Normal, |         fontWeight = FontWeight.Normal, | ||||||
|         fontSize = 16.sp, |         fontSize = 16.sp, | ||||||
|         lineHeight = 24.sp, |         lineHeight = 24.sp, | ||||||
|     letterSpacing = 0.5.sp, |         letterSpacing = 0.5.sp | ||||||
|   ), |     ) | ||||||
|     /* Other default text styles to override |     /* Other default text styles to override | ||||||
|     titleLarge = TextStyle( |     titleLarge = TextStyle( | ||||||
|         fontFamily = FontFamily.Default, |         fontFamily = FontFamily.Default, | ||||||
|  |  | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | package com.module.breeze | ||||||
|  | 
 | ||||||
|  | import org.junit.Test | ||||||
|  | 
 | ||||||
|  | import org.junit.Assert.* | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Example local unit test, which will execute on the development machine (host). | ||||||
|  |  * | ||||||
|  |  * See [testing documentation](http://d.android.com/tools/testing). | ||||||
|  |  */ | ||||||
|  | class ExampleUnitTest { | ||||||
|  |     @Test | ||||||
|  |     fun addition_isCorrect() { | ||||||
|  |         assertEquals(4, 2 + 2) | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue