Merge pull request #385 from gerlofvanek/update-fix

Fix Update notification.
This commit is contained in:
tecnovert
2025-10-21 15:11:08 +00:00
committed by GitHub
5 changed files with 82 additions and 2 deletions

View File

@@ -1509,6 +1509,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
try: try:
if version_tuple(latest_tag) > version_tuple(current_version): if version_tuple(latest_tag) > version_tuple(current_version):
self._latest_version = latest_tag
if not self._update_available: if not self._update_available:
self._update_available = True self._update_available = True
self.log.info( self.log.info(
@@ -1528,6 +1529,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
self.log.info(f"Update v{latest_tag} already notified") self.log.info(f"Update v{latest_tag} already notified")
else: else:
self._update_available = False self._update_available = False
self._latest_version = None
self.log.info(f"BasicSwap is up to date (v{current_version})") self.log.info(f"BasicSwap is up to date (v{current_version})")
except ValueError as e: except ValueError as e:
self.log.warning(f"Error comparing versions: {e}") self.log.warning(f"Error comparing versions: {e}")
@@ -2026,6 +2028,13 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
if self.ws_server and show_event: if self.ws_server and show_event:
self.ws_server.send_message_to_all(json.dumps(event_data)) self.ws_server.send_message_to_all(json.dumps(event_data))
elif event_type == NT.UPDATE_AVAILABLE:
self.log.info(
f"Update available: v{event_data.get('latest_version', 'unknown')}"
)
if self.ws_server and show_event:
event_data["event"] = "update_available"
self.ws_server.send_message_to_all(json.dumps(event_data))
else: else:
self.log.warning(f"Unknown notification {event_type}") self.log.warning(f"Unknown notification {event_type}")
@@ -11260,6 +11269,16 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
settings_copy["notifications_outgoing_transactions"] = new_value settings_copy["notifications_outgoing_transactions"] = new_value
settings_changed = True settings_changed = True
if "notifications_swap_completed" in data:
new_value = data["notifications_swap_completed"]
ensure(
isinstance(new_value, bool),
"New notifications_swap_completed value not boolean",
)
if settings_copy.get("notifications_swap_completed", True) != new_value:
settings_copy["notifications_swap_completed"] = new_value
settings_changed = True
if "notifications_duration" in data: if "notifications_duration" in data:
new_value = data["notifications_duration"] new_value = data["notifications_duration"]
ensure( ensure(
@@ -11274,6 +11293,15 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
settings_copy["notifications_duration"] = new_value settings_copy["notifications_duration"] = new_value
settings_changed = True settings_changed = True
if "check_updates" in data:
new_value = data["check_updates"]
ensure(
isinstance(new_value, bool), "New check_updates value not boolean"
)
if settings_copy.get("check_updates", True) != new_value:
settings_copy["check_updates"] = new_value
settings_changed = True
if settings_changed: if settings_changed:
settings_path = os.path.join(self.data_dir, cfg.CONFIG_FILENAME) settings_path = os.path.join(self.data_dir, cfg.CONFIG_FILENAME)
settings_path_new = settings_path + ".new" settings_path_new = settings_path + ".new"

View File

@@ -952,6 +952,32 @@ def js_notifications(self, url_split, post_string, is_json) -> bytes:
return bytes(json.dumps(swap_client.getNotifications()), "UTF-8") return bytes(json.dumps(swap_client.getNotifications()), "UTF-8")
def js_updatestatus(self, url_split, post_string, is_json) -> bytes:
swap_client = self.server.swap_client
from basicswap import __version__
return bytes(
json.dumps(
{
"update_available": swap_client._update_available,
"current_version": __version__,
"latest_version": swap_client._latest_version,
"release_url": (
f"https://github.com/basicswap/basicswap/releases/tag/v{swap_client._latest_version}"
if swap_client._latest_version
else None
),
"release_notes": (
f"New version v{swap_client._latest_version} is available. Click to view details on GitHub."
if swap_client._latest_version
else None
),
}
),
"UTF-8",
)
def js_identities(self, url_split, post_string: str, is_json: bool) -> bytes: def js_identities(self, url_split, post_string: str, is_json: bool) -> bytes:
swap_client = self.server.swap_client swap_client = self.server.swap_client
swap_client.checkSystemStatus() swap_client.checkSystemStatus()
@@ -1559,6 +1585,7 @@ endpoints = {
"rateslist": js_rates_list, "rateslist": js_rates_list,
"generatenotification": js_generatenotification, "generatenotification": js_generatenotification,
"checkupdates": js_checkupdates, "checkupdates": js_checkupdates,
"updatestatus": js_updatestatus,
"notifications": js_notifications, "notifications": js_notifications,
"identities": js_identities, "identities": js_identities,
"automationstrategies": js_automationstrategies, "automationstrategies": js_automationstrategies,

View File

@@ -321,6 +321,7 @@ function ensureToastContainer() {
updateHistoryDropdown(); updateHistoryDropdown();
this.initializeBalanceTracking(); this.initializeBalanceTracking();
this.checkForPendingUpdateNotification();
if (window.CleanupManager) { if (window.CleanupManager) {
window.CleanupManager.registerResource('notificationManager', this, (mgr) => { window.CleanupManager.registerResource('notificationManager', this, (mgr) => {
@@ -331,6 +332,29 @@ function ensureToastContainer() {
return this; return this;
}, },
checkForPendingUpdateNotification: function() {
CleanupManager.setTimeout(async () => {
try {
const response = await fetch('/json/updatestatus');
const updateStatus = await response.json();
if (updateStatus.update_available && config.showUpdateNotifications) {
this.createToast(
`Update Available: v${updateStatus.latest_version}`,
'update_available',
{
subtitle: `Current: v${updateStatus.current_version} • Click to view release`,
releaseUrl: updateStatus.release_url,
releaseNotes: updateStatus.release_notes
}
);
}
} catch (error) {
console.error('Error checking for pending update notification:', error);
}
}, 2000);
},
updateSettings: function(newSettings) { updateSettings: function(newSettings) {
saveConfig(newSettings); saveConfig(newSettings);
return this; return this;

View File

@@ -492,7 +492,7 @@
<div class="py-2"> <div class="py-2">
<div class="flex items-center"> <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 %}> <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 notification_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> <label for="check_updates" class="ml-3 text-sm font-medium text-gray-700 dark:text-gray-300">Update Notifications</label>
<button type="button" data-check-updates 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"> <button type="button" data-check-updates 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 Check Now

View File

@@ -92,7 +92,7 @@ def page_settings(self, url_split, post_string):
get_data_entry_or(form_data, "notifications_duration", "20") get_data_entry_or(form_data, "notifications_duration", "20")
), ),
"check_updates": toBool( "check_updates": toBool(
get_data_entry_or(form_data, "check_updates", "true") get_data_entry_or(form_data, "check_updates", "false")
), ),
} }
swap_client.editGeneralSettings(data) swap_client.editGeneralSettings(data)
@@ -242,6 +242,7 @@ def page_settings(self, url_split, post_string):
"notifications_duration": swap_client.settings.get( "notifications_duration": swap_client.settings.get(
"notifications_duration", 20 "notifications_duration", 20
), ),
"check_updates": swap_client.settings.get("check_updates", True),
} }
tor_control_password = ( tor_control_password = (