Skip to content

Telegram: presence at connect, reads survive a dropped tell, session fits the keychain, forum topics and pins again - #129

Open
unRekable wants to merge 27 commits into
TinyComms:mainfrom
unRekable:fix/telegram-presence-lost-reads
Open

unRekable wants to merge 27 commits into
TinyComms:mainfrom
unRekable:fix/telegram-presence-lost-reads

Conversation

@unRekable

@unRekable unRekable commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

What this fixes

Telegram fixes, each driven by real evidence from a live install: chatd's logs, the user's SQLite profile, the adapter's own request trace, and screenshots. Review in commit order.

Presence: the account showed offline while connected

connect() reports "here" once when the connection opens and then on a cadence, driven from the connection's own event loop (recv_timeout), so nothing outlives the connection and no thread leaks. The existing test proves the connect-time UpdateStatus: it appears in the fake's call log before SetTyping, and acting stays throttled to one call per HERE_EVERY (240 s).

Reads survive a dropped tell (unread came back after every restart)

Root cause, proven on the machine: a MarkRead chatd queued while Telegram was down (502/530 storms, os error 10013 socket bursts) was dropped by the offline handler — locally the chat stayed read, Telegram never heard, and the next chats sync pushed the network's stale unread_count and read_inbox_max_id back over the store.

record() now keeps the user's read watermark: where the store is ahead of the dialog, the ReadHistory is told again and messages.getPeerDialogs is asked once for what that tell left, and only then are counts written. If the follow-up fails, the row stands untouched. Covered by a_read_lost_on_the_way_is_told_again_and_the_badge_stays (fake gains lost-read / notify-changed steers and a getPeerDialogs handler).

Folder tabs painted over the conversation

The strip sits inside an overflow_hidden wrapper; the arrows appear whenever the content is wider than the sidebar. Verified with screenshots at 1120×720 and 700×720.

The Telegram session was never saved again on Windows

From the log: the session was not saved: keychain: Attribute 'password encoded as UTF-16' is longer than platform limit of 2560 chars. A Windows credential blob tops out at 2560 bytes, and a session stored as text is UTF-16 encoded, so Telegram's datacenter keys in hex alone exceed it.

session::save now writes the session deflate-packed as a secret (set_secret, Windows only) and reads unpack it; an item stored as plain text before this still reads (its blob is the UTF-16 bytes). One shared writer for save and the renamed-item migration. Regression test session::tests::a_session_too_long_as_text_still_keeps_its_words. Uses miniz_oxide, already in the tree.

Forum topics stopped coming on open

Request::Topics was a store-only read: opening a forum fetched nothing. The sidebar now sends the request that backfills when a forum is opened, once per open — a home refresh never re-asks, so no change/request loop.

Chats the folder rules pin past the newest dialog pages were missing

The chats sync reads the newest 500 dialogs; a folder's pinned chat further down never got a row, so the tab lost it. At the end of the sync, every folder-pinned chat the store lacks is asked alone (getPeerDialogs), Telegram's own order coming from the folder rules as before. Covered by a_chat_pinned_by_a_folder_beyond_the_pages_gets_its_row.

Pins, end to end

Drawn from the live trace of what Telegram answers (pinned=true on both the main read and the archive read):

  • The all-chats list carries its own pins first, whatever the archive says — the chats Telegram pins stand there even when they also live in the archive, and below them recency as usual.
  • A folder's tab takes its own pins on top, in Telegram's order, with the pin row fields written so the shell groups and draws the pin.

Both behaviours carry store tests (a_network_home_lists_its_pins_then_recency_and_a_folder_is_a_filter, with the pinned-and-archived and the folder-pin fields).

Not on this branch

A one-off debug trace (TINYCLIENT_TRACE_TELEGRAM) and debug-trace.bat stayed local only, so the debugging of the pins is reproducible on the machine without being in the PR. telegram.env (local build credentials) is git-ignored, and chatd's build script falls back to it so test loops never rebuild chatd without the app id.

Known issues left open

  • The first request on a forum while the link is still down is dropped by the offline handler; the second click works.
  • The reworked presence cadence leaves a wedged connection unattended for up to 240 s before ctx.stopped() is noticed (downstream of Event::Closed arriving, which is immediate).

Verification

Fresh on 8b04574 (trace commits dropped):

  • cargo test -p chatd --lib — 252 passed, 0 failed (includes the pins and session tests)
  • cargo test -p chatd --test telegram — 23 passed, 0 failed
  • remaining chatd suites (blobs, calls, discord, teams, slack, signal, messages, playback, polish) — all 0 failed
  • cargo test -p tinyclient --features gui — 460 passed, 0 failed

@unRekable
unRekable requested a review from itz4blitz as a code owner November 1, 2026 15:53
@unRekable

Copy link
Copy Markdown
Collaborator Author

Follow-up commit 3eacaf0: the Telegram session fits the keychain on Windows again.

Root cause from chatd.log (real machine): the session was not saved: keychain: Attribute 'password encoded as UTF-16' is longer than platform limit of 2560 chars. A Windows credential blob tops out at 2560 bytes; a session's password encoded as UTF-16 therefore only has 1280 characters, and Telegram's five datacenter keys in hex alone take more. session::save now stores the session deflate-packed as a secret (set_secret, Windows only), and the read unpacks it - one stored as plain text before the packing still comes back (its blob is the UTF-16 bytes). Regression test session::tests::a_session_too_long_as_text_still_keeps_its_words (round-trip over a >1280-char session: packed fits 2560, unpack restores, legacy text blob restores).

Fresh runs on 3eacaf0: cargo test -p chatd - lib 252 passed; telegram 22, blobs 15, calls 10, discord 40, teams 8, slack 4, signal 12, messages 11, playback 17, polish 7 - all 0 failed. tinyclient --features gui 460 passed / 0 failed.

Known environment issue, not this branch: cargo test --test e2e fails with startup-timeout / stalled-chatd panics on this machine - reproduced identically on clean main (cf496aa) in a throwaway worktree, so it predates this branch; CI verdicts there are the ones that count for that suite.

@unRekable unRekable changed the title Presence at connect and lost reads told again Telegram: presence at connect, reads survive a dropped tell, session fits the keychain, forum topics and pins again Nov 1, 2026
@unRekable
unRekable force-pushed the fix/telegram-presence-lost-reads branch from db05d44 to 8b04574 Compare November 1, 2026 21:19
itz4blitz
itz4blitz previously approved these changes Nov 1, 2026
@itz4blitz

Copy link
Copy Markdown
Collaborator

@unRekable please rebase with main

…xt tops out over what a credential keeps, so it is packed and kept as a secret, and what one stored as text before still reads.
…read only the store, so what the network said since its last pass never arrived (the Messages answer path is what backfills, and the drill had stopped asking it)
…, so a local build does not silently lose Telegram the way a release build refuses to
…at pinned inside any folder now stands with the pins, the better of its main-pin place and its folder places, like Telegram's own all-chats tab
…lace first, since a first pin of one folder never out-ranks a twelfth of another; the answer's rows carry a folder pin's place, so the shell groups them and draws the pin
… at the end of the chats sync each such pin is asked alone, so a pin past the newest 500 never sits missing from the list
…k to telegram.env next to the workspace when the shell carries no credentials, so test loops of the smaller crates never rebuild chatd without the app id again
…list itself, then recency, the folders' pins never lifted onto it (they had chats standing pinned there that nobody pinned), while a folder's own tab keeps its pins and their pin fields
…: the five chats Telegram pins both read with the archive and on the list itself stand, pin first, on both, the way the first-second view of the live install showed them
…lled at the next connect: the chats sync asks each held conversation once, one ask once and at most thirty-two, dropped when the session ends
…color rides the row from the chats table (a cache with one more column, the schema asked once) into the list, where the tile draws with it like Telegram's own list does
… icon names is asked in one request per list fetch, its still thumbnail is fetched over the session, and the topic's row shows it as its picture once it is on disk
…icon is named in its picture's fetch, so the list refreshes the moment the picture arrives, and one already on disk still tells the row that hung it
…l type named in the icon document is fetched, and an icon that is itself a still picture comes whole
…es (a topic's icon among them) as a gzip member, which is unpacked where the file is fetched, so the shell reads the picture or animation it can draw
…next ask, so the topics' icons found packed are fetched again and kept as the file inside
@unRekable
unRekable force-pushed the fix/telegram-presence-lost-reads branch from acba88d to 65a08c6 Compare November 2, 2026 04:39
@unRekable

Copy link
Copy Markdown
Collaborator Author

The rebase is done: the branch head is 65a08c6 and it contains main as of the rebase (79d1864), so the request in #129 (comment) has been handled. Main has since moved by one commit (#140, a two-line change to the mobile workflow that touches no file of this PR), and GitHub reports this pull request as mergeable with current main with no conflict. A dry-run apply of the branch diff against its rebase base is also clean, so no manual fixes were folded in during the rebase. Verified locally on Windows at 65a08c6: the telegram integration tests pass 24/24, the chatd lib tests pass 297/297, and chatd plus tinyclient with the gui features build without errors. CI is running fresh on 65a08c6; a few packaging jobs currently show failures at their build step while the run is still in progress, and the cause cannot be confirmed yet because logs are only available once the run completes.

…: the low 24 bits are the RGB its own list paints, drawn directly instead of the palette's hue next door, while a palette id stays a palette
…s footer, the thread's row is written with the post, and opening it asks Telegram once for the replies under the post's id, whose newest comment's time follows on the footer
… both called themselves that version, and the conversations table now carries both columns
…n time, and packaging a copy without Telegram is the builder's choice, not an error
…nail is its Lottie play anyway, which the shell animates the way messages do, so a topic whose emoji moves shows the same one Telegram does
…act color it packs and draws the title's first letter alone over it, so a topic without its own emoji reads the same there as here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants