async function openApp()

in src/gemini_95/index.ts [105:218]


async function openApp(appName: string): Promise<void> {
    const windowElement = document.getElementById(appName) as HTMLDivElement | null;
    if (!windowElement) {
        console.error(`Window element not found for app: ${appName}`);
        return;
    }

    // If app is already open, just bring it to front
    if (openApps.has(appName)) {
        bringToFront(windowElement);
        // Ensure window is visible (if it was minimized)
        windowElement.style.display = 'flex';
        windowElement.classList.add('active'); // Ensure active state is visually correct
        return;
    }

    // Make window visible and bring it to front
    windowElement.style.display = 'flex';
    windowElement.classList.add('active');
    bringToFront(windowElement); // Handles z-index and active state

    // Create and add taskbar button
    const taskbarButton = document.createElement('div');
    taskbarButton.classList.add('taskbar-app');
    taskbarButton.dataset.appName = appName;

    // Add icon based on appName
    let iconSrc = '';
    let title = appName; // Default title
    const iconElement = findIconElement(appName); // Use the helper function
    if (iconElement) {
        const img = iconElement.querySelector('img');
        const span = iconElement.querySelector('span');
        if(img) iconSrc = img.src;
        if(span) title = span.textContent || appName;
    } else { // Fallback for apps opened via start menu but maybe no desktop icon
         switch(appName) {
            // (Fallback logic remains the same)
            case 'myComputer': iconSrc = 'https://64.media.tumblr.com/fda654985437a7b2664e5833e086c69b/0b9b5160404412fb-f5/s540x810/43cf0d594a16ef9fb0449eb89883009e9276f8dd.png'; title = 'My Computer'; break;
            case 'internetExplorer': iconSrc = 'https://64.media.tumblr.com/78e5e1fb87d13924b0a4b410d131b930/c6cb2fd44af16922-23/s540x810/1afa8a3117c9b8643b207a66449e9a9f8317dd5e.png'; title = 'Internet Explorer'; break;
            case 'notepad': iconSrc = 'https://64.media.tumblr.com/6d0d5e90f5feb07a6ac5c7a1c6b4b6e1/a9242c5cebec16c3-73/s540x810/6c0ba179b6aa593891394d432cd4817784d5fdbe.png'; title = 'Notepad'; break;
            case 'paint': iconSrc = 'https://64.media.tumblr.com/4619a2969641630efd3be90122231635/6328ec072338dae7-17/s540x810/b4497bf01aed05b475419022e60708c01dab6f22.png'; title = 'Paint'; break;
            case 'doom': iconSrc = 'https://cdn.dos.zone/v2/icons/doom.png'; title = 'Doom II'; break;
            case 'gemini': iconSrc = 'https://static.vecteezy.com/system/resources/previews/024/118/176/original/google-gemini-icon-logo-symbol-free-png.png'; title = 'Gemini Chat'; break; // Add Gemini fallback
            case 'minesweeper': iconSrc = 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Minesweeper_Icon.svg/768px-Minesweeper_Icon.svg.png'; title = 'Minesweeper'; break;
            case 'imageViewer': iconSrc = 'https://win98icons.alexmeub.com/icons/png/display_properties-4.png'; title = 'Image Viewer'; break;
         }
    }

    if (iconSrc) {
        const img = document.createElement('img');
        img.src = iconSrc;
        img.alt = title;
        taskbarButton.appendChild(img);
    }
    taskbarButton.appendChild(document.createTextNode(title));

    taskbarButton.addEventListener('click', () => {
        if (windowElement === activeWindow && windowElement.style.display !== 'none') {
             minimizeApp(appName);
        } else {
            windowElement.style.display = 'flex';
            bringToFront(windowElement);
        }
    });

    taskbarAppsContainer.appendChild(taskbarButton);
    openApps.set(appName, { windowEl: windowElement, taskbarButton: taskbarButton });
    taskbarButton.classList.add('active'); // Mark as active since it's newly opened

    // Initialize specific applications
    if (appName === 'chrome') {
        // Initialize AI browser
        initAiBrowser(windowElement);
    }
    else if (appName === 'notepad') {
        // Initialize notepad story generation
        initNotepadStory(windowElement);
    }
    else if (appName === 'paint') {
        // Initialize the new simple paint app
        initSimplePaintApp(windowElement);

        // Show Paint assistant and start critiques
        if (paintAssistant) paintAssistant.classList.add('visible');
        if (assistantBubble) assistantBubble.textContent = 'Warming up my judging circuits...'; // Initial message
        if (paintCritiqueIntervalId) clearInterval(paintCritiqueIntervalId);
        paintCritiqueIntervalId = window.setInterval(critiquePaintDrawing, 15000); // Check every 10 seconds
    }

    // Initialize DOSBox if needed
    if (appName === 'doom' && !dosInstances['doom']) {
        const doomContainer = document.getElementById('doom-content') as HTMLDivElement;
        if (doomContainer) {
            // Create and set iframe for Doom
            doomContainer.innerHTML = '<iframe src="https://js-dos.com/games/doom.exe.html" width="100%" height="100%" frameborder="0" scrolling="no" allowfullscreen></iframe>';
            console.log("Doom initialized via iframe");

            // Store a reference to know it's initialized
            dosInstances['doom'] = { initialized: true };
        }
    } else if (appName === 'gemini') {
        // Initialize Gemini Chat (async)
        await initGeminiChat(windowElement);
    }
    // >>> Call initMinesweeperGame <<< //
    else if (appName === 'minesweeper') {
        initMinesweeperGame(windowElement);
    }
    // >>> Call initMyComputer <<< //
    else if (appName === 'myComputer') {
        initMyComputer(windowElement);
    }
}