Add support for replying to events different than room messages

This commit is contained in:
Stefan Ceriu
2023-09-21 13:28:08 +03:00
committed by Stefan Ceriu
parent 423604b18c
commit 61968cb3fb
41 changed files with 199 additions and 34 deletions
@@ -24,6 +24,7 @@ enum RoomTimelineItemFixtures {
timestamp: "10:10 AM",
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: "Jacob"),
content: .init(body: "That looks so good!"),
@@ -32,6 +33,7 @@ enum RoomTimelineItemFixtures {
timestamp: "10:11 AM",
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: "Helena"),
content: .init(body: "Let’s get lunch soon! New salad place opened up 🥗. When are y’all free? 🤗"),
@@ -42,6 +44,7 @@ enum RoomTimelineItemFixtures {
timestamp: "10:11 AM",
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: "Helena"),
content: .init(body: "I can be around on Wednesday. How about some 🌮 instead? Like https://www.tortilla.co.uk/"),
@@ -60,6 +63,7 @@ enum RoomTimelineItemFixtures {
timestamp: "5 PM",
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: "Helena"),
content: .init(body: "Wow, cool. Ok, lets go the usual place tomorrow?! Is that too soon? Here’s the menu, let me know what you want it’s on me!"),
@@ -68,6 +72,7 @@ enum RoomTimelineItemFixtures {
timestamp: "5 PM",
isOutgoing: true,
isEditable: true,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: "Bob"),
content: .init(body: "And John's speech was amazing!")),
@@ -75,6 +80,7 @@ enum RoomTimelineItemFixtures {
timestamp: "5 PM",
isOutgoing: true,
isEditable: true,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: "Bob"),
content: .init(body: "New home office set up!"),
@@ -87,6 +93,7 @@ enum RoomTimelineItemFixtures {
timestamp: "5 PM",
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: "Helena"),
content: .init(body: "",
@@ -241,6 +248,7 @@ private extension TextRoomTimelineItem {
timestamp: "10:47 am",
isOutgoing: senderDisplayName == "Alice",
isEditable: false,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "", displayName: senderDisplayName),
content: .init(body: text))
@@ -87,6 +87,8 @@ class EventTimelineItemProxy {
return .sent
}
}()
lazy var canBeRepliedTo = item.canBeRepliedTo()
lazy var isRoomState = content.kind().isRoomState
@@ -21,6 +21,7 @@ protocol EventBasedTimelineItemProtocol: RoomTimelineItemProtocol, CustomStringC
var timestamp: String { get }
var isOutgoing: Bool { get }
var isEditable: Bool { get }
var canBeRepliedTo: Bool { get }
var sender: TimelineItemSender { get }
@@ -21,6 +21,7 @@ struct AudioRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -21,6 +21,7 @@ struct EmoteRoomTimelineItem: TextBasedRoomTimelineItem, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -22,6 +22,7 @@ struct FileRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
@@ -22,6 +22,7 @@ struct ImageRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -20,6 +20,7 @@ struct LocationRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatabl
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -21,6 +21,7 @@ struct NoticeRoomTimelineItem: TextBasedRoomTimelineItem, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -22,6 +22,7 @@ struct TextRoomTimelineItem: TextBasedRoomTimelineItem, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
@@ -22,6 +22,7 @@ struct VideoRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -64,6 +64,7 @@ struct VoiceRoomTimelineView_Previews: PreviewProvider, TestablePreview {
timestamp: "Now",
isOutgoing: false,
isEditable: false,
canBeRepliedTo: true,
isThreaded: false,
sender: .init(id: "Bob"),
content: .init(body: "audio.ogg",
@@ -21,6 +21,7 @@ struct VoiceRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -29,6 +29,7 @@ struct EncryptedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let sender: TimelineItemSender
@@ -23,6 +23,7 @@ struct PollRoomTimelineItem: Equatable, EventBasedTimelineItemProtocol {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let sender: TimelineItemSender
var properties: RoomTimelineItemProperties
}
@@ -23,6 +23,7 @@ struct RedactedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let sender: TimelineItemSender
@@ -22,6 +22,7 @@ struct StateRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let sender: TimelineItemSender
@@ -22,6 +22,7 @@ struct StickerRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let sender: TimelineItemSender
@@ -26,6 +26,7 @@ struct UnsupportedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let canBeRepliedTo: Bool
let sender: TimelineItemSender
@@ -121,6 +121,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
sender: eventItemProxy.sender,
properties: RoomTimelineItemProperties())
}
@@ -142,6 +143,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
sender: eventItemProxy.sender,
imageURL: imageURL,
width: width,
@@ -172,6 +174,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
sender: eventItemProxy.sender,
properties: RoomTimelineItemProperties())
}
@@ -183,6 +186,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
sender: eventItemProxy.sender,
properties: RoomTimelineItemProperties())
}
@@ -196,6 +200,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildTextTimelineItemContent(messageContent),
@@ -215,6 +220,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildImageTimelineItemContent(messageContent),
@@ -234,6 +240,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildVideoTimelineItemContent(messageContent),
@@ -253,6 +260,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildAudioTimelineItemContent(messageContent),
@@ -272,6 +280,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildAudioTimelineItemContent(messageContent),
@@ -291,6 +300,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildFileTimelineItemContent(messageContent),
@@ -310,6 +320,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildNoticeTimelineItemContent(messageContent),
@@ -329,6 +340,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildEmoteTimelineItemContent(senderDisplayName: eventItemProxy.sender.displayName, senderID: eventItemProxy.sender.id, messageContent: messageContent),
@@ -348,6 +360,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildLocationTimelineItemContent(messageContent),
@@ -398,6 +411,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
sender: eventItemProxy.sender,
properties: RoomTimelineItemProperties(isEdited: false,
reactions: aggregateReactions(eventItemProxy.reactions),
@@ -587,6 +601,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: false,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
sender: eventItemProxy.sender)
}
@@ -614,29 +629,39 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
}
let replyContent: EventBasedMessageTimelineItemContentType
switch timelineItem.asMessage()?.msgtype() {
case .audio(let content):
if appSettings.voiceMessageEnabled, content.voice != nil {
replyContent = .voice(buildAudioTimelineItemContent(content))
} else {
replyContent = .audio(buildAudioTimelineItemContent(content))
switch timelineItem.kind() {
case .message:
switch timelineItem.asMessage()?.msgtype() {
case .audio(let content):
if appSettings.voiceMessageEnabled, content.voice != nil {
replyContent = .voice(buildAudioTimelineItemContent(content))
} else {
replyContent = .audio(buildAudioTimelineItemContent(content))
}
case .emote(let content):
replyContent = .emote(buildEmoteTimelineItemContent(senderDisplayName: sender.displayName, senderID: sender.id, messageContent: content))
case .file(let content):
replyContent = .file(buildFileTimelineItemContent(content))
case .image(let content):
replyContent = .image(buildImageTimelineItemContent(content))
case .notice(let content):
replyContent = .notice(buildNoticeTimelineItemContent(content))
case .text(let content):
replyContent = .text(buildTextTimelineItemContent(content))
case .video(let content):
replyContent = .video(buildVideoTimelineItemContent(content))
case .location(let content):
replyContent = .location(buildLocationTimelineItemContent(content))
case .none:
replyContent = .text(.init(body: L10n.commonUnsupportedEvent))
}
case .emote(let content):
replyContent = .emote(buildEmoteTimelineItemContent(senderDisplayName: sender.displayName, senderID: sender.id, messageContent: content))
case .file(let content):
replyContent = .file(buildFileTimelineItemContent(content))
case .image(let content):
replyContent = .image(buildImageTimelineItemContent(content))
case .notice(let content):
replyContent = .notice(buildNoticeTimelineItemContent(content))
case .text(let content):
replyContent = .text(buildTextTimelineItemContent(content))
case .video(let content):
replyContent = .video(buildVideoTimelineItemContent(content))
case .location(let content):
replyContent = .location(buildLocationTimelineItemContent(content))
case .none:
return nil
case .poll(let question, _, _, _, _, _):
replyContent = .text(.init(body: question))
case .sticker(let body, _, _):
replyContent = .text(.init(body: body))
default:
replyContent = .text(.init(body: L10n.commonUnsupportedEvent))
}
return .loaded(sender: sender, contentType: replyContent)