Repository navigation
feat(chat): выбор всех сообщений автора из контекстного меню - #115
Merged
Merged
Conversation
catboysense
force-pushed
the
feat/select-by-author-c9axz4
branch
from
October 20, 2026 05:23
f831075 to
b5a25b7
Compare
donutgramAuthorMessages листает messages.search по from_id (с историей мигрированной группы и в ветке, если она указана), сохраняет найденные сообщения в базу, как getMessagesLoadIfNecessary, и добавляет сохранённые удалённые. Автор без собственного access hash адресуется через своё сообщение. В секретном чате сообщения берутся из локальной базы.
catboysense
force-pushed
the
feat/select-by-author-c9axz4
branch
from
October 20, 2026 05:42
6d168e0 to
5596212
Compare
Пункт «Выбрать все сообщения: имя» («Выбрать все мои сообщения» на своём сообщении) загружает все сообщения автора с сервера под индикатором с отменой и включает выбор со всеми ними. Корень ветки ответов не выбирается: у него нет галочки, и он ушёл бы в удаление или пересылку незаметно. Если страница не загрузилась, выбираются найденные и показывается подсказка. В отложенных и быстрых ответах выбираются загруженные.
Сервер принимает пересылку по 100 сообщений, поэтому выбор, сделанный «Выбрать все сообщения», может пересылаться долго и приходить частями. Перед пересылкой такого выбора теперь спрашивается подтверждение.
catboysense
force-pushed
the
feat/select-by-author-c9axz4
branch
from
October 20, 2026 06:25
5596212 to
75dd10a
Compare
Если альбом не помещался в остаток пачки, начиналась новая пачка, а сам альбом, уже снятый с очереди, в неё не возвращался. Он оставался с часами до следующей отправки и уходил не на своём месте.
Пачки по 100 собирались только по месту назначения. Пачка, где были сообщения супергруппы и группы, из которой она мигрировала, падала на "Invalid forward peer ids" (в debug на assertionFailure), и её сообщения помечались неотправленными. Теперь источник входит в ключ пачки, а пачки уходят в порядке постановки в очередь.
MessageId сравнивает сначала номер, а супергруппа нумерует сообщения заново, тогда как группа до миграции брала номера аккаунта. Поэтому при пересылке выбора из обеих историй новые сообщения супергруппы уходили раньше старых. Теперь сообщения упорядочены по чатам (раньше начавшийся чат первым), внутри чата по id, как и раньше.
Экран выбора ждал только итог, а промежуточные .progress и knownTotals никто не читал. Загрузка теперь отдаёт один итог.
С флагом inexact сервер даёт оценку, которая может быть меньше настоящего числа. Загрузка останавливалась по ней раньше времени и не сообщала, что нашла не всё. Теперь приблизительный count не учитывается, и листание идёт до пустой страницы.
Если пир темы не нашёлся, запрос уходил без saved_peer_id и искал по всему монофоруму, а найденное попадало в выбор для удаления. Теперь поиск не делается, выбираются сообщения из окна истории и показывается подсказка, что загрузить не удалось. Так же теперь отвечает и случай, когда не нашёлся сам чат или автор.
В длинной личной переписке у собеседника бывают десятки тысяч сообщений: сотни запросов подряд, а потом выбор, в котором панель следит за каждым сообщением отдельно. Теперь загрузка останавливается на 10 000 самых новых, а подсказка говорит, что выбраны последние 10 000.
Чат исключал корень ветки и его альбом, только пока корень был в загруженном окне. В длинной ветке элементы альбома-корня, найденные поиском, попадали в выбор без галочек. Теперь загрузка сама исключает корень и весь его альбом.
В личном чате поиск messages.search по from_id находил только часть сообщений собеседника, так что выбиралась часть. Официальные клиенты так личку не ищут. Теперь личка листается целиком через getHistory, а сообщения нужного автора отбираются на устройстве. Чтобы в очень длинной переписке не листать сотни тысяч сообщений, просматривается не больше 50 000, и тогда подсказка называет число выбранных.
Личка листается через getHistory, у которого нет top_msg_id, поэтому в теме бота с топиками выбирались сообщения автора из всех тем, и удаление или пересылка забирали невидимые сообщения из других тем. Теперь из истории отбираются только сообщения открытой темы.
Когда в длинной личке срабатывал предел просмотра 50 000 сообщений, подсказка говорила «больше за раз выбрать нельзя» с любым числом, как будто это и есть предел. Теперь у этого случая свой текст, а число стоит после «Выбрано сообщений:», чтобы не склонять «сообщений» по числу (раньше выходило «последние 21 сообщений»).
catboysense
added a commit
that referenced
this pull request
Oct 23, 2026
catboysense
added a commit
that referenced
this pull request
Oct 23, 2026
В 13.1 весь TelegramCore подключает TelegramApi через internal import, а файл из #115 подключал его обычным import. TelegramCore собирается с -warnings-as-errors, и в режиме Swift 5 такое смешение даёт ошибку «ambiguous implicit access level for import of 'TelegramApi'».
catboysense
added a commit
that referenced
this pull request
Oct 23, 2026
В контекстном меню сообщения появился пункт «Выбрать все сообщения: <имя>», на своём сообщении «Выбрать все мои сообщения». Он загружает с сервера все сообщения автора в чате (в ветке ответов или теме форума только в ней) и выделяет их: не больше 10 000 самых новых, личка просматривается целиком до 50 000 сообщений. Пока идёт загрузка, виден индикатор с отменой; если загрузилось не всё или сработал предел, показывается подсказка. Перед пересылкой больше 1000 сообщений спрашивается подтверждение. Пересылка больше 100 сообщений больше не теряет альбомы, а выбор из супергруппы и группы, из которой она мигрирована, уходит по порядку и без ошибки «Invalid forward peer ids».
catboysense
added a commit
that referenced
this pull request
Oct 23, 2026
catboysense
added a commit
that referenced
this pull request
Oct 23, 2026
В 13.1 весь TelegramCore подключает TelegramApi через internal import, а файл из #115 подключал его обычным import. TelegramCore собирается с -warnings-as-errors, и в режиме Swift 5 такое смешение даёт ошибку «ambiguous implicit access level for import of 'TelegramApi'».
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что было
Чтобы выделить все сообщения одного человека в чате (например, чтобы переслать или удалить их), приходилось тыкать каждое сообщение вручную. Свои сообщения тоже выбирались только по одному.
Что стало
Как
TelegramCore/Sources/Donutgram/DonutgramAuthorMessages.swift: новыйengine.messages.donutgramAuthorMessages(peerId:threadId:authorId:sourceMessageId:). Листаетmessages.searchсfrom_idпо 100 сообщений (сtop_msg_idв ветке, сsaved_peer_idв личке канала, плюс история мигрированной группы). Личный чат листается целиком черезmessages.getHistory(не больше 50 000 сообщений), а сообщения автора отбираются на устройстве: поиск поfrom_idв личке на устройстве находил только часть сообщений собеседника. УgetHistoryнетtop_msg_id, поэтому в теме бота отбираются ещё и сообщения этой темы (threadId). Найденные сообщения, которых ещё нет в базе, сохраняются в базу черезaddMessages(..., location: .Random), как вgetMessagesLoadIfNecessary(пересылка и выбор вариантов удаления читают сообщения из базы), к ним добавляются сохранённые удалённые.from_idстроится черезapiInputPeer(_:sourceMessageId:transaction:), чтобы автор без собственного access hash ушёл какinputPeerUserFromMessage. Листание останавливается на пустой странице, на точномcount(приблизительный, с флагомinexact, не учитывается) или на пределеdonutgramAuthorMessagesLimit= 10 000. Какой предел сработал, результат сообщает отдельно (reachedLimit/reachedHistoryScanLimit), чтобы подсказка не выдавала предел просмотра за предел выбора. Следующая страница всегда начинается дальше предыдущей, чтобы не зациклиться. Корень ветки и его альбом исключаются уже здесь. Если в личке канала не нашёлся пир темы, поиск не делается вовсе, чтобы не искать по всему монофоруму.TelegramUI/Sources/Chat/ChatControllerDonutgramSelectAuthorMessages.swift: решает, показывать ли пункт, по нажатию запускает загрузку подOverlayStatusControllerс отменой, фильтрует результат черезdonutgramSelectableMessageIds, добавляет сообщения из окна истории (например, ещё отправляемые), убирает корень ветки, вызываетbeginMessageSelectionи показывает подсказку о неполной загрузке или о пределе. Там жеdonutgramConfirmLargeForwardIfNeeded, который вызывается изforwardSelectedMessagesвChatControllerLoadDisplayNode.swift.ChatInterfaceStateContextMenus.swift: уcontextMenuForChatPresentationInterfaceStateновый параметрselectAuthorMessages, пункт стоит рядом с «Выбрать».TelegramCore/Sources/State/PendingMessageManager.swift(код upstream): альбом, не поместившийся в пачку, возвращается в очередь перед новой пачкой; чат-источник входит вPendingForwardBatchKey, а пачки уходят в порядке постановки в очередь.ChatControllerForwardMessages.swift:forwardMessages(messageIds:)сортирует по чатам (раньше начавшийся чат первым), внутри чата по id. Раньше сортировка шла поMessageId, где номер сравнивается раньше чата, и новые сообщения супергруппы обгоняли старые сообщения группы.DGLocalization.swift. Имя стоит после двоеточия, потому что в «от <имя>» его пришлось бы склонять; число в подсказках по той же причине стоит после «Выбрано сообщений:».Проверка
reviews/pr-115-review.md…reviews/pr-115-review-5.md); сборку IPA делает CI этого PR. Разбивка пересылки на пачки проверена симуляцией той же логики: 95 одиночных + альбом из 10 + 5 одиночных раньше давали пачки[95, 5](альбом выпадал), теперь[95, 15]; 2000 случайных наборов до 500 сообщений: всё отправлено, порядок сохранён, пачки не больше 100.Не сделано
OverlayStatusControllerне умеет показывать текст рядом со спиннером.