From e63091c18cd58b837f3dc2bae80f88e882e23a10 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Wed, 22 Aug 2018 17:54:48 +0800 Subject: [PATCH 01/35] =?UTF-8?q?Fixed=20boundingRect(with:options:)=20mis?= =?UTF-8?q?calculation=20of=20MessageLabel=20like=20text=20=E1=8F=8A=CB=98?= =?UTF-8?q?=CC=B4=CD=88=CC=81=EA=88=8A=CB=98=CC=B4=CD=88=CC=80=E1=8F=8A?= =?UTF-8?q?=E2=8B=86=E2=9C=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ Sources/Layout/MessageSizeCalculator.swift | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd7961a2..1195ab394 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa ## Upcoming release +### Fixed + +- Fixed `boundingRect(with:options:)` miscalculation of `MessageLabel` , like text `Ꮚ˘̴͈́ꈊ˘̴͈̀Ꮚ⋆✩`、`Tomorrow is the day`. +[#824](https://github.com/MessageKit/MessageKit/pull/824) by [@zhongwuzw](https://github.com/zhongwuzw). + ### Changed - The `MessageData.emoji` case once again uses a default font of 2x the `messageLabelFont` size. diff --git a/Sources/Layout/MessageSizeCalculator.swift b/Sources/Layout/MessageSizeCalculator.swift index 7e563629b..ef7a5ae32 100644 --- a/Sources/Layout/MessageSizeCalculator.swift +++ b/Sources/Layout/MessageSizeCalculator.swift @@ -24,6 +24,8 @@ import Foundation +private let additionalWidthForBoundingRectCalculation: CGFloat = 5.0 + open class MessageSizeCalculator: CellSizeCalculator { public init(layout: MessagesCollectionViewFlowLayout? = nil) { @@ -216,8 +218,9 @@ open class MessageSizeCalculator: CellSizeCalculator { internal func labelSize(for attributedText: NSAttributedString, considering maxWidth: CGFloat) -> CGSize { let constraintBox = CGSize(width: maxWidth, height: .greatestFiniteMagnitude) let rect = attributedText.boundingRect(with: constraintBox, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).integral - - return rect.size + + // `boundingRect` method maybe not calculate correctly, like `Ꮚ˘̴͈́ꈊ˘̴͈̀Ꮚ⋆✩`, so we add 5 points to fix them temporary. + return CGSize(width: rect.width + additionalWidthForBoundingRectCalculation, height: rect.height) } } From 99c9e3f26749cb40869303450c20b155fbd32417 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Fri, 7 Sep 2018 15:52:12 +0800 Subject: [PATCH 02/35] Using NSLayoutManager to calculate size --- CHANGELOG.md | 2 +- Sources/Layout/MessageSizeCalculator.swift | 29 ++++++++++++++++++---- Sources/Views/MessageLabel.swift | 2 +- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1195ab394..882c57959 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa ### Fixed -- Fixed `boundingRect(with:options:)` miscalculation of `MessageLabel` , like text `Ꮚ˘̴͈́ꈊ˘̴͈̀Ꮚ⋆✩`、`Tomorrow is the day`. +- Fixed `boundingRect(with:options:)` miscalculation of `MessageLabel` by using `NSLayoutManager`, like text `Ꮚ˘̴͈́ꈊ˘̴͈̀Ꮚ⋆✩`、`Tomorrow is the day`. [#824](https://github.com/MessageKit/MessageKit/pull/824) by [@zhongwuzw](https://github.com/zhongwuzw). ### Changed diff --git a/Sources/Layout/MessageSizeCalculator.swift b/Sources/Layout/MessageSizeCalculator.swift index ef7a5ae32..af8c92333 100644 --- a/Sources/Layout/MessageSizeCalculator.swift +++ b/Sources/Layout/MessageSizeCalculator.swift @@ -24,8 +24,6 @@ import Foundation -private let additionalWidthForBoundingRectCalculation: CGFloat = 5.0 - open class MessageSizeCalculator: CellSizeCalculator { public init(layout: MessagesCollectionViewFlowLayout? = nil) { @@ -51,6 +49,23 @@ open class MessageSizeCalculator: CellSizeCalculator { public var incomingMessageBottomLabelAlignment = LabelAlignment(textAlignment: .left, textInsets: UIEdgeInsets(left: 42)) public var outgoingMessageBottomLabelAlignment = LabelAlignment(textAlignment: .right, textInsets: UIEdgeInsets(right: 42)) + + private lazy var textContainer: NSTextContainer = { + let textContainer = NSTextContainer() + textContainer.maximumNumberOfLines = 0 + textContainer.lineFragmentPadding = 0 + return textContainer + }() + private lazy var layoutManager: NSLayoutManager = { + let layoutManager = NSLayoutManager() + layoutManager.addTextContainer(textContainer) + return layoutManager + }() + private lazy var textStorage: NSTextStorage = { + let textStorage = NSTextStorage() + textStorage.addLayoutManager(layoutManager) + return textStorage + }() open override func configure(attributes: UICollectionViewLayoutAttributes) { guard let attributes = attributes as? MessagesCollectionViewLayoutAttributes else { return } @@ -217,10 +232,14 @@ open class MessageSizeCalculator: CellSizeCalculator { internal func labelSize(for attributedText: NSAttributedString, considering maxWidth: CGFloat) -> CGSize { let constraintBox = CGSize(width: maxWidth, height: .greatestFiniteMagnitude) - let rect = attributedText.boundingRect(with: constraintBox, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).integral - // `boundingRect` method maybe not calculate correctly, like `Ꮚ˘̴͈́ꈊ˘̴͈̀Ꮚ⋆✩`, so we add 5 points to fix them temporary. - return CGSize(width: rect.width + additionalWidthForBoundingRectCalculation, height: rect.height) + textContainer.size = constraintBox + textStorage.replaceCharacters(in: NSRange(location: 0, length: textStorage.length), with: attributedText) + layoutManager.ensureLayout(for: textContainer) + + let size = layoutManager.usedRect(for: textContainer).size + + return CGSize(width: size.width.rounded(.up), height: size.height.rounded(.up)) } } diff --git a/Sources/Views/MessageLabel.swift b/Sources/Views/MessageLabel.swift index 7270e8051..60636833d 100644 --- a/Sources/Views/MessageLabel.swift +++ b/Sources/Views/MessageLabel.swift @@ -172,7 +172,7 @@ open class MessageLabel: UILabel { open override func drawText(in rect: CGRect) { let insetRect = UIEdgeInsetsInsetRect(rect, textInsets) - textContainer.size = CGSize(width: insetRect.width, height: rect.height) + textContainer.size = CGSize(width: insetRect.width, height: insetRect.height) let origin = insetRect.origin let range = layoutManager.glyphRange(for: textContainer) From 4f5ee57d1b0087d84ed41a5c6f58c56c00de8468 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Wed, 23 Aug 2023 11:16:22 +0200 Subject: [PATCH 03/35] Update to latest IBAV --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 0ed44c8fb..5c9f5d394 100644 --- a/Package.swift +++ b/Package.swift @@ -31,7 +31,7 @@ let package = Package( .plugin(name: "SwiftFormatPlugin", targets: ["SwiftFormatPlugin"]), ], dependencies: [ - .package(url: "https://github.com/nathantannar4/InputBarAccessoryView", .upToNextMajor(from: "6.1.0")), + .package(url: "https://github.com/nathantannar4/InputBarAccessoryView", .upToNextMajor(from: "6.3.0")), ], targets: [ // MARK: - MessageKit From b5ec6825064ce0873eb8966e5ceebfedaeb85d16 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Wed, 23 Aug 2023 11:17:45 +0200 Subject: [PATCH 04/35] Changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e88fa51c..ada097519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa ### Added ### Fixed + +### Updated + +- Update InputBarAccessoryView to fix some crashes and issues by [@kaspik](https://github.com/Kaspik) ### Changed From 6304caaf889e6b8c5fc6372e9b7cebbc5e877e9f Mon Sep 17 00:00:00 2001 From: Jan de Vries Date: Wed, 23 Aug 2023 20:16:56 +0200 Subject: [PATCH 05/35] fixed minor warning in example app --- Example/Sources/View Controllers/ChatViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/Sources/View Controllers/ChatViewController.swift b/Example/Sources/View Controllers/ChatViewController.swift index f42f903df..53af2d06d 100644 --- a/Example/Sources/View Controllers/ChatViewController.swift +++ b/Example/Sources/View Controllers/ChatViewController.swift @@ -333,7 +333,7 @@ extension ChatViewController: InputBarAccessoryViewDelegate { let substring = attributedText.attributedSubstring(from: range) let context = substring.attribute(.autocompletedContext, at: 0, effectiveRange: nil) - print("Autocompleted: `", substring, "` with context: ", context ?? []) + print("Autocompleted: `", substring, "` with context: ", context ?? "-") } let components = inputBar.inputTextView.components From 7809a5b82cffb0167429c958a6caea5a65a48bb2 Mon Sep 17 00:00:00 2001 From: Jan de Vries Date: Wed, 23 Aug 2023 20:21:11 +0200 Subject: [PATCH 06/35] fixed IBAV position issue in the SwiftUI example by adding ignoresSafeArea modifier to the body (iOS 14+) --- .../Sources/Views/SwiftUI/SwiftUIExampleView.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Example/Sources/Views/SwiftUI/SwiftUIExampleView.swift b/Example/Sources/Views/SwiftUI/SwiftUIExampleView.swift index 12c69c028..b4fd02bc0 100644 --- a/Example/Sources/Views/SwiftUI/SwiftUIExampleView.swift +++ b/Example/Sources/Views/SwiftUI/SwiftUIExampleView.swift @@ -23,9 +23,20 @@ struct SwiftUIExampleView: View { self.cleanupSocket() } .navigationBarTitle("SwiftUI Example", displayMode: .inline) + .modifier(IgnoresSafeArea()) //fixes issue with IBAV placement when keyboard appears } // MARK: Private + + private struct IgnoresSafeArea: ViewModifier { + func body(content: Content) -> some View { + if #available(iOS 14.0, *) { + content.ignoresSafeArea(.keyboard, edges: .bottom) + } else { + content + } + } + } private func connectToMessageSocket() { MockSocket.shared.connect(with: [SampleData.shared.nathan, SampleData.shared.wu]).onNewMessage { message in From 9f48149297e6cd0d676bcfbb78b4858af31b0a59 Mon Sep 17 00:00:00 2001 From: Joe Puccio Date: Sun, 27 Aug 2023 19:29:44 -0400 Subject: [PATCH 07/35] Added Coursicle to the list of apps using MessageKit Coursicle began using MessageKit in production on August 21st, 2023. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5313b0350..12824dc32 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,7 @@ Interested in contributing to MessageKit? Click here to join our [Slack](https:/ Add your app to the list of apps using this library and make a pull request. - [ClassDojo](https://www.classdojo.com) +- [Coursicle](https://apps.apple.com/us/app/coursicle/id1187418307) - [Connect Messaging](https://apps.apple.com/app/id1607268774) - [Ring4](https://www.ring4.com) - [Formacar](https://itunes.apple.com/ru/app/id1180117334) From 9ecaf1fa07288c98cf4ba2e6afb719021291c6be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kutay=20Karakam=C4=B1s=CC=A7?= Date: Fri, 1 Sep 2023 15:54:19 +0300 Subject: [PATCH 08/35] duration Nan issue fix If audio url has authentication, sometimes duration came as Nan. Integer(NaN) causes crash. --- Sources/Protocols/MessagesDisplayDelegate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Protocols/MessagesDisplayDelegate.swift b/Sources/Protocols/MessagesDisplayDelegate.swift index b012d7851..2548fde8f 100644 --- a/Sources/Protocols/MessagesDisplayDelegate.swift +++ b/Sources/Protocols/MessagesDisplayDelegate.swift @@ -385,7 +385,7 @@ extension MessagesDisplayDelegate { returnValue = String(format: "0:%.02d", Int(duration.rounded(.up))) } else if duration < 3600 { returnValue = String(format: "%.02d:%.02d", Int(duration / 60), Int(duration) % 60) - } else { + } else if duration.isFinite { let hours = Int(duration / 3600) let remainingMinutesInSeconds = Int(duration) - hours * 3600 returnValue = String( From 077d8b942f34b8a13375f2691c813ec46a4deaa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Tue, 26 Sep 2023 13:49:14 +0200 Subject: [PATCH 09/35] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5313b0350..2e45a7478 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ Great! Look over these things first. - Please read our [Code of Conduct](https://github.com/MessageKit/MessageKit/blob/master/CODE_OF_CONDUCT.md) - Check the [Contributing Guide Lines](https://github.com/MessageKit/MessageKit/blob/master/CONTRIBUTING.md). -- Come join us on [Slack](https://join.slack.com/t/messagekit/shared_invite/MjI4NzIzNzMyMzU0LTE1MDMwODIzMDUtYzllYzIyNTU4MA) and 🗣 don't be a stranger. +- Come join us on [Slack](https://join.slack.com/t/messagekit/shared_invite/zt-2484ymok0-O82~1EtnHALSngQvn6Xwyw) and 🗣 don't be a stranger. - Check out the [current issues](https://github.com/MessageKit/MessageKit/issues) and see if you can tackle any of those. - Download the project and check out the current code base. Suggest any improvements by opening a new issue. - Check out the [What's Next](#whats-next) section :point_down: to see where we are headed. From 948eaf19e00ac38ec7644336355d9379c3d8268e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 27 Sep 2023 15:23:47 +0200 Subject: [PATCH 10/35] Update danger.yml --- .github/workflows/danger.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 78ecf1893..8cf94f27d 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -1,8 +1,6 @@ name: Danger -on: - pull_request_target: - types: [opened, reopened, synchronize, ready_for_review] +on: pull_request # This allows a subsequently queued workflow run to interrupt previous runs concurrency: @@ -13,8 +11,6 @@ jobs: danger: name: Run Danger runs-on: macos-13 - env: - DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer steps: - name: Checkout the Git repository uses: actions/checkout@v3 From e57a91b022afcfe07712cc214905d0f55889a967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 27 Sep 2023 15:25:10 +0200 Subject: [PATCH 11/35] Delete .github/workflows/danger.yml --- .github/workflows/danger.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .github/workflows/danger.yml diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml deleted file mode 100644 index 8cf94f27d..000000000 --- a/.github/workflows/danger.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Danger - -on: pull_request - -# This allows a subsequently queued workflow run to interrupt previous runs -concurrency: - group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' - cancel-in-progress: true - -jobs: - danger: - name: Run Danger - runs-on: macos-13 - steps: - - name: Checkout the Git repository - uses: actions/checkout@v3 - with: - fetch-depth: 40 - token: ${{ secrets.GITHUB_TOKEN }} - ref: ${{ github.event.pull_request.head.ref }} - - name: Resolve SwiftPM dependencies - run: rm -rf ".build" && swift package clean && swift package resolve - - name: Run build script - run: gem install bundler && bundle install && bundle exec danger --fail-on-errors=true - env: - DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} From a995dd3ca5613938c86f84ce68ec212814549d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 27 Sep 2023 15:25:30 +0200 Subject: [PATCH 12/35] Update ci_pr_example.yml --- .github/workflows/ci_pr_example.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci_pr_example.yml b/.github/workflows/ci_pr_example.yml index cb3215700..e8e3817e5 100644 --- a/.github/workflows/ci_pr_example.yml +++ b/.github/workflows/ci_pr_example.yml @@ -11,8 +11,6 @@ jobs: tests: name: Build Example app runs-on: macos-13 - env: - DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer steps: - name: Checkout the Git repository uses: actions/checkout@v3 From 92214f84e3401b4cd56a991b4dd7bbbad840fca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 27 Sep 2023 15:25:40 +0200 Subject: [PATCH 13/35] Update ci_pr_framework.yml --- .github/workflows/ci_pr_framework.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci_pr_framework.yml b/.github/workflows/ci_pr_framework.yml index b2a79229d..9a5653a1b 100644 --- a/.github/workflows/ci_pr_framework.yml +++ b/.github/workflows/ci_pr_framework.yml @@ -11,8 +11,6 @@ jobs: tests: name: Build Framework runs-on: macos-13 - env: - DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer steps: - name: Checkout the Git repository uses: actions/checkout@v3 From eed01474ad6b609fa9244ebdc73896bf3e5e0b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 27 Sep 2023 15:25:52 +0200 Subject: [PATCH 14/35] Update ci_pr_tests.yml --- .github/workflows/ci_pr_tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci_pr_tests.yml b/.github/workflows/ci_pr_tests.yml index e5e35f91a..298045677 100644 --- a/.github/workflows/ci_pr_tests.yml +++ b/.github/workflows/ci_pr_tests.yml @@ -11,8 +11,6 @@ jobs: tests: name: Run Tests runs-on: macos-13 - env: - DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer steps: - name: Checkout the Git repository uses: actions/checkout@v3 From 6bb85867775e12133a8014a4107045b6f9052c4b Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Fri, 20 Oct 2023 17:45:51 +0200 Subject: [PATCH 15/35] From yokochi/MessageKit/pull/1 --- Sources/Layout/MessageSizeCalculator.swift | 28 ++++++++++++++++++---- Sources/Views/MessageLabel.swift | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Sources/Layout/MessageSizeCalculator.swift b/Sources/Layout/MessageSizeCalculator.swift index 1d9065c9e..099487215 100644 --- a/Sources/Layout/MessageSizeCalculator.swift +++ b/Sources/Layout/MessageSizeCalculator.swift @@ -316,15 +316,33 @@ open class MessageSizeCalculator: CellSizeCalculator { } // MARK: Internal + internal lazy var textContainer: NSTextContainer = { + let textContainer = NSTextContainer() + textContainer.maximumNumberOfLines = 0 + textContainer.lineFragmentPadding = 0 + return textContainer + }() + internal lazy var layoutManager: NSLayoutManager = { + let layoutManager = NSLayoutManager() + layoutManager.addTextContainer(textContainer) + return layoutManager + }() + internal lazy var textStorage: NSTextStorage = { + let textStorage = NSTextStorage() + textStorage.addLayoutManager(layoutManager) + return textStorage + }() internal func labelSize(for attributedText: NSAttributedString, considering maxWidth: CGFloat) -> CGSize { let constraintBox = CGSize(width: maxWidth, height: .greatestFiniteMagnitude) - let rect = attributedText.boundingRect( - with: constraintBox, - options: [.usesLineFragmentOrigin, .usesFontLeading], - context: nil).integral - return rect.size + textContainer.size = constraintBox + textStorage.replaceCharacters(in: NSRange(location: 0, length: textStorage.length), with: attributedText) + layoutManager.ensureLayout(for: textContainer) + + let size = layoutManager.usedRect(for: textContainer).size + + return CGSize(width: size.width.rounded(.up), height: size.height.rounded(.up)) } } diff --git a/Sources/Views/MessageLabel.swift b/Sources/Views/MessageLabel.swift index feb9c95a6..91f388a82 100644 --- a/Sources/Views/MessageLabel.swift +++ b/Sources/Views/MessageLabel.swift @@ -130,7 +130,7 @@ open class MessageLabel: UILabel { open override func drawText(in rect: CGRect) { let insetRect = rect.inset(by: textInsets) - textContainer.size = CGSize(width: insetRect.width, height: rect.height) + textContainer.size = CGSize(width: insetRect.width, height: insetRect.height) let origin = insetRect.origin let range = layoutManager.glyphRange(for: textContainer) From e4eb3f3d4d1ff2c13b0797b4474ac774269febbf Mon Sep 17 00:00:00 2001 From: Fabrizio D'Urso Date: Sat, 11 Nov 2023 15:17:18 +0000 Subject: [PATCH 16/35] Add OutyPlay to list of apps using MessageKit Thanks a lot for the amazing work! --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0e2dbc1d7..d34412a50 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,7 @@ Add your app to the list of apps using this library and make a pull request. - [XPASS](https://apps.apple.com/cz/app/id1596773834) - [HeiaHeia](https://www.heiaheia.com) - [Starstruck AI](https://apps.apple.com/au/app/starstruck-message-anyone/id6446234281) +- [OutyPlay](https://apps.apple.com/app/id6450551793) _Please provide attribution, it is greatly appreciated._ From 5166b9b23cca67235de81aa501309c2dbc49a2a2 Mon Sep 17 00:00:00 2001 From: Artem Trubacheev Date: Tue, 14 Nov 2023 14:36:26 +0400 Subject: [PATCH 17/35] Added ability to specify additionalBottomSpace for keyboardManager --- Sources/Controllers/MessagesViewController+Keyboard.swift | 5 ++++- Sources/Controllers/MessagesViewController.swift | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Sources/Controllers/MessagesViewController+Keyboard.swift b/Sources/Controllers/MessagesViewController+Keyboard.swift index 90ab8efa3..be3723316 100644 --- a/Sources/Controllers/MessagesViewController+Keyboard.swift +++ b/Sources/Controllers/MessagesViewController+Keyboard.swift @@ -31,7 +31,10 @@ extension MessagesViewController { // MARK: - Register Observers internal func addKeyboardObservers() { - keyboardManager.bind(inputAccessoryView: inputContainerView) + keyboardManager.bind( + inputAccessoryView: inputContainerView, + withAdditionalBottomSpace: { [weak self] in self?.inputBarAdditionalBottomSpace() ?? 0 } + ) keyboardManager.bind(to: messagesCollectionView) /// Observe didBeginEditing to scroll content to last item if necessary diff --git a/Sources/Controllers/MessagesViewController.swift b/Sources/Controllers/MessagesViewController.swift index 7d21bf7bd..1046517d5 100644 --- a/Sources/Controllers/MessagesViewController.swift +++ b/Sources/Controllers/MessagesViewController.swift @@ -66,6 +66,11 @@ open class MessagesViewController: UIViewController, UICollectionViewDelegateFlo } } + /// withAdditionalBottomSpace parameter for InputBarAccessoryView's KeyboardManager + open func inputBarAdditionalBottomSpace() -> CGFloat { + 0 + } + open override func viewDidLoad() { super.viewDidLoad() setupDefaults() From 79192d5ed1194f5c8ab6a4f21f90b8ef2fa67e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 21 Feb 2024 09:17:48 +0100 Subject: [PATCH 18/35] Update Makefile --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 0343d308b..87ab6715a 100644 --- a/Makefile +++ b/Makefile @@ -25,15 +25,15 @@ test: @echo "Running MessageKit tests." - @set -o pipefail && xcodebuild test -scheme MessageKit -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 14" | xcpretty -c + @set -o pipefail && xcodebuild test -scheme MessageKit -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 15" | xcpretty -c framework: @echo "Building MessageKit Framework." - @set -o pipefail && xcodebuild build -scheme MessageKit -destination "platform=iOS Simulator,name=iPhone 14" | xcpretty -c + @set -o pipefail && xcodebuild build -scheme MessageKit -destination "platform=iOS Simulator,name=iPhone 15" | xcpretty -c build_example: @echo "Building & testing MessageKit Example app." - @cd Example && set -o pipefail && xcodebuild build analyze -scheme ChatExample -destination "platform=iOS Simulator,name=iPhone 14" CODE_SIGNING_REQUIRED=NO | xcpretty -c + @cd Example && set -o pipefail && xcodebuild build analyze -scheme ChatExample -destination "platform=iOS Simulator,name=iPhone 15" CODE_SIGNING_REQUIRED=NO | xcpretty -c format: @swift package --allow-writing-to-package-directory format-source-code --file . From 15e8dc07fc143b073ea9c0bfe5dd334f4c3300b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 21 Feb 2024 09:21:40 +0100 Subject: [PATCH 19/35] Update ci_pr_tests.yml --- .github/workflows/ci_pr_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_pr_tests.yml b/.github/workflows/ci_pr_tests.yml index 298045677..0d9faae68 100644 --- a/.github/workflows/ci_pr_tests.yml +++ b/.github/workflows/ci_pr_tests.yml @@ -10,7 +10,7 @@ concurrency: jobs: tests: name: Run Tests - runs-on: macos-13 + runs-on: macos-14 steps: - name: Checkout the Git repository uses: actions/checkout@v3 From 3c63339b6eb2d8fd91aa9d3d256bc8f30b07bb57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 21 Feb 2024 09:23:09 +0100 Subject: [PATCH 20/35] Update ci_pr_example.yml --- .github/workflows/ci_pr_example.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_pr_example.yml b/.github/workflows/ci_pr_example.yml index e8e3817e5..437310337 100644 --- a/.github/workflows/ci_pr_example.yml +++ b/.github/workflows/ci_pr_example.yml @@ -10,10 +10,10 @@ concurrency: jobs: tests: name: Build Example app - runs-on: macos-13 + runs-on: macos-14 steps: - name: Checkout the Git repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 10 - name: Build and run example project From 077fa6fde4f52864dee790911f414b618cf68bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 21 Feb 2024 09:23:23 +0100 Subject: [PATCH 21/35] Update ci_pr_framework.yml --- .github/workflows/ci_pr_framework.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_pr_framework.yml b/.github/workflows/ci_pr_framework.yml index 9a5653a1b..da5365c13 100644 --- a/.github/workflows/ci_pr_framework.yml +++ b/.github/workflows/ci_pr_framework.yml @@ -10,9 +10,9 @@ concurrency: jobs: tests: name: Build Framework - runs-on: macos-13 + runs-on: macos-14 steps: - name: Checkout the Git repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build framework run: make framework From 15cc36d6e643216e75db5a983c9e67b2c190a6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 21 Feb 2024 09:23:34 +0100 Subject: [PATCH 22/35] Update ci_pr_tests.yml --- .github/workflows/ci_pr_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_pr_tests.yml b/.github/workflows/ci_pr_tests.yml index 0d9faae68..0c1058452 100644 --- a/.github/workflows/ci_pr_tests.yml +++ b/.github/workflows/ci_pr_tests.yml @@ -13,6 +13,6 @@ jobs: runs-on: macos-14 steps: - name: Checkout the Git repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build and run tests run: make test From 9c23309e4e6f4821c9a1acb82f271e0d4fa09037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ka=C5=A1par?= Date: Wed, 21 Feb 2024 09:24:13 +0100 Subject: [PATCH 23/35] Update deploy_docs.yml --- .github/workflows/deploy_docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index ac3472478..9648963dd 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -15,10 +15,10 @@ concurrency: jobs: build_docs: - runs-on: macos-latest + runs-on: macos-14 steps: - name: Checkout 🛎️ - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build DocC run: | From f124ca36189792c328cf7a3f516446c022f80d60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 18:53:44 +0000 Subject: [PATCH 24/35] build(deps): Bump rexml from 3.2.5 to 3.2.8 Bumps [rexml](https://github.com/ruby/rexml) from 3.2.5 to 3.2.8. - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.2.5...v3.2.8) --- updated-dependencies: - dependency-name: rexml dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1ab5ad023..3aa7b934d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -70,11 +70,13 @@ GEM public_suffix (5.0.1) rake (13.0.6) rchardet (1.8.0) - rexml (3.2.5) + rexml (3.2.8) + strscan (>= 3.0.9) ruby2_keywords (0.0.5) sawyer (0.9.2) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) + strscan (3.1.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) thor (0.20.3) From 29beea1868921bc9e9ecb900e532fa4e6ec46adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Olmedo?= Date: Fri, 24 May 2024 17:08:47 +0200 Subject: [PATCH 25/35] Added listener for keyboard input mode changes (e.g. emoji keyboard) --- .../MessagesViewController+Keyboard.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Sources/Controllers/MessagesViewController+Keyboard.swift b/Sources/Controllers/MessagesViewController+Keyboard.swift index be3723316..7cb07c3d0 100644 --- a/Sources/Controllers/MessagesViewController+Keyboard.swift +++ b/Sources/Controllers/MessagesViewController+Keyboard.swift @@ -69,6 +69,20 @@ extension MessagesViewController { } .store(in: &disposeBag) + NotificationCenter.default + .publisher(for: UITextInputMode.currentInputModeDidChangeNotification) + .subscribe(on: DispatchQueue.global()) + .receive(on: DispatchQueue.main) + .removeDuplicates() + .sink { [weak self] _ in + self?.updateMessageCollectionViewBottomInset() + + if !(self?.maintainPositionOnInputBarHeightChanged ?? false) { + self?.messagesCollectionView.scrollToLastItem() + } + } + .store(in: &disposeBag) + /// Observe frame change of the input bar container to update collectioView bottom inset inputContainerView.publisher(for: \.center) .receive(on: DispatchQueue.main) From 944b0c828e462f5138f48d9c0dcc1ae3c765cad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Olmedo?= Date: Mon, 27 May 2024 19:01:04 +0200 Subject: [PATCH 26/35] Wait for the inputView to be laid out --- Sources/Controllers/MessagesViewController+Keyboard.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Controllers/MessagesViewController+Keyboard.swift b/Sources/Controllers/MessagesViewController+Keyboard.swift index 7cb07c3d0..974fa1077 100644 --- a/Sources/Controllers/MessagesViewController+Keyboard.swift +++ b/Sources/Controllers/MessagesViewController+Keyboard.swift @@ -74,6 +74,7 @@ extension MessagesViewController { .subscribe(on: DispatchQueue.global()) .receive(on: DispatchQueue.main) .removeDuplicates() + .delay(for: .milliseconds(50), scheduler: DispatchQueue.main) /// Wait for next runloop to lay out inputView properly .sink { [weak self] _ in self?.updateMessageCollectionViewBottomInset() From bf735591356ddb77e5f58d1bcfe58ffe7efde673 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Jul 2024 11:25:37 +0200 Subject: [PATCH 27/35] Example fixes --- Example/Sources/AppDelegate.swift | 1 + .../View Controllers/ChatViewController.swift | 1 - .../View Controllers/LaunchViewController.swift | 1 - .../MessageContainerController.swift | 12 ------------ .../MessageSubviewContainerViewController.swift | 12 ------------ 5 files changed, 1 insertion(+), 26 deletions(-) diff --git a/Example/Sources/AppDelegate.swift b/Example/Sources/AppDelegate.swift index 7959e015f..3cb9f9d4a 100644 --- a/Example/Sources/AppDelegate.swift +++ b/Example/Sources/AppDelegate.swift @@ -36,6 +36,7 @@ final internal class AppDelegate: UIResponder, UIApplicationDelegate { ] : [masterViewController] splitViewController.preferredDisplayMode = .allVisible + masterViewController.navigationItem.largeTitleDisplayMode = .never window = UIWindow(frame: UIScreen.main.bounds) window?.rootViewController = splitViewController diff --git a/Example/Sources/View Controllers/ChatViewController.swift b/Example/Sources/View Controllers/ChatViewController.swift index 53af2d06d..aeb2171ae 100644 --- a/Example/Sources/View Controllers/ChatViewController.swift +++ b/Example/Sources/View Controllers/ChatViewController.swift @@ -52,7 +52,6 @@ class ChatViewController: MessagesViewController, MessagesDataSource { override func viewDidLoad() { super.viewDidLoad() - navigationItem.largeTitleDisplayMode = .never navigationItem.title = "MessageKit" configureMessageCollectionView() diff --git a/Example/Sources/View Controllers/LaunchViewController.swift b/Example/Sources/View Controllers/LaunchViewController.swift index cb25821dd..90c42b894 100644 --- a/Example/Sources/View Controllers/LaunchViewController.swift +++ b/Example/Sources/View Controllers/LaunchViewController.swift @@ -42,7 +42,6 @@ final internal class LaunchViewController: UITableViewController { super.viewDidLoad() title = "MessageKit" navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) - navigationController?.navigationBar.prefersLargeTitles = true navigationController?.navigationBar.tintColor = .primaryColor tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") tableView.tableFooterView = UIView() diff --git a/Example/Sources/View Controllers/MessageContainerController.swift b/Example/Sources/View Controllers/MessageContainerController.swift index 91ee8ff4e..24689ea3c 100644 --- a/Example/Sources/View Controllers/MessageContainerController.swift +++ b/Example/Sources/View Controllers/MessageContainerController.swift @@ -62,18 +62,6 @@ final class MessageContainerController: UIViewController { view.addSubview(bannerView) } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.navigationBar.isTranslucent = true - navigationController?.navigationBar.barTintColor = .clear - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - navigationController?.navigationBar.isTranslucent = false - navigationController?.navigationBar.barTintColor = .primaryColor - } - override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let headerHeight: CGFloat = 200 diff --git a/Example/Sources/View Controllers/MessageSubviewContainerViewController.swift b/Example/Sources/View Controllers/MessageSubviewContainerViewController.swift index 808019a92..ed6e116c0 100644 --- a/Example/Sources/View Controllers/MessageSubviewContainerViewController.swift +++ b/Example/Sources/View Controllers/MessageSubviewContainerViewController.swift @@ -39,16 +39,4 @@ final class MessageSubviewContainerViewController: UIViewController { view.addSubview(messageSubviewViewController.view) messageSubviewViewController.didMove(toParent: self) } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.navigationBar.isTranslucent = true - navigationController?.navigationBar.barTintColor = .clear - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - navigationController?.navigationBar.isTranslucent = false - navigationController?.navigationBar.barTintColor = .primaryColor - } } From 439bb19a6f37b574f91955b32fc4c466e5608d5c Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Jul 2024 11:32:52 +0200 Subject: [PATCH 28/35] Make keyboard manager public --- .../Sources/View Controllers/MessageSubviewViewController.swift | 2 -- Sources/Controllers/MessagesViewController+State.swift | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Example/Sources/View Controllers/MessageSubviewViewController.swift b/Example/Sources/View Controllers/MessageSubviewViewController.swift index 4f7e74f7f..04d128891 100644 --- a/Example/Sources/View Controllers/MessageSubviewViewController.swift +++ b/Example/Sources/View Controllers/MessageSubviewViewController.swift @@ -56,7 +56,5 @@ final class MessageSubviewViewController: BasicExampleViewController { // MARK: Private - private var keyboardManager = KeyboardManager() - private let subviewInputBar = InputBarAccessoryView() } diff --git a/Sources/Controllers/MessagesViewController+State.swift b/Sources/Controllers/MessagesViewController+State.swift index a00700980..d72c3d186 100644 --- a/Sources/Controllers/MessagesViewController+State.swift +++ b/Sources/Controllers/MessagesViewController+State.swift @@ -40,7 +40,7 @@ extension MessagesViewController { // MARK: - Getters - var keyboardManager: KeyboardManager { state.keyboardManager } + public var keyboardManager: KeyboardManager { state.keyboardManager } var panGesture: UIPanGestureRecognizer? { get { state.panGesture } From 11615e913d3082efdda38362374d072cc214838f Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Jul 2024 20:32:49 +0200 Subject: [PATCH 29/35] Fix example projects --- Example/ChatExample.xcodeproj/project.pbxproj | 2 +- .../View Controllers/MessageContainerController.swift | 5 ----- Package.swift | 4 ++-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Example/ChatExample.xcodeproj/project.pbxproj b/Example/ChatExample.xcodeproj/project.pbxproj index 1f646ec98..10cd6690b 100644 --- a/Example/ChatExample.xcodeproj/project.pbxproj +++ b/Example/ChatExample.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ diff --git a/Example/Sources/View Controllers/MessageContainerController.swift b/Example/Sources/View Controllers/MessageContainerController.swift index 24689ea3c..3fd11c7e0 100644 --- a/Example/Sources/View Controllers/MessageContainerController.swift +++ b/Example/Sources/View Controllers/MessageContainerController.swift @@ -44,11 +44,6 @@ final class MessageContainerController: UIViewController { conversationViewController.canBecomeFirstResponder } - /// Required for the `MessageInputBar` to be visible - override var inputAccessoryView: UIView? { - conversationViewController.inputAccessoryView - } - override func viewDidLoad() { super.viewDidLoad() diff --git a/Package.swift b/Package.swift index 5c9f5d394..b4665f40f 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.6 +// swift-tools-version:5.9 // MIT License // @@ -31,7 +31,7 @@ let package = Package( .plugin(name: "SwiftFormatPlugin", targets: ["SwiftFormatPlugin"]), ], dependencies: [ - .package(url: "https://github.com/nathantannar4/InputBarAccessoryView", .upToNextMajor(from: "6.3.0")), + .package(url: "https://github.com/nathantannar4/InputBarAccessoryView", .upToNextMajor(from: "6.4.0")), ], targets: [ // MARK: - MessageKit From 93511cad3b1eb822dc1e846e5e5ab9519b4fd32e Mon Sep 17 00:00:00 2001 From: Dmitry Khudyakov Date: Sat, 13 Jul 2024 20:57:10 +0600 Subject: [PATCH 30/35] Fix for overlapping detected matches --- Sources/Views/MessageLabel.swift | 24 ++++++++++++++++++- .../Controllers Test/MessageLabelTests.swift | 15 ++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Sources/Views/MessageLabel.swift b/Sources/Views/MessageLabel.swift index 91f388a82..036bc3565 100644 --- a/Sources/Views/MessageLabel.swift +++ b/Sources/Views/MessageLabel.swift @@ -363,7 +363,7 @@ open class MessageLabel: UILabel { .filter { $0.isCustom } .map { parseForMatches(with: $0, in: text, for: range) } .joined() - matches.append(contentsOf: regexs) + matches.append(contentsOf: removeOverlappingResults(Array(regexs))) // Get all Checking Types of detectors, except for .custom because they contain their own regex let detectorCheckingTypes = enabledDetectors @@ -402,6 +402,28 @@ open class MessageLabel: UILabel { fatalError("You must pass a .custom DetectorType") } } + + private func removeOverlappingResults(_ results: [NSTextCheckingResult]) -> [NSTextCheckingResult] + { + var filteredResults: [NSTextCheckingResult] = [] + + for result in results { + let overlappingResults = results.filter { $0.range.intersection(result.range)?.length ?? 0 > 0 } + + if overlappingResults.count <= 1 { + filteredResults.append(result) + continue + } + + guard !filteredResults.contains(where: { $0.range == result.range }) else { continue } + let maxRangeResult = overlappingResults.max { $0.range.upperBound - $0.range.lowerBound < $1.range.upperBound - $1.range.lowerBound } + if let maxRangeResult { + filteredResults.append(maxRangeResult) + } + } + + return filteredResults + } private func setRangesForDetectors(in checkingResults: [NSTextCheckingResult]) { guard checkingResults.isEmpty == false else { return } diff --git a/Tests/MessageKitTests/Controllers Test/MessageLabelTests.swift b/Tests/MessageKitTests/Controllers Test/MessageLabelTests.swift index 77f4eb647..4d1264768 100644 --- a/Tests/MessageKitTests/Controllers Test/MessageLabelTests.swift +++ b/Tests/MessageKitTests/Controllers Test/MessageLabelTests.swift @@ -82,6 +82,21 @@ final class MessageLabelTests: XCTestCase { let invalidMatches = extractCustomDetectors(for: detector, with: messageLabel) XCTAssertEqual(invalidMatches.count, 0) } + + func testCustomDetectionOverlapping() { + let testText = "address MNtz8Zz1cPD1CZadoc38jT5qeqeFBS6Aif can match multiple regex's" + + let messageLabel = MessageLabel() + let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key(rawValue: "Custom"): "CustomDetected"] + let detectors = [ + DetectorType.custom(try! NSRegularExpression(pattern: "(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}", options: .caseInsensitive)), + DetectorType.custom(try! NSRegularExpression(pattern: #"([3ML][\w]{26,33})|ltc1[\w]+"#, options: .caseInsensitive)), + DetectorType.custom(try! NSRegularExpression(pattern: "[qmN][a-km-zA-HJ-NP-Z1-9]{26,33}", options: .caseInsensitive))] + + set(text: testText, and: detectors, with: attributes, to: messageLabel) + let matches = detectors.map { extractCustomDetectors(for: $0, with: messageLabel) }.joined() + XCTAssertEqual(matches.count, 1) + } func testSyncBetweenAttributedAndText() { let messageLabel = MessageLabel() From 0be65a1f82670f65c4fdbdb55c03dd3ccea019da Mon Sep 17 00:00:00 2001 From: CocoaBob Date: Tue, 30 Jul 2024 18:51:40 -0400 Subject: [PATCH 31/35] Fix timestamp label layout when not in fullscreen --- Sources/Views/Cells/MessageContentCell.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/Views/Cells/MessageContentCell.swift b/Sources/Views/Cells/MessageContentCell.swift index 034180d5a..471f36c3b 100644 --- a/Sources/Views/Cells/MessageContentCell.swift +++ b/Sources/Views/Cells/MessageContentCell.swift @@ -365,9 +365,8 @@ open class MessageContentCell: MessageCollectionViewCell { open func layoutTimeLabelView(with attributes: MessagesCollectionViewLayoutAttributes) { let paddingLeft: CGFloat = 10 let origin = CGPoint( - x: UIScreen.main.bounds.width + paddingLeft, - y: messageContainerView.frame.minY + messageContainerView.frame.height * 0.5 - messageTimestampLabel - .font.ascender * 0.5) + x: self.frame.maxX + paddingLeft, + y: messageContainerView.frame.minY + messageContainerView.frame.height * 0.5 - messageTimestampLabel.font.ascender * 0.5) let size = CGSize(width: attributes.messageTimeLabelSize.width, height: attributes.messageTimeLabelSize.height) messageTimestampLabel.frame = CGRect(origin: origin, size: size) } From 1cbc212955d8619aa9e13bd9f6f6feb178dd6a7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 20:38:46 +0000 Subject: [PATCH 32/35] build(deps): Bump rexml from 3.2.8 to 3.3.6 Bumps [rexml](https://github.com/ruby/rexml) from 3.2.8 to 3.3.6. - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.2.8...v3.3.6) --- updated-dependencies: - dependency-name: rexml dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3aa7b934d..7af99e226 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -70,8 +70,8 @@ GEM public_suffix (5.0.1) rake (13.0.6) rchardet (1.8.0) - rexml (3.2.8) - strscan (>= 3.0.9) + rexml (3.3.6) + strscan ruby2_keywords (0.0.5) sawyer (0.9.2) addressable (>= 2.3.5) From 3dffe09b4f4804df305bcad3936337927b4c4d21 Mon Sep 17 00:00:00 2001 From: GitNirajHub Date: Thu, 29 Aug 2024 00:12:16 +0530 Subject: [PATCH 33/35] Added custom image masking --- .../bobbly.imageset/Contents.json | 23 ++++++++++++++++ .../bobbly.imageset/Group 1272628320.png | Bin 0 -> 490 bytes .../bobbly.imageset/Group 1272628320@2x.png | Bin 0 -> 953 bytes .../bobbly.imageset/Group 1272628320@3x.png | Bin 0 -> 1446 bytes .../BasicExampleViewController.swift | 6 ++++- Sources/Models/MessageStyle.swift | 25 +++++++++++++----- Sources/Views/MessageContainerView.swift | 4 +-- 7 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Contents.json create mode 100644 Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Group 1272628320.png create mode 100644 Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Group 1272628320@2x.png create mode 100644 Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Group 1272628320@3x.png diff --git a/Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Contents.json b/Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Contents.json new file mode 100644 index 000000000..307a7038d --- /dev/null +++ b/Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Group 1272628320.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Group 1272628320@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Group 1272628320@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Group 1272628320.png b/Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Group 1272628320.png new file mode 100644 index 0000000000000000000000000000000000000000..faaad6d77c0392bd4026623a613162e1ea6ad17b GIT binary patch literal 490 zcmV00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPD*B!YycxrQrS$9FoE4tkqwOASq7}Lj16~*pYnfq z-}$VhaPF5BOHUIF!&n#YI(L%Yu(fWSPwx6}j5W2EbTpSUy-CRt)h8vI=Fn+LSAThA;r{WI`T)r`_c9XH?}qnX*|4+8u>cHjy$6 zT$U#2?j;F`3gqSK8dV)Och}HTN7`2)YLGzd5m^`7lOOH5yXUm43<zyJUM07*qoM6N<$g5e#^KL7v# literal 0 HcmV?d00001 diff --git a/Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Group 1272628320@2x.png b/Example/Sources/Resources/Assets.xcassets/bobbly.imageset/Group 1272628320@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bdbde8f5a9a9162744c1574c2599e2ad002b92f3 GIT binary patch literal 953 zcmV;q14jIbP)rU z0#8+=5Zp6uFua>m`8xM?Ls8U!^;@Bdt!0xPw(@n_eg_cO_&R96Cwr#hY`FVTp{rH` zkiz-8Qpis7DdW%%>lA|O1Yli_61(k?z}jrDg_Q{kf&J6;7TBE3g@s zCCk)t?3dQ*u(S3L0~p6k-P37T4XhKL6&RZhk1e##-5;zH*hR~B0x-5lA++=E!RJc% z!Pjd6$iW)q3tvCG2U9z&Q@CaXATOIat`~1oXNk`RU<#+*Hz|QV5$CPIR4R2=5T*=? zZK7!=08^dx}oEdQ+ufO;ogwQJW8T^%j!B=+D& zTs^a{9(MI8ge`EnR)PGct3_Ors}jVs=)-p&eHRR{Z*BBpJb5VZJBYLEeG+{T16)Idbls9q?fY zVc_f6bafnkW4W`-=!l!>1Gou*Z%-RLcE?k9#E-jrA3_-Tb~VxG+|wB7W=tnr_7`3K z5CGq{%(3s09;S^qaRniE&ajRL7bhi z5C*QhyHU{@j~T={6E=wtRrrsU%KJ29)SPL zqc!ivmUYHs1aa;zX##-rw9$w0#`BJM9Zlq1_)!3`O->AQt?|Z(ce`}NP4wL`0A+G3 z^y2K7yKHej3;=3uJS1pn5YNM07@*cHHjHzJjwU>y0~n_5>h}50w&O5MpA=#K%w*lv|}#JXXCY0LyMz*7;*R*A0ALEm9q~~BFoh3B69D^l7j>kd8PVhxgb44AI8&A>GQ*V=#XU0ET#e z_KTq%aWX3gsME%oZaD37F#PiXpvHquU*3%2+OBSObw2>ONH(tK`nAJN0I*FS=rb?9xn?wxBZ(#e*d{ySdCd<>JK`oR zQvsb)Qc zLKt9+c?=8A{9Q?aZ>pR%7rjCR;5x`TaA|-Zp80JP{rQ_U0eleF00VrHr>}jg`^m-= z+nVSPkAJxQyxI|WvaCh)i>6X9zFL8>AUS?!wmH+?%07*qoM6N<$g0pp- AVE_OC literal 0 HcmV?d00001 diff --git a/Example/Sources/View Controllers/BasicExampleViewController.swift b/Example/Sources/View Controllers/BasicExampleViewController.swift index 00875b7a2..9f1994faa 100644 --- a/Example/Sources/View Controllers/BasicExampleViewController.swift +++ b/Example/Sources/View Controllers/BasicExampleViewController.swift @@ -67,7 +67,11 @@ extension BasicExampleViewController: MessagesDisplayDelegate { func messageStyle(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> MessageStyle { let tail: MessageStyle.TailCorner = isFromCurrentSender(message: message) ? .bottomRight : .bottomLeft - return .bubbleTail(tail, .curved) + if let image = UIImage(named: "bobbly") { + return .customImageTail(image, tail) + } else { + return .bubbleTail(tail, .curved) + } } func configureAvatarView(_ avatarView: AvatarView, for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) { diff --git a/Sources/Models/MessageStyle.swift b/Sources/Models/MessageStyle.swift index 7fbbbd212..fcdbbf60f 100644 --- a/Sources/Models/MessageStyle.swift +++ b/Sources/Models/MessageStyle.swift @@ -30,6 +30,7 @@ public enum MessageStyle { case bubbleOutline(UIColor) case bubbleTail(TailCorner, TailStyle) case bubbleTailOutline(UIColor, TailCorner, TailStyle) + case customImageTail(UIImage,TailCorner) case custom((MessageContainerView) -> Void) // MARK: Public @@ -75,6 +76,20 @@ public enum MessageStyle { { return cachedImage } + + func strechAndCache(image: UIImage) -> UIImage { + let stretchedImage = stretch(image) + if let imageCacheKey = imageCacheKey { + MessageStyle.bubbleImageCache.setObject(stretchedImage, forKey: imageCacheKey as NSString) + } + return stretchedImage + } + + if case .customImageTail(let image, let corner) = self { + guard let cgImage = image.cgImage else { return nil } + let image = UIImage(cgImage: cgImage, scale: image.scale, orientation: corner.imageOrientation) + return strechAndCache(image: image) + } guard let imageName = imageName, @@ -86,18 +101,14 @@ public enum MessageStyle { switch self { case .none, .custom: return nil - case .bubble, .bubbleOutline: + case .bubble, .bubbleOutline, .customImageTail: break case .bubbleTail(let corner, _), .bubbleTailOutline(_, let corner, _): guard let cgImage = image.cgImage else { return nil } image = UIImage(cgImage: cgImage, scale: image.scale, orientation: corner.imageOrientation) } - let stretchedImage = stretch(image) - if let imageCacheKey = imageCacheKey { - MessageStyle.bubbleImageCache.setObject(stretchedImage, forKey: imageCacheKey as NSString) - } - return stretchedImage + return strechAndCache(image: image) } // MARK: Internal @@ -133,7 +144,7 @@ public enum MessageStyle { return "bubble_full" + tailStyle.imageNameSuffix case .bubbleTailOutline(_, _, let tailStyle): return "bubble_outlined" + tailStyle.imageNameSuffix - case .none, .custom: + case .none, .custom, .customImageTail: return nil } } diff --git a/Sources/Views/MessageContainerView.swift b/Sources/Views/MessageContainerView.swift index bcc5e3a64..e816f0d19 100644 --- a/Sources/Views/MessageContainerView.swift +++ b/Sources/Views/MessageContainerView.swift @@ -49,14 +49,14 @@ open class MessageContainerView: UIImageView { switch style { case .none, .custom: break - case .bubble, .bubbleTail, .bubbleOutline, .bubbleTailOutline: + case .bubble, .bubbleTail, .bubbleOutline, .bubbleTailOutline, .customImageTail: imageMask.frame = bounds } } private func applyMessageStyle() { switch style { - case .bubble, .bubbleTail: + case .bubble, .bubbleTail, .customImageTail: imageMask.image = style.image sizeMaskToView() mask = imageMask From 6b495662fb22ae4e7b8e3efa98e8d9e51f585850 Mon Sep 17 00:00:00 2001 From: Johannes Ebeling Date: Tue, 10 Sep 2024 11:42:03 +0200 Subject: [PATCH 34/35] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rename=20plugins=20t?= =?UTF-8?q?o=20avoid=20clashing=20with=20SwiftLintPlugins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Package.swift | 12 ++++++------ .../SwiftLintCommandPlugin.swift | 0 .../SwiftLintPlugin.swift | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename Plugins/{SwiftLintCommandPlugin => LintCommandPlugin}/SwiftLintCommandPlugin.swift (100%) rename Plugins/{SwiftLintPlugin => LintPlugin}/SwiftLintPlugin.swift (97%) diff --git a/Package.swift b/Package.swift index b4665f40f..5e487dbcb 100644 --- a/Package.swift +++ b/Package.swift @@ -27,7 +27,7 @@ let package = Package( platforms: [.iOS(.v13)], products: [ .library(name: "MessageKit", targets: ["MessageKit"]), - .plugin(name: "SwiftLintPlugin", targets: ["SwiftLintPlugin"]), + .plugin(name: "LintPlugin", targets: ["LintPlugin"]), .plugin(name: "SwiftFormatPlugin", targets: ["SwiftFormatPlugin"]), ], dependencies: [ @@ -48,24 +48,24 @@ let package = Package( // MARK: - Plugins .binaryTarget( - name: "SwiftLintBinary", + name: "LintBinary", url: "https://github.com/realm/SwiftLint/releases/download/0.47.1/SwiftLintBinary-macos.artifactbundle.zip", checksum: "82ef90b7d76b02e41edd73423687d9cedf0bb9849dcbedad8df3a461e5a7b555" ), .plugin( - name: "SwiftLintPlugin", + name: "LintPlugin", capability: .buildTool(), - dependencies: ["SwiftLintBinary"] + dependencies: ["LintBinary"] ), .plugin( - name: "SwiftLintCommandPlugin", + name: "LintCommandPlugin", capability: .command( intent: .custom( verb: "lint", description: "Lint Swift source files" ) ), - dependencies: ["SwiftLintBinary"] + dependencies: ["LintBinary"] ), .binaryTarget( diff --git a/Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift b/Plugins/LintCommandPlugin/SwiftLintCommandPlugin.swift similarity index 100% rename from Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift rename to Plugins/LintCommandPlugin/SwiftLintCommandPlugin.swift diff --git a/Plugins/SwiftLintPlugin/SwiftLintPlugin.swift b/Plugins/LintPlugin/SwiftLintPlugin.swift similarity index 97% rename from Plugins/SwiftLintPlugin/SwiftLintPlugin.swift rename to Plugins/LintPlugin/SwiftLintPlugin.swift index 174d2a0f2..e88b10abd 100644 --- a/Plugins/SwiftLintPlugin/SwiftLintPlugin.swift +++ b/Plugins/LintPlugin/SwiftLintPlugin.swift @@ -21,7 +21,7 @@ import PackagePlugin @main -struct SwiftLintPlugin: BuildToolPlugin { +struct LintPlugin: BuildToolPlugin { func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] { [ .buildCommand( From b024c1287ac30fb6ea2ee07169e6193efc11d972 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Mon, 14 Oct 2024 09:12:35 +0200 Subject: [PATCH 35/35] Bump to Swift 5.10 --- CHANGELOG.md | 17 +++++++++++++++++ Package.swift | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2373e7a3f..9cdd2b6c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,23 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa ### Removed +## 4.3.0 +- Fix for SwiftUI example IBAV position issues (example app) by @Janneman84 in https://github.com/MessageKit/MessageKit/pull/1807 +- Added Coursicle to the list of apps using MessageKit by @monstermac77 in https://github.com/MessageKit/MessageKit/pull/1809 +- duration NaN issue fix by @kkarakamis in https://github.com/MessageKit/MessageKit/pull/1812 +- Add OutyPlay to list of apps using MessageKit by @fabdurso in https://github.com/MessageKit/MessageKit/pull/1820 +- Fix #816 by @RomanPodymov in https://github.com/MessageKit/MessageKit/pull/1819 +- Update Makefile by @Kaspik in https://github.com/MessageKit/MessageKit/pull/1833 +- Added ability to specify additionalBottomSpace for keyboardManager by @Almaz5200 in https://github.com/MessageKit/MessageKit/pull/1821 +- build(deps): Bump rexml from 3.2.5 to 3.2.8 by @dependabot in https://github.com/MessageKit/MessageKit/pull/1839 +- Added listener for keyboard input mode changes (e.g. emoji keyboard) by @raulolmedocheca in https://github.com/MessageKit/MessageKit/pull/1842 +- build(deps): Bump rexml from 3.2.8 to 3.3.6 by @dependabot in https://github.com/MessageKit/MessageKit/pull/1858 +- Fix for overlapping detected matches by @SkiTles55 in https://github.com/MessageKit/MessageKit/pull/1853 +- Fix timestamp label layout when not in fullscreen by @CocoaBob in https://github.com/MessageKit/MessageKit/pull/1854 +- ♻️ Rename plugins to avoid clashing with SwiftLintPlugins by @technocidal in https://github.com/MessageKit/MessageKit/pull/1862 +- Added custom image masking by @GitNirajHub in https://github.com/MessageKit/MessageKit/pull/1860 +- Update to Swift 5.10 + ## 4.2.0 ### Added diff --git a/Package.swift b/Package.swift index 5e487dbcb..b0e0f6747 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.9 +// swift-tools-version:5.10 // MIT License // @@ -31,7 +31,7 @@ let package = Package( .plugin(name: "SwiftFormatPlugin", targets: ["SwiftFormatPlugin"]), ], dependencies: [ - .package(url: "https://github.com/nathantannar4/InputBarAccessoryView", .upToNextMajor(from: "6.4.0")), + .package(url: "https://github.com/nathantannar4/InputBarAccessoryView", .upToNextMajor(from: "6.5.0")), ], targets: [ // MARK: - MessageKit