mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-25 04:38:23 +00:00
Save scroll top state to media memento.
This commit is contained in:
parent
f6ed3dff7f
commit
15cc4502b4
@ -150,7 +150,7 @@ infoLayerTopBar: InfoTopBar {
|
||||
}
|
||||
|
||||
infoMinimalWidth: 324px;
|
||||
infoDesiredWidth: 360px;
|
||||
infoDesiredWidth: 430px;
|
||||
infoMinimalLayerMargin: 48px;
|
||||
|
||||
infoTabs: SettingsSlider(defaultTabsSlider) {
|
||||
|
@ -57,6 +57,10 @@ ContentWidget::ContentWidget(
|
||||
}
|
||||
|
||||
void ContentWidget::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void ContentWidget::updateControlsGeometry() {
|
||||
auto newScrollTop = _scroll->scrollTop() + _topDelta;
|
||||
auto scrollGeometry = rect().marginsRemoved(
|
||||
QMargins(0, _scrollTopSkip, 0, 0));
|
||||
@ -113,6 +117,10 @@ Ui::RpWidget *ContentWidget::doSetInnerWidget(
|
||||
int desired) {
|
||||
inner->setVisibleTopBottom(top, bottom);
|
||||
}, _inner->lifetime());
|
||||
|
||||
_scrollTopSkip = scrollTopSkip;
|
||||
updateControlsGeometry();
|
||||
|
||||
return _inner;
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,7 @@ private:
|
||||
RpWidget *doSetInnerWidget(
|
||||
object_ptr<RpWidget> inner,
|
||||
int scrollTopSkip);
|
||||
void updateControlsGeometry();
|
||||
|
||||
const not_null<Window::Controller*> _controller;
|
||||
const not_null<PeerData*> _peer;
|
||||
|
@ -252,9 +252,11 @@ object_ptr<ListWidget> InnerWidget::setupList(
|
||||
}
|
||||
|
||||
void InnerWidget::saveState(not_null<Memento*> memento) {
|
||||
_list->saveState(memento);
|
||||
}
|
||||
|
||||
void InnerWidget::restoreState(not_null<Memento*> memento) {
|
||||
_list->restoreState(memento);
|
||||
}
|
||||
|
||||
rpl::producer<SelectedItems> InnerWidget::selectedListValue() const {
|
||||
|
@ -720,6 +720,12 @@ bool ListWidget::isMyItem(not_null<const HistoryItem*> item) const {
|
||||
return (_peer == peer || _peer == peer->migrateTo());
|
||||
}
|
||||
|
||||
bool ListWidget::isPossiblyMyId(FullMsgId fullId) const {
|
||||
return (fullId.channel != 0)
|
||||
? (_peer->isChannel() && _peer->bareId() == fullId.channel)
|
||||
: (!_peer->isChannel() || _peer->migrateFrom());
|
||||
}
|
||||
|
||||
bool ListWidget::isItemLayout(
|
||||
not_null<const HistoryItem*> item,
|
||||
BaseLayout *layout) const {
|
||||
@ -878,6 +884,29 @@ void ListWidget::markLayoutsStale() {
|
||||
}
|
||||
}
|
||||
|
||||
void ListWidget::saveState(not_null<Memento*> memento) {
|
||||
if (_universalAroundId != kDefaultAroundId) {
|
||||
memento->setAroundId(computeFullId(_universalAroundId));
|
||||
memento->setIdsLimit(_idsLimit);
|
||||
auto state = countScrollState();
|
||||
memento->setScrollTopItem(computeFullId(state.item));
|
||||
memento->setScrollTopShift(state.shift);
|
||||
}
|
||||
}
|
||||
|
||||
void ListWidget::restoreState(not_null<Memento*> memento) {
|
||||
if (auto limit = memento->idsLimit()) {
|
||||
auto wasAroundId = memento->aroundId();
|
||||
if (isPossiblyMyId(wasAroundId)) {
|
||||
_idsLimit = limit;
|
||||
_universalAroundId = GetUniversalId(wasAroundId);
|
||||
_scrollTopState.item = GetUniversalId(memento->scrollTopItem());
|
||||
_scrollTopState.shift = memento->scrollTopShift();
|
||||
refreshViewer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ListWidget::resizeGetHeight(int newWidth) {
|
||||
if (newWidth > 0) {
|
||||
for (auto §ion : _sections) {
|
||||
@ -887,7 +916,7 @@ int ListWidget::resizeGetHeight(int newWidth) {
|
||||
return recountHeight();
|
||||
}
|
||||
|
||||
auto ListWidget::findItemByPoint(QPoint point) -> FoundItem {
|
||||
auto ListWidget::findItemByPoint(QPoint point) const -> FoundItem {
|
||||
Expects(!_sections.empty());
|
||||
auto sectionIt = findSectionAfterTop(point.y());
|
||||
if (sectionIt == _sections.end()) {
|
||||
@ -920,7 +949,7 @@ auto ListWidget::findItemDetails(
|
||||
|
||||
auto ListWidget::foundItemInSection(
|
||||
const FoundItem &item,
|
||||
const Section §ion) -> FoundItem {
|
||||
const Section §ion) const -> FoundItem {
|
||||
return {
|
||||
item.layout,
|
||||
item.geometry.translated(0, section.top()),
|
||||
@ -941,7 +970,7 @@ void ListWidget::checkMoveToOtherViewer() {
|
||||
if (width() <= 0
|
||||
|| visibleHeight <= 0
|
||||
|| _sections.empty()
|
||||
|| _scrollTopId) {
|
||||
|| _scrollTopState.item) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -994,34 +1023,39 @@ void ListWidget::checkMoveToOtherViewer() {
|
||||
}
|
||||
}
|
||||
|
||||
void ListWidget::saveScrollState() {
|
||||
auto ListWidget::countScrollState() const -> ScrollTopState {
|
||||
if (_sections.empty()) {
|
||||
_scrollTopId = 0;
|
||||
_scrollTopShift = 0;
|
||||
return;
|
||||
return { 0, 0 };
|
||||
}
|
||||
auto topItem = findItemByPoint({ 0, _visibleTop });
|
||||
_scrollTopId = GetUniversalId(topItem.layout);
|
||||
_scrollTopShift = _visibleTop - topItem.geometry.y();
|
||||
return {
|
||||
GetUniversalId(topItem.layout),
|
||||
_visibleTop - topItem.geometry.y()
|
||||
};
|
||||
}
|
||||
|
||||
void ListWidget::saveScrollState() {
|
||||
if (!_scrollTopState.item) {
|
||||
_scrollTopState = countScrollState();
|
||||
}
|
||||
}
|
||||
|
||||
void ListWidget::restoreScrollState() {
|
||||
auto scrollTopId = base::take(_scrollTopId);
|
||||
auto scrollTopShift = base::take(_scrollTopShift);
|
||||
if (_sections.empty() || !scrollTopId) {
|
||||
if (_sections.empty() || !_scrollTopState.item) {
|
||||
return;
|
||||
}
|
||||
auto sectionIt = findSectionByItem(scrollTopId);
|
||||
auto sectionIt = findSectionByItem(_scrollTopState.item);
|
||||
if (sectionIt == _sections.end()) {
|
||||
--sectionIt;
|
||||
}
|
||||
auto item = foundItemInSection(
|
||||
sectionIt->findItemNearId(scrollTopId),
|
||||
sectionIt->findItemNearId(_scrollTopState.item),
|
||||
*sectionIt);
|
||||
auto newVisibleTop = item.geometry.y() + scrollTopShift;
|
||||
auto newVisibleTop = item.geometry.y() + _scrollTopState.shift;
|
||||
if (_visibleTop != newVisibleTop) {
|
||||
_scrollToRequests.fire_copy(newVisibleTop);
|
||||
}
|
||||
_scrollTopState = ScrollTopState();
|
||||
}
|
||||
|
||||
QMargins ListWidget::padding() const {
|
||||
|
@ -74,6 +74,9 @@ public:
|
||||
clearSelected();
|
||||
}
|
||||
|
||||
void saveState(not_null<Memento*> memento);
|
||||
void restoreState(not_null<Memento*> memento);
|
||||
|
||||
~ListWidget();
|
||||
|
||||
protected:
|
||||
@ -150,6 +153,10 @@ private:
|
||||
Touch,
|
||||
Other,
|
||||
};
|
||||
struct ScrollTopState {
|
||||
UniversalMsgId item = 0;
|
||||
int shift = 0;
|
||||
};
|
||||
|
||||
void start();
|
||||
int recountHeight();
|
||||
@ -160,6 +167,7 @@ private:
|
||||
bool isItemLayout(
|
||||
not_null<const HistoryItem*> item,
|
||||
BaseLayout *layout) const;
|
||||
bool isPossiblyMyId(FullMsgId fullId) const;
|
||||
void repaintItem(const HistoryItem *item);
|
||||
void repaintItem(UniversalMsgId msgId);
|
||||
void repaintItem(const BaseLayout *item);
|
||||
@ -229,13 +237,14 @@ private:
|
||||
std::vector<Section>::const_iterator findSectionAfterBottom(
|
||||
std::vector<Section>::const_iterator from,
|
||||
int bottom) const;
|
||||
FoundItem findItemByPoint(QPoint point);
|
||||
FoundItem findItemByPoint(QPoint point) const;
|
||||
base::optional<FoundItem> findItemById(UniversalMsgId universalId);
|
||||
base::optional<FoundItem> findItemDetails(BaseLayout *item);
|
||||
FoundItem foundItemInSection(
|
||||
const FoundItem &item,
|
||||
const Section §ion);
|
||||
const Section §ion) const;
|
||||
|
||||
ScrollTopState countScrollState() const;
|
||||
void saveScrollState();
|
||||
void restoreScrollState();
|
||||
|
||||
@ -268,7 +277,8 @@ private:
|
||||
Type _type = Type::Photo;
|
||||
|
||||
static constexpr auto kMinimalIdsLimit = 16;
|
||||
UniversalMsgId _universalAroundId = (ServerMaxMsgId - 1);
|
||||
static constexpr auto kDefaultAroundId = (ServerMaxMsgId - 1);
|
||||
UniversalMsgId _universalAroundId = kDefaultAroundId;
|
||||
int _idsLimit = kMinimalIdsLimit;
|
||||
SharedMediaMergedSlice _slice;
|
||||
|
||||
@ -277,8 +287,7 @@ private:
|
||||
|
||||
int _visibleTop = 0;
|
||||
int _visibleBottom = 0;
|
||||
UniversalMsgId _scrollTopId = 0;
|
||||
int _scrollTopShift = 0;
|
||||
ScrollTopState _scrollTopState;
|
||||
rpl::event_stream<int> _scrollToRequests;
|
||||
|
||||
MouseAction _mouseAction = MouseAction::None;
|
||||
|
@ -104,7 +104,6 @@ void Widget::saveState(not_null<Memento*> memento) {
|
||||
|
||||
void Widget::restoreState(not_null<Memento*> memento) {
|
||||
_inner->restoreState(memento);
|
||||
scrollTopRestore(memento->scrollTop());
|
||||
}
|
||||
|
||||
} // namespace Media
|
||||
|
@ -52,8 +52,37 @@ public:
|
||||
return _type;
|
||||
}
|
||||
|
||||
void setAroundId(FullMsgId aroundId) {
|
||||
_aroundId = aroundId;
|
||||
}
|
||||
FullMsgId aroundId() const {
|
||||
return _aroundId;
|
||||
}
|
||||
void setIdsLimit(int limit) {
|
||||
_idsLimit = limit;
|
||||
}
|
||||
int idsLimit() const {
|
||||
return _idsLimit;
|
||||
}
|
||||
void setScrollTopItem(FullMsgId item) {
|
||||
_scrollTopItem = item;
|
||||
}
|
||||
FullMsgId scrollTopItem() const {
|
||||
return _scrollTopItem;
|
||||
}
|
||||
void setScrollTopShift(int shift) {
|
||||
_scrollTopShift = shift;
|
||||
}
|
||||
int scrollTopShift() const {
|
||||
return _scrollTopShift;
|
||||
}
|
||||
|
||||
private:
|
||||
Type _type = Type::Photo;
|
||||
FullMsgId _aroundId;
|
||||
int _idsLimit = 0;
|
||||
FullMsgId _scrollTopItem;
|
||||
int _scrollTopShift = 0;;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user