diff --git a/WhiteNights/Widgets/SightViewModel.swift b/WhiteNights/Widgets/SightViewModel.swift index 3bfdaab..2db0f13 100644 --- a/WhiteNights/Widgets/SightViewModel.swift +++ b/WhiteNights/Widgets/SightViewModel.swift @@ -8,6 +8,8 @@ import SwiftUI class SightViewModel: ObservableObject { private let fileDownloader = FileDownloader() + private var mediaCache: [String: URL] = [:] + @Published var sightName: String = "Загрузка..." @Published var allArticles: [Article] = [] @Published var selectedArticle: Article? @@ -72,86 +74,97 @@ class SightViewModel: ObservableObject { } } - // MARK: - Загрузка медиа // MARK: - Загрузка медиа @MainActor - private func updateMedia(for article: Article) async { - self.mediaState = .loading - self.downloadProgress = nil + private func updateMedia(for article: Article) async { + self.mediaState = .loading + self.downloadProgress = nil - do { - if article.isReviewArticle ?? false { - guard let sight = sightModel else { return } + do { + if article.isReviewArticle ?? false { + guard let sight = sightModel else { return } - if let videoPreviewId = sight.video_preview { - // Пытаемся загрузить видео-превью - let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(videoPreviewId)/download?lang=\(selectedLanguage)")! - let (data, _) = try await URLSession.shared.data(from: url) - - // Пробуем создать AVPlayer из данных - let localFile = try saveMediaToFile(data: data, fileExtension: "mp4") - let player = AVPlayer(url: localFile) - - // Асинхронно загружаем статус готовности - let asset = player.currentItem?.asset - if let asset = asset { - try await asset.load(.isPlayable) - - if asset.isPlayable { + if let videoPreviewId = sight.video_preview { + if let cachedURL = mediaCache[videoPreviewId] { + let player = AVPlayer(url: cachedURL) self.mediaState = .video(player) - self.downloadProgress = nil player.play() await player.seek(to: .zero) + return + } + + let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(videoPreviewId)/download?lang=\(selectedLanguage)")! + let (data, _) = try await URLSession.shared.data(from: url) + let localFile = try saveMediaToFile(data: data, fileExtension: "mp4") + mediaCache[videoPreviewId] = localFile + + let player = AVPlayer(url: localFile) + let asset = player.currentItem?.asset + if let asset = asset { + try await asset.load(.isPlayable) + if asset.isPlayable { + self.mediaState = .video(player) + player.play() + await player.seek(to: .zero) + } else { + self.mediaState = .error + } + } else { + self.mediaState = .error + } + + } else if let previewMediaId = sight.preview_media { + if let cachedURL = mediaCache[previewMediaId] { + self.mediaState = .image(cachedURL) + return + } + + let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(previewMediaId)/download?lang=\(selectedLanguage)")! + let (data, _) = try await URLSession.shared.data(from: url) + if let image = UIImage(data: data) { + let localFile = try saveMediaToFile(data: data, fileExtension: "jpeg") + mediaCache[previewMediaId] = localFile + self.mediaState = .image(localFile) } else { self.mediaState = .error } } else { self.mediaState = .error } - } else if let previewMediaId = sight.preview_media { - // Если нет видео-превью, пытаемся загрузить изображение - let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(previewMediaId)/download?lang=\(selectedLanguage)")! - let (data, _) = try await URLSession.shared.data(from: url) - - // Пробуем создать UIImage из данных - if let image = UIImage(data: data) { - let localFile = try saveMediaToFile(data: data, fileExtension: "jpeg") - self.mediaState = .image(localFile) - self.downloadProgress = nil - } else { - self.mediaState = .error - } + } else { - self.mediaState = .error - } + // Загрузка медиа для статьи + let mediaItems = try await fetchJSON( + from: "https://white-nights.krbl.ru/services/content/article/\(article.id)/media?lang=\(selectedLanguage)", + type: [ArticleMedia].self + ) - } else { - // Загрузка медиа для статьи - 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 mediaId = "\(firstMedia.id)" + if let cachedURL = mediaCache[mediaId] { + self.mediaState = .image(cachedURL) + return + } - if let firstMedia = mediaItems.first, - let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(firstMedia.id)/download?lang=\(selectedLanguage)") { - - let (data, _) = try await URLSession.shared.data(from: url) - - if let image = UIImage(data: data) { - let localFile = try saveMediaToFile(data: data, fileExtension: "jpeg") - self.mediaState = .image(localFile) - self.downloadProgress = nil - } else { - self.mediaState = .error + if let url = URL(string: "https://white-nights.krbl.ru/services/content/media/\(firstMedia.id)/download?lang=\(selectedLanguage)") { + let (data, _) = try await URLSession.shared.data(from: url) + if let image = UIImage(data: data) { + let localFile = try saveMediaToFile(data: data, fileExtension: "jpeg") + mediaCache[mediaId] = localFile + self.mediaState = .image(localFile) + } else { + self.mediaState = .error + } + } } } + } catch { + print("Ошибка загрузки файла: \(error)") + self.mediaState = .error + self.downloadProgress = nil } - } catch { - print("Ошибка загрузки файла: \(error)") - self.mediaState = .error - self.downloadProgress = nil } - } + private func saveMediaToFile(data: Data, fileExtension: String) throws -> URL { let destinationURL = FileManager.default.temporaryDirectory