95 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			3.5 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
 | 
						||
            defer {
 | 
						||
                NotificationCenter.default.post(name: .chatsReloadCompleted, object: nil)
 | 
						||
            }
 | 
						||
 | 
						||
            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: "")
 | 
						||
    }
 | 
						||
}
 |