Merge branch 'mkirk/send-design-changes' into release/2.39.0

This commit is contained in:
Michael Kirk 2019-04-22 13:45:07 -07:00
commit d071f02e9c
15 changed files with 208 additions and 124 deletions

View File

@ -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

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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]
}
}

View File

@ -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()

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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()

View File

@ -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: -

View File

@ -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? {

View File

@ -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) {

View File

@ -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
}