Timeline item sender profiles (#463)

* Adopt timeline item sender profiles for displaying user avatars and display names
* Prevent images from automatically being evicted from the in-memory cache when entering background
* Get rid of all the `urlString: String`s and start using proper URLs
* Add back manual display name loading as the sender profiles aren't working properly yet
* Implement a sender profile.
* Bump the RustSDK to v1.0.32-alpha

Co-authored-by: Doug <douglase@element.io>
This commit is contained in:
Stefan Ceriu
2023-01-18 16:29:44 +02:00
committed by GitHub
parent 8f906c7be7
commit 8f3f83167b
70 changed files with 390 additions and 495 deletions
@@ -36,7 +36,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
timelineViewFactory: RoomTimelineViewFactoryProtocol,
mediaProvider: MediaProviderProtocol,
roomName: String?,
roomAvatarUrl: String? = nil) {
roomAvatarUrl: URL? = nil) {
self.timelineController = timelineController
self.timelineViewFactory = timelineViewFactory
self.mediaProvider = mediaProvider
@@ -76,11 +76,11 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
state.contextMenuBuilder = buildContexMenuForItemId(_:)
buildTimelineViews()
if let roomAvatarUrl {
Task {
if case let .success(avatar) = await mediaProvider.loadImageFromURLString(roomAvatarUrl,
avatarSize: .room(on: .timeline)) {
if case let .success(avatar) = await mediaProvider.loadImageFromURL(roomAvatarUrl,
avatarSize: .room(on: .timeline)) {
state.roomAvatar = avatar
}
}
@@ -261,7 +261,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
}
case .reply:
state.bindings.composerFocused = true
state.composerMode = .reply(id: item.id, displayName: item.senderDisplayName ?? item.senderId)
state.composerMode = .reply(id: item.id, displayName: item.sender.displayName ?? item.sender.id)
case .viewSource:
let debugDescription = timelineController.debugDescriptionFor(item.id)
MXLog.info(debugDescription)
@@ -71,7 +71,7 @@ struct RoomHeaderView_Previews: PreviewProvider {
timelineViewFactory: RoomTimelineViewFactory(),
mediaProvider: MockMediaProvider(),
roomName: "Some Room name",
roomAvatarUrl: "mock_url")
roomAvatarUrl: URL.picturesDirectory)
RoomHeaderView(context: viewModel.context)
.previewLayout(.sizeThatFits)
@@ -60,7 +60,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
HStack(alignment: .top, spacing: 4) {
TimelineSenderAvatarView(timelineItem: timelineItem)
.accessibilityHidden(true)
Text(timelineItem.senderDisplayName ?? timelineItem.senderId)
Text(timelineItem.sender.displayName ?? timelineItem.sender.id)
.font(.element.footnoteBold)
.foregroundColor(.element.primaryContent)
.lineLimit(1)
@@ -47,7 +47,7 @@ struct TimelineItemPlainStylerView<Content: View>: View {
if timelineItem.shouldShowSenderDetails {
HStack {
TimelineSenderAvatarView(timelineItem: timelineItem)
Text(timelineItem.senderDisplayName ?? timelineItem.senderId)
Text(timelineItem.sender.displayName ?? timelineItem.sender.id)
.font(.body)
.foregroundColor(.element.primaryContent)
.fontWeight(.semibold)
@@ -22,13 +22,10 @@ struct EmoteRoomTimelineView: View {
var body: some View {
TimelineStyler(timelineItem: timelineItem) {
HStack(alignment: .top) {
Image(systemName: "face.dashed").padding(.top, 1.0)
if let attributedComponents = timelineItem.attributedComponents {
FormattedBodyText(attributedComponents: attributedComponents)
} else {
FormattedBodyText(text: timelineItem.text)
}
if let attributedComponents = timelineItem.attributedComponents {
FormattedBodyText(attributedComponents: attributedComponents)
} else {
FormattedBodyText(text: timelineItem.text)
}
}
}
@@ -59,6 +56,6 @@ struct EmoteRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: senderId)
sender: .init(id: senderId))
}
}
@@ -81,6 +81,6 @@ struct EncryptedRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: isOutgoing,
isEditable: false,
senderId: senderId)
sender: .init(id: senderId))
}
}
@@ -47,7 +47,7 @@ struct FileRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
source: nil,
thumbnailSource: nil))
@@ -57,7 +57,7 @@ struct FileRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
source: nil,
thumbnailSource: nil))
@@ -67,7 +67,7 @@ struct FileRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
source: nil,
thumbnailSource: nil))
}
@@ -62,7 +62,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
source: nil,
image: UIImage(systemName: "photo")))
@@ -72,7 +72,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
source: nil,
image: nil))
@@ -82,7 +82,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
source: nil,
image: nil,
aspectRatio: 0.7,
@@ -59,6 +59,6 @@ struct NoticeRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: senderId)
sender: .init(id: senderId))
}
}
@@ -46,6 +46,6 @@ struct RedactedRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: senderId)
sender: .init(id: senderId))
}
}
@@ -63,8 +63,8 @@ struct StickerRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
urlString: nil,
sender: .init(id: "Bob"),
imageURL: nil,
image: UIImage(systemName: "photo")))
StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: UUID().uuidString,
@@ -73,8 +73,8 @@ struct StickerRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
urlString: nil,
sender: .init(id: "Bob"),
imageURL: nil,
image: nil))
StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: UUID().uuidString,
@@ -83,8 +83,8 @@ struct StickerRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
urlString: nil,
sender: .init(id: "Bob"),
imageURL: nil,
image: nil,
aspectRatio: 0.7,
blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW"))
@@ -68,6 +68,6 @@ struct TextRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: isOutgoing,
isEditable: isOutgoing,
senderId: senderId)
sender: .init(id: senderId))
}
}
@@ -69,6 +69,6 @@ struct UnsupportedRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: isOutgoing,
isEditable: false,
senderId: senderId)
sender: .init(id: senderId))
}
}
@@ -72,7 +72,7 @@ struct VideoRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
duration: 21,
source: nil,
thumbnailSource: nil,
@@ -84,7 +84,7 @@ struct VideoRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
duration: 22,
source: nil,
thumbnailSource: nil,
@@ -96,7 +96,7 @@ struct VideoRoomTimelineView_Previews: PreviewProvider {
groupState: .single,
isOutgoing: false,
isEditable: false,
senderId: "Bob",
sender: .init(id: "Bob"),
duration: 23,
source: nil,
thumbnailSource: nil,
@@ -24,14 +24,14 @@ struct TimelineSenderAvatarView: View {
var body: some View {
ZStack(alignment: .center) {
if let avatar = timelineItem.senderAvatar {
if let avatar = timelineItem.sender.avatar {
Image(uiImage: avatar)
.resizable()
.scaledToFill()
.overlay(Circle().stroke(Color.element.accent))
} else {
PlaceholderAvatarImage(text: timelineItem.senderDisplayName ?? timelineItem.senderId,
contentId: timelineItem.senderId)
PlaceholderAvatarImage(text: timelineItem.sender.displayName ?? timelineItem.sender.id,
contentId: timelineItem.sender.id)
}
}
.clipShape(Circle())
@@ -41,6 +41,6 @@ struct TimelineSenderAvatarView: View {
.stroke(Color.element.background, lineWidth: 3)
)
.animation(.elementDefault, value: timelineItem.senderAvatar)
.animation(.elementDefault, value: timelineItem.sender.avatar)
}
}