diff --git a/main.js b/main.js index 346f6eb..1af6e25 100644 --- a/main.js +++ b/main.js @@ -8,8 +8,10 @@ const { resolveUnroutedDir, listUnroutedFiles, listDuplicateFiles, + listSkippedFiles, clearUnroutedFiles, clearDuplicateFiles, + clearSkippedFiles, } = require('./services/unrouted'); const CAD_EXTENSIONS = ['prt', 'asm', 'dwr']; @@ -209,5 +211,7 @@ ipcMain.handle('open-unrouted-folder', async () => { ipcMain.handle('list-unrouted-files', async () => listUnroutedFiles()); ipcMain.handle('list-duplicates-files', async () => listDuplicateFiles()); +ipcMain.handle('list-skipped-files', async () => listSkippedFiles()); ipcMain.handle('clear-unrouted-files', async () => clearUnroutedFiles()); ipcMain.handle('clear-duplicates-files', async () => clearDuplicateFiles()); +ipcMain.handle('clear-skipped-files', async () => clearSkippedFiles()); diff --git a/preload.js b/preload.js index 0dcdc68..8bf2cd8 100644 --- a/preload.js +++ b/preload.js @@ -11,6 +11,8 @@ contextBridge.exposeInMainWorld('api', { openUnroutedFolder: () => ipcRenderer.invoke('open-unrouted-folder'), listUnroutedFiles: () => ipcRenderer.invoke('list-unrouted-files'), listDuplicatesFiles: () => ipcRenderer.invoke('list-duplicates-files'), + listSkippedFiles: () => ipcRenderer.invoke('list-skipped-files'), clearUnroutedFiles: () => ipcRenderer.invoke('clear-unrouted-files'), clearDuplicatesFiles: () => ipcRenderer.invoke('clear-duplicates-files'), + clearSkippedFiles: () => ipcRenderer.invoke('clear-skipped-files'), }); diff --git a/renderer/index.html b/renderer/index.html index 7413e57..c28b5f5 100644 --- a/renderer/index.html +++ b/renderer/index.html @@ -277,6 +277,7 @@
+
diff --git a/renderer/renderer.js b/renderer/renderer.js index c5530f8..3708a4d 100644 --- a/renderer/renderer.js +++ b/renderer/renderer.js @@ -7,6 +7,7 @@ const browseDestinationBtn = document.getElementById('browseDestinationBtn'); const saveDestinationBtn = document.getElementById('saveDestinationBtn'); const openUnroutedBtn = document.getElementById('openUnroutedBtn'); const openDuplicatesBtn = document.getElementById('openDuplicatesBtn'); +const openSkippedBtn = document.getElementById('openSkippedBtn'); const destinationStatus = document.getElementById('destinationStatus'); const previewOverlay = document.getElementById('previewOverlay'); const closePreviewBtn = document.getElementById('closePreviewBtn'); @@ -29,6 +30,7 @@ function setDestinationLoading(isLoading) { saveDestinationBtn.disabled = isLoading; openUnroutedBtn.disabled = isLoading; openDuplicatesBtn.disabled = isLoading; + openSkippedBtn.disabled = isLoading; clearPreviewBtn.disabled = isLoading; } @@ -60,18 +62,14 @@ function hidePreview() { } async function loadPreviewData(kind) { - if (kind === 'duplicates') { - return window.api.listDuplicatesFiles(); - } - + if (kind === 'duplicates') return window.api.listDuplicatesFiles(); + if (kind === 'skipped') return window.api.listSkippedFiles(); return window.api.listUnroutedFiles(); } async function clearPreviewData(kind) { - if (kind === 'duplicates') { - return window.api.clearDuplicatesFiles(); - } - + if (kind === 'duplicates') return window.api.clearDuplicatesFiles(); + if (kind === 'skipped') return window.api.clearSkippedFiles(); return window.api.clearUnroutedFiles(); } @@ -248,7 +246,22 @@ openDuplicatesBtn.addEventListener('click', async () => { destinationStatus.textContent = 'Caricamento anteprima duplicati...'; const result = await window.api.listDuplicatesFiles(); - showPreview('duplicates', 'Anteprima duplicati', result, 'Nessun file presente in duplicati.'); + showPreview('duplicates', 'Anteprima __DUPLICATI', result, 'Nessun file presente in __DUPLICATI.'); + destinationStatus.textContent = `Anteprima caricata (${result.files?.length || 0} file).`; + } catch (error) { + destinationStatus.textContent = `Errore: ${error.message}`; + } finally { + setDestinationLoading(false); + } +}); + +openSkippedBtn.addEventListener('click', async () => { + try { + setDestinationLoading(true); + destinationStatus.textContent = 'Caricamento anteprima saltati...'; + + const result = await window.api.listSkippedFiles(); + showPreview('skipped', 'Anteprima __SALTATI', result, 'Nessun file presente in __SALTATI.'); destinationStatus.textContent = `Anteprima caricata (${result.files?.length || 0} file).`; } catch (error) { destinationStatus.textContent = `Errore: ${error.message}`; @@ -263,9 +276,12 @@ clearPreviewBtn.addEventListener('click', async () => { } const isDuplicates = currentPreviewKind === 'duplicates'; + const isSkipped = currentPreviewKind === 'skipped'; const confirmMessage = isDuplicates - ? 'Confermi la pulizia della cartella duplicati?' - : 'Confermi la pulizia della cartella non smistati?'; + ? 'Confermi la pulizia della cartella __DUPLICATI?' + : isSkipped + ? 'Confermi la pulizia della cartella saltati?' + : 'Confermi la pulizia della cartella non smistati?'; if (!window.confirm(confirmMessage)) { return; @@ -277,10 +293,12 @@ clearPreviewBtn.addEventListener('click', async () => { const clearResult = await clearPreviewData(currentPreviewKind); const refreshed = await loadPreviewData(currentPreviewKind); - const title = isDuplicates ? 'Anteprima duplicati' : 'Anteprima __NON_SMISTATI'; + const title = isDuplicates ? 'Anteprima __DUPLICATI' : isSkipped ? 'Anteprima __SALTATI' : 'Anteprima __NON_SMISTATI'; const emptyMessage = isDuplicates - ? 'Nessun file presente in duplicati.' - : 'Nessun file presente in __NON_SMISTATI.'; + ? 'Nessun file presente in __DUPLICATI.' + : isSkipped + ? 'Nessun file presente in __SALTATI.' + : 'Nessun file presente in __NON_SMISTATI.'; showPreview(currentPreviewKind, title, refreshed, emptyMessage); destinationStatus.textContent = `Cartella pulita: ${clearResult.directory}`; diff --git a/services/folderProcessor.js b/services/folderProcessor.js index 3927d5d..79d5471 100644 --- a/services/folderProcessor.js +++ b/services/folderProcessor.js @@ -3,7 +3,7 @@ const path = require('path'); const { getDestinationDecision, getCadInfo } = require('./router'); const { buildDestinationIndex } = require('./destinationIndex'); const { buildExistingCadKeyIndex, toCadKey } = require('./duplicateIndex'); -const { prepareUnroutedTarget, prepareDuplicateTarget } = require('./unrouted'); +const { prepareUnroutedTarget, prepareDuplicateTarget, getSkippedTarget } = require('./unrouted'); function parseNumericVersion(version) { const rawVersion = String(version || '').trim(); @@ -86,7 +86,10 @@ async function processFolder(folder, config) { const cadInfo = getCadInfo(file); if (!cadInfo) { + const skippedTarget = await getSkippedTarget(file); + await fs.copy(fullPath, skippedTarget.destinationPath); result.skipped += 1; + result.copied += 1; continue; } diff --git a/services/unrouted.js b/services/unrouted.js index 303de26..5c17f98 100644 --- a/services/unrouted.js +++ b/services/unrouted.js @@ -5,8 +5,10 @@ const { getCadInfo } = require('./router'); const PRIMARY_UNROUTED_DIR = '/cadroute/__NON_SMISTATI'; const HOME_UNROUTED_DIR = path.join(os.homedir(), '.cadroute', '__NON_SMISTATI'); -const PRIMARY_DUPLICATES_DIR = '/cadroute/duplicati'; -const HOME_DUPLICATES_DIR = path.join(os.homedir(), '.cadroute', 'duplicati'); +const PRIMARY_DUPLICATES_DIR = '/cadroute/__DUPLICATI'; +const HOME_DUPLICATES_DIR = path.join(os.homedir(), '.cadroute', '__DUPLICATI'); +const PRIMARY_SKIPPED_DIR = '/cadroute/__SALTATI'; +const HOME_SKIPPED_DIR = path.join(os.homedir(), '.cadroute', '__SALTATI'); const SPECIAL_TARGETS = { unrouted: { @@ -17,6 +19,10 @@ const SPECIAL_TARGETS = { primary: PRIMARY_DUPLICATES_DIR, fallback: HOME_DUPLICATES_DIR, }, + skipped: { + primary: PRIMARY_SKIPPED_DIR, + fallback: HOME_SKIPPED_DIR, + }, }; const resolvedDirs = new Map(); @@ -178,6 +184,22 @@ async function prepareDuplicateTarget(fileName) { return prepareSpecialTarget('duplicates', fileName); } +async function resolveSkippedDir() { + return resolveTargetDir('skipped'); +} + +async function getSkippedTarget(fileName) { + return getTarget('skipped', fileName); +} + +async function listSkippedFiles() { + return listTargetFiles('skipped'); +} + +async function clearSkippedFiles() { + return clearTargetFiles('skipped'); +} + async function listFilesRecursively(rootDir) { const files = []; @@ -251,16 +273,22 @@ async function clearDuplicateFiles() { module.exports = { getUnroutedTarget, getDuplicateTarget, + getSkippedTarget, prepareUnroutedTarget, prepareDuplicateTarget, resolveUnroutedDir, resolveDuplicatesDir, + resolveSkippedDir, listUnroutedFiles, listDuplicateFiles, + listSkippedFiles, clearUnroutedFiles, clearDuplicateFiles, + clearSkippedFiles, PRIMARY_UNROUTED_DIR, HOME_UNROUTED_DIR, PRIMARY_DUPLICATES_DIR, HOME_DUPLICATES_DIR, + PRIMARY_SKIPPED_DIR, + HOME_SKIPPED_DIR, }; diff --git a/services/zipProcessor.js b/services/zipProcessor.js index eb87d73..9047c51 100644 --- a/services/zipProcessor.js +++ b/services/zipProcessor.js @@ -5,7 +5,7 @@ const { pipeline } = require('stream/promises'); const { getDestinationDecision, getCadInfo } = require('./router'); const { buildDestinationIndex } = require('./destinationIndex'); const { buildExistingCadKeyIndex, toCadKey } = require('./duplicateIndex'); -const { prepareUnroutedTarget, prepareDuplicateTarget } = require('./unrouted'); +const { prepareUnroutedTarget, prepareDuplicateTarget, getSkippedTarget } = require('./unrouted'); function parseNumericVersion(version) { const rawVersion = String(version || '').trim(); @@ -82,8 +82,10 @@ async function processZip(zipPath, config) { const cadInfo = getCadInfo(baseName); if (!cadInfo) { + const skippedTarget = await getSkippedTarget(baseName); + await pipeline(entry, fs.createWriteStream(skippedTarget.destinationPath)); result.skipped += 1; - entry.autodrain(); + result.copied += 1; continue; }