From 5b0ac73d87872759a1638afa3b5f86afedb8b5c8 Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 17:30:03 -0400 Subject: [PATCH 1/9] Added label like counter --- Secretly.xcodeproj/project.pbxproj | 8 ++++---- Secretly/Info.plist | 12 ++++++------ Secretly/Views/PostCollectionViewCell.xib | 11 +++++++++++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Secretly.xcodeproj/project.pbxproj b/Secretly.xcodeproj/project.pbxproj index 8dd4829..3105640 100644 --- a/Secretly.xcodeproj/project.pbxproj +++ b/Secretly.xcodeproj/project.pbxproj @@ -635,13 +635,13 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = CF8GW6MT8Z; INFOPLIST_FILE = Secretly/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = mx.unam.ioslab.Secretly; + PRODUCT_BUNDLE_IDENTIFIER = fernando.Secretly; PRODUCT_NAME = Secretly; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; @@ -653,13 +653,13 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = CF8GW6MT8Z; INFOPLIST_FILE = Secretly/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = mx.unam.ioslab.Secretly; + PRODUCT_BUNDLE_IDENTIFIER = fernando.Secretly; PRODUCT_NAME = Secretly; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; diff --git a/Secretly/Info.plist b/Secretly/Info.plist index 154ea82..51ca4f3 100644 --- a/Secretly/Info.plist +++ b/Secretly/Info.plist @@ -2,12 +2,6 @@ - NSPhotoLibraryUsageDescription - To add some context to your posts - NSCameraUsageDescription - To add some context to your posts - NSLocationWhenInUseUsageDescription - To georeference posts within a region CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable @@ -26,6 +20,12 @@ 1 LSRequiresIPhoneOS + NSCameraUsageDescription + To add some context to your posts + NSLocationWhenInUseUsageDescription + To georeference posts within a region + NSPhotoLibraryUsageDescription + To add some context to your posts UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/Secretly/Views/PostCollectionViewCell.xib b/Secretly/Views/PostCollectionViewCell.xib index 7b3a4e2..094b01f 100644 --- a/Secretly/Views/PostCollectionViewCell.xib +++ b/Secretly/Views/PostCollectionViewCell.xib @@ -62,12 +62,22 @@ + + @@ -76,6 +86,7 @@ + From ae4cafe0e3c00bfc6eb41a5d4e09dee9b65520de Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 17:33:28 -0400 Subject: [PATCH 2/9] Implement Like model --- Secretly.xcodeproj/project.pbxproj | 4 ++++ Secretly/Models/Like.swift | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 Secretly/Models/Like.swift diff --git a/Secretly.xcodeproj/project.pbxproj b/Secretly.xcodeproj/project.pbxproj index 3105640..7aca880 100644 --- a/Secretly.xcodeproj/project.pbxproj +++ b/Secretly.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ 30C77CB6266AF48300A888DC /* CurrentUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C77CB5266AF48300A888DC /* CurrentUser.swift */; }; 30C77CB8266BD44300A888DC /* CreatePostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C77CB7266BD44300A888DC /* CreatePostViewController.swift */; }; 30FD0E722659645A006E309A /* Faker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FD0E712659645A006E309A /* Faker.swift */; }; + 5B89708B269A491D0080C464 /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708A269A491D0080C464 /* Like.swift */; }; E021984723FA35E00025C28E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984623FA35E00025C28E /* AppDelegate.swift */; }; E021984923FA35E00025C28E /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984823FA35E00025C28E /* SceneDelegate.swift */; }; E021984B23FA35E00025C28E /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984A23FA35E00025C28E /* WelcomeViewController.swift */; }; @@ -125,6 +126,7 @@ 30C77CB5266AF48300A888DC /* CurrentUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentUser.swift; sourceTree = ""; }; 30C77CB7266BD44300A888DC /* CreatePostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePostViewController.swift; sourceTree = ""; }; 30FD0E712659645A006E309A /* Faker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Faker.swift; sourceTree = ""; }; + 5B89708A269A491D0080C464 /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; E021984323FA35E00025C28E /* Secretly.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretly.app; sourceTree = BUILT_PRODUCTS_DIR; }; E021984623FA35E00025C28E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E021984823FA35E00025C28E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -248,6 +250,7 @@ 307A30572661AD540020DF8B /* User.swift */, 30C77CB3266AF47300A888DC /* Credentials.swift */, 30C77CB5266AF48300A888DC /* CurrentUser.swift */, + 5B89708A269A491D0080C464 /* Like.swift */, ); path = Models; sourceTree = ""; @@ -428,6 +431,7 @@ E021984B23FA35E00025C28E /* WelcomeViewController.swift in Sources */, 3072FBDF2680FA5A00B35C8C /* ImageProcessor.swift in Sources */, 302BB622267E38E800FD74F5 /* PostInputViewController+UIImagePickerControllerDelegate.swift in Sources */, + 5B89708B269A491D0080C464 /* Like.swift in Sources */, 302B5845267E658E007133E6 /* HttpResponse.swift in Sources */, 302B584A267E658E007133E6 /* RestClient.swift in Sources */, 302B5848267E658E007133E6 /* HttpClient.swift in Sources */, diff --git a/Secretly/Models/Like.swift b/Secretly/Models/Like.swift new file mode 100644 index 0000000..81c408b --- /dev/null +++ b/Secretly/Models/Like.swift @@ -0,0 +1,15 @@ +// +// Like.swift +// Secretly +// +// Created by Proteco on 10/07/21. +// Copyright © 2021 3zcurdia. All rights reserved. +// + +import Foundation + +struct Like: Restable { + let id: Int + let createdAt: Date + let updatedAt: Date +} From f58fe77508c621acabbf6a08b942745c1eb30949 Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 17:49:24 -0400 Subject: [PATCH 3/9] Implement LikeService --- Secretly.xcodeproj/project.pbxproj | 6 +++++ Secretly/Network/RestClient.swift | 14 ++++++++++ Secretly/Services/LikeService.swift | 42 +++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 Secretly/Services/LikeService.swift diff --git a/Secretly.xcodeproj/project.pbxproj b/Secretly.xcodeproj/project.pbxproj index 7aca880..0fabbbc 100644 --- a/Secretly.xcodeproj/project.pbxproj +++ b/Secretly.xcodeproj/project.pbxproj @@ -57,6 +57,8 @@ 30C77CB8266BD44300A888DC /* CreatePostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C77CB7266BD44300A888DC /* CreatePostViewController.swift */; }; 30FD0E722659645A006E309A /* Faker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FD0E712659645A006E309A /* Faker.swift */; }; 5B89708B269A491D0080C464 /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708A269A491D0080C464 /* Like.swift */; }; + 5B89708D269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; + 5B89708E269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; E021984723FA35E00025C28E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984623FA35E00025C28E /* AppDelegate.swift */; }; E021984923FA35E00025C28E /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984823FA35E00025C28E /* SceneDelegate.swift */; }; E021984B23FA35E00025C28E /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984A23FA35E00025C28E /* WelcomeViewController.swift */; }; @@ -127,6 +129,7 @@ 30C77CB7266BD44300A888DC /* CreatePostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePostViewController.swift; sourceTree = ""; }; 30FD0E712659645A006E309A /* Faker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Faker.swift; sourceTree = ""; }; 5B89708A269A491D0080C464 /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; + 5B89708C269A4A3E0080C464 /* LikeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeService.swift; sourceTree = ""; }; E021984323FA35E00025C28E /* Secretly.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretly.app; sourceTree = BUILT_PRODUCTS_DIR; }; E021984623FA35E00025C28E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E021984823FA35E00025C28E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -224,6 +227,7 @@ 30C77CAF266AD69700A888DC /* CurrentUserService.swift */, 304E06C726742BDA00A99128 /* CreatePostService.swift */, 304E06C926742CC500A99128 /* FeedService.swift */, + 5B89708C269A4A3E0080C464 /* LikeService.swift */, ); path = Services; sourceTree = ""; @@ -470,6 +474,7 @@ 30C77CB6266AF48300A888DC /* CurrentUser.swift in Sources */, 302BB624267E3A8700FD74F5 /* PostInputViewController+UIColorPickerViewControllerDelegate.swift in Sources */, 304E06CF267468DA00A99128 /* UIColor+Pastel.swift in Sources */, + 5B89708D269A4A3E0080C464 /* LikeService.swift in Sources */, 304E06C42674133D00A99128 /* String+isBlank.swift in Sources */, 30BC8BA42662BDEF00F7E6A5 /* ImageStore.swift in Sources */, 3033795B267537490066D94A /* FeedCollectionViewController+UICollectionViewDataSourcePrefetching.swift in Sources */, @@ -484,6 +489,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5B89708E269A4A3E0080C464 /* LikeService.swift in Sources */, E021985E23FA35E20025C28E /* SecretlyTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Secretly/Network/RestClient.swift b/Secretly/Network/RestClient.swift index 3048ccf..aebb706 100644 --- a/Secretly/Network/RestClient.swift +++ b/Secretly/Network/RestClient.swift @@ -50,6 +50,13 @@ struct RestClient { complete(newResult) } } + + func create(complete: @escaping (Result) -> Void) throws { + client.post(path: path, body: nil) { result in + let newResult = result.flatMap { parse(data: $0) } + complete(newResult) + } + } func create(model: T, complete: @escaping (Result) -> Void) throws { let data = try encoder.encode(model) @@ -66,6 +73,13 @@ struct RestClient { complete(newResult) } } + + func delete(complete: @escaping (Result) -> Void) { + client.delete(path: path) { result in + let newResult = result.flatMap { parse(data: $0) } + complete(newResult) + } + } func delete(model: T, complete: @escaping (Result) -> Void) { client.delete(path: "\(path)/\(model.id)") { result in diff --git a/Secretly/Services/LikeService.swift b/Secretly/Services/LikeService.swift new file mode 100644 index 0000000..748d3d3 --- /dev/null +++ b/Secretly/Services/LikeService.swift @@ -0,0 +1,42 @@ +// +// LikeService.swift +// Secretly +// +// Created by Proteco on 10/07/21. +// Copyright © 2021 3zcurdia. All rights reserved. +// + +import Foundation + +struct LikeService { + private var endpoint: RestClient? + + init(post: Post?) { + guard let post = post, let postId = post.id else { + self.endpoint = nil + return + } + self.endpoint = RestClient(client: AmacaConfig.shared.httpClient, path: "/api/v1/posts/\(postId)/likes") + } + + init(id: Int?) { + guard let postId = id else { + self.endpoint = nil + return + } + self.endpoint = RestClient(client: AmacaConfig.shared.httpClient, path: "/api/v1/posts/\(postId)/likes") + } + + func create(_ model: Like, complete: @escaping (Result) -> Void) { + try? endpoint?.create() { result in + DispatchQueue.main.async { complete(result) } + } + } + + func delete(_ model: Like, complete: @escaping (Result) -> Void) { + try? endpoint?.delete() { result in + DispatchQueue.main.async { complete(result) } + } + } + +} From af776d75ed6e46d5722cf7458a616f6bf4ab8ce8 Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 18:26:14 -0400 Subject: [PATCH 4/9] Implement tap gesture like --- Secretly/Models/Post.swift | 4 ++++ Secretly/Views/PostCollectionViewCell.swift | 25 +++++++++++++++++++++ Secretly/Views/PostCollectionViewCell.xib | 1 + 3 files changed, 30 insertions(+) diff --git a/Secretly/Models/Post.swift b/Secretly/Models/Post.swift index eba5ff0..758b04b 100644 --- a/Secretly/Models/Post.swift +++ b/Secretly/Models/Post.swift @@ -21,6 +21,8 @@ struct Post: Restable { let longitude: Double? let createdAt: Date? let updatedAt: Date? + var likesCount: Int? + var liked: Bool init(content: String, backgroundColor: String, latitude: Double? = nil, longitude: Double? = nil, image: UIImage? = nil) { self.content = content @@ -34,6 +36,8 @@ struct Post: Restable { self.commentsCount = nil self.createdAt = nil self.updatedAt = nil + self.likesCount = nil + self.liked = false } func encode(to encoder: Encoder) throws { diff --git a/Secretly/Views/PostCollectionViewCell.swift b/Secretly/Views/PostCollectionViewCell.swift index ee08d53..88ef2e4 100644 --- a/Secretly/Views/PostCollectionViewCell.swift +++ b/Secretly/Views/PostCollectionViewCell.swift @@ -10,9 +10,11 @@ import UIKit class PostCollectionViewCell: UICollectionViewCell { static let reuseIdentifier = "feedPostCell" + var likeService: LikeService? var post: Post? { didSet { updateView() + likeService = LikeService(post: post) } } @IBOutlet weak var authorView: AuthorView! @@ -20,9 +22,14 @@ class PostCollectionViewCell: UICollectionViewCell { @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var likeState: UIImageView! @IBOutlet weak var commentCounter: UILabel! + @IBOutlet weak var likeCounter: UILabel! override func awakeFromNib() { super.awakeFromNib() + + let tapLikeState = UITapGestureRecognizer(target: self, action: #selector(tapLike)) + self.likeState.isUserInteractionEnabled = true + self.likeState.addGestureRecognizer(tapLikeState) } func updateView() { @@ -33,9 +40,27 @@ class PostCollectionViewCell: UICollectionViewCell { } self.contentLabel.text = post.content self.commentCounter.text = String(describing: post.commentsCount ?? 0) + self.likeCounter.text = String(describing: post.likesCount ?? 0) if let postImg = post.image { ImageLoader.load(postImg.mediumUrl) { img in self.imageView.image = img } } self.authorView.author = post.user } + + @objc private func tapLike(){ + guard let post = post, let id = post.id else {return} + let updateLike = Like(id: id, createdAt: Date(), updatedAt: Date()) + if !post.liked { + likeService?.create(updateLike) { result in + self.likeState.image = UIImage(systemName: "heart.fill") + self.likeCounter.text = String(describing: post.likesCount! + 1) + } + } else { + likeService?.delete(updateLike) { result in + self.likeState.image = UIImage(systemName: "heart") + self.likeCounter.text = String(describing: post.likesCount! - 1) + } + } + } + } diff --git a/Secretly/Views/PostCollectionViewCell.xib b/Secretly/Views/PostCollectionViewCell.xib index 094b01f..bd58bf8 100644 --- a/Secretly/Views/PostCollectionViewCell.xib +++ b/Secretly/Views/PostCollectionViewCell.xib @@ -100,6 +100,7 @@ + From 673bce88c83de1e914e088ce5f5337d1d686cd2c Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 19:00:45 -0400 Subject: [PATCH 5/9] Implement Uodate Post Service --- Secretly.xcodeproj/project.pbxproj | 4 +++ Secretly/Models/Post.swift | 2 +- Secretly/Network/RestClient.swift | 2 +- Secretly/Services/UpdatePostService.swift | 28 +++++++++++++++++++ .../CreatePostViewController.swift | 2 +- .../PostInputViewController.swift | 3 +- Secretly/Views/PostCollectionViewCell.swift | 28 +++++++++++++++++++ 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 Secretly/Services/UpdatePostService.swift diff --git a/Secretly.xcodeproj/project.pbxproj b/Secretly.xcodeproj/project.pbxproj index 0fabbbc..47ebf0a 100644 --- a/Secretly.xcodeproj/project.pbxproj +++ b/Secretly.xcodeproj/project.pbxproj @@ -59,6 +59,7 @@ 5B89708B269A491D0080C464 /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708A269A491D0080C464 /* Like.swift */; }; 5B89708D269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; 5B89708E269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; + 5B897090269A58660080C464 /* UpdatePostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708F269A58660080C464 /* UpdatePostService.swift */; }; E021984723FA35E00025C28E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984623FA35E00025C28E /* AppDelegate.swift */; }; E021984923FA35E00025C28E /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984823FA35E00025C28E /* SceneDelegate.swift */; }; E021984B23FA35E00025C28E /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984A23FA35E00025C28E /* WelcomeViewController.swift */; }; @@ -130,6 +131,7 @@ 30FD0E712659645A006E309A /* Faker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Faker.swift; sourceTree = ""; }; 5B89708A269A491D0080C464 /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; 5B89708C269A4A3E0080C464 /* LikeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeService.swift; sourceTree = ""; }; + 5B89708F269A58660080C464 /* UpdatePostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdatePostService.swift; sourceTree = ""; }; E021984323FA35E00025C28E /* Secretly.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretly.app; sourceTree = BUILT_PRODUCTS_DIR; }; E021984623FA35E00025C28E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E021984823FA35E00025C28E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -228,6 +230,7 @@ 304E06C726742BDA00A99128 /* CreatePostService.swift */, 304E06C926742CC500A99128 /* FeedService.swift */, 5B89708C269A4A3E0080C464 /* LikeService.swift */, + 5B89708F269A58660080C464 /* UpdatePostService.swift */, ); path = Services; sourceTree = ""; @@ -480,6 +483,7 @@ 3033795B267537490066D94A /* FeedCollectionViewController+UICollectionViewDataSourcePrefetching.swift in Sources */, 30B9B93B268CA9E6007B1942 /* UIImage+PixelBuffer.swift in Sources */, 303379592675371C0066D94A /* FeedCollectionViewController+UICollectionViewDataSource .swift in Sources */, + 5B897090269A58660080C464 /* UpdatePostService.swift in Sources */, 304E06CA26742CC500A99128 /* FeedService.swift in Sources */, 302BB61F267E316900FD74F5 /* PostInputViewController.swift in Sources */, ); diff --git a/Secretly/Models/Post.swift b/Secretly/Models/Post.swift index 758b04b..886d444 100644 --- a/Secretly/Models/Post.swift +++ b/Secretly/Models/Post.swift @@ -24,7 +24,7 @@ struct Post: Restable { var likesCount: Int? var liked: Bool - init(content: String, backgroundColor: String, latitude: Double? = nil, longitude: Double? = nil, image: UIImage? = nil) { + init(content: String, backgroundColor: String, latitude: Double? = nil, longitude: Double? = nil, image: UIImage? = nil, liked: Bool) { self.content = content self.backgroundColor = backgroundColor self.id = nil diff --git a/Secretly/Network/RestClient.swift b/Secretly/Network/RestClient.swift index aebb706..4f24f61 100644 --- a/Secretly/Network/RestClient.swift +++ b/Secretly/Network/RestClient.swift @@ -68,7 +68,7 @@ struct RestClient { func update(model: T, complete: @escaping (Result) -> Void) throws { let data = try encoder.encode(model) - client.put(path: "\(path)/\(model.id)", body: data) { result in + client.put(path: path, body: data) { result in let newResult = result.flatMap { parse(data: $0) } complete(newResult) } diff --git a/Secretly/Services/UpdatePostService.swift b/Secretly/Services/UpdatePostService.swift new file mode 100644 index 0000000..fbd64c8 --- /dev/null +++ b/Secretly/Services/UpdatePostService.swift @@ -0,0 +1,28 @@ +// +// File.swift +// Secretly +// +// Created by Proteco on 10/07/21. +// Copyright © 2021 3zcurdia. All rights reserved. +// + +import Foundation + +struct UpdatePostService { + private var endpoint: RestClient? + + init(post: Post?) { + guard let postId = post?.id else { + self.endpoint = nil + return + } + self.endpoint = RestClient(client: AmacaConfig.shared.httpClient, path: "/api/v1/posts/\(postId)") + } + + func update(_ model: Post, complete: @escaping (Result) -> Void) { + try? endpoint?.update(model: model) { result in + DispatchQueue.main.async { complete(result) } + } + } + +} diff --git a/Secretly/ViewControllers/CreatePostViewController.swift b/Secretly/ViewControllers/CreatePostViewController.swift index 4091252..827ba16 100644 --- a/Secretly/ViewControllers/CreatePostViewController.swift +++ b/Secretly/ViewControllers/CreatePostViewController.swift @@ -19,7 +19,7 @@ class CreatePostViewController: UIViewController { @IBAction func createPost(_ sender: Any?) { - let post = Post(content: contentField.text!, backgroundColor: colorField.text!) + let post = Post(content: contentField.text!, backgroundColor: colorField.text!, liked: false) let postsEndpoint = RestClient(client: AmacaConfig.shared.httpClient, path: "/api/v1/posts") do { diff --git a/Secretly/ViewControllers/PostInputViewController.swift b/Secretly/ViewControllers/PostInputViewController.swift index 676ce35..c25fc35 100644 --- a/Secretly/ViewControllers/PostInputViewController.swift +++ b/Secretly/ViewControllers/PostInputViewController.swift @@ -141,7 +141,8 @@ class PostInputViewController: UIViewController, UINavigationControllerDelegate content: postText, backgroundColor: previewPost.backgroundColor?.hexString ?? "#3366CC", latitude: currentLocation?.latitude, - longitude: currentLocation?.longitude + longitude: currentLocation?.longitude, + liked: false ) if let uimage = previewPost.image { post.imageData = uimage.encodeBase64() diff --git a/Secretly/Views/PostCollectionViewCell.swift b/Secretly/Views/PostCollectionViewCell.swift index 88ef2e4..3f4c44c 100644 --- a/Secretly/Views/PostCollectionViewCell.swift +++ b/Secretly/Views/PostCollectionViewCell.swift @@ -11,6 +11,7 @@ import UIKit class PostCollectionViewCell: UICollectionViewCell { static let reuseIdentifier = "feedPostCell" var likeService: LikeService? + var updatePostService: UpdatePostService? var post: Post? { didSet { updateView() @@ -33,6 +34,7 @@ class PostCollectionViewCell: UICollectionViewCell { } func updateView() { + status() imageView.image = nil guard let post = post else { return } if let color = UIColor(hex: post.backgroundColor) { @@ -47,20 +49,46 @@ class PostCollectionViewCell: UICollectionViewCell { self.authorView.author = post.user } + func status() { + guard let post = post else {return} + if post.liked { + likeState.image = UIImage(systemName: "heart.fill") + } else { + likeState.image = UIImage(systemName: "heart") + } + } + @objc private func tapLike(){ guard let post = post, let id = post.id else {return} let updateLike = Like(id: id, createdAt: Date(), updatedAt: Date()) if !post.liked { likeService?.create(updateLike) { result in + self.updatePost(id: id, sum: 1, state: true) self.likeState.image = UIImage(systemName: "heart.fill") self.likeCounter.text = String(describing: post.likesCount! + 1) } } else { likeService?.delete(updateLike) { result in + self.updatePost(id: id, sum: -1, state: false) self.likeState.image = UIImage(systemName: "heart") self.likeCounter.text = String(describing: post.likesCount! - 1) } } } + func updatePost(id: Int, sum: Int, state: Bool) { + guard let post = post else {return} + var newPost = post + newPost.likesCount = post.likesCount ?? 0 + sum + newPost.liked = state + updatePostService?.update(newPost) { result in + switch result { + case .success: + print("Success update \(result)") + case .failure: + print("Failure update \(result)") + } + } + } + } From b17b43c4fb9e3a74b779d83ff0a6413027955179 Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 19:09:21 -0400 Subject: [PATCH 6/9] Implement double tap gesture like --- Secretly/Views/PostCollectionViewCell.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Secretly/Views/PostCollectionViewCell.swift b/Secretly/Views/PostCollectionViewCell.swift index 3f4c44c..17735c9 100644 --- a/Secretly/Views/PostCollectionViewCell.swift +++ b/Secretly/Views/PostCollectionViewCell.swift @@ -16,6 +16,7 @@ class PostCollectionViewCell: UICollectionViewCell { didSet { updateView() likeService = LikeService(post: post) + updatePostService = UpdatePostService(post: post) } } @IBOutlet weak var authorView: AuthorView! @@ -31,6 +32,11 @@ class PostCollectionViewCell: UICollectionViewCell { let tapLikeState = UITapGestureRecognizer(target: self, action: #selector(tapLike)) self.likeState.isUserInteractionEnabled = true self.likeState.addGestureRecognizer(tapLikeState) + + let doubleTapImageView = UITapGestureRecognizer(target: self, action: #selector(doubleTapImageViewLike)) + doubleTapImageView.numberOfTapsRequired = 2 + self.imageView.isUserInteractionEnabled = true + self.imageView.addGestureRecognizer(doubleTapImageView) } func updateView() { @@ -59,6 +65,14 @@ class PostCollectionViewCell: UICollectionViewCell { } @objc private func tapLike(){ + self.like() + } + + @objc private func doubleTapImageViewLike(_ gesture: UITapGestureRecognizer){ + self.like() + } + + private func like(){ guard let post = post, let id = post.id else {return} let updateLike = Like(id: id, createdAt: Date(), updatedAt: Date()) if !post.liked { From d9a4bbc9a8eab89b3946bf7fc55bfe56ef7fb9ba Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 21:59:44 -0400 Subject: [PATCH 7/9] Implement debug print --- Secretly.xcodeproj/project.pbxproj | 2 +- Secretly/Network/HttpResponse.swift | 15 ++++++++++++++- Secretly/Services/UpdatePostService.swift | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Secretly.xcodeproj/project.pbxproj b/Secretly.xcodeproj/project.pbxproj index 47ebf0a..45cd3b2 100644 --- a/Secretly.xcodeproj/project.pbxproj +++ b/Secretly.xcodeproj/project.pbxproj @@ -206,8 +206,8 @@ children = ( 307A305C2661CD510020DF8B /* PostCollectionViewCell.swift */, 307A305D2661CD510020DF8B /* PostCollectionViewCell.xib */, - 307A306426629B990020DF8B /* AuthorView.swift */, 302BB61B267D7CC800FD74F5 /* PreviewPostVIew.swift */, + 307A306426629B990020DF8B /* AuthorView.swift */, ); path = Views; sourceTree = ""; diff --git a/Secretly/Network/HttpResponse.swift b/Secretly/Network/HttpResponse.swift index eb0543a..1ea6e75 100644 --- a/Secretly/Network/HttpResponse.swift +++ b/Secretly/Network/HttpResponse.swift @@ -20,6 +20,19 @@ struct HttpResponse { } func result(for data: Data?) -> Result { - return status.result().map { _ in data } + //#if DEBUG + if let udata = data, !udata.isEmpty { + let currentData = String(data: udata, encoding: .utf8) + debugPrint("Response: \(status) \(self.httpUrlResponse.statusCode) \(self.httpUrlResponse.url!) -d \(String(describing: currentData))") + } else { + debugPrint("Response: \(status) \(self.httpUrlResponse.statusCode) \(self.httpUrlResponse.url!)") + } + //#endif + if let udata = data, !udata.isEmpty { + return status.result().map { _ in data } + } else { + return status.result().map { _ in nil } + } } + } diff --git a/Secretly/Services/UpdatePostService.swift b/Secretly/Services/UpdatePostService.swift index fbd64c8..3865877 100644 --- a/Secretly/Services/UpdatePostService.swift +++ b/Secretly/Services/UpdatePostService.swift @@ -21,7 +21,7 @@ struct UpdatePostService { func update(_ model: Post, complete: @escaping (Result) -> Void) { try? endpoint?.update(model: model) { result in - DispatchQueue.main.async { complete(result) } + DispatchQueue.main.async { complete(result)} } } From c77c5ec188040d2d849561e4603924e1ec6bd7a7 Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 22:38:03 -0400 Subject: [PATCH 8/9] Fix like status --- Secretly.xcodeproj/project.pbxproj | 4 --- Secretly/Models/Post.swift | 2 +- Secretly/Services/UpdatePostService.swift | 28 ------------------- .../CreatePostViewController.swift | 2 +- Secretly/Views/PostCollectionViewCell.swift | 25 +++-------------- 5 files changed, 6 insertions(+), 55 deletions(-) delete mode 100644 Secretly/Services/UpdatePostService.swift diff --git a/Secretly.xcodeproj/project.pbxproj b/Secretly.xcodeproj/project.pbxproj index 45cd3b2..d58b7e5 100644 --- a/Secretly.xcodeproj/project.pbxproj +++ b/Secretly.xcodeproj/project.pbxproj @@ -59,7 +59,6 @@ 5B89708B269A491D0080C464 /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708A269A491D0080C464 /* Like.swift */; }; 5B89708D269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; 5B89708E269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; - 5B897090269A58660080C464 /* UpdatePostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708F269A58660080C464 /* UpdatePostService.swift */; }; E021984723FA35E00025C28E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984623FA35E00025C28E /* AppDelegate.swift */; }; E021984923FA35E00025C28E /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984823FA35E00025C28E /* SceneDelegate.swift */; }; E021984B23FA35E00025C28E /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984A23FA35E00025C28E /* WelcomeViewController.swift */; }; @@ -131,7 +130,6 @@ 30FD0E712659645A006E309A /* Faker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Faker.swift; sourceTree = ""; }; 5B89708A269A491D0080C464 /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; 5B89708C269A4A3E0080C464 /* LikeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeService.swift; sourceTree = ""; }; - 5B89708F269A58660080C464 /* UpdatePostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdatePostService.swift; sourceTree = ""; }; E021984323FA35E00025C28E /* Secretly.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretly.app; sourceTree = BUILT_PRODUCTS_DIR; }; E021984623FA35E00025C28E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E021984823FA35E00025C28E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -230,7 +228,6 @@ 304E06C726742BDA00A99128 /* CreatePostService.swift */, 304E06C926742CC500A99128 /* FeedService.swift */, 5B89708C269A4A3E0080C464 /* LikeService.swift */, - 5B89708F269A58660080C464 /* UpdatePostService.swift */, ); path = Services; sourceTree = ""; @@ -483,7 +480,6 @@ 3033795B267537490066D94A /* FeedCollectionViewController+UICollectionViewDataSourcePrefetching.swift in Sources */, 30B9B93B268CA9E6007B1942 /* UIImage+PixelBuffer.swift in Sources */, 303379592675371C0066D94A /* FeedCollectionViewController+UICollectionViewDataSource .swift in Sources */, - 5B897090269A58660080C464 /* UpdatePostService.swift in Sources */, 304E06CA26742CC500A99128 /* FeedService.swift in Sources */, 302BB61F267E316900FD74F5 /* PostInputViewController.swift in Sources */, ); diff --git a/Secretly/Models/Post.swift b/Secretly/Models/Post.swift index 886d444..2c13f19 100644 --- a/Secretly/Models/Post.swift +++ b/Secretly/Models/Post.swift @@ -24,7 +24,7 @@ struct Post: Restable { var likesCount: Int? var liked: Bool - init(content: String, backgroundColor: String, latitude: Double? = nil, longitude: Double? = nil, image: UIImage? = nil, liked: Bool) { + init(content: String, backgroundColor: String, latitude: Double? = nil, longitude: Double? = nil, image: UIImage? = nil, liked: Bool, likesCount: Int? = nil) { self.content = content self.backgroundColor = backgroundColor self.id = nil diff --git a/Secretly/Services/UpdatePostService.swift b/Secretly/Services/UpdatePostService.swift deleted file mode 100644 index 3865877..0000000 --- a/Secretly/Services/UpdatePostService.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// File.swift -// Secretly -// -// Created by Proteco on 10/07/21. -// Copyright © 2021 3zcurdia. All rights reserved. -// - -import Foundation - -struct UpdatePostService { - private var endpoint: RestClient? - - init(post: Post?) { - guard let postId = post?.id else { - self.endpoint = nil - return - } - self.endpoint = RestClient(client: AmacaConfig.shared.httpClient, path: "/api/v1/posts/\(postId)") - } - - func update(_ model: Post, complete: @escaping (Result) -> Void) { - try? endpoint?.update(model: model) { result in - DispatchQueue.main.async { complete(result)} - } - } - -} diff --git a/Secretly/ViewControllers/CreatePostViewController.swift b/Secretly/ViewControllers/CreatePostViewController.swift index 827ba16..2f657f7 100644 --- a/Secretly/ViewControllers/CreatePostViewController.swift +++ b/Secretly/ViewControllers/CreatePostViewController.swift @@ -19,7 +19,7 @@ class CreatePostViewController: UIViewController { @IBAction func createPost(_ sender: Any?) { - let post = Post(content: contentField.text!, backgroundColor: colorField.text!, liked: false) + let post = Post(content: contentField.text!, backgroundColor: colorField.text!, liked: false, likesCount: 0) let postsEndpoint = RestClient(client: AmacaConfig.shared.httpClient, path: "/api/v1/posts") do { diff --git a/Secretly/Views/PostCollectionViewCell.swift b/Secretly/Views/PostCollectionViewCell.swift index 17735c9..2e4a5ae 100644 --- a/Secretly/Views/PostCollectionViewCell.swift +++ b/Secretly/Views/PostCollectionViewCell.swift @@ -11,12 +11,10 @@ import UIKit class PostCollectionViewCell: UICollectionViewCell { static let reuseIdentifier = "feedPostCell" var likeService: LikeService? - var updatePostService: UpdatePostService? var post: Post? { didSet { updateView() likeService = LikeService(post: post) - updatePostService = UpdatePostService(post: post) } } @IBOutlet weak var authorView: AuthorView! @@ -77,32 +75,17 @@ class PostCollectionViewCell: UICollectionViewCell { let updateLike = Like(id: id, createdAt: Date(), updatedAt: Date()) if !post.liked { likeService?.create(updateLike) { result in - self.updatePost(id: id, sum: 1, state: true) + self.post?.liked = true self.likeState.image = UIImage(systemName: "heart.fill") self.likeCounter.text = String(describing: post.likesCount! + 1) } } else { likeService?.delete(updateLike) { result in - self.updatePost(id: id, sum: -1, state: false) + self.post?.liked = false self.likeState.image = UIImage(systemName: "heart") - self.likeCounter.text = String(describing: post.likesCount! - 1) + self.likeCounter.text = String(describing: post.likesCount ?? 0 - 1) } } } - - func updatePost(id: Int, sum: Int, state: Bool) { - guard let post = post else {return} - var newPost = post - newPost.likesCount = post.likesCount ?? 0 + sum - newPost.liked = state - updatePostService?.update(newPost) { result in - switch result { - case .success: - print("Success update \(result)") - case .failure: - print("Failure update \(result)") - } - } - } - + } From ed6c1ab1a8c6267a957a1bb65a58e0bf4b57c2d8 Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 10 Jul 2021 22:47:14 -0400 Subject: [PATCH 9/9] Added tests --- Secretly.xcodeproj/project.pbxproj | 10 ++++++---- SecretlyTests/LikeServiceTest.swift | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 SecretlyTests/LikeServiceTest.swift diff --git a/Secretly.xcodeproj/project.pbxproj b/Secretly.xcodeproj/project.pbxproj index d58b7e5..e36d53d 100644 --- a/Secretly.xcodeproj/project.pbxproj +++ b/Secretly.xcodeproj/project.pbxproj @@ -58,7 +58,7 @@ 30FD0E722659645A006E309A /* Faker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FD0E712659645A006E309A /* Faker.swift */; }; 5B89708B269A491D0080C464 /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708A269A491D0080C464 /* Like.swift */; }; 5B89708D269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; - 5B89708E269A4A3E0080C464 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B89708C269A4A3E0080C464 /* LikeService.swift */; }; + 5B897092269A913A0080C464 /* LikeServiceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B897091269A913A0080C464 /* LikeServiceTest.swift */; }; E021984723FA35E00025C28E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984623FA35E00025C28E /* AppDelegate.swift */; }; E021984923FA35E00025C28E /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984823FA35E00025C28E /* SceneDelegate.swift */; }; E021984B23FA35E00025C28E /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E021984A23FA35E00025C28E /* WelcomeViewController.swift */; }; @@ -130,6 +130,7 @@ 30FD0E712659645A006E309A /* Faker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Faker.swift; sourceTree = ""; }; 5B89708A269A491D0080C464 /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; 5B89708C269A4A3E0080C464 /* LikeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeService.swift; sourceTree = ""; }; + 5B897091269A913A0080C464 /* LikeServiceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeServiceTest.swift; sourceTree = ""; }; E021984323FA35E00025C28E /* Secretly.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretly.app; sourceTree = BUILT_PRODUCTS_DIR; }; E021984623FA35E00025C28E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E021984823FA35E00025C28E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -306,6 +307,7 @@ children = ( E021985D23FA35E20025C28E /* SecretlyTests.swift */, E021985F23FA35E20025C28E /* Info.plist */, + 5B897091269A913A0080C464 /* LikeServiceTest.swift */, ); path = SecretlyTests; sourceTree = ""; @@ -489,8 +491,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5B89708E269A4A3E0080C464 /* LikeService.swift in Sources */, E021985E23FA35E20025C28E /* SecretlyTests.swift in Sources */, + 5B897092269A913A0080C464 /* LikeServiceTest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -682,7 +684,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = CF8GW6MT8Z; INFOPLIST_FILE = SecretlyTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.1; LD_RUNPATH_SEARCH_PATHS = ( @@ -704,7 +706,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = CF8GW6MT8Z; INFOPLIST_FILE = SecretlyTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.1; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/SecretlyTests/LikeServiceTest.swift b/SecretlyTests/LikeServiceTest.swift new file mode 100644 index 0000000..0fde5c4 --- /dev/null +++ b/SecretlyTests/LikeServiceTest.swift @@ -0,0 +1,24 @@ +// +// LikeServiceTest.swift +// SecretlyTests +// +// Created by Proteco on 10/07/21. +// Copyright © 2021 3zcurdia. All rights reserved. +// + +import XCTest +@testable import Secretly + +class LikeServiceTest: XCTestCase { + + func testCreateLike() { + let createLike = LikeService(id: 70) + XCTAssertNoThrow(createLike) + } + + func testDelteTest() { + let deleteLike = LikeService(id: 70) + XCTAssertNoThrow(deleteLike) + } + +}