diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index 6f971c43d..be53452a2 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -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 session, + const std::shared_ptr &file, + const std::optional &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()); + + 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()); + + 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()), + 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 diff --git a/Telegram/SourceFiles/api/api_sending.h b/Telegram/SourceFiles/api/api_sending.h index 0a8d9f08e..96458281b 100644 --- a/Telegram/SourceFiles/api/api_sending.h +++ b/Telegram/SourceFiles/api/api_sending.h @@ -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 peer, MTPDmessage::Flags &flags); +void SendConfirmedFile( + not_null session, + const std::shared_ptr &file, + const std::optional &oldId); + } // namespace Api diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 84ba30584..e60b9d0ed 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -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( - 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( - instance()->mainDcId(), + &session(), file.path, file.content, std::move(file.information), @@ -4326,7 +4330,7 @@ void ApiWrap::sendFiles( } } tasks.push_back(std::make_unique( - 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( - instance()->mainDcId(), + &session(), QString(), fileContent, nullptr, diff --git a/Telegram/SourceFiles/boxes/dictionaries_manager.cpp b/Telegram/SourceFiles/boxes/dictionaries_manager.cpp index facced46b..476cf9ba1 100644 --- a/Telegram/SourceFiles/boxes/dictionaries_manager.cpp +++ b/Telegram/SourceFiles/boxes/dictionaries_manager.cpp @@ -296,7 +296,7 @@ auto AddButtonWithLoader( if (toggled && (state.is() || state.is())) { const auto weak = Ui::MakeWeak(button); setLocalLoader(base::make_unique_q( - controller->content(), + QCoreApplication::instance(), &controller->session(), id, Spellchecker::GetDownloadLocation(id), diff --git a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp index d7d84f230..c5427877c 100644 --- a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp +++ b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp @@ -162,7 +162,7 @@ void DownloadDictionaryInBackground( auto sharedLoader = std::make_shared>(); *sharedLoader = base::make_unique_q( - App::main(), + QCoreApplication::instance(), session, id, GetDownloadLocation(id), diff --git a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp index 0ca837c9d..b45a533ca 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp @@ -102,7 +102,7 @@ void DicePack::tryGenerateLocalZero() { return; } auto task = FileLoadTask( - _session->mainDcId(), + _session, path, QByteArray(), nullptr, diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index e02935f4e..0b3768971 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -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; } diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index f84d1128f..a73fe0b04 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -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); + } } } diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 9768c82d7..8b6f5282b 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -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(); - 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( diff --git a/Telegram/SourceFiles/data/data_changes.cpp b/Telegram/SourceFiles/data/data_changes.cpp index 461d97e3e..fdc2ca5f0 100644 --- a/Telegram/SourceFiles/data/data_changes.cpp +++ b/Telegram/SourceFiles/data/data_changes.cpp @@ -14,8 +14,19 @@ namespace Data { template void Changes::Manager::updated( not_null 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 @@ -148,6 +159,72 @@ rpl::producer Changes::historyFlagsValue( return _historyChanges.flagsValue(history, flags); } +rpl::producer Changes::realtimeHistoryUpdates( + HistoryUpdate::Flag flag) const { + return _historyChanges.realtimeUpdates(flag); +} + +void Changes::messageUpdated( + not_null item, + MessageUpdate::Flags flags) { + const auto drop = (flags & MessageUpdate::Flag::Destroyed); + _messageChanges.updated(item, flags, drop); + if (!drop) { + scheduleNotifications(); + } +} + +rpl::producer Changes::messageUpdates( + MessageUpdate::Flags flags) const { + return _messageChanges.updates(flags); +} + +rpl::producer Changes::messageUpdates( + not_null item, + MessageUpdate::Flags flags) const { + return _messageChanges.updates(item, flags); +} + +rpl::producer Changes::messageFlagsValue( + not_null item, + MessageUpdate::Flags flags) const { + return _messageChanges.flagsValue(item, flags); +} + +rpl::producer Changes::realtimeMessageUpdates( + MessageUpdate::Flag flag) const { + return _messageChanges.realtimeUpdates(flag); +} + +void Changes::entryUpdated( + not_null entry, + EntryUpdate::Flags flags) { + _entryChanges.updated(entry, flags); + scheduleNotifications(); +} + +rpl::producer Changes::entryUpdates( + EntryUpdate::Flags flags) const { + return _entryChanges.updates(flags); +} + +rpl::producer Changes::entryUpdates( + not_null entry, + EntryUpdate::Flags flags) const { + return _entryChanges.updates(entry, flags); +} + +rpl::producer Changes::entryFlagsValue( + not_null entry, + EntryUpdate::Flags flags) const { + return _entryChanges.flagsValue(entry, flags); +} + +rpl::producer 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 diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h index 6c84c4949..cb2d435f4 100644 --- a/Telegram/SourceFiles/data/data_changes.h +++ b/Telegram/SourceFiles/data/data_changes.h @@ -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; 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; + friend inline constexpr auto is_flag_type(Flag) { return true; } + + not_null item; + Flags flags = 0; + +}; + +struct EntryUpdate { + enum class Flag : uint32 { + None = 0, + + Repaint = (1 << 0), + + LastUsedBit = (1 << 0), + }; + using Flags = base::flags; + friend inline constexpr auto is_flag_type(Flag) { return true; } + + not_null entry; + Flags flags = 0; + +}; + class Changes final { public: explicit Changes(not_null session); @@ -136,6 +181,36 @@ public: [[nodiscard]] rpl::producer historyFlagsValue( not_null history, HistoryUpdate::Flags flags) const; + [[nodiscard]] rpl::producer realtimeHistoryUpdates( + HistoryUpdate::Flag flag) const; + + void messageUpdated( + not_null item, + MessageUpdate::Flags flags); + [[nodiscard]] rpl::producer messageUpdates( + MessageUpdate::Flags flags) const; + [[nodiscard]] rpl::producer messageUpdates( + not_null item, + MessageUpdate::Flags flags) const; + [[nodiscard]] rpl::producer messageFlagsValue( + not_null item, + MessageUpdate::Flags flags) const; + [[nodiscard]] rpl::producer realtimeMessageUpdates( + MessageUpdate::Flag flag) const; + + void entryUpdated( + not_null entry, + EntryUpdate::Flags flags); + [[nodiscard]] rpl::producer entryUpdates( + EntryUpdate::Flags flags) const; + [[nodiscard]] rpl::producer entryUpdates( + not_null entry, + EntryUpdate::Flags flags) const; + [[nodiscard]] rpl::producer entryFlagsValue( + not_null entry, + EntryUpdate::Flags flags) const; + [[nodiscard]] rpl::producer 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 data, Flags flags); + void updated( + not_null data, + Flags flags, + bool dropScheduled = false); [[nodiscard]] rpl::producer updates(Flags flags) const; [[nodiscard]] rpl::producer updates( not_null data, @@ -189,6 +267,8 @@ private: rpl::event_stream _nameStream; Manager _peerChanges; Manager _historyChanges; + Manager _messageChanges; + Manager _entryChanges; bool _notify = false; diff --git a/Telegram/SourceFiles/data/data_chat_filters.cpp b/Telegram/SourceFiles/data/data_chat_filters.cpp index 7234f6401..202b18a21 100644 --- a/Telegram/SourceFiles/data/data_chat_filters.cpp +++ b/Telegram/SourceFiles/data/data_chat_filters.cpp @@ -560,12 +560,9 @@ bool ChatFilters::loadNextExceptions(bool chatsListLoaded) { } void ChatFilters::refreshHistory(not_null history) { - _refreshHistoryRequests.fire_copy(history); -} - -auto ChatFilters::refreshHistoryRequests() const --> rpl::producer> { - return _refreshHistoryRequests.events(); + if (history->inChatList() && !list().empty()) { + _owner->refreshChatListEntry(history); + } } void ChatFilters::requestSuggested() { diff --git a/Telegram/SourceFiles/data/data_chat_filters.h b/Telegram/SourceFiles/data/data_chat_filters.h index 7ad560857..04ced87a5 100644 --- a/Telegram/SourceFiles/data/data_chat_filters.h +++ b/Telegram/SourceFiles/data/data_chat_filters.h @@ -105,8 +105,6 @@ public: bool loadNextExceptions(bool chatsListLoaded); void refreshHistory(not_null history); - [[nodiscard]] auto refreshHistoryRequests() const - -> rpl::producer>; [[nodiscard]] not_null chatsList(FilterId filterId); @@ -137,7 +135,6 @@ private: std::vector _list; base::flat_map> _chatsLists; rpl::event_stream<> _listChanged; - rpl::event_stream> _refreshHistoryRequests; mtpRequestId _loadRequestId = 0; mtpRequestId _saveOrderRequestId = 0; mtpRequestId _saveOrderAfterId = 0; diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index cd1a9305b..65790e3a5 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -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(); diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index a28f68d3d..06ef2d1fa 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -55,7 +55,7 @@ rpl::producer PinnedDialogsInFolderMaxValue( //} Folder::Folder(not_null owner, FolderId id) -: Entry(owner, this) +: Entry(owner, Type::Folder) , _id(id) , _chatsList( &owner->session(), diff --git a/Telegram/SourceFiles/data/data_photo.cpp b/Telegram/SourceFiles/data/data_photo.cpp index 6829ead83..33aaa52cd 100644 --- a/Telegram/SourceFiles/data/data_photo.cpp +++ b/Telegram/SourceFiles/data/data_photo.cpp @@ -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(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 7e3e20cd4..1c5798d70 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -237,7 +237,7 @@ Session::Session(not_null session) } } - setupContactViewsViewer(); + setupMigrationViewer(); setupChannelLeavingViewer(); setupPeerNameViewer(); setupUserIsContactViewer(); @@ -822,7 +822,7 @@ void Session::deleteConversationLocally(not_null 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 peer) { } } } -void Session::newMessageSent(not_null history) { - _newMessageSent.fire_copy(history); -} - -rpl::producer> Session::newMessageSent() const { - return _newMessageSent.events(); -} void Session::cancelForwarding(not_null history) { history->setForwardDraft({}); - _forwardDraftUpdated.fire_copy(history); -} - -rpl::producer> 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 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 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 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 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> Session::channelDifferenceTooLong() const return _channelDifferenceTooLong.events(); } -void Session::historyOutboxRead(not_null history) { - _historyOutboxReads.fire_copy(history); -} - -rpl::producer> Session::historyOutboxReads() const { - return _historyOutboxReads.events(); -} - void Session::registerItemView(not_null view) { _views[view->data()].push_back(view); } @@ -3409,10 +3406,7 @@ not_null 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 { + return _chatListEntryRefreshes.events(); +} + + void Session::dialogsRowReplaced(DialogsRowReplacement replacement) { _dialogsRowReplacements.fire(std::move(replacement)); } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index c78e0fdb6..fe060e8a0 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -180,10 +180,7 @@ public: void deleteConversationLocally(not_null peer); - void newMessageSent(not_null history); - [[nodiscard]] rpl::producer> newMessageSent() const; void cancelForwarding(not_null history); - [[nodiscard]] rpl::producer> forwardDraftUpdates() const; void registerSendAction( not_null history, @@ -561,9 +558,6 @@ public: void channelDifferenceTooLong(not_null channel); [[nodiscard]] rpl::producer> channelDifferenceTooLong() const; - void historyOutboxRead(not_null history); - [[nodiscard]] rpl::producer> historyOutboxReads() const; - void registerItemView(not_null view); void unregisterItemView(not_null view); @@ -582,14 +576,20 @@ public: [[nodiscard]] not_null contactsList(); [[nodiscard]] not_null 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; struct DialogsRowReplacement { not_null 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 _megagroupParticipantRemoved; rpl::event_stream _megagroupParticipantAdded; rpl::event_stream _dialogsRowReplacements; + rpl::event_stream _chatListEntryRefreshes; Dialogs::MainList _chatsList; Dialogs::IndexedList _contactsList; @@ -879,9 +880,6 @@ private: rpl::event_stream> _webpageUpdates; rpl::event_stream> _channelDifferenceTooLong; - rpl::event_stream> _historyOutboxReads; - rpl::event_stream> _newMessageSent; - rpl::event_stream> _forwardDraftUpdated; base::flat_multi_map> _pollsClosings; base::Timer _pollsClosingTimer; diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index 4ccc2026d..8f0826e31 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -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 owner, const Key &key) +Entry::Entry(not_null 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(this); +} + +Data::Folder *Entry::asFolder() { + return _isFolder ? static_cast(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 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 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 diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.h b/Telegram/SourceFiles/dialogs/dialogs_entry.h index 237d46497..297313d78 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.h +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.h @@ -90,7 +90,11 @@ inline UnreadState operator-(const UnreadState &a, const UnreadState &b) { class Entry { public: - Entry(not_null owner, const Key &key); + enum class Type { + History, + Folder, + }; + Entry(not_null 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 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 addToChatList( FilterId filterId, @@ -116,7 +125,7 @@ public: FilterId filterId, QChar letter, not_null 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 mainChatListLink(FilterId filterId) const; Row *maybeMainChatListLink(FilterId filterId) const; - not_null _owner; - Dialogs::Key _key; + const not_null _owner; base::flat_map _chatListLinks; uint64 _sortKeyInChatList = 0; uint64 _sortKeyByDate = 0; base::flat_map _pinnedIndex; TimeId _timeId = 0; bool _isTopPromoted = false; + const bool _isFolder = false; }; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 10bcada04..c1c403e2a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -209,14 +209,6 @@ InnerWidget::InnerWidget( refresh(); }, lifetime()); - session().data().chatsFilters().refreshHistoryRequests( - ) | rpl::start_with_next([=](not_null 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 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 folder) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index ad0824bbd..847f1228c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -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); - void repaintDialogRow(RowDescriptor row); - void refreshDialogRow(RowDescriptor row); - void dragLeft(); void clearFilter(); @@ -193,6 +187,10 @@ private: not_null result, const RowDescriptor &entry) const; + void repaintDialogRow(FilterId filterId, not_null 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 chat); + void handleChatListEntryRefreshes(); not_null _controller; diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.cpp b/Telegram/SourceFiles/dialogs/dialogs_key.cpp index a402f3d79..a9013a29f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_key.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_key.cpp @@ -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) : _value(history) { +} + +Key::Key(not_null folder) : _value(folder) { +} + not_null Key::entry() const { - if (const auto p = base::get_if>(&_value)) { - return *p; - } else if (const auto p = base::get_if>(&_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>(&_value)) { - return *p; - } - return nullptr; + return _value ? _value->asHistory() : nullptr; } Folder *Key::folder() const { - if (const auto p = base::get_if>(&_value)) { - return *p; - } - return nullptr; + return _value ? _value->asFolder() : nullptr; } PeerData *Key::peer() const { - if (const auto p = base::get_if>(&_value)) { - return (*p)->peer; + if (const auto history = this->history()) { + return history->peer; } return nullptr; } diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.h b/Telegram/SourceFiles/dialogs/dialogs_key.h index a17cddd07..223488d21 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_key.h +++ b/Telegram/SourceFiles/dialogs/dialogs_key.h @@ -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) : _value(history) { - } - Key(Data::Folder *folder) : _value(folder) { - } - Key(not_null folder) : _value(folder) { + Key(History *history); + Key(Data::Folder *folder); + Key(not_null entry) : _value(entry) { } + Key(not_null history); + Key(not_null folder); explicit operator bool() const { - return !!_value; + return (_value != nullptr); } not_null entry() const; History *history() const; @@ -58,21 +59,13 @@ public: return !(*this == other); } - base::optional_variant< - not_null, - not_null> raw() const { - return _value; - } - // Not working :( //friend inline auto value_ordering_helper(const Key &key) { // return key.value; //} private: - base::optional_variant< - not_null, - not_null> _value; + Entry *_value = nullptr; }; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index da73edb44..c845833af 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -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) { - _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) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 2cd4b8412..8b4d3eda5 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -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); - void repaintDialogRow(RowDescriptor row); - void refreshDialogRow(RowDescriptor row); - void jumpToTop(); void startWidthAnimation(); @@ -212,7 +206,7 @@ private: object_ptr _scrollToTop; Data::Folder *_openedFolder = nullptr; - Key _searchInChat; + Dialogs::Key _searchInChat; History *_searchInMigrated = nullptr; UserData *_searchFromUser = nullptr; QString _lastFilterText; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 79686904a..713b4932f 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -70,7 +70,7 @@ using UpdateFlag = Data::HistoryUpdate::Flag; } // namespace History::History(not_null 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 wasRead) { diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index d085af606..c41531d16 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -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 view) { mouseActionUpdate(); }, lifetime()); - session().data().historyOutboxReads( - ) | rpl::filter([=](not_null history) { - return (_history == history); - }) | rpl::start_with_next([=] { + session().changes().historyUpdates( + _history, + Data::HistoryUpdate::Flag::OutboxRead + ) | rpl::start_with_next([=] { update(); }, lifetime()); } diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index f63774e09..eccfe232f 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -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) { diff --git a/Telegram/SourceFiles/history/history_service.cpp b/Telegram/SourceFiles/history/history_service.cpp index 05cee1a3d..63a2926d0 100644 --- a/Telegram/SourceFiles/history/history_service.cpp +++ b/Telegram/SourceFiles/history/history_service.cpp @@ -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); } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index fdceb28da..dc169c5ea 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -554,18 +554,51 @@ HistoryWidget::HistoryWidget( } }, lifetime()); - session().data().forwardDraftUpdates( - ) | rpl::filter([=](not_null history) { - return (_history == history.get()); - }) | rpl::start_with_next([=](not_null 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) { - 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 &file, - const std::optional &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()); - - 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()); - - 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()), - 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 item) { } } -void HistoryWidget::itemEdited(HistoryItem *item) { - if (item == _replyEditMsg) { +void HistoryWidget::itemEdited(not_null item) { + if (item.get() == _replyEditMsg) { updateReplyEditTexts(true); } if (_pinnedBar && item->id == _pinnedBar->msgId) { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 021064db3..dc80a5e3e 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -172,7 +172,7 @@ public: crl::time highlightStartTime(not_null item) const; MessageIdsList getSelectedItems() const; - void itemEdited(HistoryItem *item); + void itemEdited(not_null 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 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; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 13e4a01de..dabaca6e3 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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) { + 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 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 &file, - const std::optional &oldId) { - _history->sendFileConfirmed(file, oldId); -} - bool MainWidget::sendExistingDocument(not_null 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 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 ¶m return result; } -void MainWidget::repaintDialogRow( - FilterId filterId, - not_null 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(); } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 75e58752a..5489c8e96 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -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 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 ¶ms); void checkMainSectionToLayer(); - void onSendFileConfirm( - const std::shared_ptr &file, - const std::optional &oldId); bool sendExistingDocument(not_null 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 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 item); // Does offerPeer or showPeerHistory. diff --git a/Telegram/SourceFiles/storage/localimageloader.cpp b/Telegram/SourceFiles/storage/localimageloader.cpp index 40337cb7b..26d954573 100644 --- a/Telegram/SourceFiles/storage/localimageloader.cpp +++ b/Telegram/SourceFiles/storage/localimageloader.cpp @@ -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 session, const QString &filepath, const QByteArray &content, std::unique_ptr information, @@ -486,7 +487,8 @@ FileLoadTask::FileLoadTask( std::shared_ptr album, MsgId msgIdToEdit) : _id(rand_value()) -, _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 session, const QByteArray &voice, int32 duration, const VoiceWaveform &waveform, const FileLoadTo &to, const TextWithTags &caption) : _id(rand_value()) -, _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); } } diff --git a/Telegram/SourceFiles/storage/localimageloader.h b/Telegram/SourceFiles/storage/localimageloader.h index cd0c41d68..009d032db 100644 --- a/Telegram/SourceFiles/storage/localimageloader.h +++ b/Telegram/SourceFiles/storage/localimageloader.h @@ -270,7 +270,7 @@ public: std::unique_ptr &result); FileLoadTask( - MTP::DcId dcId, + not_null session, const QString &filepath, const QByteArray &content, std::unique_ptr information, @@ -280,7 +280,7 @@ public: std::shared_ptr album = nullptr, MsgId msgIdToEdit = 0); FileLoadTask( - MTP::DcId dcId, + not_null session, const QByteArray &voice, int32 duration, const VoiceWaveform &waveform, @@ -319,6 +319,7 @@ private: void removeFromAlbum(); uint64 _id = 0; + base::weak_ptr _session; MTP::DcId _dcId = 0; FileLoadTo _to; const std::shared_ptr _album;