Implement text -> media message editing.

This commit is contained in:
John Preston 2024-10-10 18:20:10 +04:00
parent 0397006894
commit f89aeb6ad4
9 changed files with 55 additions and 21 deletions

View file

@ -238,7 +238,7 @@ EditCaptionBox::EditCaptionBox(
Fn<void()> saved)
: _controller(controller)
, _historyItem(item)
, _isAllowedEditMedia(item->media() && item->media()->allowsEditMedia())
, _isAllowedEditMedia(item->allowsEditMedia())
, _albumType(ComputeAlbumType(item))
, _controls(base::make_unique_q<Ui::VerticalLayout>(this))
, _scroll(base::make_unique_q<Ui::ScrollArea>(this, st::boxScroll))
@ -253,8 +253,8 @@ EditCaptionBox::EditCaptionBox(
, _initialText(std::move(text))
, _initialList(std::move(list))
, _saved(std::move(saved)) {
Expects(item->media() != nullptr);
Expects(item->media()->allowsEditCaption());
Expects(!_initialList.files.empty());
Expects(!item->media() || item->media()->allowsEditCaption());
_mediaEditManager.start(item, spoilered, invertCaption);
@ -422,7 +422,8 @@ void EditCaptionBox::prepare() {
setInitialText();
if (!setPreparedList(std::move(_initialList))) {
rebuildPreview();
crl::on_main(this, [=] { closeBox(); });
return;
}
setupEditEventHandler();
SetupShadowsToScrollContent(this, _scroll, _contentHeight.events());

View file

@ -1074,6 +1074,13 @@ historyReplaceMedia: IconButton(historyAttach) {
color: lightButtonBgOver;
}
}
historyAddMedia: IconButton(historyAttach) {
icon: icon {{ "chat/input_attach", windowBgActive }};
iconOver: icon {{ "chat/input_attach", windowBgActive }};
ripple: RippleAnimation(defaultRippleAnimation) {
color: lightButtonBgOver;
}
}
historyAttachEmojiActive: icon {{ "chat/input_smile_face", windowBgActive }};
historyEmojiCircle: size(20px, 20px);

View file

@ -1470,12 +1470,10 @@ void HistoryItem::returnSavedMedia() {
}
void HistoryItem::savePreviousMedia() {
Expects(_media != nullptr);
AddComponents(HistoryMessageSavedMediaData::Bit());
const auto data = Get<HistoryMessageSavedMediaData>();
data->text = originalText();
data->media = _media->clone(this);
data->media = _media ? _media->clone(this) : nullptr;
}
bool HistoryItem::isEditingMedia() const {
@ -2231,6 +2229,10 @@ bool HistoryItem::allowsEdit(TimeId now) const {
&& !isEditingMedia();
}
bool HistoryItem::allowsEditMedia() const {
return !_media || _media->allowsEditMedia();
}
bool HistoryItem::canBeEdited() const {
if ((!isRegular() && !isScheduled() && !isBusinessShortcut())
|| Has<HistoryMessageVia>()

View file

@ -431,6 +431,7 @@ public:
[[nodiscard]] bool allowsSendNow() const;
[[nodiscard]] bool allowsForward() const;
[[nodiscard]] bool allowsEdit(TimeId now) const;
[[nodiscard]] bool allowsEditMedia() const;
[[nodiscard]] bool canDelete() const;
[[nodiscard]] bool canDeleteForEveryone(TimeId now) const;
[[nodiscard]] bool suggestReport() const;

View file

@ -2312,7 +2312,7 @@ void HistoryWidget::showHistory(
_processingReplyItem = _replyEditMsg = nullptr;
_processingReplyTo = _replyTo = FullReplyTo();
_editMsgId = MsgId();
_canReplaceMedia = false;
_canReplaceMedia = _canAddMedia = false;
_photoEditMedia = nullptr;
updateReplaceMediaButton();
_fieldBarCancel->hide();
@ -2700,7 +2700,7 @@ void HistoryWidget::setEditMsgId(MsgId msgId) {
_editMsgId = msgId;
if (!msgId) {
_mediaEditManager.cancel();
_canReplaceMedia = false;
_canReplaceMedia = _canAddMedia = false;
if (_preview) {
_preview->setDisabled(false);
}
@ -2756,14 +2756,16 @@ void HistoryWidget::clearAllLoadRequests() {
}
bool HistoryWidget::updateReplaceMediaButton() {
if (!_canReplaceMedia) {
if (!_canReplaceMedia && !_canAddMedia) {
const auto result = (_replaceMedia != nullptr);
_replaceMedia.destroy();
return result;
} else if (_replaceMedia) {
return false;
}
_replaceMedia.create(this, st::historyReplaceMedia);
_replaceMedia.create(
this,
_canReplaceMedia ? st::historyReplaceMedia : st::historyAddMedia);
const auto hideDuration = st::historyReplaceMedia.ripple.hideDuration;
_replaceMedia->setClickedCallback([=] {
base::call_delayed(hideDuration, this, [=] {
@ -5712,7 +5714,7 @@ bool HistoryWidget::confirmSendingFiles(
Ui::PreparedList &&list,
const QString &insertTextOnCancel) {
if (_editMsgId) {
if (_canReplaceMedia) {
if (_canReplaceMedia || _canAddMedia) {
EditCaptionBox::StartMediaReplace(
controller(),
{ _history->peer->id, _editMsgId },
@ -8002,7 +8004,7 @@ void HistoryWidget::cancelEdit() {
return;
}
_canReplaceMedia = false;
_canReplaceMedia = _canAddMedia = false;
_photoEditMedia = nullptr;
updateReplaceMediaButton();
_replyEditMsg = nullptr;
@ -8357,7 +8359,16 @@ void HistoryWidget::updateReplyEditTexts(bool force) {
if (_editMsgId && _replyEditMsg) {
_mediaEditManager.start(_replyEditMsg);
}
_canReplaceMedia = editMedia && editMedia->allowsEditMedia();
_canReplaceMedia = _editMsgId && _replyEditMsg->allowsEditMedia();
if (editMedia) {
_canAddMedia = false;
} else {
_canAddMedia = base::take(_canReplaceMedia);
}
if (_canReplaceMedia || _canAddMedia) {
// Invalidate the button, maybe icon has changed.
_replaceMedia.destroy();
}
_photoEditMedia = (_canReplaceMedia
&& editMedia->photo()
&& !editMedia->photo()->isNull())

View file

@ -662,6 +662,7 @@ private:
MsgId _editMsgId = 0;
std::shared_ptr<Data::PhotoMedia> _photoEditMedia;
bool _canReplaceMedia = false;
bool _canAddMedia = false;
HistoryView::MediaEditManager _mediaEditManager;
HistoryItem *_replyEditMsg = nullptr;

View file

@ -1153,7 +1153,7 @@ void ComposeControls::setMimeDataHook(MimeDataHook hook) {
bool ComposeControls::confirmMediaEdit(Ui::PreparedList &list) {
if (!isEditingMessage() || !_regularWindow) {
return false;
} else if (_canReplaceMedia) {
} else if (_canReplaceMedia || _canAddMedia) {
const auto queryToEdit = _header->queryToEdit();
EditCaptionBox::StartMediaReplace(
_regularWindow,
@ -1944,7 +1944,7 @@ void ComposeControls::applyDraft(FieldHistoryAction fieldHistoryAction) {
_preview->apply({ .removed = true });
_preview->setDisabled(false);
}
_canReplaceMedia = false;
_canReplaceMedia = _canAddMedia = false;
_photoEditMedia = nullptr;
return;
}
@ -1964,7 +1964,16 @@ void ComposeControls::applyDraft(FieldHistoryAction fieldHistoryAction) {
const auto resolve = [=] {
if (const auto item = _history->owner().message(editingId)) {
const auto media = item->media();
_canReplaceMedia = media && media->allowsEditMedia();
_canReplaceMedia = item->allowsEditMedia();
if (media) {
_canAddMedia = false;
} else {
_canAddMedia = base::take(_canReplaceMedia);
}
if (_canReplaceMedia || _canAddMedia) {
// Invalidate the button, maybe icon has changed.
_replaceMedia = nullptr;
}
_photoEditMedia = (_canReplaceMedia
&& _regularWindow
&& media->photo()
@ -1985,7 +1994,7 @@ void ComposeControls::applyDraft(FieldHistoryAction fieldHistoryAction) {
}
return true;
}
_canReplaceMedia = false;
_canReplaceMedia = _canAddMedia = false;
_photoEditMedia = nullptr;
_header->editMessage(editingId, false);
return false;
@ -2006,7 +2015,7 @@ void ComposeControls::applyDraft(FieldHistoryAction fieldHistoryAction) {
}
_header->replyToMessage({});
} else {
_canReplaceMedia = false;
_canReplaceMedia = _canAddMedia = false;
_photoEditMedia = nullptr;
_header->replyToMessage(draft->reply);
if (_header->replyingToMessage()) {
@ -2931,7 +2940,7 @@ void ComposeControls::editMessage(not_null<HistoryItem*> item) {
}
bool ComposeControls::updateReplaceMediaButton() {
if (!_canReplaceMedia || !_regularWindow) {
if ((!_canReplaceMedia && !_canAddMedia) || !_regularWindow) {
const auto result = (_replaceMedia != nullptr);
_replaceMedia = nullptr;
return result;
@ -2940,7 +2949,7 @@ bool ComposeControls::updateReplaceMediaButton() {
}
_replaceMedia = std::make_unique<Ui::IconButton>(
_wrap.get(),
st::historyReplaceMedia);
_canReplaceMedia ? st::historyReplaceMedia : st::historyAddMedia);
const auto hideDuration = st::historyReplaceMedia.ripple.hideDuration;
_replaceMedia->setClickedCallback([=] {
base::call_delayed(hideDuration, _wrap.get(), [=] {

View file

@ -444,6 +444,7 @@ private:
FullMsgId _editingId;
std::shared_ptr<Data::PhotoMedia> _photoEditMedia;
bool _canReplaceMedia = false;
bool _canAddMedia = false;
std::unique_ptr<Controls::WebpageProcessor> _preview;

View file

@ -29,6 +29,7 @@ void MediaEditManager::start(
std::optional<bool> invertCaption) {
const auto media = item->media();
if (!media) {
cancel();
return;
}
_item = item;