mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Further design updates to the timeline. (#524)
- Decryption banner on the timeline - Bubble colours - Background insets - Multiline composer corner radius - Read marker - GIF indicator - Reactions shape - Use RoomTimelineViewLabelStyle everywhere possible - Only set a line limit on reply quotes, allow all the lines for regular quotes. - Message label icons - Yes/No button casing - Make sender profiles immutable. - Enable copy link and invite buttons. - Fix layout loop detecting multiline composer text. - Add animation to the encryption banner.
This commit is contained in:
@@ -78,9 +78,9 @@ enum RoomTimelineItemFixtures {
|
||||
TextRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "",
|
||||
attributedComponents: [
|
||||
AttributedStringBuilderComponent(attributedString: "Hol' up", isBlockquote: false),
|
||||
AttributedStringBuilderComponent(attributedString: "New home office set up!", isBlockquote: true),
|
||||
AttributedStringBuilderComponent(attributedString: "That's amazing! Congrats 🥳", isBlockquote: false)
|
||||
AttributedStringBuilderComponent(attributedString: "Hol' up", isBlockquote: false, isReply: false),
|
||||
AttributedStringBuilderComponent(attributedString: "New home office set up!", isBlockquote: true, isReply: false),
|
||||
AttributedStringBuilderComponent(attributedString: "That's amazing! Congrats 🥳", isBlockquote: false, isReply: false)
|
||||
],
|
||||
timestamp: "5 PM",
|
||||
groupState: .single,
|
||||
|
||||
@@ -218,11 +218,12 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
updateTimelineItems()
|
||||
}
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
||||
private func updateTimelineItems() {
|
||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||
var canBackPaginate = true
|
||||
var isBackPaginating = false
|
||||
var hasEncryptedItems = false
|
||||
|
||||
var createdIdentifiers = [String: Bool]()
|
||||
|
||||
@@ -243,6 +244,9 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
if createdIdentifiers[timelineItem.id] == nil {
|
||||
newTimelineItems.append(timelineItem)
|
||||
createdIdentifiers[timelineItem.id] = true
|
||||
if timelineItem is EncryptedRoomTimelineItem {
|
||||
hasEncryptedItems = true
|
||||
}
|
||||
} else {
|
||||
MXLog.error("Found duplicated timeline item, ignoring")
|
||||
}
|
||||
@@ -280,6 +284,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
callbacks.send(.updatedTimelineItems)
|
||||
callbacks.send(.canBackPaginate(canBackPaginate))
|
||||
callbacks.send(.isBackPaginating(isBackPaginating))
|
||||
callbacks.send(.hasEncryptedItems(hasEncryptedItems))
|
||||
}
|
||||
|
||||
private func computeGroupState(for itemProxy: TimelineItemProxy,
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ enum RoomTimelineControllerCallback {
|
||||
case updatedTimelineItem(_ itemId: String)
|
||||
case canBackPaginate(Bool)
|
||||
case isBackPaginating(Bool)
|
||||
case hasEncryptedItems(Bool)
|
||||
}
|
||||
|
||||
enum RoomTimelineControllerAction {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
/// A protocol that contains the base `m.room.message` event content properties.
|
||||
/// The `CustomStringConvertible` conformance is to redact specific properties from the logs.
|
||||
@@ -95,6 +96,10 @@ extension MessageTimelineItem where Content == MatrixRustSDK.ImageMessageContent
|
||||
var blurhash: String? {
|
||||
content.info?.blurhash
|
||||
}
|
||||
|
||||
var type: UTType? {
|
||||
content.info?.mimetype.flatMap { UTType(mimeType: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
extension MatrixRustSDK.VideoMessageContent: MessageContentProtocol { }
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
#warning("This could be replaced by RoomMemberProxy if Rust includes a RoomMember.")
|
||||
struct TimelineItemSender: Identifiable, Hashable {
|
||||
let id: String
|
||||
let displayName: String?
|
||||
let avatarURL: URL?
|
||||
|
||||
// Lazy loaded properties, displayName and avatarURL will be come lets.
|
||||
var displayName: String?
|
||||
var avatarURL: URL?
|
||||
init(id: String, displayName: String? = nil, avatarURL: URL? = nil) {
|
||||
self.id = id
|
||||
self.displayName = displayName
|
||||
self.avatarURL = avatarURL
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ protocol EventBasedTimelineItemProtocol: RoomTimelineItemProtocol {
|
||||
var isOutgoing: Bool { get }
|
||||
var isEditable: Bool { get }
|
||||
|
||||
var sender: TimelineItemSender { get set }
|
||||
var sender: TimelineItemSender { get }
|
||||
|
||||
var properties: RoomTimelineItemProperties { get }
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ struct EmoteRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hash
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ struct FileRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hasha
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
let source: MediaSourceProxy?
|
||||
let thumbnailSource: MediaSourceProxy?
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
struct ImageRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hashable {
|
||||
let id: String
|
||||
@@ -24,7 +25,7 @@ struct ImageRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hash
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
let source: MediaSourceProxy?
|
||||
var cachedFileURL: URL?
|
||||
@@ -33,6 +34,7 @@ struct ImageRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hash
|
||||
var height: CGFloat?
|
||||
var aspectRatio: CGFloat?
|
||||
var blurhash: String?
|
||||
var type: UTType?
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ struct NoticeRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Has
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ struct TextRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hasha
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ struct VideoRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hash
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
let duration: UInt64
|
||||
let source: MediaSourceProxy?
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ struct EncryptedRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable,
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ struct RedactedRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, H
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ struct StateRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Hash
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ struct StickerRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable, Ha
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
let imageURL: URL
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ struct UnsupportedRoomTimelineItem: EventBasedTimelineItemProtocol, Identifiable
|
||||
let isOutgoing: Bool
|
||||
let isEditable: Bool
|
||||
|
||||
var sender: TimelineItemSender
|
||||
let sender: TimelineItemSender
|
||||
|
||||
var properties = RoomTimelineItemProperties()
|
||||
}
|
||||
|
||||
@@ -237,6 +237,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
height: message.height,
|
||||
aspectRatio: aspectRatio,
|
||||
blurhash: message.blurhash,
|
||||
type: message.type,
|
||||
properties: RoomTimelineItemProperties(isEdited: message.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
||||
|
||||
Reference in New Issue
Block a user