mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-21 05:48:23 +00:00
refactor(core/rust): refactor SwipeFlow
* remove SwipeStore in favor of Vec<dyn FlowComponent> * unify state and controllers * implement tighter coupling between controller/states and pages of the flow
This commit is contained in:
parent
4c10a4f643
commit
3fcb0acaff
@ -1,5 +1,4 @@
|
|||||||
use crate::ui::component::{swipe_detect::SwipeConfig, SwipeDirection};
|
use crate::ui::component::{swipe_detect::SwipeConfig, SwipeDirection};
|
||||||
use num_traits::ToPrimitive;
|
|
||||||
|
|
||||||
pub trait Swipable {
|
pub trait Swipable {
|
||||||
fn get_swipe_config(&self) -> SwipeConfig;
|
fn get_swipe_config(&self) -> SwipeConfig;
|
||||||
@ -22,20 +21,20 @@ pub enum FlowMsg {
|
|||||||
|
|
||||||
/// Composable event handler result.
|
/// Composable event handler result.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Decision<Q> {
|
pub enum Decision {
|
||||||
/// Do nothing, continue with processing next handler.
|
/// Do nothing, continue with processing next handler.
|
||||||
Nothing,
|
Nothing,
|
||||||
|
|
||||||
/// Initiate transition to another state, end event processing.
|
/// Initiate transition to another state, end event processing.
|
||||||
/// NOTE: it might make sense to include Option<ButtonRequest> here
|
/// NOTE: it might make sense to include Option<ButtonRequest> here
|
||||||
Goto(Q, SwipeDirection),
|
Transition(SwipeDirection),
|
||||||
|
|
||||||
/// Yield a message to the caller of the flow (i.e. micropython), end event
|
/// Yield a message to the caller of the flow (i.e. micropython), end event
|
||||||
/// processing.
|
/// processing.
|
||||||
Return(FlowMsg),
|
Return(FlowMsg),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Q> Decision<Q> {
|
impl Decision {
|
||||||
pub fn or_else(self, func: impl FnOnce() -> Self) -> Self {
|
pub fn or_else(self, func: impl FnOnce() -> Self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Decision::Nothing => func(),
|
Decision::Nothing => func(),
|
||||||
@ -44,24 +43,71 @@ impl<Q> Decision<Q> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State transition type.
|
||||||
|
///
|
||||||
|
/// Contains a new state (by convention it must be of the same concrete type as
|
||||||
|
/// the current one) and a Decision object that tells the flow what to do next.
|
||||||
|
pub type StateChange = (&'static dyn FlowState, Decision);
|
||||||
|
|
||||||
/// Encodes the flow logic as a set of states, and transitions between them
|
/// Encodes the flow logic as a set of states, and transitions between them
|
||||||
/// triggered by events and swipes.
|
/// triggered by events and swipes.
|
||||||
pub trait FlowState
|
pub trait FlowState {
|
||||||
where
|
|
||||||
Self: Sized + Copy + Eq + ToPrimitive,
|
|
||||||
{
|
|
||||||
/// There needs to be a mapping from states to indices of the FlowStore
|
|
||||||
/// array. Default implementation works for states that are enums, the
|
|
||||||
/// FlowStore has to have number of elements equal to number of states.
|
|
||||||
fn index(&self) -> usize {
|
|
||||||
unwrap!(self.to_usize())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// What to do when user swipes on screen and current component doesn't
|
/// What to do when user swipes on screen and current component doesn't
|
||||||
/// respond to swipe of that direction.
|
/// respond to swipe of that direction.
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self>;
|
///
|
||||||
|
/// By convention, the type of the new state inside the state change must be
|
||||||
|
/// Self. This can't be enforced by the type system unfortunately, because
|
||||||
|
/// this trait must remain object-safe and so can't refer to Self.
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange;
|
||||||
|
|
||||||
/// What to do when the current component emits a message in response to an
|
/// What to do when the current component emits a message in response to an
|
||||||
/// event.
|
/// event.
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self>;
|
///
|
||||||
|
/// By convention, the type of the new state inside the state change must be
|
||||||
|
/// Self. This can't be enforced by the type system unfortunately, because
|
||||||
|
/// this trait must remain object-safe and so can't refer to Self.
|
||||||
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange;
|
||||||
|
|
||||||
|
/// Page index of the current state.
|
||||||
|
fn index(&'static self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper trait for writing nicer flow logic.
|
||||||
|
pub trait DecisionBuilder: FlowState + Sized {
|
||||||
|
#[inline]
|
||||||
|
fn swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
|
(self, Decision::Transition(direction))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn swipe_left(&'static self) -> StateChange {
|
||||||
|
self.swipe(SwipeDirection::Left)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn swipe_right(&'static self) -> StateChange {
|
||||||
|
self.swipe(SwipeDirection::Right)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn swipe_up(&'static self) -> StateChange {
|
||||||
|
self.swipe(SwipeDirection::Up)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn swipe_down(&'static self) -> StateChange {
|
||||||
|
self.swipe(SwipeDirection::Down)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn do_nothing(&'static self) -> StateChange {
|
||||||
|
(self, Decision::Nothing)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn return_msg(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
|
(self, Decision::Return(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FlowState> DecisionBuilder for T {}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
pub mod base;
|
pub mod base;
|
||||||
pub mod page;
|
pub mod page;
|
||||||
mod store;
|
|
||||||
mod swipe;
|
mod swipe;
|
||||||
|
|
||||||
pub use base::{FlowMsg, FlowState, Swipable};
|
pub use base::{FlowMsg, FlowState, Swipable};
|
||||||
pub use page::SwipePage;
|
pub use page::SwipePage;
|
||||||
pub use store::{flow_store, FlowStore};
|
|
||||||
pub use swipe::SwipeFlow;
|
pub use swipe::SwipeFlow;
|
||||||
|
@ -1,190 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
error,
|
|
||||||
maybe_trace::MaybeTrace,
|
|
||||||
ui::{
|
|
||||||
component::{Component, Event, EventCtx},
|
|
||||||
flow::base::FlowMsg,
|
|
||||||
geometry::Rect,
|
|
||||||
shape::Renderer,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::gc::Gc,
|
|
||||||
ui::{component::swipe_detect::SwipeConfig, flow::Swipable},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// `FlowStore` is essentially `Vec<Gc<dyn Component + SimpleSwipable>>` except
|
|
||||||
/// that `trait Component` is not object-safe so it ends up being a kind of
|
|
||||||
/// recursively-defined tuple.
|
|
||||||
/// Implementors are something like the V in MVC.
|
|
||||||
pub trait FlowStore {
|
|
||||||
/// Call `Component::place` on all elements.
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect;
|
|
||||||
|
|
||||||
/// Call `Component::event` on i-th element.
|
|
||||||
fn event(&mut self, i: usize, ctx: &mut EventCtx, event: Event) -> Option<FlowMsg>;
|
|
||||||
|
|
||||||
/// Call `Component::render` on i-th element.
|
|
||||||
fn render<'s>(&'s self, i: usize, target: &mut impl Renderer<'s>);
|
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
|
||||||
/// Call `Trace::trace` on i-th element.
|
|
||||||
fn trace(&self, i: usize, t: &mut dyn crate::trace::Tracer);
|
|
||||||
|
|
||||||
/// Forward `SimpleSwipable` methods to i-th element.
|
|
||||||
fn map_swipable<T>(&mut self, i: usize, func: impl FnOnce(&mut dyn Swipable) -> T) -> T;
|
|
||||||
|
|
||||||
fn get_swipe_config(&self, i: usize) -> SwipeConfig;
|
|
||||||
|
|
||||||
fn get_internal_page_count(&mut self, i: usize) -> usize;
|
|
||||||
|
|
||||||
/// Add a Component to the end of a `FlowStore`.
|
|
||||||
fn add<E: Component<Msg = FlowMsg> + MaybeTrace + Swipable>(
|
|
||||||
self,
|
|
||||||
elem: E,
|
|
||||||
) -> Result<impl FlowStore, error::Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create new empty flow store.
|
|
||||||
pub fn flow_store() -> impl FlowStore {
|
|
||||||
FlowEmpty {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Terminating element of a recursive structure.
|
|
||||||
struct FlowEmpty;
|
|
||||||
|
|
||||||
// Methods that take an index panic because it's always out of bounds.
|
|
||||||
impl FlowStore for FlowEmpty {
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
|
||||||
bounds
|
|
||||||
}
|
|
||||||
|
|
||||||
fn event(&mut self, _i: usize, _ctx: &mut EventCtx, _event: Event) -> Option<FlowMsg> {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render<'s>(&self, _i: usize, _target: &mut impl Renderer<'s>) {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
|
||||||
fn trace(&self, _i: usize, _t: &mut dyn crate::trace::Tracer) {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map_swipable<T>(&mut self, _i: usize, _func: impl FnOnce(&mut dyn Swipable) -> T) -> T {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add<E: Component<Msg = FlowMsg> + MaybeTrace + Swipable>(
|
|
||||||
self,
|
|
||||||
elem: E,
|
|
||||||
) -> Result<impl FlowStore, error::Error>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Ok(FlowComponent2 {
|
|
||||||
elem: Gc::new(elem)?,
|
|
||||||
next: Self,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fn get_swipe_config(&self, _i: usize) -> SwipeConfig {
|
|
||||||
SwipeConfig::new()
|
|
||||||
}
|
|
||||||
fn get_internal_page_count(&mut self, _i: usize) -> usize {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FlowComponent2<E: Component<Msg = FlowMsg>, P> {
|
|
||||||
/// Component allocated on micropython heap.
|
|
||||||
pub elem: Gc<E>,
|
|
||||||
|
|
||||||
/// Nested FlowStore.
|
|
||||||
pub next: P,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Component<Msg = FlowMsg>, P> FlowComponent2<E, P> {
|
|
||||||
fn as_ref(&self) -> &E {
|
|
||||||
&self.elem
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_mut(&mut self) -> &mut E {
|
|
||||||
// SAFETY: micropython can only access this object through LayoutObj which wraps
|
|
||||||
// us in a RefCell which guarantees uniqueness
|
|
||||||
unsafe { Gc::as_mut(&mut self.elem) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E, P> FlowStore for FlowComponent2<E, P>
|
|
||||||
where
|
|
||||||
E: Component<Msg = FlowMsg> + MaybeTrace + Swipable,
|
|
||||||
P: FlowStore,
|
|
||||||
{
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
|
||||||
self.as_mut().place(bounds);
|
|
||||||
self.next.place(bounds);
|
|
||||||
bounds
|
|
||||||
}
|
|
||||||
|
|
||||||
fn event(&mut self, i: usize, ctx: &mut EventCtx, event: Event) -> Option<FlowMsg> {
|
|
||||||
if i == 0 {
|
|
||||||
self.as_mut().event(ctx, event)
|
|
||||||
} else {
|
|
||||||
self.next.event(i - 1, ctx, event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render<'s>(&'s self, i: usize, target: &mut impl Renderer<'s>) {
|
|
||||||
if i == 0 {
|
|
||||||
self.as_ref().render(target)
|
|
||||||
} else {
|
|
||||||
self.next.render(i - 1, target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
|
||||||
fn trace(&self, i: usize, t: &mut dyn crate::trace::Tracer) {
|
|
||||||
if i == 0 {
|
|
||||||
self.as_ref().trace(t)
|
|
||||||
} else {
|
|
||||||
self.next.trace(i - 1, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map_swipable<T>(&mut self, i: usize, func: impl FnOnce(&mut dyn Swipable) -> T) -> T {
|
|
||||||
if i == 0 {
|
|
||||||
func(self.as_mut())
|
|
||||||
} else {
|
|
||||||
self.next.map_swipable(i - 1, func)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add<F: Component<Msg = FlowMsg> + MaybeTrace + Swipable>(
|
|
||||||
self,
|
|
||||||
elem: F,
|
|
||||||
) -> Result<impl FlowStore, error::Error>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Ok(FlowComponent2 {
|
|
||||||
elem: self.elem,
|
|
||||||
next: self.next.add(elem)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_swipe_config(&self, i: usize) -> SwipeConfig {
|
|
||||||
if i == 0 {
|
|
||||||
self.as_ref().get_swipe_config()
|
|
||||||
} else {
|
|
||||||
self.next.get_swipe_config(i - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_internal_page_count(&mut self, i: usize) -> usize {
|
|
||||||
self.map_swipable(i, |swipable| swipable.get_internal_page_count())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +1,103 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error::{self, Error},
|
||||||
|
maybe_trace::MaybeTrace,
|
||||||
|
micropython::{
|
||||||
|
gc::{self, GcBox},
|
||||||
|
obj::Obj,
|
||||||
|
},
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
base::AttachType, swipe_detect::SwipeSettings, Component, Event, EventCtx, SwipeDetect,
|
base::AttachType, swipe_detect::SwipeSettings, Component, Event, EventCtx, SwipeDetect,
|
||||||
SwipeDetectMsg, SwipeDirection,
|
SwipeDetectMsg, SwipeDirection,
|
||||||
},
|
},
|
||||||
|
display::Color,
|
||||||
event::{SwipeEvent, TouchEvent},
|
event::{SwipeEvent, TouchEvent},
|
||||||
flow::{base::Decision, FlowMsg, FlowState, FlowStore},
|
flow::{base::Decision, FlowMsg, FlowState},
|
||||||
geometry::Rect,
|
geometry::Rect,
|
||||||
shape::Renderer,
|
layout::obj::ObjComponent,
|
||||||
|
shape::{render_on_display, ConcreteRenderer, Renderer, ScopedRenderer},
|
||||||
util::animation_disabled,
|
util::animation_disabled,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Given a state enum and a corresponding FlowStore, create a Component that
|
use super::{base::StateChange, Swipable};
|
||||||
/// implements a swipe navigation between the states with animated transitions.
|
|
||||||
|
use heapless::Vec;
|
||||||
|
|
||||||
|
/// Component-like proto-object-safe trait.
|
||||||
|
///
|
||||||
|
/// This copies the Component interface, but it is parametrized by a concrete
|
||||||
|
/// Renderer type, making it object-safe.
|
||||||
|
pub trait FlowComponentTrait<'s, R: Renderer<'s>>: Swipable {
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect;
|
||||||
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<FlowMsg>;
|
||||||
|
fn render(&'s self, target: &mut R);
|
||||||
|
|
||||||
|
#[cfg(feature = "ui_debug")]
|
||||||
|
fn trace(&self, t: &mut dyn crate::trace::Tracer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FlowComponentTrait implementation for Components.
|
||||||
|
///
|
||||||
|
/// Components implementing FlowComponentTrait must:
|
||||||
|
/// * also implement Swipable, required by FlowComponentTrait,
|
||||||
|
/// * use FlowMsg as their Msg type,
|
||||||
|
/// * implement MaybeTrace to be able to conform to ObjComponent.
|
||||||
|
impl<'s, R, C> FlowComponentTrait<'s, R> for C
|
||||||
|
where
|
||||||
|
C: Component<Msg = FlowMsg> + MaybeTrace + Swipable,
|
||||||
|
R: Renderer<'s>,
|
||||||
|
{
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
|
<Self as Component>::place(self, bounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<FlowMsg> {
|
||||||
|
<Self as Component>::event(self, ctx, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&'s self, target: &mut R) {
|
||||||
|
<Self as Component>::render(self, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ui_debug")]
|
||||||
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
|
<Self as crate::trace::Trace>::trace(self, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shortcut type for the concrete renderer passed into `render()` method.
|
||||||
|
type RendererImpl<'a, 'alloc, 'env> = ScopedRenderer<'alloc, 'env, ConcreteRenderer<'a, 'alloc>>;
|
||||||
|
|
||||||
|
/// Fully object-safe component-like trait for flow components.
|
||||||
|
///
|
||||||
|
/// This trait has no generic parameters:
|
||||||
|
/// * it is instantiated with a concrete Renderer type, and
|
||||||
|
/// * it requires the `FlowComponentTrait` trait to be implemented for _any_
|
||||||
|
/// lifetimes.
|
||||||
|
pub trait FlowComponentDynTrait:
|
||||||
|
for<'a, 'alloc, 'env> FlowComponentTrait<'alloc, RendererImpl<'a, 'alloc, 'env>>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> FlowComponentDynTrait for T where
|
||||||
|
T: for<'a, 'alloc, 'env> FlowComponentTrait<'alloc, RendererImpl<'a, 'alloc, 'env>>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swipe flow consisting of multiple screens.
|
||||||
|
///
|
||||||
|
/// Implements swipe navigation between the states with animated transitions,
|
||||||
|
/// based on state transitions provided by the FlowState type.
|
||||||
///
|
///
|
||||||
/// If a swipe is detected:
|
/// If a swipe is detected:
|
||||||
/// - currently active component is asked to handle the event,
|
/// - currently active component is asked to handle the event,
|
||||||
/// - if it can't then FlowState::handle_swipe is consulted.
|
/// - if it can't then FlowState::handle_swipe is consulted.
|
||||||
pub struct SwipeFlow<Q, S> {
|
pub struct SwipeFlow {
|
||||||
/// Current state.
|
/// Current state of the flow.
|
||||||
state: Q,
|
state: &'static dyn FlowState,
|
||||||
/// FlowStore with all screens/components.
|
/// Store of all screens which are part of the flow.
|
||||||
store: S,
|
store: Vec<GcBox<dyn FlowComponentDynTrait>, 10>,
|
||||||
/// Swipe detector.
|
/// Swipe detector.
|
||||||
swipe: SwipeDetect,
|
swipe: SwipeDetect,
|
||||||
/// Swipe allowed
|
/// Swipe allowed
|
||||||
@ -34,33 +108,53 @@ pub struct SwipeFlow<Q, S> {
|
|||||||
internal_pages: u16,
|
internal_pages: u16,
|
||||||
/// If triggering swipe by event, make this decision instead of default
|
/// If triggering swipe by event, make this decision instead of default
|
||||||
/// after the swipe.
|
/// after the swipe.
|
||||||
decision_override: Option<Decision<Q>>,
|
decision_override: Option<StateChange>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Q: FlowState, S: FlowStore> SwipeFlow<Q, S> {
|
impl SwipeFlow {
|
||||||
pub fn new(init: Q, store: S) -> Result<Self, error::Error> {
|
pub fn new(initial_state: &'static dyn FlowState) -> Result<Self, error::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state: init,
|
state: initial_state,
|
||||||
swipe: SwipeDetect::new(),
|
swipe: SwipeDetect::new(),
|
||||||
store,
|
store: Vec::new(),
|
||||||
allow_swipe: true,
|
allow_swipe: true,
|
||||||
internal_state: 0,
|
internal_state: 0,
|
||||||
internal_pages: 1,
|
internal_pages: 1,
|
||||||
decision_override: None,
|
decision_override: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn goto(&mut self, ctx: &mut EventCtx, direction: SwipeDirection, state: Q) {
|
|
||||||
self.state = state;
|
/// Add a page to the flow.
|
||||||
|
///
|
||||||
|
/// Pages must be inserted in the order of the flow state index.
|
||||||
|
pub fn with_page(
|
||||||
|
mut self,
|
||||||
|
state: &'static dyn FlowState,
|
||||||
|
page: impl FlowComponentDynTrait + 'static,
|
||||||
|
) -> Result<Self, error::Error> {
|
||||||
|
debug_assert!(self.store.len() == state.index());
|
||||||
|
let alloc = GcBox::new(page)?;
|
||||||
|
let page = gc::coerce!(FlowComponentDynTrait, alloc);
|
||||||
|
unwrap!(self.store.push(page));
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_page(&self) -> &GcBox<dyn FlowComponentDynTrait> {
|
||||||
|
&self.store[self.state.index()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_page_mut(&mut self) -> &mut GcBox<dyn FlowComponentDynTrait> {
|
||||||
|
&mut self.store[self.state.index()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn goto(&mut self, ctx: &mut EventCtx, direction: SwipeDirection) {
|
||||||
self.swipe = SwipeDetect::new();
|
self.swipe = SwipeDetect::new();
|
||||||
self.allow_swipe = true;
|
self.allow_swipe = true;
|
||||||
|
|
||||||
self.store.event(
|
self.current_page_mut()
|
||||||
state.index(),
|
.event(ctx, Event::Attach(AttachType::Swipe(direction)));
|
||||||
ctx,
|
|
||||||
Event::Attach(AttachType::Swipe(direction)),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.internal_pages = self.store.get_internal_page_count(state.index()) as u16;
|
self.internal_pages = self.current_page_mut().get_internal_page_count() as u16;
|
||||||
|
|
||||||
match direction {
|
match direction {
|
||||||
SwipeDirection::Up => {
|
SwipeDirection::Up => {
|
||||||
@ -75,46 +169,43 @@ impl<Q: FlowState, S: FlowStore> SwipeFlow<Q, S> {
|
|||||||
ctx.request_paint();
|
ctx.request_paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_state<'s>(&'s self, state: Q, target: &mut impl Renderer<'s>) {
|
fn render_state<'s>(&'s self, state: usize, target: &mut RendererImpl<'_, 's, '_>) {
|
||||||
self.store.render(state.index(), target)
|
self.store[state].render(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_swipe_child(
|
fn handle_swipe_child(
|
||||||
&mut self,
|
&mut self,
|
||||||
_ctx: &mut EventCtx,
|
_ctx: &mut EventCtx,
|
||||||
direction: SwipeDirection,
|
direction: SwipeDirection,
|
||||||
) -> Decision<Q> {
|
) -> StateChange {
|
||||||
self.state.handle_swipe(direction)
|
self.state.handle_swipe(direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event_child(&mut self, ctx: &mut EventCtx, event: Event) -> Decision<Q> {
|
fn handle_event_child(&mut self, ctx: &mut EventCtx, event: Event) -> StateChange {
|
||||||
let msg = self.store.event(self.state.index(), ctx, event);
|
let msg = self.current_page_mut().event(ctx, event);
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
if let Some(msg) = msg {
|
||||||
self.state.handle_event(msg)
|
self.state.handle_event(msg)
|
||||||
} else {
|
} else {
|
||||||
Decision::Nothing
|
(self.state, Decision::Nothing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
fn state_unchanged(&self) -> StateChange {
|
||||||
type Msg = FlowMsg;
|
(self.state, Decision::Nothing)
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
|
||||||
self.store.place(bounds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<FlowMsg> {
|
||||||
let mut decision: Decision<Q> = Decision::Nothing;
|
let mut state_change = self.state_unchanged();
|
||||||
let mut return_transition: AttachType = AttachType::Initial;
|
let mut return_transition: AttachType = AttachType::Initial;
|
||||||
|
|
||||||
let mut attach = false;
|
let mut attach = false;
|
||||||
|
|
||||||
let e = if self.allow_swipe {
|
let e = if self.allow_swipe {
|
||||||
let mut config = self.store.get_swipe_config(self.state.index());
|
let page = self.current_page();
|
||||||
|
let mut config = page.get_swipe_config();
|
||||||
|
|
||||||
self.internal_pages = self.store.get_internal_page_count(self.state.index()) as u16;
|
self.internal_pages = page.get_internal_page_count() as u16;
|
||||||
|
|
||||||
// add additional swipe directions if there are more internal pages
|
// add additional swipe directions if there are more internal pages
|
||||||
// todo can we get internal settings from config somehow?
|
// todo can we get internal settings from config somehow?
|
||||||
@ -135,9 +226,9 @@ impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
|||||||
match self.swipe.event(ctx, event, config) {
|
match self.swipe.event(ctx, event, config) {
|
||||||
Some(SwipeDetectMsg::Trigger(dir)) => {
|
Some(SwipeDetectMsg::Trigger(dir)) => {
|
||||||
if let Some(override_decision) = self.decision_override.take() {
|
if let Some(override_decision) = self.decision_override.take() {
|
||||||
decision = override_decision;
|
state_change = override_decision;
|
||||||
} else {
|
} else {
|
||||||
decision = self.handle_swipe_child(ctx, dir);
|
state_change = self.handle_swipe_child(ctx, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_transition = AttachType::Swipe(dir);
|
return_transition = AttachType::Swipe(dir);
|
||||||
@ -148,11 +239,11 @@ impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
|||||||
let current_state = self.internal_state;
|
let current_state = self.internal_state;
|
||||||
if dir == SwipeDirection::Left && current_state < states_num - 1 {
|
if dir == SwipeDirection::Left && current_state < states_num - 1 {
|
||||||
self.internal_state += 1;
|
self.internal_state += 1;
|
||||||
decision = Decision::Nothing;
|
state_change = self.state_unchanged();
|
||||||
attach = true;
|
attach = true;
|
||||||
} else if dir == SwipeDirection::Right && current_state > 0 {
|
} else if dir == SwipeDirection::Right && current_state > 0 {
|
||||||
self.internal_state -= 1;
|
self.internal_state -= 1;
|
||||||
decision = Decision::Nothing;
|
state_change = self.state_unchanged();
|
||||||
attach = true;
|
attach = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,77 +251,75 @@ impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
|||||||
let current_state = self.internal_state;
|
let current_state = self.internal_state;
|
||||||
if dir == SwipeDirection::Up && current_state < states_num - 1 {
|
if dir == SwipeDirection::Up && current_state < states_num - 1 {
|
||||||
self.internal_state += 1;
|
self.internal_state += 1;
|
||||||
decision = Decision::Nothing;
|
state_change = self.state_unchanged();
|
||||||
attach = true;
|
attach = true;
|
||||||
} else if dir == SwipeDirection::Down && current_state > 0 {
|
} else if dir == SwipeDirection::Down && current_state > 0 {
|
||||||
self.internal_state -= 1;
|
self.internal_state -= 1;
|
||||||
decision = Decision::Nothing;
|
state_change = self.state_unchanged();
|
||||||
attach = true;
|
attach = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Event::Swipe(SwipeEvent::End(dir)))
|
Event::Swipe(SwipeEvent::End(dir))
|
||||||
}
|
}
|
||||||
Some(SwipeDetectMsg::Move(dir, progress)) => {
|
Some(SwipeDetectMsg::Move(dir, progress)) => {
|
||||||
Some(Event::Swipe(SwipeEvent::Move(dir, progress as i16)))
|
Event::Swipe(SwipeEvent::Move(dir, progress as i16))
|
||||||
}
|
}
|
||||||
Some(SwipeDetectMsg::Start(_)) => Some(Event::Touch(TouchEvent::TouchAbort)),
|
Some(SwipeDetectMsg::Start(_)) => Event::Touch(TouchEvent::TouchAbort),
|
||||||
_ => Some(event),
|
_ => event,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(event)
|
event
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(e) = e {
|
match state_change {
|
||||||
match decision {
|
(_, Decision::Nothing) => {
|
||||||
Decision::Nothing => {
|
state_change = self.handle_event_child(ctx, e);
|
||||||
decision = self.handle_event_child(ctx, e);
|
|
||||||
|
|
||||||
// when doing internal transition, pass attach event to the child after sending
|
// when doing internal transition, pass attach event to the child after sending
|
||||||
// swipe end.
|
// swipe end.
|
||||||
if attach {
|
if attach {
|
||||||
if let Event::Swipe(SwipeEvent::End(dir)) = e {
|
if let Event::Swipe(SwipeEvent::End(dir)) = e {
|
||||||
self.store.event(
|
self.current_page_mut()
|
||||||
self.state.index(),
|
.event(ctx, Event::Attach(AttachType::Swipe(dir)));
|
||||||
ctx,
|
}
|
||||||
Event::Attach(AttachType::Swipe(dir)),
|
}
|
||||||
);
|
|
||||||
|
if ctx.disable_swipe_requested() {
|
||||||
|
self.swipe.reset();
|
||||||
|
self.allow_swipe = false;
|
||||||
|
}
|
||||||
|
if ctx.enable_swipe_requested() {
|
||||||
|
self.swipe.reset();
|
||||||
|
self.allow_swipe = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = self.current_page().get_swipe_config();
|
||||||
|
|
||||||
|
if let (_, Decision::Transition(direction)) = state_change {
|
||||||
|
if config.is_allowed(direction) {
|
||||||
|
if !animation_disabled() {
|
||||||
|
self.swipe.trigger(ctx, direction, config);
|
||||||
|
self.decision_override = Some(state_change);
|
||||||
|
state_change = self.state_unchanged();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.disable_swipe_requested() {
|
|
||||||
self.swipe.reset();
|
|
||||||
self.allow_swipe = false;
|
|
||||||
}
|
|
||||||
if ctx.enable_swipe_requested() {
|
|
||||||
self.swipe.reset();
|
|
||||||
self.allow_swipe = true;
|
self.allow_swipe = true;
|
||||||
};
|
|
||||||
|
|
||||||
let config = self.store.get_swipe_config(self.state.index());
|
|
||||||
|
|
||||||
if let Decision::Goto(_, direction) = decision {
|
|
||||||
if config.is_allowed(direction) {
|
|
||||||
if !animation_disabled() {
|
|
||||||
self.swipe.trigger(ctx, direction, config);
|
|
||||||
self.decision_override = Some(decision);
|
|
||||||
decision = Decision::Nothing;
|
|
||||||
}
|
|
||||||
self.allow_swipe = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
}
|
||||||
//ignore message, we are already transitioning
|
_ => {
|
||||||
self.store.event(self.state.index(), ctx, event);
|
//ignore message, we are already transitioning
|
||||||
}
|
self.current_page_mut().event(ctx, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (new_state, decision) = state_change;
|
||||||
|
self.state = new_state;
|
||||||
match decision {
|
match decision {
|
||||||
Decision::Goto(next_state, direction) => {
|
Decision::Transition(direction) => {
|
||||||
self.goto(ctx, direction, next_state);
|
self.state = new_state;
|
||||||
|
self.goto(ctx, direction);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Decision::Return(msg) => {
|
Decision::Return(msg) => {
|
||||||
@ -242,34 +331,49 @@ impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&mut self) {}
|
|
||||||
|
|
||||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
|
||||||
self.render_state(self.state, target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
|
||||||
impl<Q: FlowState, S: FlowStore> crate::trace::Trace for SwipeFlow<Q, S> {
|
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
|
||||||
self.store.trace(self.state.index(), t)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ObjComponent implementation for SwipeFlow.
|
||||||
|
///
|
||||||
|
/// Instead of using the generic `impl ObjComponent for ComponentMsgObj`, we
|
||||||
|
/// provide our own short-circuit implementation for `SwipeFlow`. This way we
|
||||||
|
/// can completely avoid implementing `Component`. That also allows us to pass
|
||||||
|
/// around concrete Renderers instead of having to conform to `Component`'s
|
||||||
|
/// not-object-safe interface.
|
||||||
|
///
|
||||||
|
/// This implementation relies on the fact that swipe components always return
|
||||||
|
/// `FlowMsg` as their `Component::Msg` (provided by `impl FlowComponentTrait`
|
||||||
|
/// earlier in this file).
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "micropython")]
|
||||||
impl<Q: FlowState, S: FlowStore> crate::ui::layout::obj::ComponentMsgObj for SwipeFlow<Q, S> {
|
impl ObjComponent for SwipeFlow {
|
||||||
fn msg_try_into_obj(
|
fn obj_place(&mut self, bounds: Rect) -> Rect {
|
||||||
&self,
|
for elem in self.store.iter_mut() {
|
||||||
msg: Self::Msg,
|
elem.place(bounds);
|
||||||
) -> Result<crate::micropython::obj::Obj, error::Error> {
|
}
|
||||||
match msg {
|
bounds
|
||||||
FlowMsg::Confirmed => Ok(crate::ui::layout::result::CONFIRMED.as_obj()),
|
}
|
||||||
FlowMsg::Cancelled => Ok(crate::ui::layout::result::CANCELLED.as_obj()),
|
|
||||||
FlowMsg::Info => Ok(crate::ui::layout::result::INFO.as_obj()),
|
fn obj_event(&mut self, ctx: &mut EventCtx, event: Event) -> Result<Obj, Error> {
|
||||||
FlowMsg::Choice(i) => {
|
match self.event(ctx, event) {
|
||||||
|
None => Ok(Obj::const_none()),
|
||||||
|
Some(FlowMsg::Confirmed) => Ok(crate::ui::layout::result::CONFIRMED.as_obj()),
|
||||||
|
Some(FlowMsg::Cancelled) => Ok(crate::ui::layout::result::CANCELLED.as_obj()),
|
||||||
|
Some(FlowMsg::Info) => Ok(crate::ui::layout::result::INFO.as_obj()),
|
||||||
|
Some(FlowMsg::Choice(i)) => {
|
||||||
Ok((crate::ui::layout::result::CONFIRMED.as_obj(), i.try_into()?).try_into()?)
|
Ok((crate::ui::layout::result::CONFIRMED.as_obj(), i.try_into()?).try_into()?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn obj_paint(&mut self) {
|
||||||
|
render_on_display(None, Some(Color::black()), |target| {
|
||||||
|
self.render_state(self.state.index(), target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ui_debug")]
|
||||||
|
impl crate::trace::Trace for SwipeFlow {
|
||||||
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
|
self.current_page().trace(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,8 +319,7 @@ impl LayoutObjInner {
|
|||||||
|
|
||||||
impl LayoutObj {
|
impl LayoutObj {
|
||||||
/// Create a new `LayoutObj`, wrapping a root component.
|
/// Create a new `LayoutObj`, wrapping a root component.
|
||||||
#[inline(never)]
|
pub fn new(root: impl ObjComponent + 'static) -> Result<Gc<Self>, Error> {
|
||||||
pub fn new(root: impl ComponentMsgObj + MaybeTrace + 'static) -> Result<Gc<Self>, Error> {
|
|
||||||
// SAFETY: This is a Python object and hase a base as first element
|
// SAFETY: This is a Python object and hase a base as first element
|
||||||
unsafe {
|
unsafe {
|
||||||
Gc::new_with_custom_finaliser(Self {
|
Gc::new_with_custom_finaliser(Self {
|
||||||
|
@ -1,123 +1,101 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
maybe_trace::MaybeTrace,
|
maybe_trace::MaybeTrace,
|
||||||
|
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{text::paragraphs::Paragraph, ComponentExt, SwipeDirection},
|
component::{
|
||||||
flow::{base::Decision, FlowMsg, FlowState, FlowStore},
|
swipe_detect::SwipeSettings,
|
||||||
|
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, VecExt},
|
||||||
|
Component, ComponentExt, Paginate, SwipeDirection,
|
||||||
|
},
|
||||||
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow, SwipePage,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::super::{
|
use super::super::{
|
||||||
component::{Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg},
|
component::{Frame, FrameMsg, PromptScreen, SwipeContent, VerticalMenu, VerticalMenuChoiceMsg},
|
||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: merge with code from https://github.com/trezor/trezor-firmware/pull/3805
|
// TODO: merge with code from https://github.com/trezor/trezor-firmware/pull/3805
|
||||||
// when ready
|
// when ready
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ConfirmAction {
|
pub enum ConfirmAction {
|
||||||
Intro,
|
Intro,
|
||||||
Menu,
|
Menu,
|
||||||
Confirm,
|
Confirm,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FlowState for ConfirmAction {
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
|
match (self, direction) {
|
||||||
|
(Self::Intro, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
|
(Self::Menu, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
|
(Self::Intro, SwipeDirection::Up) => Self::Confirm.swipe(direction),
|
||||||
|
(Self::Confirm, SwipeDirection::Down) => Self::Intro.swipe(direction),
|
||||||
|
(Self::Confirm, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
|
_ => self.do_nothing(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
|
match (self, msg) {
|
||||||
|
(Self::Intro, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
|
(Self::Menu, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
|
||||||
|
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled),
|
||||||
|
(Self::Menu, FlowMsg::Choice(1)) => self.return_msg(FlowMsg::Info),
|
||||||
|
(Self::Confirm, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
|
||||||
|
(Self::Confirm, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
|
_ => self.do_nothing(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ConfirmAction flow without a separate "Tap to confirm" or "Hold to confirm"
|
/// ConfirmAction flow without a separate "Tap to confirm" or "Hold to confirm"
|
||||||
/// screen. Swiping up directly from the intro screen confirms action.
|
/// screen. Swiping up directly from the intro screen confirms action.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ConfirmActionSimple {
|
pub enum ConfirmActionSimple {
|
||||||
Intro,
|
Intro,
|
||||||
Menu,
|
Menu,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for ConfirmAction {
|
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
|
||||||
match (self, direction) {
|
|
||||||
(ConfirmAction::Intro, SwipeDirection::Left) => {
|
|
||||||
Decision::Goto(ConfirmAction::Menu, direction)
|
|
||||||
}
|
|
||||||
(ConfirmAction::Menu, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(ConfirmAction::Intro, direction)
|
|
||||||
}
|
|
||||||
(ConfirmAction::Intro, SwipeDirection::Up) => {
|
|
||||||
Decision::Goto(ConfirmAction::Confirm, direction)
|
|
||||||
}
|
|
||||||
(ConfirmAction::Confirm, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(ConfirmAction::Intro, direction)
|
|
||||||
}
|
|
||||||
(ConfirmAction::Confirm, SwipeDirection::Left) => {
|
|
||||||
Decision::Goto(ConfirmAction::Menu, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
|
||||||
match (self, msg) {
|
|
||||||
(ConfirmAction::Intro, FlowMsg::Info) => {
|
|
||||||
Decision::Goto(ConfirmAction::Menu, SwipeDirection::Left)
|
|
||||||
}
|
|
||||||
(ConfirmAction::Menu, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(ConfirmAction::Intro, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(ConfirmAction::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
(ConfirmAction::Menu, FlowMsg::Choice(1)) => Decision::Return(FlowMsg::Info),
|
|
||||||
(ConfirmAction::Confirm, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Confirmed),
|
|
||||||
(ConfirmAction::Confirm, FlowMsg::Info) => {
|
|
||||||
Decision::Goto(ConfirmAction::Menu, SwipeDirection::Left)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FlowState for ConfirmActionSimple {
|
impl FlowState for ConfirmActionSimple {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(ConfirmActionSimple::Intro, SwipeDirection::Left) => {
|
(Self::Intro, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(ConfirmActionSimple::Menu, direction)
|
(Self::Menu, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
}
|
(Self::Intro, SwipeDirection::Up) => self.return_msg(FlowMsg::Confirmed),
|
||||||
(ConfirmActionSimple::Menu, SwipeDirection::Right) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ConfirmActionSimple::Intro, direction)
|
|
||||||
}
|
|
||||||
(ConfirmActionSimple::Intro, SwipeDirection::Up) => {
|
|
||||||
Decision::Return(FlowMsg::Confirmed)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(ConfirmActionSimple::Intro, FlowMsg::Info) => {
|
(Self::Intro, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(ConfirmActionSimple::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
|
||||||
}
|
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled),
|
||||||
(ConfirmActionSimple::Menu, FlowMsg::Cancelled) => {
|
(Self::Menu, FlowMsg::Choice(1)) => self.return_msg(FlowMsg::Info),
|
||||||
Decision::Goto(ConfirmActionSimple::Intro, SwipeDirection::Right)
|
_ => self.do_nothing(),
|
||||||
}
|
|
||||||
(ConfirmActionSimple::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
(ConfirmActionSimple::Menu, FlowMsg::Choice(1)) => Decision::Return(FlowMsg::Info),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
ui::{
|
|
||||||
component::{
|
|
||||||
swipe_detect::SwipeSettings,
|
|
||||||
text::paragraphs::{ParagraphSource, ParagraphVecShort, VecExt},
|
|
||||||
Component, Paginate,
|
|
||||||
},
|
|
||||||
flow::{flow_store, SwipeFlow, SwipePage},
|
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_action_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_action_obj) }
|
||||||
@ -248,15 +226,15 @@ pub fn new_confirm_action_uni<T: Component + MaybeTrace + 'static>(
|
|||||||
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
||||||
});
|
});
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&ConfirmAction::Intro)?
|
||||||
.add(content_intro)?
|
.with_page(&ConfirmAction::Intro, content_intro)?
|
||||||
.add(content_menu)?
|
.with_page(&ConfirmAction::Menu, content_menu)?
|
||||||
.add(content_confirm)?;
|
.with_page(&ConfirmAction::Confirm, content_confirm)?;
|
||||||
let res = SwipeFlow::new(ConfirmAction::Intro, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
} else {
|
} else {
|
||||||
let store = flow_store().add(content_intro)?.add(content_menu)?;
|
let res = SwipeFlow::new(&ConfirmActionSimple::Intro)?
|
||||||
let res = SwipeFlow::new(ConfirmActionSimple::Intro, store)?;
|
.with_page(&ConfirmActionSimple::Intro, content_intro)?
|
||||||
|
.with_page(&ConfirmActionSimple::Menu, content_menu)?;
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,31 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::qstr::Qstr,
|
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
button_request::ButtonRequest,
|
button_request::ButtonRequest,
|
||||||
component::{ButtonRequestExt, ComponentExt, SwipeDirection},
|
component::{swipe_detect::SwipeSettings, ButtonRequestExt, ComponentExt, SwipeDirection},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::super::{
|
use super::{
|
||||||
component::{
|
super::{
|
||||||
AddressDetails, Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg,
|
component::{
|
||||||
|
AddressDetails, Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg,
|
||||||
|
},
|
||||||
|
theme,
|
||||||
},
|
},
|
||||||
theme,
|
util::ConfirmBlobParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::util::ConfirmBlobParams;
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
|
||||||
pub enum ConfirmOutput {
|
pub enum ConfirmOutput {
|
||||||
Address,
|
Address,
|
||||||
Amount,
|
Amount,
|
||||||
@ -30,58 +36,39 @@ pub enum ConfirmOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for ConfirmOutput {
|
impl FlowState for ConfirmOutput {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(ConfirmOutput::Address | ConfirmOutput::Amount, SwipeDirection::Left) => {
|
(Self::Address | Self::Amount, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(ConfirmOutput::Menu, direction)
|
(Self::Address, SwipeDirection::Up) => Self::Amount.swipe(direction),
|
||||||
|
(Self::Amount, SwipeDirection::Up) => self.return_msg(FlowMsg::Confirmed),
|
||||||
|
(Self::Amount, SwipeDirection::Down) => Self::Address.swipe(direction),
|
||||||
|
(Self::Menu, SwipeDirection::Right) => Self::Address.swipe(direction),
|
||||||
|
(Self::Menu, SwipeDirection::Left) => Self::AccountInfo.swipe(direction),
|
||||||
|
(Self::AccountInfo | Self::CancelTap, SwipeDirection::Right) => {
|
||||||
|
Self::Menu.swipe(direction)
|
||||||
}
|
}
|
||||||
(ConfirmOutput::Address, SwipeDirection::Up) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ConfirmOutput::Amount, direction)
|
|
||||||
}
|
|
||||||
(ConfirmOutput::Amount, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed),
|
|
||||||
(ConfirmOutput::Amount, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(ConfirmOutput::Address, direction)
|
|
||||||
}
|
|
||||||
(ConfirmOutput::Menu, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(ConfirmOutput::Address, direction)
|
|
||||||
}
|
|
||||||
(ConfirmOutput::Menu, SwipeDirection::Left) => {
|
|
||||||
Decision::Goto(ConfirmOutput::AccountInfo, direction)
|
|
||||||
}
|
|
||||||
(ConfirmOutput::AccountInfo | ConfirmOutput::CancelTap, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(ConfirmOutput::Menu, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(_, FlowMsg::Info) => Decision::Goto(ConfirmOutput::Menu, SwipeDirection::Left),
|
(_, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
(ConfirmOutput::Menu, FlowMsg::Choice(0)) => {
|
(Self::Menu, FlowMsg::Choice(0)) => Self::AccountInfo.swipe_left(),
|
||||||
Decision::Goto(ConfirmOutput::AccountInfo, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Choice(1)) => Self::CancelTap.swipe_left(),
|
||||||
}
|
(Self::Menu, FlowMsg::Cancelled) => Self::Address.swipe_right(),
|
||||||
(ConfirmOutput::Menu, FlowMsg::Choice(1)) => {
|
(Self::CancelTap, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Cancelled),
|
||||||
Decision::Goto(ConfirmOutput::CancelTap, SwipeDirection::Left)
|
(_, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
}
|
_ => self.do_nothing(),
|
||||||
(ConfirmOutput::Menu, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(ConfirmOutput::Address, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(ConfirmOutput::CancelTap, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
(_, FlowMsg::Cancelled) => Decision::Goto(ConfirmOutput::Menu, SwipeDirection::Right),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings, layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmOutput::new_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmOutput::new_obj) }
|
||||||
@ -156,13 +143,12 @@ impl ConfirmOutput {
|
|||||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||||
});
|
});
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&ConfirmOutput::Address)?
|
||||||
.add(content_address)?
|
.with_page(&ConfirmOutput::Address, content_address)?
|
||||||
.add(content_amount)?
|
.with_page(&ConfirmOutput::Amount, content_amount)?
|
||||||
.add(content_menu)?
|
.with_page(&ConfirmOutput::Menu, content_menu)?
|
||||||
.add(content_account)?
|
.with_page(&ConfirmOutput::AccountInfo, content_account)?
|
||||||
.add(content_cancel_tap)?;
|
.with_page(&ConfirmOutput::CancelTap, content_cancel_tap)?;
|
||||||
let res = SwipeFlow::new(ConfirmOutput::Address, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,10 @@ use crate::{
|
|||||||
text::paragraphs::{Paragraph, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
ButtonRequestExt, ComponentExt, SwipeDirection,
|
ButtonRequestExt, ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
layout::obj::LayoutObj,
|
layout::obj::LayoutObj,
|
||||||
model_mercury::component::{PromptScreen, SwipeContent},
|
model_mercury::component::{PromptScreen, SwipeContent},
|
||||||
},
|
},
|
||||||
@ -21,7 +24,7 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ConfirmResetCreate {
|
pub enum ConfirmResetCreate {
|
||||||
Intro,
|
Intro,
|
||||||
Menu,
|
Menu,
|
||||||
@ -29,43 +32,30 @@ pub enum ConfirmResetCreate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for ConfirmResetCreate {
|
impl FlowState for ConfirmResetCreate {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(ConfirmResetCreate::Intro, SwipeDirection::Left) => {
|
(Self::Intro, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(ConfirmResetCreate::Menu, direction)
|
(Self::Intro, SwipeDirection::Up) => Self::Confirm.swipe(direction),
|
||||||
}
|
(Self::Menu, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
(ConfirmResetCreate::Intro, SwipeDirection::Up) => {
|
(Self::Confirm, SwipeDirection::Down) => Self::Intro.swipe(direction),
|
||||||
Decision::Goto(ConfirmResetCreate::Confirm, direction)
|
(Self::Confirm, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
}
|
_ => self.do_nothing(),
|
||||||
(ConfirmResetCreate::Menu, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(ConfirmResetCreate::Intro, direction)
|
|
||||||
}
|
|
||||||
(ConfirmResetCreate::Confirm, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(ConfirmResetCreate::Intro, direction)
|
|
||||||
}
|
|
||||||
(ConfirmResetCreate::Confirm, SwipeDirection::Left) => {
|
|
||||||
Decision::Goto(ConfirmResetCreate::Menu, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(ConfirmResetCreate::Intro, FlowMsg::Info) => {
|
(Self::Intro, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(ConfirmResetCreate::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
|
||||||
}
|
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled),
|
||||||
(ConfirmResetCreate::Menu, FlowMsg::Cancelled) => {
|
(Self::Confirm, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
|
||||||
Decision::Goto(ConfirmResetCreate::Intro, SwipeDirection::Right)
|
(Self::Confirm, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
}
|
_ => self.do_nothing(),
|
||||||
(ConfirmResetCreate::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
(ConfirmResetCreate::Confirm, FlowMsg::Confirmed) => {
|
|
||||||
Decision::Return(FlowMsg::Confirmed)
|
|
||||||
}
|
|
||||||
(ConfirmResetCreate::Confirm, FlowMsg::Info) => {
|
|
||||||
Decision::Goto(ConfirmResetCreate::Menu, SwipeDirection::Left)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,12 +114,10 @@ impl ConfirmResetCreate {
|
|||||||
})
|
})
|
||||||
.one_button_request(ButtonRequestCode::ResetDevice.with_type("confirm_setup_device"));
|
.one_button_request(ButtonRequestCode::ResetDevice.with_type("confirm_setup_device"));
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&ConfirmResetCreate::Intro)?
|
||||||
.add(content_intro)?
|
.with_page(&ConfirmResetCreate::Intro, content_intro)?
|
||||||
.add(content_menu)?
|
.with_page(&ConfirmResetCreate::Menu, content_menu)?
|
||||||
.add(content_confirm)?;
|
.with_page(&ConfirmResetCreate::Confirm, content_confirm)?;
|
||||||
|
|
||||||
let res = SwipeFlow::new(ConfirmResetCreate::Intro, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
|
micropython::{map::Map, obj::Obj, util},
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
button_request::ButtonRequestCode,
|
button_request::ButtonRequestCode,
|
||||||
component::{
|
component::{
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
ButtonRequestExt, ComponentExt, SwipeDirection,
|
ButtonRequestExt, ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,51 +23,37 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ConfirmResetRecover {
|
pub enum ConfirmResetRecover {
|
||||||
Intro,
|
Intro,
|
||||||
Menu,
|
Menu,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for ConfirmResetRecover {
|
impl FlowState for ConfirmResetRecover {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(ConfirmResetRecover::Intro, SwipeDirection::Left) => {
|
(Self::Intro, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(ConfirmResetRecover::Menu, direction)
|
(Self::Menu, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
}
|
(Self::Intro, SwipeDirection::Up) => self.return_msg(FlowMsg::Confirmed),
|
||||||
(ConfirmResetRecover::Menu, SwipeDirection::Right) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ConfirmResetRecover::Intro, direction)
|
|
||||||
}
|
|
||||||
(ConfirmResetRecover::Intro, SwipeDirection::Up) => {
|
|
||||||
Decision::Return(FlowMsg::Confirmed)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(ConfirmResetRecover::Intro, FlowMsg::Info) => {
|
(Self::Intro, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(ConfirmResetRecover::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
|
||||||
}
|
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled),
|
||||||
(ConfirmResetRecover::Menu, FlowMsg::Cancelled) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ConfirmResetRecover::Intro, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(ConfirmResetRecover::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings,
|
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::{PromptScreen, SwipeContent},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_confirm_reset_recover(
|
pub extern "C" fn new_confirm_reset_recover(
|
||||||
n_args: usize,
|
n_args: usize,
|
||||||
@ -104,23 +97,9 @@ impl ConfirmResetRecover {
|
|||||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||||
});
|
});
|
||||||
|
|
||||||
let content_confirm = Frame::left_aligned(
|
let res = SwipeFlow::new(&ConfirmResetRecover::Intro)?
|
||||||
TR::reset__title_create_wallet.into(),
|
.with_page(&ConfirmResetRecover::Intro, content_intro)?
|
||||||
SwipeContent::new(PromptScreen::new_hold_to_confirm()),
|
.with_page(&ConfirmResetRecover::Menu, content_menu)?;
|
||||||
)
|
|
||||||
.with_footer(TR::instructions__hold_to_confirm.into(), None)
|
|
||||||
.with_swipe(SwipeDirection::Down, SwipeSettings::default())
|
|
||||||
.map(|msg| match msg {
|
|
||||||
FrameMsg::Content(()) => Some(FlowMsg::Confirmed),
|
|
||||||
_ => Some(FlowMsg::Cancelled),
|
|
||||||
});
|
|
||||||
|
|
||||||
let store = flow_store()
|
|
||||||
.add(content_intro)?
|
|
||||||
.add(content_menu)?
|
|
||||||
.add(content_confirm)?;
|
|
||||||
|
|
||||||
let res = SwipeFlow::new(ConfirmResetRecover::Intro, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::qstr::Qstr,
|
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
ComponentExt, SwipeDirection,
|
ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, FlowMsg, FlowState, FlowStore},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -19,7 +25,7 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum SetNewPin {
|
pub enum SetNewPin {
|
||||||
Intro,
|
Intro,
|
||||||
Menu,
|
Menu,
|
||||||
@ -28,63 +34,37 @@ pub enum SetNewPin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for SetNewPin {
|
impl FlowState for SetNewPin {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
match (self, direction) {
|
fn index(&'static self) -> usize {
|
||||||
(SetNewPin::Intro, SwipeDirection::Left) => Decision::Goto(SetNewPin::Menu, direction),
|
*self as usize
|
||||||
(SetNewPin::Intro, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed),
|
}
|
||||||
|
|
||||||
(SetNewPin::Menu, SwipeDirection::Right) => Decision::Goto(SetNewPin::Intro, direction),
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
(SetNewPin::CancelPinIntro, SwipeDirection::Up) => {
|
match (self, direction) {
|
||||||
Decision::Goto(SetNewPin::CancelPinConfirm, direction)
|
(Self::Intro, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
}
|
(Self::Intro, SwipeDirection::Up) => self.return_msg(FlowMsg::Confirmed),
|
||||||
(SetNewPin::CancelPinIntro, SwipeDirection::Right) => {
|
(Self::Menu, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
Decision::Goto(SetNewPin::Intro, direction)
|
(Self::CancelPinIntro, SwipeDirection::Up) => Self::CancelPinConfirm.swipe(direction),
|
||||||
}
|
(Self::CancelPinIntro, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
(SetNewPin::CancelPinConfirm, SwipeDirection::Down) => {
|
(Self::CancelPinConfirm, SwipeDirection::Down) => Self::CancelPinIntro.swipe(direction),
|
||||||
Decision::Goto(SetNewPin::CancelPinIntro, direction)
|
(Self::CancelPinConfirm, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
}
|
_ => self.do_nothing(),
|
||||||
(SetNewPin::CancelPinConfirm, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(SetNewPin::Intro, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(SetNewPin::Intro, FlowMsg::Info) => {
|
(Self::Intro, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(SetNewPin::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Choice(0)) => Self::CancelPinIntro.swipe_left(),
|
||||||
}
|
(Self::Menu, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
|
||||||
(SetNewPin::Menu, FlowMsg::Choice(0)) => {
|
(Self::CancelPinIntro, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
|
||||||
Decision::Goto(SetNewPin::CancelPinIntro, SwipeDirection::Left)
|
(Self::CancelPinConfirm, FlowMsg::Cancelled) => Self::CancelPinIntro.swipe_right(),
|
||||||
}
|
(Self::CancelPinConfirm, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Cancelled),
|
||||||
(SetNewPin::Menu, FlowMsg::Cancelled) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(SetNewPin::Intro, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(SetNewPin::CancelPinIntro, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(SetNewPin::Intro, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(SetNewPin::CancelPinConfirm, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(SetNewPin::CancelPinIntro, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(SetNewPin::CancelPinConfirm, FlowMsg::Confirmed) => {
|
|
||||||
Decision::Return(FlowMsg::Cancelled)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings,
|
|
||||||
flow::{flow_store, SwipeFlow},
|
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_set_new_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_set_new_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, SetNewPin::new_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, SetNewPin::new_obj) }
|
||||||
@ -155,12 +135,11 @@ impl SetNewPin {
|
|||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&SetNewPin::Intro)?
|
||||||
.add(content_intro)?
|
.with_page(&SetNewPin::Intro, content_intro)?
|
||||||
.add(content_menu)?
|
.with_page(&SetNewPin::Menu, content_menu)?
|
||||||
.add(content_cancel_intro)?
|
.with_page(&SetNewPin::CancelPinIntro, content_cancel_intro)?
|
||||||
.add(content_cancel_confirm)?;
|
.with_page(&SetNewPin::CancelPinConfirm, content_cancel_confirm)?;
|
||||||
let res = SwipeFlow::new(SetNewPin::Intro, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,29 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{iter::IterBuf, qstr::Qstr},
|
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
button_request::ButtonRequest,
|
button_request::ButtonRequest,
|
||||||
component::{ButtonRequestExt, ComponentExt, SwipeDirection},
|
component::{swipe_detect::SwipeSettings, ButtonRequestExt, ComponentExt, SwipeDirection},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::super::{
|
use super::{
|
||||||
component::{Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg},
|
super::{
|
||||||
theme,
|
component::{Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg},
|
||||||
|
theme,
|
||||||
|
},
|
||||||
|
util::ShowInfoParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::util::ShowInfoParams;
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
|
||||||
pub enum ConfirmSummary {
|
pub enum ConfirmSummary {
|
||||||
Summary,
|
Summary,
|
||||||
Hold,
|
Hold,
|
||||||
@ -28,62 +34,40 @@ pub enum ConfirmSummary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for ConfirmSummary {
|
impl FlowState for ConfirmSummary {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(ConfirmSummary::Summary | ConfirmSummary::Hold, SwipeDirection::Left) => {
|
(Self::Summary | Self::Hold, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(ConfirmSummary::Menu, direction)
|
(Self::Summary, SwipeDirection::Up) => Self::Hold.swipe(direction),
|
||||||
|
(Self::Hold, SwipeDirection::Down) => Self::Summary.swipe(direction),
|
||||||
|
(Self::Menu, SwipeDirection::Right) => Self::Summary.swipe(direction),
|
||||||
|
(Self::Menu, SwipeDirection::Left) => Self::FeeInfo.swipe(direction),
|
||||||
|
(Self::AccountInfo | Self::FeeInfo | Self::CancelTap, SwipeDirection::Right) => {
|
||||||
|
Self::Menu.swipe(direction)
|
||||||
}
|
}
|
||||||
(ConfirmSummary::Summary, SwipeDirection::Up) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ConfirmSummary::Hold, direction)
|
|
||||||
}
|
|
||||||
(ConfirmSummary::Hold, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(ConfirmSummary::Summary, direction)
|
|
||||||
}
|
|
||||||
(ConfirmSummary::Menu, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(ConfirmSummary::Summary, direction)
|
|
||||||
}
|
|
||||||
(ConfirmSummary::Menu, SwipeDirection::Left) => {
|
|
||||||
Decision::Goto(ConfirmSummary::FeeInfo, direction)
|
|
||||||
}
|
|
||||||
(
|
|
||||||
ConfirmSummary::AccountInfo | ConfirmSummary::FeeInfo | ConfirmSummary::CancelTap,
|
|
||||||
SwipeDirection::Right,
|
|
||||||
) => Decision::Goto(ConfirmSummary::Menu, direction),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(_, FlowMsg::Info) => Decision::Goto(ConfirmSummary::Menu, SwipeDirection::Left),
|
(_, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
(ConfirmSummary::Hold, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Confirmed),
|
(Self::Hold, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
|
||||||
(ConfirmSummary::Menu, FlowMsg::Choice(0)) => {
|
(Self::Menu, FlowMsg::Choice(0)) => Self::FeeInfo.swipe_left(),
|
||||||
Decision::Goto(ConfirmSummary::FeeInfo, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Choice(1)) => Self::AccountInfo.swipe_left(),
|
||||||
}
|
(Self::Menu, FlowMsg::Choice(2)) => Self::CancelTap.swipe_left(),
|
||||||
(ConfirmSummary::Menu, FlowMsg::Choice(1)) => {
|
(Self::Menu, FlowMsg::Cancelled) => Self::Summary.swipe_right(),
|
||||||
Decision::Goto(ConfirmSummary::AccountInfo, SwipeDirection::Left)
|
(Self::CancelTap, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Cancelled),
|
||||||
}
|
(_, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
(ConfirmSummary::Menu, FlowMsg::Choice(2)) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ConfirmSummary::CancelTap, SwipeDirection::Left)
|
|
||||||
}
|
|
||||||
(ConfirmSummary::Menu, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(ConfirmSummary::Summary, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(ConfirmSummary::CancelTap, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
(_, FlowMsg::Cancelled) => Decision::Goto(ConfirmSummary::Menu, SwipeDirection::Right),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings, layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_confirm_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_confirm_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmSummary::new_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmSummary::new_obj) }
|
||||||
@ -171,14 +155,14 @@ impl ConfirmSummary {
|
|||||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||||
});
|
});
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&ConfirmSummary::Summary)?
|
||||||
.add(content_summary)?
|
.with_page(&ConfirmSummary::Summary, content_summary)?
|
||||||
.add(content_hold)?
|
.with_page(&ConfirmSummary::Hold, content_hold)?
|
||||||
.add(content_menu)?
|
.with_page(&ConfirmSummary::Menu, content_menu)?
|
||||||
.add(content_fee)?
|
.with_page(&ConfirmSummary::FeeInfo, content_fee)?
|
||||||
.add(content_account)?
|
.with_page(&ConfirmSummary::AccountInfo, content_account)?
|
||||||
.add(content_cancel_tap)?;
|
.with_page(&ConfirmSummary::CancelTap, content_cancel_tap)?;
|
||||||
let res = SwipeFlow::new(ConfirmSummary::Summary, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{iter::IterBuf, qstr::Qstr},
|
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
button_request::ButtonRequest,
|
button_request::ButtonRequest,
|
||||||
component::{
|
component::{
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, ParagraphSource, Paragraphs},
|
text::paragraphs::{Paragraph, ParagraphSource, Paragraphs},
|
||||||
ButtonRequestExt, ComponentExt, Qr, SwipeDirection,
|
ButtonRequestExt, ComponentExt, Qr, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
layout::util::ConfirmBlob,
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow, SwipePage,
|
||||||
|
},
|
||||||
|
layout::{obj::LayoutObj, util::ConfirmBlob},
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,7 +29,7 @@ use super::super::{
|
|||||||
|
|
||||||
const QR_BORDER: i16 = 4;
|
const QR_BORDER: i16 = 4;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum GetAddress {
|
pub enum GetAddress {
|
||||||
Address,
|
Address,
|
||||||
Tap,
|
Tap,
|
||||||
@ -37,104 +42,48 @@ pub enum GetAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for GetAddress {
|
impl FlowState for GetAddress {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(GetAddress::Address, SwipeDirection::Left) => {
|
(Self::Address, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(GetAddress::Menu, direction)
|
(Self::Address, SwipeDirection::Up) => Self::Tap.swipe(direction),
|
||||||
}
|
(Self::Tap, SwipeDirection::Down) => Self::Address.swipe(direction),
|
||||||
(GetAddress::Address, SwipeDirection::Up) => Decision::Goto(GetAddress::Tap, direction),
|
(Self::Tap, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
(GetAddress::Tap, SwipeDirection::Down) => {
|
(Self::Menu, SwipeDirection::Right) => Self::Address.swipe(direction),
|
||||||
Decision::Goto(GetAddress::Address, direction)
|
(Self::QrCode, SwipeDirection::Right) => Self::Menu.swipe(direction),
|
||||||
}
|
(Self::AccountInfo, SwipeDirection::Right) => Self::Menu.swipe_right(),
|
||||||
(GetAddress::Tap, SwipeDirection::Left) => Decision::Goto(GetAddress::Menu, direction),
|
(Self::Cancel, SwipeDirection::Up) => Self::CancelTap.swipe(direction),
|
||||||
(GetAddress::Menu, SwipeDirection::Right) => {
|
(Self::Cancel, SwipeDirection::Right) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(GetAddress::Address, direction)
|
(Self::CancelTap, SwipeDirection::Down) => Self::Cancel.swipe(direction),
|
||||||
}
|
(Self::CancelTap, SwipeDirection::Right) => Self::Menu.swipe(direction),
|
||||||
(GetAddress::QrCode, SwipeDirection::Right) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(GetAddress::Menu, direction)
|
|
||||||
}
|
|
||||||
(GetAddress::AccountInfo, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(GetAddress::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(GetAddress::Cancel, SwipeDirection::Up) => {
|
|
||||||
Decision::Goto(GetAddress::CancelTap, direction)
|
|
||||||
}
|
|
||||||
(GetAddress::Cancel, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(GetAddress::Menu, direction)
|
|
||||||
}
|
|
||||||
(GetAddress::CancelTap, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(GetAddress::Cancel, direction)
|
|
||||||
}
|
|
||||||
(GetAddress::CancelTap, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(GetAddress::Menu, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(GetAddress::Address, FlowMsg::Info) => {
|
(Self::Address, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(GetAddress::Menu, SwipeDirection::Left)
|
(Self::Tap, FlowMsg::Confirmed) => Self::Confirmed.swipe_up(),
|
||||||
}
|
(Self::Tap, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
|
(Self::Confirmed, _) => self.return_msg(FlowMsg::Confirmed),
|
||||||
(GetAddress::Tap, FlowMsg::Confirmed) => {
|
(Self::Menu, FlowMsg::Choice(0)) => Self::QrCode.swipe_left(),
|
||||||
Decision::Goto(GetAddress::Confirmed, SwipeDirection::Up)
|
(Self::Menu, FlowMsg::Choice(1)) => Self::AccountInfo.swipe_left(),
|
||||||
}
|
(Self::Menu, FlowMsg::Choice(2)) => Self::Cancel.swipe_left(),
|
||||||
|
(Self::Menu, FlowMsg::Cancelled) => Self::Address.swipe_right(),
|
||||||
(GetAddress::Tap, FlowMsg::Info) => {
|
(Self::QrCode, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
Decision::Goto(GetAddress::Menu, SwipeDirection::Left)
|
(Self::AccountInfo, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
}
|
(Self::Cancel, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
|
(Self::CancelTap, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Cancelled),
|
||||||
(GetAddress::Confirmed, _) => Decision::Return(FlowMsg::Confirmed),
|
(Self::CancelTap, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
|
_ => self.do_nothing(),
|
||||||
(GetAddress::Menu, FlowMsg::Choice(0)) => {
|
|
||||||
Decision::Goto(GetAddress::QrCode, SwipeDirection::Left)
|
|
||||||
}
|
|
||||||
|
|
||||||
(GetAddress::Menu, FlowMsg::Choice(1)) => {
|
|
||||||
Decision::Goto(GetAddress::AccountInfo, SwipeDirection::Left)
|
|
||||||
}
|
|
||||||
|
|
||||||
(GetAddress::Menu, FlowMsg::Choice(2)) => {
|
|
||||||
Decision::Goto(GetAddress::Cancel, SwipeDirection::Left)
|
|
||||||
}
|
|
||||||
|
|
||||||
(GetAddress::Menu, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(GetAddress::Address, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
|
|
||||||
(GetAddress::QrCode, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(GetAddress::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
|
|
||||||
(GetAddress::AccountInfo, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(GetAddress::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
|
|
||||||
(GetAddress::Cancel, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(GetAddress::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
|
|
||||||
(GetAddress::CancelTap, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
|
|
||||||
(GetAddress::CancelTap, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(GetAddress::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings, flow::SwipePage, layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_get_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_get_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, GetAddress::new_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, GetAddress::new_obj) }
|
||||||
@ -271,16 +220,15 @@ impl GetAddress {
|
|||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&GetAddress::Address)?
|
||||||
.add(content_address)?
|
.with_page(&GetAddress::Address, content_address)?
|
||||||
.add(content_tap)?
|
.with_page(&GetAddress::Tap, content_tap)?
|
||||||
.add(content_confirmed)?
|
.with_page(&GetAddress::Confirmed, content_confirmed)?
|
||||||
.add(content_menu)?
|
.with_page(&GetAddress::Menu, content_menu)?
|
||||||
.add(content_qr)?
|
.with_page(&GetAddress::QrCode, content_qr)?
|
||||||
.add(content_account)?
|
.with_page(&GetAddress::AccountInfo, content_account)?
|
||||||
.add(content_cancel_info)?
|
.with_page(&GetAddress::Cancel, content_cancel_info)?
|
||||||
.add(content_cancel_tap)?;
|
.with_page(&GetAddress::CancelTap, content_cancel_tap)?;
|
||||||
let res = SwipeFlow::new(GetAddress::Address, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
|
micropython::{map::Map, obj::Obj, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
ComponentExt, SwipeDirection,
|
ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, FlowMsg, FlowState, FlowStore},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,7 +25,7 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum PromptBackup {
|
pub enum PromptBackup {
|
||||||
Intro,
|
Intro,
|
||||||
Menu,
|
Menu,
|
||||||
@ -27,68 +34,39 @@ pub enum PromptBackup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for PromptBackup {
|
impl FlowState for PromptBackup {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(PromptBackup::Intro, SwipeDirection::Left) => {
|
(Self::Intro, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(PromptBackup::Menu, direction)
|
(Self::Intro, SwipeDirection::Up) => self.return_msg(FlowMsg::Confirmed),
|
||||||
|
(Self::Menu, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
|
(Self::SkipBackupIntro, SwipeDirection::Up) => Self::SkipBackupConfirm.swipe(direction),
|
||||||
|
(Self::SkipBackupIntro, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
|
(Self::SkipBackupConfirm, SwipeDirection::Down) => {
|
||||||
|
Self::SkipBackupIntro.swipe(direction)
|
||||||
}
|
}
|
||||||
(PromptBackup::Intro, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed),
|
(Self::SkipBackupConfirm, SwipeDirection::Right) => Self::Intro.swipe(direction),
|
||||||
|
_ => self.do_nothing(),
|
||||||
(PromptBackup::Menu, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(PromptBackup::Intro, direction)
|
|
||||||
}
|
|
||||||
|
|
||||||
(PromptBackup::SkipBackupIntro, SwipeDirection::Up) => {
|
|
||||||
Decision::Goto(PromptBackup::SkipBackupConfirm, direction)
|
|
||||||
}
|
|
||||||
(PromptBackup::SkipBackupIntro, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(PromptBackup::Intro, direction)
|
|
||||||
}
|
|
||||||
(PromptBackup::SkipBackupConfirm, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(PromptBackup::SkipBackupIntro, direction)
|
|
||||||
}
|
|
||||||
(PromptBackup::SkipBackupConfirm, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(PromptBackup::Intro, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(PromptBackup::Intro, FlowMsg::Info) => {
|
(Self::Intro, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(PromptBackup::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Choice(0)) => Self::SkipBackupIntro.swipe_left(),
|
||||||
}
|
(Self::Menu, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
|
||||||
(PromptBackup::Menu, FlowMsg::Choice(0)) => {
|
(Self::SkipBackupIntro, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
Decision::Goto(PromptBackup::SkipBackupIntro, SwipeDirection::Left)
|
(Self::SkipBackupConfirm, FlowMsg::Cancelled) => Self::SkipBackupIntro.swipe_right(),
|
||||||
}
|
(Self::SkipBackupConfirm, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Cancelled),
|
||||||
(PromptBackup::Menu, FlowMsg::Cancelled) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(PromptBackup::Intro, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(PromptBackup::SkipBackupIntro, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(PromptBackup::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(PromptBackup::SkipBackupConfirm, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(PromptBackup::SkipBackupIntro, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(PromptBackup::SkipBackupConfirm, FlowMsg::Confirmed) => {
|
|
||||||
Decision::Return(FlowMsg::Cancelled)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings,
|
|
||||||
flow::{flow_store, SwipeFlow},
|
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_prompt_backup(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_prompt_backup(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, PromptBackup::new_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, PromptBackup::new_obj) }
|
||||||
@ -159,12 +137,11 @@ impl PromptBackup {
|
|||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&PromptBackup::Intro)?
|
||||||
.add(content_intro)?
|
.with_page(&PromptBackup::Intro, content_intro)?
|
||||||
.add(content_menu)?
|
.with_page(&PromptBackup::Menu, content_menu)?
|
||||||
.add(content_skip_intro)?
|
.with_page(&PromptBackup::SkipBackupIntro, content_skip_intro)?
|
||||||
.add(content_skip_confirm)?;
|
.with_page(&PromptBackup::SkipBackupConfirm, content_skip_confirm)?;
|
||||||
let res = SwipeFlow::new(PromptBackup::Intro, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::qstr::Qstr,
|
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
button_request::ButtonRequest,
|
button_request::ButtonRequest,
|
||||||
component::{
|
component::{
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
ButtonRequestExt, ComponentExt, SwipeDirection,
|
ButtonRequestExt, ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,7 +27,7 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum RequestNumber {
|
pub enum RequestNumber {
|
||||||
Number,
|
Number,
|
||||||
Menu,
|
Menu,
|
||||||
@ -29,49 +35,32 @@ pub enum RequestNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for RequestNumber {
|
impl FlowState for RequestNumber {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(RequestNumber::Number, SwipeDirection::Left) => {
|
(Self::Number, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(RequestNumber::Menu, direction)
|
(Self::Menu, SwipeDirection::Right) => Self::Number.swipe(direction),
|
||||||
}
|
(Self::Info, SwipeDirection::Right) => Self::Menu.swipe(direction),
|
||||||
(RequestNumber::Menu, SwipeDirection::Right) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(RequestNumber::Number, direction)
|
|
||||||
}
|
|
||||||
(RequestNumber::Info, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(RequestNumber::Menu, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(RequestNumber::Number, FlowMsg::Info) => {
|
(Self::Number, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(RequestNumber::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Choice(0)) => Self::Info.swipe_left(),
|
||||||
}
|
(Self::Menu, FlowMsg::Cancelled) => Self::Number.swipe_right(),
|
||||||
(RequestNumber::Menu, FlowMsg::Choice(0)) => {
|
(Self::Info, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
Decision::Goto(RequestNumber::Info, SwipeDirection::Left)
|
(Self::Number, FlowMsg::Choice(n)) => self.return_msg(FlowMsg::Choice(n)),
|
||||||
}
|
_ => self.do_nothing(),
|
||||||
(RequestNumber::Menu, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(RequestNumber::Number, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(RequestNumber::Info, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(RequestNumber::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(RequestNumber::Number, FlowMsg::Choice(n)) => Decision::Return(FlowMsg::Choice(n)),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings, layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, RequestNumber::new_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, RequestNumber::new_obj) }
|
||||||
@ -143,11 +132,10 @@ impl RequestNumber {
|
|||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&RequestNumber::Number)?
|
||||||
.add(content_number_input)?
|
.with_page(&RequestNumber::Number, content_number_input)?
|
||||||
.add(content_menu)?
|
.with_page(&RequestNumber::Menu, content_menu)?
|
||||||
.add(content_info)?;
|
.with_page(&RequestNumber::Info, content_info)?;
|
||||||
let res = SwipeFlow::new(RequestNumber::Number, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,10 @@ use crate::{
|
|||||||
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs, VecExt},
|
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs, VecExt},
|
||||||
ButtonRequestExt, ComponentExt, SwipeDirection,
|
ButtonRequestExt, ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
layout::obj::LayoutObj,
|
layout::obj::LayoutObj,
|
||||||
model_mercury::component::SwipeContent,
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
@ -22,7 +25,7 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ShowShareWords {
|
pub enum ShowShareWords {
|
||||||
Instruction,
|
Instruction,
|
||||||
Words,
|
Words,
|
||||||
@ -31,39 +34,28 @@ pub enum ShowShareWords {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for ShowShareWords {
|
impl FlowState for ShowShareWords {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(ShowShareWords::Instruction, SwipeDirection::Up) => {
|
(Self::Instruction, SwipeDirection::Up) => Self::Words.swipe(direction),
|
||||||
Decision::Goto(ShowShareWords::Words, direction)
|
(Self::Confirm, SwipeDirection::Down) => Self::Words.swipe(direction),
|
||||||
}
|
(Self::Words, SwipeDirection::Up) => Self::Confirm.swipe(direction),
|
||||||
(ShowShareWords::Confirm, SwipeDirection::Down) => {
|
(Self::Words, SwipeDirection::Down) => Self::Instruction.swipe(direction),
|
||||||
Decision::Goto(ShowShareWords::Words, direction)
|
(Self::CheckBackupIntro, SwipeDirection::Up) => self.return_msg(FlowMsg::Confirmed),
|
||||||
}
|
_ => self.do_nothing(),
|
||||||
(ShowShareWords::Words, SwipeDirection::Up) => {
|
|
||||||
Decision::Goto(ShowShareWords::Confirm, direction)
|
|
||||||
}
|
|
||||||
(ShowShareWords::Words, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(ShowShareWords::Instruction, direction)
|
|
||||||
}
|
|
||||||
(ShowShareWords::CheckBackupIntro, SwipeDirection::Up) => {
|
|
||||||
Decision::Return(FlowMsg::Confirmed)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(ShowShareWords::Words, FlowMsg::Cancelled) => {
|
(Self::Words, FlowMsg::Cancelled) => Self::Instruction.swipe_down(),
|
||||||
Decision::Goto(ShowShareWords::Instruction, SwipeDirection::Down)
|
(Self::Words, FlowMsg::Confirmed) => Self::Confirm.swipe_up(),
|
||||||
}
|
(Self::Confirm, FlowMsg::Confirmed) => Self::CheckBackupIntro.swipe_up(),
|
||||||
(ShowShareWords::Words, FlowMsg::Confirmed) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ShowShareWords::Confirm, SwipeDirection::Up)
|
|
||||||
}
|
|
||||||
(ShowShareWords::Confirm, FlowMsg::Confirmed) => {
|
|
||||||
Decision::Goto(ShowShareWords::CheckBackupIntro, SwipeDirection::Up)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,12 +123,14 @@ impl ShowShareWords {
|
|||||||
.with_swipe(SwipeDirection::Up, SwipeSettings::default())
|
.with_swipe(SwipeDirection::Up, SwipeSettings::default())
|
||||||
.map(|_| Some(FlowMsg::Confirmed));
|
.map(|_| Some(FlowMsg::Confirmed));
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&ShowShareWords::Instruction)?
|
||||||
.add(content_instruction)?
|
.with_page(&ShowShareWords::Instruction, content_instruction)?
|
||||||
.add(content_words)?
|
.with_page(&ShowShareWords::Words, content_words)?
|
||||||
.add(content_confirm)?
|
.with_page(&ShowShareWords::Confirm, content_confirm)?
|
||||||
.add(content_check_backup_intro)?;
|
.with_page(
|
||||||
let res = SwipeFlow::new(ShowShareWords::Instruction, store)?;
|
&ShowShareWords::CheckBackupIntro,
|
||||||
|
content_check_backup_intro,
|
||||||
|
)?;
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
|
micropython::{map::Map, obj::Obj, util},
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
@ -7,7 +8,10 @@ use crate::{
|
|||||||
text::paragraphs::{Paragraph, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
ComponentExt, SwipeDirection,
|
ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
layout::obj::LayoutObj,
|
layout::obj::LayoutObj,
|
||||||
model_mercury::component::SwipeContent,
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
@ -18,7 +22,7 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ShowTutorial {
|
pub enum ShowTutorial {
|
||||||
StepWelcome,
|
StepWelcome,
|
||||||
StepBegin,
|
StepBegin,
|
||||||
@ -32,76 +36,43 @@ pub enum ShowTutorial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for ShowTutorial {
|
impl FlowState for ShowTutorial {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(ShowTutorial::StepBegin, SwipeDirection::Up) => {
|
(Self::StepBegin, SwipeDirection::Up) => Self::StepNavigation.swipe(direction),
|
||||||
Decision::Goto(ShowTutorial::StepNavigation, direction)
|
(Self::StepNavigation, SwipeDirection::Up) => Self::StepMenu.swipe(direction),
|
||||||
}
|
(Self::StepNavigation, SwipeDirection::Down) => Self::StepBegin.swipe(direction),
|
||||||
(ShowTutorial::StepNavigation, SwipeDirection::Up) => {
|
(Self::StepMenu, SwipeDirection::Up) => Self::StepHold.swipe(direction),
|
||||||
Decision::Goto(ShowTutorial::StepMenu, direction)
|
(Self::StepMenu, SwipeDirection::Down) => Self::StepNavigation.swipe(direction),
|
||||||
}
|
(Self::StepMenu, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
(ShowTutorial::StepNavigation, SwipeDirection::Down) => {
|
(Self::Menu, SwipeDirection::Left) => Self::DidYouKnow.swipe(direction),
|
||||||
Decision::Goto(ShowTutorial::StepBegin, direction)
|
(Self::Menu, SwipeDirection::Right) => Self::StepBegin.swipe(direction),
|
||||||
}
|
(Self::DidYouKnow, SwipeDirection::Right) => Self::Menu.swipe(direction),
|
||||||
(ShowTutorial::StepMenu, SwipeDirection::Up) => {
|
(Self::StepDone, SwipeDirection::Up) => self.return_msg(FlowMsg::Confirmed),
|
||||||
Decision::Goto(ShowTutorial::StepHold, direction)
|
_ => self.do_nothing(),
|
||||||
}
|
|
||||||
(ShowTutorial::StepMenu, SwipeDirection::Down) => {
|
|
||||||
Decision::Goto(ShowTutorial::StepNavigation, direction)
|
|
||||||
}
|
|
||||||
(ShowTutorial::StepMenu, SwipeDirection::Left) => {
|
|
||||||
Decision::Goto(ShowTutorial::Menu, direction)
|
|
||||||
}
|
|
||||||
(ShowTutorial::Menu, SwipeDirection::Left) => {
|
|
||||||
Decision::Goto(ShowTutorial::DidYouKnow, direction)
|
|
||||||
}
|
|
||||||
(ShowTutorial::Menu, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(ShowTutorial::StepBegin, direction)
|
|
||||||
}
|
|
||||||
(ShowTutorial::DidYouKnow, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(ShowTutorial::Menu, direction)
|
|
||||||
}
|
|
||||||
(ShowTutorial::StepDone, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(ShowTutorial::StepWelcome, FlowMsg::Confirmed) => {
|
(Self::StepWelcome, FlowMsg::Confirmed) => Self::StepBegin.swipe_up(),
|
||||||
Decision::Goto(ShowTutorial::StepBegin, SwipeDirection::Up)
|
(Self::StepMenu, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
}
|
(Self::Menu, FlowMsg::Choice(0)) => Self::DidYouKnow.swipe_left(),
|
||||||
(ShowTutorial::StepMenu, FlowMsg::Info) => {
|
(Self::Menu, FlowMsg::Choice(1)) => Self::StepBegin.swipe_right(),
|
||||||
Decision::Goto(ShowTutorial::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Choice(2)) => Self::HoldToExit.swipe_up(),
|
||||||
}
|
(Self::Menu, FlowMsg::Cancelled) => Self::StepMenu.swipe_right(),
|
||||||
(ShowTutorial::Menu, FlowMsg::Choice(0)) => {
|
(Self::DidYouKnow, FlowMsg::Cancelled) => Self::Menu.swipe_right(),
|
||||||
Decision::Goto(ShowTutorial::DidYouKnow, SwipeDirection::Left)
|
(Self::StepHold, FlowMsg::Confirmed) => Self::StepDone.swipe_up(),
|
||||||
}
|
(Self::HoldToExit, FlowMsg::Confirmed) => Self::StepDone.swipe_up(),
|
||||||
(ShowTutorial::Menu, FlowMsg::Choice(1)) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(ShowTutorial::StepBegin, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(ShowTutorial::Menu, FlowMsg::Choice(2)) => {
|
|
||||||
Decision::Goto(ShowTutorial::HoldToExit, SwipeDirection::Up)
|
|
||||||
}
|
|
||||||
(ShowTutorial::Menu, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(ShowTutorial::StepMenu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(ShowTutorial::DidYouKnow, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(ShowTutorial::Menu, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(ShowTutorial::StepHold, FlowMsg::Confirmed) => {
|
|
||||||
Decision::Goto(ShowTutorial::StepDone, SwipeDirection::Up)
|
|
||||||
}
|
|
||||||
(ShowTutorial::HoldToExit, FlowMsg::Confirmed) => {
|
|
||||||
Decision::Goto(ShowTutorial::StepDone, SwipeDirection::Up)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::micropython::{map::Map, obj::Obj, util};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_show_tutorial(_n_args: usize, _args: *const Obj, _kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_show_tutorial(_n_args: usize, _args: *const Obj, _kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_or_raise(ShowTutorial::new_obj) }
|
unsafe { util::try_or_raise(ShowTutorial::new_obj) }
|
||||||
@ -213,17 +184,16 @@ impl ShowTutorial {
|
|||||||
.with_footer(TR::instructions__exit_tutorial.into(), None)
|
.with_footer(TR::instructions__exit_tutorial.into(), None)
|
||||||
.map(|msg| matches!(msg, FrameMsg::Content(())).then_some(FlowMsg::Confirmed));
|
.map(|msg| matches!(msg, FrameMsg::Content(())).then_some(FlowMsg::Confirmed));
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&ShowTutorial::StepWelcome)?
|
||||||
.add(content_step_welcome)?
|
.with_page(&ShowTutorial::StepWelcome, content_step_welcome)?
|
||||||
.add(content_step_begin)?
|
.with_page(&ShowTutorial::StepBegin, content_step_begin)?
|
||||||
.add(content_step_navigation)?
|
.with_page(&ShowTutorial::StepNavigation, content_step_navigation)?
|
||||||
.add(content_step_menu)?
|
.with_page(&ShowTutorial::StepMenu, content_step_menu)?
|
||||||
.add(content_step_hold)?
|
.with_page(&ShowTutorial::StepHold, content_step_hold)?
|
||||||
.add(content_step_done)?
|
.with_page(&ShowTutorial::StepDone, content_step_done)?
|
||||||
.add(content_menu)?
|
.with_page(&ShowTutorial::Menu, content_menu)?
|
||||||
.add(content_did_you_know)?
|
.with_page(&ShowTutorial::DidYouKnow, content_did_you_know)?
|
||||||
.add(content_hold_to_exit)?;
|
.with_page(&ShowTutorial::HoldToExit, content_hold_to_exit)?;
|
||||||
let res = SwipeFlow::new(ShowTutorial::StepWelcome, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::qstr::Qstr,
|
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, ParagraphSource},
|
text::paragraphs::{Paragraph, ParagraphSource},
|
||||||
ComponentExt, SwipeDirection,
|
ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{
|
||||||
|
base::{DecisionBuilder as _, StateChange},
|
||||||
|
FlowMsg, FlowState, SwipeFlow,
|
||||||
|
},
|
||||||
|
layout::obj::LayoutObj,
|
||||||
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,7 +23,7 @@ use super::super::{
|
|||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum WarningHiPrio {
|
pub enum WarningHiPrio {
|
||||||
Message,
|
Message,
|
||||||
Menu,
|
Menu,
|
||||||
@ -25,47 +31,32 @@ pub enum WarningHiPrio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlowState for WarningHiPrio {
|
impl FlowState for WarningHiPrio {
|
||||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, direction: SwipeDirection) -> StateChange {
|
||||||
match (self, direction) {
|
match (self, direction) {
|
||||||
(WarningHiPrio::Message, SwipeDirection::Left) => {
|
(Self::Message, SwipeDirection::Left) => Self::Menu.swipe(direction),
|
||||||
Decision::Goto(WarningHiPrio::Menu, direction)
|
(Self::Message, SwipeDirection::Up) => Self::Cancelled.swipe(direction),
|
||||||
}
|
(Self::Menu, SwipeDirection::Right) => Self::Message.swipe(direction),
|
||||||
(WarningHiPrio::Message, SwipeDirection::Up) => {
|
_ => self.do_nothing(),
|
||||||
Decision::Goto(WarningHiPrio::Cancelled, direction)
|
|
||||||
}
|
|
||||||
(WarningHiPrio::Menu, SwipeDirection::Right) => {
|
|
||||||
Decision::Goto(WarningHiPrio::Message, direction)
|
|
||||||
}
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
fn handle_event(&'static self, msg: FlowMsg) -> StateChange {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(WarningHiPrio::Message, FlowMsg::Info) => {
|
(Self::Message, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
Decision::Goto(WarningHiPrio::Menu, SwipeDirection::Left)
|
(Self::Menu, FlowMsg::Choice(1)) => self.return_msg(FlowMsg::Confirmed),
|
||||||
}
|
(Self::Menu, FlowMsg::Choice(_)) => Self::Cancelled.swipe_up(),
|
||||||
(WarningHiPrio::Menu, FlowMsg::Choice(1)) => Decision::Return(FlowMsg::Confirmed),
|
(Self::Menu, FlowMsg::Cancelled) => Self::Message.swipe_right(),
|
||||||
(WarningHiPrio::Menu, FlowMsg::Choice(_)) => {
|
(Self::Cancelled, _) => self.return_msg(FlowMsg::Cancelled),
|
||||||
Decision::Goto(WarningHiPrio::Cancelled, SwipeDirection::Up)
|
_ => self.do_nothing(),
|
||||||
}
|
|
||||||
(WarningHiPrio::Menu, FlowMsg::Cancelled) => {
|
|
||||||
Decision::Goto(WarningHiPrio::Message, SwipeDirection::Right)
|
|
||||||
}
|
|
||||||
(WarningHiPrio::Cancelled, _) => Decision::Return(FlowMsg::Cancelled),
|
|
||||||
_ => Decision::Nothing,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::{
|
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
ui::{
|
|
||||||
component::swipe_detect::SwipeSettings, layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||||
pub extern "C" fn new_warning_hi_prio(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub extern "C" fn new_warning_hi_prio(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, WarningHiPrio::new_obj) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, WarningHiPrio::new_obj) }
|
||||||
@ -118,11 +109,10 @@ impl WarningHiPrio {
|
|||||||
.with_footer(TR::instructions__continue_in_app.into(), None)
|
.with_footer(TR::instructions__continue_in_app.into(), None)
|
||||||
.map(|_| Some(FlowMsg::Cancelled));
|
.map(|_| Some(FlowMsg::Cancelled));
|
||||||
|
|
||||||
let store = flow_store()
|
let res = SwipeFlow::new(&WarningHiPrio::Message)?
|
||||||
.add(content_message)?
|
.with_page(&WarningHiPrio::Message, content_message)?
|
||||||
.add(content_menu)?
|
.with_page(&WarningHiPrio::Menu, content_menu)?
|
||||||
.add(content_cancelled)?;
|
.with_page(&WarningHiPrio::Cancelled, content_cancelled)?;
|
||||||
let res = SwipeFlow::new(WarningHiPrio::Message, store)?;
|
|
||||||
Ok(LayoutObj::new(res)?.into())
|
Ok(LayoutObj::new(res)?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ pub use canvas::{
|
|||||||
};
|
};
|
||||||
pub use circle::Circle;
|
pub use circle::Circle;
|
||||||
pub use corner_highlight::CornerHighlight;
|
pub use corner_highlight::CornerHighlight;
|
||||||
pub use display::{render_on_canvas, render_on_display, unlock_bumps_on_failure};
|
pub use display::{render_on_canvas, render_on_display, unlock_bumps_on_failure, ConcreteRenderer};
|
||||||
#[cfg(feature = "ui_jpeg_decoder")]
|
#[cfg(feature = "ui_jpeg_decoder")]
|
||||||
pub use jpeg::JpegImage;
|
pub use jpeg::JpegImage;
|
||||||
pub use qrcode::QrImage;
|
pub use qrcode::QrImage;
|
||||||
pub use rawimage::RawImage;
|
pub use rawimage::RawImage;
|
||||||
pub use render::{DirectRenderer, ProgressiveRenderer, Renderer};
|
pub use render::{DirectRenderer, ProgressiveRenderer, Renderer, ScopedRenderer};
|
||||||
pub use text::Text;
|
pub use text::Text;
|
||||||
pub use toif::ToifImage;
|
pub use toif::ToifImage;
|
||||||
#[cfg(feature = "ui_image_buffer")]
|
#[cfg(feature = "ui_image_buffer")]
|
||||||
|
Loading…
Reference in New Issue
Block a user