()
| 8435 | } |
| 8436 | const randomIndex = Math.floor(Math.random() * visibleModels.length); |
| 8437 | const randomItem = visibleModels[randomIndex]; |
| 8438 | randomItem.classList.add('selected'); |
| 8439 | if (doScroll) { |
| 8440 | randomItem.scrollIntoView({ behavior: 'smooth', block: 'center' }); |
| 8441 | } |
| 8442 | previousItem = randomItem; |
| 8443 | return randomItem; |
| 8444 | }; |
| 8445 | |
| 8446 | // Spin animation without scrolling (to avoid white flashes) |
| 8447 | for (let i = 0; i < ROULETTE_SPINS; i++) { |
| 8448 | await new Promise(resolve => setTimeout(resolve, delay)); |
| 8449 | highlightRandom(); // no scrolling on intermediate spins |
| 8450 | delay += ROULETTE_DELAY_INCREMENT; // Gradually slow down |
| 8451 | } |
| 8452 | |
| 8453 | // Final selection with scrolling. |
| 8454 | const finalItem = highlightRandom(true); |
| 8455 | const filePath = finalItem.getAttribute('data-filepath'); |
| 8456 | |
| 8457 | // Add winning animation class |
| 8458 | finalItem.classList.add('roulette-winner'); |
| 8459 | setTimeout(() => finalItem.classList.remove('roulette-winner'), 3000); |
| 8460 | |
| 8461 | // Show model details and update selection state |
| 8462 | selectedModels.add(filePath); |
| 8463 | await showModelDetails(filePath); |
| 8464 | |
| 8465 | // Show celebration message |
| 8466 | await window.electron.showMessage( |
| 8467 | 'Print Roulette', |
| 8468 | 'Your next print has been chosen! 🎲\nTime to get printing!' |
| 8469 | ); |
| 8470 | } |
| 8471 | |
| 8472 | window._electronRealEventHandlers['start-print-roulette'] = function() { |
| 8473 | startPrintRoulette(); |
| 8474 | }; |
| 8475 | if (window._electronPendingEvents['start-print-roulette']) { |
| 8476 | window._electronPendingEvents['start-print-roulette'].forEach((args) => { |
| 8477 | window._electronRealEventHandlers['start-print-roulette'].apply(null, args); |
| 8478 | }); |
| 8479 | delete window._electronPendingEvents['start-print-roulette']; |
| 8480 | } |
| 8481 |
no test coverage detected