-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSessionName.tsx
More file actions
112 lines (97 loc) · 2.92 KB
/
SessionName.tsx
File metadata and controls
112 lines (97 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* Inline editable session name component
* Click to edit, blur or Enter to save
*/
import { useState, useRef, useEffect, useCallback } from 'react';
import { logger } from '../utils/logger';
import { setSessionMeta } from '../utils/document-meta';
interface SessionNameProps {
name: string | null;
sessionId?: string;
onRename: (name: string | null) => Promise<void>;
disabled?: boolean;
}
export function SessionName({ name, sessionId, onRename, disabled = false }: SessionNameProps) {
const [isEditing, setIsEditing] = useState(false);
const [editValue, setEditValue] = useState(name || '');
const [isSaving, setIsSaving] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
// Focus input when entering edit mode
useEffect(() => {
if (isEditing && inputRef.current) {
inputRef.current.focus();
inputRef.current.select();
}
}, [isEditing]);
// Update document title and meta tags
useEffect(() => {
setSessionMeta(name, sessionId);
}, [name, sessionId]);
const handleClick = useCallback(() => {
if (!disabled && !isSaving) {
setEditValue(name || '');
setIsEditing(true);
}
}, [disabled, isSaving, name]);
const handleSave = useCallback(async () => {
if (isSaving) return;
const trimmed = editValue.trim();
const newName = trimmed || null;
// Only save if changed
if (newName !== name) {
setIsSaving(true);
try {
await onRename(newName);
} catch (error) {
logger.error('Failed to rename session:', error);
// Revert on error
setEditValue(name || '');
} finally {
setIsSaving(false);
}
}
setIsEditing(false);
}, [editValue, name, onRename, isSaving]);
const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
e.preventDefault();
handleSave();
} else if (e.key === 'Escape') {
setEditValue(name || '');
setIsEditing(false);
}
}, [handleSave, name]);
const handleBlur = useCallback(() => {
handleSave();
}, [handleSave]);
const displayName = name || 'Untitled Session';
if (isEditing) {
return (
<input
ref={inputRef}
type="text"
className="session-name-input"
value={editValue}
onChange={(e) => setEditValue(e.target.value)}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
placeholder="Untitled Session"
maxLength={100}
disabled={isSaving}
aria-label="Session name"
/>
);
}
return (
<button
type="button"
className={`session-name ${disabled ? 'session-name-disabled' : ''}`}
onClick={handleClick}
title={disabled ? displayName : 'Click to rename'}
aria-label={`Session name: ${displayName}. ${disabled ? '' : 'Click to rename'}`}
>
{displayName}
{isSaving && <span className="session-name-saving">...</span>}
</button>
);
}