| @@ -30,6 +30,7 @@ import { · 29 unmodified lines |
| 30 | useRef, | 30 | useRef, |
| 31 | useState, | 31 | useState, |
| 32 | } from "react"; | 32 | } from "react"; |
| | 33 | import { flushSync } from "react-dom"; |
| 33 | import { useQuery } from "@tanstack/react-query"; | 34 | import { useQuery } from "@tanstack/react-query"; |
| 34 | import { useDebouncedValue } from "@tanstack/react-pacer"; | 35 | import { useDebouncedValue } from "@tanstack/react-pacer"; |
| 35 | import { projectSearchEntriesQueryOptions } from "~/lib/projectReactQuery"; | 36 | import { projectSearchEntriesQueryOptions } from "~/lib/projectReactQuery"; |
| @@ -71,6 +72,7 @@ import { ComposerPendingUserInputPanel } from "./ComposerPendingUserInputPanel"; · 35 unmodified lines |
| 71 | import { ComposerPlanFollowUpBanner } from "./ComposerPlanFollowUpBanner"; | 72 | import { ComposerPlanFollowUpBanner } from "./ComposerPlanFollowUpBanner"; |
| 72 | import { resolveComposerMenuActiveItemId } from "./composerMenuHighlight"; | 73 | import { resolveComposerMenuActiveItemId } from "./composerMenuHighlight"; |
| 73 | import { searchSlashCommandItems } from "./composerSlashCommandSearch"; | 74 | import { searchSlashCommandItems } from "./composerSlashCommandSearch"; |
| | 75 | import { expandMobileComposerForKeyboard } from "./mobileComposerFocus"; |
| 74 | import { | 76 | import { |
| 75 | getComposerProviderState, | 77 | getComposerProviderState, |
| 76 | renderProviderTraitsMenuContent, | 78 | renderProviderTraitsMenuContent, |
| @@ -1627,25 +1629,42 @@ export const ChatComposer = memo( · 1550 unmodified lines |
| 1627 | [blurMobileComposerAfterSend, onSend, shouldBlurMobileComposerOnSubmit], | 1629 | [blurMobileComposerAfterSend, onSend, shouldBlurMobileComposerOnSubmit], |
| 1628 | ); | 1630 | ); |
| 1629 | const expandMobileComposer = useCallback(() => { | 1631 | const expandMobileComposer = useCallback(() => { |
| 1630 | if (composerBlurFrameRef.current !== null) { | 1632 | expandMobileComposerForKeyboard({ |
| 1631 | window.cancelAnimationFrame(composerBlurFrameRef.current); | 1633 | cancelPendingBlur: () => { |
| 1632 | composerBlurFrameRef.current = null; | 1634 | if (composerBlurFrameRef.current !== null) { |
| 1633 | } | 1635 | window.cancelAnimationFrame(composerBlurFrameRef.current); |
| 1634 | if (mobileComposerExpandFrameRef.current !== null) { | 1636 | composerBlurFrameRef.current = null; |
| 1635 | window.cancelAnimationFrame(mobileComposerExpandFrameRef.current); | 1637 | } |
| 1636 | } | 1638 | }, |
| 1637 | if (mobileComposerExpandReleaseFrameRef.current !== null) { | 1639 | cancelPendingExpandFocus: () => { |
| 1638 | window.cancelAnimationFrame(mobileComposerExpandReleaseFrameRef.current); | 1640 | if (mobileComposerExpandFrameRef.current !== null) { |
| 1639 | } | 1641 | window.cancelAnimationFrame(mobileComposerExpandFrameRef.current); |
| 1640 | mobileComposerExpandInFlightRef.current = true; | 1642 | mobileComposerExpandFrameRef.current = null; |
| 1641 | setIsComposerFocused(true); | 1643 | } |
| 1642 | mobileComposerExpandFrameRef.current = window.requestAnimationFrame(() => { | 1644 | }, |
| 1643 | mobileComposerExpandFrameRef.current = null; | 1645 | cancelPendingRelease: () => { |
| 1644 | composerEditorRef.current?.focusAtEnd(); | 1646 | if (mobileComposerExpandReleaseFrameRef.current !== null) { |
| 1645 | mobileComposerExpandReleaseFrameRef.current = window.requestAnimationFrame(() => { | 1647 | window.cancelAnimationFrame(mobileComposerExpandReleaseFrameRef.current); |
| 1646 | mobileComposerExpandReleaseFrameRef.current = null; | 1648 | mobileComposerExpandReleaseFrameRef.current = null; |
| 1647 | mobileComposerExpandInFlightRef.current = false; | 1649 | } |
| 1648 | }); | 1650 | }, |
| | 1651 | setExpandInFlight: (inFlight) => { |
| | 1652 | mobileComposerExpandInFlightRef.current = inFlight; |
| | 1653 | }, |
| | 1654 | commitExpandedState: () => { |
| | 1655 | flushSync(() => { |
| | 1656 | setIsComposerFocused(true); |
| | 1657 | }); |
| | 1658 | }, |
| | 1659 | focusEditorAtEnd: () => { |
| | 1660 | composerEditorRef.current?.focusAtEnd(); |
| | 1661 | }, |
| | 1662 | scheduleRelease: () => { |
| | 1663 | mobileComposerExpandReleaseFrameRef.current = window.requestAnimationFrame(() => { |
| | 1664 | mobileComposerExpandReleaseFrameRef.current = null; |
| | 1665 | mobileComposerExpandInFlightRef.current = false; |
| | 1666 | }); |
| | 1667 | }, |
| 1649 | }); | 1668 | }); |
| 1650 | }, []); | 1669 | }, []); |
| 1651 | | 1670 | |
| @@ -2063,7 +2082,10 @@ export const ChatComposer = memo( · 411 unmodified lines |
| 2063 | : "text-muted-foreground/60", | 2082 | : "text-muted-foreground/60", |
| 2064 | !activePendingProgress?.activeQuestion?.multiSelect && "px-3 py-2", | 2083 | !activePendingProgress?.activeQuestion?.multiSelect && "px-3 py-2", |
| 2065 | )} | 2084 | )} |
| 2066 | onPointerDown={(event) => event.preventDefault()} | 2085 | onPointerDown={(event) => { |
| | 2086 | event.preventDefault(); |
| | 2087 | expandMobileComposer(); |
| | 2088 | }} |
| 2067 | onClick={expandMobileComposer} | 2089 | onClick={expandMobileComposer} |
| 2068 | aria-label="Write custom answer" | 2090 | aria-label="Write custom answer" |
| 2069 | > | 2091 | > |
| @@ -2102,7 +2124,10 @@ export const ChatComposer = memo( · 32 unmodified lines |
| 2102 | ? "text-foreground" | 2124 | ? "text-foreground" |
| 2103 | : "text-muted-foreground/35", | 2125 | : "text-muted-foreground/35", |
| 2104 | )} | 2126 | )} |
| 2105 | onPointerDown={(event) => event.preventDefault()} | 2127 | onPointerDown={(event) => { |
| | 2128 | event.preventDefault(); |
| | 2129 | expandMobileComposer(); |
| | 2130 | }} |
| 2106 | onClick={expandMobileComposer} | 2131 | onClick={expandMobileComposer} |
| 2107 | aria-label="Expand composer" | 2132 | aria-label="Expand composer" |
| 2108 | > | 2133 | > |