From 57400e1ecbd7aa8dd49f562f8f6865f5b2a74f86 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 10 Jul 2018 19:04:11 -0600 Subject: [PATCH] WIP: ActionView --- .../ConversationViewController.m | 3 +- .../MessageActionsViewController.swift | 155 +++++++++++++++++- 2 files changed, 155 insertions(+), 3 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index e2d4cd10f..1f756a25b 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -2002,8 +2002,9 @@ typedef enum : NSUInteger { [self.collectionView scrollRectToVisible:cell.frame animated:NO]; } completion:^(BOOL finished) { + // TODO pass in real actions MessageActionsViewController *messageActionsViewController = - [[MessageActionsViewController alloc] initWithFocusedView:cell]; + [[MessageActionsViewController alloc] initWithFocusedView:cell actions:@[]]; messageActionsViewController.delegate = self; diff --git a/SignalMessaging/ViewControllers/MessageActionsViewController.swift b/SignalMessaging/ViewControllers/MessageActionsViewController.swift index 51c137ab0..be893c3a3 100644 --- a/SignalMessaging/ViewControllers/MessageActionsViewController.swift +++ b/SignalMessaging/ViewControllers/MessageActionsViewController.swift @@ -15,12 +15,51 @@ class MessageActionsViewController: UIViewController { @objc weak var delegate: MessageActionsDelegate? - let focusedView: UIView + private let focusedView: UIView + private let actionSheetView: MessageActionSheetView + + static let replyAction = MessageAction(block: { (action) in + Logger.debug("\(logTag) in \(#function) action: \(action)") + }, + image: #imageLiteral(resourceName: "table_ic_verify"), + title: NSLocalizedString("MESSAGE_ACTION_REPLY", comment: "Action sheet button title"), + subtitle: nil) + + static let copyTextAction = MessageAction(block: { (action) in + Logger.debug("\(logTag) in \(#function) action: \(action)") + }, + image: #imageLiteral(resourceName: "generic-attachment-small"), + title: NSLocalizedString("MESSAGE_ACTION_COPY_TEXT", comment: "Action sheet button title"), + subtitle: nil) + + static let deleteMessageAction = MessageAction(block: { (action) in + Logger.debug("\(logTag) in \(#function) action: \(action)") + }, + image: #imageLiteral(resourceName: "message_status_failed_large"), + title: NSLocalizedString("MESSAGE_ACTION_DELETE_MESSAGE", comment: "Action sheet button title"), + subtitle: NSLocalizedString("MESSAGE_ACTION_DELETE_MESSAGE_SUBTITLE", comment: "Action sheet button subtitle")) + + static let infoAction = MessageAction(block: { (action) in + Logger.debug("\(logTag) in \(#function) action: \(action)") + }, + image: #imageLiteral(resourceName: "system_message_info"), + title: NSLocalizedString("MESSAGE_ACTION_TITLE_INFO", comment: "Action sheet button title"), + subtitle: nil) + + static let testActions: [MessageAction] = [ + replyAction, + copyTextAction, + deleteMessageAction, + infoAction + ] @objc - required init(focusedView: UIView) { + required init(focusedView: UIView, actions: [MessageAction]) { self.focusedView = focusedView + // FIXME + self.actionSheetView = MessageActionSheetView(actions: MessageActionsViewController.testActions) + super.init(nibName: nil, bundle: nil) } @@ -34,6 +73,11 @@ class MessageActionsViewController: UIViewController { highlightFocusedView() + view.addSubview(actionSheetView) + actionSheetView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .top) + actionSheetView.setContentHuggingVerticalHigh() + actionSheetView.setCompressionResistanceHigh() + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapBackground)) self.view.addGestureRecognizer(tapGesture) } @@ -59,3 +103,110 @@ class MessageActionsViewController: UIViewController { self.delegate?.messageActionsDidHide(self) } } + +// MARK: ActionView + +@objc +class MessageAction: NSObject { + let block: (MessageAction) -> Void + let image: UIImage + let title: String + let subtitle: String? + + init(block: @escaping (MessageAction) -> Void, image: UIImage, title: String, subtitle: String?) { + self.block = block + self.image = image + self.title = title + self.subtitle = subtitle + } +} + +class MessageActionView: UIView { + let action: MessageAction + + required init(action: MessageAction) { + self.action = action + + super.init(frame: CGRect.zero) + + let imageView = UIImageView(image: action.image) + let imageWidth: CGFloat = 24 + imageView.autoSetDimensions(to: CGSize(width: imageWidth, height: imageWidth)) + + let titleLabel = UILabel() + titleLabel.font = UIFont.ows_dynamicTypeBody + titleLabel.textColor = UIColor.ows_light90 + titleLabel.text = action.title + + let subtitleLabel = UILabel() + subtitleLabel.font = UIFont.ows_dynamicTypeSubheadline + subtitleLabel.textColor = UIColor.ows_light60 + subtitleLabel.text = action.subtitle + + let textColumn = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) + textColumn.axis = .vertical + textColumn.alignment = .leading + + let contentRow = UIStackView(arrangedSubviews: [imageView, textColumn]) + contentRow.axis = .horizontal + contentRow.alignment = .center + contentRow.spacing = 12 + contentRow.isLayoutMarginsRelativeArrangement = true + contentRow.layoutMargins = UIEdgeInsets(top: 17, left: 16, bottom: 17, right: 16) + + self.addSubview(contentRow) + contentRow.autoPinToSuperviewMargins() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("not implemented") + } +} + +class MessageActionSheetView: UIView { + + private let actionStackView: UIStackView + private var actions: [MessageAction] + + convenience init(actions: [MessageAction]) { + self.init(frame: CGRect.zero) + actions.forEach { self.addAction($0) } + } + + override init(frame: CGRect) { + actionStackView = UIStackView() + self.actions = [] + + super.init(frame: frame) + + addSubview(actionStackView) + actionStackView.autoPinToSuperviewEdges() + + backgroundColor = UIColor.ows_light10 + actionStackView.axis = .vertical + } + + required init?(coder aDecoder: NSCoder) { + fatalError("not implemented") + } + + public func addAction(_ action: MessageAction) { + let actionView = MessageActionView(action: action) + + if !actions.isEmpty { + self.actionStackView.addArrangedSubview(buildSeparatorView()) + } + + actions.append(action) + self.actionStackView.addArrangedSubview(actionView) + } + + private func buildSeparatorView() -> UIView { + let separatorView = UIView() + separatorView.autoSetDimension(.height, toSize: CGHairlineWidth()) + separatorView.backgroundColor = UIColor.ows_light10 + + return separatorView + } + +}