Telegram github commits and releases
4.87K subscribers
601 files
19.2K links
Broadcast from the most important Telegram clients' repositories
Download Telegram
morethanwords/tweb/master6f0cc744 files, +480/-351
perf: run the bluff-spoiler simulation entirely inside the worker

The WebGL particles simulation is extracted from DotRenderer into a
DOM-free DotRendererCore that works on both HTMLCanvasElement and
OffscreenCanvas. For bluff spoilers the worker now owns the whole
render: it steps the simulation at 60fps on its own OffscreenCanvas,
encodes a frame every 4 ticks and posts ready data URLs - the main
thread no longer runs the rAF loop, the WebGL draws, or the
createImageBitmap copy; it only assigns the received mask to the
spoiler wrappers ~12 times per second.

Playback is driven by the existing animationIntersector callbacks
(play/pause messages start and stop the worker loop), so off-screen and
idle behavior is unchanged. Bubble text/image spoilers keep the
main-thread instance via the same core; browsers without WebGL in
OffscreenCanvas keep the previous main-thread-simulation path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

morethanwords/tweb/master9dd54fc3 files, +366/-24
perf: render media-spoiler dots inside a worker via transferred canvases

Each media spoiler's dots canvas now transfers control to a dedicated
worker that owns the 480x480 particles simulation (same DotRendererCore)
and draws every visible target at 60fps - the main thread no longer
runs the simulation loop or the per-target drawImage for photo/video
spoilers, paid-media covers and gift-link dots; it only forwards
play/pause from animationIntersector.

The click reveal is split: the worker animates the dots push-zoom and
the growing clipping hole, while the main thread keeps punching the
matching hole in the underlying thumbnail (that canvas already has a 2D
context and cannot be transferred) with the same duration and easing,
and resolves the caller's promise as before. drawClippingCircle moved
to dotRendererCore for both sides. Browsers without WebGL in
OffscreenCanvas keep the main-thread path untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

morethanwords/tweb/master0c505ec6 files, +440/-319
perf: merge spoiler rendering into one SharedWorker for all tabs

The two dedicated workers (bluff masks, media dots) are merged into a
single spoilerRenderer.worker that runs as a SharedWorker - every tab
feeds from the same simulations and one GL context, and a bluff mask is
encoded once and broadcast to all tabs that play it. The worker keeps
per-port state (playing flags, media targets), steps simulations only
while some port needs them, frees the GL resources when the last port
leaves, and respects ?noSharedWorker=1 / missing SharedWorker support
(Chrome Android < 120) by falling back to a per-tab dedicated worker
with the same script.

Tab lifetime is handled with a pagehide 'bye' plus the MessagePort
close event where supported; simulations are keyed by device pixel
ratio in case tabs live on different displays. The connection is
refcounted by its two consumers, so releasing bluff does not tear down
media and vice versa.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

#webk
🫡4
morethanwords/tweb/master001f3ed8 files, +175/-134
refactor: address spoiler-renderer review findings

- The connection module now owns the consumer lifecycle: retain() takes
the consumer's message listener and returns a scoped handle whose
release() unregisters it - the per-consumer listenerAdded flags and
the implicit 'who may send bye' contract are gone (only the module
sends 'bye': on dispose and on pagehide, registered once).
- A worker loading failure is now logged and flips new spoilers to the
main-thread fallback (isWorkerSimSupported consults the failure flag,
in-flight bluff encodes are unblocked via a synthesized
connection-error message).
- The worker prunes dpr-keyed simulations as soon as no connected tab
uses them instead of waiting for the last tab to leave.
- The duplicated target-canvas creation (classes, sizing, rotate/flip
transforms) is extracted into DotRenderer.createTargetCanvas.
- simpleEasing and applyColorOnContext moved into leaf helpers
(re-exported from their old homes) so the worker shares the exact
implementations instead of mirroring them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

#webk
🫡4
morethanwords/tweb/masterea3c5359 files, +468/-80
perf: move the bubble text-spoiler overlays into the spoiler worker

The last main-thread spoiler rendering is gone: the overlay canvas of a
bubble text spoiler now transfers control to the shared spoiler worker,
which draws the tinted particle chunks and animates the click unwrap
from the same text simulation that feeds the bluff masks. The main
thread keeps everything DOM-bound - measuring the line rects and
colors, hover/click handling, the visibility class machinery - and
pushes snapshots to the worker only when they change (the unwrap
progress signal still runs on main for the class toggles; the worker
mirrors the same curve for the pixels).

The displayed size of a transferred canvas has to be pinned via inline
CSS: the placeholder keeps its default 300x150 intrinsic size, so with
the worker-side resize alone the committed bitmap would stretch (the
legacy path derives it from the width/height attributes instead).

simpleEasing/unwrapEasing/defaultEasing move into a @helpers/easings
leaf so the worker shares the exact curves, and drawImageFromSource
accepts offscreen contexts. Browsers without WebGL in OffscreenCanvas
keep the previous main-thread overlay path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

#webk
🫡4
tdlib/td/master062f2601 files, +1/-1
Fix typo in animation.has_stickers documentation

#tdlib
🫡2
morethanwords/tweb/master5f9c0fb8 files, +92/-60
refactor: migrate from deprecated mp4-muxer to mediabunny

mp4-muxer is deprecated in favor of mediabunny. Muxer/ArrayBufferTarget
become Output/Mp4OutputFormat/BufferTarget, and chunks now go through
EncodedVideo/AudioPacketSources whose async add() calls are chained from
the sync encoder callbacks (decode order + backpressure), so finalize()
is async for both callers. The opus track config is no longer declared
upfront — it is deduced from the encoder metadata passed with the first
packet. frameRate is forwarded to the video track only when the caller
sets one, because mediabunny snaps timestamps to it (gifToVideo frames
sit off-grid). mediabunny's bundled dom-mediacapture-transform typings
narrow MediaStream.getVideoTracks() globally, hence the cast in
callInstanceBase.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

#webk
🫡3
morethanwords/tweb/master12b30e96 files, +267/-60
feat: convert .mov attachments to mp4 in the send popup

QuickTime files — the default macOS screen-recording/camera format — were
sent as plain documents in browsers that can't play video/quicktime
(Chrome on macOS), and even Safari sent them as .mov that recipients on
other platforms couldn't stream. Now they get the same treatment as GIFs:
conversion starts the moment the file lands in the new-media popup (after
the open animation finishes, so the heavy work doesn't jank it), with a
progress circle on the item and the send button locked until it's done.

The conversion (helpers/movToVideo) goes through mediabunny's Conversion:
H.264+AAC sources are remuxed without re-encoding (lossless, I/O-bound —
a 650MB file repackages in about a second), other codecs are transcoded
via WebCodecs to the universally playable pair; a track that can't be
carried over makes the conversion throw, falling back to the old document
behavior with the same error toast as GIFs. Eligibility is capped by the
user's upload limit (upload_max_fileparts default/premium = 2GB/4GB, read
from the cached app config); non-H.264 sources keep the media-editor
100MB cap instead, since a real transcode runs at roughly realtime.
Outputs over 512MB use moov-at-end instead of fastStart 'in-memory',
halving the memory peak.

A convertible .mov counts as media throughout the popup (routing, albums,
spoilers, paid-media and rights checks — keyed off the converted form,
video/mp4), in the paste/drop/share entry points, and is selectable in
the "Photo or Video" picker. The GIF conversion state maps are
generalized (convertedFiles/fileConversions/failedConversions) and shared
by both flows.

Polish that fell out of testing, also affecting shared video code:

- the uploaded/local video poster box grew from 320x240 (blurry on
retina, 135x240 for portrait) to 720 max per side, matching the media
editor's thumbnail cap, never upscaling a smaller source;
- attachFiles destroys the old items only after the new ones replace
them in the DOM — destroying upfront blanked the still-visible media
out for the whole rebuild (createVideo clears src on destroy);
- an uploading video bubble no longer autoplays under the progress
spinner: the autoplay attribute is suppressed while
message.uploadingFileName is set, and since the bubble isn't
re-rendered on message_sent, playback resumes when the upload promise
resolves (rounds keep their own is_outgoing handling).

Verified e2e in the preview: a generated h264+pcm .mov pasted into Saved
Messages converts (video copied, audio transcoded to AAC) and arrives as
a streamable video/mp4; a corrupt .mov falls back to a document with the
error toast; 162MB and 647MB files remux in ~1s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

#webk
🫡3
UnigramDev/Unigram/develop4a2df732 files, +0/-2
Remove dangling event handle

UnigramDev/Unigram/develop83448cb9 files, +218/-18
Supergroup guard bot settings

UnigramDev/Unigram/develop3db620423 files, +1358/-334
Rich messages improvements

UnigramDev/Unigram/develop41773a91 files, +1/-1
Update TDLib

UnigramDev/Unigram/develop70121171 files, +4/-0
Handle automatic decline

UnigramDev/Unigram/developf059eee5 files, +55/-16
Show rich messages in shared media

UnigramDev/Unigram/developb1d121b1 files, +8/-0
Update enum

UnigramDev/Unigram/develop4f43ba81 files, +10/-2
Delete ranges

UnigramDev/Unigram/develop0fd865e1 files, +6/-6
Fix native compilation

UnigramDev/Unigram/develop23c5d291 files, +143/-15
Improve text formatting

UnigramDev/Unigram/develop7789fa53 files, +38/-22
Update session api

UnigramDev/Unigram/develop29dab751 files, +1/-1
Bump version to 12.8

UnigramDev/Unigram/develop4ef4df61 files, +1/-1
Update microtex

UnigramDev/Unigram/developd9749d91 files, +1/-1
Ignore formulas in inline text

UnigramDev/Unigram/develop4c1b6d62 files, +257/-160
Rich messages improvements

#unigram
🫡2
UnigramDev/Unigram/develop7ad76471 files, +4/-2
Remove redundant log

#unigram
🫡2
telegramdesktop/tdesktop/dev8ca06bd1 files, +2/-2
Fix OpenGL in Windows builds.

telegramdesktop/tdesktop/dev7db0d5d1 files, +1/-1
Fix parsing some incorrect formulas.

#tdesktop
🫡3
morethanwords/tweb/masterc29dfcf1 files, +2/-2
Add .kml / .kmz as potentially IP-revealing.

#webk
🫡3
New telegramdesktop/tdesktop release: v6.9.3 (stable)

- Fix possible crash in formula parsing.
- Fix field resize after Undo/Redo.
- Fix OpenGL in Windows build.

#tdesktop
🫡3
telegramdesktop/tdesktop/dev82c29541 files, +1/-1
Fix content size checks after undo/redo.

telegramdesktop/tdesktop/dev3887c786 files, +21/-15
Version 6.9.3.

- Fix possible crash in formula parsing.
- Fix field resize after Undo/Redo.
- Fix OpenGL in Windows build.

#tdesktop
🫡3
tdlib/td/master912b29b6 files, +38/-27
Add source to get_message_content_object.

tdlib/td/master09177631 files, +1/-1
Fix spelling.

tdlib/td/master9ae32a31 files, +0/-3
unset CMAKE_FIND_ROOT_PATH_MODE_PROGRAM

tdlib/td/masterc0757dd1 files, +1/-1
Revert "Set CMAKE_MAKE_PROGRAM for iOS build"

This reverts commit 04adfc87deea4c804def118e88c89a08c388b32b.

tdlib/td/mastera17f87c1 files, +33/-33
Fix typos in API scheme docs

#tdlib
🫡3
telegramdesktop/tdesktop/dev49ff0bc1 files, +1/-1
Fixed usedId assignment logic in edit_todo_list_box

#tdesktop
🫡3
telegramdesktop/tdesktop/dev8f069241 files, +774/-669
Use heredoc in Dockerfile

telegramdesktop/tdesktop/devd9a42831 files, +1/-1
Compress debug info in Docker

That should decrease cache size a lot

telegramdesktop/tdesktop/dev6da54a21 files, +1/-2
Save dnf cache in Docker

telegramdesktop/tdesktop/dev6a87fe21 files, +55/-46
Use ccache in Docker

telegramdesktop/tdesktop/dev64dce781 files, +2/-0
Prevent cache invalidation by date/time in Docker

telegramdesktop/tdesktop/dev65712851 files, +13/-1
Use ccache for libraries in Linux action

telegramdesktop/tdesktop/dev999b28a1 files, +19/-3
Cache tdesktop itself in Linux action

#tdesktop
🫡3
telegramdesktop/tdesktop/dev2ed20833 files, +2/-3
Restore dispatch autodetection

telegramdesktop/tdesktop/devae167db3 files, +3/-3
Update patches

#tdesktop
🫡4
telegramdesktop/tdesktop/devc48631428 files, +27/-1
Avoid full Telegram target rebuild on version change

#tdesktop
🫡3
TelegramMessenger/tgcalls/developmentf3080201 files, +30/-0
InstanceV2ReferenceImpl: add 20s rolling connection-failure watchdog

Mirrors NativeNetworkingImpl::checkConnectionTimeout(): a 1s media-thread
timer latches _isFailed only after 20s of continuous disconnect, armed from
start() so never-connected calls are bounded too (previously they hung in
Reconnecting forever because legacy ICE state stays STATE_INIT with no
candidate pairs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

TelegramMessenger/tgcalls/developmentac59fdb1 files, +42/-15
InstanceV2ReferenceImpl: ICE-failed is no longer terminal; debounce Reconnecting

kIceConnectionFailed previously mapped straight to State::Failed, which the
app treats as a permanent drop - WebRTC raises it ~15s after all so-far-
created pairs time out, killing calls a late-trickled candidate could still
rescue. It now just marks the connection not-connected; Failed comes only
from the 20s watchdog (V2Impl parity). Disconnected->Reconnecting reporting
is debounced 2s so the ~2.5s legacy receiving-timeout blips stop surfacing
as reconnecting episodes. Adds an empty maybeRestartIce() stub (filled in
by the ICE-restart commit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

TelegramMessenger/tgcalls/development51438ad1 files, +19/-0
InstanceV2ReferenceImpl: caller-side RestartIce() on legacy ICE-failed

On kIceConnectionFailed (all so-far-created pairs write-timed-out) the
offerer now requests an ICE restart, rate-limited to once per 5s; the
existing onRenegotiationNeeded handler ships the restart offer and
GATHER_CONTINUALLY supplies fresh candidates. Previously the impl took no
recovery action. Callee side never restarts (avoids offer glare; failure
is symmetric so the offerer also observes it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

TelegramMessenger/tgcalls/developmente3069321 files, +6/-0
Merge commit '6926af015580a1377e1b1bcad191d076453192cb' into development

#tgcalls
🫡4
telegramdesktop/tdesktop/dev9cca0051 files, +10/-1
Fix order in auctions list hashing.

#tdesktop
🫡3