@@ -136,6 +136,17 @@ func chatHistoryViewForLocation(
136136 |> map { viewData, isPossibleIntroLoaded -> ChatHistoryViewUpdate in
137137 let ( view, updateType, initialData) = viewData
138138 var effectiveIsAddedToChatList = view. isAddedToChatList
139+
140+ // Temporary diagnostics for chats that open away from the unread boundary.
141+ // Keep the actual indexes (rather than message text) so entries can be
142+ // correlated with the Postbox read-state trace without exposing content.
143+ let peerDebugId = chatLocation. peerId. map { String ( describing: $0) } ?? " none "
144+ let entriesRange = " \( String ( describing: view. entries. first? . message. index) ) ... \( String ( describing: view. entries. last? . message. index) ) "
145+ let firstIncomingUnreadIndex : MessageIndex ? = view. maxReadIndex. flatMap { maxReadIndex in
146+ return view. entries. first ( where: { entry in
147+ return !entry. message. flags. intersection ( . IsIncomingMask) . isEmpty && entry. message. index > maxReadIndex
148+ } ) ? . message. index
149+ }
139150
140151 let ( cachedData, cachedDataMessages, readStateData, peers) = extractAdditionalData ( view: view, chatLocation: chatLocation)
141152 if case let . peer( peerId) = chatLocation, let channel = peers [ peerId] as? TelegramChannel , let linkedCommunityId = channel. linkedCommunityId, let community = peers [ linkedCommunityId] as? TelegramCommunity {
@@ -147,16 +158,20 @@ func chatHistoryViewForLocation(
147158 let combinedInitialData = ChatHistoryCombinedInitialData ( initialData: initialData, buttonKeyboardMessage: view. topTaggedMessages. first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData)
148159
149160 if !isPossibleIntroLoaded {
161+ Logger . shared. log ( " ChatUnreadPosition " , " loading peer= \( peerDebugId) reason=businessIntro update= \( updateType) maxRead= \( String ( describing: view. maxReadIndex) ) firstIncomingUnread= \( String ( describing: firstIncomingUnreadIndex) ) anchor= \( view. anchorIndex) entries= \( entriesRange) holes= \( view. holeEarlier) / \( view. holeLater) " )
150162 return . Loading( initialData: combinedInitialData, type: . Generic( type: updateType) )
151163 }
152164
153165 if preloaded {
166+ Logger . shared. log ( " ChatUnreadPosition " , " update-after-initial peer= \( peerDebugId) update= \( updateType) maxRead= \( String ( describing: view. maxReadIndex) ) firstIncomingUnread= \( String ( describing: firstIncomingUnreadIndex) ) anchor= \( view. anchorIndex) entries= \( entriesRange) holes= \( view. holeEarlier) / \( view. holeLater) " )
154167 return . HistoryView( view: view, type: . Generic( type: updateType) , scrollPosition: nil , flashIndicators: false , originalScrollPosition: nil , initialData: combinedInitialData, id: location. id)
155168 } else {
156169 if view. isLoading || ( view. entries. isEmpty && ( view. holeEarlier || view. holeLater) ) {
170+ Logger . shared. log ( " ChatUnreadPosition " , " loading peer= \( peerDebugId) reason=history update= \( updateType) maxRead= \( String ( describing: view. maxReadIndex) ) firstIncomingUnread= \( String ( describing: firstIncomingUnreadIndex) ) anchor= \( view. anchorIndex) entries= \( entriesRange) holes= \( view. holeEarlier) / \( view. holeLater) " )
157171 return . Loading( initialData: combinedInitialData, type: . Generic( type: updateType) )
158172 }
159173 var scrollPosition : ChatHistoryViewScrollPosition ?
174+ var scrollDecision = " default "
160175
161176 let canScrollToRead : Bool
162177 if case let . replyThread( message) = chatLocation, !message. isForumPost, !message. isMonoforumPost {
@@ -176,12 +191,14 @@ func chatHistoryViewForLocation(
176191 if tag == nil , case let . replyThread( message) = chatLocation, message. isForumPost, view. maxReadIndex == nil {
177192 if case let . message( index) = view. anchorIndex {
178193 scrollPosition = . index( subject: MessageHistoryScrollToSubject ( index: . message( index) , quote: nil ) , position: . bottom( 0.0 ) , directionHint: . Up, animated: false , highlight: false , displayLink: false , setupReply: false )
194+ scrollDecision = " forum-anchor "
179195 }
180196 }
181197
182198 if let maxReadIndex = view. maxReadIndex, tag == nil , canScrollToRead {
183199 let aroundIndex = maxReadIndex
184200 scrollPosition = . unread( index: maxReadIndex)
201+ scrollDecision = " unread "
185202
186203 if let _ = chatLocation. peerId {
187204 var targetIndex = 0
@@ -196,11 +213,13 @@ func chatHistoryViewForLocation(
196213 let minIndex = targetIndex - 40
197214 if minIndex <= 0 && view. holeEarlier {
198215 fadeIn = true
216+ Logger . shared. log ( " ChatUnreadPosition " , " loading peer= \( peerDebugId) reason=missing-earlier-near-unread maxRead= \( maxReadIndex) firstIncomingUnread= \( String ( describing: firstIncomingUnreadIndex) ) anchor= \( view. anchorIndex) entries= \( entriesRange) holes= \( view. holeEarlier) / \( view. holeLater) " )
199217 return . Loading( initialData: combinedInitialData, type: . Generic( type: updateType) )
200218 }
201219 if maxIndex >= view. entries. count {
202220 if view. holeLater {
203221 fadeIn = true
222+ Logger . shared. log ( " ChatUnreadPosition " , " loading peer= \( peerDebugId) reason=missing-later-near-unread maxRead= \( maxReadIndex) firstIncomingUnread= \( String ( describing: firstIncomingUnreadIndex) ) anchor= \( view. anchorIndex) entries= \( entriesRange) holes= \( view. holeEarlier) / \( view. holeLater) " )
204223 return . Loading( initialData: combinedInitialData, type: . Generic( type: updateType) )
205224 }
206225 if view. holeEarlier {
@@ -213,13 +232,15 @@ func chatHistoryViewForLocation(
213232 if case let . peer( peerId) = chatLocation, let combinedReadStates = view. fixedReadStates, case let . peer( readStates) = combinedReadStates, let readState = readStates [ peerId] , readState. count == incomingCount {
214233 } else {
215234 fadeIn = true
235+ Logger . shared. log ( " ChatUnreadPosition " , " loading peer= \( peerDebugId) reason=missing-earlier-unread-count maxRead= \( maxReadIndex) firstIncomingUnread= \( String ( describing: firstIncomingUnreadIndex) ) anchor= \( view. anchorIndex) entries= \( entriesRange) holes= \( view. holeEarlier) / \( view. holeLater) " )
216236 return . Loading( initialData: combinedInitialData, type: . Generic( type: updateType) )
217237 }
218238 }
219239 }
220240 }
221241 } else if effectiveIsAddedToChatList, tag == nil , let historyScrollState = ( initialData? . storedInterfaceState) . flatMap ( _internal_decodeStoredChatInterfaceState) . flatMap ( ChatInterfaceState . parse) ? . historyScrollState {
222242 scrollPosition = . positionRestoration( index: historyScrollState. messageIndex, relativeOffset: CGFloat ( historyScrollState. relativeOffset) )
243+ scrollDecision = " saved-position "
223244 } else {
224245 if let _ = chatLocation. peerId, !effectiveIsAddedToChatList {
225246 if view. holeEarlier && view. entries. count <= 2 {
@@ -233,6 +254,7 @@ func chatHistoryViewForLocation(
233254 }
234255 }
235256
257+ Logger . shared. log ( " ChatUnreadPosition " , " initial peer= \( peerDebugId) decision= \( scrollDecision) canScrollToRead= \( canScrollToRead) update= \( updateType) maxRead= \( String ( describing: view. maxReadIndex) ) firstIncomingUnread= \( String ( describing: firstIncomingUnreadIndex) ) anchor= \( view. anchorIndex) entries= \( entriesRange) holes= \( view. holeEarlier) / \( view. holeLater) " )
236258 preloaded = true
237259 return . HistoryView( view: view, type: . Initial( fadeIn: fadeIn) , scrollPosition: scrollPosition, flashIndicators: false , originalScrollPosition: nil , initialData: ChatHistoryCombinedInitialData ( initialData: initialData, buttonKeyboardMessage: view. topTaggedMessages. first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData) , id: location. id)
238260 }
0 commit comments