session-ios/SignalMessaging/ViewControllers/MessageActionsViewController.swift

213 lines
7.1 KiB
Swift
Raw Normal View History

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
protocol MessageActionsDelegate: class {
func messageActionsDidHide(_ messageActionsViewController: MessageActionsViewController)
}
@objc
class MessageActionsViewController: UIViewController {
@objc
weak var delegate: MessageActionsDelegate?
2018-07-11 03:04:11 +02:00
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
]
2018-07-11 00:43:20 +02:00
@objc
2018-07-11 03:04:11 +02:00
required init(focusedView: UIView, actions: [MessageAction]) {
2018-07-11 00:43:20 +02:00
self.focusedView = focusedView
2018-07-11 03:04:11 +02:00
// FIXME
self.actionSheetView = MessageActionSheetView(actions: MessageActionsViewController.testActions)
2018-07-11 00:43:20 +02:00
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
self.view = UIView()
2018-07-11 00:43:20 +02:00
view.backgroundColor = UIColor.black.withAlphaComponent(0.4)
highlightFocusedView()
2018-07-11 03:04:11 +02:00
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)
}
2018-07-11 00:43:20 +02:00
private func highlightFocusedView() {
guard let snapshotView = self.focusedView.snapshotView(afterScreenUpdates: false) else {
owsFail("\(self.logTag) in \(#function) snapshotView was unexpectedly nil")
return
}
view.addSubview(snapshotView)
guard let focusedViewSuperview = focusedView.superview else {
owsFail("\(self.logTag) in \(#function) focusedViewSuperview was unexpectedly nil")
return
}
let convertedFrame = view.convert(focusedView.frame, from: focusedViewSuperview)
snapshotView.frame = convertedFrame
}
@objc
func didTapBackground() {
self.delegate?.messageActionsDidHide(self)
}
}
2018-07-11 03:04:11 +02:00
// 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
}
}