Repository navigation
Releases: Aporis3674/TelegramFreeRich
Release list
v5.5.0
A full review of the codebase. No new features — ten defects found and fixed, each one verified
rather than assumed. The three that can bite a user in normal use are first.
Fixed — a caption, a credit or a quote's source could be added but never removed
- Emptying the field and pressing OK resolved to "cancelled" rather than to "empty", so the action
returned early and left the old value in place. Clearing a media caption, its credit, or a
quote's attribution was impossible once set - The same bug swallowed an empty checklist title: the send was silently abandoned instead of using
the fallback title that exists for exactly that case
Fixed — "Test connection" wiped the settings form while you watched
- Testing saves the token, which updated the stored settings, which re-ran the effect that fills
the form — clearing the token field, the proxy password, and any unsaved edits to the chat, edit
and business IDs, mid-test. The form is now filled when the panel opens, and only then - Testing also announced "Settings saved", which was misleading: only the token is stored. It now
reports the test result and nothing else
Fixed — a cleared Edit ID came back on the next launch
- The ID was written to storage when set but never removed when cleared, so emptying the field
looked like it worked and then reverted at startup. In Edit mode the app would go on rewriting
whichever message that stale ID pointed at
Fixed — the window could be navigated away from the app, taking the bot token with it
- The preload bridge belongs to the window, not to the page: navigate that window anywhere and the
new page keepswindow.app.api(), which signs every call with the stored token. Electron
navigates a window by default when a link or file is dropped onto it - The window now stays on its own page. Links meant for a browser (
http,https,mailto) are
handed to the real browser;target="_blank"opens there instead of in a frameless Electron
window with no address bar;<webview>is refused
Fixed — the renderer could ask the main process for any Telegram method
- The method name was checked against
/^[a-zA-Z]{3,64}$/, which admitsgetUpdates(read
everything the bot receives),setWebhook(redirect it) andbanChatMember. Every call is signed
with the user's token, so anything reachable was reachable as them. Replaced with an allowlist of
the five methods the app actually sends
Fixed — the preview showed links and media the message would not carry
- The preview parsed
hrefandsrcstraight out of the editor with no filter, while the
serializer next to it applied a scheme allowlist. So anftp:link looked like a working link in
a preview of a message that would not contain it, and afile:image was rendered from disk - Both parsers now use the serializer's own lists, so the preview shows what will be sent. Media
with no usable URL is left out rather than drawn as a broken image - The editor gained the same filter: pasting HTML from a web page brought its
<img src="file://…">
along, which the app's own CSP would then load
Fixed — non-ASCII text from Telegram could come back mangled
- Response chunks were appended to a string one at a time, so a UTF-8 character split across a
chunk boundary became two replacement characters — visible on any Persian bot name or error
message, and enough to break the JSON parse when the split landed inside a string. Chunks are now
decoded once, at the end - An unparseable response now reports the HTTP status with it, so a captive portal or a block page
can be told apart from a genuine API error
Fixed — a map could point off the globe
parseFloataccepted999, 999and35 degrees, 51; the coordinates went to Telegram and came
back as an API error naming no block. Latitude and longitude are now range-checked where they are
typed, and again before they reach the wire
Fixed — the link filter was a denylist
sanitizeUrlrefusedjavascript:,data:andvbscript:by prefix. A denylist has to
anticipate every dangerous scheme and misses the ones written to defeat it. It is now the same
allowlist the serializer uses, and a bareexample.comis read ashttps://example.comrather
than dropped later on the wire
Removed
- The
open-fileIPC handler and itsopenFilebridge method. Nothing in the renderer had ever
called them; they were an unused way into the main process
Verified
- The navigation guard driven in a real Electron window: before the fix, a page the window was
navigated to reachedwindow.app.api()and the main process ran the call for it. After, the
navigation does not happen,window.openopens no window, and the app's own page still works - The malicious-paste path driven through the real editor:
<a href="javascript:…">and
<img src="file:///etc/passwd">are both refused,https://t.me/okand a real image are kept,
and no console errors - The UTF-8 fix reproduced against the old code, which turned
رباتinto��بات - The app boots, the UI renders, Persian text types correctly, the bridge exposes exactly seven
members, and the settings panel opens with every field - 305 unit tests (up from 265), lint clean
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen warns on first run.
Full Changelog: v5.4.0...v5.5.0
v5.4.0
Added — media can carry a caption
- Rich HTML captions a media item with a
<figcaption>that follows it, and that caption may name
its own source in a<cite>:
<video src="…"></video><figcaption>Clip title<cite>The Author</cite></figcaption> - Media ▸ Caption… asks for the caption, then for its credit, and writes both onto the photo,
video, audio file or gallery the caret is on. Greyed out elsewhere, ticked once something is set,
and clearing both fields removes the<figcaption>again - A gallery's caption goes inside the wrapper, which is where the documented example puts it:
<tg-slideshow><img …/><figcaption>Trip<cite>Ada</cite></figcaption></tg-slideshow> - Like the quote attribution, the text lives in an attribute rather than in the editable body, so
it survives editing; the editor shows it under the media and the live preview renders a real
<figcaption>
Fixed — a message of nothing but media could not be sent
- The send guard refused anything with zero characters, so a photo on its own, a gallery on its own
or a map on its own was rejected as "nothing to send" — media carries no text. The guard now only
refuses a document that produces no blocks at all, which the existing check after serialization
already covered
Verified
- Driven in a real Electron window: the media menu lists Caption…, both prompts appear with
their translated hints, the editor document becomes
<img data-caption="A view from the pass" data-credit="Ada Lovelace" src="…">, the preview shows
the caption with its cite, and the send payload is
<img src="…"/><figcaption>A view from the pass<cite>Ada Lovelace</cite></figcaption> - 265 unit tests
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen warns on first run.
Full Changelog: v5.3.0...v5.4.0
v5.3.0
Added — a quote can name its source
- Rich HTML documents
<blockquote>text<cite>Author</cite></blockquote>, and the same<cite>on
<aside>. The serializer already emitted it from adata-attributionattribute — but nothing
could ever set that attribute, so no quote ever carried one. A plain<blockquote>did not even
have the attribute to set - Aa ▸ Attribution… asks who said it and writes it onto the quote the caret is in — either
kind. It is greyed out outside a quote, shows a tick once a source is named, and clearing the
field removes the<cite>again - The attribution is drawn from the attribute rather than kept in the editable text, so it cannot
be half-deleted while editing, and the live preview renders it as a real<cite> block-parser.jsnow reads the attribution off a plain quote too, not only a pull quote
Internal
askTextacceptsplaceholderKeybesideplaceholder, so a translated hint can be shown where
the existing callers pass a literal example- 258 unit tests: the new menu entry and its enablement, the trimmed/cancelled prompt,
<cite>on
both quote kinds, escaping, and an empty attribution emitting no<cite>
Verified
- Driven in a real Electron window: the Aa menu lists Attribution… after Pull quote, the editor
document becomes<blockquote data-attribution="Pavel Durov">, the preview shows the cite, and
the send payload is
<blockquote><p>Bots deserve rights too</p><cite>Pavel Durov</cite></blockquote>
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen warns on first run.
Full Changelog: v5.2.1...v5.3.0
v5.2.1
Same application code as 5.2.0. Only the release notes changed: 5.2.0 shipped before the workflow
could compose them, and a published release's body cannot be rewritten afterwards — so this tag
carries the notes and the screenshots that 5.2.0's release page is missing.
The slideshow carousel, in the editor and in the preview
| A slideshow, frame 1 of 3 | The same slideshow on the video frame |
|---|---|
![]() |
![]() |
A collage stays a grid — tiles, no arrows:
- A slideshow is one frame at a time now, with
‹/›buttons, a2 / 3counter and
clickable dots, wrapping around at either end. It was a row of thumbnails scrolling sideways - A video in a gallery no longer draws a broken image. Every entry used to be rendered as
<img>, so a video or audio URL always showed the browser's broken-image icon even though
Telegram renders it perfectly once sent. Entries are<img>/<video controls>/
<audio controls>by extension, and when the media genuinely will not load in the app window the
tile says what the file is — a ▶ / ♪ / 🖼 glyph, the file name, and "Not previewable here —
Telegram will show it" - The editor's gallery is drawn by a TipTap node view, so the wire format is untouched
- Full detail in the 5.2.0 entry below
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen warns on first run.
Full Changelog: v5.2.0...v5.2.1
v5.2.0
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen and macOS Gatekeeper
will warn on first run.
See CHANGELOG.md
for what changed.
Full Changelog: v5.1.6...v5.2.0
v5.1.6
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen and macOS Gatekeeper
will warn on first run.
See CHANGELOG.md
for what changed.
Full Changelog: v5.1.5...v5.1.6
v5.1.5
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen and macOS Gatekeeper
will warn on first run.
See CHANGELOG.md
for what changed.
Full Changelog: v5.1.4...v5.1.5
v5.1.4
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen and macOS Gatekeeper
will warn on first run.
See CHANGELOG.md
for what changed.
Full Changelog: v5.1.3...v5.1.4
v5.1.3
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen and macOS Gatekeeper
will warn on first run.
See CHANGELOG.md
for what changed.
Full Changelog: v5.1.2...v5.1.3
v5.1.2
Downloads
| Platform | File | Notes |
|---|---|---|
| Windows 10/11 | TelegramFreeRich-Setup-*.exe |
Installer, per user — no admin rights needed |
| Windows 10/11 | TelegramFreeRich-*-portable.exe |
Runs as-is, nothing to install or uninstall |
| Linux | TelegramFreeRich-*.AppImage |
chmod +x and run |
Both packages are unsigned; Windows SmartScreen and macOS Gatekeeper
will warn on first run.
See CHANGELOG.md
for what changed.
Full Changelog: v5.1.1...v5.1.2


