Skip to content

Commit ac7fd36

Browse files
Customizing the message avatar view is reflected in all views that use it (#772)
1 parent be8f208 commit ac7fd36

15 files changed

+156
-55
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
99
- Add `resignsFirstResponderOnScrollDown` to `MessageListConfig` [#769](https://github.com/GetStream/stream-chat-swiftui/pull/769)
1010
### 🔄 Changed
1111
- Uploading a HEIC photo from the library is now converted to JPEG for better compatibility [#767](https://github.com/GetStream/stream-chat-swiftui/pull/767)
12+
- Customizing the message avatar view is reflected in all views that use it [#772](https://github.com/GetStream/stream-chat-swiftui/pull/772)
1213

1314
# [4.73.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.73.0)
1415
_February 28, 2025_

Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/ChatChannelHeaderViewModifier.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public struct DefaultChatChannelHeader<Factory: ViewFactory>: ToolbarContent {
8080
.accessibilityLabel(Text(L10n.Channel.Header.Info.title))
8181

8282
NavigationLink(isActive: $isActive) {
83-
LazyView(ChatChannelInfoView(channel: channel, shownFromMessageList: true))
83+
LazyView(ChatChannelInfoView(factory: factory, channel: channel, shownFromMessageList: true))
8484
} label: {
8585
EmptyView()
8686
}

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatChannelInfoHelperViews.swift

+22-7
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,21 @@ struct ChannelInfoDivider: View {
5050
}
5151
}
5252

53-
public struct ChatInfoOptionsView: View {
53+
public struct ChatInfoOptionsView<Factory: ViewFactory>: View {
5454

5555
@Injected(\.images) private var images
5656
@Injected(\.colors) private var colors
5757
@Injected(\.fonts) private var fonts
5858

5959
@StateObject var viewModel: ChatChannelInfoViewModel
60+
let factory: Factory
6061

61-
public init(viewModel: ChatChannelInfoViewModel) {
62+
public init(
63+
factory: Factory = DefaultViewFactory.shared,
64+
viewModel: ChatChannelInfoViewModel
65+
) {
6266
_viewModel = StateObject(wrappedValue: viewModel)
67+
self.factory = factory
6368
}
6469

6570
public var body: some View {
@@ -89,6 +94,7 @@ public struct ChatInfoOptionsView: View {
8994
title: L10n.ChatInfo.PinnedMessages.title
9095
) {
9196
PinnedMessagesView(
97+
factory: factory,
9298
channel: viewModel.channel,
9399
channelController: viewModel.channelController
94100
)
@@ -100,7 +106,7 @@ public struct ChatInfoOptionsView: View {
100106
icon: UIImage(systemName: "photo")!,
101107
title: L10n.ChatInfo.Media.title
102108
) {
103-
MediaAttachmentsView(channel: viewModel.channel)
109+
MediaAttachmentsView(factory: factory, channel: viewModel.channel)
104110
}
105111

106112
Divider()
@@ -239,20 +245,29 @@ public struct ChannelInfoItemView<TrailingView: View>: View {
239245
}
240246
}
241247

242-
struct ChatInfoDirectChannelView: View {
248+
struct ChatInfoDirectChannelView<Factory: ViewFactory>: View {
243249

244250
@Injected(\.fonts) private var fonts
245251
@Injected(\.colors) private var colors
246252

253+
let factory: Factory
247254
var participant: ParticipantInfo?
255+
256+
init(factory: Factory = DefaultViewFactory.shared, participant: ParticipantInfo?) {
257+
self.factory = factory
258+
self.participant = participant
259+
}
248260

249261
var body: some View {
250262
VStack {
251-
MessageAvatarView(
252-
avatarURL: participant?.chatUser.imageURL,
263+
let displayInfo = UserDisplayInfo(
264+
id: participant?.chatUser.id ?? "",
265+
name: participant?.chatUser.name ?? "",
266+
imageURL: participant?.chatUser.imageURL,
253267
size: .init(width: 64, height: 64)
254268
)
255-
269+
factory.makeMessageAvatarView(for: displayInfo)
270+
256271
Text(participant?.onlineInfoText ?? "")
257272
.font(fonts.footnote)
258273
.foregroundColor(Color(colors.textLowEmphasis))

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatChannelInfoView.swift

+14-4
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,37 @@ import StreamChat
66
import SwiftUI
77

88
// View for the channel info screen.
9-
public struct ChatChannelInfoView: View, KeyboardReadable {
9+
public struct ChatChannelInfoView<Factory: ViewFactory>: View, KeyboardReadable {
1010

1111
@Injected(\.images) private var images
1212
@Injected(\.colors) private var colors
1313
@Injected(\.fonts) private var fonts
1414

15+
let factory: Factory
16+
1517
@StateObject private var viewModel: ChatChannelInfoViewModel
1618
private var shownFromMessageList: Bool
1719

1820
@Environment(\.presentationMode) var presentationMode
19-
21+
2022
public init(
23+
factory: Factory = DefaultViewFactory.shared,
2124
channel: ChatChannel,
2225
shownFromMessageList: Bool = false
2326
) {
2427
_viewModel = StateObject(
2528
wrappedValue: ChatChannelInfoViewModel(channel: channel)
2629
)
30+
self.factory = factory
2731
self.shownFromMessageList = shownFromMessageList
2832
}
2933

30-
init(viewModel: ChatChannelInfoViewModel) {
34+
init(
35+
factory: Factory = DefaultViewFactory.shared,
36+
viewModel: ChatChannelInfoViewModel
37+
) {
3138
_viewModel = StateObject(wrappedValue: viewModel)
39+
self.factory = factory
3240
shownFromMessageList = false
3341
}
3442

@@ -38,10 +46,12 @@ public struct ChatChannelInfoView: View, KeyboardReadable {
3846
LazyVStack(spacing: 0) {
3947
if viewModel.showSingleMemberDMView {
4048
ChatInfoDirectChannelView(
49+
factory: factory,
4150
participant: viewModel.displayedParticipants.first
4251
)
4352
} else {
4453
ChatInfoParticipantsView(
54+
factory: factory,
4555
participants: viewModel.displayedParticipants,
4656
onItemAppear: viewModel.onParticipantAppear(_:)
4757
)
@@ -59,7 +69,7 @@ public struct ChatChannelInfoView: View, KeyboardReadable {
5969

6070
ChannelInfoDivider()
6171

62-
ChatInfoOptionsView(viewModel: viewModel)
72+
ChatInfoOptionsView(factory: factory, viewModel: viewModel)
6373

6474
ChannelInfoDivider()
6575
.alert(isPresented: $viewModel.errorShown) {

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatInfoParticipantsView.swift

+18-2
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,35 @@ import StreamChat
66
import SwiftUI
77

88
/// View for the chat info participants.
9-
struct ChatInfoParticipantsView: View {
9+
struct ChatInfoParticipantsView<Factory: ViewFactory>: View {
1010

1111
@Injected(\.fonts) private var fonts
1212
@Injected(\.colors) private var colors
1313

14+
let factory: Factory
1415
var participants: [ParticipantInfo]
1516
var onItemAppear: (ParticipantInfo) -> Void
17+
18+
init(
19+
factory: Factory = DefaultViewFactory.shared,
20+
participants: [ParticipantInfo],
21+
onItemAppear: @escaping (ParticipantInfo) -> Void
22+
) {
23+
self.factory = factory
24+
self.participants = participants
25+
self.onItemAppear = onItemAppear
26+
}
1627

1728
var body: some View {
1829
LazyVStack {
1930
ForEach(participants) { participant in
2031
HStack {
21-
MessageAvatarView(avatarURL: participant.chatUser.imageURL)
32+
let displayInfo = UserDisplayInfo(
33+
id: participant.chatUser.id,
34+
name: participant.chatUser.name ?? "",
35+
imageURL: participant.chatUser.imageURL
36+
)
37+
factory.makeMessageAvatarView(for: displayInfo)
2238

2339
VStack(alignment: .leading, spacing: 4) {
2440
Text(participant.displayName)

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsView.swift

+16-10
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,37 @@ import StreamChat
66
import SwiftUI
77

88
/// View displaying media attachments.
9-
public struct MediaAttachmentsView: View {
9+
public struct MediaAttachmentsView<Factory: ViewFactory>: View {
1010

1111
@Injected(\.images) private var images
1212

1313
@StateObject private var viewModel: MediaAttachmentsViewModel
14-
15-
private static let spacing: CGFloat = 2
14+
15+
let factory: Factory
1616

1717
private static var itemWidth: CGFloat {
18+
let spacing: CGFloat = 2
1819
if UIDevice.current.userInterfaceIdiom == .phone {
1920
return (UIScreen.main.bounds.size.width / 3) - spacing * 3
2021
} else {
2122
return 120
2223
}
2324
}
2425

25-
private let columns = [GridItem(.adaptive(minimum: itemWidth), spacing: spacing)]
26+
private let columns = [GridItem(.adaptive(minimum: itemWidth), spacing: 2)]
2627

27-
public init(channel: ChatChannel) {
28+
public init(factory: Factory = DefaultViewFactory.shared, channel: ChatChannel) {
2829
_viewModel = StateObject(
2930
wrappedValue: MediaAttachmentsViewModel(channel: channel)
3031
)
32+
self.factory = factory
3133
}
3234

33-
init(viewModel: MediaAttachmentsViewModel) {
35+
init(factory: Factory = DefaultViewFactory.shared, viewModel: MediaAttachmentsViewModel) {
3436
_viewModel = StateObject(
3537
wrappedValue: viewModel
3638
)
39+
self.factory = factory
3740
}
3841

3942
public var body: some View {
@@ -73,10 +76,13 @@ public struct MediaAttachmentsView: View {
7376
}
7477
.overlay(
7578
BottomRightView {
76-
MessageAvatarView(
77-
avatarURL: mediaItem.author.imageURL,
78-
size: .init(width: 24, height: 24),
79-
showOnlineIndicator: false
79+
factory.makeMessageAvatarView(
80+
for: UserDisplayInfo(
81+
id: mediaItem.author.id,
82+
name: mediaItem.author.name ?? "",
83+
imageURL: mediaItem.author.imageURL,
84+
size: .init(width: 24, height: 24)
85+
)
8086
)
8187
.overlay(
8288
Circle()

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/PinnedMessagesView.swift

+19-7
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,26 @@ import StreamChat
66
import SwiftUI
77

88
/// View displaying pinned messages in the chat info screen.
9-
public struct PinnedMessagesView: View {
9+
public struct PinnedMessagesView<Factory: ViewFactory>: View {
1010

1111
@Injected(\.images) private var images
1212

1313
@StateObject private var viewModel: PinnedMessagesViewModel
14+
15+
let factory: Factory
1416

15-
public init(channel: ChatChannel, channelController: ChatChannelController? = nil) {
17+
public init(
18+
factory: Factory = DefaultViewFactory.shared,
19+
channel: ChatChannel,
20+
channelController: ChatChannelController? = nil
21+
) {
1622
_viewModel = StateObject(
1723
wrappedValue: PinnedMessagesViewModel(
1824
channel: channel,
1925
channelController: channelController
2026
)
2127
)
28+
self.factory = factory
2229
}
2330

2431
public var body: some View {
@@ -27,7 +34,7 @@ public struct PinnedMessagesView: View {
2734
ScrollView {
2835
LazyVStack(spacing: 0) {
2936
ForEach(viewModel.pinnedMessages) { message in
30-
PinnedMessageView(message: message, channel: viewModel.channel)
37+
PinnedMessageView(factory: factory, message: message, channel: viewModel.channel)
3138
Divider()
3239
}
3340
}
@@ -45,22 +52,27 @@ public struct PinnedMessagesView: View {
4552
}
4653
}
4754

48-
struct PinnedMessageView: View {
55+
struct PinnedMessageView<Factory: ViewFactory>: View {
4956

5057
@Injected(\.fonts) private var fonts
5158
@Injected(\.colors) private var colors
5259
@Injected(\.utils) private var utils
5360

5461
private let avatarSize = CGSize(width: 56, height: 56)
5562

63+
var factory: Factory
5664
var message: ChatMessage
5765
var channel: ChatChannel
5866

5967
var body: some View {
6068
HStack {
61-
MessageAvatarView(
62-
avatarURL: message.author.imageURL,
63-
size: avatarSize
69+
factory.makeMessageAvatarView(
70+
for: UserDisplayInfo(
71+
id: message.author.id,
72+
name: message.author.name ?? "",
73+
imageURL: message.author.imageURL,
74+
size: avatarSize
75+
)
6476
)
6577

6678
VStack(alignment: .leading, spacing: 4) {

Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAllOptionsView.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import StreamChat
66
import SwiftUI
77

8-
struct PollAllOptionsView: View {
8+
struct PollAllOptionsView<Factory: ViewFactory>: View {
99

1010
@Injected(\.colors) var colors
1111
@Injected(\.fonts) var fonts
@@ -14,6 +14,8 @@ struct PollAllOptionsView: View {
1414

1515
@ObservedObject var viewModel: PollAttachmentViewModel
1616

17+
let factory: Factory
18+
1719
var body: some View {
1820
NavigationView {
1921
ScrollView {
@@ -29,6 +31,7 @@ struct PollAllOptionsView: View {
2931
ForEach(viewModel.poll.options) { option in
3032
PollOptionView(
3133
viewModel: viewModel,
34+
factory: factory,
3235
option: option,
3336
optionFont: fonts.headline,
3437
textColor: Color(colors.text),

0 commit comments

Comments
 (0)