Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live Preview #39

Merged
merged 24 commits into from
Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
87f2273
Add new camera button
daveluong Apr 4, 2019
f502787
Add PhotoGalleryLiveViewCell to show live preview of camera stream
daveluong Apr 4, 2019
ed2b84e
Make live preview a configurable
daveluong Apr 4, 2019
d52ddce
Fix setting wrong cell type & other minor code presentation
daveluong Apr 4, 2019
faddd5f
Update version to 1.4.1 & add missing files
daveluong Apr 4, 2019
7c762bd
Show old camera cell if there is no camera permission
daveluong Apr 4, 2019
c16a310
Update PhotoGalleryViewController.swift
daveluong Apr 4, 2019
23498fb
Remove Example/Pods/*
daveluong Apr 5, 2019
f485fbb
Refactor to decouple camera session handling from the cell
daveluong Apr 5, 2019
88db04e
Set version to 1.4.0
daveluong Apr 5, 2019
d05ca38
Rename property
daveluong Apr 5, 2019
3f1cbfd
Remove unused code
daveluong Apr 5, 2019
d0a003e
Remove codesign config
daveluong Apr 5, 2019
5d4a624
Missing scheme
daveluong Apr 5, 2019
cfd9113
Update CHANGELOG.md
daveluong Apr 5, 2019
4682bb9
Merge branch 'master' into feature/live-preview
daveluong Apr 8, 2019
fd69328
Make property private and fix typo
daveluong Apr 8, 2019
e1deb1e
Initialize session handler only if config has livePreviewEnabled = true
daveluong Apr 8, 2019
dc7d981
Only access capture device when starting a session
daveluong Apr 8, 2019
929302a
Make selectedAssets publicly accessible
daveluong Apr 8, 2019
4e6e808
Don't initialize the session handler if don't have permission
daveluong Apr 8, 2019
680c6e6
Use delegate instead of making the property publicly accessible
daveluong Apr 8, 2019
28d2ed4
Add method to update selectedAsset from camera to photoGallery
daveluong Apr 8, 2019
9ae0bf8
Update README.md
daveluong Apr 9, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
}
bcylin marked this conversation as resolved.
Show resolved Hide resolved
],
"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.
62 changes: 62 additions & 0 deletions Pickle/Classes/CameraSessionHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// 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")

func startSession() throws {
guard hasPermssion else {
throw CameraSessionError.noPermission
}
guard
let input = AVCaptureDevice.default(for: .video),
let deviceInput = try? AVCaptureDeviceInput(device: input) else {
throw CameraSessionError.noDeviceInput
Copy link
Contributor Author

@daveluong daveluong Apr 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessing AVCaptureDeviceInput in the initializer will prematurely prompt user for permission, so I have moved it to startSession() instead. We only use the live view when user has already granted permission previously

}
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
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
}
daveluong marked this conversation as resolved.
Show resolved Hide resolved
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