feat(core/eckhart): update Regulatory screen
What changed, and why it matters
This commit updates the regulatory information screen on the Trezor T3W1 hardware wallet. It adds new country certification icons, reorganizes the order of regions shown, and displays the device's production year on the South Korea page. There is no security-relevant change here—only user-interface text, images, and layout.
No security action required. This is a routine UI/UX update. Reviewers may optionally verify that the new `production_year` string is handled safely as a display-only `TString` and that no buffer overflow or format-string behavior exists in the rendering path, though the diff shows standard UI text rendering.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change is a UI-only feature for the Eckhart layout (T3W1). It extends the device menu API with an optional production_year string, passes it from Python via utils.unit_production_date(), and renders it on the South Korea regulatory page. It also adds/reorganizes regulatory icons (Argentina, Singapore, split Korea/Japan icons, etc.) and updates test fixtures. No cryptographic, authentication, or firmware integrity logic is modified.
Changed components
core/embed/rust/src/ui/layout_eckhart/firmware/regulatory_screen.rscore/embed/rust/src/ui/layout_eckhart/firmware/device_menu_screen.rscore/embed/rust/src/ui/layout_eckhart/theme/mod.rscore/src/apps/homescreen/device_menu.pycore/embed/rust/src/ui/api/firmware_micropython.rscore/embed/rust/src/ui/ui_firmware.rscore/mocks/generated/trezorui_api.pyiInspect captured patch +150 / −49
diff --git a/core/.changelog.d/6281.changed b/core/.changelog.d/6281.changed
new file mode 100644
index 00000000..3d83b826
--- /dev/null
+++ b/core/.changelog.d/6281.changed
@@ -0,0 +1 @@
+[T3W1] Update Regulatory screen in the device menu.
diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h
index 68f11c9c..2eba52ce 100644
--- a/core/embed/rust/librust_qstr.h
+++ b/core/embed/rust/librust_qstr.h
@@ -554,6 +554,7 @@ static void _librust_qstrs(void) {
MP_QSTR_pm_event;
MP_QSTR_prefill;
MP_QSTR_prefill_word;
+ MP_QSTR_production_year;
MP_QSTR_progress__authenticity_check;
MP_QSTR_progress__done;
MP_QSTR_progress__loading_transaction;
diff --git a/core/embed/rust/src/ui/api/firmware_micropython.rs b/core/embed/rust/src/ui/api/firmware_micropython.rs
index 361c3b0f..cf465c46 100644
--- a/core/embed/rust/src/ui/api/firmware_micropython.rs
+++ b/core/embed/rust/src/ui/api/firmware_micropython.rs
@@ -985,6 +985,9 @@ extern "C" fn new_show_device_menu(n_args: usize, args: *const Obj, kwargs: *mut
.try_into_option()?;
let led_enabled: Option<bool> = kwargs.get(Qstr::MP_QSTR_led_enabled)?.try_into_option()?;
let about_items: Obj = kwargs.get(Qstr::MP_QSTR_about_items)?;
+ let production_year: Option<TString> = kwargs
+ .get(Qstr::MP_QSTR_production_year)?
+ .try_into_option()?;
let layout = ModelUI::show_device_menu(
init_submenu_idx,
backup_failed,
@@ -1001,6 +1004,7 @@ extern "C" fn new_show_device_menu(n_args: usize, args: *const Obj, kwargs: *mut
haptics_enabled,
led_enabled,
about_items,
+ production_year,
)?;
let layout_obj = LayoutObj::new_root(layout)?;
@@ -1977,6 +1981,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// haptics_enabled: bool | None,
/// led_enabled: bool | None,
/// about_items: Sequence[tuple[str | None, StrOrBytes | None, bool | None]],
+ /// production_year: str | None,
/// ) -> LayoutObj[UiResult | tuple[int, int | None, int]]:
/// """Show the device menu. Result is either CANCELLED or a tuple (action, action_arg, parent_menu_id)."""
Qstr::MP_QSTR_show_device_menu => obj_fn_kw!(0, new_show_device_menu).as_obj(),
diff --git a/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs b/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
index 6b0d4813..d1805aa8 100644
--- a/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
@@ -948,6 +948,7 @@ impl FirmwareUI for UIBolt {
_haptics_enabled: Option<bool>,
_led_enabled: Option<bool>,
_about_items: Obj,
+ _production_year: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error> {
Err::<RootComponent<Empty, ModelUI>, Error>(Error::NotImplementedError)
}
diff --git a/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs b/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
index 0b4d22fd..8c6ade02 100644
--- a/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
@@ -1145,6 +1145,7 @@ impl FirmwareUI for UICaesar {
_haptics_enabled: Option<bool>,
_led_enabled: Option<bool>,
_about_items: Obj,
+ _production_year: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error> {
Err::<RootComponent<Empty, ModelUI>, Error>(Error::NotImplementedError)
}
diff --git a/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs b/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
index 62b9b373..c12b1b37 100644
--- a/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
@@ -1034,6 +1034,7 @@ impl FirmwareUI for UIDelizia {
_haptics_enabled: Option<bool>,
_led_enabled: Option<bool>,
_about_items: Obj,
+ _production_year: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error> {
Err::<RootComponent<Empty, ModelUI>, Error>(Error::NotImplementedError)
}
diff --git a/core/embed/rust/src/ui/layout_eckhart/firmware/device_menu_screen.rs b/core/embed/rust/src/ui/layout_eckhart/firmware/device_menu_screen.rs
index f6208e97..7cfb1ad8 100644
--- a/core/embed/rust/src/ui/layout_eckhart/firmware/device_menu_screen.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/firmware/device_menu_screen.rs
@@ -272,6 +272,9 @@ pub struct DeviceMenuScreen {
// Integer argument for DeviceMenuMsg::RefreshMenu and DeviceMenuMsg::UnpairDevice
pub result_arg: Option<u8>,
+
+ // Production year string for Regulatory screen
+ production_year: Option<TString<'static>>,
}
impl DeviceMenuScreen {
@@ -292,6 +295,7 @@ impl DeviceMenuScreen {
haptics_enabled: Option<bool>,
led_enabled: Option<bool>,
about_items: Obj,
+ production_year: Option<TString<'static>>,
) -> Result<Self, Error> {
let mut screen = Self {
bounds: Rect::zero(),
@@ -302,6 +306,7 @@ impl DeviceMenuScreen {
subscreens: Vec::new(),
submenu_index: [None; MAX_SUBMENUS],
result_arg: None,
+ production_year,
};
if pin_enabled.is_some()
@@ -882,7 +887,8 @@ impl DeviceMenuScreen {
);
}
Subscreen::RegulatoryScreen => {
- *self.active_screen.deref_mut() = ActiveScreen::Regulatory(RegulatoryScreen::new());
+ *self.active_screen.deref_mut() =
+ ActiveScreen::Regulatory(RegulatoryScreen::new(self.production_year));
}
Subscreen::BackupInfoScreen => {
*self.active_screen.deref_mut() = ActiveScreen::BackupInfo(
diff --git a/core/embed/rust/src/ui/layout_eckhart/firmware/regulatory_screen.rs b/core/embed/rust/src/ui/layout_eckhart/firmware/regulatory_screen.rs
index 8eb739dc..a653aafc 100644
--- a/core/embed/rust/src/ui/layout_eckhart/firmware/regulatory_screen.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/firmware/regulatory_screen.rs
@@ -1,4 +1,5 @@
use crate::{
+ strutil::TString,
translations::TR,
ui::{
component::{
@@ -35,15 +36,22 @@ pub enum RegulatoryMsg {
}
struct RegulatoryZone {
+ /// Name of the regulatory zone.
name: Option<&'static str>,
+ /// Main regulatory text content for this zone.
content: &'static str,
+ /// First icon to display for this regulatory zone.
icon1: Option<Icon>,
+ /// Second icon to display for this regulatory zone.
icon2: Option<Icon>,
+ /// When true, the production year should be displayed for this regulatory
+ /// zone below the last icon.
+ production_year: bool,
}
impl RegulatoryScreen {
- pub fn new() -> Self {
- let content = RegulatoryContent::new();
+ pub fn new(production_year: Option<TString<'static>>) -> Self {
+ let content = RegulatoryContent::new(production_year);
let mut action_bar = ActionBar::new_paginate_only();
// Set action bar page counter
action_bar.update(content.pager());
@@ -145,73 +153,105 @@ impl crate::trace::Trace for RegulatoryScreen {
struct RegulatoryContent {
area: Rect,
pager: Pager,
+ production_year: Option<TString<'static>>,
}
impl RegulatoryContent {
- const SCREENS: usize = 8;
- const ZONES: [RegulatoryZone; RegulatoryContent::SCREENS] = [
+ const SCREENS: usize = 12;
+ /// Regulatory zones data. EU, US, CA first, then alphabetical order.
+ const ZONES: [RegulatoryZone; Self::SCREENS] = [
+ RegulatoryZone {
+ name: Some("Europe / UK"),
+ content: "Trezor Company s.r.o.\nKundratka 2359/17a\nPrague 8, Czech Republic",
+ icon1: Some(theme::ICON_EUROPE),
+ icon2: None,
+ production_year: false,
+ },
RegulatoryZone {
name: Some("United States"),
content: "FCC ID: VUI-TS7A01",
icon1: Some(theme::ICON_FCC),
icon2: None,
+ production_year: false,
},
RegulatoryZone {
name: None,
content: "This device complies with Part 15 of the FCC Rules. Operation is subject to two conditions: (1) it may not cause harmful interference, and (2) it must accept any interference, including that which causes undesired operation.",
icon1: None,
icon2: None,
+ production_year: false,
},
RegulatoryZone {
name: Some("Canada"),
content: "IC: 7582A-TS7A01\nCAN ICES-003(B) /\nNMB-003(B)",
icon1: None,
icon2: None,
+ production_year: false,
},
RegulatoryZone {
- name: Some("Europe / UK"),
- content: "Trezor Company s.r.o.\nKundratka 2359/17a\nPrague 8, Czech Republic",
- icon1: Some(theme::ICON_EUROPE),
+ name: Some("Argentina"),
+ content: "",
+ icon1: Some(theme::ICON_ARGENTINA),
icon2: None,
+ production_year: false,
},
RegulatoryZone {
name: Some("Australia /\nNew Zealand"),
content: "",
icon1: Some(theme::ICON_RCM),
icon2: None,
+ production_year: false,
},
RegulatoryZone {
- name: Some("Ukraine"),
+ name: Some("Japan"),
content: "",
- icon1: Some(theme::ICON_UKRAINE),
+ icon1: Some(theme::ICON_JAPAN_1),
+ icon2: Some(theme::ICON_JAPAN_2),
+ production_year: false,
+ },
+ RegulatoryZone {
+ name: Some("Singapore"),
+ content: "",
+ icon1: Some(theme::ICON_SINGAPORE),
icon2: None,
+ production_year: false,
},
- // TODO: add Japan when certification completed
- // RegulatoryZone {
- // name: Some("Japan"),
- // content: "",
- // icon1: Some(theme::ICON_JAPAN),
- // icon2: Some(theme::ICON_JAPAN_2),
- // },
RegulatoryZone {
name: Some("South Korea"),
content: "",
- icon1: Some(theme::ICON_KOREA),
+ icon1: Some(theme::ICON_KOREA_1),
icon2: None,
+ production_year: true,
+ },
+ RegulatoryZone {
+ name: Some("South Korea"),
+ content: "",
+ icon1: Some(theme::ICON_KOREA_2),
+ icon2: Some(theme::ICON_KOREA_3),
+ production_year: false,
},
RegulatoryZone {
name: Some("Taiwan"),
content: "",
icon1: Some(theme::ICON_TAIWAN),
icon2: None,
+ production_year: false,
+ },
+ RegulatoryZone {
+ name: Some("Ukraine"),
+ content: "",
+ icon1: Some(theme::ICON_UKRAINE),
+ icon2: None,
+ production_year: false,
},
];
- pub fn new() -> Self {
+ pub fn new(production_year: Option<TString<'static>>) -> Self {
let pager = Pager::new(Self::SCREENS as u16);
Self {
area: Rect::zero(),
pager,
+ production_year,
}
}
@@ -305,11 +345,29 @@ impl Component for RegulatoryContent {
rest
};
- if let Some(icon2) = zone.icon2 {
+ let rest = if let Some(icon2) = zone.icon2 {
ToifImage::new(rest.top_left(), icon2.toif)
.with_align(Alignment2D::TOP_LEFT)
.with_fg(theme::GREY_LIGHT)
.render(target);
+ rest.split_top(icon2.toif.height()).1
+ } else {
+ rest
+ };
+
+ if zone.production_year {
+ self.production_year
+ .unwrap_or_else(|| TString::from_str("(N/A)"))
+ .map(|t| {
+ self.render_from_top(
+ rest,
+ theme::TEXT_SMALL_GREY,
+ Alignment::Start,
+ t,
+ theme::TEXT_VERTICAL_SPACING,
+ target,
+ );
+ });
}
}
}
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/europe.png b/core/embed/rust/src/ui/layout_eckhart/res/europe.png
deleted file mode 100644
index 183c7be8..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/europe.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/europe.toif b/core/embed/rust/src/ui/layout_eckhart/res/europe.toif
deleted file mode 100644
index a0390ace..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/europe.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/fcc.png b/core/embed/rust/src/ui/layout_eckhart/res/fcc.png
deleted file mode 100644
index ebecacbc..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/fcc.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/fcc.toif b/core/embed/rust/src/ui/layout_eckhart/res/fcc.toif
deleted file mode 100644
index dc1fdde6..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/fcc.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/japan.png b/core/embed/rust/src/ui/layout_eckhart/res/japan.png
deleted file mode 100644
index 13d95e25..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/japan.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/japan.toif b/core/embed/rust/src/ui/layout_eckhart/res/japan.toif
deleted file mode 100644
index ac7de069..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/japan.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/japan_2.png b/core/embed/rust/src/ui/layout_eckhart/res/japan_2.png
deleted file mode 100644
index ce942ed7..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/japan_2.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/japan_2.toif b/core/embed/rust/src/ui/layout_eckhart/res/japan_2.toif
deleted file mode 100644
index 5c51c609..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/japan_2.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/korea.png b/core/embed/rust/src/ui/layout_eckhart/res/korea.png
deleted file mode 100644
index f269ad24..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/korea.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/korea.toif b/core/embed/rust/src/ui/layout_eckhart/res/korea.toif
deleted file mode 100644
index a19ef732..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/korea.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/korea_full.png b/core/embed/rust/src/ui/layout_eckhart/res/korea_full.png
deleted file mode 100644
index c56f7195..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/korea_full.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/korea_full.toif b/core/embed/rust/src/ui/layout_eckhart/res/korea_full.toif
deleted file mode 100644
index 4960e562..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/korea_full.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/rcm.png b/core/embed/rust/src/ui/layout_eckhart/res/rcm.png
deleted file mode 100644
index 2bbdc298..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/rcm.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/rcm.toif b/core/embed/rust/src/ui/layout_eckhart/res/rcm.toif
deleted file mode 100644
index 158ad92f..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/rcm.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/argentina.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/argentina.png
new file mode 100644
index 00000000..371b0acc
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/argentina.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/argentina.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/argentina.toif
new file mode 100644
index 00000000..fab6b439
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/argentina.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/europe.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/europe.png
new file mode 100644
index 00000000..183c7be8
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/europe.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/europe.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/europe.toif
new file mode 100644
index 00000000..a0390ace
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/europe.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/fcc.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/fcc.png
new file mode 100644
index 00000000..ebecacbc
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/fcc.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/fcc.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/fcc.toif
new file mode 100644
index 00000000..dc1fdde6
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/fcc.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_1.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_1.png
new file mode 100644
index 00000000..531eada7
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_1.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_1.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_1.toif
new file mode 100644
index 00000000..a67ce329
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_1.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_2.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_2.png
new file mode 100644
index 00000000..13d95e25
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_2.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_2.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_2.toif
new file mode 100644
index 00000000..ac7de069
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/japan_2.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_1.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_1.png
new file mode 100644
index 00000000..73eaab8b
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_1.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_1.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_1.toif
new file mode 100644
index 00000000..802a4d10
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_1.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_2.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_2.png
new file mode 100644
index 00000000..fcbe80c3
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_2.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_2.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_2.toif
new file mode 100644
index 00000000..0a7c6e89
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_2.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_3.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_3.png
new file mode 100644
index 00000000..9842b74a
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_3.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_3.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_3.toif
new file mode 100644
index 00000000..42be6392
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/korea_3.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/rcm.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/rcm.png
new file mode 100644
index 00000000..2bbdc298
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/rcm.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/rcm.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/rcm.toif
new file mode 100644
index 00000000..158ad92f
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/rcm.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/singapore.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/singapore.png
new file mode 100644
index 00000000..59568027
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/singapore.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/singapore.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/singapore.toif
new file mode 100644
index 00000000..8c360138
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/singapore.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/taiwan.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/taiwan.png
new file mode 100644
index 00000000..9ec03c27
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/taiwan.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/taiwan.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/taiwan.toif
new file mode 100644
index 00000000..83fb822c
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/taiwan.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/ukraine.png b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/ukraine.png
new file mode 100644
index 00000000..fe7025b5
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/ukraine.png differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/regulatory/ukraine.toif b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/ukraine.toif
new file mode 100644
index 00000000..fddf3f33
Binary files /dev/null and b/core/embed/rust/src/ui/layout_eckhart/res/regulatory/ukraine.toif differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/taiwan.png b/core/embed/rust/src/ui/layout_eckhart/res/taiwan.png
deleted file mode 100644
index 0c97eb3d..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/taiwan.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/taiwan.toif b/core/embed/rust/src/ui/layout_eckhart/res/taiwan.toif
deleted file mode 100644
index f033928d..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/taiwan.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/ukraine.png b/core/embed/rust/src/ui/layout_eckhart/res/ukraine.png
deleted file mode 100644
index fe7025b5..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/ukraine.png and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/res/ukraine.toif b/core/embed/rust/src/ui/layout_eckhart/res/ukraine.toif
deleted file mode 100644
index fddf3f33..00000000
Binary files a/core/embed/rust/src/ui/layout_eckhart/res/ukraine.toif and /dev/null differ
diff --git a/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs b/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs
index b3904fcc..fa96d9af 100644
--- a/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs
@@ -187,14 +187,24 @@ include_icon!(ICON_TROPIC, "layout_eckhart/res/tropic.toif");
include_icon!(ICON_SECURED, "layout_eckhart/res/secured.toif");
// Regulatory screen icons
-include_icon!(ICON_UKRAINE, "layout_eckhart/res/ukraine.toif");
-include_icon!(ICON_JAPAN, "layout_eckhart/res/japan.toif");
-include_icon!(ICON_JAPAN_2, "layout_eckhart/res/japan_2.toif");
-include_icon!(ICON_KOREA, "layout_eckhart/res/korea_full.toif");
-include_icon!(ICON_EUROPE, "layout_eckhart/res/europe.toif");
-include_icon!(ICON_RCM, "layout_eckhart/res/rcm.toif");
-include_icon!(ICON_FCC, "layout_eckhart/res/fcc.toif");
-include_icon!(ICON_TAIWAN, "layout_eckhart/res/taiwan.toif");
+include_icon!(
+ ICON_ARGENTINA,
+ "layout_eckhart/res/regulatory/argentina.toif"
+);
+include_icon!(ICON_EUROPE, "layout_eckhart/res/regulatory/europe.toif");
+include_icon!(ICON_FCC, "layout_eckhart/res/regulatory/fcc.toif");
+include_icon!(ICON_JAPAN_1, "layout_eckhart/res/regulatory/japan_1.toif");
+include_icon!(ICON_JAPAN_2, "layout_eckhart/res/regulatory/japan_2.toif");
+include_icon!(ICON_KOREA_1, "layout_eckhart/res/regulatory/korea_1.toif");
+include_icon!(ICON_KOREA_2, "layout_eckhart/res/regulatory/korea_2.toif");
+include_icon!(ICON_KOREA_3, "layout_eckhart/res/regulatory/korea_3.toif");
+include_icon!(ICON_RCM, "layout_eckhart/res/regulatory/rcm.toif");
+include_icon!(
+ ICON_SINGAPORE,
+ "layout_eckhart/res/regulatory/singapore.toif"
+);
+include_icon!(ICON_TAIWAN, "layout_eckhart/res/regulatory/taiwan.toif");
+include_icon!(ICON_UKRAINE, "layout_eckhart/res/regulatory/ukraine.toif");
// Square icon for BLE connection items
include_icon!(ICON_SQUARE, "layout_eckhart/res/square.toif");
diff --git a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
index 861121a6..c84fc79b 100644
--- a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
@@ -1221,6 +1221,7 @@ impl FirmwareUI for UIEckhart {
haptics_enabled: Option<bool>,
led_enabled: Option<bool>,
about_items: Obj,
+ production_year: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error> {
let layout = RootComponent::new(DeviceMenuScreen::new(
init_submenu_idx,
@@ -1238,6 +1239,7 @@ impl FirmwareUI for UIEckhart {
haptics_enabled,
led_enabled,
about_items,
+ production_year,
)?);
Ok(layout)
}
diff --git a/core/embed/rust/src/ui/ui_firmware.rs b/core/embed/rust/src/ui/ui_firmware.rs
index da069c2c..ef1d1271 100644
--- a/core/embed/rust/src/ui/ui_firmware.rs
+++ b/core/embed/rust/src/ui/ui_firmware.rs
@@ -376,6 +376,7 @@ pub trait FirmwareUI {
haptics_enabled: Option<bool>,
led_enabled: Option<bool>,
about_items: Obj,
+ production_year: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_pairing_device_name(
diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi
index 09b2cbb2..10d407af 100644
--- a/core/mocks/generated/trezorui_api.pyi
+++ b/core/mocks/generated/trezorui_api.pyi
@@ -639,6 +639,7 @@ def show_device_menu(
haptics_enabled: bool | None,
led_enabled: bool | None,
about_items: Sequence[tuple[str | None, StrOrBytes | None, bool | None]],
+ production_year: str | None,
) -> LayoutObj[UiResult | tuple[int, int | None, int]]:
"""Show the device menu. Result is either CANCELLED or a tuple (action, action_arg, parent_menu_id)."""
diff --git a/core/src/apps/homescreen/device_menu.py b/core/src/apps/homescreen/device_menu.py
index 1c7f3f3b..a1ae81ca 100644
--- a/core/src/apps/homescreen/device_menu.py
+++ b/core/src/apps/homescreen/device_menu.py
@@ -30,6 +30,14 @@ def _get_hostinfo(
return (mac, None)
+def _get_production_year() -> str | None:
+ production_date = utils.unit_production_date()
+ if production_date is None:
+ return None
+ year, _, _ = production_date
+ return f"({year})"
+
+
def _find_device(connected_addr: bytes | None, bonds: list[bytes]) -> int | None:
if connected_addr is None:
return None
@@ -106,6 +114,7 @@ async def handle_device_menu() -> None:
firmware_version = ".".join(map(str, utils.VERSION))
firmware_type = "Bitcoin-only" if utils.BITCOIN_ONLY else "Universal"
+ production_year = _get_production_year()
menu_result = await interact(
trezorui_api.show_device_menu(
@@ -142,6 +151,7 @@ async def handle_device_menu() -> None:
(TR.homescreen__firmware_type, firmware_type, False),
(TR.ble__version, bluetooth_version, False),
],
+ production_year=production_year,
),
"device_menu",
raise_on_cancel=None,
diff --git a/tests/click_tests/device_menu/common.py b/tests/click_tests/device_menu/common.py
index b2629b63..5ff1a87c 100644
--- a/tests/click_tests/device_menu/common.py
+++ b/tests/click_tests/device_menu/common.py
@@ -30,15 +30,18 @@ if TYPE_CHECKING:
PIN4 = "1234"
REGULATORY_AREAS = [
+ "Europe",
"United States",
"", # additional information to the US regulations
"Canada",
- "Europe",
+ "Argentina",
"Australia",
- "Ukraine",
- # "Japan",
+ "Japan",
+ "Singapore",
"South Korea",
+ "South Korea", # additional page for South Korea
"Taiwan",
+ "Ukraine",
]
AUTOLOCK_DELAY_USB_DEFAULT_MS = 10 * 60 * 1000 # 10 minutes
diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json
index 44caf84f..ef6c71f6 100644
--- a/tests/ui_tests/fixtures.json
+++ b/tests/ui_tests/fixtures.json
@@ -29415,9 +29415,9 @@
"T3W1_cs_device_menu-test_pin.py::test_pin_remove": "d72a27002db672610b8255f20df897ff8ca6a3c5b1bdfea74d37e41c1a889310",
"T3W1_cs_device_menu-test_pin.py::test_pin_setup": "fd606de05bb1cde14ba1e87c5b8c7e5d5f67524d01606e792886eff1d0d2aa5c",
"T3W1_cs_device_menu-test_pin.py::test_pin_uninitialized": "987d1c62e6576b9cc24373e00df522efdc9736af978d6032f7d319af8daaef5d",
-"T3W1_cs_device_menu-test_traverse_menu.py::test_traverse_initialized": "62dc24563f0aae528a45b72fdf4351fbd1bf80afc8804ddae641a17cdfbecaa5",
-"T3W1_cs_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "ecb82136cd599194c7c1c1374a8a8791f9fd21fab25535abc2e9a7ddaff15fc2",
-"T3W1_cs_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "4576c117f135f88addde94cea9f495dda11b6168d7a29c43fb7eab116a452c8b",
+"T3W1_cs_device_menu-test_traverse_menu.py::test_traverse_initialized": "becb57eb05b8cd26023fc655ddf181530e35c6d834c80ce98ddc05a2b351c356",
+"T3W1_cs_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "a090a94d3fc4d1a3850f8c9d81fefab3401cfbc766b070c0a7c80c6fbbfcc494",
+"T3W1_cs_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "9709976267a8dbbf7d2bc0917b6cf1504b0b2ba98e950b4e66f0ac50061ef5f5",
"T3W1_cs_device_menu-test_wipe_code.py::test_remove_pin_without_removing_wipe_code": "ccd5d4fbe74c4ad28e33b33cb22d890a61c352842b07ea6f4de2ef0a1a8645e5",
"T3W1_cs_device_menu-test_wipe_code.py::test_wipe_code_cancel_intro": "5b7dffec3a06e745a3f74b891548a565997dcbb9476a3d1111ca21dd352e6f56",
"T3W1_cs_device_menu-test_wipe_code.py::test_wipe_code_cancel_keyboard": "dc4c3184569241beb07d1e1492cd4289b51adef08172e2f0aeafb1580ec448e5",
@@ -29519,9 +29519,9 @@
"T3W1_de_device_menu-test_pin.py::test_pin_remove": "94561b2d76202520fb8297733bf20feaf73c447a20432d8326066e7fa64173db",
"T3W1_de_device_menu-test_pin.py::test_pin_setup": "14df54d25c57d02e391bab64fd7d4fc99a286268b65dffa84ea29d0976cac0d2",
"T3W1_de_device_menu-test_pin.py::test_pin_uninitialized": "987d1c62e6576b9cc24373e00df522efdc9736af978d6032f7d319af8daaef5d",
-"T3W1_de_device_menu-test_traverse_menu.py::test_traverse_initialized": "e93043444cacbc5cfffa875c1970e46b56741ec25e29381b49f3b1c4c0c13c3e",
-"T3W1_de_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "4a3bca6687a0fa0dc0a1604e3c9405ec2f172cc02f1324d31e35fc2813058512",
-"T3W1_de_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "df0d510f1efba8054d0cbbcfe3067fd080d344784cc08306e42788c689a0df9a",
+"T3W1_de_device_menu-test_traverse_menu.py::test_traverse_initialized": "00292a990286b2aa9eef5a5017e27c98c3cc6d754ae40c5ec0443ce533c559a0",
+"T3W1_de_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "01ca383852304f489ac07bd8e2a11090029b56fe7e24319f7ea9a75eae7f7c43",
+"T3W1_de_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "4b42b684883b933a610472b01a8d465558279163438c91090de822d4b60c9d5e",
"T3W1_de_device_menu-test_wipe_code.py::test_remove_pin_without_removing_wipe_code": "2045aba4341691d08098e4cf0b1290d06b9a975dbe95c7dba62b0b79626d2a80",
"T3W1_de_device_menu-test_wipe_code.py::test_wipe_code_cancel_intro": "2db8bfa8d72e3a3227c1c61c85f86ff1569b042c63e9c69228b6d5830982b164",
"T3W1_de_device_menu-test_wipe_code.py::test_wipe_code_cancel_keyboard": "617c889adbeb0aa822f55a9d9463c4ed2ba2993ca834bc1da944975af373589b",
@@ -29623,9 +29623,9 @@
"T3W1_en_device_menu-test_pin.py::test_pin_remove": "9eed511b691a10f63a16e774435b48ae86f8363657498ad29e7541a15ad37c92",
"T3W1_en_device_menu-test_pin.py::test_pin_setup": "d2ab5a53b75280c1aac10ca49ca5a7d93565edd60b07c156340a5c2edf7e033e",
"T3W1_en_device_menu-test_pin.py::test_pin_uninitialized": "987d1c62e6576b9cc24373e00df522efdc9736af978d6032f7d319af8daaef5d",
-"T3W1_en_device_menu-test_traverse_menu.py::test_traverse_initialized": "3f475e80ea788b55f354da6101e41e47fbdfc79d7a3c2c82e64db53a1463b65a",
-"T3W1_en_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "abcb9a7e1dacd4c5da2897ff36afe52e96191012a7d577359fdb45f1834877c7",
-"T3W1_en_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "b5588195e45ef8afb8288716ea7af277fe93855be148bcf4a503e04d9a2ccc98",
+"T3W1_en_device_menu-test_traverse_menu.py::test_traverse_initialized": "e626aa27ddbbcfa7cfad6caafc1f26c805075be5c19973ea617dca3b6cc92e74",
+"T3W1_en_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "2b391b6f538f91cfccc1c4ac8d027f80e8195d8475fe1b4c41ba9fd961f6fe20",
+"T3W1_en_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "b89c86019460c572b839ff1c4995803ac4d88d66ca256b30c901f26dc19c4d13",
"T3W1_en_device_menu-test_wipe_code.py::test_remove_pin_without_removing_wipe_code": "a29e0d8bf7569003fb3e998cec7b4b8422dcafac6f7098e8e4cb2f47bab89275",
"T3W1_en_device_menu-test_wipe_code.py::test_wipe_code_cancel_intro": "5fa6cf25dc33a38d25dfdb8e7bff066c9018d42f25365773a7973befacb6b168",
"T3W1_en_device_menu-test_wipe_code.py::test_wipe_code_cancel_keyboard": "ff70e282a496ffe05feb2682eee6711be347f4b87c7e334666cde71241ae3696",
@@ -29727,9 +29727,9 @@
"T3W1_es_device_menu-test_pin.py::test_pin_remove": "4f6b6267ec09c5ad845ff3fd1b2334bb1651d3917b16af553c16fd85ded925f2",
"T3W1_es_device_menu-test_pin.py::test_pin_setup": "1a42408f464fd94fac440e7348145e903f7d27f80cece3de5d1a10e975423fdc",
"T3W1_es_device_menu-test_pin.py::test_pin_uninitialized": "987d1c62e6576b9cc24373e00df522efdc9736af978d6032f7d319af8daaef5d",
-"T3W1_es_device_menu-test_traverse_menu.py::test_traverse_initialized": "5ca82e77d94e09431146df2d9b4a000effb90e77d268c5e783a6aa88c22a52a4",
-"T3W1_es_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "19168c97e23b2638feb765fcc88df82971cba8eb443fec03597b792b5481ea3e",
-"T3W1_es_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "0be8cee10e555b6c449e0b8b86b489852036e0b664ae858be7333d0bf6722428",
+"T3W1_es_device_menu-test_traverse_menu.py::test_traverse_initialized": "62a21625aeff2d45b54d2a4231c62b15adb3244c805106c95297bc30bf3cfb04",
+"T3W1_es_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "2ef32c929c9276aaa738ce5f92d3679887338bfc5384a5b6c7f9b4e3bd0e1569",
+"T3W1_es_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "15d4c71c516a696b0b11b0781c545b2fbe8a3f5585bd352bbb723c1b66790c82",
"T3W1_es_device_menu-test_wipe_code.py::test_remove_pin_without_removing_wipe_code": "f42b6747e6e2557a19810aeed307eea887b685a651e3a95a0f4739599aa76948",
"T3W1_es_device_menu-test_wipe_code.py::test_wipe_code_cancel_intro": "429b2f5ccf2b4167f76a4a50a0577aadd726ce798db6674e7ad609a7ed9d037a",
"T3W1_es_device_menu-test_wipe_code.py::test_wipe_code_cancel_keyboard": "ed4d5b3889992fbf4a94cb7eb6600797099f5ed256de3cc7035e8bb6bb45b347",
@@ -29831,9 +29831,9 @@
"T3W1_fr_device_menu-test_pin.py::test_pin_remove": "78dfe7003b2c6e4d29d152ca4857c3da41e6d189ad3646a6394013f0c6a7dffb",
"T3W1_fr_device_menu-test_pin.py::test_pin_setup": "586a8ca22a13ca5d0436624a1c482ab665d1f6d234539bb42c34754ac3ccb3ef",
"T3W1_fr_device_menu-test_pin.py::test_pin_uninitialized": "987d1c62e6576b9cc24373e00df522efdc9736af978d6032f7d319af8daaef5d",
-"T3W1_fr_device_menu-test_traverse_menu.py::test_traverse_initialized": "6f04cf3af1635def6442dda8ff156535da47001fe286b69c06a99a9e8367aa92",
-"T3W1_fr_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "cc70bff5ce18f86e8cdb1669e0d91a9770881a0588bbf5c2e1a48adb98317465",
-"T3W1_fr_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "6c0a784b31e8ea155046696bc939b52ec0531d7f4151f2d1a08c51040bba8679",
+"T3W1_fr_device_menu-test_traverse_menu.py::test_traverse_initialized": "2350203fe26592820beda0003e3d388805d5073e7f10ea53f2350fb4e99373f4",
+"T3W1_fr_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "10d579c084564ead5bd2ba079f6c344eb7db48cf60b8d9d7e57130901fd10fd6",
+"T3W1_fr_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "2955ba937cee85d1cabec41920f08426ca1b7ed251913a6595a3e661971ef940",
"T3W1_fr_device_menu-test_wipe_code.py::test_remove_pin_without_removing_wipe_code": "96d96124c0072f1a92e3a4e09915890978131c48ba8dcb5dcaa911eabf9b89ba",
"T3W1_fr_device_menu-test_wipe_code.py::test_wipe_code_cancel_intro": "374578c1c6a8ce977151d338db5d33d4fb5ed4112cb414ad6a773517dfde48a7",
"T3W1_fr_device_menu-test_wipe_code.py::test_wipe_code_cancel_keyboard": "6a1906ddb0e20e227f352ed9a6cea9bf71e6a6f2587cef9693ed8a8773b85874",
@@ -29935,9 +29935,9 @@
"T3W1_pt_device_menu-test_pin.py::test_pin_remove": "30174a0770eacf3d2c0848477a79532b0b13e1b87d29b58bb7c8f0e74c11c5f3",
"T3W1_pt_device_menu-test_pin.py::test_pin_setup": "c2ea8a0e636a34a374237925afac85183aa22bfe74a4707f9e418c262f26352b",
"T3W1_pt_device_menu-test_pin.py::test_pin_uninitialized": "987d1c62e6576b9cc24373e00df522efdc9736af978d6032f7d319af8daaef5d",
-"T3W1_pt_device_menu-test_traverse_menu.py::test_traverse_initialized": "db853e454d5b299f84c551d44adba17cc236fe3118da6d8a89c693c9075e325b",
-"T3W1_pt_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "00106ec52aa7722c36bac1271f6e9188170eb4288a95acd748cdcd09128742de",
-"T3W1_pt_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "52ebc8bc2146433c2511b4f723a0a635c09e9d3fe51ee01e9e2974636cc24d25",
+"T3W1_pt_device_menu-test_traverse_menu.py::test_traverse_initialized": "b9cc50d8dc971a9aac7cbd7103e454f516cd7d52f3f04c46aed309894bc07e45",
+"T3W1_pt_device_menu-test_traverse_menu.py::test_traverse_initialized_no_pin": "4ad7c75e32a71d1c84965b7e1c21164364054b49f0665e86c4037538c8fc060b",
+"T3W1_pt_device_menu-test_traverse_menu.py::test_traverse_uninitialized": "4666f8ee06377d9bb084905b1c2a2dd4f055fa2f79a1d5bce9e62cc489c0ab77",
"T3W1_pt_device_menu-test_wipe_code.py::test_remove_pin_without_removing_wipe_code": "fd7416f2b10d5b75afe68616300a294274636cba88dbd1dab0cf0128cf6d9064",
"T3W1_pt_device_menu-test_wipe_code.py::test_wipe_code_cancel_intro": "220f91649961feeaaf0b2df1a5170d2c2f5247385a013146e43dda3236c568f2",
"T3W1_pt_device_menu-test_wipe_code.py::test_wipe_code_cancel_keyboard": "e95e21dbb120c0e3b9d4f7b09c9e928bb4688b5a90028dfa47cfb9e5c0dbc920",
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.