authorgravatar for 139932571+Claudesaul@users.noreply.github.comClaudesaul <139932571+Claudesaul@users.noreply.github.com> 2026-10-10 07:37:26-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-10 06:37:26-05:00
log02612c28564056ddb7ae6b06cedd31dafc235ffd
tree8ba7a31c30772a1daf4c63add9747fa2e7255aac
parent71f6f1db89a50f0108663ebf1724cf3a1a4134ed
signature Signed by PGP key B5690EEEBB952194

fix(mobile): allow starting a task with only an image (#17409)


4 files changed, 26 insertions(+), 4 deletions(-)

apps/mobile/src/features/threads/NewTaskDraftScreen.tsx+2-2
...@@ -1244,7 +1244,7 @@ export function NewTaskDraftScreen(props: {...@@ -1244,7 +1244,7 @@ export function NewTaskDraftScreen(props: {
1244 if (1244 if (
1245 attachmentBlockReason !== null ||1245 attachmentBlockReason !== null ||
1246 !modelSelection ||1246 !modelSelection ||
1247 initialMessageText.length === 0 ||1247 (initialMessageText.length === 0 && draft.attachments.length === 0) ||
1248 flow.submitting ||1248 flow.submitting ||
1249 (workspaceMode === "worktree" && !selectedBranchName)1249 (workspaceMode === "worktree" && !selectedBranchName)
1250 ) {1250 ) {
...@@ -1397,7 +1397,7 @@ export function NewTaskDraftScreen(props: {...@@ -1397,7 +1397,7 @@ export function NewTaskDraftScreen(props: {
1397 !modelUnavailable &&1397 !modelUnavailable &&
1398 Boolean(flow.selectedProject) &&1398 Boolean(flow.selectedProject) &&
1399 Boolean(flow.selectedModel) &&1399 Boolean(flow.selectedModel) &&
1400 flow.prompt.trim().length > 0 &&1400 (flow.prompt.trim().length > 0 || flow.attachments.length > 0) &&
1401 isIncomingShareReady &&1401 isIncomingShareReady &&
1402 !isImportingShare &&1402 !isImportingShare &&
1403 !flow.submitting &&1403 !flow.submitting &&
apps/mobile/src/features/threads/new-task-flow-provider.tsx+2-1
...@@ -1105,7 +1105,8 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {...@@ -1105,7 +1105,8 @@ export function NewTaskFlowProvider(props: React.PropsWithChildren) {
1105 selectedEnvironmentServerConfig,1105 selectedEnvironmentServerConfig,
1106 draft.modelSelection ?? null,1106 draft.modelSelection ?? null,
1107 ) ?? selectedModel;1107 ) ?? selectedModel;
1108 if (text.length === 0 || !draftModelSelection) {1108 // A shared image or file is a task on its own; text is optional.
1109 if ((text.length === 0 && draft.attachments.length === 0) || !draftModelSelection) {
1109 return null;1110 return null;
1110 }1111 }
1111 // A saved choice from before the project went no-project must not1112 // A saved choice from before the project went no-project must not
apps/mobile/src/state/thread-outbox-model.ts+2-1
...@@ -247,7 +247,8 @@ export function isQueuedThreadCreationSendable(message: QueuedThreadMessage): bo...@@ -247,7 +247,8 @@ export function isQueuedThreadCreationSendable(message: QueuedThreadMessage): bo
247 if (!message.creation) {247 if (!message.creation) {
248 return false;248 return false;
249 }249 }
250 if (message.text.trim().length === 0 || message.modelSelection === undefined) {250 const hasContent = message.text.trim().length > 0 || message.attachments.length > 0;
251 if (!hasContent || message.modelSelection === undefined) {
251 return false;252 return false;
252 }253 }
253 return message.creation.workspaceMode !== "worktree" || Boolean(message.creation.branch);254 return message.creation.workspaceMode !== "worktree" || Boolean(message.creation.branch);
apps/mobile/src/state/thread-outbox.test.ts+20
...@@ -1430,6 +1430,26 @@ describe("thread outbox", () => {...@@ -1430,6 +1430,26 @@ describe("thread outbox", () => {
1430 false,1430 false,
1431 );1431 );
1432 expect(isQueuedThreadCreationSendable(base)).toBe(false);1432 expect(isQueuedThreadCreationSendable(base)).toBe(false);
1433 expect(isQueuedThreadCreationSendable({ ...creationMessage, text: " " })).toBe(false);
1434 expect(
1435 isQueuedThreadCreationSendable({
1436 ...creationMessage,
1437 text: "",
1438 attachments: [
1439 {
1440 id: "image-1",
1441 type: "image",
1442 name: "photo.png",
1443 mimeType: "image/png",
1444 sizeBytes: 3,
1445 fileUri: "file:///documents/t3-composer-attachments/photo.png",
1446 previewUri: "file:///documents/t3-composer-attachments/photo.png",
1447 uploadedAttachmentId: "pending-photo-png",
1448 uploadEnvironmentId: EnvironmentId.make("environment-1"),
1449 },
1450 ],
1451 }),
1452 ).toBe(true);
1433 });1453 });
14341454
1435 it("retries transport failures but drops deterministic command failures", () => {1455 it("retries transport failures but drops deterministic command failures", () => {