Skip to content

Commit

Permalink
refactor: split wallet add page to separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
tvolk131 committed Oct 12, 2024
1 parent af2a75d commit 149a9cd
Show file tree
Hide file tree
Showing 2 changed files with 265 additions and 268 deletions.
281 changes: 13 additions & 268 deletions src/routes/bitcoin_wallet.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
use std::str::FromStr;

use fedimint_core::{
config::{ClientConfig, FederationId, META_FEDERATION_NAME_KEY},
invite_code::InviteCode,
Amount,
};
use fedimint_core::{config::FederationId, Amount};
use iced::{
widget::{
column, container::Style, horizontal_space, row, text_input, Column, Container, Space, Text,
},
widget::{column, container::Style, horizontal_space, row, Column, Container, Space, Text},
Border, Length, Shadow, Task, Theme,
};

Expand All @@ -21,30 +13,16 @@ use crate::{

use super::{container, ConnectedState, Loadable, RouteName};

mod add;
mod receive;
mod send;

#[derive(Debug, Clone)]
pub enum Message {
JoinFederationInviteCodeInputChanged(String),

LoadedFederationConfigFromInviteCode {
// The invite code that was used to load the federation config.
config_invite_code: InviteCode,
// The loaded federation config.
config: ClientConfig,
},
FailedToLoadFederationConfigFromInviteCode {
// The invite code that was used to attempt to load the federation config.
config_invite_code: InviteCode,
},

JoinFederation(InviteCode),
JoinedFederation(InviteCode),

LeaveFederation(FederationId),
LeftFederation(FederationId),

Add(add::Message),
Send(send::Message),
Receive(receive::Message),

Expand All @@ -57,148 +35,8 @@ pub struct Page {
}

impl Page {
// TODO: Remove this clippy allow.
#[allow(clippy::too_many_lines)]
pub fn update(&mut self, msg: Message) -> Task<app::Message> {
match msg {
Message::JoinFederationInviteCodeInputChanged(new_federation_invite_code) => {
let Subroute::Add(Add {
federation_invite_code,
parsed_federation_invite_code_state_or,
}) = &mut self.subroute
else {
return Task::none();
};

*federation_invite_code = new_federation_invite_code;

if let Ok(invite_code) = InviteCode::from_str(federation_invite_code) {
*parsed_federation_invite_code_state_or =
Some(ParsedFederationInviteCodeState {
invite_code: invite_code.clone(),
loadable_federation_config: Loadable::Loading,
});

Task::perform(
async move {
match fedimint_api_client::download_from_invite_code(&invite_code).await
{
Ok(config) => {
app::Message::Routes(super::Message::BitcoinWalletPage(
Message::LoadedFederationConfigFromInviteCode {
config_invite_code: invite_code,
config,
},
))
}
// TODO: Include error in message and display it in the UI.
Err(_err) => {
app::Message::Routes(super::Message::BitcoinWalletPage(
Message::FailedToLoadFederationConfigFromInviteCode {
config_invite_code: invite_code,
},
))
}
}
},
|msg| msg,
)
} else {
*parsed_federation_invite_code_state_or = None;

Task::none()
}
}
Message::LoadedFederationConfigFromInviteCode {
config_invite_code,
config,
} => {
let Subroute::Add(Add {
parsed_federation_invite_code_state_or,
..
}) = &mut self.subroute
else {
return Task::none();
};

if let Some(ParsedFederationInviteCodeState {
invite_code,
loadable_federation_config: maybe_loading_federation_config,
}) = parsed_federation_invite_code_state_or
{
// If the invite code has changed since the request was made, ignore the response.
if &config_invite_code == invite_code {
*maybe_loading_federation_config = Loadable::Loaded(config);
}
}

Task::none()
}
Message::FailedToLoadFederationConfigFromInviteCode { config_invite_code } => {
let Subroute::Add(Add {
parsed_federation_invite_code_state_or,
..
}) = &mut self.subroute
else {
return Task::none();
};

if let Some(ParsedFederationInviteCodeState {
invite_code,
loadable_federation_config: maybe_loading_federation_config,
}) = parsed_federation_invite_code_state_or
{
// If the invite code has changed since the request was made, ignore the response.
// Also only update the state if the config hasn't already been loaded.
if &config_invite_code == invite_code
&& matches!(maybe_loading_federation_config, Loadable::Loading)
{
*maybe_loading_federation_config = Loadable::Failed;
}
}

Task::none()
}
Message::JoinFederation(invite_code) => {
let wallet = self.connected_state.wallet.clone();

Task::stream(async_stream::stream! {
match wallet.join_federation(invite_code.clone()).await {
Ok(()) => {
yield app::Message::AddToast(Toast {
title: "Joined federation".to_string(),
body: "You have successfully joined the federation.".to_string(),
status: ToastStatus::Good,
});

yield app::Message::Routes(super::Message::BitcoinWalletPage(
Message::JoinedFederation(invite_code)
));
}
Err(err) => {
yield app::Message::AddToast(Toast {
title: "Failed to join federation".to_string(),
body: format!("Failed to join the federation: {err}"),
status: ToastStatus::Bad,
});
}
}
})
}
Message::JoinedFederation(invite_code) => {
// A verbose way of saying "if the user is currently on the Add page and the invite code matches the one that was just joined, navigate back to the List page".
if let Subroute::Add(add) = &self.subroute {
if let Some(invite_code_state) = &add.parsed_federation_invite_code_state_or {
if invite_code_state.invite_code == invite_code {
return Task::done(app::Message::Routes(super::Message::Navigate(
RouteName::BitcoinWallet(SubrouteName::List),
)));
}
}
}

Task::none()
}
Message::LeaveFederation(federation_id) => {
let wallet = self.connected_state.wallet.clone();

Expand Down Expand Up @@ -237,6 +75,13 @@ impl Page {

Task::none()
}
Message::Add(add_message) => {
if let Subroute::Add(add_page) = &mut self.subroute {
add_page.update(add_message)
} else {
Task::none()
}
}
Message::Send(send_message) => {
if let Subroute::Send(send_page) = &mut self.subroute {
send_page.update(send_message)
Expand Down Expand Up @@ -292,10 +137,7 @@ impl SubrouteName {
view: federation_view.clone(),
})
}
Self::Add => Subroute::Add(Add {
federation_invite_code: String::new(),
parsed_federation_invite_code_state_or: None,
}),
Self::Add => Subroute::Add(add::Page::new(connected_state)),
Self::Send => Subroute::Send(send::Page::new(connected_state)),
Self::Receive => Subroute::Receive(receive::Page::new(connected_state)),
}
Expand All @@ -305,7 +147,7 @@ impl SubrouteName {
pub enum Subroute {
List(List),
FederationDetails(FederationDetails),
Add(Add),
Add(add::Page),
Send(send::Page),
Receive(receive::Page),
}
Expand Down Expand Up @@ -517,100 +359,3 @@ impl FederationDetails {
container
}
}

pub struct Add {
federation_invite_code: String,
parsed_federation_invite_code_state_or: Option<ParsedFederationInviteCodeState>,
}

pub struct ParsedFederationInviteCodeState {
invite_code: InviteCode,
loadable_federation_config: Loadable<ClientConfig>,
}

impl Add {
fn view<'a>(&self) -> Column<'a, app::Message> {
let mut container = container("Join Federation")
.push(
text_input("Federation Invite Code", &self.federation_invite_code)
.on_input(|input| {
app::Message::Routes(super::Message::BitcoinWalletPage(
Message::JoinFederationInviteCodeInputChanged(input),
))
})
.padding(10)
.size(30),
)
.push(
icon_button("Join Federation", SvgIcon::Groups, PaletteColor::Primary)
.on_press_maybe(self.parsed_federation_invite_code_state_or.as_ref().map(
|parsed_federation_invite_code_state| {
app::Message::Routes(super::Message::BitcoinWalletPage(
Message::JoinFederation(
parsed_federation_invite_code_state.invite_code.clone(),
),
))
},
)),
);

if let Some(parsed_federation_invite_code_state) =
&self.parsed_federation_invite_code_state_or
{
container = container
.push(Text::new("Federation ID").size(25))
.push(Text::new(truncate_text(
&parsed_federation_invite_code_state
.invite_code
.federation_id()
.to_string(),
21,
true,
)));

match &parsed_federation_invite_code_state.loadable_federation_config {
Loadable::Loading => {
container = container.push(Text::new("Loading..."));
}
Loadable::Loaded(client_config) => {
container = container
.push(Text::new("Federation Name").size(25))
.push(Text::new(
client_config
.meta::<String>(META_FEDERATION_NAME_KEY)
.ok()
.flatten()
.unwrap_or_default(),
))
.push(Text::new("Modules").size(25))
.push(Text::new(
client_config
.modules
.values()
.map(|module| module.kind().to_string())
.collect::<Vec<_>>()
.join(", "),
))
.push(Text::new("Guardians").size(25));
for peer_url in client_config.global.api_endpoints.values() {
container = container
.push(Text::new(format!("{} ({})", peer_url.name, peer_url.url)));
}
}
Loadable::Failed => {
container = container.push(Text::new("Failed to load client config"));
}
}
}

container = container.push(
icon_button("Back", SvgIcon::ArrowBack, PaletteColor::Background).on_press(
app::Message::Routes(super::Message::Navigate(RouteName::BitcoinWallet(
SubrouteName::List,
))),
),
);

container
}
}
Loading

0 comments on commit 149a9cd

Please sign in to comment.