Skip to content

Commit 7aebb0b

Browse files
author
Ruslan
committed
Got the current and weekly working
1 parent 21d66fb commit 7aebb0b

14 files changed

Lines changed: 290 additions & 66 deletions

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ gloo-net = "0.6.0"
1616
gloo-storage = "0.3.0"
1717
reqwest = { version = "0.12.22", features = ["json"] }
1818
serde = { version = "1.0.217", features = ["derive"] }
19-
serde_json = "1.0.140"
19+
serde_json = "1.0.141"
2020
serde_urlencoded = "0.7.1"
2121
slint = { version = "1.12.1", features = ["gettext"] }
2222
wasm-bindgen = "0.2.100"

src/weather.rs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use chrono::{DateTime, Datelike, Timelike};
1+
use chrono::{DateTime, Datelike, Local, Timelike};
22
use serde::Deserialize;
33
use slint::VecModel;
44

5-
use crate::{Api, Coordinates, Date, Time, WeatherDaily};
5+
use crate::{Api, Coordinates, Date, Time, WeatherCurrent, WeatherDaily, WeatherType};
66

77
#[derive(Debug, Clone, PartialEq, Deserialize, Default)]
88
pub struct WeatherApiDaily {
@@ -24,8 +24,16 @@ pub struct WeatherApiHourly {
2424
pub uv_index: Vec<f32>,
2525
}
2626

27+
#[derive(Debug, Clone, PartialEq, Deserialize, Default)]
28+
pub struct WeatherApiCurrent {
29+
pub temperature_2m: f32,
30+
pub precipitation: f32,
31+
pub weather_code: i32,
32+
}
33+
2734
#[derive(Debug, Clone, PartialEq, Deserialize, Default)]
2835
struct WeatherApiData {
36+
current: WeatherApiCurrent,
2937
daily: WeatherApiDaily,
3038
hourly: WeatherApiHourly,
3139
utc_offset_seconds: i32,
@@ -36,6 +44,10 @@ async fn fetch_weather(coordinates: Coordinates) -> WeatherApiData {
3644
["latitude", &coordinates.latitude.to_string()],
3745
["longitude", &coordinates.longitude.to_string()],
3846
["timezone", &"auto".to_string()],
47+
[
48+
"current",
49+
&["temperature_2m", "weather_code", "precipitation"].join(","),
50+
],
3951
[
4052
"hourly",
4153
&["temperature_2m", "precipitation", "uv_index"].join(","),
@@ -69,6 +81,24 @@ async fn fetch_weather(coordinates: Coordinates) -> WeatherApiData {
6981
return data;
7082
}
7183

84+
fn code_to_type(code: i32) -> WeatherType {
85+
return match code {
86+
0 | 1 => WeatherType::Sunny,
87+
2 | 3 => WeatherType::Cloudy,
88+
45 | 48 => WeatherType::Fog,
89+
51 | 53 | 55 => WeatherType::Sprinkle,
90+
56 | 57 => WeatherType::Snow,
91+
61 | 63 | 65 => WeatherType::RainDrop,
92+
66 | 67 => WeatherType::RainMix,
93+
71 | 73 | 75 => WeatherType::SnowflakeCold,
94+
77 => WeatherType::SnowWind,
95+
80 | 81 | 82 => WeatherType::Rain,
96+
85 | 86 => WeatherType::SnowThunderstorm,
97+
95 | 96 | 99 => WeatherType::Thunderstorm,
98+
_ => WeatherType::Other,
99+
};
100+
}
101+
72102
pub async fn set_weather(api: Api<'_>) {
73103
let coordinates = api.get_coordinates();
74104
if coordinates.latitude == 0.0 || coordinates.longitude == 0.0 {
@@ -80,6 +110,12 @@ pub async fn set_weather(api: Api<'_>) {
80110
let offset_sec = api_data.utc_offset_seconds / 60 / 60;
81111
let offset_hours = format!("+{offset_sec}:00");
82112

113+
api.set_weather_current(WeatherCurrent {
114+
temperature: api_data.current.temperature_2m,
115+
precipitation: api_data.current.precipitation,
116+
weather_type: code_to_type(api_data.current.weather_code),
117+
});
118+
83119
let daily = api_data.daily.clone();
84120

85121
let mut weather_daily: Vec<WeatherDaily> = vec![];
@@ -93,10 +129,12 @@ pub async fn set_weather(api: Api<'_>) {
93129
let api_date = DateTime::parse_from_rfc3339(&format!("{time}T00:00:00{offset_hours}"));
94130

95131
let mut date = Date::default();
132+
let mut week_day: i32 = 0;
96133
if let Ok(d) = api_date {
97134
date.year = d.year() as i32;
98135
date.month = d.month() as i32;
99136
date.day = d.day() as i32;
137+
week_day = d.weekday().num_days_from_monday() as i32;
100138
}
101139

102140
let mut sunrise = Time::default();
@@ -124,10 +162,11 @@ pub async fn set_weather(api: Api<'_>) {
124162
}
125163

126164
weather_daily.push(WeatherDaily {
127-
weather_code: daily.weather_code[i],
128-
temperature_max: daily.temperature_2m_max[i],
129-
temperature_min: daily.temperature_2m_min[i],
130-
precipitation_sum: daily.precipitation_sum[i],
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,
131170
precipitation_probability_max: daily.precipitation_probability_max[i],
132171
date: date,
133172
sunrise: sunrise,
@@ -136,4 +175,11 @@ pub async fn set_weather(api: Api<'_>) {
136175
});
137176

138177
api.set_weather_daily(VecModel::from_slice(&weather_daily));
178+
179+
let now = Local::now();
180+
let mut time = Time::default();
181+
time.hour = now.hour() as i32;
182+
time.minute = now.minute() as i32;
183+
time.second = now.second() as i32;
184+
api.set_weather_updated_at(time);
139185
}
85.3 KB
Binary file not shown.
401 KB
Binary file not shown.

ui/api.slint

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,83 @@ import { Date, Time } from "std-widgets.slint";
22

33
export enum Pages { home, settings }
44

5+
export enum WeatherType {
6+
sunny,
7+
cloudy,
8+
fog,
9+
sprinkle,
10+
snow,
11+
rain-drop,
12+
rain-mix,
13+
snowflake-cold,
14+
snow-wind,
15+
rain,
16+
snow-thunderstorm,
17+
thunderstorm,
18+
other,
19+
}
20+
521
export struct Coordinates {
622
longitude: float,
723
latitude: float,
824
}
925

1026
export struct WeatherDaily {
11-
temperature_max: float,
12-
temperature_min: float,
27+
temperature_max: int,
28+
temperature_min: int,
1329
date: Date,
14-
precipitation_sum: float,
30+
week_day: int,
31+
precipitation_sum: int,
1532
precipitation_probability_max: int,
16-
weather_code: int,
33+
weather_type: WeatherType,
1734
sunrise: Time,
1835
sunset: Time,
1936
}
2037

38+
export struct WeatherCurrent {
39+
temperature: float,
40+
precipitation: float,
41+
weather_type: WeatherType,
42+
}
43+
2144
export global Api {
2245
in-out property <Pages> current-page: Pages.home;
2346

2447
in-out property <bool> is-yellow-bin: true;
2548
in-out property <int> days-to-bin: 0;
2649

27-
in-out property <[WeatherDaily]> weather-daily;
50+
in-out property <WeatherCurrent> weather-current;
51+
52+
in-out property <[WeatherDaily]> weather-daily: [
53+
{
54+
week-day: 1,
55+
temperature_max: 25,
56+
temperature_min: 0,
57+
date: { year: 2025, month: 3, day: 18 },
58+
precipitation_sum: 0.8,
59+
precipitation_probability_max: 23,
60+
weather_type: WeatherType.rain,
61+
sunrise: { hour: 6, minute: 55, second: 0 },
62+
sunset: { hour: 17, minute: 10, second: 0 },
63+
},
64+
{
65+
week-day: 2,
66+
temperature_max: 25,
67+
temperature_min: 10,
68+
date: { year: 2025, month: 3, day: 18 },
69+
precipitation_sum: 0,
70+
precipitation_probability_max: 0,
71+
weather_type: WeatherType.rain,
72+
sunrise: { hour: 6, minute: 55, second: 0 },
73+
sunset: { hour: 17, minute: 10, second: 0 },
74+
}
75+
];
76+
77+
in-out property <Time> weather-updated-at: {
78+
hour: 15,
79+
minute: 12,
80+
second: 33,
81+
};
2882

2983
in-out property <Coordinates> coordinates: {
3084
latitude: 0,

ui/common.slint

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1-
// Copyright © SixtyFPS GmbH <info@slint.dev>
2-
// SPDX-License-Identifier: MIT
1+
2+
export global Utils {
3+
public pure function add-number-prefix(number: int) -> string {
4+
if (number <= 9) {
5+
return "0" + number;
6+
} else {
7+
return number;
8+
}
9+
}
10+
}
311

412
export global Measurements {
513
out property <length> zone-button-spacing: 30px;
@@ -22,19 +30,12 @@ export global Measurements {
2230
}
2331

2432
export global Style {
25-
out property <length> icon-title-font-size: 10px;
2633
out property <length> normal-font-size: 12px;
2734
out property <length> H1-font-size: 46px;
2835
out property <length> H2-font-size: 21px;
2936
out property <length> H3-font-size: 18px;
3037
out property <length> H4-font-size: 15px;
3138
out property <length> tile-title-font-size: 13pt;
32-
out property <length> hvac-title-font-size: 13pt;
33-
}
34-
35-
export global Animation {
36-
out property <duration> full-screen-duration: 300ms;
37-
out property <duration> transition-duration: 500ms;
3839
}
3940

4041
export global Colors {

ui/components/bins.slint

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import "../fa-regular-400.ttf";
1+
import "../Font Awesome 7 Free-Regular-400.otf";
22
import { Palette, Style } from "../common.slint";
33

44

@@ -16,31 +16,27 @@ export component Bins {
1616
in property <bool> is-yellow-bin;
1717
in property <int> days-to-bin;
1818

19-
VerticalLayout {
19+
HorizontalLayout {
2020
alignment: start;
21+
spacing: 16px;
2122

22-
HorizontalLayout {
23-
alignment: start;
24-
spacing: 8px;
25-
26-
Bin {
27-
color: red;
28-
}
23+
Bin {
24+
color: red;
25+
}
2926

30-
Bin {
31-
color: green;
32-
}
27+
Bin {
28+
color: green;
29+
}
3330

34-
if(is-yellow-bin): Bin {
35-
color: yellow;
36-
}
31+
if(is-yellow-bin): Bin {
32+
color: yellow;
33+
}
3734

38-
Text {
39-
text: days-to-bin == 0 ? "BIN DAY TODAY" : "Days " + days-to-bin;
40-
vertical-alignment: center;
41-
color: Palette.info-foreground;
42-
font-size: Style.H2-font-size;
43-
}
35+
Text {
36+
text: days-to-bin == 0 ? "BIN DAY TODAY" : "Days " + days-to-bin;
37+
vertical-alignment: center;
38+
color: Palette.info-foreground;
39+
font-size: Style.H2-font-size;
4440
}
4541
}
4642
}

ui/components/time.slint

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
1-
import { Palette, Style } from "../common.slint";
1+
import { Palette, Style, Utils } from "../common.slint";
22
import { Date, Time } from "std-widgets.slint";
33

44
export component Time {
55

66
in property <Time> time;
77
in property <Date> date;
88

9-
function add-number-prefix(number: int) -> string {
10-
if (number <= 9) {
11-
return "0" + number;
12-
} else {
13-
return number;
14-
}
15-
}
16-
179
// I feel like this should be a UI layer, backend just gives us a date object
1810
function get-month(month: int) -> string {
1911
if (month == 1) {
@@ -48,7 +40,7 @@ export component Time {
4840
VerticalLayout {
4941
alignment: start;
5042
Text {
51-
text: time.hour + ":" + add-number-prefix(time.minute);
43+
text: time.hour + ":" + Utils.add-number-prefix(time.minute);
5244
horizontal-alignment: right;
5345
vertical-alignment: top;
5446
color: Palette.info-foreground;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { WeatherCurrent } from "../api.slint";
2+
import { Style } from "../common.slint";
3+
import { WeatherIcon } from "./weather_icon.slint";
4+
5+
export component WeatherCurrent {
6+
in property <WeatherCurrent> current;
7+
8+
VerticalLayout {
9+
alignment: start;
10+
HorizontalLayout {
11+
alignment: center;
12+
13+
Text {
14+
text: current.temperature;
15+
font-size: Style.H1-font-size;
16+
}
17+
18+
Text {
19+
text: "°C";
20+
font-size: Style.H2-font-size;
21+
vertical-alignment: center;
22+
}
23+
}
24+
25+
WeatherIcon {
26+
horizontal-alignment: center;
27+
font-size: Style.H1-font-size;
28+
type: current.weather-type;
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)