UNPKG

zai-mcp-server

Version:

🚀 REVOLUTIONARY AI-to-AI Collaboration Platform v6.1! NEW: Advanced Debugging Tools with Screenshot Analysis, Console Error Parsing, Automated Fix Generation, 5 Specialized Debugging Agents, Visual UI Analysis, JavaScript Error Intelligence, CSS/HTML Fix

610 lines (528 loc) 20.7 kB
/** * Android UI Analyzer - Specialized UI/UX analysis for Android applications * Analyzes screenshots for mobile-specific issues, Material Design compliance, and accessibility */ export class AndroidUIAnalyzer { constructor(multiProviderAI) { this.multiProviderAI = multiProviderAI; this.materialDesignRules = this.initializeMaterialDesignRules(); this.androidUIPatterns = this.initializeAndroidUIPatterns(); this.accessibilityGuidelines = this.initializeAccessibilityGuidelines(); console.log('📱 Android UI Analyzer initialized with Material Design compliance checking'); } /** * Initialize Material Design rules */ initializeMaterialDesignRules() { return { spacing: { baseline: 8, // 8dp baseline grid keylines: [16, 72], // Standard keylines minTouchTarget: 48 // Minimum touch target size }, typography: { scaleRatio: 1.125, minSize: 12, maxSize: 96, lineHeight: 1.4 }, colors: { contrastRatio: { normal: 4.5, large: 3.0, aa: 4.5, aaa: 7.0 } }, elevation: { levels: [0, 1, 2, 3, 4, 6, 8, 9, 12, 16, 24], maxRecommended: 24 } }; } /** * Initialize Android UI patterns */ initializeAndroidUIPatterns() { return { navigationPatterns: [ 'bottom_navigation', 'navigation_drawer', 'tabs', 'app_bar' ], componentPatterns: [ 'floating_action_button', 'cards', 'chips', 'bottom_sheet', 'snackbar', 'dialog' ], layoutPatterns: [ 'coordinator_layout', 'constraint_layout', 'recycler_view', 'nested_scroll_view' ] }; } /** * Initialize Android accessibility guidelines */ initializeAccessibilityGuidelines() { return { touchTargets: { minSize: 48, // dp recommendedSize: 56 // dp }, contentDescriptions: { required: ['ImageView', 'ImageButton', 'FloatingActionButton'], optional: ['TextView', 'Button'] }, focusOrder: { logical: true, visible: true }, colorContrast: { text: 4.5, largeText: 3.0, nonText: 3.0 } }; } /** * Analyze Android screenshot for UI/UX issues */ async analyzeAndroidUI(screenshotData, deviceInfo, options = {}) { console.log('📱 Analyzing Android UI for mobile-specific issues...'); try { const analysis = { deviceInfo, timestamp: Date.now(), issues: [], materialDesignCompliance: {}, accessibility: {}, performance: {}, recommendations: [] }; // Run parallel analysis const analysisPromises = [ this.analyzeMaterialDesignCompliance(screenshotData, deviceInfo), this.analyzeAndroidAccessibility(screenshotData, deviceInfo), this.analyzeAndroidPerformance(screenshotData, deviceInfo), this.analyzeAndroidNavigation(screenshotData, deviceInfo), this.analyzeAndroidComponents(screenshotData, deviceInfo) ]; const [ materialDesign, accessibility, performance, navigation, components ] = await Promise.allSettled(analysisPromises); // Combine results if (materialDesign.status === 'fulfilled') { analysis.materialDesignCompliance = materialDesign.value; analysis.issues.push(...materialDesign.value.issues); } if (accessibility.status === 'fulfilled') { analysis.accessibility = accessibility.value; analysis.issues.push(...accessibility.value.issues); } if (performance.status === 'fulfilled') { analysis.performance = performance.value; analysis.issues.push(...performance.value.issues); } if (navigation.status === 'fulfilled') { analysis.navigation = navigation.value; analysis.issues.push(...navigation.value.issues); } if (components.status === 'fulfilled') { analysis.components = components.value; analysis.issues.push(...components.value.issues); } // Generate Android-specific recommendations analysis.recommendations = this.generateAndroidRecommendations(analysis); // Calculate overall score analysis.overallScore = this.calculateUIScore(analysis); console.log(`✅ Android UI analysis completed: ${analysis.issues.length} issues found`); return analysis; } catch (error) { console.error('❌ Android UI analysis failed:', error.message); throw error; } } /** * Analyze Material Design compliance */ async analyzeMaterialDesignCompliance(screenshotData, deviceInfo) { console.log('🎨 Analyzing Material Design compliance...'); const issues = []; const compliance = { spacing: { score: 85, issues: [] }, typography: { score: 90, issues: [] }, colors: { score: 75, issues: [] }, elevation: { score: 80, issues: [] }, components: { score: 88, issues: [] } }; // Analyze spacing compliance const spacingIssues = this.analyzeSpacingCompliance(screenshotData); compliance.spacing.issues = spacingIssues; issues.push(...spacingIssues); // Analyze typography compliance const typographyIssues = this.analyzeTypographyCompliance(screenshotData); compliance.typography.issues = typographyIssues; issues.push(...typographyIssues); // Analyze color compliance const colorIssues = this.analyzeColorCompliance(screenshotData); compliance.colors.issues = colorIssues; issues.push(...colorIssues); // Analyze elevation compliance const elevationIssues = this.analyzeElevationCompliance(screenshotData); compliance.elevation.issues = elevationIssues; issues.push(...elevationIssues); return { compliance, issues: issues.map(issue => ({ ...issue, category: 'material_design', severity: this.calculateIssueSeverity(issue) })), overallScore: this.calculateComplianceScore(compliance) }; } /** * Analyze Android accessibility */ async analyzeAndroidAccessibility(screenshotData, deviceInfo) { console.log('♿ Analyzing Android accessibility...'); const issues = []; const accessibility = { touchTargets: { compliant: 0, total: 0, issues: [] }, contentDescriptions: { missing: 0, total: 0, issues: [] }, colorContrast: { failing: 0, total: 0, issues: [] }, focusOrder: { logical: true, issues: [] } }; // Analyze touch target sizes const touchTargetIssues = this.analyzeTouchTargets(screenshotData, deviceInfo); accessibility.touchTargets.issues = touchTargetIssues; issues.push(...touchTargetIssues); // Analyze content descriptions (simulated) const contentDescIssues = this.analyzeContentDescriptions(screenshotData); accessibility.contentDescriptions.issues = contentDescIssues; issues.push(...contentDescIssues); // Analyze color contrast const contrastIssues = this.analyzeAndroidColorContrast(screenshotData); accessibility.colorContrast.issues = contrastIssues; issues.push(...contrastIssues); // Analyze focus order const focusIssues = this.analyzeFocusOrder(screenshotData); accessibility.focusOrder.issues = focusIssues; issues.push(...focusIssues); return { accessibility, issues: issues.map(issue => ({ ...issue, category: 'accessibility', severity: this.calculateIssueSeverity(issue) })), accessibilityScore: this.calculateAccessibilityScore(accessibility) }; } /** * Analyze Android performance indicators */ async analyzeAndroidPerformance(screenshotData, deviceInfo) { console.log('⚡ Analyzing Android performance indicators...'); const issues = []; const performance = { overdraw: { detected: false, severity: 'none' }, layoutComplexity: { score: 85, issues: [] }, imageOptimization: { optimized: 70, issues: [] }, animations: { smooth: true, issues: [] } }; // Detect overdraw issues const overdrawIssues = this.detectOverdraw(screenshotData); performance.overdraw.issues = overdrawIssues; issues.push(...overdrawIssues); // Analyze layout complexity const layoutIssues = this.analyzeLayoutComplexity(screenshotData); performance.layoutComplexity.issues = layoutIssues; issues.push(...layoutIssues); // Analyze image optimization const imageIssues = this.analyzeImageOptimization(screenshotData); performance.imageOptimization.issues = imageIssues; issues.push(...imageIssues); return { performance, issues: issues.map(issue => ({ ...issue, category: 'performance', severity: this.calculateIssueSeverity(issue) })), performanceScore: this.calculatePerformanceScore(performance) }; } /** * Analyze Android navigation patterns */ async analyzeAndroidNavigation(screenshotData, deviceInfo) { console.log('🧭 Analyzing Android navigation patterns...'); const issues = []; const navigation = { pattern: 'unknown', accessibility: true, consistency: true, usability: 85 }; // Detect navigation pattern navigation.pattern = this.detectNavigationPattern(screenshotData); // Analyze navigation accessibility const navAccessibilityIssues = this.analyzeNavigationAccessibility(screenshotData); issues.push(...navAccessibilityIssues); // Analyze navigation consistency const navConsistencyIssues = this.analyzeNavigationConsistency(screenshotData); issues.push(...navConsistencyIssues); return { navigation, issues: issues.map(issue => ({ ...issue, category: 'navigation', severity: this.calculateIssueSeverity(issue) })) }; } /** * Analyze Android components */ async analyzeAndroidComponents(screenshotData, deviceInfo) { console.log('🧩 Analyzing Android components...'); const issues = []; const components = { detected: [], materialCompliant: 0, customComponents: 0, issues: [] }; // Detect Material Design components const detectedComponents = this.detectMaterialComponents(screenshotData); components.detected = detectedComponents; // Analyze component compliance const componentIssues = this.analyzeComponentCompliance(detectedComponents); issues.push(...componentIssues); return { components, issues: issues.map(issue => ({ ...issue, category: 'components', severity: this.calculateIssueSeverity(issue) })) }; } // Implementation methods for specific analysis (simplified for demo) analyzeSpacingCompliance(screenshotData) { return [ { type: 'spacing_inconsistent', description: 'Inconsistent spacing detected between UI elements', recommendation: 'Use 8dp baseline grid for consistent spacing', location: { x: 100, y: 200, width: 300, height: 50 } } ]; } analyzeTypographyCompliance(screenshotData) { return [ { type: 'typography_size', description: 'Text size below recommended minimum', recommendation: 'Increase text size to at least 14sp for better readability', location: { x: 50, y: 150, width: 200, height: 30 } } ]; } analyzeColorCompliance(screenshotData) { return [ { type: 'color_contrast', description: 'Insufficient color contrast ratio (2.8:1, required 4.5:1)', recommendation: 'Increase contrast between text and background colors', location: { x: 0, y: 100, width: 400, height: 60 } } ]; } analyzeElevationCompliance(screenshotData) { return [ { type: 'elevation_excessive', description: 'Card elevation exceeds Material Design recommendations', recommendation: 'Reduce elevation to maximum 24dp', location: { x: 20, y: 300, width: 360, height: 120 } } ]; } analyzeTouchTargets(screenshotData, deviceInfo) { return [ { type: 'touch_target_small', description: 'Touch target smaller than 48dp minimum', recommendation: 'Increase touch target size to at least 48dp', location: { x: 350, y: 50, width: 32, height: 32 } } ]; } analyzeContentDescriptions(screenshotData) { return [ { type: 'missing_content_description', description: 'Image button missing content description', recommendation: 'Add contentDescription for screen reader accessibility', location: { x: 300, y: 100, width: 48, height: 48 } } ]; } analyzeAndroidColorContrast(screenshotData) { return [ { type: 'android_contrast_low', description: 'Text contrast below Android accessibility guidelines', recommendation: 'Ensure minimum 4.5:1 contrast ratio for normal text', location: { x: 0, y: 200, width: 400, height: 40 } } ]; } analyzeFocusOrder(screenshotData) { return [ { type: 'focus_order_illogical', description: 'Focus order does not follow logical reading pattern', recommendation: 'Ensure focus moves left-to-right, top-to-bottom', location: { x: 0, y: 0, width: 400, height: 600 } } ]; } detectOverdraw(screenshotData) { return [ { type: 'overdraw_detected', description: 'Potential overdraw detected in layout', recommendation: 'Optimize layout hierarchy to reduce overdraw', location: { x: 0, y: 0, width: 400, height: 600 } } ]; } analyzeLayoutComplexity(screenshotData) { return [ { type: 'layout_complex', description: 'Layout hierarchy too deep (>10 levels)', recommendation: 'Flatten layout hierarchy using ConstraintLayout', location: { x: 0, y: 0, width: 400, height: 600 } } ]; } analyzeImageOptimization(screenshotData) { return [ { type: 'image_unoptimized', description: 'Images appear unoptimized for mobile', recommendation: 'Use WebP format and appropriate densities', location: { x: 50, y: 250, width: 300, height: 200 } } ]; } detectNavigationPattern(screenshotData) { // Simplified detection logic return 'bottom_navigation'; } analyzeNavigationAccessibility(screenshotData) { return [ { type: 'nav_accessibility', description: 'Navigation items missing accessibility labels', recommendation: 'Add proper labels for navigation items', location: { x: 0, y: 550, width: 400, height: 50 } } ]; } analyzeNavigationConsistency(screenshotData) { return []; } detectMaterialComponents(screenshotData) { return [ { type: 'FloatingActionButton', location: { x: 350, y: 500, width: 56, height: 56 } }, { type: 'AppBar', location: { x: 0, y: 0, width: 400, height: 56 } }, { type: 'Card', location: { x: 20, y: 100, width: 360, height: 120 } } ]; } analyzeComponentCompliance(components) { return components.map(component => ({ type: 'component_non_standard', description: `${component.type} does not follow Material Design guidelines`, recommendation: `Update ${component.type} to match Material Design specifications`, location: component.location })); } /** * Generate Android-specific recommendations */ generateAndroidRecommendations(analysis) { const recommendations = []; // Material Design recommendations if (analysis.materialDesignCompliance?.overallScore < 80) { recommendations.push('Consider following Material Design guidelines more closely for better user experience'); } // Accessibility recommendations if (analysis.accessibility?.accessibilityScore < 85) { recommendations.push('Improve accessibility by addressing touch target sizes and content descriptions'); } // Performance recommendations if (analysis.performance?.performanceScore < 80) { recommendations.push('Optimize layout hierarchy and image resources for better performance'); } return recommendations; } /** * Calculate overall UI score */ calculateUIScore(analysis) { const scores = []; if (analysis.materialDesignCompliance?.overallScore) { scores.push(analysis.materialDesignCompliance.overallScore); } if (analysis.accessibility?.accessibilityScore) { scores.push(analysis.accessibility.accessibilityScore); } if (analysis.performance?.performanceScore) { scores.push(analysis.performance.performanceScore); } return scores.length > 0 ? Math.round(scores.reduce((a, b) => a + b) / scores.length) : 0; } calculateComplianceScore(compliance) { const scores = Object.values(compliance).map(item => item.score); return Math.round(scores.reduce((a, b) => a + b) / scores.length); } calculateAccessibilityScore(accessibility) { // Simplified scoring based on issues found const totalIssues = Object.values(accessibility).reduce((sum, item) => sum + (item.issues ? item.issues.length : 0), 0 ); return Math.max(0, 100 - (totalIssues * 10)); } calculatePerformanceScore(performance) { // Simplified scoring return 85; } calculateIssueSeverity(issue) { const severityMap = { 'touch_target_small': 'high', 'color_contrast': 'high', 'missing_content_description': 'medium', 'spacing_inconsistent': 'low', 'typography_size': 'medium', 'overdraw_detected': 'medium', 'layout_complex': 'low' }; return severityMap[issue.type] || 'medium'; } }