UNPKG

ai-debug-local-mcp

Version:

🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

154 lines 7 kB
/** * Flutter Accessibility Enabler * Properly enables Flutter's accessibility tree for semantic element detection */ export class FlutterAccessibilityEnabler { /** * Enable Flutter accessibility through multiple methods */ static async enableAccessibility(page) { // console.log('🔓 Enabling Flutter accessibility...'); // Method 1: Click hidden "Enable accessibility" button if it exists const accessibilityButtonClicked = await page.evaluate(() => { // Look for the hidden accessibility button (often at -1, -1) const buttons = Array.from(document.querySelectorAll('[aria-label*="accessibility" i]')); const enableButton = buttons.find(b => { const label = b.getAttribute('aria-label') || ''; const rect = b.getBoundingClientRect(); return label.toLowerCase().includes('enable') && label.toLowerCase().includes('accessibility'); }); if (enableButton) { // Force click even if hidden enableButton.click(); return true; } return false; }); if (accessibilityButtonClicked) { // console.log('✅ Clicked "Enable accessibility" button'); await page.waitForTimeout(2000); return true; } // Method 2: Tab navigation to hidden controls // console.log('⌨️ Trying Tab navigation to enable accessibility...'); // Focus the page await page.click('body'); // Tab through hidden elements (Flutter often has accessibility toggle as first focusable) for (let i = 0; i < 5; i++) { await page.keyboard.press('Tab'); await page.waitForTimeout(100); // Check if we focused on accessibility control const focusedElement = await page.evaluate(() => { const active = document.activeElement; if (active) { const label = active.getAttribute('aria-label') || ''; return { label, tagName: active.tagName, isAccessibility: label.toLowerCase().includes('accessibility') }; } return null; }); if (focusedElement?.isAccessibility) { // console.log('📍 Found accessibility control via Tab navigation'); await page.keyboard.press('Enter'); await page.waitForTimeout(2000); return true; } } // Method 3: Programmatic enabling via Flutter internals const programmaticEnabled = await page.evaluate(() => { // Try to access Flutter's internal configuration if (window.flutter) { const flutter = window.flutter; // Try various ways to enable accessibility if (flutter.semanticsEnabled !== undefined) { flutter.semanticsEnabled = true; } if (flutter.configuration) { flutter.configuration.enableAccessibility = true; } if (flutter._configuration) { flutter._configuration.enableAccessibility = true; } // Dispatch custom event that Flutter might listen to window.dispatchEvent(new CustomEvent('flutter-enable-accessibility')); return true; } // Try to find Flutter's initialization script and modify config const scripts = Array.from(document.querySelectorAll('script')); const flutterScript = scripts.find(s => s.textContent?.includes('flutterConfiguration') || s.textContent?.includes('_flutter.loader')); if (flutterScript && window._flutter) { if (window._flutter.loader) { window._flutter.loader.config = { ...window._flutter.loader.config, enableAccessibility: true }; } return true; } return false; }); if (programmaticEnabled) { // console.log('🔧 Enabled accessibility programmatically'); await page.waitForTimeout(2000); return true; } // Method 4: Keyboard shortcut (some Flutter apps use this) // console.log('⌨️ Trying keyboard shortcuts...'); // Try Shift+Tab three times (Flutter pattern) for (let i = 0; i < 3; i++) { await page.keyboard.down('Shift'); await page.keyboard.press('Tab'); await page.keyboard.up('Shift'); await page.waitForTimeout(100); } // Try Ctrl+Alt+Z (accessibility toggle in some apps) await page.keyboard.down('Control'); await page.keyboard.down('Alt'); await page.keyboard.press('z'); await page.keyboard.up('Alt'); await page.keyboard.up('Control'); await page.waitForTimeout(2000); // Check if accessibility was enabled by looking for semantic nodes const semanticNodesAfter = await page.evaluate(() => { return document.querySelectorAll('flt-semantics, [role]:not([role="presentation"])').length; }); // console.log(`📊 Semantic nodes after attempts: ${semanticNodesAfter}`); return semanticNodesAfter > 20; // Assume success if we have many semantic nodes } /** * Verify accessibility is enabled */ static async isAccessibilityEnabled(page) { return await page.evaluate(() => { // Check for semantic nodes const semanticNodes = document.querySelectorAll('flt-semantics, [role]:not([role="presentation"])'); // Check for Flutter accessibility flag const flutterEnabled = window.flutter?.semanticsEnabled === true; // Check if we have a reasonable number of semantic nodes return semanticNodes.length > 20 || flutterEnabled; }); } /** * Wait for accessibility tree to be populated */ static async waitForAccessibilityTree(page, timeout = 5000) { const startTime = Date.now(); while (Date.now() - startTime < timeout) { const nodeCount = await page.evaluate(() => { return document.querySelectorAll('flt-semantics, [role]:not([role="presentation"])').length; }); if (nodeCount > 20) { // console.log(`✅ Accessibility tree populated with ${nodeCount} nodes`); return; } await page.waitForTimeout(500); } console.warn('⚠️ Timeout waiting for accessibility tree'); } } //# sourceMappingURL=flutter-accessibility-enabler.js.map