Skip to content

Commit

Permalink
Refactor ArticleClient
Browse files Browse the repository at this point in the history
  • Loading branch information
matax87 committed Dec 5, 2024
1 parent 6866db9 commit 107347f
Show file tree
Hide file tree
Showing 14 changed files with 284 additions and 356 deletions.
7 changes: 0 additions & 7 deletions NOICommunity.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@
319C0E9A26F3483600C6D38B /* UIControl+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C0E9926F3483600C6D38B /* UIControl+Combine.swift */; };
319C0EA026F4790300C6D38B /* CalendarAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C0E9F26F4790300C6D38B /* CalendarAdditions.swift */; };
319C4653282BB32400946AC7 /* ArticlesClient in Frameworks */ = {isa = PBXBuildFile; productRef = 319C4652282BB32400946AC7 /* ArticlesClient */; };
319C4655282BB32400946AC7 /* ArticlesClientLive in Frameworks */ = {isa = PBXBuildFile; productRef = 319C4654282BB32400946AC7 /* ArticlesClientLive */; };
319C465A282BBD8000946AC7 /* NewsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C4657282BB80F00946AC7 /* NewsListViewModel.swift */; };
319C465C282BBE5100946AC7 /* XCTestCase+awaitPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C465B282BBE5100946AC7 /* XCTestCase+awaitPublisher.swift */; };
319C465E282BCC5D00946AC7 /* collectNext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C465D282BCC5D00946AC7 /* collectNext.swift */; };
Expand Down Expand Up @@ -477,7 +476,6 @@
31E058F22812F18800D1F7FE /* KeychainAccess in Frameworks */,
319C4653282BB32400946AC7 /* ArticlesClient in Frameworks */,
3182F4A427DB3841005ADDAF /* AppPreferencesClientLive in Frameworks */,
319C4655282BB32400946AC7 /* ArticlesClientLive in Frameworks */,
317B6F9C28118BD6008D07C0 /* AuthClient in Frameworks */,
3182F4AC27DB3841005ADDAF /* EventShortTypesClientLive in Frameworks */,
311E0EC62825157800404DCE /* FirebaseMessaging in Frameworks */,
Expand Down Expand Up @@ -1093,7 +1091,6 @@
31E058F12812F18800D1F7FE /* KeychainAccess */,
311E0EC52825157800404DCE /* FirebaseMessaging */,
319C4652282BB32400946AC7 /* ArticlesClient */,
319C4654282BB32400946AC7 /* ArticlesClientLive */,
317EC888283BB83E00F30B95 /* PeopleClient */,
317EC88A283BB83E00F30B95 /* PeopleClientLive */,
3181B9202B1E12BD000D2A0F /* Core */,
Expand Down Expand Up @@ -2362,10 +2359,6 @@
isa = XCSwiftPackageProductDependency;
productName = ArticlesClient;
};
319C4654282BB32400946AC7 /* ArticlesClientLive */ = {
isa = XCSwiftPackageProductDependency;
productName = ArticlesClientLive;
};
31B1926E2C6A2136009872E9 /* FirebaseCrashlytics */ = {
isa = XCSwiftPackageProductDependency;
package = 311E0EC42825157800404DCE /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
Expand Down
42 changes: 22 additions & 20 deletions NOICommunity/NewsFeature/View Models/NewsDetailsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ final class NewsDetailsViewModel {
lazy var showAskAQuestionPublisher = showAskAQuestionSubject
.eraseToAnyPublisher()

private var fetchRequestCancellable: AnyCancellable?

init(
articlesClient: ArticlesClient,
availableNews: Article?,
Expand All @@ -45,24 +43,9 @@ final class NewsDetailsViewModel {
}

func refreshNewsDetails(newsId: String) {
isLoading = true

fetchRequestCancellable = articlesClient.detail(newsId)
.receive(on: DispatchQueue.main)
.sink(
receiveCompletion: { [weak self] completion in
self?.isLoading = false

switch completion {
case .finished:
break
case .failure(let error):
self?.error = error
}
},
receiveValue: { [weak self] in
self?.result = $0
})
Task(priority: .userInitiated) { [weak self] in
await self?.performRefreshNewsDetails(newsId: newsId)
}
}

func showExternalLink(sender: Any?) {
Expand All @@ -74,3 +57,22 @@ final class NewsDetailsViewModel {
}

}

// MARK: Private APIs

private extension NewsDetailsViewModel {

func performRefreshNewsDetails(newsId: String) async {
isLoading = true
defer {
isLoading = false
}

do {
result = try await articlesClient.getArticle(newsId: newsId)
} catch {
self.error = error
}
}

}
111 changes: 50 additions & 61 deletions NOICommunity/NewsFeature/View Models/NewsListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,66 +53,9 @@ final class NewsListViewModel {
}

func fetchNews(refresh: Bool = false) {
guard nextPage != nil || refresh
else { return }

let pageNumber: Int

if refresh {
pageNumber = firstPage
} else {
pageNumber = nextPage!
}

let currentNewsIds: [String]
if refresh {
currentNewsIds = []
} else {
currentNewsIds = newsIds
}

isLoadingFirstPage = pageNumber == firstPage
isLoading = true

var articlesListPublisher = articlesClient.list(
Date(),
"noi-communityapp",
pageSize,
pageNumber
)

if refresh {
articlesListPublisher = articlesListPublisher
.delay(for: 0.3, scheduler: RunLoop.main)
.eraseToAnyPublisher()
}

fetchRequestCancellable = articlesListPublisher
.receive(on: DispatchQueue.main)
.sink(
receiveCompletion: { [weak self] completion in
self?.isLoadingFirstPage = false
self?.isLoading = false

switch completion {
case .finished:
break
case .failure(let error):
self?.error = error
}
},
receiveValue: { [weak self] pagination in
guard let self = self
else { return }

self.nextPage = pagination.nextPage

guard let newItems = pagination.items
else { return }

newItems.forEach { self.idToNews[$0.id] = $0 }
self.newsIds = currentNewsIds + newItems.map(\.id)
})
Task(priority: .userInitiated) { [weak self] in
await self?.performFetchNews(refresh: refresh)
}
}

func news(withId newsId: String) -> Article {
Expand All @@ -131,7 +74,53 @@ final class NewsListViewModel {
// MARK: Private APIs

private extension NewsListViewModel {


func performFetchNews(refresh: Bool = false) async {
guard nextPage != nil || refresh
else { return }

let pageNumber: Int

if refresh {
pageNumber = firstPage
} else {
pageNumber = nextPage!
}

let currentNewsIds: [String]
if refresh {
currentNewsIds = []
} else {
currentNewsIds = newsIds
}

isLoadingFirstPage = pageNumber == firstPage
isLoading = true
defer {
isLoadingFirstPage = false
isLoading = false
}

do {
let pagination = try await articlesClient.getArticleList(
startDate: Date(),
publishedOn: "noi-communityapp",
pageSize: pageSize,
pageNumber: pageNumber
)

nextPage = pagination.nextPage

if let newItems = pagination.items {
newItems.forEach { idToNews[$0.id] = $0 }
newsIds = currentNewsIds + newItems.map(\.id)
}
} catch {
self.error = error
}

}

func configureBindings() {
refreshCancellable = NotificationCenter
.default
Expand Down
7 changes: 5 additions & 2 deletions NOICommunity/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import EventShortTypesClientLive
import Core
import AuthClientLive
import AuthStateStorageClient
import ArticlesClientLive
import ArticlesClient
import PeopleClientLive

#if DEBUG
Expand Down Expand Up @@ -77,7 +77,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
return .live()
}
}(),
articleClient: .live(),
articleClient: ArticlesClientImplementation(
baseURL: EventsFeatureConstants.clientBaseURL,
transport: URLSession.shared
),
peopleClient: .live(baseURL: MeetConstant.clientBaseURL)
)
}()
Expand Down
13 changes: 2 additions & 11 deletions NOICommunityLib/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ let package = Package(
name: "ArticlesClient",
targets: ["ArticlesClient"]
),
.library(
name: "ArticlesClientLive",
targets: ["ArticlesClientLive"]
),
.library(
name: "PeopleClient",
targets: ["PeopleClient"]
Expand Down Expand Up @@ -154,14 +150,9 @@ let package = Package(
),
.target(
name: "ArticlesClient",
dependencies: []
),
.target(
name: "ArticlesClientLive",
dependencies: [
"Core",
"ArticlesClient",
]
"Core"
]
),
.target(
name: "PeopleClient",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

//
// Endpoints.swift
// ArticlesClientLive
// Endpoints+ArticleClient.swift
// ArticlesClient
//
// Created by Matteo Matassoni on 11/05/22.
//

import Foundation
import Core
import ArticlesClient

private let dateFormatter: DateFormatter = { dateFormatter in
dateFormatter.calendar = Calendar(identifier: .iso8601)
Expand All @@ -24,16 +23,18 @@ private let dateFormatter: DateFormatter = { dateFormatter in
extension Endpoint {

static func articleList(
startDate: Date,
startDate: Date?,
publishedon: String?,
pageSize: Int?,
pageNumber: Int?
) -> Endpoint {
Self(path: "/v1/Article") {
URLQueryItem(
name: "startDate",
value: dateFormatter.string(from: startDate)
)
if let startDate {
URLQueryItem(
name: "startDate",
value: dateFormatter.string(from: startDate)
)
}

if let publishedon = publishedon {
URLQueryItem(
Expand Down
Loading

0 comments on commit 107347f

Please sign in to comment.