diff --git a/.gitignore b/.gitignore index 562d6089..6ba68861 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,9 @@ Pods/ Carthage/ !Sample/Carthage/ +# Ignore Products folder +Products/ + # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f108a9f..1fdea096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### ⚠️ Important -- Dependencies are no longer exposed (this includes Nuke and SwiftyGif). If you were using those dependencies we were exposing, you would need to import them manually. If you encounter any SPM-related problems, be sure to reset the package caches. +- Dependencies are no longer exposed (this includes Nuke and SwiftyGif). 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 XCFramework, see more below in the "Added" section. If you encounter any SPM-related problems, be sure to reset the package caches. ### ✅ Added - Add message preview with attachments in channel list +- Add support for pre-built XCFramework ### 🐞 Fixed - Made some `ChannelList` and `MessageListView` parameters optional diff --git a/Gemfile.lock b/Gemfile.lock index 9fd88a40..f7815be9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -183,6 +183,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) + fastlane-plugin-create_xcframework (1.1.2) fastlane-plugin-emerge (0.6.0) faraday (~> 1.1) fastlane-plugin-lizard (1.3.3) @@ -405,6 +406,7 @@ DEPENDENCIES danger danger-commit_lint fastlane + fastlane-plugin-create_xcframework fastlane-plugin-emerge fastlane-plugin-lizard fastlane-plugin-sonarcloud_metric_kit diff --git a/Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift b/Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift new file mode 100644 index 00000000..ce4f253a --- /dev/null +++ b/Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift @@ -0,0 +1,11 @@ +// +// Copyright © 2023 Stream.io Inc. All rights reserved. +// +// ⚠️ Generated file, please use `fastlane :bump_SDK_version or fastlane release major|minor|patch` lanes + +import Foundation + +enum SystemEnvironment { + /// A Stream Chat version. + public static let version: String = "4.39.0" +} diff --git a/StreamChatSwiftUI-XCFramework.podspec b/StreamChatSwiftUI-XCFramework.podspec new file mode 100644 index 00000000..f07e3926 --- /dev/null +++ b/StreamChatSwiftUI-XCFramework.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |spec| + spec.name = "StreamChatSwiftUI-XCFramework" + spec.version = "4.39.0" + spec.summary = "StreamChat SwiftUI Chat Components" + spec.description = "StreamChatSwiftUI SDK offers flexible SwiftUI components able to display data provided by StreamChat SDK." + + spec.homepage = "https://getstream.io/chat/" + spec.license = { :type => "BSD-3", :file => "LICENSE" } + spec.author = { "getstream.io" => "support@getstream.io" } + spec.social_media_url = "https://getstream.io" + spec.swift_version = '5.2' + spec.platform = :ios, "14.0" + spec.requires_arc = true + + spec.module_name = "StreamChatSwiftUI" + spec.source = { :http => "https://github.com/GetStream/stream-chat-swiftui/releases/download/#{spec.version}/#{spec.module_name}.zip" } + spec.vendored_frameworks = "#{spec.module_name}.xcframework" + spec.preserve_paths = "#{spec.module_name}.xcframework/*" + + spec.framework = "Foundation", "UIKit", "SwiftUI" + + spec.dependency "StreamChat-XCFramework", "~> 4.39.0" + + spec.cocoapods_version = ">= 1.11.0" +end diff --git a/StreamChatSwiftUI.xcodeproj/project.pbxproj b/StreamChatSwiftUI.xcodeproj/project.pbxproj index 176af532..d1a9ddc1 100644 --- a/StreamChatSwiftUI.xcodeproj/project.pbxproj +++ b/StreamChatSwiftUI.xcodeproj/project.pbxproj @@ -108,6 +108,7 @@ 82D64C1A2AD7E5B700C5C79E /* NukeCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82D64BCA2AD7E5B700C5C79E /* NukeCache.swift */; }; 82D64C1B2AD7E5B700C5C79E /* ImageCaching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82D64BCB2AD7E5B700C5C79E /* ImageCaching.swift */; }; 82D64C1C2AD7E5B700C5C79E /* DataCaching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82D64BCC2AD7E5B700C5C79E /* DataCaching.swift */; }; + 82FA42442AE67FF900C7390B /* SystemEnvironment+Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FA42432AE67FF900C7390B /* SystemEnvironment+Version.swift */; }; 8400A345282C05F60067D3A0 /* StreamChatWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8400A344282C05F60067D3A0 /* StreamChatWrapper.swift */; }; 8400A34A282C07D60067D3A0 /* InternetConnectionMonitor_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8400A349282C07D60067D3A0 /* InternetConnectionMonitor_Mock.swift */; }; 8400A34C282C081E0067D3A0 /* OHHTTPStubs in Frameworks */ = {isa = PBXBuildFile; productRef = 8400A34B282C081E0067D3A0 /* OHHTTPStubs */; }; @@ -606,6 +607,7 @@ 82D64BCB2AD7E5B700C5C79E /* ImageCaching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCaching.swift; sourceTree = ""; }; 82D64BCC2AD7E5B700C5C79E /* DataCaching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataCaching.swift; sourceTree = ""; }; 82E8D79C2902B949008A8F78 /* StreamChatSwiftUITestsApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = StreamChatSwiftUITestsApp.entitlements; sourceTree = ""; }; + 82FA42432AE67FF900C7390B /* SystemEnvironment+Version.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SystemEnvironment+Version.swift"; sourceTree = ""; }; 840008BA27E8D64A00282D88 /* MessageActions_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageActions_Tests.swift; sourceTree = ""; }; 8400A344282C05F60067D3A0 /* StreamChatWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamChatWrapper.swift; sourceTree = ""; }; 8400A349282C07D60067D3A0 /* InternetConnectionMonitor_Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternetConnectionMonitor_Mock.swift; sourceTree = ""; }; @@ -1473,6 +1475,7 @@ children = ( 8465FCED2746A95600AF091E /* L10n.swift */, 8465FCEE2746A95600AF091E /* L10n_template.stencil */, + 82FA42432AE67FF900C7390B /* SystemEnvironment+Version.swift */, ); path = Generated; sourceTree = ""; @@ -2353,6 +2356,7 @@ 8465FD9A2746A95700AF091E /* ReactionsHelperViews.swift in Sources */, 8465FDC02746A95700AF091E /* ChatChannelList.swift in Sources */, 82D64B682AD7E5AC00C5C79E /* ObjcAssociatedWeakObject.swift in Sources */, + 82FA42442AE67FF900C7390B /* SystemEnvironment+Version.swift in Sources */, 82D64BE02AD7E5B700C5C79E /* LazyImage.swift in Sources */, 82D64C052AD7E5B700C5C79E /* Deprecated.swift in Sources */, 84DEC8EC27611CAE00172876 /* SendInChannelView.swift in Sources */, diff --git a/StreamChatSwiftUIArtifacts.json b/StreamChatSwiftUIArtifacts.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/StreamChatSwiftUIArtifacts.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/docusaurus/docs/iOS/basics/integration.md b/docusaurus/docs/iOS/basics/integration.md index e6697b58..d06bac7f 100644 --- a/docusaurus/docs/iOS/basics/integration.md +++ b/docusaurus/docs/iOS/basics/integration.md @@ -36,6 +36,8 @@ You can learn more about [our Module Stable XCFrameworks here](#xcframeworks) - `https://github.com/getstream/stream-chat-swift-spm` - For the UIKit components (**StreamChatUI**, which depends on **StreamChat**) use: - `https://github.com/getstream/stream-chat-swift-spm` +- For the SwiftUI components (**StreamChatSwiftUI**, which depends on **StreamChat**) use: + - `https://github.com/getstream/stream-chat-swiftui-spm`

diff --git a/fastlane/Fastfile b/fastlane/Fastfile index bfc8d1f5..d9ac0242 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -30,25 +30,71 @@ after_all do |lane| stop_sinatra if lane == :test_e2e_mock end +lane :build_xcframeworks do + match_me + output_directory = "#{Dir.pwd}/../Products" + team_id = File.read('Matchfile').match(/team_id\("(.*)"\)/)[1] + codesign = ["codesign --timestamp -v --sign 'Apple Distribution: Stream.io Inc (#{team_id})'"] + sdk_names.each do |sdk| + create_xcframework( + project: xcode_project, + scheme: sdk, + destinations: ['iOS'], + include_BCSymbolMaps: true, + include_debug_symbols: true, + xcframework_output_directory: output_directory, + remove_xcarchives: true + ) + sh('../Scripts/removeUnneededSymbols.sh', sdk, output_directory) + codesign << lane_context[SharedValues::XCFRAMEWORK_OUTPUT_PATH] + end + sh(codesign.join(' ')) # We need to sign all frameworks at once +end + desc 'Release a new version' lane :release do |options| + previous_version_number = last_git_tag + artifacts_path = File.absolute_path('../StreamChatSwiftUIArtifacts.json') + swift_environment_path = File.absolute_path('../Sources/StreamChatSwiftUI/Generated/SystemEnvironment+Version.swift') + extra_changes = lambda do |release_version| + # Set the framework version on the artifacts + artifacts = JSON.parse(File.read(artifacts_path)) + artifacts[release_version.to_s] = "https://github.com/#{github_repo}/releases/download/#{release_version}/StreamChatSwiftUI.zip" + File.write(artifacts_path, JSON.dump(artifacts)) + + # Set the framework version in SystemEnvironment+Version.swift + new_content = File.read(swift_environment_path).gsub!(previous_version_number, release_version) + File.open(swift_environment_path, 'w') { |f| f.puts(new_content) } + end + pod_lint version_number = release_ios_sdk( version: options[:version], bump_type: options[:type], sdk_names: sdk_names, - github_repo: github_repo + podspec_names: ['StreamChatSwiftUI', 'StreamChatSwiftUI-XCFramework'], + github_repo: github_repo, + extra_changes: extra_changes ) publish_release(version: version_number) end desc "Publish a new release to GitHub and CocoaPods" lane :publish_release do |options| + clean_products + build_xcframeworks + compress_frameworks + clean_products + publish_ios_sdk( version: options[:version], sdk_names: sdk_names, - github_repo: github_repo + podspec_names: ['StreamChatSwiftUI', 'StreamChatSwiftUI-XCFramework'], + github_repo: github_repo, + upload_assets: ['Products/StreamChatSwiftUI.zip'] ) + + update_spm(version: options[:version]) end private_lane :appstore_api_key do @@ -180,6 +226,91 @@ lane :build_demo do |options| ) end +desc 'Compresses the XCFrameworks into zip files' +lane :compress_frameworks do + Dir.chdir('..') do + FileUtils.cp('LICENSE', 'Products/LICENSE') + Dir.chdir('Products') do + sdk_names.each do |framework| + sh("zip -r #{framework} ./#{framework}.xcframework ./LICENSE") + sh("swift package compute-checksum #{framework}.zip") + end + sh('zip -r "StreamChat-All" ./*.xcframework ./LICENSE') if sdk_names.size > 1 + end + end +end + +desc 'Cleans Products and DerivedData folders' +lane :clean_products do + Dir.chdir('..') do + ['*.xcframework', '*.bundle', '*.BCSymbolMaps', '*.dSYMs', 'LICENSE'].each do |f| + sh("rm -rf Products/#{f}") + end + end +end + +desc 'Update XCFrameworks and submit to the SPM repository' +private_lane :update_spm do |options| + version = options[:version] || '' + UI.user_error!('You need to pass the version of the release you want to obtain the changelog from') unless version.length > 0 + + # Generate Checksums + stream_chat_swiftui_checksum = sh('swift package compute-checksum ../Products/StreamChatSwiftUI.zip').strip + + # Update SPM Repo + spm_directory_name = 'StreamSPM' + spm_directory = "../../#{spm_directory_name}" + sh("git clone git@github.com:#{github_repo}-spm.git #{spm_directory}") + + Dir.chdir(spm_directory) do + result = sh('basename `git rev-parse --show-toplevel`').strip + UI.error("Not using #{spm_directory_name} repo") unless result.to_s == spm_directory_name + + file_lines = File.readlines('Package.swift') + file_data = '' + previous_module = '' + + file_lines.each do |line| + formatted_line = + case previous_module + when "StreamChatSwiftUI" + line.gsub(/(checksum: ")[a-z0-9]+(")/, "\\1#{stream_chat_swiftui_checksum}\\2") + else + line + end + + url_pattern = %r{(releases/download/)[.0-9]+(/)} + if line.match(url_pattern) + formatted_line = line.gsub(url_pattern, "\\1#{version}\\2") + previous_module = line.match(/([a-zA-Z]+).zip/).to_s.gsub(/.zip/, '') + end + + file_data << formatted_line + end + + # Write the new changes + File.open('./Package.swift', 'w') { |file| file << file_data } + + # Update the repo + sh('git add -A') + sh("git commit -m 'Bump #{version}'") + sh('git push') + + github_release = set_github_release( + repository_name: "#{github_repo}-spm", + api_token: ENV.fetch('GITHUB_TOKEN', nil), + name: version, + tag_name: version, + commitish: 'main', + description: "https://github.com/#{github_repo}/releases/tag/#{version}" + ) + UI.success("New SPM release available: #{github_release['html_url']}") + end + + # Clean Up + sh("rm -rf #{spm_directory}") +end + private_lane :update_testplan_on_ci do |options| update_testplan(path: options[:path], env_vars: { key: 'CI', value: 'TRUE' }) if is_ci end diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 00000000..f26ef457 --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1,5 @@ +git_url("git@github.com:GetStream/ios-certificates.git") + +storage_mode("git") + +team_id("EHV7XZLAHA") diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile index 392b377e..8f281085 100644 --- a/fastlane/Pluginfile +++ b/fastlane/Pluginfile @@ -6,3 +6,4 @@ gem 'fastlane-plugin-versioning' gem 'fastlane-plugin-emerge' gem 'fastlane-plugin-sonarcloud_metric_kit' gem 'fastlane-plugin-stream_actions', '0.3.20' +gem 'fastlane-plugin-create_xcframework'