Skip to content

Commit

Permalink
Group image and video metadata in specialised structs (#3518)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanceriu authored Nov 15, 2024
1 parent 4ea276d commit ef288a9
Show file tree
Hide file tree
Showing 27 changed files with 230 additions and 212 deletions.
10 changes: 5 additions & 5 deletions ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ import SwiftUI
extension View {
/// Constrains the max height of a media item in the timeline, whilst preserving its aspect ratio.
@ViewBuilder
func timelineMediaFrame(height contentHeight: CGFloat?, aspectRatio contentAspectRatio: CGFloat?) -> some View {
func timelineMediaFrame(imageInfo: ImageInfoProxy?) -> some View {
let defaultMediaSize = 100.0
let minMediaHeight = 100.0
let maxMediaHeight = 300.0

if let contentHeight, contentHeight < minMediaHeight { // Special case very small images
aspectRatio(contentAspectRatio, contentMode: .fit)
if let contentHeight = imageInfo?.size?.height, contentHeight < minMediaHeight { // Special case very small images
aspectRatio(imageInfo?.aspectRatio, contentMode: .fit)
.frame(minHeight: minMediaHeight, maxHeight: minMediaHeight)
} else {
if let contentAspectRatio {
if let contentAspectRatio = imageInfo?.aspectRatio {
aspectRatio(contentAspectRatio, contentMode: .fit)
.frame(maxHeight: min(maxMediaHeight, max(minMediaHeight, contentHeight ?? .infinity)))
.frame(maxHeight: min(maxMediaHeight, max(minMediaHeight, imageInfo?.size?.height ?? .infinity)))
// Required to prevent the reply details to get higher priority in rendering the width of the view.
.aspectRatio(contentAspectRatio, contentMode: .fit)
} else { // Otherwise force the image to be `defaultMediaSize` x `defaultMediaSize`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview {
eventID: "123",
eventContent: .message(.image(.init(filename: "head.png",
caption: "Image: Pushead",
source: .init(url: .picturesDirectory, mimeType: nil),
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))),
imageInfo: .mockImage,
thumbnailInfo: .mockThumbnail)))),
.loaded(sender: .init(id: "Jason"),
eventID: "123",
eventContent: .message(.notice(.init(body: "Notice: Too far gone?")))),
Expand All @@ -238,9 +238,8 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview {
eventID: "123",
eventContent: .message(.video(.init(filename: "never.mov",
caption: "Video: Through the never",
duration: 100,
source: nil,
thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))),
videoInfo: .mockVideo,
thumbnailInfo: .mockThumbnail)))),
.loading(eventID: "")
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,11 +553,11 @@ class TimelineInteractionHandler {

switch timelineItem {
case let item as ImageRoomTimelineItem:
source = item.content.source
source = item.content.imageInfo.source
filename = item.content.filename
caption = item.content.caption
case let item as VideoRoomTimelineItem:
source = item.content.source
source = item.content.videoInfo.source
filename = item.content.filename
caption = item.content.caption
case let item as FileRoomTimelineItem:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct TimelineReplyView: View {
ReplyView(sender: sender,
plainBody: content.caption ?? content.filename,
formattedBody: content.formattedCaption,
icon: .init(kind: .mediaSource(content.thumbnailSource ?? content.source), cornerRadii: iconCornerRadii))
icon: .init(kind: .mediaSource(content.thumbnailInfo?.source ?? content.imageInfo.source), cornerRadii: iconCornerRadii))
case .notice(let content):
ReplyView(sender: sender,
plainBody: content.body,
Expand All @@ -55,7 +55,7 @@ struct TimelineReplyView: View {
ReplyView(sender: sender,
plainBody: content.caption ?? content.filename,
formattedBody: content.formattedCaption,
icon: content.thumbnailSource.map { .init(kind: .mediaSource($0), cornerRadii: iconCornerRadii) })
icon: content.thumbnailInfo.map { .init(kind: .mediaSource($0.source), cornerRadii: iconCornerRadii) })
case .voice:
ReplyView(sender: sender,
plainBody: L10n.commonVoiceMessage,
Expand Down Expand Up @@ -222,9 +222,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
}()

static var previewItems: [TimelineReplyView] {
let imageSource = MediaSourceProxy(url: "https://mock.com", mimeType: "image/png")

return [
[
TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .notLoaded(eventID: "")),

TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .loading(eventID: "")),
Expand Down Expand Up @@ -268,17 +266,16 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
eventID: "123",
eventContent: .message(.image(.init(filename: "image.jpg",
caption: "Some image",
source: imageSource,
thumbnailSource: imageSource))))),
imageInfo: .mockImage,
thumbnailInfo: .mockThumbnail))))),

TimelineReplyView(placement: .timeline,
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
eventID: "123",
eventContent: .message(.video(.init(filename: "video.mp4",
caption: "Some video",
duration: 0,
source: nil,
thumbnailSource: imageSource))))),
videoInfo: .mockVideo,
thumbnailInfo: .mockThumbnail))))),
TimelineReplyView(placement: .timeline,
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
eventID: "123",
Expand Down Expand Up @@ -321,7 +318,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
}
.padding()
.environmentObject(viewModel.context)
// Allow member names to load. Reduce precission as the `imageSource` randomly renders slightly differently
// Allow member names to load. Reduce precission as the `mockThumbnail` randomly renders slightly differently
.snapshotPreferences(delay: 0.2, precision: 0.98)
.previewLayout(.sizeThatFits)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,8 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
isThreaded: false,
sender: .init(id: "Bob"),
content: .init(filename: "other.png",
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"),
thumbnailSource: nil),
imageInfo: .mockImage,
thumbnailInfo: nil),

properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))))

Expand Down Expand Up @@ -577,8 +577,8 @@ private struct MockTimelineContent: View {
isThreaded: isThreaded,
sender: .init(id: ""),
content: .init(filename: "image.jpg",
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"),
thumbnailSource: nil),
imageInfo: .mockImage,
thumbnailInfo: nil),
replyDetails: replyDetails))

LocationRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,23 @@ struct ImageRoomTimelineView: View {
@ViewBuilder
private var loadableImage: some View {
if timelineItem.content.contentType == .gif {
LoadableImage(mediaSource: timelineItem.content.source,
LoadableImage(mediaSource: timelineItem.content.imageInfo.source,
mediaType: .timelineItem,
blurhash: timelineItem.content.blurhash,
size: timelineItem.content.size,
size: timelineItem.content.imageInfo.size,
mediaProvider: context.mediaProvider) {
placeholder
}
.timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height,
aspectRatio: timelineItem.content.aspectRatio)
.timelineMediaFrame(imageInfo: timelineItem.content.imageInfo)
} else {
LoadableImage(mediaSource: timelineItem.content.thumbnailSource ?? timelineItem.content.source,
LoadableImage(mediaSource: timelineItem.content.thumbnailInfo?.source ?? timelineItem.content.imageInfo.source,
mediaType: .timelineItem,
blurhash: timelineItem.content.blurhash,
size: timelineItem.content.thumbnailSize ?? timelineItem.content.size,
size: timelineItem.content.thumbnailInfo?.size ?? timelineItem.content.imageInfo.size,
mediaProvider: context.mediaProvider) {
placeholder
}
.timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height ?? timelineItem.content.size?.height,
aspectRatio: timelineItem.content.thumbnailAspectRatio ?? timelineItem.content.aspectRatio)
.timelineMediaFrame(imageInfo: timelineItem.content.thumbnailInfo ?? timelineItem.content.imageInfo)
}
}

Expand Down Expand Up @@ -87,8 +85,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
isThreaded: false,
sender: .init(id: "Bob"),
content: .init(filename: "image.jpg",
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/jpg"),
thumbnailSource: nil)))
imageInfo: .mockImage,
thumbnailInfo: nil)))

ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent,
timestamp: "Now",
Expand All @@ -98,8 +96,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
isThreaded: false,
sender: .init(id: "Bob"),
content: .init(filename: "other.png",
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"),
thumbnailSource: nil)))
imageInfo: .mockImage,
thumbnailInfo: nil)))

ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent,
timestamp: "Now",
Expand All @@ -109,9 +107,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
isThreaded: false,
sender: .init(id: "Bob"),
content: .init(filename: "Blurhashed.jpg",
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"),
aspectRatio: 0.7,
thumbnailSource: nil,
imageInfo: .mockImage,
thumbnailInfo: nil,
blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW",
contentType: .gif)))

Expand All @@ -124,10 +121,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
sender: .init(id: "Bob"),
content: .init(filename: "Blurhashed.jpg",
caption: "This is a great image 😎",
source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"),
size: .init(width: 50, height: 50),
aspectRatio: 1,
thumbnailSource: nil,
imageInfo: .mockImage,
thumbnailInfo: .mockThumbnail,
blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW",
contentType: .gif)))
}
Expand Down
Loading

0 comments on commit ef288a9

Please sign in to comment.