From fbbb01cd26c4e819099931a389f709456189f493 Mon Sep 17 00:00:00 2001 From: aivsomkar Date: Sat, 3 Oct 2026 18:46:30 +0530 Subject: [PATCH 1/3] =?UTF-8?q?fix(ios):=20show=20the=20files=20a=20bot=20?= =?UTF-8?q?sends=20=E2=80=94=20video,=20audio,=20documents=20(MOCA-155)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since #1552 a bot can send any file with attach_file. Documents, audio and video arrive as kind:"file" attachments with a name; the phone only read kind:"image" and kind:"audio", so a file-only reply drew as an empty speech bubble. MessageImageAttachment now decodes `name`, and Message.attachedFiles lists a bot's file attachments (deduplicated, names basenamed). Each renders as the existing file card, which opens the full-screen viewer through the message-scoped file route: QuickLook plays mp4/mov video and audio and shows PDFs and Office documents. The card says "Tap to play" with a play or waveform icon for video and audio. A file-only message previews in the roster and on the Updates line as its file name instead of nothing. Co-Authored-By: Claude Opus 5.5 --- ios/App/AttachmentViews.swift | 12 +++++- ios/App/ChatView.swift | 8 ++++ ios/App/Localizable.xcstrings | 10 +++++ .../AttachedMessageContent.swift | 33 +++++++++++++++ .../CompanionCore/ChatPreferences.swift | 6 ++- ios/Sources/CompanionCore/Models.swift | 12 ++++-- .../GeneratedImageTests.swift | 41 +++++++++++++++++++ 7 files changed, 116 insertions(+), 6 deletions(-) diff --git a/ios/App/AttachmentViews.swift b/ios/App/AttachmentViews.swift index 855842bb22..45f827db8f 100644 --- a/ios/App/AttachmentViews.swift +++ b/ios/App/AttachmentViews.swift @@ -234,10 +234,18 @@ struct TranscriptAttachmentView: View { .accessibilityHint(thumbnail == nil ? "Loads the image preview" : "Opens the image full screen") } + private var fileSymbol: String { + switch attachment.fileFamily { + case .video: "play.rectangle.fill" + case .audio: "waveform" + case .document: "doc.fill" + } + } + private var fileCard: some View { Button(action: openPreview) { HStack(spacing: 10) { - Image(systemName: "doc.fill") + Image(systemName: fileSymbol) .font(.system(size: 16, weight: .medium)) .foregroundStyle(foreground) .frame(width: 38, height: 38) @@ -248,7 +256,7 @@ struct TranscriptAttachmentView: View { Text(attachment.name) .font(.system(size: 13, weight: .semibold)) .lineLimit(1) - Text(previewLoading ? "Opening…" : "Tap to preview") + Text(previewLoading ? "Opening…" : attachment.fileFamily == .document ? "Tap to preview" : "Tap to play") .font(.system(size: 11)) .foregroundStyle(foreground.opacity(0.68)) } diff --git a/ios/App/ChatView.swift b/ios/App/ChatView.swift index 9d21fffd2b..e9cb0da618 100644 --- a/ios/App/ChatView.swift +++ b/ios/App/ChatView.swift @@ -1859,6 +1859,14 @@ struct TextBubble: View { messageId: message.id, foreground: mine ? BubbleColor.mineText : .primary ) } + // Documents, audio and video a bot sent with attach_file. The + // card opens the full-screen viewer, which plays video. + ForEach(message.attachedFiles, id: \.path) { attachment in + TranscriptAttachmentView( + attachment: attachment, threadId: chat.threadId, + messageId: message.id, foreground: mine ? BubbleColor.mineText : .primary + ) + } // Bots get markdown, you do not — the same split the desktop // makes. Markdown you did not intend is worse than markdown // you did: a message about `**` should show the asterisks. diff --git a/ios/App/Localizable.xcstrings b/ios/App/Localizable.xcstrings index 603bcb15be..b1a0cb0849 100644 --- a/ios/App/Localizable.xcstrings +++ b/ios/App/Localizable.xcstrings @@ -11196,6 +11196,16 @@ } } } + }, + "Tap to play": { + "localizations": { + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Toque para reproduzir" + } + } + } } }, "version": "1.0" diff --git a/ios/Sources/CompanionCore/AttachedMessageContent.swift b/ios/Sources/CompanionCore/AttachedMessageContent.swift index 90e6633691..5098447ccc 100644 --- a/ios/Sources/CompanionCore/AttachedMessageContent.swift +++ b/ios/Sources/CompanionCore/AttachedMessageContent.swift @@ -21,6 +21,22 @@ public struct DisplayedMessageAttachment: Hashable, Sendable { self.path = path self.name = name } + + /// What a file card promises: video and audio play in the viewer, the + /// rest preview. Read from the extension, the same signal the server + /// uses to pick the file's type (mimeFor in server/message-file.ts). + public enum FileFamily: Sendable { + case video, audio, document + } + + public var fileFamily: FileFamily { + let ext = (name as NSString).pathExtension.lowercased() + switch ext { + case "mp4", "mov", "m4v", "webm": return .video + case "mp3", "m4a", "wav", "aac", "ogg", "oga", "opus", "flac": return .audio + default: return .document + } + } } public struct AttachedMessageContent: Hashable, Sendable { @@ -294,6 +310,23 @@ public struct AttachedMessageContent: Hashable, Sendable { } extension Message { + /// Files a bot sent with attach_file — documents, audio and video — in wire + /// order and deduplicated like generatedImages. Before these rendered, a + /// file-only reply was an empty bubble on the phone (MOCA-155). Paths are + /// server metadata, passed unchanged to the message-scoped file route. + public var attachedFiles: [DisplayedMessageAttachment] { + var seen = Set() + return (attachments ?? []).compactMap { attachment in + guard attachment.kind == "file", let path = attachment.path, + !path.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, + seen.insert(path).inserted else { return nil } + return DisplayedMessageAttachment( + kind: .file, path: path, + name: AttachedMessageContent.displayName(providedName: attachment.name, path: path, kind: .file) + ) + } + } + /// Paths are server metadata, passed unchanged to the message-scoped file route. public var generatedImages: [DisplayedMessageAttachment] { var seen = Set() diff --git a/ios/Sources/CompanionCore/ChatPreferences.swift b/ios/Sources/CompanionCore/ChatPreferences.swift index 5ceaa08a46..0af8142c2d 100644 --- a/ios/Sources/CompanionCore/ChatPreferences.swift +++ b/ios/Sources/CompanionCore/ChatPreferences.swift @@ -175,7 +175,11 @@ public func rosterPreview(_ messages: [Message], detail: ActivityDetail) -> Stri /// What a single message reads as in a roster row. func previewText(of message: Message) -> String { switch message.kind { - case .text: return message.webhookContent?.task ?? message.text ?? "" + case .text: + if let task = message.webhookContent?.task { return task } + if let text = message.text, !text.isEmpty { return text } + // A bot that only sent a file says so by its name. + return message.attachedFiles.first?.name ?? "" // a pending card's question is the preview; the roster row already // says "waiting on you" beside it case .options: diff --git a/ios/Sources/CompanionCore/Models.swift b/ios/Sources/CompanionCore/Models.swift index 34d9495a7c..fb33502112 100644 --- a/ios/Sources/CompanionCore/Models.swift +++ b/ios/Sources/CompanionCore/Models.swift @@ -1708,13 +1708,19 @@ public struct ServerEnvironment: Codable, Hashable, Sendable { public var version: String? } -/// Keep future attachment kinds decodable; image entries display inline and -/// audio entries render as voice notes (Message.voiceNotes). Unknown kinds -/// decode without breaking, so a newer computer never gaps the transcript. +/// Keep future attachment kinds decodable; image entries display inline, +/// file entries (a bot's attach_file: documents, audio, video) show as file +/// cards (Message.attachedFiles), and audio entries render as voice notes +/// (Message.voiceNotes). Unknown kinds decode without breaking, so a newer +/// computer never gaps the transcript. public struct MessageImageAttachment: Codable, Hashable, Sendable { public var kind: String public var path: String? public var mime: String? + /// The file's name as the bot sent it, for a `kind: "file"` entry. + /// Presentation only: it is basenamed before display and never used as + /// a path. + public var name: String? /// The server's duration estimate for an audio attachment, in /// milliseconds; shown until the player loads real metadata. public var durationMs: Double? diff --git a/ios/Tests/CompanionCoreTests/GeneratedImageTests.swift b/ios/Tests/CompanionCoreTests/GeneratedImageTests.swift index 3afa035b02..df43868a45 100644 --- a/ios/Tests/CompanionCoreTests/GeneratedImageTests.swift +++ b/ios/Tests/CompanionCoreTests/GeneratedImageTests.swift @@ -27,4 +27,45 @@ final class GeneratedImageTests: XCTestCase { XCTAssertTrue(message.generatedImages.isEmpty) XCTAssertEqual(message.text, "Still visible") } + + /// A bot's attach_file sends documents, audio and video as `kind:"file"` + /// with a name (server/bot-attachment.ts). The phone dropped them, and the + /// message read as an empty bubble (MOCA-155). They are file cards now, + /// opened through the same message-scoped file route as images. + func testABotsFileAttachmentsBecomeNamedFileCards() throws { + let source = #"{"id":"sent","role":"bot","kind":"text","at":1,"text":"","attachments":[{"kind":"file","path":"/data/attachments/9f.mp4","mime":"video/mp4","name":"demo clip.mp4"},{"kind":"image","path":"/data/attachments/a1.png","mime":"image/png"},{"kind":"file","path":"/data/attachments/77.pdf","mime":"application/pdf","name":"../../report.pdf"},{"kind":"file","path":"/data/attachments/9f.mp4","name":"again.mp4"},{"kind":"file","path":" "},{"kind":"hologram","path":"/data/attachments/x.bin"}]}"# + let message = try JSONDecoder().decode(Message.self, from: Data(source.utf8)) + XCTAssertEqual(message.attachedFiles, [ + DisplayedMessageAttachment(kind: .file, path: "/data/attachments/9f.mp4", name: "demo clip.mp4"), + // A crafted name is presentation only and never a path. + DisplayedMessageAttachment(kind: .file, path: "/data/attachments/77.pdf", name: "report.pdf"), + ]) + XCTAssertEqual(message.generatedImages.map(\.path), ["/data/attachments/a1.png"], "images keep their own card") + XCTAssertEqual(message.attachments?.first?.name, "demo clip.mp4") + // The name survives the transcript cache. + let cached = try JSONDecoder().decode(Message.self, from: JSONEncoder().encode(message)) + XCTAssertEqual(cached.attachedFiles, message.attachedFiles) + } + + func testAFileOnlyBotMessagePreviewsAsItsFileName() throws { + let source = #"{"id":"sent","role":"bot","kind":"text","at":1,"text":"","attachments":[{"kind":"file","path":"/data/attachments/9f.mp4","mime":"video/mp4","name":"demo clip.mp4"}]}"# + let message = try JSONDecoder().decode(Message.self, from: Data(source.utf8)) + XCTAssertEqual(rosterPreview([message], detail: .full), "demo clip.mp4") + var captioned = message + captioned.text = "Here is the clip" + XCTAssertEqual(rosterPreview([captioned], detail: .full), "Here is the clip", "words beat a file name") + } + + func testAFileCardKnowsVideoAndAudioFromTheExtension() { + func family(_ name: String) -> DisplayedMessageAttachment.FileFamily { + DisplayedMessageAttachment(kind: .file, path: "/data/attachments/x", name: name).fileFamily + } + XCTAssertEqual(family("demo clip.MP4"), .video) + XCTAssertEqual(family("screen.mov"), .video) + XCTAssertEqual(family("talk.webm"), .video) + XCTAssertEqual(family("memo.m4a"), .audio) + XCTAssertEqual(family("song.mp3"), .audio) + XCTAssertEqual(family("weekly-report.pdf"), .document) + XCTAssertEqual(family("notes"), .document) + } } From 1f10ebcf7fb7af5cce2904561da642c8cab463ef Mon Sep 17 00:00:00 2001 From: aivsomkar Date: Sat, 3 Oct 2026 18:52:23 +0530 Subject: [PATCH 2/3] =?UTF-8?q?fix(android):=20show=20the=20files=20a=20bo?= =?UTF-8?q?t=20sends=20=E2=80=94=20video,=20audio,=20documents=20(MOCA-155?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port of the iOS change. A bot's attach_file documents, audio and video arrive as kind:"file" attachments with a name; Android only read image and audio entries, so a file-only reply drew as an empty bubble. MessageImageAttachment decodes `name` (appended, so positional callers are unchanged) and Message.attachedFiles lists the bot's files. Each renders as the shared file card, now drawn in the bubble's own text colour (it was hard-coded white, unreadable on a light bot bubble) and labelled VIDEO or AUDIO with "Tap to play" where it plays. Tapping opens the existing file sheet through the message-scoped file route. A file-only message previews as its file name. New strings carry Simplified and Traditional Chinese. Co-Authored-By: Claude Opus 5.5 --- .../openmausbot/companion/ui/MessageRow.kt | 30 +++++++++++-- .../src/main/res/values-b+zh+Hans/strings.xml | 3 ++ .../src/main/res/values-b+zh+Hant/strings.xml | 3 ++ android/app/src/main/res/values/strings.xml | 3 ++ .../companion/core/AttachedMessageContent.kt | 33 ++++++++++++++ .../companion/core/ChatPreferences.kt | 5 ++- .../com/openmausbot/companion/core/Models.kt | 8 +++- .../companion/core/GeneratedImageTest.kt | 43 +++++++++++++++++++ 8 files changed, 122 insertions(+), 6 deletions(-) diff --git a/android/app/src/main/kotlin/com/openmausbot/companion/ui/MessageRow.kt b/android/app/src/main/kotlin/com/openmausbot/companion/ui/MessageRow.kt index 35763a1f30..0b7c913c7a 100644 --- a/android/app/src/main/kotlin/com/openmausbot/companion/ui/MessageRow.kt +++ b/android/app/src/main/kotlin/com/openmausbot/companion/ui/MessageRow.kt @@ -89,6 +89,7 @@ import androidx.compose.ui.unit.sp import com.openmausbot.companion.audio.VoiceNoteController import com.openmausbot.companion.core.Chat import com.openmausbot.companion.core.AttachedMessageContent +import com.openmausbot.companion.core.attachedFiles import com.openmausbot.companion.core.generatedImages import com.openmausbot.companion.core.voiceNotes import com.openmausbot.companion.core.DisplayedMessageAttachment @@ -545,6 +546,14 @@ private fun TextBubble( message.generatedImages.forEach { attachment -> SharedAttachmentView(threadId, message, attachment, openAttachment) } + // Documents, audio and video a bot sent with attach_file (MOCA-155). + // The card opens the file sheet; Open hands video to the player. + message.attachedFiles.forEach { attachment -> + SharedAttachmentView( + threadId, message, attachment, openAttachment, + foreground = if (mine) BubbleColor.mineText else MaterialTheme.colorScheme.onSurface, + ) + } // Bots get markdown, you do not — the same split the desktop makes. // Markdown you did not intend is worse than markdown you did: a // message about `**` should show the asterisks. @@ -596,16 +605,19 @@ private fun SharedAttachmentView( message: Message, attachment: DisplayedMessageAttachment, onOpen: ((DisplayedMessageAttachment, Message, DownloadedFile?) -> Unit)?, + /** Your own bubble is blue with white text; a bot's file sits on the theme surface. */ + foreground: Color = BubbleColor.mineText, ) { if (attachment.kind == DisplayedMessageAttachment.Kind.IMAGE) { SharedImageAttachment(threadId, message, attachment, onOpen) return } + val family = attachment.fileFamily Row( modifier = Modifier .widthIn(max = 360.dp) .clip(RoundedCornerShape(16.dp)) - .background(BubbleColor.mineText.copy(alpha = 0.10f)) + .background(foreground.copy(alpha = 0.10f)) .clickable(enabled = onOpen != null, role = Role.Button) { onOpen?.invoke(attachment, message, null) } @@ -616,17 +628,27 @@ private fun SharedAttachmentView( horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically, ) { - Text(stringResource(R.string.mobile_file_b4915d3a), fontSize = 11.sp, fontWeight = FontWeight.Bold, color = BubbleColor.mineText.copy(alpha = 0.68f)) + val label = when (family) { + DisplayedMessageAttachment.FileFamily.VIDEO -> R.string.mobile_file_video + DisplayedMessageAttachment.FileFamily.AUDIO -> R.string.mobile_file_audio + DisplayedMessageAttachment.FileFamily.DOCUMENT -> R.string.mobile_file_b4915d3a + } + val hint = if (family == DisplayedMessageAttachment.FileFamily.DOCUMENT) { + R.string.mobile_tap_to_preview_fa5ce0ea + } else { + R.string.mobile_tap_to_play + } + Text(stringResource(label), fontSize = 11.sp, fontWeight = FontWeight.Bold, color = foreground.copy(alpha = 0.68f)) Column(modifier = Modifier.weight(1f)) { Text( attachment.name, fontSize = 14.sp, fontWeight = FontWeight.Medium, - color = BubbleColor.mineText, + color = foreground, maxLines = 1, overflow = TextOverflow.Ellipsis, ) - Text(stringResource(R.string.mobile_tap_to_preview_fa5ce0ea), fontSize = 12.sp, color = BubbleColor.mineText.copy(alpha = 0.68f)) + Text(stringResource(hint), fontSize = 12.sp, color = foreground.copy(alpha = 0.68f)) } } } diff --git a/android/app/src/main/res/values-b+zh+Hans/strings.xml b/android/app/src/main/res/values-b+zh+Hans/strings.xml index 3e86c5aab0..b6b03023e3 100644 --- a/android/app/src/main/res/values-b+zh+Hans/strings.xml +++ b/android/app/src/main/res/values-b+zh+Hans/strings.xml @@ -109,6 +109,9 @@ 展开 已展开 文件 + 视频 + 音频 + 点一下以播放 例如:整理摘要并列出后续步骤 从 5 分钟到 24 小时 群组名称(选填) diff --git a/android/app/src/main/res/values-b+zh+Hant/strings.xml b/android/app/src/main/res/values-b+zh+Hant/strings.xml index e84ac70776..4f8ccf59b3 100644 --- a/android/app/src/main/res/values-b+zh+Hant/strings.xml +++ b/android/app/src/main/res/values-b+zh+Hant/strings.xml @@ -109,6 +109,9 @@ 展開 已展開 檔案 + 影片 + 音訊 + 點一下以播放 例如:整理摘要並列出後續步驟 從 5 分鐘到 24 小時 群組名稱(選填) diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 86c8130c23..5b4b6bc305 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -110,6 +110,9 @@ Expand Expanded FILE + VIDEO + AUDIO + Tap to play For example: summarize this and list the next steps From 5 minutes to 24 hours Group name (optional) diff --git a/android/core/src/main/kotlin/com/openmausbot/companion/core/AttachedMessageContent.kt b/android/core/src/main/kotlin/com/openmausbot/companion/core/AttachedMessageContent.kt index 8803bf7141..33fc03e530 100644 --- a/android/core/src/main/kotlin/com/openmausbot/companion/core/AttachedMessageContent.kt +++ b/android/core/src/main/kotlin/com/openmausbot/companion/core/AttachedMessageContent.kt @@ -10,6 +10,20 @@ data class DisplayedMessageAttachment( val durationMs: Double? = null, ) { enum class Kind { IMAGE, FILE, AUDIO } + + /** + * What a file card promises: video and audio play, the rest preview. Read + * from the extension, the signal the server uses to pick the file's type + * (mimeFor in server/message-file.ts). Port of the iOS `fileFamily`. + */ + enum class FileFamily { VIDEO, AUDIO, DOCUMENT } + + val fileFamily: FileFamily + get() = when (name.substringAfterLast('.', "").lowercase()) { + "mp4", "mov", "m4v", "webm" -> FileFamily.VIDEO + "mp3", "m4a", "wav", "aac", "ogg", "oga", "opus", "flac" -> FileFamily.AUDIO + else -> FileFamily.DOCUMENT + } } data class AttachedMessageContent( @@ -212,6 +226,25 @@ data class AttachedMessageContent( } } +/** + * Files a bot sent with attach_file — documents, audio and video — in wire + * order and deduplicated like [generatedImages]. Before these rendered, a + * file-only reply was an empty bubble on the phone (MOCA-155). The path goes + * unchanged to the originating message's authenticated file route. + */ +val Message.attachedFiles: List + get() = attachments.orEmpty() + .filter { it.kind == "file" && !it.path.isNullOrBlank() } + .distinctBy { it.path } + .map { + val path = requireNotNull(it.path) + DisplayedMessageAttachment( + kind = DisplayedMessageAttachment.Kind.FILE, + path = path, + name = AttachedMessageContent.displayName(it.name, path, DisplayedMessageAttachment.Kind.FILE), + ) + } + /** Preserve the server path exactly for the originating message's authenticated file route. */ val Message.generatedImages: List get() = attachments.orEmpty() diff --git a/android/core/src/main/kotlin/com/openmausbot/companion/core/ChatPreferences.kt b/android/core/src/main/kotlin/com/openmausbot/companion/core/ChatPreferences.kt index 88cd2eab66..85de52f6e6 100644 --- a/android/core/src/main/kotlin/com/openmausbot/companion/core/ChatPreferences.kt +++ b/android/core/src/main/kotlin/com/openmausbot/companion/core/ChatPreferences.kt @@ -130,7 +130,10 @@ fun rosterPreview(messages: List, detail: ActivityDetail): String = /** What a single message reads as in a roster row. */ internal fun previewText(message: Message): String = when (message.kind) { - Message.Kind.TEXT -> message.webhookContent?.task ?: message.text.orEmpty() + Message.Kind.TEXT -> message.webhookContent?.task + ?: message.text?.takeIf { it.isNotEmpty() } + // A bot that only sent a file says so by its name. + ?: message.attachedFiles.firstOrNull()?.name.orEmpty() // a pending card's question is the preview; the roster row already says // "waiting on you" beside it Message.Kind.OPTIONS -> { diff --git a/android/core/src/main/kotlin/com/openmausbot/companion/core/Models.kt b/android/core/src/main/kotlin/com/openmausbot/companion/core/Models.kt index e5f48679f9..1e3cf0bc4d 100644 --- a/android/core/src/main/kotlin/com/openmausbot/companion/core/Models.kt +++ b/android/core/src/main/kotlin/com/openmausbot/companion/core/Models.kt @@ -1532,7 +1532,11 @@ data class ServerSession(val id: String, val label: String, val scopes: List(source) + assertEquals( + listOf( + DisplayedMessageAttachment(DisplayedMessageAttachment.Kind.FILE, "demo clip.mp4", "/data/attachments/9f.mp4"), + // A crafted name is presentation only and never a path. + DisplayedMessageAttachment(DisplayedMessageAttachment.Kind.FILE, "report.pdf", "/data/attachments/77.pdf"), + ), + message.attachedFiles, + ) + assertEquals(listOf("/data/attachments/a1.png"), message.generatedImages.map { it.path }, "images keep their own card") + val cached = CompanionJson.decodeFromString(CompanionJson.encodeToString(message)) + assertEquals(message.attachedFiles, cached.attachedFiles) + } + + @Test + fun aFileOnlyBotMessagePreviewsAsItsFileName() { + val message = CompanionJson.decodeFromString( + """{"id":"sent","role":"bot","kind":"text","at":1,"text":"","attachments":[{"kind":"file","path":"/data/attachments/9f.mp4","mime":"video/mp4","name":"demo clip.mp4"}]}""", + ) + assertEquals("demo clip.mp4", rosterPreview(listOf(message), ActivityDetail.FULL)) + assertEquals("Here is the clip", rosterPreview(listOf(message.copy(text = "Here is the clip")), ActivityDetail.FULL)) + } + + @Test + fun aFileCardKnowsVideoAndAudioFromTheExtension() { + fun family(name: String) = DisplayedMessageAttachment(DisplayedMessageAttachment.Kind.FILE, name, "/data/attachments/x").fileFamily + assertEquals(DisplayedMessageAttachment.FileFamily.VIDEO, family("demo clip.MP4")) + assertEquals(DisplayedMessageAttachment.FileFamily.VIDEO, family("screen.mov")) + assertEquals(DisplayedMessageAttachment.FileFamily.VIDEO, family("talk.webm")) + assertEquals(DisplayedMessageAttachment.FileFamily.AUDIO, family("memo.m4a")) + assertEquals(DisplayedMessageAttachment.FileFamily.AUDIO, family("song.mp3")) + assertEquals(DisplayedMessageAttachment.FileFamily.DOCUMENT, family("weekly-report.pdf")) + assertEquals(DisplayedMessageAttachment.FileFamily.DOCUMENT, family("notes")) + } } From 4c4302016e79e777825f4997bb0ac78838132a44 Mon Sep 17 00:00:00 2001 From: aivsomkar Date: Sat, 3 Oct 2026 21:04:01 +0530 Subject: [PATCH 3/3] docs(screenshots): MOCA-155 bot file cards (iOS) Co-Authored-By: Claude Opus 5.5 --- docs/screenshots/moca-155-bot-files-ios.jpg | Bin 0 -> 57314 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/screenshots/moca-155-bot-files-ios.jpg diff --git a/docs/screenshots/moca-155-bot-files-ios.jpg b/docs/screenshots/moca-155-bot-files-ios.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c39c69a9907dc6476722c0579a00f506271223ea GIT binary patch literal 57314 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