diff --git a/.github/workflows/merge-main-to-develop.yml b/.github/workflows/merge-main-to-develop.yml deleted file mode 100644 index 43b7da2c5..000000000 --- a/.github/workflows/merge-main-to-develop.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: "Merge main to develop" - -on: - workflow_dispatch: - -permissions: - contents: write - -jobs: - merge: - name: Merge - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4.1.1 - with: - token: ${{ secrets.ADMIN_API_TOKEN }} - fetch-depth: 0 - - - uses: ./.github/actions/ruby-cache - - - run: bundle exec fastlane merge_main - env: - GITHUB_TOKEN: ${{ secrets.ADMIN_API_TOKEN }} - - - uses: 8398a7/action-slack@v3 - if: failure() - with: - status: ${{ job.status }} - text: "⚠️ , the merge of `main` to `develop` failed on CI. Consider using this command locally: `bundle exec fastlane merge_main`" - fields: repo,commit,author,workflow - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.github/workflows/release-merge.yml b/.github/workflows/release-merge.yml index 250cab82c..01763637e 100644 --- a/.github/workflows/release-merge.yml +++ b/.github/workflows/release-merge.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: jobs: - merge-comment: + merge-release-to-main: name: Merge release to main runs-on: macos-15 if: github.event_name == 'workflow_dispatch' || (github.event.issue.pull_request && github.event.issue.state == 'open' && github.event.comment.body == '/merge release') diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index b4d6e051e..79117b350 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -26,3 +26,28 @@ jobs: MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }} run: bundle exec fastlane publish_release --verbose + + merge-main-to-develop: + name: Merge main to develop + runs-on: ubuntu-latest + needs: release + steps: + - uses: actions/checkout@v4.1.1 + with: + token: ${{ secrets.ADMIN_API_TOKEN }} + fetch-depth: 0 + + - uses: ./.github/actions/ruby-cache + + - run: bundle exec fastlane merge_main + env: + GITHUB_TOKEN: ${{ secrets.ADMIN_API_TOKEN }} + + - uses: 8398a7/action-slack@v3 + if: failure() + with: + status: ${{ job.status }} + text: "⚠️ , the merge of `main` to `develop` failed on CI. Consider using this command locally: `bundle exec fastlane merge_main`" + fields: repo,commit,author,workflow + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..7e74f389b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,86 @@ +Guidance for AI coding agents (Copilot, Cursor, Aider, Claude, etc.) working in this repository. Human readers are welcome, but this file is written for tools. + +### Repository purpose + +This repo hosts Stream’s SwiftUI Chat SDK for iOS. It builds on the core client and provides SwiftUI-first chat components (views, view models, modifiers) for messaging apps. + +Agents should optimize for API stability, backwards compatibility, accessibility, and high test coverage when changing code. + +### Tech & toolchain + • Language: Swift (SwiftUI) + • Primary distribution: Swift Package Manager (SPM), secondary CocoaPods and XCFrameworks + • Xcode: 15.x or newer (Apple Silicon supported) + • Platforms / deployment targets: Use the values set in Package.swift/podspecs; do not lower targets without approval + • CI: GitHub Actions (assume PR validation for build + tests + lint) + • Linters & docs: SwiftLint via Mint + +### Project layout (high level) + +Sources/ + StreamChatSwiftUI/ # SwiftUI views, view models, theming, utils +Tests/ + StreamChatSwiftUITests/ # Unit/UI tests for SwiftUI layer + +When editing near other packages (e.g., StreamChat or StreamChatUI), prefer extending the SwiftUI layer rather than duplicating logic from dependencies. + +### Local setup (SPM) + 1. Open the repository in Xcode (root contains Package.swift). + 2. Resolve packages. + 3. Choose an iOS Simulator (e.g., iPhone 15) and Build. + +Optional: sample/demo app + +If a sample app target exists in this repo, prefer running that to validate UI changes. Keep demo configs free of credentials and use placeholders like YOUR_STREAM_KEY. + +### Schemes + +Typical scheme names include: + • StreamChatSwiftUI + • StreamChatSwiftUITests + +Agents must query existing schemes before invoking xcodebuild. + +### Build & test commands (CLI) + +Prefer Xcode for day-to-day work; use CLI for CI parity & automation. + +Build (Debug): + +``` +xcodebuild \ + -scheme StreamChatSwiftUI \ + -destination 'platform=iOS Simulator,name=iPhone 15' \ + -configuration Debug build +``` + +Run tests: + +``` +xcodebuild \ + -scheme StreamChatSwiftUI \ + -destination 'platform=iOS Simulator,name=iPhone 15' \ + -configuration Debug test +``` + +If a Makefile or scripts exist (e.g., make build, make test, ./scripts/lint.sh), prefer those to keep parity with CI. Discover with make help and ls scripts/. + +Linting & formatting + • SwiftLint (strict): + +swiftlint --strict + + • Respect .swiftlint.yml and any repo-specific rules. Do not broadly disable rules; scope exceptions and justify in PRs. + +Public API & SemVer + • Follow semantic versioning for the SwiftUI package. + • Any public API change must include updated docs and migration notes. + • Avoid source-breaking changes. If unavoidable, add deprecations first with a transition path. + +Accessibility & UI quality + • Ensure components have accessibility labels, traits, and dynamic type support. + • Support both light/dark mode. + • When altering UI, attach before/after screenshots (or screen recordings) in PRs. + +Testing policy + • Add/extend tests in StreamChatSwiftUITests/ for: + • View models and state handling \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 847f03589..086a83ab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### 🔄 Changed +# [4.88.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.88.0) +_September 10, 2025_ + +### ✅ Added +- Add `ColorPalette.navigationBarTitle`, `ColorPalette.navigationBarSubtitle`, `ColorPalette.navigationBarTintColor`, `ColorPalette.navigationBarBackground` [#939](https://github.com/GetStream/stream-chat-swiftui/pull/939) +### 🐞 Fixed +- Long message with a link preview was truncated sometimes [#940](https://github.com/GetStream/stream-chat-swiftui/pull/940) +- Fix quoted message shown in the composer when editing a quoting message [#943](https://github.com/GetStream/stream-chat-swiftui/pull/943) +- Fix pinned messages view not using relative time formatter [#946](https://github.com/GetStream/stream-chat-swiftui/pull/946) + # [4.87.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.87.0) _September 01, 2025_ @@ -22,7 +32,7 @@ _September 01, 2025_ _August 21, 2025_ ### 🐞 Fixed -- Fix inconsistencies in gallery view displaying images and videos [927](https://github.com/GetStream/stream-chat-swiftui/pull/927) +- Fix inconsistencies in gallery view displaying images and videos [#927](https://github.com/GetStream/stream-chat-swiftui/pull/927) - Prevent audio messages increasing width in reply mode [#926](https://github.com/GetStream/stream-chat-swiftui/pull/926) # [4.85.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.85.0) diff --git a/DemoAppSwiftUI/ChannelHeader/CustomChannelHeader.swift b/DemoAppSwiftUI/ChannelHeader/CustomChannelHeader.swift index 63dd46248..3886ff4c9 100644 --- a/DemoAppSwiftUI/ChannelHeader/CustomChannelHeader.swift +++ b/DemoAppSwiftUI/ChannelHeader/CustomChannelHeader.swift @@ -30,6 +30,7 @@ public struct CustomChannelHeader: ToolbarContent { Image(uiImage: images.messageActionEdit) .resizable() .scaledToFit() + .frame(width: 24, height: 24) .foregroundColor(Color.white) .padding(.all, 8) .background(colors.tintColor) @@ -41,9 +42,12 @@ public struct CustomChannelHeader: ToolbarContent { Button { actionsPopupShown = true } label: { - StreamLazyImage(url: currentUserController.currentUser?.imageURL) - .accessibilityLabel("Account Actions") - .accessibilityAddTraits(.isButton) + StreamLazyImage( + url: currentUserController.currentUser?.imageURL, + size: CGSize(width: 36, height: 36) + ) + .accessibilityLabel("Account Actions") + .accessibilityAddTraits(.isButton) } } } @@ -62,13 +66,27 @@ struct CustomChannelModifier: ChannelListHeaderViewModifier { func body(content: Content) -> some View { ZStack { - content.toolbar { - CustomChannelHeader( - title: title, - currentUserController: chatClient.currentUserController(), - isNewChatShown: $isNewChatShown, - actionsPopupShown: $actionsPopupShown - ) + if #available(iOS 26, *) { + content.toolbar { + CustomChannelHeader( + title: title, + currentUserController: chatClient.currentUserController(), + isNewChatShown: $isNewChatShown, + actionsPopupShown: $actionsPopupShown + ) + #if compiler(>=6.2) + .sharedBackgroundVisibility(.hidden) + #endif + } + } else { + content.toolbar { + CustomChannelHeader( + title: title, + currentUserController: chatClient.currentUserController(), + isNewChatShown: $isNewChatShown, + actionsPopupShown: $actionsPopupShown + ) + } } NavigationLink(isActive: $blockedUsersShown) { diff --git a/DemoAppSwiftUI/DemoAppSwiftUIApp.swift b/DemoAppSwiftUI/DemoAppSwiftUIApp.swift index 45cfa0458..02ffe0dd2 100644 --- a/DemoAppSwiftUI/DemoAppSwiftUIApp.swift +++ b/DemoAppSwiftUI/DemoAppSwiftUIApp.swift @@ -147,19 +147,13 @@ extension AppState { guard let currentUserId = chatClient.currentUserId else { fatalError("Not logged in") } switch identifier { case .initial: + var sort: [Sorting] = [Sorting(key: .default)] + if AppConfiguration.default.isChannelPinningFeatureEnabled { + sort.insert(Sorting(key: .pinnedAt), at: 0) + } return ChannelListQuery( filter: .containMembers(userIds: [currentUserId]), - sort: [ - Sorting(key: .default) - ] - ) - case .initial where AppConfiguration.default.isChannelPinningFeatureEnabled: - return ChannelListQuery( - filter: .containMembers(userIds: [currentUserId]), - sort: [ - Sorting(key: .pinnedAt), - Sorting(key: .default) - ] + sort: sort ) case .archived: return ChannelListQuery( diff --git a/Package.swift b/Package.swift index 1d5cba5cc..6ef6af55c 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( ) ], dependencies: [ - .package(url: "https://github.com/GetStream/stream-chat-swift.git", from: "4.87.0") + .package(url: "https://github.com/GetStream/stream-chat-swift.git", from: "4.88.0") ], targets: [ .target( diff --git a/README.md b/README.md index c8ecc2b2c..a0556bb11 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

- StreamChatSwiftUI + StreamChatSwiftUI

## SwiftUI StreamChat SDK diff --git a/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/ChatChannelHeaderViewModifier.swift b/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/ChatChannelHeaderViewModifier.swift index 76add56cb..6280258a5 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/ChatChannelHeaderViewModifier.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/ChatChannelHeaderViewModifier.swift @@ -77,6 +77,7 @@ public struct DefaultChatChannelHeader: ToolbarContent { ) .offset(x: 4) } + .accentColor(colors.navigationBarTintColor) .accessibilityLabel(Text(L10n.Channel.Header.Info.title)) NavigationLink(isActive: $isActive) { @@ -108,13 +109,31 @@ public struct DefaultChannelHeaderModifier: ChatChannelHea } public func body(content: Content) -> some View { - content.toolbar { - DefaultChatChannelHeader( - factory: factory, - channel: channel, - headerImage: channelHeaderLoader.image(for: channel), - isActive: $isActive - ) + if #available(iOS 26, *) { + content + .navigationBarBackground() + .toolbar { + DefaultChatChannelHeader( + factory: factory, + channel: channel, + headerImage: channelHeaderLoader.image(for: channel), + isActive: $isActive + ) + #if compiler(>=6.2) + .sharedBackgroundVisibility(.hidden) + #endif + } + } else { + content + .navigationBarBackground() + .toolbar { + DefaultChatChannelHeader( + factory: factory, + channel: channel, + headerImage: channelHeaderLoader.image(for: channel), + isActive: $isActive + ) + } } } } @@ -145,7 +164,7 @@ public struct ChannelTitleView: View { VStack(spacing: 2) { Text(channelNamer(channel, currentUserId) ?? "") .font(fonts.bodyBold) - .foregroundColor(Color(colors.text)) + .foregroundColor(Color(colors.navigationBarTitle)) .accessibilityIdentifier("chatName") if shouldShowTypingIndicator { @@ -156,7 +175,7 @@ public struct ChannelTitleView: View { } else { Text(channel.onlineInfoText(currentUserId: currentUserId)) .font(fonts.footnote) - .foregroundColor(Color(colors.textLowEmphasis)) + .foregroundColor(Color(colors.navigationBarSubtitle)) .accessibilityIdentifier("chatOnlineInfo") } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/MessageThreadHeaderViewModifier.swift b/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/MessageThreadHeaderViewModifier.swift index 77c4fedc2..009948c46 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/MessageThreadHeaderViewModifier.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/ChannelHeader/MessageThreadHeaderViewModifier.swift @@ -18,9 +18,10 @@ public struct DefaultMessageThreadHeader: ToolbarContent { VStack { Text(L10n.Message.Actions.threadReply) .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) Text(L10n.Message.Threads.subtitle) .font(fonts.footnote) - .foregroundColor(Color(colors.textLowEmphasis)) + .foregroundColor(Color(colors.navigationBarSubtitle)) } } } @@ -29,8 +30,10 @@ public struct DefaultMessageThreadHeader: ToolbarContent { /// The default message thread header modifier. public struct DefaultMessageThreadHeaderModifier: MessageThreadHeaderViewModifier { public func body(content: Content) -> some View { - content.toolbar { - DefaultMessageThreadHeader() - } + content + .navigationBarBackground() + .toolbar { + DefaultMessageThreadHeader() + } } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatChannelInfoView.swift b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatChannelInfoView.swift index 5e8fb60b8..60aab3902 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatChannelInfoView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatChannelInfoView.swift @@ -132,13 +132,14 @@ public struct ChatChannelInfoView: View, KeyboardReadable } } } + .navigationBarBackground() .toolbar { ToolbarItem(placement: .principal) { Group { if viewModel.showSingleMemberDMView { Text(viewModel.displayedParticipants.first?.chatUser.name ?? "") .font(fonts.bodyBold) - .foregroundColor(Color(colors.text)) + .foregroundColor(Color(colors.navigationBarTitle)) } else { ChannelTitleView( channel: viewModel.channel, @@ -161,6 +162,7 @@ public struct ChatChannelInfoView: View, KeyboardReadable .background(colors.tintColor) .clipShape(Circle()) } + .accentColor(colors.navigationBarTintColor) } } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/FileAttachmentsView.swift b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/FileAttachmentsView.swift index e92387791..408dcf130 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/FileAttachmentsView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/FileAttachmentsView.swift @@ -70,7 +70,15 @@ public struct FileAttachmentsView: View { } } } - .navigationTitle(L10n.ChatInfo.Files.title) + .toolbar { + ToolbarItem(placement: .principal) { + Text(L10n.ChatInfo.Files.title) + .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) + } + } + .navigationBarBackground() + .navigationBarTitleDisplayMode(.inline) } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsView.swift b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsView.swift index 39a2a3ada..4453b60f0 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsView.swift @@ -7,6 +7,8 @@ import SwiftUI /// View displaying media attachments. public struct MediaAttachmentsView: View { + @Injected(\.colors) private var colors + @Injected(\.fonts) private var fonts @Injected(\.images) private var images @StateObject private var viewModel: MediaAttachmentsViewModel @@ -98,7 +100,15 @@ public struct MediaAttachmentsView: View { } } } - .navigationTitle(L10n.ChatInfo.Media.title) + .toolbar { + ToolbarItem(placement: .principal) { + Text(L10n.ChatInfo.Media.title) + .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) + } + } + .navigationBarBackground() + .navigationBarTitleDisplayMode(.inline) } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/PinnedMessagesView.swift b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/PinnedMessagesView.swift index f9f47e4a9..4191190b7 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/PinnedMessagesView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/PinnedMessagesView.swift @@ -7,6 +7,8 @@ import SwiftUI /// View displaying pinned messages in the chat info screen. public struct PinnedMessagesView: View { + @Injected(\.colors) private var colors + @Injected(\.fonts) private var fonts @Injected(\.images) private var images @Injected(\.utils) private var utils @Injected(\.chatClient) private var chatClient @@ -71,7 +73,15 @@ public struct PinnedMessagesView: View { ) } } - .navigationTitle(L10n.ChatInfo.PinnedMessages.title) + .toolbar { + ToolbarItem(placement: .principal) { + Text(L10n.ChatInfo.PinnedMessages.title) + .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) + } + } + .navigationBarBackground() + .navigationBarTitleDisplayMode(.inline) } private func makeMessageDestination(message: ChatMessage) -> ChatChannelView { @@ -131,7 +141,7 @@ struct PinnedMessageView: View { Spacer() SubtitleText( - text: utils.dateFormatter.string(from: message.createdAt) + text: utils.messageRelativeDateFormatter.string(from: message.createdAt) ) } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift b/Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift index 3349d48bb..dfdc25dd6 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift @@ -209,7 +209,11 @@ public struct ChatChannelView: View, KeyboardReadable { } private var generatingSnapshot: Bool { - tabBarAvailable && messageDisplayInfo != nil && !viewModel.reactionsShown + if #available(iOS 26, *) { + return false + } else { + return tabBarAvailable && messageDisplayInfo != nil && !viewModel.reactionsShown + } } private var bottomPadding: CGFloat { diff --git a/Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel.swift b/Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel.swift index 7cdb6395c..203b0ef74 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel.swift @@ -281,7 +281,13 @@ open class MessageComposerViewModel: ObservableObject { return } - fillComposer(with: message) + text = message.text + mentionedUsers = message.mentionedUsers + showReplyInChannel = message.showReplyInChannel + selectedRangeLocation = message.text.count + attachmentsConverter.attachmentsToAssets(message.allAttachments) { [weak self] assets in + self?.updateComposerAssets(assets) + } } /// Populates the draft message in the composer with the current controller's draft information. @@ -290,7 +296,15 @@ open class MessageComposerViewModel: ObservableObject { return } - fillComposer(with: ChatMessage(draft)) + let message = ChatMessage(draft) + text = message.text + mentionedUsers = message.mentionedUsers + quotedMessage?.wrappedValue = message.quotedMessage + showReplyInChannel = message.showReplyInChannel + selectedRangeLocation = message.text.count + attachmentsConverter.attachmentsToAssets(message.allAttachments) { [weak self] assets in + self?.updateComposerAssets(assets) + } } /// Updates the draft message locally and on the server. @@ -642,18 +656,6 @@ open class MessageComposerViewModel: ObservableObject { // MARK: - private - private func fillComposer(with message: ChatMessage) { - text = message.text - mentionedUsers = message.mentionedUsers - quotedMessage?.wrappedValue = message.quotedMessage - showReplyInChannel = message.showReplyInChannel - selectedRangeLocation = message.text.count - - attachmentsConverter.attachmentsToAssets(message.allAttachments) { [weak self] assets in - self?.updateComposerAssets(assets) - } - } - private func updateComposerAssets(_ assets: ComposerAssets) { addedAssets = assets.mediaAssets addedFileURLs = assets.fileAssets.map(\.url) diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/FileAttachmentPreview.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/FileAttachmentPreview.swift index cc3b989a0..2b3194e3d 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/FileAttachmentPreview.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/FileAttachmentPreview.swift @@ -8,6 +8,7 @@ import SwiftUI public struct FileAttachmentPreview: View { @Environment(\.presentationMode) var presentationMode + @Injected(\.colors) private var colors @Injected(\.fonts) private var fonts @Injected(\.images) private var images @Injected(\.utils) private var utils @@ -63,10 +64,12 @@ public struct FileAttachmentPreview: View { } } .navigationBarTitleDisplayMode(.inline) + .navigationBarBackground() .toolbar { ToolbarItem(placement: .principal) { Text(navigationTitle) .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) .lineLimit(1) } @@ -75,7 +78,9 @@ public struct FileAttachmentPreview: View { presentationMode.wrappedValue.dismiss() } label: { Image(uiImage: images.close) + .renderingMode(.template) } + .accentColor(colors.navigationBarTintColor) } } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/LinkAttachmentView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/LinkAttachmentView.swift index 1c7b5158d..a334a3be3 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/LinkAttachmentView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/LinkAttachmentView.swift @@ -46,16 +46,16 @@ public struct LinkAttachmentContainer: View { ) } - let availableWidth = width - 4 * padding - let size = message.adjustedText.frameSize(maxWidth: availableWidth) - if #available(iOS 15, *) { HStack { StreamTextView(message: message) .standardPadding() Spacer() } + .layoutPriority(1) } else { + let availableWidth = width - 4 * padding + let size = message.adjustedText.frameSize(maxWidth: availableWidth) LinkTextView( message: message, width: availableWidth, diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAllOptionsView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAllOptionsView.swift index 7c9e72936..c3c1d344b 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAllOptionsView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAllOptionsView.swift @@ -16,7 +16,7 @@ struct PollAllOptionsView: View { let factory: Factory var body: some View { - NavigationView { + NavigationContainerView(embedInNavigationView: true) { ScrollView { VStack(alignment: .leading, spacing: 32) { HStack { @@ -43,10 +43,12 @@ struct PollAllOptionsView: View { } .padding() } + .navigationBarBackground() .toolbar { ToolbarItem(placement: .principal) { Text(L10n.Message.Polls.Toolbar.optionsTitle) .bold() + .foregroundColor(Color(colors.navigationBarTitle)) } ToolbarItem(placement: .navigationBarLeading) { @@ -55,6 +57,7 @@ struct PollAllOptionsView: View { } label: { Image(systemName: "xmark") } + .accentColor(colors.navigationBarTintColor) } } .navigationBarTitleDisplayMode(.inline) diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollCommentsView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollCommentsView.swift index 8c1951b86..76a245c1c 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollCommentsView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollCommentsView.swift @@ -29,7 +29,7 @@ struct PollCommentsView: View { } var body: some View { - NavigationView { + NavigationContainerView(embedInNavigationView: true) { ScrollView { LazyVStack(alignment: .leading) { ForEach(viewModel.comments) { comment in @@ -82,10 +82,12 @@ struct PollCommentsView: View { isPresented: $viewModel.errorShown, action: viewModel.refresh ) + .navigationBarBackground() .toolbar { ToolbarItem(placement: .principal) { Text(L10n.Message.Polls.Toolbar.commentsTitle) .bold() + .foregroundColor(Color(colors.navigationBarTitle)) } ToolbarItem(placement: .navigationBarLeading) { @@ -94,6 +96,7 @@ struct PollCommentsView: View { } label: { Image(systemName: "xmark") } + .accentColor(colors.navigationBarTintColor) } } .navigationBarTitleDisplayMode(.inline) diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollOptionAllVotesView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollOptionAllVotesView.swift index c72df337d..8079daa52 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollOptionAllVotesView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollOptionAllVotesView.swift @@ -6,6 +6,7 @@ import StreamChat import SwiftUI struct PollOptionAllVotesView: View { + @Injected(\.colors) var colors @StateObject var viewModel: PollOptionAllVotesViewModel let factory: Factory @@ -35,10 +36,12 @@ struct PollOptionAllVotesView: View { isPresented: $viewModel.errorShown, action: viewModel.refresh ) + .navigationBarBackground() .toolbar { ToolbarItem(placement: .principal) { Text(viewModel.option.text) .bold() + .foregroundColor(Color(colors.navigationBarTitle)) } } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollResultsView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollResultsView.swift index 17a5d7407..5ca5c56f7 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollResultsView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollResultsView.swift @@ -18,14 +18,8 @@ struct PollResultsView: View { private let numberOfItemsShown = 5 var body: some View { - if #available(iOS 16, *) { - NavigationStack { - content - } - } else { - NavigationView { - content - } + NavigationContainerView(embedInNavigationView: true) { + content } } @@ -58,10 +52,12 @@ struct PollResultsView: View { } } .background(Color(colors.background).ignoresSafeArea()) + .navigationBarBackground() .toolbar { ToolbarItem(placement: .principal) { Text(L10n.Message.Polls.Toolbar.resultsTitle) .bold() + .foregroundColor(Color(colors.navigationBarTitle)) } ToolbarItem(placement: .navigationBarLeading) { @@ -70,6 +66,7 @@ struct PollResultsView: View { } label: { Image(systemName: "xmark") } + .accentColor(colors.navigationBarTintColor) } } .navigationBarTitleDisplayMode(.inline) diff --git a/Sources/StreamChatSwiftUI/ChatChannel/Polls/CreatePollView.swift b/Sources/StreamChatSwiftUI/ChatChannel/Polls/CreatePollView.swift index 4e985af9c..56eb04778 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/Polls/CreatePollView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/Polls/CreatePollView.swift @@ -56,7 +56,7 @@ public struct CreatePollView: View { } public var body: some View { - NavigationView { + NavigationContainerView(embedInNavigationView: true) { List { VStack(alignment: .leading, spacing: 8) { Text(L10n.Composer.Polls.question) @@ -164,6 +164,7 @@ public struct CreatePollView: View { .background(Color(colors.background).ignoresSafeArea()) .listStyle(.plain) .id(listId) + .navigationBarBackground() .toolbar { ToolbarItem(placement: .cancellationAction) { Button { @@ -175,11 +176,13 @@ public struct CreatePollView: View { } label: { Text(L10n.Alert.Actions.cancel) } + .accentColor(colors.navigationBarTintColor) } ToolbarItem(placement: .principal) { Text(L10n.Composer.Polls.createPoll) .bold() + .foregroundColor(Color(colors.navigationBarTitle)) } ToolbarItem(placement: .navigationBarTrailing) { @@ -191,6 +194,7 @@ public struct CreatePollView: View { Image(systemName: "paperplane.fill") .foregroundColor(colors.tintColor) } + .accentColor(colors.navigationBarTintColor) .disabled(!viewModel.canCreatePoll) } } diff --git a/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListHeader.swift b/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListHeader.swift index be95a5d96..f06a1632c 100644 --- a/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListHeader.swift +++ b/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListHeader.swift @@ -11,6 +11,7 @@ public protocol ChannelListHeaderViewModifier: ViewModifier { /// The default channel list header. public struct DefaultChatChannelListHeader: ToolbarContent { + @Injected(\.colors) private var colors @Injected(\.fonts) private var fonts @Injected(\.images) private var images @@ -24,6 +25,7 @@ public struct DefaultChatChannelListHeader: ToolbarContent { ToolbarItem(placement: .principal) { Text(title) .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) } } } @@ -40,5 +42,6 @@ public struct DefaultChannelListHeaderModifier: ChannelListHeaderViewModifier { content.toolbar { DefaultChatChannelListHeader(title: title) } + .navigationBarBackground() } } diff --git a/Sources/StreamChatSwiftUI/ChatChannelList/MoreChannelActionsFullScreenWrappingView.swift b/Sources/StreamChatSwiftUI/ChatChannelList/MoreChannelActionsFullScreenWrappingView.swift index 5922ce602..c739ee97d 100644 --- a/Sources/StreamChatSwiftUI/ChatChannelList/MoreChannelActionsFullScreenWrappingView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannelList/MoreChannelActionsFullScreenWrappingView.swift @@ -7,15 +7,17 @@ import SwiftUI /// Default wrapping view for the channel more actions full screen presented view. struct MoreChannelActionsFullScreenWrappingView: View { + @Injected(\.colors) private var colors @Injected(\.images) private var images let presentedView: AnyView let onDismiss: () -> Void public var body: some View { - NavigationView { + NavigationContainerView(embedInNavigationView: true) { presentedView .navigationBarTitleDisplayMode(.inline) + .navigationBarBackground() .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button { @@ -25,6 +27,7 @@ struct MoreChannelActionsFullScreenWrappingView: View { .customizable() .frame(height: 16) } + .accentColor(colors.navigationBarTintColor) } } } diff --git a/Sources/StreamChatSwiftUI/ChatThreadList/ChatThreadListHeaderViewModifier.swift b/Sources/StreamChatSwiftUI/ChatThreadList/ChatThreadListHeaderViewModifier.swift index 5b7bf0120..1edcd6af6 100644 --- a/Sources/StreamChatSwiftUI/ChatThreadList/ChatThreadListHeaderViewModifier.swift +++ b/Sources/StreamChatSwiftUI/ChatThreadList/ChatThreadListHeaderViewModifier.swift @@ -5,6 +5,7 @@ import SwiftUI struct ChatThreadListHeaderViewModifier: ViewModifier { + @Injected(\.colors) private var colors @Injected(\.fonts) private var fonts let title: String @@ -12,10 +13,12 @@ struct ChatThreadListHeaderViewModifier: ViewModifier { func body(content: Content) -> some View { content .navigationBarTitleDisplayMode(.inline) + .navigationBarBackground() .toolbar { ToolbarItem(placement: .principal) { Text(title) .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) } } } diff --git a/Sources/StreamChatSwiftUI/ColorPalette.swift b/Sources/StreamChatSwiftUI/ColorPalette.swift index 816008426..ec883090c 100644 --- a/Sources/StreamChatSwiftUI/ColorPalette.swift +++ b/Sources/StreamChatSwiftUI/ColorPalette.swift @@ -8,9 +8,14 @@ import UIKit /// Provides the colors used throughout the SDK. public struct ColorPalette { public init() { - // Public init. + navigationBarTitle = text + navigationBarSubtitle = textLowEmphasis + navigationBarTintColor = tintColor } + /// Tint color used in UI components. + /// + /// - SeeAlso: ``navigationBarTintColor`` public var tintColor: Color = .accentColor // MARK: - Text @@ -87,6 +92,20 @@ public struct ColorPalette { public lazy var composerInputBackground: UIColor = background public lazy var composerInputHighlightedBorder: UIColor = innerBorder + // MARK: - Navigation Bar + + public var navigationBarTitle: UIColor { + didSet { + let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: navigationBarTitle] + UINavigationBar.appearance().titleTextAttributes = attributes + UINavigationBar.appearance().largeTitleTextAttributes = attributes + } + } + + public var navigationBarSubtitle: UIColor + public var navigationBarTintColor: Color + public var navigationBarBackground: UIColor? + // MARK: - Threads public var bannerBackgroundColor: UIColor = .streamDarkGray diff --git a/Sources/StreamChatSwiftUI/CommonViews/GalleryHeaderView.swift b/Sources/StreamChatSwiftUI/CommonViews/GalleryHeaderView.swift index bb577623c..0bdb96200 100644 --- a/Sources/StreamChatSwiftUI/CommonViews/GalleryHeaderView.swift +++ b/Sources/StreamChatSwiftUI/CommonViews/GalleryHeaderView.swift @@ -27,7 +27,7 @@ struct GalleryHeaderView: View { .frame(height: 16) } .padding() - .foregroundColor(Color(colors.text)) + .foregroundColor(closeImageColor) Spacer() } @@ -35,10 +35,30 @@ struct GalleryHeaderView: View { VStack { Text(title) .font(fonts.bodyBold) + .foregroundColor(Color(colors.navigationBarTitle)) Text(subtitle) .font(fonts.footnote) - .foregroundColor(Color(colors.textLowEmphasis)) + .foregroundColor(Color(colors.navigationBarSubtitle)) } } + .modifier(GalleryHeaderViewAppearanceViewModifier()) + } + + private var closeImageColor: Color { + // Note that default design uses `text` color + guard colors.navigationBarTintColor != colors.tintColor else { return Color(colors.text) } + return colors.navigationBarTintColor + } +} + +private struct GalleryHeaderViewAppearanceViewModifier: ViewModifier { + @Injected(\.colors) var colors + + func body(content: Content) -> some View { + if let backgroundColor = colors.navigationBarBackground { + content.background(Color(backgroundColor).edgesIgnoringSafeArea(.top)) + } else { + content + } } } diff --git a/Sources/StreamChatSwiftUI/CommonViews/NavigationBarBackgroundViewModifier.swift b/Sources/StreamChatSwiftUI/CommonViews/NavigationBarBackgroundViewModifier.swift new file mode 100644 index 000000000..4c87cb553 --- /dev/null +++ b/Sources/StreamChatSwiftUI/CommonViews/NavigationBarBackgroundViewModifier.swift @@ -0,0 +1,27 @@ +// +// Copyright © 2025 Stream.io Inc. All rights reserved. +// + +import SwiftUI + +extension View { + /// Sets background color to navigation bar if ``ColorPalette.navigationBarBackground`` is set. + func navigationBarBackground() -> some View { + modifier(NavigationBarBackgroundViewModifier()) + } +} + +private struct NavigationBarBackgroundViewModifier: ViewModifier { + @Injected(\.colors) var colors + + func body(content: Content) -> some View { + if #available(iOS 16.0, *), let background = colors.navigationBarBackground { + content + .toolbarBackground(Color(background), for: .navigationBar) + .toolbarBackground(.visible, for: .navigationBar) + + } else { + content + } + } +} diff --git a/Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift b/Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift index 27d20863c..30e96c452 100644 --- a/Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift +++ b/Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift @@ -7,5 +7,5 @@ import Foundation enum SystemEnvironment { /// A Stream Chat version. - public static let version: String = "4.87.0" + public static let version: String = "4.88.0" } diff --git a/Sources/StreamChatSwiftUI/Info.plist b/Sources/StreamChatSwiftUI/Info.plist index 93c8c9227..12e090b0a 100644 --- a/Sources/StreamChatSwiftUI/Info.plist +++ b/Sources/StreamChatSwiftUI/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 4.87.0 + 4.88.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPhotoLibraryUsageDescription diff --git a/Sources/StreamChatSwiftUI/Utils/NavigationContainerView.swift b/Sources/StreamChatSwiftUI/Utils/NavigationContainerView.swift index c0d8570c3..59882a345 100644 --- a/Sources/StreamChatSwiftUI/Utils/NavigationContainerView.swift +++ b/Sources/StreamChatSwiftUI/Utils/NavigationContainerView.swift @@ -6,6 +6,7 @@ import SwiftUI /// Reusable container view to handle the navigation container logic. struct NavigationContainerView: View { + @Injected(\.colors) var colors var embedInNavigationView: Bool var content: () -> Content @@ -14,10 +15,14 @@ struct NavigationContainerView: View { if #available(iOS 16, *), isIphone { NavigationStack { content() + .accentColor(colors.tintColor) + .navigationBarBackground() } } else { NavigationView { content() + .accentColor(colors.tintColor) + .navigationBarBackground() } } } else { diff --git a/StreamChatSwiftUI-XCFramework.podspec b/StreamChatSwiftUI-XCFramework.podspec index 3c37a188b..6ff41172e 100644 --- a/StreamChatSwiftUI-XCFramework.podspec +++ b/StreamChatSwiftUI-XCFramework.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'StreamChatSwiftUI-XCFramework' - spec.version = '4.87.0' + spec.version = '4.88.0' spec.summary = 'StreamChat SwiftUI Chat Components' spec.description = 'StreamChatSwiftUI SDK offers flexible SwiftUI components able to display data provided by StreamChat SDK.' @@ -19,7 +19,7 @@ Pod::Spec.new do |spec| spec.framework = 'Foundation', 'UIKit', 'SwiftUI' - spec.dependency 'StreamChat-XCFramework', '~> 4.87.0' + spec.dependency 'StreamChat-XCFramework', '~> 4.88.0' spec.cocoapods_version = '>= 1.11.0' end diff --git a/StreamChatSwiftUI.podspec b/StreamChatSwiftUI.podspec index 005f3f361..3d6040950 100644 --- a/StreamChatSwiftUI.podspec +++ b/StreamChatSwiftUI.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'StreamChatSwiftUI' - spec.version = '4.87.0' + spec.version = '4.88.0' spec.summary = 'StreamChat SwiftUI Chat Components' spec.description = 'StreamChatSwiftUI SDK offers flexible SwiftUI components able to display data provided by StreamChat SDK.' @@ -19,5 +19,5 @@ Pod::Spec.new do |spec| spec.framework = 'Foundation', 'UIKit', 'SwiftUI' - spec.dependency 'StreamChat', '~> 4.87.0' + spec.dependency 'StreamChat', '~> 4.88.0' end diff --git a/StreamChatSwiftUI.xcodeproj/project.pbxproj b/StreamChatSwiftUI.xcodeproj/project.pbxproj index fbe53bc56..0dcc874c7 100644 --- a/StreamChatSwiftUI.xcodeproj/project.pbxproj +++ b/StreamChatSwiftUI.xcodeproj/project.pbxproj @@ -11,7 +11,9 @@ 402C54492B6AAC0100672BFB /* StreamChatSwiftUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8465FBB52746873A00AF091E /* StreamChatSwiftUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4F03F18F2E0140C6001C71A2 /* ChannelAvatarsMerger_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F03F18E2E0140C6001C71A2 /* ChannelAvatarsMerger_Tests.swift */; }; 4F077EF82C85E05700F06D83 /* DelayedRenderingViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F077EF72C85E05700F06D83 /* DelayedRenderingViewModifier.swift */; }; + 4F0B67C92E7025B6003DA844 /* GalleryHeaderView_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F0B67C82E7025B6003DA844 /* GalleryHeaderView_Tests.swift */; }; 4F198FDD2C0480EC00148F49 /* Publisher+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F198FDC2C0480EC00148F49 /* Publisher+Extensions.swift */; }; + 4F3536942E6EFB510046678E /* NavigationBarBackgroundViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3536932E6EFB4B0046678E /* NavigationBarBackgroundViewModifier.swift */; }; 4F65F1862D06EEA7009F69A8 /* ChooseChannelQueryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F65F1852D06EEA5009F69A8 /* ChooseChannelQueryView.swift */; }; 4F65F18A2D071798009F69A8 /* ChannelListQueryIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F65F1892D071798009F69A8 /* ChannelListQueryIdentifier.swift */; }; 4F6D83352C0F05040098C298 /* PollCommentsViewModel_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F6D83342C0F05040098C298 /* PollCommentsViewModel_Tests.swift */; }; @@ -615,7 +617,9 @@ 4A65451E274BA170003C5FA8 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 4F03F18E2E0140C6001C71A2 /* ChannelAvatarsMerger_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelAvatarsMerger_Tests.swift; sourceTree = ""; }; 4F077EF72C85E05700F06D83 /* DelayedRenderingViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelayedRenderingViewModifier.swift; sourceTree = ""; }; + 4F0B67C82E7025B6003DA844 /* GalleryHeaderView_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryHeaderView_Tests.swift; sourceTree = ""; }; 4F198FDC2C0480EC00148F49 /* Publisher+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Publisher+Extensions.swift"; sourceTree = ""; }; + 4F3536932E6EFB4B0046678E /* NavigationBarBackgroundViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarBackgroundViewModifier.swift; sourceTree = ""; }; 4F65F1852D06EEA5009F69A8 /* ChooseChannelQueryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooseChannelQueryView.swift; sourceTree = ""; }; 4F65F1892D071798009F69A8 /* ChannelListQueryIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelListQueryIdentifier.swift; sourceTree = ""; }; 4F6D83342C0F05040098C298 /* PollCommentsViewModel_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollCommentsViewModel_Tests.swift; sourceTree = ""; }; @@ -1223,6 +1227,7 @@ isa = PBXGroup; children = ( 4F6D83532C1094220098C298 /* AlertBannerViewModifier_Tests.swift */, + 4F0B67C82E7025B6003DA844 /* GalleryHeaderView_Tests.swift */, ); path = CommonViews; sourceTree = ""; @@ -1756,19 +1761,20 @@ 8465FCF92746A95600AF091E /* CommonViews */ = { isa = PBXGroup; children = ( + ADE0F5652CB962470053B8B9 /* ActionBannerView.swift */, 8465FCFA2746A95600AF091E /* ActionItemView.swift */, 4F6D83502C1079A00098C298 /* AlertBannerViewModifier.swift */, - ADE0F5652CB962470053B8B9 /* ActionBannerView.swift */, - ADE0F55F2CB846EC0053B8B9 /* FloatingBannerViewModifier.swift */, 4F077EF72C85E05700F06D83 /* DelayedRenderingViewModifier.swift */, 84AB7B1C2771F4AA00631A10 /* DiscardButtonView.swift */, + 4F3536932E6EFB4B0046678E /* NavigationBarBackgroundViewModifier.swift */, + ADE0F55F2CB846EC0053B8B9 /* FloatingBannerViewModifier.swift */, 84F2908D276B92A40045472D /* GalleryHeaderView.swift */, 8465FD4B2746A95600AF091E /* LoadingView.swift */, 844EF8EC2809AACD00CC82F9 /* NoContentView.swift */, 8421BCED27A43E14000F977D /* SearchBar.swift */, + AD3AB65B2CB730090014D4D7 /* Shimmer.swift */, 8434E582277088D9001E1B83 /* TitleWithCloseButton.swift */, 846608E2278C303800D3D7B3 /* TypingIndicatorView.swift */, - AD3AB65B2CB730090014D4D7 /* Shimmer.swift */, ); path = CommonViews; sourceTree = ""; @@ -2936,6 +2942,7 @@ 82D64C0A2AD7E5B700C5C79E /* LinkedList.swift in Sources */, 84E6EC27279B0C930017207B /* ReactionsUsersView.swift in Sources */, 82D64BEC2AD7E5B700C5C79E /* OperationTask.swift in Sources */, + 4F3536942E6EFB510046678E /* NavigationBarBackgroundViewModifier.swift in Sources */, 82D64C132AD7E5B700C5C79E /* ImageDecoding.swift in Sources */, 8465FDA92746A95700AF091E /* AutoLayoutHelpers.swift in Sources */, 8465FDC32746A95700AF091E /* ChatChannelListHeader.swift in Sources */, @@ -3069,6 +3076,7 @@ 8423C346277D9BFF0092DCF1 /* TestCommandsConfig.swift in Sources */, 84B2B5D82819778D00479CEE /* FileAttachmentsViewModel_Tests.swift in Sources */, 4F6D83352C0F05040098C298 /* PollCommentsViewModel_Tests.swift in Sources */, + 4F0B67C92E7025B6003DA844 /* GalleryHeaderView_Tests.swift in Sources */, 841B2EF6278F108700ED619E /* MessageReadIndicatorView_Tests.swift in Sources */, 84CC3732290B0A4000689B73 /* StreamChatModel.xcdatamodeld in Sources */, 84E04790284A444E00BAFA17 /* CDNClient_Mock.swift in Sources */, @@ -3912,7 +3920,7 @@ repositoryURL = "https://github.com/GetStream/stream-chat-swift.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 4.87.0; + minimumVersion = 4.88.0; }; }; E3A1C01A282BAC66002D1E26 /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = { diff --git a/StreamChatSwiftUIArtifacts.json b/StreamChatSwiftUIArtifacts.json index 17587a6f3..6853d55e2 100644 --- a/StreamChatSwiftUIArtifacts.json +++ b/StreamChatSwiftUIArtifacts.json @@ -1 +1 @@ -{"4.40.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.40.0/StreamChatSwiftUI.zip","4.41.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.41.0/StreamChatSwiftUI.zip","4.42.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.42.0/StreamChatSwiftUI.zip","4.43.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.43.0/StreamChatSwiftUI.zip","4.44.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.44.0/StreamChatSwiftUI.zip","4.45.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.45.0/StreamChatSwiftUI.zip","4.46.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.46.0/StreamChatSwiftUI.zip","4.47.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.47.0/StreamChatSwiftUI.zip","4.47.1":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.47.1/StreamChatSwiftUI.zip","4.48.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.48.0/StreamChatSwiftUI.zip","4.49.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.49.0/StreamChatSwiftUI.zip","4.50.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.50.0/StreamChatSwiftUI.zip","4.50.1":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.50.1/StreamChatSwiftUI.zip","4.51.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.51.0/StreamChatSwiftUI.zip","4.52.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.52.0/StreamChatSwiftUI.zip","4.53.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.53.0/StreamChatSwiftUI.zip","4.54.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.54.0/StreamChatSwiftUI.zip","4.55.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.55.0/StreamChatSwiftUI.zip","4.56.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.56.0/StreamChatSwiftUI.zip","4.57.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.57.0/StreamChatSwiftUI.zip","4.58.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.58.0/StreamChatSwiftUI.zip","4.59.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.59.0/StreamChatSwiftUI.zip","4.60.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.60.0/StreamChatSwiftUI.zip","4.61.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.61.0/StreamChatSwiftUI.zip","4.62.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.62.0/StreamChatSwiftUI.zip","4.63.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.63.0/StreamChatSwiftUI.zip","4.64.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.64.0/StreamChatSwiftUI.zip","4.65.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.65.0/StreamChatSwiftUI.zip","4.66.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.66.0/StreamChatSwiftUI.zip","4.67.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.67.0/StreamChatSwiftUI.zip","4.68.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.68.0/StreamChatSwiftUI.zip","4.69.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.69.0/StreamChatSwiftUI.zip","4.70.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.70.0/StreamChatSwiftUI.zip","4.71.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.71.0/StreamChatSwiftUI.zip","4.72.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.72.0/StreamChatSwiftUI.zip","4.73.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.73.0/StreamChatSwiftUI.zip","4.74.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.74.0/StreamChatSwiftUI.zip","4.75.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.75.0/StreamChatSwiftUI.zip","4.76.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.76.0/StreamChatSwiftUI.zip","4.77.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.77.0/StreamChatSwiftUI.zip","4.78.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.78.0/StreamChatSwiftUI.zip","4.79.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.79.0/StreamChatSwiftUI.zip","4.79.1":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.79.1/StreamChatSwiftUI.zip","4.80.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.80.0/StreamChatSwiftUI.zip","4.81.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.81.0/StreamChatSwiftUI.zip","4.82.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.82.0/StreamChatSwiftUI.zip","4.83.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.83.0/StreamChatSwiftUI.zip","4.84.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.84.0/StreamChatSwiftUI.zip","4.85.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.85.0/StreamChatSwiftUI.zip","4.86.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.86.0/StreamChatSwiftUI.zip","4.87.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.87.0/StreamChatSwiftUI.zip"} \ No newline at end of file +{"4.40.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.40.0/StreamChatSwiftUI.zip","4.41.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.41.0/StreamChatSwiftUI.zip","4.42.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.42.0/StreamChatSwiftUI.zip","4.43.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.43.0/StreamChatSwiftUI.zip","4.44.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.44.0/StreamChatSwiftUI.zip","4.45.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.45.0/StreamChatSwiftUI.zip","4.46.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.46.0/StreamChatSwiftUI.zip","4.47.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.47.0/StreamChatSwiftUI.zip","4.47.1":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.47.1/StreamChatSwiftUI.zip","4.48.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.48.0/StreamChatSwiftUI.zip","4.49.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.49.0/StreamChatSwiftUI.zip","4.50.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.50.0/StreamChatSwiftUI.zip","4.50.1":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.50.1/StreamChatSwiftUI.zip","4.51.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.51.0/StreamChatSwiftUI.zip","4.52.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.52.0/StreamChatSwiftUI.zip","4.53.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.53.0/StreamChatSwiftUI.zip","4.54.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.54.0/StreamChatSwiftUI.zip","4.55.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.55.0/StreamChatSwiftUI.zip","4.56.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.56.0/StreamChatSwiftUI.zip","4.57.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.57.0/StreamChatSwiftUI.zip","4.58.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.58.0/StreamChatSwiftUI.zip","4.59.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.59.0/StreamChatSwiftUI.zip","4.60.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.60.0/StreamChatSwiftUI.zip","4.61.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.61.0/StreamChatSwiftUI.zip","4.62.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.62.0/StreamChatSwiftUI.zip","4.63.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.63.0/StreamChatSwiftUI.zip","4.64.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.64.0/StreamChatSwiftUI.zip","4.65.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.65.0/StreamChatSwiftUI.zip","4.66.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.66.0/StreamChatSwiftUI.zip","4.67.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.67.0/StreamChatSwiftUI.zip","4.68.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.68.0/StreamChatSwiftUI.zip","4.69.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.69.0/StreamChatSwiftUI.zip","4.70.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.70.0/StreamChatSwiftUI.zip","4.71.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.71.0/StreamChatSwiftUI.zip","4.72.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.72.0/StreamChatSwiftUI.zip","4.73.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.73.0/StreamChatSwiftUI.zip","4.74.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.74.0/StreamChatSwiftUI.zip","4.75.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.75.0/StreamChatSwiftUI.zip","4.76.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.76.0/StreamChatSwiftUI.zip","4.77.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.77.0/StreamChatSwiftUI.zip","4.78.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.78.0/StreamChatSwiftUI.zip","4.79.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.79.0/StreamChatSwiftUI.zip","4.79.1":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.79.1/StreamChatSwiftUI.zip","4.80.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.80.0/StreamChatSwiftUI.zip","4.81.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.81.0/StreamChatSwiftUI.zip","4.82.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.82.0/StreamChatSwiftUI.zip","4.83.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.83.0/StreamChatSwiftUI.zip","4.84.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.84.0/StreamChatSwiftUI.zip","4.85.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.85.0/StreamChatSwiftUI.zip","4.86.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.86.0/StreamChatSwiftUI.zip","4.87.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.87.0/StreamChatSwiftUI.zip","4.88.0":"https://github.com/GetStream/stream-chat-swiftui/releases/download/4.88.0/StreamChatSwiftUI.zip"} \ No newline at end of file diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/ChatChannelInfoView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/ChatChannelInfoView_Tests.swift index 10629161e..84464a9a4 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/ChatChannelInfoView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/ChatChannelInfoView_Tests.swift @@ -10,6 +10,31 @@ import SwiftUI import XCTest class ChatChannelInfoView_Tests: StreamChatTestCase { + func test_chatChannelInfoView_navigationBarAppearance() { + // Given + customizedNavigationBarAppearance() + let members = ChannelInfoMockUtils.setupMockMembers( + count: 8, + currentUserId: chatClient.currentUserId!, + onlineUserIndexes: [0, 1] + ) + let channel = ChatChannel.mock( + cid: .unique, + name: "Test Group", + ownCapabilities: [.deleteChannel, .updateChannel, .updateChannelMembers], + lastActiveMembers: members, + memberCount: members.count + ) + + // When + let view = NavigationContainerView(embedInNavigationView: true) { + ChatChannelInfoView(channel: channel) + }.applyDefaultSize() + + // Then + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } + func test_chatChannelInfoView_directChannelOfflineSnapshot() { // Given let members = ChannelInfoMockUtils.setupMockMembers( diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentPreview_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentPreview_Tests.swift index d1b7c997c..fd57407fa 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentPreview_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentPreview_Tests.swift @@ -17,4 +17,15 @@ class FileAttachmentPreview_Tests: StreamChatTestCase { assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) } + + func test_fileAttachmentPreview_navigationBarAppearance() { + customizedNavigationBarAppearance() + + let view = FileAttachmentPreview( + title: "Document title", + url: URL.localYodaQuote + ).applyDefaultSize() + + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } } diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentsView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentsView_Tests.swift index 9d11b0be0..64e9c62fb 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentsView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/FileAttachmentsView_Tests.swift @@ -67,4 +67,24 @@ class FileAttachmentsView_Tests: StreamChatTestCase { // Then assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) } + + func test_fileAttachmentsView_themedSnapshot() { + // Given + customizedNavigationBarAppearance() + let messages = ChannelInfoMockUtils.generateMessagesWithFileAttachments(count: 20) + let messageSearchController = ChatMessageSearchController_Mock.mock(client: chatClient) + messageSearchController.messages_mock = messages + let viewModel = FileAttachmentsViewModel( + channel: .mockDMChannel(), + messageSearchController: messageSearchController + ) + + // When + let view = NavigationContainerView(embedInNavigationView: true) { + FileAttachmentsView(viewModel: viewModel) + }.applyDefaultSize() + + // Then + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } } diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/MediaAttachmentsView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/MediaAttachmentsView_Tests.swift index 3fe637f2e..6c8e8763c 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/MediaAttachmentsView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/MediaAttachmentsView_Tests.swift @@ -57,4 +57,27 @@ class MediaAttachmentsView_Tests: StreamChatTestCase { // Then assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) } + + func test_mediaAttachmentsView_themedSnapshot() { + // Given + customizedNavigationBarAppearance() + let messages = ChannelInfoMockUtils.generateMessagesWithAttachments( + withImages: 10, + withVideos: 5 + ) + let messageSearchController = ChatMessageSearchController_Mock.mock(client: chatClient) + messageSearchController.messages_mock = messages + let viewModel = MediaAttachmentsViewModel( + channel: .mockDMChannel(), + messageSearchController: messageSearchController + ) + + // When + let view = NavigationContainerView(embedInNavigationView: true) { + MediaAttachmentsView(viewModel: viewModel) + }.applyDefaultSize() + + // Then + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } } diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/PinnedMessagesView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/PinnedMessagesView_Tests.swift index 959c7b486..50a86df04 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/PinnedMessagesView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/PinnedMessagesView_Tests.swift @@ -113,6 +113,22 @@ class PinnedMessagesView_Tests: StreamChatTestCase { // Then AssertSnapshot(view, size: defaultScreenSize) } + + func test_pinnedMessagesView_themedSnapshot() { + // Given + customizedNavigationBarAppearance() + let channel = ChatChannel.mockDMChannel( + pinnedMessages: [ChannelInfoMockUtils.pinnedMessage] + ) + + // When + let view = NavigationContainerView(embedInNavigationView: true) { + PinnedMessagesView(channel: channel) + }.applyDefaultSize() + + // Then + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } } // Temp solution for failing tests. diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/ChatChannelInfoView_Tests/test_chatChannelInfoView_navigationBarAppearance.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/ChatChannelInfoView_Tests/test_chatChannelInfoView_navigationBarAppearance.1.png new file mode 100644 index 000000000..d3eeb6fa4 Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/ChatChannelInfoView_Tests/test_chatChannelInfoView_navigationBarAppearance.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentPreview_Tests/test_fileAttachmentPreview_navigationBarAppearance.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentPreview_Tests/test_fileAttachmentPreview_navigationBarAppearance.1.png new file mode 100644 index 000000000..17eba6b10 Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentPreview_Tests/test_fileAttachmentPreview_navigationBarAppearance.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentPreview_Tests/test_fileAttachmentPreview_pdf.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentPreview_Tests/test_fileAttachmentPreview_pdf.1.png index 30822789e..069475f5a 100644 Binary files a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentPreview_Tests/test_fileAttachmentPreview_pdf.1.png and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentPreview_Tests/test_fileAttachmentPreview_pdf.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentsView_Tests/test_fileAttachmentsView_themedSnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentsView_Tests/test_fileAttachmentsView_themedSnapshot.1.png new file mode 100644 index 000000000..164db0985 Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/FileAttachmentsView_Tests/test_fileAttachmentsView_themedSnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/MediaAttachmentsView_Tests/test_mediaAttachmentsView_themedSnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/MediaAttachmentsView_Tests/test_mediaAttachmentsView_themedSnapshot.1.png new file mode 100644 index 000000000..88abe2a43 Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/MediaAttachmentsView_Tests/test_mediaAttachmentsView_themedSnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_imageSnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_imageSnapshot.1.png index 2ef661be7..0fe1c5236 100644 Binary files a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_imageSnapshot.1.png and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_imageSnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_notEmptySnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_notEmptySnapshot.1.png index d481c0026..abca2da13 100644 Binary files a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_notEmptySnapshot.1.png and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_notEmptySnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_pollSnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_pollSnapshot.1.png index 8fa18d02e..8432cc8fe 100644 Binary files a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_pollSnapshot.1.png and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_pollSnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_themedSnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_themedSnapshot.1.png new file mode 100644 index 000000000..6e4245d4f Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_themedSnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_videoSnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_videoSnapshot.1.png index d29488364..f4abc26ae 100644 Binary files a/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_videoSnapshot.1.png and b/StreamChatSwiftUITests/Tests/ChatChannel/ChannelInfo/__Snapshots__/PinnedMessagesView_Tests/test_pinnedMessagesView_videoSnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/ChatChannelView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/ChatChannelView_Tests.swift index 0ea0793c5..6b231c0d8 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/ChatChannelView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/ChatChannelView_Tests.swift @@ -133,4 +133,43 @@ class ChatChannelView_Tests: StreamChatTestCase { // Then assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) } + + func test_chatChannelView_customizedNavigationBar_snapshot() { + // Given + customizedNavigationBarAppearance() + let controller = ChatChannelController_Mock.mock( + channelQuery: .init(cid: .unique), + channelListQuery: nil, + client: chatClient + ) + let mockChannel = ChatChannel.mock(cid: .unique, name: "Test channel") + var messages = [ChatMessage]() + for i in 0..<15 { + messages.append( + ChatMessage.mock( + id: .unique, + cid: mockChannel.cid, + text: "Test \(i)", + author: .mock(id: .unique, name: "Martin") + ) + ) + } + controller.simulateInitial(channel: mockChannel, messages: messages, state: .remoteDataFetched) + + // When + let view = NavigationView { + ScrollView { + ChatChannelView( + viewFactory: DefaultViewFactory.shared, + channelController: controller + ) + .frame(width: defaultScreenSize.width, height: defaultScreenSize.height - 64) + } + .navigationBarTitleDisplayMode(.inline) + } + .applyDefaultSize() + + // Then + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } } diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/CreatePollView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/CreatePollView_Tests.swift index 1ec6417c0..1a1ea7d5a 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/CreatePollView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/CreatePollView_Tests.swift @@ -82,4 +82,17 @@ final class CreatePollView_Tests: StreamChatTestCase { // Then AssertSnapshot(view, variants: .onlyUserInterfaceStyles) } + + func test_createPollView_customizedNavigationBarSnapshot() { + // Given + customizedNavigationBarAppearance() + let view = CreatePollView( + chatController: .init(channelQuery: .init(cid: .unique), channelListQuery: nil, client: chatClient), + messageController: nil + ) + .applyDefaultSize() + + // Then + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } } diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerView_Tests.swift index 2d4a3ba02..ddf3fe295 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerView_Tests.swift @@ -647,6 +647,22 @@ class MessageComposerView_Tests: StreamChatTestCase { AssertSnapshot(view, variants: [.defaultLight], size: size) } + func test_composerView_editingMessageWithQuotedMessage() { + let size = CGSize(width: defaultScreenSize.width, height: 100) + let mockEditedMessage = ChatMessage.mock( + id: .unique, + cid: .unique, + text: "This is a message being edited", + author: .mock(id: .unique), + quotedMessage: .mock(text: "Should not appear") + ) + + let view = makeComposerViewWithEditedMessage(mockEditedMessage) + .frame(width: size.width, height: size.height) + + AssertSnapshot(view, variants: [.defaultLight], size: size) + } + func test_composerView_editingMessageWithImageAttachment() throws { let size = CGSize(width: defaultScreenSize.width, height: 200) let mockEditedMessage = ChatMessage.mock( diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/ChatChannelHeader_Tests/test_channelTitleView_theme_snapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/ChatChannelHeader_Tests/test_channelTitleView_theme_snapshot.1.png index 6c198bafe..56a848615 100644 Binary files a/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/ChatChannelHeader_Tests/test_channelTitleView_theme_snapshot.1.png and b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/ChatChannelHeader_Tests/test_channelTitleView_theme_snapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/ChatChannelView_Tests/test_chatChannelView_customizedNavigationBar_snapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/ChatChannelView_Tests/test_chatChannelView_customizedNavigationBar_snapshot.1.png new file mode 100644 index 000000000..7d491341c Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/ChatChannelView_Tests/test_chatChannelView_customizedNavigationBar_snapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/CreatePollView_Tests/test_createPollView_customizedNavigationBarSnapshot.1.png b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/CreatePollView_Tests/test_createPollView_customizedNavigationBarSnapshot.1.png new file mode 100644 index 000000000..3514e6a87 Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/CreatePollView_Tests/test_createPollView_customizedNavigationBarSnapshot.1.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageComposerView_Tests/test_composerView_editingMessageWithQuotedMessage.default-light.png b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageComposerView_Tests/test_composerView_editingMessageWithQuotedMessage.default-light.png new file mode 100644 index 000000000..d7c9666ed Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageComposerView_Tests/test_composerView_editingMessageWithQuotedMessage.default-light.png differ diff --git a/StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListView_Tests.swift b/StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListView_Tests.swift index fb3ab81eb..7449d5502 100644 --- a/StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListView_Tests.swift +++ b/StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListView_Tests.swift @@ -120,6 +120,21 @@ class ChatChannelListView_Tests: StreamChatTestCase { // Then assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) } + + func test_channelListView_customizedNavigationBar() { + // Given + let controller = makeChannelListController() + + // When + customizedNavigationBarAppearance() + let view = ChatChannelListView( + channelListController: controller + ) + .applyDefaultSize() + + // Then + assertSnapshot(matching: view, as: .image(perceptualPrecision: precision)) + } private func makeChannelListController() -> ChatChannelListController_Mock { let channelListController = ChatChannelListController_Mock.mock(client: chatClient) diff --git a/StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_channelListView_customizedNavigationBar.1.png b/StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_channelListView_customizedNavigationBar.1.png new file mode 100644 index 000000000..14471c6bd Binary files /dev/null and b/StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_channelListView_customizedNavigationBar.1.png differ diff --git a/StreamChatSwiftUITests/Tests/CommonViews/GalleryHeaderView_Tests.swift b/StreamChatSwiftUITests/Tests/CommonViews/GalleryHeaderView_Tests.swift new file mode 100644 index 000000000..0424dfa84 --- /dev/null +++ b/StreamChatSwiftUITests/Tests/CommonViews/GalleryHeaderView_Tests.swift @@ -0,0 +1,32 @@ +// +// Copyright © 2025 Stream.io Inc. All rights reserved. +// + +import SnapshotTesting +@testable import StreamChat +@testable import StreamChatSwiftUI +import SwiftUI +import XCTest + +final class GalleryHeaderView_Tests: StreamChatTestCase { + let size = CGSize(width: 300, height: 60) + + func test_default_snapshot() { + // When + let view = GalleryHeaderView(title: "Title", subtitle: "Subtitle", isShown: .constant(false)) + .applySize(size) + + // Then + AssertSnapshot(view, variants: [.defaultLight], size: size) + } + + func test_customized_snapshot() { + // When + customizedNavigationBarAppearance() + let view = GalleryHeaderView(title: "Title", subtitle: "Subtitle", isShown: .constant(false)) + .applySize(size) + + // Then + AssertSnapshot(view, variants: [.defaultLight], size: size) + } +} diff --git a/StreamChatSwiftUITests/Tests/CommonViews/__Snapshots__/GalleryHeaderView_Tests/test_customized_snapshot.default-light.png b/StreamChatSwiftUITests/Tests/CommonViews/__Snapshots__/GalleryHeaderView_Tests/test_customized_snapshot.default-light.png new file mode 100644 index 000000000..e205f9380 Binary files /dev/null and b/StreamChatSwiftUITests/Tests/CommonViews/__Snapshots__/GalleryHeaderView_Tests/test_customized_snapshot.default-light.png differ diff --git a/StreamChatSwiftUITests/Tests/CommonViews/__Snapshots__/GalleryHeaderView_Tests/test_default_snapshot.default-light.png b/StreamChatSwiftUITests/Tests/CommonViews/__Snapshots__/GalleryHeaderView_Tests/test_default_snapshot.default-light.png new file mode 100644 index 000000000..1bf824d6d Binary files /dev/null and b/StreamChatSwiftUITests/Tests/CommonViews/__Snapshots__/GalleryHeaderView_Tests/test_default_snapshot.default-light.png differ diff --git a/StreamChatSwiftUITests/Tests/StreamChatTestCase.swift b/StreamChatSwiftUITests/Tests/StreamChatTestCase.swift index e28d648e1..cbc6c92fc 100644 --- a/StreamChatSwiftUITests/Tests/StreamChatTestCase.swift +++ b/StreamChatSwiftUITests/Tests/StreamChatTestCase.swift @@ -34,4 +34,13 @@ open class StreamChatTestCase: XCTestCase { block(&appearance) streamChat.appearance = appearance } + + func customizedNavigationBarAppearance() { + adjustAppearance { appearance in + appearance.colors.navigationBarTintColor = .purple + appearance.colors.navigationBarTitle = .blue + appearance.colors.navigationBarSubtitle = .cyan + appearance.colors.navigationBarBackground = .yellow + } + } } diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 9075886a9..5311566b1 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -143,8 +143,6 @@ lane :publish_release do |options| ) update_spm(version: release_version) - - sh('gh workflow run merge-main-to-develop.yml --ref main') end lane :get_sdk_version_from_environment do