Skip to content

Commit

Permalink
Merge pull request #39 from carousell/feature/live-preview
Browse files Browse the repository at this point in the history
Live Preview
  • Loading branch information
daveluong authored Apr 9, 2019
2 parents 303056c + 9ae0bf8 commit 889000b
Show file tree
Hide file tree
Showing 19 changed files with 282 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .jazzy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ github_url: https://github.com/carousell/pickle
github_file_prefix: https://github.com/carousell/pickle/blob/master
xcodebuild_arguments: [-project, Pickle.xcodeproj, -scheme, Pickle]
module: Pickle
module_version: 1.3.1
module_version: 1.4.0
output: docs/output
theme: fullwidth
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* Swift 4.2
* Move the framework and example targets into a single project
* Add new configurable to show live camera view cell in photo picker

## v1.3.1

Expand Down
2 changes: 2 additions & 0 deletions Example/CarousellImagePickerController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ private struct CarousellTheme: ImagePickerConfigurable {

let doneBarButtonItem: UIBarButtonItem? = UIBarButtonItem(title: "Next", style: .plain, target: nil, action: nil)

let isLiveCameraViewEnabled: Bool? = true

// MARK: - Navigation Bar

let navigationBarStyle: UIBarStyle? = .blackTranslucent
Expand Down
17 changes: 16 additions & 1 deletion Example/Images.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
Expand Down Expand Up @@ -29,10 +39,15 @@
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
}
2 changes: 1 addition & 1 deletion Pickle.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Pickle'
s.version = '1.3.1'
s.version = '1.4.0'
s.summary = 'Carousell flavoured image picker with multiple photo selections.'
s.homepage = 'https://github.com/carousell/pickle'
s.license = { :type => 'Apache License 2.0', :file => 'LICENSE' }
Expand Down
23 changes: 21 additions & 2 deletions Pickle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
20DB284F22560DB000037FEF /* LiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20DB284D22560DB000037FEF /* LiveView.swift */; };
20DB285022560DB000037FEF /* PhotoGalleryLiveViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20DB284E22560DB000037FEF /* PhotoGalleryLiveViewCell.swift */; };
20FC48032256FAC3004CCD1D /* CameraSessionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20FC48022256FAC3004CCD1D /* CameraSessionHandler.swift */; };
5D5D6367F14D7B8C139E10E9 /* Pods_PickleUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D176E52E185B871CF8D97C4 /* Pods_PickleUITests.framework */; };
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
Expand Down Expand Up @@ -78,6 +81,9 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
20DB284D22560DB000037FEF /* LiveView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiveView.swift; sourceTree = "<group>"; };
20DB284E22560DB000037FEF /* PhotoGalleryLiveViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoGalleryLiveViewCell.swift; sourceTree = "<group>"; };
20FC48022256FAC3004CCD1D /* CameraSessionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraSessionHandler.swift; sourceTree = "<group>"; };
4B31C2D2E0E432A6637C5883 /* Pods_PickleExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PickleExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD01AFB9204008FA782 /* PickleExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PickleExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -269,6 +275,9 @@
B57BEA54216AAFD700A2C776 /* PhotoGalleryCameraCell.swift */,
B57BEA5E216AAFD700A2C776 /* PhotoGalleryCameraIconView.swift */,
B57BEA57216AAFD700A2C776 /* PhotoGalleryCell.swift */,
20DB284D22560DB000037FEF /* LiveView.swift */,
20FC48022256FAC3004CCD1D /* CameraSessionHandler.swift */,
20DB284E22560DB000037FEF /* PhotoGalleryLiveViewCell.swift */,
B57BEA4F216AAFD700A2C776 /* PhotoGalleryHintLabel.swift */,
B57BEA5B216AAFD700A2C776 /* PhotoGalleryTagLabel.swift */,
B57BEA5F216AAFD700A2C776 /* PhotoGalleryViewController+UIViewControllerPreviewing.swift */,
Expand Down Expand Up @@ -363,12 +372,13 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 1000;
LastUpgradeCheck = 1010;
ORGANIZATIONNAME = Carousell;
TargetAttributes = {
607FACCF1AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
LastSwiftMigration = 0900;
ProvisioningStyle = Manual;
};
B563515A1F06278E00B5A46D = {
CreatedOnToolsVersion = 8.3.3;
Expand Down Expand Up @@ -516,6 +526,7 @@
buildActionMask = 2147483647;
files = (
B57BEA78216AAFD700A2C776 /* CameraCompatible.swift in Sources */,
20DB284F22560DB000037FEF /* LiveView.swift in Sources */,
B57BEA74216AAFD700A2C776 /* ImagePickerConfigurable.swift in Sources */,
B57BEA68216AAFD700A2C776 /* ImagePickerController.swift in Sources */,
B57BEA72216AAFD700A2C776 /* ImagePickerControllerDelegate.swift in Sources */,
Expand All @@ -529,7 +540,9 @@
B57BEA7A216AAFD700A2C776 /* PhotoGalleryCameraIconView.swift in Sources */,
B57BEA73216AAFD700A2C776 /* PhotoGalleryCell.swift in Sources */,
B57BEA6B216AAFD700A2C776 /* PhotoGalleryHintLabel.swift in Sources */,
20FC48032256FAC3004CCD1D /* CameraSessionHandler.swift in Sources */,
B57BEA77216AAFD700A2C776 /* PhotoGalleryTagLabel.swift in Sources */,
20DB285022560DB000037FEF /* PhotoGalleryLiveViewCell.swift in Sources */,
B57BEA7B216AAFD700A2C776 /* PhotoGalleryViewController+UIViewControllerPreviewing.swift in Sources */,
B57BEA75216AAFD700A2C776 /* PhotoGalleryViewController.swift in Sources */,
B57BEA6D216AAFD700A2C776 /* SlideDownDismissingAnimator.swift in Sources */,
Expand Down Expand Up @@ -587,6 +600,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
Expand Down Expand Up @@ -643,6 +657,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
Expand Down Expand Up @@ -695,13 +710,15 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "com.carousell.pickle-example";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
};
name = Debug;
Expand All @@ -713,13 +730,15 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "com.carousell.pickle-example";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
};
name = Release;
Expand Down Expand Up @@ -771,7 +790,7 @@
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1000"
LastUpgradeVersion = "1010"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
22 changes: 22 additions & 0 deletions Pickle/Assets/Images.xcassets/camera-icon.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "[email protected]",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 63 additions & 0 deletions Pickle/Classes/CameraSessionHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// This source file is part of the carousell/pickle open source project
//
// Copyright © 2019 Carousell and the project authors
// Licensed under Apache License v2.0
//
// See https://github.com/carousell/pickle/blob/master/LICENSE for license information
// See https://github.com/carousell/pickle/graphs/contributors for the list of project authors
//


import Foundation
import AVFoundation

final class CameraSessionHandler {

enum CameraSessionError: Error {
case noDeviceInput, noPermission
}

private let session = AVCaptureSession()

weak var previewView: LiveView? {
didSet {
previewView?.session = session
}
}

var isRunning: Bool {
return session.isRunning
}

var hasPermssion: Bool {
return AVCaptureDevice.authorizationStatus(for: .video) == .authorized
}

private let sessionQueue = DispatchQueue(label: "pickle.liveView.sessionQueue")

init() throws {
guard hasPermssion else { throw CameraSessionError.noPermission }
}

func startSession() throws {
guard
let input = AVCaptureDevice.default(for: .video),
let deviceInput = try? AVCaptureDeviceInput(device: input) else {
throw CameraSessionError.noDeviceInput
}
if session.inputs.count == 0 {
session.addInput(deviceInput)
}
sessionQueue.async { [weak self] in
guard self?.session.isRunning == .some(false) else { return }
self?.session.startRunning()
}
}

func stopSession() {
sessionQueue.async { [weak self] in
self?.session.stopRunning()
}
}
}
4 changes: 4 additions & 0 deletions Pickle/Classes/ImagePickerConfigurable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ public protocol ImagePickerConfigurable {

/// The margin for the text of the hint label.
var hintTextMargin: UIEdgeInsets? { get }

// MARK: -
/// Specifies whether the photo gallery should show a live camera view cell
var isLiveCameraViewEnabled: Bool? { get }
}


Expand Down
10 changes: 9 additions & 1 deletion Pickle/Classes/ImagePickerController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ open class ImagePickerController: UINavigationController {
showPermissionErrorIfNeeded?()
}

public func updateSelectedAssets(with assets: [PHAsset]) {
selectedAssets = assets
galleryViewController?.collectionView.reloadData()
}
}


Expand Down Expand Up @@ -382,7 +386,11 @@ fileprivate extension ImagePickerController {
}
}
default:
present(camera(), animated: true, completion: nil)
present(camera(), animated: true) { [weak self] in
guard let self = self else { return }
self.imagePickerDelegate?.imagePickerController?(
self, didFinishLaunchingCameraWith: self.selectedAssets)
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions Pickle/Classes/ImagePickerControllerDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ public protocol ImagePickerControllerDelegate: UINavigationControllerDelegate {
/// Asks the delegate if the image picker should launch camera with certain permission status.
func imagePickerController(_ picker: ImagePickerController, shouldLaunchCameraWithAuthorization status: AVAuthorizationStatus) -> Bool

/// Tells the delegate that picker has finished launching camera with an array of selected assets
@objc optional func imagePickerController(_ picker: ImagePickerController, didFinishLaunchingCameraWith assets: [PHAsset])

/// Tells the delegate that the user picked image assets.
func imagePickerController(_ picker: ImagePickerController, didFinishPickingImageAssets assets: [PHAsset])

Expand Down
36 changes: 36 additions & 0 deletions Pickle/Classes/LiveView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// This source file is part of the carousell/pickle open source project
//
// Copyright © 2019 Carousell and the project authors
// Licensed under Apache License v2.0
//
// See https://github.com/carousell/pickle/blob/master/LICENSE for license information
// See https://github.com/carousell/pickle/graphs/contributors for the list of project authors
//

import AVFoundation
import UIKit

final class LiveView: UIView {

override class var layerClass: AnyClass {
return AVCaptureVideoPreviewLayer.self
}

private var videoPreviewLayer: AVCaptureVideoPreviewLayer {
guard let layer = self.layer as? AVCaptureVideoPreviewLayer else {
fatalError("Expected `AVCaptureVideoPreviewLayer` type for layer. Check LiveView.layerClass implementation.")
}
layer.videoGravity = .resizeAspectFill
return layer
}

var session: AVCaptureSession? {
get {
return videoPreviewLayer.session
}
set {
videoPreviewLayer.session = newValue
}
}
}
6 changes: 6 additions & 0 deletions Pickle/Classes/Parameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import UIKit
/// A struct with placeholders that `ImagePickerConfigurable` requires.
public struct Parameters: ImagePickerConfigurable {


/// Returns a configuration instance with default parameters.
public init() {}

Expand Down Expand Up @@ -79,4 +80,9 @@ public struct Parameters: ImagePickerConfigurable {
/// The margin for the text of the hint label.
public var hintTextMargin: UIEdgeInsets?

// MARK: -

/// Specifies weather photo gallery should show a live preview
public var isLiveCameraViewEnabled: Bool?

}
Loading

0 comments on commit 889000b

Please sign in to comment.