gui: add redirection to selected transaction panel
This commit is contained in:
parent
505b218618
commit
0c1a1b8d6d
@ -5,6 +5,7 @@ pub enum Menu {
|
||||
Receive,
|
||||
PSBTs,
|
||||
Transactions,
|
||||
TransactionPreSelected(Txid),
|
||||
Settings,
|
||||
Coins,
|
||||
CreateSpendTx,
|
||||
|
||||
@ -84,6 +84,7 @@ impl Panels {
|
||||
Menu::Receive => &self.receive,
|
||||
Menu::PSBTs => &self.psbts,
|
||||
Menu::Transactions => &self.transactions,
|
||||
Menu::TransactionPreSelected(_) => &self.transactions,
|
||||
Menu::Settings => &self.settings,
|
||||
Menu::Coins => &self.coins,
|
||||
Menu::CreateSpendTx => &self.create_spend,
|
||||
@ -99,6 +100,7 @@ impl Panels {
|
||||
Menu::Receive => &mut self.receive,
|
||||
Menu::PSBTs => &mut self.psbts,
|
||||
Menu::Transactions => &mut self.transactions,
|
||||
Menu::TransactionPreSelected(_) => &mut self.transactions,
|
||||
Menu::Settings => &mut self.settings,
|
||||
Menu::Coins => &mut self.coins,
|
||||
Menu::CreateSpendTx => &mut self.create_spend,
|
||||
@ -152,6 +154,17 @@ impl App {
|
||||
|
||||
fn set_current_panel(&mut self, menu: Menu) -> Command<Message> {
|
||||
match &menu {
|
||||
menu::Menu::TransactionPreSelected(txid) => {
|
||||
if let Ok(Some(tx)) = self
|
||||
.daemon
|
||||
.get_history_txs(&[*txid])
|
||||
.map(|txs| txs.first().cloned())
|
||||
{
|
||||
self.panels.transactions.preselect(tx);
|
||||
self.panels.current = menu;
|
||||
return Command::none();
|
||||
};
|
||||
}
|
||||
menu::Menu::PsbtPreSelected(txid) => {
|
||||
// Get preselected spend from DB in case it's not yet in the cache.
|
||||
// We only need this single spend as we will go straight to its view and not show the PSBTs list.
|
||||
|
||||
@ -36,7 +36,7 @@ pub struct TransactionsPanel {
|
||||
pending_txs: Vec<HistoryTransaction>,
|
||||
txs: Vec<HistoryTransaction>,
|
||||
labels_edited: LabelsEdited,
|
||||
selected_tx: Option<usize>,
|
||||
selected_tx: Option<HistoryTransaction>,
|
||||
warning: Option<Error>,
|
||||
create_rbf_modal: Option<CreateRbfModal>,
|
||||
}
|
||||
@ -52,16 +52,17 @@ impl TransactionsPanel {
|
||||
create_rbf_modal: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preselect(&mut self, tx: HistoryTransaction) {
|
||||
self.selected_tx = Some(tx);
|
||||
self.warning = None;
|
||||
self.create_rbf_modal = None;
|
||||
}
|
||||
}
|
||||
|
||||
impl State for TransactionsPanel {
|
||||
fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> {
|
||||
if let Some(i) = self.selected_tx {
|
||||
let tx = if i < self.pending_txs.len() {
|
||||
&self.pending_txs[i]
|
||||
} else {
|
||||
&self.txs[i - self.pending_txs.len()]
|
||||
};
|
||||
if let Some(tx) = self.selected_tx.as_ref() {
|
||||
let content = view::transactions::tx_view(
|
||||
cache,
|
||||
tx,
|
||||
@ -121,40 +122,42 @@ impl State for TransactionsPanel {
|
||||
return self.reload(daemon);
|
||||
}
|
||||
Message::View(view::Message::Select(i)) => {
|
||||
self.selected_tx = Some(i);
|
||||
self.selected_tx = if i < self.pending_txs.len() {
|
||||
self.pending_txs.get(i).cloned()
|
||||
} else {
|
||||
self.txs.get(i - self.pending_txs.len()).cloned()
|
||||
};
|
||||
}
|
||||
Message::View(view::Message::CreateRbf(view::CreateRbfMessage::Cancel)) => {
|
||||
self.create_rbf_modal = None;
|
||||
}
|
||||
Message::View(view::Message::CreateRbf(view::CreateRbfMessage::New(is_cancel))) => {
|
||||
if let Some(idx) = self.selected_tx {
|
||||
if let Some(tx) = self.pending_txs.get(idx) {
|
||||
if tx.fee_amount.is_some() {
|
||||
let tx = tx.clone();
|
||||
let txid = tx.tx.txid();
|
||||
return Command::perform(
|
||||
async move {
|
||||
daemon
|
||||
// TODO: filter for spending coins when this is possible:
|
||||
// https://github.com/wizardsardine/liana/issues/677
|
||||
.list_coins()
|
||||
.map(|res| {
|
||||
res.coins
|
||||
.iter()
|
||||
.filter_map(|c| {
|
||||
if c.outpoint.txid == txid {
|
||||
c.spend_info.map(|info| info.txid)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.map_err(|e| e.into())
|
||||
},
|
||||
move |res| Message::RbfModal(tx, is_cancel, res),
|
||||
);
|
||||
}
|
||||
if let Some(tx) = &self.selected_tx {
|
||||
if tx.fee_amount.is_some() {
|
||||
let tx = tx.clone();
|
||||
let txid = tx.tx.txid();
|
||||
return Command::perform(
|
||||
async move {
|
||||
daemon
|
||||
// TODO: filter for spending coins when this is possible:
|
||||
// https://github.com/wizardsardine/liana/issues/677
|
||||
.list_coins()
|
||||
.map(|res| {
|
||||
res.coins
|
||||
.iter()
|
||||
.filter_map(|c| {
|
||||
if c.outpoint.txid == txid {
|
||||
c.spend_info.map(|info| info.txid)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.map_err(|e| e.into())
|
||||
},
|
||||
move |res| Message::RbfModal(tx, is_cancel, res),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,31 +315,8 @@ pub fn payment_view<'a>(
|
||||
.spacing(5),
|
||||
))
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
// We do not need to display inputs for external incoming transactions
|
||||
.push_maybe(if tx.is_external() {
|
||||
None
|
||||
} else {
|
||||
Some(super::psbt::inputs_view(
|
||||
&tx.coins,
|
||||
&tx.tx,
|
||||
&tx.labels,
|
||||
labels_editing,
|
||||
))
|
||||
})
|
||||
.push(super::psbt::outputs_view(
|
||||
&tx.tx,
|
||||
cache.network,
|
||||
if tx.is_external() {
|
||||
None
|
||||
} else {
|
||||
Some(tx.change_indexes.clone())
|
||||
},
|
||||
&tx.labels,
|
||||
labels_editing,
|
||||
tx.is_single_payment().is_some(),
|
||||
)),
|
||||
button::primary(None, "See transaction details")
|
||||
.on_press(Message::Menu(Menu::TransactionPreSelected(tx.tx.txid()))),
|
||||
)
|
||||
.spacing(20),
|
||||
)
|
||||
|
||||
@ -184,6 +184,44 @@ pub trait Daemon: Debug {
|
||||
Ok(txs)
|
||||
}
|
||||
|
||||
fn get_history_txs(
|
||||
&self,
|
||||
txids: &[Txid],
|
||||
) -> Result<Vec<model::HistoryTransaction>, DaemonError> {
|
||||
let info = self.get_info()?;
|
||||
let coins = self.list_coins()?.coins;
|
||||
let txs = self.list_txs(txids)?.transactions;
|
||||
let mut txs = txs
|
||||
.into_iter()
|
||||
.map(|tx| {
|
||||
let mut tx_coins = Vec::new();
|
||||
let mut change_indexes = Vec::new();
|
||||
for coin in &coins {
|
||||
if coin.outpoint.txid == tx.tx.txid() {
|
||||
change_indexes.push(coin.outpoint.vout as usize)
|
||||
} else if tx
|
||||
.tx
|
||||
.input
|
||||
.iter()
|
||||
.any(|input| input.previous_output == coin.outpoint)
|
||||
{
|
||||
tx_coins.push(coin.clone());
|
||||
}
|
||||
}
|
||||
model::HistoryTransaction::new(
|
||||
tx.tx,
|
||||
tx.height,
|
||||
tx.time,
|
||||
tx_coins,
|
||||
change_indexes,
|
||||
info.network,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
load_labels(self, &mut txs)?;
|
||||
Ok(txs)
|
||||
}
|
||||
|
||||
fn list_pending_txs(&self) -> Result<Vec<model::HistoryTransaction>, DaemonError> {
|
||||
let info = self.get_info()?;
|
||||
let coins = self.list_coins()?.coins;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user