Skip to content
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

4.64.0 Release #617

Merged
merged 27 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6a522fc
Reduce view updates when computing frame for long press action (#607)
laevandus Sep 23, 2024
f70197e
ChatChannelListView navigation did not trigger when using a custom co…
laevandus Sep 23, 2024
64dc5fa
Bump puma from 6.4.2 to 6.4.3 (#608)
dependabot[bot] Sep 23, 2024
816076e
Channel was sometimes not marked as read when tapping the x on the un…
laevandus Sep 24, 2024
f04bcb4
Bump fastlane plugin
testableapple Sep 24, 2024
89a3b4e
[CI] Fix snapshots path
testableapple Sep 24, 2024
4dd1264
Use LLC polls branch
nuno-vieira Sep 27, 2024
4883a85
Fix the vote progress view not having full width when the Poll is closed
nuno-vieira Sep 27, 2024
21e57a6
Fix checkbox not marked when current user voted from another device
nuno-vieira Sep 27, 2024
58d8f90
Fix latest voter logic incorrect
nuno-vieira Sep 27, 2024
ac6b1c9
Fix deprecated poll vote list query initializers
nuno-vieira Sep 27, 2024
11e4303
Improve voting UX by making it possible taping the option as well
nuno-vieira Sep 28, 2024
c6eca07
Reuse logic from LLC
nuno-vieira Sep 28, 2024
65a9211
Use latestVotes order directly from LLC
nuno-vieira Sep 29, 2024
c38c7b8
Update CHANGELOG.md
nuno-vieira Sep 30, 2024
20507e8
Merge branch 'develop' into add/polls-improvements
nuno-vieira Sep 30, 2024
7871a1f
Fix SwiftFormat
nuno-vieira Sep 30, 2024
4a84d28
[CI] Improvements (#613)
testableapple Sep 30, 2024
f73f436
[CI] Remove the merge of main to develop from the pipeline and do it …
testableapple Sep 30, 2024
6e1c0a9
Change branch to develop
nuno-vieira Oct 1, 2024
8678af8
Merge branch 'develop' into add/polls-improvements
nuno-vieira Oct 1, 2024
5e9de53
Merge pull request #612 from GetStream/add/polls-improvements
nuno-vieira Oct 2, 2024
d7bdf43
Made replacesMessageSent open in TwoStepMentionCommand (#615)
martinmitrevski Oct 2, 2024
ed14434
Bump webrick from 1.8.1 to 1.8.2 (#614)
dependabot[bot] Oct 2, 2024
20a2d4a
Updated StreamChat dependency to 4.64.0 (#616)
laevandus Oct 3, 2024
daa05d6
Channel was sometimes not selected when setting selectedChannelId (#611)
laevandus Oct 3, 2024
ab2ecce
Bump 4.64.0
Oct 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/release-publish.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
name: "Publish new release"

on:
push:
branches:
- main

workflow_dispatch:

jobs:
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### 🔄 Changed

# [4.64.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.64.0)
_October 03, 2024_

### 🔄 Changed
- Improves Poll voting UX by making it possible to tap on the whole option as well [#612](https://github.com/GetStream/stream-chat-swiftui/pull/612)
### 🐞 Fixed
- Rare crash when accessing frame of the view [#607](https://github.com/GetStream/stream-chat-swiftui/pull/607)
- `ChatChannelListView` navigation did not trigger when using a custom container and its body reloaded [#609](https://github.com/GetStream/stream-chat-swiftui/pull/609)
- Channel was sometimes not marked as read when tapping the x on the unread message pill in the message list [#610](https://github.com/GetStream/stream-chat-swiftui/pull/610)
- Channel was sometimes not selected if `ChatChannelViewModel.selectedChannelId` was set to a channel created a moments ago [#611](https://github.com/GetStream/stream-chat-swiftui/pull/611)
- Fix the poll vote progress view not having full width when the Poll is closed [#612](https://github.com/GetStream/stream-chat-swiftui/pull/612)
- Fix the last vote author not accurate in the channel preview [#612](https://github.com/GetStream/stream-chat-swiftui/pull/612)

# [4.63.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.63.0)
_September 12, 2024_

Expand Down
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ GEM
fastlane
pry
fastlane-plugin-sonarcloud_metric_kit (0.2.1)
fastlane-plugin-stream_actions (0.3.63)
fastlane-plugin-stream_actions (0.3.70)
xctest_list (= 1.2.1)
fastlane-plugin-versioning (0.5.2)
ffi (1.17.0)
Expand Down Expand Up @@ -306,7 +306,7 @@ GEM
coderay (~> 1.1)
method_source (~> 1.0)
public_suffix (4.0.7)
puma (6.4.2)
puma (6.4.3)
nio4r (~> 2.0)
racc (1.8.1)
rack (3.1.7)
Expand Down Expand Up @@ -396,7 +396,7 @@ GEM
concurrent-ruby (~> 1.0)
uber (0.1.0)
unicode-display_width (2.5.0)
webrick (1.8.1)
webrick (1.8.2)
word_wrap (1.0.0)
xcinvoke (0.3.0)
liferaft (~> 0.0.6)
Expand Down Expand Up @@ -427,7 +427,7 @@ DEPENDENCIES
fastlane-plugin-create_xcframework
fastlane-plugin-lizard
fastlane-plugin-sonarcloud_metric_kit
fastlane-plugin-stream_actions (= 0.3.63)
fastlane-plugin-stream_actions (= 0.3.70)
fastlane-plugin-versioning
jazzy
json
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let package = Package(
)
],
dependencies: [
.package(url: "https://github.com/GetStream/stream-chat-swift.git", from: "4.63.0"),
.package(url: "https://github.com/GetStream/stream-chat-swift.git", from: "4.64.0"),
],
targets: [
.target(
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<p align="center">
<a href="https://sonarcloud.io/summary/new_code?id=GetStream_stream-chat-swiftui"><img src="https://sonarcloud.io/api/project_badges/measure?project=GetStream_stream-chat-swiftui&metric=coverage" /></a>

<img id="stream-chat-swiftui-label" alt="StreamChatSwiftUI" src="https://img.shields.io/badge/StreamChatSwiftUI-7.11%20MB-blue"/>
<img id="stream-chat-swiftui-label" alt="StreamChatSwiftUI" src="https://img.shields.io/badge/StreamChatSwiftUI-7.14%20MB-blue"/>
</p>

## SwiftUI StreamChat SDK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ open class TwoStepMentionCommand: CommandHandler {
self.displayInfo = displayInfo
}

public func canHandleCommand(in text: String, caretLocation: Int) -> ComposerCommand? {
open func canHandleCommand(in text: String, caretLocation: Int) -> ComposerCommand? {
if text == id {
return ComposerCommand(
id: id,
Expand All @@ -59,7 +59,7 @@ open class TwoStepMentionCommand: CommandHandler {
}
}

public func handleCommand(
open func handleCommand(
for text: Binding<String>,
selectedRangeLocation: Binding<Int>,
command: Binding<ComposerCommand?>,
Expand All @@ -84,19 +84,19 @@ open class TwoStepMentionCommand: CommandHandler {
selectedRangeLocation.wrappedValue = newCaretLocation
}

public func canBeExecuted(composerCommand: ComposerCommand) -> Bool {
open func canBeExecuted(composerCommand: ComposerCommand) -> Bool {
selectedUser != nil
}

public func commandHandler(for command: ComposerCommand) -> CommandHandler? {
open func commandHandler(for command: ComposerCommand) -> CommandHandler? {
if let selectedUser = selectedUser,
command.typingSuggestion.text != "\(mentionSymbol)\(selectedUser.mentionText)" {
self.selectedUser = nil
}
return command.id == id ? self : nil
}

public func showSuggestions(
open func showSuggestions(
for command: ComposerCommand
) -> Future<SuggestionInfo, Error> {
if selectedUser != nil {
Expand Down Expand Up @@ -126,7 +126,7 @@ open class TwoStepMentionCommand: CommandHandler {
return mentionsCommandHandler.showSuggestions(for: updated)
}

public var replacesMessageSent: Bool {
open var replacesMessageSent: Bool {
true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
GeometryReader { proxy in
Rectangle().fill(Color.clear)
.onChange(of: computeFrame, perform: { _ in
DispatchQueue.main.async {
frame = proxy.frame(in: .global)
}
frame = proxy.frame(in: .global)
})
}
)
Expand Down Expand Up @@ -347,9 +345,8 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
showsMessageActions: Bool,
showsBottomContainer: Bool = true
) {
computeFrame = true
computeFrame.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
computeFrame = false
triggerHapticFeedback(style: .medium)
onLongPress(
MessageDisplayInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ public struct MessageListView<Factory: ViewFactory>: View, KeyboardReadable {
_ = onJumpToMessage?(firstUnreadMessageId ?? .unknownMessageId)
},
onClose: {
firstUnreadMessageId = nil
chatClient.channelController(for: channel.cid).markRead()
unreadButtonDismissed = true
}
) : nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ struct PollAllOptionsView: View {
viewModel: viewModel,
option: option,
optionFont: fonts.headline,
alternativeStyle: true
alternativeStyle: true,
checkboxButtonSpacing: 8
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public struct PollAttachmentView<Factory: ViewFactory>: View {
PollOptionView(
viewModel: viewModel,
option: option,
optionVotes: poll.voteCountsByOption?[option.id],
maxVotes: poll.voteCountsByOption?.values.max()
optionVotes: poll.voteCount(for: option),
maxVotes: poll.currentMaximumVoteCount
)
.layoutPriority(1) // do not compress long text
}
Expand Down Expand Up @@ -190,53 +190,63 @@ struct PollOptionView: View {
var maxVotes: Int?
/// If true, only option name and vote count is shown, otherwise votes indicator and avatars appear as well.
var alternativeStyle: Bool = false

/// The spacing between the checkbox and the option name.
/// By default it is 4. For All Options View is 8.
var checkboxButtonSpacing: CGFloat = 4

var body: some View {
VStack(spacing: 4) {
HStack(alignment: .top) {
if !viewModel.poll.isClosed {
Button {
if viewModel.optionVotedByCurrentUser(option) {
viewModel.removePollVote(for: option)
} else {
viewModel.castPollVote(for: option)
}
} label: {
if viewModel.optionVotedByCurrentUser(option) {
Image(systemName: "checkmark.circle.fill")
} else {
Image(systemName: "circle")
}
HStack(alignment: .top, spacing: checkboxButtonSpacing) {
if !viewModel.poll.isClosed {
Button {
togglePollVote()
} label: {
if viewModel.optionVotedByCurrentUser(option) {
Image(systemName: "checkmark.circle.fill")
} else {
Image(systemName: "circle")
}
}

Text(option.text)
.font(optionFont)
Spacer()
if !alternativeStyle, viewModel.showVoterAvatars {
HStack(spacing: -4) {
ForEach(
option.latestVotes.sorted(by: { $0.createdAt > $1.createdAt }).suffix(2)
) { vote in
MessageAvatarView(
avatarURL: vote.user?.imageURL,
size: .init(width: 20, height: 20)
)
}
VStack(spacing: 4) {
HStack(alignment: .top) {
Text(option.text)
.font(optionFont)
Spacer()
if !alternativeStyle, viewModel.showVoterAvatars {
HStack(spacing: -4) {
ForEach(
option.latestVotes.prefix(2)
) { vote in
MessageAvatarView(
avatarURL: vote.user?.imageURL,
size: .init(width: 20, height: 20)
)
}
}
}
Text("\(viewModel.poll.voteCountsByOption?[option.id] ?? 0)")
}
if !alternativeStyle {
PollVotesIndicatorView(
alternativeStyle: viewModel.poll.isClosed && viewModel.hasMostVotes(for: option),
optionVotes: optionVotes ?? 0,
maxVotes: maxVotes ?? 0
)
}
Text("\(viewModel.poll.voteCountsByOption?[option.id] ?? 0)")
}

if !alternativeStyle {
PollVotesIndicatorView(
alternativeStyle: viewModel.poll.isClosed && viewModel.hasMostVotes(for: option),
optionVotes: optionVotes ?? 0,
maxVotes: maxVotes ?? 0
)
.padding(.leading, 24)
}
}
.contentShape(Rectangle())
.onTapGesture {
togglePollVote()
}
}

func togglePollVote() {
if viewModel.optionVotedByCurrentUser(option) {
viewModel.removePollVote(for: option)
} else {
viewModel.castPollVote(for: option)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public class PollAttachmentViewModel: ObservableObject, PollControllerDelegate {

/// True, if the current user has voted for the specified option, otherwise false.
public func optionVotedByCurrentUser(_ option: PollOption) -> Bool {
currentUserVote(for: option) != nil
poll.hasCurrentUserVoted(for: option)
}

/// Adds a new option to the poll.
Expand All @@ -219,13 +219,7 @@ public class PollAttachmentViewModel: ObservableObject, PollControllerDelegate {
///
/// - Note: When multiple options have the highest vote count, this function returns false.
public func hasMostVotes(for option: PollOption) -> Bool {
guard let allCounts = poll.voteCountsByOption else { return false }
guard let optionVoteCount = allCounts[option.id], optionVoteCount > 0 else { return false }
guard let highestVotePerOption = allCounts.values.max() else { return false }
guard optionVoteCount == highestVotePerOption else { return false }
// Check if only one option has highest number for votes
let optionsByVoteCounts = Dictionary(grouping: allCounts, by: { $0.value })
return optionsByVoteCounts[optionVoteCount]?.count == 1
poll.isOptionWithMostVotes(option)
}

// MARK: - PollControllerDelegate
Expand All @@ -244,7 +238,7 @@ public class PollAttachmentViewModel: ObservableObject, PollControllerDelegate {
// MARK: - private

private func currentUserVote(for option: PollOption) -> PollVote? {
currentUserVotes.first(where: { $0.optionId == option.id })
poll.currentUserVote(for: option)
}

private func notifySheetPresentation(shown: Bool) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ class PollCommentsViewModel: ObservableObject, PollVoteListControllerDelegate {
convenience init(poll: Poll, pollController: PollController) {
let query = PollVoteListQuery(
pollId: poll.id,
optionId: nil,
filter: .and(
[.equal(.pollId, to: poll.id), .equal(.isAnswer, to: true)]
)
filter: .equal(.isAnswer, to: true)
)
self.init(
pollController: pollController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class PollOptionAllVotesViewModel: ObservableObject, PollVoteListControllerDeleg
self.option = option
let query = PollVoteListQuery(
pollId: poll.id,
optionId: option.id, filter: .equal(.optionId, to: option.id)
optionId: option.id
)
controller = InjectedValues[\.chatClient].pollVoteListController(query: query)
controller.delegate = self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct PollResultsView: View {
poll: viewModel.poll,
option: option,
votes: Array(
option.latestVotes.sorted(by: { $0.createdAt > $1.createdAt })
option.latestVotes
.prefix(numberOfItemsShown)
),
hasMostVotes: viewModel.hasMostVotes(for: option),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ extension ChatChannel {
private func pollMessageText(for previewMessage: ChatMessage) -> String? {
guard let poll = previewMessage.poll, !previewMessage.isDeleted else { return nil }
var components = ["📊"]
if let latestVoter = poll.latestVotesByOption.first?.latestVotes.first?.user {
if previewMessage.isSentByCurrentUser {
if let latestVoter = poll.latestVotes.first?.user {
if latestVoter.id == membership?.id {
components.append(L10n.Channel.Item.pollYouVoted)
} else {
components.append(L10n.Channel.Item.pollSomeoneVoted(latestVoter.name ?? latestVoter.id))
Expand Down
Loading
Loading