Add simple forwarding options on bar click.

This commit is contained in:
John Preston 2021-08-31 19:47:38 +03:00
parent e9a5c45f34
commit 9dfc60026e
18 changed files with 378 additions and 94 deletions

View File

@ -2511,6 +2511,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_date_input_month" = "Month";
"lng_date_input_year" = "Year";
"lng_forward_header" = "Forward message";
"lng_forward_title" = "Forward Message";
"lng_forward_many_title#one" = "Forward {count} Message";
"lng_forward_many_title#other" = "Forward {count} Messages";
"lng_forward_about" = "You can remove the sender's name from this message as if it was sent by you.";
"lng_forward_about_many#one" = "You can remove senders' name from {count} forwarded message as if it was sent by you.";
"lng_forward_about_many#other" = "You can remove senders' names from {count} forwarded messages as if they were sent by you.";
"lng_forward_show_sender" = "Show sender's name";
"lng_forward_show_senders" = "Show senders' names";
"lng_forward_show_caption" = "Show caption";
"lng_forward_show_captions" = "Show captions";
"lng_forward_change_recipient" = "Change recipient";
"lng_forward_sender_names_removed" = "Sender names removed";
"lng_passport_title" = "Telegram passport";
"lng_passport_request1" = "{bot} requests access to your personal data";
"lng_passport_request2" = "to sign you up for their services";

View File

@ -3580,9 +3580,11 @@ void ApiWrap::sendAction(const SendAction &action) {
void ApiWrap::finishForwarding(const SendAction &action) {
const auto history = action.history;
auto toForward = history->validateForwardDraft();
if (!toForward.empty()) {
const auto error = GetErrorTextForSending(history->peer, toForward);
auto toForward = history->resolveForwardDraft();
if (!toForward.items.empty()) {
const auto error = GetErrorTextForSending(
history->peer,
toForward.items);
if (!error.isEmpty()) {
return;
}
@ -3600,10 +3602,10 @@ void ApiWrap::finishForwarding(const SendAction &action) {
}
void ApiWrap::forwardMessages(
HistoryItemsList &&items,
Data::ResolvedForwardDraft &&draft,
const SendAction &action,
FnMut<void()> &&successCallback) {
Expects(!items.empty());
Expects(!draft.items.empty());
auto &histories = _session->data().histories();
@ -3618,8 +3620,10 @@ void ApiWrap::forwardMessages(
shared->callback = std::move(successCallback);
}
const auto count = int(items.size());
const auto genClientSideMessage = action.generateLocal && (count < 2);
const auto count = int(draft.items.size());
const auto genClientSideMessage = action.generateLocal
&& (count < 2)
&& (draft.options == Data::ForwardOptions::PreserveInfo);
const auto history = action.history;
const auto peer = history->peer;
@ -3640,8 +3644,14 @@ void ApiWrap::forwardMessages(
} else {
flags |= MessageFlag::LocalHistoryEntry;
}
if (draft.options != Data::ForwardOptions::PreserveInfo) {
sendFlags |= MTPmessages_ForwardMessages::Flag::f_drop_author;
}
if (draft.options == Data::ForwardOptions::NoNamesAndCaptions) {
sendFlags |= MTPmessages_ForwardMessages::Flag::f_drop_media_captions;
}
auto forwardFrom = items.front()->history()->peer;
auto forwardFrom = draft.items.front()->history()->peer;
auto ids = QVector<MTPint>();
auto randomIds = QVector<MTPlong>();
auto localIds = std::shared_ptr<base::flat_map<uint64, FullMsgId>>();
@ -3688,7 +3698,7 @@ void ApiWrap::forwardMessages(
ids.reserve(count);
randomIds.reserve(count);
for (const auto item : items) {
for (const auto item : draft.items) {
const auto randomId = openssl::RandomValue<uint64>();
if (genClientSideMessage) {
if (const auto message = item->toHistoryMessage()) {

View File

@ -29,6 +29,7 @@ class Session;
namespace Data {
struct UpdatedFileReferences;
class WallPaper;
struct ResolvedForwardDraft;
} // namespace Data
namespace InlineBots {
@ -319,7 +320,7 @@ public:
void sendAction(const SendAction &action);
void finishForwarding(const SendAction &action);
void forwardMessages(
HistoryItemsList &&items,
Data::ResolvedForwardDraft &&draft,
const SendAction &action,
FnMut<void()> &&successCallback = nullptr);
void shareContact(

View File

@ -201,7 +201,7 @@ bool Media::canBeGrouped() const {
return false;
}
QString Media::chatListText() const {
QString Media::chatListText(DrawInDialog way) const {
auto result = notificationText();
return result.isEmpty()
? QString()
@ -341,10 +341,11 @@ QString MediaPhoto::notificationText() const {
parent()->originalText().text);
}
QString MediaPhoto::chatListText() const {
return WithCaptionDialogsText(
tr::lng_in_dlg_photo(tr::now),
parent()->originalText().text);
QString MediaPhoto::chatListText(DrawInDialog way) const {
const auto caption = (way == DrawInDialog::WithoutSenderAndCaption)
? QString()
: parent()->originalText().text;
return WithCaptionDialogsText(tr::lng_in_dlg_photo(tr::now), caption);
}
QString MediaPhoto::pinnedTextSubstring() const {
@ -510,9 +511,9 @@ bool MediaFile::replyPreviewLoaded() const {
return _document->replyPreviewLoaded();
}
QString MediaFile::chatListText() const {
QString MediaFile::chatListText(DrawInDialog way) const {
if (const auto sticker = _document->sticker()) {
return Media::chatListText();
return Media::chatListText(way);
}
const auto type = [&] {
using namespace Ui::Text;
@ -532,7 +533,10 @@ QString MediaFile::chatListText() const {
}
return tr::lng_in_dlg_file(tr::now);
}();
return WithCaptionDialogsText(type, parent()->originalText().text);
const auto caption = (way == DrawInDialog::WithoutSenderAndCaption)
? QString()
: parent()->originalText().text;
return WithCaptionDialogsText(type, caption);
}
QString MediaFile::notificationText() const {
@ -851,7 +855,7 @@ Data::CloudImage *MediaLocation::location() const {
return _location;
}
QString MediaLocation::chatListText() const {
QString MediaLocation::chatListText(DrawInDialog way) const {
return WithCaptionDialogsText(tr::lng_maps_point(tr::now), _title);
}
@ -1045,7 +1049,7 @@ bool MediaWebPage::replyPreviewLoaded() const {
return true;
}
QString MediaWebPage::chatListText() const {
QString MediaWebPage::chatListText(DrawInDialog way) const {
return notificationText();
}

View File

@ -27,6 +27,7 @@ namespace HistoryView {
enum class Context : char;
class Element;
class Media;
enum class DrawInDialog;
} // namespace HistoryView
namespace Data {
@ -72,6 +73,8 @@ public:
not_null<HistoryItem*> parent() const;
using DrawInDialog = HistoryView::DrawInDialog;
virtual std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) = 0;
virtual DocumentData *document() const;
@ -92,7 +95,7 @@ public:
virtual bool replyPreviewLoaded() const;
// Returns text with link-start and link-end commands for service-color highlighting.
// Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text"
virtual QString chatListText() const;
virtual QString chatListText(DrawInDialog way) const;
virtual QString notificationText() const = 0;
virtual QString pinnedTextSubstring() const = 0;
virtual TextForMimeData clipboardText() const = 0;
@ -148,7 +151,7 @@ public:
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString chatListText() const override;
QString chatListText(DrawInDialog way) const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;
@ -186,7 +189,7 @@ public:
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString chatListText() const override;
QString chatListText(DrawInDialog way) const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;
@ -252,7 +255,7 @@ public:
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
Data::CloudImage *location() const override;
QString chatListText() const override;
QString chatListText(DrawInDialog way) const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;
@ -320,7 +323,7 @@ public:
bool hasReplyPreview() const override;
Image *replyPreview() const override;
bool replyPreviewLoaded() const override;
QString chatListText() const override;
QString chatListText(DrawInDialog way) const override;
QString notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;

View File

@ -336,16 +336,27 @@ void History::draftSavedToCloud() {
session().local().writeDrafts(this);
}
HistoryItemsList History::validateForwardDraft() {
auto result = owner().idsToItems(_forwardDraft);
if (result.size() != _forwardDraft.size()) {
setForwardDraft(owner().itemsToIds(result));
Data::ResolvedForwardDraft History::resolveForwardDraft(
const Data::ForwardDraft &draft) const {
return Data::ResolvedForwardDraft{
.items = owner().idsToItems(draft.ids),
.options = draft.options,
};
}
Data::ResolvedForwardDraft History::resolveForwardDraft() {
auto result = resolveForwardDraft(_forwardDraft);
if (result.items.size() != _forwardDraft.ids.size()) {
setForwardDraft({
.ids = owner().itemsToIds(result.items),
.options = result.options,
});
}
return result;
}
void History::setForwardDraft(MessageIdsList &&items) {
_forwardDraft = std::move(items);
void History::setForwardDraft(Data::ForwardDraft &&draft) {
_forwardDraft = std::move(draft);
}
HistoryItem *History::createItem(

View File

@ -33,6 +33,23 @@ struct Draft;
class Session;
class Folder;
class ChatFilter;
enum class ForwardOptions {
PreserveInfo,
NoSenderNames,
NoNamesAndCaptions,
};
struct ForwardDraft {
MessageIdsList ids;
ForwardOptions options = ForwardOptions::PreserveInfo;
};
struct ResolvedForwardDraft {
HistoryItemsList items;
ForwardOptions options = ForwardOptions::PreserveInfo;
};
} // namespace Data
namespace Dialogs {
@ -354,11 +371,13 @@ public:
void applyCloudDraft();
void draftSavedToCloud();
const MessageIdsList &forwardDraft() const {
[[nodiscard]] const Data::ForwardDraft &forwardDraft() const {
return _forwardDraft;
}
HistoryItemsList validateForwardDraft();
void setForwardDraft(MessageIdsList &&items);
[[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft(
const Data::ForwardDraft &draft) const;
[[nodiscard]] Data::ResolvedForwardDraft resolveForwardDraft();
void setForwardDraft(Data::ForwardDraft &&draft);
History *migrateSibling() const;
[[nodiscard]] bool useTopPromotion() const;
@ -598,7 +617,7 @@ private:
Data::HistoryDrafts _drafts;
TimeId _acceptCloudDraftsAfter = 0;
int _savingCloudDraftRequests = 0;
MessageIdsList _forwardDraft;
Data::ForwardDraft _forwardDraft;
QString _topPromotedMessage;
QString _topPromotedType;

View File

@ -936,20 +936,19 @@ QString HistoryItem::notificationText() const {
}
QString HistoryItem::inDialogsText(DrawInDialog way) const {
auto getText = [this]() {
const auto plainText = [&] {
if (_media) {
if (_groupId) {
return textcmdLink(1, TextUtilities::Clean(tr::lng_in_dlg_album(tr::now)));
}
return _media->chatListText();
return _media->chatListText(way);
} else if (!emptyText()) {
return TextUtilities::Clean(_text.toString());
}
return QString();
};
const auto plainText = getText();
}();
const auto sender = [&]() -> PeerData* {
if (isPost() || isEmpty() || (way == DrawInDialog::WithoutSender)) {
if (isPost() || isEmpty() || (way != DrawInDialog::Normal)) {
return nullptr;
} else if (!_history->peer->isUser() || out()) {
return displayFrom();

View File

@ -52,6 +52,11 @@ enum class CursorState : char;
enum class PointState : char;
enum class Context : char;
class ElementDelegate;
enum class DrawInDialog {
Normal,
WithoutSender,
WithoutSenderAndCaption,
};
} // namespace HistoryView
struct HiddenSenderInfo;
@ -291,10 +296,7 @@ public:
}
[[nodiscard]] virtual QString notificationText() const;
enum class DrawInDialog {
Normal,
WithoutSender,
};
using DrawInDialog = HistoryView::DrawInDialog;
// Returns text with link-start and link-end commands for service-color highlighting.
// Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text"

View File

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/ripple_animation.h"
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper
#include "ui/text/format_values.h"
#include "ui/chat/forward_options_box.h"
#include "ui/chat/message_bar.h"
#include "ui/chat/attach/attach_send_files_way.h"
#include "ui/image/image.h"
@ -3285,7 +3286,7 @@ void HistoryWidget::send(Api::SendOptions options) {
if (_canSendMessages) {
const auto error = GetErrorTextForSending(
_peer,
_toForward,
_toForward.items,
message.textWithTags,
options.scheduled);
if (!error.isEmpty()) {
@ -3819,7 +3820,7 @@ QRect HistoryWidget::floatPlayerAvailableRect() {
}
bool HistoryWidget::readyToForward() const {
return _canSendMessages && !_toForward.empty();
return _canSendMessages && !_toForward.items.empty();
}
bool HistoryWidget::hasSilentToggle() const {
@ -4741,11 +4742,11 @@ void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
toggleKeyboard();
_kbReplyTo = nullptr;
}
auto found = ranges::find(_toForward, item);
if (found != _toForward.end()) {
_toForward.erase(found);
auto found = ranges::find(_toForward.items, item);
if (found != _toForward.items.end()) {
_toForward.items.erase(found);
updateForwardingTexts();
if (_toForward.empty()) {
if (_toForward.items.empty()) {
updateControlsVisibility();
updateControlsGeometry();
}
@ -5316,14 +5317,63 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
updateField();
} else if (_inReplyEditForward) {
if (readyToForward()) {
const auto items = std::move(_toForward);
session().data().cancelForwarding(_history);
auto list = ranges::views::all(
items
) | ranges::views::transform(
&HistoryItem::fullId
) | ranges::to_vector;
Window::ShowForwardMessagesBox(controller(), std::move(list));
using Options = Data::ForwardOptions;
const auto now = _toForward.options;
const auto count = _toForward.items.size();
const auto dropNames = (now != Options::PreserveInfo);
const auto hasCaptions = [&] {
for (const auto item : _toForward.items) {
if (const auto media = item->media()) {
if (!item->originalText().text.isEmpty()
&& (media->photo() || media->document())
&& !media->webpage()) {
return true;
}
}
}
return false;
}();
const auto dropCaptions = (now == Options::NoNamesAndCaptions);
const auto weak = Ui::MakeWeak(this);
const auto changeRecipient = crl::guard(weak, [=] {
if (_toForward.items.empty()) {
return;
}
const auto draft = std::move(_toForward);
session().data().cancelForwarding(_history);
auto list = session().data().itemsToIds(draft.items);
Window::ShowForwardMessagesBox(controller(), {
.ids = session().data().itemsToIds(draft.items),
.options = draft.options,
});
});
const auto optionsChanged = crl::guard(weak, [=](
Ui::ForwardOptions options) {
const auto newOptions = (options.hasCaptions
&& options.dropCaptions)
? Options::NoNamesAndCaptions
: options.dropNames
? Options::NoSenderNames
: Options::PreserveInfo;
if (_history && _toForward.options != newOptions) {
_toForward.options = newOptions;
_history->setForwardDraft({
.ids = session().data().itemsToIds(_toForward.items),
.options = newOptions,
});
updateField();
}
});
controller()->show(Box(
Ui::ForwardOptionsBox,
count,
Ui::ForwardOptions{
.dropNames = dropNames,
.hasCaptions = hasCaptions,
.dropCaptions = dropCaptions,
},
optionsChanged,
changeRecipient));
} else {
Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId());
}
@ -5964,7 +6014,7 @@ void HistoryWidget::replyToMessage(not_null<HistoryItem*> item) {
crl::guard(this, [=] {
controller()->content()->setForwardDraft(
_peer->id,
{ 1, itemId });
{ .ids = { 1, itemId } });
})));
}
return;
@ -6617,10 +6667,10 @@ void HistoryWidget::updateReplyEditTexts(bool force) {
void HistoryWidget::updateForwarding() {
if (_history) {
_toForward = _history->validateForwardDraft();
_toForward = _history->resolveForwardDraft();
updateForwardingTexts();
} else {
_toForward.clear();
_toForward = {};
}
updateControlsVisibility();
updateControlsGeometry();
@ -6629,13 +6679,17 @@ void HistoryWidget::updateForwarding() {
void HistoryWidget::updateForwardingTexts() {
int32 version = 0;
QString from, text;
if (const auto count = int(_toForward.size())) {
const auto keepNames = (_toForward.options
== Data::ForwardOptions::PreserveInfo);
const auto keepCaptions = (_toForward.options
!= Data::ForwardOptions::NoNamesAndCaptions);
if (const auto count = int(_toForward.items.size())) {
auto insertedPeers = base::flat_set<not_null<PeerData*>>();
auto insertedNames = base::flat_set<QString>();
auto fullname = QString();
auto names = std::vector<QString>();
names.reserve(_toForward.size());
for (const auto item : _toForward) {
names.reserve(_toForward.items.size());
for (const auto item : _toForward.items) {
if (const auto from = item->senderOriginal()) {
if (!insertedPeers.contains(from)) {
insertedPeers.emplace(from);
@ -6654,7 +6708,9 @@ void HistoryWidget::updateForwardingTexts() {
Unexpected("Corrupt forwarded information in message.");
}
}
if (names.size() > 2) {
if (!keepNames) {
from = tr::lng_forward_sender_names_removed(tr::now);
} else if (names.size() > 2) {
from = tr::lng_forwarding_from(tr::now, lt_count, names.size() - 1, lt_user, names[0]);
} else if (names.size() < 2) {
from = fullname;
@ -6663,7 +6719,9 @@ void HistoryWidget::updateForwardingTexts() {
}
if (count < 2) {
text = _toForward.front()->inReplyText();
text = _toForward.items.front()->inDialogsText(keepCaptions
? HistoryItem::DrawInDialog::WithoutSender
: HistoryItem::DrawInDialog::WithoutSenderAndCaption);
} else {
text = textcmdLink(1, tr::lng_forward_messages(tr::now, lt_count, count));
}
@ -6673,19 +6731,25 @@ void HistoryWidget::updateForwardingTexts() {
st::messageTextStyle,
text,
Ui::DialogTextOptions());
_toForwardNameVersion = version;
_toForwardNameVersion = keepNames ? version : keepCaptions ? -1 : -2;
}
void HistoryWidget::checkForwardingInfo() {
if (!_toForward.empty()) {
auto version = 0;
for (const auto item : _toForward) {
if (const auto from = item->senderOriginal()) {
version += from->nameVersion;
} else if (const auto info = item->hiddenForwardedInfo()) {
++version;
} else {
Unexpected("Corrupt forwarded information in message.");
if (!_toForward.items.empty()) {
const auto keepNames = (_toForward.options
== Data::ForwardOptions::PreserveInfo);
const auto keepCaptions = (_toForward.options
!= Data::ForwardOptions::NoNamesAndCaptions);
auto version = keepNames ? 0 : keepCaptions ? -1 : -2;
if (keepNames) {
for (const auto item : _toForward.items) {
if (const auto from = item->senderOriginal()) {
version += from->nameVersion;
} else if (const auto info = item->hiddenForwardedInfo()) {
++version;
} else {
Unexpected("Corrupt forwarded information in message.");
}
}
}
if (version != _toForwardNameVersion) {
@ -6772,9 +6836,9 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
auto forwardLeft = st::historyReplySkip;
st::historyForwardIcon.paint(p, st::historyReplyIconPosition + QPoint(0, backy), width());
if (!drawWebPagePreview) {
const auto firstItem = _toForward.front();
const auto firstItem = _toForward.items.front();
const auto firstMedia = firstItem->media();
const auto preview = (_toForward.size() < 2 && firstMedia && firstMedia->hasReplyPreview())
const auto preview = (_toForward.items.size() < 2 && firstMedia && firstMedia->hasReplyPreview())
? firstMedia->replyPreview()
: nullptr;
if (preview) {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "history/history_drag_area.h"
#include "history/history.h"
#include "ui/widgets/tooltip.h"
#include "mainwidget.h"
#include "chat_helpers/bot_command.h"
@ -607,7 +608,7 @@ private:
Ui::Text::String _replyToName;
int _replyToNameVersion = 0;
HistoryItemsList _toForward;
Data::ResolvedForwardDraft _toForward;
Ui::Text::String _toForwardFrom, _toForwardText;
int _toForwardNameVersion = 0;

View File

@ -502,20 +502,20 @@ void MainWidget::floatPlayerDoubleClickEvent(
_controller->showPeerHistoryAtItem(item);
}
bool MainWidget::setForwardDraft(PeerId peerId, MessageIdsList &&items) {
bool MainWidget::setForwardDraft(PeerId peerId, Data::ForwardDraft &&draft) {
Expects(peerId != 0);
const auto peer = session().data().peer(peerId);
const auto error = GetErrorTextForSending(
peer,
session().data().idsToItems(items),
session().data().idsToItems(draft.ids),
true);
if (!error.isEmpty()) {
Ui::show(Box<InformBox>(error), Ui::LayerOption::KeepOther);
return false;
}
peer->owner().history(peer)->setForwardDraft(std::move(items));
peer->owner().history(peer)->setForwardDraft(std::move(draft));
_controller->showPeerHistory(
peer,
SectionShow::Way::Forward,
@ -603,7 +603,10 @@ void MainWidget::onFilesOrForwardDrop(
Expects(peerId != 0);
if (data->hasFormat(qsl("application/x-td-forward"))) {
if (!setForwardDraft(peerId, session().data().takeMimeForwardIds())) {
auto draft = Data::ForwardDraft{
.ids = session().data().takeMimeForwardIds(),
};
if (!setForwardDraft(peerId, std::move(draft))) {
// We've already released the mouse button, so the forwarding is cancelled.
if (_hider) {
_hider->startHide();
@ -704,9 +707,9 @@ void MainWidget::hiderLayer(base::unique_qptr<Window::HistoryHider> hider) {
floatPlayerCheckVisibility();
}
void MainWidget::showForwardLayer(MessageIdsList &&items) {
auto callback = [=, items = std::move(items)](PeerId peer) mutable {
return setForwardDraft(peer, std::move(items));
void MainWidget::showForwardLayer(Data::ForwardDraft &&draft) {
auto callback = [=, draft = std::move(draft)](PeerId peer) mutable {
return setForwardDraft(peer, std::move(draft));
};
hiderLayer(base::make_unique_q<Window::HistoryHider>(
this,

View File

@ -39,6 +39,7 @@ class Session;
namespace Data {
class WallPaper;
struct ForwardDraft;
} // namespace Data
namespace Dialogs {
@ -159,12 +160,12 @@ public:
int32 dlgsWidth() const;
void showForwardLayer(MessageIdsList &&items);
void showForwardLayer(Data::ForwardDraft &&draft);
void showSendPathsLayer();
void shareUrlLayer(const QString &url, const QString &text);
void inlineSwitchLayer(const QString &botAndQuery);
void hiderLayer(base::unique_qptr<Window::HistoryHider> h);
bool setForwardDraft(PeerId peer, MessageIdsList &&items);
bool setForwardDraft(PeerId peer, Data::ForwardDraft &&draft);
bool shareUrl(
PeerId peerId,
const QString &url,

View File

@ -0,0 +1,106 @@
/*
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 "ui/chat/forward_options_box.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "lang/lang_keys.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
namespace Ui {
void ForwardOptionsBox(
not_null<GenericBox*> box,
int count,
ForwardOptions options,
Fn<void(ForwardOptions)> optionsChanged,
Fn<void()> changeRecipient) {
Expects(optionsChanged != nullptr);
Expects(changeRecipient != nullptr);
box->setTitle((count == 1)
? tr::lng_forward_title()
: tr::lng_forward_many_title(
lt_count,
rpl::single(count) | tr::to_count()));
box->addButton(tr::lng_box_done(), [=] {
box->closeBox();
});
box->addRow(
object_ptr<Ui::FlatLabel>(
box.get(),
(count == 1
? tr::lng_forward_about()
: tr::lng_forward_about_many(
lt_count,
rpl::single(count) | tr::to_count())),
st::boxLabel),
st::boxRowPadding);
const auto checkboxPadding = style::margins(
st::boxRowPadding.left(),
st::boxRowPadding.left(),
st::boxRowPadding.right(),
st::boxRowPadding.bottom());
const auto names = box->addRow(
object_ptr<Ui::Checkbox>(
box.get(),
(count == 1
? tr::lng_forward_show_sender
: tr::lng_forward_show_senders)(),
!options.dropNames,
st::defaultBoxCheckbox),
checkboxPadding);
const auto captions = options.hasCaptions
? box->addRow(
object_ptr<Ui::Checkbox>(
box.get(),
(count == 1
? tr::lng_forward_show_caption
: tr::lng_forward_show_captions)(),
!options.dropCaptions,
st::defaultBoxCheckbox),
checkboxPadding)
: nullptr;
const auto notify = [=] {
optionsChanged({
.dropNames = !names->checked(),
.hasCaptions = options.hasCaptions,
.dropCaptions = (captions && !captions->checked()),
});
};
names->checkedChanges(
) | rpl::start_with_next([=](bool showNames) {
if (showNames && captions && !captions->checked()) {
captions->setChecked(true);
} else {
notify();
}
}, names->lifetime());
if (captions) {
captions->checkedChanges(
) | rpl::start_with_next([=](bool showCaptions) {
if (!showCaptions && names->checked()) {
names->setChecked(false);
} else {
notify();
}
}, captions->lifetime());
}
box->addRow(
object_ptr<Ui::LinkButton>(
box.get(),
tr::lng_forward_change_recipient(tr::now)),
checkboxPadding
)->setClickedCallback([=] {
box->closeBox();
changeRecipient();
});
}
} // namespace Ui

View File

@ -0,0 +1,27 @@
/*
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
#include "ui/layers/generic_box.h"
namespace Ui {
struct ForwardOptions {
bool dropNames = false;
bool hasCaptions = false;
bool dropCaptions = false;
};
void ForwardOptionsBox(
not_null<GenericBox*> box,
int count,
ForwardOptions options,
Fn<void(ForwardOptions)> optionsChanged,
Fn<void()> changeRecipient);
} // namespace Ui

View File

@ -963,27 +963,29 @@ void BlockSenderFromRepliesBox(
QPointer<Ui::RpWidget> ShowForwardMessagesBox(
not_null<Window::SessionNavigation*> navigation,
MessageIdsList &&items,
Data::ForwardDraft &&draft,
FnMut<void()> &&successCallback) {
const auto weak = std::make_shared<QPointer<PeerListBox>>();
auto callback = [
ids = std::move(items),
draft = std::move(draft),
callback = std::move(successCallback),
weak,
navigation
](not_null<PeerData*> peer) mutable {
const auto content = navigation->parentController()->content();
if (peer->isSelf()) {
auto items = peer->owner().idsToItems(ids);
if (!items.empty()) {
const auto history = peer->owner().history(peer);
auto resolved = history->resolveForwardDraft(draft);
if (!resolved.items.empty()) {
const auto api = &peer->session().api();
auto action = Api::SendAction(peer->owner().history(peer));
action.clearDraft = false;
action.generateLocal = false;
api->forwardMessages(std::move(items), action, [] {
api->forwardMessages(std::move(resolved), action, [] {
Ui::Toast::Show(tr::lng_share_done(tr::now));
});
}
} else if (!navigation->parentController()->content()->setForwardDraft(peer->id, std::move(ids))) {
} else if (!content->setForwardDraft(peer->id, std::move(draft))) {
return;
}
if (const auto strong = *weak) {
@ -1006,6 +1008,16 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
return weak->data();
}
QPointer<Ui::RpWidget> ShowForwardMessagesBox(
not_null<Window::SessionNavigation*> navigation,
MessageIdsList &&items,
FnMut<void()> &&successCallback) {
return ShowForwardMessagesBox(
navigation,
Data::ForwardDraft{ .ids = std::move(items) },
std::move(successCallback));
}
QPointer<Ui::RpWidget> ShowSendNowMessagesBox(
not_null<Window::SessionNavigation*> navigation,
not_null<History*> history,

View File

@ -21,6 +21,7 @@ class GenericBox;
namespace Data {
class Folder;
class Session;
struct ForwardDraft;
} // namespace Data
namespace Dialogs {
@ -94,6 +95,10 @@ void ToggleHistoryArchived(not_null<History*> history, bool archived);
Fn<void()> ClearHistoryHandler(not_null<PeerData*> peer);
Fn<void()> DeleteAndLeaveHandler(not_null<PeerData*> peer);
QPointer<Ui::RpWidget> ShowForwardMessagesBox(
not_null<Window::SessionNavigation*> navigation,
Data::ForwardDraft &&draft,
FnMut<void()> &&successCallback = nullptr);
QPointer<Ui::RpWidget> ShowForwardMessagesBox(
not_null<Window::SessionNavigation*> navigation,
MessageIdsList &&items,

View File

@ -139,6 +139,8 @@ PRIVATE
ui/chat/chat_style.h
ui/chat/chat_theme.cpp
ui/chat/chat_theme.h
ui/chat/forward_options_box.cpp
ui/chat/forward_options_box.h
ui/chat/group_call_bar.cpp
ui/chat/group_call_bar.h
ui/chat/group_call_userpics.cpp