mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-27 02:12:35 +00:00
chore(eckhart): provide short and long vertical menu
This commit is contained in:
parent
1e653a33cc
commit
00f58bd199
@ -18,14 +18,14 @@ use crate::{
|
||||
constant::SCREEN,
|
||||
firmware::{
|
||||
Header, HeaderMsg, TextScreen, TextScreenMsg, VerticalMenu, VerticalMenuScreen,
|
||||
VerticalMenuScreenMsg, MENU_MAX_ITEMS,
|
||||
VerticalMenuScreenMsg, SHORT_MENU_ITEMS,
|
||||
},
|
||||
},
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::theme;
|
||||
use super::{theme, ShortMenuVec};
|
||||
use heapless::Vec;
|
||||
|
||||
const MAX_DEPTH: usize = 3;
|
||||
@ -96,11 +96,11 @@ impl MenuItem {
|
||||
struct Submenu {
|
||||
header_text: TString<'static>,
|
||||
show_battery: bool,
|
||||
items: Vec<MenuItem, MENU_MAX_ITEMS>,
|
||||
items: Vec<MenuItem, SHORT_MENU_ITEMS>,
|
||||
}
|
||||
|
||||
impl Submenu {
|
||||
pub fn new(header_text: TString<'static>, items: Vec<MenuItem, MENU_MAX_ITEMS>) -> Self {
|
||||
pub fn new(header_text: TString<'static>, items: Vec<MenuItem, SHORT_MENU_ITEMS>) -> Self {
|
||||
Self {
|
||||
header_text,
|
||||
show_battery: false,
|
||||
@ -140,7 +140,7 @@ pub struct DeviceMenuScreen<'a> {
|
||||
// as defined by `enum Subscreen` (DeviceScreen is still a VerticalMenuScreen!)
|
||||
// The active one will be Some(...) and the other one will be None.
|
||||
// This way we only need to keep one screen at any time in memory.
|
||||
menu_screen: GcBox<Option<VerticalMenuScreen>>,
|
||||
menu_screen: GcBox<Option<VerticalMenuScreen<ShortMenuVec>>>,
|
||||
about_screen: GcBox<Option<TextScreen<Paragraphs<[Paragraph<'a>; 2]>>>>,
|
||||
|
||||
// Information needed to construct any subscreen on demand
|
||||
@ -209,7 +209,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
paired_devices: Vec<TString<'static>, 1>,
|
||||
paired_device_indices: Vec<usize, 1>,
|
||||
) -> usize {
|
||||
let mut items: Vec<MenuItem, MENU_MAX_ITEMS> = Vec::new();
|
||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||
for (device, idx) in paired_devices.iter().zip(paired_device_indices) {
|
||||
unwrap!(items.push(
|
||||
MenuItem::new(*device, Some(Action::GoTo(idx))).with_subtext(Some((
|
||||
@ -224,7 +224,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
}
|
||||
|
||||
fn add_pair_and_connect_menu(&mut self, manage_devices_index: usize) -> usize {
|
||||
let mut items: Vec<MenuItem, MENU_MAX_ITEMS> = Vec::new();
|
||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||
unwrap!(items.push(
|
||||
MenuItem::new(
|
||||
"Manage paired devices".into(),
|
||||
@ -245,7 +245,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
}
|
||||
|
||||
fn add_settings_menu(&mut self, security_index: usize, device_index: usize) -> usize {
|
||||
let mut items: Vec<MenuItem, MENU_MAX_ITEMS> = Vec::new();
|
||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||
unwrap!(items.push(MenuItem::new(
|
||||
"Security".into(),
|
||||
Some(Action::GoTo(security_index))
|
||||
@ -260,7 +260,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
}
|
||||
|
||||
fn add_security_menu(&mut self) -> usize {
|
||||
let mut items: Vec<MenuItem, MENU_MAX_ITEMS> = Vec::new();
|
||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||
unwrap!(items.push(MenuItem::new(
|
||||
"Check backup".into(),
|
||||
Some(Action::Return(DeviceMenuMsg::CheckBackup)),
|
||||
@ -275,7 +275,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
}
|
||||
|
||||
fn add_device_menu(&mut self, device_name: TString<'static>, about_index: usize) -> usize {
|
||||
let mut items: Vec<MenuItem, MENU_MAX_ITEMS> = Vec::new();
|
||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||
unwrap!(
|
||||
items.push(MenuItem::new("Name".into(), None).with_subtext(Some((device_name, None))))
|
||||
);
|
||||
@ -298,7 +298,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
pair_and_connect_index: usize,
|
||||
settings_index: usize,
|
||||
) -> usize {
|
||||
let mut items: Vec<MenuItem, MENU_MAX_ITEMS> = Vec::new();
|
||||
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
|
||||
if failed_backup {
|
||||
unwrap!(items.push(
|
||||
MenuItem::new(
|
||||
@ -349,7 +349,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
Subscreen::Submenu(ref mut submenu_index) => {
|
||||
let submenu = &self.submenus[*submenu_index];
|
||||
*self.about_screen.deref_mut() = None;
|
||||
let mut menu = VerticalMenu::empty().with_separators();
|
||||
let mut menu = VerticalMenu::<ShortMenuVec>::empty().with_separators();
|
||||
for item in &submenu.items {
|
||||
let button = if let Some((subtext, subtext_style)) = item.subtext {
|
||||
Button::new_menu_item_with_subtext(
|
||||
@ -361,7 +361,7 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
} else {
|
||||
Button::new_menu_item(item.text, item.stylesheet)
|
||||
};
|
||||
menu = menu.item(button);
|
||||
menu.item(button);
|
||||
}
|
||||
let mut header = Header::new(submenu.header_text).with_close_button();
|
||||
if submenu.show_battery {
|
||||
@ -385,8 +385,8 @@ impl<'a> DeviceMenuScreen<'a> {
|
||||
Subscreen::DeviceScreen(device, _) => {
|
||||
*self.about_screen.deref_mut() = None;
|
||||
let mut menu = VerticalMenu::empty().with_separators();
|
||||
menu = menu.item(Button::new_menu_item(device, theme::menu_item_title()));
|
||||
menu = menu.item(Button::new_menu_item(
|
||||
menu.item(Button::new_menu_item(device, theme::menu_item_title()));
|
||||
menu.item(Button::new_menu_item(
|
||||
"Disconnect".into(),
|
||||
theme::menu_item_title_red(),
|
||||
));
|
||||
|
@ -40,7 +40,10 @@ pub use qr_screen::{QrMsg, QrScreen};
|
||||
pub use select_word_screen::{SelectWordMsg, SelectWordScreen};
|
||||
pub use share_words::{ShareWordsScreen, ShareWordsScreenMsg};
|
||||
pub use text_screen::{AllowedTextContent, TextScreen, TextScreenMsg};
|
||||
pub use vertical_menu::{VerticalMenu, VerticalMenuMsg, MENU_MAX_ITEMS};
|
||||
pub use vertical_menu::{
|
||||
LongMenuGc, MenuItems, ShortMenuVec, VerticalMenu, VerticalMenuMsg, LONG_MENU_ITEMS,
|
||||
SHORT_MENU_ITEMS,
|
||||
};
|
||||
pub use vertical_menu_screen::{VerticalMenuScreen, VerticalMenuScreenMsg};
|
||||
|
||||
use super::{constant, theme};
|
||||
|
@ -1,9 +1,14 @@
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx},
|
||||
event::TouchEvent,
|
||||
geometry::{Direction, Insets, Offset, Rect},
|
||||
shape::{Bar, Renderer},
|
||||
util::animation_disabled,
|
||||
use core::ops::DerefMut;
|
||||
|
||||
use crate::{
|
||||
micropython::gc::GcBox,
|
||||
ui::{
|
||||
component::{Component, Event, EventCtx},
|
||||
event::TouchEvent,
|
||||
geometry::{Direction, Insets, Offset, Rect},
|
||||
shape::{Bar, Renderer},
|
||||
util::animation_disabled,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -14,15 +19,78 @@ use heapless::Vec;
|
||||
|
||||
/// Number of buttons.
|
||||
/// Presently, VerticalMenu holds only fixed number of buttons.
|
||||
pub const MENU_MAX_ITEMS: usize = 5;
|
||||
pub const LONG_MENU_ITEMS: usize = 100;
|
||||
pub const SHORT_MENU_ITEMS: usize = 5;
|
||||
|
||||
type VerticalMenuButtons = Vec<Button, MENU_MAX_ITEMS>;
|
||||
pub type LongMenuGc = GcBox<Vec<Button, LONG_MENU_ITEMS>>;
|
||||
pub type ShortMenuVec = Vec<Button, SHORT_MENU_ITEMS>;
|
||||
|
||||
pub struct VerticalMenu {
|
||||
pub trait MenuItems: Default {
|
||||
fn empty() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
fn push(&mut self, button: Button);
|
||||
fn iter(&self) -> core::slice::Iter<'_, Button>;
|
||||
fn iter_mut(&mut self) -> core::slice::IterMut<'_, Button>;
|
||||
fn get_len(&self) -> usize;
|
||||
fn get_last(&self) -> Option<&Button>;
|
||||
}
|
||||
|
||||
impl MenuItems for ShortMenuVec {
|
||||
fn push(&mut self, button: Button) {
|
||||
unwrap!(self.push(button));
|
||||
}
|
||||
|
||||
fn iter(&self) -> core::slice::Iter<'_, Button> {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
|
||||
fn iter_mut(&mut self) -> core::slice::IterMut<'_, Button> {
|
||||
self.as_mut_slice().iter_mut()
|
||||
}
|
||||
|
||||
fn get_len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn get_last(&self) -> Option<&Button> {
|
||||
self.last()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GcBox<Vec<Button, LONG_MENU_ITEMS>> {
|
||||
fn default() -> Self {
|
||||
unwrap!(GcBox::new(Vec::new()))
|
||||
}
|
||||
}
|
||||
|
||||
impl MenuItems for LongMenuGc {
|
||||
fn push(&mut self, button: Button) {
|
||||
unwrap!(self.deref_mut().push(button));
|
||||
}
|
||||
|
||||
fn iter(&self) -> core::slice::Iter<'_, Button> {
|
||||
self.as_slice().iter()
|
||||
}
|
||||
|
||||
fn iter_mut(&mut self) -> core::slice::IterMut<'_, Button> {
|
||||
self.as_mut_slice().iter_mut()
|
||||
}
|
||||
|
||||
fn get_len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn get_last(&self) -> Option<&Button> {
|
||||
self.last()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VerticalMenu<T = ShortMenuVec> {
|
||||
/// Bounds the sliding window of the menu.
|
||||
bounds: Rect,
|
||||
/// Menu items.
|
||||
buttons: VerticalMenuButtons,
|
||||
buttons: T,
|
||||
/// Full height of the menu, including overflowing items.
|
||||
total_height: i16,
|
||||
/// Vertical offset of the current view.
|
||||
@ -37,12 +105,12 @@ pub enum VerticalMenuMsg {
|
||||
Selected(usize),
|
||||
}
|
||||
|
||||
impl VerticalMenu {
|
||||
impl<T: MenuItems> VerticalMenu<T> {
|
||||
const SIDE_INSETS: Insets = Insets::sides(12);
|
||||
const DEFAULT_PADDING: i16 = 28;
|
||||
const MIN_PADDING: i16 = 2;
|
||||
|
||||
fn new(buttons: VerticalMenuButtons) -> Self {
|
||||
fn new(buttons: T) -> Self {
|
||||
Self {
|
||||
bounds: Rect::zero(),
|
||||
buttons,
|
||||
@ -54,7 +122,7 @@ impl VerticalMenu {
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self::new(VerticalMenuButtons::new())
|
||||
Self::new(T::default())
|
||||
}
|
||||
|
||||
pub fn with_separators(mut self) -> Self {
|
||||
@ -62,8 +130,13 @@ impl VerticalMenu {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn item(mut self, button: Button) -> Self {
|
||||
unwrap!(self.buttons.push(button));
|
||||
pub fn with_item(mut self, button: Button) -> Self {
|
||||
self.buttons.push(button);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn item(&mut self, button: Button) -> &mut Self {
|
||||
self.buttons.push(button);
|
||||
self
|
||||
}
|
||||
|
||||
@ -112,7 +185,7 @@ impl VerticalMenu {
|
||||
debug_assert!(dir == Direction::Up || dir == Direction::Down);
|
||||
|
||||
// For single button, the menu is not scrollable
|
||||
if self.buttons.len() < 2 {
|
||||
if self.buttons.get_len() < 2 {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -120,7 +193,11 @@ impl VerticalMenu {
|
||||
let current = self.offset_y;
|
||||
let mut cumsum = 0;
|
||||
|
||||
for button in &self.buttons[..self.buttons.len() - 1] {
|
||||
for button in self
|
||||
.buttons
|
||||
.iter()
|
||||
.take(self.buttons.get_len().saturating_sub(1))
|
||||
{
|
||||
let new_cumsum = cumsum + button.area().height();
|
||||
match dir {
|
||||
Direction::Up if new_cumsum > current => {
|
||||
@ -146,7 +223,7 @@ impl VerticalMenu {
|
||||
self.offset_y_max = self.total_height
|
||||
- self
|
||||
.buttons
|
||||
.last()
|
||||
.get_last()
|
||||
.unwrap_or(&Button::empty())
|
||||
.area()
|
||||
.height();
|
||||
@ -158,7 +235,7 @@ impl VerticalMenu {
|
||||
|
||||
// Find the first button from the top that would completely fit in the menu area
|
||||
// in the bottom position
|
||||
for button in &self.buttons {
|
||||
for button in self.buttons.iter() {
|
||||
let offset = button.area().top_left().y - self.bounds.top_left().y;
|
||||
if offset > menu_overflow {
|
||||
self.offset_y_max = offset;
|
||||
@ -186,15 +263,16 @@ impl VerticalMenu {
|
||||
}
|
||||
|
||||
fn render_buttons<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
for button in &self.buttons {
|
||||
for button in self.buttons.iter() {
|
||||
button.render(target);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_separators<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
for i in 1..self.buttons.len() {
|
||||
let button = &self.buttons[i];
|
||||
let button_prev = &self.buttons[i - 1];
|
||||
for pair in self.buttons.iter().as_slice().windows(2) {
|
||||
let [button_prev, button] = pair else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !button.is_pressed() && !button_prev.is_pressed() {
|
||||
let separator = Rect::from_top_left_and_size(
|
||||
@ -212,7 +290,7 @@ impl VerticalMenu {
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for VerticalMenu {
|
||||
impl<T: MenuItems> Component for VerticalMenu<T> {
|
||||
type Msg = VerticalMenuMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
@ -269,11 +347,14 @@ impl Component for VerticalMenu {
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl crate::trace::Trace for VerticalMenu {
|
||||
impl<T: MenuItems> crate::trace::Trace for VerticalMenu<T> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
// Trace the VerticalMenu component
|
||||
t.component("VerticalMenu");
|
||||
|
||||
// Trace the buttons as a list
|
||||
t.in_list("buttons", &|button_list| {
|
||||
for button in &self.buttons {
|
||||
for button in self.buttons.iter() {
|
||||
button_list.child(button);
|
||||
}
|
||||
});
|
||||
|
@ -13,12 +13,12 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use super::{constant::SCREEN, theme, Header, HeaderMsg, VerticalMenu, VerticalMenuMsg};
|
||||
use super::{constant::SCREEN, theme, Header, HeaderMsg, MenuItems, VerticalMenu, VerticalMenuMsg};
|
||||
|
||||
pub struct VerticalMenuScreen {
|
||||
pub struct VerticalMenuScreen<T> {
|
||||
header: Header,
|
||||
/// Scrollable vertical menu
|
||||
menu: VerticalMenu,
|
||||
menu: VerticalMenu<T>,
|
||||
/// Base position of the menu sliding window to scroll around
|
||||
offset_base: i16,
|
||||
/// Swipe detector
|
||||
@ -37,9 +37,9 @@ pub enum VerticalMenuScreenMsg {
|
||||
Menu,
|
||||
}
|
||||
|
||||
impl VerticalMenuScreen {
|
||||
impl<T: MenuItems> VerticalMenuScreen<T> {
|
||||
const TOUCH_SENSITIVITY_DIVIDER: i16 = 15;
|
||||
pub fn new(menu: VerticalMenu) -> Self {
|
||||
pub fn new(menu: VerticalMenu<T>) -> Self {
|
||||
Self {
|
||||
header: Header::new(TString::empty()),
|
||||
menu,
|
||||
@ -164,7 +164,7 @@ impl VerticalMenuScreen {
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for VerticalMenuScreen {
|
||||
impl<T: MenuItems> Component for VerticalMenuScreen<T> {
|
||||
type Msg = VerticalMenuScreenMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
@ -211,7 +211,7 @@ impl Component for VerticalMenuScreen {
|
||||
}
|
||||
|
||||
#[cfg(feature = "micropython")]
|
||||
impl Swipable for VerticalMenuScreen {
|
||||
impl<T: MenuItems> Swipable for VerticalMenuScreen<T> {
|
||||
fn get_swipe_config(&self) -> SwipeConfig {
|
||||
self.swipe_config
|
||||
}
|
||||
@ -222,7 +222,7 @@ impl Swipable for VerticalMenuScreen {
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl crate::trace::Trace for VerticalMenuScreen {
|
||||
impl<T: MenuItems> crate::trace::Trace for VerticalMenuScreen<T> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("VerticalMenuScreen");
|
||||
t.child("Header", &self.header);
|
||||
|
@ -19,8 +19,8 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, FidoCredential, Header, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
ActionBar, FidoCredential, Header, LongMenuGc, ShortMenuVec, TextScreen, TextScreenMsg,
|
||||
VerticalMenu, VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -111,13 +111,13 @@ pub fn new_confirm_fido(
|
||||
});
|
||||
|
||||
// Choose credential screen
|
||||
let mut credentials = VerticalMenu::empty();
|
||||
let mut credentials = VerticalMenu::<LongMenuGc>::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::new_menu_item(label, theme::menu_item_title()));
|
||||
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()))
|
||||
@ -158,10 +158,9 @@ pub fn new_confirm_fido(
|
||||
});
|
||||
|
||||
// Menu screen
|
||||
let content_menu = VerticalMenuScreen::new(VerticalMenu::empty().item(Button::new_menu_item(
|
||||
TR::buttons__cancel.into(),
|
||||
theme::menu_item_title_orange(),
|
||||
)))
|
||||
let content_menu = VerticalMenuScreen::new(VerticalMenu::<ShortMenuVec>::empty().with_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)),
|
||||
|
@ -22,8 +22,8 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, Header, TextScreen, TextScreenMsg, VerticalMenu, VerticalMenuScreen,
|
||||
VerticalMenuScreenMsg,
|
||||
ActionBar, Header, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -213,11 +213,11 @@ fn content_main_menu(
|
||||
address_params: bool,
|
||||
account_params: bool,
|
||||
cancel_menu_label: TString<'static>,
|
||||
) -> MsgMap<VerticalMenuScreen, impl Fn(VerticalMenuScreenMsg) -> Option<FlowMsg>> {
|
||||
let mut main_menu = VerticalMenu::empty();
|
||||
) -> MsgMap<VerticalMenuScreen<ShortMenuVec>, impl Fn(VerticalMenuScreenMsg) -> Option<FlowMsg>> {
|
||||
let mut main_menu = VerticalMenu::<ShortMenuVec>::empty();
|
||||
let mut main_menu_items = Vec::<usize, 3>::new();
|
||||
if address_params {
|
||||
main_menu = main_menu.item(
|
||||
main_menu.item(
|
||||
Button::with_text(address_title)
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start),
|
||||
@ -225,7 +225,7 @@ fn content_main_menu(
|
||||
unwrap!(main_menu_items.push(MENU_ITEM_ADDRESS_INFO));
|
||||
}
|
||||
if account_params {
|
||||
main_menu = main_menu.item(
|
||||
main_menu.item(
|
||||
Button::with_text(TR::address_details__account_info.into())
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start)
|
||||
@ -233,7 +233,7 @@ fn content_main_menu(
|
||||
);
|
||||
unwrap!(main_menu_items.push(MENU_ITEM_ACCOUNT_INFO));
|
||||
}
|
||||
main_menu = main_menu.item(
|
||||
main_menu.item(
|
||||
Button::with_text(cancel_menu_label)
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
@ -241,7 +241,7 @@ fn content_main_menu(
|
||||
);
|
||||
unwrap!(main_menu_items.push(MENU_ITEM_CANCEL));
|
||||
|
||||
VerticalMenuScreen::new(main_menu)
|
||||
VerticalMenuScreen::<ShortMenuVec>::new(main_menu)
|
||||
.with_header(Header::new(TString::empty()).with_close_button())
|
||||
.map(move |msg| match msg {
|
||||
VerticalMenuScreenMsg::Selected(i) => {
|
||||
@ -434,18 +434,17 @@ pub fn new_confirm_output(
|
||||
.with_pages(|_| 1);
|
||||
|
||||
// SummaryMenu
|
||||
let mut summary_menu = VerticalMenu::empty();
|
||||
let mut summary_menu = VerticalMenu::<ShortMenuVec>::empty();
|
||||
let mut summary_menu_items = Vec::<usize, 3>::new();
|
||||
if account_menu_item {
|
||||
summary_menu = summary_menu.item(Button::with_text(account_title));
|
||||
summary_menu.item(Button::with_text(account_title));
|
||||
unwrap!(summary_menu_items.push(MENU_ITEM_EXTRA_INFO));
|
||||
}
|
||||
if fee_menu_item {
|
||||
summary_menu =
|
||||
summary_menu.item(Button::with_text(TR::confirm_total__title_fee.into()));
|
||||
summary_menu.item(Button::with_text(TR::confirm_total__title_fee.into()));
|
||||
unwrap!(summary_menu_items.push(MENU_ITEM_FEE_INFO));
|
||||
}
|
||||
summary_menu = summary_menu
|
||||
summary_menu
|
||||
.item(Button::with_text(cancel_menu_label).styled(theme::menu_item_title_orange()));
|
||||
unwrap!(summary_menu_items.push(MENU_ITEM_CANCEL));
|
||||
let content_summary_menu = VerticalMenuScreen::new(summary_menu)
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
FlowController, FlowMsg, SwipeFlow,
|
||||
},
|
||||
geometry::{Alignment, Direction, Offset},
|
||||
layout_eckhart::component::Button,
|
||||
layout_eckhart::{component::Button, firmware::ShortMenuVec},
|
||||
},
|
||||
};
|
||||
|
||||
@ -84,7 +84,7 @@ pub fn new_confirm_reset(recovery: bool) -> Result<SwipeFlow, error::Error> {
|
||||
.one_button_request(br);
|
||||
|
||||
let content_menu = VerticalMenuScreen::new(
|
||||
VerticalMenu::empty().item(
|
||||
VerticalMenu::<ShortMenuVec>::empty().with_item(
|
||||
Button::with_text(TR::buttons__cancel.into())
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
|
@ -20,8 +20,8 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, Header, Hint, TextScreen, TextScreenMsg, VerticalMenu, VerticalMenuScreen,
|
||||
VerticalMenuScreenMsg,
|
||||
ActionBar, Header, Hint, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -131,11 +131,11 @@ pub fn new_confirm_summary(
|
||||
});
|
||||
|
||||
// Menu
|
||||
let mut menu = VerticalMenu::empty();
|
||||
let mut menu = VerticalMenu::<ShortMenuVec>::empty();
|
||||
let mut menu_items = Vec::<usize, 3>::new();
|
||||
|
||||
if account_paragraphs.is_some() {
|
||||
menu = menu.item(
|
||||
menu.item(
|
||||
Button::with_text(TR::address_details__account_info.into())
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start)
|
||||
@ -144,7 +144,7 @@ pub fn new_confirm_summary(
|
||||
unwrap!(menu_items.push(MENU_ITEM_ACCOUNT_INFO));
|
||||
}
|
||||
if extra_paragraphs.is_some() {
|
||||
menu = menu.item(
|
||||
menu.item(
|
||||
Button::with_text(extra_title.unwrap_or(TR::buttons__more_info.into()))
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start)
|
||||
@ -152,7 +152,7 @@ pub fn new_confirm_summary(
|
||||
);
|
||||
unwrap!(menu_items.push(MENU_ITEM_EXTRA_INFO));
|
||||
}
|
||||
menu = menu.item(
|
||||
menu.item(
|
||||
Button::with_text(verb_cancel.unwrap_or(TR::buttons__cancel.into()))
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
|
@ -23,8 +23,8 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, Header, TextScreen, TextScreenMsg, VerticalMenu, VerticalMenuScreen,
|
||||
VerticalMenuScreenMsg,
|
||||
ActionBar, Header, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -208,7 +208,7 @@ pub fn new_continue_recovery_homepage(
|
||||
|
||||
let res = if show_instructions {
|
||||
let content_menu = VerticalMenuScreen::new(
|
||||
VerticalMenu::empty().item(
|
||||
VerticalMenu::<ShortMenuVec>::empty().with_item(
|
||||
Button::with_text(cancel_btn.into())
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
@ -228,8 +228,8 @@ pub fn new_continue_recovery_homepage(
|
||||
res
|
||||
} else if pages.is_none() {
|
||||
let content_menu = VerticalMenuScreen::new(
|
||||
VerticalMenu::empty()
|
||||
.item(
|
||||
VerticalMenu::<ShortMenuVec>::empty()
|
||||
.with_item(
|
||||
Button::with_text_and_subtext(
|
||||
TR::words__recovery_share.into(),
|
||||
TR::buttons__more_info.into(),
|
||||
@ -239,7 +239,7 @@ pub fn new_continue_recovery_homepage(
|
||||
.with_text_align(Alignment::Start)
|
||||
.with_content_offset(Offset::x(12)),
|
||||
)
|
||||
.item(
|
||||
.with_item(
|
||||
Button::with_text(cancel_btn.into())
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
@ -280,14 +280,14 @@ pub fn new_continue_recovery_homepage(
|
||||
res
|
||||
} else {
|
||||
let content_menu = VerticalMenuScreen::new(
|
||||
VerticalMenu::empty()
|
||||
.item(
|
||||
VerticalMenu::<ShortMenuVec>::empty()
|
||||
.with_item(
|
||||
Button::with_text(TR::recovery__title_remaining_shares.into())
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start)
|
||||
.with_content_offset(Offset::x(12)),
|
||||
)
|
||||
.item(
|
||||
.with_item(
|
||||
Button::with_text(cancel_btn.into())
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
|
@ -20,8 +20,8 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, Header, HeaderMsg, Hint, QrScreen, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
ActionBar, Header, HeaderMsg, Hint, QrScreen, ShortMenuVec, TextScreen, TextScreenMsg,
|
||||
VerticalMenu, VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -132,20 +132,20 @@ pub fn new_get_address(
|
||||
// Menu
|
||||
|
||||
let content_menu = VerticalMenuScreen::new(
|
||||
VerticalMenu::empty()
|
||||
.item(
|
||||
VerticalMenu::<ShortMenuVec>::empty()
|
||||
.with_item(
|
||||
Button::with_text(TR::address__qr_code.into())
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start)
|
||||
.with_content_offset(Offset::x(12)),
|
||||
)
|
||||
.item(
|
||||
.with_item(
|
||||
Button::with_text(TR::address_details__account_info.into())
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start)
|
||||
.with_content_offset(Offset::x(12)),
|
||||
)
|
||||
.item(
|
||||
.with_item(
|
||||
Button::with_text(TR::buttons__cancel.into())
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
|
@ -18,7 +18,7 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, Header, HeaderMsg, Hint, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
ActionBar, Header, HeaderMsg, Hint, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
@ -73,7 +73,7 @@ pub fn new_prompt_backup() -> Result<SwipeFlow, error::Error> {
|
||||
});
|
||||
|
||||
let content_menu = VerticalMenuScreen::new(
|
||||
VerticalMenu::empty().item(
|
||||
VerticalMenu::<ShortMenuVec>::empty().with_item(
|
||||
Button::with_text(TR::backup__title_skip.into())
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
|
@ -18,8 +18,8 @@ use crate::{
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, Header, HeaderMsg, TextScreen, TextScreenMsg, VerticalMenu, VerticalMenuScreen,
|
||||
VerticalMenuScreenMsg,
|
||||
ActionBar, Header, HeaderMsg, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
|
||||
VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -89,15 +89,15 @@ pub fn new_show_danger(
|
||||
|
||||
// Menu
|
||||
let content_menu = VerticalMenuScreen::new(
|
||||
VerticalMenu::empty()
|
||||
VerticalMenu::<ShortMenuVec>::empty()
|
||||
.with_separators()
|
||||
.item(
|
||||
.with_item(
|
||||
Button::with_text(verb_cancel)
|
||||
.styled(theme::menu_item_title())
|
||||
.with_text_align(Alignment::Start)
|
||||
.with_content_offset(Offset::x(12)),
|
||||
)
|
||||
.item(
|
||||
.with_item(
|
||||
Button::with_text(TR::words__continue_anyway.into())
|
||||
.styled(theme::menu_item_title_orange())
|
||||
.with_text_align(Alignment::Start)
|
||||
|
Loading…
Reference in New Issue
Block a user