Skip to content
This repository was archived by the owner on Dec 11, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
410 changes: 205 additions & 205 deletions WeTransfer Sample Project/MainViewController.swift

Large diffs are not rendered by default.

194 changes: 97 additions & 97 deletions WeTransfer Sample Project/MediaPicker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,104 +11,104 @@ import Photos

/// Basic wrapper for UIImagePickerController to handle authorization and configuring and presenting the controller
final class MediaPicker: NSObject {
struct Media {
let url: URL
let previewImage: UIImage
}
typealias PickedMediaHandler = (_ media: Media?) -> Void
private var mediaHandler: PickedMediaHandler?
private var presentedImagePickerControler: UIImagePickerController?
func show(from viewController: UIViewController, mediaHandler: @escaping PickedMediaHandler) {
guard self.mediaHandler == nil else {
return
}
self.mediaHandler = mediaHandler
authorize { [weak self] (succeeded) in
guard succeeded, UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
self?.finish(with: nil)
return
}
self?.presentImagePicker(from: viewController)
}
}
private func presentImagePicker(from viewController: UIViewController) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.sourceType = .photoLibrary
if let mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary) {
imagePickerController.mediaTypes = mediaTypes
}
viewController.present(imagePickerController, animated: true, completion: nil)
presentedImagePickerControler = imagePickerController
}
private func authorize(with completion: @escaping (Bool) -> Void) {
switch PHPhotoLibrary.authorizationStatus() {
case .authorized:
completion(true)
case .denied, .restricted:
completion(false)
case .notDetermined:
PHPhotoLibrary.requestAuthorization { (status) in
guard status == .authorized else {
completion(false)
return
}
completion(true)
}
}
}
private func finish(with item: URL?) {
guard let url = item else {
mediaHandler?(nil)
dismissPickerController()
return
}
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
var pickedMedia: Media?
let asset = AVAsset(url: url)
if asset.duration.seconds > 0 {
// Get first frame if video
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
if let image = try? imageGenerator.copyCGImage(at: CMTime.zero, actualTime: nil) {
pickedMedia = Media(url: url, previewImage: UIImage(cgImage: image))
}
} else {
if let image = UIImage(contentsOfFile: url.path) {
pickedMedia = Media(url: url, previewImage: image)
}
}
DispatchQueue.main.async {
self?.mediaHandler?(pickedMedia)
self?.dismissPickerController()
}
}
}
private func dismissPickerController() {
mediaHandler = nil
presentedImagePickerControler?.presentingViewController?.dismiss(animated: true, completion: nil)
presentedImagePickerControler = nil
}
struct Media {
let url: URL
let previewImage: UIImage
}
typealias PickedMediaHandler = (_ media: Media?) -> Void
private var mediaHandler: PickedMediaHandler?
private var presentedImagePickerControler: UIImagePickerController?
func show(from viewController: UIViewController, mediaHandler: @escaping PickedMediaHandler) {
guard self.mediaHandler == nil else {
return
}
self.mediaHandler = mediaHandler
authorize { [weak self] (succeeded) in
guard succeeded, UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
self?.finish(with: nil)
return
}
self?.presentImagePicker(from: viewController)
}
}
private func presentImagePicker(from viewController: UIViewController) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.sourceType = .photoLibrary
if let mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary) {
imagePickerController.mediaTypes = mediaTypes
}
viewController.present(imagePickerController, animated: true, completion: nil)
presentedImagePickerControler = imagePickerController
}
private func authorize(with completion: @escaping (Bool) -> Void) {
switch PHPhotoLibrary.authorizationStatus() {
case .authorized:
completion(true)
case .denied, .restricted:
completion(false)
case .notDetermined:
PHPhotoLibrary.requestAuthorization { (status) in
guard status == .authorized else {
completion(false)
return
}
completion(true)
}
}
}
private func finish(with item: URL?) {
guard let url = item else {
mediaHandler?(nil)
dismissPickerController()
return
}
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
var pickedMedia: Media?
let asset = AVAsset(url: url)
if asset.duration.seconds > 0 {
// Get first frame if video
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
if let image = try? imageGenerator.copyCGImage(at: CMTime.zero, actualTime: nil) {
pickedMedia = Media(url: url, previewImage: UIImage(cgImage: image))
}
} else {
if let image = UIImage(contentsOfFile: url.path) {
pickedMedia = Media(url: url, previewImage: image)
}
}
DispatchQueue.main.async {
self?.mediaHandler?(pickedMedia)
self?.dismissPickerController()
}
}
}
private func dismissPickerController() {
mediaHandler = nil
presentedImagePickerControler?.presentingViewController?.dismiss(animated: true, completion: nil)
presentedImagePickerControler = nil
}
}

extension MediaPicker: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
finish(with: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
guard let url = info[UIImagePickerController.InfoKey.imageURL] as? URL ?? info[UIImagePickerController.InfoKey.mediaURL] as? URL else {
finish(with: nil)
return
}
finish(with: url)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
finish(with: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
guard let url = info[UIImagePickerController.InfoKey.imageURL] as? URL ?? info[UIImagePickerController.InfoKey.mediaURL] as? URL else {
finish(with: nil)
return
}
finish(with: url)
}
}
102 changes: 51 additions & 51 deletions WeTransfer Sample Project/RoundedButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,55 @@ import UIKit

/// Button with colored background and rounded corners
final class RoundedButton: UIButton {
enum Style {
case regular
case alternative
}
private let horizontalPadding: CGFloat = 22
private let minimumHeight: CGFloat = 44
var style: Style = .regular {
didSet {
updateBackgroundColor()
updateTitleColor()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
layer.cornerRadius = 8
updateBackgroundColor()
updateTitleColor()
titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
heightAnchor.constraint(greaterThanOrEqualToConstant: minimumHeight).isActive = true
contentEdgeInsets = UIEdgeInsets(top: 0, left: horizontalPadding, bottom: 0, right: horizontalPadding)
}
override var isEnabled: Bool {
didSet {
updateBackgroundColor()
updateTitleColor()
}
}
private func updateBackgroundColor() {
if isEnabled {
let enabledColor = UIColor(red: 64 / 255, green: 159 / 255, blue: 255 / 255, alpha: 1)
let alternativeColor = UIColor(white: 235 / 255, alpha: 1)
backgroundColor = style == .alternative ? alternativeColor : enabledColor
} else {
backgroundColor = UIColor(red: 165 / 255, green: 168 / 255, blue: 172 / 255, alpha: 1)
}
}
private func updateTitleColor() {
let titleColor = UIColor.white
let alternativeTitleColor = UIColor(white: 75 / 255, alpha: 1)
setTitleColor(style == .alternative ? alternativeTitleColor : titleColor, for: .normal)
}
enum Style {
case regular
case alternative
}
private let horizontalPadding: CGFloat = 22
private let minimumHeight: CGFloat = 44
var style: Style = .regular {
didSet {
updateBackgroundColor()
updateTitleColor()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
layer.cornerRadius = 8
updateBackgroundColor()
updateTitleColor()
titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
heightAnchor.constraint(greaterThanOrEqualToConstant: minimumHeight).isActive = true
contentEdgeInsets = UIEdgeInsets(top: 0, left: horizontalPadding, bottom: 0, right: horizontalPadding)
}
override var isEnabled: Bool {
didSet {
updateBackgroundColor()
updateTitleColor()
}
}
private func updateBackgroundColor() {
if isEnabled {
let enabledColor = UIColor(red: 64 / 255, green: 159 / 255, blue: 255 / 255, alpha: 1)
let alternativeColor = UIColor(white: 235 / 255, alpha: 1)
backgroundColor = style == .alternative ? alternativeColor : enabledColor
} else {
backgroundColor = UIColor(red: 165 / 255, green: 168 / 255, blue: 172 / 255, alpha: 1)
}
}
private func updateTitleColor() {
let titleColor = UIColor.white
let alternativeTitleColor = UIColor(white: 75 / 255, alpha: 1)
setTitleColor(style == .alternative ? alternativeTitleColor : titleColor, for: .normal)
}
}
12 changes: 6 additions & 6 deletions WeTransfer Sample Project/Supporting Files/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import UIKit

@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
}
Loading