mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Remove non-UI calls to App::main.
This commit is contained in:
parent
3c4e959468
commit
f450f81215
36 changed files with 768 additions and 675 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -102,7 +102,7 @@ void DicePack::tryGenerateLocalZero() {
|
|||
return;
|
||||
}
|
||||
auto task = FileLoadTask(
|
||||
_session->mainDcId(),
|
||||
_session,
|
||||
path,
|
||||
QByteArray(),
|
||||
nullptr,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ¶m
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -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 ¶ms);
|
||||
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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue