mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 20:29:53 +00:00
ios: open chat on first unread, "scroll" to quoted items that were not loaded (#5392)
* ios: open chat on first unread, "scroll" to quoted items that were not loaded * more changes * changes * unused * fix reveal logic * debug * changes * test * Revert "test" This reverts commit553be124d5
. * change * change * changes * changes * changes * commented deceleration logic * changes * fixes * optimized item identifiers to use merged item directly * fixed counters * encreased initial and preload counters * fix initial loading and trimming items * optimize * allow marking read * 10 instead of 5 * performance * one more parameter in hash * disable trimming * performance * performance - in background * optimization * next/prev * changes * markread * finally * less logs * read * change after merge * trimming, edge cases * wait until items loaded * Revert "wait until items loaded" This reverts commit895218b978
. * progress indicator * optimization * disable scroll helper * experiment * Revert "experiment" This reverts commitc952c9e623
. * jump * no read * layoutIfNeeded * changes * EndlessScrollView * read * changes * changes * changes * reduce time to open a chat (by ~300ms) * open from the first unread when clicking member chat * refactored and removed unused code * handling search emptiness to scroll to correct position * changes * read state maintain * remove protocol * avoid parsing chatId * pass chat * changes * remove reveal * refactor spaghetti * remove ItemsScrollModel * rename * remove setUpdateListener * unused * optimization * scrollToTop * fix * scrollbar working again * scrollToBottom * fix * scrollBar hiding when not many items on screen * small safer change --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
parent
704bab171d
commit
9d1329498b
24 changed files with 2177 additions and 711 deletions
|
@ -53,7 +53,11 @@ class ItemsModel: ObservableObject {
|
|||
var itemAdded = false {
|
||||
willSet { publisher.send() }
|
||||
}
|
||||
|
||||
|
||||
// set listener here that will be notified on every add/delete of a chat item
|
||||
let chatState = ActiveChatState()
|
||||
var chatItemsChangesListener: RecalculatePositions = RecalculatePositions()
|
||||
|
||||
// Publishes directly to `objectWillChange` publisher,
|
||||
// this will cause reversedChatItems to be rendered without throttling
|
||||
@Published var isLoading = false
|
||||
|
@ -83,18 +87,16 @@ class ItemsModel: ObservableObject {
|
|||
} catch {}
|
||||
}
|
||||
Task {
|
||||
if let chat = ChatModel.shared.getChat(chatId) {
|
||||
await MainActor.run { self.isLoading = true }
|
||||
// try? await Task.sleep(nanoseconds: 5000_000000)
|
||||
await loadChat(chat: chat)
|
||||
navigationTimeout.cancel()
|
||||
progressTimeout.cancel()
|
||||
await MainActor.run {
|
||||
self.isLoading = false
|
||||
self.showLoadingProgress = false
|
||||
willNavigate()
|
||||
ChatModel.shared.chatId = chatId
|
||||
}
|
||||
await MainActor.run { self.isLoading = true }
|
||||
// try? await Task.sleep(nanoseconds: 5000_000000)
|
||||
await loadChat(chatId: chatId)
|
||||
navigationTimeout.cancel()
|
||||
progressTimeout.cancel()
|
||||
await MainActor.run {
|
||||
self.isLoading = false
|
||||
self.showLoadingProgress = false
|
||||
willNavigate()
|
||||
// ChatModel.shared.chatId = id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -546,6 +548,7 @@ final class ChatModel: ObservableObject {
|
|||
ci.meta.itemStatus = status
|
||||
}
|
||||
im.reversedChatItems.insert(ci, at: hasLiveDummy ? 1 : 0)
|
||||
im.chatItemsChangesListener.added((ci.id, ci.isRcvNew), hasLiveDummy ? 1 : 0)
|
||||
im.itemAdded = true
|
||||
ChatItemDummyModel.shared.sendUpdate()
|
||||
return true
|
||||
|
@ -591,8 +594,9 @@ final class ChatModel: ObservableObject {
|
|||
// remove from current chat
|
||||
if chatId == cInfo.id {
|
||||
if let i = getChatItemIndex(cItem) {
|
||||
_ = withAnimation {
|
||||
im.reversedChatItems.remove(at: i)
|
||||
withAnimation {
|
||||
let item = im.reversedChatItems.remove(at: i)
|
||||
im.chatItemsChangesListener.removed([(item.id, i, item.isRcvNew)], im.reversedChatItems.reversed())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -641,6 +645,7 @@ final class ChatModel: ObservableObject {
|
|||
let cItem = ChatItem.liveDummy(chatInfo.chatType)
|
||||
withAnimation {
|
||||
im.reversedChatItems.insert(cItem, at: 0)
|
||||
im.chatItemsChangesListener.added((cItem.id, cItem.isRcvNew), 0)
|
||||
im.itemAdded = true
|
||||
}
|
||||
return cItem
|
||||
|
@ -664,7 +669,6 @@ final class ChatModel: ObservableObject {
|
|||
// update preview
|
||||
_updateChat(cInfo.id) { chat in
|
||||
self.decreaseUnreadCounter(user: self.currentUser!, chat: chat)
|
||||
self.updateFloatingButtons(unreadCount: 0)
|
||||
ChatTagsModel.shared.markChatTagRead(chat)
|
||||
chat.chatStats = ChatStats()
|
||||
}
|
||||
|
@ -682,12 +686,6 @@ final class ChatModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
private func updateFloatingButtons(unreadCount: Int) {
|
||||
let fbm = ChatView.FloatingButtonModel.shared
|
||||
fbm.totalUnread = unreadCount
|
||||
fbm.objectWillChange.send()
|
||||
}
|
||||
|
||||
func markChatItemsRead(_ cInfo: ChatInfo, aboveItem: ChatItem? = nil) {
|
||||
if let cItem = aboveItem {
|
||||
if chatId == cInfo.id, let i = getChatItemIndex(cItem) {
|
||||
|
@ -716,7 +714,6 @@ final class ChatModel: ObservableObject {
|
|||
ChatTagsModel.shared.updateChatTagRead(chat, wasUnread: wasUnread)
|
||||
let by = chat.chatInfo.chatSettings?.enableNtfs == .mentions ? markedMentionsCount : markedCount
|
||||
self.decreaseUnreadCounter(user: self.currentUser!, by: by)
|
||||
self.updateFloatingButtons(unreadCount: chat.chatStats.unreadCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -746,16 +743,22 @@ final class ChatModel: ObservableObject {
|
|||
if chatId == cInfo.id {
|
||||
chatItemStatuses = [:]
|
||||
im.reversedChatItems = []
|
||||
im.chatItemsChangesListener.cleared()
|
||||
}
|
||||
}
|
||||
|
||||
func markChatItemsRead(_ cInfo: ChatInfo, _ itemIds: [ChatItem.ID], _ mentionsRead: Int) {
|
||||
if self.chatId == cInfo.id {
|
||||
var unreadItemIds: Set<ChatItem.ID> = []
|
||||
for itemId in itemIds {
|
||||
if let i = im.reversedChatItems.firstIndex(where: { $0.id == itemId }) {
|
||||
if im.reversedChatItems[i].isRcvNew {
|
||||
unreadItemIds.insert(itemId)
|
||||
}
|
||||
markChatItemRead_(i)
|
||||
}
|
||||
}
|
||||
im.chatItemsChangesListener.read(unreadItemIds, im.reversedChatItems.reversed())
|
||||
}
|
||||
self.unreadCollector.changeUnreadCounter(cInfo.id, by: -itemIds.count, unreadMentions: -mentionsRead)
|
||||
}
|
||||
|
@ -783,9 +786,6 @@ final class ChatModel: ObservableObject {
|
|||
}
|
||||
|
||||
func changeUnreadCounter(_ chatId: ChatId, by count: Int, unreadMentions: Int) {
|
||||
if chatId == ChatModel.shared.chatId {
|
||||
ChatView.FloatingButtonModel.shared.totalUnread += count
|
||||
}
|
||||
let (unread, mentions) = self.unreadCounts[chatId] ?? (0, 0)
|
||||
self.unreadCounts[chatId] = (unread + count, mentions + unreadMentions)
|
||||
subject.send()
|
||||
|
@ -979,12 +979,17 @@ final class ChatModel: ObservableObject {
|
|||
|
||||
// returns the previous member in the same merge group and the count of members in this group
|
||||
func getPrevHiddenMember(_ member: GroupMember, _ range: ClosedRange<Int>) -> (GroupMember?, Int) {
|
||||
let items = im.reversedChatItems
|
||||
var prevMember: GroupMember? = nil
|
||||
var memberIds: Set<Int64> = []
|
||||
for i in range {
|
||||
if case let .groupRcv(m) = im.reversedChatItems[i].chatDir {
|
||||
if prevMember == nil && m.groupMemberId != member.groupMemberId { prevMember = m }
|
||||
memberIds.insert(m.groupMemberId)
|
||||
if i < items.count {
|
||||
if case let .groupRcv(m) = items[i].chatDir {
|
||||
if prevMember == nil && m.groupMemberId != member.groupMemberId { prevMember = m }
|
||||
memberIds.insert(m.groupMemberId)
|
||||
}
|
||||
} else {
|
||||
logger.error("getPrevHiddenMember: index >= count of reversed items: \(i) vs \(items.count)")
|
||||
}
|
||||
}
|
||||
return (prevMember, memberIds.count)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue