mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
section poping
This commit is contained in:
@@ -13,11 +13,6 @@ import Combine
|
||||
|
||||
private let memberImageSize: CGFloat = 34
|
||||
|
||||
struct PaginationBoundary {
|
||||
var oldest: Bool
|
||||
var latest: Bool
|
||||
}
|
||||
|
||||
struct ChatView: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@ObservedObject var im = ItemsModel.shared
|
||||
@@ -37,7 +32,6 @@ struct ChatView: View {
|
||||
@State private var customUserProfile: Profile?
|
||||
@State private var connectionCode: String?
|
||||
@State private var loadingItems = false
|
||||
@State private var paginationBoundary = PaginationBoundary(oldest: false, latest: false)
|
||||
@State private var revealedChatItem: ChatItem?
|
||||
@State private var searchMode = false
|
||||
@State private var searchText: String = ""
|
||||
@@ -171,10 +165,6 @@ struct ChatView: View {
|
||||
selectedChatItems = nil
|
||||
initChatView()
|
||||
}
|
||||
.onChange(of: sectionModel.activeSection) { ac in
|
||||
paginationBoundary.oldest = false
|
||||
paginationBoundary.latest = false
|
||||
}
|
||||
.onChange(of: chatModel.chatId) { cId in
|
||||
showChatInfoSheet = false
|
||||
selectedChatItems = nil
|
||||
@@ -868,11 +858,11 @@ struct ChatView: View {
|
||||
}
|
||||
|
||||
private func boundaryReached(_ direction: ChatScrollDirection) -> Bool {
|
||||
return (direction == .toLatest && paginationBoundary.latest) || (direction == .toOldest && paginationBoundary.oldest)
|
||||
return (direction == .toLatest && sectionModel.boundaries.latest) || (direction == .toOldest && sectionModel.boundaries.oldest)
|
||||
}
|
||||
|
||||
private func setBoundary(_ direction: ChatScrollDirection) {
|
||||
direction == .toLatest ? (paginationBoundary.latest = true) : (paginationBoundary.oldest = true)
|
||||
direction == .toLatest ? (sectionModel.boundaries.latest = true) : (sectionModel.boundaries.oldest = true)
|
||||
}
|
||||
|
||||
private func loadChatItems(_ cInfo: ChatInfo, _ direction: ChatScrollDirection, _ section: ChatSection, _ chatItem: ChatItem?) {
|
||||
@@ -902,6 +892,7 @@ struct ChatView: View {
|
||||
chatItemsAvailable = !chatItems.isEmpty
|
||||
reversedPage.append(contentsOf: chatItems.reversed())
|
||||
}
|
||||
|
||||
await MainActor.run {
|
||||
if reversedPage.count == 0 {
|
||||
setBoundary(direction)
|
||||
|
||||
@@ -101,6 +101,13 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
let firstItem = self.getFirstItemInItemSection(indexPath: indexPath)
|
||||
self.representer.loadPage(.toLatest, section, firstItem)
|
||||
}
|
||||
|
||||
if (self.scrollDirection == .toOldest && indexPath.item - ReverseListSectionModel.IDEAL_SECTION_SIZE > 8) ||
|
||||
(self.scrollDirection == .toLatest && indexPath.item < ReverseListSectionModel.IDEAL_SECTION_SIZE) {
|
||||
Task {
|
||||
self.representer.sectionModel.manageActiveSection(scrollDirection: self.scrollDirection)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseId, for: indexPath)
|
||||
@@ -200,8 +207,10 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
func scroll(to index: Int?, position: UITableView.ScrollPosition, section: ChatSection, shouldTryAnimate: Bool) {
|
||||
let activeSectionBeforeScroll = representer.sectionModel.activeSection
|
||||
|
||||
Task {
|
||||
representer.sectionModel.activeSection = section
|
||||
if section != activeSectionBeforeScroll {
|
||||
Task {
|
||||
representer.sectionModel.changeActiveSection(section)
|
||||
}
|
||||
}
|
||||
var animated = false
|
||||
if #available(iOS 16.0, *) {
|
||||
@@ -410,10 +419,18 @@ class ReverseListScrollModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
struct SectionBoundaryReached {
|
||||
var oldest: Bool
|
||||
var latest: Bool
|
||||
}
|
||||
|
||||
/// Manages ``ReverseList`` sections
|
||||
class ReverseListSectionModel: ObservableObject {
|
||||
static let shared = ReverseListSectionModel()
|
||||
@Published var activeSection: ChatSection = .bottom
|
||||
static let MAX_SECTION_SIZE = 50
|
||||
static let IDEAL_SECTION_SIZE = 35
|
||||
@Published private(set) var activeSection: ChatSection = .bottom
|
||||
@Published var boundaries = SectionBoundaryReached(oldest: false, latest: false)
|
||||
@Published private var itemSection: [Int64: ChatSection] = [:]
|
||||
@Published private var sections = Set<ChatSection>()
|
||||
|
||||
@@ -421,6 +438,12 @@ class ReverseListSectionModel: ObservableObject {
|
||||
return itemSection[id]
|
||||
}
|
||||
|
||||
func changeActiveSection(_ section: ChatSection) {
|
||||
activeSection = section
|
||||
boundaries.latest = false
|
||||
boundaries.oldest = false
|
||||
}
|
||||
|
||||
func maybeDropSection(_ section: ChatSection) {
|
||||
if section == .bottom { return }
|
||||
let im = ItemsModel.shared
|
||||
@@ -429,6 +452,76 @@ class ReverseListSectionModel: ObservableObject {
|
||||
im.reversedChatItems = im.reversedChatItems.filter { it in itemSection[it.id] != section }
|
||||
}
|
||||
|
||||
private func activeSectionItemsCount() -> Int {
|
||||
// TODO: check
|
||||
return itemSection.values.filter { $0 == self.activeSection }.count
|
||||
}
|
||||
|
||||
private func trimSection(scrollDirection: ChatScrollDirection, section: ChatSection) {
|
||||
let im = ItemsModel.shared
|
||||
var i = scrollDirection == .toLatest ? 0 : im.reversedChatItems.count - 1
|
||||
let moveToNextIndex: () -> Bool = {
|
||||
if scrollDirection == .toLatest {
|
||||
if i < im.reversedChatItems.count - 1 {
|
||||
i += 1
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if i > 0 {
|
||||
i -= 1
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
var sectionCount = 0
|
||||
var completed = false
|
||||
var toRemoveIndexes = IndexSet()
|
||||
|
||||
while (!completed) {
|
||||
let it = im.reversedChatItems[i]
|
||||
if itemSection[it.id] == section {
|
||||
if sectionCount >= ReverseListSectionModel.IDEAL_SECTION_SIZE {
|
||||
toRemoveIndexes.insert(i)
|
||||
itemSection.removeValue(forKey: it.id)
|
||||
} else {
|
||||
sectionCount += 1
|
||||
}
|
||||
}
|
||||
completed = moveToNextIndex()
|
||||
}
|
||||
|
||||
if (!toRemoveIndexes.isEmpty) {
|
||||
im.reversedChatItems.remove(atOffsets: toRemoveIndexes)
|
||||
}
|
||||
}
|
||||
|
||||
func manageActiveSection(scrollDirection: ChatScrollDirection) {
|
||||
let activeSectionCount = activeSectionItemsCount()
|
||||
|
||||
switch self.activeSection {
|
||||
case .bottom:
|
||||
if scrollDirection == .toLatest, activeSectionCount > ReverseListSectionModel.MAX_SECTION_SIZE {
|
||||
// boundaries?, the visible item needs to not be there
|
||||
boundaries.oldest = false
|
||||
self.trimSection(scrollDirection: scrollDirection, section: self.activeSection)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if activeSectionCount > ReverseListSectionModel.MAX_SECTION_SIZE {
|
||||
if scrollDirection == .toLatest {
|
||||
boundaries.oldest = false
|
||||
} else {
|
||||
boundaries.latest = false
|
||||
}
|
||||
self.trimSection(scrollDirection: scrollDirection, section: self.activeSection)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getSectionsOrdered() -> [ChatSection] {
|
||||
var orderedSections: [ChatSection] = [.bottom]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user