refresh profile
This commit is contained in:
parent
8fd955d3cb
commit
a716b296d5
@ -3,10 +3,10 @@ import UIKit
|
||||
|
||||
struct RefreshableScrollView<Content: View>: UIViewRepresentable {
|
||||
var content: Content
|
||||
var onRefresh: (UIRefreshControl) -> Void
|
||||
var onRefresh: () -> Void
|
||||
var isRefreshing: Binding<Bool>
|
||||
|
||||
init(isRefreshing: Binding<Bool>, onRefresh: @escaping (UIRefreshControl) -> Void, @ViewBuilder content: () -> Content) {
|
||||
init(isRefreshing: Binding<Bool>, onRefresh: @escaping () -> Void, @ViewBuilder content: () -> Content) {
|
||||
self.content = content()
|
||||
self.onRefresh = onRefresh
|
||||
self.isRefreshing = isRefreshing
|
||||
@ -15,17 +15,14 @@ struct RefreshableScrollView<Content: View>: UIViewRepresentable {
|
||||
func makeUIView(context: Context) -> UIScrollView {
|
||||
let scrollView = UIScrollView()
|
||||
|
||||
// Создаем UIRefreshControl и добавляем его
|
||||
let refreshControl = UIRefreshControl()
|
||||
refreshControl.addTarget(context.coordinator, action: #selector(Coordinator.handleRefresh), for: .valueChanged)
|
||||
scrollView.refreshControl = refreshControl
|
||||
|
||||
// Создаем хостинг для нашего SwiftUI контента
|
||||
let hostingController = UIHostingController(rootView: content)
|
||||
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
scrollView.addSubview(hostingController.view)
|
||||
|
||||
// Настраиваем Auto Layout
|
||||
NSLayoutConstraint.activate([
|
||||
hostingController.view.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
|
||||
hostingController.view.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
|
||||
@ -40,14 +37,15 @@ struct RefreshableScrollView<Content: View>: UIViewRepresentable {
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIScrollView, context: Context) {
|
||||
// Обновляем состояние индикатора
|
||||
if isRefreshing.wrappedValue {
|
||||
uiView.refreshControl?.beginRefreshing()
|
||||
} else {
|
||||
// Отложенное завершение, чтобы избежать цикла обновлений
|
||||
DispatchQueue.main.async {
|
||||
uiView.refreshControl?.endRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
// Обновляем SwiftUI View, если нужно
|
||||
context.coordinator.hostingController?.rootView = content
|
||||
}
|
||||
|
||||
@ -63,9 +61,8 @@ struct RefreshableScrollView<Content: View>: UIViewRepresentable {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
@objc func handleRefresh(_ sender: UIRefreshControl) {
|
||||
parent.isRefreshing.wrappedValue = true
|
||||
parent.onRefresh(sender)
|
||||
@objc func handleRefresh() {
|
||||
parent.onRefresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ struct HomeTab: View {
|
||||
if isLoading {
|
||||
ProgressView("Загрузка ленты...")
|
||||
} else {
|
||||
RefreshableScrollView(isRefreshing: $isRefreshing, onRefresh: { _ in
|
||||
RefreshableScrollView(isRefreshing: $isRefreshing, onRefresh: {
|
||||
fetchData()
|
||||
}) {
|
||||
LazyVStack(spacing: 24) {
|
||||
|
||||
@ -2,12 +2,12 @@ import SwiftUI
|
||||
|
||||
struct ProfileContentTabbedGrid: View {
|
||||
let isContentLoaded: Bool
|
||||
@Binding var allPosts: [Post]
|
||||
@Binding var isLoading: Bool
|
||||
@State private var selectedTabIndex = 0
|
||||
@State private var selectedCategory = "#все"
|
||||
@State private var searchQuery = ""
|
||||
@State private var selectedSort = "По дате"
|
||||
@State private var allPosts: [Post] = []
|
||||
@State private var isLoading = true
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
@ -73,15 +73,6 @@ struct ProfileContentTabbedGrid: View {
|
||||
isLoading: isLoading
|
||||
)
|
||||
}
|
||||
.onAppear {
|
||||
if allPosts.isEmpty {
|
||||
isLoading = true
|
||||
PostService.shared.fetchAllPosts { result in
|
||||
self.allPosts = result
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Вкладка с меню
|
||||
|
||||
@ -2,13 +2,6 @@ import SwiftUI
|
||||
|
||||
struct ProfileTab: View {
|
||||
@ObservedObject var viewModel: LoginViewModel
|
||||
// @State private var selectedTabIndex = 0
|
||||
// @State private var selectedSort = "По дате"
|
||||
// @State private var selectedCategory = "#все"
|
||||
// @State private var searchQuery = ""
|
||||
// @State private var searchQueryArchive = ""
|
||||
// @State private var searchQuerySaved = ""
|
||||
// @State private var searchQueryLiked = ""
|
||||
@State private var isContentLoaded = true
|
||||
|
||||
@State private var accounts = ["@user1", "@user2", "@user3"]
|
||||
@ -20,43 +13,38 @@ struct ProfileTab: View {
|
||||
@State private var sheetType: SheetType? = nil
|
||||
enum SheetType: Identifiable {
|
||||
case accountShare
|
||||
var id: Int { self.hashValue }
|
||||
}
|
||||
|
||||
var id: Int {
|
||||
switch self {
|
||||
case .accountShare: return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@State private var allPosts: [Post] = []
|
||||
@State private var isLoading = true
|
||||
@State private var isRefreshing = false
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
if !isContentLoaded{
|
||||
if !isContentLoaded {
|
||||
SplashScreenView()
|
||||
} else {
|
||||
GeometryReader { geometry in
|
||||
RefreshableScrollView(isRefreshing: $isRefreshing, onRefresh: {
|
||||
fetchData()
|
||||
}) {
|
||||
VStack(spacing: 0) {
|
||||
ScrollView {
|
||||
// ───── Шапка профиля (занимает ~50% экрана) ─────
|
||||
header
|
||||
.frame(minHeight: geometry.size.height * 0.5)
|
||||
.frame(minHeight: 300)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color(.systemBackground))
|
||||
|
||||
// ───── Скролл с контентом ─────
|
||||
|
||||
ProfileContentTabbedGrid(isContentLoaded: isContentLoaded)
|
||||
|
||||
ProfileContentTabbedGrid(
|
||||
isContentLoaded: isContentLoaded,
|
||||
allPosts: $allPosts,
|
||||
isLoading: $isLoading
|
||||
)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .principal) {
|
||||
Button(action: {
|
||||
sheetType = .accountShare
|
||||
}) {
|
||||
Button(action: { sheetType = .accountShare }) {
|
||||
HStack(spacing: 4) {
|
||||
Text("custom_user_name")
|
||||
.font(.headline)
|
||||
@ -67,7 +55,6 @@ struct ProfileTab: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
NavigationLink(destination: SettingsView(viewModel: viewModel)) {
|
||||
Image(systemName: "wrench")
|
||||
@ -91,13 +78,28 @@ struct ProfileTab: View {
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
// .onAppear {
|
||||
// if !isContentLoaded {
|
||||
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
// isContentLoaded = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
.onAppear {
|
||||
if allPosts.isEmpty {
|
||||
fetchData(isInitialLoad: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchData(isInitialLoad: Bool = false) {
|
||||
if isInitialLoad {
|
||||
isLoading = true
|
||||
} else {
|
||||
isRefreshing = true
|
||||
}
|
||||
|
||||
PostService.shared.fetchAllPosts { fetchedPosts in
|
||||
self.allPosts = fetchedPosts
|
||||
|
||||
if isInitialLoad {
|
||||
self.isLoading = false
|
||||
}
|
||||
self.isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Шапка профиля
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user