ios_app/Shared/Views/Tab/NewHomeTab.swift
2025-08-14 20:21:26 +03:00

140 lines
6.3 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
struct NewHomeTab: View {
@ObservedObject var viewModel: NewHomeTabViewModel
// Ширина колонки теперь вычисляется в ViewModel, но нам она нужна и здесь для PostGridItem
private let columnWidth = (UIScreen.main.bounds.width - 14) / 2
var body: some View {
VStack {
if viewModel.isLoading {
ProgressView("Загрузка ленты...")
} else {
RefreshableScrollView(isRefreshing: $viewModel.isRefreshing, onRefresh: {
viewModel.refreshData()
}) {
HStack(alignment: .top, spacing: 6) {
LazyVStack(spacing: 6) {
ForEach(viewModel.column1Posts) { post in
PostGridItem(post: post, width: columnWidth)
}
}
LazyVStack(spacing: 6) {
ForEach(viewModel.column2Posts) { post in
PostGridItem(post: post, width: columnWidth)
}
}
}
.padding(.horizontal, 4)
}
}
}
.onAppear {
viewModel.fetchDataIfNeeded()
}
// .background(Color(.secondarySystemBackground)) // Фон для всей вкладки
}
}
struct PostGridItem: View {
let post: Post
let width: CGFloat // Ширина элемента
// Формируем URL для загрузки изображения
private var imageURL: URL? {
// Используем picsum.photos для получения уникального изображения для каждого поста
// Используем реальные размеры для большей вариативности
if let media = post.media.first, let w = media.width, let h = media.height {
return URL(string: "https://picsum.photos/seed/\(post.id.uuidString)/\(w)/\(h)")
}
return URL(string: "https://picsum.photos/seed/\(post.id.uuidString)/400/400")
}
// Вычисляем высоту изображения на основе данных из модели
private var imageHeight: CGFloat {
guard let media = post.media.first,
let mediaWidth = media.width,
let mediaHeight = media.height,
mediaWidth > 0 else {
return width // Возвращаем 1:1, если данных нет
}
let aspectRatio = CGFloat(mediaHeight) / CGFloat(mediaWidth)
return width * aspectRatio
}
var body: some View {
NavigationLink(destination: PostDetailView(post: post)) {
VStack(alignment: .leading, spacing: 0) { // Убираем отступ между картинкой и текстом
// 1. Медиа контент
if let url = imageURL {
// Создаем контейнер с четкими границами, чтобы избежать перекрытия
Color.clear
.frame(width: width, height: imageHeight) // Используем вычисленную высоту
.background(
RemoteImageView(url: url)
.scaledToFill()
)
.clipped()
}
// Контейнер для текста, который создает эффект "расширения"
VStack(alignment: .leading, spacing: 8) {
// 2. Название поста
if let title = post.title, !title.isEmpty {
Text(title)
.font(.subheadline)
.lineLimit(2)
}
// 3. Информация об авторе и лайки
HStack {
Button(action: {
print("account \(post.id)")
// пока ничего не делаем
}) {
HStack(spacing: 4) {
Image(systemName: "person.circle.fill")
.resizable()
.frame(width: 20, height: 20)
.foregroundColor(.gray)
Text(post.authorUsername)
.font(.footnote)
.lineLimit(1)
.foregroundColor(.primary)
}
}
.contentShape(Rectangle())
Spacer()
Button(action: {
print("like \(post.id)")
// пока ничего не делаем
}) {
HStack(spacing: 4) {
Image(systemName: post.isLikedByCurrentUser ? "heart.fill" : "heart")
.foregroundColor(post.isLikedByCurrentUser ? .red : .primary)
Text("\(post.likes)")
.font(.subheadline)
.foregroundColor(.primary)
}
}
.contentShape(Rectangle())
}
}
.padding(8)
.background(Color(UIColor.systemBackground)) // Фон только для текстовой части
}
.cornerRadius(6) // Закругляем всю карточку
.clipped() // Обрезаем дочерние вью по закругленной форме родителя
.shadow(color: Color.black.opacity(0.1), radius: 5, x: 0, y: 2)
}
.buttonStyle(PlainButtonStyle()) // Убираем стандартный стиль кнопки, чтобы не влиять на UI
}
}