mirror of
https://github.com/skoelle/wt32sc01-dashboard.git
synced 2026-09-17 17:30:25 +00:00
calender and weather UI updates
This commit is contained in:
@@ -63,4 +63,23 @@ inline String formatShortDE(const String &iso, bool allDay) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Date-only column text, e.g. "Mo 3.8." (used in the calendar detail table).
|
||||||
|
inline String formatDateDE(const String &iso) {
|
||||||
|
ParsedDateTime p = parseIso(iso);
|
||||||
|
if (!p.valid) return iso;
|
||||||
|
int wd = computeWeekdayMonBased(p.year, p.month, p.day);
|
||||||
|
return String(weekdayShortDE(wd)) + " " + String(p.day) + "." + String(p.month) + ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time-only column text, e.g. "14:00". Returns "-" for all-day events so the
|
||||||
|
// table row keeps a consistent column structure.
|
||||||
|
inline String formatTimeDE(const String &iso, bool allDay) {
|
||||||
|
if (allDay) return "-";
|
||||||
|
ParsedDateTime p = parseIso(iso);
|
||||||
|
if (!p.valid) return "";
|
||||||
|
char buf[8];
|
||||||
|
snprintf(buf, sizeof(buf), "%02d:%02d", p.hour, p.minute);
|
||||||
|
return String(buf);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace DateUtils
|
} // namespace DateUtils
|
||||||
|
|||||||
@@ -26,23 +26,37 @@ void buildList() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Columns (content width = 280 - 2*6 pad = 268):
|
||||||
|
// date 88 px left | time 56 px centered @94 | summary 112 px @156
|
||||||
for (const auto &ev : lastCalendar.events) {
|
for (const auto &ev : lastCalendar.events) {
|
||||||
lv_obj_t *row = lv_obj_create(list);
|
lv_obj_t *row = lv_obj_create(list);
|
||||||
lv_obj_set_size(row, 280, LV_SIZE_CONTENT);
|
lv_obj_set_size(row, 280, LV_SIZE_CONTENT);
|
||||||
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, 0);
|
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, 0);
|
||||||
lv_obj_set_style_border_width(row, 0, 0);
|
lv_obj_set_style_border_width(row, 1, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_side(row, LV_BORDER_SIDE_BOTTOM, 0);
|
||||||
|
lv_obj_set_style_border_color(row, Theme::bgCard(), 0);
|
||||||
lv_obj_set_style_pad_all(row, 6, 0);
|
lv_obj_set_style_pad_all(row, 6, 0);
|
||||||
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
|
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
|
|
||||||
|
lv_obj_t *date = lv_label_create(row);
|
||||||
|
lv_label_set_text(date, DateUtils::formatDateDE(ev.startAt).c_str());
|
||||||
|
lv_obj_set_style_text_color(date, Theme::textDim(), 0);
|
||||||
|
lv_obj_set_width(date, 88);
|
||||||
|
lv_obj_align(date, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||||
|
|
||||||
|
lv_obj_t *time = lv_label_create(row);
|
||||||
|
lv_label_set_text(time, DateUtils::formatTimeDE(ev.startAt, ev.allDay).c_str());
|
||||||
|
lv_obj_set_style_text_color(time, Theme::accentCalendar(), 0);
|
||||||
|
lv_obj_set_style_text_align(time, LV_TEXT_ALIGN_CENTER, 0);
|
||||||
|
lv_obj_set_width(time, 56);
|
||||||
|
lv_obj_align(time, LV_ALIGN_TOP_LEFT, 94, 0);
|
||||||
|
|
||||||
lv_obj_t *sum = lv_label_create(row);
|
lv_obj_t *sum = lv_label_create(row);
|
||||||
lv_label_set_text(sum, sanitizeGermanText(ev.summary.substring(0, 30)).c_str());
|
lv_label_set_text(sum, sanitizeGermanText(ev.summary.substring(0, 30)).c_str());
|
||||||
lv_obj_set_style_text_color(sum, Theme::text(), 0);
|
lv_obj_set_style_text_color(sum, Theme::text(), 0);
|
||||||
lv_obj_align(sum, LV_ALIGN_TOP_LEFT, 0, 0);
|
lv_label_set_long_mode(sum, LV_TEXT_LONG_DOT);
|
||||||
|
lv_obj_set_width(sum, 112);
|
||||||
lv_obj_t *when = lv_label_create(row);
|
lv_obj_align(sum, LV_ALIGN_TOP_LEFT, 156, 0);
|
||||||
lv_label_set_text(when, DateUtils::formatShortDE(ev.startAt, ev.allDay).c_str());
|
|
||||||
lv_obj_set_style_text_color(when, Theme::accentCalendar(), 0);
|
|
||||||
lv_obj_align(when, LV_ALIGN_TOP_LEFT, 0, 20);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,42 +25,67 @@ void buildList() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header row with current conditions.
|
// Header row with column titles.
|
||||||
String header = String(lastWeather.current.temperature) + " C " +
|
lv_obj_t *header = lv_label_create(list);
|
||||||
sanitizeGermanText(lastWeather.current.description);
|
lv_label_set_text(header, "Icon Uhrzeit Grad Text Regen %");
|
||||||
lv_obj_t *h = lv_label_create(list);
|
lv_obj_set_style_text_font(header, &lv_font_montserrat_12, 0);
|
||||||
lv_label_set_text(h, header.c_str());
|
lv_obj_set_style_text_color(header, Theme::text(), 0);
|
||||||
lv_obj_set_style_text_font(h, &lv_font_montserrat_20, 0);
|
|
||||||
lv_obj_set_style_text_color(h, Theme::text(), 0);
|
// Separator line below header.
|
||||||
|
lv_obj_t *header_line = lv_line_create(list);
|
||||||
|
static lv_point_t header_points[] = {{0, 0}, {280, 0}};
|
||||||
|
lv_line_set_points(header_line, header_points, 2);
|
||||||
|
lv_obj_set_style_line_color(header_line, Theme::textDim(), 0);
|
||||||
|
lv_obj_set_style_line_width(header_line, 1, 0);
|
||||||
|
|
||||||
for (const auto &fe : lastWeather.forecast) {
|
for (const auto &fe : lastWeather.forecast) {
|
||||||
lv_obj_t *row = lv_obj_create(list);
|
lv_obj_t *row = lv_obj_create(list);
|
||||||
lv_obj_set_size(row, 280, LV_SIZE_CONTENT);
|
lv_obj_set_size(row, 280, 30);
|
||||||
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, 0);
|
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, 0);
|
||||||
lv_obj_set_style_border_width(row, 0, 0);
|
lv_obj_set_style_border_width(row, 0, 0);
|
||||||
lv_obj_set_style_pad_all(row, 6, 0);
|
lv_obj_set_style_pad_all(row, 4, 0);
|
||||||
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
|
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
|
|
||||||
// time hh:mm
|
// time hh:mm
|
||||||
int tIdx = fe.time.indexOf('T');
|
int tIdx = fe.time.indexOf('T');
|
||||||
String hhmm = tIdx > 0 ? fe.time.substring(tIdx + 1, tIdx + 6) : fe.time;
|
String hhmm = tIdx > 0 ? fe.time.substring(tIdx + 1, tIdx + 6) : fe.time;
|
||||||
|
|
||||||
String left = hhmm + " " + String(fe.temperature) + "C";
|
// icon - use weather symbol
|
||||||
lv_obj_t *l = lv_label_create(row);
|
lv_obj_t *icon = Icons::createWeatherIcon(row, fe.symbol, fe.description, 24);
|
||||||
lv_label_set_text(l, left.c_str());
|
|
||||||
lv_obj_set_style_text_color(l, Theme::text(), 0);
|
|
||||||
lv_obj_align(l, LV_ALIGN_TOP_LEFT, 0, 0);
|
|
||||||
|
|
||||||
String desc = sanitizeGermanText(fe.description.substring(0, 16));
|
// time column
|
||||||
|
lv_obj_t *time_label = lv_label_create(row);
|
||||||
|
lv_label_set_text(time_label, hhmm.c_str());
|
||||||
|
lv_obj_set_style_text_color(time_label, Theme::text(), 0);
|
||||||
|
lv_obj_align(time_label, LV_ALIGN_TOP_LEFT, 44, 0);
|
||||||
|
|
||||||
|
// degree column
|
||||||
|
lv_obj_t *temp_label = lv_label_create(row);
|
||||||
|
lv_label_set_text(temp_label, String(fe.temperature) + "C");
|
||||||
|
lv_obj_set_style_text_color(temp_label, Theme::text(), 0);
|
||||||
|
lv_obj_align(temp_label, LV_ALIGN_TOP_LEFT, 160, 0);
|
||||||
|
|
||||||
|
// text column
|
||||||
|
String desc = sanitizeGermanText(fe.description.substring(0, 20));
|
||||||
if (fe.precipitationType == "rain" && fe.precipitationProbability > 0.0f) {
|
if (fe.precipitationType == "rain" && fe.precipitationProbability > 0.0f) {
|
||||||
char buf[8];
|
char buf[8];
|
||||||
snprintf(buf, sizeof(buf), " %.0f%%", fe.precipitationProbability * 100);
|
snprintf(buf, sizeof(buf), " %.0f%%", fe.precipitationProbability * 100);
|
||||||
desc += buf;
|
desc += buf;
|
||||||
}
|
}
|
||||||
lv_obj_t *d = lv_label_create(row);
|
lv_obj_t *desc_label = lv_label_create(row);
|
||||||
lv_label_set_text(d, desc.c_str());
|
lv_label_set_text(desc_label, desc.c_str());
|
||||||
lv_obj_set_style_text_color(d, Theme::textDim(), 0);
|
lv_obj_set_style_text_color(desc_label, Theme::textDim(), 0);
|
||||||
lv_obj_align(d, LV_ALIGN_TOP_LEFT, 0, 18);
|
lv_obj_align(desc_label, LV_ALIGN_TOP_LEFT, 220, 0);
|
||||||
|
|
||||||
|
// rain probability column - show percentage for rain
|
||||||
|
if (fe.precipitationType == "rain" && fe.precipitationProbability > 0.0f) {
|
||||||
|
char buf[8];
|
||||||
|
snprintf(buf, sizeof(buf), "%.0f%%", fe.precipitationProbability * 100);
|
||||||
|
lv_obj_t *rain_label = lv_label_create(row);
|
||||||
|
lv_label_set_text(rain_label, buf);
|
||||||
|
lv_obj_set_style_text_color(rain_label, Theme::accentRain(), 0);
|
||||||
|
lv_obj_align(rain_label, LV_ALIGN_TOP_LEFT, 260, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user