From 25374362119c4f97189dfee01cc61140fdf76919 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Fri, 10 Mar 2023 18:26:42 +0100 Subject: [PATCH] feat(core): update bootloader style [no changelog] --- core/assets/check40.png | Bin 0 -> 6608 bytes core/assets/{menu.png => download32.png} | Bin 5194 -> 4820 bytes core/assets/erase_big.png | Bin 9543 -> 0 bytes core/assets/fire24.png | Bin 0 -> 6887 bytes core/assets/fire32.png | Bin 0 -> 5082 bytes core/assets/fire40.png | Bin 0 -> 9138 bytes core/assets/{close.png => menu32.png} | Bin 4782 -> 4672 bytes core/assets/refresh24.png | Bin 0 -> 6963 bytes core/assets/warning40.png | Bin 0 -> 9207 bytes core/embed/bootloader/bootui.c | 4 +- core/embed/bootloader/main.c | 2 + core/embed/rust/src/ui/component/pad.rs | 7 + .../src/ui/model_tt/bootloader/confirm.rs | 171 ++++++++++------ .../rust/src/ui/model_tt/bootloader/intro.rs | 39 ++-- .../rust/src/ui/model_tt/bootloader/menu.rs | 51 +++-- .../rust/src/ui/model_tt/bootloader/mod.rs | 164 ++++++++-------- .../rust/src/ui/model_tt/bootloader/theme.rs | 185 ++++++++---------- .../rust/src/ui/model_tt/component/result.rs | 34 ++-- .../rust/src/ui/model_tt/res/check40.toif | Bin 0 -> 87 bytes .../embed/rust/src/ui/model_tt/res/close.toif | Bin 94 -> 0 bytes .../rust/src/ui/model_tt/res/download32.toif | Bin 0 -> 107 bytes .../rust/src/ui/model_tt/res/erase_big.toif | Bin 220 -> 0 bytes .../rust/src/ui/model_tt/res/fire24.toif | Bin 0 -> 176 bytes .../rust/src/ui/model_tt/res/fire32.toif | Bin 0 -> 235 bytes .../rust/src/ui/model_tt/res/fire40.toif | Bin 0 -> 285 bytes core/embed/rust/src/ui/model_tt/res/menu.toif | Bin 47 -> 0 bytes .../rust/src/ui/model_tt/res/menu32.toif | Bin 0 -> 29 bytes .../rust/src/ui/model_tt/res/reboot.toif | Bin 126 -> 0 bytes .../rust/src/ui/model_tt/res/refresh24.toif | Bin 0 -> 159 bytes .../rust/src/ui/model_tt/res/warning40.toif | Bin 0 -> 258 bytes core/embed/rust/src/ui/model_tt/screens.rs | 23 ++- core/embed/rust/src/ui/model_tt/theme.rs | 15 +- 32 files changed, 386 insertions(+), 309 deletions(-) create mode 100644 core/assets/check40.png rename core/assets/{menu.png => download32.png} (55%) delete mode 100644 core/assets/erase_big.png create mode 100644 core/assets/fire24.png create mode 100644 core/assets/fire32.png create mode 100644 core/assets/fire40.png rename core/assets/{close.png => menu32.png} (60%) create mode 100644 core/assets/refresh24.png create mode 100644 core/assets/warning40.png create mode 100644 core/embed/rust/src/ui/model_tt/res/check40.toif delete mode 100644 core/embed/rust/src/ui/model_tt/res/close.toif create mode 100644 core/embed/rust/src/ui/model_tt/res/download32.toif delete mode 100644 core/embed/rust/src/ui/model_tt/res/erase_big.toif create mode 100644 core/embed/rust/src/ui/model_tt/res/fire24.toif create mode 100644 core/embed/rust/src/ui/model_tt/res/fire32.toif create mode 100644 core/embed/rust/src/ui/model_tt/res/fire40.toif delete mode 100644 core/embed/rust/src/ui/model_tt/res/menu.toif create mode 100644 core/embed/rust/src/ui/model_tt/res/menu32.toif delete mode 100644 core/embed/rust/src/ui/model_tt/res/reboot.toif create mode 100644 core/embed/rust/src/ui/model_tt/res/refresh24.toif create mode 100644 core/embed/rust/src/ui/model_tt/res/warning40.toif diff --git a/core/assets/check40.png b/core/assets/check40.png new file mode 100644 index 0000000000000000000000000000000000000000..6e5e48114b63d2bfcc0808b252a845e9c2e275c1 GIT binary patch literal 6608 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 literal 0 HcmV?d00001 diff --git a/core/assets/menu.png b/core/assets/download32.png similarity index 55% rename from core/assets/menu.png rename to core/assets/download32.png index 55027b2da4d71fde67311cbbce583125b7a1215f..bbd7ff7e844b94a9e9c53cc45f30a36a4e70be5d 100644 GIT binary patch delta 1621 zcmV-b2CDhWDAXl?iBL{Q4GJ0x0000DNk~Le0000W0000W2m}BC0NHc0e*gdjh;nv zrylN}s_yEEg($#6mXb`s<+lI+?d~5GCXUXBq%p_1p!n>6GZzeW*-IHMEq=74@SMW) zjolp+43nUj{ZZrezu4&ruy+Nca1}_`IZ5SrgZit?UgwB!?I>wSbjQB^ zdT-jtnz4%FBdCsZQJ1BR5&SArSZZ~E77;UI4=H-98C9{XSE$yOb*ZQ;Wn$>j$y1|3 zowm`hv;v~%&2hqjd1VC`sb2Qs*RDnke*tT!-vl_`pIVZC+M4vMDk*f-4h( z(bxnpR`==)z1vYBTJ+!wxR{M>z%b>kg&P#1K1mIO;7h$PrmH}~U@Y4a$so4wA!?xC zH-QYH1&#szeq1QE82}U^bpRL=C;-)P9w^e1m=h6*R0vc6oyBv70u%x_fMhQcp^dVo z#w&?`hARh#*};y>3`zuvlAukN0eqC_7OHEsDWupySY4clu*y5Hp-SSpCwpth0eGfhM)V1ec4%Mct z5A_ArXsX6TDRWGRYOtns2|;$91k((HvGWAQlSzOL&8FF+1ef4kUG1sYzS+0+&%xX~(A)(wD9CM4CMq6aor*`q55uPJ@I3~Z-y~ff0?yc!V)H_=DG@%!t(*&&U6d$r0{v)HS!7J)9Whj?&wZHsrUja_jP)2d-r{IUXcF@T-ALK$KSajpX~1z z=-zZe-Uj;oqWHXb?_ubF7^pk^waV@nq23H4XM5SS0003alWzqTf4@q@P!z_0X+@>@ zXHXo(A)sr)#Y`?$AqWaFRm72Fk^{cdz{FpC!s-;cvN z-*@kYmYsxYIkyXGRu!(_8(a>q?1eYlbXaAD?I0}kp68v=cs^gTjJ|Y@SM%JTXFiI{ zP&!j(VO~^V?Tejhf0Y|nv3}e455*5+J4&-i{3PCq(#Wvc_0wb${&Cf&7<8^1vKD{8tzpKgXa4!d zFUFrxRHFpK7qgiLO9CV}V`OG#FfcJKVr4lrEi^DSWi2^nIW#RcW;HQkGBY?ZVP-g! z2nin~VKZVkGi5nsEiy7;FfBA>GGQ$_WH4bZGch$}W;kImGdE>slS>IFBx7Y^HDzUH zVl6gdFf%PQVPr8aIX7W4EoCufWjA3nVqr2lWs{Z(Tn#uhI5IggIXE^jH8(Yr{|VJ3 zF)}k@V=*vcEiz*DfkdzCd~xn!L~EzaAENr1Z1zyeg#~lRV|^ TqVa5x00000NkvXXu0mjfj{fB3 delta 2064 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 SqesEqA(p1QOp14SMEnOpohmT^ literal 0 HcmV?d00001 diff --git a/core/assets/fire32.png b/core/assets/fire32.png new file mode 100644 index 0000000000000000000000000000000000000000..e22e038a716a83c76640e30bc4e46b5a6f540e62 GIT binary patch literal 5082 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 H^@hIy@*uLj literal 0 HcmV?d00001 diff --git a/core/assets/fire40.png b/core/assets/fire40.png new file mode 100644 index 0000000000000000000000000000000000000000..48ee4f203ae4459827da2bacfacad2ff11104ea6 GIT binary patch literal 9138 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 G3j7~bgpAVw literal 0 HcmV?d00001 diff --git a/core/assets/close.png b/core/assets/menu32.png similarity index 60% rename from core/assets/close.png rename to core/assets/menu32.png index e758076743f3258fbac1d092d44ad4953e463da1..383c6e7eb061aafa4ebc60a46342b55a832f60e3 100644 GIT binary patch delta 1490 zcmV;@1ugonCBP(qiBL{Q4GJ0x0000DNk~Le0000W0000W2m}BC0NHc0e*gdjNqSUR zbW&k=AaHVTW@&6?Aar?fWgumEX=VTbc-rlkTXO6u42IuX#Vo;+5E9G5V5(*ZXZiEX zc6*XePb!^0b!r}B%3OpjggzN}r|s9@GyR2&dEu1Rywp;E7F@aJ$_*V~j;rl8EqSl^ zi_a;H-^tT8!4L^rIfhI2^pA+l*iJDLQerM=hNW!D=Vw{HRX-N2( zpwmD*wzZV%_I3;FcC_QR6F=@0mDsWMo00o*HbieIgu=WD$%0zsbU@;kBn=%w9n&Eq z^t1Rbxoru50eKXs>#Fc*hO7CZ(mN_wj~>g@J*~{AirfXcT%9^FMh?m36geb3lM%LSn>=caC3*?Z7iVJepP1lI~|7UYnljZ#q@S=~WxEPYu~ zI#puun3QQyqe`-X3NtFSPEPcnGg)d)dU$!ni z?W;Lf9t2e;7$ZFLbV<)XFlW39M2lasf?v!LY`78RqJ|oX&^&{xdw_4{{tB)Ff*Mhd zSEM4a>tSM5`u8M|9kf7E(H^f0**Fa#L|9tk3<(H;8i`V&#h8r(7Aauk982R7qg|DiAx@CvFarsdA_g{98erwD$REp&9BL|>Rkf(8Yt>ey6MYgn_va>LUN3azcY%9>YAYguje zwXUrreR}TNOSkU5_BMFP!1*!Cu;HVQw$X-vRNC^UTiI;$t!`~1)uyDGr_M5M`mD2E z)K07)$`jP+q{cg`P_&C0q-Hl06vv4MGXTR^gh1Q^0TP;n+2WKl2f1LjR2+Yz3@0_1 z4GLl)m^WgbbYqwJAR6Re;+8DGHe@Dyt_;f_?ECJ*z!-)kQ(XZ5DFG0TG@s9SASYczuQM_3-f+B0;n8?qLEzpY`$ zsb~KA#xKU7P*kG?!WXl^1WN)WVKiiAH(@koEnzb@Vl6abF*hw?G&W={Ff%q}VK*~n zGdN^1lP?D!Br-NQVPa%9H7ztSFk~$>H8(UZVmW0nEjTq|H8*B9HaRn5G?Q`%CnPpw zVK!wjVKOaZWi~V|G&E&7En+fdV=ZQ8Fk)h6HaRpoV>6Sz2V4y}G&nIbIW#smF*7qZ zlO_n&Bs4K)HeokmGc99gF=H(>GC5%_Vr67yEjKe_HD+WsWnncjIg=j=NDMPAF)&mz zF*-CjIx(|z32z7lsPa!WljadENCOHKFb>RF3w8hi04GUAK~zY`V_+Bs!wLMq|DP0a sAEu9KH0Vat!Du=dO$VdtU=$z$01QHox5o{~NdN!<07*qoM6N<$f==0!`v3p{ delta 1651 zcmV-(28{W@B(5cYiBL{Q4GJ0x0000DNk~Le0000G0000G2m}BC0JZuz>Hq)(WqMRt zbW&k=AaHVTW@&6?Aar?fWgumEX=VTbc-p;}ZI+}e42J)+in|1p5E7PyAm`j2+~waF zwd}5snNwOlBP}3?B;JSm5$<|(H%;fgtbW-jRXv|VMbX^LyTKTNmI z-FP@&Fop!JY>%FH`P(>6cbcf6r{5HL-CxZ2FLK=V`-7t0kPMF)owh5=yCUK31?>vT zwyY^-x9>}sm#uBLmH2jtQHia(4<(P!(Gb0+7!>A3NG8-Gy8|+A2~yV1s2zeNhCWL| z9p$zp1msnJoQ^BQqdr`XFNN-?96fqH9v*2$-bLgg$mwWbjtA1$RMyacvmAZz@%{L$ zo2oE9M1S19H}C73v5FECLY?+S-IlWUAUDIrFzo^Q(qy<5Dr_wo#j&d^sI{q1GfJgQ z3|yTeH7e9;S=&k#E=FDg8#>IDWgT=e&Rk{ii=$9~XOk>V94zaKJqjPb&}ueMHLTVg zmK#Bo3CajlPM2_YLhs`!5KVr>3VtzWaGfRc3<9Le4NfwS zOadE!oFtgW6r)v?l`$MJj${TBit}Y)lcfMwjEenZ(Xoe$ibhpUYU-M`BuO!8O3Bhl zip9iYFtuc6ZrO^9M^{g7?w-A5&Vr<=Ic3Y9b1nro3p5wZE)XbX=2_-AYnan)v(I@h z72BuAsx?)sUUMytn>6H)mYOwhxs`<$Y^5cCF1n<}7GLsGI<{Ju&|}x0x^?flmxJ1l z^{JeoMmsfLNew|esA1IXrh-N~(ZLMB@D(8tw}Ai~ng_GVDMlXT2D2$6{fRQ1)WNLL zAO?bQA=XYec7ZpdgWN~lg2g*-e3e`n=uVP*=JtwO8=s-N65CGU2b@1^!0?NAr`vES?fs&T;ZNc4kssg8hfmkE`Qz9}m+U`_gnPa3PCHNS4R!AX`-E5F z+M=Fkh0j9#)rK>O-`Uw8M=4yh|J?pjYM0vZnIB(M!q50K_R$BK=qEDdllkA{|3lO+ z=A$cT?K3rJlK&g(!nF`z$wzOh|7-bw=yb-g0**|g@tJxc-+I|y?bW{Y$uJfYJL~8ye?gTzaLx% zSI*)aHXT-3!w#dW=zHD?t>^O<%jiqjc(u>{c^2ZNilj4D9u;K`*1otmtqa2{Hf{(0 zq4+`U#91DTpTs+H78^FZewI$6A5U|e7jo|$eRsvXmhNbJ4tj_PZwaoOInSZ|V3yAbkHMEMH(6glkO9FplG%_?W zFfwE2=~W;0Y(#Hkb#0Sx2M;7OHDY98G&5!`H8eJ5Ei^YWG%YwXI5;h3HZo!{ zIA$?pW;igDq6b_JH8?jjHZU|aG%z_cG?NPm)g&`AWi~lsIAkqhW;bIkG%z=0En;M3 zWi2%~Gi5Y5Gd4LfFl3Vi2}lewEigD#F*iCgHaax3SP5?k1c~iLK$FW6Eq?+C5E?Az zGS6KA004SPL_t(2&vlSd4S+xlLmL#F1SCufQjmZHB!B}XAOQ(TK*HmLBe}7$zojqT zS}}9dD;bQ7v6HFS9uZ8tii#*4@O8nsfc04d;^c?~*(0g!kX&vM*pyE-=ckwVb{5)w xp7!ED4@eB=kUV#TaOAlwvK)wkQGdNm*bTeOz^OOYL7e~q002ovPDHLkV1jZ$+ll}H diff --git a/core/assets/refresh24.png b/core/assets/refresh24.png new file mode 100644 index 0000000000000000000000000000000000000000..a2fa27ace4791ed88cb6e00145f0b34f5de4cafa GIT binary patch literal 6963 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 XZ%6HwDV`m&= 1) { - mini_snprintf(count_str, sizeof(count_str), "Done! Restarting in %d s", + mini_snprintf(count_str, sizeof(count_str), "DONE! RESTARTING IN %d", restart_seconds); str = count_str; } else { - str = "Done! Unplug the device."; + str = "DONE! RECONNECT THE DEVICE"; } screen_install_success(str, initial_setup, full_redraw); diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index cdcca3254..a00567ac3 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -146,11 +146,13 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr, r = process_msg_WipeDevice(USB_IFACE_NUM, msg_size, buf); if (r < 0) { // error screen_wipe_fail(); + hal_delay(100); usb_stop(); usb_deinit(); return SHUTDOWN; } else { // success screen_wipe_success(); + hal_delay(100); usb_stop(); usb_deinit(); return SHUTDOWN; diff --git a/core/embed/rust/src/ui/component/pad.rs b/core/embed/rust/src/ui/component/pad.rs index 70a79707c..cf13ab452 100644 --- a/core/embed/rust/src/ui/component/pad.rs +++ b/core/embed/rust/src/ui/component/pad.rs @@ -18,6 +18,13 @@ impl Pad { } } + pub fn with_clear(self) -> Self { + Self { + clear: true, + ..self + } + } + pub fn place(&mut self, area: Rect) { self.area = area; } diff --git a/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs b/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs index e86aca6ad..943a3d5a3 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs @@ -9,8 +9,8 @@ use crate::ui::{ geometry::{Alignment, Insets, Offset, Point, Rect, TOP_CENTER}, model_tt::{ bootloader::theme::{ - button_bld_menu, BUTTON_AREA_START, CLOSE, CONTENT_PADDING, CORNER_BUTTON_AREA, - INFO_SMALL, TEXT_TITLE, TITLE_AREA, + button_bld_menu, BUTTON_AREA_START, BUTTON_HEIGHT, CONTENT_PADDING, CORNER_BUTTON_AREA, + CORNER_BUTTON_TOUCH_EXPANSION, INFO32, TEXT_TITLE, TITLE_AREA, TITLE_Y_ADJUSTMENT, X32, }, component::{Button, ButtonMsg::Clicked}, constant::WIDTH, @@ -18,6 +18,10 @@ use crate::ui::{ }, }; +const ICON_TOP: i16 = 17; +const CONTENT_START_WITH_ICON: i16 = 40 + CONTENT_PADDING; +const CONTENT_START: i16 = 58; + #[derive(Copy, Clone, ToPrimitive)] pub enum ConfirmMsg { Cancel = 1, @@ -29,27 +33,28 @@ pub struct Confirm<'a> { content_pad: Pad, bg_color: Color, icon: Option, - title: Option>>, - message: Child>>, - left: Child>, - right: Child>, + title: Option>>, + message: Child>, + alert: Option>>, + left_button: Child>, + right_button: Child>, info_button: Option>, close_button: Option>, info_title: Option>>, - info_text: Option>>, + info_text: Option>>>, show_info: bool, - - confirm_left: bool, } impl<'a> Confirm<'a> { + #[allow(clippy::too_many_arguments)] pub fn new( bg_color: Color, icon: Option, - left: Button<&'static str>, - right: Button<&'static str>, - confirm_left: bool, - confirm: (Option<&'static str>, Paragraphs>), + left_button: Button<&'static str>, + right_button: Button<&'static str>, + title: Option>, + msg: Label<&'a str>, + alert: Option>, info: Option<(&'static str, Paragraphs>)>, ) -> Self { let mut instance = Self { @@ -57,31 +62,29 @@ impl<'a> Confirm<'a> { content_pad: Pad::with_background(bg_color), bg_color, icon, - message: Child::new(confirm.1), - left: Child::new(left), - right: Child::new(right), + title: title.map(Child::new), + message: Child::new(msg), + alert: alert.map(Child::new), + left_button: Child::new(left_button), + right_button: Child::new(right_button), close_button: None, info_button: None, info_title: None, info_text: None, - confirm_left, show_info: false, - title: confirm - .0 - .map(|title| Child::new(Label::new(title, Alignment::Start, TEXT_TITLE))), }; if let Some((title, text)) = info { instance.info_title = Some(Child::new(Label::new(title, Alignment::Start, TEXT_TITLE))); - instance.info_text = Some(text); + instance.info_text = Some(text.into_child()); instance.info_button = Some( - Button::with_icon(Icon::new(INFO_SMALL)) + Button::with_icon(Icon::new(INFO32)) .styled(button_bld_menu()) - .with_expanded_touch_area(Insets::uniform(13)), + .with_expanded_touch_area(Insets::uniform(CORNER_BUTTON_TOUCH_EXPANSION)), ); instance.close_button = Some( - Button::with_icon(Icon::new(CLOSE)) + Button::with_icon(Icon::new(X32)) .styled(button_bld_menu()) - .with_expanded_touch_area(Insets::uniform(13)), + .with_expanded_touch_area(Insets::uniform(CORNER_BUTTON_TOUCH_EXPANSION)), ); } instance.bg.clear(); @@ -98,29 +101,86 @@ impl<'a> Component for Confirm<'a> { Point::zero(), Point::new(WIDTH, BUTTON_AREA_START), )); - let icon_height = if let Some(icon) = self.icon { - icon.toif.height() - } else { - 0 - }; - self.message.place(Rect::new( - Point::new(CONTENT_PADDING, 32 + icon_height), - Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START), - )); - let button_size = Offset::new(106, 38); - self.left.place(Rect::from_top_left_and_size( + let content_area_start = if self.icon.is_some() { + CONTENT_START_WITH_ICON + } else { + CONTENT_START + }; + + let content_area = Rect::new( + Point::new(CONTENT_PADDING, content_area_start), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING), + ); + + self.message.place(content_area); + let message_height = self.message.inner().area().height(); + + if let Some(alert) = &mut self.alert { + alert.place(content_area); + let alert_height = alert.inner().area().height(); + + let space_height = (content_area.height() - message_height - alert_height) / 3; + + self.message.place(Rect::new( + Point::new(CONTENT_PADDING, content_area_start + space_height), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START), + )); + self.alert.place(Rect::new( + Point::new( + CONTENT_PADDING, + content_area_start + 2 * space_height + message_height, + ), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START), + )); + } else { + self.message.place(Rect::new( + Point::new( + CONTENT_PADDING, + content_area.center().y - (message_height / 2), + ), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING), + )); + } + + let button_size = Offset::new((WIDTH - 3 * CONTENT_PADDING) / 2, BUTTON_HEIGHT); + self.left_button.place(Rect::from_top_left_and_size( Point::new(CONTENT_PADDING, BUTTON_AREA_START), button_size, )); - self.right.place(Rect::from_top_left_and_size( - Point::new(124, BUTTON_AREA_START), + self.right_button.place(Rect::from_top_left_and_size( + Point::new(2 * CONTENT_PADDING + button_size.x, BUTTON_AREA_START), button_size, )); self.info_button.place(CORNER_BUTTON_AREA); self.close_button.place(CORNER_BUTTON_AREA); - self.info_title.place(TITLE_AREA); - self.title.place(TITLE_AREA); + + if let Some(title) = self.info_title.as_mut() { + title.place(TITLE_AREA); + let title_height = title.inner().area().height(); + + title.place(Rect::new( + Point::new( + CONTENT_PADDING, + TITLE_AREA.center().y - (title_height / 2) - TITLE_Y_ADJUSTMENT, + ), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING), + )); + } + + if let Some(title) = self.title.as_mut() { + title.place(TITLE_AREA); + let title_height = title.inner().area().height(); + + title.place(Rect::new( + Point::new( + CONTENT_PADDING, + TITLE_AREA.center().y - (title_height / 2) - TITLE_Y_ADJUSTMENT, + ), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING), + )); + } + self.info_text.place(Rect::new( Point::new(CONTENT_PADDING, TITLE_AREA.y1), Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START), @@ -144,19 +204,11 @@ impl<'a> Component for Confirm<'a> { self.content_pad.clear(); return None; } - if let Some(Clicked) = self.left.event(ctx, event) { - return if self.confirm_left { - Some(Self::Msg::Confirm) - } else { - Some(Self::Msg::Cancel) - }; + if let Some(Clicked) = self.left_button.event(ctx, event) { + return Some(Self::Msg::Cancel); }; - if let Some(Clicked) = self.right.event(ctx, event) { - return if self.confirm_left { - Some(Self::Msg::Cancel) - } else { - Some(Self::Msg::Confirm) - }; + if let Some(Clicked) = self.right_button.event(ctx, event) { + return Some(Self::Msg::Confirm); }; None } @@ -169,17 +221,18 @@ impl<'a> Component for Confirm<'a> { self.close_button.paint(); self.info_title.paint(); self.info_text.paint(); - self.left.paint(); - self.right.paint(); + self.left_button.paint(); + self.right_button.paint(); } else { self.info_button.paint(); self.title.paint(); self.message.paint(); - self.left.paint(); - self.right.paint(); + self.alert.paint(); + self.left_button.paint(); + self.right_button.paint(); if let Some(icon) = self.icon { icon.draw( - Point::new(screen().center().x, 32), + Point::new(screen().center().x, ICON_TOP), TOP_CENTER, WHITE, self.bg_color, @@ -190,7 +243,7 @@ impl<'a> Component for Confirm<'a> { #[cfg(feature = "ui_bounds")] fn bounds(&self, sink: &mut dyn FnMut(Rect)) { - self.left.bounds(sink); - self.right.bounds(sink); + self.left_button.bounds(sink); + self.right_button.bounds(sink); } } diff --git a/core/embed/rust/src/ui/model_tt/bootloader/intro.rs b/core/embed/rust/src/ui/model_tt/bootloader/intro.rs index e275e152d..4ec81114b 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/intro.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/intro.rs @@ -7,14 +7,17 @@ use crate::ui::{ display::Icon, geometry::{Alignment, Insets, Point, Rect}, model_tt::{ - bootloader::theme::{button_bld_menu, button_bld_menu_item, BLD_BG, MENU}, + bootloader::theme::{button_bld, button_bld_menu, BLD_BG, MENU32}, component::ButtonMsg::Clicked, }, }; use heapless::String; use crate::ui::model_tt::{ - bootloader::theme::{CONTENT_PADDING, CORNER_BUTTON_AREA, TEXT_TITLE, TITLE_AREA}, + bootloader::theme::{ + BUTTON_AREA_START, BUTTON_HEIGHT, CONTENT_PADDING, CORNER_BUTTON_AREA, TEXT_TITLE, + TITLE_AREA, TITLE_Y_ADJUSTMENT, + }, component::Button, constant::WIDTH, }; @@ -40,20 +43,17 @@ impl<'a> Intro<'a> { unwrap!(title.push_str("BOOTLOADER ")); unwrap!(title.push_str(bld_version)); - let mut instance = Self { - bg: Pad::with_background(BLD_BG), + Self { + bg: Pad::with_background(BLD_BG).with_clear(), title: Child::new(Label::new(title, Alignment::Start, TEXT_TITLE)), menu: Child::new( - Button::with_icon(Icon::new(MENU)) + Button::with_icon(Icon::new(MENU32)) .styled(button_bld_menu()) .with_expanded_touch_area(Insets::uniform(13)), ), - host: Child::new(Button::with_text("INSTALL FIRMWARE").styled(button_bld_menu_item())), + host: Child::new(Button::with_text("INSTALL FIRMWARE").styled(button_bld())), text: Child::new(content), - }; - - instance.bg.clear(); - instance + } } } @@ -61,17 +61,26 @@ impl<'a> Component for Intro<'a> { type Msg = IntroMsg; fn place(&mut self, bounds: Rect) -> Rect { - const BUTTON_AREA_START: i16 = 188; self.bg.place(screen()); + self.title.place(TITLE_AREA); + let title_height = self.title.inner().area().height(); + self.title.place(Rect::new( + Point::new( + CONTENT_PADDING, + TITLE_AREA.center().y - (title_height / 2) - TITLE_Y_ADJUSTMENT, + ), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING), + )); + self.menu.place(CORNER_BUTTON_AREA); self.host.place(Rect::new( - Point::new(10, BUTTON_AREA_START), - Point::new(10 + 220, BUTTON_AREA_START + 38), + Point::new(CONTENT_PADDING, BUTTON_AREA_START), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START + BUTTON_HEIGHT), )); self.text.place(Rect::new( - Point::new(CONTENT_PADDING, 75), - Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START), + Point::new(CONTENT_PADDING, TITLE_AREA.y1 + CONTENT_PADDING), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING), )); bounds } diff --git a/core/embed/rust/src/ui/model_tt/bootloader/menu.rs b/core/embed/rust/src/ui/model_tt/bootloader/menu.rs index 820bc234a..319fa5f82 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/menu.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/menu.rs @@ -1,18 +1,22 @@ use crate::ui::{ component::{Child, Component, Event, EventCtx, Label, Pad}, - constant::{screen, WIDTH}, + constant::{screen, HEIGHT, WIDTH}, display::Icon, geometry::{Alignment, Insets, Point, Rect}, model_tt::{ bootloader::theme::{ - button_bld_menu, button_bld_menu_item, BLD_BG, CLOSE, CONTENT_PADDING, - CORNER_BUTTON_AREA, ERASE, REBOOT, TEXT_TITLE, TITLE_AREA, + button_bld, button_bld_menu, BLD_BG, BUTTON_HEIGHT, CONTENT_PADDING, + CORNER_BUTTON_AREA, CORNER_BUTTON_TOUCH_EXPANSION, FIRE24, REFRESH24, TEXT_TITLE, + TITLE_AREA, TITLE_Y_ADJUSTMENT, X32, }, component::{Button, ButtonMsg::Clicked, IconText}, }, }; use heapless::String; +const BUTTON_AREA_START: i16 = 56; +const BUTTON_SPACING: i16 = 8; + #[repr(u32)] #[derive(Copy, Clone, ToPrimitive)] pub enum MenuMsg { @@ -30,28 +34,23 @@ pub struct Menu { } impl Menu { - pub fn new(bld_version: &'static str) -> Self { - let content_reboot = IconText::new("REBOOT TREZOR", Icon::new(REBOOT)); - let content_reset = IconText::new("FACTORY RESET", Icon::new(ERASE)); + pub fn new(_bld_version: &'static str) -> Self { + let content_reboot = IconText::new("REBOOT TREZOR", Icon::new(REFRESH24)); + let content_reset = IconText::new("FACTORY RESET", Icon::new(FIRE24)); let mut title: String<32> = String::new(); unwrap!(title.push_str("BOOTLOADER ")); - unwrap!(title.push_str(bld_version)); let mut instance = Self { bg: Pad::with_background(BLD_BG), title: Child::new(Label::new(title, Alignment::Start, TEXT_TITLE)), close: Child::new( - Button::with_icon(Icon::new(CLOSE)) + Button::with_icon(Icon::new(X32)) .styled(button_bld_menu()) - .with_expanded_touch_area(Insets::uniform(13)), - ), - reboot: Child::new( - Button::with_icon_and_text(content_reboot).styled(button_bld_menu_item()), - ), - reset: Child::new( - Button::with_icon_and_text(content_reset).styled(button_bld_menu_item()), + .with_expanded_touch_area(Insets::uniform(CORNER_BUTTON_TOUCH_EXPANSION)), ), + reboot: Child::new(Button::with_icon_and_text(content_reboot).styled(button_bld())), + reset: Child::new(Button::with_icon_and_text(content_reset).styled(button_bld())), }; instance.bg.clear(); instance @@ -64,14 +63,28 @@ impl Component for Menu { fn place(&mut self, bounds: Rect) -> Rect { self.bg.place(screen()); self.title.place(TITLE_AREA); + let title_height = self.title.inner().area().height(); + self.title.place(Rect::new( + Point::new( + CONTENT_PADDING, + TITLE_AREA.center().y - (title_height / 2) - TITLE_Y_ADJUSTMENT, + ), + Point::new(WIDTH - CONTENT_PADDING, HEIGHT), + )); self.close.place(CORNER_BUTTON_AREA); self.reboot.place(Rect::new( - Point::new(CONTENT_PADDING, 64), - Point::new(WIDTH - CONTENT_PADDING, 64 + 38), + Point::new(CONTENT_PADDING, BUTTON_AREA_START), + Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START + BUTTON_HEIGHT), )); self.reset.place(Rect::new( - Point::new(CONTENT_PADDING, 110), - Point::new(WIDTH - CONTENT_PADDING, 110 + 38), + Point::new( + CONTENT_PADDING, + BUTTON_AREA_START + BUTTON_HEIGHT + BUTTON_SPACING, + ), + Point::new( + WIDTH - CONTENT_PADDING, + BUTTON_AREA_START + 2 * BUTTON_HEIGHT + BUTTON_SPACING, + ), )); bounds } diff --git a/core/embed/rust/src/ui/model_tt/bootloader/mod.rs b/core/embed/rust/src/ui/model_tt/bootloader/mod.rs index 79f4a8875..3f9b8c77a 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/mod.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/mod.rs @@ -1,7 +1,7 @@ use crate::{ trezorhal::io::io_touch_read, ui::{ - component::{Component, Event, EventCtx, Never}, + component::{Component, Event, EventCtx, Label, Never}, display::{self, Font}, event::TouchEvent, geometry::Point, @@ -23,20 +23,20 @@ use crate::{ component::text::paragraphs::{Paragraph, ParagraphVecShort, Paragraphs, VecExt}, constant::screen, display::{Color, Icon}, - geometry::{LinearPlacement, CENTER}, + geometry::{Alignment, LinearPlacement, CENTER}, model_tt::{ bootloader::{ connect::Connect, theme::{ - button_install_cancel, button_install_confirm, button_wipe_cancel, - button_wipe_confirm, BLD_BG, BLD_FG, BLD_WIPE_COLOR, ERASE_BIG, LOGO_EMPTY, - RECEIVE, TEXT_WIPE_BOLD, WELCOME_COLOR, + button_bld, button_confirm, button_wipe_cancel, button_wipe_confirm, BLD_BG, + BLD_BTN_COLOR, BLD_FG, BLD_WIPE_CANCEL_BTN_COLOR, BLD_WIPE_COLOR, CHECK24, + CHECK40, DOWNLOAD32, FIRE32, FIRE40, LOGO_EMPTY, TEXT_WIPE_BOLD, + TEXT_WIPE_NORMAL, WARNING40, WELCOME_COLOR, WELCOME_HIGHLIGHT_COLOR, X24, }, }, component::{Button, ResultScreen}, theme::{ - BACKLIGHT_DIM, BACKLIGHT_NORMAL, BG, BLACK, FG, GREY_DARK, ICON_SUCCESS_SMALL, - ICON_WARN_SMALL, TEXT_ERROR_BOLD, TEXT_ERROR_NORMAL, WHITE, + BACKLIGHT_DIM, BACKLIGHT_NORMAL, BLACK, FG, GREY_DARK, TEXT_ERROR_HIGHLIGHT, WHITE, }, }, util::{from_c_array, from_c_str}, @@ -66,11 +66,11 @@ where } fn fadein() { - display::fade_backlight_duration(BACKLIGHT_NORMAL, 500); + display::fade_backlight_duration(BACKLIGHT_NORMAL, 150); } fn fadeout() { - display::fade_backlight_duration(BACKLIGHT_DIM, 500); + display::fade_backlight_duration(BACKLIGHT_DIM, 150); } fn run(frame: &mut F) -> u32 @@ -145,34 +145,31 @@ extern "C" fn screen_install_confirm( core::str::from_utf8_unchecked(fingerprint_buffer.as_ref()) }; - let mut version_str: String<64> = String::new(); + let mut version_str: String<128> = String::new(); unwrap!(version_str.push_str("Firmware version ")); unwrap!(version_str.push_str(version)); - - let mut vendor_str: String<64> = String::new(); - unwrap!(vendor_str.push_str("by ")); - unwrap!(vendor_str.push_str(text)); + unwrap!(version_str.push_str("\nby ")); + unwrap!(version_str.push_str(text)); let title = if downgrade { - "DOWNGRADE FW" + Label::new("DOWNGRADE FW", Alignment::Start, theme::TEXT_BOLD) } else if vendor { - "CHANGE FW VENDOR" + Label::new("CHANGE FW\nVENDOR", Alignment::Start, theme::TEXT_BOLD) } else { - "UPDATE FIRMWARE" + Label::new("UPDATE FIRMWARE", Alignment::Start, theme::TEXT_BOLD) }; - let mut messages = ParagraphVecShort::new(); + let msg = Label::new(version_str.as_ref(), Alignment::Start, theme::TEXT_NORMAL); - messages.add(Paragraph::new(&theme::TEXT_NORMAL, version_str.as_ref())); - messages.add(Paragraph::new(&theme::TEXT_NORMAL, vendor_str.as_ref())); - - if vendor || downgrade { - messages - .add(Paragraph::new(&theme::TEXT_BOLD, "Seed will be erased!").with_top_padding(16)); - } - - let message = - Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); + let alert = if vendor || downgrade { + Some(Label::new( + "SEED WILL BE ERASED!", + Alignment::Start, + theme::TEXT_BOLD, + )) + } else { + None + }; let mut messages = ParagraphVecShort::new(); messages.add(Paragraph::new(&theme::TEXT_FINGERPRINT, fingerprint_str)); @@ -180,16 +177,24 @@ extern "C" fn screen_install_confirm( let fingerprint = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); - let left = Button::with_text("CANCEL").styled(button_install_cancel()); - let right = Button::with_text("INSTALL").styled(button_install_confirm()); + let (left, right) = if !(vendor || downgrade) { + let l = Button::with_text("CANCEL").styled(button_bld()); + let r = Button::with_text("INSTALL").styled(button_confirm()); + (l, r) + } else { + let l = Button::with_icon(Icon::new(X24)).styled(button_bld()); + let r = Button::with_icon(Icon::new(CHECK24)).styled(button_confirm()); + (l, r) + }; let mut frame = Confirm::new( BLD_BG, None, left, right, - false, - (Some(title), message), + Some(title), + msg, + alert, Some(("FW FINGERPRINT", fingerprint)), ); @@ -198,32 +203,30 @@ extern "C" fn screen_install_confirm( #[no_mangle] extern "C" fn screen_wipe_confirm() -> u32 { - let icon = Some(Icon::new(ERASE_BIG)); + let icon = Some(Icon::new(FIRE40)); - let mut messages = ParagraphVecShort::new(); - - messages.add( - Paragraph::new( - &TEXT_ERROR_NORMAL, - "Are you sure you want to factory reset the device?", - ) - .centered(), + let msg = Label::new( + "Are you sure you want to factory reset the device?", + Alignment::Center, + TEXT_WIPE_NORMAL, + ); + let alert = Label::new( + "SEED AND FIRMWARE\nWILL BE ERASED!", + Alignment::Center, + TEXT_WIPE_BOLD, ); - messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "Seed and firmware\nwill be erased!").centered()); - let message = - Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); - - let left = Button::with_text("RESET").styled(button_wipe_confirm()); - let right = Button::with_text("CANCEL").styled(button_wipe_cancel()); + let right = Button::with_text("RESET").styled(button_wipe_confirm()); + let left = Button::with_text("CANCEL").styled(button_wipe_cancel()); let mut frame = Confirm::new( BLD_WIPE_COLOR, icon, left, right, - true, - (None, message), + None, + msg, + Some(alert), None, ); @@ -261,7 +264,7 @@ extern "C" fn screen_intro( messages.add(Paragraph::new(&theme::TEXT_NORMAL, fw.as_ref())); messages.add(Paragraph::new(&theme::TEXT_NORMAL, vendor_.as_ref())); - let p = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_start()); + let p = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); let mut frame = Intro::new(bld_version, p); @@ -282,7 +285,7 @@ fn screen_progress( } display::text_center( - Point::new(constant::WIDTH / 2, 214), + Point::new(constant::WIDTH / 2, 195), text, Font::NORMAL, fg_color, @@ -296,28 +299,28 @@ fn screen_progress( #[no_mangle] extern "C" fn screen_install_progress(progress: u16, initialize: bool, initial_setup: bool) { - let bg_color = if initial_setup { WELCOME_COLOR } else { BG }; + let bg_color = if initial_setup { WELCOME_COLOR } else { BLD_BG }; let fg_color = if initial_setup { FG } else { BLD_FG }; screen_progress( - "Installing firmware...", + "Installing firmware", progress, initialize, fg_color, bg_color, - Some((Icon::new(RECEIVE), fg_color)), + Some((Icon::new(DOWNLOAD32), fg_color)), ) } #[no_mangle] extern "C" fn screen_wipe_progress(progress: u16, initialize: bool) { screen_progress( - "Resetting Trezor...", + "Resetting Trezor", progress, initialize, theme::BLD_FG, BLD_WIPE_COLOR, - Some((Icon::new(ERASE_BIG), theme::BLD_FG)), + Some((Icon::new(FIRE32), theme::BLD_FG)), ) } @@ -331,15 +334,15 @@ extern "C" fn screen_connect() { extern "C" fn screen_wipe_success() { let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "Trezor reset").centered()); - messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "successfully.").centered()); + messages.add(Paragraph::new(&TEXT_WIPE_NORMAL, "Trezor reset").centered()); + messages.add(Paragraph::new(&TEXT_WIPE_NORMAL, "successfully").centered()); let m_top = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "PLEASE RECONNECT").centered()); - messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "THE DEVICE").centered()); + messages.add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, "PLEASE RECONNECT").centered()); + messages.add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, "THE DEVICE").centered()); let m_bottom = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); @@ -347,7 +350,8 @@ extern "C" fn screen_wipe_success() { let mut frame = ResultScreen::new( WHITE, BLD_WIPE_COLOR, - Icon::new(ICON_SUCCESS_SMALL), + BLD_WIPE_CANCEL_BTN_COLOR, + Icon::new(CHECK40), m_top, m_bottom, true, @@ -359,22 +363,23 @@ extern "C" fn screen_wipe_success() { extern "C" fn screen_wipe_fail() { let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "Trezor reset was").centered()); - messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "not successful.").centered()); + messages.add(Paragraph::new(&TEXT_WIPE_NORMAL, "Trezor reset was").centered()); + messages.add(Paragraph::new(&TEXT_WIPE_NORMAL, "not successful.").centered()); let m_top = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "PLEASE RECONNECT").centered()); - messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "THE DEVICE").centered()); + messages.add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, "PLEASE RECONNECT").centered()); + messages.add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, "THE DEVICE").centered()); let m_bottom = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); let mut frame = ResultScreen::new( WHITE, BLD_WIPE_COLOR, - Icon::new(ICON_WARN_SMALL), + BLD_WIPE_CANCEL_BTN_COLOR, + Icon::new(WARNING40), m_top, m_bottom, true, @@ -408,8 +413,8 @@ extern "C" fn screen_boot_empty(firmware_present: bool, fading: bool) { #[no_mangle] extern "C" fn screen_install_fail() { let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&theme::TEXT_BOLD, "Firmware installation was").centered()); - messages.add(Paragraph::new(&theme::TEXT_BOLD, "not successful.").centered()); + messages.add(Paragraph::new(&theme::TEXT_NORMAL, "Firmware installation was").centered()); + messages.add(Paragraph::new(&theme::TEXT_NORMAL, "not successful.").centered()); let m_top = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); @@ -423,7 +428,8 @@ extern "C" fn screen_install_fail() { let mut frame = ResultScreen::new( WHITE, BLD_BG, - Icon::new(ICON_WARN_SMALL), + BLD_BTN_COLOR, + Icon::new(WARNING40), m_top, m_bottom, true, @@ -433,8 +439,8 @@ extern "C" fn screen_install_fail() { fn screen_install_success_bld(msg: &'static str, complete_draw: bool) { let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&theme::TEXT_BOLD, "Firmware installed").centered()); - messages.add(Paragraph::new(&theme::TEXT_BOLD, "successfully.").centered()); + messages.add(Paragraph::new(&theme::TEXT_NORMAL, "Firmware installed").centered()); + messages.add(Paragraph::new(&theme::TEXT_NORMAL, "successfully").centered()); let m_top = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); @@ -446,7 +452,8 @@ fn screen_install_success_bld(msg: &'static str, complete_draw: bool) { let mut frame = ResultScreen::new( WHITE, BLD_BG, - Icon::new(ICON_SUCCESS_SMALL), + BLD_BTN_COLOR, + Icon::new(CHECK40), m_top, m_bottom, complete_draw, @@ -456,8 +463,8 @@ fn screen_install_success_bld(msg: &'static str, complete_draw: bool) { fn screen_install_success_initial(msg: &'static str, complete_draw: bool) { let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&theme::TEXT_WELCOME_BOLD, "Firmware installed").centered()); - messages.add(Paragraph::new(&theme::TEXT_WELCOME_BOLD, "successfully.").centered()); + messages.add(Paragraph::new(&theme::TEXT_WELCOME_URL, "Firmware installed").centered()); + messages.add(Paragraph::new(&theme::TEXT_WELCOME_URL, "successfully").centered()); let m_top = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); @@ -471,7 +478,8 @@ fn screen_install_success_initial(msg: &'static str, complete_draw: bool) { let mut frame = ResultScreen::new( FG, WELCOME_COLOR, - Icon::new(ICON_SUCCESS_SMALL), + WELCOME_HIGHLIGHT_COLOR, + Icon::new(CHECK40), m_top, m_bottom, complete_draw, @@ -501,11 +509,7 @@ extern "C" fn screen_welcome() { let mut messages = ParagraphVecShort::new(); messages.add(Paragraph::new(&theme::TEXT_WELCOME, "Get started with").centered()); messages.add(Paragraph::new(&theme::TEXT_WELCOME, "your trezor at").centered()); - messages.add( - Paragraph::new(&theme::TEXT_WELCOME_BOLD, "trezor.io/start") - .centered() - .with_top_padding(2), - ); + messages.add(Paragraph::new(&theme::TEXT_WELCOME_URL, "trezor.io/start").centered()); let mut frame = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); show(&mut frame, false); diff --git a/core/embed/rust/src/ui/model_tt/bootloader/theme.rs b/core/embed/rust/src/ui/model_tt/bootloader/theme.rs index bba7416a1..090df5b13 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/theme.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/theme.rs @@ -1,107 +1,77 @@ -use crate::{ - alpha, - ui::{ - component::{text::TextStyle, LineBreaking::BreakWordsNoHyphen}, - constant::WIDTH, - display::{Color, Font}, - geometry::{Offset, Point, Rect}, - model_tt::{ - component::{ButtonStyle, ButtonStyleSheet}, - theme::{BLACK, FG, GREY_DARK, GREY_LIGHT, GREY_MEDIUM, WHITE}, - }, +use crate::ui::{ + component::{text::TextStyle, LineBreaking::BreakWordsNoHyphen}, + constant::WIDTH, + display::{Color, Font}, + geometry::{Offset, Point, Rect}, + model_tt::{ + component::{ButtonStyle, ButtonStyleSheet}, + theme::{BLACK, FG, GREY_DARK, GREY_LIGHT, GREY_MEDIUM, WHITE}, }, }; -pub const BLD_BG: Color = Color::rgb(0x00, 0x17, 0xA3); +pub const BLD_BG: Color = Color::rgb(0x00, 0x1E, 0xAD); pub const BLD_FG: Color = WHITE; -pub const BLD_WIPE_COLOR: Color = Color::rgb(0xAD, 0x2B, 0x2B); -pub const BLD_WIPE_TEXT_COLOR: Color = Color::rgb(0xD6, 0x95, 0x95); +pub const BLD_WIPE_COLOR: Color = Color::rgb(0xE7, 0x0E, 0x0E); +pub const BLD_WIPE_TEXT_COLOR: Color = WHITE; -pub const BLD_WIPE_BTN_COLOR: Color = Color::alpha(BLD_WIPE_COLOR, alpha!(0.3)); -pub const BLD_WIPE_BTN_COLOR_ACTIVE: Color = Color::rgb(0xB9, 0x4B, 0x4B); -pub const BLD_WIPE_CANCEL_BTN_COLOR_ACTIVE: Color = Color::rgb(0xF3, 0xDF, 0xDF); +pub const BLD_WIPE_BTN_COLOR: Color = WHITE; +pub const BLD_WIPE_BTN_COLOR_ACTIVE: Color = Color::rgb(0xFA, 0xCF, 0xCF); -pub const BLD_INSTALL_BTN_COLOR: Color = Color::alpha(BLD_BG, alpha!(0.3)); -pub const BLD_INSTALL_BTN_COLOR_ACTIVE: Color = Color::rgb(0xD9, 0xDC, 0xF1); -pub const BLD_INSTALL_CANCEL_BTN_COLOR_ACTIVE: Color = Color::rgb(0x26, 0x3A, 0xB1); +pub const BLD_WIPE_CANCEL_BTN_COLOR: Color = Color::rgb(0xFF, 0x41, 0x41); +pub const BLD_WIPE_CANCEL_BTN_COLOR_ACTIVE: Color = Color::rgb(0xAE, 0x09, 0x09); -pub const BLD_COLOR_SUBMSG: Color = Color::rgb(0x80, 0x8B, 0xD1); +pub const BLD_INSTALL_BTN_COLOR_ACTIVE: Color = Color::rgb(0xCD, 0xD2, 0xEF); -pub const BLD_BTN_MENU_COLOR: Color = Color::alpha(BLD_BG, alpha!(0.22)); -pub const BLD_BTN_MENU_COLOR_ACTIVE: Color = Color::alpha(BLD_BG, alpha!(0.11)); -pub const BLD_BTN_MENUITEM_COLOR: Color = Color::alpha(BLD_BG, alpha!(0.33)); -pub const BLD_BTN_MENUITEM_COLOR_ACTIVE: Color = - Color::rgba(BLD_BG, 0xFF, 0xFF, 0xFF, alpha!(0.11)); -pub const BLD_TITLE_COLOR: Color = Color::rgba(BLD_BG, 0xFF, 0xFF, 0xFF, alpha!(0.75)); +pub const BLD_BTN_COLOR: Color = Color::rgb(0x2D, 0x42, 0xBF); +pub const BLD_BTN_COLOR_ACTIVE: Color = Color::rgb(0x04, 0x10, 0x58); + +pub const BLD_TITLE_COLOR: Color = WHITE; pub const WELCOME_COLOR: Color = BLACK; +pub const WELCOME_HIGHLIGHT_COLOR: Color = Color::rgb(0x28, 0x28, 0x28); // Commonly used corner radius (i.e. for buttons). pub const RADIUS: u8 = 2; // Commonly used constants for UI elements. -pub const CONTENT_PADDING: i16 = 10; -pub const TITLE_AREA: Rect = Rect::new(Point::new(15, 14), Point::new(200, 30)); -pub const CORNER_BUTTON_SIZE: i16 = 32; -pub const CORNER_BUTTON_PADDING: i16 = 8; +pub const CONTENT_PADDING: i16 = 6; +pub const TITLE_AREA: Rect = Rect::new( + Point::new(CONTENT_PADDING, CONTENT_PADDING), + Point::new(WIDTH, CORNER_BUTTON_SIZE + CONTENT_PADDING), +); + +pub const CORNER_BUTTON_TOUCH_EXPANSION: i16 = 13; +pub const CORNER_BUTTON_SIZE: i16 = 44; pub const CORNER_BUTTON_AREA: Rect = Rect::from_top_left_and_size( Point::new( - WIDTH - CORNER_BUTTON_SIZE - CORNER_BUTTON_PADDING, - CORNER_BUTTON_PADDING, + WIDTH - CORNER_BUTTON_SIZE - CONTENT_PADDING, + CONTENT_PADDING, ), Offset::uniform(CORNER_BUTTON_SIZE), ); pub const TITLE_AREA_HEIGHT: i16 = 16; pub const TITLE_AREA_START_Y: i16 = 8; -pub const BUTTON_AREA_START: i16 = 188; - -// UI icons. -pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/x24.toif"); -pub const ICON_CONFIRM: &[u8] = include_res!("model_tt/res/check24.toif"); +pub const BUTTON_AREA_START: i16 = 184; +pub const BUTTON_HEIGHT: i16 = 50; +pub const TITLE_Y_ADJUSTMENT: i16 = 3; // BLD icons -pub const CLOSE: &[u8] = include_res!("model_tt/res/close.toif"); -pub const ERASE: &[u8] = include_res!("model_tt/res/erase.toif"); -pub const ERASE_BIG: &[u8] = include_res!("model_tt/res/erase_big.toif"); -pub const REBOOT: &[u8] = include_res!("model_tt/res/reboot.toif"); -pub const MENU: &[u8] = include_res!("model_tt/res/menu.toif"); -pub const RECEIVE: &[u8] = include_res!("model_tt/res/receive.toif"); +pub const X24: &[u8] = include_res!("model_tt/res/x24.toif"); +pub const X32: &[u8] = include_res!("model_tt/res/x32.toif"); +pub const FIRE24: &[u8] = include_res!("model_tt/res/fire24.toif"); +pub const FIRE32: &[u8] = include_res!("model_tt/res/fire32.toif"); +pub const FIRE40: &[u8] = include_res!("model_tt/res/fire40.toif"); +pub const REFRESH24: &[u8] = include_res!("model_tt/res/refresh24.toif"); +pub const MENU32: &[u8] = include_res!("model_tt/res/menu32.toif"); +pub const INFO32: &[u8] = include_res!("model_tt/res/info32.toif"); +pub const DOWNLOAD32: &[u8] = include_res!("model_tt/res/download32.toif"); +pub const WARNING40: &[u8] = include_res!("model_tt/res/warning40.toif"); +pub const CHECK24: &[u8] = include_res!("model_tt/res/check24.toif"); +pub const CHECK40: &[u8] = include_res!("model_tt/res/check40.toif"); + pub const LOGO_EMPTY: &[u8] = include_res!("model_tt/res/trezor_empty.toif"); -pub const INFO_SMALL: &[u8] = include_res!("model_tt/res/info_small.toif"); -pub fn button_install_cancel() -> ButtonStyleSheet { - ButtonStyleSheet { - normal: &ButtonStyle { - font: Font::BOLD, - text_color: WHITE, - button_color: BLD_BTN_MENUITEM_COLOR, - background_color: BLD_BG, - border_color: BLD_BG, - border_radius: RADIUS, - border_width: 0, - }, - active: &ButtonStyle { - font: Font::BOLD, - text_color: WHITE, - button_color: BLD_INSTALL_CANCEL_BTN_COLOR_ACTIVE, - background_color: BLD_BG, - border_color: BLD_BG, - border_radius: RADIUS, - border_width: 0, - }, - disabled: &ButtonStyle { - font: Font::BOLD, - text_color: GREY_LIGHT, - button_color: GREY_DARK, - background_color: WHITE, - border_color: WHITE, - border_radius: RADIUS, - border_width: 0, - }, - } -} - -pub fn button_install_confirm() -> ButtonStyleSheet { +pub fn button_confirm() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::BOLD, @@ -137,8 +107,8 @@ pub fn button_wipe_cancel() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::BOLD, - text_color: BLD_WIPE_COLOR, - button_color: WHITE, + text_color: WHITE, + button_color: BLD_WIPE_CANCEL_BTN_COLOR, background_color: BLD_WIPE_COLOR, border_color: BLD_WIPE_COLOR, border_radius: RADIUS, @@ -146,7 +116,7 @@ pub fn button_wipe_cancel() -> ButtonStyleSheet { }, active: &ButtonStyle { font: Font::BOLD, - text_color: BLD_WIPE_COLOR, + text_color: WHITE, button_color: BLD_WIPE_CANCEL_BTN_COLOR_ACTIVE, background_color: BLD_WIPE_COLOR, border_color: BLD_WIPE_COLOR, @@ -169,7 +139,7 @@ pub fn button_wipe_confirm() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::BOLD, - text_color: WHITE, + text_color: BLD_WIPE_COLOR, button_color: BLD_WIPE_BTN_COLOR, background_color: BLD_WIPE_COLOR, border_color: BLD_WIPE_COLOR, @@ -178,7 +148,7 @@ pub fn button_wipe_confirm() -> ButtonStyleSheet { }, active: &ButtonStyle { font: Font::BOLD, - text_color: WHITE, + text_color: BLD_WIPE_COLOR, button_color: BLD_WIPE_BTN_COLOR_ACTIVE, background_color: BLD_WIPE_COLOR, border_color: BLD_WIPE_COLOR, @@ -202,39 +172,39 @@ pub fn button_bld_menu() -> ButtonStyleSheet { normal: &ButtonStyle { font: Font::BOLD, text_color: BLD_FG, - button_color: BLD_BTN_MENU_COLOR, + button_color: BLD_BG, background_color: BLD_BG, - border_color: BLD_BG, - border_radius: 4, - border_width: 0, + border_color: BLD_BTN_COLOR, + border_radius: 2, + border_width: 2, }, active: &ButtonStyle { font: Font::BOLD, text_color: BLD_FG, - button_color: BLD_BTN_MENU_COLOR_ACTIVE, + button_color: BLD_BG, background_color: BLD_BG, - border_color: BLD_BG, - border_radius: 4, - border_width: 0, + border_color: BLD_BTN_COLOR_ACTIVE, + border_radius: 2, + border_width: 2, }, disabled: &ButtonStyle { font: Font::BOLD, text_color: GREY_LIGHT, - button_color: BLD_BTN_MENU_COLOR, + button_color: BLD_BG, background_color: BLD_BG, border_color: BLD_BG, - border_radius: 4, - border_width: 0, + border_radius: 2, + border_width: 2, }, } } -pub fn button_bld_menu_item() -> ButtonStyleSheet { +pub fn button_bld() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::BOLD, text_color: BLD_FG, - button_color: BLD_BTN_MENUITEM_COLOR, + button_color: BLD_BTN_COLOR, background_color: BLD_BG, border_color: BLD_BG, border_radius: 4, @@ -243,7 +213,7 @@ pub fn button_bld_menu_item() -> ButtonStyleSheet { active: &ButtonStyle { font: Font::BOLD, text_color: BLD_FG, - button_color: BLD_BTN_MENUITEM_COLOR_ACTIVE, + button_color: BLD_BTN_COLOR_ACTIVE, background_color: BLD_BG, border_color: BLD_BG, border_radius: 4, @@ -252,7 +222,7 @@ pub fn button_bld_menu_item() -> ButtonStyleSheet { disabled: &ButtonStyle { font: Font::BOLD, text_color: GREY_LIGHT, - button_color: BLD_BTN_MENUITEM_COLOR, + button_color: BLD_BTN_COLOR, background_color: BLD_BG, border_color: BLD_BG, border_radius: 4, @@ -267,7 +237,7 @@ pub const TEXT_WELCOME: TextStyle = TextStyle::new( GREY_MEDIUM, GREY_MEDIUM, ); -pub const TEXT_WELCOME_BOLD: TextStyle = TextStyle::new(Font::BOLD, FG, WELCOME_COLOR, FG, FG); +pub const TEXT_WELCOME_URL: TextStyle = TextStyle::new(Font::NORMAL, FG, WELCOME_COLOR, FG, FG); pub const TEXT_TITLE: TextStyle = TextStyle::new( Font::BOLD, BLD_TITLE_COLOR, @@ -277,8 +247,8 @@ pub const TEXT_TITLE: TextStyle = TextStyle::new( ); pub const TEXT_SUBMSG_INITIAL: TextStyle = TextStyle::new( Font::BOLD, - GREY_MEDIUM, - WELCOME_COLOR, + WHITE, + WELCOME_HIGHLIGHT_COLOR, GREY_MEDIUM, GREY_MEDIUM, ); @@ -295,10 +265,11 @@ pub const TEXT_WIPE_BOLD: TextStyle = TextStyle::new( BLD_WIPE_TEXT_COLOR, BLD_WIPE_TEXT_COLOR, ); -pub const TEXT_SUBMSG: TextStyle = TextStyle::new( - Font::BOLD, - BLD_COLOR_SUBMSG, - BLD_BG, - BLD_COLOR_SUBMSG, - BLD_COLOR_SUBMSG, +pub const TEXT_WIPE_NORMAL: TextStyle = TextStyle::new( + Font::NORMAL, + BLD_WIPE_TEXT_COLOR, + BLD_WIPE_COLOR, + BLD_WIPE_TEXT_COLOR, + BLD_WIPE_TEXT_COLOR, ); +pub const TEXT_SUBMSG: TextStyle = TextStyle::new(Font::BOLD, WHITE, BLD_BTN_COLOR, WHITE, WHITE); diff --git a/core/embed/rust/src/ui/model_tt/component/result.rs b/core/embed/rust/src/ui/model_tt/component/result.rs index 7c16eb1b0..6a3ae9c48 100644 --- a/core/embed/rust/src/ui/model_tt/component/result.rs +++ b/core/embed/rust/src/ui/model_tt/component/result.rs @@ -1,14 +1,11 @@ -use crate::{ - alpha, - ui::{ - component::{ - text::paragraphs::{ParagraphStrType, ParagraphVecShort, Paragraphs}, - Child, Component, Event, EventCtx, Never, Pad, - }, - constant::screen, - display::{self, Color, Icon}, - geometry::{Offset, Point, Rect, CENTER}, +use crate::ui::{ + component::{ + text::paragraphs::{ParagraphStrType, ParagraphVecShort, Paragraphs}, + Child, Component, Event, EventCtx, Never, Pad, }, + constant::screen, + display::{self, Color, Icon}, + geometry::{Point, Rect, CENTER}, }; use crate::ui::model_tt::constant::{HEIGHT, WIDTH}; @@ -18,6 +15,7 @@ pub struct ResultScreen { small_pad: Pad, fg_color: Color, bg_color: Color, + msg_area_color: Color, icon: Icon, message_top: Child>>, message_bottom: Child>>, @@ -27,6 +25,7 @@ impl ResultScreen { pub fn new( fg_color: Color, bg_color: Color, + msg_area_color: Color, icon: Icon, message_top: Paragraphs>, message_bottom: Paragraphs>, @@ -37,6 +36,7 @@ impl ResultScreen { small_pad: Pad::with_background(bg_color), fg_color, bg_color, + msg_area_color, icon, message_top: Child::new(message_top), message_bottom: Child::new(message_bottom), @@ -59,9 +59,9 @@ impl Component for ResultScreen { .place(Rect::new(Point::new(0, 0), Point::new(WIDTH, HEIGHT))); self.message_top - .place(Rect::new(Point::new(15, 59), Point::new(WIDTH - 15, 149))); + .place(Rect::new(Point::new(15, 59), Point::new(WIDTH - 15, 176))); - let bottom_area = Rect::new(Point::new(15, 151), Point::new(WIDTH - 15, HEIGHT)); + let bottom_area = Rect::new(Point::new(6, 176), Point::new(WIDTH - 6, 176 + 56)); self.small_pad.place(bottom_area); self.message_bottom.place(bottom_area); @@ -83,11 +83,13 @@ impl Component for ResultScreen { self.fg_color, self.bg_color, ); - display::rect_fill( - Rect::from_top_left_and_size(Point::new(12, 149), Offset::new(216, 1)), - Color::alpha(self.bg_color, alpha!(0.2)), - ); self.message_top.paint(); + display::rect_fill_rounded( + Rect::new(Point::new(6, 176), Point::new(WIDTH - 6, 176 + 56)), + self.msg_area_color, + self.bg_color, + 2, + ); self.message_bottom.paint(); } } diff --git a/core/embed/rust/src/ui/model_tt/res/check40.toif b/core/embed/rust/src/ui/model_tt/res/check40.toif new file mode 100644 index 0000000000000000000000000000000000000000..c18a3894e5b033b462d121833ebbab43d238a85b GIT binary patch literal 87 zcmV-d0I2^|Pf15804M-U0001EU>KfY5j%#E!e4F-u}k-vFqP@jPuVwiOl9BdF->du t&yH!@k9tf?!3xnW1t~;#8&Dyp+kVtzdZFR}KTI$D!1O6YgVr!iM*!h-C4v9| literal 0 HcmV?d00001 diff --git a/core/embed/rust/src/ui/model_tt/res/close.toif b/core/embed/rust/src/ui/model_tt/res/close.toif deleted file mode 100644 index a53d508b3dcb563ccbd05817fc0df9fa00ed99d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94 zcmV-k0HOa>Pf14*01yCD0002H!NdRr26ex6LGU|>j2P~eVv;QF-wfxOM1-97^Q4#jf(U$56v|I!YGg*(_KaA;cU*RtYl)a&z z;c-2PF^h@evo1rydnN{kg#Wn=zkmvUaWgPnI{)AEKTzzUKZt+r|9qg*g8d8%|Ctni z>4WtBV@UuSoWKTR|KL0j53}SG-zPp8`+@ye9vFK;{tr$VdqVvWm^&C6`oANIf8&O+ zH^hIGgRwvAZ^(!HjVA%-Q-Qy148NfUHQZ-lcvKHz|Ih>ZMH|H2^qv_=Uj84+tg!9B WEl5P+*MA_G4>3aF*uVGHASM9emS__I diff --git a/core/embed/rust/src/ui/model_tt/res/fire24.toif b/core/embed/rust/src/ui/model_tt/res/fire24.toif new file mode 100644 index 0000000000000000000000000000000000000000..0333bc08e68c36c91959efaf65426bb46eefcbd2 GIT binary patch literal 176 zcmV;h08jr^Pf14@02lzI0001EU;qIF1_b!5i(vme&j@2G{Qt`hV^5fWsUITP!}v+x z;6Dpk@W1a*PKNKYAoiDg|Nk>FYyd0z&GBPC1B1hRkn;CT3Ys7xpoW6^5VL-8GB9k2 zhp@i_ZMa|$VSnNUvh@+{1O5>97oeI6{ZQv|f(!;bQQ1$qQ;27LXR<7vJVIYC8FtWz3Q9N(n~{I?P=YIT3M$zG2=Kff6e_;J)XW z+Iw@Wa1SXy@z2Arc<)XHc}H(kzu49k?~>dfP<)KPx3FSMmcXe{n$QKdeXr0kK5k zJ(6!e%0pd@BzC|aVr@N=*n)g8wE;OaCO~|*!5>Mi0k;^`2o&=QkmKtBM3cjPF!;v-6T1jg_;fuYS^Vh-3vNbE jMHBwdH)Sx~4vbPHu;@Ps^f98OmZDSt?`1MF&;|ei5dMUM literal 0 HcmV?d00001 diff --git a/core/embed/rust/src/ui/model_tt/res/menu.toif b/core/embed/rust/src/ui/model_tt/res/menu.toif deleted file mode 100644 index b690421488fbb26470d4e71d0c18d6202e563bb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47 zcmWIX_jDIw5MWSdU|_htPnv62{r~o+zdS0<(d7#h-kmNFFz7D{t~(f8@QFv{3IhWG DgS!#+ diff --git a/core/embed/rust/src/ui/model_tt/res/menu32.toif b/core/embed/rust/src/ui/model_tt/res/menu32.toif new file mode 100644 index 0000000000000000000000000000000000000000..5403e18dfc10b8e62addf3d04f9b3836a63c29c4 GIT binary patch literal 29 kcmWIX_jFfaP+$;bU|>j2SYZC+w>;mwpAmj6YB_$MOdzx%gTV9u|K~D+*moJ8{onWce?5r(zu>>&2{e2~yHki`G@tRQy6d!Ua0=VyZT{o-I?`1k)m8;JddkAWd6Ee&k;1AT;j z8~m}eAJ`+L3z|MNw42nn3;^6qQY8QY literal 0 HcmV?d00001 diff --git a/core/embed/rust/src/ui/model_tt/res/warning40.toif b/core/embed/rust/src/ui/model_tt/res/warning40.toif new file mode 100644 index 0000000000000000000000000000000000000000..21840bc00d619169d158096a2ac7651fdf1f8d4b GIT binary patch literal 258 zcmV+d0sa0|Pf15804M42T90Eaxa zVM)mp8^Z?43M}EXb, file: &str) { }; let mut messages = ParagraphVecShort::new(); - messages - .add(Paragraph::new(&TEXT_ERROR_BOLD, "PLEASE CONTACT\nTREZOR SUPPORT".into()).centered()); + messages.add( + Paragraph::new( + &TEXT_ERROR_HIGHLIGHT, + "PLEASE CONTACT\nTREZOR SUPPORT".into(), + ) + .centered(), + ); let m_bottom = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); let mut frame = ResultScreen::new( WHITE, FATAL_ERROR_COLOR, - Icon::new(ICON_WARN_SMALL), + FATAL_ERROR_HIGHLIGHT_COLOR, + Icon::new(ICON_WARNING40), m_top, m_bottom, true, @@ -87,14 +96,16 @@ pub fn screen_error_shutdown(label: &str, msg: Option<&str>) { }; let mut messages = ParagraphVecShort::new(); - messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "PLEASE UNPLUG\nTHE DEVICE".into()).centered()); + messages + .add(Paragraph::new(&TEXT_ERROR_HIGHLIGHT, "PLEASE UNPLUG\nTHE DEVICE".into()).centered()); let m_bottom = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center()); let mut frame = ResultScreen::new( WHITE, FATAL_ERROR_COLOR, - Icon::new(ICON_WARN_SMALL), + FATAL_ERROR_HIGHLIGHT_COLOR, + Icon::new(ICON_WARNING40), m_top, m_bottom, true, diff --git a/core/embed/rust/src/ui/model_tt/theme.rs b/core/embed/rust/src/ui/model_tt/theme.rs index 6acf0bc81..d0cfb3e7c 100644 --- a/core/embed/rust/src/ui/model_tt/theme.rs +++ b/core/embed/rust/src/ui/model_tt/theme.rs @@ -42,7 +42,8 @@ pub const GREY_MEDIUM: Color = Color::rgb(0x4F, 0x4F, 0x4F); // button pressed pub const GREY_DARK: Color = Color::rgb(0x28, 0x28, 0x28); // button pub const VIOLET: Color = Color::rgb(0x95, 0x00, 0xCA); -pub const FATAL_ERROR_COLOR: Color = Color::rgb(0xAD, 0x2B, 0x2B); +pub const FATAL_ERROR_COLOR: Color = Color::rgb(0xE7, 0x0E, 0x0E); +pub const FATAL_ERROR_HIGHLIGHT_COLOR: Color = Color::rgb(0xFF, 0x41, 0x41); // Commonly used corner radius (i.e. for buttons). pub const RADIUS: u8 = 2; @@ -70,6 +71,7 @@ pub const ICON_LIST_CHECK: &[u8] = include_res!("model_tt/res/check16.toif"); // Homescreen notifications. pub const ICON_WARN: &[u8] = include_res!("model_tt/res/warning16.toif"); +pub const ICON_WARNING40: &[u8] = include_res!("model_tt/res/warning40.toif"); pub const ICON_LOCK: &[u8] = include_res!("model_tt/res/lock16.toif"); pub const ICON_COINJOIN: &[u8] = include_res!("model_tt/res/coinjoin16.toif"); pub const ICON_MAGIC: &[u8] = include_res!("model_tt/res/magic.toif"); @@ -108,10 +110,6 @@ pub const DOT_INACTIVE_HALF: &[u8] = include_res!("model_tt/res/scroll-inactive- pub const DOT_INACTIVE_QUARTER: &[u8] = include_res!("model_tt/res/scroll-inactive-quarter.toif"); pub const DOT_SMALL: &[u8] = include_res!("model_tt/res/scroll-small.toif"); -// Bootloader. TODO -pub const ICON_SUCCESS_SMALL: &[u8] = include_res!("model_tt/res/success_bld.toif"); -pub const ICON_WARN_SMALL: &[u8] = include_res!("model_tt/res/warn_bld.toif"); - pub const fn label_default() -> TextStyle { TEXT_NORMAL } @@ -522,6 +520,13 @@ pub const TEXT_ERROR_NORMAL: TextStyle = TextStyle::new(Font::NORMAL, FG, FATAL_ERROR_COLOR, GREY_LIGHT, GREY_LIGHT); pub const TEXT_ERROR_BOLD: TextStyle = TextStyle::new(Font::BOLD, FG, FATAL_ERROR_COLOR, GREY_LIGHT, GREY_LIGHT); +pub const TEXT_ERROR_HIGHLIGHT: TextStyle = TextStyle::new( + Font::BOLD, + FG, + FATAL_ERROR_HIGHLIGHT_COLOR, + GREY_LIGHT, + GREY_LIGHT, +); pub const TEXT_NORMAL_OFF_WHITE: TextStyle = TextStyle::new(Font::NORMAL, OFF_WHITE, BG, GREY_LIGHT, GREY_LIGHT);