Refactor + Optimizations

This commit is contained in:
gerlofvanek
2025-10-10 11:08:23 +02:00
parent 2f7e425da9
commit 73d486d6f0
79 changed files with 5835 additions and 4419 deletions

View File

@@ -1,5 +1,5 @@
{% include 'header.html' %}
{% from 'style.html' import breadcrumb_line_svg, circular_arrows_svg, withdraw_svg, utxo_groups_svg, create_utxo_svg, lock_svg, eye_show_svg %}
{% from 'style.html' import circular_arrows_svg, withdraw_svg, utxo_groups_svg, create_utxo_svg, lock_svg, eye_show_svg %}
<section class="py-3 px-4 mt-6">
<div class="lg:container mx-auto">
@@ -190,425 +190,7 @@
{% include 'footer.html' %}
<script>
document.addEventListener('DOMContentLoaded', function() {
if (window.WebSocketManager && typeof window.WebSocketManager.initialize === 'function') {
window.WebSocketManager.initialize();
}
function setupWalletsWebSocketUpdates() {
window.BalanceUpdatesManager.setup({
contextKey: 'wallets',
balanceUpdateCallback: updateWalletBalances,
swapEventCallback: updateWalletBalances,
errorContext: 'Wallets',
enablePeriodicRefresh: true,
periodicInterval: 60000
});
if (window.WebSocketManager && typeof window.WebSocketManager.addMessageHandler === 'function') {
const priceHandlerId = window.WebSocketManager.addMessageHandler('message', (data) => {
if (data && data.event) {
if (data.event === 'price_updated' || data.event === 'prices_updated') {
clearTimeout(window.walletsPriceUpdateTimeout);
window.walletsPriceUpdateTimeout = setTimeout(() => {
if (window.WalletManager && typeof window.WalletManager.updatePrices === 'function') {
window.WalletManager.updatePrices(true);
}
}, 500);
}
}
});
window.walletsPriceHandlerId = priceHandlerId;
}
}
function updateWalletBalances(balanceData) {
if (balanceData) {
balanceData.forEach(coin => {
updateWalletDisplay(coin);
});
setTimeout(() => {
if (window.WalletManager && typeof window.WalletManager.updatePrices === 'function') {
window.WalletManager.updatePrices(true);
}
}, 250);
} else {
window.BalanceUpdatesManager.fetchBalanceData()
.then(data => updateWalletBalances(data))
.catch(error => {
console.error('Error updating wallet balances:', error);
});
}
}
function updateWalletDisplay(coinData) {
if (coinData.name === 'Particl') {
updateSpecificBalance('Particl', 'Balance:', coinData.balance, coinData.ticker || 'PART');
} else if (coinData.name === 'Particl Anon') {
updateSpecificBalance('Particl', 'Anon Balance:', coinData.balance, coinData.ticker || 'PART');
removePendingBalance('Particl', 'Anon Balance:');
if (coinData.pending && parseFloat(coinData.pending) > 0) {
updatePendingBalance('Particl', 'Anon Balance:', coinData.pending, coinData.ticker || 'PART', 'Anon Pending:', coinData);
}
} else if (coinData.name === 'Particl Blind') {
updateSpecificBalance('Particl', 'Blind Balance:', coinData.balance, coinData.ticker || 'PART');
removePendingBalance('Particl', 'Blind Balance:');
if (coinData.pending && parseFloat(coinData.pending) > 0) {
updatePendingBalance('Particl', 'Blind Balance:', coinData.pending, coinData.ticker || 'PART', 'Blind Unconfirmed:', coinData);
}
} else {
updateSpecificBalance(coinData.name, 'Balance:', coinData.balance, coinData.ticker || coinData.name);
if (coinData.name !== 'Particl Anon' && coinData.name !== 'Particl Blind' && coinData.name !== 'Litecoin MWEB') {
if (coinData.pending && parseFloat(coinData.pending) > 0) {
updatePendingDisplay(coinData);
} else {
removePendingDisplay(coinData.name);
}
}
}
}
function updateSpecificBalance(coinName, labelText, balance, ticker, isPending = false) {
const balanceElements = document.querySelectorAll('.coinname-value[data-coinname]');
let found = false;
balanceElements.forEach(element => {
const elementCoinName = element.getAttribute('data-coinname');
if (elementCoinName === coinName) {
const parentDiv = element.closest('.flex.mb-2.justify-between.items-center');
const labelElement = parentDiv ? parentDiv.querySelector('h4') : null;
if (labelElement) {
const currentLabel = labelElement.textContent.trim();
if (currentLabel === labelText) {
if (isPending) {
const cleanBalance = balance.toString().replace(/^\+/, '');
element.textContent = `+${cleanBalance} ${ticker}`;
} else {
element.textContent = `${balance} ${ticker}`;
}
found = true;
}
}
}
});
}
function updatePendingDisplay(coinData) {
const walletContainer = findWalletContainer(coinData.name);
if (!walletContainer) return;
const existingPendingElements = walletContainer.querySelectorAll('.flex.mb-2.justify-between.items-center');
let staticPendingElement = null;
let staticUsdElement = null;
existingPendingElements.forEach(element => {
const labelElement = element.querySelector('h4');
if (labelElement) {
const labelText = labelElement.textContent;
if (labelText.includes('Pending:') && !labelText.includes('USD')) {
staticPendingElement = element;
} else if (labelText.includes('Pending USD value:')) {
staticUsdElement = element;
}
}
});
if (staticPendingElement && staticUsdElement) {
const pendingSpan = staticPendingElement.querySelector('.coinname-value');
if (pendingSpan) {
const cleanPending = coinData.pending.toString().replace(/^\+/, '');
pendingSpan.textContent = `+${cleanPending} ${coinData.ticker || coinData.name}`;
}
let initialUSD = '$0.00';
if (window.WalletManager && window.WalletManager.coinPrices) {
const coinId = coinData.name.toLowerCase().replace(' ', '-');
const price = window.WalletManager.coinPrices[coinId];
if (price && price.usd) {
const cleanPending = coinData.pending.toString().replace(/^\+/, '');
const usdValue = (parseFloat(cleanPending) * price.usd).toFixed(2);
initialUSD = `$${usdValue}`;
}
}
const usdDiv = staticUsdElement.querySelector('.usd-value');
if (usdDiv) {
usdDiv.textContent = initialUSD;
}
return;
}
let pendingContainer = walletContainer.querySelector('.pending-container');
if (!pendingContainer) {
pendingContainer = document.createElement('div');
pendingContainer.className = 'pending-container';
const pendingRow = document.createElement('div');
pendingRow.className = 'flex mb-2 justify-between items-center';
const cleanPending = coinData.pending.toString().replace(/^\+/, '');
pendingRow.innerHTML = `
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">Pending:</h4>
<span class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 coinname-value" data-coinname="${coinData.name}">+${cleanPending} ${coinData.ticker || coinData.name}</span>
`;
pendingContainer.appendChild(pendingRow);
let initialUSD = '$0.00';
if (window.WalletManager && window.WalletManager.coinPrices) {
const coinId = coinData.name.toLowerCase().replace(' ', '-');
const price = window.WalletManager.coinPrices[coinId];
if (price && price.usd) {
const usdValue = (parseFloat(cleanPending) * price.usd).toFixed(2);
initialUSD = `$${usdValue}`;
}
}
const usdRow = document.createElement('div');
usdRow.className = 'flex mb-2 justify-between items-center';
usdRow.innerHTML = `
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">Pending USD value:</h4>
<div class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 usd-value">${initialUSD}</div>
`;
pendingContainer.appendChild(usdRow);
const balanceRow = walletContainer.querySelector('.flex.mb-2.justify-between.items-center');
let insertAfterElement = balanceRow;
if (balanceRow) {
let nextElement = balanceRow.nextElementSibling;
while (nextElement) {
const labelElement = nextElement.querySelector('h4');
if (labelElement && labelElement.textContent.includes('USD value:') &&
!labelElement.textContent.includes('Pending') && !labelElement.textContent.includes('Unconfirmed')) {
insertAfterElement = nextElement;
break;
}
nextElement = nextElement.nextElementSibling;
}
}
if (insertAfterElement && insertAfterElement.nextSibling) {
walletContainer.insertBefore(pendingContainer, insertAfterElement.nextSibling);
} else {
walletContainer.appendChild(pendingContainer);
}
} else {
const pendingElement = pendingContainer.querySelector('.coinname-value');
if (pendingElement) {
const cleanPending = coinData.pending.toString().replace(/^\+/, ''); // Remove existing + if any
pendingElement.textContent = `+${cleanPending} ${coinData.ticker || coinData.name}`;
}
}
}
function removePendingDisplay(coinName) {
const walletContainer = findWalletContainer(coinName);
if (!walletContainer) return;
const pendingContainer = walletContainer.querySelector('.pending-container');
if (pendingContainer) {
pendingContainer.remove();
}
const existingPendingElements = walletContainer.querySelectorAll('.flex.mb-2.justify-between.items-center');
existingPendingElements.forEach(element => {
const labelElement = element.querySelector('h4');
if (labelElement) {
const labelText = labelElement.textContent;
if (labelText.includes('Pending:') || labelText.includes('Pending USD value:')) {
element.style.display = 'none';
}
}
});
}
function removeSpecificPending(coinName, labelText) {
const balanceElements = document.querySelectorAll('.coinname-value[data-coinname]');
balanceElements.forEach(element => {
const elementCoinName = element.getAttribute('data-coinname');
if (elementCoinName === coinName) {
const parentDiv = element.closest('.flex.mb-2.justify-between.items-center');
const labelElement = parentDiv ? parentDiv.querySelector('h4') : null;
if (labelElement) {
const currentLabel = labelElement.textContent.trim();
if (currentLabel === labelText) {
parentDiv.remove();
}
}
}
});
}
function updatePendingBalance(coinName, balanceType, pendingAmount, ticker, pendingLabel, coinData) {
const balanceElements = document.querySelectorAll('.coinname-value[data-coinname]');
let targetElement = null;
balanceElements.forEach(element => {
const elementCoinName = element.getAttribute('data-coinname');
if (elementCoinName === coinName) {
const parentElement = element.closest('.flex.mb-2.justify-between.items-center');
if (parentElement) {
const labelElement = parentElement.querySelector('h4');
if (labelElement && labelElement.textContent.includes(balanceType)) {
targetElement = parentElement;
}
}
}
});
if (!targetElement) return;
let insertAfterElement = targetElement;
let nextElement = targetElement.nextElementSibling;
while (nextElement) {
const labelElement = nextElement.querySelector('h4');
if (labelElement) {
const labelText = labelElement.textContent;
if (labelText.includes('USD value:') && !labelText.includes('Pending') && !labelText.includes('Unconfirmed')) {
insertAfterElement = nextElement;
break;
}
if (labelText.includes('Balance:') || labelText.includes('Pending:') || labelText.includes('Unconfirmed:')) {
break;
}
}
nextElement = nextElement.nextElementSibling;
}
let pendingElement = insertAfterElement.nextElementSibling;
while (pendingElement && !pendingElement.querySelector('h4')?.textContent.includes(pendingLabel)) {
pendingElement = pendingElement.nextElementSibling;
if (pendingElement && pendingElement.querySelector('h4')?.textContent.includes('Balance:')) {
pendingElement = null;
break;
}
}
if (!pendingElement) {
const newPendingElement = document.createElement('div');
newPendingElement.className = 'flex mb-2 justify-between items-center';
newPendingElement.innerHTML = `
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">${pendingLabel}</h4>
<span class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 coinname-value" data-coinname="${coinName}">+${pendingAmount} ${ticker}</span>
`;
insertAfterElement.parentNode.insertBefore(newPendingElement, insertAfterElement.nextSibling);
let initialUSD = '$0.00';
if (window.WalletManager && window.WalletManager.coinPrices) {
const coinId = coinName.toLowerCase().replace(' ', '-');
const price = window.WalletManager.coinPrices[coinId];
if (price && price.usd) {
const usdValue = (parseFloat(pendingAmount) * price.usd).toFixed(2);
initialUSD = `$${usdValue}`;
}
}
const usdElement = document.createElement('div');
usdElement.className = 'flex mb-2 justify-between items-center';
usdElement.innerHTML = `
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">${pendingLabel.replace(':', '')} USD value:</h4>
<div class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 usd-value">${initialUSD}</div>
`;
newPendingElement.parentNode.insertBefore(usdElement, newPendingElement.nextSibling);
} else {
const pendingSpan = pendingElement.querySelector('.coinname-value');
if (pendingSpan) {
pendingSpan.textContent = `+${pendingAmount} ${ticker}`;
}
}
}
function removePendingBalance(coinName, balanceType) {
const balanceElements = document.querySelectorAll('.coinname-value[data-coinname]');
let targetElement = null;
balanceElements.forEach(element => {
const elementCoinName = element.getAttribute('data-coinname');
if (elementCoinName === coinName) {
const parentElement = element.closest('.flex.mb-2.justify-between.items-center');
if (parentElement) {
const labelElement = parentElement.querySelector('h4');
if (labelElement && labelElement.textContent.includes(balanceType)) {
targetElement = parentElement;
}
}
}
});
if (!targetElement) return;
let nextElement = targetElement.nextElementSibling;
while (nextElement) {
const labelElement = nextElement.querySelector('h4');
if (labelElement) {
const labelText = labelElement.textContent;
if (labelText.includes('Pending:') || labelText.includes('Unconfirmed:') ||
labelText.includes('Anon Pending:') || labelText.includes('Blind Unconfirmed:') ||
labelText.includes('Pending USD value:') || labelText.includes('Unconfirmed USD value:') ||
labelText.includes('Anon Pending USD value:') || labelText.includes('Blind Unconfirmed USD value:')) {
const elementToRemove = nextElement;
nextElement = nextElement.nextElementSibling;
elementToRemove.remove();
} else if (labelText.includes('Balance:')) {
break; // Stop if we hit another balance
} else {
nextElement = nextElement.nextElementSibling;
}
} else {
nextElement = nextElement.nextElementSibling;
}
}
}
function findWalletContainer(coinName) {
const balanceElements = document.querySelectorAll('.coinname-value[data-coinname]');
for (const element of balanceElements) {
if (element.getAttribute('data-coinname') === coinName) {
return element.closest('.bg-coolGray-100, .dark\\:bg-gray-600');
}
}
return null;
}
function cleanupWalletsBalanceUpdates() {
window.BalanceUpdatesManager.cleanup('wallets');
if (window.walletsPriceHandlerId && window.WebSocketManager) {
window.WebSocketManager.removeMessageHandler('message', window.walletsPriceHandlerId);
}
clearTimeout(window.walletsPriceUpdateTimeout);
}
window.BalanceUpdatesManager.initialize();
setupWalletsWebSocketUpdates();
setTimeout(() => {
updateWalletBalances();
}, 1000);
if (window.CleanupManager) {
window.CleanupManager.registerResource('walletsBalanceUpdates', null, cleanupWalletsBalanceUpdates);
}
window.addEventListener('beforeunload', cleanupWalletsBalanceUpdates);
});
</script>
<script src="/static/js/pages/wallets-page.js"></script>
</body>
</html>