Skip to content

Commit ad6fd9a

Browse files
Exposed factory methods for gallery and video player view (#808)
1 parent fb71e2c commit ad6fd9a

File tree

9 files changed

+157
-39
lines changed

9 files changed

+157
-39
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
44
# Upcoming
55

66
### ✅ Added
7+
- Add factory methods for gallery and video player view [#808](https://github.com/GetStream/stream-chat-swiftui/pull/808)
78
- Add support for editing message attachments [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)
89
### 🐞 Fixed
910
- Fix scrolling to the bottom when editing a message [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsView.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public struct MediaAttachmentsView<Factory: ViewFactory>: View {
5858
if !mediaItem.isVideo, let imageAttachment = mediaItem.imageAttachment {
5959
let index = viewModel.allImageAttachments.firstIndex { $0.id == imageAttachment.id } ?? 0
6060
ImageAttachmentContentView(
61+
factory: factory,
6162
mediaItem: mediaItem,
6263
imageAttachment: imageAttachment,
6364
allImageAttachments: viewModel.allImageAttachments,
@@ -66,8 +67,9 @@ public struct MediaAttachmentsView<Factory: ViewFactory>: View {
6667
)
6768
} else if let videoAttachment = mediaItem.videoAttachment {
6869
VideoAttachmentContentView(
70+
factory: factory,
6971
attachment: videoAttachment,
70-
author: mediaItem.author,
72+
message: mediaItem.message,
7173
width: Self.itemWidth,
7274
ratio: 1,
7375
cornerRadius: 0
@@ -78,9 +80,9 @@ public struct MediaAttachmentsView<Factory: ViewFactory>: View {
7880
BottomRightView {
7981
factory.makeMessageAvatarView(
8082
for: UserDisplayInfo(
81-
id: mediaItem.author.id,
82-
name: mediaItem.author.name ?? "",
83-
imageURL: mediaItem.author.imageURL,
83+
id: mediaItem.message.author.id,
84+
name: mediaItem.message.author.name ?? "",
85+
imageURL: mediaItem.message.author.imageURL,
8486
size: .init(width: 24, height: 24)
8587
)
8688
)
@@ -108,10 +110,11 @@ public struct MediaAttachmentsView<Factory: ViewFactory>: View {
108110
}
109111
}
110112

111-
struct ImageAttachmentContentView: View {
113+
struct ImageAttachmentContentView<Factory: ViewFactory>: View {
112114

113115
@State private var galleryShown = false
114116

117+
let factory: Factory
115118
let mediaItem: MediaItem
116119
let imageAttachment: ChatMessageImageAttachment
117120
let allImageAttachments: [ChatMessageImageAttachment]
@@ -134,11 +137,11 @@ struct ImageAttachmentContentView: View {
134137
.clipped()
135138
}
136139
.fullScreenCover(isPresented: $galleryShown) {
137-
GalleryView(
138-
imageAttachments: allImageAttachments,
139-
author: mediaItem.author,
140+
factory.makeGalleryView(
141+
mediaAttachments: allImageAttachments.map { MediaAttachment(from: $0) },
142+
message: mediaItem.message,
140143
isShown: $galleryShown,
141-
selected: index
144+
options: .init(selectedIndex: index)
142145
)
143146
}
144147
}

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsViewModel.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class MediaAttachmentsViewModel: ObservableObject, ChatMessageSearchControllerDe
8484
let mediaItem = MediaItem(
8585
id: imageAttachment.id.rawValue,
8686
isVideo: false,
87-
author: message.author,
87+
message: message,
8888
videoAttachment: nil,
8989
imageAttachment: imageAttachment
9090
)
@@ -94,7 +94,7 @@ class MediaAttachmentsViewModel: ObservableObject, ChatMessageSearchControllerDe
9494
let mediaItem = MediaItem(
9595
id: videoAttachment.id.rawValue,
9696
isVideo: true,
97-
author: message.author,
97+
message: message,
9898
videoAttachment: videoAttachment,
9999
imageAttachment: nil
100100
)
@@ -110,7 +110,7 @@ class MediaAttachmentsViewModel: ObservableObject, ChatMessageSearchControllerDe
110110
struct MediaItem: Identifiable {
111111
let id: String
112112
let isVideo: Bool
113-
let author: ChatUser
113+
let message: ChatMessage
114114

115115
var videoAttachment: ChatMessageVideoAttachment?
116116
var imageAttachment: ChatMessageImageAttachment?

Sources/StreamChatSwiftUI/ChatChannel/Gallery/GalleryView.swift

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,7 @@ public struct GalleryView: View {
2828
isShown: Binding<Bool>,
2929
selected: Int
3030
) {
31-
let mediaAttachments = imageAttachments.map { attachment in
32-
let url: URL
33-
if let state = attachment.uploadingState {
34-
url = state.localFileURL
35-
} else {
36-
url = attachment.imageURL
37-
}
38-
return MediaAttachment(
39-
url: url,
40-
type: .image,
41-
uploadingState: attachment.uploadingState
42-
)
43-
}
31+
let mediaAttachments = imageAttachments.map { MediaAttachment(from: $0) }
4432
self.init(
4533
mediaAttachments: mediaAttachments,
4634
author: author,
@@ -49,7 +37,7 @@ public struct GalleryView: View {
4937
)
5038
}
5139

52-
init(
40+
public init(
5341
mediaAttachments: [MediaAttachment],
5442
author: ChatUser,
5543
isShown: Binding<Bool>,

Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ public struct ImageAttachmentContainer<Factory: ViewFactory>: View {
6262
.fullScreenCover(isPresented: $galleryShown, onDismiss: {
6363
self.selectedIndex = 0
6464
}) {
65-
GalleryView(
65+
factory.makeGalleryView(
6666
mediaAttachments: sources,
67-
author: message.author,
67+
message: message,
6868
isShown: $galleryShown,
69-
selected: selectedIndex
69+
options: .init(selectedIndex: selectedIndex)
7070
)
7171
}
7272
.accessibilityIdentifier("ImageAttachmentContainer")
@@ -431,7 +431,7 @@ extension ChatMessage {
431431
}
432432
}
433433

434-
struct MediaAttachment {
434+
public struct MediaAttachment {
435435
@Injected(\.utils) var utils
436436

437437
let url: URL
@@ -460,7 +460,29 @@ struct MediaAttachment {
460460
}
461461
}
462462

463+
extension MediaAttachment {
464+
init(from attachment: ChatMessageImageAttachment) {
465+
let url: URL
466+
if let state = attachment.uploadingState {
467+
url = state.localFileURL
468+
} else {
469+
url = attachment.imageURL
470+
}
471+
self.init(
472+
url: url,
473+
type: .image,
474+
uploadingState: attachment.uploadingState
475+
)
476+
}
477+
}
478+
463479
enum MediaAttachmentType {
464480
case image
465481
case video
466482
}
483+
484+
/// Options for the gallery view.
485+
public struct MediaViewsOptions {
486+
/// The index of the selected media item.
487+
public let selectedIndex: Int
488+
}

Sources/StreamChatSwiftUI/ChatChannel/MessageList/VideoAttachmentView.swift

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public struct VideoAttachmentsContainer<Factory: ViewFactory>: View {
2424
)
2525

2626
VideoAttachmentsList(
27+
factory: factory,
2728
message: message,
2829
width: width
2930
)
@@ -38,6 +39,7 @@ public struct VideoAttachmentsContainer<Factory: ViewFactory>: View {
3839
)
3940
} else {
4041
VideoAttachmentsList(
42+
factory: factory,
4143
message: message,
4244
width: width
4345
)
@@ -63,12 +65,18 @@ public struct VideoAttachmentsContainer<Factory: ViewFactory>: View {
6365
}
6466
}
6567

66-
public struct VideoAttachmentsList: View {
68+
public struct VideoAttachmentsList<Factory: ViewFactory>: View {
6769

70+
let factory: Factory
6871
let message: ChatMessage
6972
let width: CGFloat
7073

71-
public init(message: ChatMessage, width: CGFloat) {
74+
public init(
75+
factory: Factory = DefaultViewFactory.shared,
76+
message: ChatMessage,
77+
width: CGFloat
78+
) {
79+
self.factory = factory
7280
self.message = message
7381
self.width = width
7482
}
@@ -77,6 +85,7 @@ public struct VideoAttachmentsList: View {
7785
VStack {
7886
ForEach(message.videoAttachments, id: \.self) { attachment in
7987
VideoAttachmentView(
88+
factory: factory,
8089
attachment: attachment,
8190
message: message,
8291
width: width
@@ -90,21 +99,24 @@ public struct VideoAttachmentsList: View {
9099
}
91100
}
92101

93-
public struct VideoAttachmentView: View {
102+
public struct VideoAttachmentView<Factory: ViewFactory>: View {
94103

104+
let factory: Factory
95105
let attachment: ChatMessageVideoAttachment
96106
let message: ChatMessage
97107
let width: CGFloat
98108
var ratio: CGFloat = 0.75
99109
var cornerRadius: CGFloat = 24
100110

101111
public init(
112+
factory: Factory = DefaultViewFactory.shared,
102113
attachment: ChatMessageVideoAttachment,
103114
message: ChatMessage,
104115
width: CGFloat,
105116
ratio: CGFloat = 0.75,
106117
cornerRadius: CGFloat = 24
107118
) {
119+
self.factory = factory
108120
self.attachment = attachment
109121
self.message = message
110122
self.width = width
@@ -118,8 +130,9 @@ public struct VideoAttachmentView: View {
118130

119131
public var body: some View {
120132
VideoAttachmentContentView(
133+
factory: factory,
121134
attachment: attachment,
122-
author: message.author,
135+
message: message,
123136
width: width,
124137
ratio: ratio,
125138
cornerRadius: cornerRadius
@@ -128,7 +141,7 @@ public struct VideoAttachmentView: View {
128141
}
129142
}
130143

131-
struct VideoAttachmentContentView: View {
144+
struct VideoAttachmentContentView<Factory: ViewFactory>: View {
132145

133146
@Injected(\.utils) private var utils
134147
@Injected(\.images) private var images
@@ -137,8 +150,9 @@ struct VideoAttachmentContentView: View {
137150
utils.videoPreviewLoader
138151
}
139152

153+
let factory: Factory
140154
let attachment: ChatMessageVideoAttachment
141-
let author: ChatUser
155+
let message: ChatMessage
142156
let width: CGFloat
143157
var ratio: CGFloat = 0.75
144158
var cornerRadius: CGFloat = 24
@@ -183,10 +197,11 @@ struct VideoAttachmentContentView: View {
183197
.frame(width: width, height: width * ratio)
184198
.cornerRadius(cornerRadius)
185199
.fullScreenCover(isPresented: $fullScreenShown) {
186-
VideoPlayerView(
200+
factory.makeVideoPlayerView(
187201
attachment: attachment,
188-
author: author,
189-
isShown: $fullScreenShown
202+
message: message,
203+
isShown: $fullScreenShown,
204+
options: .init(selectedIndex: 0)
190205
)
191206
}
192207
.onAppear {

Sources/StreamChatSwiftUI/DefaultViewFactory.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,33 @@ extension ViewFactory {
445445
)
446446
}
447447

448+
public func makeGalleryView(
449+
mediaAttachments: [MediaAttachment],
450+
message: ChatMessage,
451+
isShown: Binding<Bool>,
452+
options: MediaViewsOptions
453+
) -> some View {
454+
GalleryView(
455+
mediaAttachments: mediaAttachments,
456+
author: message.author,
457+
isShown: isShown,
458+
selected: options.selectedIndex
459+
)
460+
}
461+
462+
public func makeVideoPlayerView(
463+
attachment: ChatMessageVideoAttachment,
464+
message: ChatMessage,
465+
isShown: Binding<Bool>,
466+
options: MediaViewsOptions
467+
) -> some View {
468+
VideoPlayerView(
469+
attachment: attachment,
470+
author: message.author,
471+
isShown: isShown
472+
)
473+
}
474+
448475
public func makeDeletedMessageView(
449476
for message: ChatMessage,
450477
isFirst: Bool,

Sources/StreamChatSwiftUI/ViewFactory.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,36 @@ public protocol ViewFactory: AnyObject {
439439
availableWidth: CGFloat,
440440
scrolledId: Binding<String?>
441441
) -> VideoAttachmentViewType
442+
443+
associatedtype GalleryViewType: View
444+
/// Creates the gallery view.
445+
/// - Parameters:
446+
/// - mediaAttachments: the media attachments that will be displayed.
447+
/// - message: the message whose attachments will be displayed.
448+
/// - isShown: whether the gallery is shown.
449+
/// - options: additional options used to configure the gallery view.
450+
/// - Returns: view displayed in the gallery slot.
451+
func makeGalleryView(
452+
mediaAttachments: [MediaAttachment],
453+
message: ChatMessage,
454+
isShown: Binding<Bool>,
455+
options: MediaViewsOptions
456+
) -> GalleryViewType
457+
458+
associatedtype VideoPlayerViewType: View
459+
/// Creates the video player view.
460+
/// - Parameters:
461+
/// - attachment: the video attachment that will be displayed.
462+
/// - message: the message whose attachments will be displayed.
463+
/// - isShown: whether the video player is shown.
464+
/// - options: additional options used to configure the gallery view.
465+
/// - Returns: view displayed in the video player slot.
466+
func makeVideoPlayerView(
467+
attachment: ChatMessageVideoAttachment,
468+
message: ChatMessage,
469+
isShown: Binding<Bool>,
470+
options: MediaViewsOptions
471+
) -> VideoPlayerViewType
442472

443473
associatedtype DeletedMessageViewType: View
444474
/// Creates the deleted message view.

0 commit comments

Comments
 (0)