| author | |
| committer | |
| log | 02612c28564056ddb7ae6b06cedd31dafc235ffd |
| tree | 8ba7a31c30772a1daf4c63add9747fa2e7255aac |
| parent | 71f6f1db89a50f0108663ebf1724cf3a1a4134ed |
| signature | Signed by PGP key B5690EEEBB952194 |
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 not | 1112 | // 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 | }); |
| 1434 | 1454 | ||
| 1435 | it("retries transport failures but drops deterministic command failures", () => { | 1455 | it("retries transport failures but drops deterministic command failures", () => { |