1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 06:18:07 +00:00

feat(core/mercury): change homescreen flow

This commit is contained in:
tychovrahe 2024-06-10 09:22:25 +02:00 committed by TychoVrahe
parent f396d00c67
commit 3a3259b574
18 changed files with 211 additions and 58 deletions

View File

@ -0,0 +1 @@
[T3T1]: improved change homescreen flow

View File

@ -843,6 +843,9 @@ def cargo_build():
features.append('ui_blurring') features.append('ui_blurring')
features.append('ui_jpeg_decoder') features.append('ui_jpeg_decoder')
if NEW_RENDERING and TREZOR_MODEL in ('T3T1', 'DISC2'):
features.append('ui_image_buffer')
features.extend(FEATURES_AVAILABLE) features.extend(FEATURES_AVAILABLE)
cargo_opts = [ cargo_opts = [

View File

@ -885,6 +885,8 @@ def cargo_build():
features.append('ui_blurring') features.append('ui_blurring')
features.append('ui_jpeg_decoder') features.append('ui_jpeg_decoder')
if NEW_RENDERING and TREZOR_MODEL in ('T3T1', ):
features.append('ui_image_buffer')
if NEW_RENDERING: if NEW_RENDERING:
features.append('new_rendering') features.append('new_rendering')

View File

@ -26,6 +26,7 @@ ui_bounds = []
ui_antialiasing = [] ui_antialiasing = []
ui_blurring = [] ui_blurring = []
ui_jpeg_decoder = ["jpeg"] ui_jpeg_decoder = ["jpeg"]
ui_image_buffer = []
new_rendering = [] new_rendering = []
bootloader = [] bootloader = []
button = [] button = []
@ -60,6 +61,7 @@ test = [
"ui", "ui",
"ui_jpeg_decoder", "ui_jpeg_decoder",
"ui_blurring", "ui_blurring",
"ui_image_buffer",
"universal_fw", "universal_fw",
] ]
universal_fw = [] universal_fw = []

View File

@ -251,6 +251,8 @@ static void _librust_qstrs(void) {
MP_QSTR_homescreen__click_to_connect; MP_QSTR_homescreen__click_to_connect;
MP_QSTR_homescreen__click_to_unlock; MP_QSTR_homescreen__click_to_unlock;
MP_QSTR_homescreen__set_default; MP_QSTR_homescreen__set_default;
MP_QSTR_homescreen__settings_subtitle;
MP_QSTR_homescreen__settings_title;
MP_QSTR_homescreen__title_backup_failed; MP_QSTR_homescreen__title_backup_failed;
MP_QSTR_homescreen__title_backup_needed; MP_QSTR_homescreen__title_backup_needed;
MP_QSTR_homescreen__title_coinjoin_authorized; MP_QSTR_homescreen__title_coinjoin_authorized;

View File

@ -546,7 +546,7 @@ pub enum TranslatedString {
homescreen__title_no_usb_connection = 327, // "No USB connection" homescreen__title_no_usb_connection = 327, // "No USB connection"
homescreen__title_pin_not_set = 328, // "PIN not set" homescreen__title_pin_not_set = 328, // "PIN not set"
homescreen__title_seedless = 329, // "Seedless" homescreen__title_seedless = 329, // "Seedless"
homescreen__title_set = 330, // "Change homescreen?" homescreen__title_set = 330, // "Change wallpaper"
inputs__back = 331, // "BACK" inputs__back = 331, // "BACK"
inputs__cancel = 332, // "CANCEL" inputs__cancel = 332, // "CANCEL"
inputs__delete = 333, // "DELETE" inputs__delete = 333, // "DELETE"
@ -1334,9 +1334,11 @@ pub enum TranslatedString {
recovery__title_unlock_repeated_backup = 933, // "Multi-share backup" recovery__title_unlock_repeated_backup = 933, // "Multi-share backup"
recovery__unlock_repeated_backup = 934, // "Create additional backup?" recovery__unlock_repeated_backup = 934, // "Create additional backup?"
recovery__unlock_repeated_backup_verb = 935, // "Create backup" recovery__unlock_repeated_backup_verb = 935, // "Create backup"
homescreen__set_default = 936, // "Do you really want to set default homescreen image?" homescreen__set_default = 936, // "Change wallpaper to default image?"
reset__words_may_repeat = 937, // "Words may repeat." reset__words_may_repeat = 937, // "Words may repeat."
reset__repeat_for_all_shares = 938, // "Repeat for all shares." reset__repeat_for_all_shares = 938, // "Repeat for all shares."
homescreen__settings_subtitle = 939, // "Settings"
homescreen__settings_title = 940, // "Homescreen"
} }
impl TranslatedString { impl TranslatedString {
@ -1877,7 +1879,7 @@ impl TranslatedString {
Self::homescreen__title_no_usb_connection => "No USB connection", Self::homescreen__title_no_usb_connection => "No USB connection",
Self::homescreen__title_pin_not_set => "PIN not set", Self::homescreen__title_pin_not_set => "PIN not set",
Self::homescreen__title_seedless => "Seedless", Self::homescreen__title_seedless => "Seedless",
Self::homescreen__title_set => "Change homescreen?", Self::homescreen__title_set => "Change wallpaper",
Self::inputs__back => "BACK", Self::inputs__back => "BACK",
Self::inputs__cancel => "CANCEL", Self::inputs__cancel => "CANCEL",
Self::inputs__delete => "DELETE", Self::inputs__delete => "DELETE",
@ -2665,9 +2667,11 @@ impl TranslatedString {
Self::recovery__title_unlock_repeated_backup => "Multi-share backup", Self::recovery__title_unlock_repeated_backup => "Multi-share backup",
Self::recovery__unlock_repeated_backup => "Create additional backup?", Self::recovery__unlock_repeated_backup => "Create additional backup?",
Self::recovery__unlock_repeated_backup_verb => "Create backup", Self::recovery__unlock_repeated_backup_verb => "Create backup",
Self::homescreen__set_default => "Do you really want to set default homescreen image?", Self::homescreen__set_default => "Change wallpaper to default image?",
Self::reset__words_may_repeat => "Words may repeat.", Self::reset__words_may_repeat => "Words may repeat.",
Self::reset__repeat_for_all_shares => "Repeat for all shares.", Self::reset__repeat_for_all_shares => "Repeat for all shares.",
Self::homescreen__settings_subtitle => "Settings",
Self::homescreen__settings_title => "Homescreen",
} }
} }
@ -4000,6 +4004,8 @@ impl TranslatedString {
Qstr::MP_QSTR_homescreen__set_default => Some(Self::homescreen__set_default), Qstr::MP_QSTR_homescreen__set_default => Some(Self::homescreen__set_default),
Qstr::MP_QSTR_reset__words_may_repeat => Some(Self::reset__words_may_repeat), Qstr::MP_QSTR_reset__words_may_repeat => Some(Self::reset__words_may_repeat),
Qstr::MP_QSTR_reset__repeat_for_all_shares => Some(Self::reset__repeat_for_all_shares), Qstr::MP_QSTR_reset__repeat_for_all_shares => Some(Self::reset__repeat_for_all_shares),
Qstr::MP_QSTR_homescreen__settings_subtitle => Some(Self::homescreen__settings_subtitle),
Qstr::MP_QSTR_homescreen__settings_title => Some(Self::homescreen__settings_title),
_ => None, _ => None,
} }
} }

View File

@ -0,0 +1,98 @@
use crate::{
io::BinaryData,
ui::{
component::{Component, Event, EventCtx, Never},
display::image::ImageInfo,
geometry::{Offset, Point, Rect},
shape,
shape::{render_on_canvas, ImageBuffer, Renderer, Rgb565Canvas},
},
};
pub struct CachedJpeg {
area: Rect,
image_size: Offset,
jpeg: ImageBuffer<Rgb565Canvas<'static>>,
scale: u8,
}
impl CachedJpeg {
pub fn new(image: BinaryData<'static>, scale: u8) -> Self {
let size = match ImageInfo::parse(image) {
ImageInfo::Jpeg(info) => {
if info.mcu_height() > 16 {
Offset::zero()
} else {
Offset::new(info.width(), info.height())
}
}
_ => Offset::zero(),
};
let mut buf = unwrap!(ImageBuffer::new(size), "no image buf");
render_on_canvas(buf.canvas(), None, |target| {
shape::JpegImage::new_image(Point::zero(), image)
.with_scale(scale)
.render(target);
});
Self {
area: Rect::zero(),
image_size: size,
jpeg: buf,
scale,
}
}
}
impl Component for CachedJpeg {
type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect {
self.area = bounds;
self.area
}
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
None
}
fn paint(&mut self) {}
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
let off = Offset::new(
self.image_size.x / (2 << self.scale),
self.image_size.y / (2 << self.scale),
);
let pos = self.area.center() - off;
shape::RawImage::new(
Rect::from_top_left_and_size(pos, self.image_size * (1.0 / (1 << self.scale) as f32)),
self.jpeg.view(),
)
.render(target);
}
#[cfg(feature = "ui_bounds")]
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.area)
}
}
#[cfg(feature = "ui_debug")]
impl crate::trace::Trace for CachedJpeg {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.component("CachedJpeg");
}
}
#[cfg(feature = "micropython")]
mod micropython {
use crate::{error::Error, micropython::obj::Obj, ui::layout::obj::ComponentMsgObj};
impl ComponentMsgObj for super::CachedJpeg {
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
unreachable!();
}
}
}

View File

@ -4,6 +4,8 @@ pub mod bar;
pub mod base; pub mod base;
pub mod border; pub mod border;
pub mod button_request; pub mod button_request;
#[cfg(all(feature = "jpeg", feature = "ui_image_buffer", feature = "micropython"))]
pub mod cached_jpeg;
pub mod connect; pub mod connect;
pub mod empty; pub mod empty;
pub mod image; pub mod image;
@ -28,6 +30,8 @@ pub use bar::Bar;
pub use base::{Child, Component, ComponentExt, Event, EventCtx, Never, Root, TimerToken}; pub use base::{Child, Component, ComponentExt, Event, EventCtx, Never, Root, TimerToken};
pub use border::Border; pub use border::Border;
pub use button_request::{ButtonRequestExt, OneButtonRequest}; pub use button_request::{ButtonRequestExt, OneButtonRequest};
#[cfg(all(feature = "jpeg", feature = "ui_image_buffer", feature = "micropython"))]
pub use cached_jpeg::CachedJpeg;
pub use empty::Empty; pub use empty::Empty;
#[cfg(all(feature = "jpeg", feature = "micropython"))] #[cfg(all(feature = "jpeg", feature = "micropython"))]
pub use jpeg::Jpeg; pub use jpeg::Jpeg;

View File

@ -173,7 +173,7 @@ fn new_confirm_action_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Err
} }
#[inline(never)] #[inline(never)]
pub fn new_confirm_action_simple<T: Component + Paginate + MaybeTrace + 'static>( pub fn new_confirm_action_uni<T: Component + MaybeTrace + 'static>(
content: T, content: T,
title: TString<'static>, title: TString<'static>,
subtitle: Option<TString<'static>>, subtitle: Option<TString<'static>>,
@ -182,8 +182,7 @@ pub fn new_confirm_action_simple<T: Component + Paginate + MaybeTrace + 'static>
hold: bool, hold: bool,
info: bool, info: bool,
) -> Result<Obj, error::Error> { ) -> Result<Obj, error::Error> {
let mut content_intro = let mut content_intro = Frame::left_aligned(title, content)
Frame::left_aligned(title, SwipeContent::new(SwipePage::vertical(content)))
.with_menu_button() .with_menu_button()
.with_footer(TR::instructions__swipe_up.into(), None) .with_footer(TR::instructions__swipe_up.into(), None)
.with_swipe(SwipeDirection::Up, SwipeSettings::default()) .with_swipe(SwipeDirection::Up, SwipeSettings::default())
@ -261,3 +260,24 @@ pub fn new_confirm_action_simple<T: Component + Paginate + MaybeTrace + 'static>
Ok(LayoutObj::new(res)?.into()) Ok(LayoutObj::new(res)?.into())
} }
} }
#[inline(never)]
pub fn new_confirm_action_simple<T: Component + Paginate + MaybeTrace + 'static>(
content: T,
title: TString<'static>,
subtitle: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
prompt_screen: Option<TString<'static>>,
hold: bool,
info: bool,
) -> Result<Obj, error::Error> {
new_confirm_action_uni(
SwipeContent::new(SwipePage::vertical(content)),
title,
subtitle,
verb_cancel,
prompt_screen,
hold,
info,
)
}

View File

@ -22,7 +22,6 @@ use crate::{
component::{ component::{
base::{AttachType, ComponentExt}, base::{AttachType, ComponentExt},
connect::Connect, connect::Connect,
jpeg::Jpeg,
swipe_detect::SwipeSettings, swipe_detect::SwipeSettings,
text::{ text::{
op::OpTextLayout, op::OpTextLayout,
@ -32,7 +31,7 @@ use crate::{
}, },
TextStyle, TextStyle,
}, },
Border, Component, FormattedText, Label, Never, SwipeDirection, Timeout, Border, CachedJpeg, Component, FormattedText, Label, Never, SwipeDirection, Timeout,
}, },
flow::Swipable, flow::Swipable,
geometry, geometry,
@ -41,7 +40,10 @@ use crate::{
result::{CANCELLED, CONFIRMED, INFO}, result::{CANCELLED, CONFIRMED, INFO},
util::{upy_disable_animation, ConfirmBlob, PropsList}, util::{upy_disable_animation, ConfirmBlob, PropsList},
}, },
model_mercury::component::{check_homescreen_format, SwipeContent}, model_mercury::{
component::{check_homescreen_format, SwipeContent},
flow::new_confirm_action_simple,
},
}, },
}; };
@ -516,39 +518,39 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
let obj = if jpeg.is_empty() { let obj = if jpeg.is_empty() {
// Incoming data may be empty, meaning we should // Incoming data may be empty, meaning we should
// display default homescreen message. // display default homescreen message.
LayoutObj::new(SwipeUpScreen::new( let paragraphs = ParagraphVecShort::from_iter([Paragraph::new(
Frame::centered(
title,
SwipeContent::new(Paragraphs::new([Paragraph::new(
&theme::TEXT_DEMIBOLD, &theme::TEXT_DEMIBOLD,
TR::homescreen__set_default, TR::homescreen__set_default,
)])
.into_paragraphs();
new_confirm_action_simple(
paragraphs,
TR::homescreen__settings_title.into(),
Some(TR::homescreen__settings_subtitle.into()),
None,
Some(TR::homescreen__settings_title.into()),
false,
false,
) )
.centered()])),
)
.with_cancel_button()
.with_footer(
TR::instructions__swipe_up.into(),
Some(TR::buttons__change.into()),
)
.with_swipe(SwipeDirection::Up, SwipeSettings::default()),
))
} else { } else {
if !check_homescreen_format(jpeg) { if !check_homescreen_format(jpeg) {
return Err(value_error!(c"Invalid image.")); return Err(value_error!(c"Invalid image."));
}; };
LayoutObj::new(SwipeUpScreen::new( let obj = LayoutObj::new(SwipeUpScreen::new(
Frame::left_aligned(title, Jpeg::new(jpeg, 1)) Frame::left_aligned(title, SwipeContent::new(CachedJpeg::new(jpeg, 1)))
.with_cancel_button() .with_cancel_button()
.with_footer( .with_footer(
TR::instructions__swipe_up.into(), TR::instructions__swipe_up.into(),
Some(TR::buttons__change.into()), Some(TR::buttons__change.into()),
) )
.with_swipe(SwipeDirection::Up, SwipeSettings::default()), .with_swipe(SwipeDirection::Up, SwipeSettings::default()),
)) ));
};
Ok(obj?.into()) Ok(obj?.into())
}; };
obj
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
} }

View File

@ -36,5 +36,5 @@ pub use rawimage::RawImage;
pub use render::{DirectRenderer, ProgressiveRenderer, Renderer}; pub use render::{DirectRenderer, ProgressiveRenderer, Renderer};
pub use text::Text; pub use text::Text;
pub use toif::ToifImage; pub use toif::ToifImage;
#[cfg(feature = "model_mercury")] #[cfg(feature = "ui_image_buffer")]
pub use utils::ImageBuffer; pub use utils::ImageBuffer;

View File

@ -1,5 +1,7 @@
mod blur; mod blur;
mod circle; mod circle;
#[cfg(feature = "ui_image_buffer")]
mod imagebuf; mod imagebuf;
mod line; mod line;
mod trigo; mod trigo;
@ -7,7 +9,7 @@ mod trigo;
pub use blur::{BlurAlgorithm, BlurBuff}; pub use blur::{BlurAlgorithm, BlurBuff};
pub use circle::circle_points; pub use circle::circle_points;
#[cfg(feature = "model_mercury")] #[cfg(feature = "ui_image_buffer")]
pub use imagebuf::ImageBuffer; pub use imagebuf::ImageBuffer;
pub use line::line_points; pub use line::line_points;

View File

@ -356,7 +356,9 @@ class TR:
haptic_feedback__title: str = "Haptic feedback" haptic_feedback__title: str = "Haptic feedback"
homescreen__click_to_connect: str = "Click to Connect" homescreen__click_to_connect: str = "Click to Connect"
homescreen__click_to_unlock: str = "Click to Unlock" homescreen__click_to_unlock: str = "Click to Unlock"
homescreen__set_default: str = "Do you really want to set default homescreen image?" homescreen__set_default: str = "Change wallpaper to default image?"
homescreen__settings_subtitle: str = "Settings"
homescreen__settings_title: str = "Homescreen"
homescreen__title_backup_failed: str = "Backup failed" homescreen__title_backup_failed: str = "Backup failed"
homescreen__title_backup_needed: str = "Backup needed" homescreen__title_backup_needed: str = "Backup needed"
homescreen__title_coinjoin_authorized: str = "Coinjoin authorized" homescreen__title_coinjoin_authorized: str = "Coinjoin authorized"
@ -364,7 +366,7 @@ class TR:
homescreen__title_no_usb_connection: str = "No USB connection" homescreen__title_no_usb_connection: str = "No USB connection"
homescreen__title_pin_not_set: str = "PIN not set" homescreen__title_pin_not_set: str = "PIN not set"
homescreen__title_seedless: str = "Seedless" homescreen__title_seedless: str = "Seedless"
homescreen__title_set: str = "Change homescreen?" homescreen__title_set: str = "Change wallpaper"
inputs__back: str = "BACK" inputs__back: str = "BACK"
inputs__cancel: str = "CANCEL" inputs__cancel: str = "CANCEL"
inputs__delete: str = "DELETE" inputs__delete: str = "DELETE"

View File

@ -425,6 +425,11 @@ def confirm_multisig_warning() -> Awaitable[None]:
def confirm_homescreen( def confirm_homescreen(
image: bytes, image: bytes,
) -> Awaitable[None]: ) -> Awaitable[None]:
from trezor import workflow
workflow.close_others()
return raise_if_not_confirmed( return raise_if_not_confirmed(
interact( interact(
RustLayout( RustLayout(

View File

@ -365,8 +365,10 @@
"homescreen__title_no_usb_connection": "No USB connection", "homescreen__title_no_usb_connection": "No USB connection",
"homescreen__title_pin_not_set": "PIN not set", "homescreen__title_pin_not_set": "PIN not set",
"homescreen__title_seedless": "Seedless", "homescreen__title_seedless": "Seedless",
"homescreen__title_set": "Change homescreen?", "homescreen__title_set": "Change wallpaper",
"homescreen__set_default": "Do you really want to set default homescreen image?", "homescreen__settings_title": "Homescreen",
"homescreen__settings_subtitle": "Settings",
"homescreen__set_default": "Change wallpaper to default image?",
"inputs__back": "BACK", "inputs__back": "BACK",
"inputs__cancel": "CANCEL", "inputs__cancel": "CANCEL",
"inputs__delete": "DELETE", "inputs__delete": "DELETE",

View File

@ -937,5 +937,7 @@
"935": "recovery__unlock_repeated_backup_verb", "935": "recovery__unlock_repeated_backup_verb",
"936": "homescreen__set_default", "936": "homescreen__set_default",
"937": "reset__words_may_repeat", "937": "reset__words_may_repeat",
"938": "reset__repeat_for_all_shares" "938": "reset__repeat_for_all_shares",
"939": "homescreen__settings_subtitle",
"940": "homescreen__settings_title"
} }

View File

@ -1,8 +1,8 @@
{ {
"current": { "current": {
"merkle_root": "965333c69ea67f8fb0c199da2293677c7568962e5c1221624f4f13011e8ac88d", "merkle_root": "5b5781c3374ff27125228c121ab97436a2ba1f0581657ee56b9fa601fe3bde97",
"datetime": "2024-06-14T10:32:18.803684", "datetime": "2024-06-24T13:47:55.544267",
"commit": "3e5af95a88c28082ea2c37f38339956991c1255a" "commit": "d79768cec726c26ac1f82e62fc71b6d4568786a2"
}, },
"history": [ "history": [
{ {

View File

@ -2243,9 +2243,9 @@
"T2B1_cs_test_language.py::test_switch_from_english_not_silent": "fb2e18e513a44a58cd1e31fa563c3c9783d5ec0a692ffb0b6635b833e13d76d5", "T2B1_cs_test_language.py::test_switch_from_english_not_silent": "fb2e18e513a44a58cd1e31fa563c3c9783d5ec0a692ffb0b6635b833e13d76d5",
"T2B1_cs_test_language.py::test_switch_language": "0c2bc505e2a70aa7f544d15a20c2cbec91ae70da6cc48fe6947ffa4de9bcebda", "T2B1_cs_test_language.py::test_switch_language": "0c2bc505e2a70aa7f544d15a20c2cbec91ae70da6cc48fe6947ffa4de9bcebda",
"T2B1_cs_test_language.py::test_translations_renders_on_screen": "fd543359e3be7f3e65c8e1129df243572305b0a458997343524d7f79a553fe74", "T2B1_cs_test_language.py::test_translations_renders_on_screen": "fd543359e3be7f3e65c8e1129df243572305b0a458997343524d7f79a553fe74",
"T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "2ceb28bcde3e1af715411e08be2858b0f3fd4f3d7dcf198776e66449f0055a16", "T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "14b9aba9fd57cf4bc0efbd34decb35c4d86c75bdce7e9593679b361ba3243551",
"T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "4bd7fc29a9ff8ab05c5bd5631800c6cb6884585b5eb63f1cbfbeec148a5477c5", "T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "ca1c06375c98d3f9ebd84d4ebc63fcded735ec2320babf81e04185ea3ac5edfe",
"T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "f0b4b3f8352e82e83de2b756ce4a88c8de6937213054f0b7eb7fa990b880653a", "T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "4cb5fb5f00faec18c34436b4d97ac7199bc10d619c772cc97bbdaa9aa84e69b7",
"T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "df85ab8b2b58b571f6f7176713d6cdc572b25cec8a3a5303019017ba945c2142", "T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "df85ab8b2b58b571f6f7176713d6cdc572b25cec8a3a5303019017ba945c2142",
"T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "df85ab8b2b58b571f6f7176713d6cdc572b25cec8a3a5303019017ba945c2142", "T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "df85ab8b2b58b571f6f7176713d6cdc572b25cec8a3a5303019017ba945c2142",
"T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "df85ab8b2b58b571f6f7176713d6cdc572b25cec8a3a5303019017ba945c2142", "T2B1_cs_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "df85ab8b2b58b571f6f7176713d6cdc572b25cec8a3a5303019017ba945c2142",
@ -5025,9 +5025,9 @@
"T2B1_en_test_language.py::test_switch_from_english_not_silent": "8c801bd0142e5c1ad4aad50b34c7debb1b8f17a2e0a87eb7f95531b9fd15e095", "T2B1_en_test_language.py::test_switch_from_english_not_silent": "8c801bd0142e5c1ad4aad50b34c7debb1b8f17a2e0a87eb7f95531b9fd15e095",
"T2B1_en_test_language.py::test_switch_language": "b74085538e1bb7f0217ba5880c41542938ce41ded7e2499b1807c0aaf51d6fc7", "T2B1_en_test_language.py::test_switch_language": "b74085538e1bb7f0217ba5880c41542938ce41ded7e2499b1807c0aaf51d6fc7",
"T2B1_en_test_language.py::test_translations_renders_on_screen": "47922d94fd02016582810dea2286605d73f71ae325532daa72d55dc94ba7bb31", "T2B1_en_test_language.py::test_translations_renders_on_screen": "47922d94fd02016582810dea2286605d73f71ae325532daa72d55dc94ba7bb31",
"T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "eee723c40995e36155677033d1371af0ec8d7ec466ebba19fa915ae33005a402", "T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "e27094d0aa2dcf0aed21de9500df795dcda1c0c4c8ee61124fc3369ea21b9cc5",
"T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "76a9871967a82b747811eb0a63b8ad66ff5d2273461da749f07ca145db998ae7", "T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "e46c4e3e502dcad92ff6795352a2e1c423be352e1a1ed79623fce78e8673d1a1",
"T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "bb644f67c0d8e20639482a7cc7f736b391c2ed5217e84fcfd09e1e7b69d8aa5e", "T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "6629641be9c219175d87a006358d20c8a68e05324c5b8b047ea8fbe884a0c7a4",
"T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "10972f76d7d6b64f42602484d31d6ae6c932ee62ff39c57de654c5b5ddf71c75", "T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "10972f76d7d6b64f42602484d31d6ae6c932ee62ff39c57de654c5b5ddf71c75",
"T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "10972f76d7d6b64f42602484d31d6ae6c932ee62ff39c57de654c5b5ddf71c75", "T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "10972f76d7d6b64f42602484d31d6ae6c932ee62ff39c57de654c5b5ddf71c75",
"T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "10972f76d7d6b64f42602484d31d6ae6c932ee62ff39c57de654c5b5ddf71c75", "T2B1_en_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "10972f76d7d6b64f42602484d31d6ae6c932ee62ff39c57de654c5b5ddf71c75",
@ -6416,9 +6416,9 @@
"T2B1_es_test_language.py::test_switch_from_english_not_silent": "a9b0e47be4dac0a6e99582439a6225527e8e365b7e74cca03892675853b1a152", "T2B1_es_test_language.py::test_switch_from_english_not_silent": "a9b0e47be4dac0a6e99582439a6225527e8e365b7e74cca03892675853b1a152",
"T2B1_es_test_language.py::test_switch_language": "26c80e43afd26df2a04f55e21c44c36cf8bbb9c4f5ee3012ee7a4a5f8e2313c7", "T2B1_es_test_language.py::test_switch_language": "26c80e43afd26df2a04f55e21c44c36cf8bbb9c4f5ee3012ee7a4a5f8e2313c7",
"T2B1_es_test_language.py::test_translations_renders_on_screen": "7f3f39ddad3967195db73c2609822dced686f8fc8efe77c72c5606b840b17231", "T2B1_es_test_language.py::test_translations_renders_on_screen": "7f3f39ddad3967195db73c2609822dced686f8fc8efe77c72c5606b840b17231",
"T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "1d2ccf6cd4b02e47db80071bc00b536d21bf03286c57c2f69b66c0d2cd7307b7", "T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "05d1fa08b413e81a2466285c59eb37bf9ac9c56cbb3c36cca6261b465fad449e",
"T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "2e8da6d392e9a734f9355e7b83ed9fe369cc663e15dbce5a8d8d7001134efc6b", "T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "2756046c76d02f4adcff4a2807d26cd8cc27f6fed3a753ca48f91e4da4e7664b",
"T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "42d31cb3e5f776a6512929f0a38b08f8de26752fa6f30ede6cae926558ac2f02", "T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "9a453e964eeeb279c1f11855a380a1b44399e2726f8f29aedb7ab44fc4878950",
"T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "9782109663489ddba01055e2f470b877dfed5de60711f1153529dc22b292051f", "T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "9782109663489ddba01055e2f470b877dfed5de60711f1153529dc22b292051f",
"T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "9782109663489ddba01055e2f470b877dfed5de60711f1153529dc22b292051f", "T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "9782109663489ddba01055e2f470b877dfed5de60711f1153529dc22b292051f",
"T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "9782109663489ddba01055e2f470b877dfed5de60711f1153529dc22b292051f", "T2B1_es_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "9782109663489ddba01055e2f470b877dfed5de60711f1153529dc22b292051f",
@ -7807,9 +7807,9 @@
"T2B1_fr_test_language.py::test_switch_from_english_not_silent": "2d59eedb25da2468512d9576ef7d7f4528804d4fb8bb1921d4ee8d4d20d91196", "T2B1_fr_test_language.py::test_switch_from_english_not_silent": "2d59eedb25da2468512d9576ef7d7f4528804d4fb8bb1921d4ee8d4d20d91196",
"T2B1_fr_test_language.py::test_switch_language": "d64c176bfb4ea6ddbb57c7b609ac0983b335ae0ce503c653480d379caf71976a", "T2B1_fr_test_language.py::test_switch_language": "d64c176bfb4ea6ddbb57c7b609ac0983b335ae0ce503c653480d379caf71976a",
"T2B1_fr_test_language.py::test_translations_renders_on_screen": "c96510d7b9812933713c70d22e2a549f12e888a28d8a2624a649d73bf3871d12", "T2B1_fr_test_language.py::test_translations_renders_on_screen": "c96510d7b9812933713c70d22e2a549f12e888a28d8a2624a649d73bf3871d12",
"T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "dff1e20db00e7445a6bf6f45c1e409fae384e0b59308bbf86b226a76ba9f5603", "T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "6fbb8c3d87ac90a8bfe8553489db45d7974a12095faf9b312a135812e2ae1ece",
"T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "4b78cfafde8d47ad5190c86f9a0f22142c6db6400451176a4eb61a1049896461", "T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "6a2aa372458517e208753585d9b7964dd59f48d4d4c09f83048ccec5e8d180ff",
"T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "55fbc311b8bac5c3b50b0c3e0dee2677d696243418d6695fc3cc93b1ab8f0032", "T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_notification": "7ea6d0c55fa400dd8b6181146e6c4ffe0605959487243e8ae3a2b71aedc92086",
"T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "662074a147c0862555541b4415136a3f50f88ba72a92e208c26f7ae140459684", "T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_wrong_size": "662074a147c0862555541b4415136a3f50f88ba72a92e208c26f7ae140459684",
"T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "662074a147c0862555541b4415136a3f50f88ba72a92e208c26f7ae140459684", "T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_upload_jpeg_fail": "662074a147c0862555541b4415136a3f50f88ba72a92e208c26f7ae140459684",
"T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "662074a147c0862555541b4415136a3f50f88ba72a92e208c26f7ae140459684", "T2B1_fr_test_msg_applysettings.py::test_apply_homescreen_tr_upload_t1_fail": "662074a147c0862555541b4415136a3f50f88ba72a92e208c26f7ae140459684",
@ -12467,7 +12467,7 @@
"T2T1_en_test_language.py::test_switch_from_english_not_silent": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3", "T2T1_en_test_language.py::test_switch_from_english_not_silent": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3",
"T2T1_en_test_language.py::test_switch_language": "96d22e81bdc95a01571b678688798ea58868f818372bbc28fff6cb2415531d56", "T2T1_en_test_language.py::test_switch_language": "96d22e81bdc95a01571b678688798ea58868f818372bbc28fff6cb2415531d56",
"T2T1_en_test_language.py::test_translations_renders_on_screen": "bc06283850dbfad95bf96a97768c276df1543073d41d89909097ea2fc4f3f9ad", "T2T1_en_test_language.py::test_translations_renders_on_screen": "bc06283850dbfad95bf96a97768c276df1543073d41d89909097ea2fc4f3f9ad",
"T2T1_en_test_msg_applysettings.py::test_apply_homescreen_jpeg": "0e2a71ac60add6bebc03645b6f4f6f19abdba56f1e55e799479b116e5a66aef6", "T2T1_en_test_msg_applysettings.py::test_apply_homescreen_jpeg": "d4e26a1227c1867413ce73f259f16174e43b3e75d75b508dd71b117e06749243",
"T2T1_en_test_msg_applysettings.py::test_apply_homescreen_jpeg_progressive": "4d7c67024ee17436071e5cf2f79c36453249c95314a732580623cb1f1cdbfdf3", "T2T1_en_test_msg_applysettings.py::test_apply_homescreen_jpeg_progressive": "4d7c67024ee17436071e5cf2f79c36453249c95314a732580623cb1f1cdbfdf3",
"T2T1_en_test_msg_applysettings.py::test_apply_homescreen_jpeg_wrong_size": "4d7c67024ee17436071e5cf2f79c36453249c95314a732580623cb1f1cdbfdf3", "T2T1_en_test_msg_applysettings.py::test_apply_homescreen_jpeg_wrong_size": "4d7c67024ee17436071e5cf2f79c36453249c95314a732580623cb1f1cdbfdf3",
"T2T1_en_test_msg_applysettings.py::test_apply_homescreen_toif": "4d7c67024ee17436071e5cf2f79c36453249c95314a732580623cb1f1cdbfdf3", "T2T1_en_test_msg_applysettings.py::test_apply_homescreen_toif": "4d7c67024ee17436071e5cf2f79c36453249c95314a732580623cb1f1cdbfdf3",