/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "api/api_todo_lists.h" //#include "api/api_common.h" //#include "api/api_updates.h" #include "apiwrap.h" //#include "base/random.h" //#include "data/business/data_shortcut_messages.h" //#include "data/data_changes.h" //#include "data/data_histories.h" #include "data/data_todo_list.h" #include "data/data_session.h" #include "history/history.h" #include "history/history_item.h" //#include "history/history_item_helpers.h" // ShouldSendSilent #include "main/main_session.h" namespace Api { namespace { constexpr auto kSendTogglesDelay = 3 * crl::time(1000); [[nodiscard]] TimeId UnixtimeFromMsgId(mtpMsgId msgId) { return TimeId(msgId >> 32); } } // namespace TodoLists::TodoLists(not_null api) : _session(&api->session()) , _api(&api->instance()) , _sendTimer([=] { sendAccumulatedToggles(false); }) { } // //void TodoLists::create( // const PollData &data, // SendAction action, // Fn done, // Fn fail) { // _session->api().sendAction(action); // // const auto history = action.history; // const auto peer = history->peer; // const auto topicRootId = action.replyTo.messageId // ? action.replyTo.topicRootId // : 0; // const auto monoforumPeerId = action.replyTo.monoforumPeerId; // auto sendFlags = MTPmessages_SendMedia::Flags(0); // if (action.replyTo) { // sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to; // } // const auto clearCloudDraft = action.clearDraft; // if (clearCloudDraft) { // sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; // history->clearLocalDraft(topicRootId, monoforumPeerId); // history->clearCloudDraft(topicRootId, monoforumPeerId); // history->startSavingCloudDraft(topicRootId, monoforumPeerId); // } // const auto silentPost = ShouldSendSilent(peer, action.options); // const auto starsPaid = std::min( // peer->starsPerMessageChecked(), // action.options.starsApproved); // if (silentPost) { // sendFlags |= MTPmessages_SendMedia::Flag::f_silent; // } // if (action.options.scheduled) { // sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; // } // if (action.options.shortcutId) { // sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; // } // if (action.options.effectId) { // sendFlags |= MTPmessages_SendMedia::Flag::f_effect; // } // if (starsPaid) { // action.options.starsApproved -= starsPaid; // sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars; // } // const auto sendAs = action.options.sendAs; // if (sendAs) { // sendFlags |= MTPmessages_SendMedia::Flag::f_send_as; // } // auto &histories = history->owner().histories(); // const auto randomId = base::RandomValue(); // histories.sendPreparedMessage( // history, // action.replyTo, // randomId, // Data::Histories::PrepareMessage( // MTP_flags(sendFlags), // peer->input, // Data::Histories::ReplyToPlaceholder(), // PollDataToInputMedia(&data), // MTP_string(), // MTP_long(randomId), // MTPReplyMarkup(), // MTPVector(), // MTP_int(action.options.scheduled), // (sendAs ? sendAs->input : MTP_inputPeerEmpty()), // Data::ShortcutIdToMTP(_session, action.options.shortcutId), // MTP_long(action.options.effectId), // MTP_long(starsPaid) // ), [=](const MTPUpdates &result, const MTP::Response &response) { // if (clearCloudDraft) { // history->finishSavingCloudDraft( // topicRootId, // monoforumPeerId, // UnixtimeFromMsgId(response.outerMsgId)); // } // _session->changes().historyUpdated( // history, // (action.options.scheduled // ? Data::HistoryUpdate::Flag::ScheduledSent // : Data::HistoryUpdate::Flag::MessageSent)); // done(); // }, [=](const MTP::Error &error, const MTP::Response &response) { // if (clearCloudDraft) { // history->finishSavingCloudDraft( // topicRootId, // monoforumPeerId, // UnixtimeFromMsgId(response.outerMsgId)); // } // fail(); // }); //} void TodoLists::toggleCompletion(FullMsgId itemId, int id, bool completed) { auto &entry = _toggles[itemId]; if (completed) { if (!entry.completed.emplace(id).second) { return; } } else { if (!entry.incompleted.emplace(id).second) { return; } } entry.scheduled = crl::now(); if (!entry.requestId && !_sendTimer.isActive()) { _sendTimer.callOnce(kSendTogglesDelay); } } void TodoLists::sendAccumulatedToggles(bool force) { const auto now = crl::now(); auto nearest = crl::time(0); for (auto &[itemId, entry] : _toggles) { if (entry.requestId) { continue; } const auto wait = entry.scheduled + kSendTogglesDelay - now; if (wait <= 0) { entry.scheduled = 0; send(itemId, entry); } else if (!nearest || nearest > wait) { nearest = wait; } } if (nearest > 0) { _sendTimer.callOnce(nearest); } } void TodoLists::send(FullMsgId itemId, Accumulated &entry) { const auto item = _session->data().message(itemId); if (!item) { return; } auto completed = entry.completed | ranges::views::transform([](int id) { return MTP_int(id); }); auto incompleted = entry.incompleted | ranges::views::transform([](int id) { return MTP_int(id); }); entry.requestId = _api.request(MTPmessages_ToggleTodoCompleted( item->history()->peer->input, MTP_int(item->id), MTP_vector_from_range(completed), MTP_vector_from_range(incompleted) )).done([=](const MTPUpdates &result) { _session->api().applyUpdates(result); finishRequest(itemId); }).fail([=](const MTP::Error &error) { finishRequest(itemId); }).send(); entry.completed.clear(); entry.incompleted.clear(); } void TodoLists::finishRequest(FullMsgId itemId) { auto &entry = _toggles[itemId]; entry.requestId = 0; if (entry.completed.empty() && entry.incompleted.empty()) { _toggles.remove(itemId); } else { sendAccumulatedToggles(false); } } } // namespace Api