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;
}