Remember scroll state between topic openings.

This commit is contained in:
John Preston 2022-11-03 16:29:22 +04:00
parent d7f2385275
commit 0dd45de254
14 changed files with 103 additions and 28 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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<HistoryView::ListMemento*> ForumTopic::listMemento() {
if (!_listMemento) {
_listMemento = std::make_unique<HistoryView::ListMemento>();
}
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;
}

View File

@ -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<HistoryView::ListMemento*> 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<HistoryItem*> item);
void applyItemRemoved(MsgId id);
void maybeSetLastMessage(not_null<HistoryItem*> item);
@ -169,6 +174,7 @@ private:
const not_null<Forum*> _forum;
const not_null<Dialogs::MainList*> _list;
std::shared_ptr<RepliesList> _replies;
std::unique_ptr<HistoryView::ListMemento> _listMemento;
std::shared_ptr<HistoryView::SendActionPainter> _sendActionPainter;
MsgId _rootId = 0;
MsgId _lastKnownServerMessageId = 0;

View File

@ -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);
}

View File

@ -27,6 +27,7 @@ struct EditorData {
enum class CropType {
Rect,
Ellipse,
RoundedRect,
};
CropType cropType = CropType::Rect;

View File

@ -67,6 +67,7 @@ void OpenWithPreparedFile(
void PrepareProfilePhoto(
not_null<Ui::RpWidget*> parent,
not_null<Window::Controller*> controller,
ImageRoundRadius radius,
Fn<void(QImage &&image)> &&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<Ui::RpWidget*> parent,
not_null<Window::Controller*> controller,
ImageRoundRadius radius,
Fn<void(QImage &&image)> &&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));
};

View File

@ -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<Ui::RpWidget*> parent,
not_null<Window::Controller*> controller,
ImageRoundRadius radius,
Fn<void(QImage &&image)> &&doneCallback,
QImage &&image);
void PrepareProfilePhotoFromFile(
not_null<Ui::RpWidget*> parent,
not_null<Window::Controller*> controller,
ImageRoundRadius radius,
Fn<void(QImage &&image)> &&doneCallback);
class PhotoEditor;

View File

@ -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()) {

View File

@ -1693,11 +1693,9 @@ QString ListWidget::elementAuthorRank(not_null<const Element*> view) {
void ListWidget::saveState(not_null<ListMemento*> 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<ListMemento*> 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)

View File

@ -146,6 +146,13 @@ RepliesMemento::RepliesMemento(
}
}
void RepliesMemento::setFromTopic(not_null<Data::ForumTopic*> 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,

View File

@ -398,6 +398,8 @@ public:
return _replies;
}
void setFromTopic(not_null<Data::ForumTopic*> topic);
void setReplyReturns(const QVector<FullMsgId> &list) {
_replyReturns = list;
}

View File

@ -59,6 +59,7 @@ bool IsCameraAvailable() {
void CameraBox(
not_null<Ui::GenericBox*> box,
not_null<Window::Controller*> controller,
PeerData *peer,
Fn<void(QImage &&image)> &&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<Ui::PopupMenu>(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());
}

View File

@ -523,7 +523,7 @@ void SessionNavigation::showRepliesForMessage(
history,
rootId,
commentId);
memento->setReplies(std::move(replies));
memento->setFromTopic(topic);
showSection(std::move(memento), params);
return;
}