Compare commits

...

13 Commits

Author SHA1 Message Date
Evgeny Poberezkin ba0e61b422 reduce to 2 seconds 2024-08-02 12:39:02 +01:00
Evgeny Poberezkin 65055e2582 fix, simplify 2024-08-02 12:35:29 +01:00
Evgeny Poberezkin 308ceaf5cd restore special case for the current chat 2024-08-01 23:13:12 +01:00
Evgeny Poberezkin 178634d581 diff 2024-08-01 22:00:47 +01:00
Evgeny Poberezkin 2f4da10dc1 remove file 2024-08-01 21:56:09 +01:00
Evgeny Poberezkin 6d66593688 better updateChats 2024-08-01 21:53:29 +01:00
Evgeny Poberezkin d5689a922b optimize 2024-08-01 21:38:37 +01:00
Evgeny Poberezkin 892b8b988e fix 2024-08-01 21:11:47 +01:00
Evgeny Poberezkin 25d39877f4 move chats every 3 seconds 2024-08-01 21:10:06 +01:00
Evgeny Poberezkin 4dbefcce32 dont pop the first chat 2024-08-01 21:04:21 +01:00
Evgeny Poberezkin 31ebfb03fa throttle, update unread 2024-08-01 20:58:19 +01:00
Levitating Pineapple cf6e608384 cleanup 2024-08-01 18:59:00 +03:00
Levitating Pineapple e9797da238 ios: add throttling for incoming messages 2024-08-01 18:41:07 +03:00
2 changed files with 61 additions and 16 deletions
+59 -14
View File
@@ -337,12 +337,10 @@ final class ChatModel: ObservableObject {
increaseUnreadCounter(user: currentUser!)
}
if i > 0 {
if chatId == nil {
withAnimation { popChat_(i) }
} else if chatId == cInfo.id {
if chatId == cInfo.id {
chatToTop = cInfo.id
} else {
popChat_(i)
popChatCollector.addChat(cInfo.id)
}
}
} else {
@@ -579,7 +577,7 @@ final class ChatModel: ObservableObject {
// update current chat
markChatItemRead_(itemIndex)
// update preview
unreadCollector.decreaseUnreadCounter(chatIndex)
unreadCollector.decreaseUnreadCounter(cInfo.id)
}
}
}
@@ -588,29 +586,76 @@ final class ChatModel: ObservableObject {
private let unreadCollector = UnreadCollector()
class UnreadCollector {
private let subject = PassthroughSubject<Int, Never>()
private let subject = PassthroughSubject<Void, Never>()
private var bag = Set<AnyCancellable>()
private var dictionary = Dictionary<Int, Int>()
private var unreadCounts: [ChatId: Int] = [:]
init() {
subject
.debounce(for: 1, scheduler: DispatchQueue.main)
.sink { _ in
self.dictionary.forEach { key, value in
ChatModel.shared.decreaseUnreadCounter(key, by: value)
.sink {
let m = ChatModel.shared
for (chatId, count) in self.unreadCounts {
if let i = m.getChatIndex(chatId) {
m.decreaseUnreadCounter(i, by: count)
}
}
self.dictionary = Dictionary<Int, Int>()
self.unreadCounts = [:]
}
.store(in: &bag)
}
// Only call from main thread
func decreaseUnreadCounter(_ chatIndex: Int) {
dictionary[chatIndex] = (dictionary[chatIndex] ?? 0) + 1
subject.send(chatIndex)
func decreaseUnreadCounter(_ chatId: ChatId) {
unreadCounts[chatId] = (unreadCounts[chatId] ?? 0) + 1
subject.send()
}
}
let popChatCollector = PopChatCollector()
class PopChatCollector {
private let subject = PassthroughSubject<Void, Never>()
private var bag = Set<AnyCancellable>()
private var chatsToPop: [ChatId: Date] = [:]
init() {
subject
.throttle(for: 2, scheduler: DispatchQueue.main, latest: true)
.sink { self.popRecentChats() }
.store(in: &bag)
}
// Only call from main thread
func addChat(_ chatId: ChatId) {
chatsToPop[chatId] = Date.now
subject.send()
}
func popRecentChats() {
let m = ChatModel.shared
var ixs: IndexSet = []
var chs: [(Chat, Date)] = []
// collect chats that received updates
for (chatId, ts) in chatsToPop {
if m.chatId != chatId, let i = m.getChatIndex(chatId) {
ixs.insert(i)
chs.append((m.chats[i], ts))
}
}
// sort chats by timestamp in descending order
chs.sort { ch1, ch2 in ch1.1 > ch2.1 }
withAnimation {
m.chats.remove(atOffsets: ixs)
m.chats.insert(contentsOf: chs.map { $0.0 }, at: 0)
}
chatsToPop = [:]
}
}
private func markChatItemRead_(_ i: Int) {
let meta = im.reversedChatItems[i].meta
if case .rcvNew = meta.itemStatus {
@@ -158,8 +158,8 @@ struct ChatListView: View {
.offset(x: -8)
}
}
.onChange(of: chatModel.chatId) { _ in
if chatModel.chatId == nil, let chatId = chatModel.chatToTop {
.onChange(of: chatModel.chatId) { chId in
if chId == nil, let chatId = chatModel.chatToTop {
chatModel.chatToTop = nil
chatModel.popChat(chatId)
}