mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 18:38:09 +01:00
Merge pull request #358 from gerlofvanek/update_notification
Show notification when new release of BSX
This commit is contained in:
@@ -382,6 +382,13 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
self._expiring_offers = [] # List of offers expiring soon
|
||||
self._updating_wallets_info = {}
|
||||
self._last_updated_wallets_info = 0
|
||||
|
||||
self.check_updates_seconds = self.get_int_setting(
|
||||
"check_updates_seconds", 24 * 60 * 60, 60 * 60, 7 * 24 * 60 * 60
|
||||
)
|
||||
self._last_checked_updates = 0
|
||||
self._latest_version = None
|
||||
self._update_available = False
|
||||
self._notifications_enabled = self.settings.get("notifications_enabled", True)
|
||||
self._disabled_notification_types = self.settings.get(
|
||||
"disabled_notification_types", []
|
||||
@@ -1325,6 +1332,65 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
if ci.isWalletLocked():
|
||||
raise LockedCoinError(Coins.PART)
|
||||
|
||||
def checkForUpdates(self) -> None:
|
||||
if not self.settings.get("check_updates", True):
|
||||
return
|
||||
|
||||
now = time.time()
|
||||
if now - self._last_checked_updates < self.check_updates_seconds:
|
||||
return
|
||||
|
||||
self._last_checked_updates = now
|
||||
self.log.info("Checking for BasicSwap updates...")
|
||||
|
||||
try:
|
||||
url = "https://api.github.com/repos/basicswap/basicswap/tags"
|
||||
response_data = self.readURL(url, timeout=30)
|
||||
tags_data = json.loads(response_data.decode("utf-8"))
|
||||
|
||||
if not tags_data or not isinstance(tags_data, list) or len(tags_data) == 0:
|
||||
self.log.warning("Could not determine latest version from GitHub tags")
|
||||
return
|
||||
|
||||
latest_tag = tags_data[0].get("name", "").lstrip("v")
|
||||
if not latest_tag:
|
||||
self.log.warning("Could not determine latest version from GitHub tags")
|
||||
return
|
||||
|
||||
self._latest_version = latest_tag
|
||||
current_version = __version__
|
||||
|
||||
def version_tuple(v):
|
||||
return tuple(map(int, v.split(".")))
|
||||
|
||||
try:
|
||||
if version_tuple(latest_tag) > version_tuple(current_version):
|
||||
if not self._update_available:
|
||||
self._update_available = True
|
||||
self.log.info(
|
||||
f"Update available: v{latest_tag} (current: v{current_version})"
|
||||
)
|
||||
|
||||
self.notify(
|
||||
NT.UPDATE_AVAILABLE,
|
||||
{
|
||||
"current_version": current_version,
|
||||
"latest_version": latest_tag,
|
||||
"release_url": f"https://github.com/basicswap/basicswap/releases/tag/v{latest_tag}",
|
||||
"release_notes": f"New version v{latest_tag} is available. Click to view details on GitHub.",
|
||||
},
|
||||
)
|
||||
else:
|
||||
self.log.info(f"Update v{latest_tag} already notified")
|
||||
else:
|
||||
self._update_available = False
|
||||
self.log.info(f"BasicSwap is up to date (v{current_version})")
|
||||
except ValueError as e:
|
||||
self.log.warning(f"Error comparing versions: {e}")
|
||||
|
||||
except Exception as e:
|
||||
self.log.warning(f"Failed to check for updates: {e}")
|
||||
|
||||
def isBaseCoinActive(self, c) -> bool:
|
||||
if c not in chainparams:
|
||||
return False
|
||||
@@ -10798,6 +10864,9 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
||||
self.checkDelayedAutoAccept()
|
||||
self._last_checked_delayed_auto_accept = now
|
||||
|
||||
if now - self._last_checked_updates >= self.check_updates_seconds:
|
||||
self.checkForUpdates()
|
||||
|
||||
except Exception as ex:
|
||||
self.logException(f"update {ex}")
|
||||
|
||||
|
||||
@@ -244,6 +244,7 @@ class NotificationTypes(IntEnum):
|
||||
BID_RECEIVED = auto()
|
||||
BID_ACCEPTED = auto()
|
||||
SWAP_COMPLETED = auto()
|
||||
UPDATE_AVAILABLE = auto()
|
||||
|
||||
|
||||
class ConnectionRequestTypes(IntEnum):
|
||||
|
||||
@@ -842,9 +842,19 @@ def js_generatenotification(self, url_split, post_string, is_json) -> bytes:
|
||||
if not swap_client.debug:
|
||||
raise ValueError("Debug mode not active.")
|
||||
|
||||
r = random.randint(0, 3)
|
||||
r = random.randint(0, 4)
|
||||
if r == 0:
|
||||
swap_client.notify(NT.OFFER_RECEIVED, {"offer_id": random.randbytes(28).hex()})
|
||||
swap_client.notify(
|
||||
NT.OFFER_RECEIVED,
|
||||
{
|
||||
"offer_id": random.randbytes(28).hex(),
|
||||
"coin_from": 2,
|
||||
"coin_to": 6,
|
||||
"amount_from": 100000000,
|
||||
"amount_to": 15500000000000,
|
||||
"rate": 15500000000000,
|
||||
},
|
||||
)
|
||||
elif r == 1:
|
||||
swap_client.notify(
|
||||
NT.BID_RECEIVED,
|
||||
@@ -852,6 +862,13 @@ def js_generatenotification(self, url_split, post_string, is_json) -> bytes:
|
||||
"type": "atomic",
|
||||
"bid_id": random.randbytes(28).hex(),
|
||||
"offer_id": random.randbytes(28).hex(),
|
||||
"coin_from": 2,
|
||||
"coin_to": 6,
|
||||
"amount_from": 100000000,
|
||||
"amount_to": 15500000000000,
|
||||
"bid_amount": 50000000,
|
||||
"bid_amount_to": 7750000000000,
|
||||
"rate": 15500000000000,
|
||||
},
|
||||
)
|
||||
elif r == 2:
|
||||
@@ -863,12 +880,71 @@ def js_generatenotification(self, url_split, post_string, is_json) -> bytes:
|
||||
"type": "ads",
|
||||
"bid_id": random.randbytes(28).hex(),
|
||||
"offer_id": random.randbytes(28).hex(),
|
||||
"coin_from": 1,
|
||||
"coin_to": 3,
|
||||
"amount_from": 500000000,
|
||||
"amount_to": 100000000,
|
||||
"bid_amount": 250000000,
|
||||
"bid_amount_to": 50000000,
|
||||
"rate": 20000000,
|
||||
},
|
||||
)
|
||||
elif r == 4:
|
||||
swap_client.notify(NT.SWAP_COMPLETED, {"bid_id": random.randbytes(28).hex()})
|
||||
|
||||
return bytes(json.dumps({"type": r}), "UTF-8")
|
||||
|
||||
|
||||
def js_checkupdates(self, url_split, post_string, is_json) -> bytes:
|
||||
swap_client = self.server.swap_client
|
||||
from basicswap import __version__
|
||||
|
||||
if not swap_client.settings.get("check_updates", True):
|
||||
return bytes(
|
||||
json.dumps({"error": "Update checking is disabled in settings"}), "UTF-8"
|
||||
)
|
||||
|
||||
import time
|
||||
|
||||
now = time.time()
|
||||
last_manual_check = getattr(swap_client, "_last_manual_update_check", 0)
|
||||
|
||||
if not swap_client.debug and (now - last_manual_check) < 3600:
|
||||
remaining = int(3600 - (now - last_manual_check))
|
||||
return bytes(
|
||||
json.dumps(
|
||||
{
|
||||
"error": f"Please wait {remaining // 60} minutes before checking again"
|
||||
}
|
||||
),
|
||||
"UTF-8",
|
||||
)
|
||||
|
||||
swap_client._last_manual_update_check = now
|
||||
swap_client.log.info("Manual update check requested via web interface")
|
||||
|
||||
swap_client.checkForUpdates()
|
||||
|
||||
if swap_client._update_available:
|
||||
swap_client.log.info(
|
||||
f"Manual check result: Update available v{swap_client._latest_version} (current: v{__version__})"
|
||||
)
|
||||
else:
|
||||
swap_client.log.info(f"Manual check result: Up to date (v{__version__})")
|
||||
|
||||
return bytes(
|
||||
json.dumps(
|
||||
{
|
||||
"message": "Update check completed",
|
||||
"current_version": __version__,
|
||||
"latest_version": swap_client._latest_version,
|
||||
"update_available": swap_client._update_available,
|
||||
}
|
||||
),
|
||||
"UTF-8",
|
||||
)
|
||||
|
||||
|
||||
def js_notifications(self, url_split, post_string, is_json) -> bytes:
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
@@ -1377,6 +1453,7 @@ endpoints = {
|
||||
"rates": js_rates,
|
||||
"rateslist": js_rates_list,
|
||||
"generatenotification": js_generatenotification,
|
||||
"checkupdates": js_checkupdates,
|
||||
"notifications": js_notifications,
|
||||
"identities": js_identities,
|
||||
"automationstrategies": js_automationstrategies,
|
||||
|
||||
@@ -8,6 +8,7 @@ const NotificationManager = (function() {
|
||||
showBalanceChanges: true,
|
||||
showOutgoingTransactions: true,
|
||||
showSwapCompleted: true,
|
||||
showUpdateNotifications: true,
|
||||
notificationDuration: 20000
|
||||
};
|
||||
|
||||
@@ -67,6 +68,7 @@ const NotificationManager = (function() {
|
||||
coinSymbol: options.coinSymbol || '',
|
||||
coinFrom: options.coinFrom || null,
|
||||
coinTo: options.coinTo || null,
|
||||
releaseUrl: options.releaseUrl || null,
|
||||
timestamp: new Date().toLocaleString(),
|
||||
timestampMs: Date.now()
|
||||
};
|
||||
@@ -183,6 +185,10 @@ const NotificationManager = (function() {
|
||||
return `window.location.href='/bids'`;
|
||||
}
|
||||
|
||||
if (item.type === 'update_available' && item.releaseUrl) {
|
||||
return `window.open('${item.releaseUrl}', '_blank')`;
|
||||
}
|
||||
|
||||
if (item.title.includes('offer') || item.title.includes('Offer')) {
|
||||
return `window.location.href='/offers'`;
|
||||
}
|
||||
@@ -231,6 +237,9 @@ function ensureToastContainer() {
|
||||
'balance_change': `<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M4 4a2 2 0 00-2 2v4a2 2 0 002 2V6h10a2 2 0 00-2-2H4zm2 6a2 2 0 012-2h8a2 2 0 012 2v4a2 2 0 01-2 2H8a2 2 0 01-2-2v-4zm6 4a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path>
|
||||
</svg>`,
|
||||
'update_available': `<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z" clip-rule="evenodd"></path>
|
||||
</svg>`,
|
||||
'success': `<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
|
||||
</svg>`
|
||||
@@ -245,6 +254,7 @@ function ensureToastContainer() {
|
||||
'bid_accepted': 'bg-purple-500',
|
||||
'swap_completed': 'bg-green-600',
|
||||
'balance_change': 'bg-yellow-500',
|
||||
'update_available': 'bg-blue-600',
|
||||
'success': 'bg-blue-500'
|
||||
};
|
||||
|
||||
@@ -425,6 +435,18 @@ function ensureToastContainer() {
|
||||
);
|
||||
}, 4000);
|
||||
|
||||
setTimeout(() => {
|
||||
this.createToast(
|
||||
'Update Available: v0.15.0',
|
||||
'update_available',
|
||||
{
|
||||
subtitle: 'Current: v0.14.6 • Click to view release',
|
||||
releaseUrl: 'https://github.com/basicswap/basicswap/releases/tag/v0.15.0',
|
||||
releaseNotes: 'New version v0.15.0 is available. Click to view details on GitHub.'
|
||||
}
|
||||
);
|
||||
}, 4500);
|
||||
|
||||
},
|
||||
|
||||
initializeBalanceTracking: function() {
|
||||
@@ -466,7 +488,6 @@ function ensureToastContainer() {
|
||||
const staleThreshold = 10 * 60 * 1000;
|
||||
|
||||
if (!lastFetch || (now - parseInt(lastFetch)) > staleThreshold) {
|
||||
console.log('Resetting stale balance tracking to prevent false notifications');
|
||||
this.resetBalanceTracking();
|
||||
}
|
||||
},
|
||||
@@ -504,6 +525,8 @@ function ensureToastContainer() {
|
||||
const iconColor = getToastColor(type, options);
|
||||
const icon = getToastIcon(type);
|
||||
|
||||
const isPersistent = type === 'update_available';
|
||||
|
||||
let coinIconHtml = '';
|
||||
if (options.coinSymbol) {
|
||||
const coinIcon = getCoinIcon(options.coinSymbol);
|
||||
@@ -523,6 +546,9 @@ function ensureToastContainer() {
|
||||
} else if (options.coinSymbol) {
|
||||
clickAction = `onclick="window.location.href='/wallet/${options.coinSymbol}'"`;
|
||||
cursorStyle = 'cursor-pointer';
|
||||
} else if (options.releaseUrl) {
|
||||
clickAction = `onclick="window.open('${options.releaseUrl}', '_blank')"`;
|
||||
cursorStyle = 'cursor-pointer';
|
||||
}
|
||||
|
||||
message.innerHTML = `
|
||||
@@ -558,17 +584,19 @@ function ensureToastContainer() {
|
||||
`;
|
||||
messages.appendChild(message);
|
||||
|
||||
setTimeout(() => {
|
||||
if (message.parentNode) {
|
||||
message.classList.add('toast-slide-out');
|
||||
setTimeout(() => {
|
||||
if (message.parentNode) {
|
||||
message.parentNode.removeChild(message);
|
||||
}
|
||||
if (!isPersistent) {
|
||||
setTimeout(() => {
|
||||
if (message.parentNode) {
|
||||
message.classList.add('toast-slide-out');
|
||||
setTimeout(() => {
|
||||
if (message.parentNode) {
|
||||
message.parentNode.removeChild(message);
|
||||
}
|
||||
|
||||
}, 300);
|
||||
}
|
||||
}, config.notificationDuration);
|
||||
}, 300);
|
||||
}
|
||||
}, config.notificationDuration);
|
||||
}
|
||||
},
|
||||
|
||||
handleWebSocketEvent: function(data) {
|
||||
@@ -633,6 +661,15 @@ function ensureToastContainer() {
|
||||
shouldShowToast = config.showSwapCompleted;
|
||||
break;
|
||||
|
||||
case 'update_available':
|
||||
toastTitle = `Update Available: v${data.latest_version}`;
|
||||
toastOptions.subtitle = `Current: v${data.current_version} • Click to view release`;
|
||||
toastOptions.releaseUrl = data.release_url;
|
||||
toastOptions.releaseNotes = data.release_notes;
|
||||
toastType = 'update_available';
|
||||
shouldShowToast = config.showUpdateNotifications;
|
||||
break;
|
||||
|
||||
case 'coin_balance_updated':
|
||||
if (data.coin && config.showBalanceChanges) {
|
||||
this.handleBalanceUpdate(data);
|
||||
|
||||
@@ -503,6 +503,17 @@
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 ml-7 mt-1">Show notifications when swaps complete successfully</p>
|
||||
</div>
|
||||
|
||||
<div class="py-2">
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox" id="check_updates" name="check_updates" value="true" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"{% if general_settings.check_updates %} checked{% endif %}>
|
||||
<label for="check_updates" class="ml-3 text-sm font-medium text-gray-700 dark:text-gray-300">Update Notifications</label>
|
||||
<button type="button" onclick="checkForUpdatesNow()" class="ml-3 text-xs bg-gray-600 hover:bg-gray-700 text-white font-medium py-1 px-3 rounded transition-colors focus:outline-none">
|
||||
Check Now
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 ml-7 mt-1">Check for BasicSwap updates and show notifications when available</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
@@ -537,10 +548,16 @@
|
||||
<div>
|
||||
<h4 class="text-sm font-medium text-gray-900 dark:text-white mb-4">Test Notifications</h4>
|
||||
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
|
||||
<div>
|
||||
<div class="space-y-3">
|
||||
<button type="button" onclick="window.NotificationManager && window.NotificationManager.testToasts()" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition-colors focus:outline-none">
|
||||
Test All Notification Types
|
||||
</button>
|
||||
<button type="button" onclick="testUpdateNotification()" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition-colors focus:outline-none">
|
||||
Test Update Notification
|
||||
</button>
|
||||
<button type="button" onclick="testLiveUpdateCheck()" class="bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition-colors focus:outline-none">
|
||||
Test Live Update Check
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -570,6 +587,7 @@
|
||||
showBalanceChanges: document.getElementById('notifications_balance_changes').checked,
|
||||
showOutgoingTransactions: document.getElementById('notifications_outgoing_transactions').checked,
|
||||
showSwapCompleted: document.getElementById('notifications_swap_completed').checked,
|
||||
showUpdateNotifications: document.getElementById('check_updates').checked,
|
||||
notificationDuration: parseInt(document.getElementById('notifications_duration').value) * 1000
|
||||
};
|
||||
|
||||
@@ -581,6 +599,141 @@
|
||||
setTimeout(syncNotificationSettings, 100);
|
||||
});
|
||||
|
||||
function testUpdateNotification() {
|
||||
if (window.NotificationManager) {
|
||||
window.NotificationManager.createToast(
|
||||
'Update Available: v0.15.0',
|
||||
'update_available',
|
||||
{
|
||||
subtitle: 'Current: v{{ version }} • Click to view release',
|
||||
releaseUrl: 'https://github.com/basicswap/basicswap/releases/tag/v0.15.0',
|
||||
releaseNotes: 'New version v0.15.0 is available. Click to view details on GitHub.'
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function testLiveUpdateCheck() {
|
||||
const button = event.target;
|
||||
const originalText = button.textContent;
|
||||
button.textContent = 'Checking...';
|
||||
button.disabled = true;
|
||||
|
||||
fetch('/json/checkupdates', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (window.NotificationManager) {
|
||||
if (data.update_available) {
|
||||
window.NotificationManager.createToast(
|
||||
`Live Update Available: v${data.latest_version}`,
|
||||
'update_available',
|
||||
{
|
||||
subtitle: `Current: v${data.current_version} • Click to view release`,
|
||||
releaseUrl: `https://github.com/basicswap/basicswap/releases/tag/v${data.latest_version}`,
|
||||
releaseNotes: 'This is a real update check from GitHub API.'
|
||||
}
|
||||
);
|
||||
} else {
|
||||
window.NotificationManager.createToast(
|
||||
'No Updates Available',
|
||||
'success',
|
||||
{
|
||||
subtitle: `Current version v${data.current_version} is up to date`
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Update check failed:', error);
|
||||
if (window.NotificationManager) {
|
||||
window.NotificationManager.createToast(
|
||||
'Update Check Failed',
|
||||
'error',
|
||||
{
|
||||
subtitle: 'Could not check for updates. See console for details.'
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
button.textContent = originalText;
|
||||
button.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
function checkForUpdatesNow() {
|
||||
const button = event.target;
|
||||
const originalText = button.textContent;
|
||||
button.textContent = 'Checking...';
|
||||
button.disabled = true;
|
||||
|
||||
fetch('/json/checkupdates', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
if (window.NotificationManager) {
|
||||
window.NotificationManager.createToast(
|
||||
'Update Check Failed',
|
||||
'error',
|
||||
{
|
||||
subtitle: data.error
|
||||
}
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.NotificationManager) {
|
||||
if (data.update_available) {
|
||||
window.NotificationManager.createToast(
|
||||
`Update Available: v${data.latest_version}`,
|
||||
'update_available',
|
||||
{
|
||||
subtitle: `Current: v${data.current_version} • Click to view release`,
|
||||
releaseUrl: `https://github.com/basicswap/basicswap/releases/tag/v${data.latest_version}`,
|
||||
releaseNotes: `New version v${data.latest_version} is available. Click to view details on GitHub.`
|
||||
}
|
||||
);
|
||||
} else {
|
||||
window.NotificationManager.createToast(
|
||||
'You\'re Up to Date!',
|
||||
'success',
|
||||
{
|
||||
subtitle: `Current version v${data.current_version} is the latest`
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Update check failed:', error);
|
||||
if (window.NotificationManager) {
|
||||
window.NotificationManager.createToast(
|
||||
'Update Check Failed',
|
||||
'error',
|
||||
{
|
||||
subtitle: 'Network error. Please try again later.'
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
button.textContent = originalText;
|
||||
button.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
syncNotificationSettings();
|
||||
});
|
||||
|
||||
@@ -665,7 +665,7 @@ function fillDonationAddress(address, type) {
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if donation_info %}
|
||||
{% if debug_ui and donation_info %}
|
||||
<tr>
|
||||
<td colspan="2" class="py-3 px-6">
|
||||
<div class="p-4 bg-coolGray-100 dark:bg-gray-500 border border-coolGray-200 dark:border-gray-400 rounded-lg">
|
||||
|
||||
@@ -94,6 +94,9 @@ def page_settings(self, url_split, post_string):
|
||||
"notifications_duration": int(
|
||||
get_data_entry_or(form_data, "notifications_duration", "20")
|
||||
),
|
||||
"check_updates": toBool(
|
||||
get_data_entry_or(form_data, "check_updates", "true")
|
||||
),
|
||||
}
|
||||
swap_client.editGeneralSettings(data)
|
||||
messages.append("Notification settings applied.")
|
||||
@@ -207,6 +210,7 @@ def page_settings(self, url_split, post_string):
|
||||
"debug": swap_client.debug,
|
||||
"debug_ui": swap_client.debug_ui,
|
||||
"expire_db_records": swap_client._expire_db_records,
|
||||
"check_updates": swap_client.settings.get("check_updates", True),
|
||||
}
|
||||
|
||||
chart_api_key = get_api_key_setting(
|
||||
|
||||
@@ -410,5 +410,6 @@ def page_wallet(self, url_split, post_string):
|
||||
"summary": summary,
|
||||
"block_unknown_seeds": swap_client._restrict_unknown_seed_wallets,
|
||||
"donation_info": donation_info,
|
||||
"debug_ui": swap_client.debug_ui,
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user