mirror of
https://github.com/MessageKit/MessageKit.git
synced 2026-02-06 19:03:19 +00:00
* build: Swiftlint plugin * build: Swiftformat plugin * build: Swiftformat plugin * build: Swiftformat bash command * style: Swiftformat rules * style: Swiftformat applied to codebase * style: Ignore Tests for Swiftlint * Update bundler * Update changelog and migration guide * style: Ignore Example for Swiftlint * chore: Changelog * Update Xcode version for ci_pr_tests.yml * Update ci_pr_framework.yml * Update ci_pr_example.yml * chore: Changelog Co-authored-by: Jakub Kaspar <kaspikk@gmail.com>
413 lines
16 KiB
Swift
413 lines
16 KiB
Swift
// MIT License
|
|
//
|
|
// Copyright (c) 2017-2022 MessageKit
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
|
|
import Foundation
|
|
import UIKit
|
|
|
|
// MARK: - MessagesLayoutDelegate
|
|
|
|
/// A protocol used by the `MessagesCollectionViewFlowLayout` object to determine
|
|
/// the size and layout of a `MessageCollectionViewCell` and its contents.
|
|
public protocol MessagesLayoutDelegate: AnyObject {
|
|
/// Specifies the size to use for a header view.
|
|
///
|
|
/// - Parameters:
|
|
/// - section: The section number of the header.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this header will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is a size of `GGSize.zero`.
|
|
func headerViewSize(for section: Int, in messagesCollectionView: MessagesCollectionView) -> CGSize
|
|
|
|
/// Specifies the size to use for a footer view.
|
|
///
|
|
/// - Parameters:
|
|
/// - section: The section number of the footer.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this footer will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is a size of `GGSize.zero`.
|
|
func footerViewSize(for section: Int, in messagesCollectionView: MessagesCollectionView) -> CGSize
|
|
|
|
/// Specifies the size to use for a typing indicator view.
|
|
///
|
|
/// - Parameters:
|
|
/// - layout: The `MessagesCollectionViewFlowLayout` layout.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is the width of the `messagesCollectionView` minus insets and a height of 62.
|
|
func typingIndicatorViewSize(for layout: MessagesCollectionViewFlowLayout) -> CGSize
|
|
|
|
/// Specifies the top inset to use for a typing indicator view.
|
|
///
|
|
/// - Parameters:
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this view will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is a top inset of 15.
|
|
func typingIndicatorViewTopInset(in messagesCollectionView: MessagesCollectionView) -> CGFloat
|
|
|
|
/// Specifies the height for the `MessageContentCell`'s top label.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The `MessageType` that will be displayed for this cell.
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is zero.
|
|
func cellTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView)
|
|
-> CGFloat
|
|
|
|
/// Specifies the height for the `MessageContentCell`'s bottom label.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The `MessageType` that will be displayed for this cell.
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is zero.
|
|
func cellBottomLabelHeight(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CGFloat
|
|
|
|
/// Specifies the height for the message bubble's top label.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The `MessageType` that will be displayed for this cell.
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is zero.
|
|
func messageTopLabelHeight(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CGFloat
|
|
|
|
/// Specifies the label alignment for the message bubble's top label.
|
|
/// - Parameters:
|
|
/// - message: The `MessageType` that will be displayed for this cell.
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
/// - Returns: Optional LabelAlignment for the message bubble's top label. If nil is returned or the delegate method is not implemented,
|
|
/// alignment from MessageSizeCalculator will be used depending if the message is outgoing or incoming
|
|
func messageTopLabelAlignment(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> LabelAlignment?
|
|
|
|
/// Specifies the height for the `MessageContentCell`'s bottom label.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The `MessageType` that will be displayed for this cell.
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default value returned by this method is zero.
|
|
func messageBottomLabelHeight(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CGFloat
|
|
|
|
/// Specifies the label alignment for the message bubble's bottom label.
|
|
/// - Parameters:
|
|
/// - message: The `MessageType` that will be displayed for this cell.
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
/// - Returns: Optional LabelAlignment for the message bubble's bottom label. If nil is returned or the delegate method is not implemented,
|
|
/// alignment from MessageSizeCalculator will be used depending if the message is outgoing or incoming
|
|
func messageBottomLabelAlignment(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> LabelAlignment?
|
|
|
|
/// Specifies the size for the `MessageContentCell`'s avatar image view.
|
|
/// - Parameters:
|
|
/// - message: The `MessageType` that will be displayed for this cell.
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
/// - Returns: Optional CGSize for the avatar image view. If nil is returned or delegate method is not implemented,
|
|
/// size from `MessageSizeCalculator`'s `incomingAvatarSize` or `outgoingAvatarSize` will be used depending if the message is outgoing or incoming
|
|
func avatarSize(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView)
|
|
-> CGSize?
|
|
|
|
/// Text cell size calculator for messages with MessageType.text.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The text message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.text.
|
|
func textCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Attributed text cell size calculator for messages with MessageType.attributedText.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The attributedText message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.attributedText.
|
|
func attributedTextCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Emoji cell size calculator for messages with MessageType.emoji.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The emoji message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.emoji.
|
|
func emojiCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Photo cell size calculator for messages with MessageType.photo.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The photo message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.text.
|
|
func photoCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Video cell size calculator for messages with MessageType.video.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The video message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.video.
|
|
func videoCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Location cell size calculator for messages with MessageType.location.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The location message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.location.
|
|
func locationCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Audio cell size calculator for messages with MessageType.audio.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The audio message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.audio.
|
|
func audioCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Contact cell size calculator for messages with MessageType.contact.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The contact message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will return nil. You must override this method if you are using your own cell for messages with MessageType.contact.
|
|
func contactCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator?
|
|
|
|
/// Custom cell size calculator for messages with MessageType.custom.
|
|
///
|
|
/// - Parameters:
|
|
/// - message: The custom message
|
|
/// - indexPath: The `IndexPath` of the cell.
|
|
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
|
|
///
|
|
/// - Note:
|
|
/// The default implementation will throw fatalError(). You must override this method if you are using messages with MessageType.custom.
|
|
func customCellSizeCalculator(
|
|
for message: MessageType,
|
|
at indexPath: IndexPath,
|
|
in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator
|
|
}
|
|
|
|
extension MessagesLayoutDelegate {
|
|
public func headerViewSize(for _: Int, in _: MessagesCollectionView) -> CGSize {
|
|
.zero
|
|
}
|
|
|
|
public func footerViewSize(for _: Int, in _: MessagesCollectionView) -> CGSize {
|
|
.zero
|
|
}
|
|
|
|
public func typingIndicatorViewSize(for layout: MessagesCollectionViewFlowLayout) -> CGSize {
|
|
let collectionViewWidth = layout.messagesCollectionView.bounds.width
|
|
let contentInset = layout.messagesCollectionView.contentInset
|
|
let inset = layout.sectionInset.horizontal + contentInset.horizontal
|
|
return CGSize(width: collectionViewWidth - inset, height: 62)
|
|
}
|
|
|
|
public func typingIndicatorViewTopInset(in _: MessagesCollectionView) -> CGFloat {
|
|
15
|
|
}
|
|
|
|
public func cellTopLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
0
|
|
}
|
|
|
|
public func cellBottomLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
0
|
|
}
|
|
|
|
public func messageTopLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
0
|
|
}
|
|
|
|
public func messageTopLabelAlignment(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> LabelAlignment? {
|
|
nil
|
|
}
|
|
|
|
public func messageBottomLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
0
|
|
}
|
|
|
|
public func avatarSize(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGSize? {
|
|
nil
|
|
}
|
|
|
|
public func messageBottomLabelAlignment(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> LabelAlignment?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func textCellSizeCalculator(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CellSizeCalculator? {
|
|
nil
|
|
}
|
|
|
|
public func attributedTextCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func emojiCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func photoCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func videoCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func locationCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func audioCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func contactCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator?
|
|
{
|
|
nil
|
|
}
|
|
|
|
public func customCellSizeCalculator(
|
|
for _: MessageType,
|
|
at _: IndexPath,
|
|
in _: MessagesCollectionView)
|
|
-> CellSizeCalculator
|
|
{
|
|
fatalError("Must return a CellSizeCalculator for MessageKind.custom(Any?)")
|
|
}
|
|
}
|