diff --git a/src/renderer/components/thread/ThreadComposer.tsx b/src/renderer/components/thread/ThreadComposer.tsx
index cbbae3ae..f01fa3a9 100644
--- a/src/renderer/components/thread/ThreadComposer.tsx
+++ b/src/renderer/components/thread/ThreadComposer.tsx
@@ -155,6 +155,7 @@ export function ThreadComposer(props: {
hideSubmitButton?: boolean;
submitLabel: string;
submitDisabled: boolean;
+ submitPending?: boolean;
stopPending?: boolean;
preserveDisabledControlStyle?: boolean;
onPromptChange: (value: string) => void;
@@ -178,6 +179,7 @@ export function ThreadComposer(props: {
hideSubmitButton = false,
submitLabel,
submitDisabled,
+ submitPending = false,
stopPending = false,
preserveDisabledControlStyle = false,
onPromptChange,
@@ -569,10 +571,13 @@ export function ThreadComposer(props: {
aria-label={submitLabel}
className="lightcode-composer-send"
isDisabled={submitDisabled || promptDisabled}
+ isPending={submitPending}
onPress={onSubmit}
size="sm"
>
-
+ {({ isPending }) =>
+ isPending ? :
+ }
);
};
diff --git a/src/renderer/components/thread/ThreadDraftComposerArea.tsx b/src/renderer/components/thread/ThreadDraftComposerArea.tsx
index 5485e485..558da1c8 100644
--- a/src/renderer/components/thread/ThreadDraftComposerArea.tsx
+++ b/src/renderer/components/thread/ThreadDraftComposerArea.tsx
@@ -75,6 +75,7 @@ export function ThreadDraftComposerArea(props: {
// launched agent would race with the still-running install and could pick up
// either binary, which is a confusing state to debug.
const [agentUpdating, setAgentUpdating] = useState(false);
+ const [isSubmitting, setIsSubmitting] = useState(false);
const mentionRef = useRef(null);
const attachments = useAttachments();
const inboxKey = props.paneId ?? `draft:${props.project.id}`;
@@ -111,6 +112,7 @@ export function ThreadDraftComposerArea(props: {
const latestSegmentsRef = useRef([]);
const attachmentsRef = useRef(attachments.attachments);
attachmentsRef.current = attachments.attachments;
+ const submittedRef = useRef(false);
const initialDraftRef = useRef(useAppStore.getState().draftContents[props.project.id]);
const availableCommands = resolveAvailableSlashCommands(
undefined,
@@ -210,6 +212,8 @@ export function ThreadDraftComposerArea(props: {
}
resetDraftRefs();
+ submittedRef.current = true;
+ setIsSubmitting(true);
const useWorktree = branchSelection?.isWorktree ?? props.worktreeMode;
if (props.supportsModePicker) {
props.onRememberPresentationMode();
@@ -235,7 +239,6 @@ export function ThreadDraftComposerArea(props: {
}
: {}),
});
- attachments.clearAll();
}
useLayoutEffect(() => {
@@ -257,6 +260,7 @@ export function ThreadDraftComposerArea(props: {
useEffect(() => {
const pid = props.project.id;
return () => {
+ if (submittedRef.current) return;
const segments = latestSegmentsRef.current;
const atts = attachmentsRef.current;
if (segments.length > 0 || atts.length > 0) {
@@ -382,8 +386,12 @@ export function ThreadDraftComposerArea(props: {
placeholder="Send a message..."
prompt={prompt}
submitDisabled={
- authRequired || agentUpdating || !(hasContent || attachments.attachments.length > 0)
+ authRequired ||
+ agentUpdating ||
+ isSubmitting ||
+ !(hasContent || attachments.attachments.length > 0)
}
+ submitPending={isSubmitting}
submitLabel="Launch thread"
onPromptChange={setPrompt}
onSubmit={() => {