Compare commits

...

1 Commits

Author SHA1 Message Date
cheykrym
6d5b32602b aboba 2025-08-14 02:09:38 +03:00
5 changed files with 142 additions and 37 deletions

View File

@ -132,9 +132,16 @@ class PostService {
}
}
func fetchAllPosts(completion: @escaping ([Post]) -> Void) {
func fetchAllPosts(page: Int, limit: Int, completion: @escaping ([Post]) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
completion(self.posts)
let start = page * limit
let end = min(start + limit, self.posts.count)
if start < end {
completion(Array(self.posts[start..<end]))
} else {
completion([])
}
}
}

View File

@ -5,26 +5,70 @@ class NewHomeTabViewModel: ObservableObject {
@Published var posts: [Post] = []
@Published var isLoading = true
@Published var isRefreshing = false
@Published var isLoadingPage = false
@Published var canLoadMorePages = true
private var currentPage = 0
private let postsPerPage = 10
private var hasLoadedData = false
func fetchDataIfNeeded() {
guard !hasLoadedData else { return }
refreshData()
guard posts.isEmpty else { return }
fetchPosts()
}
func refreshData() {
DispatchQueue.main.async {
self.isRefreshing = true
guard !isRefreshing else { return }
isRefreshing = true
currentPage = 0
canLoadMorePages = true
fetchPosts(isRefresh: true)
}
func loadMoreContentIfNeeded(currentItem item: Post?) {
guard let item = item else {
fetchPosts()
return
}
PostService.shared.fetchAllPosts { [weak self] fetchedPosts in
let thresholdIndex = posts.index(posts.endIndex, offsetBy: -5)
if posts.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
fetchPosts()
}
}
private func fetchPosts(isRefresh: Bool = false) {
guard !isLoadingPage, canLoadMorePages else {
if isRefresh {
DispatchQueue.main.async {
self.isRefreshing = false
}
}
return
}
isLoadingPage = true
if isRefresh {
currentPage = 0
} else {
currentPage += 1
}
PostService.shared.fetchAllPosts(page: currentPage, limit: postsPerPage) { [weak self] fetchedPosts in
guard let self = self else { return }
DispatchQueue.main.async {
self.posts = fetchedPosts
if isRefresh {
self.posts = fetchedPosts
} else {
self.posts.append(contentsOf: fetchedPosts)
}
self.canLoadMorePages = !fetchedPosts.isEmpty
self.isLoading = false
self.hasLoadedData = true
self.isLoadingPage = false
self.isRefreshing = false
}
}

View File

@ -32,6 +32,25 @@ struct HomeTab: View {
}
}
// private func fetchData(isInitialLoad: Bool = false) {
// if isInitialLoad {
// isLoading = true
// } else {
// isRefreshing = true
// }
//
// PostService.shared.fetchAllPosts { fetchedPosts in
// self.posts = fetchedPosts
//
// if isInitialLoad {
// print("content updated")
// self.isLoading = false
// }
// self.isRefreshing = false
// }
// }
private func fetchData(isInitialLoad: Bool = false) {
if isInitialLoad {
isLoading = true
@ -39,14 +58,13 @@ struct HomeTab: View {
isRefreshing = true
}
PostService.shared.fetchAllPosts { fetchedPosts in
self.posts = fetchedPosts
if isInitialLoad {
print("content updated")
self.isLoading = false
}
self.isRefreshing = false
// Временный код вместо PostService
self.posts = [] // или сюда можно подставить мок-данные
// Сбрасываем индикаторы загрузки
if isInitialLoad {
self.isLoading = false
}
self.isRefreshing = false
}
}

View File

@ -19,19 +19,37 @@ struct NewHomeTab: View {
RefreshableScrollView(isRefreshing: $viewModel.isRefreshing, onRefresh: {
viewModel.refreshData()
}) {
HStack(alignment: .top, spacing: 6) {
LazyVStack(spacing: 6) {
ForEach(column1Posts) { post in
PostGridItem(post: post)
VStack {
HStack(alignment: .top, spacing: 6) {
LazyVStack(spacing: 6) {
ForEach(column1Posts) { post in
PostGridItem(post: post)
.onAppear {
viewModel.loadMoreContentIfNeeded(currentItem: post)
}
}
}
LazyVStack(spacing: 6) {
ForEach(column2Posts) { post in
PostGridItem(post: post)
.onAppear {
viewModel.loadMoreContentIfNeeded(currentItem: post)
}
}
}
}
LazyVStack(spacing: 6) {
ForEach(column2Posts) { post in
PostGridItem(post: post)
}
.padding(.horizontal, 4)
if viewModel.isLoadingPage {
ProgressView()
} else if !viewModel.canLoadMorePages {
Text(":(")
.foregroundColor(.secondary)
.padding()
}
Spacer()
}
.padding(.horizontal, 4)
}
}
}

View File

@ -67,6 +67,7 @@ struct ProfileTab: View {
self.selectedPostData = (post, posts)
}
)
Spacer()
}
}
}
@ -79,6 +80,23 @@ struct ProfileTab: View {
}
}
// 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
// }
// }
private func fetchData(isInitialLoad: Bool = false) {
if isInitialLoad {
isLoading = true
@ -86,16 +104,16 @@ struct ProfileTab: View {
isRefreshing = true
}
PostService.shared.fetchAllPosts { fetchedPosts in
self.allPosts = fetchedPosts
if isInitialLoad {
self.isLoading = false
}
self.isRefreshing = false
}
}
// Временный код вместо PostService
self.allPosts = [] // или сюда можно подставить мок-данные
// Сбрасываем индикаторы загрузки
if isInitialLoad {
self.isLoading = false
}
self.isRefreshing = false
}
// MARK: - Шапка профиля
private var header: some View {
VStack(spacing: 12) {