Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion core/SConscript.firmware
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,11 @@ env.Ignore(hdr_moduledefs, qstr_generated)
if FROZEN:
SOURCE_PY_DIR = 'src/'

SOURCE_PY = Glob(SOURCE_PY_DIR + '*.py')
SOURCE_PY = Glob(SOURCE_PY_DIR + '*.py',
exclude=[
SOURCE_PY_DIR + 'ble.py',
] if "ble" not in FEATURES_AVAILABLE else []
)
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/*.py',
exclude=[
SOURCE_PY_DIR + 'trezor/sdcard.py',
Expand Down
6 changes: 5 additions & 1 deletion core/SConscript.unix
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,11 @@ env.Ignore(micropy_defines, qstr_generated)
if FROZEN:
SOURCE_PY_DIR = 'src/'

SOURCE_PY = Glob(SOURCE_PY_DIR + '*.py')
SOURCE_PY = Glob(SOURCE_PY_DIR + '*.py',
exclude=[
SOURCE_PY_DIR + 'ble.py',
] if "ble" not in FEATURES_AVAILABLE else []
)
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/*.py',
exclude=[
SOURCE_PY_DIR + 'trezor/sdcard.py',
Expand Down
14 changes: 11 additions & 3 deletions core/embed/rust/src/ui/api/firmware_micropython.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,8 +878,11 @@ extern "C" fn new_show_pairing_device_name(

extern "C" fn new_show_pairing_code(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
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 layout = ModelUI::show_pairing_code(code)?;
let button: bool = kwargs.get_or(Qstr::MP_QSTR_button, true)?;
let layout = ModelUI::show_pairing_code(title, description, code, button)?;
let layout_obj = LayoutObj::new_root(layout)?;
Ok(layout_obj.into())
};
Expand Down Expand Up @@ -1674,14 +1677,19 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// *,
/// device_name: str,
/// ) -> LayoutObj[UiResult]:
/// """Pairing device: first screen (device name)."""
/// """Pairing device: first screen (device name).
/// Returns if BLEEvent::PairingRequest is received."""
Qstr::MP_QSTR_show_pairing_device_name => obj_fn_kw!(0, new_show_pairing_device_name).as_obj(),

/// def show_pairing_code(
/// *,
/// title: str,
/// description: str,
/// code: str,
/// button: bool = True,
/// ) -> LayoutObj[UiResult]:
/// """Pairing device: second screen (pairing code)."""
/// """Pairing device: second screen (pairing code).
/// Returns on BLEEvent::{PairingCanceled, Disconnected}."""
Qstr::MP_QSTR_show_pairing_code => obj_fn_kw!(0, new_show_pairing_code).as_obj(),

/// def show_info(
Expand Down
86 changes: 86 additions & 0 deletions core/embed/rust/src/ui/component/ble.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use crate::ui::{
component::{Component, Event, EventCtx},
event::BLEEvent,
geometry::Rect,
shape::Renderer,
};

pub struct BLEHandler<T> {
inner: T,
waiting_for_pairing: bool,
}

pub enum BLEHandlerMsg<T> {
Content(T),
PairingCode(u32),
Cancelled,
}

impl<T> BLEHandler<T> {
pub fn new(inner: T, waiting_for_pairing: bool) -> Self {
Self {
inner,
waiting_for_pairing,
}
}
}

impl<T> Component for BLEHandler<T>
where
T: Component,
{
type Msg = BLEHandlerMsg<T::Msg>;

fn place(&mut self, bounds: Rect) -> Rect {
self.inner.place(bounds)
}

fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
match (event, self.waiting_for_pairing) {
(Event::BLE(BLEEvent::PairingRequest(num)), true) => {
return Some(BLEHandlerMsg::PairingCode(num))
}
(Event::BLE(BLEEvent::PairingCanceled | BLEEvent::Disconnected), _) => {
return Some(BLEHandlerMsg::Cancelled)
}
_ => {}
}
self.inner.event(ctx, event).map(BLEHandlerMsg::Content)
}

fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
self.inner.render(target)
}
}

#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for BLEHandler<T>
where
T: crate::trace::Trace,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
self.inner.trace(t)
}
}

#[cfg(feature = "micropython")]
mod micropython {
use super::*;
use crate::{
error::Error,
micropython::obj::Obj,
ui::layout::{obj::ComponentMsgObj, result::CANCELLED},
};
impl<T> ComponentMsgObj for BLEHandler<T>
where
T: ComponentMsgObj,
{
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
BLEHandlerMsg::Content(msg) => self.inner.msg_try_into_obj(msg),
BLEHandlerMsg::PairingCode(num) => num.try_into(),
BLEHandlerMsg::Cancelled => Ok(CANCELLED.as_obj()),
}
}
}
}
4 changes: 4 additions & 0 deletions core/embed/rust/src/ui/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

pub mod bar;
pub mod base;
#[cfg(feature = "ble")]
mod ble;
pub mod border;
pub mod button_request;
#[cfg(all(
Expand Down Expand Up @@ -32,6 +34,8 @@ 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 border::Border;
pub use button_request::{ButtonRequestExt, SendButtonRequest};
#[cfg(all(
Expand Down
23 changes: 19 additions & 4 deletions core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,10 +899,25 @@ impl FirmwareUI for UIBolt {
))
}

fn show_pairing_code(_code: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(
c"show_pairing_code not supported",
))
fn show_pairing_code(
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,
false,
false,
false,
false,
None,
)
}

fn show_info(
Expand Down
7 changes: 6 additions & 1 deletion core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,12 @@ impl FirmwareUI for UICaesar {
))
}

fn show_pairing_code(_code: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
fn show_pairing_code(
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",
))
Expand Down
7 changes: 6 additions & 1 deletion core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,12 @@ impl FirmwareUI for UIDelizia {
))
}

fn show_pairing_code(_code: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
fn show_pairing_code(
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",
))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
strutil::TString,
translations::TR,
ui::{
component::{Component, Event, EventCtx, Timeout},
Expand Down Expand Up @@ -128,6 +129,14 @@ impl ActionBar {
Self::new(Mode::PaginateOnly, None, None, None)
}

pub fn new_text_only(text: TString<'static>) -> Self {
Comment thread
obrusvit marked this conversation as resolved.
Self::new_single(
Button::with_text(text)
.styled(theme::button_always_disabled())
.initially_enabled(false),
)
}

pub fn with_left_short(mut self, short: bool) -> Self {
if let Mode::Double { ref mut left_short } = self.mode {
*left_short = short;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,21 @@ impl<'a> DeviceMenuScreen<'a> {
let device = screen.add_device_menu(device_name, about, auto_lock_delay);
let settings = screen.add_settings_menu(security, device);

let is_connected = !paired_devices.is_empty(); // FIXME after BLE API has this
let connected_subtext: Option<TString<'static>> =
is_connected.then_some("1 device connected".into());

let mut paired_device_indices: Vec<usize, 1> = Vec::new();
for (i, device) in paired_devices.iter().enumerate() {
unwrap!(paired_device_indices
.push(screen.add_subscreen(Subscreen::DeviceScreen(*device, i))));
}

let devices = screen.add_paired_devices_menu(paired_devices, paired_device_indices);
let pair_and_connect = screen.add_pair_and_connect_menu(devices);
let pair_and_connect = screen.add_pair_and_connect_menu(devices, connected_subtext);

let root = screen.add_root_menu(failed_backup, pair_and_connect, settings);
let root =
screen.add_root_menu(failed_backup, pair_and_connect, settings, connected_subtext);

screen.set_active_subscreen(root);

Expand Down Expand Up @@ -238,16 +243,18 @@ impl<'a> DeviceMenuScreen<'a> {
self.add_subscreen(Subscreen::Submenu(submenu_index))
}

fn add_pair_and_connect_menu(&mut self, manage_devices_index: usize) -> usize {
fn add_pair_and_connect_menu(
&mut self,
manage_devices_index: usize,
connected_subtext: Option<TString<'static>>,
) -> usize {
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
let mut manage_paired_item = MenuItem::new(
"Manage paired devices".into(),
Some(Action::GoTo(manage_devices_index)),
);
manage_paired_item.with_subtext(Some((
"1 device connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN),
)));
manage_paired_item
.with_subtext(connected_subtext.map(|t| (t, Some(Button::SUBTEXT_STYLE_GREEN))));
unwrap!(items.push(manage_paired_item));
unwrap!(items.push(MenuItem::new(
"Pair new device".into(),
Expand Down Expand Up @@ -326,6 +333,7 @@ impl<'a> DeviceMenuScreen<'a> {
failed_backup: bool,
pair_and_connect_index: usize,
settings_index: usize,
connected_subtext: Option<TString<'static>>,
) -> usize {
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
if failed_backup {
Expand All @@ -341,10 +349,8 @@ impl<'a> DeviceMenuScreen<'a> {
"Pair & connect".into(),
Some(Action::GoTo(pair_and_connect_index)),
);
item_pair_and_connect.with_subtext(Some((
"1 device connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN),
)));
item_pair_and_connect
.with_subtext(connected_subtext.map(|t| (t, Some(Button::SUBTEXT_STYLE_GREEN))));
unwrap!(items.push(item_pair_and_connect));
unwrap!(items.push(MenuItem::new(
"Settings".into(),
Expand Down
16 changes: 16 additions & 0 deletions core/embed/rust/src/ui/layout_eckhart/theme/firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,22 @@ pub const fn button_keyboard_next() -> ButtonStyleSheet {
}
}

// Things that look like button but don't do anything.
pub const fn button_always_disabled() -> ButtonStyleSheet {
let style = &ButtonStyle {
font: fonts::FONT_SATOSHI_MEDIUM_26,
text_color: GREY_LIGHT,
button_color: BG,
icon_color: GREY_LIGHT,
background_color: BG,
};
ButtonStyleSheet {
normal: style,
active: style,
disabled: style,
}
}

pub const fn input_mnemonic() -> ButtonStyleSheet {
ButtonStyleSheet {
normal: &ButtonStyle {
Expand Down
25 changes: 16 additions & 9 deletions core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1048,23 +1048,30 @@ impl FirmwareUI for UIEckhart {
ops = ops.text(text, font);
let screen = TextScreen::new(FormattedText::new(ops))
.with_header(Header::new("Pair with new device".into()).with_close_button())
.with_action_bar(ActionBar::new_single(Button::with_text(
"Continue on host".into(),
)));
.with_action_bar(ActionBar::new_text_only("Continue on host".into()));
#[cfg(feature = "ble")]
let screen = crate::ui::component::BLEHandler::new(screen, true);
let layout = RootComponent::new(screen);
Ok(layout)
}

fn show_pairing_code(code: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
let text: TString<'static> = "Pairing code match?".into();
fn show_pairing_code(
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 = ops.text(text, fonts::FONT_SATOSHI_REGULAR_38);
ops = ops.text(description, fonts::FONT_SATOSHI_REGULAR_38);
ops = ops.newline().newline().newline();
ops = ops.alignment(Alignment::Center);
ops = ops.text(code, fonts::FONT_SATOSHI_EXTRALIGHT_72);
let screen = TextScreen::new(FormattedText::new(ops))
.with_header(Header::new("Bluetooth pairing".into()))
.with_action_bar(ActionBar::new_cancel_confirm());
let mut screen = TextScreen::new(FormattedText::new(ops)).with_header(Header::new(title));
if button {
screen = screen.with_action_bar(ActionBar::new_cancel_confirm());
}
#[cfg(feature = "ble")]
let screen = crate::ui::component::BLEHandler::new(screen, false);
let layout = RootComponent::new(screen);
Ok(layout)
}
Expand Down
7 changes: 6 additions & 1 deletion core/embed/rust/src/ui/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,12 @@ pub trait FirmwareUI {
device_name: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;

fn show_pairing_code(code: TString<'static>) -> Result<impl LayoutMaybeTrace, Error>;
fn show_pairing_code(
title: TString<'static>,
description: TString<'static>,
code: TString<'static>,
button: bool,
) -> Result<impl LayoutMaybeTrace, Error>;

fn show_info(
title: TString<'static>,
Expand Down
Loading
Loading