Files
WhiteNights_iOS/WhiteNights/Widgets/SightView.swift
2025-08-24 14:44:50 +03:00

138 lines
5.5 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 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)
}
}