History: display details of transactions with multiple recipients

This commit is contained in:
rating89us 2021-06-03 19:06:12 +02:00 committed by rating89us
parent 2946127ed7
commit 7b2c886ddc
4 changed files with 209 additions and 67 deletions

View file

@ -16,6 +16,7 @@ Text {
property alias tooltipLeft: tooltip.tooltipLeft property alias tooltipLeft: tooltip.tooltipLeft
property alias tooltipIconVisible: tooltip.tooltipIconVisible property alias tooltipIconVisible: tooltip.tooltipIconVisible
property alias tooltipPopup: tooltip.tooltipPopup property alias tooltipPopup: tooltip.tooltipPopup
property alias tooltipWrapMode: tooltip.tooltipWrapMode
font.family: MoneroComponents.Style.fontMedium.name font.family: MoneroComponents.Style.fontMedium.name
font.bold: false font.bold: false
font.pixelSize: 14 font.pixelSize: 14

View file

@ -36,6 +36,7 @@ import "." as MoneroComponents
Rectangle { Rectangle {
property alias text: tooltip.text property alias text: tooltip.text
property alias tooltipPopup: popup property alias tooltipPopup: popup
property alias tooltipWrapMode: tooltip.wrapMode
property bool tooltipIconVisible: false property bool tooltipIconVisible: false
property bool tooltipLeft: false property bool tooltipLeft: false
property bool tooltipBottom: tooltipIconVisible ? false : true property bool tooltipBottom: tooltipIconVisible ? false : true

View file

@ -2,13 +2,33 @@ function destinationsToAmount(destinations){
// Gets amount from destinations line // Gets amount from destinations line
// input: "20.000000000000: 9tLGyK277MnYrDc7Vzi6TB1pJvstFoviziFwsqQNFbwA9rvg5RxYVYjEezFKDjvDHgAzTELJhJHVx6JAaWZKeVqSUZkXeKk" // input: "20.000000000000: 9tLGyK277MnYrDc7Vzi6TB1pJvstFoviziFwsqQNFbwA9rvg5RxYVYjEezFKDjvDHgAzTELJhJHVx6JAaWZKeVqSUZkXeKk"
// returns: 20.000000000000 // returns: 20.000000000000
return destinations.split(" ")[0].split(":")[0]; var numberOfDestinations = (destinations.match(/:/g) || []).length;
var amountList = "";
for (var i = 0; i < numberOfDestinations; i++) {
var destinationAndAmount = destinations.split("<br> ")[i];
var amount = destinationAndAmount.split(":")[0];
if (i+1 != numberOfDestinations) {
amountList += amount + " ";
} else {
amountList += amount;
}
}
return amountList;
} }
function destinationsToAddress(destinations){ function destinationsToAddress(destinations){
var address = destinations.split(" ")[1]; var numberOfDestinations = (destinations.match(/:/g) || []).length;
if(address === undefined) return "" var addressList = "";
return address; for (var i = 0; i < numberOfDestinations; i++) {
var destinationAndAmount = destinations.split("<br> ")[i];
var address = destinationAndAmount.split(": ")[1];
if (i+1 != numberOfDestinations) {
addressList += address + " ";
} else {
addressList += address;
}
}
return addressList;
} }
function addressTruncate(address, range){ function addressTruncate(address, range){

View file

@ -573,7 +573,7 @@ Rectangle {
anchors.right: parent ? parent.right : undefined anchors.right: parent ? parent.right : undefined
height: { height: {
if(!collapsed) return 60; if(!collapsed) return 60;
return 320; return 200 + middleColumn.height;
} }
color: { color: {
if(!collapsed) return "transparent" if(!collapsed) return "transparent"
@ -628,9 +628,10 @@ Rectangle {
Layout.preferredHeight: 60 Layout.preferredHeight: 60
ColumnLayout { ColumnLayout {
id: leftColumn
spacing: 0 spacing: 0
clip: true clip: true
Layout.preferredHeight: 120 Layout.preferredHeight: 100 + amountRectangle.height
Layout.minimumWidth: 180 Layout.minimumWidth: 180
Rectangle { Rectangle {
@ -656,23 +657,63 @@ Rectangle {
} }
Rectangle { Rectangle {
id: amountRectangle
color: "transparent" color: "transparent"
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 20 Layout.preferredHeight: amountColumn.height
Component.onCompleted: {
var amountListArray = [];
amountListArray = amountList.split(" ");
for (var i = 0; i < amountListArray.length; i++) {
amountFieldModel.append({amountArray: amountListArray[i]});
}
}
MoneroComponents.TextPlain { ListModel {
font.family: MoneroComponents.Style.fontRegular.name id: amountFieldModel
font.pixelSize: 15 }
text: (amount == 0 ? qsTr("Unknown amount") : displayAmount) + translationManager.emptyString
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
MouseArea { ColumnLayout {
state: "copyable" id: amountColumn
anchors.fill: parent
hoverEnabled: true Repeater {
onEntered: parent.color = MoneroComponents.Style.orange id: amountFieldRepeater
onExited: parent.color = MoneroComponents.Style.defaultFontColor model: amountFieldModel
MoneroComponents.TextPlain {
id: amountField
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
text: {
if (numberOfDestinations > 1) {
if(!collapsed) {
if (index == 0) {
return displayAmount;
} else {
return "";
}
} else {
return amountFieldModel.get(index).amountArray + " XMR"
}
} else {
if (amount == 0) {
return qsTr("Unknown amount") + translationManager.emptyString
} else {
return displayAmount;
}
}
}
MouseArea {
state: "copyable"
anchors.fill: parent
hoverEnabled: true
onEntered: parent.color = MoneroComponents.Style.orange
onExited: parent.color = MoneroComponents.Style.defaultFontColor
}
}
} }
} }
} }
@ -740,9 +781,10 @@ Rectangle {
} }
ColumnLayout { ColumnLayout {
id: middleColumn
spacing: 0 spacing: 0
clip: true clip: true
Layout.preferredHeight: 120 Layout.preferredHeight: 100 + addressRectangle.height
Layout.minimumWidth: 230 Layout.minimumWidth: 230
Rectangle { Rectangle {
@ -768,51 +810,101 @@ Rectangle {
} }
Rectangle { Rectangle {
id: addressRectangle
color: "transparent" color: "transparent"
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 20 Layout.preferredHeight: addressColumn.height
Component.onCompleted: {
var addressListArray = [];
addressListArray = addressList.split(" ");
for (var i = 0; i < addressListArray.length; i++) {
addressFieldModel.append({addressArray: addressListArray[i]});
}
}
MoneroComponents.TextPlain { ListModel {
id: addressField id: addressFieldModel
font.family: MoneroComponents.Style.fontRegular.name }
font.pixelSize: 15
text: { ColumnLayout {
if (isout) { id: addressColumn
if (address) {
return (addressBookName ? FontAwesome.addressBook + " " + addressBookName : TxUtils.addressTruncate(address, 8)); Repeater {
} id: addressFieldRepeater
if (amount != 0) { model: addressFieldModel
return qsTr("Unknown recipient") + translationManager.emptyString;
} else { MoneroComponents.TextPlain {
return qsTr("My wallet") + translationManager.emptyString; id: addressField
} font.family: MoneroComponents.Style.fontRegular.name
} else { font.pixelSize: 15
if (receivingAddress) { textFormat: Text.RichText
if (subaddrIndex == 0) { color: MoneroComponents.Style.defaultFontColor
return qsTr("Address") + " #0" + " (" + qsTr("Primary address") + ")" + translationManager.emptyString; property var addressFromAddressListArray: ""
tooltip: numberOfDestinations > 1 ? (!collapsed ? "" : addressFromAddressListArray)
: address ? address
: receivingAddress ? receivingAddress
: ""
tooltipWrapMode: Text.Wrap
text: {
if (numberOfDestinations > 1) {
if(!collapsed) {
if (index == 0) {
return qsTr("Multiple recipients") + " (" + numberOfDestinations + ")" + translationManager.emptyString;
} else {
return "";
}
} else {
addressFromAddressListArray = addressFieldModel.get(index).addressArray;
var addressOnAddressBook = currentWallet ? currentWallet.addressBook.getDescription(addressFromAddressListArray) : null;
if (addressOnAddressBook) {
return FontAwesome.addressBook + " " + addressOnAddressBook;
} else {
return TxUtils.addressTruncate(addressFieldModel.get(index).addressArray, 8);
}
}
} else { } else {
if (receivingAddressLabel) { if (isout) {
return qsTr("Address") + " #" + subaddrIndex + " (" + receivingAddressLabel + ")" + translationManager.emptyString; if (address) {
return (addressBookName ? FontAwesome.addressBook + " " + addressBookName : TxUtils.addressTruncate(address, 8));
}
if (amount != 0) {
return qsTr("Unknown recipient") + translationManager.emptyString;
} else {
return qsTr("My wallet") + translationManager.emptyString;
}
} else { } else {
return qsTr("Address") + " #" + subaddrIndex + " (" + TxUtils.addressTruncate(receivingAddress, 4) + ")" + translationManager.emptyString; if (receivingAddress) {
if (subaddrIndex == 0) {
return qsTr("Address") + " #0" + " (" + qsTr("Primary address") + ")" + translationManager.emptyString;
} else {
if (receivingAddressLabel) {
return qsTr("Address") + " #" + subaddrIndex + " (" + receivingAddressLabel + ")" + translationManager.emptyString;
} else {
return qsTr("Address") + " #" + subaddrIndex + " (" + TxUtils.addressTruncate(receivingAddress, 4) + ")" + translationManager.emptyString;
}
}
} else {
return qsTr("Unknown address") + translationManager.emptyString;
}
} }
} }
} else { }
return qsTr("Unknown address") + translationManager.emptyString;
MouseArea {
state: isout ? "copyable_address" : "copyable_receiving_address"
anchors.fill: parent
hoverEnabled: true
onEntered: {
parent.color = MoneroComponents.Style.orange
tooltip ? parent.tooltipPopup.open() : ""
}
onExited: {
parent.color = MoneroComponents.Style.defaultFontColor
tooltip ? parent.tooltipPopup.close() : ""
}
} }
} }
} }
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
MouseArea {
state: isout ? "copyable_address" : "copyable_receiving_address"
anchors.fill: parent
hoverEnabled: true
onEntered: parent.color = MoneroComponents.Style.orange
onExited: parent.color = MoneroComponents.Style.defaultFontColor
}
} }
} }
@ -875,10 +967,12 @@ Rectangle {
} }
ColumnLayout { ColumnLayout {
id: rightColumn
spacing: 0 spacing: 0
clip: true clip: true
Layout.preferredHeight: 120 Layout.preferredHeight: 120
Layout.minimumWidth: 130 Layout.minimumWidth: 130
Layout.alignment: Qt.AlignTop
Rectangle { Rectangle {
color: "transparent" color: "transparent"
@ -1245,7 +1339,9 @@ Rectangle {
for(var i = 0; i < res.length; i+=1){ for(var i = 0; i < res.length; i+=1){
if(res[i].containsMouse === true){ if(res[i].containsMouse === true){
if(res[i].state === 'copyable' && res[i].parent.hasOwnProperty('text')) toClipboard(res[i].parent.text); if(res[i].state === 'copyable' && res[i].parent.hasOwnProperty('text')) toClipboard(res[i].parent.text);
if(res[i].state === 'copyable_address') (address ? root.toClipboard(address) : root.toClipboard(addressField.text)); if(res[i].state === 'copyable_address') (address ? root.toClipboard(address)
: res[i].parent.addressFromAddressListArray ? root.toClipboard(res[i].parent.addressFromAddressListArray)
: root.toClipboard(res[i].parent.text));
if(res[i].state === 'copyable_receiving_address') root.toClipboard(currentWallet.address(subaddrAccount, subaddrIndex)); if(res[i].state === 'copyable_receiving_address') root.toClipboard(currentWallet.address(subaddrAccount, subaddrIndex));
if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]); if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]);
if(res[i].state === 'set_tx_note') root.editDescription(hash, tx_note); if(res[i].state === 'set_tx_note') root.editDescription(hash, tx_note);
@ -1434,7 +1530,11 @@ Rectangle {
} }
if(root.sortSearchString.length >= 1){ if(root.sortSearchString.length >= 1){
if(item.amount && item.amount.toString().startsWith(root.sortSearchString)){ if(item.displayAmount && item.displayAmount.startsWith(root.sortSearchString)){
txs.push(item);
} else if(item.amountList != "" && item.amountList.toLowerCase().includes(root.sortSearchString.toLowerCase())){
txs.push(item);
} else if(item.addressList != "" && item.addressList.toLowerCase().includes(root.sortSearchString.toLowerCase())){
txs.push(item); txs.push(item);
} else if(item.address !== "" && item.address.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){ } else if(item.address !== "" && item.address.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
txs.push(item); txs.push(item);
@ -1538,26 +1638,43 @@ Rectangle {
var subaddrIndex = model.data(idx, TransactionHistoryModel.TransactionSubaddrIndexRole); var subaddrIndex = model.data(idx, TransactionHistoryModel.TransactionSubaddrIndexRole);
var timestamp = new Date(date + " " + time).getTime() / 1000; var timestamp = new Date(date + " " + time).getTime() / 1000;
var dateHuman = Utils.ago(timestamp); var dateHuman = Utils.ago(timestamp);
var numberOfDestinations = (destinations.match(/:/g) || []).length;
var amountList = TxUtils.destinationsToAmount(destinations);
if (amount === 0) { if (numberOfDestinations >1) {
// transactions to the same account have amount === 0, while the 'destinations string' var totalAmount = 0;
// has the correct amount, so we try to fetch it from that instead. for (var i = 0; i < numberOfDestinations; i++) {
amount = Number(TxUtils.destinationsToAmount(destinations)); var amountFromAmountList = amountList.split(" ")[i];
var amountAsNumber = Number(amountFromAmountList);
totalAmount += amountAsNumber;
}
var displayAmount = Utils.removeTrailingZeros(totalAmount.toFixed(12)) + " XMR";
} else {
if (amount === 0) {
// transactions to the same account have amount === 0, while the 'destinations string'
// has the correct amount, so we try to fetch it from that instead.
amount = Number(TxUtils.destinationsToAmount(destinations));
}
var displayAmount = Utils.removeTrailingZeros(amount.toFixed(12)) + " XMR";
} }
var displayAmount = Utils.removeTrailingZeros(amount.toFixed(12)) + " XMR";
var tx_note = currentWallet.getUserNote(hash); var tx_note = currentWallet.getUserNote(hash);
var address = ""; var address = "";
var addressBookName = ""; var addressBookName = "";
var receivingAddress = ""; var receivingAddress = "";
var receivingAddressLabel = ""; var receivingAddressLabel = "";
var addressList = "";
if (isout) { if (numberOfDestinations >1) {
address = TxUtils.destinationsToAddress(destinations); addressList = TxUtils.destinationsToAddress(destinations);
addressBookName = currentWallet ? currentWallet.addressBook.getDescription(address) : null;
} else { } else {
receivingAddress = currentWallet ? currentWallet.address(subaddrAccount, subaddrIndex) : null; if (isout) {
receivingAddressLabel = currentWallet ? appWindow.currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) : null; address = TxUtils.destinationsToAddress(destinations);
addressBookName = currentWallet ? currentWallet.addressBook.getDescription(address) : null;
} else {
receivingAddress = currentWallet ? currentWallet.address(subaddrAccount, subaddrIndex) : null;
receivingAddressLabel = currentWallet ? appWindow.currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) : null;
}
} }
if (isout) if (isout)
@ -1572,11 +1689,14 @@ Rectangle {
"isout": isout, "isout": isout,
"amount": amount, "amount": amount,
"displayAmount": displayAmount, "displayAmount": displayAmount,
"amountList": amountList,
"hash": hash, "hash": hash,
"paymentId": paymentId, "paymentId": paymentId,
"address": address, "address": address,
"addressList": addressList,
"addressBookName": addressBookName, "addressBookName": addressBookName,
"destinations": destinations, "destinations": destinations,
"numberOfDestinations": numberOfDestinations,
"tx_note": tx_note, "tx_note": tx_note,
"dateHuman": dateHuman, "dateHuman": dateHuman,
"dateTime": date + " " + time, "dateTime": date + " " + time,