Skip to content

Commit ed139b4

Browse files
nuno-vieiraStream-SDK-BotStream Bot
authored
Change the gallery header view to show the message timestamp instead of online status (#962)
* Change the gallery header view to show the message timestamp instead of online status * Update CHANGELOG with recent fixes and changes * [CI] Snapshots (#963) Co-authored-by: Stream Bot <[email protected]> --------- Co-authored-by: Stream SDK Bot <[email protected]> Co-authored-by: Stream Bot <[email protected]>
1 parent 7dd9fbf commit ed139b4

File tree

10 files changed

+114
-6
lines changed

10 files changed

+114
-6
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1111
- Fix swipe to reply enabled when quoting a message is disabled [#977](https://github.com/GetStream/stream-chat-swiftui/pull/957)
1212
- Fix composer not showing images in the composer when editing signed attachments [#956](https://github.com/GetStream/stream-chat-swiftui/pull/956)
1313
- Fix replacing an image while editing a message not showing the new image in the message list [#956](https://github.com/GetStream/stream-chat-swiftui/pull/956)
14-
- Improve precision when scrolling to the newest message with long text #958
14+
- Improve precision when scrolling to the newest message with long text [#958](https://github.com/GetStream/stream-chat-swiftui/pull/958)
15+
### 🔄 Changed
16+
- Change the gallery header view to show the message timestamp instead of online status [#962](https://github.com/GetStream/stream-chat-swiftui/pull/962)
1517

1618
# [4.88.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.88.0)
1719
_September 10, 2025_

Sources/StreamChatSwiftUI/ChatChannel/Gallery/GalleryView.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ public struct GalleryView<Factory: ViewFactory>: View {
1313
@Injected(\.colors) private var colors
1414
@Injected(\.fonts) private var fonts
1515
@Injected(\.images) private var images
16+
@Injected(\.utils) private var utils
1617

1718
private let viewFactory: Factory
1819
var mediaAttachments: [MediaAttachment]
1920
var author: ChatUser
21+
var message: ChatMessage?
2022
@Binding var isShown: Bool
2123
@State private var selected: Int
2224
@State private var loadedImages = [Int: UIImage]()
@@ -27,15 +29,17 @@ public struct GalleryView<Factory: ViewFactory>: View {
2729
imageAttachments: [ChatMessageImageAttachment],
2830
author: ChatUser,
2931
isShown: Binding<Bool>,
30-
selected: Int
32+
selected: Int,
33+
message: ChatMessage? = nil
3134
) {
3235
let mediaAttachments = imageAttachments.map { MediaAttachment(from: $0) }
3336
self.init(
3437
viewFactory: viewFactory,
3538
mediaAttachments: mediaAttachments,
3639
author: author,
3740
isShown: isShown,
38-
selected: selected
41+
selected: selected,
42+
message: message
3943
)
4044
}
4145

@@ -44,21 +48,25 @@ public struct GalleryView<Factory: ViewFactory>: View {
4448
mediaAttachments: [MediaAttachment],
4549
author: ChatUser,
4650
isShown: Binding<Bool>,
47-
selected: Int
51+
selected: Int,
52+
message: ChatMessage? = nil
4853
) {
4954
self.viewFactory = viewFactory
5055
self.mediaAttachments = mediaAttachments
5156
self.author = author
5257
_isShown = isShown
5358
_selected = State(initialValue: selected)
59+
self.message = message
5460
}
5561

5662
public var body: some View {
5763
GeometryReader { reader in
5864
VStack {
5965
viewFactory.makeGalleryHeaderView(
6066
title: author.name ?? "",
61-
subtitle: author.onlineText,
67+
subtitle: message.map {
68+
utils.galleryHeaderViewDateFormatter.string(from: $0.createdAt)
69+
} ?? author.onlineText,
6270
shown: $isShown
6371
)
6472

Sources/StreamChatSwiftUI/DefaultViewFactory.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,8 @@ extension ViewFactory {
466466
mediaAttachments: mediaAttachments,
467467
author: message.author,
468468
isShown: isShown,
469-
selected: options.selectedIndex
469+
selected: options.selectedIndex,
470+
message: message
470471
)
471472
}
472473

Sources/StreamChatSwiftUI/Utils.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class Utils {
1616
///
1717
/// - SeeAlso: ``ChannelListConfig/messageRelativeDateFormatEnabled``.
1818
public var messageRelativeDateFormatter: DateFormatter
19+
public var galleryHeaderViewDateFormatter: DateFormatter
1920
public var videoPreviewLoader: VideoPreviewLoader
2021
public var imageLoader: ImageLoading
2122
public var imageCDN: ImageCDN
@@ -77,6 +78,7 @@ public class Utils {
7778
public init(
7879
dateFormatter: DateFormatter = .makeDefault(),
7980
messageRelativeDateFormatter: DateFormatter = MessageRelativeDateFormatter(),
81+
galleryHeaderViewDateFormatter: DateFormatter = GalleryHeaderViewDateFormatter(),
8082
videoPreviewLoader: VideoPreviewLoader = DefaultVideoPreviewLoader(),
8183
imageLoader: ImageLoading = NukeImageLoader(),
8284
imageCDN: ImageCDN = StreamImageCDN(),
@@ -104,6 +106,7 @@ public class Utils {
104106
) {
105107
self.dateFormatter = dateFormatter
106108
self.messageRelativeDateFormatter = messageRelativeDateFormatter
109+
self.galleryHeaderViewDateFormatter = galleryHeaderViewDateFormatter
107110
self.videoPreviewLoader = videoPreviewLoader
108111
self.imageLoader = imageLoader
109112
self.imageCDN = imageCDN
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// Copyright © 2025 Stream.io Inc. All rights reserved.
3+
//
4+
5+
/// A formatter used to display the message timestamp in the gallery header view.
6+
public final class GalleryHeaderViewDateFormatter: DateFormatter, @unchecked Sendable {
7+
override public init() {
8+
super.init()
9+
10+
locale = .autoupdatingCurrent
11+
dateStyle = .short
12+
timeStyle = .none
13+
}
14+
15+
@available(*, unavailable)
16+
required init?(coder: NSCoder) {
17+
fatalError("init(coder:) has not been implemented")
18+
}
19+
20+
override public func string(from date: Date) -> String {
21+
if calendar.isDateInToday(date) {
22+
return dayFormatter.string(from: date)
23+
}
24+
25+
if calendar.isDateInYesterday(date) {
26+
return dayFormatter.string(from: date)
27+
}
28+
29+
return super.string(from: date)
30+
}
31+
32+
let dayFormatter: DateFormatter = {
33+
let formatter = DateFormatter()
34+
formatter.locale = .autoupdatingCurrent
35+
formatter.dateStyle = .short
36+
formatter.timeStyle = .none
37+
formatter.doesRelativeDateFormatting = true
38+
return formatter
39+
}()
40+
}

StreamChatSwiftUI.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@
527527
AD3AB65C2CB730090014D4D7 /* Shimmer.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3AB65B2CB730090014D4D7 /* Shimmer.swift */; };
528528
AD3AB65E2CB731360014D4D7 /* ChatThreadListLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3AB65D2CB731360014D4D7 /* ChatThreadListLoadingView.swift */; };
529529
AD3AB6602CB7403C0014D4D7 /* ChatThreadListHeaderViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3AB65F2CB7403C0014D4D7 /* ChatThreadListHeaderViewModifier.swift */; };
530+
AD3DB82F2E7C2E190023D377 /* GalleryHeaderViewDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3DB82E2E7C2E190023D377 /* GalleryHeaderViewDateFormatter.swift */; };
530531
AD51D9182DB9543A0068D0B0 /* MessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD51D9172DB9543A0068D0B0 /* MessageViewModel.swift */; };
531532
AD5C0A5F2D6FDD9700E1E500 /* BouncedMessageActionsModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD5C0A5E2D6FDD8600E1E500 /* BouncedMessageActionsModifier.swift */; };
532533
AD6B7E052D356E8800ADEF39 /* ReactionsUsersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6B7E042D356E8800ADEF39 /* ReactionsUsersViewModel.swift */; };
@@ -1140,6 +1141,7 @@
11401141
AD3AB65B2CB730090014D4D7 /* Shimmer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shimmer.swift; sourceTree = "<group>"; };
11411142
AD3AB65D2CB731360014D4D7 /* ChatThreadListLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatThreadListLoadingView.swift; sourceTree = "<group>"; };
11421143
AD3AB65F2CB7403C0014D4D7 /* ChatThreadListHeaderViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatThreadListHeaderViewModifier.swift; sourceTree = "<group>"; };
1144+
AD3DB82E2E7C2E190023D377 /* GalleryHeaderViewDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryHeaderViewDateFormatter.swift; sourceTree = "<group>"; };
11431145
AD51D9172DB9543A0068D0B0 /* MessageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageViewModel.swift; sourceTree = "<group>"; };
11441146
AD5C0A5E2D6FDD8600E1E500 /* BouncedMessageActionsModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BouncedMessageActionsModifier.swift; sourceTree = "<group>"; };
11451147
AD6B7E042D356E8800ADEF39 /* ReactionsUsersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsUsersViewModel.swift; sourceTree = "<group>"; };
@@ -1950,6 +1952,7 @@
19501952
8465FD382746A95600AF091E /* Common */ = {
19511953
isa = PBXGroup;
19521954
children = (
1955+
AD3DB82E2E7C2E190023D377 /* GalleryHeaderViewDateFormatter.swift */,
19531956
4FCD7DBC2D633F6C000EEB0F /* AttributedString+Extensions.swift */,
19541957
8465FD392746A95600AF091E /* AutoLayoutHelpers.swift */,
19551958
8465FD452746A95600AF091E /* Cache.swift */,
@@ -2778,6 +2781,7 @@
27782781
82D64BD62AD7E5B700C5C79E /* Animator.swift in Sources */,
27792782
8465FDB52746A95700AF091E /* Cache.swift in Sources */,
27802783
84A1CAD12816C6900046595A /* AddUsersViewModel.swift in Sources */,
2784+
AD3DB82F2E7C2E190023D377 /* GalleryHeaderViewDateFormatter.swift in Sources */,
27812785
82D64BDA2AD7E5B700C5C79E /* UIImage.swift in Sources */,
27822786
4F198FDD2C0480EC00148F49 /* Publisher+Extensions.swift in Sources */,
27832787
84289BEF2807246E00282ABE /* FileAttachmentsViewModel.swift in Sources */,

StreamChatSwiftUITests/Tests/ChatChannel/GalleryView_Tests.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,56 @@ class GalleryView_Tests: StreamChatTestCase {
4646
assertSnapshot(matching: header, as: .image(perceptualPrecision: precision))
4747
}
4848

49+
func test_galleryHeader_withMessageCreatedToday_snapshot() {
50+
// Given
51+
let imageMessage = ChatMessage.mock(
52+
id: .unique,
53+
cid: .unique,
54+
text: "test message",
55+
author: .mock(id: .unique),
56+
createdAt: .now,
57+
attachments: ChatChannelTestHelpers.imageAttachments
58+
)
59+
60+
// When
61+
let view = GalleryView(
62+
imageAttachments: imageMessage.imageAttachments,
63+
author: imageMessage.author,
64+
isShown: .constant(true),
65+
selected: 0,
66+
message: imageMessage
67+
)
68+
.applyDefaultSize()
69+
70+
// Then
71+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
72+
}
73+
74+
func test_galleryHeader_withMessageExactDate_snapshot() {
75+
// Given
76+
let imageMessage = ChatMessage.mock(
77+
id: .unique,
78+
cid: .unique,
79+
text: "test message",
80+
author: .mock(id: .unique),
81+
createdAt: Date(timeIntervalSince1970: 1_726_662_904),
82+
attachments: ChatChannelTestHelpers.imageAttachments
83+
)
84+
85+
// When
86+
let view = GalleryView(
87+
imageAttachments: imageMessage.imageAttachments,
88+
author: imageMessage.author,
89+
isShown: .constant(true),
90+
selected: 0,
91+
message: imageMessage
92+
)
93+
.applyDefaultSize()
94+
95+
// Then
96+
assertSnapshot(matching: view, as: .image(perceptualPrecision: precision))
97+
}
98+
4999
func test_gridView_snapshotLoading() {
50100
// Given
51101
let view = GridMediaView(
-16 Bytes
Loading
60.4 KB
Loading
61.5 KB
Loading

0 commit comments

Comments
 (0)