diff --git a/src/components/settings/ImportExportSettingsPanel.jsx b/src/components/settings/ImportExportSettingsPanel.jsx index 4ebe81b..db23dbb 100644 --- a/src/components/settings/ImportExportSettingsPanel.jsx +++ b/src/components/settings/ImportExportSettingsPanel.jsx @@ -26,10 +26,6 @@ import brandAutomat from '../../automats/brandAutomat'; import { orderAutomat } from '../../automats/orderAutomat'; import SkeleHashImage from './SkeleHashImage'; -// Keep only the most recent N image events in state to avoid unbounded growth -// on large imports (thousands of images). -const MAX_STREAMED_IMAGES = 60; - function formatBytes(bytes) { if (bytes == null || isNaN(bytes) || bytes === 0) return '0 B'; const units = ['B', 'KB', 'MB', 'GB', 'TB']; @@ -104,8 +100,8 @@ export default class ImportExportSettingsPanel extends Component { uploadLoaded: 0, uploadTotal: 0, importProgress: null, // raw counters from the `progress` event - // Most recent SkeleHashes from the stream ({ id, hash }) - importedImages: [], + // Latest SkeleHash shown (first hash of the most recent images batch) + streamedHash: null, importedImageCount: 0, statusMessage: null, importStats: null, @@ -252,7 +248,6 @@ export default class ImportExportSettingsPanel extends Component { this.uploadAbortController = new AbortController(); - this.imageSeq = 0; this.setState({ uploading: true, uploadStage: 'upload', @@ -260,7 +255,7 @@ export default class ImportExportSettingsPanel extends Component { uploadLoaded: 0, uploadTotal: selectedFile.size, importProgress: null, - importedImages: [], + streamedHash: null, importedImageCount: 0, statusMessage: null, importStats: null, @@ -294,25 +289,16 @@ export default class ImportExportSettingsPanel extends Component { onImages: (images) => { const list = Array.isArray(images) ? images.filter(Boolean) : []; if (!list.length) return; - this.setState((prev) => { - let seq = this.imageSeq ?? 0; - const batch = list.map((item) => { - seq += 1; - return { - id: seq, - hash: typeof item === 'string' ? item : (item?.skelehash ?? null), - }; - }); - this.imageSeq = seq; - const next = [...batch.reverse(), ...prev.importedImages]; - if (next.length > MAX_STREAMED_IMAGES) next.length = MAX_STREAMED_IMAGES; - return { - uploadStage: 'server', - importedImages: next, - importedImageCount: prev.importedImageCount + list.length, - statusMessage: null, - }; - }); + // Only the first hash of each batch; it replaces the previously + // shown placeholder. + const first = list[0]; + const hash = typeof first === 'string' ? first : (first?.skelehash ?? null); + this.setState((prev) => ({ + uploadStage: 'server', + streamedHash: hash, + importedImageCount: prev.importedImageCount + list.length, + statusMessage: null, + })); }, onDone: (stats) => { this.setState({ @@ -383,7 +369,7 @@ export default class ImportExportSettingsPanel extends Component { uploadLoaded, uploadTotal, importProgress, - importedImages, + streamedHash, importedImageCount, statusMessage, importStats, @@ -831,88 +817,44 @@ export default class ImportExportSettingsPanel extends Component { )} - {/* Live stream of decoded SkeleHash placeholders */} - {importedImages.length > 0 && ( - + {/* Latest decoded SkeleHash placeholder (replaces previous) */} + {streamedHash && ( + - - SkeleHash-Platzhalter (Vorschau) - - - {importedImageCount} Bild(er) verarbeitet - + - - {importedImages.map((image) => ( - - {image.hash ? ( - - ) : ( - - Kein Hash - - )} - - - {shortHash(image.hash)} - - - - ))} - + {shortHash(streamedHash)} + + + {importedImageCount} Bild(er) verarbeitet + )}