(model)
| 11029 | // Single thumbnail |
| 11030 | thumbnailSrc = model.thumbnail; |
| 11031 | } |
| 11032 | } |
| 11033 | |
| 11034 | // For 3MF files, try to get primary thumbnail from database if not found in model.thumbnail |
| 11035 | // Load asynchronously to avoid blocking — never getAllThumbnails for a single display slot |
| 11036 | (async () => { |
| 11037 | if (!thumbnailSrc && model.filePath && model.filePath.toLowerCase().endsWith('.3mf')) { |
| 11038 | try { |
| 11039 | const primary = await fetchPrimaryThumbnailForGrid(model.filePath); |
| 11040 | if (primary) { |
| 11041 | thumbnailSrc = primary; |
| 11042 | thumbnailImg.src = thumbnailSrc; |
| 11043 | thumbnailImg.style.width = '100%'; |
| 11044 | thumbnailImg.style.height = '100%'; |
| 11045 | thumbnailImg.style.objectFit = 'cover'; |
| 11046 | } |
| 11047 | } catch (e) { |
| 11048 | console.log('Could not fetch 3MF thumbnail from database:', e); |
| 11049 | } |
| 11050 | } |
| 11051 | })(); |
| 11052 | |
| 11053 | if (thumbnailSrc) { |
| 11054 | thumbnailImg.src = thumbnailSrc; |
| 11055 | thumbnailImg.style.width = '100%'; |
| 11056 | thumbnailImg.style.height = '100%'; |
| 11057 | thumbnailImg.style.objectFit = 'cover'; |
| 11058 | thumbnailImg.onerror = () => { |
| 11059 | // If image fails to load, show placeholder |
| 11060 | thumbnailImg.style.width = '40px'; |
| 11061 | thumbnailImg.style.height = '40px'; |
| 11062 | thumbnailImg.style.opacity = '0.3'; |
| 11063 | thumbnailImg.src = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 9h6v6H9z"/></svg>'; |
| 11064 | }; |
| 11065 | } else { |
| 11066 | thumbnailImg.style.width = '40px'; |
| 11067 | thumbnailImg.style.height = '40px'; |
| 11068 | thumbnailImg.style.opacity = '0.3'; |
| 11069 | thumbnailImg.src = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 9h6v6H9z"/></svg>'; |
| 11070 | } |
| 11071 | thumbnailContainer.appendChild(thumbnailImg); |
| 11072 | |
| 11073 | // Model info |
| 11074 | const modelInfo = document.createElement('div'); |
| 11075 | modelInfo.style.flex = '1'; |
| 11076 | modelInfo.style.minWidth = '0'; |
| 11077 | modelInfo.innerHTML = ` |
| 11078 | <div style="color: #4a9eff; font-weight: 600; font-size: 15px; margin-bottom: 4px;">${fileName}</div> |
| 11079 | <div style="color: #999; font-size: 12px; word-break: break-all;">${filePath}</div> |
| 11080 | `; |
| 11081 | |
| 11082 | modelHeader.appendChild(thumbnailContainer); |
| 11083 | modelHeader.appendChild(modelInfo); |
| 11084 | modelSection.appendChild(modelHeader); |
| 11085 | |
| 11086 | // Existing tags |
| 11087 | if (existingTags.length > 0) { |
| 11088 | const existingDiv = document.createElement('div'); |
no test coverage detected