From 9803b8b20dc218ad92005374332f063e9ccb4482 Mon Sep 17 00:00:00 2001 From: tr1x_em Date: Thu, 7 Aug 2025 11:55:35 +0530 Subject: [PATCH] Weather Dynamic Widgets --- modules/widget.py | 70 ++++++++++++++++++++- styles/colors.css | 18 +++--- styles/widgets.css | 153 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 12 deletions(-) diff --git a/modules/widget.py b/modules/widget.py index 47cfc97..8e91d9e 100644 --- a/modules/widget.py +++ b/modules/widget.py @@ -32,6 +32,51 @@ LOCATION_CACHE_TIMEOUT = 604800 # 7 days (extended from 24h) # Thread pool for async operations executor = ThreadPoolExecutor(max_workers=4) +# Weather condition to CSS class mapping (iOS-style gradients) +WEATHER_GRADIENT_MAP = { + # Clear/Sunny conditions - bright blue to lighter blue + 0: "weather-clear", # Clear sky + 1: "weather-mostly-clear", # Mainly clear + + # Cloudy conditions - grey gradients + 2: "weather-partly-cloudy", # Partly cloudy + 3: "weather-overcast", # Overcast + + # Fog conditions - muted grey/blue + 45: "weather-fog", # Fog + 48: "weather-fog", # Depositing rime fog + + # Light rain/drizzle - blue-grey gradients + 51: "weather-light-rain", # Light drizzle + 53: "weather-rain", # Moderate drizzle + 55: "weather-rain", # Dense drizzle + 61: "weather-light-rain", # Slight rain + 80: "weather-light-rain", # Slight rain showers + + # Heavy rain - darker blue-grey + 63: "weather-heavy-rain", # Moderate rain + 65: "weather-heavy-rain", # Heavy rain + 81: "weather-heavy-rain", # Moderate rain showers + 82: "weather-storm", # Violent rain showers + + # Snow conditions - blue-white gradients + 56: "weather-snow", # Light freezing drizzle + 57: "weather-snow", # Dense freezing drizzle + 66: "weather-snow", # Light freezing rain + 67: "weather-snow", # Heavy freezing rain + 71: "weather-snow", # Slight snow fall + 73: "weather-heavy-snow", # Moderate snow fall + 75: "weather-heavy-snow", # Heavy snow fall + 77: "weather-snow", # Snow grains + 85: "weather-snow", # Slight snow showers + 86: "weather-heavy-snow", # Heavy snow showers + + # Storm conditions - dark dramatic gradients + 95: "weather-storm", # Thunderstorm + 96: "weather-storm", # Thunderstorm with slight hail + 99: "weather-storm", # Thunderstorm with heavy hail +} + # Weather condition to emoji mapping WEATHER_EMOJI_MAP = { 0: "☀️", # Clear sky @@ -187,6 +232,7 @@ def format_weather_data(weather_data: Dict[str, Any], city: str) -> List[str]: weather_code = current['weathercode'] emoji = WEATHER_EMOJI_MAP.get(weather_code, "🌤️") condition = WEATHER_DESC_MAP.get(weather_code, "Unknown") + gradient_class = WEATHER_GRADIENT_MAP.get(weather_code, "weather-clear") # Temperature temp = f"{round(current['temperature'])}°" @@ -195,7 +241,7 @@ def format_weather_data(weather_data: Dict[str, Any], city: str) -> List[str]: max_temp = f"{round(daily['temperature_2m_max'][0])}°" min_temp = f"{round(daily['temperature_2m_min'][0])}°" - return [emoji, temp, condition, city, max_temp, min_temp] + return [emoji, temp, condition, city, max_temp, min_temp, gradient_class] except (KeyError, IndexError, TypeError) as e: print(f"Error formatting weather data: {e}") @@ -322,10 +368,10 @@ class Weather(Box): def update_labels(self, weather_info: List[str]): """Update weather labels with new data.""" - if not weather_info or len(weather_info) != 6: + if not weather_info or len(weather_info) != 7: return - emoji, temp, condition, location, maxtemp, mintemp = weather_info + emoji, temp, condition, location, maxtemp, mintemp, gradient_class = weather_info maxmin = f"H:{maxtemp} L:{mintemp}" # Batch update labels for better performance @@ -340,6 +386,8 @@ class Weather(Box): for label, text in label_updates: label.set_label(text) + # Apply gradient background based on weather condition + self.parent.apply_weather_gradient(gradient_class) self.parent.set_visible(True) @@ -358,6 +406,22 @@ class WeatherContainer(Box): children=[Weather(self)], **kwargs, ) + + # Track current gradient class for smooth transitions + self.current_gradient_class = None + + def apply_weather_gradient(self, gradient_class: str): + """Apply weather-specific gradient background.""" + if self.current_gradient_class == gradient_class: + return # No change needed + + # Remove previous gradient class + if self.current_gradient_class: + self.remove_style_class(self.current_gradient_class) + + # Add new gradient class + self.add_style_class(gradient_class) + self.current_gradient_class = gradient_class class Date(Box): diff --git a/styles/colors.css b/styles/colors.css index 26eb35f..1a391d3 100644 --- a/styles/colors.css +++ b/styles/colors.css @@ -2,19 +2,19 @@ --foreground: #e4e1e9; --background: #131318; --cursor: #e4e1e9; - --primary: #bcc2ff; - --on-primary: #242b61; - --secondary: #c4c5dd; - --on-secondary: #2d2f42; - --tertiary: #e6bad6; - --on-tertiary: #45263d; + --primary: #bec2ff; + --on-primary: #262b60; + --secondary: #c5c4dd; + --on-secondary: #2e2f42; + --tertiary: #e7b9d5; + --on-tertiary: #45263c; --surface: #131318; --surface-bright: #39393f; --error: #ffb4ab; --error-dim: #ff8678; --on-error: #690005; --error-container: #93000a; - --outline: #90909a; + --outline: #91909a; --shadow: #000000; --red: #ffb2b9; --red-dim: #ff7f8b; @@ -22,8 +22,8 @@ --green-dim: #70c789; --yellow: #b8cf84; --yellow-dim: #a3c15f; - --blue: #bdc2ff; - --blue-dim: #8a93ff; + --blue: #bec2ff; + --blue-dim: #8b92ff; --magenta: #e4b7f3; --magenta-dim: #d48bec; --cyan: #82d3e2; diff --git a/styles/widgets.css b/styles/widgets.css index eccaba1..5e8d36c 100644 --- a/styles/widgets.css +++ b/styles/widgets.css @@ -4,6 +4,159 @@ min-width: 170px; min-height: 170px; border-radius: 16px; + transition: background 0.8s ease-in-out; +} + +/* Dynamic Weather Gradient Backgrounds (Clean 2-Color Design) */ + +/* ☀️ Clear Sky - Brightest, most vibrant blue */ +#weather-container.weather-clear.weather-clear { + background: linear-gradient(135deg, #1e90ff 0%, #87ceeb 100%); +} + +/* 🌤️ Mostly Clear - Slightly less bright */ +#weather-container.weather-mostly-clear.weather-mostly-clear { + background: linear-gradient(135deg, #4169e1 0%, #b0e0e6 100%); +} + +/* ⛅ Partly Cloudy - Muted blue to grey (darker than clear) */ +#weather-container.weather-partly-cloudy.weather-partly-cloudy { + background: linear-gradient(135deg, #4682b4 0%, #b8c6db 100%); +} + +/* ☁️ Overcast - Grey gradient */ +#weather-container.weather-overcast.weather-overcast { + background: linear-gradient(135deg, #485563 0%, #8fa0ad 100%); +} + +/* 🌫️ Fog - Misty grey */ +#weather-container.weather-fog.weather-fog { + background: linear-gradient(135deg, #606c88 0%, #c1d3dd 100%); +} + +/* 🌦️ Light Rain - Light blue */ +#weather-container.weather-light-rain.weather-light-rain { + background: linear-gradient(135deg, #2c5aa0 0%, #92a8d1 100%); +} + +/* 🌧️ Rain - Deep blue */ +#weather-container.weather-rain.weather-rain { + background: linear-gradient(135deg, #1a365d 0%, #4299e1 100%); +} + +/* ⛈️ Heavy Rain/Storm - Dark dramatic */ +#weather-container.weather-heavy-rain.weather-heavy-rain, +#weather-container.weather-storm.weather-storm { + background: linear-gradient(135deg, #0f172a 0%, #64748b 100%); +} + +/* 🌨️ Snow - Winter blue to white */ +#weather-container.weather-snow.weather-snow { + background: linear-gradient(135deg, #a8c8ec 0%, #ffffff 100%); +} + +/* ❄️ Heavy Snow - Bright winter */ +#weather-container.weather-heavy-snow.weather-heavy-snow { + background: linear-gradient(135deg, #9fb3d3 0%, #f8fbff 100%); +} + +/* Text color adjustments for better readability on photorealistic gradients */ + +/* Light/Bright Gradients - Dark Text */ +#weather-container.weather-clear #city, +#weather-container.weather-mostly-clear #city, +#weather-container.weather-snow #city, +#weather-container.weather-heavy-snow #city { + color: #1a202c; + text-shadow: 0 1px 3px rgba(255,255,255,0.6); + font-weight: 700; +} + +#weather-container.weather-clear #temperature, +#weather-container.weather-mostly-clear #temperature, +#weather-container.weather-snow #temperature, +#weather-container.weather-heavy-snow #temperature { + color: #2d3748; + text-shadow: 0 1px 3px rgba(255,255,255,0.6); + font-weight: 400; +} + +#weather-container.weather-clear #condition, +#weather-container.weather-mostly-clear #condition, +#weather-container.weather-snow #condition, +#weather-container.weather-heavy-snow #condition { + color: #4a5568; + text-shadow: 0 1px 2px rgba(255,255,255,0.5); + font-weight: 600; +} + +#weather-container.weather-clear #feels-like, +#weather-container.weather-mostly-clear #feels-like, +#weather-container.weather-snow #feels-like, +#weather-container.weather-heavy-snow #feels-like { + color: #4a5568; + text-shadow: 0 1px 2px rgba(255,255,255,0.5); + font-weight: 600; +} + +/* Medium Gradients - Semi-dark Text */ +#weather-container.weather-partly-cloudy #city, +#weather-container.weather-fog #city, +#weather-container.weather-light-rain #city { + color: #2d3748; + text-shadow: 0 1px 2px rgba(255,255,255,0.4); + font-weight: 700; +} + +#weather-container.weather-partly-cloudy #temperature, +#weather-container.weather-fog #temperature, +#weather-container.weather-light-rain #temperature { + color: #2d3748; + text-shadow: 0 1px 2px rgba(255,255,255,0.4); + font-weight: 400; +} + +#weather-container.weather-partly-cloudy #condition, +#weather-container.weather-partly-cloudy #feels-like, +#weather-container.weather-fog #condition, +#weather-container.weather-fog #feels-like, +#weather-container.weather-light-rain #condition, +#weather-container.weather-light-rain #feels-like { + color: #4a5568; + text-shadow: 0 1px 2px rgba(255,255,255,0.3); + font-weight: 600; +} + +/* Dark Gradients - Light Text */ +#weather-container.weather-overcast #city, +#weather-container.weather-rain #city, +#weather-container.weather-heavy-rain #city, +#weather-container.weather-storm #city { + color: #f7fafc; + text-shadow: 0 2px 4px rgba(0,0,0,0.6); + font-weight: 700; +} + +#weather-container.weather-overcast #temperature, +#weather-container.weather-rain #temperature, +#weather-container.weather-heavy-rain #temperature, +#weather-container.weather-storm #temperature { + color: #ffffff; + text-shadow: 0 2px 4px rgba(0,0,0,0.6); + font-weight: 400; +} + +#weather-container.weather-overcast #condition, +#weather-container.weather-overcast #feels-like, +#weather-container.weather-rain #condition, +#weather-container.weather-rain #feels-like, +#weather-container.weather-heavy-rain #condition, +#weather-container.weather-heavy-rain #feels-like, +#weather-container.weather-storm #condition, +#weather-container.weather-storm #feels-like { + color: #e2e8f0; + text-shadow: 0 2px 3px rgba(0,0,0,0.5); + font-weight: 600; } #weather-widget label {