mirror of
https://github.com/JetBrains/intellij-platform-plugin-template.git
synced 2025-12-05 14:21:55 +00:00
Add WeatherDetailsCard widget implementation
This commit is contained in:
parent
6fd30b231d
commit
aeef1e7811
@ -12,7 +12,10 @@ import org.jetbrains.plugins.template.weatherApp.model.Location
|
||||
import org.jetbrains.plugins.template.weatherApp.model.WeatherForecastData
|
||||
import org.jetbrains.plugins.template.weatherApp.model.WeatherType
|
||||
import org.jetbrains.plugins.template.weatherApp.model.WindDirection
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import kotlin.random.Random
|
||||
|
||||
@Service
|
||||
internal class WeatherForecastService(private val cs: CoroutineScope) {
|
||||
@ -45,11 +48,18 @@ internal class WeatherForecastService(private val cs: CoroutineScope) {
|
||||
return WeatherForecastData(
|
||||
cityName = location.name,
|
||||
temperature = temperature,
|
||||
currentTime = LocalDateTime.now(),
|
||||
currentTime = LocalDateTime.of(LocalDate.now(), getRandomTime()),
|
||||
windSpeed = windSpeed,
|
||||
windDirection = WindDirection.random(),
|
||||
humidity = humidity,
|
||||
weatherType = WeatherType.random()
|
||||
)
|
||||
}
|
||||
|
||||
private fun getRandomTime(): LocalTime {
|
||||
val hour = Random.nextInt(0, 24)
|
||||
val minute = Random.nextInt(0, 60)
|
||||
val second = Random.nextInt(0, 60)
|
||||
return LocalTime.of(hour, minute, second)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,196 @@
|
||||
package org.jetbrains.plugins.template.weatherApp.ui.components
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.jetbrains.jewel.ui.component.*
|
||||
import org.jetbrains.jewel.ui.icons.AllIconsKeys
|
||||
import org.jetbrains.plugins.template.weatherApp.model.WeatherForecastData
|
||||
import org.jetbrains.plugins.template.weatherApp.model.WeatherType
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* A composable function that displays a weather card with Jewel theme.
|
||||
* The card displays city name, temperature, current time, wind information,
|
||||
* humidity, and a background icon representing the weather state.
|
||||
* The card and text color change based on temperature and time of day.
|
||||
*
|
||||
* @param weatherForecastData The weather data to display
|
||||
* @param modifier Additional modifier for the card
|
||||
*/
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
internal fun WeatherDetailsCard(
|
||||
modifier: Modifier = Modifier,
|
||||
weatherForecastData: WeatherForecastData,
|
||||
onReloadWeatherData: () -> Unit
|
||||
) {
|
||||
val isNightTime = isNightTime(weatherForecastData.currentTime)
|
||||
val cardColor = getCardColorByTemperature(weatherForecastData.temperature, isNightTime)
|
||||
val textColor = Color.White
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(cardColor)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
|
||||
// Card content
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
// City name
|
||||
Text(
|
||||
text = weatherForecastData.cityName,
|
||||
color = textColor,
|
||||
fontSize = 28.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
|
||||
ActionButton(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(Color.Transparent)
|
||||
.padding(8.dp),
|
||||
tooltip = { Text("Refresh weather data") },
|
||||
onClick = { onReloadWeatherData() },
|
||||
) {
|
||||
Icon(
|
||||
key = AllIconsKeys.Actions.Refresh,
|
||||
contentDescription = "Refresh",
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// Temperature and weather type column (vertically aligned)
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
// Temperature (emphasized)
|
||||
Text(
|
||||
text = "${weatherForecastData.temperature.toInt()}°C",
|
||||
color = textColor,
|
||||
fontSize = 48.sp,
|
||||
fontWeight = FontWeight.ExtraBold
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
// Weather type
|
||||
Text(
|
||||
text = weatherForecastData.weatherType.label,
|
||||
color = textColor,
|
||||
fontSize = 24.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// Current time
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
// Simple text for time
|
||||
Text(
|
||||
text = "Time: ${formatDateTime(weatherForecastData.currentTime)}",
|
||||
color = textColor,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// Wind and humidity info
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
// Wind info
|
||||
Text(
|
||||
text = "Wind: ${weatherForecastData.windSpeed.toInt()} km/h ${weatherForecastData.windDirection.label}",
|
||||
color = textColor,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
|
||||
// Humidity info
|
||||
Text(
|
||||
text = "Humidity: ${weatherForecastData.humidity}%",
|
||||
color = textColor,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a color for the weather type indicator.
|
||||
*/
|
||||
fun getWeatherTypeColor(weatherType: WeatherType, baseColor: Color): Color {
|
||||
return when (weatherType) {
|
||||
WeatherType.SUNNY -> Color.Yellow.copy(alpha = 0.2f)
|
||||
WeatherType.CLOUDY -> Color.Gray.copy(alpha = 0.2f)
|
||||
WeatherType.PARTLY_CLOUDY -> Color.LightGray.copy(alpha = 0.2f)
|
||||
WeatherType.RAINY -> Color.Blue.copy(alpha = 0.2f)
|
||||
WeatherType.SNOWY -> Color.White.copy(alpha = 0.3f)
|
||||
WeatherType.STORMY -> Color.DarkGray.copy(alpha = 0.2f)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if it's night time based on the current hour.
|
||||
* Night time is considered to be between 7 PM (19:00) and 6 AM (6:00).
|
||||
*/
|
||||
fun isNightTime(dateTime: LocalDateTime): Boolean {
|
||||
val hour = Random.nextInt(0, 24)
|
||||
return hour < 6 || hour >= 19
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a color based on the temperature and whether it's night time.
|
||||
* - Cold temperatures: blue/purple
|
||||
* - Warm temperatures: red/pink
|
||||
* - Night time: darker shades
|
||||
*/
|
||||
fun getCardColorByTemperature(temperature: Float, isNightTime: Boolean): Color {
|
||||
return when {
|
||||
isNightTime -> Color(0xFF1A237E) // Dark blue for night
|
||||
temperature < 0 -> Color(0xFF3F51B5) // Cold: blue
|
||||
temperature < 10 -> Color(0xFF5E35B1) // Cool: purple
|
||||
temperature < 20 -> Color(0xFF039BE5) // Mild: light blue
|
||||
temperature < 30 -> Color(0xFFFF9800) // Warm: orange
|
||||
else -> Color(0xFFE91E63) // Hot: pink/red
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the date time to a readable string.
|
||||
*/
|
||||
fun formatDateTime(dateTime: LocalDateTime): String {
|
||||
val formatter = DateTimeFormatter.ofPattern("MMM dd, yyyy HH:mm")
|
||||
return dateTime.format(formatter)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user