Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
tankista committed Nov 2, 2017
2 parents 8174281 + f860536 commit dfa3336
Show file tree
Hide file tree
Showing 14 changed files with 432 additions and 115 deletions.
4 changes: 2 additions & 2 deletions ExampleApp/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ let sectionsData: [(String?, String?)] = [
("Assets Source", nil),
("Asset Items in a row", nil),
("Capture mode", nil),
("Save Assets", "Assets will be saved to Photo Library")
("Save Assets", "Assets will be saved to Photo Library. This applies to photos only. Live photos and videos are always saved.")
]

///
Expand Down Expand Up @@ -227,7 +227,7 @@ class ViewController: UITableViewController {
}

// save capture assets to photo library?
imagePicker.captureSettings.savesCapturedAssetToPhotoLibrary = savesCapturedAssets
imagePicker.captureSettings.savesCapturedPhotosToPhotoLibrary = savesCapturedAssets

// presentation
// before we present VC we can ask for authorization to photo library,
Expand Down
36 changes: 26 additions & 10 deletions ImagePicker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
425777531F98D110000824F0 /* ActionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 425777511F98D10F000824F0 /* ActionCell.swift */; };
425777541F98D119000824F0 /* ActionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 425777521F98D10F000824F0 /* ActionCell.xib */; };
425BEC851F7D351A0091D008 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 425BEC841F7D351A0091D008 /* Assets.xcassets */; };
427271701FA1D304008AC2B4 /* CarvedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4272716F1FA1D304008AC2B4 /* CarvedLabel.swift */; };
427925F31F9636D700B6D55F /* StationaryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 427925F21F9636D700B6D55F /* StationaryButton.swift */; };
427925F51F96381400B6D55F /* ShutterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 427925F41F96381400B6D55F /* ShutterButton.swift */; };
427925F71F96388000B6D55F /* RecordButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 427925F61F96388000B6D55F /* RecordButton.swift */; };
427925FD1F963A8D00B6D55F /* VideoCameraCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 427925FB1F963A8C00B6D55F /* VideoCameraCell.swift */; };
427925FE1F963B2800B6D55F /* VideoCameraCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 427925FC1F963A8C00B6D55F /* VideoCameraCell.xib */; };
427926011F963E9C00B6D55F /* LivePhotoCameraCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 427925FF1F963E9B00B6D55F /* LivePhotoCameraCell.swift */; };
427926021F96407900B6D55F /* LivePhotoCameraCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 427926001F963E9C00B6D55F /* LivePhotoCameraCell.xib */; };
42990DBF1FA07AF7001658C4 /* RecordDurationLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42990DBE1FA07AF7001658C4 /* RecordDurationLabel.swift */; };
429BFDAA1F68161D00029440 /* ImagePickerAssetModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 429BFDA91F68161D00029440 /* ImagePickerAssetModel.swift */; };
42A037E01F66C9E700534350 /* CustomVideoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 42A037DF1F66C9E700534350 /* CustomVideoCell.xib */; };
42D097991F7BD6E200A66E33 /* UIImageEffects.m in Sources */ = {isa = PBXBuildFile; fileRef = 42D097971F7BD6E100A66E33 /* UIImageEffects.m */; };
Expand Down Expand Up @@ -110,13 +112,15 @@
425777511F98D10F000824F0 /* ActionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCell.swift; sourceTree = "<group>"; };
425777521F98D10F000824F0 /* ActionCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ActionCell.xib; sourceTree = "<group>"; };
425BEC841F7D351A0091D008 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4272716F1FA1D304008AC2B4 /* CarvedLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarvedLabel.swift; sourceTree = "<group>"; };
427925F21F9636D700B6D55F /* StationaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StationaryButton.swift; sourceTree = "<group>"; };
427925F41F96381400B6D55F /* ShutterButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShutterButton.swift; sourceTree = "<group>"; };
427925F61F96388000B6D55F /* RecordButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordButton.swift; sourceTree = "<group>"; };
427925FB1F963A8C00B6D55F /* VideoCameraCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCameraCell.swift; sourceTree = "<group>"; };
427925FC1F963A8C00B6D55F /* VideoCameraCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VideoCameraCell.xib; sourceTree = "<group>"; };
427925FF1F963E9B00B6D55F /* LivePhotoCameraCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LivePhotoCameraCell.swift; sourceTree = "<group>"; };
427926001F963E9C00B6D55F /* LivePhotoCameraCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LivePhotoCameraCell.xib; sourceTree = "<group>"; };
42990DBE1FA07AF7001658C4 /* RecordDurationLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordDurationLabel.swift; sourceTree = "<group>"; };
429BFDA91F68161D00029440 /* ImagePickerAssetModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePickerAssetModel.swift; sourceTree = "<group>"; };
42A037DF1F66C9E700534350 /* CustomVideoCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CustomVideoCell.xib; sourceTree = "<group>"; };
42D097971F7BD6E100A66E33 /* UIImageEffects.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIImageEffects.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -190,23 +194,14 @@
420C24181F5D82F9008935D4 /* ImagePicker.h */,
42D7036F1F7909100057D557 /* Public */,
42D703701F790A3F0057D557 /* Media */,
42990DBD1FA07A6C001658C4 /* Views */,
420C24351F5ED4AA008935D4 /* ImagePickerLayout.swift */,
429BFDA91F68161D00029440 /* ImagePickerAssetModel.swift */,
420C24271F5D925A008935D4 /* ImagePickerDataSource.swift */,
420C24331F5DA022008935D4 /* ImagePickerDelegate.swift */,
420C243E1F5EEA19008935D4 /* LayoutModel.swift */,
4214426E1F604498006BA45A /* ImagePickerSelectionPolicy.swift */,
42EDD4151F712B2A00EAD2F5 /* Miscellaneous.swift */,
42D0979B1F7BF6B300A66E33 /* AssetCell.swift */,
427925F21F9636D700B6D55F /* StationaryButton.swift */,
427925F41F96381400B6D55F /* ShutterButton.swift */,
427925F61F96388000B6D55F /* RecordButton.swift */,
427925FB1F963A8C00B6D55F /* VideoCameraCell.swift */,
427925FC1F963A8C00B6D55F /* VideoCameraCell.xib */,
427925FF1F963E9B00B6D55F /* LivePhotoCameraCell.swift */,
427926001F963E9C00B6D55F /* LivePhotoCameraCell.xib */,
425777511F98D10F000824F0 /* ActionCell.swift */,
425777521F98D10F000824F0 /* ActionCell.xib */,
425BEC841F7D351A0091D008 /* Assets.xcassets */,
42D097981F7BD6E100A66E33 /* UIImageEffects.h */,
42D097971F7BD6E100A66E33 /* UIImageEffects.m */,
Expand All @@ -228,6 +223,25 @@
path = "Custom Views";
sourceTree = "<group>";
};
42990DBD1FA07A6C001658C4 /* Views */ = {
isa = PBXGroup;
children = (
425777511F98D10F000824F0 /* ActionCell.swift */,
425777521F98D10F000824F0 /* ActionCell.xib */,
42D0979B1F7BF6B300A66E33 /* AssetCell.swift */,
427925FF1F963E9B00B6D55F /* LivePhotoCameraCell.swift */,
427926001F963E9C00B6D55F /* LivePhotoCameraCell.xib */,
427925F61F96388000B6D55F /* RecordButton.swift */,
42990DBE1FA07AF7001658C4 /* RecordDurationLabel.swift */,
427925F41F96381400B6D55F /* ShutterButton.swift */,
427925F21F9636D700B6D55F /* StationaryButton.swift */,
427925FB1F963A8C00B6D55F /* VideoCameraCell.swift */,
427925FC1F963A8C00B6D55F /* VideoCameraCell.xib */,
4272716F1FA1D304008AC2B4 /* CarvedLabel.swift */,
);
name = Views;
sourceTree = "<group>";
};
42D7036F1F7909100057D557 /* Public */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -399,6 +413,7 @@
42E736521F8510B70060E24D /* VideoCaptureDelegate.swift in Sources */,
429BFDAA1F68161D00029440 /* ImagePickerAssetModel.swift in Sources */,
42D7036B1F7908B10057D557 /* CaptureSettings.swift in Sources */,
42990DBF1FA07AF7001658C4 /* RecordDurationLabel.swift in Sources */,
42EDD41A1F716F6300EAD2F5 /* PhotoCaptureDelegate.swift in Sources */,
420C24341F5DA022008935D4 /* ImagePickerDelegate.swift in Sources */,
420C24281F5D925A008935D4 /* ImagePickerDataSource.swift in Sources */,
Expand All @@ -413,6 +428,7 @@
42EDD4161F712B2A00EAD2F5 /* Miscellaneous.swift in Sources */,
427926011F963E9C00B6D55F /* LivePhotoCameraCell.swift in Sources */,
42311FFC1F73DBBF00B1AEB4 /* VideoOuptutSampleBufferDelegate.swift in Sources */,
427271701FA1D304008AC2B4 /* CarvedLabel.swift in Sources */,
42F7D8011F7A5B72009D378A /* Appearance.swift in Sources */,
420C24261F5D8393008935D4 /* ImagePickerController.swift in Sources */,
42EDD4051F7125C700EAD2F5 /* CaptureSession.swift in Sources */,
Expand Down
13 changes: 4 additions & 9 deletions ImagePicker/CaptureSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,6 @@ final class CaptureSession : NSObject {

var presetConfiguration: SessionPresetConfiguration = .photos

///
/// Save assets to library or not. Appropriate delegate is called in all cases.
///
var saveCapturedAssetsToPhotoLibrary = false

///
/// Set this method to orientation that mathches UI orientation before `prepare()`
/// method is called. If you need to update orientation when session is running,
Expand Down Expand Up @@ -699,7 +694,7 @@ extension CaptureSession {

extension CaptureSession {

func capturePhoto(livePhotoMode: LivePhotoMode) {
func capturePhoto(livePhotoMode: LivePhotoMode, saveToPhotoLibrary: Bool) {
/*
Retrieve the video preview layer's video orientation on the main queue before
entering the session queue. We do this to ensure UI elements are accessed on
Expand Down Expand Up @@ -795,7 +790,7 @@ extension CaptureSession {
}
})

photoCaptureDelegate.savesPhotoToLibrary = self.saveCapturedAssetsToPhotoLibrary
photoCaptureDelegate.savesPhotoToLibrary = saveToPhotoLibrary

/*
The Photo Output keeps a weak reference to the photo capture delegate so
Expand All @@ -811,7 +806,7 @@ extension CaptureSession {

extension CaptureSession {

func startVideoRecording() {
func startVideoRecording(saveToPhotoLibrary: Bool) {

guard let movieFileOutput = self.videoFileOutput else {
return log("capture session: trying to record a video but no movie file output is set")
Expand Down Expand Up @@ -884,7 +879,7 @@ extension CaptureSession {
}
}
})
recordingDelegate.savesPhotoToLibrary = strongSelf.saveCapturedAssetsToPhotoLibrary
recordingDelegate.savesVideoToLibrary = saveToPhotoLibrary

// start recording
movieFileOutput.startRecording(to: outputURL, recordingDelegate: recordingDelegate)
Expand Down
15 changes: 11 additions & 4 deletions ImagePicker/CaptureSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,23 @@ public struct CaptureSettings {
public var cameraMode: CameraMode

///
/// Return true if captured assets will be saved to photo library. Image picker
/// will prompt user with request for permisssions when needed. Default value is false.
/// Return true if captured photos will be saved to photo library. Image picker
/// will prompt user with request for permisssions when needed. Default value is false
/// for photos. Live photos and videos are always true.
///
public var savesCapturedAssetToPhotoLibrary: Bool
/// - note: please note, that at current implementation this applies to photos only. For
/// live photos and videos this is always true.
///
public var savesCapturedPhotosToPhotoLibrary: Bool

let savesCapturedLivePhotosToPhotoLibrary: Bool = true
let savesCapturedVideosToPhotoLibrary: Bool = true

/// Default configuration
public static var `default`: CaptureSettings {
return CaptureSettings(
cameraMode: .photo,
savesCapturedAssetToPhotoLibrary: false
savesCapturedPhotosToPhotoLibrary: false
)
}
}
Expand Down
113 changes: 113 additions & 0 deletions ImagePicker/CarvedLabel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// CarvedLabel.swift
// ImagePicker
//
// Created by Peter Stajger on 26/10/2017.
// Copyright © 2017 Inloop. All rights reserved.
//

import UIKit

fileprivate typealias TextAttributes = [NSAttributedStringKey: Any]

///
/// A label whose transparent text is carved into solid color.
///
/// - please note that text is always aligned to center
///
@IBDesignable
final class CarvedLabel : UIView {

@IBInspectable var text: String? {
didSet {
invalidateIntrinsicContentSize()
setNeedsDisplay()
}
}

var font: UIFont? {
didSet {
invalidateIntrinsicContentSize()
setNeedsDisplay()
}
}

@IBInspectable var cornerRadius: CGFloat = 0 {
didSet { setNeedsDisplay() }
}

@IBInspectable var verticalInset: CGFloat = 0 {
didSet {
invalidateIntrinsicContentSize()
setNeedsDisplay()
}
}

@IBInspectable var horizontalInset: CGFloat = 0 {
didSet {
invalidateIntrinsicContentSize()
setNeedsDisplay()
}

}

override init(frame: CGRect) {
super.init(frame: frame)
_ = backgroundColor
isOpaque = false
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
_ = backgroundColor
isOpaque = false
}

override var backgroundColor: UIColor? {
get { return UIColor.clear }
set { super.backgroundColor = UIColor.clear }
}

fileprivate var textAttributes: TextAttributes {
let activeFont = font ?? UIFont.systemFont(ofSize: 12, weight: .regular)
return [
NSAttributedStringKey.font: activeFont
]
}

fileprivate var attributedString: NSAttributedString {
return NSAttributedString(string: text ?? "", attributes: textAttributes)
}

override func draw(_ rect: CGRect) {
let color = tintColor!
color.setFill()

let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
path.fill()

guard let context = UIGraphicsGetCurrentContext(), (text?.characters.count ?? 0) > 0 else {
return
}

let attributedString = self.attributedString
let stringSize = attributedString.size()

let xOrigin: CGFloat = max(horizontalInset, (rect.width - stringSize.width)/2)
let yOrigin: CGFloat = max(verticalInset, (rect.height - stringSize.height)/2)

context.saveGState()
context.setBlendMode(.destinationOut)
attributedString.draw(at: CGPoint(x: xOrigin, y: yOrigin))
context.restoreGState()
}

override func sizeThatFits(_ size: CGSize) -> CGSize {
let stringSize = attributedString.size()
return CGSize(width: stringSize.width + horizontalInset*2, height: stringSize.height + verticalInset*2)
}

override var intrinsicContentSize: CGSize {
return sizeThatFits(.zero)
}
}
16 changes: 11 additions & 5 deletions ImagePicker/ImagePickerController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ public protocol ImagePickerControllerDelegate : class {
///
func imagePicker(controller: ImagePickerController, didTake image: UIImage)

///
/// Called when user takes new photo.
///
//TODO:
//func imagePicker(controller: ImagePickerController, didCaptureVideo url: UIImage)
//func imagePicker(controller: ImagePickerController, didTake livePhoto: UIImage, videoUrl: UIImage)

///
/// Called right before an action item collection view cell is displayed. Use this method
/// to configure your cell.
Expand Down Expand Up @@ -303,7 +310,7 @@ open class ImagePickerController : UIViewController {
collectionViewDataSource.cellRegistrator = cellRegistrator
collectionViewDelegate.delegate = self
collectionViewDelegate.layout = ImagePickerLayout(configuration: layoutConfiguration)

//register for photo library updates - this is needed when changing permissions to photo library
//TODO: this is expensive (loading library for the first time)
PHPhotoLibrary.shared().register(self)
Expand All @@ -316,7 +323,6 @@ open class ImagePickerController : UIViewController {
let session = CaptureSession()
captureSession = session
session.presetConfiguration = captureSettings.cameraMode.captureSessionPresetConfiguration
session.saveCapturedAssetsToPhotoLibrary = captureSettings.savesCapturedAssetToPhotoLibrary
session.videoOrientation = UIApplication.shared.statusBarOrientation.captureVideoOrientation
session.delegate = self
session.videoRecordingDelegate = self
Expand Down Expand Up @@ -678,15 +684,15 @@ extension ImagePickerController : CaptureSessionVideoRecordingDelegate {
extension ImagePickerController: CameraCollectionViewCellDelegate {

func takePicture() {
captureSession?.capturePhoto(livePhotoMode: .off)
captureSession?.capturePhoto(livePhotoMode: .off, saveToPhotoLibrary: captureSettings.savesCapturedPhotosToPhotoLibrary)
}

func takeLivePhoto() {
captureSession?.capturePhoto(livePhotoMode: .on)
captureSession?.capturePhoto(livePhotoMode: .on, saveToPhotoLibrary: captureSettings.savesCapturedLivePhotosToPhotoLibrary)
}

func startVideoRecording() {
captureSession?.startVideoRecording()
captureSession?.startVideoRecording(saveToPhotoLibrary: captureSettings.savesCapturedVideosToPhotoLibrary)
}

func stopVideoRecording() {
Expand Down
Loading

0 comments on commit dfa3336

Please sign in to comment.