Download src/hooks/use-conversation-name-context-menu.ts from SaylorTwift/openhands: direct link, hf CLI and curl.
- Browser
- Download file 7.56 kB
-
https://huggingface.co/SaylorTwift/openhands/resolve/main/src/hooks/use-conversation-name-context-menu.ts
- Command line
-
hf download hf://SaylorTwift/openhands/src/hooks/use-conversation-name-context-menu.ts
-
curl -L -o use-conversation-name-context-menu.ts https://huggingface.co/SaylorTwift/openhands/resolve/main/src/hooks/use-conversation-name-context-menu.ts
7.56 kB
| import React from "react"; | |
| import { useTranslation } from "react-i18next"; | |
| import { useNavigation } from "#/context/navigation-context"; | |
| import { useActiveBackend } from "#/contexts/active-backend-context"; | |
| import { useDeleteConversation } from "./mutation/use-delete-conversation"; | |
| import { useUnifiedPauseConversation } from "./mutation/use-unified-stop-conversation"; | |
| import { useUpdateConversationPublicFlag } from "./mutation/use-update-conversation-public-flag"; | |
| import { useActiveConversation } from "./query/use-active-conversation"; | |
| import { useEventStore } from "#/stores/use-event-store"; | |
| import { displaySuccessToast } from "#/utils/custom-toast-handlers"; | |
| import { I18nKey } from "#/i18n/declaration"; | |
| import { getStoredConversationMetadata } from "#/api/conversation-metadata-store"; | |
| import { useDownloadConversation } from "./use-download-conversation"; | |
| import { | |
| adaptSystemMessage, | |
| SystemMessageForModal, | |
| } from "#/utils/system-message-adapter"; | |
| import { ExecutionStatus } from "#/types/agent-server/core/base/common"; | |
| import { isExecutionActive } from "#/utils/status"; | |
| import { useSelectConversationTab } from "./use-select-conversation-tab"; | |
| interface UseConversationNameContextMenuProps { | |
| conversationId?: string; | |
| executionStatus?: ExecutionStatus | null; | |
| showOptions?: boolean; | |
| onContextMenuToggle?: (isOpen: boolean) => void; | |
| } | |
| export function useConversationNameContextMenu({ | |
| conversationId, | |
| executionStatus, | |
| showOptions = false, | |
| onContextMenuToggle, | |
| }: UseConversationNameContextMenuProps) { | |
| const { t } = useTranslation(); | |
| const { conversationId: currentConversationId, navigate } = useNavigation(); | |
| const { backend } = useActiveBackend(); | |
| const events = useEventStore((state) => state.events); | |
| const { mutate: deleteConversation } = useDeleteConversation(); | |
| const { mutate: stopConversation } = useUnifiedPauseConversation(); | |
| const { mutate: updatePublicFlag } = useUpdateConversationPublicFlag(); | |
| const { data: conversation } = useActiveConversation(); | |
| const [systemModalVisible, setSystemModalVisible] = React.useState(false); | |
| const [skillsModalVisible, setSkillsModalVisible] = React.useState(false); | |
| const [pluginsModalVisible, setPluginsModalVisible] = React.useState(false); | |
| const [hooksModalVisible, setHooksModalVisible] = React.useState(false); | |
| const [confirmDeleteModalVisible, setConfirmDeleteModalVisible] = | |
| React.useState(false); | |
| const [confirmStopModalVisible, setConfirmStopModalVisible] = | |
| React.useState(false); | |
| const { mutateAsync: downloadConversation } = useDownloadConversation(); | |
| const { navigateToTab } = useSelectConversationTab(); | |
| const systemMessage: SystemMessageForModal | null = | |
| adaptSystemMessage(events); | |
| const handleDelete = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| setConfirmDeleteModalVisible(true); | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleStop = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| setConfirmStopModalVisible(true); | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleConfirmDelete = () => { | |
| if (conversationId) { | |
| deleteConversation( | |
| { conversationId }, | |
| { | |
| onSuccess: () => { | |
| if (conversationId === currentConversationId) { | |
| navigate("/conversations"); | |
| } | |
| }, | |
| }, | |
| ); | |
| } | |
| setConfirmDeleteModalVisible(false); | |
| }; | |
| const handleConfirmStop = () => { | |
| if (conversationId) { | |
| stopConversation({ conversationId }); | |
| } | |
| setConfirmStopModalVisible(false); | |
| }; | |
| const handleEdit = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| // This will be handled by the parent component to switch to edit mode | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleDownloadConversation = async ( | |
| event: React.MouseEvent<HTMLButtonElement>, | |
| ) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| if (conversationId) { | |
| await downloadConversation(conversationId); | |
| } | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleDisplayCost = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.stopPropagation(); | |
| navigateToTab("usage"); | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleShowAgentTools = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.stopPropagation(); | |
| setSystemModalVisible(true); | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleShowSkills = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.stopPropagation(); | |
| setSkillsModalVisible(true); | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleShowPlugins = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.stopPropagation(); | |
| setPluginsModalVisible(true); | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleShowHooks = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.stopPropagation(); | |
| setHooksModalVisible(true); | |
| onContextMenuToggle?.(false); | |
| }; | |
| const handleTogglePublic = (nextIsPublic?: boolean) => { | |
| if (conversationId && conversation) { | |
| updatePublicFlag({ | |
| conversationId, | |
| isPublic: nextIsPublic ?? !conversation.public, | |
| }); | |
| } | |
| // Intentionally don't close the menu — let the user see the toggle flip. | |
| }; | |
| const shareUrl = React.useMemo(() => { | |
| if (!conversationId) return ""; | |
| // On cloud backends, the shareable URL must point at the cloud | |
| // environment's host (e.g. the cloud app domain) rather than the local | |
| // dev origin so the link works for anyone the user shares it with. | |
| const origin = | |
| backend.kind === "cloud" | |
| ? backend.host.replace(/\/+$/, "") | |
| : window.location.origin; | |
| return `${origin}/shared/conversations/${conversationId}`; | |
| }, [conversationId, backend.kind, backend.host]); | |
| const handleCopyShareLink = (event: React.MouseEvent<HTMLButtonElement>) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| if (!shareUrl) { | |
| onContextMenuToggle?.(false); | |
| return; | |
| } | |
| navigator.clipboard.writeText(shareUrl); | |
| displaySuccessToast(t(I18nKey.CONVERSATION$LINK_COPIED)); | |
| }; | |
| return { | |
| // Handlers | |
| handleDelete, | |
| handleStop, | |
| handleEdit, | |
| handleDownloadConversation, | |
| handleDisplayCost, | |
| handleShowAgentTools, | |
| handleShowSkills, | |
| handleShowPlugins, | |
| handleShowHooks, | |
| handleTogglePublic, | |
| handleCopyShareLink, | |
| shareUrl, | |
| handleConfirmDelete, | |
| handleConfirmStop, | |
| // Modal states | |
| systemModalVisible, | |
| setSystemModalVisible, | |
| skillsModalVisible, | |
| setSkillsModalVisible, | |
| pluginsModalVisible, | |
| setPluginsModalVisible, | |
| hooksModalVisible, | |
| setHooksModalVisible, | |
| confirmDeleteModalVisible, | |
| setConfirmDeleteModalVisible, | |
| confirmStopModalVisible, | |
| setConfirmStopModalVisible, | |
| // Data | |
| systemMessage, | |
| shouldShowStop: isExecutionActive(executionStatus), | |
| shouldShowDownloadConversation: Boolean(conversationId && showOptions), | |
| shouldShowDisplayCost: showOptions, | |
| shouldShowAgentTools: Boolean(showOptions && systemMessage), | |
| shouldShowSkills: Boolean(showOptions && conversationId), | |
| shouldShowPlugins: Boolean( | |
| showOptions && | |
| conversationId && | |
| (getStoredConversationMetadata(conversationId)?.plugins?.length ?? 0) > 0, | |
| ), | |
| shouldShowHooks: Boolean( | |
| showOptions && conversationId && isExecutionActive(executionStatus), | |
| ), | |
| }; | |
| } | |