2019-05-13 07:21:16 +02:00
|
|
|
|
|
|
|
@objc final class FriendRequestView : UIView {
|
2019-05-14 03:27:34 +02:00
|
|
|
@objc var message: TSMessage! { didSet { handleMessageChanged() } }
|
2019-05-13 07:21:16 +02:00
|
|
|
@objc weak var delegate: FriendRequestViewDelegate?
|
2019-05-14 03:27:34 +02:00
|
|
|
private let kind: Kind
|
2019-05-15 08:48:16 +02:00
|
|
|
|
2019-05-16 04:08:37 +02:00
|
|
|
private var didAcceptRequest: Bool {
|
|
|
|
return message.thread.friendRequestStatus == .friends
|
|
|
|
}
|
|
|
|
|
2019-05-15 08:48:16 +02:00
|
|
|
private var didDeclineRequest: Bool {
|
|
|
|
guard let message = message as? TSIncomingMessage else { preconditionFailure() }
|
|
|
|
return message.thread.friendRequestStatus == .none
|
|
|
|
}
|
|
|
|
|
2019-05-14 03:27:34 +02:00
|
|
|
// MARK: Types
|
|
|
|
enum Kind : String { case incoming, outgoing }
|
2019-05-13 07:21:16 +02:00
|
|
|
|
|
|
|
// MARK: Components
|
|
|
|
private lazy var label: UILabel = {
|
|
|
|
let result = UILabel()
|
|
|
|
result.textColor = Theme.secondaryColor
|
|
|
|
result.font = UIFont.ows_dynamicTypeSubheadlineClamped
|
|
|
|
result.numberOfLines = 0
|
|
|
|
result.textAlignment = .center
|
|
|
|
result.lineBreakMode = .byWordWrapping
|
|
|
|
return result
|
|
|
|
}()
|
2019-05-15 08:48:16 +02:00
|
|
|
|
|
|
|
private lazy var buttonStackView: UIStackView = {
|
|
|
|
let result = UIStackView()
|
|
|
|
result.axis = .horizontal
|
|
|
|
result.distribution = .fillEqually
|
|
|
|
return result
|
|
|
|
}()
|
|
|
|
|
|
|
|
private lazy var buttonFont = UIFont.ows_dynamicTypeBodyClamped.ows_mediumWeight()
|
|
|
|
private lazy var buttonHeight = buttonFont.pointSize * 48 / 17
|
2019-05-13 07:21:16 +02:00
|
|
|
|
|
|
|
// MARK: Initialization
|
2019-05-14 03:27:34 +02:00
|
|
|
init(kind: Kind) {
|
|
|
|
self.kind = kind
|
|
|
|
super.init(frame: CGRect.zero)
|
2019-05-14 04:54:13 +02:00
|
|
|
initialize()
|
2019-05-14 03:27:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@objc convenience init?(rawKind: String) {
|
|
|
|
guard let kind = Kind(rawValue: rawKind) else { return nil }
|
|
|
|
self.init(kind: kind)
|
|
|
|
}
|
|
|
|
|
2019-05-13 07:21:16 +02:00
|
|
|
required init?(coder: NSCoder) {
|
2019-05-14 03:27:34 +02:00
|
|
|
fatalError("Using FriendRequestView.init(coder:) isn't allowed. Use FriendRequestView.init(kind:) instead.")
|
2019-05-13 07:21:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override init(frame: CGRect) {
|
2019-05-14 03:27:34 +02:00
|
|
|
fatalError("Using FriendRequestView.init(frame:) isn't allowed. Use FriendRequestView.init(kind:) instead.")
|
2019-05-13 07:21:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private func initialize() {
|
|
|
|
let mainStackView = UIStackView()
|
|
|
|
mainStackView.axis = .vertical
|
|
|
|
mainStackView.distribution = .fill
|
|
|
|
mainStackView.addArrangedSubview(label)
|
2019-05-14 03:27:34 +02:00
|
|
|
switch kind {
|
|
|
|
case .incoming:
|
|
|
|
mainStackView.addArrangedSubview(buttonStackView)
|
|
|
|
let acceptButton = OWSFlatButton.button(title: NSLocalizedString("Accept", comment: ""), font: buttonFont, titleColor: .ows_materialBlue, backgroundColor: .white, target: self, selector: #selector(accept))
|
|
|
|
acceptButton.autoSetDimension(.height, toSize: buttonHeight)
|
|
|
|
buttonStackView.addArrangedSubview(acceptButton)
|
|
|
|
let declineButton = OWSFlatButton.button(title: NSLocalizedString("Decline", comment: ""), font: buttonFont, titleColor: .ows_destructiveRed, backgroundColor: .white, target: self, selector: #selector(decline))
|
|
|
|
declineButton.autoSetDimension(.height, toSize: buttonHeight)
|
|
|
|
buttonStackView.addArrangedSubview(declineButton)
|
|
|
|
case .outgoing: break
|
|
|
|
}
|
2019-05-13 07:21:16 +02:00
|
|
|
addSubview(mainStackView)
|
|
|
|
mainStackView.autoPin(toEdgesOf: self)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Updating
|
|
|
|
private func handleMessageChanged() {
|
2019-05-14 03:27:34 +02:00
|
|
|
precondition(message != nil)
|
|
|
|
switch kind {
|
|
|
|
case .incoming:
|
|
|
|
guard let message = message as? TSIncomingMessage else { preconditionFailure() }
|
2019-05-17 03:41:28 +02:00
|
|
|
buttonStackView.isHidden = didAcceptRequest || didDeclineRequest
|
2019-05-15 08:48:16 +02:00
|
|
|
let text: String = {
|
2019-05-16 04:08:37 +02:00
|
|
|
if didAcceptRequest {
|
|
|
|
return String(format: NSLocalizedString("You've accepted %@'s friend request", comment: ""), message.authorId)
|
|
|
|
} else if didDeclineRequest {
|
2019-05-15 08:48:16 +02:00
|
|
|
return String(format: NSLocalizedString("You've declined %@'s friend request", comment: ""), message.authorId)
|
|
|
|
} else {
|
|
|
|
return String(format: NSLocalizedString("%@ sent you a friend request", comment: ""), message.authorId)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
label.text = text
|
2019-05-14 03:27:34 +02:00
|
|
|
case .outgoing:
|
|
|
|
guard let message = message as? TSOutgoingMessage else { preconditionFailure() }
|
2019-05-17 03:58:46 +02:00
|
|
|
let text: String = {
|
|
|
|
if didAcceptRequest {
|
|
|
|
return String(format: NSLocalizedString("%@ accepted your friend request", comment: ""), message.thread.contactIdentifier()!)
|
|
|
|
} else {
|
|
|
|
return String(format: NSLocalizedString("You've sent %@ a friend request", comment: ""), message.thread.contactIdentifier()!)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
label.text = text
|
2019-05-14 03:27:34 +02:00
|
|
|
}
|
2019-05-13 07:21:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Interaction
|
|
|
|
@objc private func accept() {
|
2019-05-14 03:27:34 +02:00
|
|
|
guard let message = message as? TSIncomingMessage else { preconditionFailure() }
|
2019-05-13 07:21:16 +02:00
|
|
|
delegate?.acceptFriendRequest(message)
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc private func decline() {
|
2019-05-14 03:27:34 +02:00
|
|
|
guard let message = message as? TSIncomingMessage else { preconditionFailure() }
|
2019-05-13 07:21:16 +02:00
|
|
|
delegate?.declineFriendRequest(message)
|
2019-05-15 08:48:16 +02:00
|
|
|
handleMessageChanged() // Update UI
|
2019-05-13 07:21:16 +02:00
|
|
|
}
|
2019-05-14 02:28:02 +02:00
|
|
|
|
|
|
|
// MARK: Measuring
|
2019-05-14 03:27:34 +02:00
|
|
|
@objc static func calculateHeight(message: TSMessage, conversationStyle: ConversationStyle) -> CGFloat {
|
2019-05-14 02:28:02 +02:00
|
|
|
let width = conversationStyle.contentWidth
|
|
|
|
let topSpacing: CGFloat = 12
|
2019-05-14 03:27:34 +02:00
|
|
|
let kind: Kind = {
|
|
|
|
switch (message) {
|
|
|
|
case is TSIncomingMessage: return .incoming
|
|
|
|
case is TSOutgoingMessage: return .outgoing
|
|
|
|
default: preconditionFailure()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
let dummyFriendRequestView = FriendRequestView(kind: kind)
|
2019-05-14 02:28:02 +02:00
|
|
|
dummyFriendRequestView.message = message
|
|
|
|
let messageHeight = dummyFriendRequestView.label.sizeThatFits(CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)).height
|
2019-05-14 03:27:34 +02:00
|
|
|
let totalHeight: CGFloat = {
|
|
|
|
switch kind {
|
|
|
|
case .incoming:
|
2019-05-16 04:20:56 +02:00
|
|
|
let buttonHeight = dummyFriendRequestView.buttonStackView.isHidden ? 0 : dummyFriendRequestView.buttonHeight
|
2019-05-14 03:27:34 +02:00
|
|
|
return topSpacing + messageHeight + buttonHeight
|
|
|
|
case .outgoing:
|
|
|
|
return topSpacing + messageHeight
|
|
|
|
}
|
|
|
|
}()
|
2019-05-14 02:28:02 +02:00
|
|
|
return totalHeight.rounded(.up)
|
|
|
|
}
|
2019-05-13 07:21:16 +02:00
|
|
|
}
|