From f89aeb6ad4819fb0d6417d60bae593fa5c630806 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 10 Oct 2024 18:20:10 +0400 Subject: [PATCH] Implement text -> media message editing. --- .../SourceFiles/boxes/edit_caption_box.cpp | 9 ++++--- .../chat_helpers/chat_helpers.style | 7 ++++++ Telegram/SourceFiles/history/history_item.cpp | 8 +++--- Telegram/SourceFiles/history/history_item.h | 1 + .../SourceFiles/history/history_widget.cpp | 25 +++++++++++++------ Telegram/SourceFiles/history/history_widget.h | 1 + .../history_view_compose_controls.cpp | 23 +++++++++++------ .../controls/history_view_compose_controls.h | 1 + ...istory_view_compose_media_edit_manager.cpp | 1 + 9 files changed, 55 insertions(+), 21 deletions(-) diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 96d8fa782..f6e48b221 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -238,7 +238,7 @@ EditCaptionBox::EditCaptionBox( Fn saved) : _controller(controller) , _historyItem(item) -, _isAllowedEditMedia(item->media() && item->media()->allowsEditMedia()) +, _isAllowedEditMedia(item->allowsEditMedia()) , _albumType(ComputeAlbumType(item)) , _controls(base::make_unique_q(this)) , _scroll(base::make_unique_q(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()); diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style index 25e4852a6..a7da478ef 100644 --- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style +++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style @@ -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); diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index ec57dee50..ddb539d82 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -1470,12 +1470,10 @@ void HistoryItem::returnSavedMedia() { } void HistoryItem::savePreviousMedia() { - Expects(_media != nullptr); - AddComponents(HistoryMessageSavedMediaData::Bit()); const auto data = Get(); 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() diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index bab7f4d7c..169295c92 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -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; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 6036cd685..a6c6450e7 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -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()) diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 17e836beb..ec06c0bd6 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -662,6 +662,7 @@ private: MsgId _editMsgId = 0; std::shared_ptr _photoEditMedia; bool _canReplaceMedia = false; + bool _canAddMedia = false; HistoryView::MediaEditManager _mediaEditManager; HistoryItem *_replyEditMsg = nullptr; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 4314f738c..acef28096 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -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 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( _wrap.get(), - st::historyReplaceMedia); + _canReplaceMedia ? st::historyReplaceMedia : st::historyAddMedia); const auto hideDuration = st::historyReplaceMedia.ripple.hideDuration; _replaceMedia->setClickedCallback([=] { base::call_delayed(hideDuration, _wrap.get(), [=] { diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h index 91e7e9d27..f1da1fa6e 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h @@ -444,6 +444,7 @@ private: FullMsgId _editingId; std::shared_ptr _photoEditMedia; bool _canReplaceMedia = false; + bool _canAddMedia = false; std::unique_ptr _preview; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_media_edit_manager.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_media_edit_manager.cpp index 35fbc2134..45ababebc 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_media_edit_manager.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_media_edit_manager.cpp @@ -29,6 +29,7 @@ void MediaEditManager::start( std::optional invertCaption) { const auto media = item->media(); if (!media) { + cancel(); return; } _item = item;