92 lines
3.3 KiB
Swift
92 lines
3.3 KiB
Swift
import Foundation
|
||
|
||
final class PrivateChatsViewModel: ObservableObject {
|
||
@Published private(set) var chats: [PrivateChatListItem] = []
|
||
@Published private(set) var isInitialLoading: Bool = false
|
||
@Published private(set) var isLoadingMore: Bool = false
|
||
@Published var errorMessage: String?
|
||
|
||
private let chatService: ChatService
|
||
private let pageSize: Int
|
||
private var offset: Int = 0
|
||
private var hasMore: Bool = true
|
||
|
||
init(chatService: ChatService = ChatService(), pageSize: Int = 20) {
|
||
self.chatService = chatService
|
||
self.pageSize = pageSize
|
||
}
|
||
|
||
func loadInitialChats(force: Bool = false) {
|
||
guard !isInitialLoading else { return }
|
||
if !force && !chats.isEmpty { return }
|
||
|
||
isInitialLoading = true
|
||
errorMessage = nil
|
||
let previousOffset = offset
|
||
let previousHasMore = hasMore
|
||
offset = 0
|
||
hasMore = true
|
||
|
||
chatService.fetchPrivateChats(offset: 0, limit: pageSize) { [weak self] result in
|
||
guard let self else { return }
|
||
self.isInitialLoading = false
|
||
|
||
switch result {
|
||
case .success(let data):
|
||
self.chats = data.items
|
||
self.offset = data.items.count
|
||
self.hasMore = data.hasMore
|
||
case .failure(let error):
|
||
self.errorMessage = self.message(for: error)
|
||
self.offset = previousOffset
|
||
self.hasMore = previousHasMore
|
||
}
|
||
}
|
||
}
|
||
|
||
func refresh() {
|
||
loadInitialChats(force: true)
|
||
}
|
||
|
||
func loadMoreIfNeeded(currentItem item: PrivateChatListItem) {
|
||
guard hasMore, !isLoadingMore, item.id == chats.last?.id else { return }
|
||
|
||
isLoadingMore = true
|
||
|
||
chatService.fetchPrivateChats(offset: offset, limit: pageSize) { [weak self] result in
|
||
guard let self else { return }
|
||
self.isLoadingMore = false
|
||
|
||
switch result {
|
||
case .success(let data):
|
||
self.chats.append(contentsOf: data.items)
|
||
self.offset = self.chats.count
|
||
self.hasMore = data.hasMore
|
||
case .failure(let error):
|
||
self.errorMessage = self.message(for: error)
|
||
}
|
||
}
|
||
}
|
||
|
||
private func message(for error: Error) -> String {
|
||
if let chatError = error as? ChatServiceError {
|
||
return chatError.errorDescription ?? NSLocalizedString("Не удалось загрузить чаты.", comment: "")
|
||
}
|
||
|
||
if let networkError = error as? NetworkError {
|
||
switch networkError {
|
||
case .unauthorized:
|
||
return NSLocalizedString("Сессия истекла. Войдите снова.", comment: "")
|
||
case .invalidURL, .noResponse:
|
||
return NSLocalizedString("Ошибка соединения с сервером.", comment: "")
|
||
case .network(let underlying):
|
||
return String(format: NSLocalizedString("Ошибка сети: %@", comment: ""), underlying.localizedDescription)
|
||
case .server(let statusCode, _):
|
||
return String(format: NSLocalizedString("Ошибка сервера (%@).", comment: ""), "\(statusCode)")
|
||
}
|
||
}
|
||
|
||
return NSLocalizedString("Неизвестная ошибка. Попробуйте позже.", comment: "")
|
||
}
|
||
}
|