zcatgui/docs/BUG_ADVANCEDTABLE_KEYBOARD_2025-12-17.md
reugenio bd95013ffc fix(advanced_table): Teclado funciona - result.selected_row/col
Bug: Las flechas no movían la selección en AdvancedTable.

Causa raíz:
- handleKeyboard seteaba result.selection_changed = true
- PERO NO seteaba result.selected_row / result.selected_col
- zsimifactu sincroniza selección desde DataManager cada frame
- Sin esos valores, DataManager no se actualizaba
- Siguiente frame: selección se reseteaba al valor anterior

Solución:
- Añadir result.selected_row y result.selected_col a todas
  las teclas de navegación (up, down, left, right, page_up,
  page_down, home, end)

Cambios visuales:
- Celda seleccionada: borde + tinte sutil (15%) en lugar
  de fondo sólido azul

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 20:06:17 +01:00

3.3 KiB

Bug: AdvancedTable Keyboard Navigation No Funciona

Fecha: 2025-12-17 Estado: RESUELTO Severidad: ALTA


Síntoma

Las flechas de teclado no mueven la selección en AdvancedTable cuando se usa en zsimifactu.


Causa Raíz (ENCONTRADA)

El problema era una combinación de dos factores:

1. handleKeyboard no seteaba result.selected_row / result.selected_col

En el código original:

.down => {
    if (table_state.selected_row < row_count - 1) {
        table_state.selectCell(...);
        result.selection_changed = true;
        // FALTABA: result.selected_row = new_row;
        // FALTABA: result.selected_col = new_col;
    }
},

2. zsimifactu sincroniza la selección desde DataManager cada frame

En who_list_advanced.zig líneas 199-205:

// Sincronizar selección con DataManager
if (dm.getSelectedWhoIndex()) |idx| {
    const idx_i32: i32 = @intCast(idx);
    if (self.table_state.selected_row != idx_i32) {
        self.table_state.selected_row = idx_i32;  // ← RESETEA cada frame
    }
}

Flujo del bug:

  1. Usuario presiona flecha abajo
  2. handleKeyboard detecta la tecla y ejecuta selectCell(new_row, new_col)
  3. selected_row cambia de 1 a 2 ✓
  4. result.selection_changed = true
  5. PERO result.selected_row es null
  6. zsimifactu verifica if (result.selected_row) |row_idx| → es null → no actualiza DataManager
  7. Siguiente frame: zsimifactu sincroniza desde DataManager → selected_row vuelve a 1

Solución

Añadir result.selected_row y result.selected_col a todas las teclas de navegación en handleKeyboard:

.down => {
    if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1) {
        const new_row: usize = @intCast(table_state.selected_row + 1);
        const new_col: usize = @intCast(@max(0, table_state.selected_col));
        table_state.selectCell(new_row, new_col);
        result.selection_changed = true;
        result.selected_row = new_row;    // ← AÑADIDO
        result.selected_col = new_col;    // ← AÑADIDO
    }
},

Teclas corregidas:

  • .up
  • .down
  • .left
  • .right
  • .page_up
  • .page_down
  • .home (y Ctrl+Home)
  • .end (y Ctrl+End)

Verificación

Debug añadido temporalmente mostró:

[ADV-TABLE] DOWN: after selectCell, selected_row=2   ← SÍ cambia
[ADV-TABLE] navKey detected: down, selected_row=1    ← Pero vuelve a 1 en siguiente frame

Después del fix, las flechas funcionan correctamente.


Archivos modificados

  • src/widgets/advanced_table/advanced_table.zig - handleKeyboard corregido

Lecciones aprendidas

  1. El resultado de un widget debe ser completo - Si selection_changed = true, también debe informar QUÉ cambió (selected_row, selected_col).

  2. Cuidado con la sincronización bidireccional - Cuando un widget y un data manager ambos pueden modificar el mismo estado, hay que asegurar que los cambios del widget se propaguen al data manager antes de que éste resetee el estado.

  3. Debug incremental - Añadir debug DENTRO de la función problemática (no antes) para ver el flujo real.


Documentado por: Claude Code (Opus 4.5) Fecha resolución: 2025-12-17 ~19:30