mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-09 06:50:58 +00:00
fix(core/ui): allow component to terminate flow on swipe
[skip_ci]
This commit is contained in:
parent
cbcd9dd8bd
commit
9c14cae656
@ -65,15 +65,15 @@ pub trait ButtonRequestExt {
|
|||||||
impl<T: Component> ButtonRequestExt for T {}
|
impl<T: Component> ButtonRequestExt for T {}
|
||||||
|
|
||||||
#[cfg(all(feature = "micropython", feature = "touch", feature = "new_rendering"))]
|
#[cfg(all(feature = "micropython", feature = "touch", feature = "new_rendering"))]
|
||||||
impl<T> crate::ui::flow::Swipable for OneButtonRequest<T>
|
impl<T> crate::ui::flow::Swipable<T::Msg> for OneButtonRequest<T>
|
||||||
where
|
where
|
||||||
T: Component + crate::ui::flow::Swipable,
|
T: Component + crate::ui::flow::Swipable<T::Msg>,
|
||||||
{
|
{
|
||||||
fn swipe_start(
|
fn swipe_start(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
direction: crate::ui::component::SwipeDirection,
|
direction: crate::ui::component::SwipeDirection,
|
||||||
) -> bool {
|
) -> crate::ui::flow::SwipableResult<T::Msg> {
|
||||||
self.inner.swipe_start(ctx, direction)
|
self.inner.swipe_start(ctx, direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,12 +52,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "micropython", feature = "touch", feature = "new_rendering"))]
|
#[cfg(all(feature = "micropython", feature = "touch", feature = "new_rendering"))]
|
||||||
impl<T, F> crate::ui::flow::Swipable for MsgMap<T, F>
|
impl<T, F, U> crate::ui::flow::Swipable<U> for MsgMap<T, F>
|
||||||
where
|
where
|
||||||
T: Component + crate::ui::flow::Swipable,
|
T: Component + crate::ui::flow::Swipable<T::Msg>,
|
||||||
|
F: Fn(T::Msg) -> Option<U>,
|
||||||
{
|
{
|
||||||
fn swipe_start(&mut self, ctx: &mut EventCtx, direction: super::SwipeDirection) -> bool {
|
fn swipe_start(
|
||||||
self.inner.swipe_start(ctx, direction)
|
&mut self,
|
||||||
|
ctx: &mut EventCtx,
|
||||||
|
direction: super::SwipeDirection,
|
||||||
|
) -> crate::ui::flow::SwipableResult<U> {
|
||||||
|
self.inner.swipe_start(ctx, direction).map(&self.func)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swipe_finished(&self) -> bool {
|
fn swipe_finished(&self) -> bool {
|
||||||
@ -118,11 +123,15 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "micropython", feature = "touch", feature = "new_rendering"))]
|
#[cfg(all(feature = "micropython", feature = "touch", feature = "new_rendering"))]
|
||||||
impl<T, F> crate::ui::flow::Swipable for PageMap<T, F>
|
impl<T, F> crate::ui::flow::Swipable<T::Msg> for PageMap<T, F>
|
||||||
where
|
where
|
||||||
T: Component + crate::ui::flow::Swipable,
|
T: Component + crate::ui::flow::Swipable<T::Msg>,
|
||||||
{
|
{
|
||||||
fn swipe_start(&mut self, ctx: &mut EventCtx, direction: super::SwipeDirection) -> bool {
|
fn swipe_start(
|
||||||
|
&mut self,
|
||||||
|
ctx: &mut EventCtx,
|
||||||
|
direction: super::SwipeDirection,
|
||||||
|
) -> crate::ui::flow::SwipableResult<T::Msg> {
|
||||||
self.inner.swipe_start(ctx, direction)
|
self.inner.swipe_start(ctx, direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,18 @@ use num_traits::ToPrimitive;
|
|||||||
/// Component must implement this trait in order to be part of swipe-based flow.
|
/// Component must implement this trait in order to be part of swipe-based flow.
|
||||||
///
|
///
|
||||||
/// Default implementation ignores every swipe.
|
/// Default implementation ignores every swipe.
|
||||||
pub trait Swipable {
|
pub trait Swipable<T> {
|
||||||
/// Attempt a swipe. Return false if component in its current state doesn't
|
/// Attempt a swipe. Return `Ignored` if the component in its current state
|
||||||
/// accept a swipe in the given direction. Start a transition animation
|
/// doesn't accept a swipe in that direction. Return `Animating` if
|
||||||
/// if true is returned.
|
/// component accepted the swipe and started a transition animation. The
|
||||||
fn swipe_start(&mut self, _ctx: &mut EventCtx, _direction: SwipeDirection) -> bool {
|
/// `Return(x)` variant indicates that the current flow should be terminated
|
||||||
false
|
/// with the result `x`.
|
||||||
|
fn swipe_start(
|
||||||
|
&mut self,
|
||||||
|
_ctx: &mut EventCtx,
|
||||||
|
_direction: SwipeDirection,
|
||||||
|
) -> SwipableResult<T> {
|
||||||
|
SwipableResult::Ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true when transition animation is finished. SwipeFlow needs to
|
/// Return true when transition animation is finished. SwipeFlow needs to
|
||||||
@ -19,6 +25,28 @@ pub trait Swipable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum SwipableResult<T> {
|
||||||
|
Ignored,
|
||||||
|
Animating,
|
||||||
|
Return(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SwipableResult<T> {
|
||||||
|
pub fn map<U>(self, func: impl FnOnce(T) -> Option<U>) -> SwipableResult<U> {
|
||||||
|
match self {
|
||||||
|
SwipableResult::Ignored => SwipableResult::Ignored,
|
||||||
|
SwipableResult::Animating => SwipableResult::Animating,
|
||||||
|
SwipableResult::Return(x) => {
|
||||||
|
if let Some(res) = func(x) {
|
||||||
|
SwipableResult::Return(res)
|
||||||
|
} else {
|
||||||
|
SwipableResult::Ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Component::Msg for component parts of a flow. Converting results of
|
/// Component::Msg for component parts of a flow. Converting results of
|
||||||
/// different screens to a shared type makes things easier to work with.
|
/// different screens to a shared type makes things easier to work with.
|
||||||
///
|
///
|
||||||
|
@ -3,7 +3,7 @@ pub mod page;
|
|||||||
mod store;
|
mod store;
|
||||||
mod swipe;
|
mod swipe;
|
||||||
|
|
||||||
pub use base::{FlowMsg, FlowState, Swipable};
|
pub use base::{FlowMsg, FlowState, Swipable, SwipableResult};
|
||||||
pub use page::{IgnoreSwipe, SwipePage};
|
pub use page::{IgnoreSwipe, SwipePage};
|
||||||
pub use store::{flow_store, FlowStore};
|
pub use store::{flow_store, FlowStore};
|
||||||
pub use swipe::SwipeFlow;
|
pub use swipe::SwipeFlow;
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
ui::{
|
ui::{
|
||||||
animation::Animation,
|
animation::Animation,
|
||||||
component::{Component, Event, EventCtx, Paginate, SwipeDirection},
|
component::{Component, Event, EventCtx, Paginate, SwipeDirection},
|
||||||
flow::base::Swipable,
|
flow::base::{Swipable, SwipableResult},
|
||||||
geometry::{Axis, Rect},
|
geometry::{Axis, Rect},
|
||||||
shape::Renderer,
|
shape::Renderer,
|
||||||
util,
|
util,
|
||||||
@ -117,17 +117,27 @@ impl<T: Component + Paginate + Clone> Component for SwipePage<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Component + Paginate + Clone> Swipable for SwipePage<T> {
|
impl<T: Component + Paginate + Clone> Swipable<T::Msg> for SwipePage<T> {
|
||||||
fn swipe_start(&mut self, ctx: &mut EventCtx, direction: SwipeDirection) -> bool {
|
fn swipe_start(
|
||||||
|
&mut self,
|
||||||
|
ctx: &mut EventCtx,
|
||||||
|
direction: SwipeDirection,
|
||||||
|
) -> SwipableResult<T::Msg> {
|
||||||
match (self.axis, direction) {
|
match (self.axis, direction) {
|
||||||
// Wrong direction
|
// Wrong direction
|
||||||
(Axis::Horizontal, SwipeDirection::Up | SwipeDirection::Down) => return false,
|
(Axis::Horizontal, SwipeDirection::Up | SwipeDirection::Down) => {
|
||||||
(Axis::Vertical, SwipeDirection::Left | SwipeDirection::Right) => return false,
|
return SwipableResult::Ignored
|
||||||
|
}
|
||||||
|
(Axis::Vertical, SwipeDirection::Left | SwipeDirection::Right) => {
|
||||||
|
return SwipableResult::Ignored
|
||||||
|
}
|
||||||
// Begin
|
// Begin
|
||||||
(_, SwipeDirection::Right | SwipeDirection::Down) if self.current == 0 => return false,
|
(_, SwipeDirection::Right | SwipeDirection::Down) if self.current == 0 => {
|
||||||
|
return SwipableResult::Ignored
|
||||||
|
}
|
||||||
// End
|
// End
|
||||||
(_, SwipeDirection::Left | SwipeDirection::Up) if self.current + 1 >= self.pages => {
|
(_, SwipeDirection::Left | SwipeDirection::Up) if self.current + 1 >= self.pages => {
|
||||||
return false
|
return SwipableResult::Ignored;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
@ -138,7 +148,7 @@ impl<T: Component + Paginate + Clone> Swipable for SwipePage<T> {
|
|||||||
if util::animation_disabled() {
|
if util::animation_disabled() {
|
||||||
self.inner.change_page(self.current);
|
self.inner.change_page(self.current);
|
||||||
ctx.request_paint();
|
ctx.request_paint();
|
||||||
return true;
|
return SwipableResult::Animating;
|
||||||
}
|
}
|
||||||
self.transition = Some(Transition {
|
self.transition = Some(Transition {
|
||||||
cloned: unwrap!(Gc::new(self.inner.clone())),
|
cloned: unwrap!(Gc::new(self.inner.clone())),
|
||||||
@ -148,7 +158,7 @@ impl<T: Component + Paginate + Clone> Swipable for SwipePage<T> {
|
|||||||
self.inner.change_page(self.current);
|
self.inner.change_page(self.current);
|
||||||
ctx.request_anim_frame();
|
ctx.request_anim_frame();
|
||||||
ctx.request_paint();
|
ctx.request_paint();
|
||||||
true
|
SwipableResult::Animating
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swipe_finished(&self) -> bool {
|
fn swipe_finished(&self) -> bool {
|
||||||
@ -195,7 +205,7 @@ impl<T: Component> Component for IgnoreSwipe<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Swipable for IgnoreSwipe<T> {}
|
impl<T: Component> Swipable<T::Msg> for IgnoreSwipe<T> {}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for IgnoreSwipe<T>
|
impl<T> crate::trace::Trace for IgnoreSwipe<T>
|
||||||
|
@ -29,10 +29,14 @@ pub trait FlowStore {
|
|||||||
fn trace(&self, i: usize, t: &mut dyn crate::trace::Tracer);
|
fn trace(&self, i: usize, t: &mut dyn crate::trace::Tracer);
|
||||||
|
|
||||||
/// Forward `Swipable` methods to i-th element.
|
/// Forward `Swipable` methods to i-th element.
|
||||||
fn map_swipable<T>(&mut self, i: usize, func: impl FnOnce(&mut dyn Swipable) -> T) -> T;
|
fn map_swipable<T>(
|
||||||
|
&mut self,
|
||||||
|
i: usize,
|
||||||
|
func: impl FnOnce(&mut dyn Swipable<FlowMsg>) -> T,
|
||||||
|
) -> T;
|
||||||
|
|
||||||
/// Add a Component to the end of a `FlowStore`.
|
/// Add a Component to the end of a `FlowStore`.
|
||||||
fn add<E: Component<Msg = FlowMsg> + MaybeTrace + Swipable>(
|
fn add<E: Component<Msg = FlowMsg> + MaybeTrace + Swipable<FlowMsg>>(
|
||||||
self,
|
self,
|
||||||
elem: E,
|
elem: E,
|
||||||
) -> Result<impl FlowStore, error::Error>
|
) -> Result<impl FlowStore, error::Error>
|
||||||
@ -67,11 +71,15 @@ impl FlowStore for FlowEmpty {
|
|||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_swipable<T>(&mut self, _i: usize, _func: impl FnOnce(&mut dyn Swipable) -> T) -> T {
|
fn map_swipable<T>(
|
||||||
|
&mut self,
|
||||||
|
_i: usize,
|
||||||
|
_func: impl FnOnce(&mut dyn Swipable<FlowMsg>) -> T,
|
||||||
|
) -> T {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<E: Component<Msg = FlowMsg> + MaybeTrace + Swipable>(
|
fn add<E: Component<Msg = FlowMsg> + MaybeTrace + Swipable<FlowMsg>>(
|
||||||
self,
|
self,
|
||||||
elem: E,
|
elem: E,
|
||||||
) -> Result<impl FlowStore, error::Error>
|
) -> Result<impl FlowStore, error::Error>
|
||||||
@ -107,7 +115,7 @@ impl<E: Component<Msg = FlowMsg>, P> FlowComponent<E, P> {
|
|||||||
|
|
||||||
impl<E, P> FlowStore for FlowComponent<E, P>
|
impl<E, P> FlowStore for FlowComponent<E, P>
|
||||||
where
|
where
|
||||||
E: Component<Msg = FlowMsg> + MaybeTrace + Swipable,
|
E: Component<Msg = FlowMsg> + MaybeTrace + Swipable<FlowMsg>,
|
||||||
P: FlowStore,
|
P: FlowStore,
|
||||||
{
|
{
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -141,7 +149,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_swipable<T>(&mut self, i: usize, func: impl FnOnce(&mut dyn Swipable) -> T) -> T {
|
fn map_swipable<T>(
|
||||||
|
&mut self,
|
||||||
|
i: usize,
|
||||||
|
func: impl FnOnce(&mut dyn Swipable<FlowMsg>) -> T,
|
||||||
|
) -> T {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
func(self.as_mut())
|
func(self.as_mut())
|
||||||
} else {
|
} else {
|
||||||
@ -149,7 +161,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<F: Component<Msg = FlowMsg> + MaybeTrace + Swipable>(
|
fn add<F: Component<Msg = FlowMsg> + MaybeTrace + Swipable<FlowMsg>>(
|
||||||
self,
|
self,
|
||||||
elem: F,
|
elem: F,
|
||||||
) -> Result<impl FlowStore, error::Error>
|
) -> Result<impl FlowStore, error::Error>
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
ui::{
|
ui::{
|
||||||
animation::Animation,
|
animation::Animation,
|
||||||
component::{Component, Event, EventCtx, Swipe, SwipeDirection},
|
component::{Component, Event, EventCtx, Swipe, SwipeDirection},
|
||||||
flow::{base::Decision, FlowMsg, FlowState, FlowStore},
|
flow::{base::Decision, FlowMsg, FlowState, FlowStore, SwipableResult},
|
||||||
geometry::Rect,
|
geometry::Rect,
|
||||||
shape::Renderer,
|
shape::Renderer,
|
||||||
util,
|
util,
|
||||||
@ -135,13 +135,13 @@ impl<Q: FlowState, S: FlowStore> SwipeFlow<Q, S> {
|
|||||||
|
|
||||||
fn handle_swipe_child(&mut self, ctx: &mut EventCtx, direction: SwipeDirection) -> Decision<Q> {
|
fn handle_swipe_child(&mut self, ctx: &mut EventCtx, direction: SwipeDirection) -> Decision<Q> {
|
||||||
let i = self.state.index();
|
let i = self.state.index();
|
||||||
if self
|
match self
|
||||||
.store
|
.store
|
||||||
.map_swipable(i, |s| s.swipe_start(ctx, direction))
|
.map_swipable(i, |s| s.swipe_start(ctx, direction))
|
||||||
{
|
{
|
||||||
Decision::Goto(self.state, direction)
|
SwipableResult::Ignored => Decision::Nothing,
|
||||||
} else {
|
SwipableResult::Animating => Decision::Goto(self.state, direction),
|
||||||
Decision::Nothing
|
SwipableResult::Return(x) => Decision::Return(x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,4 +230,4 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "micropython")]
|
||||||
impl<U> crate::ui::flow::Swipable for IconDialog<U> {}
|
impl<U: Component> crate::ui::flow::Swipable<U::Msg> for IconDialog<U> {}
|
||||||
|
@ -252,16 +252,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "micropython")]
|
||||||
impl<T> crate::ui::flow::Swipable for Frame<T>
|
impl<T> crate::ui::flow::Swipable<FrameMsg<T::Msg>> for Frame<T>
|
||||||
where
|
where
|
||||||
T: Component + crate::ui::flow::Swipable,
|
T: Component + crate::ui::flow::Swipable<T::Msg>,
|
||||||
{
|
{
|
||||||
fn swipe_start(
|
fn swipe_start(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
direction: crate::ui::component::SwipeDirection,
|
direction: crate::ui::component::SwipeDirection,
|
||||||
) -> bool {
|
) -> crate::ui::flow::SwipableResult<FrameMsg<T::Msg>> {
|
||||||
self.update_content(ctx, |ctx, inner| inner.swipe_start(ctx, direction))
|
self.update_content(ctx, |ctx, inner| inner.swipe_start(ctx, direction))
|
||||||
|
.map(|x| Some(FrameMsg::Content(x)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swipe_finished(&self) -> bool {
|
fn swipe_finished(&self) -> bool {
|
||||||
|
@ -134,7 +134,7 @@ impl Component for PromptScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "micropython")]
|
||||||
impl crate::ui::flow::Swipable for PromptScreen {}
|
impl crate::ui::flow::Swipable<()> for PromptScreen {}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl crate::trace::Trace for PromptScreen {
|
impl crate::trace::Trace for PromptScreen {
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
ui::{
|
ui::{
|
||||||
animation::Animation,
|
animation::Animation,
|
||||||
component::{Component, Event, EventCtx, Never, SwipeDirection},
|
component::{Component, Event, EventCtx, Never, SwipeDirection},
|
||||||
flow::Swipable,
|
flow::{Swipable, SwipableResult},
|
||||||
geometry::{Alignment, Alignment2D, Insets, Offset, Rect},
|
geometry::{Alignment, Alignment2D, Insets, Offset, Rect},
|
||||||
model_mercury::component::Footer,
|
model_mercury::component::Footer,
|
||||||
shape,
|
shape,
|
||||||
@ -160,8 +160,12 @@ impl<'a> Component for ShareWords<'a> {
|
|||||||
fn bounds(&self, _sink: &mut dyn FnMut(Rect)) {}
|
fn bounds(&self, _sink: &mut dyn FnMut(Rect)) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Swipable for ShareWords<'a> {
|
impl<'a> Swipable<Never> for ShareWords<'a> {
|
||||||
fn swipe_start(&mut self, ctx: &mut EventCtx, direction: SwipeDirection) -> bool {
|
fn swipe_start(
|
||||||
|
&mut self,
|
||||||
|
ctx: &mut EventCtx,
|
||||||
|
direction: SwipeDirection,
|
||||||
|
) -> SwipableResult<Never> {
|
||||||
match direction {
|
match direction {
|
||||||
SwipeDirection::Up if !self.is_final_page() => {
|
SwipeDirection::Up if !self.is_final_page() => {
|
||||||
self.prev_index = self.page_index;
|
self.prev_index = self.page_index;
|
||||||
@ -171,11 +175,11 @@ impl<'a> Swipable for ShareWords<'a> {
|
|||||||
self.prev_index = self.page_index;
|
self.prev_index = self.page_index;
|
||||||
self.page_index = self.page_index.saturating_sub(1);
|
self.page_index = self.page_index.saturating_sub(1);
|
||||||
}
|
}
|
||||||
_ => return false,
|
_ => return SwipableResult::Ignored,
|
||||||
};
|
};
|
||||||
if util::animation_disabled() {
|
if util::animation_disabled() {
|
||||||
ctx.request_paint();
|
ctx.request_paint();
|
||||||
return true;
|
return SwipableResult::Animating;
|
||||||
}
|
}
|
||||||
self.animation = Some(Animation::new(
|
self.animation = Some(Animation::new(
|
||||||
0.0f32,
|
0.0f32,
|
||||||
@ -185,7 +189,7 @@ impl<'a> Swipable for ShareWords<'a> {
|
|||||||
));
|
));
|
||||||
ctx.request_anim_frame();
|
ctx.request_anim_frame();
|
||||||
ctx.request_paint();
|
ctx.request_paint();
|
||||||
true
|
SwipableResult::Animating
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swipe_finished(&self) -> bool {
|
fn swipe_finished(&self) -> bool {
|
||||||
|
@ -151,4 +151,4 @@ impl crate::trace::Trace for VerticalMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "micropython")]
|
||||||
impl crate::ui::flow::Swipable for VerticalMenu {}
|
impl crate::ui::flow::Swipable<VerticalMenuChoiceMsg> for VerticalMenu {}
|
||||||
|
@ -89,7 +89,7 @@ impl ConfirmBlobParams {
|
|||||||
|
|
||||||
pub fn into_layout(
|
pub fn into_layout(
|
||||||
self,
|
self,
|
||||||
) -> Result<impl Component<Msg = FlowMsg> + Swipable + MaybeTrace, Error> {
|
) -> Result<impl Component<Msg = FlowMsg> + Swipable<FlowMsg> + MaybeTrace, Error> {
|
||||||
let paragraphs = ConfirmBlob {
|
let paragraphs = ConfirmBlob {
|
||||||
description: self.description.unwrap_or("".into()),
|
description: self.description.unwrap_or("".into()),
|
||||||
extra: self.extra.unwrap_or("".into()),
|
extra: self.extra.unwrap_or("".into()),
|
||||||
@ -187,7 +187,7 @@ impl ShowInfoParams {
|
|||||||
|
|
||||||
pub fn into_layout(
|
pub fn into_layout(
|
||||||
self,
|
self,
|
||||||
) -> Result<impl Component<Msg = FlowMsg> + Swipable + MaybeTrace, Error> {
|
) -> Result<impl Component<Msg = FlowMsg> + Swipable<FlowMsg> + MaybeTrace, Error> {
|
||||||
let mut paragraphs = ParagraphVecShort::new();
|
let mut paragraphs = ParagraphVecShort::new();
|
||||||
let mut first: bool = true;
|
let mut first: bool = true;
|
||||||
for item in self.items {
|
for item in self.items {
|
||||||
|
Loading…
Reference in New Issue
Block a user