Skip to content

Commit a80f2e2

Browse files
committed
refactor(chat): tighten table copy fallback and helper placement
- writeLoadedRowsWithChip now requires a chip to carry; with none it falls through to the canonical paged path (preserving its row loading and truncation notice) instead of doing a bare synchronous write. - Reuse selectedColumnIds in the context-menu memo. - Restore resolveTableSelectionResource's TSDoc, orphaned when renderTableCell was extracted between the doc and its function.
1 parent 6421994 commit a80f2e2

2 files changed

Lines changed: 22 additions & 18 deletions

File tree

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,13 @@ function buildTableSelectionContext(opts: {
360360

361361
/**
362362
* Copies `rows` synchronously on the copy event so a chat-selection chip can
363-
* ride alongside the tab-separated text. Only viable when every selected row is
364-
* already loaded and the set is within the chip cap — otherwise the caller falls
365-
* back to the paged `writeSelectionToClipboard`, whose async Clipboard API write
366-
* replaces the whole clipboard and so cannot carry a custom MIME type.
363+
* ride alongside the tab-separated text. The paged `writeSelectionToClipboard`
364+
* cannot do this: its async Clipboard API write replaces the whole clipboard and
365+
* so cannot carry a custom MIME type.
366+
*
367+
* Taking this path requires a chip to carry AND every selected row already
368+
* loaded and within the chip cap; otherwise the canonical paged path handles the
369+
* copy, including its row loading and truncation notice.
367370
*
368371
* @returns True when it handled the copy, false to fall through to the paged path.
369372
*/
@@ -374,13 +377,15 @@ function writeLoadedRowsWithChip(opts: {
374377
buildCells: (row: TableRowType) => string[]
375378
context: ChatContext | null
376379
}): boolean {
377-
const { rows } = opts
378-
if (!opts.allLoaded || rows.length === 0 || rows.length > MAX_TABLE_SELECTION_ROWS) return false
380+
const { rows, context } = opts
381+
if (!context || !opts.allLoaded || rows.length === 0 || rows.length > MAX_TABLE_SELECTION_ROWS) {
382+
return false
383+
}
379384
opts.clipboardData?.setData(
380385
'text/plain',
381386
rows.map((row) => opts.buildCells(row).join('\t')).join('\n')
382387
)
383-
if (opts.context) attachSelectionContextToClipboard(opts.clipboardData, opts.context)
388+
attachSelectionContextToClipboard(opts.clipboardData, context)
384389
toast.success(`Copied ${rows.length} ${rows.length === 1 ? 'row' : 'rows'}`)
385390
return true
386391
}
@@ -3836,11 +3841,9 @@ export function TableGrid({
38363841
if (!sel) return undefined
38373842
const contextRowArrayIndex = rows.findIndex((r) => r.id === contextMenu.row!.id)
38383843
if (contextRowArrayIndex < sel.startRow || contextRowArrayIndex > sel.endRow) return undefined
3839-
const ids: string[] = []
3840-
for (let c = sel.startCol; c <= sel.endCol; c++) {
3841-
const col = displayColumns[c]
3842-
if (col) ids.push(getColumnId(col))
3843-
}
3844+
// Collapsed here too (not only in buildTableSelectionContext) because this
3845+
// also decides whether the menu item reads "cell range" or "rows".
3846+
const ids = selectedColumnIds(displayColumns, sel)
38443847
return ids.length > 0 && ids.length < displayColumns.length ? ids : undefined
38453848
}, [contextMenu.isOpen, contextMenu.row, rowSelection, normalizedSelection, rows, displayColumns])
38463849

apps/sim/lib/copilot/chat/process-contents.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -930,19 +930,20 @@ async function resolveFileSelectionResource(
930930
}
931931
}
932932

933-
/**
934-
* Resolves a table selection into an inline markdown table. Rows are re-fetched
935-
* by id from the DB (never trusting client-sent cell values); when `columnIds`
936-
* is present the projection is narrowed to that cell range, otherwise every
937-
* column is included.
938-
*/
939933
/** Renders one cell for a markdown table row, escaping the delimiters. */
940934
function renderTableCell(value: unknown): string {
941935
if (value === null || value === undefined) return ''
942936
const cell = typeof value === 'string' ? value : JSON.stringify(value)
943937
return cell.replace(/\|/g, '\\|').replace(/\n/g, ' ')
944938
}
945939

940+
/**
941+
* Resolves a table selection into an inline markdown table. Rows are re-fetched
942+
* by id from the DB (never trusting client-sent cell values); when `columnIds`
943+
* is present the projection is narrowed to that cell range, otherwise every
944+
* column is included. Output is bounded by
945+
* {@link MAX_TABLE_SELECTION_CONTENT_LENGTH}, not just the row and column caps.
946+
*/
946947
async function resolveTableSelectionResource(
947948
tableId: string,
948949
workspaceId: string,

0 commit comments

Comments
 (0)