From d8b24e986f4b63c2e39bdcd35de551555f1dc270 Mon Sep 17 00:00:00 2001 From: Volodymyr Chekyrta Date: Thu, 25 May 2023 17:40:06 +0300 Subject: [PATCH] Fix Discussion incorrect replies count --- Core/Core.xcodeproj/project.pbxproj | 4 +++ Core/Core/Data/Model/Data_Discovery.swift | 8 +++-- Core/Core/Domain/Model/Pagination.swift | 22 ++++++++++++ .../Data/Model/Data_CommentsResponse.swift | 34 +++++++++---------- .../Data/Network/DiscussionRepository.swift | 30 ++++++++-------- .../Domain/DiscussionInteractor.swift | 12 +++---- .../Base/BaseResponsesViewModel.swift | 2 ++ .../Comments/Responses/ResponsesView.swift | 8 ++--- .../Responses/ResponsesViewModel.swift | 5 +-- .../Comments/Thread/ThreadView.swift | 8 ++--- .../Comments/Thread/ThreadViewModel.swift | 13 ++++--- 11 files changed, 87 insertions(+), 59 deletions(-) create mode 100644 Core/Core/Domain/Model/Pagination.swift diff --git a/Core/Core.xcodeproj/project.pbxproj b/Core/Core.xcodeproj/project.pbxproj index f8b06176f..731ba83cb 100644 --- a/Core/Core.xcodeproj/project.pbxproj +++ b/Core/Core.xcodeproj/project.pbxproj @@ -97,6 +97,7 @@ 072787B628D37A0E002E9142 /* Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 072787B528D37A0E002E9142 /* Validator.swift */; }; 07460FE1294B706200F70538 /* CollectionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07460FE0294B706200F70538 /* CollectionExtension.swift */; }; 07460FE3294B72D700F70538 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07460FE2294B72D700F70538 /* Notification.swift */; }; + 076F297F2A1F80C800967E7D /* Pagination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 076F297E2A1F80C800967E7D /* Pagination.swift */; }; 0770DE1928D0847D006D8A5D /* BaseRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0770DE1828D0847D006D8A5D /* BaseRouter.swift */; }; 0770DE2528D08FBA006D8A5D /* AppStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0770DE2428D08FBA006D8A5D /* AppStorage.swift */; }; 0770DE2A28D0929E006D8A5D /* HTTPTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0770DE2928D0929E006D8A5D /* HTTPTask.swift */; }; @@ -217,6 +218,7 @@ 07460FE0294B706200F70538 /* CollectionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtension.swift; sourceTree = ""; }; 07460FE2294B72D700F70538 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = ""; }; 0754BB7841E3C0F8D6464951 /* Pods-App-Core.releasestage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Core.releasestage.xcconfig"; path = "Target Support Files/Pods-App-Core/Pods-App-Core.releasestage.xcconfig"; sourceTree = ""; }; + 076F297E2A1F80C800967E7D /* Pagination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pagination.swift; sourceTree = ""; }; 0770DE0828D07831006D8A5D /* Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Core.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0770DE1828D0847D006D8A5D /* BaseRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseRouter.swift; sourceTree = ""; }; 0770DE2428D08FBA006D8A5D /* AppStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStorage.swift; sourceTree = ""; }; @@ -425,6 +427,7 @@ 027BD39B2908810C00392132 /* RegisterUser.swift */, 028F9F38293A452B00DE65D0 /* ResetPassword.swift */, 020C31C8290AC3F700D6DEA2 /* PickerFields.swift */, + 076F297E2A1F80C800967E7D /* Pagination.swift */, ); path = Model; sourceTree = ""; @@ -779,6 +782,7 @@ 027BD3AE2909475000392132 /* KeyboardScrollerOptions.swift in Sources */, 027BD3BE2909478B00392132 /* UIResponder+CurrentResponder.swift in Sources */, 070019AE28F701B200D5FC78 /* Certificate.swift in Sources */, + 076F297F2A1F80C800967E7D /* Pagination.swift in Sources */, 0770DE5F28D0B22C006D8A5D /* Strings.swift in Sources */, 02C917F029CDA99E00DBB8BD /* Data_Dashboard.swift in Sources */, 024FCD0028EF1CD300232339 /* WebBrowser.swift in Sources */, diff --git a/Core/Core/Data/Model/Data_Discovery.swift b/Core/Core/Data/Model/Data_Discovery.swift index e44786bc9..6bbc014b5 100644 --- a/Core/Core/Data/Model/Data_Discovery.swift +++ b/Core/Core/Data/Model/Data_Discovery.swift @@ -7,8 +7,6 @@ import Foundation -// MARK: "/api/courses/v1/courses/" - // MARK: - Pagination public extension DataLayer { struct Pagination: Codable { @@ -115,3 +113,9 @@ public extension DataLayer.DiscoveryResponce { return listReady } } + +public extension DataLayer.Pagination { + var domain: Pagination { + Pagination(next: next, previous: previous, count: count, numPages: numPages) + } +} diff --git a/Core/Core/Domain/Model/Pagination.swift b/Core/Core/Domain/Model/Pagination.swift new file mode 100644 index 000000000..9cbad7b18 --- /dev/null +++ b/Core/Core/Domain/Model/Pagination.swift @@ -0,0 +1,22 @@ +// +// Pagination.swift +// Core +// +// Created by Vladimir Chekyrta on 25.05.2023. +// + +import Foundation + +public struct Pagination { + public let next: String? + public let previous: String? + public let count: Int + public let numPages: Int + + public init(next: String?, previous: String?, count: Int, numPages: Int) { + self.next = next + self.previous = previous + self.count = count + self.numPages = numPages + } +} diff --git a/Discussion/Discussion/Data/Model/Data_CommentsResponse.swift b/Discussion/Discussion/Data/Model/Data_CommentsResponse.swift index d99831abb..d95cde415 100644 --- a/Discussion/Discussion/Data/Model/Data_CommentsResponse.swift +++ b/Discussion/Discussion/Data/Model/Data_CommentsResponse.swift @@ -105,23 +105,23 @@ public extension DataLayer { public extension DataLayer.CommentsResponse { var domain: [UserComment] { self.comments.map { comment in - UserComment( - authorName: comment.author ?? DiscussionLocalization.anonymous, - authorAvatar: comment.users?.userName?.profile?.image?.imageURLLarge ?? "", - postDate: Date(iso8601: comment.createdAt), - postTitle: "", - postBody: comment.rawBody, - postBodyHtml: comment.renderedBody, - postVisible: true, - voted: comment.voted, - followed: false, - votesCount: comment.voteCount, - responsesCount: pagination.count, - threadID: comment.threadID, - commentID: comment.id, - parentID: comment.id, - abuseFlagged: comment.abuseFlagged - ) + UserComment( + authorName: comment.author ?? DiscussionLocalization.anonymous, + authorAvatar: comment.users?.userName?.profile?.image?.imageURLLarge ?? "", + postDate: Date(iso8601: comment.createdAt), + postTitle: "", + postBody: comment.rawBody, + postBodyHtml: comment.renderedBody, + postVisible: true, + voted: comment.voted, + followed: false, + votesCount: comment.voteCount, + responsesCount: comment.childCount, + threadID: comment.threadID, + commentID: comment.id, + parentID: comment.id, + abuseFlagged: comment.abuseFlagged + ) } } } diff --git a/Discussion/Discussion/Data/Network/DiscussionRepository.swift b/Discussion/Discussion/Data/Network/DiscussionRepository.swift index db9b95627..d213ddb67 100644 --- a/Discussion/Discussion/Data/Network/DiscussionRepository.swift +++ b/Discussion/Discussion/Data/Network/DiscussionRepository.swift @@ -17,9 +17,9 @@ public protocol DiscussionRepositoryProtocol { page: Int) async throws -> ThreadLists func searchThreads(courseID: String, searchText: String, pageNumber: Int) async throws -> ThreadLists func getTopics(courseID: String) async throws -> Topics - func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) - func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) - func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Int) + func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) + func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) + func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Pagination) func addCommentTo(threadID: String, rawBody: String, parentID: String?) async throws -> Post func voteThread(voted: Bool, threadID: String) async throws func voteResponse(voted: Bool, responseID: String) async throws @@ -72,25 +72,25 @@ public class DiscussionRepository: DiscussionRepositoryProtocol { return topics.domain } - public func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) { + public func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { let response = try await api.requestData(DiscussionEndpoint .getDiscussionComments(threadID: threadID, page: page)) let result = try await renameUsers(data: response) - return (result.domain, result.pagination.numPages) + return (result.domain, result.pagination.domain) } - public func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) { + public func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { let response = try await api.requestData(DiscussionEndpoint .getQuestionComments(threadID: threadID, page: page)) let result = try await renameUsers(data: response) - return (result.domain, result.pagination.numPages) + return (result.domain, result.pagination.domain) } - public func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Int) { + public func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Pagination) { let response = try await api.requestData(DiscussionEndpoint .getCommentResponses(commentID: commentID, page: page)) let result = try await renameUsers(data: response) - return (result.domain, result.pagination.numPages) + return (result.domain, result.pagination.domain) } public func addCommentTo(threadID: String, rawBody: String, parentID: String? = nil) async throws -> Post { @@ -327,16 +327,16 @@ public class DiscussionRepositoryMock: DiscussionRepositoryProtocol { ) } - public func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) { - (comments, 10) + public func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { + (comments, Pagination(next: nil, previous: nil, count: 10, numPages: 1)) } - public func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) { - (comments, 10) + public func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { + (comments, Pagination(next: nil, previous: nil, count: 10, numPages: 1)) } - public func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Int) { - (comments, 10) + public func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Pagination) { + (comments, Pagination(next: nil, previous: nil, count: 10, numPages: 1)) } public func addCommentTo(threadID: String, rawBody: String, parentID: String?) async throws -> Post { diff --git a/Discussion/Discussion/Domain/DiscussionInteractor.swift b/Discussion/Discussion/Domain/DiscussionInteractor.swift index d17043b03..ee6de6716 100644 --- a/Discussion/Discussion/Domain/DiscussionInteractor.swift +++ b/Discussion/Discussion/Domain/DiscussionInteractor.swift @@ -17,9 +17,9 @@ public protocol DiscussionInteractorProtocol { page: Int) async throws -> ThreadLists func getTopics(courseID: String) async throws -> Topics func searchThreads(courseID: String, searchText: String, pageNumber: Int) async throws -> ThreadLists - func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) - func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) - func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Int) + func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) + func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) + func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Pagination) func addCommentTo(threadID: String, rawBody: String, parentID: String?) async throws -> Post func voteThread(voted: Bool, threadID: String) async throws func voteResponse(voted: Bool, responseID: String) async throws @@ -54,15 +54,15 @@ public class DiscussionInteractor: DiscussionInteractorProtocol { return try await repository.getTopics(courseID: courseID) } - public func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) { + public func getDiscussionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { return try await repository.getDiscussionComments(threadID: threadID, page: page) } - public func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Int) { + public func getQuestionComments(threadID: String, page: Int) async throws -> ([UserComment], Pagination) { return try await repository.getQuestionComments(threadID: threadID, page: page) } - public func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Int) { + public func getCommentResponses(commentID: String, page: Int) async throws -> ([UserComment], Pagination) { return try await repository.getCommentResponses(commentID: commentID, page: page) } diff --git a/Discussion/Discussion/Presentation/Comments/Base/BaseResponsesViewModel.swift b/Discussion/Discussion/Presentation/Comments/Base/BaseResponsesViewModel.swift index 3a3694fc5..d7b7ce10d 100644 --- a/Discussion/Discussion/Presentation/Comments/Base/BaseResponsesViewModel.swift +++ b/Discussion/Discussion/Presentation/Comments/Base/BaseResponsesViewModel.swift @@ -22,6 +22,7 @@ public class BaseResponsesViewModel { public var nextPage = 2 public var totalPages = 1 + @Published public var itemsCount = 0 public var fetchInProgress = false var errorMessage: String? { @@ -138,6 +139,7 @@ public class BaseResponsesViewModel { var newPostWithAvatar = post newPostWithAvatar.authorAvatar = storage.userProfile?.profileImage?.imageURLLarge ?? "" postComments?.comments.append(newPostWithAvatar) + itemsCount += 1 } private func toggleLikeOnParrent() { diff --git a/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift b/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift index 2e70cb9a2..7f8dde1b0 100644 --- a/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift +++ b/Discussion/Discussion/Presentation/Comments/Responses/ResponsesView.swift @@ -85,11 +85,9 @@ public struct ResponsesView: View { onFollowTap: {} ) HStack { - if let responsesCount = viewModel.postComments?.responsesCount { - Text("\(responsesCount)") - Text(DiscussionLocalization.commentsCount(responsesCount)) - Spacer() - } + Text("\(viewModel.itemsCount)") + Text(DiscussionLocalization.commentsCount(viewModel.itemsCount)) + Spacer() }.padding(.top, 40) .padding(.bottom, 14) .padding(.leading, 24) diff --git a/Discussion/Discussion/Presentation/Comments/Responses/ResponsesViewModel.swift b/Discussion/Discussion/Presentation/Comments/Responses/ResponsesViewModel.swift index f3f377d14..b165565b9 100644 --- a/Discussion/Discussion/Presentation/Comments/Responses/ResponsesViewModel.swift +++ b/Discussion/Discussion/Presentation/Comments/Responses/ResponsesViewModel.swift @@ -92,9 +92,10 @@ public class ResponsesViewModel: BaseResponsesViewModel, ObservableObject { public func getComments(commentID: String, parentComment: Post, page: Int) async -> Bool { guard !fetchInProgress else { return false } do { - let (comments, totalPages) = try await interactor + let (comments, pagination) = try await interactor .getCommentResponses(commentID: commentID, page: page) - self.totalPages = totalPages + self.totalPages = pagination.numPages + self.itemsCount = pagination.count self.comments += comments postComments = generateCommentsResponses(comments: self.comments, parentComment: parentComment) return true diff --git a/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift b/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift index dc40a34f7..12513d490 100644 --- a/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift +++ b/Discussion/Discussion/Presentation/Comments/Thread/ThreadView.swift @@ -96,11 +96,9 @@ public struct ThreadView: View { ) HStack { - if let responsesCount = viewModel.postComments?.responsesCount { - Text("\(responsesCount)") - Text(DiscussionLocalization.responsesCount(responsesCount)) - Spacer() - } + Text("\(viewModel.itemsCount)") + Text(DiscussionLocalization.responsesCount(viewModel.itemsCount)) + Spacer() }.padding(.top, 40) .padding(.bottom, 14) .padding(.leading, 24) diff --git a/Discussion/Discussion/Presentation/Comments/Thread/ThreadViewModel.swift b/Discussion/Discussion/Presentation/Comments/Thread/ThreadViewModel.swift index a4ac75651..0457c8be0 100644 --- a/Discussion/Discussion/Presentation/Comments/Thread/ThreadViewModel.swift +++ b/Discussion/Discussion/Presentation/Comments/Thread/ThreadViewModel.swift @@ -128,20 +128,19 @@ public class ThreadViewModel: BaseResponsesViewModel, ObservableObject { try await interactor.readBody(threadID: thread.id) switch thread.type { case .question: - let (comments, totalPages) = try await interactor + let (comments, pagination) = try await interactor .getQuestionComments(threadID: thread.id, page: page) self.totalPages = totalPages + self.itemsCount = pagination.count self.comments += comments - - postComments = - generateComments(comments: self.comments, thread: thread) + postComments = generateComments(comments: self.comments, thread: thread) case .discussion: - let (comments, totalPages) = try await interactor + let (comments, pagination) = try await interactor .getDiscussionComments(threadID: thread.id, page: page) self.totalPages = totalPages + self.itemsCount = pagination.count self.comments += comments - postComments = - generateComments(comments: self.comments, thread: thread) + postComments = generateComments(comments: self.comments, thread: thread) } fetchInProgress = false return true