generated from coulomb/repo-seed
Implement document proxy concept with archive/live views
- Add content hash (MD5) for document deduplication - Separate local state (archived) from server state (binectStatus) - Add archive toggle button to switch between live/archived views - Add archive/restore/delete actions for documents - Refactor pdf-queue.ts with DocumentProxy interface - Add hash.ts utility for content hashing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,8 @@ import { loadCredentials, saveCredentials, deleteCredentials, updateLastUse } fr
|
||||
import { uploadPDF, testConnection, BinectAPIError, Document } from '../utils/binect-api';
|
||||
import { fetchPDFBytes, DetectedPDF } from '../utils/pdf-detector';
|
||||
import { addTrackingEntry } from '../tracking/tracker';
|
||||
import { PDFQueueEntry, PDFStatus, PDFStatusMeta } from '../utils/pdf-queue';
|
||||
import { DocumentProxy, PDFQueueEntry, PDFStatus, PDFStatusMeta } from '../utils/pdf-queue';
|
||||
import { computeMD5 } from '../utils/hash';
|
||||
|
||||
// DOM Elements
|
||||
const authView = document.getElementById('authView')!;
|
||||
@@ -25,6 +26,9 @@ const loginBtn = document.getElementById('loginBtn') as HTMLButtonElement;
|
||||
const authError = document.getElementById('authError')!;
|
||||
|
||||
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;
|
||||
@@ -32,8 +36,9 @@ const eyeIcon = document.getElementById('eyeIcon')!;
|
||||
const eyeOffIcon = document.getElementById('eyeOffIcon')!;
|
||||
|
||||
// State
|
||||
let pdfQueue: PDFQueueEntry[] = [];
|
||||
let pdfQueue: DocumentProxy[] = [];
|
||||
let currentCredentials: { username: string; password: string } | null = null;
|
||||
let showingArchive = false; // false = live view, true = archive view
|
||||
|
||||
/**
|
||||
* Initialize popup
|
||||
@@ -76,11 +81,35 @@ async function init() {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle toggle between live and archive view
|
||||
*/
|
||||
async function handleToggleArchiveView() {
|
||||
showingArchive = !showingArchive;
|
||||
|
||||
// Update toggle button appearance
|
||||
if (showingArchive) {
|
||||
archiveIcon.style.display = 'none';
|
||||
liveIcon.style.display = 'block';
|
||||
archiveToggleBtn.title = 'Show live documents';
|
||||
archiveToggleBtn.classList.add('active');
|
||||
} else {
|
||||
archiveIcon.style.display = 'block';
|
||||
liveIcon.style.display = 'none';
|
||||
archiveToggleBtn.title = 'Show archived';
|
||||
archiveToggleBtn.classList.remove('active');
|
||||
}
|
||||
|
||||
// Reload the appropriate list
|
||||
await loadPDFQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle password visibility toggle
|
||||
*/
|
||||
@@ -152,43 +181,50 @@ async function handleLogin(e: Event) {
|
||||
* Load PDF queue from background and current tab
|
||||
*/
|
||||
async function loadPDFQueue() {
|
||||
console.log('[Popup] Loading PDF queue...');
|
||||
console.log('[Popup] Loading PDF queue, showingArchive:', showingArchive);
|
||||
|
||||
// Get all PDFs from background script (including completed ones)
|
||||
let response = await chrome.runtime.sendMessage({ action: 'getAllPDFs' });
|
||||
pdfQueue = response?.entries || [];
|
||||
console.log('[Popup] Got', pdfQueue.length, 'entries from background');
|
||||
if (showingArchive) {
|
||||
// Get archived proxies only
|
||||
const response = await chrome.runtime.sendMessage({ action: 'getArchivedProxies' });
|
||||
pdfQueue = response?.entries || [];
|
||||
console.log('[Popup] Got', pdfQueue.length, 'archived entries');
|
||||
} else {
|
||||
// Get live proxies
|
||||
let response = await chrome.runtime.sendMessage({ action: 'getLiveProxies' });
|
||||
pdfQueue = response?.entries || [];
|
||||
console.log('[Popup] Got', pdfQueue.length, 'live entries from background');
|
||||
|
||||
// Check current tab for PDF and add to persistent queue via background
|
||||
const currentTabPDF = await checkCurrentTabForPDF();
|
||||
if (currentTabPDF) {
|
||||
// Add via background service (will check for duplicates/dismissed)
|
||||
const addResult = await chrome.runtime.sendMessage({
|
||||
action: 'addPDF',
|
||||
pdf: currentTabPDF
|
||||
});
|
||||
if (addResult?.entry) {
|
||||
console.log('[Popup] Added current tab PDF to persistent queue:', currentTabPDF.filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: check recent downloads if queue is still empty
|
||||
if (pdfQueue.length === 0) {
|
||||
console.log('[Popup] Queue empty, checking recent downloads...');
|
||||
const recentPDFs = await checkRecentDownloads();
|
||||
for (const pdf of recentPDFs) {
|
||||
// Add each PDF via background service (will check for duplicates/dismissed)
|
||||
await chrome.runtime.sendMessage({
|
||||
// Check current tab for PDF and add to persistent queue via background
|
||||
const currentTabPDF = await checkCurrentTabForPDF();
|
||||
if (currentTabPDF) {
|
||||
// Add via background service (will check for duplicates)
|
||||
const addResult = await chrome.runtime.sendMessage({
|
||||
action: 'addPDF',
|
||||
pdf
|
||||
pdf: currentTabPDF
|
||||
});
|
||||
if (addResult?.entry) {
|
||||
console.log('[Popup] Added current tab PDF to persistent queue:', currentTabPDF.filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload queue after potential additions
|
||||
response = await chrome.runtime.sendMessage({ action: 'getAllPDFs' });
|
||||
pdfQueue = response?.entries || [];
|
||||
console.log('[Popup] Final queue count:', pdfQueue.length);
|
||||
// Fallback: check recent downloads if queue is still empty
|
||||
if (pdfQueue.length === 0) {
|
||||
console.log('[Popup] Queue empty, checking recent downloads...');
|
||||
const recentPDFs = await checkRecentDownloads();
|
||||
for (const pdf of recentPDFs) {
|
||||
// Add each PDF via background service (will check for duplicates)
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'addPDF',
|
||||
pdf
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Reload live queue after potential additions
|
||||
response = await chrome.runtime.sendMessage({ action: 'getLiveProxies' });
|
||||
pdfQueue = response?.entries || [];
|
||||
console.log('[Popup] Final live queue count:', pdfQueue.length);
|
||||
}
|
||||
|
||||
// Render the list
|
||||
renderPDFList();
|
||||
@@ -244,15 +280,6 @@ async function checkRecentDownloads(): Promise<DetectedPDF[]> {
|
||||
* Render the PDF list with grouped sections
|
||||
*/
|
||||
function renderPDFList() {
|
||||
// Group PDFs by status category
|
||||
const pendingUpload = pdfQueue.filter(p => p.status === 'pending' || p.status === 'uploading' || p.status === 'failed');
|
||||
const inBasket = pdfQueue.filter(p => p.status === 'in_basket' || p.status === 'ordering');
|
||||
const inProduction = pdfQueue.filter(p => p.status === 'in_production');
|
||||
const completed = pdfQueue.filter(p => p.status === 'sent' || p.status === 'canceled');
|
||||
|
||||
// Count actionable items
|
||||
const actionableCount = pendingUpload.length + inBasket.length;
|
||||
|
||||
if (pdfQueue.length === 0) {
|
||||
showNoPDF();
|
||||
return;
|
||||
@@ -261,46 +288,66 @@ function renderPDFList() {
|
||||
noPdfView.style.display = 'none';
|
||||
pdfListView.style.display = 'block';
|
||||
|
||||
// Update count
|
||||
if (actionableCount > 0) {
|
||||
pdfCount.textContent = `${actionableCount} PDF${actionableCount > 1 ? 's' : ''} need attention`;
|
||||
} else if (inProduction.length > 0) {
|
||||
pdfCount.textContent = `${inProduction.length} in production`;
|
||||
} else {
|
||||
pdfCount.textContent = `${completed.length} completed`;
|
||||
}
|
||||
|
||||
// Build HTML for each section
|
||||
let html = '';
|
||||
|
||||
if (pendingUpload.length > 0) {
|
||||
html += `<div class="pdf-section">
|
||||
<div class="pdf-section-header">Ready to Upload</div>
|
||||
${pendingUpload.map(pdf => renderPDFItem(pdf, 'pending')).join('')}
|
||||
</div>`;
|
||||
}
|
||||
if (showingArchive) {
|
||||
// Archive view - show all archived documents in a flat list
|
||||
pdfCount.textContent = `${pdfQueue.length} archived document${pdfQueue.length !== 1 ? 's' : ''}`;
|
||||
|
||||
if (inBasket.length > 0) {
|
||||
html += `<div class="pdf-section">
|
||||
<div class="pdf-section-header">In Basket</div>
|
||||
${inBasket.map(pdf => renderPDFItem(pdf, 'basket')).join('')}
|
||||
html = `<div class="pdf-section">
|
||||
<div class="pdf-section-header">Archived Documents</div>
|
||||
${pdfQueue.map(pdf => renderPDFItem(pdf, 'archived')).join('')}
|
||||
</div>`;
|
||||
}
|
||||
} else {
|
||||
// Live view - group by Binect status
|
||||
const pendingUpload = pdfQueue.filter(p => p.binectStatus === 'pending' || p.binectStatus === 'uploading' || p.binectStatus === 'failed');
|
||||
const inBasket = pdfQueue.filter(p => p.binectStatus === 'in_basket' || p.binectStatus === 'ordering');
|
||||
const inProduction = pdfQueue.filter(p => p.binectStatus === 'in_production');
|
||||
const completed = pdfQueue.filter(p => p.binectStatus === 'sent' || p.binectStatus === 'canceled');
|
||||
|
||||
if (inProduction.length > 0) {
|
||||
html += `<div class="pdf-section">
|
||||
<div class="pdf-section-header">In Production</div>
|
||||
${inProduction.map(pdf => renderPDFItem(pdf, 'production')).join('')}
|
||||
</div>`;
|
||||
}
|
||||
// Count actionable items
|
||||
const actionableCount = pendingUpload.length + inBasket.length;
|
||||
|
||||
if (completed.length > 0) {
|
||||
// Show only last 5 completed items
|
||||
const recentCompleted = completed.slice(0, 5);
|
||||
html += `<div class="pdf-section pdf-section-completed">
|
||||
<div class="pdf-section-header">Recently Completed</div>
|
||||
${recentCompleted.map(pdf => renderPDFItem(pdf, 'completed')).join('')}
|
||||
</div>`;
|
||||
// Update count
|
||||
if (actionableCount > 0) {
|
||||
pdfCount.textContent = `${actionableCount} PDF${actionableCount > 1 ? 's' : ''} need attention`;
|
||||
} else if (inProduction.length > 0) {
|
||||
pdfCount.textContent = `${inProduction.length} in production`;
|
||||
} else if (completed.length > 0) {
|
||||
pdfCount.textContent = `${completed.length} completed`;
|
||||
} else {
|
||||
pdfCount.textContent = 'No documents';
|
||||
}
|
||||
|
||||
if (pendingUpload.length > 0) {
|
||||
html += `<div class="pdf-section">
|
||||
<div class="pdf-section-header">Ready to Upload</div>
|
||||
${pendingUpload.map(pdf => renderPDFItem(pdf, 'pending')).join('')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (inBasket.length > 0) {
|
||||
html += `<div class="pdf-section">
|
||||
<div class="pdf-section-header">In Basket</div>
|
||||
${inBasket.map(pdf => renderPDFItem(pdf, 'basket')).join('')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (inProduction.length > 0) {
|
||||
html += `<div class="pdf-section">
|
||||
<div class="pdf-section-header">In Production</div>
|
||||
${inProduction.map(pdf => renderPDFItem(pdf, 'production')).join('')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (completed.length > 0) {
|
||||
// Show only last 5 completed items in live view
|
||||
const recentCompleted = completed.slice(0, 5);
|
||||
html += `<div class="pdf-section pdf-section-completed">
|
||||
<div class="pdf-section-header">Recently Completed</div>
|
||||
${recentCompleted.map(pdf => renderPDFItem(pdf, 'completed')).join('')}
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
pdfList.innerHTML = html;
|
||||
@@ -313,8 +360,8 @@ function renderPDFList() {
|
||||
/**
|
||||
* Render a single PDF item
|
||||
*/
|
||||
function renderPDFItem(pdf: PDFQueueEntry, section: 'pending' | 'basket' | 'production' | 'completed'): string {
|
||||
const statusClass = getStatusClass(pdf.status);
|
||||
function renderPDFItem(pdf: DocumentProxy, section: 'pending' | 'basket' | 'production' | 'completed' | 'archived'): string {
|
||||
const statusClass = getStatusClass(pdf.binectStatus);
|
||||
const statusText = getStatusText(pdf);
|
||||
const priceText = pdf.price ? `${(pdf.price / 100).toFixed(2)} €` : '';
|
||||
|
||||
@@ -323,34 +370,42 @@ function renderPDFItem(pdf: PDFQueueEntry, section: 'pending' | 'basket' | 'prod
|
||||
switch (section) {
|
||||
case 'pending':
|
||||
actionsHtml = `
|
||||
<button class="btn-send-item" data-id="${escapeHtml(pdf.id)}" ${pdf.status === 'uploading' ? 'disabled' : ''}>
|
||||
${pdf.status === 'uploading' ? 'Uploading...' : (pdf.status === 'failed' ? 'Retry' : 'Upload')}
|
||||
<button class="btn-send-item" data-id="${escapeHtml(pdf.id)}" ${pdf.binectStatus === 'uploading' ? 'disabled' : ''}>
|
||||
${pdf.binectStatus === 'uploading' ? 'Uploading...' : (pdf.binectStatus === 'failed' ? 'Retry' : 'Upload')}
|
||||
</button>
|
||||
<button class="btn-dismiss" data-id="${escapeHtml(pdf.id)}">Dismiss</button>
|
||||
<button class="btn-archive" data-id="${escapeHtml(pdf.id)}">Archive</button>
|
||||
`;
|
||||
break;
|
||||
case 'basket':
|
||||
actionsHtml = `
|
||||
<button class="btn-order-item" data-id="${escapeHtml(pdf.id)}" ${pdf.status === 'ordering' ? 'disabled' : ''}>
|
||||
${pdf.status === 'ordering' ? 'Ordering...' : 'Order'}
|
||||
<button class="btn-order-item" data-id="${escapeHtml(pdf.id)}" ${pdf.binectStatus === 'ordering' ? 'disabled' : ''}>
|
||||
${pdf.binectStatus === 'ordering' ? 'Ordering...' : 'Order'}
|
||||
</button>
|
||||
<button class="btn-dismiss" data-id="${escapeHtml(pdf.id)}">Cancel</button>
|
||||
<button class="btn-archive" data-id="${escapeHtml(pdf.id)}">Archive</button>
|
||||
`;
|
||||
break;
|
||||
case 'production':
|
||||
// No individual actions - use global refresh button in header
|
||||
actionsHtml = '';
|
||||
// Archive button only
|
||||
actionsHtml = `
|
||||
<button class="btn-archive" data-id="${escapeHtml(pdf.id)}">Archive</button>
|
||||
`;
|
||||
break;
|
||||
case 'completed':
|
||||
actionsHtml = `
|
||||
<button class="btn-dismiss btn-remove" data-id="${escapeHtml(pdf.id)}">Remove</button>
|
||||
<button class="btn-archive" data-id="${escapeHtml(pdf.id)}">Archive</button>
|
||||
`;
|
||||
break;
|
||||
case 'archived':
|
||||
actionsHtml = `
|
||||
<button class="btn-restore" data-id="${escapeHtml(pdf.id)}">Restore</button>
|
||||
<button class="btn-dismiss btn-remove" data-id="${escapeHtml(pdf.id)}">Delete</button>
|
||||
`;
|
||||
break;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="pdf-list-item ${statusClass}" data-id="${escapeHtml(pdf.id)}">
|
||||
<div class="pdf-item-icon">${getStatusIcon(pdf.status)}</div>
|
||||
<div class="pdf-item-icon">${getStatusIcon(pdf.binectStatus)}</div>
|
||||
<div class="pdf-item-details">
|
||||
<div class="pdf-item-filename" title="${escapeHtml(pdf.filename)}">${escapeHtml(pdf.filename)}</div>
|
||||
<div class="pdf-item-meta">
|
||||
@@ -387,11 +442,27 @@ function setupPDFListEventListeners() {
|
||||
});
|
||||
});
|
||||
|
||||
// Dismiss/Cancel/Remove buttons
|
||||
// Archive buttons
|
||||
pdfList.querySelectorAll('.btn-archive').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const id = (e.target as HTMLElement).dataset.id;
|
||||
if (id) handleArchivePDF(id);
|
||||
});
|
||||
});
|
||||
|
||||
// Restore buttons
|
||||
pdfList.querySelectorAll('.btn-restore').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const id = (e.target as HTMLElement).dataset.id;
|
||||
if (id) handleRestorePDF(id);
|
||||
});
|
||||
});
|
||||
|
||||
// Delete/Remove buttons
|
||||
pdfList.querySelectorAll('.btn-dismiss').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const id = (e.target as HTMLElement).dataset.id;
|
||||
if (id) handleDismissPDF(id);
|
||||
if (id) handleDeletePDF(id);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -399,8 +470,8 @@ function setupPDFListEventListeners() {
|
||||
/**
|
||||
* Get status text for a PDF
|
||||
*/
|
||||
function getStatusText(pdf: PDFQueueEntry): string {
|
||||
switch (pdf.status) {
|
||||
function getStatusText(pdf: DocumentProxy): string {
|
||||
switch (pdf.binectStatus) {
|
||||
case 'pending':
|
||||
return formatTimestamp(pdf.timestamp);
|
||||
case 'uploading':
|
||||
@@ -483,7 +554,7 @@ async function handleSendPDF(id: string) {
|
||||
}
|
||||
|
||||
// Update local state
|
||||
pdf.status = 'uploading';
|
||||
pdf.binectStatus = 'uploading';
|
||||
renderPDFList();
|
||||
|
||||
// Notify background
|
||||
@@ -497,6 +568,9 @@ async function handleSendPDF(id: string) {
|
||||
// Fetch PDF bytes
|
||||
const pdfBytes = await fetchPDFBytes(pdf.url);
|
||||
|
||||
// Compute content hash for deduplication
|
||||
const contentHash = await computeMD5(pdfBytes);
|
||||
|
||||
// Upload to Binect with credentials
|
||||
const document = await uploadPDF(
|
||||
pdfBytes,
|
||||
@@ -521,7 +595,8 @@ async function handleSendPDF(id: string) {
|
||||
const meta: PDFStatusMeta = {
|
||||
binectDocumentId: document.id,
|
||||
binectStatus: document.status.code,
|
||||
binectStatusText: document.status.text
|
||||
binectStatusText: document.status.text,
|
||||
contentHash
|
||||
};
|
||||
|
||||
if (document.letter?.letterData) {
|
||||
@@ -538,10 +613,11 @@ async function handleSendPDF(id: string) {
|
||||
});
|
||||
|
||||
// Update local state
|
||||
pdf.status = 'in_basket';
|
||||
pdf.binectStatus = 'in_basket';
|
||||
pdf.binectDocumentId = document.id;
|
||||
pdf.binectStatus = document.status.code;
|
||||
pdf.binectStatusCode = document.status.code;
|
||||
pdf.binectStatusText = document.status.text;
|
||||
pdf.contentHash = contentHash;
|
||||
if (document.letter?.letterData) {
|
||||
pdf.price = document.letter.letterData.price?.priceAfterTax;
|
||||
pdf.recipientAddress = document.letter.letterData.recipientAddress;
|
||||
@@ -591,7 +667,7 @@ async function handleSendPDF(id: string) {
|
||||
});
|
||||
|
||||
// Update local state
|
||||
pdf.status = 'failed';
|
||||
pdf.binectStatus = 'failed';
|
||||
pdf.errorMessage = errorMessage;
|
||||
renderPDFList();
|
||||
|
||||
@@ -609,7 +685,7 @@ async function handleOrderPDF(id: string) {
|
||||
}
|
||||
|
||||
// Update local state
|
||||
pdf.status = 'ordering';
|
||||
pdf.binectStatus = 'ordering';
|
||||
renderPDFList();
|
||||
|
||||
// Notify background
|
||||
@@ -646,8 +722,8 @@ async function handleOrderPDF(id: string) {
|
||||
});
|
||||
|
||||
// Update local state
|
||||
pdf.status = 'in_production';
|
||||
pdf.binectStatus = result.status;
|
||||
pdf.binectStatus = 'in_production';
|
||||
pdf.binectStatusCode = result.status;
|
||||
pdf.binectStatusText = result.statusText;
|
||||
renderPDFList();
|
||||
|
||||
@@ -670,7 +746,7 @@ async function handleOrderPDF(id: string) {
|
||||
});
|
||||
|
||||
// Update local state
|
||||
pdf.status = 'in_basket';
|
||||
pdf.binectStatus = 'in_basket';
|
||||
pdf.errorMessage = errorMessage;
|
||||
renderPDFList();
|
||||
|
||||
@@ -689,7 +765,7 @@ async function handleRefreshAll() {
|
||||
// Find all documents that have been uploaded and are still visible
|
||||
const uploadedDocs = pdfQueue.filter(p =>
|
||||
p.binectDocumentId &&
|
||||
(p.status === 'in_basket' || p.status === 'in_production')
|
||||
(p.binectStatus === 'in_basket' || p.binectStatus === 'in_production')
|
||||
);
|
||||
|
||||
if (uploadedDocs.length === 0) {
|
||||
@@ -748,7 +824,7 @@ async function handleRefreshStatus(id: string) {
|
||||
}
|
||||
|
||||
// Determine new local status based on Binect status code
|
||||
let newStatus: PDFStatus = pdf.status;
|
||||
let newStatus: PDFStatus = pdf.binectStatus;
|
||||
if (result.status === 5) {
|
||||
newStatus = 'sent';
|
||||
} else if (result.status === 6) {
|
||||
@@ -775,8 +851,8 @@ async function handleRefreshStatus(id: string) {
|
||||
});
|
||||
|
||||
// Update local state
|
||||
pdf.status = newStatus;
|
||||
pdf.binectStatus = result.status;
|
||||
pdf.binectStatus = newStatus;
|
||||
pdf.binectStatusCode = result.status;
|
||||
pdf.binectStatusText = result.statusText;
|
||||
if (result.price) pdf.price = result.price;
|
||||
if (result.recipientAddress) pdf.recipientAddress = result.recipientAddress;
|
||||
@@ -795,20 +871,32 @@ async function handleRefreshStatus(id: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dismiss PDF
|
||||
* Handle archive PDF (move from live to archive)
|
||||
*/
|
||||
async function handleDismissPDF(id: string) {
|
||||
const pdf = pdfQueue.find(p => p.id === id);
|
||||
if (!pdf) return;
|
||||
async function handleArchivePDF(id: string) {
|
||||
await chrome.runtime.sendMessage({ action: 'archiveProxy', id });
|
||||
pdfQueue = pdfQueue.filter(p => p.id !== id);
|
||||
renderPDFList();
|
||||
showStatus('Document archived', 'success');
|
||||
setTimeout(() => hideStatus(), 2000);
|
||||
}
|
||||
|
||||
// For pending/failed/in_basket items, mark as dismissed to prevent re-showing
|
||||
// For completed items (sent/canceled), actually remove from storage
|
||||
if (pdf.status === 'sent' || pdf.status === 'canceled') {
|
||||
await chrome.runtime.sendMessage({ action: 'removePDF', id });
|
||||
} else {
|
||||
await chrome.runtime.sendMessage({ action: 'dismissPDF', id });
|
||||
}
|
||||
/**
|
||||
* Handle restore PDF (move from archive to live)
|
||||
*/
|
||||
async function handleRestorePDF(id: string) {
|
||||
await chrome.runtime.sendMessage({ action: 'restoreProxy', id });
|
||||
pdfQueue = pdfQueue.filter(p => p.id !== id);
|
||||
renderPDFList();
|
||||
showStatus('Document restored', 'success');
|
||||
setTimeout(() => hideStatus(), 2000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle delete PDF (permanently remove)
|
||||
*/
|
||||
async function handleDeletePDF(id: string) {
|
||||
await chrome.runtime.sendMessage({ action: 'removePDF', id });
|
||||
pdfQueue = pdfQueue.filter(p => p.id !== id);
|
||||
renderPDFList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user