mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Allow editing caption above/below media.
This commit is contained in:
parent
67f7816088
commit
8c0351be4e
10 changed files with 200 additions and 91 deletions
|
@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "main/main_session_settings.h"
|
#include "main/main_session_settings.h"
|
||||||
#include "mainwidget.h" // controller->content() -> QWidget*
|
#include "mainwidget.h" // controller->content() -> QWidget*
|
||||||
|
#include "menu/menu_send.h"
|
||||||
#include "mtproto/mtproto_config.h"
|
#include "mtproto/mtproto_config.h"
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
#include "storage/localimageloader.h" // SendMediaType
|
#include "storage/localimageloader.h" // SendMediaType
|
||||||
|
@ -225,13 +226,6 @@ void EditPhotoImage(
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
EditCaptionBox::EditCaptionBox(
|
|
||||||
QWidget*,
|
|
||||||
not_null<Window::SessionController*> controller,
|
|
||||||
not_null<HistoryItem*> item)
|
|
||||||
: EditCaptionBox({}, controller, item, PrepareEditText(item), {}, {}) {
|
|
||||||
}
|
|
||||||
|
|
||||||
EditCaptionBox::EditCaptionBox(
|
EditCaptionBox::EditCaptionBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
|
@ -365,9 +359,21 @@ void EditCaptionBox::StartPhotoEdit(
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditCaptionBox::prepare() {
|
void EditCaptionBox::prepare() {
|
||||||
addButton(tr::lng_settings_save(), [=] { save(); });
|
const auto button = addButton(tr::lng_settings_save(), [=] { save(); });
|
||||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||||
|
|
||||||
|
const auto details = crl::guard(this, [=] {
|
||||||
|
return SendMenu::Details();
|
||||||
|
});
|
||||||
|
const auto callback = [=](SendMenu::Action action, const auto &) {
|
||||||
|
|
||||||
|
};
|
||||||
|
SendMenu::SetupMenuAndShortcuts(
|
||||||
|
button,
|
||||||
|
nullptr,
|
||||||
|
details,
|
||||||
|
crl::guard(this, callback));
|
||||||
|
|
||||||
updateBoxSize();
|
updateBoxSize();
|
||||||
|
|
||||||
setupField();
|
setupField();
|
||||||
|
@ -899,6 +905,7 @@ void EditCaptionBox::save() {
|
||||||
auto options = Api::SendOptions();
|
auto options = Api::SendOptions();
|
||||||
options.scheduled = item->isScheduled() ? item->date() : 0;
|
options.scheduled = item->isScheduled() ? item->date() : 0;
|
||||||
options.shortcutId = item->shortcutId();
|
options.shortcutId = item->shortcutId();
|
||||||
|
//options.invertCaption = _invertCaption;
|
||||||
|
|
||||||
if (!_preparedList.files.empty()) {
|
if (!_preparedList.files.empty()) {
|
||||||
if ((_albumType != Ui::AlbumType::None)
|
if ((_albumType != Ui::AlbumType::None)
|
||||||
|
|
|
@ -32,10 +32,6 @@ enum class AlbumType;
|
||||||
|
|
||||||
class EditCaptionBox final : public Ui::BoxContent {
|
class EditCaptionBox final : public Ui::BoxContent {
|
||||||
public:
|
public:
|
||||||
EditCaptionBox(
|
|
||||||
QWidget*,
|
|
||||||
not_null<Window::SessionController*> controller,
|
|
||||||
not_null<HistoryItem*> item);
|
|
||||||
EditCaptionBox(
|
EditCaptionBox(
|
||||||
QWidget*,
|
QWidget*,
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
|
|
|
@ -379,7 +379,7 @@ Fn<SendMenu::Details()> SendFilesBox::prepareSendMenuDetails(
|
||||||
const auto canMoveCaption = _list.canMoveCaption(
|
const auto canMoveCaption = _list.canMoveCaption(
|
||||||
way.groupFiles() && way.sendImagesAsPhotos(),
|
way.groupFiles() && way.sendImagesAsPhotos(),
|
||||||
way.sendImagesAsPhotos()
|
way.sendImagesAsPhotos()
|
||||||
) && _caption && !_caption->getLastText().isEmpty();
|
) && _caption && HasSendText(_caption);
|
||||||
result.caption = !canMoveCaption
|
result.caption = !canMoveCaption
|
||||||
? SendMenu::CaptionState::None
|
? SendMenu::CaptionState::None
|
||||||
: _invertCaption
|
: _invertCaption
|
||||||
|
@ -638,14 +638,15 @@ void SendFilesBox::addMenuButton() {
|
||||||
const auto &tabbed = _st.tabbed;
|
const auto &tabbed = _st.tabbed;
|
||||||
const auto &icons = tabbed.icons;
|
const auto &icons = tabbed.icons;
|
||||||
_menu = base::make_unique_q<Ui::PopupMenu>(top, tabbed.menu);
|
_menu = base::make_unique_q<Ui::PopupMenu>(top, tabbed.menu);
|
||||||
|
const auto position = QCursor::pos();
|
||||||
SendMenu::FillSendMenu(
|
SendMenu::FillSendMenu(
|
||||||
_menu.get(),
|
_menu.get(),
|
||||||
_show,
|
_show,
|
||||||
_sendMenuDetails(),
|
_sendMenuDetails(),
|
||||||
_sendMenuCallback,
|
_sendMenuCallback,
|
||||||
&_st.tabbed.icons,
|
&_st.tabbed.icons,
|
||||||
QCursor::pos());
|
position);
|
||||||
_menu->popup(QCursor::pos());
|
_menu->popup(position);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,7 +324,12 @@ HistoryWidget::HistoryWidget(
|
||||||
{
|
{
|
||||||
using namespace SendMenu;
|
using namespace SendMenu;
|
||||||
const auto sendAction = [=](Action action, Details) {
|
const auto sendAction = [=](Action action, Details) {
|
||||||
if (action.type == ActionType::Send) {
|
if (action.type == ActionType::CaptionUp
|
||||||
|
|| action.type == ActionType::CaptionDown
|
||||||
|
|| action.type == ActionType::SpoilerOn
|
||||||
|
|| action.type == ActionType::SpoilerOff) {
|
||||||
|
_mediaEditSpoiler.apply(action);
|
||||||
|
} else if (action.type == ActionType::Send) {
|
||||||
send(action.options);
|
send(action.options);
|
||||||
} else {
|
} else {
|
||||||
sendScheduled(action.options);
|
sendScheduled(action.options);
|
||||||
|
@ -2672,7 +2677,7 @@ void HistoryWidget::setEditMsgId(MsgId msgId) {
|
||||||
unregisterDraftSources();
|
unregisterDraftSources();
|
||||||
_editMsgId = msgId;
|
_editMsgId = msgId;
|
||||||
if (!msgId) {
|
if (!msgId) {
|
||||||
_mediaEditSpoiler.setSpoilerOverride(std::nullopt);
|
_mediaEditSpoiler.cancel();
|
||||||
_canReplaceMedia = false;
|
_canReplaceMedia = false;
|
||||||
if (_preview) {
|
if (_preview) {
|
||||||
_preview->setDisabled(false);
|
_preview->setDisabled(false);
|
||||||
|
@ -4056,15 +4061,14 @@ void HistoryWidget::saveEditMsg() {
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto options = Api::SendOptions();
|
|
||||||
_saveEditMsgRequestId = Api::EditTextMessage(
|
_saveEditMsgRequestId = Api::EditTextMessage(
|
||||||
item,
|
item,
|
||||||
sending,
|
sending,
|
||||||
webPageDraft,
|
webPageDraft,
|
||||||
options,
|
{ .invertCaption = _mediaEditSpoiler.invertCaption() },
|
||||||
done,
|
done,
|
||||||
fail,
|
fail,
|
||||||
_mediaEditSpoiler.spoilerOverride());
|
_mediaEditSpoiler.spoilered());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::hideChildWidgets() {
|
void HistoryWidget::hideChildWidgets() {
|
||||||
|
@ -4222,6 +4226,12 @@ SendMenu::Details HistoryWidget::sendMenuDetails() const {
|
||||||
return { .type = type, .effectAllowed = effectAllowed };
|
return { .type = type, .effectAllowed = effectAllowed };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SendMenu::Details HistoryWidget::saveMenuDetails() const {
|
||||||
|
return (_editMsgId && _replyEditMsg)
|
||||||
|
? _mediaEditSpoiler.sendMenuDetails(HasSendText(_field))
|
||||||
|
: SendMenu::Details();
|
||||||
|
}
|
||||||
|
|
||||||
auto HistoryWidget::computeSendButtonType() const {
|
auto HistoryWidget::computeSendButtonType() const {
|
||||||
using Type = Ui::SendButton::Type;
|
using Type = Ui::SendButton::Type;
|
||||||
|
|
||||||
|
@ -4236,7 +4246,11 @@ auto HistoryWidget::computeSendButtonType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMenu::Details HistoryWidget::sendButtonMenuDetails() const {
|
SendMenu::Details HistoryWidget::sendButtonMenuDetails() const {
|
||||||
if (computeSendButtonType() != Ui::SendButton::Type::Send) {
|
using Type = Ui::SendButton::Type;
|
||||||
|
const auto type = computeSendButtonType();
|
||||||
|
if (type == Type::Save) {
|
||||||
|
return saveMenuDetails();
|
||||||
|
} else if (type != Type::Send) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return sendMenuDetails();
|
return sendMenuDetails();
|
||||||
|
@ -6587,8 +6601,8 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
&& (e->button() == Qt::RightButton)) {
|
&& (e->button() == Qt::RightButton)) {
|
||||||
_mediaEditSpoiler.showMenu(
|
_mediaEditSpoiler.showMenu(
|
||||||
_list,
|
_list,
|
||||||
session().data().message(_history->peer, _editMsgId),
|
[=] { mouseMoveEvent(nullptr); },
|
||||||
[=](bool) { mouseMoveEvent(nullptr); });
|
HasSendText(_field));
|
||||||
} else if (_inPhotoEdit && _photoEditMedia) {
|
} else if (_inPhotoEdit && _photoEditMedia) {
|
||||||
EditCaptionBox::StartPhotoEdit(
|
EditCaptionBox::StartPhotoEdit(
|
||||||
controller(),
|
controller(),
|
||||||
|
@ -8171,6 +8185,9 @@ void HistoryWidget::updateReplyEditTexts(bool force) {
|
||||||
const auto editMedia = _editMsgId
|
const auto editMedia = _editMsgId
|
||||||
? _replyEditMsg->media()
|
? _replyEditMsg->media()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
if (_editMsgId && _replyEditMsg) {
|
||||||
|
_mediaEditSpoiler.start(_replyEditMsg);
|
||||||
|
}
|
||||||
_canReplaceMedia = editMedia && editMedia->allowsEditMedia();
|
_canReplaceMedia = editMedia && editMedia->allowsEditMedia();
|
||||||
_photoEditMedia = (_canReplaceMedia
|
_photoEditMedia = (_canReplaceMedia
|
||||||
&& editMedia->photo()
|
&& editMedia->photo()
|
||||||
|
@ -8264,14 +8281,12 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
|
||||||
? drawMsgText->media()
|
? drawMsgText->media()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto hasPreview = media && media->hasReplyPreview();
|
const auto hasPreview = media && media->hasReplyPreview();
|
||||||
const auto preview = _mediaEditSpoiler.spoilerOverride()
|
const auto preview = _mediaEditSpoiler
|
||||||
? _mediaEditSpoiler.mediaPreview(drawMsgText)
|
? _mediaEditSpoiler.mediaPreview()
|
||||||
: hasPreview
|
: hasPreview
|
||||||
? media->replyPreview()
|
? media->replyPreview()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto spoilered = _mediaEditSpoiler.spoilerOverride()
|
const auto spoilered = _mediaEditSpoiler.spoilered();
|
||||||
? (*_mediaEditSpoiler.spoilerOverride())
|
|
||||||
: (preview && media->hasSpoiler());
|
|
||||||
if (!spoilered) {
|
if (!spoilered) {
|
||||||
_replySpoiler = nullptr;
|
_replySpoiler = nullptr;
|
||||||
} else if (!_replySpoiler) {
|
} else if (!_replySpoiler) {
|
||||||
|
|
|
@ -269,6 +269,7 @@ public:
|
||||||
void clearSelected();
|
void clearSelected();
|
||||||
|
|
||||||
[[nodiscard]] SendMenu::Details sendMenuDetails() const;
|
[[nodiscard]] SendMenu::Details sendMenuDetails() const;
|
||||||
|
[[nodiscard]] SendMenu::Details saveMenuDetails() const;
|
||||||
bool sendExistingDocument(
|
bool sendExistingDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
Api::SendOptions options,
|
Api::SendOptions options,
|
||||||
|
|
|
@ -124,7 +124,8 @@ class FieldHeader final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
FieldHeader(
|
FieldHeader(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
std::shared_ptr<ChatHelpers::Show> show);
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
Fn<bool()> hasSendText);
|
||||||
|
|
||||||
void setHistory(const SetHistoryArgs &args);
|
void setHistory(const SetHistoryArgs &args);
|
||||||
void updateTopicRootId(MsgId topicRootId);
|
void updateTopicRootId(MsgId topicRootId);
|
||||||
|
@ -187,6 +188,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::shared_ptr<ChatHelpers::Show> _show;
|
const std::shared_ptr<ChatHelpers::Show> _show;
|
||||||
|
const Fn<bool()> _hasSendText;
|
||||||
|
|
||||||
History *_history = nullptr;
|
History *_history = nullptr;
|
||||||
MsgId _topicRootId = 0;
|
MsgId _topicRootId = 0;
|
||||||
|
|
||||||
|
@ -230,9 +233,11 @@ private:
|
||||||
|
|
||||||
FieldHeader::FieldHeader(
|
FieldHeader::FieldHeader(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
std::shared_ptr<ChatHelpers::Show> show)
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
Fn<bool()> hasSendText)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _show(std::move(show))
|
, _show(std::move(show))
|
||||||
|
, _hasSendText(std::move(hasSendText))
|
||||||
, _forwardPanel(
|
, _forwardPanel(
|
||||||
std::make_unique<ForwardPanel>([=] { customEmojiRepaint(); }))
|
std::make_unique<ForwardPanel>([=] { customEmojiRepaint(); }))
|
||||||
, _data(&_show->session().data())
|
, _data(&_show->session().data())
|
||||||
|
@ -406,8 +411,8 @@ void FieldHeader::init() {
|
||||||
if (inPreviewRect && isEditingMessage()) {
|
if (inPreviewRect && isEditingMessage()) {
|
||||||
_mediaEditSpoiler.showMenu(
|
_mediaEditSpoiler.showMenu(
|
||||||
this,
|
this,
|
||||||
_data->message(_editMsgId.current()),
|
[=] { update(); },
|
||||||
[=](bool) { update(); });
|
_hasSendText());
|
||||||
} else if (const auto reply = replyingToMessage()) {
|
} else if (const auto reply = replyingToMessage()) {
|
||||||
_jumpToItemRequests.fire_copy(reply);
|
_jumpToItemRequests.fire_copy(reply);
|
||||||
}
|
}
|
||||||
|
@ -582,14 +587,12 @@ void FieldHeader::paintEditOrReplyToMessage(Painter &p) {
|
||||||
|
|
||||||
const auto media = _shownMessage->media();
|
const auto media = _shownMessage->media();
|
||||||
_shownMessageHasPreview = media && media->hasReplyPreview();
|
_shownMessageHasPreview = media && media->hasReplyPreview();
|
||||||
const auto preview = _mediaEditSpoiler.spoilerOverride()
|
const auto preview = _mediaEditSpoiler
|
||||||
? _mediaEditSpoiler.mediaPreview(_shownMessage)
|
? _mediaEditSpoiler.mediaPreview()
|
||||||
: _shownMessageHasPreview
|
: _shownMessageHasPreview
|
||||||
? media->replyPreview()
|
? media->replyPreview()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto spoilered = _mediaEditSpoiler.spoilerOverride()
|
const auto spoilered = _mediaEditSpoiler.spoilered();
|
||||||
? (*_mediaEditSpoiler.spoilerOverride())
|
|
||||||
: (preview && media->hasSpoiler());
|
|
||||||
if (!spoilered) {
|
if (!spoilered) {
|
||||||
_shownPreviewSpoiler = nullptr;
|
_shownPreviewSpoiler = nullptr;
|
||||||
} else if (!_shownPreviewSpoiler) {
|
} else if (!_shownPreviewSpoiler) {
|
||||||
|
@ -734,7 +737,7 @@ void FieldHeader::editMessage(FullMsgId id, bool photoEditAllowed) {
|
||||||
_photoEditAllowed = photoEditAllowed;
|
_photoEditAllowed = photoEditAllowed;
|
||||||
_editMsgId = id;
|
_editMsgId = id;
|
||||||
if (!photoEditAllowed) {
|
if (!photoEditAllowed) {
|
||||||
_mediaEditSpoiler.setSpoilerOverride(std::nullopt);
|
_mediaEditSpoiler.cancel();
|
||||||
_inPhotoEdit = false;
|
_inPhotoEdit = false;
|
||||||
_inPhotoEditOver.stop();
|
_inPhotoEditOver.stop();
|
||||||
}
|
}
|
||||||
|
@ -781,8 +784,9 @@ MessageToEdit FieldHeader::queryToEdit() {
|
||||||
.options = {
|
.options = {
|
||||||
.scheduled = item->isScheduled() ? item->date() : 0,
|
.scheduled = item->isScheduled() ? item->date() : 0,
|
||||||
.shortcutId = item->shortcutId(),
|
.shortcutId = item->shortcutId(),
|
||||||
|
.invertCaption = _mediaEditSpoiler.invertCaption(),
|
||||||
},
|
},
|
||||||
.spoilerMediaOverride = _mediaEditSpoiler.spoilerOverride(),
|
.spoilerMediaOverride = _mediaEditSpoiler.spoilered(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,7 +846,10 @@ ComposeControls::ComposeControls(
|
||||||
parent,
|
parent,
|
||||||
_show,
|
_show,
|
||||||
&_st.tabbed))
|
&_st.tabbed))
|
||||||
, _header(std::make_unique<FieldHeader>(_wrap.get(), _show))
|
, _header(std::make_unique<FieldHeader>(
|
||||||
|
_wrap.get(),
|
||||||
|
_show,
|
||||||
|
[=] { return HasSendText(_field); }))
|
||||||
, _voiceRecordBar(std::make_unique<VoiceRecordBar>(
|
, _voiceRecordBar(std::make_unique<VoiceRecordBar>(
|
||||||
_wrap.get(),
|
_wrap.get(),
|
||||||
Controls::VoiceRecordBarDescriptor{
|
Controls::VoiceRecordBarDescriptor{
|
||||||
|
|
|
@ -10,74 +10,134 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "menu/menu_send.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
#include "styles/style_chat_helpers.h"
|
||||||
#include "styles/style_menu_icons.h"
|
#include "styles/style_menu_icons.h"
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
|
||||||
MediaEditSpoilerManager::MediaEditSpoilerManager() = default;
|
MediaEditSpoilerManager::MediaEditSpoilerManager() = default;
|
||||||
|
|
||||||
|
void MediaEditSpoilerManager::start(not_null<HistoryItem*> item) {
|
||||||
|
const auto media = item->media();
|
||||||
|
if (!media) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_item = item;
|
||||||
|
_spoilered = media->hasSpoiler();
|
||||||
|
_invertCaption = item->invertMedia();
|
||||||
|
_lifetime = item->history()->owner().itemRemoved(
|
||||||
|
) | rpl::start_with_next([=](not_null<const HistoryItem*> removed) {
|
||||||
|
if (removed == _item) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaEditSpoilerManager::apply(SendMenu::Action action) {
|
||||||
|
using Type = SendMenu::Action::Type;
|
||||||
|
if (action.type == Type::CaptionUp) {
|
||||||
|
_invertCaption = true;
|
||||||
|
} else if (action.type == Type::CaptionDown) {
|
||||||
|
_invertCaption = false;
|
||||||
|
} else if (action.type == Type::SpoilerOn) {
|
||||||
|
_spoilered = true;
|
||||||
|
} else if (action.type == Type::SpoilerOff) {
|
||||||
|
_spoilered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaEditSpoilerManager::cancel() {
|
||||||
|
_menu = nullptr;
|
||||||
|
_item = nullptr;
|
||||||
|
_lifetime.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
void MediaEditSpoilerManager::showMenu(
|
void MediaEditSpoilerManager::showMenu(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<HistoryItem*> item,
|
Fn<void()> finished,
|
||||||
Fn<void(bool)> callback) {
|
bool hasCaptionText) {
|
||||||
const auto media = item->media();
|
if (!_item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto media = _item->media();
|
||||||
const auto hasPreview = media && media->hasReplyPreview();
|
const auto hasPreview = media && media->hasReplyPreview();
|
||||||
const auto preview = hasPreview ? media->replyPreview() : nullptr;
|
const auto preview = hasPreview ? media->replyPreview() : nullptr;
|
||||||
if (!preview || (media && media->webpage())) {
|
if (!preview || (media && media->webpage())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto spoilered = _spoilerOverride
|
_menu = base::make_unique_q<Ui::PopupMenu>(
|
||||||
? (*_spoilerOverride)
|
|
||||||
: (preview && media->hasSpoiler());
|
|
||||||
const auto menu = Ui::CreateChild<Ui::PopupMenu>(
|
|
||||||
parent,
|
parent,
|
||||||
st::popupMenuWithIcons);
|
st::popupMenuWithIcons);
|
||||||
menu->addAction(
|
const auto callback = [=](SendMenu::Action action, const auto &) {
|
||||||
spoilered
|
apply(action);
|
||||||
? tr::lng_context_disable_spoiler(tr::now)
|
};
|
||||||
: tr::lng_context_spoiler_effect(tr::now),
|
const auto position = QCursor::pos();
|
||||||
[=] {
|
SendMenu::FillSendMenu(
|
||||||
_spoilerOverride = (!spoilered);
|
_menu.get(),
|
||||||
if (callback) {
|
nullptr,
|
||||||
callback(!spoilered);
|
sendMenuDetails(hasCaptionText),
|
||||||
}
|
callback,
|
||||||
},
|
&st::defaultComposeIcons,
|
||||||
spoilered ? &st::menuIconSpoilerOff : &st::menuIconSpoiler);
|
position);
|
||||||
menu->popup(QCursor::pos());
|
_menu->popup(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Image *MediaEditSpoilerManager::mediaPreview(
|
[[nodiscard]] Image *MediaEditSpoilerManager::mediaPreview() {
|
||||||
not_null<HistoryItem*> item) {
|
if (const auto media = _item ? _item->media() : nullptr) {
|
||||||
if (!_spoilerOverride) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (const auto media = item->media()) {
|
|
||||||
if (const auto photo = media->photo()) {
|
if (const auto photo = media->photo()) {
|
||||||
return photo->getReplyPreview(
|
return photo->getReplyPreview(
|
||||||
item->fullId(),
|
_item->fullId(),
|
||||||
item->history()->peer,
|
_item->history()->peer,
|
||||||
*_spoilerOverride);
|
_spoilered);
|
||||||
} else if (const auto document = media->document()) {
|
} else if (const auto document = media->document()) {
|
||||||
return document->getReplyPreview(
|
return document->getReplyPreview(
|
||||||
item->fullId(),
|
_item->fullId(),
|
||||||
item->history()->peer,
|
_item->history()->peer,
|
||||||
*_spoilerOverride);
|
_spoilered);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaEditSpoilerManager::setSpoilerOverride(
|
bool MediaEditSpoilerManager::spoilered() const {
|
||||||
std::optional<bool> spoilerOverride) {
|
return _spoilered;
|
||||||
_spoilerOverride = spoilerOverride;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<bool> MediaEditSpoilerManager::spoilerOverride() const {
|
bool MediaEditSpoilerManager::invertCaption() const {
|
||||||
return _spoilerOverride;
|
return _invertCaption;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendMenu::Details MediaEditSpoilerManager::sendMenuDetails(
|
||||||
|
bool hasCaptionText) const {
|
||||||
|
const auto media = _item ? _item->media() : nullptr;
|
||||||
|
if (!media) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto editingMedia = media->allowsEditMedia();
|
||||||
|
const auto editPhoto = editingMedia ? media->photo() : nullptr;
|
||||||
|
const auto editDocument = editingMedia ? media->document() : nullptr;
|
||||||
|
const auto canSaveSpoiler = (editPhoto && !editPhoto->isNull())
|
||||||
|
|| (editDocument
|
||||||
|
&& (editDocument->isVideoFile() || editDocument->isGifv()));
|
||||||
|
const auto canMoveCaption = media->allowsEditCaption() && hasCaptionText;
|
||||||
|
return {
|
||||||
|
.spoiler = (!canSaveSpoiler
|
||||||
|
? SendMenu::SpoilerState::None
|
||||||
|
: _spoilered
|
||||||
|
? SendMenu::SpoilerState::Enabled
|
||||||
|
: SendMenu::SpoilerState::Possible),
|
||||||
|
.caption = (!canMoveCaption
|
||||||
|
? SendMenu::CaptionState::None
|
||||||
|
: _invertCaption
|
||||||
|
? SendMenu::CaptionState::Above
|
||||||
|
: SendMenu::CaptionState::Below),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -7,8 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/unique_qptr.h"
|
||||||
|
|
||||||
|
namespace SendMenu {
|
||||||
|
struct Details;
|
||||||
|
struct Action;
|
||||||
|
} // namespace SendMenu
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RpWidget;
|
class RpWidget;
|
||||||
|
class PopupMenu;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class Image;
|
class Image;
|
||||||
|
@ -20,19 +28,34 @@ class MediaEditSpoilerManager final {
|
||||||
public:
|
public:
|
||||||
MediaEditSpoilerManager();
|
MediaEditSpoilerManager();
|
||||||
|
|
||||||
|
void start(not_null<HistoryItem*> item);
|
||||||
|
void apply(SendMenu::Action action);
|
||||||
|
void cancel();
|
||||||
|
|
||||||
void showMenu(
|
void showMenu(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<HistoryItem*> item,
|
Fn<void()> finished,
|
||||||
Fn<void(bool)> callback);
|
bool hasCaptionText);
|
||||||
|
|
||||||
[[nodiscard]] Image *mediaPreview(not_null<HistoryItem*> item);
|
[[nodiscard]] Image *mediaPreview();
|
||||||
|
|
||||||
void setSpoilerOverride(std::optional<bool> spoilerOverride);
|
[[nodiscard]] bool spoilered() const;
|
||||||
|
[[nodiscard]] bool invertCaption() const;
|
||||||
|
|
||||||
std::optional<bool> spoilerOverride() const;
|
[[nodiscard]] SendMenu::Details sendMenuDetails(
|
||||||
|
bool hasCaptionText) const;
|
||||||
|
|
||||||
|
[[nodiscard]] explicit operator bool() const {
|
||||||
|
return _item != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<bool> _spoilerOverride;
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
HistoryItem *_item = nullptr;
|
||||||
|
bool _spoilered = false;
|
||||||
|
bool _invertCaption = false;
|
||||||
|
|
||||||
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -396,7 +396,7 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// date
|
// date
|
||||||
if (_parent->media() == this) {
|
if (_parent->media() == this && isBubbleBottom()) {
|
||||||
auto fullRight = width();
|
auto fullRight = width();
|
||||||
auto fullBottom = height();
|
auto fullBottom = height();
|
||||||
if (needInfoDisplay()) {
|
if (needInfoDisplay()) {
|
||||||
|
|
|
@ -615,7 +615,8 @@ FillMenuResult FillSendMenu(
|
||||||
const style::ComposeIcons *iconsOverride,
|
const style::ComposeIcons *iconsOverride,
|
||||||
std::optional<QPoint> desiredPositionOverride) {
|
std::optional<QPoint> desiredPositionOverride) {
|
||||||
const auto type = details.type;
|
const auto type = details.type;
|
||||||
const auto empty = (type == Type::Disabled)
|
const auto sending = (type != Type::Disabled);
|
||||||
|
const auto empty = !sending
|
||||||
&& (details.spoiler == SpoilerState::None)
|
&& (details.spoiler == SpoilerState::None)
|
||||||
&& (details.caption == CaptionState::None);
|
&& (details.caption == CaptionState::None);
|
||||||
if (empty || !action) {
|
if (empty || !action) {
|
||||||
|
@ -653,18 +654,16 @@ FillMenuResult FillSendMenu(
|
||||||
toggles = true;
|
toggles = true;
|
||||||
}
|
}
|
||||||
if (toggles && type != Type::Disabled) {
|
if (toggles && type != Type::Disabled) {
|
||||||
menu->addSeparator();
|
menu->addSeparator(&st::expandedMenuSeparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != Type::Reminder) {
|
if (sending && type != Type::Reminder) {
|
||||||
menu->addAction(
|
menu->addAction(
|
||||||
tr::lng_send_silent_message(tr::now),
|
tr::lng_send_silent_message(tr::now),
|
||||||
[=] { action(
|
[=] { action({ Api::SendOptions{ .silent = true } }, details); },
|
||||||
{ Api::SendOptions{ .silent = true } },
|
|
||||||
details); },
|
|
||||||
&icons.menuMute);
|
&icons.menuMute);
|
||||||
}
|
}
|
||||||
if (type != Type::SilentOnly) {
|
if (sending && type != Type::SilentOnly) {
|
||||||
menu->addAction(
|
menu->addAction(
|
||||||
(type == Type::Reminder
|
(type == Type::Reminder
|
||||||
? tr::lng_reminder_message(tr::now)
|
? tr::lng_reminder_message(tr::now)
|
||||||
|
@ -672,7 +671,7 @@ FillMenuResult FillSendMenu(
|
||||||
[=] { action({ .type = ActionType::Schedule }, details); },
|
[=] { action({ .type = ActionType::Schedule }, details); },
|
||||||
&icons.menuSchedule);
|
&icons.menuSchedule);
|
||||||
}
|
}
|
||||||
if (type == Type::ScheduledToUser) {
|
if (sending && type == Type::ScheduledToUser) {
|
||||||
menu->addAction(
|
menu->addAction(
|
||||||
tr::lng_scheduled_send_until_online(tr::now),
|
tr::lng_scheduled_send_until_online(tr::now),
|
||||||
[=] { action(
|
[=] { action(
|
||||||
|
|
Loading…
Add table
Reference in a new issue