Skip to content

Commit 4ee5094

Browse files
committed
feat: support ctrl+c and ctrl+v of cell
1 parent d98cfe7 commit 4ee5094

File tree

5 files changed

+49
-1
lines changed

5 files changed

+49
-1
lines changed

src/main/ipc/handleConnection.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default class ConnectionIpcHandler {
1111
register() {
1212
ipcMain.handle('connect', async (_, [store]: [ConnectionStoreItem]) => {
1313
if (store.type === 'mysql') {
14+
console.log('create mysql connection');
1415
this.connection = new MySQLConnection(
1516
store.config as unknown as DatabaseConnectionConfig
1617
);

src/renderer/components/ResizableTable/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export default function ResizableTable({
9191
</div>
9292
{header.icon && (
9393
<div className={styles.headerContentIcon}>
94-
header.icon
94+
{header.icon}
9595
</div>
9696
)}
9797
</div>

src/renderer/screens/DatabaseScreen/QueryResultViewer/TableCell/TableCellString.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ const TableCellString = createTableCellType({
4747
diff: (prev: string, current: string) => prev !== current,
4848
content: TableCellStringContent,
4949
editor: TableCellStringEditor,
50+
onCopy: (value: string) => {
51+
return value;
52+
},
53+
onPaste: (value: string) => {
54+
return { accept: true, value };
55+
},
5056
});
5157

5258
export default TableCellString;

src/renderer/screens/DatabaseScreen/QueryResultViewer/TableCell/TableEditableCell.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
forwardRef,
66
useImperativeHandle,
77
Ref,
8+
useEffect,
89
} from 'react';
910
import styles from './styles.module.css';
1011
import { useQueryResultChange } from 'renderer/contexts/QueryResultChangeProvider';
@@ -34,6 +35,10 @@ interface TableEditableCellProps {
3435
col: number;
3536
value: unknown;
3637
readOnly?: boolean;
38+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
39+
onCopy?: (value: any) => string;
40+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
41+
onPaste?: (value: string) => { accept: boolean; value: any };
3742
}
3843

3944
const TableEditableCell = forwardRef(function TableEditableCell(
@@ -46,6 +51,8 @@ const TableEditableCell = forwardRef(function TableEditableCell(
4651
row,
4752
value,
4853
readOnly,
54+
onCopy,
55+
onPaste,
4956
}: TableEditableCellProps,
5057
ref: Ref<TableEditableCellHandler>
5158
) {
@@ -104,6 +111,36 @@ const TableEditableCell = forwardRef(function TableEditableCell(
104111
[setOnEditMode, setAfterValue, diff, value]
105112
);
106113

114+
useEffect(() => {
115+
if (onFocus) {
116+
const onKeyBinding = (e: KeyboardEvent) => {
117+
if (e.ctrlKey && e.key === 'c') {
118+
if (onCopy) {
119+
window.navigator.clipboard.writeText(onCopy(value));
120+
}
121+
} else if (e.ctrlKey && e.key === 'v') {
122+
if (onPaste) {
123+
window.navigator.clipboard.readText().then((pastedValue) => {
124+
const acceptPasteResult = onPaste(pastedValue);
125+
if (acceptPasteResult.accept) {
126+
const newValue = acceptPasteResult.value;
127+
setAfterValue(newValue);
128+
if (diff(value, newValue)) {
129+
setChange(row, col, newValue);
130+
} else {
131+
removeChange(row, col);
132+
}
133+
}
134+
});
135+
}
136+
}
137+
};
138+
139+
document.addEventListener('keydown', onKeyBinding);
140+
return () => document.removeEventListener('keydown', onKeyBinding);
141+
}
142+
}, [onFocus, onCopy, value, diff, setAfterValue]);
143+
107144
const className = [
108145
styles.container,
109146
hasChanged ? styles.changed : undefined,

src/renderer/screens/DatabaseScreen/QueryResultViewer/TableCell/createTableCellType.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ interface TableCellCustomTypeOptions<T> {
1010
editor: React.FC<TableEditableEditorProps>;
1111
content: React.FC<TableEditableContentProps>;
1212
detachEditor?: boolean;
13+
onCopy?: (value: T) => string;
14+
onPaste?: (value: string) => { accept: boolean; value: T };
1315
}
1416

1517
interface TableCellCustomTypeProps<T> {
@@ -48,6 +50,8 @@ export default function createTableCellType<T>(
4850
content={options.content}
4951
readOnly={readOnly}
5052
detactEditor={options.detachEditor}
53+
onCopy={options.onCopy}
54+
onPaste={options.onPaste}
5155
/>
5256
);
5357
};

0 commit comments

Comments
 (0)