telegramdesktop/tdesktop/public-canary • 74503d9 • 1 files, +26/-10
Extracted shared video encoder setup from H264 encoder.
telegramdesktop/tdesktop/public-canary • cb897b2 • 2 files, +7/-3
Added VP9 encoder and webm muxer to ffmpeg build configs.
telegramdesktop/tdesktop/public-canary • 46be7b3 • 2 files, +150/-20
Added webm sticker output mode to video encoder.
telegramdesktop/tdesktop/public-canary • 181a39f • 7 files, +332/-69
Added adapting video stickers into custom emoji.
Related commit: 9895e5bb89.
#tdesktop
Extracted shared video encoder setup from H264 encoder.
telegramdesktop/tdesktop/public-canary • cb897b2 • 2 files, +7/-3
Added VP9 encoder and webm muxer to ffmpeg build configs.
telegramdesktop/tdesktop/public-canary • 46be7b3 • 2 files, +150/-20
Added webm sticker output mode to video encoder.
telegramdesktop/tdesktop/public-canary • 181a39f • 7 files, +332/-69
Added adapting video stickers into custom emoji.
Related commit: 9895e5bb89.
#tdesktop
🫡4🤨1
morethanwords/tweb/master • ef41b29 • 183 files, +7649/-4673
Migrate legacy rows to Solid RowTsx
#webk
Migrate legacy rows to Solid RowTsx
#webk
🫡4
telegramdesktop/tdesktop/dev • 70f4f42 • 1 files, +1/-1
Fixed crash constructing a raced shared Lottie state.
A shared provider is destroyed by the first render() that fails, on the
renderer thread, while SharedState is constructed on a crl::async one -
so _shared could go away between valid() and construct(). Tolerate that
instead of asserting, and treat a missing cover as a failed animation:
the metadata copied at load time no longer describes such a state, and
frameForPaint() would have asserted on its null frame later on.
telegramdesktop/tdesktop/dev • 50efdbc • 1 files, +8/-1
Guard enlarging a group call video with no monitors.
videoEndpointLargeValue() fires on data, not on user input, so it can
reach enlargeVideo() during the interval when the last monitor is gone
and QWidget::screen() is nullptr.
telegramdesktop/tdesktop/dev • 8bcbab7 • 1 files, +5/-1
Show the moved service message in its new topic.
The half beside applyItemRemoved() was missing: the edited item left the
old topic but was never offered to the new one, so its preview and order
in the topic list stayed stale until a reload.
telegramdesktop/tdesktop/dev • 23b6c1b • 1 files, +1/-1
Destroy a removed menu item before its action.
An item reads action() while it is being torn down, so removeAction()
deleting the action first left it pointing at freed memory for the whole
widget destructor. clearActions() and clearLastSeparator() already do it
in this order.
telegramdesktop/tdesktop/dev • 9732805 • 1 files, +1/-1
Don't clear metadata through a null display updater.
init() registers the ButtonPressed handler before it fills in the display
updater, so an E_OUTOFMEMORY in between leaves the token set and the
updater null - and the destructor takes exactly that branch, calling
ClearAll() on a null projected interface at process exit.
telegramdesktop/tdesktop/dev • 7f65351 • 2 files, +12/-4
Destroy the info controller with its content widgets.
createMemento() freed the Controller while _content lived on, and the
content widgets hold it by a raw pointer: MainWidget::showHistory takes
the memento, runs a whole HistoryWidget::showHistory - which reaches
itemVisibilitiesUpdated() and the still-subscribed media list - and only
then destroys the section. The nulling was never a lifetime requirement,
just the "memento already taken" flag showInternal() reads, so make that
a flag and let the controller die with the widget after _content.
telegramdesktop/tdesktop/dev • 4023790 • 1 files, +1/-1
Update lib_ui.
#tdesktop
Fixed crash constructing a raced shared Lottie state.
A shared provider is destroyed by the first render() that fails, on the
renderer thread, while SharedState is constructed on a crl::async one -
so _shared could go away between valid() and construct(). Tolerate that
instead of asserting, and treat a missing cover as a failed animation:
the metadata copied at load time no longer describes such a state, and
frameForPaint() would have asserted on its null frame later on.
telegramdesktop/tdesktop/dev • 50efdbc • 1 files, +8/-1
Guard enlarging a group call video with no monitors.
videoEndpointLargeValue() fires on data, not on user input, so it can
reach enlargeVideo() during the interval when the last monitor is gone
and QWidget::screen() is nullptr.
telegramdesktop/tdesktop/dev • 8bcbab7 • 1 files, +5/-1
Show the moved service message in its new topic.
The half beside applyItemRemoved() was missing: the edited item left the
old topic but was never offered to the new one, so its preview and order
in the topic list stayed stale until a reload.
telegramdesktop/tdesktop/dev • 23b6c1b • 1 files, +1/-1
Destroy a removed menu item before its action.
An item reads action() while it is being torn down, so removeAction()
deleting the action first left it pointing at freed memory for the whole
widget destructor. clearActions() and clearLastSeparator() already do it
in this order.
telegramdesktop/tdesktop/dev • 9732805 • 1 files, +1/-1
Don't clear metadata through a null display updater.
init() registers the ButtonPressed handler before it fills in the display
updater, so an E_OUTOFMEMORY in between leaves the token set and the
updater null - and the destructor takes exactly that branch, calling
ClearAll() on a null projected interface at process exit.
telegramdesktop/tdesktop/dev • 7f65351 • 2 files, +12/-4
Destroy the info controller with its content widgets.
createMemento() freed the Controller while _content lived on, and the
content widgets hold it by a raw pointer: MainWidget::showHistory takes
the memento, runs a whole HistoryWidget::showHistory - which reaches
itemVisibilitiesUpdated() and the still-subscribed media list - and only
then destroys the section. The nulling was never a lifetime requirement,
just the "memento already taken" flag showInternal() reads, so make that
a flag and let the controller die with the widget after _content.
telegramdesktop/tdesktop/dev • 4023790 • 1 files, +1/-1
Update lib_ui.
#tdesktop
🫡3
telegramdesktop/tdesktop/dev • ba23d84 • 1 files, +3/-1
Fixed nosound flag dropping animated attribute from sent GIFs.
Regression was introduced in fe7e967258.
telegramdesktop/tdesktop/dev • 3fe5164 • 1 files, +7/-4
Added mp4 conversion for quicktime videos sent as GIFs.
Related commit: fe7e967258.
telegramdesktop/tdesktop/dev • 049b4ad • 2 files, +6/-0
Added getter of automatic clear time to emoji statuses.
telegramdesktop/tdesktop/dev • 2661216 • 8 files, +137/-0
Added emoji status actions to custom emoji context menu.
#tdesktop
Fixed nosound flag dropping animated attribute from sent GIFs.
Regression was introduced in fe7e967258.
telegramdesktop/tdesktop/dev • 3fe5164 • 1 files, +7/-4
Added mp4 conversion for quicktime videos sent as GIFs.
Related commit: fe7e967258.
telegramdesktop/tdesktop/dev • 049b4ad • 2 files, +6/-0
Added getter of automatic clear time to emoji statuses.
telegramdesktop/tdesktop/dev • 2661216 • 8 files, +137/-0
Added emoji status actions to custom emoji context menu.
#tdesktop
🫡4🤝1
UnigramDev/Unigram/develop • f902c66 • 8 files, +52/-1
Toast when adding/removing from a folder
UnigramDev/Unigram/develop • 40f235a • 4 files, +68/-11
Add a solution for the Win32 flavour
UnigramDev/Unigram/develop • 9b3d428 • 6 files, +28/-6
Windows Hello support in Win32 project
UnigramDev/Unigram/develop • e12bb7f • 1 files, +0/-1
Don't clear passcode from session closed handler
UnigramDev/Unigram/develop • b82f6cf • 15 files, +2046/-1868
Reorganize extensions
UnigramDev/Unigram/develop • 708a738 • 1 files, +31/-2
Fix parsing spaces in html paste
UnigramDev/Unigram/develop • 5182e58 • 5 files, +1/-96
Remove dead code from the extension helpers
UnigramDev/Unigram/develop • bd846e9 • 4 files, +46/-108
Collapse duplicated extension overloads
UnigramDev/Unigram/develop • 0d6bfb0 • 1 files, +123/-33
Reset pooled spans and bound the text element pool
UnigramDev/Unigram/develop • 1278bc5 • 1 files, +127/-75
Fix search collection asking for more items forever
UnigramDev/Unigram/develop • 1a078d0 • 57 files, +1413/-284
Replace Rg.DiffUtils with an in-tree diff reader
UnigramDev/Unigram/develop • e949899 • 1 files, +35/-0
Hash the stowed origin trace into the crash group
UnigramDev/Unigram/develop • 88c5aa5 • 2 files, +16/-1
Fix null ref
UnigramDev/Unigram/develop • 99bb3f1 • 64 files, +428/-549
Merge MvxObservableCollection into DiffObservableCollection
UnigramDev/Unigram/develop • d6ecdaa • 2 files, +3/-11
Remove ToTimestampMilliseconds
#unigram
Toast when adding/removing from a folder
UnigramDev/Unigram/develop • 40f235a • 4 files, +68/-11
Add a solution for the Win32 flavour
UnigramDev/Unigram/develop • 9b3d428 • 6 files, +28/-6
Windows Hello support in Win32 project
UnigramDev/Unigram/develop • e12bb7f • 1 files, +0/-1
Don't clear passcode from session closed handler
UnigramDev/Unigram/develop • b82f6cf • 15 files, +2046/-1868
Reorganize extensions
UnigramDev/Unigram/develop • 708a738 • 1 files, +31/-2
Fix parsing spaces in html paste
UnigramDev/Unigram/develop • 5182e58 • 5 files, +1/-96
Remove dead code from the extension helpers
UnigramDev/Unigram/develop • bd846e9 • 4 files, +46/-108
Collapse duplicated extension overloads
UnigramDev/Unigram/develop • 0d6bfb0 • 1 files, +123/-33
Reset pooled spans and bound the text element pool
UnigramDev/Unigram/develop • 1278bc5 • 1 files, +127/-75
Fix search collection asking for more items forever
UnigramDev/Unigram/develop • 1a078d0 • 57 files, +1413/-284
Replace Rg.DiffUtils with an in-tree diff reader
UnigramDev/Unigram/develop • e949899 • 1 files, +35/-0
Hash the stowed origin trace into the crash group
UnigramDev/Unigram/develop • 88c5aa5 • 2 files, +16/-1
Fix null ref
UnigramDev/Unigram/develop • 99bb3f1 • 64 files, +428/-549
Merge MvxObservableCollection into DiffObservableCollection
UnigramDev/Unigram/develop • d6ecdaa • 2 files, +3/-11
Remove ToTimestampMilliseconds
#unigram
UnigramDev/Unigram/streaming-download-buttons • 6736c6e • 3 files, +73/-0
Track the files a reader is streaming
UnigramDev/Unigram/streaming-download-buttons • bb7a503 • 13 files, +181/-138
Hide a download that only feeds a reader from the file buttons
#unigram
Track the files a reader is streaming
UnigramDev/Unigram/streaming-download-buttons • bb7a503 • 13 files, +181/-138
Hide a download that only feeds a reader from the file buttons
#unigram
UnigramDev/Unigram/streaming-download-buttons • f8a6759 • 3 files, +73/-0
Track the files a reader is streaming
UnigramDev/Unigram/streaming-download-buttons • 278c0a1 • 13 files, +181/-138
Hide a download that only feeds a reader from the file buttons
#unigram
Track the files a reader is streaming
UnigramDev/Unigram/streaming-download-buttons • 278c0a1 • 13 files, +181/-138
Hide a download that only feeds a reader from the file buttons
#unigram
UnigramDev/Unigram/incremental-loading-terminates • b21d133 • 1 files, +14/-7
Stop the reaction list asking for more items forever
#unigram
Stop the reaction list asking for more items forever
#unigram
UnigramDev/Unigram/video-chat-aliases-itemssource • 5d2aea8 • 1 files, +5/-1
Pass the projected sender vector to VideoChatAliasesPopup
#unigram
Pass the projected sender vector to VideoChatAliasesPopup
#unigram
morethanwords/tweb/master • 882c48a • 1 files, +10/-0
Fix stale forum avatar unread badge
morethanwords/tweb/master • e934b90 • 3 files, +4/-5
Remove ripple from archive and community rows
morethanwords/tweb/master • 8f6b380 • 9 files, +152/-61
Show forum membership actions
morethanwords/tweb/master • 119c827 • 3 files, +65/-83
Align chat actions plate with translation layout
morethanwords/tweb/master • 1cb8bb8 • 9 files, +513/-203
Use thread separators instead of topic chips
morethanwords/tweb/master • 1d0e373 • 11 files, +218/-64
Pinned message plate: thread-scoped everywhere, no flicker
Opening a forum topic flashed the plate with the channel-wide pin: the initial
hint came from `fullPeer.pinned_msg_id` while the plate's own list is fetched
with `threadId`, so a topic with no pins revealed the plate and hid it again
one task later (and shifted `--pinned-floating-height` with it).
topbar: seed the hint only when there is no threadId; key the staged setup by
peer + thread (on mobile one chat instance is reused across peer changes, so
peerId alone kept the previous topic's plate); pass threadId into the pinned
tab and its title counter; drop the eagerly created throwaway plate
pinnedMessage: clear pinnedMid/pinnedIndex when the list resolves to empty, so
no phantom hint is saved into ChatSavedPosition and re-flashed next open
Pinning while sitting at the end of the chat kept the previous pin with a
bumped counter: the `peer_pinned_messages` anchor was unconditional. Anchor
only while the user is actually walking the pin list (locked /
waitForScrollBottom) and not already at the end of the history.
Rest of the review of the plate:
- forum: unpin-all / hide are thread-scoped too (top_msg_id, thread-keyed
hiddenPinnedMessages, thread-filtered local pFlags.pinned sweep), and both
pin events carry threadId so a change in one topic no longer resets the
plate of every other open topic
- chat: isPinnedMessagesNeeded() dropped the stale `|| isForum`, which put a
plate inside a forum's own pinned-messages tab (and scheduled, and search)
- getPinnedMessage remembers an empty list; testMid mirrors setCorrectIndex's
no-pins guard, so a jump-to-message in a chat without pins stops refetching
- _setPinnedMessage takes a render seq so an older run can't commit over a
newer pin; destroy() cancels the debounce, throttle and leaving-button
timers; the stale dataset.mid is cleared when nothing is pinned
- getCurrentIndexPromise is reset before the trailing testMid/setCorrectIndex
so a fetch they start isn't orphaned
- followPinnedMessage falls back to mids[0] when pinnedMaxMid isn't known yet,
instead of wrapping onto the oldest pin
- setCorrectIndex returns for static (Discussion) plates instead of doing an
elementFromPoint reflow on every throttled scroll
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
Fix stale forum avatar unread badge
morethanwords/tweb/master • e934b90 • 3 files, +4/-5
Remove ripple from archive and community rows
morethanwords/tweb/master • 8f6b380 • 9 files, +152/-61
Show forum membership actions
morethanwords/tweb/master • 119c827 • 3 files, +65/-83
Align chat actions plate with translation layout
morethanwords/tweb/master • 1cb8bb8 • 9 files, +513/-203
Use thread separators instead of topic chips
morethanwords/tweb/master • 1d0e373 • 11 files, +218/-64
Pinned message plate: thread-scoped everywhere, no flicker
Opening a forum topic flashed the plate with the channel-wide pin: the initial
hint came from `fullPeer.pinned_msg_id` while the plate's own list is fetched
with `threadId`, so a topic with no pins revealed the plate and hid it again
one task later (and shifted `--pinned-floating-height` with it).
topbar: seed the hint only when there is no threadId; key the staged setup by
peer + thread (on mobile one chat instance is reused across peer changes, so
peerId alone kept the previous topic's plate); pass threadId into the pinned
tab and its title counter; drop the eagerly created throwaway plate
pinnedMessage: clear pinnedMid/pinnedIndex when the list resolves to empty, so
no phantom hint is saved into ChatSavedPosition and re-flashed next open
Pinning while sitting at the end of the chat kept the previous pin with a
bumped counter: the `peer_pinned_messages` anchor was unconditional. Anchor
only while the user is actually walking the pin list (locked /
waitForScrollBottom) and not already at the end of the history.
Rest of the review of the plate:
- forum: unpin-all / hide are thread-scoped too (top_msg_id, thread-keyed
hiddenPinnedMessages, thread-filtered local pFlags.pinned sweep), and both
pin events carry threadId so a change in one topic no longer resets the
plate of every other open topic
- chat: isPinnedMessagesNeeded() dropped the stale `|| isForum`, which put a
plate inside a forum's own pinned-messages tab (and scheduled, and search)
- getPinnedMessage remembers an empty list; testMid mirrors setCorrectIndex's
no-pins guard, so a jump-to-message in a chat without pins stops refetching
- _setPinnedMessage takes a render seq so an older run can't commit over a
newer pin; destroy() cancels the debounce, throttle and leaving-button
timers; the stale dataset.mid is cleared when nothing is pinned
- getCurrentIndexPromise is reset before the trailing testMid/setCorrectIndex
so a fetch they start isn't orphaned
- followPinnedMessage falls back to mids[0] when pinnedMaxMid isn't known yet,
instead of wrapping onto the oldest pin
- setCorrectIndex returns for static (Discussion) plates instead of doing an
elementFromPoint reflow on every throttled scroll
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
🫡3
morethanwords/tweb/master • cc42eb7 • 1 files, +8/-7
Let the link preview be dismissed back to the reply plate
Quoting a message and then typing a link left the plate stuck on the web page:
neither Escape, nor the cross, nor "Remove preview" could get rid of it.
setTopInfo({type: 'webpage'}) only repaints the plate - helperType stays
'reply' - so onHelperCancel restores the previous helper by calling
helperFunc(). But willSendWebPage was dropped only AFTER that call, and
setTopInfo bails out early on `willSendWebPage && type === 'reply'`, so the
reply was never repainted: the plate kept showing a preview that was already
gone from the state. setCurrentHover got an undefined element along the way,
which also killed the hover menu holding "Remove preview" - hence "stuck".
Drop willSendWebPage before restoring the helper; lastUrl / noWebPage are
still restored afterwards, since setTopInfo's clearHelper resets them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
morethanwords/tweb/master • f30c242 • 3 files, +151/-26
Offer Reopen Topic in the chat actions plate
A closed forum topic gave a manager no way back: the input stayed writable
(canSendToPeer lets canManageTopic through) but reopening was buried in the
chat-list context menu. tdesktop puts a TopicReopenBar right in the bar stack
that already carries the peer-settings actions, so the same plate carries it
here.
dialogsStorage.canReopenTopic(peerId, threadId) composes the two halves of
tdesktop's state - the topic is closed, and we may manage it - into one sync
read, so the UI asks once instead of fetching the topic and then asking about
rights.
actions plate:
- the peer-settings actions and the reopen action are now independent halves
recombined by applyButtons(), which decides the visible list (reopen first)
and the hidden state synchronously - the peer-change path keeps committing
in one go, no flicker
- the close button renders only for the peer-settings half: tdesktop's reopen
bar has no cross, and hidePeerSettingsBar would be meaningless there.
Dismissing now clears only that half, so a still-closed topic keeps its
button
- a lone button with no close beside it spans the plate (is-single) instead of
sitting in the centred pill width that reserves an end slot for the cross
- state follows the topic live: dialogs_multiupdate carries the closed flag
(it arrives as a messageActionTopicEdit service message) and chat_update
covers rights changing under us, which is what tdesktop watches
adminRightsValue for
- gated to ChatType.Chat with a thread on a chat peer, so it can't surface in
the pinned/discussion/saved views
The topic check joins the existing acked getPeerSettings call, and it answers
from worker cache, so the chat-open batch stays uncached-round-trip free.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
Let the link preview be dismissed back to the reply plate
Quoting a message and then typing a link left the plate stuck on the web page:
neither Escape, nor the cross, nor "Remove preview" could get rid of it.
setTopInfo({type: 'webpage'}) only repaints the plate - helperType stays
'reply' - so onHelperCancel restores the previous helper by calling
helperFunc(). But willSendWebPage was dropped only AFTER that call, and
setTopInfo bails out early on `willSendWebPage && type === 'reply'`, so the
reply was never repainted: the plate kept showing a preview that was already
gone from the state. setCurrentHover got an undefined element along the way,
which also killed the hover menu holding "Remove preview" - hence "stuck".
Drop willSendWebPage before restoring the helper; lastUrl / noWebPage are
still restored afterwards, since setTopInfo's clearHelper resets them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
morethanwords/tweb/master • f30c242 • 3 files, +151/-26
Offer Reopen Topic in the chat actions plate
A closed forum topic gave a manager no way back: the input stayed writable
(canSendToPeer lets canManageTopic through) but reopening was buried in the
chat-list context menu. tdesktop puts a TopicReopenBar right in the bar stack
that already carries the peer-settings actions, so the same plate carries it
here.
dialogsStorage.canReopenTopic(peerId, threadId) composes the two halves of
tdesktop's state - the topic is closed, and we may manage it - into one sync
read, so the UI asks once instead of fetching the topic and then asking about
rights.
actions plate:
- the peer-settings actions and the reopen action are now independent halves
recombined by applyButtons(), which decides the visible list (reopen first)
and the hidden state synchronously - the peer-change path keeps committing
in one go, no flicker
- the close button renders only for the peer-settings half: tdesktop's reopen
bar has no cross, and hidePeerSettingsBar would be meaningless there.
Dismissing now clears only that half, so a still-closed topic keeps its
button
- a lone button with no close beside it spans the plate (is-single) instead of
sitting in the centred pill width that reserves an end slot for the cross
- state follows the topic live: dialogs_multiupdate carries the closed flag
(it arrives as a messageActionTopicEdit service message) and chat_update
covers rights changing under us, which is what tdesktop watches
adminRightsValue for
- gated to ChatType.Chat with a thread on a chat peer, so it can't surface in
the pinned/discussion/saved views
The topic check joins the existing acked getPeerSettings call, and it answers
from worker cache, so the chat-open batch stays uncached-round-trip free.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
🫡3
morethanwords/tweb/master • 1f060db • 5 files, +342/-93
Page forum topics by server-order offsets, immune to drafts
A topic draft injects its topic into the topic-list folder on startup
('draft_updated' -> getForumTopicById), and the next-page offsets were
derived from the tail of the locally sorted list - so the very first
messages.getForumTopics request could start deep in the list, never
loading everything above the drafted topic, and a mid-list draft punched
a permanent hole below the loaded frontier. Offsets now advance strictly
in the server's response order, per forum (tdesktop's model); only
server search still pages by its own results' tail. Also stop
double-counting server-counted topics in a virtual folder's count.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
morethanwords/tweb/master • 173f3c6 • 1 files, +8/-4
Play the round video while it uploads
12b30e902 stopped an uploading video bubble from autoplaying under the
progress spinner: the autoplay attribute is suppressed while
message.uploadingFileName is set, and playback resumes when the upload
promise settles. Round videos were excluded from both halves, on the
assumption that their is_outgoing handling covers it — but that path
(divRound.onLoad) only wires up the global, with-sound media element.
The looping muted preview inside the circle is the plain inline <video>,
which was left with autoplay=false and paused until the bubble got
re-rendered, i.e. until the chat was reopened. Scrolling away and back
did not help either: animationIntersector only resumes players whose
autoplay is set.
A round video now keeps its autoplay attribute through the upload, as
the official clients do (tdesktop's autoplayEligible only skips a file
that is still 'preparing'), so the circle plays from the moment it is
sent. A regular video would just play under the spinner, so it still
waits — and when its upload completes it now gets the attribute back
instead of a bare play(), so the intersector picks it up again after it
scrolls out of view.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
Page forum topics by server-order offsets, immune to drafts
A topic draft injects its topic into the topic-list folder on startup
('draft_updated' -> getForumTopicById), and the next-page offsets were
derived from the tail of the locally sorted list - so the very first
messages.getForumTopics request could start deep in the list, never
loading everything above the drafted topic, and a mid-list draft punched
a permanent hole below the loaded frontier. Offsets now advance strictly
in the server's response order, per forum (tdesktop's model); only
server search still pages by its own results' tail. Also stop
double-counting server-counted topics in a virtual folder's count.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
morethanwords/tweb/master • 173f3c6 • 1 files, +8/-4
Play the round video while it uploads
12b30e902 stopped an uploading video bubble from autoplaying under the
progress spinner: the autoplay attribute is suppressed while
message.uploadingFileName is set, and playback resumes when the upload
promise settles. Round videos were excluded from both halves, on the
assumption that their is_outgoing handling covers it — but that path
(divRound.onLoad) only wires up the global, with-sound media element.
The looping muted preview inside the circle is the plain inline <video>,
which was left with autoplay=false and paused until the bubble got
re-rendered, i.e. until the chat was reopened. Scrolling away and back
did not help either: animationIntersector only resumes players whose
autoplay is set.
A round video now keeps its autoplay attribute through the upload, as
the official clients do (tdesktop's autoplayEligible only skips a file
that is still 'preparing'), so the circle plays from the moment it is
sent. A regular video would just play under the spinner, so it still
waits — and when its upload completes it now gets the attribute back
instead of a bare play(), so the intersector picks it up again after it
scrolls out of view.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
🫡3
UnigramDev/Unigram/data-auto-bind-back-guard • cf5b360 • 1 files, +7/-0
Skip the auto-download limit bind-back when there is no view model
#unigram
Skip the auto-download limit bind-back when there is no view model
#unigram
UnigramDev/Unigram/translate-more-system-messages • 753a746 • 1 files, +5/-0
Translate two more wrong-thread and three more no-interface messages
#unigram
Translate two more wrong-thread and three more no-interface messages
#unigram
UnigramDev/Unigram/data-auto-bind-back-guard • 8bdd7a2 • 1 files, +4/-2
Say why the bind-back needs the null check
#unigram
Say why the bind-back needs the null check
#unigram
morethanwords/tweb/master • d5c66a0 • 9 files, +282/-136
Update tlottie and ship its no-SIMD build
Repin the vendored renderer to dkaraush/tlottie cbfaf4fa, which now builds
the same sources twice - with and without `-C target-feature=simd128`.
Both artifacts are vendored, and lottieLoader hands the scalar one to
browsers that fail IS_WEB_ASSEMBLY_SIMD_SUPPORTED, so stickers stay
animated on Chrome 75-90, Firefox 79-88 and Safari 15-16.3 instead of
freezing on their static thumbnail.
Which build runs is now separate from whether lottie runs at all: apart
from simd128 both need only bulk-memory, sign-extension and non-trapping
float-to-int, so the NO_WASM gates moved to a new probe for exactly those
(the shared validate() guard is factored out of both environment flags).
The vendoring script takes the upstream examples/web directory, verifies
each variant against its own source and stripped-output checksum, and
refuses a binary whose target_features contradict the expected variant.
Both builds render frame-identical output - the test asserts it across
every bundled asset and all six Fitz tones, so the golden hashes are
unchanged by the renderer update.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
Update tlottie and ship its no-SIMD build
Repin the vendored renderer to dkaraush/tlottie cbfaf4fa, which now builds
the same sources twice - with and without `-C target-feature=simd128`.
Both artifacts are vendored, and lottieLoader hands the scalar one to
browsers that fail IS_WEB_ASSEMBLY_SIMD_SUPPORTED, so stickers stay
animated on Chrome 75-90, Firefox 79-88 and Safari 15-16.3 instead of
freezing on their static thumbnail.
Which build runs is now separate from whether lottie runs at all: apart
from simd128 both need only bulk-memory, sign-extension and non-trapping
float-to-int, so the NO_WASM gates moved to a new probe for exactly those
(the shared validate() guard is factored out of both environment flags).
The vendoring script takes the upstream examples/web directory, verifies
each variant against its own source and stripped-output checksum, and
refuses a binary whose target_features contradict the expected variant.
Both builds render frame-identical output - the test asserts it across
every bundled asset and all six Fitz tones, so the golden hashes are
unchanged by the renderer update.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
🫡3
telegramdesktop/tdesktop/public-canary • a2a664b • 1 files, +1/-1
Fixed crash constructing a raced shared Lottie state.
A shared provider is destroyed by the first render() that fails, on the
renderer thread, while SharedState is constructed on a crl::async one -
so _shared could go away between valid() and construct(). Tolerate that
instead of asserting, and treat a missing cover as a failed animation:
the metadata copied at load time no longer describes such a state, and
frameForPaint() would have asserted on its null frame later on.
telegramdesktop/tdesktop/public-canary • 9a50ddd • 1 files, +8/-1
Guard enlarging a group call video with no monitors.
videoEndpointLargeValue() fires on data, not on user input, so it can
reach enlargeVideo() during the interval when the last monitor is gone
and QWidget::screen() is nullptr.
telegramdesktop/tdesktop/public-canary • 481d5bd • 1 files, +5/-1
Show the moved service message in its new topic.
The half beside applyItemRemoved() was missing: the edited item left the
old topic but was never offered to the new one, so its preview and order
in the topic list stayed stale until a reload.
telegramdesktop/tdesktop/public-canary • 320d0c6 • 1 files, +1/-1
Destroy a removed menu item before its action.
An item reads action() while it is being torn down, so removeAction()
deleting the action first left it pointing at freed memory for the whole
widget destructor. clearActions() and clearLastSeparator() already do it
in this order.
telegramdesktop/tdesktop/public-canary • 6c1a17a • 1 files, +1/-1
Don't clear metadata through a null display updater.
init() registers the ButtonPressed handler before it fills in the display
updater, so an E_OUTOFMEMORY in between leaves the token set and the
updater null - and the destructor takes exactly that branch, calling
ClearAll() on a null projected interface at process exit.
telegramdesktop/tdesktop/public-canary • 31712e9 • 2 files, +12/-4
Destroy the info controller with its content widgets.
createMemento() freed the Controller while _content lived on, and the
content widgets hold it by a raw pointer: MainWidget::showHistory takes
the memento, runs a whole HistoryWidget::showHistory - which reaches
itemVisibilitiesUpdated() and the still-subscribed media list - and only
then destroys the section. The nulling was never a lifetime requirement,
just the "memento already taken" flag showInternal() reads, so make that
a flag and let the controller die with the widget after _content.
telegramdesktop/tdesktop/public-canary • 8265059 • 1 files, +1/-1
Update lib_ui.
#tdesktop
Fixed crash constructing a raced shared Lottie state.
A shared provider is destroyed by the first render() that fails, on the
renderer thread, while SharedState is constructed on a crl::async one -
so _shared could go away between valid() and construct(). Tolerate that
instead of asserting, and treat a missing cover as a failed animation:
the metadata copied at load time no longer describes such a state, and
frameForPaint() would have asserted on its null frame later on.
telegramdesktop/tdesktop/public-canary • 9a50ddd • 1 files, +8/-1
Guard enlarging a group call video with no monitors.
videoEndpointLargeValue() fires on data, not on user input, so it can
reach enlargeVideo() during the interval when the last monitor is gone
and QWidget::screen() is nullptr.
telegramdesktop/tdesktop/public-canary • 481d5bd • 1 files, +5/-1
Show the moved service message in its new topic.
The half beside applyItemRemoved() was missing: the edited item left the
old topic but was never offered to the new one, so its preview and order
in the topic list stayed stale until a reload.
telegramdesktop/tdesktop/public-canary • 320d0c6 • 1 files, +1/-1
Destroy a removed menu item before its action.
An item reads action() while it is being torn down, so removeAction()
deleting the action first left it pointing at freed memory for the whole
widget destructor. clearActions() and clearLastSeparator() already do it
in this order.
telegramdesktop/tdesktop/public-canary • 6c1a17a • 1 files, +1/-1
Don't clear metadata through a null display updater.
init() registers the ButtonPressed handler before it fills in the display
updater, so an E_OUTOFMEMORY in between leaves the token set and the
updater null - and the destructor takes exactly that branch, calling
ClearAll() on a null projected interface at process exit.
telegramdesktop/tdesktop/public-canary • 31712e9 • 2 files, +12/-4
Destroy the info controller with its content widgets.
createMemento() freed the Controller while _content lived on, and the
content widgets hold it by a raw pointer: MainWidget::showHistory takes
the memento, runs a whole HistoryWidget::showHistory - which reaches
itemVisibilitiesUpdated() and the still-subscribed media list - and only
then destroys the section. The nulling was never a lifetime requirement,
just the "memento already taken" flag showInternal() reads, so make that
a flag and let the controller die with the widget after _content.
telegramdesktop/tdesktop/public-canary • 8265059 • 1 files, +1/-1
Update lib_ui.
#tdesktop
🫡3
telegramdesktop/tdesktop/public-canary • 50476a7 • 1 files, +3/-1
Fixed nosound flag dropping animated attribute from sent GIFs.
Regression was introduced in fe7e967258.
telegramdesktop/tdesktop/public-canary • 4da399d • 1 files, +7/-4
Added mp4 conversion for quicktime videos sent as GIFs.
Related commit: fe7e967258.
telegramdesktop/tdesktop/public-canary • d57be4d • 2 files, +6/-0
Added getter of automatic clear time to emoji statuses.
telegramdesktop/tdesktop/public-canary • 681abc1 • 8 files, +137/-0
Added emoji status actions to custom emoji context menu.
telegramdesktop/tdesktop/public-canary • 527f10e • 1 files, +3/-6
Returned reading of muted dialogs in mark as read for folders.
Related commit: 3abdc67424.
telegramdesktop/tdesktop/public-canary • 05c3f57 • 3 files, +3/-15
Replaced experimental option of muted dialogs with counter setting.
Related commit: 3abdc67424.
telegramdesktop/tdesktop/public-canary • c2a861f • 1 files, +10/-2
Added unread badge condition for mark as read of all chats.
Related commit: 3abdc67424.
telegramdesktop/tdesktop/public-canary • 9f95b22 • 1 files, +3/-1
Fixed shown time guard blocking left clicks in reactions selector.
Related commit: 164d3781ea.
telegramdesktop/tdesktop/public-canary • 1e887af • 1 files, +1/-1
Fixed width growth of profile section stack on visibility change.
Regression was introduced in 49dda200a1.
telegramdesktop/tdesktop/public-canary • d33f3ca • 1 files, +1/-1
Fixed extra width of text in info line of profile.
Related commit: c4f45c4b7c.
telegramdesktop/tdesktop/public-canary • 24cb561 • 4 files, +27/-0
Added demanded content width to markdown article.
telegramdesktop/tdesktop/public-canary • 2e1dd5a • 2 files, +22/-4
Added widening of rich message bubble to demanded content width.
#tdesktop
Fixed nosound flag dropping animated attribute from sent GIFs.
Regression was introduced in fe7e967258.
telegramdesktop/tdesktop/public-canary • 4da399d • 1 files, +7/-4
Added mp4 conversion for quicktime videos sent as GIFs.
Related commit: fe7e967258.
telegramdesktop/tdesktop/public-canary • d57be4d • 2 files, +6/-0
Added getter of automatic clear time to emoji statuses.
telegramdesktop/tdesktop/public-canary • 681abc1 • 8 files, +137/-0
Added emoji status actions to custom emoji context menu.
telegramdesktop/tdesktop/public-canary • 527f10e • 1 files, +3/-6
Returned reading of muted dialogs in mark as read for folders.
Related commit: 3abdc67424.
telegramdesktop/tdesktop/public-canary • 05c3f57 • 3 files, +3/-15
Replaced experimental option of muted dialogs with counter setting.
Related commit: 3abdc67424.
telegramdesktop/tdesktop/public-canary • c2a861f • 1 files, +10/-2
Added unread badge condition for mark as read of all chats.
Related commit: 3abdc67424.
telegramdesktop/tdesktop/public-canary • 9f95b22 • 1 files, +3/-1
Fixed shown time guard blocking left clicks in reactions selector.
Related commit: 164d3781ea.
telegramdesktop/tdesktop/public-canary • 1e887af • 1 files, +1/-1
Fixed width growth of profile section stack on visibility change.
Regression was introduced in 49dda200a1.
telegramdesktop/tdesktop/public-canary • d33f3ca • 1 files, +1/-1
Fixed extra width of text in info line of profile.
Related commit: c4f45c4b7c.
telegramdesktop/tdesktop/public-canary • 24cb561 • 4 files, +27/-0
Added demanded content width to markdown article.
telegramdesktop/tdesktop/public-canary • 2e1dd5a • 2 files, +22/-4
Added widening of rich message bubble to demanded content width.
#tdesktop
🫡3
telegramdesktop/tdesktop/public-canary • 9a04f2f • 1 files, +3/-1
Fixed horizontal scroll of quote with author in rich message.
Regression was introduced in af71b4c1c7.
telegramdesktop/tdesktop/public-canary • a611a60 • 4 files, +20/-2
Added archive job description to prepared files with box preview.
telegramdesktop/tdesktop/public-canary • 34da7c2 • 4 files, +565/-0
Added zip archive writer for folders and file sets.
telegramdesktop/tdesktop/public-canary • 008b963 • 7 files, +109/-17
Added archive writing to uploader with preparing progress in bubble.
telegramdesktop/tdesktop/public-canary • 34e1ede • 9 files, +83/-1
Added folder drop zones for archive and separate files sending.
telegramdesktop/tdesktop/public-canary • 5bf317f • 9 files, +50/-1
Added drop zone for archiving of multiple files into one archive.
telegramdesktop/tdesktop/public-canary • 48fbe51 • 6 files, +103/-3
Added archive drop mode for media files under keyboard modifier.
telegramdesktop/tdesktop/public-canary • f4118ab • 7 files, +66/-25
Added archive drop zone for folders and files in message editing.
telegramdesktop/tdesktop/public-canary • 09b8b04 • 3 files, +30/-4
Added folder drop zones with height limit to send files box.
#tdesktop
Fixed horizontal scroll of quote with author in rich message.
Regression was introduced in af71b4c1c7.
telegramdesktop/tdesktop/public-canary • a611a60 • 4 files, +20/-2
Added archive job description to prepared files with box preview.
telegramdesktop/tdesktop/public-canary • 34da7c2 • 4 files, +565/-0
Added zip archive writer for folders and file sets.
telegramdesktop/tdesktop/public-canary • 008b963 • 7 files, +109/-17
Added archive writing to uploader with preparing progress in bubble.
telegramdesktop/tdesktop/public-canary • 34e1ede • 9 files, +83/-1
Added folder drop zones for archive and separate files sending.
telegramdesktop/tdesktop/public-canary • 5bf317f • 9 files, +50/-1
Added drop zone for archiving of multiple files into one archive.
telegramdesktop/tdesktop/public-canary • 48fbe51 • 6 files, +103/-3
Added archive drop mode for media files under keyboard modifier.
telegramdesktop/tdesktop/public-canary • f4118ab • 7 files, +66/-25
Added archive drop zone for folders and files in message editing.
telegramdesktop/tdesktop/public-canary • 09b8b04 • 3 files, +30/-4
Added folder drop zones with height limit to send files box.
#tdesktop
🫡3
morethanwords/tweb/master • d3bf83c • 1 files, +21/-6
Fix day period rendering for locales that don't put it last
updateAmPm() obtained the AM/PM string by splitting the formatted time on
whitespace and taking index 1. That assumes the "12:00 AM" shape, which only
holds for locales placing the day period last, separated by a space.
Locales that place it first render "undefined", because the split yields a
single element (zh 上午12:34, ja 午後12:34 — no separator at all), or repeat
the time, because index 1 lands on the time itself (ko 오전 12:34, tr ÖÖ 12:34).
Locales whose day period contains a space get truncated (es/ca "12:34 p. m."
turns into "12:34 p.").
Read the dayPeriod part by type via formatToParts() instead, and remember
whether it comes first and which separator Intl uses, so the time is assembled
in the locale's own order.
Verified across 26 locales: the 6 broken ones now match Intl's native output,
the remaining 20 are byte-identical to before.
morethanwords/tweb/master • dae1293 • 9 files, +14/-7
Split the quote icon into quote and blockquote
The markup tooltip's quote button drew the block-quote mark - a vertical bar
with indented lines - which is what the formatting does, but not what the
button means next to bold/italic/spoiler. Give it a real pair of quotation
marks and keep the old glyph under its own name for the places that render
the quote block itself.
- assets/icons/quote.svg is now the quotation marks; its previous path moves
verbatim to assets/icons/blockquote.svg
- regenerated the tgico font (blockquote = eb7e, cache-buster akge1f)
- markupTooltip drops the ['quote', 'quote', 'quote_filled'] triple: the new
glyph has no filled variant, so the button no longer swaps icon when active
blockquote has no callers yet - it is meant for the rendered quote block
(see the commented-out --quote-icon in index.ts and Icon('quote_filled',
'quote-icon') in wrapRichText.ts), which stays as it is for now.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
Fix day period rendering for locales that don't put it last
updateAmPm() obtained the AM/PM string by splitting the formatted time on
whitespace and taking index 1. That assumes the "12:00 AM" shape, which only
holds for locales placing the day period last, separated by a space.
Locales that place it first render "undefined", because the split yields a
single element (zh 上午12:34, ja 午後12:34 — no separator at all), or repeat
the time, because index 1 lands on the time itself (ko 오전 12:34, tr ÖÖ 12:34).
Locales whose day period contains a space get truncated (es/ca "12:34 p. m."
turns into "12:34 p.").
Read the dayPeriod part by type via formatToParts() instead, and remember
whether it comes first and which separator Intl uses, so the time is assembled
in the locale's own order.
Verified across 26 locales: the 6 broken ones now match Intl's native output,
the remaining 20 are byte-identical to before.
morethanwords/tweb/master • dae1293 • 9 files, +14/-7
Split the quote icon into quote and blockquote
The markup tooltip's quote button drew the block-quote mark - a vertical bar
with indented lines - which is what the formatting does, but not what the
button means next to bold/italic/spoiler. Give it a real pair of quotation
marks and keep the old glyph under its own name for the places that render
the quote block itself.
- assets/icons/quote.svg is now the quotation marks; its previous path moves
verbatim to assets/icons/blockquote.svg
- regenerated the tgico font (blockquote = eb7e, cache-buster akge1f)
- markupTooltip drops the ['quote', 'quote', 'quote_filled'] triple: the new
glyph has no filled variant, so the button no longer swaps icon when active
blockquote has no callers yet - it is meant for the rendered quote block
(see the commented-out --quote-icon in index.ts and Icon('quote_filled',
'quote-icon') in wrapRichText.ts), which stays as it is for now.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#webk
🫡3
morethanwords/tweb/master • 36bf1a7 • 7 files, +391/-60
Complete the chat actions plate's peer-settings states
The plate only ever read four of the peer settings, so three states the other
clients show never appeared. Filling them in also meant replacing the flat flag
filter with the priority chain tdesktop's `ContactStatus::PeerState` walks — a
contact is only ever offered the share-phone bar, and the join-request line
takes the whole plate from everything below it.
share_contact -> "Share my phone number"
A contact who has us saved but cannot see our number. Confirms with our own
formatted number and their title, then the new appUsersManager.acceptContact()
(contacts.acceptContact + refreshPeerSettingsIfNeeded), then a toast; the bar
goes away on the server's updatePeerSettings, not locally.
request_chat_title/date/broadcast -> the join-request line
Not buttons but a tappable label - "X is an admin of Y, a group you requested
to join" - opening a box with the request date and a lone "I understand" that
hides the settings bar. No cross: there is no dismissable half here.
The label wraps, so the plate measures itself ('auto' height with a min-height
for the button rows) and applyState re-runs setFloating so the stack follows.
set_bot_photo -> "Set Profile Photo"
A bot we manage that has no photo, whose chat was empty the first time we
opened it this session. Everything but that last bit is on the cached user, so
a chat that cannot want the prompt costs no round-trip; the two session-scoped
caches mirror the fields tdesktop keeps on BotInfo. Its cross dismisses the
prompt locally and never touches the server-side bar.
Supporting bits:
- TopbarPlate.PrimaryButton gains `quiet` for a button that should carry the
plain text colour and a neutral hover instead of the primary tint, built the
same way `danger` already was
- topbar.editBot() opens the same tab as the profile's edit button
- the nine lang keys are the official ones from the other clients, so the
translations come from the langpack rather than staying English
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
morethanwords/tweb/master • f252a5e • 1 files, +25/-14
Harden the day-period probe after review
- Normalize U+202F/U+00A0 from formatToParts to a plain space: Chromium
keeps ICU's narrow no-break space in parts while normalizing format()
output, so the captured separator (and e.g. Spanish "p. m.") silently
changed timestamp bytes for nearly every trailing locale.
- Probe the same 2-digit skeleton update() renders: day-period position
is skeleton-dependent (Amharic is leading in h:mm but trailing in
hh:mm), so deriving structure from hour: 'numeric' could place the
day period on the wrong side of the zero-padded string.
- Reuse the AM part index for PM (one formatter has one pattern
skeleton), replace the throw-as-goto with an early return, and declare
the fallback values once.
- Roll back lastRequestedLangCode when a language-pack load fails so the
am/pm cache can't be derived from a language that was never applied.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
morethanwords/tweb/master • 064dc79 • 1 files, +36/-10
Merge pull request #703 from SliverKeigo/fix/day-period-non-english-locales
Fix day period rendering for locales that don't put it last
#webk
Complete the chat actions plate's peer-settings states
The plate only ever read four of the peer settings, so three states the other
clients show never appeared. Filling them in also meant replacing the flat flag
filter with the priority chain tdesktop's `ContactStatus::PeerState` walks — a
contact is only ever offered the share-phone bar, and the join-request line
takes the whole plate from everything below it.
share_contact -> "Share my phone number"
A contact who has us saved but cannot see our number. Confirms with our own
formatted number and their title, then the new appUsersManager.acceptContact()
(contacts.acceptContact + refreshPeerSettingsIfNeeded), then a toast; the bar
goes away on the server's updatePeerSettings, not locally.
request_chat_title/date/broadcast -> the join-request line
Not buttons but a tappable label - "X is an admin of Y, a group you requested
to join" - opening a box with the request date and a lone "I understand" that
hides the settings bar. No cross: there is no dismissable half here.
The label wraps, so the plate measures itself ('auto' height with a min-height
for the button rows) and applyState re-runs setFloating so the stack follows.
set_bot_photo -> "Set Profile Photo"
A bot we manage that has no photo, whose chat was empty the first time we
opened it this session. Everything but that last bit is on the cached user, so
a chat that cannot want the prompt costs no round-trip; the two session-scoped
caches mirror the fields tdesktop keeps on BotInfo. Its cross dismisses the
prompt locally and never touches the server-side bar.
Supporting bits:
- TopbarPlate.PrimaryButton gains `quiet` for a button that should carry the
plain text colour and a neutral hover instead of the primary tint, built the
same way `danger` already was
- topbar.editBot() opens the same tab as the profile's edit button
- the nine lang keys are the official ones from the other clients, so the
translations come from the langpack rather than staying English
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
morethanwords/tweb/master • f252a5e • 1 files, +25/-14
Harden the day-period probe after review
- Normalize U+202F/U+00A0 from formatToParts to a plain space: Chromium
keeps ICU's narrow no-break space in parts while normalizing format()
output, so the captured separator (and e.g. Spanish "p. m.") silently
changed timestamp bytes for nearly every trailing locale.
- Probe the same 2-digit skeleton update() renders: day-period position
is skeleton-dependent (Amharic is leading in h:mm but trailing in
hh:mm), so deriving structure from hour: 'numeric' could place the
day period on the wrong side of the zero-padded string.
- Reuse the AM part index for PM (one formatter has one pattern
skeleton), replace the throw-as-goto with an early return, and declare
the fallback values once.
- Roll back lastRequestedLangCode when a language-pack load fails so the
am/pm cache can't be derived from a language that was never applied.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
morethanwords/tweb/master • 064dc79 • 1 files, +36/-10
Merge pull request #703 from SliverKeigo/fix/day-period-non-english-locales
Fix day period rendering for locales that don't put it last
#webk
🫡3