Skip to content

Instantly share code, notes, and snippets.

@lotusirous
Created July 23, 2024 14:33
Show Gist options
  • Save lotusirous/5ab2ddd581ca8290598dfa0e82c46c11 to your computer and use it in GitHub Desktop.
Save lotusirous/5ab2ddd581ca8290598dfa0e82c46c11 to your computer and use it in GitHub Desktop.
class HomeViewModel: ObservableObject {
@Published var articles: [Article] = []
private let cacheFile = "articles.json"
private var cancellables = Set<AnyCancellable>()
struct ListArticleParams {
let limit: Int
let offset: Int
let useCache: Bool
}
var loadArticle = PassthroughSubject<HomeViewModel.ListArticleParams, Never>()
init() {
let emptyArticle: [Article] = []
self.loadArticle
.debounce(for: 0.5, scheduler: RunLoop.main)
.flatMap { params -> AnyPublisher<[Article], Error> in
if params.useCache {
let out: AnyPublisher<([Article], Int), Error> = DefaultStorage.readPublisher(fileName: self.cacheFile)
return out.map { articles, _ in articles }.eraseToAnyPublisher()
}
return DefaultHTTPClient.listArticles(limit: params.limit, offset: params.offset)
.map { $0.articles }
.flatMap { DefaultStorage.writePublisher(input: $0, fileName: self.cacheFile) }
.eraseToAnyPublisher()
}
.replaceError(with: emptyArticle)
.receive(on: DispatchQueue.main)
.assign(to: &self.$articles)
}
}
struct HomeView: View {
@EnvironmentObject var appState: AppState
@ObservedObject var viewModel = HomeViewModel()
var body: some View {
VStack {
Text("Home page ").font(/*@START_MENU_TOKEN@*/ .title/*@END_MENU_TOKEN@*/)
ForEach(viewModel.articles, id: \.uuid) { article in
Text("title: \(article.slug)")
}
Button {
viewModel.loadArticle.send(HomeViewModel.ListArticleParams(limit: 0, offset: 10, useCache: false))
} label: {
Text("Load")
}
}
}
}
#Preview {
HomeView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment