1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-24 07:28:34 +00:00

refactor(eckhart): move pairing cancel button to menu

[no changelog]
This commit is contained in:
Ioan Bizău 2025-06-18 12:39:31 +02:00 committed by Ioan Bizău
parent a7f6bf5bda
commit 785f52f082
13 changed files with 136 additions and 34 deletions

View File

@ -879,8 +879,7 @@ extern "C" fn new_show_pairing_code(n_args: usize, args: *const Obj, kwargs: *mu
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let code: TString = kwargs.get(Qstr::MP_QSTR_code)?.try_into()?;
let button: bool = kwargs.get_or(Qstr::MP_QSTR_button, true)?;
let layout = ModelUI::show_pairing_code(title, description, code, button)?;
let layout = ModelUI::show_pairing_code(title, description, code)?;
let layout_obj = LayoutObj::new_root(layout)?;
Ok(layout_obj.into())
};
@ -1695,7 +1694,6 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// title: str,
/// description: str,
/// code: str,
/// button: bool = True,
/// ) -> LayoutObj[UiResult]:
/// """Pairing device: second screen (pairing code).
/// Returns on BLEEvent::{PairingCanceled, Disconnected}."""

View File

@ -625,6 +625,7 @@ pub enum FlowMsg {
Next,
Choice(usize),
Text(ShortString),
Number(u32),
}
#[cfg(feature = "micropython")]
@ -640,6 +641,7 @@ impl TryFrom<FlowMsg> for crate::micropython::obj::Obj {
FlowMsg::Info => Ok(result::INFO.as_obj()),
FlowMsg::Choice(i) => i.try_into(),
FlowMsg::Text(s) => s.as_str().try_into(),
FlowMsg::Number(i) => i.try_into(),
}
}
}

View File

@ -3,15 +3,19 @@ use crate::ui::{
event::BLEEvent,
geometry::Rect,
shape::Renderer,
util::Pager,
};
#[cfg(all(feature = "micropython", feature = "touch"))]
use crate::ui::{component::swipe_detect::SwipeConfig, flow::Swipable};
pub struct BLEHandler<T> {
inner: T,
waiting_for_pairing: bool,
}
pub enum BLEHandlerMsg<T> {
Content(T),
pub enum BLEHandlerMsg<TMsg> {
Content(TMsg),
PairingCode(u32),
Cancelled,
}
@ -25,6 +29,19 @@ impl<T> BLEHandler<T> {
}
}
#[cfg(all(feature = "micropython", feature = "touch"))]
impl<T> Swipable for BLEHandler<T>
where
T: Component,
{
fn get_pager(&self) -> Pager {
Pager::single_page()
}
fn get_swipe_config(&self) -> SwipeConfig {
SwipeConfig::default()
}
}
impl<T> Component for BLEHandler<T>
where
T: Component,

View File

@ -35,7 +35,7 @@ pub mod timeout;
pub use bar::Bar;
pub use base::{Child, Component, ComponentExt, Event, EventCtx, FlowMsg, Never, Timer};
#[cfg(feature = "ble")]
pub use ble::BLEHandler;
pub use ble::{BLEHandler, BLEHandlerMsg};
pub use border::Border;
pub use button_request::{ButtonRequestExt, SendButtonRequest};
#[cfg(all(

View File

@ -896,14 +896,13 @@ impl FirmwareUI for UIBolt {
title: TString<'static>,
description: TString<'static>,
code: TString<'static>,
button: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
Self::confirm_action(
title,
Some(code),
Some(description),
None,
button.then_some(TR::buttons__confirm.into()),
None,
None,
false,
false,

View File

@ -1093,7 +1093,6 @@ impl FirmwareUI for UICaesar {
_title: TString<'static>,
_description: TString<'static>,
_code: TString<'static>,
_button: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(
c"show_pairing_code not supported",

View File

@ -920,7 +920,6 @@ impl FirmwareUI for UIDelizia {
_title: TString<'static>,
_description: TString<'static>,
_code: TString<'static>,
_button: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(
c"show_pairing_code not supported",

View File

@ -13,6 +13,7 @@ pub mod prompt_backup;
pub mod request_number;
pub mod request_passphrase;
pub mod show_danger;
pub mod show_pairing_code;
pub mod show_share_words;
#[cfg(feature = "universal_fw")]
@ -30,4 +31,5 @@ pub use prompt_backup::PromptBackup;
pub use request_number::new_request_number;
pub use request_passphrase::RequestPassphrase;
pub use show_danger::ShowDanger;
pub use show_pairing_code::new_show_pairing_code;
pub use show_share_words::new_show_share_words_flow;

View File

@ -0,0 +1,107 @@
use crate::{
error,
strutil::TString,
translations::TR,
ui::{
component::{text::op::OpTextLayout, ComponentExt, FormattedText},
flow::{
base::{Decision, DecisionBuilder as _},
FlowController, FlowMsg, SwipeFlow,
},
geometry::{Alignment, Direction},
},
};
#[cfg(feature = "ble")]
use crate::ui::component::BLEHandlerMsg;
use super::super::{
component::Button,
firmware::{
Header, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu, VerticalMenuScreen,
VerticalMenuScreenMsg,
},
fonts, theme,
};
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ShowPairingCode {
Main,
Menu,
}
impl FlowController for ShowPairingCode {
#[inline]
fn index(&'static self) -> usize {
*self as usize
}
fn handle_swipe(&'static self, _direction: Direction) -> Decision {
self.do_nothing()
}
fn handle_event(&'static self, msg: FlowMsg) -> Decision {
match (self, msg) {
(Self::Main, FlowMsg::Cancelled) => self.return_msg(FlowMsg::Cancelled),
(Self::Main, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
(Self::Main, FlowMsg::Info) => Self::Menu.goto(),
(Self::Main, FlowMsg::Number(pairing_code)) => {
self.return_msg(FlowMsg::Number(pairing_code))
}
(Self::Menu, FlowMsg::Choice(..)) => self.return_msg(FlowMsg::Cancelled),
(Self::Menu, FlowMsg::Cancelled) => Self::Main.goto(),
_ => self.do_nothing(),
}
}
}
pub fn new_show_pairing_code(
title: TString<'static>,
description: TString<'static>,
code: TString<'static>,
) -> Result<SwipeFlow, error::Error> {
let mut ops = OpTextLayout::new(theme::firmware::TEXT_REGULAR);
ops.add_text(description, fonts::FONT_SATOSHI_REGULAR_38)
.add_newline()
.add_newline()
.add_newline()
.add_alignment(Alignment::Center)
.add_text(code, fonts::FONT_SATOSHI_EXTRALIGHT_72);
let screen =
TextScreen::new(FormattedText::new(ops)).with_header(Header::new(title).with_menu_button());
#[cfg(feature = "ble")]
let main_content = crate::ui::component::BLEHandler::new(screen, false).map(|msg| match msg {
BLEHandlerMsg::Cancelled => Some(FlowMsg::Cancelled),
BLEHandlerMsg::Content(TextScreenMsg::Cancelled) => Some(FlowMsg::Cancelled),
BLEHandlerMsg::Content(TextScreenMsg::Confirmed) => Some(FlowMsg::Confirmed),
BLEHandlerMsg::Content(TextScreenMsg::Menu) => Some(FlowMsg::Info),
BLEHandlerMsg::PairingCode(code) => Some(FlowMsg::Number(code)),
});
#[cfg(not(feature = "ble"))]
let main_content = screen.map(|msg| match msg {
TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
TextScreenMsg::Menu => Some(FlowMsg::Info),
});
let mut menu = VerticalMenu::<ShortMenuVec>::empty();
menu.item(Button::new_menu_item(
TR::buttons__cancel.into(),
theme::menu_item_title_orange(),
));
let menu_content = VerticalMenuScreen::new(menu)
.with_header(Header::new(TString::empty()).with_close_button())
.map(move |msg| match msg {
VerticalMenuScreenMsg::Selected(i) => Some(FlowMsg::Choice(i)),
VerticalMenuScreenMsg::Close => Some(FlowMsg::Cancelled),
_ => None,
});
let mut flow = SwipeFlow::new(&ShowPairingCode::Main)?;
flow.add_page(&ShowPairingCode::Main, main_content)?
.add_page(&ShowPairingCode::Menu, menu_content)?;
Ok(flow)
}

View File

@ -18,7 +18,7 @@ use crate::{
},
ComponentExt as _, Empty, FormattedText, Timeout,
},
geometry::{Alignment, LinearPlacement, Offset},
geometry::{LinearPlacement, Offset},
layout::{
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
util::{ConfirmValueParams, PropsList, RecoveryType, StrOrBytes},
@ -1083,27 +1083,9 @@ impl FirmwareUI for UIEckhart {
title: TString<'static>,
description: TString<'static>,
code: TString<'static>,
button: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
let mut ops = OpTextLayout::new(theme::firmware::TEXT_REGULAR);
ops.add_text(description, fonts::FONT_SATOSHI_REGULAR_38)
.add_newline()
.add_newline()
.add_newline()
.add_alignment(Alignment::Center)
.add_text(code, fonts::FONT_SATOSHI_EXTRALIGHT_72);
let mut screen = TextScreen::new(FormattedText::new(ops));
if button {
screen = screen
.with_header(Header::new(title))
.with_action_bar(ActionBar::new_cancel_confirm());
} else {
screen = screen.with_header(Header::new(title).with_close_button());
}
#[cfg(feature = "ble")]
let screen = crate::ui::component::BLEHandler::new(screen, false);
let layout = RootComponent::new(screen);
Ok(layout)
let flow = flow::show_pairing_code::new_show_pairing_code(title, description, code)?;
Ok(flow)
}
fn show_info(

View File

@ -329,7 +329,6 @@ pub trait FirmwareUI {
title: TString<'static>,
description: TString<'static>,
code: TString<'static>,
button: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_info(

View File

@ -576,7 +576,6 @@ def show_pairing_code(
title: str,
description: str,
code: str,
button: bool = True,
) -> LayoutObj[UiResult]:
"""Pairing device: second screen (pairing code).
Returns on BLEEvent::{PairingCanceled, Disconnected}."""

View File

@ -32,7 +32,6 @@ async def pair_new_device() -> None:
title="Bluetooth pairing",
description="Pairing code match?",
code=f"{code:0>6}",
button=True,
),
None,
)