Skip to content

Commit 7dbaa0e

Browse files
author
Ruslan
committed
Get daily weather setup and clean up code
1 parent 8efc975 commit 7dbaa0e

17 files changed

Lines changed: 239 additions & 79 deletions

build.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
fn main() {
2-
slint_build::compile("ui/app.slint").unwrap();
2+
slint_build::compile_with_config(
3+
"ui/app.slint",
4+
slint_build::CompilerConfiguration::new()
5+
// .with_sdf_fonts(true)
6+
// .embed_resources(slint_build::EmbedResourcesKind::EmbedForSoftwareRenderer)
7+
.with_style("cosmic-dark".into()),
8+
)
9+
.unwrap();
310
}

src/weather.rs

Lines changed: 77 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use chrono::{DateTime, Datelike, Local, Timelike};
22
use serde::Deserialize;
33
use slint::VecModel;
44

5-
use crate::{Api, Coordinates, Date, Time, WeatherCurrent, WeatherDaily, WeatherType};
5+
use crate::{
6+
Api, Coordinates, Date, Time, WeatherCurrent, WeatherDaily, WeatherHourly, WeatherType,
7+
};
68

79
#[derive(Debug, Clone, PartialEq, Deserialize, Default)]
810
pub struct WeatherApiDaily {
@@ -22,6 +24,7 @@ pub struct WeatherApiHourly {
2224
pub precipitation: Vec<f32>,
2325
pub time: Vec<String>,
2426
pub uv_index: Vec<f32>,
27+
pub precipitation_probability: Vec<i32>,
2528
}
2629

2730
#[derive(Debug, Clone, PartialEq, Deserialize, Default)]
@@ -50,7 +53,13 @@ async fn fetch_weather(coordinates: Coordinates) -> WeatherApiData {
5053
],
5154
[
5255
"hourly",
53-
&["temperature_2m", "precipitation", "uv_index"].join(","),
56+
&[
57+
"temperature_2m",
58+
"precipitation",
59+
"uv_index",
60+
"precipitation_probability",
61+
]
62+
.join(","),
5463
],
5564
[
5665
"daily",
@@ -117,64 +126,85 @@ pub async fn set_weather(api: Api<'_>) {
117126
});
118127

119128
let daily = api_data.daily.clone();
129+
let hourly = api_data.hourly.clone();
120130

121131
let mut weather_daily: Vec<WeatherDaily> = vec![];
122132

123-
api_data
124-
.daily
125-
.time
126-
.iter()
127-
.enumerate()
128-
.for_each(|(i, time)| {
129-
let api_date = DateTime::parse_from_rfc3339(&format!("{time}T00:00:00{offset_hours}"));
133+
daily.time.iter().enumerate().for_each(|(i, time)| {
134+
let api_date = DateTime::parse_from_rfc3339(&format!("{time}T00:00:00{offset_hours}"));
135+
136+
let mut date = Date::default();
137+
let mut week_day: i32 = 0;
138+
if let Ok(d) = api_date {
139+
date.year = d.year() as i32;
140+
date.month = d.month() as i32;
141+
date.day = d.day() as i32;
142+
week_day = d.weekday().num_days_from_monday() as i32;
143+
}
144+
145+
let mut sunrise = Time::default();
146+
let api_sunrise = DateTime::parse_from_rfc3339(&format!(
147+
"{}:00{offset_hours}",
148+
api_data.daily.sunrise[i]
149+
));
150+
if let Ok(t) = api_sunrise {
151+
sunrise.hour = t.hour() as i32;
152+
sunrise.minute = t.minute() as i32;
153+
sunrise.second = t.second() as i32;
154+
}
155+
156+
let api_sunset =
157+
DateTime::parse_from_rfc3339(&format!("{}:00{offset_hours}", api_data.daily.sunset[i]));
158+
159+
let mut sunset = Time::default();
160+
161+
if let Ok(t) = api_sunset {
162+
sunset.hour = t.hour() as i32;
163+
sunset.minute = t.minute() as i32;
164+
sunset.second = t.second() as i32;
165+
}
166+
167+
weather_daily.push(WeatherDaily {
168+
weather_type: code_to_type(daily.weather_code[i]),
169+
week_day: week_day,
170+
temperature_max: daily.temperature_2m_max[i] as i32,
171+
temperature_min: daily.temperature_2m_min[i] as i32,
172+
precipitation_sum: daily.precipitation_sum[i] as i32,
173+
precipitation_probability_max: daily.precipitation_probability_max[i],
174+
date: date,
175+
sunrise: sunrise,
176+
sunset: sunset,
177+
});
178+
});
130179

180+
api.set_weather_daily(VecModel::from_slice(&weather_daily));
181+
182+
let mut weather_hourly: Vec<WeatherHourly> = vec![];
183+
hourly.time.iter().enumerate().for_each(|(i, time)| {
184+
// Time example: "2025-08-09T00:00"
185+
let api_date = DateTime::parse_from_rfc3339(&format!("{time}:00{offset_hours}"));
186+
let current_time = Local::now();
187+
188+
if api_date.is_ok() && api_date.unwrap() >= current_time {
131189
let mut date = Date::default();
132-
let mut week_day: i32 = 0;
190+
let mut time = Time::default();
133191
if let Ok(d) = api_date {
134192
date.year = d.year() as i32;
135193
date.month = d.month() as i32;
136194
date.day = d.day() as i32;
137-
week_day = d.weekday().num_days_from_monday() as i32;
138-
}
139-
140-
let mut sunrise = Time::default();
141-
let api_sunrise = DateTime::parse_from_rfc3339(&format!(
142-
"{}:00{offset_hours}",
143-
api_data.daily.sunrise[i]
144-
));
145-
if let Ok(t) = api_sunrise {
146-
sunrise.hour = t.hour() as i32;
147-
sunrise.minute = t.minute() as i32;
148-
sunrise.second = t.second() as i32;
149-
}
150-
151-
let api_sunset = DateTime::parse_from_rfc3339(&format!(
152-
"{}:00{offset_hours}",
153-
api_data.daily.sunset[i]
154-
));
155-
156-
let mut sunset = Time::default();
157-
158-
if let Ok(t) = api_sunset {
159-
sunset.hour = t.hour() as i32;
160-
sunset.minute = t.minute() as i32;
161-
sunset.second = t.second() as i32;
195+
time.hour = d.hour() as i32;
196+
time.minute = d.minute() as i32;
162197
}
163198

164-
weather_daily.push(WeatherDaily {
165-
weather_type: code_to_type(daily.weather_code[i]),
166-
week_day: week_day,
167-
temperature_max: daily.temperature_2m_max[i] as i32,
168-
temperature_min: daily.temperature_2m_min[i] as i32,
169-
precipitation_sum: daily.precipitation_sum[i] as i32,
170-
precipitation_probability_max: daily.precipitation_probability_max[i],
199+
weather_hourly.push(WeatherHourly {
200+
temperature: hourly.temperature_2m[i] as i32,
201+
precipitation_mm: hourly.precipitation[i],
171202
date: date,
172-
sunrise: sunrise,
173-
sunset: sunset,
203+
time: time,
174204
});
175-
});
176-
177-
api.set_weather_daily(VecModel::from_slice(&weather_daily));
205+
}
206+
});
207+
api.set_weather_hourly(VecModel::from_slice(&weather_hourly));
178208

179209
let now = Local::now();
180210
let mut time = Time::default();

ui/api.slint

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ export struct WeatherDaily {
3535
sunset: Time,
3636
}
3737

38+
export struct WeatherHourly {
39+
temperature: int,
40+
precipitation_mm: float,
41+
date: Date,
42+
time: Time,
43+
}
3844
export struct WeatherCurrent {
3945
temperature: int,
4046
precipitation: int,
@@ -49,6 +55,51 @@ export global Api {
4955

5056
in-out property <WeatherCurrent> weather-current;
5157

58+
in-out property <[WeatherHourly]> weather-hourly: [
59+
{
60+
temperature: 10,
61+
precipitation_mm: 0.2,
62+
time: { hour: 16, minute: 0, second: 0 },
63+
date: { year: 2025, month: 1, day: 1 }
64+
},
65+
{
66+
temperature: 13,
67+
precipitation_mm: 0,
68+
time: { hour: 17, minute: 0, second: 0 },
69+
date: { year: 2025, month: 1, day: 1 }
70+
},
71+
{
72+
temperature: 13,
73+
precipitation_mm: 0,
74+
time: { hour: 18, minute: 0, second: 0 },
75+
date: { year: 2025, month: 1, day: 1 }
76+
},
77+
{
78+
temperature: 14,
79+
precipitation_mm: 0,
80+
time: { hour: 19, minute: 0, second: 0 },
81+
date: { year: 2025, month: 1, day: 1 }
82+
},
83+
{
84+
temperature: 11,
85+
precipitation_mm: 0,
86+
time: { hour: 20, minute: 0, second: 0 },
87+
date: { year: 2025, month: 1, day: 1 }
88+
},
89+
{
90+
temperature: 12,
91+
precipitation_mm: 0,
92+
time: { hour: 21, minute: 0, second: 0 },
93+
date: { year: 2025, month: 1, day: 1 }
94+
},
95+
{
96+
temperature: 10,
97+
precipitation_mm: 0,
98+
time: { hour: 22, minute: 0, second: 0 },
99+
date: { year: 2025, month: 1, day: 1 }
100+
},
101+
];
102+
52103
in-out property <[WeatherDaily]> weather-daily: [
53104
{
54105
week-day: 1,

ui/app.slint

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import { Time } from "components/time.slint";
44
import { Bins } from "components/bins.slint";
55
import { HomePage } from "./pages/home_page.slint";
66
import { SettingsPage } from "pages/settings_page.slint";
7+
import { AppFonts } from "common.slint";
78

89
export {Api}
910

1011

1112
export component App inherits Window {
13+
14+
default-font-family: AppFonts.default-font-name;
1215
width: 800px;
1316
height: 480px;
1417

File renamed without changes.
File renamed without changes.

ui/assets/OpenSans-Bold.ttf

128 KB
Binary file not shown.

ui/assets/OpenSans-Regular.ttf

128 KB
Binary file not shown.

ui/common.slint

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
import "../assets/Font Awesome 7 Free-Regular-400.otf";
2+
import "../assets/Font Awesome 7 Free-Solid-900.otf";
3+
import "../assets/OpenSans-Bold.ttf";
4+
import "../assets/OpenSans-Regular.ttf";
5+
6+
export global AppFonts {
7+
out property <string> default-font-name: "Open Sans";
8+
out property <string> icon-font-name: "Font Awesome 7 Free";
9+
}
110

211
export global Utils {
312
public pure function add-number-prefix(number: int) -> string {

ui/components/bins.slint

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import "../Font Awesome 7 Free-Regular-400.otf";
2-
import { Palette, Style } from "../common.slint";
1+
import { Palette, Style, AppFonts } from "../common.slint";
32

43

54
component Bin {
65
in property <color> color;
76
Text {
87
font-size: 48px;
9-
font-family: "Font Awesome 6 Free";
8+
font-family: AppFonts.icon-font-name;
109
color: color;
1110
text: @tr(""); // https://fontawesome.com/icons/trash-can?f=classic&s=regular
1211
}
@@ -18,7 +17,7 @@ export component Bins {
1817

1918
HorizontalLayout {
2019
alignment: start;
21-
spacing: 16px;
20+
spacing: 24px;
2221

2322
Bin {
2423
color: red;

0 commit comments

Comments
 (0)