@@ -1188,6 +1188,7 @@ typedef struct {
11881188 time_t newest_timestamp ;
11891189 char * batch_oldest_msgid ; /* owned copy */
11901190 gboolean is_catchup ;
1191+ gboolean chathistory_end ; /* server signalled no more history (draft/chathistory-end) */
11911192 guint idle_tag ;
11921193 scrollback_db * db ; /* for transaction begin/commit between chunks */
11931194} chathistory_chunk_state ;
@@ -1236,6 +1237,10 @@ finish_batch_processing (chathistory_chunk_state *chunk)
12361237 sess -> oldest_msgid = g_strdup (chunk -> batch_oldest_msgid );
12371238 }
12381239
1240+ /* Server explicitly signalled end of history via draft/chathistory-end tag */
1241+ if (chunk -> chathistory_end )
1242+ sess -> history_exhausted = TRUE;
1243+
12391244 /* Catch-up loop */
12401245 if (chunk -> is_catchup )
12411246 {
@@ -1244,10 +1249,9 @@ finish_batch_processing (chathistory_chunk_state *chunk)
12441249 /* --- BEFORE pagination phase --- */
12451250 sess -> history_catchup_retrieved += chunk -> msg_count ;
12461251
1247- /* Empty batch → server has no more history */
1248- if (chunk -> raw_count == 0 )
1252+ /* No more history (empty batch or chathistory-end tag) */
1253+ if (chunk -> raw_count == 0 || sess -> history_exhausted )
12491254 {
1250- sess -> history_exhausted = TRUE;
12511255 finish_catchup (sess );
12521256 chathistory_check_before_catchup (serv );
12531257 return ;
@@ -1467,12 +1471,16 @@ chathistory_process_batch (server *serv, batch_info *batch)
14671471 if (!batch -> messages )
14681472 {
14691473 gboolean used_msgid = sess -> history_request_used_msgid ;
1474+ if (batch -> chathistory_end )
1475+ sess -> history_exhausted = TRUE;
14701476 chathistory_request_complete (sess );
14711477 if (is_catchup )
14721478 {
14731479 /* Server may not recognize our msgid (e.g., server restart).
1474- * Fall back to timestamp-based LATEST, then LATEST *. */
1475- if (used_msgid && sess -> scrollback_newest_time > 0 )
1480+ * Fall back to timestamp-based LATEST, then LATEST *.
1481+ * But not if chathistory-end tells us there's nothing. */
1482+ if (!sess -> history_exhausted &&
1483+ used_msgid && sess -> scrollback_newest_time > 0 )
14761484 {
14771485 char ref [64 ];
14781486 g_snprintf (ref , sizeof (ref ), "timestamp=%" G_GINT64_FORMAT ,
@@ -1481,8 +1489,8 @@ chathistory_process_batch (server *serv, batch_info *batch)
14811489 return ;
14821490 }
14831491 /* Catch-up complete — no new messages since last disconnect.
1484- * Don't set history_exhausted: older history may still exist
1485- * for scroll-to-top requests. */
1492+ * Don't set history_exhausted unless chathistory-end was sent:
1493+ * older history may still exist for scroll-to-top requests. */
14861494 finish_catchup (sess );
14871495 if (serv -> chathistory_latest_pending > 0 )
14881496 serv -> chathistory_latest_pending -- ;
@@ -1527,6 +1535,7 @@ chathistory_process_batch (server *serv, batch_info *batch)
15271535 sync_state .remaining = batch -> messages ;
15281536 sync_state .raw_count = raw_count ;
15291537 sync_state .is_catchup = is_catchup ;
1538+ sync_state .chathistory_end = batch -> chathistory_end ;
15301539 sync_state .batch_oldest_msgid = (char * )batch_oldest_msgid ; /* borrowed, not freed */
15311540
15321541 if (db )
@@ -1552,6 +1561,7 @@ chathistory_process_batch (server *serv, batch_info *batch)
15521561 chunk -> remaining = batch -> messages ;
15531562 chunk -> raw_count = raw_count ;
15541563 chunk -> is_catchup = is_catchup ;
1564+ chunk -> chathistory_end = batch -> chathistory_end ;
15551565 chunk -> db = db ;
15561566 chunk -> batch_oldest_msgid = g_strdup (batch_oldest_msgid );
15571567 batch -> messages = NULL ; /* prevent batch_info_free from freeing */
0 commit comments