diff --git a/gui/src/app/state/mod.rs b/gui/src/app/state/mod.rs index a7a9c4d1..ca70cf82 100644 --- a/gui/src/app/state/mod.rs +++ b/gui/src/app/state/mod.rs @@ -21,6 +21,8 @@ use liana_ui::widget::*; use super::{cache::Cache, error::Error, menu::Menu, message::Message, view, wallet::Wallet}; +pub const HISTORY_EVENT_PAGE_SIZE: u64 = 20; + use crate::daemon::{ model::{remaining_sequence, Coin, HistoryTransaction, Labelled}, Daemon, @@ -72,6 +74,8 @@ pub struct Home { expiring_coins: Vec, pending_events: Vec, events: Vec, + is_last_page: bool, + processing: bool, selected_event: Option<(usize, usize)>, labels_edited: LabelsEdited, warning: Option, @@ -102,6 +106,8 @@ impl Home { pending_events: Vec::new(), labels_edited: LabelsEdited::default(), warning: None, + is_last_page: false, + processing: false, } } } @@ -133,6 +139,8 @@ impl State for Home { &self.expiring_coins, &self.pending_events, &self.events, + self.is_last_page, + self.processing, ), ) } @@ -185,12 +193,15 @@ impl State for Home { self.warning = None; self.events = events; self.events.sort_by(|a, b| b.time.cmp(&a.time)); + self.is_last_page = (self.events.len() as u64) < HISTORY_EVENT_PAGE_SIZE; } }, Message::HistoryTransactionsExtension(res) => match res { Err(e) => self.warning = Some(e), Ok(events) => { + self.processing = false; self.warning = None; + self.is_last_page = (events.len() as u64) < HISTORY_EVENT_PAGE_SIZE; for event in events { if !self.events.iter().any(|other| other.tx == event.tx) { self.events.push(event); @@ -236,9 +247,10 @@ impl State for Home { if let Some(last) = self.events.last() { let daemon = daemon.clone(); let last_event_date = last.time.unwrap(); + self.processing = true; return Command::perform( async move { - let mut limit = view::home::HISTORY_EVENT_PAGE_SIZE; + let mut limit = HISTORY_EVENT_PAGE_SIZE; let mut events = daemon .list_history_txs(0_u32, last_event_date, limit) .await?; @@ -262,7 +274,7 @@ impl State for Home { && events.len() as u64 == limit { // increments of the equivalent of one page more. - limit += view::home::HISTORY_EVENT_PAGE_SIZE; + limit += HISTORY_EVENT_PAGE_SIZE; events = daemon.list_history_txs(0, last_event_date, limit).await?; } Ok(events) @@ -300,7 +312,7 @@ impl State for Home { Command::perform( async move { daemon1 - .list_history_txs(0, now, view::home::HISTORY_EVENT_PAGE_SIZE) + .list_history_txs(0, now, HISTORY_EVENT_PAGE_SIZE) .await .map_err(|e| e.into()) }, diff --git a/gui/src/app/state/transactions.rs b/gui/src/app/state/transactions.rs index aa1a62d2..e0e15e6f 100644 --- a/gui/src/app/state/transactions.rs +++ b/gui/src/app/state/transactions.rs @@ -16,6 +16,8 @@ use liana_ui::{ widget::*, }; +pub const HISTORY_EVENT_PAGE_SIZE: u64 = 20; + use crate::{ app::{ cache::Cache, @@ -41,6 +43,8 @@ pub struct TransactionsPanel { selected_tx: Option, warning: Option, create_rbf_modal: Option, + is_last_page: bool, + processing: bool, } impl TransactionsPanel { @@ -53,6 +57,8 @@ impl TransactionsPanel { labels_edited: LabelsEdited::default(), warning: None, create_rbf_modal: None, + is_last_page: false, + processing: false, } } @@ -83,6 +89,8 @@ impl State for TransactionsPanel { &self.pending_txs, &self.txs, self.warning.as_ref(), + self.is_last_page, + self.processing, ) } } @@ -98,6 +106,17 @@ impl State for TransactionsPanel { Err(e) => self.warning = Some(e), Ok(txs) => { self.warning = None; + self.txs = txs; + self.is_last_page = (self.txs.len() as u64) < HISTORY_EVENT_PAGE_SIZE; + self.txs.sort_by(|a, b| b.time.cmp(&a.time)); + } + }, + Message::HistoryTransactionsExtension(res) => match res { + Err(e) => self.warning = Some(e), + Ok(txs) => { + self.processing = false; + self.warning = None; + self.is_last_page = (txs.len() as u64) < HISTORY_EVENT_PAGE_SIZE; for tx in txs { if let Some(t) = self.txs.iter_mut().find(|other| other.tx == tx.tx) { t.labels = tx.labels; @@ -202,9 +221,10 @@ impl State for TransactionsPanel { if let Some(last) = self.txs.last() { let daemon = daemon.clone(); let last_tx_date = last.time.unwrap(); + self.processing = true; return Command::perform( async move { - let mut limit = view::home::HISTORY_EVENT_PAGE_SIZE; + let mut limit = HISTORY_EVENT_PAGE_SIZE; let mut txs = daemon.list_history_txs(0_u32, last_tx_date, limit).await?; @@ -227,12 +247,12 @@ impl State for TransactionsPanel { && txs.len() as u64 == limit { // increments of the equivalent of one page more. - limit += view::home::HISTORY_EVENT_PAGE_SIZE; + limit += HISTORY_EVENT_PAGE_SIZE; txs = daemon.list_history_txs(0, last_tx_date, limit).await?; } Ok(txs) }, - Message::HistoryTransactions, + Message::HistoryTransactionsExtension, ); } } @@ -267,7 +287,7 @@ impl State for TransactionsPanel { Command::perform( async move { daemon1 - .list_history_txs(0, now, view::home::HISTORY_EVENT_PAGE_SIZE) + .list_history_txs(0, now, HISTORY_EVENT_PAGE_SIZE) .await .map_err(|e| e.into()) }, diff --git a/gui/src/app/view/home.rs b/gui/src/app/view/home.rs index 7adc4f90..eedc70d6 100644 --- a/gui/src/app/view/home.rs +++ b/gui/src/app/view/home.rs @@ -21,8 +21,7 @@ use crate::{ daemon::model::{HistoryTransaction, TransactionKind}, }; -pub const HISTORY_EVENT_PAGE_SIZE: u64 = 20; - +#[allow(clippy::too_many_arguments)] pub fn home_view<'a>( balance: &'a bitcoin::Amount, unconfirmed_balance: &'a bitcoin::Amount, @@ -30,6 +29,8 @@ pub fn home_view<'a>( expiring_coins: &[bitcoin::OutPoint], pending_events: &'a [HistoryTransaction], events: &'a [HistoryTransaction], + is_last_page: bool, + processing: bool, ) -> Element<'a, Message> { Column::new() .push(h3("Balance")) @@ -119,27 +120,33 @@ pub fn home_view<'a>( } }, )) - .push_maybe( - if events.len() % HISTORY_EVENT_PAGE_SIZE as usize == 0 && !events.is_empty() { - Some( - Container::new( - Button::new( - text("See more") - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), - ) + .push_maybe(if !is_last_page && !events.is_empty() { + Some( + Container::new( + Button::new( + text(if processing { + "Fetching ..." + } else { + "See more" + }) .width(Length::Fill) - .padding(15) - .style(theme::Button::TransparentBorder) - .on_press(Message::Next), + .horizontal_alignment(alignment::Horizontal::Center), ) .width(Length::Fill) - .style(theme::Container::Card(theme::Card::Simple)), + .padding(15) + .style(theme::Button::TransparentBorder) + .on_press_maybe(if !processing { + Some(Message::Next) + } else { + None + }), ) - } else { - None - }, - ), + .width(Length::Fill) + .style(theme::Container::Card(theme::Card::Simple)), + ) + } else { + None + }), ) .spacing(20) .into() diff --git a/gui/src/app/view/transactions.rs b/gui/src/app/view/transactions.rs index f1e1437d..0b2a5d12 100644 --- a/gui/src/app/view/transactions.rs +++ b/gui/src/app/view/transactions.rs @@ -20,13 +20,13 @@ use crate::{ daemon::model::{HistoryTransaction, Txid}, }; -pub const HISTORY_EVENT_PAGE_SIZE: u64 = 20; - pub fn transactions_view<'a>( cache: &'a Cache, pending_txs: &'a [HistoryTransaction], txs: &'a [HistoryTransaction], warning: Option<&'a Error>, + is_last_page: bool, + processing: bool, ) -> Element<'a, Message> { dashboard( &Menu::Transactions, @@ -56,27 +56,33 @@ pub fn transactions_view<'a>( col.push(tx_list_view(i + pending_txs.len(), tx)) }), ) - .push_maybe( - if txs.len() % HISTORY_EVENT_PAGE_SIZE as usize == 0 && !txs.is_empty() { - Some( - Container::new( - Button::new( - text("See more") - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), - ) + .push_maybe(if !is_last_page && !txs.is_empty() { + Some( + Container::new( + Button::new( + text(if processing { + "Fetching ..." + } else { + "See more" + }) .width(Length::Fill) - .padding(15) - .style(theme::Button::TransparentBorder) - .on_press(Message::Next), + .horizontal_alignment(alignment::Horizontal::Center), ) .width(Length::Fill) - .style(theme::Container::Card(theme::Card::Simple)), + .padding(15) + .style(theme::Button::TransparentBorder) + .on_press_maybe(if !processing { + Some(Message::Next) + } else { + None + }), ) - } else { - None - }, - ), + .width(Length::Fill) + .style(theme::Container::Card(theme::Card::Simple)), + ) + } else { + None + }), ) .align_items(Alignment::Center) .spacing(30),