Merge #1359: fix history events and txs pagination

0219752f784db12fa7a92231e596b7f264df8523 Add processing state to next page load (edouardparis)
1a370d380655b0cf852f2a51688cd15a327e1d7e fix history events and txs pagination (edouardparis)

Pull request description:

  The problem:
  We display the button if the size of the list is a multiple of the page size. Otherwise, we assume that the user has reached a partial page, indicating they've reached the bottom. However, since we chose to include all transactions with the same block time on a single page (because it's not possible to order them by block index in the database, as we don't store the block index), this can cause the page size to exceed the set limit. As a result, the list size may not be a multiple of the page size.

  The solution:
  keep in the state if the last fetched page has a length inferior of the expected page size and do not display the button 'See more' then as we reached the bottom.

ACKs for top commit:
  jp1ac4:
    Tested ACK 0219752f78.

Tree-SHA512: acba63aaa269e1c974ca3b6ffc7e5f7545d273b6cea8cea4f380c76a3aa569eaa5ac7b413525e613e1fbb55b7076b0b541bc72f802b5c619eeef3244f3366b52
This commit is contained in:
edouardparis 2024-09-24 12:32:17 +02:00
commit 1374f53483
No known key found for this signature in database
GPG Key ID: E65F7A089C20DC8F
4 changed files with 90 additions and 45 deletions

View File

@ -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<OutPoint>,
pending_events: Vec<HistoryTransaction>,
events: Vec<HistoryTransaction>,
is_last_page: bool,
processing: bool,
selected_event: Option<(usize, usize)>,
labels_edited: LabelsEdited,
warning: Option<Error>,
@ -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())
},

View File

@ -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<HistoryTransaction>,
warning: Option<Error>,
create_rbf_modal: Option<CreateRbfModal>,
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())
},

View File

@ -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()

View File

@ -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),