mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-27 07:52:57 +02:00
PoC suggested accept/decline.
This commit is contained in:
parent
e4a4be1f53
commit
cb987c1baf
21 changed files with 390 additions and 45 deletions
|
@ -176,6 +176,8 @@ PRIVATE
|
||||||
api/api_statistics_data_deserialize.h
|
api/api_statistics_data_deserialize.h
|
||||||
api/api_statistics_sender.cpp
|
api/api_statistics_sender.cpp
|
||||||
api/api_statistics_sender.h
|
api/api_statistics_sender.h
|
||||||
|
api/api_suggest_post.cpp
|
||||||
|
api/api_suggest_post.h
|
||||||
api/api_text_entities.cpp
|
api/api_text_entities.cpp
|
||||||
api/api_text_entities.h
|
api/api_text_entities.h
|
||||||
api/api_todo_lists.cpp
|
api/api_todo_lists.cpp
|
||||||
|
|
|
@ -638,6 +638,7 @@ void SendConfirmedFile(
|
||||||
edition.useSameMarkup = true;
|
edition.useSameMarkup = true;
|
||||||
edition.useSameReplies = true;
|
edition.useSameReplies = true;
|
||||||
edition.useSameReactions = true;
|
edition.useSameReactions = true;
|
||||||
|
edition.useSameSuggest = true;
|
||||||
edition.savePreviousMedia = true;
|
edition.savePreviousMedia = true;
|
||||||
itemToEdit->applyEdition(std::move(edition));
|
itemToEdit->applyEdition(std::move(edition));
|
||||||
} else {
|
} else {
|
||||||
|
|
199
Telegram/SourceFiles/api/api_suggest_post.cpp
Normal file
199
Telegram/SourceFiles/api/api_suggest_post.cpp
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
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_suggest_post.h"
|
||||||
|
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
|
#include "core/click_handler_types.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "history/history.h"
|
||||||
|
#include "history/history_item.h"
|
||||||
|
#include "history/history_item_components.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "ui/boxes/choose_date_time.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
|
||||||
|
namespace Api {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void SendApproval(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
TimeId scheduleDate = 0) {
|
||||||
|
using Flag = MTPmessages_ToggleSuggestedPostApproval::Flag;
|
||||||
|
const auto suggestion = item->Get<HistoryMessageSuggestedPost>();
|
||||||
|
if (!suggestion
|
||||||
|
|| suggestion->accepted
|
||||||
|
|| suggestion->rejected
|
||||||
|
|| suggestion->requestId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto id = item->fullId();
|
||||||
|
const auto weak = base::make_weak(controller);
|
||||||
|
const auto session = &controller->session();
|
||||||
|
const auto finish = [=] {
|
||||||
|
if (const auto item = session->data().message(id)) {
|
||||||
|
const auto suggestion = item->Get<HistoryMessageSuggestedPost>();
|
||||||
|
if (suggestion) {
|
||||||
|
suggestion->requestId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
suggestion->requestId = session->api().request(
|
||||||
|
MTPmessages_ToggleSuggestedPostApproval(
|
||||||
|
MTP_flags(scheduleDate ? Flag::f_schedule_date : Flag()),
|
||||||
|
item->history()->peer->input,
|
||||||
|
MTP_int(item->id.bare),
|
||||||
|
MTP_int(scheduleDate),
|
||||||
|
MTPstring()) // reject_comment
|
||||||
|
).done([=](const MTPUpdates &result) {
|
||||||
|
session->api().applyUpdates(result);
|
||||||
|
finish();
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
if (const auto window = weak.get()) {
|
||||||
|
window->showToast(error.type());
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendDecline(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
const QString &comment) {
|
||||||
|
using Flag = MTPmessages_ToggleSuggestedPostApproval::Flag;
|
||||||
|
const auto suggestion = item->Get<HistoryMessageSuggestedPost>();
|
||||||
|
if (!suggestion
|
||||||
|
|| suggestion->accepted
|
||||||
|
|| suggestion->rejected
|
||||||
|
|| suggestion->requestId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto id = item->fullId();
|
||||||
|
const auto weak = base::make_weak(controller);
|
||||||
|
const auto session = &controller->session();
|
||||||
|
const auto finish = [=] {
|
||||||
|
if (const auto item = session->data().message(id)) {
|
||||||
|
const auto suggestion = item->Get<HistoryMessageSuggestedPost>();
|
||||||
|
if (suggestion) {
|
||||||
|
suggestion->requestId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
suggestion->requestId = session->api().request(
|
||||||
|
MTPmessages_ToggleSuggestedPostApproval(
|
||||||
|
MTP_flags(Flag::f_reject
|
||||||
|
| (comment.isEmpty() ? Flag() : Flag::f_reject_comment)),
|
||||||
|
item->history()->peer->input,
|
||||||
|
MTP_int(item->id.bare),
|
||||||
|
MTPint(), // schedule_date
|
||||||
|
MTP_string(comment))
|
||||||
|
).done([=](const MTPUpdates &result) {
|
||||||
|
session->api().applyUpdates(result);
|
||||||
|
finish();
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
if (const auto window = weak.get()) {
|
||||||
|
window->showToast(error.type());
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestApprovalDate(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<HistoryItem*> item) {
|
||||||
|
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||||
|
const auto done = [=](TimeId result) {
|
||||||
|
SendApproval(controller, item, result);
|
||||||
|
if (const auto strong = weak->data()) {
|
||||||
|
strong->closeBox();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto dateBox = Box(Ui::ChooseDateTimeBox, Ui::ChooseDateTimeBoxArgs{
|
||||||
|
.title = tr::lng_suggest_options_date(),
|
||||||
|
.submit = tr::lng_settings_save(),
|
||||||
|
.done = done,
|
||||||
|
.min = [] { return base::unixtime::now() + 1; },
|
||||||
|
.time = (base::unixtime::now() + 86400),
|
||||||
|
});
|
||||||
|
*weak = dateBox.data();
|
||||||
|
controller->uiShow()->show(std::move(dateBox));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::shared_ptr<ClickHandler> AcceptClickHandler(
|
||||||
|
not_null<HistoryItem*> item) {
|
||||||
|
const auto session = &item->history()->session();
|
||||||
|
const auto id = item->fullId();
|
||||||
|
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||||
|
const auto my = context.other.value<ClickHandlerContext>();
|
||||||
|
const auto controller = my.sessionWindow.get();
|
||||||
|
if (!controller || &controller->session() != session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto item = session->data().message(id);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto suggestion = item->Get<HistoryMessageSuggestedPost>();
|
||||||
|
if (!suggestion) {
|
||||||
|
return;
|
||||||
|
} else if (!suggestion->date) {
|
||||||
|
RequestApprovalDate(controller, item);
|
||||||
|
} else {
|
||||||
|
SendApproval(controller, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ClickHandler> DeclineClickHandler(
|
||||||
|
not_null<HistoryItem*> item) {
|
||||||
|
const auto session = &item->history()->session();
|
||||||
|
const auto id = item->fullId();
|
||||||
|
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||||
|
const auto my = context.other.value<ClickHandlerContext>();
|
||||||
|
const auto controller = my.sessionWindow.get();
|
||||||
|
if (!controller || &controller->session() != session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto item = session->data().message(id);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto suggestion = item->Get<HistoryMessageSuggestedPost>();
|
||||||
|
if (!suggestion) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
SendDecline(controller, item, "sorry, bro..");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ClickHandler> SuggestChangesClickHandler(
|
||||||
|
not_null<HistoryItem*> item) {
|
||||||
|
const auto session = &item->history()->session();
|
||||||
|
const auto id = item->fullId();
|
||||||
|
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||||
|
const auto my = context.other.value<ClickHandlerContext>();
|
||||||
|
const auto window = my.sessionWindow.get();
|
||||||
|
if (!window || &window->session() != session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto item = session->data().message(id);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Api
|
21
Telegram/SourceFiles/api/api_suggest_post.h
Normal file
21
Telegram/SourceFiles/api/api_suggest_post.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class ClickHandler;
|
||||||
|
|
||||||
|
namespace Api {
|
||||||
|
|
||||||
|
[[nodiscard]] std::shared_ptr<ClickHandler> AcceptClickHandler(
|
||||||
|
not_null<HistoryItem*> item);
|
||||||
|
[[nodiscard]] std::shared_ptr<ClickHandler> DeclineClickHandler(
|
||||||
|
not_null<HistoryItem*> item);
|
||||||
|
[[nodiscard]] std::shared_ptr<ClickHandler> SuggestChangesClickHandler(
|
||||||
|
not_null<HistoryItem*> item);
|
||||||
|
|
||||||
|
} // namespace Api
|
|
@ -2154,6 +2154,9 @@ void ApiWrap::saveDraftsToCloud() {
|
||||||
if (!textWithTags.tags.isEmpty()) {
|
if (!textWithTags.tags.isEmpty()) {
|
||||||
flags |= MTPmessages_SaveDraft::Flag::f_entities;
|
flags |= MTPmessages_SaveDraft::Flag::f_entities;
|
||||||
}
|
}
|
||||||
|
if (cloudDraft->suggest) {
|
||||||
|
flags |= MTPmessages_SaveDraft::Flag::f_suggested_post;
|
||||||
|
}
|
||||||
auto entities = Api::EntitiesToMTP(
|
auto entities = Api::EntitiesToMTP(
|
||||||
_session,
|
_session,
|
||||||
TextUtilities::ConvertTextTagsToEntities(textWithTags.tags),
|
TextUtilities::ConvertTextTagsToEntities(textWithTags.tags),
|
||||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "menu/menu_ttl_validator.h"
|
#include "menu/menu_ttl_validator.h"
|
||||||
|
#include "ui/boxes/confirm_box.h"
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
@ -32,6 +33,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kPaidShowLive = 86400;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
DeleteMessagesBox::DeleteMessagesBox(
|
DeleteMessagesBox::DeleteMessagesBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
|
@ -492,7 +499,41 @@ void DeleteMessagesBox::keyPressEvent(QKeyEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DeleteMessagesBox::hasPaidSuggestedPosts() const {
|
||||||
|
const auto now = base::unixtime::now();
|
||||||
|
for (const auto &id : _ids) {
|
||||||
|
if (const auto item = _session->data().message(id)) {
|
||||||
|
if (item->isPaidSuggestedPost()) {
|
||||||
|
const auto date = item->date();
|
||||||
|
if (now < date || now - date <= kPaidShowLive) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void DeleteMessagesBox::deleteAndClear() {
|
void DeleteMessagesBox::deleteAndClear() {
|
||||||
|
if (hasPaidSuggestedPosts() && !_confirmedDeletePaidSuggestedPosts) {
|
||||||
|
const auto weak = Ui::MakeWeak(this);
|
||||||
|
const auto callback = [=](Fn<void()> close) {
|
||||||
|
close();
|
||||||
|
if (const auto strong = weak.data()) {
|
||||||
|
strong->_confirmedDeletePaidSuggestedPosts = true;
|
||||||
|
strong->deleteAndClear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AssertIsDebug();
|
||||||
|
uiShow()->show(Ui::MakeConfirmBox({
|
||||||
|
.text = u"You won't receive Stars for this post if you delete it now. The post must remain visible for at least 24 hours after it was published."_q,
|
||||||
|
.confirmed = callback,
|
||||||
|
.confirmText = u"Delete Anyway"_q,
|
||||||
|
.confirmStyle = &st::attentionBoxButton,
|
||||||
|
.title = u"Stars will be lost"_q,
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_revoke
|
if (_revoke
|
||||||
&& _revokeRemember
|
&& _revokeRemember
|
||||||
&& _revokeRemember->toggled()
|
&& _revokeRemember->toggled()
|
||||||
|
|
|
@ -58,6 +58,7 @@ private:
|
||||||
[[nodiscard]] bool hasScheduledMessages() const;
|
[[nodiscard]] bool hasScheduledMessages() const;
|
||||||
[[nodiscard]] std::optional<RevokeConfig> revokeText(
|
[[nodiscard]] std::optional<RevokeConfig> revokeText(
|
||||||
not_null<PeerData*> peer) const;
|
not_null<PeerData*> peer) const;
|
||||||
|
[[nodiscard]] bool hasPaidSuggestedPosts() const;
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
|
||||||
|
@ -82,6 +83,7 @@ private:
|
||||||
object_ptr<Ui::LinkButton> _autoDeleteSettings = { nullptr };
|
object_ptr<Ui::LinkButton> _autoDeleteSettings = { nullptr };
|
||||||
|
|
||||||
int _fullHeight = 0;
|
int _fullHeight = 0;
|
||||||
|
bool _confirmedDeletePaidSuggestedPosts = false;
|
||||||
|
|
||||||
Fn<void()> _deleteConfirmedCallback;
|
Fn<void()> _deleteConfirmedCallback;
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ Draft::Draft(
|
||||||
mtpRequestId saveRequestId)
|
mtpRequestId saveRequestId)
|
||||||
: textWithTags(textWithTags)
|
: textWithTags(textWithTags)
|
||||||
, reply(std::move(reply))
|
, reply(std::move(reply))
|
||||||
|
, suggest(suggest)
|
||||||
, cursor(cursor)
|
, cursor(cursor)
|
||||||
, webpage(webpage)
|
, webpage(webpage)
|
||||||
, saveRequestId(saveRequestId) {
|
, saveRequestId(saveRequestId) {
|
||||||
|
@ -69,6 +70,7 @@ Draft::Draft(
|
||||||
mtpRequestId saveRequestId)
|
mtpRequestId saveRequestId)
|
||||||
: textWithTags(field->getTextWithTags())
|
: textWithTags(field->getTextWithTags())
|
||||||
, reply(std::move(reply))
|
, reply(std::move(reply))
|
||||||
|
, suggest(suggest)
|
||||||
, cursor(field)
|
, cursor(field)
|
||||||
, webpage(webpage) {
|
, webpage(webpage) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,6 +257,7 @@ using HistoryDrafts = base::flat_map<DraftKey, std::unique_ptr<Draft>>;
|
||||||
}
|
}
|
||||||
return (a->textWithTags == b->textWithTags)
|
return (a->textWithTags == b->textWithTags)
|
||||||
&& (a->reply == b->reply)
|
&& (a->reply == b->reply)
|
||||||
|
&& (a->suggest == b->suggest)
|
||||||
&& (a->webpage == b->webpage);
|
&& (a->webpage == b->webpage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,6 +353,8 @@ enum class MessageFlag : uint64 {
|
||||||
ReactionsAllowed = (1ULL << 50),
|
ReactionsAllowed = (1ULL << 50),
|
||||||
|
|
||||||
HideDisplayDate = (1ULL << 51),
|
HideDisplayDate = (1ULL << 51),
|
||||||
|
|
||||||
|
PaidSuggestedPost = (1ULL << 52),
|
||||||
};
|
};
|
||||||
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
||||||
using MessageFlags = base::flags<MessageFlag>;
|
using MessageFlags = base::flags<MessageFlag>;
|
||||||
|
|
|
@ -1593,6 +1593,10 @@ bool HistoryItem::isEditingMedia() const {
|
||||||
return Has<HistoryMessageSavedMediaData>();
|
return Has<HistoryMessageSavedMediaData>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HistoryItem::isPaidSuggestedPost() const {
|
||||||
|
return _flags & MessageFlag::PaidSuggestedPost;
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryItem::clearSavedMedia() {
|
void HistoryItem::clearSavedMedia() {
|
||||||
RemoveComponents(HistoryMessageSavedMediaData::Bit());
|
RemoveComponents(HistoryMessageSavedMediaData::Bit());
|
||||||
}
|
}
|
||||||
|
@ -1887,6 +1891,21 @@ void HistoryItem::applyEdition(HistoryMessageEdition &&edition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!edition.useSameSuggest) {
|
||||||
|
if (edition.suggest.exists) {
|
||||||
|
if (!Has<HistoryMessageSuggestedPost>()) {
|
||||||
|
AddComponents(HistoryMessageSuggestedPost::Bit());
|
||||||
|
}
|
||||||
|
auto suggest = Get<HistoryMessageSuggestedPost>();
|
||||||
|
suggest->stars = edition.suggest.stars;
|
||||||
|
suggest->date = edition.suggest.date;
|
||||||
|
suggest->accepted = edition.suggest.accepted;
|
||||||
|
suggest->rejected = edition.suggest.rejected;
|
||||||
|
} else {
|
||||||
|
RemoveComponents(HistoryMessageSuggestedPost::Bit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
applyTTL(edition.ttl);
|
applyTTL(edition.ttl);
|
||||||
setFactcheck(FromMTP(this, edition.mtpFactcheck));
|
setFactcheck(FromMTP(this, edition.mtpFactcheck));
|
||||||
|
|
||||||
|
@ -2398,7 +2417,8 @@ bool HistoryItem::allowsSendNow() const {
|
||||||
&& isScheduled()
|
&& isScheduled()
|
||||||
&& !isSending()
|
&& !isSending()
|
||||||
&& !hasFailed()
|
&& !hasFailed()
|
||||||
&& !isEditingMedia();
|
&& !isEditingMedia()
|
||||||
|
&& !isPaidSuggestedPost();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryItem::allowsReschedule() const {
|
bool HistoryItem::allowsReschedule() const {
|
||||||
|
@ -2425,7 +2445,8 @@ bool HistoryItem::allowsEdit(TimeId now) const {
|
||||||
&& !isTooOldForEdit(now)
|
&& !isTooOldForEdit(now)
|
||||||
&& (!_media || _media->allowsEdit())
|
&& (!_media || _media->allowsEdit())
|
||||||
&& !isLegacyMessage()
|
&& !isLegacyMessage()
|
||||||
&& !isEditingMedia();
|
&& !isEditingMedia()
|
||||||
|
&& !isPaidSuggestedPost();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryItem::allowsEditMedia() const {
|
bool HistoryItem::allowsEditMedia() const {
|
||||||
|
@ -5928,8 +5949,15 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
||||||
return prepareTodoAppendTasksText();
|
return prepareTodoAppendTasksText();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto prepareSuggestedPostApproval = [&](const MTPDmessageActionSuggestedPostApproval &) {
|
auto prepareSuggestedPostApproval = [&](const MTPDmessageActionSuggestedPostApproval &data) {
|
||||||
return PreparedServiceText{ { "process_suggested" } }; AssertIsDebug();
|
if (data.is_balance_too_low()) {
|
||||||
|
return PreparedServiceText{ { u"balance too low :( need %1 stars"_q.arg(data.vstars_amount().value_or_empty()) } };
|
||||||
|
} else if (data.is_rejected()) {
|
||||||
|
return PreparedServiceText{ { u"rejected :( comment: %1"_q.arg(qs(data.vreject_comment().value_or_empty())) } };
|
||||||
|
} else if (const auto date = data.vschedule_date().value_or_empty()) {
|
||||||
|
return PreparedServiceText{ { u"approved!! for date: %1"_q.arg(langDateTime(base::unixtime::parse(date))) } };
|
||||||
|
}
|
||||||
|
return PreparedServiceText{ { "approved!!" } }; AssertIsDebug();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto prepareConferenceCall = [&](const MTPDmessageActionConferenceCall &) -> PreparedServiceText {
|
auto prepareConferenceCall = [&](const MTPDmessageActionConferenceCall &) -> PreparedServiceText {
|
||||||
|
|
|
@ -312,6 +312,7 @@ public:
|
||||||
[[nodiscard]] bool hasRealFromId() const;
|
[[nodiscard]] bool hasRealFromId() const;
|
||||||
[[nodiscard]] bool isPostHidingAuthor() const;
|
[[nodiscard]] bool isPostHidingAuthor() const;
|
||||||
[[nodiscard]] bool isPostShowingAuthor() const;
|
[[nodiscard]] bool isPostShowingAuthor() const;
|
||||||
|
[[nodiscard]] bool isPaidSuggestedPost() const;
|
||||||
[[nodiscard]] bool isRegular() const;
|
[[nodiscard]] bool isRegular() const;
|
||||||
[[nodiscard]] bool isUploading() const;
|
[[nodiscard]] bool isUploading() const;
|
||||||
void sendFailed();
|
void sendFailed();
|
||||||
|
|
|
@ -618,6 +618,7 @@ struct HistoryMessageSuggestedPost
|
||||||
: RuntimeComponent<HistoryMessageSuggestedPost, HistoryItem> {
|
: RuntimeComponent<HistoryMessageSuggestedPost, HistoryItem> {
|
||||||
int stars = 0;
|
int stars = 0;
|
||||||
TimeId date = 0;
|
TimeId date = 0;
|
||||||
|
mtpRequestId requestId = 0;
|
||||||
bool accepted = false;
|
bool accepted = false;
|
||||||
bool rejected = false;
|
bool rejected = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,8 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
|
||||||
HistoryMessageEdition::HistoryMessageEdition(
|
HistoryMessageEdition::HistoryMessageEdition(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPDmessage &message) {
|
const MTPDmessage &message)
|
||||||
|
: suggest(HistoryMessageSuggestInfo(message.vsuggested_post())) {
|
||||||
isEditHide = message.is_edit_hide();
|
isEditHide = message.is_edit_hide();
|
||||||
isMediaUnread = message.is_media_unread();
|
isMediaUnread = message.is_media_unread();
|
||||||
editDate = message.vedit_date().value_or(-1);
|
editDate = message.vedit_date().value_or(-1);
|
||||||
|
|
|
@ -30,11 +30,13 @@ struct HistoryMessageEdition {
|
||||||
bool useSameReplies = false;
|
bool useSameReplies = false;
|
||||||
bool useSameMarkup = false;
|
bool useSameMarkup = false;
|
||||||
bool useSameReactions = false;
|
bool useSameReactions = false;
|
||||||
|
bool useSameSuggest = false;
|
||||||
bool savePreviousMedia = false;
|
bool savePreviousMedia = false;
|
||||||
bool invertMedia = false;
|
bool invertMedia = false;
|
||||||
TextWithEntities textWithEntities;
|
TextWithEntities textWithEntities;
|
||||||
HistoryMessageMarkupData replyMarkup;
|
HistoryMessageMarkupData replyMarkup;
|
||||||
HistoryMessageRepliesData replies;
|
HistoryMessageRepliesData replies;
|
||||||
|
HistoryMessageSuggestInfo suggest;
|
||||||
const MTPMessageMedia *mtpMedia = nullptr;
|
const MTPMessageMedia *mtpMedia = nullptr;
|
||||||
const MTPMessageReactions *mtpReactions = nullptr;
|
const MTPMessageReactions *mtpReactions = nullptr;
|
||||||
const MTPFactCheck *mtpFactcheck = nullptr;
|
const MTPFactCheck *mtpFactcheck = nullptr;
|
||||||
|
|
|
@ -762,6 +762,9 @@ MessageFlags FlagsFromMTP(
|
||||||
| ((flags & MTP::f_invert_media) ? Flag::InvertMedia : Flag())
|
| ((flags & MTP::f_invert_media) ? Flag::InvertMedia : Flag())
|
||||||
| ((flags & MTP::f_video_processing_pending)
|
| ((flags & MTP::f_video_processing_pending)
|
||||||
? Flag::EstimatedDate
|
? Flag::EstimatedDate
|
||||||
|
: Flag())
|
||||||
|
| ((flags & MTP::f_paid_suggested_post)
|
||||||
|
? Flag::PaidSuggestedPost
|
||||||
: Flag());
|
: Flag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3172,9 +3172,17 @@ void HistoryWidget::applySuggestOptions(SuggestPostOptions suggest) {
|
||||||
controller(),
|
controller(),
|
||||||
_peer,
|
_peer,
|
||||||
suggest);
|
suggest);
|
||||||
_suggestOptions->repaints() | rpl::start_with_next([=] {
|
_suggestOptions->updates() | rpl::start_with_next([=] {
|
||||||
updateField();
|
updateField();
|
||||||
|
saveDraftWithTextNow();
|
||||||
}, _suggestOptions->lifetime());
|
}, _suggestOptions->lifetime());
|
||||||
|
saveDraftWithTextNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::saveDraftWithTextNow() {
|
||||||
|
_saveDraftText = true;
|
||||||
|
_saveDraftStart = crl::now();
|
||||||
|
saveDraft();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::refreshSuggestPostToggle() {
|
void HistoryWidget::refreshSuggestPostToggle() {
|
||||||
|
@ -4644,9 +4652,7 @@ void HistoryWidget::send(Api::SendOptions options) {
|
||||||
if (_preview) {
|
if (_preview) {
|
||||||
_preview->apply({ .removed = true });
|
_preview->apply({ .removed = true });
|
||||||
}
|
}
|
||||||
_saveDraftText = true;
|
saveDraftWithTextNow();
|
||||||
_saveDraftStart = crl::now();
|
|
||||||
saveDraft();
|
|
||||||
|
|
||||||
hideSelectorControlsAnimated();
|
hideSelectorControlsAnimated();
|
||||||
|
|
||||||
|
@ -7680,9 +7686,7 @@ void HistoryWidget::sendInlineResult(InlineBots::ResultSelected result) {
|
||||||
result.messageSendingFrom.localId);
|
result.messageSendingFrom.localId);
|
||||||
|
|
||||||
clearFieldText();
|
clearFieldText();
|
||||||
_saveDraftText = true;
|
saveDraftWithTextNow();
|
||||||
_saveDraftStart = crl::now();
|
|
||||||
saveDraft();
|
|
||||||
|
|
||||||
auto &bots = cRefRecentInlineBots();
|
auto &bots = cRefRecentInlineBots();
|
||||||
const auto index = bots.indexOf(result.bot);
|
const auto index = bots.indexOf(result.bot);
|
||||||
|
@ -8296,9 +8300,7 @@ bool HistoryWidget::sendExistingDocument(
|
||||||
|
|
||||||
if (_autocomplete && _autocomplete->stickersShown()) {
|
if (_autocomplete && _autocomplete->stickersShown()) {
|
||||||
clearFieldText();
|
clearFieldText();
|
||||||
//_saveDraftText = true;
|
//saveDraftWithTextNow();
|
||||||
//_saveDraftStart = crl::now();
|
|
||||||
//saveDraft();
|
|
||||||
|
|
||||||
// won't be needed if SendInlineBotResult will clear the cloud draft
|
// won't be needed if SendInlineBotResult will clear the cloud draft
|
||||||
saveCloudDraft();
|
saveCloudDraft();
|
||||||
|
@ -8634,10 +8636,7 @@ void HistoryWidget::setReplyFieldsFromProcessing() {
|
||||||
refreshTopBarActiveChat();
|
refreshTopBarActiveChat();
|
||||||
}
|
}
|
||||||
|
|
||||||
_saveDraftText = true;
|
saveDraftWithTextNow();
|
||||||
_saveDraftStart = crl::now();
|
|
||||||
saveDraft();
|
|
||||||
|
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8702,10 +8701,7 @@ void HistoryWidget::editMessage(
|
||||||
updateField();
|
updateField();
|
||||||
SelectTextInFieldWithMargins(_field, selection);
|
SelectTextInFieldWithMargins(_field, selection);
|
||||||
|
|
||||||
_saveDraftText = true;
|
saveDraftWithTextNow();
|
||||||
_saveDraftStart = crl::now();
|
|
||||||
saveDraft();
|
|
||||||
|
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8794,9 +8790,7 @@ bool HistoryWidget::cancelReply(bool lastKeyboardUsed) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wasReply) {
|
if (wasReply) {
|
||||||
_saveDraftText = true;
|
saveDraftWithTextNow();
|
||||||
_saveDraftStart = crl::now();
|
|
||||||
saveDraft();
|
|
||||||
}
|
}
|
||||||
if (!_editMsgId
|
if (!_editMsgId
|
||||||
&& _keyboard->singleUse()
|
&& _keyboard->singleUse()
|
||||||
|
@ -8841,9 +8835,7 @@ void HistoryWidget::cancelEdit() {
|
||||||
_saveEditMsgRequestId = 0;
|
_saveEditMsgRequestId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_saveDraftText = true;
|
saveDraftWithTextNow();
|
||||||
_saveDraftStart = crl::now();
|
|
||||||
saveDraft();
|
|
||||||
|
|
||||||
mouseMoveEvent(nullptr);
|
mouseMoveEvent(nullptr);
|
||||||
if (!readyToForward()
|
if (!readyToForward()
|
||||||
|
@ -8891,6 +8883,7 @@ bool HistoryWidget::cancelSuggestPost() {
|
||||||
_suggestOptions = nullptr;
|
_suggestOptions = nullptr;
|
||||||
updateControlsVisibility();
|
updateControlsVisibility();
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
|
saveDraftWithTextNow();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,6 +391,7 @@ private:
|
||||||
void saveDraft(bool delayed = false);
|
void saveDraft(bool delayed = false);
|
||||||
void saveCloudDraft();
|
void saveCloudDraft();
|
||||||
void saveDraftDelayed();
|
void saveDraftDelayed();
|
||||||
|
void saveDraftWithTextNow();
|
||||||
void showMembersDropdown();
|
void showMembersDropdown();
|
||||||
void windowIsVisibleChanged();
|
void windowIsVisibleChanged();
|
||||||
void saveFieldToHistoryLocalDraft();
|
void saveFieldToHistoryLocalDraft();
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "history/view/history_view_message.h"
|
#include "history/view/history_view_message.h"
|
||||||
|
|
||||||
|
#include "api/api_suggest_post.h"
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "core/click_handler_types.h" // ClickHandlerContext
|
#include "core/click_handler_types.h" // ClickHandlerContext
|
||||||
#include "core/ui_integration.h"
|
#include "core/ui_integration.h"
|
||||||
|
@ -24,11 +25,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/share_box.h"
|
#include "boxes/share_box.h"
|
||||||
#include "ui/effects/glare.h"
|
#include "ui/effects/glare.h"
|
||||||
#include "ui/effects/reaction_fly_animation.h"
|
#include "ui/effects/reaction_fly_animation.h"
|
||||||
#include "ui/rect.h"
|
|
||||||
#include "ui/round_rect.h"
|
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/text/text_extended_data.h"
|
#include "ui/text/text_extended_data.h"
|
||||||
#include "ui/power_saving.h"
|
#include "ui/power_saving.h"
|
||||||
|
#include "ui/rect.h"
|
||||||
|
#include "ui/round_rect.h"
|
||||||
#include "data/components/factchecks.h"
|
#include "data/components/factchecks.h"
|
||||||
#include "data/components/sponsored_messages.h"
|
#include "data/components/sponsored_messages.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -456,17 +457,45 @@ void Message::initPaidInformation() {
|
||||||
const auto item = data();
|
const auto item = data();
|
||||||
if (!item->history()->peer->isUser()) {
|
if (!item->history()->peer->isUser()) {
|
||||||
|
|
||||||
|
|
||||||
if (const auto suggest = item->Get<HistoryMessageSuggestedPost>()) {
|
if (const auto suggest = item->Get<HistoryMessageSuggestedPost>()) {
|
||||||
|
auto text = PreparedServiceText();
|
||||||
if (!suggest->stars && !suggest->date) {
|
if (!suggest->stars && !suggest->date) {
|
||||||
setServicePreMessage({ { u"suggestion to publish for free anytime"_q } });
|
text = { { u"suggestion to publish for free anytime"_q } };
|
||||||
} else if (!suggest->date) {
|
} else if (!suggest->date) {
|
||||||
setServicePreMessage({ { u"suggestion to publish for %1 stars anytime"_q.arg(suggest->stars) }});
|
text = { { u"suggestion to publish for %1 stars anytime"_q.arg(suggest->stars) } };
|
||||||
} else if (!suggest->stars) {
|
} else if (!suggest->stars) {
|
||||||
setServicePreMessage({ { u"suggestion to publish for free %1"_q.arg(langDateTime(base::unixtime::parse(suggest->date))) }});
|
text = { { u"suggestion to publish for free %1"_q.arg(langDateTime(base::unixtime::parse(suggest->date))) } };
|
||||||
} else {
|
} else {
|
||||||
setServicePreMessage({ { u"suggestion to publish for %1 stars %2"_q.arg(suggest->stars).arg(langDateTime(base::unixtime::parse(suggest->date))) } });
|
text = { { u"suggestion to publish for %1 stars %2"_q.arg(suggest->stars).arg(langDateTime(base::unixtime::parse(suggest->date))) } };
|
||||||
}
|
}
|
||||||
|
const auto channelIsAuthor = item->from()->isChannel();
|
||||||
|
const auto amMonoforumAdmin = item->history()->peer->amMonoforumAdmin();
|
||||||
|
const auto broadcast = item->history()->peer->monoforumBroadcast();
|
||||||
|
const auto canDecline = item->isRegular()
|
||||||
|
&& !(suggest->accepted || suggest->rejected)
|
||||||
|
&& (channelIsAuthor ? !amMonoforumAdmin : amMonoforumAdmin);
|
||||||
|
const auto canAccept = canDecline
|
||||||
|
&& (channelIsAuthor
|
||||||
|
? !amMonoforumAdmin
|
||||||
|
: (amMonoforumAdmin
|
||||||
|
&& broadcast
|
||||||
|
&& broadcast->canPostMessages()));
|
||||||
|
if (canDecline) {
|
||||||
|
text.links.push_back(Api::DeclineClickHandler(item));
|
||||||
|
text.text.append(", ").append(Ui::Text::Link("[Decline]", text.links.size()));
|
||||||
|
if (canAccept) {
|
||||||
|
text.links.push_back(Api::AcceptClickHandler(item));
|
||||||
|
text.text.append(", ").append(Ui::Text::Link("[Accept]", text.links.size()));
|
||||||
|
|
||||||
|
text.links.push_back(Api::SuggestChangesClickHandler(item));
|
||||||
|
text.text.append(", ").append(Ui::Text::Link("[SuggestChanges]", text.links.size()));
|
||||||
|
}
|
||||||
|
} else if (suggest->accepted) {
|
||||||
|
text.text.append(", accepted!");
|
||||||
|
} else if (suggest->rejected) {
|
||||||
|
text.text.append(", rejected :(");
|
||||||
|
}
|
||||||
|
setServicePreMessage(std::move(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -94,15 +94,27 @@ void EditOptionsBox(
|
||||||
st::settingsButtonNoIcon);
|
st::settingsButtonNoIcon);
|
||||||
|
|
||||||
time->setClickedCallback([=] {
|
time->setClickedCallback([=] {
|
||||||
box->uiShow()->show(Box(Ui::ChooseDateTimeBox, Ui::ChooseDateTimeBoxArgs{
|
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||||
|
const auto parentWeak = Ui::MakeWeak(box);
|
||||||
|
const auto done = [=](TimeId result) {
|
||||||
|
if (parentWeak) {
|
||||||
|
state->date = result;
|
||||||
|
}
|
||||||
|
if (const auto strong = weak->data()) {
|
||||||
|
strong->closeBox();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto dateBox = Box(Ui::ChooseDateTimeBox, Ui::ChooseDateTimeBoxArgs{
|
||||||
.title = tr::lng_suggest_options_date(),
|
.title = tr::lng_suggest_options_date(),
|
||||||
.submit = tr::lng_settings_save(),
|
.submit = tr::lng_settings_save(),
|
||||||
.done = [=](TimeId result) { state->date = result; },
|
.done = done,
|
||||||
.min = [] { return base::unixtime::now() + 1; },
|
.min = [] { return base::unixtime::now() + 1; },
|
||||||
.time = (state->date.current()
|
.time = (state->date.current()
|
||||||
? state->date.current()
|
? state->date.current()
|
||||||
: (base::unixtime::now() + 86400)),
|
: (base::unixtime::now() + 86400)),
|
||||||
}));
|
});
|
||||||
|
*weak = dateBox.data();
|
||||||
|
box->uiShow()->show(std::move(dateBox));
|
||||||
});
|
});
|
||||||
|
|
||||||
Ui::AddSkip(container);
|
Ui::AddSkip(container);
|
||||||
|
@ -172,7 +184,7 @@ void SuggestOptions::edit() {
|
||||||
const auto apply = [=](SuggestPostOptions values) {
|
const auto apply = [=](SuggestPostOptions values) {
|
||||||
_values = values;
|
_values = values;
|
||||||
updateTexts();
|
updateTexts();
|
||||||
_repaints.fire({});
|
_updates.fire({});
|
||||||
};
|
};
|
||||||
const auto broadcast = _peer->monoforumBroadcast();
|
const auto broadcast = _peer->monoforumBroadcast();
|
||||||
const auto &appConfig = _peer->session().appConfig();
|
const auto &appConfig = _peer->session().appConfig();
|
||||||
|
@ -226,8 +238,8 @@ SuggestPostOptions SuggestOptions::values() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<> SuggestOptions::repaints() const {
|
rpl::producer<> SuggestOptions::updates() const {
|
||||||
return _repaints.events();
|
return _updates.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::lifetime &SuggestOptions::lifetime() {
|
rpl::lifetime &SuggestOptions::lifetime() {
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] SuggestPostOptions values() const;
|
[[nodiscard]] SuggestPostOptions values() const;
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<> repaints() const;
|
[[nodiscard]] rpl::producer<> updates() const;
|
||||||
|
|
||||||
[[nodiscard]] rpl::lifetime &lifetime();
|
[[nodiscard]] rpl::lifetime &lifetime();
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ private:
|
||||||
Ui::Text::String _text;
|
Ui::Text::String _text;
|
||||||
|
|
||||||
SuggestPostOptions _values;
|
SuggestPostOptions _values;
|
||||||
rpl::event_stream<> _repaints;
|
rpl::event_stream<> _updates;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue