Merge branch 'mkirk/send-design-changes' into release/2.39.0
This commit is contained in:
commit
d071f02e9c
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "plus-24@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "plus-24@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "plus-24@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 168 B |
Binary file not shown.
After Width: | Height: | Size: 248 B |
Binary file not shown.
After Width: | Height: | Size: 348 B |
|
@ -334,7 +334,7 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
|
|||
|
||||
galleryRailView.configureCellViews(itemProvider: currentItem.album,
|
||||
focusedItem: currentItem,
|
||||
cellViewBuilder: { return GalleryRailCellView() })
|
||||
cellViewBuilder: { _ in return GalleryRailCellView() })
|
||||
}
|
||||
|
||||
// MARK: Actions
|
||||
|
@ -774,17 +774,23 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
|
|||
}
|
||||
|
||||
extension MediaGalleryItem: GalleryRailItem {
|
||||
public var aspectRatio: CGFloat {
|
||||
return self.imageSize.aspectRatio
|
||||
public func buildRailItemView() -> UIView {
|
||||
let imageView = UIImageView()
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
getRailImage().map { [weak imageView] image in
|
||||
guard let imageView = imageView else { return }
|
||||
imageView.image = image
|
||||
}.retainUntilComplete()
|
||||
|
||||
return imageView
|
||||
}
|
||||
|
||||
public func getRailImage() -> Promise<UIImage> {
|
||||
let (guarantee, fulfill) = Guarantee<UIImage>.pending()
|
||||
if let image = self.thumbnailImage(async: { fulfill($0) }) {
|
||||
fulfill(image)
|
||||
public func getRailImage() -> Guarantee<UIImage> {
|
||||
return Guarantee<UIImage> { fulfill in
|
||||
if let image = self.thumbnailImage(async: { fulfill($0) }) {
|
||||
fulfill(image)
|
||||
}
|
||||
}
|
||||
|
||||
return Promise(guarantee)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,9 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
|
|||
|
||||
collectionView.register(PhotoGridViewCell.self, forCellWithReuseIdentifier: PhotoGridViewCell.reuseIdentifier)
|
||||
|
||||
// ensure images at the end of the list can be scrolled above the bottom buttons
|
||||
let bottomButtonInset = -1 * SendMediaNavigationController.bottomButtonsCenterOffset + SendMediaNavigationController.bottomButtonWidth / 2
|
||||
collectionView.contentInset.bottom = bottomButtonInset + 8
|
||||
view.backgroundColor = .ows_gray95
|
||||
|
||||
// The PhotoCaptureVC needs a shadow behind it's cancel button, so we use a custom icon.
|
||||
|
@ -223,6 +226,11 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
|
|||
// We don't need to do this when pushing VCs onto the SignalsNavigationController - only when
|
||||
// presenting directly from ConversationVC.
|
||||
_ = self.becomeFirstResponder()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// pre-layout collectionPicker for snappier response
|
||||
self.collectionPickerController.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
// HACK: Though we don't have an input accessory view, the VC we are presented above (ConversationVC) does.
|
||||
|
@ -235,6 +243,10 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
|
|||
|
||||
// MARK:
|
||||
|
||||
var lastPageYOffset: CGFloat {
|
||||
return collectionView.contentSize.height - collectionView.frame.height
|
||||
}
|
||||
|
||||
func scrollToBottom(animated: Bool) {
|
||||
self.view.layoutIfNeeded()
|
||||
|
||||
|
@ -243,11 +255,27 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
|
|||
return
|
||||
}
|
||||
|
||||
let lastSection = collectionView.numberOfSections - 1
|
||||
let lastItem = collectionView.numberOfItems(inSection: lastSection) - 1
|
||||
if lastSection >= 0 && lastItem >= 0 {
|
||||
let lastIndex = IndexPath(item: lastItem, section: lastSection)
|
||||
collectionView.scrollToItem(at: lastIndex, at: .bottom, animated: animated)
|
||||
let yOffset = lastPageYOffset
|
||||
guard yOffset > 0 else {
|
||||
// less than 1 page of content. Do not offset.
|
||||
return
|
||||
}
|
||||
|
||||
collectionView.setContentOffset(CGPoint(x: 0, y: yOffset), animated: animated)
|
||||
}
|
||||
|
||||
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if !hasEverAppeared, collectionView.contentOffset.y != lastPageYOffset {
|
||||
// We initially want the user to be scrolled to the bottom of the media library content.
|
||||
// However, at least on iOS12, we were finding that when the view finally presented,
|
||||
// the content was not *quite* to the bottom (~20px above it).
|
||||
//
|
||||
// Debugging shows that initially we have the correct offset, but that *something* is
|
||||
// causing the content to adjust *after* viewWillAppear and viewSafeAreaInsetsDidChange.
|
||||
// Because that something results in `scrollViewDidScroll` we re-adjust the content
|
||||
// insets to the bottom.
|
||||
Logger.debug("adjusting scroll offset back to bottom")
|
||||
scrollToBottom(animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,26 +406,23 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
|
|||
|
||||
// MARK: - PhotoCollectionPicker Presentation
|
||||
|
||||
var isShowingCollectionPickerController: Bool {
|
||||
return collectionPickerController != nil
|
||||
}
|
||||
var isShowingCollectionPickerController: Bool = false
|
||||
|
||||
lazy var collectionPickerController: PhotoCollectionPickerController = {
|
||||
return PhotoCollectionPickerController(library: library,
|
||||
collectionDelegate: self)
|
||||
}()
|
||||
|
||||
var collectionPickerController: PhotoCollectionPickerController?
|
||||
func showCollectionPicker() {
|
||||
Logger.debug("")
|
||||
|
||||
let collectionPickerController = PhotoCollectionPickerController(library: library,
|
||||
previousPhotoCollection: photoCollection,
|
||||
collectionDelegate: self)
|
||||
|
||||
guard let collectionPickerView = collectionPickerController.view else {
|
||||
owsFailDebug("collectionView was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
|
||||
assert(self.collectionPickerController == nil)
|
||||
self.collectionPickerController = collectionPickerController
|
||||
|
||||
assert(!isShowingCollectionPickerController)
|
||||
isShowingCollectionPickerController = true
|
||||
addChild(collectionPickerController)
|
||||
|
||||
view.addSubview(collectionPickerView)
|
||||
|
@ -416,18 +441,16 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
|
|||
|
||||
func hideCollectionPicker() {
|
||||
Logger.debug("")
|
||||
guard let collectionPickerController = collectionPickerController else {
|
||||
owsFailDebug("collectionPickerController was unexpectedly nil")
|
||||
return
|
||||
}
|
||||
self.collectionPickerController = nil
|
||||
|
||||
assert(isShowingCollectionPickerController)
|
||||
isShowingCollectionPickerController = false
|
||||
|
||||
UIView.animate(.promise, duration: 0.25, delay: 0, options: .curveEaseInOut) {
|
||||
collectionPickerController.view.frame = self.view.frame.offsetBy(dx: 0, dy: self.view.frame.height)
|
||||
self.collectionPickerController.view.frame = self.view.frame.offsetBy(dx: 0, dy: self.view.frame.height)
|
||||
self.titleView.rotateIcon(.down)
|
||||
}.done { _ in
|
||||
collectionPickerController.view.removeFromSuperview()
|
||||
collectionPickerController.removeFromParent()
|
||||
self.collectionPickerController.view.removeFromSuperview()
|
||||
self.collectionPickerController.removeFromParent()
|
||||
}.retainUntilComplete()
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ class PhotoCaptureViewController: OWSViewController {
|
|||
let fixedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
|
||||
fixedSpace.width = 16
|
||||
|
||||
navigationItem.rightBarButtonItems = [flashModeControl.barButtonItem, fixedSpace, switchCameraControl.barButtonItem]
|
||||
navigationItem.rightBarButtonItems = [switchCameraControl.barButtonItem, fixedSpace, flashModeControl.barButtonItem]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,14 +15,11 @@ class PhotoCollectionPickerController: OWSTableViewController, PhotoLibraryDeleg
|
|||
private weak var collectionDelegate: PhotoCollectionPickerDelegate?
|
||||
|
||||
private let library: PhotoLibrary
|
||||
private let previousPhotoCollection: PhotoCollection
|
||||
private var photoCollections: [PhotoCollection]
|
||||
|
||||
required init(library: PhotoLibrary,
|
||||
previousPhotoCollection: PhotoCollection,
|
||||
collectionDelegate: PhotoCollectionPickerDelegate) {
|
||||
self.library = library
|
||||
self.previousPhotoCollection = previousPhotoCollection
|
||||
self.photoCollections = library.allPhotoCollections()
|
||||
self.collectionDelegate = collectionDelegate
|
||||
super.init()
|
||||
|
|
|
@ -135,6 +135,7 @@ class SendMediaNavigationController: OWSNavigationController {
|
|||
}
|
||||
|
||||
// MARK: Views
|
||||
public static let bottomButtonWidth: CGFloat = 44
|
||||
|
||||
private lazy var doneButton: DoneButton = {
|
||||
let button = DoneButton()
|
||||
|
@ -149,7 +150,7 @@ class SendMediaNavigationController: OWSNavigationController {
|
|||
tintColor: .ows_gray60,
|
||||
block: { [weak self] in self?.didTapBatchModeButton() })
|
||||
|
||||
let width: CGFloat = 44
|
||||
let width: CGFloat = type(of: self).bottomButtonWidth
|
||||
button.autoSetDimensions(to: CGSize(width: width, height: width))
|
||||
button.layer.cornerRadius = width / 2
|
||||
button.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
|
||||
|
@ -164,7 +165,7 @@ class SendMediaNavigationController: OWSNavigationController {
|
|||
tintColor: .ows_gray60,
|
||||
block: { [weak self] in self?.didTapCameraModeButton() })
|
||||
|
||||
let width: CGFloat = 44
|
||||
let width: CGFloat = type(of: self).bottomButtonWidth
|
||||
button.autoSetDimensions(to: CGSize(width: width, height: width))
|
||||
button.layer.cornerRadius = width / 2
|
||||
button.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
|
||||
|
@ -179,7 +180,7 @@ class SendMediaNavigationController: OWSNavigationController {
|
|||
tintColor: .ows_gray60,
|
||||
block: { [weak self] in self?.didTapMediaLibraryModeButton() })
|
||||
|
||||
let width: CGFloat = 44
|
||||
let width: CGFloat = type(of: self).bottomButtonWidth
|
||||
button.autoSetDimensions(to: CGSize(width: width, height: width))
|
||||
button.layer.cornerRadius = width / 2
|
||||
button.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
|
||||
|
@ -264,10 +265,20 @@ extension SendMediaNavigationController: UINavigationControllerDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
if viewController is PhotoCaptureViewController && !isInBatchSelectMode {
|
||||
// We're either showing the captureView for the first time or the user is navigating "back"
|
||||
// indicating they want to "retake". We should discard any current image.
|
||||
discardCameraDraft()
|
||||
switch viewController {
|
||||
case is PhotoCaptureViewController:
|
||||
if attachmentDraftCollection.count == 1 && !isInBatchSelectMode {
|
||||
// User is navigating "back" to the previous view, indicating
|
||||
// they want to discard the previously captured item
|
||||
discardDraft()
|
||||
}
|
||||
case is ImagePickerGridController:
|
||||
if attachmentDraftCollection.count == 1 && !isInBatchSelectMode {
|
||||
isInBatchSelectMode = true
|
||||
self.mediaLibraryViewController.batchSelectModeDidChange()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
self.updateButtons(topViewController: viewController)
|
||||
|
@ -317,12 +328,12 @@ extension SendMediaNavigationController: PhotoCaptureViewControllerDelegate {
|
|||
didRequestExit(dontAbandonText: dontAbandonText)
|
||||
}
|
||||
|
||||
func discardCameraDraft() {
|
||||
assert(attachmentDraftCollection.cameraAttachments.count <= 1)
|
||||
if let lastCameraAttachment = attachmentDraftCollection.cameraAttachments.last {
|
||||
attachmentDraftCollection.remove(attachment: lastCameraAttachment)
|
||||
func discardDraft() {
|
||||
assert(attachmentDraftCollection.attachmentDrafts.count <= 1)
|
||||
if let lastAttachmentDraft = attachmentDraftCollection.attachmentDrafts.last {
|
||||
attachmentDraftCollection.remove(attachment: lastAttachmentDraft.attachment)
|
||||
}
|
||||
assert(attachmentDraftCollection.cameraAttachments.count == 0)
|
||||
assert(attachmentDraftCollection.attachmentDrafts.count == 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import UIKit
|
|||
|
||||
protocol ApprovalRailCellViewDelegate: class {
|
||||
func approvalRailCellView(_ approvalRailCellView: ApprovalRailCellView, didRemoveItem attachmentItem: SignalAttachmentItem)
|
||||
func canRemoveApprovalRailCellView(_ approvalRailCellView: ApprovalRailCellView) -> Bool
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
@ -55,10 +56,13 @@ public class ApprovalRailCellView: GalleryRailCellView {
|
|||
super.setIsSelected(isSelected)
|
||||
|
||||
if isSelected {
|
||||
addSubview(deleteButton)
|
||||
if let approvalRailCellDelegate = self.approvalRailCellDelegate,
|
||||
approvalRailCellDelegate.canRemoveApprovalRailCellView(self) {
|
||||
|
||||
deleteButton.autoPinEdge(toSuperviewEdge: .top, withInset: cellBorderWidth)
|
||||
deleteButton.autoPinEdge(toSuperviewEdge: .trailing, withInset: cellBorderWidth + 4)
|
||||
addSubview(deleteButton)
|
||||
deleteButton.autoPinEdge(toSuperviewEdge: .top, withInset: cellBorderWidth)
|
||||
deleteButton.autoPinEdge(toSuperviewEdge: .trailing, withInset: cellBorderWidth + 4)
|
||||
}
|
||||
} else {
|
||||
deleteButton.removeFromSuperview()
|
||||
}
|
||||
|
|
|
@ -32,9 +32,8 @@ class AttachmentApprovalInputAccessoryView: UIView {
|
|||
|
||||
let kGalleryRailViewHeight: CGFloat = 72
|
||||
|
||||
required init(isAddMoreVisible: Bool) {
|
||||
attachmentTextToolbar = AttachmentTextToolbar(isAddMoreVisible: isAddMoreVisible)
|
||||
|
||||
required init() {
|
||||
attachmentTextToolbar = AttachmentTextToolbar()
|
||||
attachmentCaptionToolbar = AttachmentCaptionToolbar()
|
||||
|
||||
galleryRailView = GalleryRailView()
|
||||
|
|
|
@ -40,6 +40,7 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
|
|||
// MARK: - Properties
|
||||
|
||||
private let mode: AttachmentApprovalViewControllerMode
|
||||
private let isAddMoreVisible: Bool
|
||||
|
||||
public weak var approvalDelegate: AttachmentApprovalViewControllerDelegate?
|
||||
|
||||
|
@ -64,7 +65,9 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
|
|||
assert(attachments.count > 0)
|
||||
self.mode = mode
|
||||
let attachmentItems = attachments.map { SignalAttachmentItem(attachment: $0 )}
|
||||
self.attachmentItemCollection = AttachmentItemCollection(attachmentItems: attachmentItems)
|
||||
self.isAddMoreVisible = mode == .sharedNavigation
|
||||
|
||||
self.attachmentItemCollection = AttachmentItemCollection(attachmentItems: attachmentItems, isAddMoreVisible: isAddMoreVisible)
|
||||
|
||||
let options: [UIPageViewController.OptionsKey: Any] = [.interPageSpacing: kSpacingBetweenItems]
|
||||
super.init(transitionStyle: .scroll,
|
||||
|
@ -118,8 +121,7 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
|
|||
}
|
||||
|
||||
lazy var bottomToolView: AttachmentApprovalInputAccessoryView = {
|
||||
let isAddMoreVisible = mode == .sharedNavigation
|
||||
let bottomToolView = AttachmentApprovalInputAccessoryView(isAddMoreVisible: isAddMoreVisible)
|
||||
let bottomToolView = AttachmentApprovalInputAccessoryView()
|
||||
bottomToolView.delegate = self
|
||||
|
||||
return bottomToolView
|
||||
|
@ -536,17 +538,31 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
|
|||
return
|
||||
}
|
||||
|
||||
let cellViewBuilder: () -> ApprovalRailCellView = { [weak self] in
|
||||
let cell = ApprovalRailCellView()
|
||||
cell.approvalRailCellDelegate = self
|
||||
return cell
|
||||
let cellViewBuilder: (GalleryRailItem) -> GalleryRailCellView = { [weak self] railItem in
|
||||
switch railItem {
|
||||
case is AddMoreRailItem:
|
||||
return GalleryRailCellView()
|
||||
case is SignalAttachmentItem:
|
||||
let cell = ApprovalRailCellView()
|
||||
cell.approvalRailCellDelegate = self
|
||||
return cell
|
||||
default:
|
||||
owsFailDebug("unexpted rail item type: \(railItem)")
|
||||
return GalleryRailCellView()
|
||||
}
|
||||
}
|
||||
|
||||
galleryRailView.configureCellViews(itemProvider: attachmentItemCollection,
|
||||
focusedItem: currentItem,
|
||||
cellViewBuilder: cellViewBuilder)
|
||||
|
||||
galleryRailView.isHidden = attachmentItemCollection.attachmentItems.count < 2
|
||||
if isAddMoreVisible {
|
||||
galleryRailView.isHidden = false
|
||||
} else if attachmentItemCollection.attachmentItems.count > 1 {
|
||||
galleryRailView.isHidden = false
|
||||
} else {
|
||||
galleryRailView.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
let attachmentItemCollection: AttachmentItemCollection
|
||||
|
@ -699,10 +715,6 @@ extension AttachmentApprovalViewController: AttachmentTextToolbarDelegate {
|
|||
approvalDelegate?.attachmentApproval(self, didApproveAttachments: attachments, messageText: attachmentTextToolbar.messageText)
|
||||
}
|
||||
|
||||
func attachmentTextToolbarDidAddMore(_ attachmentTextToolbar: AttachmentTextToolbar) {
|
||||
self.approvalDelegate?.attachmentApprovalDidTapAddMore?(self)
|
||||
}
|
||||
|
||||
func attachmentTextToolbarDidChange(_ attachmentTextToolbar: AttachmentTextToolbar) {
|
||||
approvalDelegate?.attachmentApproval(self, didChangeMessageText: attachmentTextToolbar.messageText)
|
||||
}
|
||||
|
@ -723,12 +735,15 @@ extension AttachmentApprovalViewController: AttachmentPrepViewControllerDelegate
|
|||
// MARK: GalleryRail
|
||||
|
||||
extension SignalAttachmentItem: GalleryRailItem {
|
||||
var aspectRatio: CGFloat {
|
||||
return self.imageSize.aspectRatio
|
||||
}
|
||||
func buildRailItemView() -> UIView {
|
||||
let imageView = UIImageView()
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
|
||||
func getRailImage() -> Promise<UIImage> {
|
||||
return self.getThumbnailImage()
|
||||
getThumbnailImage().map { image in
|
||||
imageView.image = image
|
||||
}.retainUntilComplete()
|
||||
|
||||
return imageView
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -736,7 +751,11 @@ extension SignalAttachmentItem: GalleryRailItem {
|
|||
|
||||
extension AttachmentItemCollection: GalleryRailItemProvider {
|
||||
var railItems: [GalleryRailItem] {
|
||||
return self.attachmentItems
|
||||
if isAddMoreVisible {
|
||||
return self.attachmentItems + [AddMoreRailItem()]
|
||||
} else {
|
||||
return self.attachmentItems
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -744,6 +763,11 @@ extension AttachmentItemCollection: GalleryRailItemProvider {
|
|||
|
||||
extension AttachmentApprovalViewController: GalleryRailViewDelegate {
|
||||
public func galleryRailView(_ galleryRailView: GalleryRailView, didTapItem imageRailItem: GalleryRailItem) {
|
||||
if imageRailItem is AddMoreRailItem {
|
||||
self.approvalDelegate?.attachmentApprovalDidTapAddMore?(self)
|
||||
return
|
||||
}
|
||||
|
||||
guard let targetItem = imageRailItem as? SignalAttachmentItem else {
|
||||
owsFailDebug("unexpected imageRailItem: \(imageRailItem)")
|
||||
return
|
||||
|
@ -777,6 +801,10 @@ extension AttachmentApprovalViewController: ApprovalRailCellViewDelegate {
|
|||
func approvalRailCellView(_ approvalRailCellView: ApprovalRailCellView, didRemoveItem attachmentItem: SignalAttachmentItem) {
|
||||
remove(attachmentItem: attachmentItem)
|
||||
}
|
||||
|
||||
func canRemoveApprovalRailCellView(_ approvalRailCellView: ApprovalRailCellView) -> Bool {
|
||||
return self.attachmentItems.count > 1
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
|
|
@ -5,6 +5,22 @@
|
|||
import Foundation
|
||||
import PromiseKit
|
||||
|
||||
class AddMoreRailItem: GalleryRailItem {
|
||||
func buildRailItemView() -> UIView {
|
||||
let view = UIView()
|
||||
view.backgroundColor = UIColor.black.withAlphaComponent(0.33)
|
||||
|
||||
let iconView = UIImageView(image: #imageLiteral(resourceName: "ic_plus_24").withRenderingMode(.alwaysTemplate))
|
||||
iconView.tintColor = .ows_white
|
||||
view.addSubview(iconView)
|
||||
iconView.setCompressionResistanceHigh()
|
||||
iconView.setContentHuggingHigh()
|
||||
iconView.autoCenterInSuperview()
|
||||
|
||||
return view
|
||||
}
|
||||
}
|
||||
|
||||
class SignalAttachmentItem: Hashable {
|
||||
|
||||
enum SignalAttachmentItemError: Error {
|
||||
|
@ -75,8 +91,10 @@ class SignalAttachmentItem: Hashable {
|
|||
|
||||
class AttachmentItemCollection {
|
||||
private (set) var attachmentItems: [SignalAttachmentItem]
|
||||
init(attachmentItems: [SignalAttachmentItem]) {
|
||||
let isAddMoreVisible: Bool
|
||||
init(attachmentItems: [SignalAttachmentItem], isAddMoreVisible: Bool) {
|
||||
self.attachmentItems = attachmentItems
|
||||
self.isAddMoreVisible = isAddMoreVisible
|
||||
}
|
||||
|
||||
func itemAfter(item: SignalAttachmentItem) -> SignalAttachmentItem? {
|
||||
|
|
|
@ -12,7 +12,6 @@ protocol AttachmentTextToolbarDelegate: class {
|
|||
func attachmentTextToolbarDidTapSend(_ attachmentTextToolbar: AttachmentTextToolbar)
|
||||
func attachmentTextToolbarDidBeginEditing(_ attachmentTextToolbar: AttachmentTextToolbar)
|
||||
func attachmentTextToolbarDidEndEditing(_ attachmentTextToolbar: AttachmentTextToolbar)
|
||||
func attachmentTextToolbarDidAddMore(_ attachmentTextToolbar: AttachmentTextToolbar)
|
||||
func attachmentTextToolbarDidChange(_ attachmentTextToolbar: AttachmentTextToolbar)
|
||||
}
|
||||
|
||||
|
@ -44,8 +43,7 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate {
|
|||
|
||||
// MARK: - Initializers
|
||||
|
||||
init(isAddMoreVisible: Bool) {
|
||||
self.addMoreButton = UIButton(type: .custom)
|
||||
init() {
|
||||
self.sendButton = UIButton(type: .system)
|
||||
self.textViewHeight = kMinTextViewHeight
|
||||
|
||||
|
@ -59,11 +57,6 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate {
|
|||
|
||||
textView.delegate = self
|
||||
|
||||
let addMoreIcon = #imageLiteral(resourceName: "album_add_more").withRenderingMode(.alwaysTemplate)
|
||||
addMoreButton.setImage(addMoreIcon, for: .normal)
|
||||
addMoreButton.tintColor = Theme.darkThemePrimaryColor
|
||||
addMoreButton.addTarget(self, action: #selector(didTapAddMore), for: .touchUpInside)
|
||||
|
||||
let sendTitle = NSLocalizedString("ATTACHMENT_APPROVAL_SEND_BUTTON", comment: "Label for 'send' button in the 'attachment approval' dialog.")
|
||||
sendButton.setTitle(sendTitle, for: .normal)
|
||||
sendButton.addTarget(self, action: #selector(didTapSend), for: .touchUpInside)
|
||||
|
@ -79,10 +72,6 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate {
|
|||
contentView.addSubview(sendButton)
|
||||
contentView.addSubview(textContainer)
|
||||
contentView.addSubview(lengthLimitLabel)
|
||||
if isAddMoreVisible {
|
||||
contentView.addSubview(addMoreButton)
|
||||
}
|
||||
|
||||
addSubview(contentView)
|
||||
contentView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
|
@ -105,15 +94,7 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate {
|
|||
// I believe this is a bug in PureLayout. Filed here: https://github.com/PureLayout/PureLayout/issues/209
|
||||
textContainer.autoPinEdge(toSuperviewMargin: .top)
|
||||
textContainer.autoPinEdge(toSuperviewMargin: .bottom)
|
||||
if isAddMoreVisible {
|
||||
addMoreButton.autoPinEdge(toSuperviewMargin: .left)
|
||||
textContainer.autoPinEdge(.left, to: .right, of: addMoreButton, withOffset: kToolbarMargin)
|
||||
addMoreButton.autoAlignAxis(.horizontal, toSameAxisOf: sendButton)
|
||||
addMoreButton.setContentHuggingHigh()
|
||||
addMoreButton.setCompressionResistanceHigh()
|
||||
} else {
|
||||
textContainer.autoPinEdge(toSuperviewMargin: .left)
|
||||
}
|
||||
textContainer.autoPinEdge(toSuperviewMargin: .left)
|
||||
|
||||
sendButton.autoPinEdge(.left, to: .right, of: textContainer, withOffset: kToolbarMargin)
|
||||
sendButton.autoPinEdge(.bottom, to: .bottom, of: textContainer, withOffset: -3)
|
||||
|
@ -145,7 +126,6 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate {
|
|||
|
||||
// MARK: - Subviews
|
||||
|
||||
private let addMoreButton: UIButton
|
||||
private let sendButton: UIButton
|
||||
|
||||
private lazy var lengthLimitLabel: UILabel = {
|
||||
|
@ -221,10 +201,6 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate {
|
|||
attachmentTextToolbarDelegate?.attachmentTextToolbarDidTapSend(self)
|
||||
}
|
||||
|
||||
@objc func didTapAddMore() {
|
||||
attachmentTextToolbarDelegate?.attachmentTextToolbarDidAddMore(self)
|
||||
}
|
||||
|
||||
// MARK: - UITextViewDelegate
|
||||
|
||||
public func textViewDidChange(_ textView: UITextView) {
|
||||
|
|
|
@ -9,8 +9,7 @@ public protocol GalleryRailItemProvider: class {
|
|||
}
|
||||
|
||||
public protocol GalleryRailItem: class {
|
||||
func getRailImage() -> Promise<UIImage>
|
||||
var aspectRatio: CGFloat { get }
|
||||
func buildRailItemView() -> UIView
|
||||
}
|
||||
|
||||
protocol GalleryRailCellViewDelegate: class {
|
||||
|
@ -26,8 +25,9 @@ public class GalleryRailCellView: UIView {
|
|||
|
||||
layoutMargins = .zero
|
||||
clipsToBounds = false
|
||||
addSubview(imageView)
|
||||
imageView.autoPinEdgesToSuperviewMargins()
|
||||
addSubview(contentContainer)
|
||||
contentContainer.autoPinEdgesToSuperviewMargins()
|
||||
contentContainer.layer.cornerRadius = 4.8
|
||||
|
||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap(sender:)))
|
||||
addGestureRecognizer(tapGesture)
|
||||
|
@ -52,18 +52,20 @@ public class GalleryRailCellView: UIView {
|
|||
self.item = item
|
||||
self.delegate = delegate
|
||||
|
||||
item.getRailImage().done { image in
|
||||
guard self.item === item else { return }
|
||||
for view in contentContainer.subviews {
|
||||
view.removeFromSuperview()
|
||||
}
|
||||
|
||||
self.imageView.image = image
|
||||
}.retainUntilComplete()
|
||||
let itemView = item.buildRailItemView()
|
||||
contentContainer.addSubview(itemView)
|
||||
itemView.autoPinEdgesToSuperviewEdges()
|
||||
}
|
||||
|
||||
// MARK: Selected
|
||||
|
||||
private(set) var isSelected: Bool = false
|
||||
|
||||
public let cellBorderWidth: CGFloat = 2
|
||||
public let cellBorderWidth: CGFloat = 3
|
||||
|
||||
func setIsSelected(_ isSelected: Bool) {
|
||||
self.isSelected = isSelected
|
||||
|
@ -72,24 +74,21 @@ public class GalleryRailCellView: UIView {
|
|||
layoutMargins = UIEdgeInsets(top: 0, left: cellBorderWidth, bottom: 0, right: cellBorderWidth)
|
||||
|
||||
if isSelected {
|
||||
imageView.layer.borderColor = Theme.galleryHighlightColor.cgColor
|
||||
imageView.layer.borderWidth = cellBorderWidth
|
||||
imageView.layer.cornerRadius = cellBorderWidth
|
||||
contentContainer.layer.borderColor = Theme.galleryHighlightColor.cgColor
|
||||
contentContainer.layer.borderWidth = cellBorderWidth
|
||||
} else {
|
||||
imageView.layer.borderWidth = 0
|
||||
imageView.layer.cornerRadius = 0
|
||||
contentContainer.layer.borderWidth = 0
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Subview Helpers
|
||||
|
||||
let imageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
imageView.autoPinToSquareAspectRatio()
|
||||
imageView.clipsToBounds = true
|
||||
let contentContainer: UIView = {
|
||||
let view = UIView()
|
||||
view.autoPinToSquareAspectRatio()
|
||||
view.clipsToBounds = true
|
||||
|
||||
return imageView
|
||||
return view
|
||||
}()
|
||||
}
|
||||
|
||||
|
@ -124,7 +123,7 @@ public class GalleryRailView: UIView, GalleryRailCellViewDelegate {
|
|||
|
||||
// MARK: Public
|
||||
|
||||
public func configureCellViews(itemProvider: GalleryRailItemProvider?, focusedItem: GalleryRailItem?, cellViewBuilder: () -> GalleryRailCellView) {
|
||||
public func configureCellViews(itemProvider: GalleryRailItemProvider?, focusedItem: GalleryRailItem?, cellViewBuilder: (GalleryRailItem) -> GalleryRailCellView) {
|
||||
let animationDuration: TimeInterval = 0.2
|
||||
|
||||
guard let itemProvider = itemProvider else {
|
||||
|
@ -179,7 +178,7 @@ public class GalleryRailView: UIView, GalleryRailCellViewDelegate {
|
|||
self.cellViews = cellViews
|
||||
let stackView = UIStackView(arrangedSubviews: cellViews)
|
||||
stackView.axis = .horizontal
|
||||
stackView.spacing = 2
|
||||
stackView.spacing = 0
|
||||
stackView.clipsToBounds = false
|
||||
|
||||
scrollView.addSubview(stackView)
|
||||
|
@ -210,9 +209,9 @@ public class GalleryRailView: UIView, GalleryRailCellViewDelegate {
|
|||
return scrollView
|
||||
}()
|
||||
|
||||
private func buildCellViews(items: [GalleryRailItem], cellViewBuilder: () -> GalleryRailCellView) -> [GalleryRailCellView] {
|
||||
private func buildCellViews(items: [GalleryRailItem], cellViewBuilder: (GalleryRailItem) -> GalleryRailCellView) -> [GalleryRailCellView] {
|
||||
return items.map { item in
|
||||
let cellView = cellViewBuilder()
|
||||
let cellView = cellViewBuilder(item)
|
||||
cellView.configure(item: item, delegate: self)
|
||||
return cellView
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue