-
Notifications
You must be signed in to change notification settings - Fork 225
Change the gallery header view to show the message timestamp instead of online status #3818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change the gallery header view to show the message timestamp instead of online status #3818
Conversation
WalkthroughAdds a timestamp-focused header in GalleryVC. Introduces a new gallery header date formatter protocol and default implementation, wires it via Appearance.Formatters, and updates GalleryVC to optionally show message timestamps instead of user status. Updates project references, changelog entry, and adds snapshot tests for today/older dates. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant GalleryVC
participant Appearance.Formatters as Formatters
participant HeaderView as Header
User->>GalleryVC: Open gallery (message with createdAt)
GalleryVC->>GalleryVC: updateContent()
alt showMessageTimestamp == true
GalleryVC->>Formatters: format(createdAt)
Formatters-->>GalleryVC: "Today"/"Yesterday"/short date
GalleryVC->>Header: Set subtitle = formatted date
else
GalleryVC->>GalleryVC: Determine online / last seen
GalleryVC->>Header: Set subtitle = status/last seen/offline
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Public Interface+ open class DefaultGalleryHeaderViewDateFormatter: GalleryHeaderViewDateFormatter
+
+ public var dateFormatter: DateFormatter
+
+
+ public init()
+
+
+ open func format(_ date: Date)-> String
+ public protocol GalleryHeaderViewDateFormatter
open class GalleryVC: _ViewController, UIGestureRecognizerDelegate, AppearanceProvider, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, ComponentsProvider
- open var transitionController: ZoomTransitionController!
+ open var messageTimestampFormatter: (Date) -> String?
- open private lazy var attachmentsFlowLayout: UICollectionViewFlowLayout
+ public var showMessageTimestamp: Bool
- open private lazy var attachmentsCollectionView: UICollectionView
+ open var transitionController: ZoomTransitionController!
- open private lazy var topBarView
+ open private lazy var attachmentsFlowLayout: UICollectionViewFlowLayout
- open private lazy var topBarContainerStackView
+ open private lazy var attachmentsCollectionView: UICollectionView
- open private lazy var infoContainerStackView
+ open private lazy var topBarView
- open private lazy var userLabel
+ open private lazy var topBarContainerStackView
- open private lazy var dateLabel
+ open private lazy var infoContainerStackView
- open private lazy var bottomBarView
+ open private lazy var userLabel
- open private lazy var bottomBarContainerStackView
+ open private lazy var dateLabel
- open private lazy var currentPhotoLabel
+ open private lazy var bottomBarView
- open private lazy var closeButton
+ open private lazy var bottomBarContainerStackView
- open private lazy var videoPlaybackBar: VideoPlaybackControlView
+ open private lazy var currentPhotoLabel
- open private lazy var shareButton
+ open private lazy var closeButton
- open private var topBarTopConstraint: NSLayoutConstraint?
+ open private lazy var videoPlaybackBar: VideoPlaybackControlView
- open private var bottomBarBottomConstraint: NSLayoutConstraint?
+ open private lazy var shareButton
- open var currentItemIndexPath: IndexPath
+ open private var topBarTopConstraint: NSLayoutConstraint?
- open var currentItem: AnyChatMessageAttachment
+ open private var bottomBarBottomConstraint: NSLayoutConstraint?
- open var imageViewToAnimateWhenDismissing: UIImageView?
+ open var currentItemIndexPath: IndexPath
-
+ open var currentItem: AnyChatMessageAttachment
-
+ open var imageViewToAnimateWhenDismissing: UIImageView?
- override open func setUpAppearance()
+
- override open func setUp()
+
- override open func setUpLayout()
+ override open func setUpAppearance()
- override open func viewDidLoad()
+ override open func setUp()
- override open func viewDidAppear(_ animated: Bool)
+ override open func setUpLayout()
- override open func viewWillDisappear(_ animated: Bool)
+ override open func viewDidLoad()
- override open func updateContent()
+ override open func viewDidAppear(_ animated: Bool)
- @objc open func handlePan(with gestureRecognizer: UIPanGestureRecognizer)
+ override open func viewWillDisappear(_ animated: Bool)
- @objc open func closeButtonTapped()
+ override open func updateContent()
- @objc open func shareButtonTapped()
+ @objc open func handlePan(with gestureRecognizer: UIPanGestureRecognizer)
- open func updateCurrentPage()
+ @objc open func closeButtonTapped()
- open func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int)-> Int
+ @objc open func shareButtonTapped()
- open func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath)-> UICollectionViewCell
+ open func updateCurrentPage()
- open func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath)-> CGSize
+ open func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int)-> Int
- open func collectionView(_ collectionView: UICollectionView,targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint)-> CGPoint
+ open func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath)-> UICollectionViewCell
- open func scrollViewDidEndDecelerating(_ scrollView: UIScrollView)
+ open func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath)-> CGSize
- open func scrollViewDidScroll(_ scrollView: UIScrollView)
+ open func collectionView(_ collectionView: UICollectionView,targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint)-> CGPoint
- override open func viewWillTransition(to size: CGSize,with coordinator: UIViewControllerTransitionCoordinator)
+ open func scrollViewDidEndDecelerating(_ scrollView: UIScrollView)
- open func shareItem(at indexPath: IndexPath)-> Any?
+ open func scrollViewDidScroll(_ scrollView: UIScrollView)
- open func cellReuseIdentifierForItem(at indexPath: IndexPath)-> String?
+ override open func viewWillTransition(to size: CGSize,with coordinator: UIViewControllerTransitionCoordinator)
- open func handleSingleTapOnCell(at indexPath: IndexPath)
+ open func shareItem(at indexPath: IndexPath)-> Any?
-
+ open func cellReuseIdentifierForItem(at indexPath: IndexPath)-> String?
-
+ open func handleSingleTapOnCell(at indexPath: IndexPath)
- public struct Content
+
-
+
- public var message: ChatMessage
+ public struct Content
- public var currentPage: Int
+
-
+ public var message: ChatMessage
-
+ public var currentPage: Int
- public init(message: ChatMessage,currentPage: Int = 0)
+
+
+ public init(message: ChatMessage,currentPage: Int = 0) |
SDK Size
|
SDK Performance
|
SDK Size
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (10)
CHANGELOG.md (1)
12-15
: Link this entry to the current PR (and optionally reference the SwiftUI one).Replace the SwiftUI PR link with this PR, and keep the SwiftUI reference as context.
Apply this diff:
-## StreamChatUI -### 🔄 Changed -- Change gallery header view to show message timestamp instead of online status [#962](https://github.com/GetStream/stream-chat-swiftui/pull/962) +## StreamChatUI +### 🔄 Changed +- Change gallery header view to show message timestamp instead of online status [#3818](https://github.com/GetStream/stream-chat-swift/pull/3818) (mirrors SwiftUI [#962](https://github.com/GetStream/stream-chat-swiftui/pull/962))Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift (4)
14-20
: Make the formatter lazy and document it; set autoupdating time zone.Avoid unnecessary instantiation, explicitly track TZ changes, and document the public API surface.
Apply this diff:
- public var dateFormatter: DateFormatter = { + /// Base formatter used when the date is neither today nor yesterday. + public lazy var dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = .autoupdatingCurrent + formatter.timeZone = .autoupdatingCurrent formatter.dateStyle = .short formatter.timeStyle = .none return formatter }()
22-29
: Tighten visibility and mirror TZ behavior.This helper isn’t part of the public API; make it private and lazy, and keep TZ in sync with
dateFormatter
.Apply this diff:
- let dayFormatter: DateFormatter = { + private lazy var dayFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = .autoupdatingCurrent + formatter.timeZone = .autoupdatingCurrent formatter.dateStyle = .short formatter.timeStyle = .none formatter.doesRelativeDateFormatting = true return formatter }()
31-31
: Prefer an autoupdating calendar (and consider injection).Use
autoupdatingCurrent
so “today/yesterday” tracks user setting changes; optional: add a convenience init for injecting a calendar in tests.Apply this diff:
- var calendar: StreamCalendar = Calendar.current + var calendar: StreamCalendar = Calendar.autoupdatingCurrentOptionally add:
+ public convenience init(calendar: StreamCalendar) { + self.init() + self.calendar = calendar + }
35-45
: Confirm product copy: do we need time-of-day for “Today”?Current output for today/yesterday is just the relative day (“Today”/“Yesterday”). If UX expects a timestamp (e.g., “Today, 3:42 PM”), adjust here or in the consumer.
If needed, one option:
- if calendar.isDateInToday(date) { - return dayFormatter.string(from: date) - } + if calendar.isDateInToday(date) { + // e.g., "Today, 3:42 PM" + let time = DateFormatter.localizedString(from: date, dateStyle: .none, timeStyle: .short) + return "\(dayFormatter.string(from: date)), \(time)" + }Please confirm the expected format against the SwiftUI implementation and existing snapshots. If alignment is required, I can update both formatter and tests.
StreamChat.xcodeproj/project.pbxproj (1)
8955-8955
: Optional: keep group children sorted to reduce future diff churn.If the project prefers alphabetical order in groups, consider reordering the new file under Appearance+Formatters. Purely a nit.
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift (1)
150-164
: Stability for older-date snapshot.Hard-coded epoch is fine, but output still varies by locale/time zone since the formatter uses auto-updating settings. Ensure tests force a stable locale/time zone, or inject a stub formatter returning a fixed string.
Sources/StreamChatUI/Gallery/GalleryVC.swift (3)
51-53
: Return non-optional frommessageTimestampFormatter
.
DefaultGalleryHeaderViewDateFormatter.format
returnsString
(non-optional). Expose the property as(Date) -> String
for clarity and to avoid implying nil is valid.Apply:
- open var messageTimestampFormatter: (Date) -> String? { appearance.formatters.galleryHeaderViewDateFormatter.format } + open var messageTimestampFormatter: (Date) -> String { appearance.formatters.galleryHeaderViewDateFormatter.format }
55-56
: Update view when togglingshowMessageTimestamp
.Without a
didSet
, changing this at runtime won’t refresh the header until the next lifecycle/update. Trigger an update to reflect the change immediately.Apply:
- public var showMessageTimestamp: Bool = true + public var showMessageTimestamp: Bool = true { + didSet { updateContentIfNeeded() } + }
276-288
: Header update branch reads well; keep a11y in mind.When showing timestamps, consider setting an accessibilityLabel (e.g., “Sent on ”) for
dateLabel
in a follow-up to improve VO clarity.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (2)
Tests/StreamChatUITests/SnapshotTests/Gallery/__Snapshots__/GalleryVC_Tests/test_snapshotWithMessageTimestampOlderDate.default-light.png
is excluded by!**/*.png
Tests/StreamChatUITests/SnapshotTests/Gallery/__Snapshots__/GalleryVC_Tests/test_snapshotWithMessageTimestampToday.default-light.png
is excluded by!**/*.png
📒 Files selected for processing (6)
CHANGELOG.md
(1 hunks)Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift
(1 hunks)Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift
(1 hunks)Sources/StreamChatUI/Gallery/GalleryVC.swift
(2 hunks)StreamChat.xcodeproj/project.pbxproj
(5 hunks)Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
(4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
**/*.swift
: Respect .swiftlint.yml rules; do not suppress SwiftLint rules broadly—scope and justify any exceptions
Adhere to the project’s zero warnings policy—fix new warnings and avoid introducing any
Files:
Sources/StreamChatUI/Gallery/GalleryVC.swift
Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
Sources/{StreamChat,StreamChatUI}/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
When altering public API, update inline documentation comments in source
Files:
Sources/StreamChatUI/Gallery/GalleryVC.swift
Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift
CHANGELOG.md
📄 CodeRabbit inference engine (AGENTS.md)
Update CHANGELOG for user-visible SDK changes
Files:
CHANGELOG.md
Tests/{StreamChatTests,StreamChatUITests}/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Tests/{StreamChatTests,StreamChatUITests}/**/*.swift
: Add or extend tests in the matching module’s Tests folder
Prefer using provided test fakes/mocks in tests when possible
Files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
Tests/StreamChatUITests/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Ensure tests cover view controllers and UI behaviors of StreamChatUI
Files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
🧠 Learnings (4)
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Sources/{StreamChat,StreamChatUI}/**/*.swift : When altering public API, update inline documentation comments in source
Applied to files:
StreamChat.xcodeproj/project.pbxproj
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatTests/**/*.swift : Ensure tests cover core models and API surface of StreamChat
Applied to files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatUITests/**/*.swift : Ensure tests cover view controllers and UI behaviors of StreamChatUI
Applied to files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/{StreamChatTests,StreamChatUITests}/**/*.swift : Prefer using provided test fakes/mocks in tests when possible
Applied to files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
🧬 Code graph analysis (3)
Sources/StreamChatUI/Gallery/GalleryVC.swift (3)
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift (1)
format
(35-45)Sources/StreamChatUI/Appearance+Formatters/UserLastActivityFormatter.swift (1)
format
(16-18)Sources/StreamChatUI/Utils/DateUtils.swift (1)
timeAgo
(9-52)
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift (1)
Tests/StreamChatUITests/Mocks/Utils/Calendar_Mock.swift (2)
isDateInToday
(13-15)isDateInYesterday
(17-19)
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift (1)
TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageImageAttachment_Mock.swift (1)
mock
(10-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build Test App and Frameworks
- GitHub Check: Test LLC (Debug)
- GitHub Check: Automated Code Review
- GitHub Check: Metrics
- GitHub Check: Metrics
🔇 Additional comments (9)
StreamChat.xcodeproj/project.pbxproj (4)
10938-10938
: Looks like correct target membership; just confirm it’s not added to a test/host‑app target.Assuming this Sources phase is the StreamChatUI framework, this entry is expected. Please cross‑check with the script above to ensure it’s not compiled into a unit‑test or demo app target.
13085-13085
: Second Sources membership: confirm it’s the other UI target (e.g., another platform) rather than a host app.Two targets compiling the file is fine; compiling into an app in addition to the framework would duplicate types. Validate with the mapping script.
4323-4323
: PBXFileReference verified — file present and SPM pickup OK.
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift exists; Package.swift defines the StreamChatUI target; Appearance.Formatters registers galleryHeaderViewDateFormatter and the public/open declarations have triple‑slash doc comments.
1459-1460
: Verify dual “in Sources” entries map to distinct targets (avoid duplicate compilation in a single target).Two PBXBuildFile entries are expected if the file is compiled into two different targets. Please confirm they’re attached to different PBXSourcesBuildPhases and not duplicated within the same target.
Run this script to resolve which targets compile the file and flag duplicates:
Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift (1)
48-50
: New formatter hook looks good; confirm docs and theming guides updated.API shape and defaults align with existing formatters. Please ensure the public API docs and theming/customization guides reference
galleryHeaderViewDateFormatter
.Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift (4)
33-33
: Good call setting the default off for legacy snapshots.
129-129
: Consistent override in subclassing test.
174-186
: Helper enhancement looks good; defaultcreatedAt
is sensible.The optional
createdAt
parameter improves test readability. No issues.
134-148
: Make the “today” snapshot deterministic.Replace Date() in test_snapshotWithMessageTimestampToday (Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift, lines 134–148) with a fixed Date or stub the date formatter / pin Locale/TimeZone (e.g. Locale(identifier: "en_US_POSIX"), TimeZone(secondsFromGMT: 0)) to avoid flakiness across locales/time zones and near midnight.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (5)
Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift (1)
48-50
: Naming nit: drop “View” for consistencyOther formatter names avoid UI-type suffixes (e.g., channelName, userLastActivity). Consider
galleryHeaderDate
orgalleryHeaderMessageTimestamp
for alignment. Non-blocking.Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift (1)
22-29
: Use autoupdating Calendar and expose knobs for tests/customization
- Prefer
Calendar.autoupdatingCurrent
so “today/yesterday” reacts to system changes.- Consider making
dayFormatter
andcalendar
open
to enable subclass tweaks and easier test injection (you already exposedateFormatter
).Apply:
- let dayFormatter: DateFormatter = { + open var dayFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = .autoupdatingCurrent formatter.dateStyle = .short formatter.timeStyle = .none formatter.doesRelativeDateFormatting = true return formatter }() - var calendar: StreamCalendar = Calendar.current + open var calendar: StreamCalendar = Calendar.autoupdatingCurrentAlso applies to: 31-31
Sources/StreamChatUI/Gallery/GalleryVC.swift (1)
55-55
: Refresh UI when toggling the flagEnsure header updates if clients change
showMessageTimestamp
after the view is visible.- public var showMessageTimestamp: Bool = true + public var showMessageTimestamp: Bool = true { + didSet { if oldValue != showMessageTimestamp { updateContent() } } + }Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift (2)
134-148
: Stabilize today-based snapshot across locales/timezones“Today” string and short-date formats vary by locale/timezone and around midnight. Inject a fixed locale/timezone (and optionally a mock calendar) into the formatter to avoid flakiness.
Example tweak inside the test before asserting:
- let vc = makeGalleryVC(content: content) + var appearance = Appearance() + let fmt = DefaultGalleryHeaderViewDateFormatter() + fmt.dateFormatter.locale = Locale(identifier: "en_US_POSIX") + fmt.dayFormatter.locale = Locale(identifier: "en_US_POSIX") // @testable gives access + fmt.dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) + fmt.dayFormatter.timeZone = TimeZone(secondsFromGMT: 0) + appearance.formatters.galleryHeaderViewDateFormatter = fmt + + let vc = makeGalleryVC(content: content) + vc.appearance = appearance vc.showMessageTimestamp = trueOptionally, use
Calendar_Mock
(from Tests/…/Calendar_Mock.swift) viafmt.calendar
to force “today”.
150-164
: Same determinism concern for older-date snapshotApply the same fixed locale/timezone (and no “today/yesterday” mock) to keep short-date output consistent on CI and dev machines.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (2)
Tests/StreamChatUITests/SnapshotTests/Gallery/__Snapshots__/GalleryVC_Tests/test_snapshotWithMessageTimestampOlderDate.default-light.png
is excluded by!**/*.png
Tests/StreamChatUITests/SnapshotTests/Gallery/__Snapshots__/GalleryVC_Tests/test_snapshotWithMessageTimestampToday.default-light.png
is excluded by!**/*.png
📒 Files selected for processing (6)
CHANGELOG.md
(1 hunks)Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift
(1 hunks)Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift
(1 hunks)Sources/StreamChatUI/Gallery/GalleryVC.swift
(2 hunks)StreamChat.xcodeproj/project.pbxproj
(5 hunks)Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
(4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
**/*.swift
: Respect .swiftlint.yml rules; do not suppress SwiftLint rules broadly—scope and justify any exceptions
Adhere to the project’s zero warnings policy—fix new warnings and avoid introducing any
Files:
Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift
Sources/StreamChatUI/Gallery/GalleryVC.swift
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift
Sources/{StreamChat,StreamChatUI}/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
When altering public API, update inline documentation comments in source
Files:
Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift
Sources/StreamChatUI/Gallery/GalleryVC.swift
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift
CHANGELOG.md
📄 CodeRabbit inference engine (AGENTS.md)
Update CHANGELOG for user-visible SDK changes
Files:
CHANGELOG.md
Tests/{StreamChatTests,StreamChatUITests}/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Tests/{StreamChatTests,StreamChatUITests}/**/*.swift
: Add or extend tests in the matching module’s Tests folder
Prefer using provided test fakes/mocks in tests when possible
Files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
Tests/StreamChatUITests/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Ensure tests cover view controllers and UI behaviors of StreamChatUI
Files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
🧠 Learnings (4)
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Sources/{StreamChat,StreamChatUI}/**/*.swift : When altering public API, update inline documentation comments in source
Applied to files:
CHANGELOG.md
StreamChat.xcodeproj/project.pbxproj
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to CHANGELOG.md : Update CHANGELOG for user-visible SDK changes
Applied to files:
CHANGELOG.md
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatTests/**/*.swift : Ensure tests cover core models and API surface of StreamChat
Applied to files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatUITests/**/*.swift : Ensure tests cover view controllers and UI behaviors of StreamChatUI
Applied to files:
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift
🧬 Code graph analysis (3)
Sources/StreamChatUI/Gallery/GalleryVC.swift (2)
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift (1)
format
(35-45)Sources/StreamChatUI/Appearance+Formatters/UserLastActivityFormatter.swift (1)
format
(16-18)
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift (1)
TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageImageAttachment_Mock.swift (1)
mock
(10-42)
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift (1)
Tests/StreamChatUITests/Mocks/Utils/Calendar_Mock.swift (2)
isDateInToday
(13-15)isDateInYesterday
(17-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Test Integration
- GitHub Check: Build Demo App + Example Apps
- GitHub Check: Test UI (Debug)
- GitHub Check: Test LLC (Debug)
🔇 Additional comments (12)
CHANGELOG.md (1)
12-15
: Enrich CHANGELOG: document new public API and opt‑outAdd an "Added" entry for the new public API (formatters, Appearance hook, GalleryVC flags) and a one‑liner showing how to revert; update inline documentation for the new public API.
File: CHANGELOG.md (lines 12-15)
## StreamChatUI -### 🔄 Changed -- Change gallery header view to show message timestamp instead of online status [#3818](https://github.com/GetStream/stream-chat-swift/pull/3818) +### ✅ Added +- `Appearance.Formatters.galleryHeaderViewDateFormatter` to customize gallery header timestamps. Introduces `GalleryHeaderViewDateFormatter` and `DefaultGalleryHeaderViewDateFormatter`. [#3818](https://github.com/GetStream/stream-chat-swift/pull/3818) +- `GalleryVC.showMessageTimestamp` (default `true`) and `GalleryVC.messageTimestampFormatter` for per‑screen overrides. [#3818](https://github.com/GetStream/stream-chat-swift/pull/3818) +### 🔄 Changed +- Gallery header now shows the message timestamp instead of the user's online status (parity with other SDKs). To restore the previous behavior, set `showMessageTimestamp = false`. [#3818](https://github.com/GetStream/stream-chat-swift/pull/3818)Verify symbol names before publishing:
#!/bin/bash rg -n -C2 -g '!**/Pods/**' -e '\bGalleryHeaderViewDateFormatter\b' -e '\bDefaultGalleryHeaderViewDateFormatter\b' -e '\bgalleryHeaderViewDateFormatter\b' -e '\bshowMessageTimestamp\b' -e '\bmessageTimestampFormatter\b'StreamChat.xcodeproj/project.pbxproj (5)
8955-8955
: Good group placement under Appearance+Formatters.Organizationally consistent with other formatters.
10938-10938
: Confirm target membership for this Sources entry.This should belong to StreamChatUI targets only (not core StreamChat or test bundles). If it appears twice within the same target, remove the duplicate.
Use the script in the comment for Lines 1459–1460 to see the owning target of this build-file ID.
13085-13085
: Second Sources entry — ensure it’s for a different UI target (e.g., static vs dynamic).If both this and Line 10938 resolve to the same target, dedupe one of them.
Use the ownership script from Lines 1459–1460 to confirm.
4323-4323
: PBXFileReference OK — file present and included by SPM/CocoaPodsGalleryHeaderViewDateFormatter.swift exists at Sources/StreamChatUI/Appearance+Formatters, is referenced in StreamChat.xcodeproj/project.pbxproj, StreamChatUI target in Package.swift only excludes Info.plist and Generated/L10n_template.stencil, and StreamChatUI.podspec uses Sources/StreamChatUI/**/*.swift (covers the file).
1459-1460
: Confirmed — no duplicate inclusion; each PBXBuildFile entry belongs to a different target.
AD3DB8312E7C48BF0023D377 and AD3DB8322E7C48BF0023D377 map to different PBXSourcesBuildPhase/targets (verification: OK).Sources/StreamChatUI/Appearance+Formatters/Appearance+Formatters.swift (1)
48-50
: Formatter injection for gallery header — looks goodPublic surface and docs are consistent with existing formatters.
Sources/StreamChatUI/Appearance+Formatters/GalleryHeaderViewDateFormatter.swift (1)
35-45
: Default formatting behavior is saneRelative “Today/Yesterday” else short date is a reasonable default.
Sources/StreamChatUI/Gallery/GalleryVC.swift (1)
276-288
: Branching logic is clearThe timestamp path vs. status/last-seen fallback reads well.
Tests/StreamChatUITests/SnapshotTests/Gallery/GalleryVC_Tests.swift (3)
33-33
: Keeps legacy snapshot stableDisabling timestamps in setUp preserves existing “default appearance” baseline. Good call.
129-129
: Subclassing snapshot baseline preservedExplicitly disabling timestamps here is consistent with setUp.
174-184
: Helper extension to pass createdAt — goodThis makes tests concise and targeted.
|
🔗 Issue Links
https://linear.app/stream/issue/IOS-1059/deputy-replace-a-user-status-with-a-message-date-in-the-galary
Same as GetStream/stream-chat-swiftui#962 but for UIKit
🎯 Goal
Change the gallery header view to show the message timestamp instead of online status.
This is to make it aligned with the other SDKs.
🧪 Manual Testing Notes
☑️ Contributor Checklist
docs-content
repoSummary by CodeRabbit