Skip to content

Commit

Permalink
Merge pull request #497 from refly-ai/feat/support-edit-node-title
Browse files Browse the repository at this point in the history
Feat/support edit node title
  • Loading branch information
mrcfps authored Feb 12, 2025
2 parents 3abafe6 + 3cc98dd commit db3b391
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 21 deletions.
24 changes: 18 additions & 6 deletions packages/ai-workspace-common/src/components/canvas/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { useCallback, useMemo, useEffect, useState, useRef, memo } from 'react';
import { useTranslation } from 'react-i18next';
import { ReactFlow, Background, MiniMap, ReactFlowProvider, useReactFlow } from '@xyflow/react';
import {
ReactFlow,
Background,
MiniMap,
ReactFlowProvider,
useReactFlow,
Node,
} from '@xyflow/react';
import { Button } from 'antd';
import { nodeTypes, CanvasNode } from './nodes';
import { LaunchPad } from './launchpad';
Expand Down Expand Up @@ -460,15 +467,20 @@ const Flow = memo(({ canvasId }: { canvasId: string }) => {
const memoizedNodeTypes = useMemo(() => nodeTypes, []);

// Optimize node dragging performance
const { setIsNodeDragging } = useEditorPerformance();
const { setIsNodeDragging, setDraggingNodeId } = useEditorPerformance();

const onNodeDragStart = useCallback(() => {
setIsNodeDragging(true);
}, [setIsNodeDragging]);
const onNodeDragStart = useCallback(
(_: React.MouseEvent, node: Node) => {
setIsNodeDragging(true);
setDraggingNodeId(node.id);
},
[setIsNodeDragging, setDraggingNodeId],
);

const onNodeDragStop = useCallback(() => {
setIsNodeDragging(false);
}, [setIsNodeDragging]);
setDraggingNodeId(null);
}, [setIsNodeDragging, setDraggingNodeId]);

const onSelectionContextMenu = useCallback(
(event: React.MouseEvent) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { NodeHeader } from './shared/node-header';
import { ContentPreview } from './shared/content-preview';
import { useCreateDocument } from '@refly-packages/ai-workspace-common/hooks/canvas/use-create-document';
import { useDeleteDocument } from '@refly-packages/ai-workspace-common/hooks/canvas/use-delete-document';
import { useEditorPerformance } from '@refly-packages/ai-workspace-common/context/editor-performance';

export const DocumentNode = memo(
({
Expand All @@ -50,7 +51,9 @@ export const DocumentNode = memo(
operatingNodeId: state.operatingNodeId,
}));

const { draggingNodeId } = useEditorPerformance();
const isOperating = operatingNodeId === id;
const isDragging = draggingNodeId === id;
const sizeMode = data?.metadata?.sizeMode || 'adaptive';
const node = useMemo(() => getNode(id), [id, getNode]);

Expand Down Expand Up @@ -199,7 +202,7 @@ export const DocumentNode = memo(
onClick={onNodeClick}
style={isPreview ? { width: 288, height: 200 } : containerStyle}
>
{!isPreview && !hideActions && (
{!isPreview && !hideActions && !isDragging && (
<ActionButtons type="document" nodeId={id} isNodeHovered={isHovered} />
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CanvasNodeType } from '@refly/openapi-schema';
import { useAddNode } from '@refly-packages/ai-workspace-common/hooks/canvas/use-add-node';
import { useNodeCluster } from '@refly-packages/ai-workspace-common/hooks/canvas/use-node-cluster';
import Moveable from 'react-moveable';
import { useEditorPerformance } from '@refly-packages/ai-workspace-common/context/editor-performance';

interface GroupMetadata {
label?: string;
Expand Down Expand Up @@ -67,6 +68,8 @@ export const GroupNode = memo(

// Memoize node and its measurements
const node = useMemo(() => getNode(id), [id, getNode]);
const { draggingNodeId } = useEditorPerformance();
const isDragging = draggingNodeId === id;

const initialSize = useMemo(
() => ({
Expand Down Expand Up @@ -317,7 +320,9 @@ export const GroupNode = memo(

{!isPreview && !hideActions && (
<>
<ActionButtons type="group" nodeId={id} isNodeHovered={isHovered} />
{!isDragging && (
<ActionButtons type="group" nodeId={id} isNodeHovered={isHovered} />
)}
<GroupActionButtons
nodeId={id}
isTemporary={data.metadata?.isTemporary}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { useAddToContext } from '@refly-packages/ai-workspace-common/hooks/canva
import { useDeleteNode } from '@refly-packages/ai-workspace-common/hooks/canvas/use-delete-node';
import Moveable from 'react-moveable';
import { useSetNodeDataByEntity } from '@refly-packages/ai-workspace-common/hooks/canvas/use-set-node-data-by-entity';
import { useEditorPerformance } from '@refly-packages/ai-workspace-common/context/editor-performance';

export const ImageNode = memo(
({ id, data, isPreview, selected, hideActions, hideHandles, onNodeClick }: ImageNodeProps) => {
Expand All @@ -43,7 +44,9 @@ export const ImageNode = memo(
operatingNodeId: state.operatingNodeId,
}));

const { draggingNodeId } = useEditorPerformance();
const isOperating = operatingNodeId === id;
const isDragging = draggingNodeId === id;
const node = useMemo(() => getNode(id), [id, getNode]);

const { containerStyle, handleResize } = useNodeSize({
Expand Down Expand Up @@ -182,7 +185,7 @@ export const ImageNode = memo(
'nodrag nopan select-text': isOperating,
})}
>
{!isPreview && !hideActions && (
{!isPreview && !hideActions && !isDragging && (
<ActionButtons type="image" nodeId={id} isNodeHovered={isHovered} />
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { ContentPreview } from './shared/content-preview';
import { useCreateDocument } from '@refly-packages/ai-workspace-common/hooks/canvas/use-create-document';
import { message } from 'antd';
import getClient from '@refly-packages/ai-workspace-common/requests/proxiedRequest';

import { useEditorPerformance } from '@refly-packages/ai-workspace-common/context/editor-performance';
export const ResourceNode = memo(
({ id, data, isPreview, selected, hideActions, hideHandles, onNodeClick }: ResourceNodeProps) => {
const [isHovered, setIsHovered] = useState(false);
Expand All @@ -54,7 +54,9 @@ export const ResourceNode = memo(
operatingNodeId: state.operatingNodeId,
}));

const { draggingNodeId } = useEditorPerformance();
const isOperating = operatingNodeId === id;
const isDragging = draggingNodeId === id;
const sizeMode = data?.metadata?.sizeMode || 'adaptive';
const node = useMemo(() => getNode(id), [id, getNode]);

Expand Down Expand Up @@ -249,7 +251,7 @@ export const ResourceNode = memo(
'nodrag nopan select-text': isOperating,
})}
>
{!isPreview && !hideActions && (
{!isPreview && !hideActions && !isDragging && (
<ActionButtons type="resource" nodeId={id} isNodeHovered={isHovered} />
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Position, useReactFlow } from '@xyflow/react';
import { useTranslation } from 'react-i18next';
import Moveable from 'react-moveable';
import classNames from 'classnames';
import { Divider, message } from 'antd';
import { Divider, Input, message } from 'antd';
import { CanvasNode, SkillResponseNodeProps } from './shared/types';
import { useState, useCallback, useRef, useEffect, useMemo, memo } from 'react';
import { CustomHandle } from './shared/custom-handle';
Expand Down Expand Up @@ -47,24 +47,39 @@ import { NodeResizer as NodeResizerComponent } from './shared/node-resizer';
import { useNodeSize } from '@refly-packages/ai-workspace-common/hooks/canvas/use-node-size';
import { ContentPreview } from './shared/content-preview';
import { useActionPolling } from '@refly-packages/ai-workspace-common/hooks/canvas/use-action-polling';

import { useSetNodeDataByEntity } from '@refly-packages/ai-workspace-common/hooks/canvas/use-set-node-data-by-entity';
import { useEditorPerformance } from '@refly-packages/ai-workspace-common/context/editor-performance';
const POLLING_WAIT_TIME = 15000;

const NodeHeader = memo(
({ query, skillName, skill }: { query: string; skillName: string; skill: any }) => {
({
query,
skillName,
skill,
updateTitle,
}: { query: string; skillName: string; skill: any; updateTitle: (title: string) => void }) => {
const [editTitle, setEditTitle] = useState(query);
return (
<>
<div className="flex-shrink-0 mb-3">
<div className="flex items-center gap-2">
<div className="w-6 h-6 rounded bg-[#F79009] shadow-lg flex items-center justify-center flex-shrink-0">
<IconResponse className="w-4 h-4 text-white" />
</div>
<span
<Input
className="!border-transparent font-bold focus:!bg-transparent px-0.5 py-0"
value={editTitle}
onChange={(e) => {
setEditTitle(e.target.value);
updateTitle?.(e.target.value);
}}
/>
{/* <span
className="text-sm font-medium leading-normal truncate block cursor-pointer"
title={query}
>
{query}
</span>
</span> */}
</div>
</div>
{skillName && skillName !== 'commonQnA' && (
Expand Down Expand Up @@ -146,12 +161,14 @@ export const SkillResponseNode = memo(
onNodeClick,
}: SkillResponseNodeProps) => {
const [isHovered, setIsHovered] = useState(false);
const { draggingNodeId } = useEditorPerformance();
const isDragging = draggingNodeId === id;

const { edges, operatingNodeId } = useCanvasStoreShallow((state) => ({
edges: state.data[state.currentCanvasId]?.edges ?? [],
operatingNodeId: state.operatingNodeId,
}));

const setNodeDataByEntity = useSetNodeDataByEntity();
const patchNodeData = usePatchNodeData();
const { getNode } = useReactFlow();
const { handleMouseEnter: onHoverStart, handleMouseLeave: onHoverEnd } = useNodeHoverEffect(id);
Expand Down Expand Up @@ -402,6 +419,18 @@ export const SkillResponseNode = memo(
nodeActionEmitter.emit(createNodeEventName(id, 'cloneAskAI.completed'));
}, [id, data?.entityId, addNode, t]);

const onTitleChange = (newTitle: string) => {
setNodeDataByEntity(
{
entityId: data.entityId,
type: 'skillResponse',
},
{
title: newTitle,
},
);
};

// Update size when content changes
useEffect(() => {
if (!targetRef.current) return;
Expand Down Expand Up @@ -470,7 +499,7 @@ export const SkillResponseNode = memo(
onMouseLeave={handleMouseLeave}
onClick={onNodeClick}
>
{!isPreview && !hideActions && (
{!isPreview && !hideActions && !isDragging && (
<ActionButtons type="skillResponse" nodeId={id} isNodeHovered={isHovered} />
)}

Expand Down Expand Up @@ -499,7 +528,12 @@ export const SkillResponseNode = memo(
<div className="absolute bottom-0 left-0 right-0 h-[15%] bg-gradient-to-t from-white to-transparent pointer-events-none z-10" />

<div className="flex flex-col h-full">
<NodeHeader query={query} skillName={skillName} skill={skill} />
<NodeHeader
query={query}
skillName={skillName}
skill={skill}
updateTitle={onTitleChange}
/>

<div className={'flex-grow overflow-y-auto pr-2 -mr-2'}>
<div className="flex flex-col gap-3">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { NodeResizer as NodeResizerComponent } from './shared/node-resizer';
import classNames from 'classnames';
import Moveable from 'react-moveable';
import { useUploadImage } from '@refly-packages/ai-workspace-common/hooks/use-upload-image';
import { useEditorPerformance } from '@refly-packages/ai-workspace-common/context/editor-performance';

type SkillNode = Node<CanvasNodeData<SkillNodeMeta>, 'skill'>;

Expand Down Expand Up @@ -115,7 +116,9 @@ export const SkillNode = memo(
const { operatingNodeId } = useCanvasStoreShallow((state) => ({
operatingNodeId: state.operatingNodeId,
}));
const { draggingNodeId } = useEditorPerformance();
const isOperating = operatingNodeId === id;
const isDragging = draggingNodeId === id;
const node = useMemo(() => getNode(id), [id, getNode]);
const { containerStyle, handleResize, updateSize } = useNodeSize({
id,
Expand Down Expand Up @@ -344,7 +347,7 @@ export const SkillNode = memo(
onMouseLeave={handleMouseLeave}
style={containerStyle}
>
<ActionButtons type="skill" nodeId={id} isNodeHovered={isHovered} />
{!isDragging && <ActionButtons type="skill" nodeId={id} isNodeHovered={isHovered} />}
<div className={`w-full h-full ${getNodeCommonStyles({ selected, isHovered })}`}>
<CustomHandle
type="target"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@ import { createContext, useContext, useState } from 'react';
interface EditorPerformanceContextType {
isNodeDragging: boolean;
setIsNodeDragging: (dragging: boolean) => void;
draggingNodeId: string | null;
setDraggingNodeId: (nodeId: string | null) => void;
}

const EditorPerformanceContext = createContext<EditorPerformanceContextType>({
isNodeDragging: false,
setIsNodeDragging: () => {},
draggingNodeId: null,
setDraggingNodeId: () => {},
});

export const EditorPerformanceProvider = ({ children }) => {
const [isNodeDragging, setIsNodeDragging] = useState(false);
const [draggingNodeId, setDraggingNodeId] = useState<string | null>(null);

return (
<EditorPerformanceContext.Provider value={{ isNodeDragging, setIsNodeDragging }}>
<EditorPerformanceContext.Provider
value={{ isNodeDragging, setIsNodeDragging, draggingNodeId, setDraggingNodeId }}
>
{children}
</EditorPerformanceContext.Provider>
);
Expand Down

0 comments on commit db3b391

Please sign in to comment.