tabbed frametype filtering
This commit is contained in:
165
BUTTON_PERSISTENCE_FIX.md
Normal file
165
BUTTON_PERSISTENCE_FIX.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Button Persistence Fix Summary
|
||||
|
||||
## Problem Solved ✅
|
||||
Dark buttons were appearing early in the load process but then disappearing, causing a confusing user experience where buttons would flicker in and out of existence during PCAP parsing.
|
||||
|
||||
## Root Cause Analysis
|
||||
The issue was in the `refresh_frame_types()` method in `filtered_flow_view.py`:
|
||||
|
||||
1. **Initial Creation**: Buttons were created during `compose()` with predefined frame types and 0 counts
|
||||
2. **Early Refresh**: `on_mount()` called `refresh_frame_types()`, which filtered out buttons with 0 counts
|
||||
3. **Button Removal**: Predefined buttons with 0 counts were removed (causing disappearance)
|
||||
4. **Later Recreation**: When data arrived and counts became > 0, buttons reappeared
|
||||
|
||||
### Code Issue #1: Hiding Zero-Count Buttons
|
||||
```python
|
||||
# OLD CODE (problematic):
|
||||
for i, (frame_type, flow_count) in enumerate(sorted_frame_types[:9]):
|
||||
if i < len(hotkeys) and flow_count > 0: # ❌ Hid buttons with 0 counts
|
||||
btn = FrameTypeButton(frame_type, hotkeys[i], flow_count)
|
||||
```
|
||||
|
||||
### Code Issue #2: Order Comparison Excluding Zero-Count Types
|
||||
```python
|
||||
# OLD CODE (problematic):
|
||||
current_order = [ft for ft, _ in sorted_frame_types[:9] if frame_type_flow_counts[ft] > 0]
|
||||
# ❌ Excluded predefined types with 0 counts from order comparison
|
||||
```
|
||||
|
||||
## Solution Implemented
|
||||
|
||||
### 1. **Always Show Predefined Frame Types**
|
||||
Modified the button creation logic to show predefined frame types even with 0 counts:
|
||||
|
||||
```python
|
||||
# FIXED CODE:
|
||||
for i, (frame_type, flow_count) in enumerate(sorted_frame_types[:9]):
|
||||
# Always show predefined frame types, even with 0 count during early loading
|
||||
# Only skip if count is 0 AND it's not a predefined frame type
|
||||
should_show = (flow_count > 0) or (frame_type in self.predefined_frame_types)
|
||||
|
||||
if i < len(hotkeys) and should_show:
|
||||
btn = FrameTypeButton(frame_type, hotkeys[i], flow_count)
|
||||
```
|
||||
|
||||
### 2. **Include Zero-Count Predefined Types in Order Comparison**
|
||||
Modified order comparison to include predefined types with 0 counts:
|
||||
|
||||
```python
|
||||
# FIXED CODE:
|
||||
# Include predefined frame types even with 0 count to avoid unnecessary recreation
|
||||
current_order = [ft for ft, _ in sorted_frame_types[:9]
|
||||
if frame_type_flow_counts[ft] > 0 or ft in self.predefined_frame_types]
|
||||
```
|
||||
|
||||
### 3. **Flexible Order Matching During Loading**
|
||||
Added intelligent logic to avoid unnecessary button recreation during loading:
|
||||
|
||||
```python
|
||||
# FIXED CODE:
|
||||
# Check if we can just update counts instead of recreating buttons
|
||||
# During early loading, be more flexible about order changes for predefined types
|
||||
can_update_counts_only = False
|
||||
|
||||
if len(current_order) == len(previous_order):
|
||||
# Same number of buttons - check if they're the same set (order can be different during loading)
|
||||
current_set = set(current_order)
|
||||
previous_set = set(previous_order)
|
||||
|
||||
if current_set == previous_set:
|
||||
# Same frame types, just update counts without recreating
|
||||
can_update_counts_only = True
|
||||
elif all(ft in self.predefined_frame_types for ft in current_set.symmetric_difference(previous_set)):
|
||||
# Only predefined types differ - still safe to just update counts during loading
|
||||
can_update_counts_only = True
|
||||
|
||||
if can_update_counts_only:
|
||||
# Just update counts in existing buttons
|
||||
self._update_button_counts(frame_type_flow_counts)
|
||||
return
|
||||
```
|
||||
|
||||
## User Experience Improvement
|
||||
|
||||
### Before Fix (Confusing):
|
||||
```
|
||||
Loading starts: [1.Overview] [2.CH10(0)] [3.UDP(0)] [4.PTP(0)] ← Dark buttons appear
|
||||
Early refresh: [1.Overview] ← Buttons disappear!
|
||||
Data arrives: [1.Overview] [2.CH10(500)] [3.UDP(200)] ← Buttons reappear
|
||||
```
|
||||
|
||||
### After Fix (Stable):
|
||||
```
|
||||
Loading starts: [1.Overview] [2.CH10(0)] [3.UDP(0)] [4.PTP(0)] ← Buttons appear
|
||||
Early refresh: [1.Overview] [2.CH10(0)] [3.UDP(0)] [4.PTP(0)] ← Buttons stay visible!
|
||||
Data arrives: [1.Overview] [2.CH10(500)] [3.UDP(200)] [4.PTP(0)] ← Counts update smoothly
|
||||
```
|
||||
|
||||
## Technical Benefits
|
||||
|
||||
### 1. **Stable Visual Interface**
|
||||
- No more button flickering during loading
|
||||
- Consistent button layout from start to finish
|
||||
- Users always see available filter options
|
||||
|
||||
### 2. **Better Loading Experience**
|
||||
- Immediate visual feedback of available frame types
|
||||
- No confusing disappearing/reappearing elements
|
||||
- Professional, stable interface behavior
|
||||
|
||||
### 3. **Performance Improvements**
|
||||
- Fewer widget recreations during loading
|
||||
- Reduced DOM manipulation overhead
|
||||
- Smoother UI updates
|
||||
|
||||
### 4. **Logical Consistency**
|
||||
- Predefined buttons represent expected frame types
|
||||
- Zero counts indicate "not yet detected" rather than "unavailable"
|
||||
- Intuitive behavior matches user expectations
|
||||
|
||||
## Test Results ✅
|
||||
|
||||
The fix was verified with comprehensive testing:
|
||||
|
||||
```
|
||||
✅ Predefined buttons stay visible with 0 counts
|
||||
✅ Buttons don't disappear during early loading
|
||||
✅ No unnecessary button recreation/flicker
|
||||
✅ Proper ordering: data-rich types first, then predefined
|
||||
✅ Smart count-only updates vs full recreation
|
||||
✅ Flexible order matching during loading phase
|
||||
```
|
||||
|
||||
## Edge Cases Handled
|
||||
|
||||
1. **Empty Data State**: Buttons show with (0) counts
|
||||
2. **Partial Loading**: Some frame types get data, others remain at 0
|
||||
3. **Reordering**: When counts change significantly, proper reordering occurs
|
||||
4. **New Frame Types**: Non-predefined types still get added dynamically
|
||||
5. **Mixed States**: Combination of loaded and unloaded frame types
|
||||
|
||||
## Backward Compatibility ✅
|
||||
|
||||
All existing functionality preserved:
|
||||
- Same keyboard shortcuts (1-9, 0)
|
||||
- Same click behavior
|
||||
- Same visual styling
|
||||
- Same filtering logic
|
||||
- Same count display format
|
||||
|
||||
## Files Modified
|
||||
|
||||
- **`filtered_flow_view.py`**: Updated button creation and order comparison logic
|
||||
- **`test_button_persistence.py`**: Comprehensive test coverage for the fixes
|
||||
|
||||
## Summary
|
||||
|
||||
The button persistence issue has been **completely resolved**. Users will now see:
|
||||
|
||||
✅ **Stable buttons** throughout the entire loading process
|
||||
✅ **No flickering** or disappearing buttons
|
||||
✅ **Immediate feedback** on available frame types
|
||||
✅ **Professional appearance** with consistent UI behavior
|
||||
✅ **Smooth updates** as data loads and counts increase
|
||||
|
||||
The StreamLens TUI now provides a much better user experience during PCAP analysis startup! 🎉
|
||||
Reference in New Issue
Block a user