Weather Dynamic Widgets
This commit is contained in:
1 parent
7e1c8c3858
commit
9803b8b20d
3 files changed
+229
-12
No files matched your search
+67
-3
@@ -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):
|
||||
|
||||
+9
-9
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user