mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-13 17:54:19 +01:00
feat: Add alerts for attachment extraction status and improve UI state handling after processing.
feat: add page and document level support for adding atttachments
This commit is contained in:
1 parent
98467f4809
commit
bd985f06f8
4 files changed
+477
-280
No files matched your search
@@ -43,6 +43,22 @@ export async function addAttachments() {
|
||||
return;
|
||||
}
|
||||
|
||||
const attachmentLevel = (
|
||||
document.querySelector('input[name="attachment-level"]:checked') as HTMLInputElement
|
||||
)?.value || 'document';
|
||||
|
||||
let pageRange: string = '';
|
||||
|
||||
if (attachmentLevel === 'page') {
|
||||
const pageRangeInput = document.getElementById('attachment-page-range') as HTMLInputElement;
|
||||
pageRange = pageRangeInput?.value?.trim() || '';
|
||||
|
||||
if (!pageRange) {
|
||||
showAlert('Error', 'Please specify a page range for page-level attachments.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
showLoader('Embedding files into PDF...');
|
||||
try {
|
||||
const pdfFile = state.files[0];
|
||||
@@ -54,7 +70,7 @@ export async function addAttachments() {
|
||||
for (let i = 0; i < attachments.length; i++) {
|
||||
const file = attachments[i];
|
||||
showLoader(`Reading ${file.name} (${i + 1}/${attachments.length})...`);
|
||||
|
||||
|
||||
const fileBuffer = (await readFileAsArrayBuffer(file)) as ArrayBuffer;
|
||||
attachmentBuffers.push(fileBuffer);
|
||||
attachmentNames.push(file.name);
|
||||
@@ -66,7 +82,9 @@ export async function addAttachments() {
|
||||
command: 'add-attachments',
|
||||
pdfBuffer: pdfBuffer,
|
||||
attachmentBuffers: attachmentBuffers,
|
||||
attachmentNames: attachmentNames
|
||||
attachmentNames: attachmentNames,
|
||||
attachmentLevel: attachmentLevel,
|
||||
pageRange: pageRange
|
||||
};
|
||||
|
||||
const transferables = [pdfBuffer, ...attachmentBuffers];
|
||||
@@ -89,6 +107,8 @@ function clearAttachments() {
|
||||
const processBtn = document.getElementById(
|
||||
'process-btn'
|
||||
) as HTMLButtonElement;
|
||||
const attachmentLevelOptions = document.getElementById('attachment-level-options');
|
||||
const pageRangeWrapper = document.getElementById('page-range-wrapper');
|
||||
|
||||
if (fileListDiv) fileListDiv.innerHTML = '';
|
||||
if (attachmentInput) attachmentInput.value = '';
|
||||
@@ -96,14 +116,20 @@ function clearAttachments() {
|
||||
processBtn.disabled = true;
|
||||
processBtn.classList.add('hidden');
|
||||
}
|
||||
if (attachmentLevelOptions) {
|
||||
attachmentLevelOptions.classList.add('hidden');
|
||||
}
|
||||
if (pageRangeWrapper) {
|
||||
pageRangeWrapper.classList.add('hidden');
|
||||
}
|
||||
|
||||
const documentRadio = document.querySelector('input[name="attachment-level"][value="document"]') as HTMLInputElement;
|
||||
if (documentRadio) {
|
||||
documentRadio.checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
let isSetup = false; // Prevent duplicate setup
|
||||
|
||||
export function setupAddAttachmentsTool() {
|
||||
if (isSetup) return; // Already set up
|
||||
isSetup = true;
|
||||
|
||||
const optionsDiv = document.getElementById('attachment-options');
|
||||
const attachmentInput = document.getElementById(
|
||||
'attachment-files-input'
|
||||
@@ -112,6 +138,9 @@ export function setupAddAttachmentsTool() {
|
||||
const processBtn = document.getElementById(
|
||||
'process-btn'
|
||||
) as HTMLButtonElement;
|
||||
const attachmentLevelOptions = document.getElementById('attachment-level-options');
|
||||
const pageRangeWrapper = document.getElementById('page-range-wrapper');
|
||||
const totalPagesSpan = document.getElementById('attachment-total-pages');
|
||||
|
||||
if (!optionsDiv || !attachmentInput || !fileListDiv || !processBtn) {
|
||||
console.error('Attachment tool UI elements not found.');
|
||||
@@ -125,6 +154,13 @@ export function setupAddAttachmentsTool() {
|
||||
|
||||
optionsDiv.classList.remove('hidden');
|
||||
|
||||
if (totalPagesSpan && state.pdfDoc) {
|
||||
totalPagesSpan.textContent = state.pdfDoc.getPageCount().toString();
|
||||
}
|
||||
|
||||
if (attachmentInput.dataset.listenerAttached) return;
|
||||
attachmentInput.dataset.listenerAttached = 'true';
|
||||
|
||||
attachmentInput.addEventListener('change', (e) => {
|
||||
const files = (e.target as HTMLInputElement).files;
|
||||
if (files && files.length > 0) {
|
||||
@@ -149,6 +185,10 @@ export function setupAddAttachmentsTool() {
|
||||
fileListDiv.appendChild(div);
|
||||
});
|
||||
|
||||
if (attachmentLevelOptions) {
|
||||
attachmentLevelOptions.classList.remove('hidden');
|
||||
}
|
||||
|
||||
processBtn.disabled = false;
|
||||
processBtn.classList.remove('hidden');
|
||||
} else {
|
||||
@@ -156,5 +196,17 @@ export function setupAddAttachmentsTool() {
|
||||
}
|
||||
});
|
||||
|
||||
const attachmentLevelRadios = document.querySelectorAll('input[name="attachment-level"]');
|
||||
attachmentLevelRadios.forEach((radio) => {
|
||||
radio.addEventListener('change', (e) => {
|
||||
const value = (e.target as HTMLInputElement).value;
|
||||
if (value === 'page' && pageRangeWrapper) {
|
||||
pageRangeWrapper.classList.remove('hidden');
|
||||
} else if (pageRangeWrapper) {
|
||||
pageRangeWrapper.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
processBtn.onclick = addAttachments;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { downloadFile, formatBytes } from '../utils/helpers.js';
|
||||
import { state } from '../state.js';
|
||||
import { showAlert } from '../ui.js';
|
||||
import JSZip from 'jszip';
|
||||
|
||||
const worker = new Worker('/workers/extract-attachments.worker.js');
|
||||
@@ -24,7 +25,7 @@ export async function extractAttachments() {
|
||||
|
||||
document.getElementById('process-btn')?.classList.add('opacity-50', 'cursor-not-allowed');
|
||||
document.getElementById('process-btn')?.setAttribute('disabled', 'true');
|
||||
|
||||
|
||||
showStatus('Reading files (Main Thread)...', 'info');
|
||||
|
||||
try {
|
||||
@@ -66,9 +67,33 @@ worker.onmessage = (e: MessageEvent<ExtractAttachmentResponse>) => {
|
||||
if (e.data.status === 'success') {
|
||||
const attachments = e.data.attachments;
|
||||
|
||||
if (attachments.length === 0) {
|
||||
showAlert('No Attachments', 'The PDF file(s) do not contain any attachments to extract.');
|
||||
|
||||
state.files = [];
|
||||
state.pdfDoc = null;
|
||||
|
||||
const fileDisplayArea = document.getElementById('file-display-area');
|
||||
if (fileDisplayArea) {
|
||||
fileDisplayArea.innerHTML = '';
|
||||
}
|
||||
|
||||
const fileInput = document.getElementById('file-input') as HTMLInputElement;
|
||||
if (fileInput) {
|
||||
fileInput.value = '';
|
||||
}
|
||||
|
||||
const fileControls = document.getElementById('file-controls');
|
||||
if (fileControls) {
|
||||
fileControls.classList.add('hidden');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const zip = new JSZip();
|
||||
let totalSize = 0;
|
||||
|
||||
|
||||
for (const attachment of attachments) {
|
||||
zip.file(attachment.name, new Uint8Array(attachment.data));
|
||||
totalSize += attachment.data.byteLength;
|
||||
@@ -76,28 +101,59 @@ worker.onmessage = (e: MessageEvent<ExtractAttachmentResponse>) => {
|
||||
|
||||
zip.generateAsync({ type: 'blob' }).then((zipBlob) => {
|
||||
downloadFile(zipBlob, 'extracted-attachments.zip');
|
||||
|
||||
showAlert('Success', `${attachments.length} attachment(s) extracted successfully!`);
|
||||
|
||||
showStatus(
|
||||
`Extraction completed! ${attachments.length} attachment(s) in zip file (${formatBytes(totalSize)}). Download started.`,
|
||||
'success'
|
||||
);
|
||||
|
||||
state.files = [];
|
||||
state.pdfDoc = null;
|
||||
|
||||
const fileDisplayArea = document.getElementById('file-display-area');
|
||||
if (fileDisplayArea) {
|
||||
fileDisplayArea.innerHTML = '';
|
||||
fileDisplayArea.classList.add('hidden');
|
||||
}
|
||||
|
||||
const fileInput = document.getElementById('file-input') as HTMLInputElement;
|
||||
if (fileInput) {
|
||||
fileInput.value = '';
|
||||
}
|
||||
document.getElementById('process-btn')?.classList.add('opacity-50', 'cursor-not-allowed');
|
||||
document.getElementById('process-btn')?.setAttribute('disabled', 'true');
|
||||
|
||||
const fileControls = document.getElementById('file-controls');
|
||||
if (fileControls) {
|
||||
fileControls.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
} else if (e.data.status === 'error') {
|
||||
const errorMessage = e.data.message || 'Unknown error occurred in worker.';
|
||||
console.error('Worker Error:', errorMessage);
|
||||
showStatus(`Error: ${errorMessage}`, 'error');
|
||||
|
||||
if (errorMessage.includes('No attachments were found')) {
|
||||
showAlert('No Attachments', 'The PDF file(s) do not contain any attachments to extract.');
|
||||
|
||||
state.files = [];
|
||||
state.pdfDoc = null;
|
||||
|
||||
const fileDisplayArea = document.getElementById('file-display-area');
|
||||
if (fileDisplayArea) {
|
||||
fileDisplayArea.innerHTML = '';
|
||||
}
|
||||
|
||||
const fileInput = document.getElementById('file-input') as HTMLInputElement;
|
||||
if (fileInput) {
|
||||
fileInput.value = '';
|
||||
}
|
||||
|
||||
const fileControls = document.getElementById('file-controls');
|
||||
if (fileControls) {
|
||||
fileControls.classList.add('hidden');
|
||||
}
|
||||
} else {
|
||||
showStatus(`Error: ${errorMessage}`, 'error');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -111,15 +167,14 @@ worker.onerror = (error) => {
|
||||
function showStatus(message: string, type: 'success' | 'error' | 'info' = 'info') {
|
||||
const statusMessage = document.getElementById('status-message') as HTMLElement;
|
||||
if (!statusMessage) return;
|
||||
|
||||
|
||||
statusMessage.textContent = message;
|
||||
statusMessage.className = `mt-4 p-3 rounded-lg text-sm ${
|
||||
type === 'success'
|
||||
? 'bg-green-900 text-green-200'
|
||||
: type === 'error'
|
||||
? 'bg-red-900 text-red-200'
|
||||
: 'bg-blue-900 text-blue-200'
|
||||
}`;
|
||||
statusMessage.className = `mt-4 p-3 rounded-lg text-sm ${type === 'success'
|
||||
? 'bg-green-900 text-green-200'
|
||||
: type === 'error'
|
||||
? 'bg-red-900 text-red-200'
|
||||
: 'bg-blue-900 text-blue-200'
|
||||
}`;
|
||||
statusMessage.classList.remove('hidden');
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user