0011 0012 patch fixes
This commit is contained in:
1 parent
65605ded95
commit
57eaf56023
3 files changed
+128
-16
No files matched your search
@@ -96,6 +96,7 @@ final class AppModel: ObservableObject {
|
||||
private var lastSuccessfulMAMSync: Date?
|
||||
private var lastSuccessfulMAMCursor: String?
|
||||
private var mamCheckpoints: [MAMArchiveKey: MAMArchiveCheckpoint] = [:]
|
||||
private var hasMoreOlderHistoryByConversation: [String: Bool] = [:]
|
||||
private var pendingRoomPasswords: [String: String] = [:]
|
||||
private var joiningRoomJIDs: Set<String> = []
|
||||
private var mediaSendActivity = MediaSendActivityTracker()
|
||||
@@ -510,22 +511,31 @@ final class AppModel: ObservableObject {
|
||||
// }
|
||||
// schedulePersist()
|
||||
// syncWatch()
|
||||
hasMoreOlderHistory = true
|
||||
// hasMoreOlderHistory = true
|
||||
hasMoreOlderHistory = hasMoreOlderHistoryByConversation[normalized] ?? true
|
||||
}
|
||||
|
||||
func loadOlderHistoryForSelectedConversation() {
|
||||
guard !isLoadingOlderHistory,
|
||||
hasMoreOlderHistory,
|
||||
let conversation = selectedConversation else { return }
|
||||
// let oldestServerID = selectedMessages
|
||||
// .sorted { lhs, rhs in
|
||||
// if lhs.timestamp != rhs.timestamp { return lhs.timestamp < rhs.timestamp }
|
||||
// return lhs.id < rhs.id
|
||||
// }
|
||||
// .compactMap(\.stanzaID)
|
||||
// .first
|
||||
let oldestServerID = selectedMessages
|
||||
.sorted { lhs, rhs in
|
||||
.filter { $0.stanzaID != nil }
|
||||
.min { lhs, rhs in
|
||||
if lhs.timestamp != rhs.timestamp { return lhs.timestamp < rhs.timestamp }
|
||||
return lhs.id < rhs.id
|
||||
}
|
||||
.compactMap(\.stanzaID)
|
||||
.first
|
||||
}?
|
||||
.stanzaID
|
||||
|
||||
isLoadingOlderHistory = true
|
||||
let conversationID = conversation.id.lowercased()
|
||||
xmpp.loadOlderHistory(
|
||||
conversationJID: conversation.jid,
|
||||
isGroup: conversation.isGroup,
|
||||
@@ -535,7 +545,11 @@ final class AppModel: ObservableObject {
|
||||
self.isLoadingOlderHistory = false
|
||||
switch result {
|
||||
case .success(let hasMore):
|
||||
self.hasMoreOlderHistory = hasMore
|
||||
// self.hasMoreOlderHistory = hasMore
|
||||
self.hasMoreOlderHistoryByConversation[conversationID] = hasMore
|
||||
if self.selectedConversationID == conversationID {
|
||||
self.hasMoreOlderHistory = hasMore
|
||||
}
|
||||
case .failure(let error):
|
||||
self.errorMessage = error.localizedDescription
|
||||
}
|
||||
@@ -1926,6 +1940,9 @@ final class AppModel: ObservableObject {
|
||||
}
|
||||
|
||||
private func consumeMessage(_ envelope: XMPPService.MessageEnvelope) {
|
||||
if !envelope.isGroupMessage {
|
||||
upsertConversation(jid: envelope.peerJID, name: nil)
|
||||
}
|
||||
if let stanzaID = envelope.stanzaID,
|
||||
messageIndex(referenceID: stanzaID, conversationID: envelope.peerJID) != nil
|
||||
{
|
||||
|
||||
@@ -45,6 +45,7 @@ struct ChatView: View {
|
||||
@State private var hasCompletedInitialScroll = false
|
||||
@State private var isNearTimelineBottom = true
|
||||
@State private var historyLoadAnchorID: String?
|
||||
@State private var historyTopTriggerArmed = true
|
||||
@State private var activeCaptureMode: ComposerCaptureMode?
|
||||
@State private var preparingCaptureMode: ComposerCaptureMode?
|
||||
@State private var captureGestureIsActive = false
|
||||
@@ -239,6 +240,7 @@ struct ChatView: View {
|
||||
hasCompletedInitialScroll = false
|
||||
isNearTimelineBottom = true
|
||||
historyLoadAnchorID = nil
|
||||
historyTopTriggerArmed = true
|
||||
}
|
||||
.onDisappear {
|
||||
model.endComposerActivity(in: liveConversation)
|
||||
@@ -332,10 +334,30 @@ struct ChatView: View {
|
||||
Color.clear
|
||||
.frame(height: 1)
|
||||
.accessibilityHidden(true)
|
||||
.onAppear {
|
||||
guard !model.isLoadingOlderHistory else { return }
|
||||
historyLoadAnchorID = timelineEntries.first?.id
|
||||
model.loadOlderHistoryForSelectedConversation()
|
||||
// .onAppear {
|
||||
//// guard !model.isLoadingOlderHistory else { return }
|
||||
// guard historyTopTriggerArmed,
|
||||
// !model.isLoadingOlderHistory
|
||||
// else {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// historyTopTriggerArmed = false
|
||||
// historyLoadAnchorID = timelineEntries.first?.id
|
||||
// model.loadOlderHistoryForSelectedConversation()
|
||||
// }
|
||||
.background {
|
||||
GeometryReader { geometry in
|
||||
Color.clear.preference(
|
||||
key: TimelineTopYPreferenceKey.self,
|
||||
value: geometry.frame(
|
||||
in: .named(Self.timelineCoordinateSpace)
|
||||
).minY
|
||||
)
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
historyTopTriggerArmed = true
|
||||
}
|
||||
if model.isLoadingOlderHistory {
|
||||
ProgressView()
|
||||
@@ -419,6 +441,16 @@ struct ChatView: View {
|
||||
)
|
||||
}
|
||||
#endif
|
||||
.onPreferenceChange(TimelineTopYPreferenceKey.self) { topY in
|
||||
guard hasCompletedInitialScroll,
|
||||
!timelineEntries.isEmpty,
|
||||
model.hasMoreOlderHistory,
|
||||
!model.isLoadingOlderHistory,
|
||||
topY <= 24
|
||||
else { return }
|
||||
historyLoadAnchorID = timelineEntries.first?.id
|
||||
model.loadOlderHistoryForSelectedConversation()
|
||||
}
|
||||
.task(id: timelineEntries.last?.id) {
|
||||
await performInitialScrollAfterLayout(using: proxy)
|
||||
}
|
||||
@@ -1576,6 +1608,14 @@ private struct TimelineBottomYPreferenceKey: PreferenceKey {
|
||||
}
|
||||
}
|
||||
|
||||
private struct TimelineTopYPreferenceKey: PreferenceKey {
|
||||
static var defaultValue: CGFloat = .greatestFiniteMagnitude
|
||||
|
||||
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
|
||||
value = nextValue()
|
||||
}
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
/// Reads the real UIScrollView offset without replacing its delegate or
|
||||
/// installing another pan recognizer. SwiftUI geometry preferences can stop
|
||||
|
||||
@@ -296,6 +296,13 @@ final class XMPPService {
|
||||
private var mucCatchupLastCursor: String?
|
||||
private var mucCursorFallbackArchives: Set<MAMArchiveKey> = []
|
||||
private var delayedLiveByArchive: [MAMArchiveKey: [BufferedLiveDelivery]] = [:]
|
||||
private struct PendingOlderHistoryRequest {
|
||||
let conversationJID: String
|
||||
let isGroup: Bool
|
||||
let before: String?
|
||||
let completion: (Result<Bool, Error>) -> Void
|
||||
}
|
||||
private var pendingOlderHistoryRequest: PendingOlderHistoryRequest?
|
||||
private let archiveStanzaInbox = ArchiveStanzaInbox(
|
||||
maximumCount: ArchiveMessageBatchPolicy.maximumBufferedStanzas
|
||||
)
|
||||
@@ -825,12 +832,38 @@ final class XMPPService {
|
||||
completion(.failure(LumaXMPPError.notConnected))
|
||||
return
|
||||
}
|
||||
guard !archiveSyncStarted, activeMUCCatchup == nil else {
|
||||
completion(.success(false))
|
||||
// guard !archiveSyncStarted, activeMUCCatchup == nil else {
|
||||
// completion(.success(false))
|
||||
if archiveSyncStarted || activeMUCCatchup != nil {
|
||||
pendingOlderHistoryRequest = PendingOlderHistoryRequest(
|
||||
conversationJID: conversationJID,
|
||||
isGroup: isGroup,
|
||||
before: before,
|
||||
completion: completion
|
||||
)
|
||||
return
|
||||
}
|
||||
performOlderHistoryRequest(
|
||||
conversationJID: conversationJID,
|
||||
isGroup: isGroup,
|
||||
before: before,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
|
||||
private func performOlderHistoryRequest(
|
||||
conversationJID: String,
|
||||
isGroup: Bool,
|
||||
before: String?,
|
||||
completion: @escaping (Result<Bool, Error>) -> Void
|
||||
) {
|
||||
guard let client, client.state == .connected() else {
|
||||
completion(.failure(LumaXMPPError.notConnected))
|
||||
return
|
||||
}
|
||||
guard let version = client.module(.mam).availableVersions.first else {
|
||||
completion(.success(false))
|
||||
// completion(.success(false))
|
||||
completion(.failure(LumaXMPPError.connection("MAM недоступен")))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -893,7 +926,8 @@ final class XMPPService {
|
||||
message: stanza.message,
|
||||
timestamp: stanza.timestamp,
|
||||
archiveID: stanza.archiveID,
|
||||
isArchived: true
|
||||
isArchived: true,
|
||||
archivedPeerJID: isGroup ? nil : BareJID(conversationJID.lowercased())
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -911,6 +945,20 @@ final class XMPPService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func startPendingOlderHistoryIfPossible() {
|
||||
guard !archiveSyncStarted,
|
||||
activeMUCCatchup == nil,
|
||||
let pending = pendingOlderHistoryRequest
|
||||
else { return }
|
||||
pendingOlderHistoryRequest = nil
|
||||
performOlderHistoryRequest(
|
||||
conversationJID: pending.conversationJID,
|
||||
isGroup: pending.isGroup,
|
||||
before: pending.before,
|
||||
completion: pending.completion
|
||||
)
|
||||
}
|
||||
|
||||
func sendRetraction(
|
||||
to recipient: String,
|
||||
@@ -1567,7 +1615,8 @@ final class XMPPService {
|
||||
message: Message,
|
||||
timestamp: Date,
|
||||
archiveID: String?,
|
||||
isArchived: Bool = false
|
||||
isArchived: Bool = false,
|
||||
archivedPeerJID: BareJID? = nil
|
||||
) {
|
||||
guard message.type != .error,
|
||||
message.type != .groupchat,
|
||||
@@ -1578,8 +1627,12 @@ final class XMPPService {
|
||||
let ownJID = client.userBareJid
|
||||
let outgoing = sender == ownJID
|
||||
// guard let peer = outgoing ? message.to?.bareJid : message.from?.bareJid else { return }
|
||||
// let peer: BareJID?
|
||||
// if outgoing {
|
||||
let peer: BareJID?
|
||||
if outgoing {
|
||||
if isArchived, let archivedPeerJID {
|
||||
peer = archivedPeerJID
|
||||
} else if outgoing {
|
||||
peer = message.to?.bareJid ?? message.from?.bareJid
|
||||
} else {
|
||||
peer = message.from?.bareJid
|
||||
@@ -2707,6 +2760,7 @@ final class XMPPService {
|
||||
mucCatchupLastCursor = nil
|
||||
replayDelayedLive(for: archive)
|
||||
startNextMUCCatchupIfPossible()
|
||||
startPendingOlderHistoryIfPossible()
|
||||
}
|
||||
guard succeeded else { return }
|
||||
let checkpoint = MAMArchiveCheckpoint(
|
||||
@@ -3181,6 +3235,7 @@ final class XMPPService {
|
||||
}
|
||||
setArchiveSyncIndicator(false)
|
||||
archiveSyncStarted = false
|
||||
startPendingOlderHistoryIfPossible()
|
||||
archiveIsBootstrapQuery = false
|
||||
archiveHighWatermark = nil
|
||||
archiveHasCompletedPage = false
|
||||
|
||||
Reference in new issue
Block a user