Skip to content

Commit 9c7e60f

Browse files
fix: improved terminal window handling
1 parent 6119722 commit 9c7e60f

File tree

2 files changed

+24
-20
lines changed

2 files changed

+24
-20
lines changed

src/hooks/usePanes.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,18 @@ export default function usePanes(panesFile: string, skipLoading: boolean) {
3333
const [panes, setPanes] = useState<DmuxPane[]>([]);
3434
const [isLoading, setIsLoading] = useState(true);
3535
const initialLoadComplete = useRef(false);
36+
const isLoadingPanes = useRef(false); // Guard against concurrent loadPanes calls
3637

3738
const loadPanes = async () => {
3839
if (skipLoading) return;
3940

41+
// Prevent concurrent loadPanes calls which can cause race conditions
42+
// and duplicate pane detection
43+
if (isLoadingPanes.current) {
44+
return;
45+
}
46+
isLoadingPanes.current = true;
47+
4048
try {
4149
// Load panes from file and rebind IDs based on tmux state
4250
const { panes: loadedPanes, allPaneIds, titleToId } = await loadAndProcessPanes(
@@ -140,6 +148,7 @@ export default function usePanes(panesFile: string, skipLoading: boolean) {
140148
'usePanes'
141149
);
142150
} finally {
151+
isLoadingPanes.current = false;
143152
if (isLoading) setIsLoading(false);
144153
}
145154
};

src/utils/shellPaneDetection.ts

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -157,32 +157,27 @@ export async function getUntrackedPanes(
157157
* Creates a DmuxPane object for a shell pane
158158
* @param paneId The tmux pane ID
159159
* @param nextId The next available dmux ID number
160-
* @param existingTitle Optional existing title to preserve
160+
* @param existingTitle Optional existing title (used for display but not for tracking)
161161
* @returns DmuxPane object for the shell pane
162162
*/
163163
export async function createShellPane(paneId: string, nextId: number, existingTitle?: string): Promise<DmuxPane> {
164164
const tmuxService = TmuxService.getInstance();
165165
const shellType = await detectShellType(paneId);
166166

167-
// Use existing title if available and it's not a dmux internal title
168-
// Otherwise generate shell-N naming
169-
let slug: string;
170-
if (existingTitle &&
171-
existingTitle !== 'dmux-spacer' &&
172-
!existingTitle.startsWith('dmux v') &&
173-
existingTitle !== 'Welcome') {
174-
slug = existingTitle;
175-
} else {
176-
slug = `shell-${nextId}`;
177-
// Only set the title if we're generating a new one
178-
try {
179-
await tmuxService.setPaneTitle(paneId, slug);
180-
} catch (error) {
181-
// LogService.getInstance().debug(
182-
// `Failed to set title for shell pane ${paneId}`,
183-
// 'shellDetection'
184-
// );
185-
}
167+
// CRITICAL: Always generate unique shell-N slugs for shell panes.
168+
// Using existing titles (like hostname "Gigablaster.local") causes tracking bugs
169+
// because multiple panes can have the same title, and titleToId Map can only
170+
// store one mapping per title. This leads to duplicate pane entries.
171+
const slug = `shell-${nextId}`;
172+
173+
// Always set the title to ensure unique titles for proper rebinding
174+
try {
175+
await tmuxService.setPaneTitle(paneId, slug);
176+
} catch (error) {
177+
// LogService.getInstance().debug(
178+
// `Failed to set title for shell pane ${paneId}`,
179+
// 'shellDetection'
180+
// );
186181
}
187182

188183
return {

0 commit comments

Comments
 (0)