Files
WhiteNights_iOS/WhiteNights/Widgets/SightViewModel.swift
15lu.akari a87a3d12ab big update
2025-08-26 23:37:39 +03:00

112 lines
4.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import AVKit
import Combine
@MainActor
class SightViewModel: ObservableObject {
@Published var sightName: String = "Загрузка..."
@Published var allArticles: [Article] = []
@Published var selectedArticle: Article?
@Published var articleHeading: String = ""
@Published var articleBody: String = ""
@Published var mediaState: MediaState = .loading
private var sightModel: SightModel?
private var selectedLanguage: String = "ru" // по умолчанию
enum MediaState {
case loading
case image(URL)
case video(AVPlayer)
case error
}
func setLanguage(_ language: String) {
self.selectedLanguage = language
}
func loadInitialData(sightId: Int) async {
do {
async let sightModelTask = fetchJSON(
from: "https://white-nights.krbl.ru/services/content/sight/\(sightId)?lang=\(selectedLanguage)",
type: SightModel.self
)
async let articlesTask = fetchJSON(
from: "https://white-nights.krbl.ru/services/content/sight/\(sightId)/article?lang=\(selectedLanguage)",
type: [Article].self
)
let (fetchedSightModel, fetchedArticles) = try await (sightModelTask, articlesTask)
self.sightModel = fetchedSightModel
self.sightName = fetchedSightModel.name
let reviewArticle = Article(id: -1, body: "", heading: "Обзор", isReviewArticle: true)
self.allArticles = [reviewArticle] + fetchedArticles
selectArticle(reviewArticle)
} catch {
print("Ошибка начальной загрузки данных: \(error)")
self.mediaState = .error
}
}
func selectArticle(_ article: Article) {
guard selectedArticle != article else { return }
self.selectedArticle = article
self.articleHeading = article.heading
self.articleBody = article.body
Task {
await updateMedia(for: article)
}
}
private func updateMedia(for article: Article) async {
self.mediaState = .loading
if article.isReviewArticle == true {
guard let sight = sightModel else {
self.mediaState = .error
return
}
if let videoPreviewId = sight.video_preview,
let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(videoPreviewId)/download?lang=\(selectedLanguage)") {
let player = AVPlayer(url: url)
player.play()
self.mediaState = .video(player)
} else if let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(sight.preview_media)/download?lang=\(selectedLanguage)") {
self.mediaState = .image(url)
} else {
self.mediaState = .error
}
} else {
do {
let mediaItems = try await fetchJSON(
from: "https://white-nights.krbl.ru/services/content/article/\(article.id)/media?lang=\(selectedLanguage)",
type: [ArticleMedia].self
)
if let firstMedia = mediaItems.first,
let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(firstMedia.id)/download?lang=\(selectedLanguage)") {
self.mediaState = .image(url)
} else {
self.mediaState = .error
}
} catch {
print("Ошибка загрузки медиа для статьи '\(article.heading)': \(error)")
self.mediaState = .error
}
}
}
private func fetchJSON<T: Decodable>(from urlString: String, type: T.Type) async throws -> T {
guard let url = URL(string: urlString) else {
throw URLError(.badURL)
}
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(T.self, from: data)
}
}