|
|
|
@ -1,6 +1,6 @@ |
|
|
|
"use client"; |
|
|
|
|
|
|
|
import { useState, useMemo, useCallback, useEffect, type ReactNode } from "react"; |
|
|
|
import { useState, useMemo, useCallback, useEffect, useRef, type ReactNode } from "react"; |
|
|
|
import Link from "next/link"; |
|
|
|
import { useSearchParams } from "next/navigation"; |
|
|
|
import { |
|
|
|
@ -16,6 +16,7 @@ import { CostIndicator } from "./CostIndicator"; |
|
|
|
import { useI18n } from "@/i18n"; |
|
|
|
import { buildSerializedWorkflow } from "@/store/utils/workflowSerialization"; |
|
|
|
import { HeaderUserMenu } from "@/components/auth/HeaderUserMenu"; |
|
|
|
import { useCommitOnOutsidePointerDown } from "@/hooks/useCommitOnOutsidePointerDown"; |
|
|
|
|
|
|
|
const SHOW_UNUSED_HEADER_ACTIONS = false; |
|
|
|
|
|
|
|
@ -123,6 +124,9 @@ export function Header() { |
|
|
|
|
|
|
|
const [showSettingsModal, setShowSettingsModal] = useState(false); |
|
|
|
const [workflowNameDraft, setWorkflowNameDraft] = useState(workflowName || ""); |
|
|
|
const [isEditingWorkflowName, setIsEditingWorkflowName] = useState(false); |
|
|
|
const workflowNameEditorRef = useRef<HTMLDivElement>(null); |
|
|
|
const lastCommittedWorkflowNameDraftRef = useRef<string | null>(null); |
|
|
|
const currentCanvasWorkflowDescription = useCanvasWorkflowStore((state) => state.currentCanvasWorkflowDescription); |
|
|
|
const setCurrentCanvasWorkflow = useCanvasWorkflowStore((state) => state.setCurrentCanvasWorkflow); |
|
|
|
|
|
|
|
@ -159,12 +163,20 @@ export function Header() { |
|
|
|
|
|
|
|
const commitWorkflowName = useCallback(() => { |
|
|
|
const nextName = workflowNameDraft.trim(); |
|
|
|
if (lastCommittedWorkflowNameDraftRef.current === nextName) { |
|
|
|
setIsEditingWorkflowName(false); |
|
|
|
return; |
|
|
|
} |
|
|
|
lastCommittedWorkflowNameDraftRef.current = nextName; |
|
|
|
|
|
|
|
if (!nextName || nextName === workflowName) { |
|
|
|
setWorkflowNameDraft(workflowName || ""); |
|
|
|
setIsEditingWorkflowName(false); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
setWorkflowName(nextName); |
|
|
|
setIsEditingWorkflowName(false); |
|
|
|
if (urlWorkflowId) { |
|
|
|
setCurrentCanvasWorkflow({ |
|
|
|
title: nextName, |
|
|
|
@ -180,6 +192,12 @@ export function Header() { |
|
|
|
setCurrentCanvasWorkflow, |
|
|
|
]); |
|
|
|
|
|
|
|
useCommitOnOutsidePointerDown({ |
|
|
|
active: isEditingWorkflowName, |
|
|
|
rootRef: workflowNameEditorRef, |
|
|
|
onCommit: commitWorkflowName, |
|
|
|
}); |
|
|
|
|
|
|
|
const handleRevertAIChanges = useCallback(() => { |
|
|
|
const confirmed = window.confirm( |
|
|
|
t("header.revertConfirm") |
|
|
|
@ -205,7 +223,7 @@ export function Header() { |
|
|
|
</Link> |
|
|
|
|
|
|
|
<div className="flex min-w-0 items-center gap-2 pl-2"> |
|
|
|
<div className="grid shrink-0"> |
|
|
|
<div ref={workflowNameEditorRef} className="grid shrink-0"> |
|
|
|
<span |
|
|
|
aria-hidden="true" |
|
|
|
className="invisible col-start-1 row-start-1 whitespace-pre text-sm font-medium" |
|
|
|
@ -214,7 +232,11 @@ export function Header() { |
|
|
|
</span> |
|
|
|
<input |
|
|
|
value={workflowNameDraft} |
|
|
|
onChange={(event) => setWorkflowNameDraft(event.target.value)} |
|
|
|
onChange={(event) => { |
|
|
|
lastCommittedWorkflowNameDraftRef.current = null; |
|
|
|
setWorkflowNameDraft(event.target.value); |
|
|
|
}} |
|
|
|
onFocus={() => setIsEditingWorkflowName(true)} |
|
|
|
onBlur={commitWorkflowName} |
|
|
|
onKeyDown={(event) => { |
|
|
|
if (event.key === "Enter") { |
|
|
|
|