Fix zombie tab context menus (#1390)

The memoizing of the tabs was causing the callbacks for
handleContextMenu to become dead ends. This makes more of the callbacks
into memoized callbacks and makes the handleContextMenu function itself
a memoized callback to ensure it's properly updated when its upstream
callbacks change.
This commit is contained in:
Evan Simkowitz 2024-12-04 20:30:28 -05:00 committed by GitHub
parent 87aea21184
commit df2889f280
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 46 deletions

View File

@ -7,7 +7,7 @@ import { TabRpcClient } from "@/app/store/wshrpcutil";
import { Button } from "@/element/button"; import { Button } from "@/element/button";
import { ContextMenuModel } from "@/store/contextmenu"; import { ContextMenuModel } from "@/store/contextmenu";
import { clsx } from "clsx"; import { clsx } from "clsx";
import { forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react"; import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
import { ObjectService } from "../store/services"; import { ObjectService } from "../store/services";
import { makeORef, useWaveObjectValue } from "../store/wos"; import { makeORef, useWaveObjectValue } from "../store/wos";
import "./tab.scss"; import "./tab.scss";
@ -144,10 +144,11 @@ const Tab = memo(
event.stopPropagation(); event.stopPropagation();
}; };
function handleContextMenu(e: React.MouseEvent<HTMLDivElement, MouseEvent>) { const handleContextMenu = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
e.preventDefault(); e.preventDefault();
let menu: ContextMenuItem[] = [ let menu: ContextMenuItem[] = [
{ label: isPinned ? "Unpin Tab" : "Pin Tab", click: onPinChange }, { label: isPinned ? "Unpin Tab" : "Pin Tab", click: () => onPinChange() },
{ label: "Rename Tab", click: () => handleRenameTab(null) }, { label: "Rename Tab", click: () => handleRenameTab(null) },
{ label: "Copy TabId", click: () => navigator.clipboard.writeText(id) }, { label: "Copy TabId", click: () => navigator.clipboard.writeText(id) },
{ type: "separator" }, { type: "separator" },
@ -184,7 +185,9 @@ const Tab = memo(
} }
menu.push({ label: "Close Tab", click: () => onClose(null) }); menu.push({ label: "Close Tab", click: () => onClose(null) });
ContextMenuModel.showContextMenu(menu, e); ContextMenuModel.showContextMenu(menu, e);
} },
[onPinChange, handleRenameTab, id, onClose, isPinned]
);
return ( return (
<div <div

View File

@ -574,12 +574,15 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
deleteLayoutModelForTab(tabId); deleteLayoutModelForTab(tabId);
}; };
const handlePinChange = (tabId: string, pinned: boolean) => { const handlePinChange = useCallback(
(tabId: string, pinned: boolean) => {
console.log("handlePinChange", tabId, pinned); console.log("handlePinChange", tabId, pinned);
fireAndForget(async () => { fireAndForget(async () => {
await WorkspaceService.ChangeTabPinning(workspace.oid, tabId, pinned); await WorkspaceService.ChangeTabPinning(workspace.oid, tabId, pinned);
}); });
}; },
[workspace]
);
const handleTabLoaded = useCallback((tabId: string) => { const handleTabLoaded = useCallback((tabId: string) => {
setTabsLoaded((prev) => { setTabsLoaded((prev) => {