From ef734246ccd4519eaf85d16a21696d6ba9b47f61 Mon Sep 17 00:00:00 2001 From: Broque Thomas Date: Thu, 24 Jul 2025 18:37:21 -0700 Subject: [PATCH] good --- ui/pages/sync.py | 56 +++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/ui/pages/sync.py b/ui/pages/sync.py index a4dedb23..18ecf8ff 100644 --- a/ui/pages/sync.py +++ b/ui/pages/sync.py @@ -278,13 +278,14 @@ class SyncStatusProcessingWorkerSignals(QObject): class SyncStatusProcessingWorker(QRunnable): """ Runs download status processing in a background thread for the sync modal. - It checks the slskd API and returns a list of updates for the main thread. + It checks the slskd API and the file system to provide a reliable status. """ - def __init__(self, soulseek_client, download_items_data): + def __init__(self, soulseek_client, download_items_data, transfers_directory): super().__init__() self.signals = SyncStatusProcessingWorkerSignals() self.soulseek_client = soulseek_client self.download_items_data = download_items_data + self.transfers_directory = transfers_directory # NEW: Pass the transfers directory def run(self): """The main logic of the background worker.""" @@ -300,8 +301,7 @@ class SyncStatusProcessingWorker(QRunnable): results = [] if not transfers_data: - self.signals.completed.emit([]) - return + transfers_data = [] all_transfers = [ file for user_data in transfers_data if 'directories' in user_data @@ -314,20 +314,11 @@ class SyncStatusProcessingWorker(QRunnable): for item_data in self.download_items_data: matching_transfer = transfers_by_id.get(item_data['download_id']) - if not matching_transfer: - import os - dl_filename = os.path.basename(item_data['file_path']).lower() - for t in all_transfers: - if os.path.basename(t.get('filename', '')).lower() == dl_filename: - matching_transfer = t - break - if matching_transfer: state = matching_transfer.get('state', 'Unknown') progress = matching_transfer.get('percentComplete', 0) new_status = 'queued' - # Correct order of checks: Terminal states first. if 'Cancelled' in state or 'Canceled' in state: new_status = 'cancelled' elif 'Failed' in state or 'Errored' in state: @@ -340,7 +331,7 @@ class SyncStatusProcessingWorker(QRunnable): new_status = 'queued' payload = { - 'widget_id': item_data['widget_id'], # This will be the download_index + 'widget_id': item_data['widget_id'], 'status': new_status, 'progress': int(progress), 'transfer_id': matching_transfer.get('id'), @@ -348,15 +339,34 @@ class SyncStatusProcessingWorker(QRunnable): } results.append(payload) else: - # Handle downloads that disappear from the API - item_data['api_missing_count'] = item_data.get('api_missing_count', 0) + 1 - if item_data['api_missing_count'] >= 3: + # --- NEW LOGIC: Check file system for completed downloads --- + # The download is no longer in the API. Check if the file exists. + import os + expected_filename = os.path.basename(item_data['file_path']) + expected_filepath = os.path.join(self.transfers_directory, expected_filename) + + if os.path.exists(expected_filepath): + # File exists! The download was successful. + print(f"✅ Verified completed download via file system: {expected_filename}") payload = { 'widget_id': item_data['widget_id'], - 'status': 'failed', + 'status': 'completed', + 'progress': 100, 'transfer_id': item_data['download_id'], } results.append(payload) + else: + # File doesn't exist. It might be a genuine failure. + # Use the existing counter logic as a fallback. + item_data['api_missing_count'] = item_data.get('api_missing_count', 0) + 1 + if item_data['api_missing_count'] >= 3: # After 3 checks (6 seconds) + print(f"❌ Download {item_data['download_id']} failed (missing from API and file system).") + payload = { + 'widget_id': item_data['widget_id'], + 'status': 'failed', + 'transfer_id': item_data['download_id'], + } + results.append(payload) self.signals.completed.emit(results) except Exception as e: @@ -364,6 +374,8 @@ class SyncStatusProcessingWorker(QRunnable): traceback.print_exc() self.signals.error.emit(str(e)) + + class PlaylistLoaderThread(QThread): playlist_loaded = pyqtSignal(object) # Single playlist loading_finished = pyqtSignal(int) # Total count @@ -3117,12 +3129,16 @@ class DownloadMissingTracksModal(QDialog): if not items_to_check: self._is_status_update_running = False return - - worker = SyncStatusProcessingWorker(self.parent_page.soulseek_client, items_to_check) + + # NEW: Get the transfers directory and pass it to the worker + transfers_dir = self.downloads_page.transfers_directory + worker = SyncStatusProcessingWorker(self.parent_page.soulseek_client, items_to_check, transfers_dir) + worker.signals.completed.connect(self._handle_processed_status_updates) worker.signals.error.connect(lambda e: print(f"Status Worker Error: {e}")) self.download_status_pool.start(worker) + def _handle_processed_status_updates(self, results): """Applies status updates and triggers retry logic.""" import time