Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Session/Conversations/ConversationVC+Interaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ extension ConversationVC:
ContextMenuActionDelegate,
SendMediaNavDelegate,
AttachmentApprovalViewControllerDelegate,
GifPickerViewControllerDelegate
GifPickerViewControllerDelegate,
UIGestureRecognizerDelegate
{
// MARK: - Open Settings

Expand All @@ -33,6 +34,11 @@ extension ConversationVC:
openSettingsFromTitleView()
}

// Handle taps outside of tableview cell to dismiss keyboard
@MainActor @objc func dismissKeyboardOnTap() {
_ = self.snInputView.resignFirstResponder()
}

@MainActor func openSettingsFromTitleView() {
// If we shouldn't be able to access settings then disable the title view shortcuts
guard viewModel.threadData.canAccessSettings(using: viewModel.dependencies) else { return }
Expand Down Expand Up @@ -254,6 +260,11 @@ extension ConversationVC:

return true
}

// MARK: - UIGestureRecognizerDelegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}

// MARK: - SendMediaNavDelegate

Expand Down Expand Up @@ -1063,7 +1074,7 @@ extension ConversationVC:
}

// MARK: MessageCellDelegate

func handleItemLongPressed(_ cellViewModel: MessageViewModel) {
// Show the unblock modal if needed
guard self.viewModel.threadData.threadIsBlocked != true else {
Expand Down
16 changes: 15 additions & 1 deletion Session/Conversations/ConversationVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,16 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa

return result
}()

// Handle taps outside of tableview cell
private lazy var tableViewTapGesture: UITapGestureRecognizer = {
let result: UITapGestureRecognizer = UITapGestureRecognizer()
result.delegate = self
result.addTarget(self, action: #selector(dismissKeyboardOnTap))
result.cancelsTouchesInView = false

return result
}()

// MARK: - Settings

Expand Down Expand Up @@ -537,6 +547,9 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa
object: nil
)
}

// Gesture
view.addGestureRecognizer(tableViewTapGesture)

self.viewModel.navigatableState.setupBindings(viewController: self, disposables: &self.viewModel.disposables)

Expand Down Expand Up @@ -1580,7 +1593,8 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa
// value will break things)
let tableViewBottom: CGFloat = (tableView.contentSize.height - tableView.bounds.height + tableView.contentInset.bottom)

if tableView.contentOffset.y < (tableViewBottom - 5) {
// Added `insetDifference > 0` to remove sudden table collapse and overscroll
if tableView.contentOffset.y < (tableViewBottom - 5) && insetDifference > 0 {
tableView.contentOffset.y += insetDifference
}

Expand Down
15 changes: 15 additions & 0 deletions Session/Conversations/Input View/InputView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
return result
}()

private lazy var swipeGestureRecognizer: UISwipeGestureRecognizer = {
let result: UISwipeGestureRecognizer = UISwipeGestureRecognizer()
result.direction = .down
result.addTarget(self, action: #selector(didSwipeDown))
result.cancelsTouchesInView = false

return result
}()

private var bottomStackView: UIStackView?
private lazy var attachmentsButton: ExpandingAttachmentsButton = {
let result = ExpandingAttachmentsButton(delegate: delegate)
Expand Down Expand Up @@ -227,6 +236,7 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
autoresizingMask = .flexibleHeight

addGestureRecognizer(tapGestureRecognizer)
addGestureRecognizer(swipeGestureRecognizer)

// Background & blur
let backgroundView = UIView()
Expand Down Expand Up @@ -454,6 +464,7 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
self.accessibilityIdentifier = updatedInputState.accessibility?.identifier
self.accessibilityLabel = updatedInputState.accessibility?.label
tapGestureRecognizer.isEnabled = (updatedInputState.allowedInputTypes == .none)

inputState = updatedInputState
disabledInputLabel.text = (updatedInputState.message ?? "")
disabledInputLabel.accessibilityIdentifier = updatedInputState.messageAccessibility?.identifier
Expand Down Expand Up @@ -630,6 +641,10 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
@objc private func characterLimitLabelTapped() {
delegate?.handleCharacterLimitLabelTapped()
}

@objc private func didSwipeDown() {
inputTextView.resignFirstResponder()
}

// MARK: - Convenience

Expand Down
20 changes: 9 additions & 11 deletions Session/Conversations/Message Cells/CallMessageCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ final class CallMessageCell: MessageCell {

override var contextSnapshotView: UIView? { return container }

override var allowedGestureRecognizers: Set<GestureRecognizerType> {
return [
.longPress,
.tap
]
}

// MARK: - UI

private lazy var topConstraint: NSLayoutConstraint = mainStackView.pin(.top, to: .top, of: self, withInset: CallMessageCell.inset)
Expand Down Expand Up @@ -115,15 +122,6 @@ final class CallMessageCell: MessageCell {
mainStackView.pin(.bottom, to: .bottom, of: self, withInset: -CallMessageCell.inset)
}

override func setUpGestureRecognizers() {
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
addGestureRecognizer(longPressRecognizer)

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}

// MARK: - Updating

override func update(
Expand Down Expand Up @@ -207,7 +205,7 @@ final class CallMessageCell: MessageCell {

// MARK: - Interaction

@objc func handleLongPress(_ gestureRecognizer: UITapGestureRecognizer) {
override func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
if [ .ended, .cancelled, .failed ].contains(gestureRecognizer.state) {
isHandlingLongPress = false
return
Expand All @@ -218,7 +216,7 @@ final class CallMessageCell: MessageCell {
isHandlingLongPress = true
}

@objc private func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
override func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
guard
let dependencies: Dependencies = self.dependencies,
let cellViewModel: MessageViewModel = self.viewModel,
Expand Down
22 changes: 10 additions & 12 deletions Session/Conversations/Message Cells/InfoMessageCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ final class InfoMessageCell: MessageCell {

override var contextSnapshotView: UIView? { return label }

override var allowedGestureRecognizers: Set<GestureRecognizerType> {
return [
.longPress,
.tap
]
}

// MARK: - UI

private lazy var iconContainerViewWidthConstraint = iconContainerView.set(.width, to: InfoMessageCell.iconSize)
Expand Down Expand Up @@ -77,15 +84,6 @@ final class InfoMessageCell: MessageCell {
stackView.pin(.right, to: .right, of: self, withInset: -Values.massiveSpacing)
stackView.pin(.bottom, to: .bottom, of: self, withInset: -InfoMessageCell.inset)
}

override func setUpGestureRecognizers() {
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
addGestureRecognizer(longPressRecognizer)

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}

// MARK: - Updating

Expand Down Expand Up @@ -169,7 +167,7 @@ final class InfoMessageCell: MessageCell {

// MARK: - Interaction

@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
override func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
if [ .ended, .cancelled, .failed ].contains(gestureRecognizer.state) {
isHandlingLongPress = false
return
Expand All @@ -180,9 +178,9 @@ final class InfoMessageCell: MessageCell {
isHandlingLongPress = true
}

@objc func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
override func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
guard let cellViewModel: MessageViewModel = self.viewModel else { return }

if cellViewModel.variant == .infoDisappearingMessagesUpdate && cellViewModel.canDoFollowingSetting() {
delegate?.handleItemTapped(cellViewModel, cell: self, cellLocation: gestureRecognizer.location(in: self))
}
Expand Down
42 changes: 41 additions & 1 deletion Session/Conversations/Message Cells/MessageCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ public enum SwipeState {
case cancelled
}

public enum GestureRecognizerType {
case tap, longPress, doubleTap
}

public class MessageCell: UITableViewCell {
var dependencies: Dependencies?
var viewModel: MessageViewModel?
weak var delegate: MessageCellDelegate?
open var contextSnapshotView: UIView? { return nil }
open var allowedGestureRecognizers: Set<GestureRecognizerType> { return [] } // Override to have gestures

// MARK: - Lifecycle

Expand All @@ -41,7 +46,32 @@ public class MessageCell: UITableViewCell {
}

func setUpGestureRecognizers() {
// To be overridden by subclasses
var tapGestureRecognizer: UITapGestureRecognizer?
var doubleTapGestureRecognizer: UITapGestureRecognizer?

if allowedGestureRecognizers.contains(.tap) {
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGesture.numberOfTapsRequired = 1
addGestureRecognizer(tapGesture)
tapGestureRecognizer = tapGesture
}

if allowedGestureRecognizers.contains(.doubleTap) {
let doubleTapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
addGestureRecognizer(doubleTapGesture)
doubleTapGestureRecognizer = doubleTapGesture
}

if allowedGestureRecognizers.contains(.longPress) {
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
addGestureRecognizer(longPressGesture)
}

// If we have both tap and double tap gestures then the single tap should fail if a double tap occurs
if let tapGesture: UITapGestureRecognizer = tapGestureRecognizer, let doubleTapGesture: UITapGestureRecognizer = doubleTapGestureRecognizer {
tapGesture.require(toFail: doubleTapGesture)
}
}

// MARK: - Updating
Expand Down Expand Up @@ -93,6 +123,16 @@ public class MessageCell: UITableViewCell {
return CallMessageCell.self
}
}

// MARK: - Gesture events
@objc
func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {}

@objc
func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {}

@objc
func handleDoubleTap() {}
}

// MARK: - MessageCellDelegate
Expand Down
32 changes: 13 additions & 19 deletions Session/Conversations/Message Cells/VisibleMessageCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {

override var contextSnapshotView: UIView? { return snContentView }

override var allowedGestureRecognizers: Set<GestureRecognizerType> {
return [
.tap,
.longPress,
.doubleTap
]
}

// Constraints
internal lazy var authorLabelTopConstraint = authorLabel.pin(.top, to: .top, of: self)
private lazy var authorLabelHeightConstraint = authorLabel.set(.height, to: 0)
Expand Down Expand Up @@ -270,21 +278,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
messageStatusLabelPaddingView.pin(.leading, to: .leading, of: messageStatusContainerView)
messageStatusLabelPaddingView.pin(.trailing, to: .trailing, of: messageStatusContainerView)
}

override func setUpGestureRecognizers() {
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
addGestureRecognizer(longPressRecognizer)

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)

let doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTapGestureRecognizer.numberOfTapsRequired = 2
addGestureRecognizer(doubleTapGestureRecognizer)
tapGestureRecognizer.require(toFail: doubleTapGestureRecognizer)
}


// MARK: - Updating

override func update(
Expand Down Expand Up @@ -968,7 +962,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
}
}

@objc func handleLongPress(_ gestureRecognizer: UITapGestureRecognizer) {
override func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
if [ .ended, .cancelled, .failed ].contains(gestureRecognizer.state) {
isHandlingLongPress = false
return
Expand All @@ -994,9 +988,9 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
isHandlingLongPress = true
}

@objc private func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
override func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
guard let cellViewModel: MessageViewModel = self.viewModel else { return }

let location = gestureRecognizer.location(in: self)

if profilePictureView.bounds.contains(profilePictureView.convert(location, from: self)), cellViewModel.shouldShowProfile {
Expand Down Expand Up @@ -1062,7 +1056,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
}
}

@objc private func handleDoubleTap() {
override func handleDoubleTap() {
guard let cellViewModel: MessageViewModel = self.viewModel else { return }

delegate?.handleItemDoubleTapped(cellViewModel)
Expand Down