// // Copyright 2025 Element Creations Ltd. // Copyright 2023-2025 New Vector Ltd. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. // Please see LICENSE files in the repository root for full details. // import Foundation nonisolated enum EventBasedMessageTimelineItemContentType: Hashable { case audio(AudioRoomTimelineItemContent) case emote(EmoteRoomTimelineItemContent) case file(FileRoomTimelineItemContent) case image(ImageRoomTimelineItemContent) case notice(NoticeRoomTimelineItemContent) case text(TextRoomTimelineItemContent) case video(VideoRoomTimelineItemContent) case location(LocationRoomTimelineItemContent) case voice(AudioRoomTimelineItemContent) } nonisolated protocol EventBasedMessageTimelineItemProtocol: EventBasedTimelineItemProtocol { var contentType: EventBasedMessageTimelineItemContentType { get } } nonisolated extension EventBasedMessageTimelineItemProtocol { var supportsMediaCaption: Bool { switch contentType { case .audio, .file, .image, .video: true case .emote, .notice, .text, .location, .voice: false } } var hasMediaCaption: Bool { mediaCaption != nil } var mediaCaption: String? { switch contentType { case .audio(let content): content.caption case .file(let content): content.caption case .image(let content): content.caption case .video(let content): content.caption case .emote, .notice, .text, .location, .voice: nil } } var formattedMediaCaption: AttributedString? { switch contentType { case .audio(let content): content.formattedCaption case .file(let content): content.formattedCaption case .image(let content): content.formattedCaption case .video(let content): content.formattedCaption case .emote, .notice, .text, .location, .voice: nil } } }