History

fix: improve business logic in prompt editor and fix cursor bugs in Plan mode (#867)

Noah Gregory committed 8 months ago

Commit f63cda21 parent b60a34e2 files · +50 −20Browse files

Unified · Split

2 files
  1. apps/web/src/components/ChatView.tsx +32 −9
  2. apps/web/src/components/ComposerPromptEditor.tsx +18 −11
apps/web/src/components/ChatView.tsx+32−9
@@ -633,23 +633,46 @@ export default function ChatView({ threadId }: ChatViewProps) { · 632 unmodified lines
633633 pendingUserInputs.length > 0 ||
634634 (showPlanFollowUpPrompt && activeProposedPlan !== null);
635635 const composerFooterHasWideActions = showPlanFollowUpPrompt || activePendingProgress !== null;
636+ const lastSyncedPendingInputRef = useRef<{
637+ requestId: string | null;
638+ questionId: string | null;
639+ } | null>(null);
636640 useEffect(() => {
637− if (!activePendingProgress) {
641+ const nextCustomAnswer = activePendingProgress?.customAnswer;
642+ if (typeof nextCustomAnswer !== "string") {
643+ lastSyncedPendingInputRef.current = null;
638644 return;
639645 }
640− promptRef.current = activePendingProgress.customAnswer;
641− setComposerCursor(activePendingProgress.customAnswer.length);
646+ const nextRequestId = activePendingUserInput?.requestId ?? null;
647+ const nextQuestionId = activePendingProgress?.activeQuestion?.id ?? null;
648+ const questionChanged =
649+ lastSyncedPendingInputRef.current?.requestId !== nextRequestId ||
650+ lastSyncedPendingInputRef.current?.questionId !== nextQuestionId;
651+ const textChangedExternally = promptRef.current !== nextCustomAnswer;
652+
653+ lastSyncedPendingInputRef.current = {
654+ requestId: nextRequestId,
655+ questionId: nextQuestionId,
656+ };
657+
658+ if (!questionChanged && !textChangedExternally) {
659+ return;
660+ }
661+
662+ promptRef.current = nextCustomAnswer;
663+ setComposerCursor(nextCustomAnswer.length);
642664 setComposerTrigger(
643665 detectComposerTrigger(
644− activePendingProgress.customAnswer,
645− expandCollapsedComposerCursor(
646− activePendingProgress.customAnswer,
647− activePendingProgress.customAnswer.length,
648− ),
666+ nextCustomAnswer,
667+ expandCollapsedComposerCursor(nextCustomAnswer, nextCustomAnswer.length),
649668 ),
650669 );
651670 setComposerHighlightedItemId(null);
652− }, [activePendingProgress, activePendingUserInput?.requestId]);
671+ }, [
672+ activePendingProgress?.customAnswer,
673+ activePendingUserInput?.requestId,
674+ activePendingProgress?.activeQuestion?.id,
675+ ]);
653676 useEffect(() => {
654677 attachmentPreviewHandoffByMessageIdRef.current = attachmentPreviewHandoffByMessageId;
655678 }, [attachmentPreviewHandoffByMessageId]);
apps/web/src/components/ComposerPromptEditor.tsx+18−11
@@ -629,6 +629,7 @@ function ComposerPromptEditorInner({ · 628 unmodified lines
629629 const [editor] = useLexicalComposerContext();
630630 const onChangeRef = useRef(onChange);
631631 const snapshotRef = useRef({ value, cursor: clampCursor(value, cursor) });
632+ const isApplyingControlledUpdateRef = useRef(false);
632633
633634 useEffect(() => {
634635 onChangeRef.current = onChange;
@@ -645,21 +646,26 @@ function ComposerPromptEditorInner({ · 10 unmodified lines
645646 return;
646647 }
647648
648− if (previousSnapshot.value !== value) {
649− editor.update(() => {
650− $setComposerEditorPrompt(value);
651− });
652− }
653−
654649 snapshotRef.current = { value, cursor: normalizedCursor };
655650
656651 const rootElement = editor.getRootElement();
657− if (!rootElement || document.activeElement !== rootElement) {
652+ const isFocused = Boolean(rootElement && document.activeElement === rootElement);
653+ if (previousSnapshot.value === value && !isFocused) {
658654 return;
659655 }
660656
657+ isApplyingControlledUpdateRef.current = true;
661658 editor.update(() => {
662− $setSelectionAtComposerOffset(normalizedCursor);
659+ const valueChanged = previousSnapshot.value !== value;
660+ if (previousSnapshot.value !== value) {
661+ $setComposerEditorPrompt(value);
662+ }
663+ if (valueChanged || isFocused) {
664+ $setSelectionAtComposerOffset(normalizedCursor);
665+ }
666+ });
667+ queueMicrotask(() => {
668+ isApplyingControlledUpdateRef.current = false;
663669 });
664670 }, [cursor, editor, value]);
665671
@@ -705,9 +711,7 @@ function ComposerPromptEditorInner({ · 39 unmodified lines
705711 focus: () => {
706712 focusAt(snapshotRef.current.cursor);
707713 },
708− focusAt: (nextCursor: number) => {
709− focusAt(nextCursor);
710− },
714+ focusAt,
711715 focusAtEnd: () => {
712716 focusAt(snapshotRef.current.value.length);
713717 },
@@ -728,6 +732,9 @@ function ComposerPromptEditorInner({ · 14 unmodified lines
728732 if (previousSnapshot.value === nextValue && previousSnapshot.cursor === nextCursor) {
729733 return;
730734 }
735+ if (isApplyingControlledUpdateRef.current) {
736+ return;
737+ }
731738 snapshotRef.current = {
732739 value: nextValue,
733740 cursor: nextCursor,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t