Thread Decorator (#1686)

* just added the isThreaded property to message based events

* done but I should add a bunch of tests for images and videos and locations

* handling for image and videos, but locations might need to be double checked

* code improvement

* better tests and removed code that is not used, we need to fix first the appearence of replies

* bubble style is solved, we now need plain style

* also added plain style

* better handling for bubble style

* rounded corner only for bubbles in location

* fix for wrong aspect ratio in replies

* all changes done

* better testing

* swift format

* changelog

* PR comments and rebase.

* Simplify corner radius on location timeline view.

---------

Co-authored-by: Doug <douglase@element.io>
This commit is contained in:
Mauro
2023-09-15 12:58:30 +02:00
committed by GitHub
parent 64d5ba7a69
commit 7642508135
42 changed files with 618 additions and 116 deletions
@@ -30,4 +30,5 @@ enum EventBasedMessageTimelineItemContentType: Hashable {
protocol EventBasedMessageTimelineItemProtocol: EventBasedTimelineItemProtocol {
var replyDetails: TimelineItemReplyDetails? { get }
var contentType: EventBasedMessageTimelineItemContentType { get }
var isThreaded: Bool { get }
}
@@ -21,6 +21,7 @@ struct AudioRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
let content: AudioRoomTimelineItemContent
@@ -21,6 +21,7 @@ struct EmoteRoomTimelineItem: TextBasedRoomTimelineItem, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -23,6 +23,8 @@ struct FileRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
let content: FileRoomTimelineItemContent
@@ -22,6 +22,7 @@ struct ImageRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -20,7 +20,8 @@ struct LocationRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatabl
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
let content: LocationRoomTimelineItemContent
@@ -21,6 +21,7 @@ struct NoticeRoomTimelineItem: TextBasedRoomTimelineItem, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -23,6 +23,8 @@ struct TextRoomTimelineItem: TextBasedRoomTimelineItem, Equatable {
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
let content: TextRoomTimelineItemContent
@@ -22,6 +22,7 @@ struct VideoRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable {
let timestamp: String
let isOutgoing: Bool
let isEditable: Bool
let isThreaded: Bool
let sender: TimelineItemSender
@@ -80,23 +80,24 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
fatalError("Invalid message timeline item: \(eventItemProxy)")
}
let isThreaded = messageTimelineItem.isThreaded()
switch messageTimelineItem.msgtype() {
case .text(content: let content):
return buildTextTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildTextTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .image(content: let content):
return buildImageTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildImageTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .video(let content):
return buildVideoTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildVideoTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .file(let content):
return buildFileTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildFileTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .notice(content: let content):
return buildNoticeTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildNoticeTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .emote(content: let content):
return buildEmoteTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildEmoteTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .audio(let content):
return buildAudioTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildAudioTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .location(let content):
return buildLocationTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing)
return buildLocationTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
case .none:
return nil
}
@@ -182,11 +183,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildTextTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: TextMessageContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
TextRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildTextTimelineItemContent(messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
@@ -199,11 +202,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildImageTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: ImageMessageContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
ImageRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildImageTimelineItemContent(messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
@@ -216,11 +221,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildVideoTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: VideoMessageContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
VideoRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildVideoTimelineItemContent(messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
@@ -233,11 +240,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildAudioTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: AudioMessageContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
AudioRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildAudioTimelineItemContent(messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
@@ -250,11 +259,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildFileTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: FileMessageContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
FileRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildFileTimelineItemContent(messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
@@ -267,11 +278,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildNoticeTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: NoticeMessageContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
NoticeRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildNoticeTimelineItemContent(messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
@@ -284,11 +297,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildEmoteTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: EmoteMessageContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
EmoteRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildEmoteTimelineItemContent(senderDisplayName: eventItemProxy.sender.displayName, senderID: eventItemProxy.sender.id, messageContent: messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
@@ -301,11 +316,13 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildLocationTimelineItem(for eventItemProxy: EventTimelineItemProxy,
_ messageTimelineItem: Message,
_ messageContent: LocationContent,
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
_ isOutgoing: Bool,
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
LocationRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
isOutgoing: isOutgoing,
isEditable: eventItemProxy.isEditable,
isThreaded: isThreaded,
sender: eventItemProxy.sender,
content: buildLocationTimelineItemContent(messageContent),
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),