Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d5b32602b |
@ -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) {
|
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([])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,26 +5,70 @@ class NewHomeTabViewModel: ObservableObject {
|
|||||||
@Published var posts: [Post] = []
|
@Published var posts: [Post] = []
|
||||||
@Published var isLoading = true
|
@Published var isLoading = true
|
||||||
@Published var isRefreshing = false
|
@Published var isRefreshing = false
|
||||||
|
@Published var isLoadingPage = false
|
||||||
|
|
||||||
private var hasLoadedData = false
|
@Published var canLoadMorePages = true
|
||||||
|
|
||||||
|
private var currentPage = 0
|
||||||
|
private let postsPerPage = 10
|
||||||
|
|
||||||
func fetchDataIfNeeded() {
|
func fetchDataIfNeeded() {
|
||||||
guard !hasLoadedData else { return }
|
guard posts.isEmpty else { return }
|
||||||
refreshData()
|
fetchPosts()
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshData() {
|
func refreshData() {
|
||||||
DispatchQueue.main.async {
|
guard !isRefreshing else { return }
|
||||||
self.isRefreshing = true
|
|
||||||
|
isRefreshing = true
|
||||||
|
currentPage = 0
|
||||||
|
canLoadMorePages = true
|
||||||
|
|
||||||
|
fetchPosts(isRefresh: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
PostService.shared.fetchAllPosts { [weak self] fetchedPosts in
|
func loadMoreContentIfNeeded(currentItem item: Post?) {
|
||||||
|
guard let item = item else {
|
||||||
|
fetchPosts()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }
|
guard let self = self else { return }
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
if isRefresh {
|
||||||
self.posts = fetchedPosts
|
self.posts = fetchedPosts
|
||||||
|
} else {
|
||||||
|
self.posts.append(contentsOf: fetchedPosts)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.canLoadMorePages = !fetchedPosts.isEmpty
|
||||||
self.isLoading = false
|
self.isLoading = false
|
||||||
self.hasLoadedData = true
|
self.isLoadingPage = false
|
||||||
self.isRefreshing = false
|
self.isRefreshing = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
private func fetchData(isInitialLoad: Bool = false) {
|
||||||
if isInitialLoad {
|
if isInitialLoad {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
@ -39,14 +58,13 @@ struct HomeTab: View {
|
|||||||
isRefreshing = true
|
isRefreshing = true
|
||||||
}
|
}
|
||||||
|
|
||||||
PostService.shared.fetchAllPosts { fetchedPosts in
|
// Временный код вместо PostService
|
||||||
self.posts = fetchedPosts
|
self.posts = [] // или сюда можно подставить мок-данные
|
||||||
|
|
||||||
|
// Сбрасываем индикаторы загрузки
|
||||||
if isInitialLoad {
|
if isInitialLoad {
|
||||||
print("content updated")
|
|
||||||
self.isLoading = false
|
self.isLoading = false
|
||||||
}
|
}
|
||||||
self.isRefreshing = false
|
self.isRefreshing = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -19,19 +19,37 @@ struct NewHomeTab: View {
|
|||||||
RefreshableScrollView(isRefreshing: $viewModel.isRefreshing, onRefresh: {
|
RefreshableScrollView(isRefreshing: $viewModel.isRefreshing, onRefresh: {
|
||||||
viewModel.refreshData()
|
viewModel.refreshData()
|
||||||
}) {
|
}) {
|
||||||
|
VStack {
|
||||||
HStack(alignment: .top, spacing: 6) {
|
HStack(alignment: .top, spacing: 6) {
|
||||||
LazyVStack(spacing: 6) {
|
LazyVStack(spacing: 6) {
|
||||||
ForEach(column1Posts) { post in
|
ForEach(column1Posts) { post in
|
||||||
PostGridItem(post: post)
|
PostGridItem(post: post)
|
||||||
|
.onAppear {
|
||||||
|
viewModel.loadMoreContentIfNeeded(currentItem: post)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LazyVStack(spacing: 6) {
|
LazyVStack(spacing: 6) {
|
||||||
ForEach(column2Posts) { post in
|
ForEach(column2Posts) { post in
|
||||||
PostGridItem(post: post)
|
PostGridItem(post: post)
|
||||||
|
.onAppear {
|
||||||
|
viewModel.loadMoreContentIfNeeded(currentItem: post)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 4)
|
.padding(.horizontal, 4)
|
||||||
|
|
||||||
|
if viewModel.isLoadingPage {
|
||||||
|
ProgressView()
|
||||||
|
} else if !viewModel.canLoadMorePages {
|
||||||
|
Text(":(")
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,6 +67,7 @@ struct ProfileTab: View {
|
|||||||
self.selectedPostData = (post, posts)
|
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) {
|
private func fetchData(isInitialLoad: Bool = false) {
|
||||||
if isInitialLoad {
|
if isInitialLoad {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
@ -86,15 +104,15 @@ struct ProfileTab: View {
|
|||||||
isRefreshing = true
|
isRefreshing = true
|
||||||
}
|
}
|
||||||
|
|
||||||
PostService.shared.fetchAllPosts { fetchedPosts in
|
// Временный код вместо PostService
|
||||||
self.allPosts = fetchedPosts
|
self.allPosts = [] // или сюда можно подставить мок-данные
|
||||||
|
|
||||||
|
// Сбрасываем индикаторы загрузки
|
||||||
if isInitialLoad {
|
if isInitialLoad {
|
||||||
self.isLoading = false
|
self.isLoading = false
|
||||||
}
|
}
|
||||||
self.isRefreshing = false
|
self.isRefreshing = false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Шапка профиля
|
// MARK: - Шапка профиля
|
||||||
private var header: some View {
|
private var header: some View {
|
||||||
|
|||||||
Reference in New Issue
Block a user