feat: show a loading indicator on gateway attachments while they open (#917)

Tapping a gateway attachment gave zero feedback while the file
downloaded (a 100MB file could sit there silently for tens of seconds).
Mirror the save spinner: ChatUiState gains openingAttachmentPath, set
when openAttachment starts the download and cleared in a finally, and
the attachment card renders a small CircularProgressIndicator while its
path is being fetched. Wired through FullBleedChatList, ChatBubble and
FullBleedAgentMessage.

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-08-15 23:28:04 +03:00
1 parent d8be45b8fc
commit 75023a2bf0
6 files changed
+89 -18

No files matched your search

@@ -3643,4 +3643,44 @@ class ChatViewModelTest {
.contains("missing.pdf"),
)
}
@Test
fun `openAttachment shows opening state while fetch is in flight and clears it after`() =
runTest {
mockkObject(GatewayFileClient)
val cacheDir =
java.io.File(
System.getProperty("java.io.tmpdir"),
"gw_open_${System.nanoTime()}",
).apply { mkdirs() }
every { app.cacheDir } returns cacheDir
every { app.applicationContext } returns app
every { app.getApplicationContext() } returns app
val firstResult = CompletableDeferred<GatewayFileResult>()
val fetchedPaths = mutableListOf<String>()
coEvery { GatewayFileClient.fetch(capture(fetchedPaths), any()) } coAnswers { firstResult.await() }
val vm = createViewModel()
val attachment =
Attachment(
uri = "gateway:/tmp/big.pdf",
name = "big.pdf",
mimeType = "application/pdf",
source = AttachmentSource.GATEWAY,
)
vm.openAttachment(attachment)
runCurrent()
// Indicator visible while the download is in flight…
assertEquals(listOf("/tmp/big.pdf"), fetchedPaths)
assertEquals("/tmp/big.pdf", vm.uiState.value.openingAttachmentPath)
firstResult.complete(GatewayFileResult.NotFound)
advanceUntilIdle()
// …and cleared in all outcomes.
assertNull(vm.uiState.value.openingAttachmentPath)
assertTrue(vm.uiState.value.openError.orEmpty().contains("big.pdf"))
}
}