mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-04-20 17:19:01 +00:00
fixup! feat(eckhart): add FIDO2 support FidoCredential component, confirm_fido flow and icons
This commit is contained in:
parent
f4fd6a2f0b
commit
80174621db
@ -8,22 +8,25 @@ use crate::{
|
||||
paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs},
|
||||
TextStyle,
|
||||
},
|
||||
Component, Event, EventCtx, LineBreaking,
|
||||
Component, Event, EventCtx, LineBreaking, Never,
|
||||
},
|
||||
geometry::{Insets, LinearPlacement, Offset, Rect},
|
||||
geometry::{LinearPlacement, Rect},
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::super::{firmware::fido_icons::get_fido_icon_data, theme};
|
||||
|
||||
pub struct FidoCredential<F: Fn() -> TString<'static>> {
|
||||
pub trait FidoAccountName: Fn() -> TString<'static> {}
|
||||
impl<T: Fn() -> TString<'static>> FidoAccountName for T {}
|
||||
|
||||
pub struct FidoCredential<F: FidoAccountName> {
|
||||
app_icon: Option<Image>,
|
||||
text: Paragraphs<ParagraphVecShort<'static>>,
|
||||
get_account: F,
|
||||
}
|
||||
|
||||
impl<F: Fn() -> TString<'static>> FidoCredential<F> {
|
||||
impl<F: FidoAccountName> FidoCredential<F> {
|
||||
const ICON_SIZE: i16 = 32;
|
||||
const SPACING: i16 = 24;
|
||||
|
||||
@ -32,6 +35,7 @@ impl<F: Fn() -> TString<'static>> FidoCredential<F> {
|
||||
app_name: TString<'static>,
|
||||
get_account: F,
|
||||
) -> Self {
|
||||
// Text style without line-breaking hyphens
|
||||
const STYLE: TextStyle =
|
||||
theme::TEXT_REGULAR.with_line_breaking(LineBreaking::BreakWordsNoHyphen);
|
||||
let app_icon = get_fido_icon_data(icon_name).map(Image::new);
|
||||
@ -50,21 +54,19 @@ impl<F: Fn() -> TString<'static>> FidoCredential<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Fn() -> TString<'static>> Component for FidoCredential<F> {
|
||||
type Msg = ();
|
||||
impl<F: FidoAccountName> Component for FidoCredential<F> {
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
let icon_size = self.app_icon.map_or(Offset::zero(), |i| i.toif.size());
|
||||
let (icon_area, text_area) = bounds.split_top(icon_size.y);
|
||||
let text_area = text_area.inset(Insets::top(Self::SPACING));
|
||||
self.text.place(text_area);
|
||||
// let text_height = self.text.area().height();
|
||||
// let vertical_space = bounds.height() - icon_size.y - Self::SPACING -
|
||||
// text_height; let off = Offset::y(vertical_space / 2);
|
||||
let text_area = if let Some(app_icon) = &mut self.app_icon {
|
||||
let icon_size = app_icon.toif.size();
|
||||
let (icon_area, text_area) = bounds.split_top(icon_size.y + Self::SPACING);
|
||||
app_icon.place(icon_area.with_width(icon_size.x).with_height(icon_size.y));
|
||||
text_area
|
||||
} else {
|
||||
bounds
|
||||
};
|
||||
|
||||
// let icon_area = icon_area.with_width(icon_size.x).translate(off);
|
||||
// let text_area = text_area.with_height(text_height).translate(off);
|
||||
self.app_icon.place(icon_area);
|
||||
self.text.place(text_area);
|
||||
bounds
|
||||
}
|
||||
@ -85,11 +87,15 @@ impl<F: Fn() -> TString<'static>> Component for FidoCredential<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Fn() -> TString<'static>> SinglePage for FidoCredential<F> {}
|
||||
impl<F: FidoAccountName> SinglePage for FidoCredential<F> {}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<F: Fn() -> TString<'static>> crate::trace::Trace for FidoCredential<F> {
|
||||
impl<F: FidoAccountName> crate::trace::Trace for FidoCredential<F> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("FidoCredential");
|
||||
if let Some(app_icon) = self.app_icon.as_ref() {
|
||||
t.child("app_icon", app_icon);
|
||||
}
|
||||
t.child("paragraphs", &self.text);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ pub use action_bar::{ActionBar, ActionBarMsg};
|
||||
pub use brightness_screen::SetBrightnessScreen;
|
||||
pub use confirm_homescreen::{ConfirmHomescreen, ConfirmHomescreenMsg};
|
||||
pub use device_menu_screen::{DeviceMenuMsg, DeviceMenuScreen};
|
||||
pub use fido::FidoCredential;
|
||||
pub use fido::{FidoAccountName, FidoCredential};
|
||||
pub use header::{Header, HeaderMsg};
|
||||
pub use hint::Hint;
|
||||
pub use hold_to_confirm::HoldToConfirmAnim;
|
||||
|
@ -19,7 +19,7 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, FidoCredential, Header, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
ActionBar, FidoCredential, Header, HeaderMsg, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
@ -57,7 +57,13 @@ impl FlowController for ConfirmFido {
|
||||
Self::Authenticate.goto()
|
||||
}
|
||||
(_, FlowMsg::Info) => Self::Menu.goto(),
|
||||
(Self::Authenticate, FlowMsg::Cancelled) => Self::ChooseCredential.goto(),
|
||||
(Self::Authenticate, FlowMsg::Cancelled) => {
|
||||
if single_cred() {
|
||||
self.return_msg(FlowMsg::Cancelled)
|
||||
} else {
|
||||
Self::ChooseCredential.goto()
|
||||
}
|
||||
}
|
||||
(Self::Authenticate, FlowMsg::Confirmed) => {
|
||||
self.return_msg(FlowMsg::Choice(CRED_SELECTED.load(Ordering::Relaxed)))
|
||||
}
|
||||
@ -88,6 +94,7 @@ pub fn new_confirm_fido(
|
||||
SINGLE_CRED.store(num_accounts <= 1, Ordering::Relaxed);
|
||||
CRED_SELECTED.store(0, Ordering::Relaxed);
|
||||
|
||||
// Intro screen
|
||||
let content_intro = TextScreen::new(
|
||||
Paragraph::new::<TString>(&theme::TEXT_REGULAR, TR::fido__select_intro.into())
|
||||
.into_paragraphs()
|
||||
@ -103,54 +110,63 @@ pub fn new_confirm_fido(
|
||||
_ => None,
|
||||
});
|
||||
|
||||
// Choose credential screen
|
||||
let mut credentials = VerticalMenu::empty();
|
||||
for i in 0..num_accounts {
|
||||
let account = unwrap!(accounts.get(i));
|
||||
let label = account
|
||||
.try_into()
|
||||
.unwrap_or_else(|_| TString::from_str("-"));
|
||||
credentials = credentials.item(Button::with_text(label));
|
||||
credentials = credentials.item(Button::new_menu_item(label, theme::menu_item_title()));
|
||||
}
|
||||
let content_choose_credential = VerticalMenuScreen::new(credentials)
|
||||
.with_header(Header::new(TR::fido__title_select_credential.into()))
|
||||
.map(|msg| match msg {
|
||||
VerticalMenuScreenMsg::Selected(i) => Some(FlowMsg::Choice(i)),
|
||||
VerticalMenuScreenMsg::Close => Some(FlowMsg::Cancelled),
|
||||
VerticalMenuScreenMsg::Menu => Some(FlowMsg::Info),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
// Authenticate screen
|
||||
let get_account = move || {
|
||||
let current = CRED_SELECTED.load(Ordering::Relaxed);
|
||||
let account = unwrap!(accounts.get(current));
|
||||
account.try_into().unwrap_or_else(|_| TString::from_str(""))
|
||||
};
|
||||
|
||||
let mut auth_header = Header::new(TR::fido__title_credential_details.into());
|
||||
auth_header = if single_cred() {
|
||||
auth_header.with_menu_button()
|
||||
let auth_header = if single_cred() {
|
||||
Header::new(title)
|
||||
} else {
|
||||
auth_header.with_close_button()
|
||||
Header::new(TR::fido__title_credential_details.into()).with_close_button()
|
||||
};
|
||||
let auth_action_bar = if single_cred() {
|
||||
ActionBar::new_cancel_confirm()
|
||||
} else {
|
||||
ActionBar::new_single(
|
||||
Button::with_text(TR::words__authenticate.into()).styled(theme::button_confirm()),
|
||||
)
|
||||
};
|
||||
|
||||
let content_authenticate =
|
||||
TextScreen::new(FidoCredential::new(icon_name, app_name, get_account))
|
||||
.with_header(auth_header)
|
||||
.with_action_bar(ActionBar::new_single(
|
||||
Button::with_text(TR::words__authenticate.into()).styled(theme::button_confirm()),
|
||||
))
|
||||
.with_action_bar(auth_action_bar)
|
||||
.map(|msg| match msg {
|
||||
TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
|
||||
TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
|
||||
TextScreenMsg::Menu => Some(FlowMsg::Info),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let content_menu = VerticalMenuScreen::new(VerticalMenu::empty().item(
|
||||
Button::with_text(TR::buttons__cancel.into()).styled(theme::menu_item_title_orange()),
|
||||
))
|
||||
.with_header(Header::new(TR::fido__title_authenticate.into()).with_close_button())
|
||||
// Menu screen
|
||||
let content_menu = VerticalMenuScreen::new(VerticalMenu::empty().item(Button::new_menu_item(
|
||||
TR::buttons__cancel.into(),
|
||||
theme::menu_item_title_orange(),
|
||||
)))
|
||||
.with_header(Header::new(title).with_close_button())
|
||||
.map(|msg| match msg {
|
||||
VerticalMenuScreenMsg::Selected(0) => Some(FlowMsg::Choice(0)),
|
||||
VerticalMenuScreenMsg::Menu => Some(FlowMsg::Info),
|
||||
VerticalMenuScreenMsg::Close => Some(FlowMsg::Cancelled),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user