import SwiftUI import AVKit import NukeUI import UIKit // MARK: - SightView struct SightView: View { let sightId: Int @StateObject private var viewModel = SightViewModel() var body: some View { VStack(alignment: .leading, spacing: 4) { mediaSection VStack(alignment: .leading, spacing: 8) { // Заголовок статьи Text(viewModel.selectedArticle?.isReviewArticle == true ? viewModel.sightName : viewModel.articleHeading) .font(.title2) .fontWeight(.bold) .foregroundColor(.white) .frame(maxWidth: .infinity, alignment: viewModel.selectedArticle?.isReviewArticle == true ? .center : .leading) // Тело статьи ScrollView { if viewModel.selectedArticle?.isReviewArticle == true { VStack { Text(viewModel.articleBody) .font(.system(size: 13)) .foregroundColor(.white) .frame(maxWidth: .infinity, maxHeight: .infinity) } } else { Text(viewModel.articleBody) .font(.system(size: 13)) .foregroundColor(.white) .frame(maxWidth: .infinity, alignment: .leading) } } // Список статей (кнопки навигации) - ФИНАЛЬНОЕ ИСПРАВЛЕНИЕ ЦЕНТРИРОВАНИЯ GeometryReader { geometry in ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 6) { // Spacers для центрирования Spacer(minLength: 0) ForEach(viewModel.allArticles) { article in Text(article.heading) .font(.system(size: 12)) .lineLimit(1) .padding(.vertical, 6) .padding(.horizontal, 6) .frame(minWidth: 70) .foregroundColor(.white) .overlay( Rectangle() .frame(height: 2) .foregroundColor(viewModel.selectedArticle == article ? Color.white : Color.clear), alignment: .bottom ) .onTapGesture { viewModel.selectArticle(article) } } Spacer(minLength: 0) } // Принудительно задаем ширину HStack как ширину GeometryReader .frame(minWidth: geometry.size.width) } .scrollIndicators(.hidden) // Скрываем полосу прокрутки } // Задаем высоту для GeometryReader .frame(height: 34) .frame(maxWidth: .infinity) } .padding(.horizontal, 8) .padding(.bottom, 10) } .task(id: sightId) { await viewModel.loadInitialData(sightId: sightId) } .blockStyle(cornerRadius: 25) } // Медиа-секция @ViewBuilder private var mediaSection: some View { Group { switch viewModel.mediaState { case .loading: ZStack { Color.gray.opacity(0.3) ProgressView() .progressViewStyle(.circular) .tint(.white) } .frame(maxWidth: .infinity) .aspectRatio(16/9, contentMode: .fit) .cornerRadius(24, corners: [.topLeft, .topRight]) .clipped() case .image(let url): LazyImage(url: url) { state in if let image = state.image { image .resizable() .scaledToFit() } else { ProgressView() } } .cornerRadius(24, corners: [.topLeft, .topRight]) .clipped() case .video(let player): VideoPlayer(player: player) .aspectRatio(16/9, contentMode: .fit) .cornerRadius(24, corners: [.topLeft, .topRight]) .clipped() case .error: Image(systemName: "photo") .resizable() .aspectRatio(contentMode: .fit) .foregroundColor(.gray) .frame(maxWidth: .infinity, minHeight: 200) .cornerRadius(24, corners: [.topLeft, .topRight]) .clipped() } } .padding(4) .frame(maxWidth: .infinity) } }