Releases: ChuYanLon/telegram.nvim
Releases · ChuYanLon/telegram.nvim
Release list
v0.7.1
Added
- blink.cmp source — full completion source for telegram buffers: emoji (
:name), @mentions with async member fetch, bot commands (/cmd), code block languages (```lang) - Polls — create (
@createpoll), vote (@vote), view voters (@voters), stop (@stoppoll); supports multi-answer, timed polls - Rich text highlights — bold, italic, code, strikethrough, spoiler, link text with dedicated highlight groups
- 15+ new service message types — contacts, venues, locations, stories, boosts, payments, gifts, giveaways, stake dice, TON, etc.
- Translation —
@translate/@translate_zhwith floating window display - Jump to date —
@jump_to_datesupportsYYYY-MM-DD,today,yesterday - Profile management —
@myprofileview/edit name and bio - Contacts browsing —
@contactslist and DM contacts - Join request management —
@joinrequestsapprove/decline pending requests - Admin event log —
@eventlogbrowse recent admin actions - Shared chat/user opener —
@opensharedfor shared chats/users from messages - @-less mention — mention members without @username via
textEntityTypeMentionName - Link previews — structured multi-line display with site info
- Docs automation — tools table and feature sections auto-generated from Lua source
Fixed
- blink scan loop —
/trigger inget_trigger_characters()but notget_completions()fixed - blink member dedup/cache/async guards — stale data, duplicate items, permanent fetch lock all fixed
- blink registration — use
add_filetype_source()public API instead of config mutation - Poll stop/vote/error handling —
reply_markupremoved from stopPoll payload, sendPoll returns errors - Link preview, profile fetch, server JSON null, timer leaks — various crash/behavior fixes
Changed
- blink trigger — bot commands moved from
!to/(standard Telegram prefix) translate_zhdefault key —z→tt- Poll
Vkeymap — removed, use@voteinstead - Performance — message window capped at 200, curl timeouts reduced, exit freeze fixed
v0.7.0
Features
- Chat folders — browse Telegram folders with dedicated picker, async chat loading
- Forward with reply context — new
Fkey preserves reply chains when forwarding - Deleted message tombstoning — messages show "[Message deleted]" instead of disappearing
UI / Docs Site
- Docs site redesigned with Astro-inspired dark theme, responsive layout
- Dark / light / auto theme toggle
- Prism syntax highlighting for code blocks
- Copy button on code blocks
- Self-hosted fonts (removed external CDN dependency)
Docs Automation
pnpm gen:docs— auto-generates keymaps table from config.lua into README + wiki pages- CI auto-fixes stale docs and syncs to GitHub Wiki on push to main
- CLAUDE.md added for AI-assisted development
- README feature checklist simplified to high-level categories
Bug Fixes
- Timer crash on destroy — graceful
pcallwrap forvim.fn.timer_stop - Chat folder name parsing — fix nested
textfield access - Deleted message rendering — render placeholder instead of crash
Security
- Express 4 → 5 migration
- ws 8.21.1, vite 7.3.5, esbuild 0.28.1 — all Dependabot alerts patched
pnpm.overridespins transitive deps to secure versions
Chores
- Bumped all dependencies to latest compatible versions
- Removed redundant folder notifications
v0.6.0
What's new
- Input editor redesign — bottom-panel style with context preview for reply/edit modes; markdown syntax highlighting while typing
- Connection status indicator — title bar shows red dot when TDLib reports disconnected/connecting state
- Link previews — messages with URLs show
[site — title](url)preview below the link - Forwarded from label — forwarded messages show
↳ nameabove the content - Edited indicator — edited messages show
[edited]in the message footer alongside views and reactions;editDatefield propagated through TypeScript backend and Lua state - Copy message text — press
yyin the chat window to copy the current message's text to the system clipboard - Favorites (Saved Messages) — dedicated chat always present in group list with 📌 icon; press
sto forward current message to Favorites with confirmation dialog - View counts — channel messages show
👀 Nfooter with k/M formatting; real-time sync viaupdateMessageInteractionInfoWebSocket event - Read receipts — outgoing private messages display
(read HH:MM)in header when recipient has read the message; usesgetMessageReadDate+updateMessageReadDatereal-time updates - Configurable panel position —
panel_positionoption supports"right"(default),"left","bottom","top"
Fixed
- Message object field preservation —
views,readDate,reactions,editDatenow stored on new message objects in Lua state - Favorites chat identification —
isSavedflag replaces existing chat entry in list instead of duplicating - Favorites notifications — messages in Favorites chat excluded from
should_notify()viasaved_chat_id - Cursor positioning on empty chat —
set_cursor_to_idxguards against nil message when target index is out of bounds
v0.5.4
What's new
- Loading indicators and empty state — chat buffer shows loading spinner during fetch and "No messages" when empty
- Date separators and unread divider — date group headers between messages; "Unread messages" divider at the unread boundary
- Unread-aware loading — initial load fetches 30 messages (up from 10), centered around
lastReadInboxMessageId
Fixed
- Cursor positioned at first unread message — jumps to first message below the unread divider, not date group boundary
- Unread divider stays fixed — stays at original position until all messages above are read; per-message read tracking
- Read receipt reliability —
last_read_idpersisted per-chat likesaved_cursors, protected from stale server responses; read only marked when cursor reaches last line of a message - Unread count accuracy — deduplicated
load_newercounting; own/at-bottom messages no longer increment;math.min()guards against stale server counts - Cursor maintenance — tracked by message ID during older loads, not buffer line number
extra_beforedelta — corrected cumulative offset calc using(extra - prev_extra)in incremental loops- Immediate title/status update —
CursorMovedcallsupdate_title()+redrawstatusright after marking read, no longer waiting for server round-trip
Changed
- Initial message load — 10 → 30 messages on first chat open
getChatreturnslastReadInboxMessageId— Lua side receives it for unread-aware positioning
v0.5.3
What's new
- Message reactions — press
ron a message to open the emoji picker (40+ verified emojis); same emoji toggles off, different auto-switches; real-time sync via WebSocket - Admin custom titles — shows custom titles next to admin names in messages and member list
- Unread count in lualine —
require("telegram").lualineshows unread badge and @mention indicators with color-coded status - Configurable notification types —
notify_chat_typessetting to control which chats trigger desktop notifications - HD media auto-download —
@refreshmediadownloads highest-quality photos/videos under cursor
Fixed
- Unread count double-counting —
chatReadInbox(TDLib authoritative count) now correctly overrides local increment. Status bar refreshes immediately when count changes. - Stale
unread_mention_count— ignored whenunread_countis 0 - Sticker auto-download — prefers high-quality mediaPath over thumbnail
- Service messages no longer trigger media download
mention_countreset — cleared when opening chat or scrolling past unread messageslast_msgpreserved — across group list refreshes
Refactor
ui.luasplit — dedicated modules: state, groups, reactions, editor, help, title
v0.5.2
[0.5.2] - 2026-06-03
Performance
- Message window capped at 200 —
state.messagesno longer grows unbounded; trimmed on scroll and new message arrival to prevent long-session lag - CursorMoved handler debounced — O(n) message scan and pagination trigger deferred to 50ms after last cursor movement, eliminating jank on rapid scrolling
curl_with_retrytimeouts reduced — retries 4→2, max-time 15s→5s, connect-timeout 5s→2s for faster failure recovery- Chat title update debounced —
VimResized/WinScrolledno longer share the same augroup (VimResized was silently dropped) close_chatnon-blocking — replaced synchronousvim.fn.system("curl")with fire-and-forgetrequest_async, preventing exit freeze- Timer leaks fixed —
refresh_timer,_scroll_timer,_typing_timer,_title_update_timernow properly stopped indestroy_chat, logout, and VimLeavePre _edit_tsstale entries cleaned — expired edit debounce timestamps removed on each new edit
Caching
_userscache — capped at 5,000 entries with gentle FIFO eviction; updated in real-time viaupdateUserevents_chatscache — capped at 500 entries; new chats fromupdateNewChatevict oldest when full; individual chat inserts use_cacheChat_pinnedMessageIdscache — capped at 200 entries; pin/unpin events update cache; unpin removes entry
Fixed
- Exit freeze on Neovim close — server now exits immediately on SIGTERM (without awaiting TDLib close), Neovim doesn't wait for the job
- First-exit lag — TDLib's first-time database finalization no longer blocks Neovim's shutdown
- Remote session termination —
updateAuthorizationState(closed/logging-out) clears all caches and notifies Lua UI - Stale typing indicators —
typing_usersentries for the previous chat are cleaned up onopen_chatswitch
Changed
- SIGTERM exits immediately — closes HTTP/WS servers and calls
process.exit(0)withouttgClient.shutdown(); SIGINT (Ctrl+C) still does graceful shutdown getGroups()always fetches fresh — reverted togetChats(true)to avoid stale chat list when chats are removed
[0.5.0] - 2026-06-01
v0.5.1
[0.5.0] - 2026-06-01
Added
- Customizable keymaps — all 21 keymaps configurable via
setup({ keys = { ... } }); set tofalseto disable - Theme-adaptive highlights — all highlight groups derive from Neovim theme (
Comment,DiffAdd,DiagnosticOk, etc.) with no hardcoded colors - Granular default permissions editor — interactive floating window with 14 permission toggles, toggle-all switch, color-coded highlights for enabled/disabled/unknown states
- Edit invite links — frontend wrapper and UI entry for editing invite links (member limit + expiration)
- Expiration support for invite links — create/edit invite links with optional expiry time
- @username search for adding members — search by username instead of raw numeric user ID
- Invite link fallback — when adding a member to a supergroup fails, the invite link is returned to the user instead of a generic error
- Member list includes admins and creator — dual-filter search merges
chatMembersFilterAdministratorsandchatMembersFilterMembers - WebSocket sync for chat metadata — user name changes, online/offline status, group description/member count, group kicked/banned now sync in real-time from other clients
- Online status — user is marked as online after login with periodic heartbeat (30s), visible to other clients
- Device model — session shows as
telegram.nvim(with version and OS) in Telegram device list - Defensive error guards —
getChatInviteLinkshandlesgetMe()failure;handleChatMemberUpdateguards undefined user IDs; SIGTERM now does graceful shutdown
Fixed
- Channel unsubscribe now actually leaves — changed from
deleteChatHistorytoleaveChat restrictChatMember/unrestrictChatMembernot working — used wrong TDLib fieldcan_send_messagesinstead ofcan_send_basic_messages- Member actions shown regardless of status — Ban/Unban/Restrict/Promote now dynamically shown based on member's current status
- promoteChatMember grants
can_promote_members— removed to prevent privilege escalation - Title float covering messages — buffer padding now syncs with float height on every
update_title()call, preventing overlap (#123) - Cursor move freeze —
msg_line_countscache eliminates#fmt_msg()re-render on every cursor movement - WinScrolled storm — debounced
update_title()calls (100ms) reduce float recreation overhead on scroll - User name not updating in rendered messages — on
userUpdate, sender names in existing messages are refreshed viarender() ChatPositionevent name mismatch — migrated frombroadcastRaw(uppercase) to explicit lowercase handlertruncate_textnegative width — pinned message/description titles no longer break at narrow window widths
Changed
- Removed nui.nvim dependency — help popup and input editor migrated from
nui.popupto built-innvim_open_win request_async— restored to prefervim.net.requestwith curl fallback (reverted experimental change)set_groups— now storesuser_idfor private chat lookups
What's Changed
- chore(deps-dev): bump tsx from 4.22.3 to 4.22.4 by @dependabot[bot] in #128
New Contributors
- @dependabot[bot] made their first contribution in #128
Full Changelog: v0.5.0...v0.5.1
v0.5.0
[0.5.0] - 2026-06-01
Added
- Customizable keymaps — all 21 keymaps configurable via
setup({ keys = { ... } }); set tofalseto disable - Theme-adaptive highlights — all highlight groups derive from Neovim theme (
Comment,DiffAdd,DiagnosticOk, etc.) with no hardcoded colors - Granular default permissions editor — interactive floating window with 14 permission toggles, toggle-all switch, color-coded highlights for enabled/disabled/unknown states
- Edit invite links — frontend wrapper and UI entry for editing invite links (member limit + expiration)
- Expiration support for invite links — create/edit invite links with optional expiry time
- @username search for adding members — search by username instead of raw numeric user ID
- Invite link fallback — when adding a member to a supergroup fails, the invite link is returned to the user instead of a generic error
- Member list includes admins and creator — dual-filter search merges
chatMembersFilterAdministratorsandchatMembersFilterMembers - WebSocket sync for chat metadata — user name changes, online/offline status, group description/member count, group kicked/banned now sync in real-time from other clients
- Online status — user is marked as online after login with periodic heartbeat (30s), visible to other clients
- Device model — session shows as
telegram.nvim(with version and OS) in Telegram device list - Defensive error guards —
getChatInviteLinkshandlesgetMe()failure;handleChatMemberUpdateguards undefined user IDs; SIGTERM now does graceful shutdown
Fixed
- Channel unsubscribe now actually leaves — changed from
deleteChatHistorytoleaveChat restrictChatMember/unrestrictChatMembernot working — used wrong TDLib fieldcan_send_messagesinstead ofcan_send_basic_messages- Member actions shown regardless of status — Ban/Unban/Restrict/Promote now dynamically shown based on member's current status
- promoteChatMember grants
can_promote_members— removed to prevent privilege escalation - Title float covering messages — buffer padding now syncs with float height on every
update_title()call, preventing overlap (#123) - Cursor move freeze —
msg_line_countscache eliminates#fmt_msg()re-render on every cursor movement - WinScrolled storm — debounced
update_title()calls (100ms) reduce float recreation overhead on scroll - User name not updating in rendered messages — on
userUpdate, sender names in existing messages are refreshed viarender() ChatPositionevent name mismatch — migrated frombroadcastRaw(uppercase) to explicit lowercase handlertruncate_textnegative width — pinned message/description titles no longer break at narrow window widths
Changed
- Removed nui.nvim dependency — help popup and input editor migrated from
nui.popupto built-innvim_open_win request_async— restored to prefervim.net.requestwith curl fallback (reverted experimental change)set_groups— now storesuser_idfor private chat lookups
What's Changed
- feat: channel support, group management, async search, vim.net.request by @ChuYanLon in #127
Full Changelog: v0.4.1...v0.5.0
v0.4.1
[0.4.0] - 2026-05-28
Added
:TgPrsquash merge — now offers "squash" and "commit" merge strategies when merging PRs- Private chat support — press
con a message to open DM with sender;@newchattool to start DM by @username - Snacks picker — chat picker now uses
snacks.nvimwith fuzzy search, falls back tovim.ui.select - Confirmation prompt before opening DM —
vim.ui.selectasks Yes/No before opening a private chat - ImageMagick requirement — documented in README for image display in Kitty terminal
Changed
- Updated all documentation — CONTRIBUTING, WORKFLOW, wiki pages, PR template, and CHANGELOG synced with current TypeScript architecture and feature set
- Terminology — user-facing text unified to use "chat" instead of "group" (picker, help popup, notifications)
- Online count — now fetched synchronously from TDLib on chat open with cache fallback; stale 0 values from WebSocket ignored
- Typing indicator — shown in a floating popup below the winbar instead of replacing the title bar
- Service message prefixes — changed from markdown-significant characters (
+,-,*,>) to bracket format ([+],[-],[*],[>]) - README screenshots — reorganized with new screenshot categories and Image Preview section
Fixed
- Service message highlighting — added
TgServicehighlight group for service messages - Wiki sync workflow — pull rebase before push to avoid push conflicts
- Online count - stale 0 values from WebSocket no longer overwrite cached counts
Full Changelog: v0.4.0...v0.4.1
v0.4.0
[0.4.0] - 2026-05-29
Added
- Missing TDLib update handlers — message edits, deletions, group list, unread sync now broadcast via WebSocket in real-time
- Graceful shutdown — SIGINT handler closes TDLib/WebSocket/HTTP properly, preventing binlog corruption
- Date-based pagination — load_older/load_newer use
message.dateinstead ofmessage.id, fixing wrong messages loading in migrated groups - Login timeout — 5-minute timeout for TDLib login to prevent hanging forever
- getChats iteration limit — max 1000 loops to prevent infinite pagination
- Server route tests — expanded from 1 to 17 tests covering all endpoints
- :TgPr squash merge — now offers
squashandcommitmerge strategies - Private chat support — press
con a message to open DM;@newchattool to DM by @username - Snacks picker — chat picker uses snacks.nvim with fuzzy search, falls back to vim.ui.select
- ImageMagick requirement — documented for image display in Kitty terminal
Changed
- GitHub ops extracted — :TgPr and :TgIssue moved to
lua/telegram/github.lua, reducing init.lua by 370 lines - Updated all documentation — wiki pages synced with current architecture and features
- Online count — fetched synchronously from TDLib with cache fallback
- Typing indicator — floating popup below winbar instead of replacing title bar
- Service message prefixes — bracket format (
[+],[-], etc.) for safety - Console logging added —
console.warnin all empty catch blocks for debuggability
Fixed
- Inconsistent chatId type conversion — normalized across all API endpoints (#113 by @jaideepkathiresan)
- Auth race condition — wait for server ack before re-prompting auth input
- TDLib version parsing — regex handles pre-release tags like
1.8.64-beta - JSON null safety — LuaJIT cdata handling for
chatLastMessageUpdatedevent - Service message highlighting —
TgServicehighlight group - Wiki sync workflow — pull before commit to avoid push conflicts
- Online count — stale 0 values from WebSocket no longer overwrite cached counts
Docs
- README — remove groups sidebar item, add ImageMagick requirement, reorganize screenshots (#115 by @ChuYanLon)
- Group management — split into separate todo items (#112 by @ChuYanLon)
- Wiki — synced with v0.4.0 architecture and features