From 0dd45de254bc7b9696323100e5e0d06bfe42b0ed Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 3 Nov 2022 16:29:22 +0400 Subject: [PATCH] Remember scroll state between topic openings. --- Telegram/SourceFiles/data/data_forum.cpp | 24 +++++++++++---- Telegram/SourceFiles/data/data_forum.h | 6 ++-- .../SourceFiles/data/data_forum_topic.cpp | 30 +++++++++++++++---- Telegram/SourceFiles/data/data_forum_topic.h | 6 ++++ Telegram/SourceFiles/editor/editor_crop.cpp | 6 ++++ .../SourceFiles/editor/photo_editor_common.h | 1 + .../editor/photo_editor_layer_widget.cpp | 7 ++++- .../editor/photo_editor_layer_widget.h | 4 +++ Telegram/SourceFiles/history/history.cpp | 5 +++- .../history/view/history_view_list_widget.cpp | 10 +++---- .../view/history_view_replies_section.cpp | 19 +++++++++--- .../view/history_view_replies_section.h | 2 ++ Telegram/SourceFiles/ui/special_buttons.cpp | 9 +++++- .../window/window_session_controller.cpp | 2 +- 14 files changed, 103 insertions(+), 28 deletions(-) diff --git a/Telegram/SourceFiles/data/data_forum.cpp b/Telegram/SourceFiles/data/data_forum.cpp index 53183dd26..a33937c1d 100644 --- a/Telegram/SourceFiles/data/data_forum.cpp +++ b/Telegram/SourceFiles/data/data_forum.cpp @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_unread_things.h" #include "main/main_session.h" #include "base/random.h" +#include "base/unixtime.h" #include "apiwrap.h" #include "lang/lang_keys.h" #include "core/application.h" @@ -319,7 +320,10 @@ ForumTopic *Forum::applyTopicAdded( MsgId rootId, const QString &title, int32 colorId, - DocumentId iconId) { + DocumentId iconId, + PeerId creatorId, + TimeId date, + bool my) { Expects(rootId != 0); const auto i = _topics.find(rootId); @@ -332,8 +336,10 @@ ForumTopic *Forum::applyTopicAdded( raw->applyTitle(title); raw->applyColorId(colorId); raw->applyIconId(iconId); + raw->applyCreator(creatorId); + raw->applyCreationDate(date); + raw->applyIsMy(my); if (!creating(rootId)) { - requestTopic(rootId); raw->addToChatList(FilterId(), topicsList()); _chatsListChanges.fire({}); } @@ -346,9 +352,14 @@ MsgId Forum::reserveCreatingId( DocumentId iconId) { const auto result = owner().nextLocalMessageId(); _creatingRootIds.emplace(result); - const auto topic = applyTopicAdded(result, title, colorId, iconId); - // Perhaps it will be created from some public channel name. - //topic->applyCreator(session().userPeerId()); + const auto topic = applyTopicAdded( + result, + title, + colorId, + iconId, + session().userPeerId(), + base::unixtime::now(), + true); return result; } @@ -419,7 +430,8 @@ ForumTopic *Forum::enforceTopicFor(MsgId rootId) { if (i != end(_topics)) { return i->second.get(); } - return applyTopicAdded(rootId, {}, {}, {}); + requestTopic(rootId); + return applyTopicAdded(rootId, {}, {}, {}, {}, {}, {}); } bool Forum::topicDeleted(MsgId rootId) const { diff --git a/Telegram/SourceFiles/data/data_forum.h b/Telegram/SourceFiles/data/data_forum.h index aed485e27..6d0a141a8 100644 --- a/Telegram/SourceFiles/data/data_forum.h +++ b/Telegram/SourceFiles/data/data_forum.h @@ -60,8 +60,10 @@ public: MsgId rootId, const QString &title, int32 colorId, - DocumentId iconId); - void applyTopicCreated(MsgId rootId, MsgId realId); + DocumentId iconId, + PeerId creatorId, + TimeId date, + bool my); void applyTopicDeleted(MsgId rootId); [[nodiscard]] ForumTopic *topicFor(MsgId rootId); [[nodiscard]] ForumTopic *enforceTopicFor(MsgId rootId); diff --git a/Telegram/SourceFiles/data/data_forum_topic.cpp b/Telegram/SourceFiles/data/data_forum_topic.cpp index 1b6ca4487..ae1a2757e 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.cpp +++ b/Telegram/SourceFiles/data/data_forum_topic.cpp @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "history/history_unread_things.h" #include "history/view/history_view_item_preview.h" +#include "history/view/history_view_replies_section.h" #include "main/main_session.h" #include "base/unixtime.h" #include "ui/painter.h" @@ -220,6 +221,13 @@ TimeId ForumTopic::creationDate() const { return _creationDate; } +not_null ForumTopic::listMemento() { + if (!_listMemento) { + _listMemento = std::make_unique(); + } + return _listMemento.get(); +} + bool ForumTopic::my() const { return (_flags & Flag::My); } @@ -286,7 +294,7 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) { Expects(_rootId == data.vid().v); applyCreator(peerFromMTP(data.vfrom_id())); - _creationDate = data.vdate().v; + applyCreationDate(data.vdate().v); applyTitle(qs(data.vtitle())); if (const auto iconId = data.vicon_emoji_id()) { @@ -312,11 +320,7 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) { _rootId, draft->c_draftMessage()); } - if (data.is_my()) { - _flags |= Flag::My; - } else { - _flags &= ~Flag::My; - } + applyIsMy(data.is_my()); setClosed(data.is_closed()); _replies->setInboxReadTill( @@ -335,6 +339,20 @@ void ForumTopic::applyCreator(PeerId creatorId) { } } +void ForumTopic::applyCreationDate(TimeId date) { + _creationDate = date; +} + +void ForumTopic::applyIsMy(bool my) { + if (my != this->my()) { + if (my) { + _flags |= Flag::My; + } else { + _flags &= ~Flag::My; + } + } +} + bool ForumTopic::closed() const { return _flags & Flag::Closed; } diff --git a/Telegram/SourceFiles/data/data_forum_topic.h b/Telegram/SourceFiles/data/data_forum_topic.h index 8d55661ee..86c2f7d02 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.h +++ b/Telegram/SourceFiles/data/data_forum_topic.h @@ -27,6 +27,7 @@ class Session; namespace HistoryView { class SendActionPainter; +class ListMemento; } // namespace HistoryView namespace Data { @@ -66,6 +67,8 @@ public: [[nodiscard]] PeerId creatorId() const; [[nodiscard]] TimeId creationDate() const; + [[nodiscard]] not_null listMemento(); + [[nodiscard]] bool my() const; [[nodiscard]] bool canWrite() const; [[nodiscard]] bool canSendPolls() const; @@ -117,6 +120,8 @@ public: [[nodiscard]] int32 colorId() const; void applyColorId(int32 colorId); void applyCreator(PeerId creatorId); + void applyCreationDate(TimeId date); + void applyIsMy(bool my); void applyItemAdded(not_null item); void applyItemRemoved(MsgId id); void maybeSetLastMessage(not_null item); @@ -169,6 +174,7 @@ private: const not_null _forum; const not_null _list; std::shared_ptr _replies; + std::unique_ptr _listMemento; std::shared_ptr _sendActionPainter; MsgId _rootId = 0; MsgId _lastKnownServerMessageId = 0; diff --git a/Telegram/SourceFiles/editor/editor_crop.cpp b/Telegram/SourceFiles/editor/editor_crop.cpp index f730984e0..9e3885a28 100644 --- a/Telegram/SourceFiles/editor/editor_crop.cpp +++ b/Telegram/SourceFiles/editor/editor_crop.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "editor/editor_crop.h" #include "styles/style_editor.h" +#include "styles/style_basic.h" +#include "styles/style_dialogs.h" namespace Editor { namespace { @@ -145,6 +147,10 @@ void Crop::setCropPaint(QRectF &&rect) { _painterPath.addRect(_innerRect); if (_data.cropType == EditorData::CropType::Ellipse) { _painterPath.addEllipse(_cropPaint); + } else if (_data.cropType == EditorData::CropType::RoundedRect) { + const auto radius = std::min(_cropPaint.width(), _cropPaint.height()) + * st::roundRadiusLarge / float64(st::defaultDialogRow.photoSize); + _painterPath.addRoundedRect(_cropPaint, radius, radius); } else { _painterPath.addRect(_cropPaint); } diff --git a/Telegram/SourceFiles/editor/photo_editor_common.h b/Telegram/SourceFiles/editor/photo_editor_common.h index 835819e47..b73512905 100644 --- a/Telegram/SourceFiles/editor/photo_editor_common.h +++ b/Telegram/SourceFiles/editor/photo_editor_common.h @@ -27,6 +27,7 @@ struct EditorData { enum class CropType { Rect, Ellipse, + RoundedRect, }; CropType cropType = CropType::Rect; diff --git a/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp b/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp index d2acfdd9d..23d53e9cc 100644 --- a/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_layer_widget.cpp @@ -67,6 +67,7 @@ void OpenWithPreparedFile( void PrepareProfilePhoto( not_null parent, not_null controller, + ImageRoundRadius radius, Fn &&doneCallback, QImage &&image) { const auto resizeToMinSize = [=]( @@ -119,7 +120,9 @@ void PrepareProfilePhoto( PhotoModifications{ .crop = std::move(crop) }, std::move(applyModifications), EditorData{ - .cropType = EditorData::CropType::Ellipse, + .cropType = (radius == ImageRoundRadius::Ellipse + ? EditorData::CropType::Ellipse + : EditorData::CropType::RoundedRect), .keepAspectRatio = true, }), Ui::LayerOption::KeepOther); } @@ -127,6 +130,7 @@ void PrepareProfilePhoto( void PrepareProfilePhotoFromFile( not_null parent, not_null controller, + ImageRoundRadius radius, Fn &&doneCallback) { const auto callback = [=, done = std::move(doneCallback)]( const FileDialog::OpenResult &result) mutable { @@ -142,6 +146,7 @@ void PrepareProfilePhotoFromFile( PrepareProfilePhoto( parent, controller, + radius, std::move(done), std::move(image)); }; diff --git a/Telegram/SourceFiles/editor/photo_editor_layer_widget.h b/Telegram/SourceFiles/editor/photo_editor_layer_widget.h index 44b226c9f..cce4a97d8 100644 --- a/Telegram/SourceFiles/editor/photo_editor_layer_widget.h +++ b/Telegram/SourceFiles/editor/photo_editor_layer_widget.h @@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "editor/photo_editor_common.h" #include "ui/image/image.h" +enum class ImageRoundRadius; + namespace Ui { struct PreparedFile; } // namespace Ui @@ -34,12 +36,14 @@ void OpenWithPreparedFile( void PrepareProfilePhoto( not_null parent, not_null controller, + ImageRoundRadius radius, Fn &&doneCallback, QImage &&image); void PrepareProfilePhotoFromFile( not_null parent, not_null controller, + ImageRoundRadius radius, Fn &&doneCallback); class PhotoEditor; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 51f4c6def..4437cac51 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -1199,7 +1199,10 @@ void History::applyServiceChanges( item->id, qs(data.vtitle()), data.vicon_color().v, - data.vicon_emoji_id().value_or(DocumentId())); + data.vicon_emoji_id().value_or(DocumentId()), + item->from()->id, + item->date(), + item->out()); } }, [&](const MTPDmessageActionTopicEdit &data) { if (const auto topic = item->topic()) { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index c22cfef31..10a7d442e 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1693,11 +1693,9 @@ QString ListWidget::elementAuthorRank(not_null view) { void ListWidget::saveState(not_null memento) { memento->setAroundPosition(_aroundPosition); - auto state = countScrollState(); - if (state.item) { - memento->setIdsLimit(_idsLimit); - memento->setScrollTopState(state); - } + const auto state = countScrollState(); + memento->setIdsLimit(state.item ? _idsLimit : 0); + memento->setScrollTopState(state); } void ListWidget::restoreState(not_null memento) { @@ -2346,7 +2344,7 @@ auto ListWidget::countScrollState() const -> ScrollTopState { if (_items.empty() || _visibleBottom == height()) { return { Data::MessagePosition(), 0 }; } - auto topItem = findItemByY(_visibleTop); + const auto topItem = findItemByY(_visibleTop); return { topItem->data()->position(), _visibleTop - itemTop(topItem) diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 2a78f8d17..f2afd1754 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -146,6 +146,13 @@ RepliesMemento::RepliesMemento( } } +void RepliesMemento::setFromTopic(not_null topic) { + _replies = topic->replies(); + if (!_list.aroundPosition()) { + _list = *topic->listMemento(); + } +} + void RepliesMemento::setReadInformation( MsgId inboxReadTillId, int unreadCount, @@ -384,10 +391,14 @@ RepliesWidget::~RepliesWidget() { base::take(_sendAction); session().api().saveCurrentDraftToCloud(); controller()->sendingAnimation().clear(); - if (_topic && _topic->creating()) { - _emptyPainter = nullptr; - _topic->discard(); - _topic = nullptr; + if (_topic) { + if (_topic->creating()) { + _emptyPainter = nullptr; + _topic->discard(); + _topic = nullptr; + } else { + _inner->saveState(_topic->listMemento()); + } } _history->owner().sendActionManager().repliesPainterRemoved( _history, diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.h b/Telegram/SourceFiles/history/view/history_view_replies_section.h index 214cc749f..3b5060e2a 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.h +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.h @@ -398,6 +398,8 @@ public: return _replies; } + void setFromTopic(not_null topic); + void setReplyReturns(const QVector &list) { _replyReturns = list; } diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp index a80267c1e..f2deb371a 100644 --- a/Telegram/SourceFiles/ui/special_buttons.cpp +++ b/Telegram/SourceFiles/ui/special_buttons.cpp @@ -59,6 +59,7 @@ bool IsCameraAvailable() { void CameraBox( not_null box, not_null controller, + PeerData *peer, Fn &&doneCallback) { using namespace Webrtc; @@ -87,6 +88,9 @@ void CameraBox( Editor::PrepareProfilePhoto( box, controller, + ((peer && peer->isForum()) + ? ImageRoundRadius::Large + : ImageRoundRadius::Ellipse), std::move(done), track->frame(FrameRequest()).mirrored(true, false)); }); @@ -295,6 +299,9 @@ void UserpicButton::choosePhotoLocally() { Editor::PrepareProfilePhotoFromFile( this, _window, + ((_peer && _peer->isForum()) + ? ImageRoundRadius::Large + : ImageRoundRadius::Ellipse), callback); })); }; @@ -304,7 +311,7 @@ void UserpicButton::choosePhotoLocally() { _menu = base::make_unique_q(this); _menu->addAction(tr::lng_attach_file(tr::now), chooseFile); _menu->addAction(tr::lng_attach_camera(tr::now), [=] { - _window->show(Box(CameraBox, _window, callback)); + _window->show(Box(CameraBox, _window, _peer, callback)); }); _menu->popup(QCursor::pos()); } diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index ad6aabef5..c7610d8ae 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -523,7 +523,7 @@ void SessionNavigation::showRepliesForMessage( history, rootId, commentId); - memento->setReplies(std::move(replies)); + memento->setFromTopic(topic); showSection(std::move(memento), params); return; }