mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Add simple forwarding options on bar click.
This commit is contained in:
parent
e9a5c45f34
commit
9dfc60026e
18 changed files with 378 additions and 94 deletions
|
@ -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";
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
106
Telegram/SourceFiles/ui/chat/forward_options_box.cpp
Normal file
106
Telegram/SourceFiles/ui/chat/forward_options_box.cpp
Normal 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
|
27
Telegram/SourceFiles/ui/chat/forward_options_box.h
Normal file
27
Telegram/SourceFiles/ui/chat/forward_options_box.h
Normal 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
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue