Dwayne Harris
6 years ago
20 changed files with 435 additions and 284 deletions
-
44elpha-ios.xcodeproj/project.pbxproj
-
21elpha-ios/AbstractStatusTableViewController.swift
-
12elpha-ios/Assets.xcassets/Icons/Placeholder Half.imageset/Contents.json
-
BINelpha-ios/Assets.xcassets/Icons/Placeholder Half.imageset/placeholder-half.pdf
-
12elpha-ios/Assets.xcassets/Icons/Placeholder Small.imageset/Contents.json
-
BINelpha-ios/Assets.xcassets/Icons/Placeholder Small.imageset/placeholder-small.pdf
-
12elpha-ios/Assets.xcassets/Icons/Placeholder.imageset/Contents.json
-
BINelpha-ios/Assets.xcassets/Icons/Placeholder.imageset/placeholder.pdf
-
207elpha-ios/AttachmentManager.swift
-
111elpha-ios/AttachmentsView.swift
-
49elpha-ios/AttachmentsView.xib
-
9elpha-ios/Base.lproj/Main.storyboard
-
24elpha-ios/ImageAttachmentCollectionViewCell.swift
-
39elpha-ios/ImageAttachmentCollectionViewCell.xib
-
2elpha-ios/MainStatusTableViewCell.swift
-
24elpha-ios/StatusTableViewController.swift
-
37elpha-ios/StatusView.swift
-
49elpha-ios/StatusView.xib
-
42elpha-ios/VideoAttachmentCollectionViewCell.swift
-
25elpha-ios/VideoAttachmentCollectionViewCell.xib
@ -0,0 +1,12 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "universal", |
|||
"filename" : "placeholder-half.pdf" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "universal", |
|||
"filename" : "placeholder-small.pdf" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
{ |
|||
"images" : [ |
|||
{ |
|||
"idiom" : "universal", |
|||
"filename" : "placeholder.pdf" |
|||
} |
|||
], |
|||
"info" : { |
|||
"version" : 1, |
|||
"author" : "xcode" |
|||
} |
|||
} |
@ -1,207 +0,0 @@ |
|||
// |
|||
// AttachmentManager.swift |
|||
// elpha-ios |
|||
// |
|||
// Created by Dwayne Harris on 10/6/18. |
|||
// Copyright © 2018 Elpha. All rights reserved. |
|||
// |
|||
|
|||
import Kingfisher |
|||
import UIKit |
|||
|
|||
protocol AttachmentManagerDelegate: class { |
|||
func attachmentTapped(_ sender: Any, index: Int) |
|||
} |
|||
|
|||
class AttachmentManager: NSObject { |
|||
weak var delegate: AttachmentManagerDelegate? |
|||
|
|||
@objc func attachmentTapped(_ gestureRecognizer: UITapGestureRecognizer) { |
|||
if let delegate = delegate, let name = gestureRecognizer.name { |
|||
delegate.attachmentTapped(self, index: Int(name)!) |
|||
} |
|||
} |
|||
|
|||
func setupAttachmentView(_ view: UIView, withAttachments attachments: NSOrderedSet?) { |
|||
guard let attachments = attachments, attachments.count > 0 else { |
|||
return |
|||
} |
|||
|
|||
let placeholder = UIImage(named: "Help") |
|||
let halfWidth = (view.frame.width / 2) - 1 |
|||
|
|||
let fullSize = CGSize(width: view.frame.width, height: view.frame.width) |
|||
let tallSize = CGSize(width: halfWidth, height: view.frame.width) |
|||
let smallSize = CGSize(width: halfWidth, height: halfWidth) |
|||
|
|||
let fullResizingProcessor = ResizingImageProcessor(referenceSize: fullSize, mode: .aspectFill) >> CroppingImageProcessor(size: fullSize) |
|||
let tallResizingProcessor = ResizingImageProcessor(referenceSize: tallSize, mode: .aspectFill) >> CroppingImageProcessor(size: tallSize) |
|||
let smallResizingProcessor = ResizingImageProcessor(referenceSize: smallSize, mode: .aspectFill) >> CroppingImageProcessor(size: smallSize) |
|||
|
|||
for subview in view.subviews as [UIView] { |
|||
subview.removeFromSuperview() |
|||
} |
|||
|
|||
switch attachments.count { |
|||
case 0: |
|||
return |
|||
case 1: |
|||
let attachment = attachments.firstObject as! AttachmentMO |
|||
|
|||
let imageView = UIImageView() |
|||
imageView.contentMode = UIImageView.ContentMode.scaleAspectFill |
|||
imageView.isUserInteractionEnabled = true |
|||
imageView.kf.indicatorType = .activity |
|||
imageView.kf.setImage(with: attachment.url!, placeholder: placeholder, options: [.processor(fullResizingProcessor)]) |
|||
|
|||
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(attachmentTapped)) |
|||
tapGestureRecognizer.delegate = self |
|||
tapGestureRecognizer.numberOfTapsRequired = 1 |
|||
tapGestureRecognizer.numberOfTouchesRequired = 1 |
|||
tapGestureRecognizer.name = "0" |
|||
|
|||
imageView.addGestureRecognizer(tapGestureRecognizer) |
|||
|
|||
view.addSubview(imageView) |
|||
imageView.translatesAutoresizingMaskIntoConstraints = false |
|||
|
|||
NSLayoutConstraint.activate([ |
|||
imageView.topAnchor.constraint(equalTo: view.topAnchor), |
|||
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor), |
|||
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor), |
|||
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor), |
|||
]) |
|||
case 2: |
|||
let imageViews = [ |
|||
UIImageView(), |
|||
UIImageView(), |
|||
] |
|||
|
|||
for (index, imageView) in imageViews.enumerated() { |
|||
let attachment = attachments[index] as! AttachmentMO |
|||
|
|||
imageView.contentMode = UIImageView.ContentMode.scaleAspectFill |
|||
imageView.isUserInteractionEnabled = true |
|||
imageView.kf.indicatorType = .activity |
|||
imageView.kf.setImage(with: attachment.url!, placeholder: placeholder, options: [.processor(tallResizingProcessor)]) |
|||
|
|||
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(attachmentTapped)) |
|||
tapGestureRecognizer.delegate = self |
|||
tapGestureRecognizer.numberOfTapsRequired = 1 |
|||
tapGestureRecognizer.numberOfTouchesRequired = 1 |
|||
tapGestureRecognizer.name = String(index) |
|||
|
|||
imageView.addGestureRecognizer(tapGestureRecognizer) |
|||
|
|||
view.addSubview(imageView) |
|||
imageView.translatesAutoresizingMaskIntoConstraints = false |
|||
|
|||
NSLayoutConstraint.activate([ |
|||
imageView.topAnchor.constraint(equalTo: view.topAnchor), |
|||
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor), |
|||
imageView.widthAnchor.constraint(equalToConstant: halfWidth), |
|||
]) |
|||
} |
|||
|
|||
NSLayoutConstraint.activate([ |
|||
imageViews[0].leadingAnchor.constraint(equalTo: view.leadingAnchor), |
|||
imageViews[1].trailingAnchor.constraint(equalTo: view.trailingAnchor), |
|||
]) |
|||
case 3: |
|||
let imageViews = [ |
|||
UIImageView(), |
|||
UIImageView(), |
|||
UIImageView(), |
|||
] |
|||
|
|||
for (index, imageView) in imageViews.enumerated() { |
|||
let attachment = attachments[index] as! AttachmentMO |
|||
var processor: ImageProcessor |
|||
|
|||
if index == 0 { |
|||
processor = tallResizingProcessor |
|||
} else { |
|||
processor = smallResizingProcessor |
|||
} |
|||
|
|||
imageView.contentMode = UIImageView.ContentMode.scaleAspectFill |
|||
imageView.isUserInteractionEnabled = true |
|||
imageView.kf.indicatorType = .activity |
|||
imageView.kf.setImage(with: attachment.url!, placeholder: placeholder, options: [.processor(processor)]) |
|||
|
|||
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(attachmentTapped)) |
|||
tapGestureRecognizer.delegate = self |
|||
tapGestureRecognizer.numberOfTapsRequired = 1 |
|||
tapGestureRecognizer.numberOfTouchesRequired = 1 |
|||
tapGestureRecognizer.name = String(index) |
|||
|
|||
imageView.addGestureRecognizer(tapGestureRecognizer) |
|||
|
|||
view.addSubview(imageView) |
|||
imageView.translatesAutoresizingMaskIntoConstraints = false |
|||
|
|||
if index == 0 { |
|||
NSLayoutConstraint.activate([ |
|||
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor), |
|||
imageView.topAnchor.constraint(equalTo: view.topAnchor), |
|||
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor), |
|||
imageView.widthAnchor.constraint(equalToConstant: halfWidth), |
|||
]) |
|||
} else { |
|||
NSLayoutConstraint.activate([ |
|||
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor), |
|||
imageView.widthAnchor.constraint(equalToConstant: halfWidth), |
|||
imageView.heightAnchor.constraint(equalToConstant: halfWidth), |
|||
]) |
|||
} |
|||
} |
|||
|
|||
NSLayoutConstraint.activate([ |
|||
imageViews[1].topAnchor.constraint(equalTo: view.topAnchor), |
|||
imageViews[2].bottomAnchor.constraint(equalTo: view.bottomAnchor), |
|||
]) |
|||
default: |
|||
let imageViews = [ |
|||
UIImageView(), |
|||
UIImageView(), |
|||
UIImageView(), |
|||
UIImageView(), |
|||
] |
|||
|
|||
for (index, imageView) in imageViews.enumerated() { |
|||
let attachment = attachments[index] as! AttachmentMO |
|||
|
|||
imageView.contentMode = UIImageView.ContentMode.scaleAspectFill |
|||
imageView.isUserInteractionEnabled = true |
|||
imageView.kf.indicatorType = .activity |
|||
imageView.kf.setImage(with: attachment.url!, placeholder: placeholder, options: [.processor(smallResizingProcessor)]) |
|||
|
|||
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(attachmentTapped)) |
|||
tapGestureRecognizer.delegate = self |
|||
tapGestureRecognizer.numberOfTapsRequired = 1 |
|||
tapGestureRecognizer.numberOfTouchesRequired = 1 |
|||
tapGestureRecognizer.name = String(index) |
|||
|
|||
imageView.addGestureRecognizer(tapGestureRecognizer) |
|||
|
|||
view.addSubview(imageView) |
|||
imageView.translatesAutoresizingMaskIntoConstraints = false |
|||
} |
|||
|
|||
NSLayoutConstraint.activate([ |
|||
imageViews[0].topAnchor.constraint(equalTo: view.topAnchor), |
|||
imageViews[0].leadingAnchor.constraint(equalTo: view.leadingAnchor), |
|||
imageViews[1].topAnchor.constraint(equalTo: view.topAnchor), |
|||
imageViews[1].trailingAnchor.constraint(equalTo: view.trailingAnchor), |
|||
imageViews[2].leadingAnchor.constraint(equalTo: view.leadingAnchor), |
|||
imageViews[2].bottomAnchor.constraint(equalTo: view.bottomAnchor), |
|||
imageViews[3].bottomAnchor.constraint(equalTo: view.bottomAnchor), |
|||
imageViews[3].trailingAnchor.constraint(equalTo: view.trailingAnchor), |
|||
]) |
|||
} |
|||
} |
|||
} |
|||
|
|||
extension AttachmentManager: UIGestureRecognizerDelegate { |
|||
|
|||
} |
@ -0,0 +1,111 @@ |
|||
// |
|||
// AttachmentsView.swift |
|||
// elpha-ios |
|||
// |
|||
// Created by Dwayne Harris on 11/28/18. |
|||
// Copyright © 2018 Elpha. All rights reserved. |
|||
// |
|||
|
|||
import UIKit |
|||
|
|||
protocol AttachmentsViewDelegate: class { |
|||
func attachmentTapped(_ sender: Any, index: Int) |
|||
} |
|||
|
|||
class AttachmentsView: UIView { |
|||
@IBOutlet var contentView: UIView! |
|||
@IBOutlet var attachmentsCollectionView: UICollectionView! |
|||
|
|||
var attachments: [AttachmentMO]? |
|||
weak var delegate: AttachmentsViewDelegate? |
|||
|
|||
override init(frame: CGRect) { |
|||
super.init(frame: frame) |
|||
setup() |
|||
} |
|||
|
|||
required init?(coder aDecoder: NSCoder) { |
|||
super.init(coder: aDecoder) |
|||
setup() |
|||
} |
|||
|
|||
private func setup() { |
|||
Bundle.main.loadNibNamed("AttachmentsView", owner: self, options: nil) |
|||
addSubview(contentView) |
|||
contentView.frame = self.bounds |
|||
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] |
|||
|
|||
attachmentsCollectionView.dataSource = self |
|||
attachmentsCollectionView.delegate = self |
|||
|
|||
attachmentsCollectionView.register(UINib(nibName: "ImageAttachmentCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ImageAttachmentCollectionViewCell") |
|||
attachmentsCollectionView.register(UINib(nibName: "VideoAttachmentCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "VideoAttachmentCollectionViewCell") |
|||
} |
|||
|
|||
func update(withAttachments attachments: [AttachmentMO]) { |
|||
self.attachments = attachments |
|||
|
|||
attachmentsCollectionView.collectionViewLayout.invalidateLayout() |
|||
attachmentsCollectionView.reloadData() |
|||
attachmentsCollectionView.setNeedsLayout() |
|||
} |
|||
} |
|||
|
|||
extension AttachmentsView: UICollectionViewDelegate, UICollectionViewDataSource { |
|||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { |
|||
return attachments?.count ?? 0 |
|||
} |
|||
|
|||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { |
|||
guard let attachment = attachments?[indexPath.row] else { |
|||
fatalError("") |
|||
} |
|||
|
|||
let attachmentType = AttachmentType(rawValue: attachment.type!)! |
|||
|
|||
switch attachmentType { |
|||
case .gifv, .video: |
|||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VideoAttachmentCollectionViewCell", for: indexPath) as! VideoAttachmentCollectionViewCell |
|||
cell.update(withAttachment: attachment) |
|||
|
|||
return cell |
|||
default: |
|||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageAttachmentCollectionViewCell", for: indexPath) as! ImageAttachmentCollectionViewCell |
|||
cell.update(withAttachment: attachment) |
|||
|
|||
return cell |
|||
} |
|||
} |
|||
|
|||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { |
|||
delegate?.attachmentTapped(self, index: indexPath.row) |
|||
} |
|||
} |
|||
|
|||
extension AttachmentsView: UICollectionViewDelegateFlowLayout { |
|||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { |
|||
let halfWidth = (frame.size.width / 2) - 1 |
|||
let tallSize = CGSize(width: halfWidth, height: frame.size.width) |
|||
let smallSize = CGSize(width: halfWidth, height: halfWidth) |
|||
|
|||
switch attachments?.count ?? 0 { |
|||
case 1: return CGSize(width: frame.size.width, height: frame.size.width) |
|||
case 2: return tallSize |
|||
case 3: return indexPath.row == 0 ? tallSize : smallSize |
|||
case 4: return smallSize |
|||
default: return CGSize.zero |
|||
} |
|||
} |
|||
|
|||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { |
|||
return 0 |
|||
} |
|||
|
|||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { |
|||
return 2 |
|||
} |
|||
|
|||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { |
|||
return UIEdgeInsets.zero |
|||
} |
|||
} |
@ -0,0 +1,49 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> |
|||
<device id="retina4_7" orientation="portrait"> |
|||
<adaptation id="fullscreen"/> |
|||
</device> |
|||
<dependencies> |
|||
<deployment identifier="iOS"/> |
|||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/> |
|||
<capability name="Safe area layout guides" minToolsVersion="9.0"/> |
|||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
|||
</dependencies> |
|||
<objects> |
|||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AttachmentsView" customModule="elpha_ios" customModuleProvider="target"> |
|||
<connections> |
|||
<outlet property="attachmentsCollectionView" destination="XgR-gy-s01" id="392-HX-a4n"/> |
|||
<outlet property="contentView" destination="iN0-l3-epB" id="wc2-nq-QWB"/> |
|||
</connections> |
|||
</placeholder> |
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
|||
<view contentMode="scaleToFill" id="iN0-l3-epB"> |
|||
<rect key="frame" x="0.0" y="0.0" width="375" height="375"/> |
|||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
|||
<subviews> |
|||
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="none" prefetchingEnabled="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XgR-gy-s01"> |
|||
<rect key="frame" x="0.0" y="0.0" width="375" height="375"/> |
|||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> |
|||
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="aaI-cP-xj8"> |
|||
<size key="itemSize" width="50" height="50"/> |
|||
<size key="headerReferenceSize" width="0.0" height="0.0"/> |
|||
<size key="footerReferenceSize" width="0.0" height="0.0"/> |
|||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> |
|||
</collectionViewFlowLayout> |
|||
</collectionView> |
|||
</subviews> |
|||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
|||
<constraints> |
|||
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="XgR-gy-s01" secondAttribute="trailing" id="MKv-iq-hUD"/> |
|||
<constraint firstItem="XgR-gy-s01" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="MRt-HO-y16"/> |
|||
<constraint firstItem="XgR-gy-s01" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="ba3-15-hfG"/> |
|||
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="XgR-gy-s01" secondAttribute="bottom" id="yCC-41-Mwc"/> |
|||
</constraints> |
|||
<nil key="simulatedTopBarMetrics"/> |
|||
<nil key="simulatedBottomBarMetrics"/> |
|||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> |
|||
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/> |
|||
<point key="canvasLocation" x="138.40000000000001" y="284.70764617691157"/> |
|||
</view> |
|||
</objects> |
|||
</document> |
@ -0,0 +1,24 @@ |
|||
// |
|||
// ImageAttachmentCollectionViewCell.swift |
|||
// elpha-ios |
|||
// |
|||
// Created by Dwayne Harris on 11/29/18. |
|||
// Copyright © 2018 Elpha. All rights reserved. |
|||
// |
|||
|
|||
import Kingfisher |
|||
import UIKit |
|||
|
|||
class ImageAttachmentCollectionViewCell: UICollectionViewCell { |
|||
@IBOutlet var imageView: UIImageView! |
|||
var attachment: AttachmentMO? |
|||
|
|||
override func awakeFromNib() { |
|||
super.awakeFromNib() |
|||
} |
|||
|
|||
func update(withAttachment attachment: AttachmentMO) { |
|||
self.attachment = attachment |
|||
imageView.kf.setImage(with: attachment.url!, placeholder: UIImage(named: "Placeholder")) |
|||
} |
|||
} |
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> |
|||
<device id="retina4_7" orientation="portrait"> |
|||
<adaptation id="fullscreen"/> |
|||
</device> |
|||
<dependencies> |
|||
<deployment identifier="iOS"/> |
|||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/> |
|||
<capability name="Safe area layout guides" minToolsVersion="9.0"/> |
|||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
|||
</dependencies> |
|||
<objects> |
|||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> |
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
|||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="ImageAttachmentCollectionViewCell" id="gTV-IL-0wX" customClass="ImageAttachmentCollectionViewCell" customModule="elpha_ios" customModuleProvider="target"> |
|||
<rect key="frame" x="0.0" y="0.0" width="375" height="375"/> |
|||
<autoresizingMask key="autoresizingMask"/> |
|||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> |
|||
<rect key="frame" x="0.0" y="0.0" width="375" height="375"/> |
|||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> |
|||
<subviews> |
|||
<imageView clipsSubviews="YES" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="X7C-Rz-5zN"> |
|||
<rect key="frame" x="0.0" y="0.0" width="375" height="375"/> |
|||
</imageView> |
|||
</subviews> |
|||
</view> |
|||
<constraints> |
|||
<constraint firstAttribute="trailing" secondItem="X7C-Rz-5zN" secondAttribute="trailing" id="58Q-wS-bVY"/> |
|||
<constraint firstAttribute="bottom" secondItem="X7C-Rz-5zN" secondAttribute="bottom" id="A26-zo-rCZ"/> |
|||
<constraint firstItem="X7C-Rz-5zN" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="Cxe-QE-g8T"/> |
|||
<constraint firstItem="X7C-Rz-5zN" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="KZG-bH-MzT"/> |
|||
</constraints> |
|||
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/> |
|||
<connections> |
|||
<outlet property="imageView" destination="X7C-Rz-5zN" id="WMo-NR-zpQ"/> |
|||
</connections> |
|||
</collectionViewCell> |
|||
</objects> |
|||
</document> |
@ -0,0 +1,42 @@ |
|||
// |
|||
// VideoAttachmentCollectionViewCell.swift |
|||
// elpha-ios |
|||
// |
|||
// Created by Dwayne Harris on 11/29/18. |
|||
// Copyright © 2018 Elpha. All rights reserved. |
|||
// |
|||
|
|||
import AVFoundation |
|||
import AVKit |
|||
import UIKit |
|||
|
|||
class VideoAttachmentCollectionViewCell: UICollectionViewCell { |
|||
var attachment: AttachmentMO? |
|||
var player: AVQueuePlayer! |
|||
var playerLayer: AVPlayerLayer! |
|||
var playerLooper: AVPlayerLooper? |
|||
|
|||
override func awakeFromNib() { |
|||
super.awakeFromNib() |
|||
|
|||
player = AVQueuePlayer() |
|||
player.preventsDisplaySleepDuringVideoPlayback = false |
|||
player.usesExternalPlaybackWhileExternalScreenIsActive = false |
|||
player.isMuted = true |
|||
|
|||
playerLayer = AVPlayerLayer(player: player) |
|||
playerLayer.videoGravity = .resizeAspectFill |
|||
} |
|||
|
|||
func update(withAttachment attachment: AttachmentMO) { |
|||
self.attachment = attachment |
|||
|
|||
layer.addSublayer(playerLayer) |
|||
playerLayer.frame = bounds |
|||
playerLooper = AVPlayerLooper(player: player!, templateItem: AVPlayerItem(url: attachment.url!)) |
|||
|
|||
if SettingsManager.automaticallyPlayGIFs { |
|||
player.play() |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,25 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> |
|||
<device id="retina4_7" orientation="portrait"> |
|||
<adaptation id="fullscreen"/> |
|||
</device> |
|||
<dependencies> |
|||
<deployment identifier="iOS"/> |
|||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/> |
|||
<capability name="Safe area layout guides" minToolsVersion="9.0"/> |
|||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
|||
</dependencies> |
|||
<objects> |
|||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> |
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
|||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="VideoAttachmentCollectionViewCell" id="gTV-IL-0wX" customClass="VideoAttachmentCollectionViewCell" customModule="elpha_ios" customModuleProvider="target"> |
|||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/> |
|||
<autoresizingMask key="autoresizingMask"/> |
|||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> |
|||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/> |
|||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> |
|||
</view> |
|||
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/> |
|||
</collectionViewCell> |
|||
</objects> |
|||
</document> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue