diff --git a/src/background/service-worker.ts b/src/background/service-worker.ts index 051ef53..811f05e 100644 --- a/src/background/service-worker.ts +++ b/src/background/service-worker.ts @@ -256,9 +256,12 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { sendResponse({ success: true, ...result }); }) .catch(error => { + // Include error code for 404 detection + const errorCode = (error as { statusCode?: number }).statusCode; sendResponse({ success: false, - error: error instanceof Error ? error.message : 'Failed to get status' + error: error instanceof Error ? error.message : 'Failed to get status', + errorCode }); }); return true; diff --git a/src/popup/popup.html b/src/popup/popup.html index 7a3a72c..9f1ca5b 100644 --- a/src/popup/popup.html +++ b/src/popup/popup.html @@ -22,13 +22,6 @@ - diff --git a/src/popup/popup.ts b/src/popup/popup.ts index 18425a5..9e483cc 100644 --- a/src/popup/popup.ts +++ b/src/popup/popup.ts @@ -29,7 +29,6 @@ const logoutBtn = document.getElementById('logoutBtn')!; const archiveToggleBtn = document.getElementById('archiveToggleBtn')!; const archiveIcon = document.getElementById('archiveIcon')!; const liveIcon = document.getElementById('liveIcon')!; -const refreshBtn = document.getElementById('refreshBtn')!; const helpBtn = document.getElementById('helpBtn')!; const togglePasswordBtn = document.getElementById('togglePassword') as HTMLButtonElement; const eyeIcon = document.getElementById('eyeIcon')!; @@ -87,9 +86,16 @@ function setupEventListeners() { loginForm.addEventListener('submit', handleLogin); logoutBtn.addEventListener('click', handleLogout); archiveToggleBtn.addEventListener('click', handleToggleArchiveView); - refreshBtn.addEventListener('click', handleRefreshAll); helpBtn.addEventListener('click', handleHelp); - togglePasswordBtn.addEventListener('click', handleTogglePassword); + + // Password toggle - ensure button exists and attach handler + if (togglePasswordBtn) { + togglePasswordBtn.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + handleTogglePassword(); + }); + } } /** @@ -434,7 +440,7 @@ function renderPDFItem(pdf: DocumentProxy, section: 'pending' | 'basket' | 'prod case 'basket': actionsHtml = ` `; @@ -539,7 +545,7 @@ function getStatusText(pdf: DocumentProxy): string { case 'in_basket': return pdf.binectStatusText || 'Ready to order'; case 'ordering': - return 'Ordering...'; + return 'Sending...'; case 'in_production': return pdf.binectStatusText || 'In production'; case 'sent': @@ -788,7 +794,7 @@ async function handleOrderPDF(id: string) { pdf.binectStatusText = result.statusText; renderPDFList(); - showStatus('Order placed! Document is in production.', 'success'); + showStatus('Sent! Document is in production.', 'success'); // Start auto-refresh sequence startAutoRefresh(); @@ -799,7 +805,7 @@ async function handleOrderPDF(id: string) { }, 3000); } catch (error) { - const errorMessage = error instanceof Error ? error.message : 'Order failed'; + const errorMessage = error instanceof Error ? error.message : 'Send failed'; // Revert to in_basket status await chrome.runtime.sendMessage({ @@ -833,14 +839,10 @@ async function handleRefreshAll() { ); if (uploadedDocs.length === 0) { - showStatus('No documents to refresh', 'success'); - setTimeout(() => hideStatus(), 2000); return; } - // Disable refresh button during refresh - refreshBtn.classList.add('refreshing'); - showStatus(`Refreshing ${uploadedDocs.length} document${uploadedDocs.length > 1 ? 's' : ''}...`, 'uploading'); + console.log(`[Popup] Refreshing ${uploadedDocs.length} document(s)...`); let successCount = 0; let errorCount = 0; @@ -854,15 +856,9 @@ async function handleRefreshAll() { } } - refreshBtn.classList.remove('refreshing'); - - if (errorCount === 0) { - showStatus(`Refreshed ${successCount} document${successCount > 1 ? 's' : ''}`, 'success'); - } else { - showStatus(`Refreshed ${successCount}, ${errorCount} failed`, 'error'); + if (errorCount > 0) { + console.log(`[Popup] Refresh complete: ${successCount} ok, ${errorCount} failed`); } - - setTimeout(() => hideStatus(), 3000); } /** @@ -884,6 +880,13 @@ async function handleRefreshStatus(id: string) { }); if (!result.success) { + // Check if document was deleted on server (404) + if (result.errorCode === 404) { + console.log('[Popup] Document deleted on server, archiving:', id); + await handleArchivePDF(id); + showStatus('Document no longer exists on server', 'error'); + return; + } throw new Error(result.error || 'Failed to get status'); } @@ -922,15 +925,9 @@ async function handleRefreshStatus(id: string) { if (result.recipientAddress) pdf.recipientAddress = result.recipientAddress; renderPDFList(); - showStatus(`Status: ${result.statusText}`, 'success'); - - setTimeout(() => { - hideStatus(); - }, 3000); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : 'Failed to refresh'; - showStatus(errorMessage, 'error'); + console.error('[Popup] Refresh error:', error); + // Only show errors that aren't already handled (like 404) } } diff --git a/src/utils/binect-api.ts b/src/utils/binect-api.ts index cfcbb66..060c248 100644 --- a/src/utils/binect-api.ts +++ b/src/utils/binect-api.ts @@ -445,6 +445,10 @@ export async function getDocumentStatus( } if (error instanceof BinectApiError) { + // Check for 404 - document not found (deleted on server) + if (error.status === 404) { + throw new BinectAPIError('Document not found on server', 404); + } throw BinectAPIError.fromBinectError(error); }