Merge pull request #37 from matt1398/feat/session-id

feat: add copy functionality to session context menu
This commit is contained in:
matt 2026-02-20 12:53:39 +09:00 committed by GitHub
commit 7a264a882c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -4,10 +4,10 @@
* Shows keyboard shortcut hints for actions that have them. * Shows keyboard shortcut hints for actions that have them.
*/ */
import { useEffect, useRef } from 'react'; import { useEffect, useRef, useState } from 'react';
import { MAX_PANES } from '@renderer/types/panes'; import { MAX_PANES } from '@renderer/types/panes';
import { Eye, EyeOff, Pin, PinOff } from 'lucide-react'; import { Check, ClipboardCopy, Eye, EyeOff, Pin, PinOff, Terminal } from 'lucide-react';
interface SessionContextMenuProps { interface SessionContextMenuProps {
x: number; x: number;
@ -29,6 +29,7 @@ interface SessionContextMenuProps {
export const SessionContextMenu = ({ export const SessionContextMenu = ({
x, x,
y, y,
sessionId,
paneCount, paneCount,
isPinned, isPinned,
isHidden, isHidden,
@ -40,6 +41,7 @@ export const SessionContextMenu = ({
onToggleHide, onToggleHide,
}: SessionContextMenuProps): React.JSX.Element => { }: SessionContextMenuProps): React.JSX.Element => {
const menuRef = useRef<HTMLDivElement>(null); const menuRef = useRef<HTMLDivElement>(null);
const [copiedField, setCopiedField] = useState<'id' | 'command' | null>(null);
useEffect(() => { useEffect(() => {
const handleMouseDown = (e: MouseEvent): void => { const handleMouseDown = (e: MouseEvent): void => {
@ -59,7 +61,7 @@ export const SessionContextMenu = ({
}, [onClose]); }, [onClose]);
const menuWidth = 240; const menuWidth = 240;
const menuHeight = 204; const menuHeight = 290;
const clampedX = Math.min(x, window.innerWidth - menuWidth - 8); const clampedX = Math.min(x, window.innerWidth - menuWidth - 8);
const clampedY = Math.min(y, window.innerHeight - menuHeight - 8); const clampedY = Math.min(y, window.innerHeight - menuHeight - 8);
@ -68,6 +70,19 @@ export const SessionContextMenu = ({
onClose(); onClose();
}; };
const handleCopy = (text: string, field: 'id' | 'command') => async () => {
try {
await navigator.clipboard.writeText(text);
setCopiedField(field);
setTimeout(() => {
setCopiedField(null);
onClose();
}, 600);
} catch {
// Silently fail
}
};
const atMaxPanes = paneCount >= MAX_PANES; const atMaxPanes = paneCount >= MAX_PANES;
return ( return (
@ -101,6 +116,29 @@ export const SessionContextMenu = ({
icon={isHidden ? <Eye className="size-4" /> : <EyeOff className="size-4" />} icon={isHidden ? <Eye className="size-4" /> : <EyeOff className="size-4" />}
onClick={handleClick(onToggleHide)} onClick={handleClick(onToggleHide)}
/> />
<div className="mx-2 my-1 border-t" style={{ borderColor: 'var(--color-border)' }} />
<MenuItem
label={copiedField === 'id' ? 'Copied!' : 'Copy Session ID'}
icon={
copiedField === 'id' ? (
<Check className="size-4 text-green-400" />
) : (
<ClipboardCopy className="size-4" />
)
}
onClick={handleCopy(sessionId, 'id')}
/>
<MenuItem
label={copiedField === 'command' ? 'Copied!' : 'Copy Resume Command'}
icon={
copiedField === 'command' ? (
<Check className="size-4 text-green-400" />
) : (
<Terminal className="size-4" />
)
}
onClick={handleCopy(`claude --resume ${sessionId}`, 'command')}
/>
</div> </div>
); );
}; };