mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
7.2 KiB
Swift
203 lines
7.2 KiB
Swift
6 years ago
|
//
|
||
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
import UIKit
|
||
5 years ago
|
import SessionUIKit
|
||
6 years ago
|
|
||
6 years ago
|
protocol AttachmentApprovalInputAccessoryViewDelegate: class {
|
||
|
func attachmentApprovalInputUpdateMediaRail()
|
||
6 years ago
|
func attachmentApprovalInputStartEditingCaptions()
|
||
|
func attachmentApprovalInputStopEditingCaptions()
|
||
6 years ago
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
6 years ago
|
class AttachmentApprovalInputAccessoryView: UIView {
|
||
6 years ago
|
|
||
|
weak var delegate: AttachmentApprovalInputAccessoryViewDelegate?
|
||
|
|
||
6 years ago
|
let attachmentTextToolbar: AttachmentTextToolbar
|
||
6 years ago
|
let attachmentCaptionToolbar: AttachmentCaptionToolbar
|
||
6 years ago
|
let galleryRailView: GalleryRailView
|
||
6 years ago
|
let currentCaptionLabel = UILabel()
|
||
|
let currentCaptionWrapper = UIView()
|
||
6 years ago
|
|
||
|
var isEditingMediaMessage: Bool {
|
||
6 years ago
|
return attachmentTextToolbar.textView.isFirstResponder
|
||
6 years ago
|
}
|
||
|
|
||
6 years ago
|
private var isEditingCaptions: Bool = false
|
||
|
private var currentAttachmentItem: SignalAttachmentItem?
|
||
|
|
||
6 years ago
|
let kGalleryRailViewHeight: CGFloat = 72
|
||
|
|
||
6 years ago
|
required init() {
|
||
|
attachmentTextToolbar = AttachmentTextToolbar()
|
||
6 years ago
|
attachmentCaptionToolbar = AttachmentCaptionToolbar()
|
||
|
|
||
6 years ago
|
galleryRailView = GalleryRailView()
|
||
|
galleryRailView.scrollFocusMode = .keepWithinBounds
|
||
|
galleryRailView.autoSetDimension(.height, toSize: kGalleryRailViewHeight)
|
||
|
|
||
|
super.init(frame: .zero)
|
||
|
|
||
6 years ago
|
createContents()
|
||
|
}
|
||
|
|
||
|
required init?(coder aDecoder: NSCoder) {
|
||
|
fatalError("init(coder:) has not been implemented")
|
||
|
}
|
||
|
|
||
|
private func createContents() {
|
||
6 years ago
|
// Specifying auto-resizing mask and an intrinsic content size allows proper
|
||
|
// sizing when used as an input accessory view.
|
||
|
self.autoresizingMask = .flexibleHeight
|
||
|
self.translatesAutoresizingMaskIntoConstraints = false
|
||
6 years ago
|
self.backgroundColor = .clear
|
||
6 years ago
|
|
||
|
preservesSuperviewLayoutMargins = true
|
||
|
|
||
6 years ago
|
// Use a background view that extends below the keyboard to avoid animation glitches.
|
||
|
let backgroundView = UIView()
|
||
5 years ago
|
backgroundView.backgroundColor = isLightMode ? UIColor.black.withAlphaComponent(0.2) : UIColor.black.withAlphaComponent(0.6)
|
||
6 years ago
|
addSubview(backgroundView)
|
||
6 years ago
|
backgroundView.autoPinEdgesToSuperviewEdges()
|
||
6 years ago
|
|
||
5 years ago
|
currentCaptionLabel.textColor = .white
|
||
|
currentCaptionLabel.font = .systemFont(ofSize: Values.mediumFontSize)
|
||
6 years ago
|
currentCaptionLabel.numberOfLines = 5
|
||
|
currentCaptionLabel.lineBreakMode = .byWordWrapping
|
||
|
|
||
|
currentCaptionWrapper.isUserInteractionEnabled = true
|
||
|
currentCaptionWrapper.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(captionTapped)))
|
||
|
currentCaptionWrapper.addSubview(currentCaptionLabel)
|
||
|
currentCaptionLabel.autoPinEdgesToSuperviewMargins()
|
||
|
|
||
|
attachmentCaptionToolbar.attachmentCaptionToolbarDelegate = self
|
||
|
|
||
|
let stackView = UIStackView(arrangedSubviews: [currentCaptionWrapper, attachmentCaptionToolbar, galleryRailView, attachmentTextToolbar])
|
||
6 years ago
|
stackView.axis = .vertical
|
||
|
|
||
|
addSubview(stackView)
|
||
6 years ago
|
stackView.autoPinEdge(toSuperviewEdge: .top)
|
||
|
stackView.autoPinEdge(toSuperviewEdge: .leading)
|
||
|
stackView.autoPinEdge(toSuperviewEdge: .trailing)
|
||
|
// We pin to the superview's _margin_. Otherwise the notch breaks
|
||
|
// the layout if you hide the keyboard in the simulator (or if the
|
||
|
// user uses an external keyboard).
|
||
|
stackView.autoPinEdge(toSuperviewMargin: .bottom)
|
||
6 years ago
|
}
|
||
|
|
||
6 years ago
|
// MARK: - Events
|
||
|
|
||
|
@objc func captionTapped(sender: UIGestureRecognizer) {
|
||
|
guard sender.state == .recognized else {
|
||
|
return
|
||
|
}
|
||
6 years ago
|
delegate?.attachmentApprovalInputStartEditingCaptions()
|
||
6 years ago
|
}
|
||
|
|
||
|
// MARK:
|
||
|
|
||
6 years ago
|
private var shouldHideControls = false
|
||
6 years ago
|
|
||
|
private func updateContents() {
|
||
|
var hasCurrentCaption = false
|
||
|
if let currentAttachmentItem = currentAttachmentItem,
|
||
|
let captionText = currentAttachmentItem.captionText {
|
||
|
hasCurrentCaption = captionText.count > 0
|
||
|
|
||
|
attachmentCaptionToolbar.textView.text = captionText
|
||
|
currentCaptionLabel.text = captionText
|
||
|
} else {
|
||
|
attachmentCaptionToolbar.textView.text = nil
|
||
|
currentCaptionLabel.text = nil
|
||
|
}
|
||
|
|
||
|
attachmentCaptionToolbar.isHidden = !isEditingCaptions
|
||
|
currentCaptionWrapper.isHidden = isEditingCaptions || !hasCurrentCaption
|
||
|
attachmentTextToolbar.isHidden = isEditingCaptions
|
||
|
|
||
6 years ago
|
updateFirstResponder()
|
||
|
|
||
|
layoutSubviews()
|
||
|
}
|
||
|
|
||
|
private func updateFirstResponder() {
|
||
6 years ago
|
if (shouldHideControls) {
|
||
|
if attachmentCaptionToolbar.textView.isFirstResponder {
|
||
|
attachmentCaptionToolbar.textView.resignFirstResponder()
|
||
|
} else if attachmentTextToolbar.textView.isFirstResponder {
|
||
|
attachmentTextToolbar.textView.resignFirstResponder()
|
||
|
}
|
||
|
} else if (isEditingCaptions) {
|
||
6 years ago
|
// While editing captions, the keyboard should always remain visible.
|
||
6 years ago
|
if !attachmentCaptionToolbar.textView.isFirstResponder {
|
||
|
attachmentCaptionToolbar.textView.becomeFirstResponder()
|
||
|
}
|
||
6 years ago
|
} else {
|
||
|
if attachmentCaptionToolbar.textView.isFirstResponder {
|
||
|
attachmentCaptionToolbar.textView.resignFirstResponder()
|
||
|
}
|
||
6 years ago
|
}
|
||
6 years ago
|
// NOTE: We don't automatically make attachmentTextToolbar.textView
|
||
|
// first responder;
|
||
6 years ago
|
}
|
||
|
|
||
|
public func update(isEditingCaptions: Bool,
|
||
6 years ago
|
currentAttachmentItem: SignalAttachmentItem?,
|
||
|
shouldHideControls: Bool) {
|
||
|
// De-bounce
|
||
|
guard self.isEditingCaptions != isEditingCaptions ||
|
||
|
self.currentAttachmentItem != currentAttachmentItem ||
|
||
|
self.shouldHideControls != shouldHideControls else {
|
||
6 years ago
|
|
||
|
updateFirstResponder()
|
||
|
return
|
||
6 years ago
|
}
|
||
|
|
||
6 years ago
|
self.isEditingCaptions = isEditingCaptions
|
||
|
self.currentAttachmentItem = currentAttachmentItem
|
||
6 years ago
|
self.shouldHideControls = shouldHideControls
|
||
6 years ago
|
|
||
|
updateContents()
|
||
6 years ago
|
}
|
||
|
|
||
|
// MARK:
|
||
|
|
||
|
override var intrinsicContentSize: CGSize {
|
||
|
get {
|
||
|
// Since we have `self.autoresizingMask = UIViewAutoresizingFlexibleHeight`, we must specify
|
||
|
// an intrinsicContentSize. Specifying CGSize.zero causes the height to be determined by autolayout.
|
||
|
return CGSize.zero
|
||
|
}
|
||
|
}
|
||
6 years ago
|
|
||
|
public var hasFirstResponder: Bool {
|
||
|
return (isFirstResponder ||
|
||
|
attachmentCaptionToolbar.textView.isFirstResponder ||
|
||
|
attachmentTextToolbar.textView.isFirstResponder)
|
||
|
}
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
|
// MARK: -
|
||
|
|
||
|
extension AttachmentApprovalInputAccessoryView: AttachmentCaptionToolbarDelegate {
|
||
|
public func attachmentCaptionToolbarDidEdit(_ attachmentCaptionToolbar: AttachmentCaptionToolbar) {
|
||
|
guard let currentAttachmentItem = currentAttachmentItem else {
|
||
|
owsFailDebug("Missing currentAttachmentItem.")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentAttachmentItem.attachment.captionText = attachmentCaptionToolbar.textView.text
|
||
|
|
||
|
delegate?.attachmentApprovalInputUpdateMediaRail()
|
||
|
}
|
||
6 years ago
|
|
||
|
public func attachmentCaptionToolbarDidComplete() {
|
||
|
delegate?.attachmentApprovalInputStopEditingCaptions()
|
||
|
}
|
||
6 years ago
|
}
|