From b3a33ec4f390451289246c549557b650e73db9c6 Mon Sep 17 00:00:00 2001 From: "R.Eugenio" Date: Sun, 28 Dec 2025 12:50:30 +0100 Subject: [PATCH] fix(virtual_table): RowIdGetter now handles injected rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: Tab within injected row was triggering immediate row commit. This happened because RowIdGetter.getRowId() returned the REAL row ID for the injected row index, instead of NEW_ROW_ID. Fix: - RowIdGetter now takes injected_idx parameter - Returns NEW_ROW_ID for injected row - Adjusts indices for rows after injection (row-1) - num_rows calculation now accounts for injection (+1) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../paged_datasource.zig | 2 ++ .../virtual_advanced_table.zig | 35 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/widgets/virtual_advanced_table/paged_datasource.zig b/src/widgets/virtual_advanced_table/paged_datasource.zig index e2e71ab..8e1e64a 100644 --- a/src/widgets/virtual_advanced_table/paged_datasource.zig +++ b/src/widgets/virtual_advanced_table/paged_datasource.zig @@ -80,11 +80,13 @@ pub const PagedDataSource = struct { if (row == inj_idx) { // Esta es la fila inyectada - leer del edit buffer if (self.state.row_edit_buffer.getPendingValue(col)) |pending| { + std.debug.print("[PDS-DEBUG] injected row={} col={} pending=\"{s}\"\n", .{ row, col, pending }); const copy_len = @min(pending.len, buf.len); @memcpy(buf[0..copy_len], pending[0..copy_len]); return buf[0..copy_len]; } // Sin valor pendiente - retornar vacío (celda nueva) + std.debug.print("[PDS-DEBUG] injected row={} col={} NO pending\n", .{ row, col }); return ""; } else if (row > inj_idx) { // Fila después de la inyección - ajustar índice (-1) diff --git a/src/widgets/virtual_advanced_table/virtual_advanced_table.zig b/src/widgets/virtual_advanced_table/virtual_advanced_table.zig index d905ce6..4ce11a1 100644 --- a/src/widgets/virtual_advanced_table/virtual_advanced_table.zig +++ b/src/widgets/virtual_advanced_table/virtual_advanced_table.zig @@ -343,10 +343,19 @@ pub fn virtualAdvancedTableRect( const edited_cell = list_state.getEditingCell().?; const new_value = list_state.getEditText(); + std.debug.print("[VT-DEBUG] editor committed: cell=({},{}) value=\"{s}\" hasChanged={} is_injected={}\n", .{ + edited_cell.row, + edited_cell.col, + new_value, + list_state.hasValueChanged(), + list_state.row_edit_buffer.is_injected, + }); + // Añadir cambio al buffer de fila (NO commit inmediato) // El commit real se hace cuando el usuario abandona la fila if (list_state.hasValueChanged()) { list_state.row_edit_buffer.addChange(edited_cell.col, new_value); + std.debug.print("[VT-DEBUG] addChange: col={} value=\"{s}\"\n", .{ edited_cell.col, new_value }); // Compatibilidad: mantener flags antiguos result.cell_committed = true; @@ -435,23 +444,43 @@ pub fn virtualAdvancedTableRect( const is_tab = result.navigate_direction == .next_cell or result.navigate_direction == .prev_cell; if (is_tab) { // Wrapper para DataProvider que implementa getRowId(usize) -> i64 + // Tiene en cuenta filas inyectadas (Ctrl+N) y ghost row const RowIdGetter = struct { prov: DataProvider, total: usize, + injected_idx: ?usize, pub fn getRowId(self: @This(), row: usize) i64 { - // Ghost row está al final (índice = total) + // Fila inyectada siempre retorna NEW_ROW_ID + if (self.injected_idx) |inj_idx| { + if (row == inj_idx) return table_core.NEW_ROW_ID; + // Filas después de inyección: ajustar índice hacia provider + if (row > inj_idx) { + const adjusted_row = row - 1; + if (adjusted_row >= self.total) return table_core.NEW_ROW_ID; + return self.prov.getRowId(adjusted_row) orelse table_core.NEW_ROW_ID; + } + } + // Ghost row está al final if (row >= self.total) return table_core.NEW_ROW_ID; return self.prov.getRowId(row) orelse table_core.NEW_ROW_ID; } }; - const getter = RowIdGetter{ .prov = provider, .total = total_rows }; + const getter = RowIdGetter{ + .prov = provider, + .total = total_rows, + .injected_idx = list_state.injected_row_idx, + }; const current_row = list_state.getSelectedRow() orelse 0; const forward = result.navigate_direction == .next_cell; const num_cols = config.columns.len; // VirtualAdvancedTable siempre tiene ghost row disponible - const num_rows = total_rows + 1; + // Si hay inyección, sumar 1 extra al conteo visual + var num_rows = total_rows + 1; // +1 para ghost row + if (list_state.injected_row_idx != null) { + num_rows += 1; // +1 para fila inyectada + } const plan = table_core.planTabNavigation( &list_state.row_edit_buffer,