Merge pull request #397

ad5115a Add estimated time countdown for locked balance (Jaquee)
205bfcd History: Show num of confirmations + unconfirmed payments (Jaquee)
This commit is contained in:
Riccardo Spagni 2017-01-14 10:40:22 -05:00
commit a1c5e7fed2
No known key found for this signature in database
GPG Key ID: 55432DF31CCD4FCD
12 changed files with 88 additions and 11 deletions

View File

@ -39,6 +39,7 @@ Rectangle {
property alias balanceText: balanceText.text property alias balanceText: balanceText.text
property alias networkStatus : networkStatus property alias networkStatus : networkStatus
property alias progressBar : progressBar property alias progressBar : progressBar
property alias minutesToUnlockTxt: unlockedBalanceLabel.text
signal dashboardClicked() signal dashboardClicked()
signal historyClicked() signal historyClicked()
@ -154,7 +155,8 @@ Rectangle {
} }
Label { Label {
text: qsTr("Unlocked balance") + translationManager.emptyString id: unlockedBalanceLabel
text: qsTr("Unlocked balance")
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 50 anchors.leftMargin: 50
tipText: qsTr("Test tip 2<br/><br/>line 2") + translationManager.emptyString tipText: qsTr("Test tip 2<br/><br/>line 2") + translationManager.emptyString

View File

@ -263,9 +263,18 @@ ListView {
//elide: Text.ElideRight //elide: Text.ElideRight
font.family: "Arial" font.family: "Arial"
font.pixelSize: 13 font.pixelSize: 13
font.letterSpacing: -1 color: (confirmations < 10)? "#FF6C3C" : "#545454"
color: "#545454" text: {
text: (typeof blockHeight != "undefined")? blockHeight : qsTr("Pending") + translationManager.emptyString if (!isPending)
if(confirmations < 10)
return blockHeight + " " + qsTr("(%1/10 confirmations)").arg(confirmations)
else
return blockHeight
if (!isOut)
return qsTr("UNCONFIRMED") + translationManager.emptyString
return qsTr("PENDING") + translationManager.emptyString
}
} }
} }

View File

@ -61,6 +61,10 @@ ApplicationWindow {
property int maxWindowHeight: (Screen.height < 900)? 720 : 800; property int maxWindowHeight: (Screen.height < 900)? 720 : 800;
property bool daemonRunning: false property bool daemonRunning: false
property alias toolTip: toolTip property alias toolTip: toolTip
property string walletName
property bool viewOnly: false
property bool foundNewBlock: false
property int timeToUnlock: 0
// true if wallet ever synchronized // true if wallet ever synchronized
property bool walletInitialized : false property bool walletInitialized : false
@ -208,6 +212,7 @@ ApplicationWindow {
currentWallet.newBlock.disconnect(onWalletNewBlock) currentWallet.newBlock.disconnect(onWalletNewBlock)
currentWallet.moneySpent.disconnect(onWalletMoneySent) currentWallet.moneySpent.disconnect(onWalletMoneySent)
currentWallet.moneyReceived.disconnect(onWalletMoneyReceived) currentWallet.moneyReceived.disconnect(onWalletMoneyReceived)
currentWallet.unconfirmedMoneyReceived.disconnect(onWalletUnconfirmedMoneyReceived)
currentWallet.transactionCreated.disconnect(onTransactionCreated) currentWallet.transactionCreated.disconnect(onTransactionCreated)
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged) currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
middlePanel.paymentClicked.disconnect(handlePayment); middlePanel.paymentClicked.disconnect(handlePayment);
@ -229,6 +234,7 @@ ApplicationWindow {
currentWallet.newBlock.connect(onWalletNewBlock) currentWallet.newBlock.connect(onWalletNewBlock)
currentWallet.moneySpent.connect(onWalletMoneySent) currentWallet.moneySpent.connect(onWalletMoneySent)
currentWallet.moneyReceived.connect(onWalletMoneyReceived) currentWallet.moneyReceived.connect(onWalletMoneyReceived)
currentWallet.unconfirmedMoneyReceived.connect(onWalletUnconfirmedMoneyReceived)
currentWallet.transactionCreated.connect(onTransactionCreated) currentWallet.transactionCreated.connect(onTransactionCreated)
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged) currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
middlePanel.paymentClicked.connect(handlePayment); middlePanel.paymentClicked.connect(handlePayment);
@ -291,6 +297,15 @@ ApplicationWindow {
console.log(">>> wallet updated") console.log(">>> wallet updated")
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(currentWallet.unlockedBalance); middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(currentWallet.unlockedBalance);
middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance); middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance);
console.log("time to unlock: ", currentWallet.history.minutesToUnlock);
// Update history if new block found since last update and balance is locked.
if(foundNewBlock && currentWallet.history.locked) {
foundNewBlock = false;
console.log("New block found - updating history")
currentWallet.history.refresh()
timeToUnlock = currentWallet.history.minutesToUnlock
leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance");
}
} }
function onWalletRefresh() { function onWalletRefresh() {
@ -335,13 +350,11 @@ ApplicationWindow {
} }
} }
// initialize transaction history once wallet is initializef first time; // initialize transaction history once wallet is initializef first time;
if (!walletInitialized) { if (!walletInitialized) {
currentWallet.history.refresh() currentWallet.history.refresh()
walletInitialized = true walletInitialized = true
} }
onWalletUpdate(); onWalletUpdate();
} }
@ -368,7 +381,6 @@ ApplicationWindow {
function onWalletNewBlock(blockHeight) { function onWalletNewBlock(blockHeight) {
// Update progress bar // Update progress bar
var currHeight = blockHeight var currHeight = blockHeight
//fast refresh until restoreHeight is reached //fast refresh until restoreHeight is reached
@ -378,6 +390,7 @@ ApplicationWindow {
splashCounter = currHeight splashCounter = currHeight
leftPanel.progressBar.updateProgress(currHeight,currentWallet.daemonBlockChainTargetHeight()); leftPanel.progressBar.updateProgress(currHeight,currentWallet.daemonBlockChainTargetHeight());
} }
foundNewBlock = true;
} }
function onWalletMoneyReceived(txId, amount) { function onWalletMoneyReceived(txId, amount) {
@ -386,6 +399,12 @@ ApplicationWindow {
currentWallet.history.refresh() // this will refresh model currentWallet.history.refresh() // this will refresh model
} }
function onWalletUnconfirmedMoneyReceived(txId, amount) {
// refresh history
console.log("unconfirmed money found")
currentWallet.history.refresh()
}
function onWalletMoneySent(txId, amount) { function onWalletMoneySent(txId, amount) {
// refresh transaction history here // refresh transaction history here
currentWallet.refresh() currentWallet.refresh()

View File

@ -138,7 +138,7 @@ Rectangle {
if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address) if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address)
informationPopup.text = qsTr("Invalid address") informationPopup.text = qsTr("Invalid address")
else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id) else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id)
informationPopup.text = qsTr("Invalid Payment ID") informationPopup.text = currentWallet.addressBook.errorString()
else else
informationPopup.text = qsTr("Can't create entry") informationPopup.text = qsTr("Can't create entry")

View File

@ -31,7 +31,9 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
QDateTime firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block QDateTime firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones) QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
quint64 lastTxHeight = 0;
m_locked = false;
m_minutesToUnlock = 0;
TransactionHistory * parent = const_cast<TransactionHistory*>(this); TransactionHistory * parent = const_cast<TransactionHistory*>(this);
for (const auto i : m_pimpl->getAll()) { for (const auto i : m_pimpl->getAll()) {
TransactionInfo * ti = new TransactionInfo(i, parent); TransactionInfo * ti = new TransactionInfo(i, parent);
@ -43,6 +45,14 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
if (ti->timestamp() <= firstDateTime) { if (ti->timestamp() <= firstDateTime) {
firstDateTime = ti->timestamp(); firstDateTime = ti->timestamp();
} }
// store last tx height
if (ti->confirmations() < 10 && ti->blockHeight() >= lastTxHeight ){
lastTxHeight = ti->blockHeight();
// TODO: Fetch block time and confirmations needed from wallet2?
m_minutesToUnlock = (10 - ti->confirmations()) * 2;
m_locked = true;
}
} }
emit refreshFinished(); emit refreshFinished();
@ -81,9 +91,19 @@ QDateTime TransactionHistory::lastDateTime() const
return m_lastDateTime; return m_lastDateTime;
} }
quint64 TransactionHistory::minutesToUnlock() const
{
return m_minutesToUnlock;
}
bool TransactionHistory::TransactionHistory::locked() const
{
return m_locked;
}
TransactionHistory::TransactionHistory(Monero::TransactionHistory *pimpl, QObject *parent) TransactionHistory::TransactionHistory(Monero::TransactionHistory *pimpl, QObject *parent)
: QObject(parent), m_pimpl(pimpl) : QObject(parent), m_pimpl(pimpl), m_minutesToUnlock(0), m_locked(false)
{ {
m_firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block m_firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
m_lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones) m_lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)

View File

@ -17,6 +17,8 @@ class TransactionHistory : public QObject
Q_PROPERTY(int count READ count) Q_PROPERTY(int count READ count)
Q_PROPERTY(QDateTime firstDateTime READ firstDateTime NOTIFY firstDateTimeChanged) Q_PROPERTY(QDateTime firstDateTime READ firstDateTime NOTIFY firstDateTimeChanged)
Q_PROPERTY(QDateTime lastDateTime READ lastDateTime NOTIFY lastDateTimeChanged) Q_PROPERTY(QDateTime lastDateTime READ lastDateTime NOTIFY lastDateTimeChanged)
Q_PROPERTY(int minutesToUnlock READ minutesToUnlock)
Q_PROPERTY(bool locked READ locked)
public: public:
Q_INVOKABLE TransactionInfo *transaction(int index); Q_INVOKABLE TransactionInfo *transaction(int index);
@ -26,6 +28,8 @@ public:
quint64 count() const; quint64 count() const;
QDateTime firstDateTime() const; QDateTime firstDateTime() const;
QDateTime lastDateTime() const; QDateTime lastDateTime() const;
quint64 minutesToUnlock() const;
bool locked() const;
signals: signals:
void refreshStarted() const; void refreshStarted() const;
@ -45,6 +49,9 @@ private:
mutable QList<TransactionInfo*> m_tinfo; mutable QList<TransactionInfo*> m_tinfo;
mutable QDateTime m_firstDateTime; mutable QDateTime m_firstDateTime;
mutable QDateTime m_lastDateTime; mutable QDateTime m_lastDateTime;
mutable int m_minutesToUnlock;
// history contains locked transfers
mutable bool m_locked;
}; };

View File

@ -46,6 +46,11 @@ quint64 TransactionInfo::blockHeight() const
return m_pimpl->blockHeight(); return m_pimpl->blockHeight();
} }
quint64 TransactionInfo::confirmations() const
{
return m_pimpl->confirmations();
}
QString TransactionInfo::hash() const QString TransactionInfo::hash() const
{ {
return QString::fromStdString(m_pimpl->hash()); return QString::fromStdString(m_pimpl->hash());

View File

@ -18,6 +18,7 @@ class TransactionInfo : public QObject
Q_PROPERTY(QString displayAmount READ displayAmount) Q_PROPERTY(QString displayAmount READ displayAmount)
Q_PROPERTY(QString fee READ fee) Q_PROPERTY(QString fee READ fee)
Q_PROPERTY(quint64 blockHeight READ blockHeight) Q_PROPERTY(quint64 blockHeight READ blockHeight)
Q_PROPERTY(quint64 confirmations READ confirmations)
Q_PROPERTY(QString hash READ hash) Q_PROPERTY(QString hash READ hash)
Q_PROPERTY(QDateTime timestamp READ timestamp) Q_PROPERTY(QDateTime timestamp READ timestamp)
Q_PROPERTY(QString date READ date) Q_PROPERTY(QString date READ date)
@ -42,6 +43,7 @@ public:
QString displayAmount() const; QString displayAmount() const;
QString fee() const; QString fee() const;
quint64 blockHeight() const; quint64 blockHeight() const;
quint64 confirmations() const;
//! transaction_id //! transaction_id
QString hash() const; QString hash() const;
QDateTime timestamp() const; QDateTime timestamp() const;

View File

@ -44,6 +44,12 @@ public:
emit m_wallet->moneyReceived(QString::fromStdString(txId), amount); emit m_wallet->moneyReceived(QString::fromStdString(txId), amount);
} }
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
{
qDebug() << __FUNCTION__;
emit m_wallet->unconfirmedMoneyReceived(QString::fromStdString(txId), amount);
}
virtual void newBlock(uint64_t height) virtual void newBlock(uint64_t height)
{ {
// qDebug() << __FUNCTION__; // qDebug() << __FUNCTION__;

View File

@ -206,6 +206,7 @@ signals:
void moneySpent(const QString &txId, quint64 amount); void moneySpent(const QString &txId, quint64 amount);
void moneyReceived(const QString &txId, quint64 amount); void moneyReceived(const QString &txId, quint64 amount);
void unconfirmedMoneyReceived(const QString &txId, quint64 amount);
void newBlock(quint64 height); void newBlock(quint64 height);
void historyModelChanged() const; void historyModelChanged() const;

View File

@ -81,6 +81,10 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
result = tInfo->blockHeight(); result = tInfo->blockHeight();
} }
break; break;
case TransactionConfirmationsRole:
result = tInfo->confirmations();
break;
case TransactionHashRole: case TransactionHashRole:
result = tInfo->hash(); result = tInfo->hash();
break; break;
@ -125,6 +129,7 @@ QHash<int, QByteArray> TransactionHistoryModel::roleNames() const
roleNames.insert(TransactionAtomicAmountRole, "atomicAmount"); roleNames.insert(TransactionAtomicAmountRole, "atomicAmount");
roleNames.insert(TransactionFeeRole, "fee"); roleNames.insert(TransactionFeeRole, "fee");
roleNames.insert(TransactionBlockHeightRole, "blockHeight"); roleNames.insert(TransactionBlockHeightRole, "blockHeight");
roleNames.insert(TransactionConfirmationsRole, "confirmations");
roleNames.insert(TransactionHashRole, "hash"); roleNames.insert(TransactionHashRole, "hash");
roleNames.insert(TransactionTimeStampRole, "timeStamp"); roleNames.insert(TransactionTimeStampRole, "timeStamp");
roleNames.insert(TransactionPaymentIdRole, "paymentId"); roleNames.insert(TransactionPaymentIdRole, "paymentId");

View File

@ -25,6 +25,7 @@ public:
TransactionDisplayAmountRole, TransactionDisplayAmountRole,
TransactionFeeRole, TransactionFeeRole,
TransactionBlockHeightRole, TransactionBlockHeightRole,
TransactionConfirmationsRole,
TransactionHashRole, TransactionHashRole,
TransactionTimeStampRole, TransactionTimeStampRole,
TransactionPaymentIdRole, TransactionPaymentIdRole,