Remove non-UI calls to App::main.

This commit is contained in:
John Preston 2020-06-12 18:09:04 +04:00
parent 3c4e959468
commit f450f81215
36 changed files with 768 additions and 675 deletions

View file

@ -16,14 +16,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "data/stickers/data_stickers.h"
#include "history/history.h"
#include "history/history_message.h" // NewMessageFlags.
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
#include "ui/text/text_entity.h" // TextWithEntities.
#include "ui/text_options.h" // Ui::ItemTextOptions.
#include "main/main_session.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "storage/localimageloader.h"
#include "storage/file_upload.h"
#include "mainwidget.h"
#include "apiwrap.h"
#include "app.h"
@ -329,4 +333,203 @@ void FillMessagePostFlags(
InnerFillMessagePostFlags(action.options, peer, flags);
}
void SendConfirmedFile(
not_null<Main::Session*> session,
const std::shared_ptr<FileLoadResult> &file,
const std::optional<FullMsgId> &oldId) {
const auto isEditing = oldId.has_value();
const auto channelId = peerToChannel(file->to.peer);
const auto newId = oldId.value_or(
FullMsgId(channelId, session->data().nextLocalMessageId()));
auto groupId = file->album ? file->album->groupId : uint64(0);
if (file->album) {
const auto proj = [](const SendingAlbum::Item &item) {
return item.taskId;
};
const auto it = ranges::find(file->album->items, file->taskId, proj);
Assert(it != file->album->items.end());
it->msgId = newId;
}
file->edit = isEditing;
session->uploader().upload(newId, file);
const auto itemToEdit = isEditing
? session->data().message(newId)
: nullptr;
const auto history = session->data().history(file->to.peer);
const auto peer = history->peer;
auto action = Api::SendAction(history);
action.options = file->to.options;
action.clearDraft = false;
action.replyTo = file->to.replyTo;
action.generateLocal = true;
session->api().sendAction(action);
auto caption = TextWithEntities{
file->caption.text,
TextUtilities::ConvertTextTagsToEntities(file->caption.tags)
};
const auto prepareFlags = Ui::ItemTextOptions(
history,
session->user()).flags;
TextUtilities::PrepareForSending(caption, prepareFlags);
TextUtilities::Trim(caption);
auto localEntities = Api::EntitiesToMTP(session, caption.entities);
if (itemToEdit) {
if (const auto id = itemToEdit->groupId()) {
groupId = id.value;
}
}
auto flags = (isEditing ? MTPDmessage::Flags() : NewMessageFlags(peer))
| MTPDmessage::Flag::f_entities
| MTPDmessage::Flag::f_media;
auto clientFlags = NewMessageClientFlags();
if (file->to.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
}
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = file->to.options.silent;
Api::FillMessagePostFlags(action, peer, flags);
if (silentPost) {
flags |= MTPDmessage::Flag::f_silent;
}
if (groupId) {
flags |= MTPDmessage::Flag::f_grouped_id;
}
if (file->to.options.scheduled) {
flags |= MTPDmessage::Flag::f_from_scheduled;
} else {
clientFlags |= MTPDmessage_ClientFlag::f_local_history_entry;
}
const auto messageFromId = channelPost ? 0 : session->userId();
const auto messagePostAuthor = channelPost
? session->user()->name
: QString();
if (file->type == SendMediaType::Photo) {
const auto photoFlags = MTPDmessageMediaPhoto::Flag::f_photo | 0;
const auto photo = MTP_messageMediaPhoto(
MTP_flags(photoFlags),
file->photo,
MTPint());
const auto mtpMessage = MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(file->to.peer),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(file->to.replyTo),
MTP_int(HistoryItem::NewMessageDate(file->to.options.scheduled)),
MTP_string(caption.text),
photo,
MTPReplyMarkup(),
localEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTP_long(groupId),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>());
if (itemToEdit) {
itemToEdit->savePreviousMedia();
itemToEdit->applyEdition(mtpMessage.c_message());
} else {
history->addNewMessage(
mtpMessage,
clientFlags,
NewMessageType::Unread);
}
} else if (file->type == SendMediaType::File) {
const auto documentFlags = MTPDmessageMediaDocument::Flag::f_document | 0;
const auto document = MTP_messageMediaDocument(
MTP_flags(documentFlags),
file->document,
MTPint());
const auto mtpMessage = MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(file->to.peer),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(file->to.replyTo),
MTP_int(HistoryItem::NewMessageDate(file->to.options.scheduled)),
MTP_string(caption.text),
document,
MTPReplyMarkup(),
localEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTP_long(groupId),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>());
if (itemToEdit) {
itemToEdit->savePreviousMedia();
itemToEdit->applyEdition(mtpMessage.c_message());
} else {
history->addNewMessage(
mtpMessage,
clientFlags,
NewMessageType::Unread);
}
} else if (file->type == SendMediaType::Audio) {
if (!peer->isChannel() || peer->isMegagroup()) {
flags |= MTPDmessage::Flag::f_media_unread;
}
const auto documentFlags = MTPDmessageMediaDocument::Flag::f_document | 0;
const auto document = MTP_messageMediaDocument(
MTP_flags(documentFlags),
file->document,
MTPint());
history->addNewMessage(
MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(file->to.peer),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(file->to.replyTo),
MTP_int(
HistoryItem::NewMessageDate(file->to.options.scheduled)),
MTP_string(caption.text),
document,
MTPReplyMarkup(),
localEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTP_long(groupId),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>()),
clientFlags,
NewMessageType::Unread);
// Voices can't be edited.
} else {
Unexpected("Type in sendFilesConfirmed.");
}
if (isEditing) {
return;
}
session->data().sendHistoryChangeNotifications();
session->changes().historyUpdated(
history,
Data::HistoryUpdate::Flag::MessageSent);
}
} // namespace Api

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class History;
class PhotoData;
class DocumentData;
struct FileLoadResult;
namespace Api {
@ -30,4 +31,9 @@ void FillMessagePostFlags(
not_null<PeerData*> peer,
MTPDmessage::Flags &flags);
void SendConfirmedFile(
not_null<Main::Session*> session,
const std::shared_ptr<FileLoadResult> &file,
const std::optional<FullMsgId> &oldId);
} // namespace Api

View file

@ -4010,7 +4010,9 @@ void ApiWrap::finishForwarding(const SendAction &action) {
}
_session->data().sendHistoryChangeNotifications();
_session->data().newMessageSent(history);
_session->changes().historyUpdated(
history,
Data::HistoryUpdate::Flag::MessageSent);
}
void ApiWrap::forwardMessages(
@ -4248,7 +4250,9 @@ void ApiWrap::sendSharedContact(
sendMedia(item, media, options);
_session->data().sendHistoryChangeNotifications();
_session->data().newMessageSent(history);
_session->changes().historyUpdated(
history,
Data::HistoryUpdate::Flag::MessageSent);
}
void ApiWrap::sendVoiceMessage(
@ -4259,7 +4263,7 @@ void ApiWrap::sendVoiceMessage(
const auto caption = TextWithTags();
const auto to = fileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>(
instance()->mainDcId(),
&session(),
result,
duration,
waveform,
@ -4278,7 +4282,7 @@ void ApiWrap::editMedia(
auto &file = list.files.front();
const auto to = fileLoadTaskOptions(action);
_fileLoader->addTask(std::make_unique<FileLoadTask>(
instance()->mainDcId(),
&session(),
file.path,
file.content,
std::move(file.information),
@ -4326,7 +4330,7 @@ void ApiWrap::sendFiles(
}
}
tasks.push_back(std::make_unique<FileLoadTask>(
instance()->mainDcId(),
&session(),
file.path,
file.content,
std::move(file.information),
@ -4353,7 +4357,7 @@ void ApiWrap::sendFile(
const auto to = fileLoadTaskOptions(action);
auto caption = TextWithTags();
_fileLoader->addTask(std::make_unique<FileLoadTask>(
instance()->mainDcId(),
&session(),
QString(),
fileContent,
nullptr,

View file

@ -296,7 +296,7 @@ auto AddButtonWithLoader(
if (toggled && (state.is<Available>() || state.is<Failed>())) {
const auto weak = Ui::MakeWeak(button);
setLocalLoader(base::make_unique_q<Loader>(
controller->content(),
QCoreApplication::instance(),
&controller->session(),
id,
Spellchecker::GetDownloadLocation(id),

View file

@ -162,7 +162,7 @@ void DownloadDictionaryInBackground(
auto sharedLoader = std::make_shared<base::unique_qptr<DictLoader>>();
*sharedLoader = base::make_unique_q<DictLoader>(
App::main(),
QCoreApplication::instance(),
session,
id,
GetDownloadLocation(id),

View file

@ -102,7 +102,7 @@ void DicePack::tryGenerateLocalZero() {
return;
}
auto task = FileLoadTask(
_session->mainDcId(),
_session,
path,
QByteArray(),
nullptr,

View file

@ -340,8 +340,8 @@ void Application::showTheme(
PeerData *Application::ui_getPeerForMouseAction() {
if (_mediaView && !_mediaView->isHidden()) {
return _mediaView->ui_getPeerForMouseAction();
} else if (auto main = App::main()) {
return main->ui_getPeerForMouseAction();
} else if (const auto m = App::main()) { // multi good
return m->ui_getPeerForMouseAction();
}
return nullptr;
}

View file

@ -111,7 +111,9 @@ QString MentionClickHandler::copyToClipboardContextItemText() const {
void MentionClickHandler::onClick(ClickContext context) const {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
App::main()->openPeerByName(_tag.mid(1), ShowAtProfileMsgId);
if (const auto m = App::main()) { // multi good
m->openPeerByName(_tag.mid(1), ShowAtProfileMsgId);
}
}
}

View file

@ -133,9 +133,11 @@ bool ShareUrl(
auto url = params.value(qsl("url"));
if (url.isEmpty()) {
return false;
} else if (const auto controller = App::wnd()->sessionController()) {
controller->content()->shareUrlLayer(url, params.value("text"));
return true;
}
App::main()->shareUrlLayer(url, params.value("text"));
return true;
return false;
}
bool ConfirmPhone(
@ -291,12 +293,15 @@ bool ResolveUsername(
post = ShowAtGameShareMsgId;
}
const auto clickFromMessageId = context.value<FullMsgId>();
App::main()->openPeerByName(
domain,
post,
startToken,
clickFromMessageId);
return true;
if (const auto controller = App::wnd()->sessionController()) {
controller->content()->openPeerByName(
domain,
post,
startToken,
clickFromMessageId);
return true;
}
return false;
}
bool ResolvePrivatePost(

View file

@ -14,8 +14,19 @@ namespace Data {
template <typename DataType, typename UpdateType>
void Changes::Manager<DataType, UpdateType>::updated(
not_null<DataType*> data,
Flags flags) {
Flags flags,
bool dropScheduled) {
sendRealtimeNotifications(data, flags);
if (dropScheduled) {
const auto i = _updates.find(data);
if (i != _updates.end()) {
flags |= i->second;
_updates.erase(i);
}
_stream.fire({ data, flags });
} else {
_updates[data] |= flags;
}
}
template <typename DataType, typename UpdateType>
@ -148,6 +159,72 @@ rpl::producer<HistoryUpdate> Changes::historyFlagsValue(
return _historyChanges.flagsValue(history, flags);
}
rpl::producer<HistoryUpdate> Changes::realtimeHistoryUpdates(
HistoryUpdate::Flag flag) const {
return _historyChanges.realtimeUpdates(flag);
}
void Changes::messageUpdated(
not_null<HistoryItem*> item,
MessageUpdate::Flags flags) {
const auto drop = (flags & MessageUpdate::Flag::Destroyed);
_messageChanges.updated(item, flags, drop);
if (!drop) {
scheduleNotifications();
}
}
rpl::producer<MessageUpdate> Changes::messageUpdates(
MessageUpdate::Flags flags) const {
return _messageChanges.updates(flags);
}
rpl::producer<MessageUpdate> Changes::messageUpdates(
not_null<HistoryItem*> item,
MessageUpdate::Flags flags) const {
return _messageChanges.updates(item, flags);
}
rpl::producer<MessageUpdate> Changes::messageFlagsValue(
not_null<HistoryItem*> item,
MessageUpdate::Flags flags) const {
return _messageChanges.flagsValue(item, flags);
}
rpl::producer<MessageUpdate> Changes::realtimeMessageUpdates(
MessageUpdate::Flag flag) const {
return _messageChanges.realtimeUpdates(flag);
}
void Changes::entryUpdated(
not_null<Dialogs::Entry*> entry,
EntryUpdate::Flags flags) {
_entryChanges.updated(entry, flags);
scheduleNotifications();
}
rpl::producer<EntryUpdate> Changes::entryUpdates(
EntryUpdate::Flags flags) const {
return _entryChanges.updates(flags);
}
rpl::producer<EntryUpdate> Changes::entryUpdates(
not_null<Dialogs::Entry*> entry,
EntryUpdate::Flags flags) const {
return _entryChanges.updates(entry, flags);
}
rpl::producer<EntryUpdate> Changes::entryFlagsValue(
not_null<Dialogs::Entry*> entry,
EntryUpdate::Flags flags) const {
return _entryChanges.flagsValue(entry, flags);
}
rpl::producer<EntryUpdate> Changes::realtimeEntryUpdates(
EntryUpdate::Flag flag) const {
return _entryChanges.realtimeUpdates(flag);
}
void Changes::scheduleNotifications() {
if (!_notify) {
_notify = true;
@ -164,6 +241,8 @@ void Changes::sendNotifications() {
_notify = false;
_peerChanges.sendNotifications();
_historyChanges.sendNotifications();
_messageChanges.sendNotifications();
_entryChanges.sendNotifications();
}
} // namespace Data

View file

@ -11,6 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class History;
class PeerData;
class HistoryItem;
namespace Dialogs {
class Entry;
} // namespace Dialogs
namespace Data {
@ -89,8 +94,13 @@ struct HistoryUpdate {
UnreadMentions = (1 << 4),
LocalMessages = (1 << 5),
ChatOccupied = (1 << 6),
MessageSent = (1 << 7),
ForwardDraft = (1 << 8),
OutboxRead = (1 << 9),
BotKeyboard = (1 << 10),
CloudDraft = (1 << 11),
LastUsedBit = (1 << 6),
LastUsedBit = (1 << 11),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; }
@ -100,6 +110,41 @@ struct HistoryUpdate {
};
struct MessageUpdate {
enum class Flag : uint32 {
None = 0,
Edited = (1 << 0),
Destroyed = (1 << 1),
DialogRowRepaint = (1 << 2),
DialogRowRefresh = (1 << 3),
LastUsedBit = (1 << 3),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; }
not_null<HistoryItem*> item;
Flags flags = 0;
};
struct EntryUpdate {
enum class Flag : uint32 {
None = 0,
Repaint = (1 << 0),
LastUsedBit = (1 << 0),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; }
not_null<Dialogs::Entry*> entry;
Flags flags = 0;
};
class Changes final {
public:
explicit Changes(not_null<Main::Session*> session);
@ -136,6 +181,36 @@ public:
[[nodiscard]] rpl::producer<HistoryUpdate> historyFlagsValue(
not_null<History*> history,
HistoryUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<HistoryUpdate> realtimeHistoryUpdates(
HistoryUpdate::Flag flag) const;
void messageUpdated(
not_null<HistoryItem*> item,
MessageUpdate::Flags flags);
[[nodiscard]] rpl::producer<MessageUpdate> messageUpdates(
MessageUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<MessageUpdate> messageUpdates(
not_null<HistoryItem*> item,
MessageUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<MessageUpdate> messageFlagsValue(
not_null<HistoryItem*> item,
MessageUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<MessageUpdate> realtimeMessageUpdates(
MessageUpdate::Flag flag) const;
void entryUpdated(
not_null<Dialogs::Entry*> entry,
EntryUpdate::Flags flags);
[[nodiscard]] rpl::producer<EntryUpdate> entryUpdates(
EntryUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<EntryUpdate> entryUpdates(
not_null<Dialogs::Entry*> entry,
EntryUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<EntryUpdate> entryFlagsValue(
not_null<Dialogs::Entry*> entry,
EntryUpdate::Flags flags) const;
[[nodiscard]] rpl::producer<EntryUpdate> realtimeEntryUpdates(
EntryUpdate::Flag flag) const;
void sendNotifications();
@ -156,7 +231,10 @@ private:
using Flag = typename UpdateType::Flag;
using Flags = typename UpdateType::Flags;
void updated(not_null<DataType*> data, Flags flags);
void updated(
not_null<DataType*> data,
Flags flags,
bool dropScheduled = false);
[[nodiscard]] rpl::producer<UpdateType> updates(Flags flags) const;
[[nodiscard]] rpl::producer<UpdateType> updates(
not_null<DataType*> data,
@ -189,6 +267,8 @@ private:
rpl::event_stream<NameUpdate> _nameStream;
Manager<PeerData, PeerUpdate> _peerChanges;
Manager<History, HistoryUpdate> _historyChanges;
Manager<HistoryItem, MessageUpdate> _messageChanges;
Manager<Dialogs::Entry, EntryUpdate> _entryChanges;
bool _notify = false;

View file

@ -560,12 +560,9 @@ bool ChatFilters::loadNextExceptions(bool chatsListLoaded) {
}
void ChatFilters::refreshHistory(not_null<History*> history) {
_refreshHistoryRequests.fire_copy(history);
}
auto ChatFilters::refreshHistoryRequests() const
-> rpl::producer<not_null<History*>> {
return _refreshHistoryRequests.events();
if (history->inChatList() && !list().empty()) {
_owner->refreshChatListEntry(history);
}
}
void ChatFilters::requestSuggested() {

View file

@ -105,8 +105,6 @@ public:
bool loadNextExceptions(bool chatsListLoaded);
void refreshHistory(not_null<History*> history);
[[nodiscard]] auto refreshHistoryRequests() const
-> rpl::producer<not_null<History*>>;
[[nodiscard]] not_null<Dialogs::MainList*> chatsList(FilterId filterId);
@ -137,7 +135,6 @@ private:
std::vector<ChatFilter> _list;
base::flat_map<FilterId, std::unique_ptr<Dialogs::MainList>> _chatsLists;
rpl::event_stream<> _listChanged;
rpl::event_stream<not_null<History*>> _refreshHistoryRequests;
mtpRequestId _loadRequestId = 0;
mtpRequestId _saveOrderRequestId = 0;
mtpRequestId _saveOrderAfterId = 0;

View file

@ -400,7 +400,11 @@ void DocumentCancelClickHandler::onClickImpl() const {
return;
} else if (data->uploading()) {
if (const auto item = data->owner().message(context())) {
App::main()->cancelUploadLayer(item);
if (const auto m = App::main()) { // multi good
if (&m->session() == &data->session()) {
m->cancelUploadLayer(item);
}
}
}
} else {
data->cancel();

View file

@ -55,7 +55,7 @@ rpl::producer<int> PinnedDialogsInFolderMaxValue(
//}
Folder::Folder(not_null<Data::Session*> owner, FolderId id)
: Entry(owner, this)
: Entry(owner, Type::Folder)
, _id(id)
, _chatsList(
&owner->session(),

View file

@ -353,7 +353,11 @@ void PhotoCancelClickHandler::onClickImpl() const {
return;
} else if (data->uploading()) {
if (const auto item = data->owner().message(context())) {
App::main()->cancelUploadLayer(item);
if (const auto m = App::main()) { // multi good
if (&m->session() == &data->session()) {
m->cancelUploadLayer(item);
}
}
}
} else {
data->cancel();

View file

@ -237,7 +237,7 @@ Session::Session(not_null<Main::Session*> session)
}
}
setupContactViewsViewer();
setupMigrationViewer();
setupChannelLeavingViewer();
setupPeerNameViewer();
setupUserIsContactViewer();
@ -822,7 +822,7 @@ void Session::deleteConversationLocally(not_null<PeerData*> peer) {
if (history->folderKnown()) {
setChatPinned(history, FilterId(), false);
}
App::main()->removeDialog(history);
removeChatListEntry(history);
history->clear(peer->isChannel()
? History::ClearType::Unload
: History::ClearType::DeleteChat);
@ -836,21 +836,12 @@ void Session::deleteConversationLocally(not_null<PeerData*> peer) {
}
}
}
void Session::newMessageSent(not_null<History*> history) {
_newMessageSent.fire_copy(history);
}
rpl::producer<not_null<History*>> Session::newMessageSent() const {
return _newMessageSent.events();
}
void Session::cancelForwarding(not_null<History*> history) {
history->setForwardDraft({});
_forwardDraftUpdated.fire_copy(history);
}
rpl::producer<not_null<History*>> Session::forwardDraftUpdates() const {
return _forwardDraftUpdated.events();
session().changes().historyUpdated(
history,
Data::HistoryUpdate::Flag::ForwardDraft);
}
void Session::registerSendAction(
@ -1044,16 +1035,24 @@ void Session::forgetPassportCredentials() {
_passportCredentials = nullptr;
}
void Session::setupContactViewsViewer() {
void Session::setupMigrationViewer() {
session().changes().peerUpdates(
PeerUpdate::Flag::IsContact
PeerUpdate::Flag::Migration
) | rpl::map([](const PeerUpdate &update) {
return update.peer->asUser();
}) | rpl::start_with_next([=](not_null<UserData*> user) {
const auto i = _contactViews.find(peerToUser(user->id));
if (i != _contactViews.end()) {
for (const auto view : i->second) {
requestViewResize(view);
return update.peer->asChat();
}) | rpl::filter([=](ChatData *chat) {
return (chat != nullptr);
}) | rpl::start_with_next([=](not_null<ChatData*> chat) {
const auto channel = chat->migrateTo();
if (!channel) {
return;
}
if (const auto from = historyLoaded(chat)) {
if (const auto to = historyLoaded(channel)) {
if (to->inChatList() && from->inChatList()) {
removeChatListEntry(from);
}
}
}
}, _lifetime);
@ -1089,21 +1088,27 @@ void Session::setupPeerNameViewer() {
void Session::setupUserIsContactViewer() {
session().changes().peerUpdates(
PeerUpdate::Flag::IsContact
) | rpl::start_with_next([=](const PeerUpdate &update) {
const auto user = update.peer->asUser();
Assert(user != nullptr);
) | rpl::map([](const PeerUpdate &update) {
return update.peer->asUser();
}) | rpl::start_with_next([=](not_null<UserData*> user) {
const auto i = _contactViews.find(peerToUser(user->id));
if (i != _contactViews.end()) {
for (const auto view : i->second) {
requestViewResize(view);
}
}
if (user->loadedStatus != PeerData::FullLoaded) {
LOG(("API Error: "
"userIsContactChanged() called for a not loaded user!"));
return;
}
if (user->isContact()) {
const auto history = user->owner().history(user->id);
const auto history = this->history(user->id);
_contactsList.addByName(history);
if (!history->inChatList()) {
_contactsNoChatsList.addByName(history);
}
} else if (const auto history = user->owner().historyLoaded(user)) {
} else if (const auto history = historyLoaded(user)) {
_contactsNoChatsList.del(history);
_contactsList.del(history);
}
@ -1619,12 +1624,12 @@ void Session::applyDialog(
setPinnedFromDialog(history, data.is_pinned());
if (const auto from = history->peer->migrateFrom()) {
if (const auto historyFrom = from->owner().historyLoaded(from)) {
App::main()->removeDialog(historyFrom);
if (const auto historyFrom = historyLoaded(from)) {
removeChatListEntry(historyFrom);
}
} else if (const auto to = history->peer->migrateTo()) {
if (to->amIn()) {
App::main()->removeDialog(history);
removeChatListEntry(history);
}
}
}
@ -1898,9 +1903,9 @@ void Session::updateDependentMessages(not_null<HistoryItem*> item) {
dependent->updateDependencyItem();
}
}
if (App::main()) {
App::main()->itemEdited(item);
}
session().changes().messageUpdated(
item,
Data::MessageUpdate::Flag::Edited);
}
void Session::registerDependentMessage(
@ -3312,14 +3317,6 @@ rpl::producer<not_null<ChannelData*>> Session::channelDifferenceTooLong() const
return _channelDifferenceTooLong.events();
}
void Session::historyOutboxRead(not_null<History*> history) {
_historyOutboxReads.fire_copy(history);
}
rpl::producer<not_null<History*>> Session::historyOutboxReads() const {
return _historyOutboxReads.events();
}
void Session::registerItemView(not_null<ViewElement*> view) {
_views[view->data()].push_back(view);
}
@ -3409,10 +3406,7 @@ not_null<Dialogs::IndexedList*> Session::contactsNoChatsList() {
return &_contactsNoChatsList;
}
auto Session::refreshChatListEntry(
Dialogs::Key key,
FilterId filterIdForResult)
-> RefreshChatListEntryResult {
void Session::refreshChatListEntry(Dialogs::Key key) {
Expects(key.entry()->folderKnown());
using namespace Dialogs;
@ -3420,42 +3414,47 @@ auto Session::refreshChatListEntry(
const auto entry = key.entry();
const auto history = key.history();
const auto mainList = chatsList(entry->folder());
auto mainListResult = RefreshChatListEntryResult();
mainListResult.changed = !entry->inChatList();
if (mainListResult.changed) {
auto event = ChatListEntryRefresh{ .key = key };
const auto creating = event.existenceChanged = !entry->inChatList();
if (event.existenceChanged) {
const auto mainRow = entry->addToChatList(0, mainList);
_contactsNoChatsList.del(key, mainRow);
} else {
mainListResult.moved = entry->adjustByPosInChatList(0, mainList);
event.moved = entry->adjustByPosInChatList(0, mainList);
}
if (event) {
_chatListEntryRefreshes.fire(std::move(event));
}
auto result = filterIdForResult
? RefreshChatListEntryResult()
: mainListResult;
if (!history) {
return result;
return;
}
for (const auto &filter : _chatsFilters->list()) {
const auto id = filter.id();
const auto filterList = chatsFilters().chatsList(id);
auto filterResult = RefreshChatListEntryResult();
auto event = ChatListEntryRefresh{ .key = key, .filterId = id };
if (filter.contains(history)) {
filterResult.changed = !entry->inChatList(id);
if (filterResult.changed) {
event.existenceChanged = !entry->inChatList(id);
if (event.existenceChanged) {
entry->addToChatList(id, filterList);
} else {
filterResult.moved = entry->adjustByPosInChatList(
id,
filterList);
event.moved = entry->adjustByPosInChatList(id, filterList);
}
} else if (entry->inChatList(id)) {
entry->removeFromChatList(id, filterList);
filterResult.changed = true;
event.existenceChanged = true;
}
if (id == filterIdForResult) {
result = filterResult;
if (event) {
_chatListEntryRefreshes.fire(std::move(event));
}
}
if (creating) {
if (const auto from = history->peer->migrateFrom()) {
if (const auto migrated = historyLoaded(from)) {
removeChatListEntry(migrated);
}
}
}
return result;
}
void Session::removeChatListEntry(Dialogs::Key key) {
@ -3466,21 +3465,39 @@ void Session::removeChatListEntry(Dialogs::Key key) {
return;
}
Assert(entry->folderKnown());
const auto mainList = chatsList(entry->folder());
entry->removeFromChatList(0, mainList);
for (const auto &filter : _chatsFilters->list()) {
const auto id = filter.id();
if (entry->inChatList(id)) {
entry->removeFromChatList(id, chatsFilters().chatsList(id));
_chatListEntryRefreshes.fire(ChatListEntryRefresh{
.key = key,
.filterId = id,
.existenceChanged = true
});
}
}
const auto mainList = chatsList(entry->folder());
entry->removeFromChatList(0, mainList);
_chatListEntryRefreshes.fire(ChatListEntryRefresh{
.key = key,
.existenceChanged = true
});
if (_contactsList.contains(key)) {
if (!_contactsNoChatsList.contains(key)) {
_contactsNoChatsList.addByName(key);
}
}
if (const auto history = key.history()) {
session().notifications().clearFromHistory(history);
}
}
auto Session::chatListEntryRefreshes() const
-> rpl::producer<ChatListEntryRefresh> {
return _chatListEntryRefreshes.events();
}
void Session::dialogsRowReplaced(DialogsRowReplacement replacement) {
_dialogsRowReplacements.fire(std::move(replacement));
}

View file

@ -180,10 +180,7 @@ public:
void deleteConversationLocally(not_null<PeerData*> peer);
void newMessageSent(not_null<History*> history);
[[nodiscard]] rpl::producer<not_null<History*>> newMessageSent() const;
void cancelForwarding(not_null<History*> history);
[[nodiscard]] rpl::producer<not_null<History*>> forwardDraftUpdates() const;
void registerSendAction(
not_null<History*> history,
@ -561,9 +558,6 @@ public:
void channelDifferenceTooLong(not_null<ChannelData*> channel);
[[nodiscard]] rpl::producer<not_null<ChannelData*>> channelDifferenceTooLong() const;
void historyOutboxRead(not_null<History*> history);
[[nodiscard]] rpl::producer<not_null<History*>> historyOutboxReads() const;
void registerItemView(not_null<ViewElement*> view);
void unregisterItemView(not_null<ViewElement*> view);
@ -582,14 +576,20 @@ public:
[[nodiscard]] not_null<Dialogs::IndexedList*> contactsList();
[[nodiscard]] not_null<Dialogs::IndexedList*> contactsNoChatsList();
struct RefreshChatListEntryResult {
bool changed = false;
struct ChatListEntryRefresh {
Dialogs::Key key;
Dialogs::PositionChange moved;
FilterId filterId = 0;
bool existenceChanged = false;
explicit operator bool() const {
return existenceChanged || (moved.from != moved.to);
}
};
RefreshChatListEntryResult refreshChatListEntry(
Dialogs::Key key,
FilterId filterIdForResult);
void refreshChatListEntry(Dialogs::Key key);
void removeChatListEntry(Dialogs::Key key);
[[nodiscard]] auto chatListEntryRefreshes() const
-> rpl::producer<ChatListEntryRefresh>;
struct DialogsRowReplacement {
not_null<Dialogs::Row*> old;
@ -645,7 +645,7 @@ private:
void suggestStartExport();
void setupContactViewsViewer();
void setupMigrationViewer();
void setupChannelLeavingViewer();
void setupPeerNameViewer();
void setupUserIsContactViewer();
@ -808,6 +808,7 @@ private:
rpl::event_stream<MegagroupParticipant> _megagroupParticipantRemoved;
rpl::event_stream<MegagroupParticipant> _megagroupParticipantAdded;
rpl::event_stream<DialogsRowReplacement> _dialogsRowReplacements;
rpl::event_stream<ChatListEntryRefresh> _chatListEntryRefreshes;
Dialogs::MainList _chatsList;
Dialogs::IndexedList _contactsList;
@ -879,9 +880,6 @@ private:
rpl::event_stream<not_null<WebPageData*>> _webpageUpdates;
rpl::event_stream<not_null<ChannelData*>> _channelDifferenceTooLong;
rpl::event_stream<not_null<History*>> _historyOutboxReads;
rpl::event_stream<not_null<History*>> _newMessageSent;
rpl::event_stream<not_null<History*>> _forwardDraftUpdated;
base::flat_multi_map<TimeId, not_null<PollData*>> _pollsClosings;
base::Timer _pollsClosingTimer;

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "dialogs/dialogs_key.h"
#include "dialogs/dialogs_indexed_list.h"
#include "data/data_changes.h"
#include "data/data_session.h"
#include "data/data_folder.h"
#include "data/data_chat_filters.h"
@ -41,10 +42,10 @@ uint64 PinnedDialogPos(int pinnedIndex) {
} // namespace
Entry::Entry(not_null<Data::Session*> owner, const Key &key)
Entry::Entry(not_null<Data::Session*> owner, Type type)
: lastItemTextCache(st::dialogsTextWidthMin)
, _owner(owner)
, _key(key) {
, _isFolder(type == Type::Folder) {
}
Data::Session &Entry::owner() const {
@ -55,6 +56,14 @@ Main::Session &Entry::session() const {
return _owner->session();
}
History *Entry::asHistory() {
return _isFolder ? nullptr : static_cast<History*>(this);
}
Data::Folder *Entry::asFolder() {
return _isFolder ? static_cast<Data::Folder*>(this) : nullptr;
}
void Entry::pinnedIndexChanged(int was, int now) {
if (session().supportMode()) {
// Force reorder in support mode.
@ -159,13 +168,11 @@ void Entry::notifyUnreadStateChange(const UnreadState &wasState) {
}
void Entry::setChatListExistence(bool exists) {
if (const auto main = App::main()) {
if (exists && _sortKeyInChatList) {
main->refreshDialog(_key);
updateChatListEntry();
} else {
main->removeDialog(_key);
}
if (exists && _sortKeyInChatList) {
owner().refreshChatListEntry(this);
updateChatListEntry();
} else {
owner().removeChatListEntry(this);
}
}
@ -228,7 +235,7 @@ not_null<Row*> Entry::addToChatList(
}
return _chatListLinks.emplace(
filterId,
list->addEntry(_key)
list->addEntry(this)
).first->second.main;
}
@ -236,7 +243,7 @@ void Entry::removeFromChatList(
FilterId filterId,
not_null<MainList*> list) {
if (isPinnedDialog(filterId)) {
owner().setChatPinned(_key, filterId, false);
owner().setChatPinned(this, filterId, false);
}
const auto i = _chatListLinks.find(filterId);
@ -244,7 +251,7 @@ void Entry::removeFromChatList(
return;
}
_chatListLinks.erase(i);
list->removeEntry(_key);
list->removeEntry(this);
}
void Entry::removeChatListEntryByLetter(FilterId filterId, QChar letter) {
@ -264,16 +271,8 @@ void Entry::addChatListEntryByLetter(
}
}
void Entry::updateChatListEntry() const {
if (const auto main = App::main()) {
for (const auto &[filterId, links] : _chatListLinks) {
main->repaintDialogRow(filterId, links.main);
}
if (session().supportMode()
&& !session().settings().supportAllSearchResults()) {
main->repaintDialogRow({ _key, FullMsgId() });
}
}
void Entry::updateChatListEntry() {
session().changes().entryUpdated(this, Data::EntryUpdate::Flag::Repaint);
}
} // namespace Dialogs

View file

@ -90,7 +90,11 @@ inline UnreadState operator-(const UnreadState &a, const UnreadState &b) {
class Entry {
public:
Entry(not_null<Data::Session*> owner, const Key &key);
enum class Type {
History,
Folder,
};
Entry(not_null<Data::Session*> owner, Type type);
Entry(const Entry &other) = delete;
Entry &operator=(const Entry &other) = delete;
virtual ~Entry() = default;
@ -98,12 +102,17 @@ public:
[[nodiscard]] Data::Session &owner() const;
[[nodiscard]] Main::Session &session() const;
History *asHistory();
Data::Folder *asFolder();
PositionChange adjustByPosInChatList(
FilterId filterId,
not_null<MainList*> list);
[[nodiscard]] bool inChatList(FilterId filterId = 0) const {
return _chatListLinks.contains(filterId);
}
RowsByLetter *chatListLinks(FilterId filterId);
const RowsByLetter *chatListLinks(FilterId filterId) const;
[[nodiscard]] int posInChatList(FilterId filterId) const;
not_null<Row*> addToChatList(
FilterId filterId,
@ -116,7 +125,7 @@ public:
FilterId filterId,
QChar letter,
not_null<Row*> row);
void updateChatListEntry() const;
void updateChatListEntry();
[[nodiscard]] bool isPinnedDialog(FilterId filterId) const {
return lookupPinnedIndex(filterId) != 0;
}
@ -202,19 +211,17 @@ private:
[[nodiscard]] uint64 computeSortPosition(FilterId filterId) const;
void setChatListExistence(bool exists);
RowsByLetter *chatListLinks(FilterId filterId);
const RowsByLetter *chatListLinks(FilterId filterId) const;
not_null<Row*> mainChatListLink(FilterId filterId) const;
Row *maybeMainChatListLink(FilterId filterId) const;
not_null<Data::Session*> _owner;
Dialogs::Key _key;
const not_null<Data::Session*> _owner;
base::flat_map<FilterId, RowsByLetter> _chatListLinks;
uint64 _sortKeyInChatList = 0;
uint64 _sortKeyByDate = 0;
base::flat_map<FilterId, int> _pinnedIndex;
TimeId _timeId = 0;
bool _isTopPromoted = false;
const bool _isFolder = false;
};

View file

@ -209,14 +209,6 @@ InnerWidget::InnerWidget(
refresh();
}, lifetime());
session().data().chatsFilters().refreshHistoryRequests(
) | rpl::start_with_next([=](not_null<History*> history) {
if (history->inChatList()
&& !session().data().chatsFilters().list().empty()) {
refreshDialog(history);
}
}, lifetime());
subscribe(Window::Theme::Background(), [=](const Window::Theme::BackgroundUpdate &data) {
if (data.paletteChanged()) {
Layout::clearUnreadBadgesCache();
@ -241,7 +233,6 @@ InnerWidget::InnerWidget(
UpdateFlag::Name
| UpdateFlag::Photo
| UpdateFlag::IsContact
| UpdateFlag::Migration
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
if (update.flags & (UpdateFlag::Name | UpdateFlag::Photo)) {
this->update();
@ -251,10 +242,34 @@ InnerWidget::InnerWidget(
// contactsNoChatsList could've changed.
Ui::PostponeCall(this, [=] { refresh(); });
}
if (update.flags & UpdateFlag::Migration) {
if (const auto chat = update.peer->asChat()) {
handleChatMigration(chat);
}
}, lifetime());
session().changes().messageUpdates(
Data::MessageUpdate::Flag::DialogRowRepaint
| Data::MessageUpdate::Flag::DialogRowRefresh
) | rpl::start_with_next([=](const Data::MessageUpdate &update) {
const auto item = update.item;
if (update.flags & Data::MessageUpdate::Flag::DialogRowRefresh) {
refreshDialogRow({ item->history(), item->fullId() });
}
if (update.flags & Data::MessageUpdate::Flag::DialogRowRepaint) {
repaintDialogRow({ item->history(), item->fullId() });
}
}, lifetime());
session().changes().entryUpdates(
Data::EntryUpdate::Flag::Repaint
) | rpl::start_with_next([=](const Data::EntryUpdate &update) {
const auto entry = update.entry;
const auto repaintId = (_state == WidgetState::Default)
? _filterId
: 0;
if (const auto links = entry->chatListLinks(repaintId)) {
repaintDialogRow(repaintId, links->main);
}
if (session().supportMode()
&& !session().settings().supportAllSearchResults()) {
repaintDialogRow({ entry, FullMsgId() });
}
}, lifetime());
@ -272,6 +287,8 @@ InnerWidget::InnerWidget(
switchToFilter(filterId);
}, lifetime());
handleChatListEntryRefreshes();
refreshWithCollapsedRows(true);
setupShortcuts();
@ -281,21 +298,6 @@ Main::Session &InnerWidget::session() const {
return _controller->session();
}
void InnerWidget::handleChatMigration(not_null<ChatData*> chat) {
const auto channel = chat->migrateTo();
if (!channel) {
return;
}
if (const auto from = chat->owner().historyLoaded(chat)) {
if (const auto to = chat->owner().historyLoaded(channel)) {
if (to->inChatList() && from->inChatList()) {
removeDialog(from);
}
}
}
}
void InnerWidget::refreshWithCollapsedRows(bool toTop) {
const auto pressed = _collapsedPressed;
const auto selected = _collapsedSelected;
@ -1443,68 +1445,56 @@ void InnerWidget::dialogRowReplaced(
}
}
void InnerWidget::refreshDialog(Key key) {
if (const auto history = key.history()) {
if (history->peer->loadedStatus
!= PeerData::LoadedStatus::FullLoaded) {
LOG(("API Error: "
"InnerWidget::refreshDialog() called for a non loaded peer!"
));
return;
}
}
void InnerWidget::handleChatListEntryRefreshes() {
using Event = Data::Session::ChatListEntryRefresh;
session().data().chatListEntryRefreshes(
) | rpl::filter([=](const Event &event) {
return (event.filterId == _filterId);
}) | rpl::start_with_next([=](const Event &event) {
const auto rowHeight = st::dialogsRowHeight;
const auto from = dialogsOffset() + event.moved.from * rowHeight;
const auto to = dialogsOffset() + event.moved.to * rowHeight;
const auto &key = event.key;
const auto entry = key.entry();
const auto result = session().data().refreshChatListEntry(
key,
_filterId);
const auto rowHeight = st::dialogsRowHeight;
const auto from = dialogsOffset() + result.moved.from * rowHeight;
const auto to = dialogsOffset() + result.moved.to * rowHeight;
if (!_dragging
&& (from != to)
&& (key.entry()->folder() == _openedFolder)) {
// Don't jump in chats list scroll position while dragging.
emit dialogMoved(from, to);
}
if (result.changed) {
refresh();
} else if (_state == WidgetState::Default && from != to) {
update(
0,
std::min(from, to),
width(),
std::abs(from - to) + rowHeight);
}
}
void InnerWidget::removeDialog(Key key) {
if (key == _menuRow.key && _menu) {
InvokeQueued(this, [=] { _menu = nullptr; });
}
if (_selected && _selected->key() == key) {
_selected = nullptr;
}
if (_pressed && _pressed->key() == key) {
setPressed(nullptr);
}
session().data().removeChatListEntry(key);
if (const auto history = key.history()) {
session().notifications().clearFromHistory(history);
}
const auto i = ranges::find(_filterResults, key, &Row::key);
if (i != _filterResults.end()) {
if (_filteredSelected == (i - _filterResults.begin())
&& (i + 1) == _filterResults.end()) {
_filteredSelected = -1;
if (!_dragging
&& (from != to)
&& (entry->folder() == _openedFolder)
&& (_state == WidgetState::Default)) {
emit dialogMoved(from, to);
}
_filterResults.erase(i);
refresh();
}
_updated.fire({});
refresh();
if (event.existenceChanged) {
if (!entry->inChatList()) {
if (key == _menuRow.key && _menu) {
InvokeQueued(this, [=] { _menu = nullptr; });
}
if (_selected && _selected->key() == key) {
_selected = nullptr;
}
if (_pressed && _pressed->key() == key) {
setPressed(nullptr);
}
const auto i = ranges::find(_filterResults, key, &Row::key);
if (i != _filterResults.end()) {
if (_filteredSelected == (i - _filterResults.begin())
&& (i + 1) == _filterResults.end()) {
_filteredSelected = -1;
}
_filterResults.erase(i);
}
_updated.fire({});
}
refresh();
} else if (_state == WidgetState::Default && from != to) {
update(
0,
std::min(from, to),
width(),
std::abs(from - to) + rowHeight);
}
}, lifetime());
}
void InnerWidget::repaintCollapsedFolderRow(not_null<Data::Folder*> folder) {

View file

@ -86,12 +86,6 @@ public:
void selectSkip(int32 direction);
void selectSkipPage(int32 pixels, int32 direction);
void refreshDialog(Key key);
void removeDialog(Key key);
void repaintDialogRow(FilterId filterId, not_null<Row*> row);
void repaintDialogRow(RowDescriptor row);
void refreshDialogRow(RowDescriptor row);
void dragLeft();
void clearFilter();
@ -193,6 +187,10 @@ private:
not_null<FakeRow*> result,
const RowDescriptor &entry) const;
void repaintDialogRow(FilterId filterId, not_null<Row*> row);
void repaintDialogRow(RowDescriptor row);
void refreshDialogRow(RowDescriptor row);
void clearMouseSelection(bool clearSelection = false);
void mousePressReleased(QPoint globalPosition, Qt::MouseButton button);
void clearIrrelevantState();
@ -316,7 +314,7 @@ private:
int countPinnedIndex(Row *ofRow);
void savePinnedOrder();
bool pinnedShiftAnimationCallback(crl::time now);
void handleChatMigration(not_null<ChatData*> chat);
void handleChatListEntryRefreshes();
not_null<Window::SessionController*> _controller;

View file

@ -17,32 +17,35 @@ using Folder = Data::Folder;
} // namespace
Key::Key(History *history) : _value(history) {
}
Key::Key(Data::Folder *folder) : _value(folder) {
}
Key::Key(not_null<History*> history) : _value(history) {
}
Key::Key(not_null<Data::Folder*> folder) : _value(folder) {
}
not_null<Entry*> Key::entry() const {
if (const auto p = base::get_if<not_null<History*>>(&_value)) {
return *p;
} else if (const auto p = base::get_if<not_null<Folder*>>(&_value)) {
return *p;
}
Unexpected("Empty Dialogs::Key in Key::entry().");
Expects(_value != nullptr);
return _value;
}
History *Key::history() const {
if (const auto p = base::get_if<not_null<History*>>(&_value)) {
return *p;
}
return nullptr;
return _value ? _value->asHistory() : nullptr;
}
Folder *Key::folder() const {
if (const auto p = base::get_if<not_null<Folder*>>(&_value)) {
return *p;
}
return nullptr;
return _value ? _value->asFolder() : nullptr;
}
PeerData *Key::peer() const {
if (const auto p = base::get_if<not_null<History*>>(&_value)) {
return (*p)->peer;
if (const auto history = this->history()) {
return history->peer;
}
return nullptr;
}

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/value_ordering.h"
class History;
class PeerData;
namespace Data {
class Folder;
@ -22,17 +23,17 @@ class Entry;
class Key {
public:
Key() = default;
Key(History *history) : _value(history) {
Key(Entry *entry) : _value(entry) {
}
Key(not_null<History*> history) : _value(history) {
}
Key(Data::Folder *folder) : _value(folder) {
}
Key(not_null<Data::Folder*> folder) : _value(folder) {
Key(History *history);
Key(Data::Folder *folder);
Key(not_null<Entry*> entry) : _value(entry) {
}
Key(not_null<History*> history);
Key(not_null<Data::Folder*> folder);
explicit operator bool() const {
return !!_value;
return (_value != nullptr);
}
not_null<Entry*> entry() const;
History *history() const;
@ -58,21 +59,13 @@ public:
return !(*this == other);
}
base::optional_variant<
not_null<History*>,
not_null<Data::Folder*>> raw() const {
return _value;
}
// Not working :(
//friend inline auto value_ordering_helper(const Key &key) {
// return key.value;
//}
private:
base::optional_variant<
not_null<History*>,
not_null<Data::Folder*>> _value;
Entry *_value = nullptr;
};

View file

@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_folder.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "facades.h"
#include "app.h"
#include "styles/style_dialogs.h"
@ -188,7 +189,8 @@ Widget::Widget(
refreshLoadMoreButton(mayBlock, isBlocked);
}, lifetime());
session().data().newMessageSent(
session().changes().historyUpdates(
Data::HistoryUpdate::Flag::MessageSent
) | rpl::start_with_next([=] {
jumpToTop();
}, lifetime());
@ -558,34 +560,6 @@ void Widget::setInnerFocus() {
}
}
void Widget::refreshDialog(Key key) {
const auto creating = !key.entry()->inChatList();
_inner->refreshDialog(key);
const auto history = key.history();
if (creating && history && history->peer->migrateFrom()) {
if (const auto migrated = history->owner().historyLoaded(
history->peer->migrateFrom())) {
if (migrated->inChatList()) {
_inner->removeDialog(migrated);
}
}
}
}
void Widget::repaintDialogRow(
FilterId filterId,
not_null<Row*> row) {
_inner->repaintDialogRow(filterId, row);
}
void Widget::repaintDialogRow(RowDescriptor row) {
_inner->repaintDialogRow(row);
}
void Widget::refreshDialogRow(RowDescriptor row) {
_inner->refreshDialogRow(row);
}
void Widget::jumpToTop() {
if (session().supportMode()) {
return;
@ -1743,10 +1717,6 @@ void Widget::scrollToEntry(const RowDescriptor &entry) {
_inner->scrollToEntry(entry);
}
void Widget::removeDialog(Key key) {
_inner->removeDialog(key);
}
void Widget::cancelSearchRequest() {
session().api().request(base::take(_searchRequest)).cancel();
if (_searchInHistoryRequest) {

View file

@ -66,12 +66,6 @@ public:
void searchInChat(Key chat);
void setInnerFocus();
void refreshDialog(Key key);
void removeDialog(Key key);
void repaintDialogRow(FilterId filterId, not_null<Row*> row);
void repaintDialogRow(RowDescriptor row);
void refreshDialogRow(RowDescriptor row);
void jumpToTop();
void startWidthAnimation();
@ -212,7 +206,7 @@ private:
object_ptr<Ui::HistoryDownButton> _scrollToTop;
Data::Folder *_openedFolder = nullptr;
Key _searchInChat;
Dialogs::Key _searchInChat;
History *_searchInMigrated = nullptr;
UserData *_searchFromUser = nullptr;
QString _lastFilterText;

View file

@ -70,7 +70,7 @@ using UpdateFlag = Data::HistoryUpdate::Flag;
} // namespace
History::History(not_null<Data::Session*> owner, PeerId peerId)
: Entry(owner, this)
: Entry(owner, Type::History)
, peer(owner->peer(peerId))
, cloudDraftTextCache(st::dialogsTextWidthMin)
, _mute(owner->notifyIsMuted(peer))
@ -88,9 +88,7 @@ void History::clearLastKeyboard() {
lastKeyboardHiddenId = 0;
}
lastKeyboardId = 0;
if (auto main = App::main()) {
main->updateBotKeyboard(this);
}
session().changes().historyUpdated(this, UpdateFlag::BotKeyboard);
}
lastKeyboardInited = true;
lastKeyboardFrom = 0;
@ -327,9 +325,7 @@ void History::applyCloudDraft() {
} else {
createLocalDraftFromCloud();
updateChatListSortPosition();
if (const auto main = App::main()) {
main->applyCloudDraft(this);
}
session().changes().historyUpdated(this, UpdateFlag::CloudDraft);
}
}
@ -1759,13 +1755,13 @@ void History::outboxRead(MsgId upTo) {
setOutboxReadTill(upTo);
if (const auto last = chatListMessage()) {
if (last->out() && IsServerMsgId(last->id) && last->id <= upTo) {
if (const auto main = App::main()) {
main->repaintDialogRow({ this, last->fullId() });
}
session().changes().messageUpdated(
last,
Data::MessageUpdate::Flag::DialogRowRepaint);
}
}
updateChatListEntry();
session().data().historyOutboxRead(this);
session().changes().historyUpdated(this, UpdateFlag::OutboxRead);
}
void History::outboxRead(not_null<const HistoryItem*> wasRead) {

View file

@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "data/stickers/data_stickers.h"
#include "facades.h"
#include "app.h"
@ -198,10 +199,10 @@ HistoryInner::HistoryInner(
}) | rpl::start_with_next([this](not_null<const Element*> view) {
mouseActionUpdate();
}, lifetime());
session().data().historyOutboxReads(
) | rpl::filter([=](not_null<History*> history) {
return (_history == history);
}) | rpl::start_with_next([=] {
session().changes().historyUpdates(
_history,
Data::HistoryUpdate::Flag::OutboxRead
) | rpl::start_with_next([=] {
update();
}, lifetime());
}

View file

@ -265,10 +265,9 @@ PeerData *HistoryItem::displayFrom() const {
}
void HistoryItem::invalidateChatListEntry() {
if (const auto main = App::main()) {
// #TODO feeds search results
main->refreshDialogRow({ history(), fullId() });
}
history()->session().changes().messageUpdated(
this,
Data::MessageUpdate::Flag::DialogRowRefresh);
// invalidate cache for drawInDialog
if (history()->textCachedFor == this) {

View file

@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_game.h"
#include "data/data_channel.h"
#include "data/data_user.h"
#include "data/data_changes.h"
#include "window/notifications_manager.h"
#include "window/window_session_controller.h"
#include "storage/storage_shared_media.h"
@ -748,10 +749,9 @@ void HistoryService::updateDependentText() {
// feed->updateChatListEntry();
// }
//}
if (const auto main = App::main()) {
// #TODO feeds search results
main->repaintDialogRow({ history(), fullId() });
}
history()->session().changes().messageUpdated(
this,
Data::MessageUpdate::Flag::DialogRowRepaint);
history()->owner().updateDependentMessages(this);
}

View file

@ -554,18 +554,51 @@ HistoryWidget::HistoryWidget(
}
}, lifetime());
session().data().forwardDraftUpdates(
) | rpl::filter([=](not_null<History*> history) {
return (_history == history.get());
}) | rpl::start_with_next([=](not_null<History*> history) {
updateForwarding();
session().changes().historyUpdates(
Data::HistoryUpdate::Flag::MessageSent
| Data::HistoryUpdate::Flag::ForwardDraft
| Data::HistoryUpdate::Flag::BotKeyboard
| Data::HistoryUpdate::Flag::CloudDraft
| Data::HistoryUpdate::Flag::UnreadMentions
| Data::HistoryUpdate::Flag::UnreadView
| Data::HistoryUpdate::Flag::TopPromoted
| Data::HistoryUpdate::Flag::LocalMessages
) | rpl::filter([=](const Data::HistoryUpdate &update) {
return (_history == update.history.get());
}) | rpl::start_with_next([=](const Data::HistoryUpdate &update) {
if (update.flags & Data::HistoryUpdate::Flag::MessageSent) {
synteticScrollToY(_scroll->scrollTopMax());
}
if (update.flags & Data::HistoryUpdate::Flag::ForwardDraft) {
updateForwarding();
}
if (update.flags & Data::HistoryUpdate::Flag::BotKeyboard) {
updateBotKeyboard(update.history);
}
if (update.flags & Data::HistoryUpdate::Flag::CloudDraft) {
applyCloudDraft(update.history);
}
if (update.flags & Data::HistoryUpdate::Flag::LocalMessages) {
updateSendButtonType();
}
if (update.flags & Data::HistoryUpdate::Flag::UnreadMentions) {
updateUnreadMentionsVisibility();
}
if (update.flags & Data::HistoryUpdate::Flag::UnreadView) {
unreadCountUpdated();
}
if (update.flags & Data::HistoryUpdate::Flag::TopPromoted) {
updateHistoryGeometry();
updateControlsVisibility();
updateControlsGeometry();
this->update();
}
}, lifetime());
session().data().newMessageSent(
) | rpl::filter([=](not_null<History*> history) {
return (_history == history.get());
}) | rpl::start_with_next([=] {
synteticScrollToY(_scroll->scrollTopMax());
session().changes().messageUpdates(
Data::MessageUpdate::Flag::Edited
) | rpl::start_with_next([=](const Data::MessageUpdate &update) {
itemEdited(update.item);
}, lifetime());
subscribe(Media::Player::instance()->switchToNextNotifier(), [this](const Media::Player::Instance::Switch &pair) {
@ -574,33 +607,6 @@ HistoryWidget::HistoryWidget(
}
});
session().changes().historyUpdates(
Data::HistoryUpdate::Flag::UnreadMentions
| Data::HistoryUpdate::Flag::UnreadView
| Data::HistoryUpdate::Flag::TopPromoted
| Data::HistoryUpdate::Flag::LocalMessages
) | rpl::filter([=](const Data::HistoryUpdate &update) {
return (update.history->peer.get() == _peer);
}) | rpl::map([](const Data::HistoryUpdate &update) {
return update.flags;
}) | rpl::start_with_next([=](Data::HistoryUpdate::Flags flags) {
if (flags & Data::HistoryUpdate::Flag::LocalMessages) {
updateSendButtonType();
}
if (flags & Data::HistoryUpdate::Flag::UnreadMentions) {
updateUnreadMentionsVisibility();
}
if (flags & Data::HistoryUpdate::Flag::UnreadView) {
unreadCountUpdated();
}
if (flags & Data::HistoryUpdate::Flag::TopPromoted) {
updateHistoryGeometry();
updateControlsVisibility();
updateControlsGeometry();
this->update();
}
}, lifetime());
using UpdateFlag = Data::PeerUpdate::Flag;
session().changes().peerUpdates(
UpdateFlag::Rights
@ -727,6 +733,7 @@ HistoryWidget::HistoryWidget(
}
}, lifetime());
subscribeToUploader();
setupScheduledToggle();
orderWidgets();
setupShortcuts();
@ -3177,7 +3184,9 @@ void HistoryWidget::send(Api::SendOptions options) {
if (!_keyboard->hasMarkup() && _keyboard->forceReply() && !_kbReplyTo) {
toggleKeyboard();
}
session().data().newMessageSent(_history);
session().changes().historyUpdated(
_history,
Data::HistoryUpdate::Flag::MessageSent);
}
void HistoryWidget::sendWithModifiers(Qt::KeyboardModifiers modifiers) {
@ -4640,26 +4649,35 @@ void HistoryWidget::uploadFile(
}
void HistoryWidget::subscribeToUploader() {
if (_uploaderSubscriptions) {
return;
}
using namespace Storage;
session().uploader().photoReady(
) | rpl::start_with_next([=](const UploadedPhoto &data) {
if (data.edit) {
photoEdited(data.fullId, data.options, data.file);
session().api().editUploadedFile(
data.fullId,
data.file,
std::nullopt,
data.options,
false);
} else {
photoUploaded(data.fullId, data.options, data.file);
session().api().sendUploadedPhoto(
data.fullId,
data.file,
data.options);
}
}, _uploaderSubscriptions);
}, lifetime());
session().uploader().photoProgress(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
photoProgress(fullId);
}, _uploaderSubscriptions);
}, lifetime());
session().uploader().photoFailed(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
photoFailed(fullId);
}, _uploaderSubscriptions);
}, lifetime());
session().uploader().documentReady(
) | rpl::start_with_next([=](const UploadedDocument &data) {
if (data.edit) {
@ -4667,7 +4685,8 @@ void HistoryWidget::subscribeToUploader() {
} else {
documentUploaded(data.fullId, data.options, data.file);
}
}, _uploaderSubscriptions);
}, lifetime());
session().uploader().thumbDocumentReady(
) | rpl::start_with_next([=](const UploadedThumbDocument &data) {
thumbDocumentUploaded(
@ -4676,222 +4695,17 @@ void HistoryWidget::subscribeToUploader() {
data.file,
data.thumb,
data.edit);
}, _uploaderSubscriptions);
}, lifetime());
session().uploader().documentProgress(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
documentProgress(fullId);
}, _uploaderSubscriptions);
}, lifetime());
session().uploader().documentFailed(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
documentFailed(fullId);
}, _uploaderSubscriptions);
}
void HistoryWidget::sendFileConfirmed(
const std::shared_ptr<FileLoadResult> &file,
const std::optional<FullMsgId> &oldId) {
const auto isEditing = oldId.has_value();
const auto channelId = peerToChannel(file->to.peer);
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
channelId,
file->to.replyTo));
const auto newId = oldId.value_or(
FullMsgId(channelId, session().data().nextLocalMessageId()));
auto groupId = file->album ? file->album->groupId : uint64(0);
if (file->album) {
const auto proj = [](const SendingAlbum::Item &item) {
return item.taskId;
};
const auto it = ranges::find(file->album->items, file->taskId, proj);
Assert(it != file->album->items.end());
it->msgId = newId;
}
subscribeToUploader();
file->edit = isEditing;
session().uploader().upload(newId, file);
const auto itemToEdit = isEditing
? session().data().message(newId)
: nullptr;
const auto history = session().data().history(file->to.peer);
const auto peer = history->peer;
auto action = Api::SendAction(history);
action.options = file->to.options;
action.clearDraft = false;
action.replyTo = file->to.replyTo;
action.generateLocal = true;
session().api().sendAction(action);
auto caption = TextWithEntities{
file->caption.text,
TextUtilities::ConvertTextTagsToEntities(file->caption.tags)
};
const auto prepareFlags = Ui::ItemTextOptions(
history,
session().user()).flags;
TextUtilities::PrepareForSending(caption, prepareFlags);
TextUtilities::Trim(caption);
auto localEntities = Api::EntitiesToMTP(&session(), caption.entities);
if (itemToEdit) {
if (const auto id = itemToEdit->groupId()) {
groupId = id.value;
}
}
auto flags = (isEditing ? MTPDmessage::Flags() : NewMessageFlags(peer))
| MTPDmessage::Flag::f_entities
| MTPDmessage::Flag::f_media;
auto clientFlags = NewMessageClientFlags();
if (file->to.replyTo) {
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
}
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = file->to.options.silent;
Api::FillMessagePostFlags(action, peer, flags);
if (silentPost) {
flags |= MTPDmessage::Flag::f_silent;
}
if (groupId) {
flags |= MTPDmessage::Flag::f_grouped_id;
}
if (file->to.options.scheduled) {
flags |= MTPDmessage::Flag::f_from_scheduled;
} else {
clientFlags |= MTPDmessage_ClientFlag::f_local_history_entry;
}
const auto messageFromId = channelPost ? 0 : session().userId();
const auto messagePostAuthor = channelPost
? session().user()->name
: QString();
if (file->type == SendMediaType::Photo) {
const auto photoFlags = MTPDmessageMediaPhoto::Flag::f_photo | 0;
const auto photo = MTP_messageMediaPhoto(
MTP_flags(photoFlags),
file->photo,
MTPint());
const auto mtpMessage = MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(file->to.peer),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(file->to.replyTo),
MTP_int(HistoryItem::NewMessageDate(file->to.options.scheduled)),
MTP_string(caption.text),
photo,
MTPReplyMarkup(),
localEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTP_long(groupId),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>());
if (itemToEdit) {
itemToEdit->savePreviousMedia();
itemToEdit->applyEdition(mtpMessage.c_message());
} else {
history->addNewMessage(
mtpMessage,
clientFlags,
NewMessageType::Unread);
}
} else if (file->type == SendMediaType::File) {
const auto documentFlags = MTPDmessageMediaDocument::Flag::f_document | 0;
const auto document = MTP_messageMediaDocument(
MTP_flags(documentFlags),
file->document,
MTPint());
const auto mtpMessage = MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(file->to.peer),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(file->to.replyTo),
MTP_int(HistoryItem::NewMessageDate(file->to.options.scheduled)),
MTP_string(caption.text),
document,
MTPReplyMarkup(),
localEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTP_long(groupId),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>());
if (itemToEdit) {
itemToEdit->savePreviousMedia();
itemToEdit->applyEdition(mtpMessage.c_message());
} else {
history->addNewMessage(
mtpMessage,
clientFlags,
NewMessageType::Unread);
}
} else if (file->type == SendMediaType::Audio) {
if (!peer->isChannel() || peer->isMegagroup()) {
flags |= MTPDmessage::Flag::f_media_unread;
}
const auto documentFlags = MTPDmessageMediaDocument::Flag::f_document | 0;
const auto document = MTP_messageMediaDocument(
MTP_flags(documentFlags),
file->document,
MTPint());
history->addNewMessage(
MTP_message(
MTP_flags(flags),
MTP_int(newId.msg),
MTP_int(messageFromId),
peerToMTP(file->to.peer),
MTPMessageFwdHeader(),
MTPint(),
MTP_int(file->to.replyTo),
MTP_int(
HistoryItem::NewMessageDate(file->to.options.scheduled)),
MTP_string(caption.text),
document,
MTPReplyMarkup(),
localEntities,
MTP_int(1),
MTPint(),
MTP_string(messagePostAuthor),
MTP_long(groupId),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>()),
clientFlags,
NewMessageType::Unread);
// Voices can't be edited.
} else {
Unexpected("Type in sendFilesConfirmed.");
}
if (isEditing) {
return;
}
session().data().sendHistoryChangeNotifications();
session().data().newMessageSent(history);
}
void HistoryWidget::photoUploaded(
const FullMsgId &newId,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().sendUploadedPhoto(newId, file, options);
}, lifetime());
}
void HistoryWidget::documentUploaded(
@ -4908,13 +4722,6 @@ void HistoryWidget::documentEdited(
session().api().editUploadedFile(newId, file, std::nullopt, options, true);
}
void HistoryWidget::photoEdited(
const FullMsgId &newId,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().editUploadedFile(newId, file, std::nullopt, options, false);
}
void HistoryWidget::thumbDocumentUploaded(
const FullMsgId &newId,
Api::SendOptions options,
@ -5151,8 +4958,8 @@ void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
}
}
void HistoryWidget::itemEdited(HistoryItem *item) {
if (item == _replyEditMsg) {
void HistoryWidget::itemEdited(not_null<HistoryItem*> item) {
if (item.get() == _replyEditMsg) {
updateReplyEditTexts(true);
}
if (_pinnedBar && item->id == _pinnedBar->msgId) {

View file

@ -172,7 +172,7 @@ public:
crl::time highlightStartTime(not_null<const HistoryItem*> item) const;
MessageIdsList getSelectedItems() const;
void itemEdited(HistoryItem *item);
void itemEdited(not_null<HistoryItem*> item);
void updateScrollColors();
@ -477,10 +477,6 @@ private:
void subscribeToUploader();
void photoUploaded(
const FullMsgId &msgId,
Api::SendOptions options,
const MTPInputFile &file);
void photoProgress(const FullMsgId &msgId);
void photoFailed(const FullMsgId &msgId);
void documentUploaded(
@ -501,11 +497,6 @@ private:
Api::SendOptions options,
const MTPInputFile &file);
void photoEdited(
const FullMsgId &msgId,
Api::SendOptions options,
const MTPInputFile &file);
void itemRemoved(not_null<const HistoryItem*> item);
// Updates position of controls around the message field,
@ -767,8 +758,6 @@ private:
int _recordingSamples = 0;
int _recordCancelWidth;
rpl::lifetime _uploaderSubscriptions;
// This can animate for a very long time (like in music playing),
// so it should be a Basic, not a Simple animation.
Ui::Animations::Basic _recordingAnimation;

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer_values.h"
#include "data/data_drafts.h"
#include "data/data_session.h"
#include "data/data_changes.h"
#include "data/data_media_types.h"
#include "data/data_folder.h"
#include "data/data_channel.h"
@ -281,8 +282,10 @@ MainWidget::MainWidget(
[this] { updateControlsGeometry(); },
lifetime());
session().data().newMessageSent(
) | rpl::start_with_next([=](not_null<History*> history) {
session().changes().historyUpdates(
Data::HistoryUpdate::Flag::MessageSent
) | rpl::start_with_next([=](const Data::HistoryUpdate &update) {
const auto history = update.history;
history->forgetScrollState();
if (const auto from = history->peer->migrateFrom()) {
if (const auto migrated = history->owner().historyLoaded(from)) {
@ -758,10 +761,6 @@ bool MainWidget::selectingPeer() const {
return _hider ? true : false;
}
void MainWidget::removeDialog(Dialogs::Key key) {
_dialogs->removeDialog(key);
}
void MainWidget::cacheBackground() {
if (Window::Theme::Background()->colorForFill()) {
return;
@ -850,13 +849,6 @@ void MainWidget::searchMessages(const QString &query, Dialogs::Key inChat) {
}
}
void MainWidget::itemEdited(not_null<HistoryItem*> item) {
if (_history->peer() == item->history()->peer
|| (_history->peer() && _history->peer() == item->history()->peer->migrateTo())) {
_history->itemEdited(item);
}
}
void MainWidget::handleAudioUpdate(const Media::Player::TrackState &state) {
using State = Media::Player::State;
const auto document = state.id.audio();
@ -1087,12 +1079,6 @@ void MainWidget::inlineResultLoadFailed(FileLoader *loader, bool started) {
//Ui::repaintInlineItem();
}
void MainWidget::onSendFileConfirm(
const std::shared_ptr<FileLoadResult> &file,
const std::optional<FullMsgId> &oldId) {
_history->sendFileConfirmed(file, oldId);
}
bool MainWidget::sendExistingDocument(not_null<DocumentData*> document) {
return _history->sendExistingDocument(document);
}
@ -1234,10 +1220,6 @@ Image *MainWidget::newBackgroundThumb() {
: nullptr;
}
void MainWidget::updateBotKeyboard(History *h) {
_history->updateBotKeyboard(h);
}
void MainWidget::pushReplyReturn(not_null<HistoryItem*> item) {
_history->pushReplyReturn(item);
}
@ -1339,10 +1321,6 @@ void MainWidget::viewsIncrementFail(const RPCError &error, mtpRequestId requestI
}
}
void MainWidget::refreshDialog(Dialogs::Key key) {
_dialogs->refreshDialog(key);
}
void MainWidget::choosePeer(PeerId peerId, MsgId showAtMsgId) {
if (selectingPeer()) {
_hider->offerPeer(peerId);
@ -1956,20 +1934,6 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams &param
return result;
}
void MainWidget::repaintDialogRow(
FilterId filterId,
not_null<Dialogs::Row*> row) {
_dialogs->repaintDialogRow(filterId, row);
}
void MainWidget::repaintDialogRow(Dialogs::RowDescriptor row) {
_dialogs->repaintDialogRow(row);
}
void MainWidget::refreshDialogRow(Dialogs::RowDescriptor row) {
_dialogs->refreshDialogRow(row);
}
void MainWidget::windowShown() {
_history->windowShown();
}
@ -2801,10 +2765,6 @@ int32 MainWidget::dlgsWidth() const {
return _dialogs->width();
}
void MainWidget::applyCloudDraft(History *history) {
_history->applyCloudDraft(history);
}
void MainWidget::saveFieldToHistoryLocalDraft() {
_history->saveFieldToHistoryLocalDraft();
}

View file

@ -129,12 +129,6 @@ public:
bool started();
void activate();
void refreshDialog(Dialogs::Key key);
void removeDialog(Dialogs::Key key);
void repaintDialogRow(FilterId filterId, not_null<Dialogs::Row*> row);
void repaintDialogRow(Dialogs::RowDescriptor row);
void refreshDialogRow(Dialogs::RowDescriptor row);
void windowShown();
void dialogsToUp();
@ -155,15 +149,11 @@ public:
QPixmap grabForShowAnimation(const Window::SectionSlideParams &params);
void checkMainSectionToLayer();
void onSendFileConfirm(
const std::shared_ptr<FileLoadResult> &file,
const std::optional<FullMsgId> &oldId);
bool sendExistingDocument(not_null<DocumentData*> sticker);
bool isActive() const;
[[nodiscard]] bool doWeMarkAsRead() const;
void applyCloudDraft(History *history);
void saveFieldToHistoryLocalDraft();
int32 dlgsWidth() const;
@ -201,7 +191,6 @@ public:
bool insertBotCommand(const QString &cmd);
void searchMessages(const QString &query, Dialogs::Key inChat);
void itemEdited(not_null<HistoryItem*> item);
QPixmap cachedBackground(const QRect &forRect, int &x, int &y);
void updateScrollColors();
@ -214,8 +203,6 @@ public:
void checkChatBackground();
Image *newBackgroundThumb();
void updateBotKeyboard(History *h);
void pushReplyReturn(not_null<HistoryItem*> item);
// Does offerPeer or showPeerHistory.

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localimageloader.h"
#include "api/api_text_entities.h"
#include "api/api_sending.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "core/file_utilities.h"
@ -476,7 +477,7 @@ void FileLoadResult::setThumbData(const QByteArray &thumbdata) {
FileLoadTask::FileLoadTask(
MTP::DcId dcId,
not_null<Main::Session*> session,
const QString &filepath,
const QByteArray &content,
std::unique_ptr<FileMediaInformation> information,
@ -486,7 +487,8 @@ FileLoadTask::FileLoadTask(
std::shared_ptr<SendingAlbum> album,
MsgId msgIdToEdit)
: _id(rand_value<uint64>())
, _dcId(dcId)
, _session(session)
, _dcId(session->mainDcId())
, _to(to)
, _album(std::move(album))
, _filepath(filepath)
@ -499,14 +501,15 @@ FileLoadTask::FileLoadTask(
}
FileLoadTask::FileLoadTask(
MTP::DcId dcId,
not_null<Main::Session*> session,
const QByteArray &voice,
int32 duration,
const VoiceWaveform &waveform,
const FileLoadTo &to,
const TextWithTags &caption)
: _id(rand_value<uint64>())
, _dcId(dcId)
, _session(session)
, _dcId(session->mainDcId())
, _to(to)
, _content(voice)
, _duration(duration)
@ -965,13 +968,13 @@ void FileLoadTask::finish() {
tr::lng_send_image_too_large(tr::now, lt_name, _filepath)),
Ui::LayerOption::KeepOther);
removeFromAlbum();
} else if (App::main()) {
} else if (const auto session = _session.get()) {
const auto fullId = _msgIdToEdit
? std::make_optional(FullMsgId(
peerToChannel(_to.peer),
_msgIdToEdit))
: std::nullopt;
App::main()->onSendFileConfirm(_result, fullId);
Api::SendConfirmedFile(session, _result, fullId);
}
}

View file

@ -270,7 +270,7 @@ public:
std::unique_ptr<FileMediaInformation> &result);
FileLoadTask(
MTP::DcId dcId,
not_null<Main::Session*> session,
const QString &filepath,
const QByteArray &content,
std::unique_ptr<FileMediaInformation> information,
@ -280,7 +280,7 @@ public:
std::shared_ptr<SendingAlbum> album = nullptr,
MsgId msgIdToEdit = 0);
FileLoadTask(
MTP::DcId dcId,
not_null<Main::Session*> session,
const QByteArray &voice,
int32 duration,
const VoiceWaveform &waveform,
@ -319,6 +319,7 @@ private:
void removeFromAlbum();
uint64 _id = 0;
base::weak_ptr<Main::Session> _session;
MTP::DcId _dcId = 0;
FileLoadTo _to;
const std::shared_ptr<SendingAlbum> _album;