Files
bookibra/ios/Bookibra/ViewModels/AddBooksViewModel.swift
sbilketay 98e2a1d3f1 fix(ios): iptal edilen isteklerde hata gösterimini düzelt
- API uç noktasını yeni IP adresine güncelle
- Docker yapılandırmasında node_modules için adlandırılmış volume ekle
- Arama işlemlerinde iptal durumlarını yoksay ve hata mesajı gösterme
- NetworkErrorView'da wifi ikonunu kaldır
2026-02-11 22:22:20 +03:00

106 lines
3.0 KiB
Swift

import Foundation
@MainActor
final class AddBooksViewModel: ObservableObject {
enum Mode: String, CaseIterable {
case title
case scan
case filter
var title: String {
switch self {
case .title: return String(localized: "add.searchByTitle")
case .scan: return String(localized: "add.scanBarcode")
case .filter: return String(localized: "add.filter")
}
}
}
@Published var mode: Mode = .title
@Published var titleQuery = ""
@Published var filterTitle = ""
@Published var filterYear = ""
@Published var results: [BookRemote] = []
@Published var isLoading = false
@Published var errorMessage: String?
private var debounceTask: Task<Void, Never>?
private let booksService: BooksServiceProtocol
init(booksService: BooksServiceProtocol) {
self.booksService = booksService
}
func titleChanged() {
debounceTask?.cancel()
let query = titleQuery.trimmingCharacters(in: .whitespacesAndNewlines)
guard query.count >= 2 else {
results = []
return
}
debounceTask = Task {
try? await Task.sleep(for: .milliseconds(400))
await searchByTitle(query)
}
}
func searchByTitle(_ query: String? = nil) async {
let value = query ?? titleQuery
guard !value.isEmpty else { return }
isLoading = true
defer { isLoading = false }
do {
results = try await booksService.searchByTitle(value, locales: "tr,en")
errorMessage = nil
} catch {
guard !isIgnorable(error) else { return }
errorMessage = error.localizedDescription
}
}
func searchByISBN(_ isbn: String) async {
guard !isbn.isEmpty else { return }
isLoading = true
defer { isLoading = false }
do {
results = try await booksService.searchByISBN(isbn, locales: "tr,en")
errorMessage = nil
} catch {
guard !isIgnorable(error) else { return }
errorMessage = error.localizedDescription
}
}
func applyFilter() async {
guard !filterTitle.isEmpty, !filterYear.isEmpty else { return }
isLoading = true
defer { isLoading = false }
do {
results = try await booksService.filter(title: filterTitle, year: filterYear, locales: "tr,en")
errorMessage = nil
} catch {
guard !isIgnorable(error) else { return }
errorMessage = error.localizedDescription
}
}
private func isIgnorable(_ error: Error) -> Bool {
if error is CancellationError {
return true
}
let nsError = error as NSError
if nsError.domain == NSURLErrorDomain, nsError.code == NSURLErrorCancelled {
return true
}
let message = error.localizedDescription.lowercased()
return message.contains("cancelled") || message.contains("vazgeç")
}
}