Fix scroll state management in Downloads.

This commit is contained in:
John Preston 2022-02-27 20:19:16 +03:00
parent bff8313a37
commit a61048d219
19 changed files with 139 additions and 37 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1020 B

View File

@ -878,14 +878,14 @@ SetupChannelBox::SetupChannelBox(
(channel->isMegagroup()
? tr::lng_create_public_group_about
: tr::lng_create_public_channel_about)(tr::now),
_defaultOptions,
kDefaultTextOptions,
_aboutPublicWidth)
, _aboutPrivate(
st::defaultTextStyle,
(channel->isMegagroup()
? tr::lng_create_private_group_about
: tr::lng_create_private_channel_about)(tr::now),
_defaultOptions,
kDefaultTextOptions,
_aboutPublicWidth)
, _link(
this,

View File

@ -327,4 +327,6 @@ downloadLoadingLeft: 15px;
downloadLoadingSize: 24px;
downloadLoadingLine: 2px;
downloadLoadedSize: 30px;
downloadIconDocument: icon {{ "history_file_document", windowFgActive }};
downloadIconDocument: icon {{ "dialogs/dialogs_downloads", windowFgActive }};
downloadIconSize: 16px;
downloadIconSizeDone: 20px;

View File

@ -504,8 +504,6 @@ void InnerWidget::clearAndRequestLog() {
}
void InnerWidget::updateEmptyText() {
auto options = _defaultOptions;
options.flags |= TextParseMarkdown;
auto hasSearch = !_searchQuery.isEmpty();
auto hasFilter = (_filter.flags != 0) || !_filter.allUsers;
auto text = Ui::Text::Semibold((hasSearch || hasFilter)
@ -522,7 +520,7 @@ void InnerWidget::updateEmptyText() {
? tr::lng_admin_log_no_events_text(tr::now)
: tr::lng_admin_log_no_events_text_channel(tr::now);
text.text.append(qstr("\n\n") + description);
_emptyText.setMarkedText(st::defaultTextStyle, text, options);
_emptyText.setMarkedText(st::defaultTextStyle, text);
}
QString InnerWidget::tooltipText() const {

View File

@ -524,7 +524,7 @@ ReplyKeyboard::ReplyKeyboard(
button.text.setText(
_st->textStyle(),
TextUtilities::SingleLine(text),
_textPlainOptions);
kPlainTextOptions);
button.characters = text.isEmpty() ? 1 : text.size();
newRow.push_back(std::move(button));
}

View File

@ -56,9 +56,7 @@ void EmptyListBubbleWidget::paintEvent(QPaintEvent *e) {
void EmptyListBubbleWidget::setText(
const TextWithEntities &textWithEntities) {
auto options = _defaultOptions;
options.flags |= TextParseMarkdown;
_text.setMarkedText(st::defaultTextStyle, textWithEntities, options);
_text.setMarkedText(st::defaultTextStyle, textWithEntities);
updateGeometry(size());
}

View File

@ -386,16 +386,49 @@ QString Provider::showInFolderPath(
return (i != end(_elements)) ? i->path : QString();
}
int64 Provider::scrollTopStatePosition(not_null<HistoryItem*> item) {
const auto i = ranges::find(_elements, item, &Element::item);
return (i != end(_elements)) ? i->started : 0;
}
HistoryItem *Provider::scrollTopStateItem(ListScrollTopState state) {
if (!state.position) {
return _elements.empty() ? nullptr : _elements.back().item.get();
}
const auto i = ranges::lower_bound(
_elements,
state.position,
ranges::less(),
&Element::started);
return (i != end(_elements))
? i->item.get()
: _elements.empty()
? nullptr
: _elements.back().item.get();
}
void Provider::saveState(
not_null<Media::Memento*> memento,
ListScrollTopState scrollState) {
if (!_elements.empty() && scrollState.item) {
memento->setAroundId({ PeerId(), 1 });
memento->setScrollTopItem(scrollState.item->globalId());
memento->setScrollTopItemPosition(scrollState.position);
memento->setScrollTopShift(scrollState.shift);
}
}
void Provider::restoreState(
not_null<Media::Memento*> memento,
Fn<void(ListScrollTopState)> restoreScrollState) {
if (memento->aroundId() == FullMsgId(PeerId(), 1)) {
restoreScrollState({
.position = memento->scrollTopItemPosition(),
.item = MessageByGlobalId(memento->scrollTopItem()),
.shift = memento->scrollTopShift(),
});
refreshViewer();
}
}
} // namespace Info::Downloads

View File

@ -70,6 +70,10 @@ public:
not_null<const HistoryItem*> item,
not_null<DocumentData*> document) override;
int64 scrollTopStatePosition(not_null<HistoryItem*> item) override;
HistoryItem *scrollTopStateItem(
Media::ListScrollTopState state) override;
void saveState(
not_null<Media::Memento*> memento,
Media::ListScrollTopState scrollState) override;

View File

@ -59,6 +59,7 @@ struct ListContext {
};
struct ListScrollTopState {
int64 position = 0; // ListProvider-specific.
HistoryItem *item = nullptr;
int shift = 0;
};
@ -157,6 +158,10 @@ public:
not_null<const HistoryItem*> item,
not_null<DocumentData*> document) = 0;
[[nodiscard]] virtual int64 scrollTopStatePosition(
not_null<HistoryItem*> item) = 0;
[[nodiscard]] virtual HistoryItem *scrollTopStateItem(
ListScrollTopState state) = 0;
virtual void saveState(
not_null<Memento*> memento,
ListScrollTopState scrollState) = 0;

View File

@ -163,7 +163,7 @@ void ListWidget::start() {
if (_controller->isDownloads()) {
_provider->refreshViewer();
} else {
subscribeToSession(&session(), lifetime());
trackSession(&session());
_controller->mediaSourceQueryValue(
) | rpl::start_with_next([this] {
@ -482,6 +482,7 @@ bool ListWidget::preventAutoHide() const {
void ListWidget::saveState(not_null<Memento*> memento) {
_provider->saveState(memento, countScrollState());
_trackedSessions.clear();
}
void ListWidget::restoreState(not_null<Memento*> memento) {
@ -655,12 +656,14 @@ void ListWidget::clearHeavyItems() {
}
ListScrollTopState ListWidget::countScrollState() const {
if (_sections.empty()) {
if (_sections.empty() || _visibleTop <= 0) {
return {};
}
const auto topItem = findItemByPoint({ st::infoMediaSkip, _visibleTop });
const auto item = topItem.layout->getItem();
return {
.item = topItem.layout->getItem(),
.position = _provider->scrollTopStatePosition(item),
.item = item,
.shift = _visibleTop - topItem.geometry.y(),
};
}
@ -672,16 +675,22 @@ void ListWidget::saveScrollState() {
}
void ListWidget::restoreScrollState() {
if (_sections.empty() || !_scrollTopState.item) {
if (_sections.empty() || !_scrollTopState.position) {
return;
}
_scrollTopState.item = _provider->scrollTopStateItem(_scrollTopState);
if (!_scrollTopState.item) {
return;
}
auto sectionIt = findSectionByItem(_scrollTopState.item);
if (sectionIt == _sections.end()) {
--sectionIt;
}
auto item = foundItemInSection( // #TODO downloads
sectionIt->findItemNearId(GetUniversalId(_scrollTopState.item)),
*sectionIt);
const auto found = sectionIt->findItemByItem(_scrollTopState.item);
if (!found) {
return;
}
auto item = foundItemInSection(*found, *sectionIt);
auto newVisibleTop = item.geometry.y() + _scrollTopState.shift;
if (_visibleTop != newVisibleTop) {
_scrollToRequests.fire_copy(newVisibleTop);
@ -1080,7 +1089,9 @@ void ListWidget::deleteItems(SelectedItems &&items, Fn<void()> confirmed) {
return item.globalId;
}) | ranges::to_vector;
Core::App().downloadManager().deleteFiles(ids);
confirmed();
if (confirmed) {
confirmed();
}
};
setActionBoxWeak(window->show(Box<Ui::ConfirmBox>(
phrase,

View File

@ -511,6 +511,21 @@ void Provider::applyDragSelection(
}
}
int64 Provider::scrollTopStatePosition(not_null<HistoryItem*> item) {
return GetUniversalId(item).bare;
}
HistoryItem *Provider::scrollTopStateItem(ListScrollTopState state) {
if (state.item && _slice.indexOf(state.item->fullId())) {
return state.item;
} else if (const auto id = _slice.nearest(state.position)) {
if (const auto item = _controller->session().data().message(*id)) {
return item;
}
}
return state.item;
}
void Provider::saveState(
not_null<Memento*> memento,
ListScrollTopState scrollState) {
@ -518,6 +533,7 @@ void Provider::saveState(
memento->setAroundId(computeFullId(_universalAroundId));
memento->setIdsLimit(_idsLimit);
memento->setScrollTopItem(scrollState.item->globalId());
memento->setScrollTopItemPosition(scrollState.position);
memento->setScrollTopShift(scrollState.shift);
}
}
@ -531,6 +547,7 @@ void Provider::restoreState(
_idsLimit = limit;
_universalAroundId = GetUniversalId(wasAroundId);
restoreScrollState({
.position = memento->scrollTopItemPosition(),
.item = MessageByGlobalId(memento->scrollTopItem()),
.shift = memento->scrollTopShift(),
});

View File

@ -63,6 +63,8 @@ public:
not_null<const HistoryItem*> item,
not_null<DocumentData*> document) override;
int64 scrollTopStatePosition(not_null<HistoryItem*> item) override;
HistoryItem *scrollTopStateItem(ListScrollTopState state) override;
void saveState(
not_null<Memento*> memento,
ListScrollTopState scrollState) override;

View File

@ -34,9 +34,9 @@ public:
not_null<Controller*> controller,
const QRect &geometry) override;
Section section() const override;
[[nodiscard]] Section section() const override;
Type type() const {
[[nodiscard]] Type type() const {
return _type;
}
@ -44,32 +44,38 @@ public:
void setAroundId(FullMsgId aroundId) {
_aroundId = aroundId;
}
FullMsgId aroundId() const {
[[nodiscard]] FullMsgId aroundId() const {
return _aroundId;
}
void setIdsLimit(int limit) {
_idsLimit = limit;
}
int idsLimit() const {
[[nodiscard]] int idsLimit() const {
return _idsLimit;
}
void setScrollTopItem(GlobalMsgId item) {
_scrollTopItem = item;
}
GlobalMsgId scrollTopItem() const {
[[nodiscard]] GlobalMsgId scrollTopItem() const {
return _scrollTopItem;
}
void setScrollTopItemPosition(int64 position) {
_scrollTopItemPosition = position;
}
[[nodiscard]] int64 scrollTopItemPosition() const {
return _scrollTopItemPosition;
}
void setScrollTopShift(int shift) {
_scrollTopShift = shift;
}
int scrollTopShift() const {
[[nodiscard]] int scrollTopShift() const {
return _scrollTopShift;
}
void setSearchState(SearchState &&state) {
_searchState = std::move(state);
}
SearchState searchState() {
[[nodiscard]] SearchState searchState() {
return std::move(_searchState);
}
@ -77,6 +83,7 @@ private:
Type _type = Type::Photo;
FullMsgId _aroundId;
int _idsLimit = 0;
int64 _scrollTopItemPosition = 0;
GlobalMsgId _scrollTopItem;
int _scrollTopShift = 0;
SearchState _searchState;

View File

@ -189,7 +189,7 @@ void ConfirmBox::init(const QString &text) {
_text.setText(
st::boxLabelStyle,
text,
_informative ? kInformBoxTextOptions : _textPlainOptions);
_informative ? kInformBoxTextOptions : kPlainTextOptions);
}
void ConfirmBox::init(const TextWithEntities &text) {

View File

@ -39,6 +39,12 @@ DownloadBar::DownloadBar(
paint(p, clip);
}, lifetime());
style::PaletteChanged(
) | rpl::start_with_next([=] {
refreshIcon();
}, lifetime());
refreshIcon();
_progress.value(
) | rpl::start_with_next([=](const DownloadBarProgress &progress) {
refreshInfo(progress);
@ -56,7 +62,8 @@ void DownloadBar::show(DownloadBarContent &&content) {
_radial.start(computeProgress());
}
_content = content;
_title.setMarkedText(st::defaultTextStyle,
_title.setMarkedText(
st::defaultTextStyle,
(content.count > 1
? Ui::Text::Bold(
tr::lng_profile_files(tr::now, lt_count, content.count))
@ -64,8 +71,24 @@ void DownloadBar::show(DownloadBarContent &&content) {
refreshInfo(_progress.current());
}
void DownloadBar::refreshIcon() {
_documentIconOriginal = st::downloadIconDocument.instance(
st::windowFgActive->c,
style::kScaleMax / style::DevicePixelRatio());
const auto make = [&](int size) {
auto result = _documentIconOriginal.scaledToWidth(
size * style::DevicePixelRatio(),
Qt::SmoothTransformation);
result.setDevicePixelRatio(style::DevicePixelRatio());
return result;
};
_documentIcon = make(st::downloadIconSize);
_documentIconDone = make(st::downloadIconSizeDone);
}
void DownloadBar::refreshInfo(const DownloadBarProgress &progress) {
_info.setMarkedText(st::downloadInfoStyle,
_info.setMarkedText(
st::downloadInfoStyle,
(progress.ready < progress.total
? Text::WithEntities(
FormatDownloadText(progress.ready, progress.total))
@ -146,12 +169,10 @@ void DownloadBar::paint(Painter &p, QRect clip) {
p.setOpacity(1.);
}
}
p.save();
p.translate(full.center());
p.scale(0.6, 0.6);
p.translate(-full.center());
st::downloadIconDocument.paintInCenter(p, full);
p.restore();
p.drawImage(
full.x() + (full.width() - st::downloadIconSize) / 2,
full.y() + (full.height() - st::downloadIconSize) / 2,
_documentIcon);
}
const auto minleft = std::min(

View File

@ -49,6 +49,7 @@ public:
private:
void paint(Painter &p, QRect clip);
void refreshIcon();
void refreshInfo(const DownloadBarProgress &progress);
void radialAnimationCallback(crl::time now);
[[nodiscard]] float64 computeProgress() const;
@ -57,6 +58,9 @@ private:
PlainShadow _shadow;
DownloadBarContent _content;
rpl::variable<DownloadBarProgress> _progress;
QImage _documentIconOriginal;
QImage _documentIcon;
QImage _documentIconDone;
Text::String _title;
Text::String _info;
RadialAnimation _radial;

@ -1 +1 @@
Subproject commit bd7c4ee06d7292fddf5f4dbd2249efd4d7bc8e85
Subproject commit 5214f96bbafa1d879fca39c3374cb182687084c8