diff --git a/Podfile b/Podfile index 77cfa72..8059642 100644 --- a/Podfile +++ b/Podfile @@ -6,7 +6,7 @@ target 'fakestagram' do use_frameworks! # Pods for fakestagram pod 'SAMKeychain' - + pod 'DVR' target 'fakestagramTests' do inherit! :search_paths pod 'DVR' diff --git a/Podfile.lock b/Podfile.lock index 12505e8..5495345 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -15,6 +15,6 @@ SPEC CHECKSUMS: DVR: 062c287b9dc613a84120e44640176e4ef3ecf943 SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c -PODFILE CHECKSUM: 02c21c317ba9be4fdecdfff242f3fa20e9b269bd +PODFILE CHECKSUM: 6ce291ef5eb8e282e4a60dab177e509bc0c5ab9d -COCOAPODS: 1.8.3 +COCOAPODS: 1.8.4 diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index fd88dc7..44276b5 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */; }; + 103D72B423C9B88900C66B7D /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 103D72B323C9B88900C66B7D /* LikeService.swift */; }; + 10612B0223D212F300655D31 /* PhotoEditingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10612B0123D212F300655D31 /* PhotoEditingController.swift */; }; D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */; }; E023A5542380859200B13B7D /* NotificationKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E023A5532380859200B13B7D /* NotificationKeys.swift */; }; E038FCED233FC78600E28571 /* PostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E038FCEC233FC78600E28571 /* PostViewController.swift */; }; @@ -63,6 +65,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 103D72B323C9B88900C66B7D /* LikeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeService.swift; sourceTree = ""; }; + 10612B0123D212F300655D31 /* PhotoEditingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoEditingController.swift; sourceTree = ""; }; 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.release.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.release.xcconfig"; sourceTree = ""; }; 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.debug.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig"; sourceTree = ""; }; CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.release.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig"; sourceTree = ""; }; @@ -154,6 +158,7 @@ children = ( E045844823762E10006574FA /* CreatePostService.swift */, E0458456237725B9006574FA /* IndexService.swift */, + 103D72B323C9B88900C66B7D /* LikeService.swift */, ); path = Services; sourceTree = ""; @@ -241,6 +246,7 @@ E0A9ED50235A782F00A0527E /* PostsViewController.swift */, E038FCEC233FC78600E28571 /* PostViewController.swift */, E0E25462235B675100C55767 /* CameraViewController.swift */, + 10612B0123D212F300655D31 /* PhotoEditingController.swift */, ); path = ViewControllers; sourceTree = ""; @@ -494,6 +500,7 @@ files = ( E0C93EA42352452900FD330C /* AuthorView.swift in Sources */, E0E2545F235A9F3A00C55767 /* UIDevice+models.swift in Sources */, + 103D72B423C9B88900C66B7D /* LikeService.swift in Sources */, E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E045845123766203006574FA /* CacheImage.swift in Sources */, E045844B237652DD006574FA /* StorageType.swift in Sources */, @@ -515,6 +522,7 @@ E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, E0A9ED51235A782F00A0527E /* PostsViewController.swift in Sources */, E045844923762E10006574FA /* CreatePostService.swift in Sources */, + 10612B0223D212F300655D31 /* PhotoEditingController.swift in Sources */, E0C93EA62352454E00FD330C /* Author.swift in Sources */, E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */, E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, @@ -689,13 +697,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = 446P28FHN3; INFOPLIST_FILE = fakestagram/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; + PRODUCT_BUNDLE_IDENTIFIER = com.puebafakeinsta; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -711,13 +720,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = 446P28FHN3; INFOPLIST_FILE = fakestagram/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; + PRODUCT_BUNDLE_IDENTIFIER = com.puebafakeinsta; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/fakestagram/AppDelegate.swift b/fakestagram/AppDelegate.swift index 2660552..04801e1 100644 --- a/fakestagram/AppDelegate.swift +++ b/fakestagram/AppDelegate.swift @@ -35,7 +35,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func loadOrCreateAccount() { if Credentials.apiToken.get() != nil { return } - let account = Account(id: nil, name: "Juan Camaney", deviceNumber: UIDevice.identifier, deviceModel: UIDevice.modelName) + let account = Account(id: nil, name: "pk.gs", deviceNumber: UIDevice.identifier, deviceModel: UIDevice.modelName) let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/accounts") client.create(account) { account in guard let account = account, let idx = account.id else { return } diff --git a/fakestagram/Assets.xcassets/babyYoda.imageset/Contents.json b/fakestagram/Assets.xcassets/babyYoda.imageset/Contents.json new file mode 100644 index 0000000..629afa1 --- /dev/null +++ b/fakestagram/Assets.xcassets/babyYoda.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "babyyodatomate-8b881a58a88a7f62498ea2ce59c9d69e-1200x800.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/fakestagram/Assets.xcassets/babyYoda.imageset/babyyodatomate-8b881a58a88a7f62498ea2ce59c9d69e-1200x800.jpg b/fakestagram/Assets.xcassets/babyYoda.imageset/babyyodatomate-8b881a58a88a7f62498ea2ce59c9d69e-1200x800.jpg new file mode 100644 index 0000000..d11ab9a Binary files /dev/null and b/fakestagram/Assets.xcassets/babyYoda.imageset/babyyodatomate-8b881a58a88a7f62498ea2ce59c9d69e-1200x800.jpg differ diff --git a/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json b/fakestagram/Assets.xcassets/default.imageset/Contents.json similarity index 86% rename from fakestagram/Assets.xcassets/spacecat.imageset/Contents.json rename to fakestagram/Assets.xcassets/default.imageset/Contents.json index d1bb6ed..8182200 100644 --- a/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json +++ b/fakestagram/Assets.xcassets/default.imageset/Contents.json @@ -2,7 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "spacecat.jpg", + "filename" : "photo_default_2.png", "scale" : "1x" }, { diff --git a/fakestagram/Assets.xcassets/default.imageset/photo_default_2.png b/fakestagram/Assets.xcassets/default.imageset/photo_default_2.png new file mode 100644 index 0000000..831cc87 Binary files /dev/null and b/fakestagram/Assets.xcassets/default.imageset/photo_default_2.png differ diff --git a/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg b/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg deleted file mode 100644 index 32ea7fd..0000000 Binary files a/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg and /dev/null differ diff --git a/fakestagram/Base.lproj/Main.storyboard b/fakestagram/Base.lproj/Main.storyboard index 469596b..0a1fe68 100644 --- a/fakestagram/Base.lproj/Main.storyboard +++ b/fakestagram/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - - + + - + @@ -13,11 +13,11 @@ - + - + @@ -47,39 +47,44 @@ + - + - + - + - - - + + + @@ -101,12 +106,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -143,4 +307,7 @@ + + + diff --git a/fakestagram/Info.plist b/fakestagram/Info.plist index d1b73e7..d2c18a0 100644 --- a/fakestagram/Info.plist +++ b/fakestagram/Info.plist @@ -2,6 +2,8 @@ + NSPhotoLibraryAddUsageDescription + Please allow access to save photo in your photo library CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable @@ -44,7 +46,7 @@ UILaunchStoryboardName - LaunchScreen + Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities diff --git a/fakestagram/Services/LikeService.swift b/fakestagram/Services/LikeService.swift new file mode 100644 index 0000000..c4ccd32 --- /dev/null +++ b/fakestagram/Services/LikeService.swift @@ -0,0 +1,29 @@ +// +// LikeService.swift +// fakestagram +// +// Created by Javier Ferrer on 1/11/20. +// Copyright © 2020 3zcurdia. All rights reserved. +// + +import Foundation + +struct CreateLike: Codable { + let postID: Int? +} + +class CreateLikeService { + func call(postID: Int?, success: @escaping (Int?) -> Void) { + let newLike = CreateLike( + postID: postID + ) + + let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/\(newLike.postID!)/like") + client.create(newLike) { post in + NotificationCenter.default.post(name: NotificationKeys.didFinishPostCreation.value, object: nil) + success(post?.postID) + } + } + + +} diff --git a/fakestagram/ViewControllers/CameraViewController.swift b/fakestagram/ViewControllers/CameraViewController.swift index a7996c7..7330801 100644 --- a/fakestagram/ViewControllers/CameraViewController.swift +++ b/fakestagram/ViewControllers/CameraViewController.swift @@ -10,7 +10,7 @@ import UIKit import CoreLocation import AVFoundation -class CameraViewController: UIViewController { +class CameraViewController: UIViewController, AVCapturePhotoCaptureDelegate { override func viewDidLoad() { super.viewDidLoad() enableBasicLocationServices() @@ -28,6 +28,7 @@ class CameraViewController: UIViewController { } let service = CreatePostService() + @IBAction func onTapCreate(_ sender: Any) { print("📸") let settings: AVCapturePhotoSettings @@ -40,17 +41,24 @@ class CameraViewController: UIViewController { } settings.flashMode = .auto photoOutput.capturePhoto(with: settings, delegate: self) + } + + func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { + + debugPrint(photo.metadata) + guard let data = photo.fileDataRepresentation(), let img = UIImage(data: data) else { return } + UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil) + + } - /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ +// override func prepare(for segue: UIStoryboardSegue, sender: Any?) { +// // Get the new view controller using segue.destination. +// // Pass the selected object to the new view controller. +// } // MARK: - CoreLocation methods let locationManager = CLLocationManager() @@ -99,7 +107,7 @@ class CameraViewController: UIViewController { func setupCaptureSession() { session.beginConfiguration() - let device = AVCaptureDevice.default(.builtInDualCamera, + let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)! guard let videoDeviceInput = try? AVCaptureDeviceInput(device: device), session.canAddInput(videoDeviceInput) else { return } @@ -114,19 +122,6 @@ class CameraViewController: UIViewController { session.startRunning() } - -} - -extension CameraViewController: AVCapturePhotoCaptureDelegate { - func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { - debugPrint(photo.metadata) - - guard let data = photo.fileDataRepresentation(), let img = UIImage(data: data) else { return } - service.call(image: img, title: UUID().uuidString) { postId in - print("Successful!") - print(postId ?? -1) - } - } } extension CameraViewController: CLLocationManagerDelegate { diff --git a/fakestagram/ViewControllers/PhotoEditingController.swift b/fakestagram/ViewControllers/PhotoEditingController.swift new file mode 100644 index 0000000..ef156f7 --- /dev/null +++ b/fakestagram/ViewControllers/PhotoEditingController.swift @@ -0,0 +1,158 @@ +// +// PhotoEditingController.swift +// fakestagram +// +// Created by Javier Ferrer on 1/17/20. +// Copyright © 2020 3zcurdia. All rights reserved. +// + +import UIKit +import CoreImage +import CoreGraphics + + +class PhotoEditingViewController : UIViewController, UIScrollViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate{ + + @IBOutlet weak var scrollView: UIScrollView! + + @IBOutlet weak var titleTextField: UITextField! + + var image_: UIImage! + var imgview = UIImageView() + + private var originalImage : UIImage? + + let service = CreatePostService() + + override func viewDidLoad() { + + scrollView.delegate = self + imgview.frame = CGRect(x: 0, y: 0, width: scrollView.frame.size.width, height: scrollView.frame.size.height) + imgview.image = UIImage(named: "default"); + imgview.isUserInteractionEnabled = true + scrollView.addSubview(imgview) + + let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(PhotoEditingViewController.loadImage(_:))) + tapGestureRecognizer.numberOfTouchesRequired = 1 + imgview.addGestureRecognizer(tapGestureRecognizer) + } + + @objc func loadImage(_ sender: UITapGestureRecognizer){ + let imagePicker = UIImagePickerController() + imagePicker.allowsEditing = true + imagePicker.delegate = self + imagePicker.sourceType = .photoLibrary + + self.present(imagePicker, animated: true, completion: nil) + } + + func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { + + if let image = info[.editedImage] as? UIImage { + imgview.image = image + originalImage = image + }else if let image = info[.originalImage] as? UIImage { + imgview.image = image + originalImage = image + } + picker.dismiss(animated: true, completion: nil) + } + + @IBAction func Dismiss(_ sender: UIButton) { + dismiss(animated: true, completion: nil) + } + + struct Filtro { + let nombreDeFiltro : String + var valorFiltro : Any? + var nombreDeValorDelFiltro: String? + + init(nombreDeFiltro : String, valorFiltro : Any?, nombreDeValorDelFiltro: String?) { + self.nombreDeFiltro = nombreDeFiltro + self.nombreDeValorDelFiltro = nombreDeValorDelFiltro + self.valorFiltro = valorFiltro + } + } + + private func applyFilter(image : UIImage, filterEffect : Filtro) -> UIImage? { + + guard let cgImage = image.cgImage else { return nil } + + let context = CIContext(options: nil) + + let ciImage = CIImage(cgImage: cgImage) + let filter = CIFilter(name: filterEffect.nombreDeFiltro) + + filter?.setValue(ciImage, forKey: kCIInputImageKey) + + if let filterEffectValue = filterEffect.valorFiltro, let filterEffectValueName = filterEffect.nombreDeValorDelFiltro { + filter?.setValue(filterEffectValue, forKey: filterEffectValueName) + } + + var imagenFiltrada : UIImage? + + if let output = filter?.value(forKey: kCIOutputImageKey) as? CIImage, let cgiImageResult = context.createCGImage(output, from: output.extent){ + imagenFiltrada = UIImage(cgImage: cgiImageResult) + } + return imagenFiltrada + } + + @IBAction func applySepia(_ sender: Any){ + + guard let image = imgview.image else { return } + + imgview.image = applyFilter(image: image, filterEffect: Filtro(nombreDeFiltro: "CISepiaTone", valorFiltro: 2.85, nombreDeValorDelFiltro: kCIInputIntensityKey)) + + } + + @IBAction func applyPhotoTransferEffect(_ sender: Any){ + + guard let image = imgview.image else { return } + + imgview.image = applyFilter(image: image, filterEffect: Filtro(nombreDeFiltro: "CIPhotoEffectProcess", valorFiltro: nil, nombreDeValorDelFiltro: nil)) + + } + + @IBAction func applyBlur(_ sender: Any){ + + guard let image = imgview.image else { return } + + imgview.image = applyFilter(image: image, filterEffect: Filtro(nombreDeFiltro: "CIGaussianBlur", valorFiltro: 8.0, nombreDeValorDelFiltro: kCIInputRadiusKey)) + + } + + @IBAction func applyPhotoEffectNoir(_ sender: Any){ + + guard let image = imgview.image else { return } + + imgview.image = applyFilter(image: image, filterEffect: Filtro(nombreDeFiltro: "CIPhotoEffectNoir", valorFiltro: nil, nombreDeValorDelFiltro: nil)) + } + + @IBAction func clearFilters(_ sender: Any){ + imgview.image = originalImage + } + + @IBAction func newPost(_ sender: Any) { + + var titulo : String? + titulo = titleTextField.text + let isEmpty = (titleTextField.text ?? "").isEmpty + + if isEmpty == true { + let alert = UIAlertController(title: "Title Missing", message: "Please write an image title", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + self.present(alert, animated: true, completion: nil) + + } else { + + if let img = imgview.image{ + service.call(image: img, title: titulo!) { postId in + print("Successful!") + print(postId ?? -1) + } + } + } + } + +} + diff --git a/fakestagram/ViewControllers/PostsViewController.swift b/fakestagram/ViewControllers/PostsViewController.swift index a49ab76..5935038 100644 --- a/fakestagram/ViewControllers/PostsViewController.swift +++ b/fakestagram/ViewControllers/PostsViewController.swift @@ -71,4 +71,5 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: self.view.frame.width, height: 650) } + } diff --git a/fakestagram/Views/PostCollectionViewCell.swift b/fakestagram/Views/PostCollectionViewCell.swift index 1d5be7b..a4877dc 100644 --- a/fakestagram/Views/PostCollectionViewCell.swift +++ b/fakestagram/Views/PostCollectionViewCell.swift @@ -15,12 +15,12 @@ class PostCollectionViewCell: UICollectionViewCell { updateView() } } + @IBOutlet weak var authorView: AuthorView! @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var likeCounter: UILabel! @IBOutlet weak var titleLabel: UILabel! - @IBOutlet weak var likeBttn: UIButton! - @IBOutlet weak var commentBttn: UIButton! + @IBOutlet weak var likeBttn: UIButton! func reset() { self.imageView.image = nil @@ -34,9 +34,20 @@ class PostCollectionViewCell: UICollectionViewCell { self.authorView.author = post.author self.titleLabel.text = post.title self.likeCounter.text = post.likesCountText() + post.load { [unowned self] img in self.imageView.image = img } } + + @IBAction func tapLike(_ sender: UIButton) { + + let service = CreateLikeService() + guard let post = self.post else { return } + service.call(postID: post.id) { postId in + print("NewLike") + print(postId ?? -1) + } + } } diff --git a/fakestagram/Views/PostCollectionViewCell.xib b/fakestagram/Views/PostCollectionViewCell.xib index afff929..84fcad4 100644 --- a/fakestagram/Views/PostCollectionViewCell.xib +++ b/fakestagram/Views/PostCollectionViewCell.xib @@ -1,8 +1,8 @@ - + - + @@ -10,14 +10,14 @@ - + - + - + @@ -35,7 +35,11 @@