Merge pull request #14630 from overleaf/mj-table-copy-paste

[visual] Fix copying and pasting with multicolumn

GitOrigin-RevId: 4710cedb40493ed018daf122e68aecfb91e1efc4
This commit is contained in:
Mathias Jakobsen 2023-09-04 11:22:01 +01:00 committed by Copybot
parent a2e231185c
commit 5d33e5a658
2 changed files with 56 additions and 25 deletions

View file

@ -262,24 +262,26 @@ export const Table: FC = () => {
const changes: ChangeSpec[] = []
const data = event.clipboardData?.getData('text/plain')
if (data) {
const rows = data.split('\n')
const { minX, minY } = selection.normalized()
for (let row = 0; row < rows.length; row++) {
if (tableData.rows.length <= minY + row) {
// TODO: Add rows
continue
const cells = data.split('\n').map(row => row.split('\t'))
const { minY, minX } = selection.normalized()
for (let row = 0; row < cells.length; ++row) {
const rowIndex = minY + row
if (rowIndex >= tableData.rows.length) {
// TODO: add more rows
break
}
const cells = rows[row].split('\t')
for (let cell = 0; cell < cells.length; cell++) {
if (tableData.columns.length <= minX + cell) {
// TODO: Add columns
continue
const cellStart = tableData.getCellIndex(rowIndex, minX)
for (let column = 0; column < cells[row].length; ++column) {
const cellIndex = cellStart + column
if (cellIndex >= tableData.rows[rowIndex].cells.length) {
// TODO: add more columns
break
}
const cellData = tableData.getCell(minY + row, minX + cell)
const cell = tableData.rows[rowIndex].cells[cellIndex]
changes.push({
from: cellData.from,
to: cellData.to,
insert: cells[cell],
from: cell.from,
to: cell.to,
insert: cells[row][column],
})
}
}
@ -293,16 +295,16 @@ export const Table: FC = () => {
return false
}
event.preventDefault()
const { minX, minY, maxX, maxY } = selection.normalized()
const content = []
for (let row = minY; row <= maxY; row++) {
const rowContent = []
for (let cell = minX; cell <= maxX; cell++) {
rowContent.push(tableData.getCell(row, cell).content)
}
content.push(rowContent.join('\t'))
}
navigator.clipboard.writeText(content.join('\n'))
const { minY, maxY } = selection.normalized()
const cells: string[][] = Array.from(
{ length: maxY - minY + 1 },
() => []
)
tableData.iterateSelection(selection, (cell, row) => {
cells[row - minY].push(cell.content)
})
const content = cells.map(row => row.join('\t')).join('\n')
navigator.clipboard.writeText(content)
}
window.addEventListener('paste', onPaste)
window.addEventListener('copy', onCopy)

View file

@ -5,6 +5,7 @@ import { Toolbar } from './toolbar/toolbar'
import { Table } from './table'
import {
SelectionContextProvider,
TableSelection,
useSelectionContext,
} from './contexts/selection-context'
import {
@ -78,6 +79,34 @@ export class TableData {
return this.rows[row].cells.length - 1
}
iterateCells(
minRow: number,
maxRow: number,
minColumn: number,
maxColumn: number,
callback: (cell: CellData, row: number, column: number) => void
) {
for (let row = minRow; row <= maxRow; ++row) {
let currentCellOffset = this.getCellBoundaries(row, minColumn).from
const minX = this.getCellIndex(row, minColumn)
const maxX = this.getCellIndex(row, maxColumn)
for (let column = minX; column <= maxX; ++column) {
const currentCell = this.rows[row].cells[column]
const skip = currentCell.multiColumn?.columnSpan ?? 1
callback(currentCell, row, currentCellOffset)
currentCellOffset += skip
}
}
}
iterateSelection(
selection: TableSelection,
callback: (cell: CellData, row: number, column: number) => void
) {
const { minX, maxX, minY, maxY } = selection.normalized()
this.iterateCells(minY, maxY, minX, maxX, callback)
}
getCell(row: number, column: number): CellData {
return this.rows[row].cells[this.getCellIndex(row, column)]
}