Keep the news at the end of a tile's line: a shorter "Yest. 9:15 PM" and a robot's battery that stays
A tile has one line under the name, and LVGL cuts what doesn't fit off the end, which is where that line often carries what you want to read. Two lines lost it: - "Yesterday 9:15 PM" (English with a 12-hour clock) read "Yesterday 9:1…" on both boards. The tile now takes a shorter wording of the same line when the full one doesn't fit, screen.script.yesterday_time_short; every language whose word is short enough keeps the same text there. - A robot's battery stood behind Home Assistant's own word for its state, so German, French and Polish showed "Angedockt / 10…". The battery keeps its room now and the word takes the dots: "Angedo… / 10 %". `tools/i18n.py check` measures a tile line with a 12-hour clock in its placeholder, so a translation that is too long for the line fails there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,7 +99,7 @@ inline void refresh_detail(unsigned index);
|
||||
inline const char *weather_icon(const std::string &condition);
|
||||
inline const char *weather_text(const std::string &condition);
|
||||
inline std::string timer_text(const Tile &t);
|
||||
inline std::string last_run_text(uint32_t epoch);
|
||||
inline std::string last_run_text(uint32_t epoch, bool compact = false);
|
||||
// "07:12": a time of day as Home Assistant and ESP Screens send it, for screen_text::clock_text.
|
||||
inline std::string hhmm(const esphome::ESPTime &time) {
|
||||
char b[8]; snprintf(b, sizeof(b), "%02d:%02d", time.hour, time.minute);
|
||||
@@ -1204,6 +1204,31 @@ inline lv_obj_t *detail_shape(lv_obj_t *parent,int x,int y,int w,int h,theme::Ro
|
||||
inline int text_width(const std::string &text,const lv_font_t *font){
|
||||
lv_point_t size;lv_text_get_size(&size,text.c_str(),font,0,0,LV_COORD_MAX,LV_TEXT_FLAG_NONE);return size.x;
|
||||
}
|
||||
// The status line under a tile's name, once its room is known. LVGL cuts the end of a line that doesn't fit, which
|
||||
// is where this line carries its news, so (firmware 0.2.76+):
|
||||
// `shorter` another wording of the whole line, taken when the full one doesn't fit ("Yest. 9:15 PM");
|
||||
// `tail` the end that has to stay readable (a robot's battery): the words in front of it take the dots,
|
||||
// "Angedockt / 10 %" becomes "Angedo… / 10 %".
|
||||
// A line that fits, or a room too small for the tail itself, is left to LVGL as before.
|
||||
inline void fit_value(lv_obj_t *obj,const std::string &value,const std::string &shorter,const std::string &tail,int room){
|
||||
const lv_font_t *font=lv_obj_get_style_text_font(obj,LV_PART_MAIN);
|
||||
if(!font||room<=0||text_width(value,font)<=room)return;
|
||||
if(!shorter.empty()&&shorter!=value&&text_width(shorter,font)<=room){label(obj,shorter);return;}
|
||||
if(tail.empty()||value.size()<=tail.size())return;
|
||||
static const std::string dots="…";
|
||||
const int head_room=room-text_width(dots+tail,font);
|
||||
if(head_room<=0)return;
|
||||
const std::string head=value.substr(0,value.size()-tail.size());
|
||||
std::string cut;
|
||||
for(size_t i=0;i<head.size();){
|
||||
size_t next=i+1;
|
||||
while(next<head.size()&&(static_cast<unsigned char>(head[next])&0xC0)==0x80)++next;
|
||||
if(text_width(head.substr(0,next),font)>head_room)break;
|
||||
cut=head.substr(0,next);i=next;
|
||||
}
|
||||
while(!cut.empty()&&cut.back()==' ')cut.pop_back();
|
||||
label(obj,cut+dots+tail);
|
||||
}
|
||||
// The state colour, as Home Assistant colours a vacuum: teal while cleaning, blue on the way back, amber
|
||||
// when paused, red on an error; a docked or idle robot keeps the card's own blue. `tint` is the halo.
|
||||
struct VacuumLook { uint32_t accent, tint; };
|
||||
@@ -2187,16 +2212,18 @@ inline std::string countdown(uint32_t seconds) {
|
||||
return b;
|
||||
}
|
||||
// "Last 14:32" today, "Yesterday 14:32", else "Last 13 Sep", in the screen's language; scripts and scenes have no
|
||||
// useful on/off.
|
||||
// useful on/off. `compact` takes the short wording of yesterday a tile has room for ("Yest. 9:15 PM"); every
|
||||
// language that needs no shorter word keeps the same text there.
|
||||
inline std::string month_short(const esphome::ESPTime &now);
|
||||
inline std::string last_run_text(uint32_t epoch) {
|
||||
inline std::string last_run_text(uint32_t epoch, bool compact) {
|
||||
if (!epoch) return tr(txt::script_never_run);
|
||||
auto when = esphome::ESPTime::from_epoch_local(epoch);
|
||||
auto now = now_time ? now_time() : esphome::ESPTime{};
|
||||
if (!when.is_valid()) return tr(txt::script_never_run);
|
||||
std::string clock = screen_text::clock_text(hhmm(when), screen_settings::current.clock_24h != 0);
|
||||
if (now.is_valid() && now.year == when.year && now.day_of_year == when.day_of_year) return fill(txt::script_last_time, "time", clock);
|
||||
if (now.is_valid() && now.year == when.year && now.day_of_year == when.day_of_year + 1) return fill(txt::script_yesterday_time, "time", clock);
|
||||
if (now.is_valid() && now.year == when.year && now.day_of_year == when.day_of_year + 1)
|
||||
return fill(compact ? txt::script_yesterday_time_short : txt::script_yesterday_time, "time", clock);
|
||||
std::string date = fill(fill(txt::date_day_month, "day", std::to_string(when.day_of_month)), "month", month_short(when));
|
||||
return fill(txt::script_last_date, "date", date);
|
||||
}
|
||||
@@ -3168,10 +3195,14 @@ inline void render_slot(size_t slot) {
|
||||
else if (!t.unit.empty() || d == "number" || d == "input_number" || d == "counter") value = screen_text::localize(value);
|
||||
bool pending=t.loading(esphome::millis());
|
||||
if(d=="weather" && std::isfinite(t.current)) {value=screen_text::decimal(t.current,1);if(!watch)value=screen_text::with_unit(value,t.unit);}
|
||||
if(d=="vacuum" && std::isfinite(t.battery))value += " / "+screen_text::percent((int)t.battery);
|
||||
// What a narrow tile falls back to once its room is known (fit_value): another wording of the whole line, and the
|
||||
// end that must stay readable whatever happens to the words in front of it.
|
||||
std::string value_short,value_tail;
|
||||
if((d=="script"||d=="scene"||d=="button"||d=="input_button") && t.state!="on")value_short=last_run_text(t.last_run,true);
|
||||
if(d=="vacuum" && std::isfinite(t.battery)){value_tail=" / "+screen_text::percent((int)t.battery);value+=value_tail;}
|
||||
// Direct controls: only a wide card in the standard layout has room for the panel.
|
||||
bool with_panel=w.wide && !t.controls.empty() && !t.builtin() && !watch && t.inline_control!="slider" && fresh() && t.available();
|
||||
if(with_panel){std::string status=tile_controls::status_text(t);if(!status.empty())value=status;}
|
||||
if(with_panel){std::string status=tile_controls::status_text(t);if(!status.empty()){value=status;value_short.clear();value_tail.clear();}}
|
||||
label(w.value, value);
|
||||
bool mini=t.inline_control=="slider" && !watch && t.available();
|
||||
bool large_tile=tile_height(w)>80;
|
||||
@@ -3239,7 +3270,9 @@ inline void render_slot(size_t slot) {
|
||||
int chevron_w=t.is_page() && !watch?lv_font_get_line_height(chevron_font):0;
|
||||
if(chevron_w)text_room-=chevron_w+(large_tile?8:4);
|
||||
lv_obj_set_width(w.title,std::max(1,text_room-text_x));
|
||||
lv_obj_set_width(w.value,std::max(1,text_room-(watch?0:(mini||graph_strip)?text_x:w.value_x)));
|
||||
int value_room=std::max(1,text_room-(watch?0:(mini||graph_strip)?text_x:w.value_x));
|
||||
lv_obj_set_width(w.value,value_room);
|
||||
fit_value(w.value,value,value_short,value_tail,value_room);
|
||||
if(watch){
|
||||
int gap=large_tile?6:2,header=std::max(circle_size,title_height);
|
||||
int group_y=std::max(0,(content_h-header-gap-value_height)/2);
|
||||
|
||||
@@ -144,144 +144,145 @@ constexpr uint16_t script_running = 179;
|
||||
constexpr uint16_t script_never_run = 180;
|
||||
constexpr uint16_t script_last_time = 181;
|
||||
constexpr uint16_t script_yesterday_time = 182;
|
||||
constexpr uint16_t script_last_date = 183;
|
||||
constexpr uint16_t camera_no_image = 184;
|
||||
constexpr uint16_t camera_loading = 185;
|
||||
constexpr uint16_t camera_live = 186;
|
||||
constexpr uint16_t camera_recording = 187;
|
||||
constexpr uint16_t camera_tap_to_view = 188;
|
||||
constexpr uint16_t camera_no_image_yet = 189;
|
||||
constexpr uint16_t calibration_title = 190;
|
||||
constexpr uint16_t calibration_touch_check = 191;
|
||||
constexpr uint16_t calibration_hold = 192;
|
||||
constexpr uint16_t calibration_crosshair = 193;
|
||||
constexpr uint16_t calibration_gently = 194;
|
||||
constexpr uint16_t calibration_same = 195;
|
||||
constexpr uint16_t calibration_rejected = 196;
|
||||
constexpr uint16_t calibration_save_failed = 197;
|
||||
constexpr uint16_t ha_on = 198;
|
||||
constexpr uint16_t ha_off = 199;
|
||||
constexpr uint16_t ha_unavailable = 200;
|
||||
constexpr uint16_t ha_climate_off = 201;
|
||||
constexpr uint16_t ha_climate_heat = 202;
|
||||
constexpr uint16_t ha_climate_cool = 203;
|
||||
constexpr uint16_t ha_climate_heat_cool = 204;
|
||||
constexpr uint16_t ha_climate_auto = 205;
|
||||
constexpr uint16_t ha_climate_dry = 206;
|
||||
constexpr uint16_t ha_climate_fan_only = 207;
|
||||
constexpr uint16_t ha_hvac_action_heating = 208;
|
||||
constexpr uint16_t ha_hvac_action_cooling = 209;
|
||||
constexpr uint16_t ha_hvac_action_idle = 210;
|
||||
constexpr uint16_t ha_hvac_action_off = 211;
|
||||
constexpr uint16_t ha_hvac_action_drying = 212;
|
||||
constexpr uint16_t ha_hvac_action_fan = 213;
|
||||
constexpr uint16_t ha_hvac_action_preheating = 214;
|
||||
constexpr uint16_t ha_hvac_action_defrosting = 215;
|
||||
constexpr uint16_t ha_cover_open = 216;
|
||||
constexpr uint16_t ha_cover_closed = 217;
|
||||
constexpr uint16_t ha_cover_opening = 218;
|
||||
constexpr uint16_t ha_cover_closing = 219;
|
||||
constexpr uint16_t ha_media_playing = 220;
|
||||
constexpr uint16_t ha_media_paused = 221;
|
||||
constexpr uint16_t ha_media_idle = 222;
|
||||
constexpr uint16_t ha_media_standby = 223;
|
||||
constexpr uint16_t ha_person_home = 224;
|
||||
constexpr uint16_t ha_person_not_home = 225;
|
||||
constexpr uint16_t ha_sun_above_horizon = 226;
|
||||
constexpr uint16_t ha_sun_below_horizon = 227;
|
||||
constexpr uint16_t ha_vacuum_docked = 228;
|
||||
constexpr uint16_t ha_vacuum_cleaning = 229;
|
||||
constexpr uint16_t ha_vacuum_paused = 230;
|
||||
constexpr uint16_t ha_vacuum_returning = 231;
|
||||
constexpr uint16_t ha_vacuum_idle = 232;
|
||||
constexpr uint16_t ha_weather_sunny = 233;
|
||||
constexpr uint16_t ha_weather_clear_night = 234;
|
||||
constexpr uint16_t ha_weather_cloudy = 235;
|
||||
constexpr uint16_t ha_weather_partlycloudy = 236;
|
||||
constexpr uint16_t ha_weather_rainy = 237;
|
||||
constexpr uint16_t ha_weather_pouring = 238;
|
||||
constexpr uint16_t ha_weather_snowy = 239;
|
||||
constexpr uint16_t ha_weather_snowy_rainy = 240;
|
||||
constexpr uint16_t ha_weather_fog = 241;
|
||||
constexpr uint16_t ha_weather_hail = 242;
|
||||
constexpr uint16_t ha_weather_lightning = 243;
|
||||
constexpr uint16_t ha_weather_lightning_rainy = 244;
|
||||
constexpr uint16_t ha_weather_windy = 245;
|
||||
constexpr uint16_t ha_weather_exceptional = 246;
|
||||
constexpr uint16_t ha_binary_battery_on = 247;
|
||||
constexpr uint16_t ha_binary_battery_off = 248;
|
||||
constexpr uint16_t ha_binary_battery_charging_on = 249;
|
||||
constexpr uint16_t ha_binary_battery_charging_off = 250;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_on = 251;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_off = 252;
|
||||
constexpr uint16_t ha_binary_cold_on = 253;
|
||||
constexpr uint16_t ha_binary_cold_off = 254;
|
||||
constexpr uint16_t ha_binary_connectivity_on = 255;
|
||||
constexpr uint16_t ha_binary_connectivity_off = 256;
|
||||
constexpr uint16_t ha_binary_door_on = 257;
|
||||
constexpr uint16_t ha_binary_door_off = 258;
|
||||
constexpr uint16_t ha_binary_garage_door_on = 259;
|
||||
constexpr uint16_t ha_binary_garage_door_off = 260;
|
||||
constexpr uint16_t ha_binary_gas_on = 261;
|
||||
constexpr uint16_t ha_binary_gas_off = 262;
|
||||
constexpr uint16_t ha_binary_heat_on = 263;
|
||||
constexpr uint16_t ha_binary_heat_off = 264;
|
||||
constexpr uint16_t ha_binary_light_on = 265;
|
||||
constexpr uint16_t ha_binary_light_off = 266;
|
||||
constexpr uint16_t ha_binary_lock_on = 267;
|
||||
constexpr uint16_t ha_binary_lock_off = 268;
|
||||
constexpr uint16_t ha_binary_moisture_on = 269;
|
||||
constexpr uint16_t ha_binary_moisture_off = 270;
|
||||
constexpr uint16_t ha_binary_motion_on = 271;
|
||||
constexpr uint16_t ha_binary_motion_off = 272;
|
||||
constexpr uint16_t ha_binary_moving_on = 273;
|
||||
constexpr uint16_t ha_binary_moving_off = 274;
|
||||
constexpr uint16_t ha_binary_occupancy_on = 275;
|
||||
constexpr uint16_t ha_binary_occupancy_off = 276;
|
||||
constexpr uint16_t ha_binary_opening_on = 277;
|
||||
constexpr uint16_t ha_binary_opening_off = 278;
|
||||
constexpr uint16_t ha_binary_plug_on = 279;
|
||||
constexpr uint16_t ha_binary_plug_off = 280;
|
||||
constexpr uint16_t ha_binary_power_on = 281;
|
||||
constexpr uint16_t ha_binary_power_off = 282;
|
||||
constexpr uint16_t ha_binary_presence_on = 283;
|
||||
constexpr uint16_t ha_binary_presence_off = 284;
|
||||
constexpr uint16_t ha_binary_problem_on = 285;
|
||||
constexpr uint16_t ha_binary_problem_off = 286;
|
||||
constexpr uint16_t ha_binary_running_on = 287;
|
||||
constexpr uint16_t ha_binary_running_off = 288;
|
||||
constexpr uint16_t ha_binary_safety_on = 289;
|
||||
constexpr uint16_t ha_binary_safety_off = 290;
|
||||
constexpr uint16_t ha_binary_smoke_on = 291;
|
||||
constexpr uint16_t ha_binary_smoke_off = 292;
|
||||
constexpr uint16_t ha_binary_sound_on = 293;
|
||||
constexpr uint16_t ha_binary_sound_off = 294;
|
||||
constexpr uint16_t ha_binary_tamper_on = 295;
|
||||
constexpr uint16_t ha_binary_tamper_off = 296;
|
||||
constexpr uint16_t ha_binary_update_on = 297;
|
||||
constexpr uint16_t ha_binary_update_off = 298;
|
||||
constexpr uint16_t ha_binary_vibration_on = 299;
|
||||
constexpr uint16_t ha_binary_vibration_off = 300;
|
||||
constexpr uint16_t ha_binary_window_on = 301;
|
||||
constexpr uint16_t ha_binary_window_off = 302;
|
||||
constexpr uint16_t ha_button_activate = 303;
|
||||
constexpr uint16_t ha_button_run = 304;
|
||||
constexpr uint16_t ha_button_press = 305;
|
||||
constexpr uint16_t ha_climate_fan_auto = 306;
|
||||
constexpr uint16_t ha_climate_fan_low = 307;
|
||||
constexpr uint16_t ha_climate_fan_medium = 308;
|
||||
constexpr uint16_t ha_climate_fan_high = 309;
|
||||
constexpr uint16_t ha_climate_fan_middle = 310;
|
||||
constexpr uint16_t ha_climate_fan_focus = 311;
|
||||
constexpr uint16_t ha_climate_fan_diffuse = 312;
|
||||
constexpr uint16_t ha_climate_fan_top = 313;
|
||||
constexpr uint16_t ha_climate_fan_on = 314;
|
||||
constexpr uint16_t ha_climate_fan_off = 315;
|
||||
constexpr uint16_t ha_climate_swing_on = 316;
|
||||
constexpr uint16_t ha_climate_swing_off = 317;
|
||||
constexpr uint16_t ha_climate_swing_both = 318;
|
||||
constexpr uint16_t ha_climate_swing_vertical = 319;
|
||||
constexpr uint16_t ha_climate_swing_horizontal = 320;
|
||||
constexpr uint16_t script_yesterday_time_short = 183;
|
||||
constexpr uint16_t script_last_date = 184;
|
||||
constexpr uint16_t camera_no_image = 185;
|
||||
constexpr uint16_t camera_loading = 186;
|
||||
constexpr uint16_t camera_live = 187;
|
||||
constexpr uint16_t camera_recording = 188;
|
||||
constexpr uint16_t camera_tap_to_view = 189;
|
||||
constexpr uint16_t camera_no_image_yet = 190;
|
||||
constexpr uint16_t calibration_title = 191;
|
||||
constexpr uint16_t calibration_touch_check = 192;
|
||||
constexpr uint16_t calibration_hold = 193;
|
||||
constexpr uint16_t calibration_crosshair = 194;
|
||||
constexpr uint16_t calibration_gently = 195;
|
||||
constexpr uint16_t calibration_same = 196;
|
||||
constexpr uint16_t calibration_rejected = 197;
|
||||
constexpr uint16_t calibration_save_failed = 198;
|
||||
constexpr uint16_t ha_on = 199;
|
||||
constexpr uint16_t ha_off = 200;
|
||||
constexpr uint16_t ha_unavailable = 201;
|
||||
constexpr uint16_t ha_climate_off = 202;
|
||||
constexpr uint16_t ha_climate_heat = 203;
|
||||
constexpr uint16_t ha_climate_cool = 204;
|
||||
constexpr uint16_t ha_climate_heat_cool = 205;
|
||||
constexpr uint16_t ha_climate_auto = 206;
|
||||
constexpr uint16_t ha_climate_dry = 207;
|
||||
constexpr uint16_t ha_climate_fan_only = 208;
|
||||
constexpr uint16_t ha_hvac_action_heating = 209;
|
||||
constexpr uint16_t ha_hvac_action_cooling = 210;
|
||||
constexpr uint16_t ha_hvac_action_idle = 211;
|
||||
constexpr uint16_t ha_hvac_action_off = 212;
|
||||
constexpr uint16_t ha_hvac_action_drying = 213;
|
||||
constexpr uint16_t ha_hvac_action_fan = 214;
|
||||
constexpr uint16_t ha_hvac_action_preheating = 215;
|
||||
constexpr uint16_t ha_hvac_action_defrosting = 216;
|
||||
constexpr uint16_t ha_cover_open = 217;
|
||||
constexpr uint16_t ha_cover_closed = 218;
|
||||
constexpr uint16_t ha_cover_opening = 219;
|
||||
constexpr uint16_t ha_cover_closing = 220;
|
||||
constexpr uint16_t ha_media_playing = 221;
|
||||
constexpr uint16_t ha_media_paused = 222;
|
||||
constexpr uint16_t ha_media_idle = 223;
|
||||
constexpr uint16_t ha_media_standby = 224;
|
||||
constexpr uint16_t ha_person_home = 225;
|
||||
constexpr uint16_t ha_person_not_home = 226;
|
||||
constexpr uint16_t ha_sun_above_horizon = 227;
|
||||
constexpr uint16_t ha_sun_below_horizon = 228;
|
||||
constexpr uint16_t ha_vacuum_docked = 229;
|
||||
constexpr uint16_t ha_vacuum_cleaning = 230;
|
||||
constexpr uint16_t ha_vacuum_paused = 231;
|
||||
constexpr uint16_t ha_vacuum_returning = 232;
|
||||
constexpr uint16_t ha_vacuum_idle = 233;
|
||||
constexpr uint16_t ha_weather_sunny = 234;
|
||||
constexpr uint16_t ha_weather_clear_night = 235;
|
||||
constexpr uint16_t ha_weather_cloudy = 236;
|
||||
constexpr uint16_t ha_weather_partlycloudy = 237;
|
||||
constexpr uint16_t ha_weather_rainy = 238;
|
||||
constexpr uint16_t ha_weather_pouring = 239;
|
||||
constexpr uint16_t ha_weather_snowy = 240;
|
||||
constexpr uint16_t ha_weather_snowy_rainy = 241;
|
||||
constexpr uint16_t ha_weather_fog = 242;
|
||||
constexpr uint16_t ha_weather_hail = 243;
|
||||
constexpr uint16_t ha_weather_lightning = 244;
|
||||
constexpr uint16_t ha_weather_lightning_rainy = 245;
|
||||
constexpr uint16_t ha_weather_windy = 246;
|
||||
constexpr uint16_t ha_weather_exceptional = 247;
|
||||
constexpr uint16_t ha_binary_battery_on = 248;
|
||||
constexpr uint16_t ha_binary_battery_off = 249;
|
||||
constexpr uint16_t ha_binary_battery_charging_on = 250;
|
||||
constexpr uint16_t ha_binary_battery_charging_off = 251;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_on = 252;
|
||||
constexpr uint16_t ha_binary_carbon_monoxide_off = 253;
|
||||
constexpr uint16_t ha_binary_cold_on = 254;
|
||||
constexpr uint16_t ha_binary_cold_off = 255;
|
||||
constexpr uint16_t ha_binary_connectivity_on = 256;
|
||||
constexpr uint16_t ha_binary_connectivity_off = 257;
|
||||
constexpr uint16_t ha_binary_door_on = 258;
|
||||
constexpr uint16_t ha_binary_door_off = 259;
|
||||
constexpr uint16_t ha_binary_garage_door_on = 260;
|
||||
constexpr uint16_t ha_binary_garage_door_off = 261;
|
||||
constexpr uint16_t ha_binary_gas_on = 262;
|
||||
constexpr uint16_t ha_binary_gas_off = 263;
|
||||
constexpr uint16_t ha_binary_heat_on = 264;
|
||||
constexpr uint16_t ha_binary_heat_off = 265;
|
||||
constexpr uint16_t ha_binary_light_on = 266;
|
||||
constexpr uint16_t ha_binary_light_off = 267;
|
||||
constexpr uint16_t ha_binary_lock_on = 268;
|
||||
constexpr uint16_t ha_binary_lock_off = 269;
|
||||
constexpr uint16_t ha_binary_moisture_on = 270;
|
||||
constexpr uint16_t ha_binary_moisture_off = 271;
|
||||
constexpr uint16_t ha_binary_motion_on = 272;
|
||||
constexpr uint16_t ha_binary_motion_off = 273;
|
||||
constexpr uint16_t ha_binary_moving_on = 274;
|
||||
constexpr uint16_t ha_binary_moving_off = 275;
|
||||
constexpr uint16_t ha_binary_occupancy_on = 276;
|
||||
constexpr uint16_t ha_binary_occupancy_off = 277;
|
||||
constexpr uint16_t ha_binary_opening_on = 278;
|
||||
constexpr uint16_t ha_binary_opening_off = 279;
|
||||
constexpr uint16_t ha_binary_plug_on = 280;
|
||||
constexpr uint16_t ha_binary_plug_off = 281;
|
||||
constexpr uint16_t ha_binary_power_on = 282;
|
||||
constexpr uint16_t ha_binary_power_off = 283;
|
||||
constexpr uint16_t ha_binary_presence_on = 284;
|
||||
constexpr uint16_t ha_binary_presence_off = 285;
|
||||
constexpr uint16_t ha_binary_problem_on = 286;
|
||||
constexpr uint16_t ha_binary_problem_off = 287;
|
||||
constexpr uint16_t ha_binary_running_on = 288;
|
||||
constexpr uint16_t ha_binary_running_off = 289;
|
||||
constexpr uint16_t ha_binary_safety_on = 290;
|
||||
constexpr uint16_t ha_binary_safety_off = 291;
|
||||
constexpr uint16_t ha_binary_smoke_on = 292;
|
||||
constexpr uint16_t ha_binary_smoke_off = 293;
|
||||
constexpr uint16_t ha_binary_sound_on = 294;
|
||||
constexpr uint16_t ha_binary_sound_off = 295;
|
||||
constexpr uint16_t ha_binary_tamper_on = 296;
|
||||
constexpr uint16_t ha_binary_tamper_off = 297;
|
||||
constexpr uint16_t ha_binary_update_on = 298;
|
||||
constexpr uint16_t ha_binary_update_off = 299;
|
||||
constexpr uint16_t ha_binary_vibration_on = 300;
|
||||
constexpr uint16_t ha_binary_vibration_off = 301;
|
||||
constexpr uint16_t ha_binary_window_on = 302;
|
||||
constexpr uint16_t ha_binary_window_off = 303;
|
||||
constexpr uint16_t ha_button_activate = 304;
|
||||
constexpr uint16_t ha_button_run = 305;
|
||||
constexpr uint16_t ha_button_press = 306;
|
||||
constexpr uint16_t ha_climate_fan_auto = 307;
|
||||
constexpr uint16_t ha_climate_fan_low = 308;
|
||||
constexpr uint16_t ha_climate_fan_medium = 309;
|
||||
constexpr uint16_t ha_climate_fan_high = 310;
|
||||
constexpr uint16_t ha_climate_fan_middle = 311;
|
||||
constexpr uint16_t ha_climate_fan_focus = 312;
|
||||
constexpr uint16_t ha_climate_fan_diffuse = 313;
|
||||
constexpr uint16_t ha_climate_fan_top = 314;
|
||||
constexpr uint16_t ha_climate_fan_on = 315;
|
||||
constexpr uint16_t ha_climate_fan_off = 316;
|
||||
constexpr uint16_t ha_climate_swing_on = 317;
|
||||
constexpr uint16_t ha_climate_swing_off = 318;
|
||||
constexpr uint16_t ha_climate_swing_both = 319;
|
||||
constexpr uint16_t ha_climate_swing_vertical = 320;
|
||||
constexpr uint16_t ha_climate_swing_horizontal = 321;
|
||||
constexpr uint16_t date_weekdays = 18;
|
||||
constexpr uint16_t date_weekdays_count = 7;
|
||||
constexpr uint16_t date_weekdays_short = 25;
|
||||
@@ -293,6 +294,6 @@ constexpr uint16_t date_months_count = 12;
|
||||
constexpr uint16_t date_months_short = 51;
|
||||
constexpr uint16_t date_months_short_count = 12;
|
||||
} // namespace txt
|
||||
constexpr uint16_t KEY_COUNT = 321;
|
||||
constexpr uint32_t KEYS_HASH = 0x8FB53847u;
|
||||
constexpr uint16_t KEY_COUNT = 322;
|
||||
constexpr uint32_t KEYS_HASH = 0x6D3912FFu;
|
||||
} // namespace screen_text
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Nie ausgeführt",
|
||||
"last_time": "Zuletzt {time}",
|
||||
"yesterday_time": "Gestern {time}",
|
||||
"yesterday_time_short": "Gestern {time}",
|
||||
"last_date": "Zuletzt {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Never run",
|
||||
"last_time": "Last {time}",
|
||||
"yesterday_time": "Yesterday {time}",
|
||||
"yesterday_time_short": "Yest. {time}",
|
||||
"last_date": "Last {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Nunca ejecutado",
|
||||
"last_time": "Última {time}",
|
||||
"yesterday_time": "Ayer {time}",
|
||||
"yesterday_time_short": "Ayer {time}",
|
||||
"last_date": "Última {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Jamais lancé",
|
||||
"last_time": "Dernier {time}",
|
||||
"yesterday_time": "Hier {time}",
|
||||
"yesterday_time_short": "Hier {time}",
|
||||
"last_date": "Dernier {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Mai eseguito",
|
||||
"last_time": "Ultima {time}",
|
||||
"yesterday_time": "Ieri {time}",
|
||||
"yesterday_time_short": "Ieri {time}",
|
||||
"last_date": "Ultima {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Nooit uitgevoerd",
|
||||
"last_time": "Laatst {time}",
|
||||
"yesterday_time": "Gisteren {time}",
|
||||
"yesterday_time_short": "Gisteren {time}",
|
||||
"last_date": "Laatst {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Nie uruchamiano",
|
||||
"last_time": "Ostatnio {time}",
|
||||
"yesterday_time": "Wczoraj {time}",
|
||||
"yesterday_time_short": "Wczoraj {time}",
|
||||
"last_date": "Ostatnio {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -238,6 +238,7 @@
|
||||
"never_run": "Nunca executado",
|
||||
"last_time": "Última {time}",
|
||||
"yesterday_time": "Ontem {time}",
|
||||
"yesterday_time_short": "Ontem {time}",
|
||||
"last_date": "Última {date}"
|
||||
},
|
||||
"camera": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#pragma once
|
||||
#include "components/smart_display/screen_text.h"
|
||||
|
||||
static_assert(screen_text::KEYS_HASH == 0x8FB53847u && screen_text::KEY_COUNT == 321,
|
||||
static_assert(screen_text::KEYS_HASH == 0x6D3912FFu && screen_text::KEY_COUNT == 322,
|
||||
"screen_text_keys.h does not match screen_manager/translations/en.json: run tools/i18n.py header");
|
||||
const char *const screen_text::TABLE[] = {
|
||||
".",
|
||||
@@ -189,6 +189,7 @@ const char *const screen_text::TABLE[] = {
|
||||
"Never run",
|
||||
"Last {time}",
|
||||
"Yesterday {time}",
|
||||
"Yest. {time}",
|
||||
"Last {date}",
|
||||
"No image from this camera",
|
||||
"Loading image",
|
||||
|
||||
+10
-3
@@ -133,10 +133,13 @@ def check():
|
||||
if ours and code != 'en' and len(text) > max(8, len(source) * 1.6) and not plural:
|
||||
notes.append(f'{code}: {key} is much longer than the English ({len(text)} vs {len(source)})')
|
||||
if width and key in TILE_LINES:
|
||||
shown_text = text
|
||||
for name, sample in TILE_SAMPLES.items():
|
||||
shown_text = shown_text.replace('{' + name + '}', sample)
|
||||
for board, (size, room) in TILE_LINES[key].items():
|
||||
if width(size, text) > room:
|
||||
problems.append(f'{code}: {key} "{text}" is too wide for a tile on the {board} '
|
||||
f'({width(size, text):.0f} of {room} px); make it shorter')
|
||||
if width(size, shown_text) > room:
|
||||
problems.append(f'{code}: {key} "{shown_text}" is too wide for a tile on the {board} '
|
||||
f'({width(size, shown_text):.0f} of {room} px); make it shorter')
|
||||
# The weather columns of the CYD hold a day of two letters beside its icon.
|
||||
if key.startswith('screen.date.weekdays_min.') and len(text) > 2:
|
||||
problems.append(f'{code}: {key} "{text}" is longer than two letters; the CYD\'s weather columns cut it')
|
||||
@@ -154,8 +157,12 @@ TILE_ROOM = {'CYD': (11, 88), 'Guition': (16, 128)}
|
||||
# Camera tiles are the Guition's alone.
|
||||
TILE_LINES = {'screen.tile.tap_to_open': TILE_ROOM, 'screen.script.never_run': TILE_ROOM, 'screen.script.running': TILE_ROOM,
|
||||
'screen.media.not_playing': TILE_ROOM, 'screen.timer.paused': TILE_ROOM,
|
||||
'screen.script.last_time': TILE_ROOM, 'screen.script.yesterday_time_short': TILE_ROOM,
|
||||
'screen.camera.tap_to_view': {'Guition': TILE_ROOM['Guition']},
|
||||
'screen.camera.no_image_yet': {'Guition': TILE_ROOM['Guition']}}
|
||||
# What a placeholder stands for while a tile line is measured: the widest clock a screen writes is a 12-hour one
|
||||
# with its AM/PM ("Yesterday 9:15 PM" is why screen.script.yesterday_time_short exists).
|
||||
TILE_SAMPLES = {'time': '9:15 PM'}
|
||||
|
||||
|
||||
def text_width():
|
||||
|
||||
Reference in New Issue
Block a user