Skip to content

Commit

Permalink
Release/4.6.0 (#1715)
Browse files Browse the repository at this point in the history
* Bump 4.6.0

* Adding bootstrap script to the Github action

* [CIS-1378] Safely access indexes of collections (#1692)

* Add safe subscript to avoid crashing on accessing an array element

* Centralize logging + assertions in Collections extension

* Add tests for SafeSubscript

* Update Sources/StreamChatUI/Utils/Array+SafeSubscript.swift

Co-authored-by: Boris Bielik <h3sperian@gmail.com>

* Remove unneeded guard

* Apply SwiftFormat

* Update Changelog

Co-authored-by: Boris Bielik <h3sperian@gmail.com>

* Execute generateSPMFileLists

* Add smoke checks for PRs pointing to a release branch

* Add more safety when data source index is not present by returning a valid cell

* Added docs for inline replies in the SwiftUI SDK (#1694)

* Fix reload rows out of bounds (#1697)

* Remove layout options from chat message layout options (#1698)

* Expose `QueryOptions` and `start/stopWatching` (#1696)

* UnknownEvent is now deprecated and was renamed to UnknownChannelEvent (#1695)

Provides new UnknownUserEvent model for custom user events

* Linting

* SwiftyGif 5.4.2

* Adds missing reference for source file - SwiftyGif

* Remove smoke checks

* Update CHANGELOG.md

Co-authored-by: Boris Bielik <h3sperian@gmail.com>

* Update CHANGELOG.md

* 4.6.0 Release (#1690)

Release 4.6.0.

* We need to setup the ENV for bootstrap to run correctly (including SSH Bot)

* Fixing the YML validation and fixing the CHANGELOG date entry

* Removing duplicate inside the full checks yml file

* Release 4.6.0 (#1700)

* Disabling automatic signing for both StreamChat and StreamChatUI framework

* Move away from submodules (#1709)

* Move away from submodules

* Remove cloned repos after dependencies updates

* Pod trunk push all specs (#1711)

* Pod trunk push all specs

* Updating workflow scripts along with fastfile (#1714)

* Updating workflow scripts along with fastfile

* Pulling in changes for updating podspecs across all Pods

Co-authored-by: Adam Rush <adam.rush@getstream.io>

* Update CHANGELOG.md

Co-authored-by: Boris Bielik <h3sperian@gmail.com>

Co-authored-by: Adam Rush <adam.rush@getstream.io>
Co-authored-by: Boris Bielik <h3sperian@gmail.com>
Co-authored-by: Martin Mitrevski <martinmitrevski.oh@gmail.com>
Co-authored-by: Tommaso Barbugli <tbarbugli@gmail.com>
Co-authored-by: Nuno Vieira <nuno.fcvieira93@gmail.com>
Co-authored-by: Bahadır Öncel <bahadir@getstream.io>
Co-authored-by: Boris Bielik <boris.bielik@getstream.io>
Co-authored-by: Adam Rush <adam@adr-studio.co.uk>
  • Loading branch information
9 people committed Dec 20, 2021
1 parent 48f13c1 commit 2b868ca
Show file tree
Hide file tree
Showing 62 changed files with 890 additions and 327 deletions.
26 changes: 1 addition & 25 deletions .github/workflows/full-checks.yml
Expand Up @@ -101,30 +101,6 @@ jobs:
- name: Run Stress Tests - Latest iOS (Release)
run: bundle exec fastlane stress_test_release device:"iPhone 12"

stress-tests:
name: Stress Test LLC - Latest iOS (Release)
runs-on: macos-11
steps:
- uses: actions/checkout@v1
- uses: ./.github/actions/set-build-image-var
- name: Cache RubyGems
uses: actions/cache@v2
id: rubygem-cache
with:
path: vendor/bundle
key: ${{ runner.os }}-${{ env.ImageVersion }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: ${{ runner.os }}-${{ env.ImageVersion }}-gem-
- name: Cache Mint
uses: actions/cache@v2
id: mint-cache
with:
path: /usr/local/lib/mint
key: ${{ runner.os }}-mint-${{ hashFiles('./Mintfile') }}
restore-keys: ${{ runner.os }}-mint-
- uses: ./.github/actions/bootstrap
- name: Run Stress Tests - Latest iOS (Release)
run: bundle exec fastlane stress_test_release device:"iPhone 12"

stress-tests-ios13:
name: Stress Test LLC - iOS 13.5 (Release)
runs-on: macos-11
Expand Down Expand Up @@ -259,4 +235,4 @@ jobs:
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
MATRIX_CONTEXT: ${{ toJson(matrix) }}
if: ${{ github.event_name == 'push' && failure() }}
if: ${{ github.event_name == 'push' && failure() }}
34 changes: 30 additions & 4 deletions .github/workflows/publish-release.yml
Expand Up @@ -13,8 +13,34 @@ jobs:
runs-on: macos-11
if: github.event.pull_request.merged == true # only merged pull requests must trigger this job
steps:
- name: If the release branch contains the version, let's go!
- name: Install Bot SSH Key
uses: webfactory/ssh-agent@v0.4.1
with:
ssh-private-key: ${{ secrets.BOT_SSH_PRIVATE_KEY }}
- uses: actions/checkout@v1
- name: "Set build image var"
run: echo "ImageVersion=$ImageVersion" >> $GITHUB_ENV
- name: Cache RubyGems
uses: actions/cache@v2
id: rubygem-cache
with:
path: vendor/bundle
key: ${{ runner.os }}-${{ env.ImageVersion }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: ${{ runner.os }}-${{ env.ImageVersion }}-gem-
- name: Cache Mint
uses: actions/cache@v2
id: mint-cache
with:
path: /usr/local/lib/mint
key: ${{ runner.os }}-mint-${{ hashFiles('./Mintfile') }}
restore-keys: ${{ runner.os }}-mint-
- name: Extract version from branch name (for release branches)
if: startsWith(github.event.pull_request.head.ref, 'release/')
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
VERSION=${BRANCH_NAME#release/}
run: bundle exec fastlane publish_release version:$VERSION
run: |
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
VERSION=${BRANCH_NAME#release/}
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV
- uses: ./.github/actions/bootstrap
- name: "Starting on the Fastlane Publish Release"
if: startsWith(github.event.pull_request.head.ref, 'release/')
run: bundle exec fastlane publish_release version:${{ env.RELEASE_VERSION }}
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -77,3 +77,6 @@ docusaurus/.env

# Ignore Products folder
Products/

# Ignore Dependencies folder
Dependencies/
9 changes: 0 additions & 9 deletions .gitmodules

This file was deleted.

27 changes: 19 additions & 8 deletions CHANGELOG.md
Expand Up @@ -3,24 +3,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

# Upcoming

### 🔄 Changed

# [4.6.0](https://github.com/GetStream/stream-chat-swift/releases/tag/4.6.0)
_December 20, 2021_

### ⚠️ Important
- Dependencies are no longer exposed (this includes Nuke, SwiftyGif and Starscream). If you were using those dependencies we were exposing, you would need to import them manually. This is due to our newest addition supporting Module Stable XCFrameworks, see more below in the "Added" section.

### 🔄 Changed
- Change `ChatMessageLayoutOptions` to a `Set` instead of an `OptionSet` for a more flexible and safer customization [#1651](https://github.com/GetStream/stream-chat-swift/issues/1651)
- There is a new `ChatMessageListDateSeparatorView` component that should be used instead of the `ChatMessageListScrollOverlayView` if the goal is customize the styling of the date separator. Read [here](https://getstream.io/chat/docs/sdk/ios/uikit/components/message/#date-separators) for more details.
- `UnknownEvent` is now deprecated, use `UnknownChannelEvent` or `UnknownUserEvent` instead. [#1695](https://github.com/GetStream/stream-chat-swift/pull/1695).
- SwiftyGif now points to [v5.4.2](https://github.com/kirualex/SwiftyGif/releases/tag/5.4.2) that resolves crash related to leaked delegate reference.

### 🐞 Fixed
- Fix `stopTyping` can be called on `TypingEventSender` after calling `startTyping` [#1649](https://github.com/GetStream/stream-chat-swift/issues/1649)
- Reactions no longer cover the text in message bubble [#1666](https://github.com/GetStream/stream-chat-swift/pull/1666)
- Fix `error` type messages rendered as user's messages and interactive [#1672](https://github.com/GetStream/stream-chat-swift/issues/1672)
- Fix `ChannelListController` makes one redundant API call [#1687](https://github.com/GetStream/stream-chat-swift/issues/1687)
- Fix `stopTyping` can be called on `TypingEventSender` after calling `startTyping` [#1649](https://github.com/GetStream/stream-chat-swift/issues/1649).
- Reactions no longer cover the text in message bubble [#1666](https://github.com/GetStream/stream-chat-swift/pull/1666).
- Fix `error` type messages rendered as user's messages and interactive [#1672](https://github.com/GetStream/stream-chat-swift/issues/1672).
- Fix `ChannelListController` makes one redundant API call [#1687](https://github.com/GetStream/stream-chat-swift/issues/1687).
- Safely access indexes of collections [#1692](https://github.com/GetStream/stream-chat-swift/pull/1692).

### ✅ Added
- Add support for pre-built XCFrameworks [#1665](https://github.com/GetStream/stream-chat-swift/pull/1665)
- Added `LogConfig.destinationTypes` for ease of adding new destinations to logger [#1681](https://github.com/GetStream/stream-chat-swift/issues/1681)
- Expose container embedding top & bottom containers by `ChatChannelListItemView` [#1670](https://github.com/GetStream/stream-chat-swift/issues/1670)
- Add Static Message List Date Separators [#1686](https://github.com/GetStream/stream-chat-swift/issues/1686) (You can read this [doc](https://getstream.io/chat/docs/sdk/ios/uikit/components/message/#date-separators) to understand how to configure this feature)
- Add support for pre-built XCFrameworks [#1665](https://github.com/GetStream/stream-chat-swift/pull/1665).
- Added `LogConfig.destinationTypes` for ease of adding new destinations to logger [#1681](https://github.com/GetStream/stream-chat-swift/issues/1681).
- Expose container embedding top & bottom containers by `ChatChannelListItemView` [#1670](https://github.com/GetStream/stream-chat-swift/issues/1670).
- Add Static Message List Date Separators [#1686](https://github.com/GetStream/stream-chat-swift/issues/1686) (You can read this [doc](https://getstream.io/chat/docs/sdk/ios/uikit/components/message/#date-separators) to understand how to configure this feature).
- Adds `UnknownUserEvent` that models custom user event [#1695](https://github.com/GetStream/stream-chat-swift/pull/1695).
- `ChannelQuery.options` and `ChannelListQuery.options` are now public and mutable [#1696](https://github.com/GetStream/stream-chat-swift/issues/1696)
- `ChannelController.startWatching` and `stopWatching` are now `public`. You can explicitly stop watching a channel [#1696](https://github.com/GetStream/stream-chat-swift/issues/1696).

# [4.5.2](https://github.com/GetStream/stream-chat-swift/releases/tag/4.5.2)
_December 10, 2021_
Expand Down
1 change: 0 additions & 1 deletion Dependencies/Nuke
Submodule Nuke deleted from c0b32b
1 change: 0 additions & 1 deletion Dependencies/Starscream
Submodule Starscream deleted from df8d82
1 change: 0 additions & 1 deletion Dependencies/SwiftyGif
Submodule SwiftyGif deleted from 652b34
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -61,7 +61,7 @@ update_dependencies:
echo "👉 Updating Starscream"
make update_starscream version=4.0.4
echo "👉 Updating SwiftyGif"
make update_swiftygif version=5.4.1
make update_swiftygif version=5.4.2

update_nuke: check_version_parameter
./Scripts/updateDependency.sh $(version) Dependencies/Nuke Sources/StreamChatUI/StreamNuke Sources
Expand Down
4 changes: 3 additions & 1 deletion Package.swift
Expand Up @@ -87,15 +87,16 @@ var streamChatSourcesExcluded: [String] { [
"APIClient/HTTPHeader_Tests.swift",
"APIClient/Endpoints/GuestEndpoints_Tests.swift",
"APIClient/Endpoints/Payloads/CustomDataHashMap_Tests.swift",
"APIClient/Endpoints/Payloads/UnknownUserEvent_Tests.swift",
"APIClient/Endpoints/Payloads/DevicePayloads_Tests.swift",
"APIClient/Endpoints/Payloads/MessageAttachmentPayload_Tests.swift",
"APIClient/Endpoints/Payloads/MutedChannelPayload_Tests.swift",
"APIClient/Endpoints/Payloads/CurrentUserPayloads_Tests.swift",
"APIClient/Endpoints/Payloads/FlagMessagePayload_Tests.swift",
"APIClient/Endpoints/Payloads/UnknownChannelEvent_Tests.swift",
"APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift",
"APIClient/Endpoints/Payloads/FlagUserPayload_Tests.swift",
"APIClient/Endpoints/Payloads/MessagePayloads_Tests.swift",
"APIClient/Endpoints/Payloads/UnknownEvent_Tests.swift",
"APIClient/Endpoints/Payloads/MissingEventsPayload_Tests.swift",
"APIClient/Endpoints/Payloads/FileUploadPayload_Tests.swift",
"APIClient/Endpoints/Payloads/UserPayloads_Tests.swift",
Expand Down Expand Up @@ -773,6 +774,7 @@ var streamChatUIFilesExcluded: [String] { [
"Utils/UIViewController+Extensions_Tests.swift",
"Utils/ChatChannelNamer_Tests.swift",
"Utils/ComponentsProvider_Tests.swift",
"Utils/Array+SafeSubscript_Tests.swift",
"Utils/AppearanceProvider_Tests.swift",
"Utils/ImageCDN_Tests.swift",
"Utils/DateUtils_Tests.swift",
Expand Down
23 changes: 22 additions & 1 deletion Scripts/updateDependency.sh
Expand Up @@ -18,7 +18,25 @@ dependency_directory=$2
output_directory=$3
sources_directory=$4

git submodule update --init
dependency_url=""

# Nuke
if [[ $dependency_directory == *"Nuke"* ]]; then
dependency_url="git@github.com:kean/Nuke.git"
elif [[ $dependency_directory == *"SwiftyGif"* ]]; then
dependency_url="git@github.com:kirualex/SwiftyGif.git"
elif [[ $dependency_directory == *"Starscream"* ]]; then
dependency_url="git@github.com:daltoniam/Starscream.git"
else
echo "→ Unknown dependency at $dependency_directory"
exit 1
fi

if ! [[ -d "$dependency_directory" ]]; then
echo "$dependency_directory does not exist in your filesystem. Cloning the repo"
git clone $dependency_url $dependency_directory
fi

cd $dependency_directory

ensure_clean_git
Expand All @@ -30,6 +48,7 @@ ensure_clean_git

cd -

echo "→ Copying source files"
rm -rf $output_directory
mkdir $output_directory
cp -r "$dependency_directory/$sources_directory/." $output_directory
Expand All @@ -40,3 +59,5 @@ do
echo "→ Removing $f"
rm $f
done

rm -rf $dependency_directory
Expand Up @@ -6,7 +6,7 @@ import Foundation

/// An event type SDK fallbacks to if incoming event was failed to be
/// decoded as a system event.
public struct UnknownEvent: Event, Hashable {
public struct UnknownChannelEvent: Event, Hashable {
/// An event type.
public let type: EventType

Expand All @@ -19,13 +19,13 @@ public struct UnknownEvent: Event, Hashable {
/// An event creation date.
public let createdAt: Date

/// A dictionary with custom fields.
let payload: [String: RawJSON]
/// A dictionary containing the entire event JSON.
public let payload: [String: RawJSON]
}

// MARK: - Decodable

extension UnknownEvent: Decodable {
extension UnknownChannelEvent: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: EventPayload.CodingKeys.self)

Expand All @@ -37,14 +37,13 @@ extension UnknownEvent: Decodable {
payload: try decoder
.singleValueContainer()
.decode([String: RawJSON].self)
.removingValues(forKeys: EventPayload.CodingKeys.allCases.map(\.rawValue))
)
}
}

// MARK: - Payload

public extension UnknownEvent {
public extension UnknownChannelEvent {
/// Decodes a payload of the given type from the event.
///
/// - Parameter ofType: The type of payload the custom fields should be treated as.
Expand Down
Expand Up @@ -5,7 +5,7 @@
@testable import StreamChat
import XCTest

final class UnknownEvent_Tests: XCTestCase {
final class UnknownChannelEvent_Tests: XCTestCase {
func test_unkownEvent_decoding() throws {
// Create event fields
let userId: UserId = .unique
Expand Down Expand Up @@ -40,24 +40,25 @@ final class UnknownEvent_Tests: XCTestCase {
"idea" : "\(ideaPayload.idea)"
}
""".data(using: .utf8)!

// Decode unkown event from JSON.
let unknownEvent = try JSONDecoder.default.decode(UnknownEvent.self, from: json)
let unknownEvent = try JSONDecoder.default.decode(UnknownChannelEvent.self, from: json)
let payload = try JSONDecoder.default.decode([String: RawJSON].self, from: json)

// Assert all fields are correct.
XCTAssertEqual(unknownEvent.cid, cid)
XCTAssertEqual(unknownEvent.userId, userId)
XCTAssertEqual(unknownEvent.createdAt, createdAt.toDate())
XCTAssertEqual(unknownEvent.type, IdeaEventPayload.eventType)
XCTAssertEqual(unknownEvent.payload, ["idea": .string(ideaPayload.idea)])
XCTAssertEqual(unknownEvent.payload, payload)
}

func test_whenAllFieldsArePresentedAndTypeMatches_customPayloadIsDecoded() throws {
// Create custom event payload.
let payload = IdeaEventPayload.unique

// Create event with `IdeaEventPayload` payload.
let unkownEvent = UnknownEvent(
let unkownEvent = UnknownChannelEvent(
type: IdeaEventPayload.eventType,
cid: .unique,
userId: .unique,
Expand All @@ -71,7 +72,7 @@ final class UnknownEvent_Tests: XCTestCase {

func test_whenFieldsAreMissing_customPayloadIsNotDecoded() throws {
// Create event with `IdeaEventPayload` fields missing.
let unkownEvent = UnknownEvent(
let unkownEvent = UnknownChannelEvent(
type: IdeaEventPayload.eventType,
cid: .unique,
userId: .unique,
Expand All @@ -88,7 +89,7 @@ final class UnknownEvent_Tests: XCTestCase {
let randomEventType = EventType(rawValue: .unique)

// Create event with `IdeaEventPayload` fields missing.
let unkownEvent = UnknownEvent(
let unkownEvent = UnknownChannelEvent(
type: randomEventType,
cid: .unique,
userId: .unique,
Expand Down
@@ -0,0 +1,54 @@
//
// Copyright © 2021 Stream.io Inc. All rights reserved.
//

import Foundation

/// An event type SDK fallbacks to if incoming event was failed to be
/// decoded as a system event.
public struct UnknownUserEvent: Event, Hashable {
/// An event type.
public let type: EventType

/// A user the event is triggered for.
public let userId: UserId

/// An event creation date.
public let createdAt: Date

/// A dictionary containing the entire event JSON.
public let payload: [String: RawJSON]
}

extension UnknownUserEvent: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: EventPayload.CodingKeys.self)

self.init(
type: try container.decode(EventType.self, forKey: .eventType),
userId: try container.decode(UserPayload.self, forKey: .user).id,
createdAt: try container.decode(Date.self, forKey: .createdAt),
payload: try decoder
.singleValueContainer()
.decode([String: RawJSON].self)
)
}
}

// MARK: - Payload

public extension UnknownUserEvent {
/// Decodes a payload of the given type from the event.
///
/// - Parameter ofType: The type of payload the custom fields should be treated as.
/// - Returns: A payload of the given type if decoding succeeds and if event type matches the one declared in custom payload type. Otherwise `nil` is returned.
func payload<T: CustomEventPayload>(ofType: T.Type) -> T? {
guard
T.eventType == type,
let payloadData = try? JSONEncoder.default.encode(payload),
let payload = try? JSONDecoder.default.decode(T.self, from: payloadData)
else { return nil }

return payload
}
}

0 comments on commit 2b868ca

Please sign in to comment.