#!/usr/bin/env python3 """ Debug script specifically for button visibility and text issues """ import sys import asyncio import time from pathlib import Path # Add analyzer to path sys.path.insert(0, str(Path(__file__).parent)) from analyzer.tui.textual.app_v2 import StreamLensAppV2 from analyzer.analysis.core import EthernetAnalyzer from textual_inspector import inspect_textual_app, print_widget_tree, analyze_layout_issues from textual_state_visualizer import TextualStateMonitor async def debug_button_lifecycle(): """Debug the button lifecycle to understand visibility issues""" print("šŸ” Debugging Button Lifecycle Issues") print("=" * 60) # Create analyzer and app instance analyzer = EthernetAnalyzer() app = StreamLensAppV2(analyzer=analyzer) async with app.run_test() as pilot: print("\nšŸ“± App started successfully") # Let the app initialize await asyncio.sleep(2) print("\nšŸ” PHASE 1: Initial App State") print("-" * 40) # Inspect initial state app_data = inspect_textual_app(app) print_widget_tree(app_data.get('current_screen', {})) # Look specifically for buttons print("\nšŸ”˜ BUTTON ANALYSIS:") buttons_found = [] def find_buttons(widget_data, path=""): if widget_data.get('type') == 'Button' or 'Button' in widget_data.get('type', ''): button_info = { 'path': path, 'id': widget_data.get('id'), 'label': widget_data.get('label', 'NO LABEL'), 'visible': widget_data.get('visible', False), 'size': widget_data.get('size', {}), 'classes': widget_data.get('classes', []) } buttons_found.append(button_info) print(f" šŸ“¦ Found button: {button_info}") for child in widget_data.get('children', []): find_buttons(child, f"{path}/{widget_data.get('type', 'Unknown')}") find_buttons(app_data.get('current_screen', {})) if not buttons_found: print(" āŒ NO BUTTONS FOUND!") else: print(f" āœ… Found {len(buttons_found)} buttons") # Check for layout issues print("\nāš ļø LAYOUT ISSUES:") issues = analyze_layout_issues(app_data) if issues: for issue in issues: print(f" 🚨 {issue}") else: print(" āœ… No obvious layout issues detected") # Look for the filter bar specifically print("\nšŸ” FILTER BAR ANALYSIS:") filter_bar_found = False def find_filter_bar(widget_data, path=""): nonlocal filter_bar_found if widget_data.get('id') == 'filter-bar': filter_bar_found = True print(f" šŸ“¦ Filter bar found at: {path}") print(f" Size: {widget_data.get('size', {})}") print(f" Visible: {widget_data.get('visible', False)}") print(f" Children: {len(widget_data.get('children', []))}") for i, child in enumerate(widget_data.get('children', [])): print(f" Child {i+1}: {child.get('type')} #{child.get('id')} - {child.get('label', 'no label')}") for child in widget_data.get('children', []): find_filter_bar(child, f"{path}/{widget_data.get('type', 'Unknown')}") find_filter_bar(app_data.get('current_screen', {})) if not filter_bar_found: print(" āŒ FILTER BAR NOT FOUND!") # Wait a bit and check again to see if buttons appear print(f"\nā±ļø PHASE 2: Waiting 5 seconds for changes...") await asyncio.sleep(5) print("\nšŸ” PHASE 2: After Waiting") print("-" * 40) # Check state again app_data_2 = inspect_textual_app(app) buttons_found_2 = [] def find_buttons_2(widget_data, path=""): if widget_data.get('type') == 'Button' or 'Button' in widget_data.get('type', ''): button_info = { 'path': path, 'id': widget_data.get('id'), 'label': widget_data.get('label', 'NO LABEL'), 'visible': widget_data.get('visible', False), 'size': widget_data.get('size', {}), 'classes': widget_data.get('classes', []) } buttons_found_2.append(button_info) for child in widget_data.get('children', []): find_buttons_2(child, f"{path}/{widget_data.get('type', 'Unknown')}") find_buttons_2(app_data_2.get('current_screen', {})) print(f"\nšŸ”˜ BUTTON COMPARISON:") print(f" Phase 1: {len(buttons_found)} buttons") print(f" Phase 2: {len(buttons_found_2)} buttons") if len(buttons_found) != len(buttons_found_2): print(" 🚨 BUTTON COUNT CHANGED!") # Show what disappeared phase1_ids = {b.get('id') for b in buttons_found} phase2_ids = {b.get('id') for b in buttons_found_2} disappeared = phase1_ids - phase2_ids appeared = phase2_ids - phase1_ids if disappeared: print(f" šŸ“‰ Disappeared: {disappeared}") if appeared: print(f" šŸ“ˆ Appeared: {appeared}") # Check specific button text/label issues print(f"\nšŸ“ BUTTON TEXT ANALYSIS:") for button in buttons_found_2: label = button.get('label', 'NO LABEL') size = button.get('size', {}) visible = button.get('visible', False) print(f" Button #{button.get('id')}:") print(f" Label: '{label}'") print(f" Size: {size.get('width', 0)}x{size.get('height', 0)}") print(f" Visible: {visible}") # Check for text display issues if label and label != 'NO LABEL': if size.get('width', 0) == 0 or size.get('height', 0) == 0: print(f" 🚨 ISSUE: Button has text but zero size!") elif not visible: print(f" 🚨 ISSUE: Button has text but not visible!") else: print(f" āœ… Button appears properly configured") else: print(f" 🚨 ISSUE: Button has no text/label!") print(f"\nšŸ“Š SUMMARY:") print(f" Total buttons found: {len(buttons_found_2)}") print(f" Buttons with text: {sum(1 for b in buttons_found_2 if b.get('label') and b.get('label') != 'NO LABEL')}") print(f" Visible buttons: {sum(1 for b in buttons_found_2 if b.get('visible'))}") print(f" Properly sized buttons: {sum(1 for b in buttons_found_2 if b.get('size', {}).get('width', 0) > 0 and b.get('size', {}).get('height', 0) > 0)}") def main(): print("šŸ” StreamLens Button Debug Tool") print("This tool will analyze button visibility and text issues") print("=" * 60) try: asyncio.run(debug_button_lifecycle()) except KeyboardInterrupt: print("\nšŸ›‘ Debugging interrupted by user") except Exception as e: print(f"\nāŒ Debug failed with error: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()