mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Show downloaded files in Downloads.
This commit is contained in:
parent
1f2eba9dc9
commit
3425dc027c
12 changed files with 257 additions and 83 deletions
|
@ -1949,7 +1949,8 @@ void GroupCall::applySelfUpdate(const MTPDgroupCallParticipant &data) {
|
|||
}
|
||||
return;
|
||||
} else if (data.vsource().v != _joinState.ssrc) {
|
||||
if (!_mySsrcs.contains(data.vsource().v)) {
|
||||
const auto ssrc = uint32(data.vsource().v);
|
||||
if (!_mySsrcs.contains(ssrc)) {
|
||||
// I joined from another device, hangup.
|
||||
LOG(("Call Info: "
|
||||
"Hangup after '!left' with ssrc %1, my %2."
|
||||
|
|
|
@ -13,10 +13,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_changes.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_message.h"
|
||||
#include "core/application.h"
|
||||
#include "ui/controls/download_bar.h"
|
||||
|
||||
|
@ -30,7 +32,7 @@ constexpr auto ByItem = [](const auto &entry) {
|
|||
return entry.object.item;
|
||||
} else {
|
||||
const auto resolved = entry.object.get();
|
||||
return resolved ? resolved->item : nullptr;
|
||||
return resolved ? resolved->item.get() : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -87,6 +89,17 @@ void DownloadManager::trackSession(not_null<Main::Session*> session) {
|
|||
}, data.lifetime);
|
||||
}
|
||||
|
||||
int64 DownloadManager::computeNextStarted() {
|
||||
const auto now = base::unixtime::now();
|
||||
if (_lastStartedBase != now) {
|
||||
_lastStartedBase = now;
|
||||
_lastStartedAdded = 0;
|
||||
} else {
|
||||
++_lastStartedAdded;
|
||||
}
|
||||
return int64(_lastStartedBase) * 1000 + _lastStartedAdded;
|
||||
}
|
||||
|
||||
void DownloadManager::addLoading(DownloadObject object) {
|
||||
Expects(object.item != nullptr);
|
||||
Expects(object.document || object.photo);
|
||||
|
@ -109,7 +122,11 @@ void DownloadManager::addLoading(DownloadObject object) {
|
|||
? object.document->size
|
||||
: object.photo->imageByteSize(PhotoSize::Large);
|
||||
|
||||
data.downloading.push_back({ .object = object, .total = size });
|
||||
data.downloading.push_back({
|
||||
.object = object,
|
||||
.started = computeNextStarted(),
|
||||
.total = size,
|
||||
});
|
||||
_loading.emplace(item);
|
||||
_loadingProgress = DownloadProgress{
|
||||
.ready = _loadingProgress.current().ready,
|
||||
|
@ -181,6 +198,7 @@ void DownloadManager::addLoaded(
|
|||
.object = std::make_unique<DownloadObject>(object),
|
||||
});
|
||||
_loaded.emplace(item);
|
||||
_loadedAdded.fire(&data.downloaded.back());
|
||||
|
||||
const auto i = ranges::find(data.downloading, item, ByItem);
|
||||
if (i != end(data.downloading)) {
|
||||
|
@ -208,11 +226,15 @@ void DownloadManager::addLoaded(
|
|||
}
|
||||
|
||||
auto DownloadManager::loadingList() const
|
||||
-> ranges::any_view<DownloadingId, ranges::category::input> {
|
||||
-> ranges::any_view<const DownloadingId*, ranges::category::input> {
|
||||
return ranges::views::all(
|
||||
_sessions
|
||||
) | ranges::views::transform([=](const auto &pair) {
|
||||
return ranges::views::all(pair.second.downloading);
|
||||
return ranges::views::all(
|
||||
pair.second.downloading
|
||||
) | ranges::views::transform([](const DownloadingId &id) {
|
||||
return &id;
|
||||
});
|
||||
}) | ranges::views::join;
|
||||
}
|
||||
|
||||
|
@ -239,6 +261,31 @@ void DownloadManager::clearLoading() {
|
|||
}
|
||||
}
|
||||
|
||||
auto DownloadManager::loadedList() const
|
||||
-> ranges::any_view<const DownloadedId*, ranges::category::input> {
|
||||
return ranges::views::all(
|
||||
_sessions
|
||||
) | ranges::views::transform([=](const auto &pair) {
|
||||
return ranges::views::all(
|
||||
pair.second.downloaded
|
||||
) | ranges::views::filter([](const DownloadedId &id) {
|
||||
return (id.object != nullptr);
|
||||
}) | ranges::views::transform([](const DownloadedId &id) {
|
||||
return &id;
|
||||
});
|
||||
}) | ranges::views::join;
|
||||
}
|
||||
|
||||
auto DownloadManager::loadedAdded() const
|
||||
-> rpl::producer<not_null<const DownloadedId*>> {
|
||||
return _loadedAdded.events();
|
||||
}
|
||||
|
||||
auto DownloadManager::loadedRemoved() const
|
||||
-> rpl::producer<not_null<const HistoryItem*>> {
|
||||
return _loadedRemoved.events();
|
||||
}
|
||||
|
||||
void DownloadManager::remove(
|
||||
SessionData &data,
|
||||
std::vector<DownloadingId>::iterator i) {
|
||||
|
@ -271,16 +318,14 @@ void DownloadManager::cancel(
|
|||
void DownloadManager::changed(not_null<const HistoryItem*> item) {
|
||||
if (_loaded.contains(item)) {
|
||||
auto &data = sessionData(item);
|
||||
const auto i = ranges::find(data.downloaded, item, ByItem);
|
||||
const auto i = ranges::find(data.downloaded, item.get(), ByItem);
|
||||
Assert(i != end(data.downloaded));
|
||||
|
||||
const auto media = item->media();
|
||||
const auto photo = media ? media->photo() : nullptr;
|
||||
const auto document = media ? media->document() : nullptr;
|
||||
if (i->object->photo != photo || i->object->document != document) {
|
||||
*i->object = DownloadObject();
|
||||
|
||||
_loaded.remove(item);
|
||||
detach(*i);
|
||||
}
|
||||
}
|
||||
if (_loading.contains(item) || _loadingDone.contains(item)) {
|
||||
|
@ -291,11 +336,9 @@ void DownloadManager::changed(not_null<const HistoryItem*> item) {
|
|||
void DownloadManager::removed(not_null<const HistoryItem*> item) {
|
||||
if (_loaded.contains(item)) {
|
||||
auto &data = sessionData(item);
|
||||
const auto i = ranges::find(data.downloaded, item, ByItem);
|
||||
const auto i = ranges::find(data.downloaded, item.get(), ByItem);
|
||||
Assert(i != end(data.downloaded));
|
||||
*i->object = DownloadObject();
|
||||
|
||||
_loaded.remove(item);
|
||||
detach(*i);
|
||||
}
|
||||
if (_loading.contains(item) || _loadingDone.contains(item)) {
|
||||
auto &data = sessionData(item);
|
||||
|
@ -310,6 +353,62 @@ void DownloadManager::removed(not_null<const HistoryItem*> item) {
|
|||
}
|
||||
}
|
||||
|
||||
not_null<HistoryItem*> DownloadManager::generateItem(
|
||||
const DownloadObject &object) {
|
||||
Expects(object.document || object.photo);
|
||||
|
||||
const auto session = object.document
|
||||
? &object.document->session()
|
||||
: &object.photo->session();
|
||||
const auto fromId = object.item
|
||||
? object.item->from()->id
|
||||
: session->userPeerId();
|
||||
const auto history = object.item
|
||||
? object.item->history()
|
||||
: session->data().history(session->user());
|
||||
const auto flags = MessageFlag::FakeHistoryItem;
|
||||
const auto replyTo = MsgId();
|
||||
const auto viaBotId = UserId();
|
||||
const auto groupedId = uint64();
|
||||
const auto date = base::unixtime::now();
|
||||
const auto postAuthor = QString();
|
||||
const auto caption = TextWithEntities();
|
||||
const auto make = [&](const auto media) {
|
||||
return history->makeMessage(
|
||||
history->nextNonHistoryEntryId(),
|
||||
flags,
|
||||
replyTo,
|
||||
viaBotId,
|
||||
date,
|
||||
fromId,
|
||||
QString(),
|
||||
media,
|
||||
caption,
|
||||
HistoryMessageMarkupData());
|
||||
};
|
||||
const auto result = object.document
|
||||
? make(object.document)
|
||||
: make(object.photo);
|
||||
_generated.emplace(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void DownloadManager::detach(DownloadedId &id) {
|
||||
Expects(id.object != nullptr);
|
||||
Expects(_loaded.contains(id.object->item));
|
||||
Expects(!_generated.contains(id.object->item));
|
||||
|
||||
// Maybe generate new document?
|
||||
const auto was = id.object->item;
|
||||
const auto now = generateItem(*id.object);
|
||||
_loaded.remove(was);
|
||||
_loaded.emplace(now);
|
||||
id.object->item = now;
|
||||
|
||||
_loadedRemoved.fire_copy(was);
|
||||
_loadedAdded.fire_copy(&id);
|
||||
}
|
||||
|
||||
DownloadManager::SessionData &DownloadManager::sessionData(
|
||||
not_null<Main::Session*> session) {
|
||||
const auto i = _sessions.find(session);
|
||||
|
@ -357,13 +456,13 @@ rpl::producer<Ui::DownloadBarContent> MakeDownloadBarContent() {
|
|||
manager.loadingListChanges() | rpl::to_empty
|
||||
) | rpl::map([=, &manager] {
|
||||
auto result = Ui::DownloadBarContent();
|
||||
for (const auto &id : manager.loadingList()) {
|
||||
for (const auto id : manager.loadingList()) {
|
||||
if (result.singleName.isEmpty()) {
|
||||
result.singleName = id.object.document->filename();
|
||||
result.singleName = id->object.document->filename();
|
||||
result.singleThumbnail = QImage();
|
||||
}
|
||||
++result.count;
|
||||
if (id.done) {
|
||||
if (id->done) {
|
||||
++result.done;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ inline constexpr bool operator==(
|
|||
}
|
||||
|
||||
struct DownloadObject {
|
||||
HistoryItem *item = nullptr;
|
||||
not_null<HistoryItem*> item;
|
||||
DocumentData *document = nullptr;
|
||||
PhotoData *photo = nullptr;
|
||||
};
|
||||
|
@ -82,12 +82,19 @@ public:
|
|||
DownloadDate started);
|
||||
|
||||
[[nodiscard]] auto loadingList() const
|
||||
-> ranges::any_view<DownloadingId, ranges::category::input>;
|
||||
-> ranges::any_view<const DownloadingId*, ranges::category::input>;
|
||||
[[nodiscard]] DownloadProgress loadingProgress() const;
|
||||
[[nodiscard]] rpl::producer<> loadingListChanges() const;
|
||||
[[nodiscard]] auto loadingProgressValue() const
|
||||
-> rpl::producer<DownloadProgress>;
|
||||
|
||||
[[nodiscard]] auto loadedList() const
|
||||
-> ranges::any_view<const DownloadedId*, ranges::category::input>;
|
||||
[[nodiscard]] auto loadedAdded() const
|
||||
-> rpl::producer<not_null<const DownloadedId*>>;
|
||||
[[nodiscard]] auto loadedRemoved() const
|
||||
-> rpl::producer<not_null<const HistoryItem*>>;
|
||||
|
||||
private:
|
||||
struct SessionData {
|
||||
std::vector<DownloadedId> downloaded;
|
||||
|
@ -98,6 +105,7 @@ private:
|
|||
void check(not_null<const HistoryItem*> item);
|
||||
void changed(not_null<const HistoryItem*> item);
|
||||
void removed(not_null<const HistoryItem*> item);
|
||||
void detach(DownloadedId &id);
|
||||
void untrack(not_null<Main::Session*> session);
|
||||
void remove(
|
||||
SessionData &data,
|
||||
|
@ -107,6 +115,10 @@ private:
|
|||
std::vector<DownloadingId>::iterator i);
|
||||
void clearLoading();
|
||||
|
||||
[[nodiscard]] int64 computeNextStarted();
|
||||
[[nodiscard]] not_null<HistoryItem*> generateItem(
|
||||
const DownloadObject &object);
|
||||
|
||||
[[nodiscard]] SessionData &sessionData(not_null<Main::Session*> session);
|
||||
[[nodiscard]] SessionData &sessionData(
|
||||
not_null<const HistoryItem*> item);
|
||||
|
@ -115,10 +127,17 @@ private:
|
|||
base::flat_set<not_null<const HistoryItem*>> _loading;
|
||||
base::flat_set<not_null<const HistoryItem*>> _loadingDone;
|
||||
base::flat_set<not_null<const HistoryItem*>> _loaded;
|
||||
base::flat_set<not_null<HistoryItem*>> _generated;
|
||||
|
||||
TimeId _lastStartedBase = 0;
|
||||
int _lastStartedAdded = 0;
|
||||
|
||||
rpl::event_stream<> _loadingListChanges;
|
||||
rpl::variable<DownloadProgress> _loadingProgress;
|
||||
|
||||
rpl::event_stream<not_null<const DownloadedId*>> _loadedAdded;
|
||||
rpl::event_stream<not_null<const HistoryItem*>> _loadedRemoved;
|
||||
|
||||
base::Timer _clearLoadingTimer;
|
||||
|
||||
};
|
||||
|
|
|
@ -434,9 +434,9 @@ void Widget::setupDownloadBar() {
|
|||
) | rpl::start_with_next([=] {
|
||||
auto &&list = Core::App().downloadManager().loadingList();
|
||||
auto first = (HistoryItem*)nullptr;
|
||||
for (const auto &id : list) {
|
||||
for (const auto id : list) {
|
||||
if (!first) {
|
||||
first = id.object.item;
|
||||
first = id->object.item;
|
||||
} else {
|
||||
controller()->showSection(
|
||||
Info::Downloads::Make(
|
||||
|
|
|
@ -95,33 +95,111 @@ void Provider::refreshViewer() {
|
|||
manager.loadingListChanges() | rpl::to_empty
|
||||
) | rpl::start_with_next([=, &manager] {
|
||||
auto copy = _downloading;
|
||||
auto added = false;
|
||||
for (const auto &id : manager.loadingList()) {
|
||||
if (!id.done) {
|
||||
const auto item = id.object.item;
|
||||
if (!copy.remove(item)) {
|
||||
added = true;
|
||||
for (const auto id : manager.loadingList()) {
|
||||
if (!id->done) {
|
||||
const auto item = id->object.item;
|
||||
if (!copy.remove(item) && !_downloaded.contains(item)) {
|
||||
_downloading.emplace(item);
|
||||
_elements.push_back(Element{ item, id.started });
|
||||
_elements.push_back(Element{ item, id->started });
|
||||
trackItemSession(item);
|
||||
refreshPostponed(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto &item : copy) {
|
||||
_downloading.remove(item);
|
||||
// #TODO downloads check if downloaded
|
||||
_elements.erase(
|
||||
ranges::remove(_elements, item, &Element::item),
|
||||
end(_elements));
|
||||
Assert(!_downloaded.contains(item));
|
||||
remove(item);
|
||||
}
|
||||
_fullCount = _elements.size();
|
||||
if (added) {
|
||||
ranges::sort(_elements, ranges::less(), &Element::started);
|
||||
_refreshed.fire({});
|
||||
} else if (!copy.empty()) {
|
||||
_refreshed.fire({});
|
||||
if (!_fullCount.has_value()) {
|
||||
refreshPostponed(false);
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
for (const auto id : manager.loadedList()) {
|
||||
addPostponed(id);
|
||||
}
|
||||
|
||||
manager.loadedAdded(
|
||||
) | rpl::start_with_next([=](not_null<const Data::DownloadedId*> entry) {
|
||||
addPostponed(entry);
|
||||
}, _lifetime);
|
||||
|
||||
manager.loadedRemoved(
|
||||
) | rpl::start_with_next([=](not_null<const HistoryItem*> item) {
|
||||
if (!_downloading.contains(item)) {
|
||||
remove(item);
|
||||
} else {
|
||||
_downloaded.remove(item);
|
||||
_addPostponed.remove(item);
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
performAdd();
|
||||
performRefresh();
|
||||
}
|
||||
|
||||
void Provider::addPostponed(not_null<const Data::DownloadedId*> entry) {
|
||||
Expects(entry->object != nullptr);
|
||||
|
||||
const auto item = entry->object->item;
|
||||
trackItemSession(item);
|
||||
if (_addPostponed.emplace(item, entry->started).second
|
||||
&& _addPostponed.size() == 1) {
|
||||
Ui::PostponeCall(this, [=] {
|
||||
performAdd();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Provider::performAdd() {
|
||||
if (_addPostponed.empty()) {
|
||||
return;
|
||||
}
|
||||
for (const auto &[item, started] : base::take(_addPostponed)) {
|
||||
_downloaded.emplace(item);
|
||||
if (!_downloading.remove(item)) {
|
||||
_elements.push_back(Element{ item, started });
|
||||
}
|
||||
}
|
||||
refreshPostponed(true);
|
||||
}
|
||||
|
||||
void Provider::remove(not_null<const HistoryItem*> item) {
|
||||
_addPostponed.remove(item);
|
||||
_downloading.remove(item);
|
||||
_downloaded.remove(item);
|
||||
_elements.erase(
|
||||
ranges::remove(_elements, item, &Element::item),
|
||||
end(_elements));
|
||||
if (const auto i = _layouts.find(item); i != end(_layouts)) {
|
||||
_layoutRemoved.fire(i->second.item.get());
|
||||
_layouts.erase(i);
|
||||
}
|
||||
refreshPostponed(false);
|
||||
}
|
||||
|
||||
void Provider::refreshPostponed(bool added) {
|
||||
if (added) {
|
||||
_postponedRefreshSort = true;
|
||||
}
|
||||
if (!_postponedRefresh) {
|
||||
_postponedRefresh = true;
|
||||
Ui::PostponeCall(this, [=] {
|
||||
performRefresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Provider::performRefresh() {
|
||||
if (!_postponedRefresh) {
|
||||
return;
|
||||
}
|
||||
_postponedRefresh = false;
|
||||
_fullCount = _elements.size();
|
||||
if (base::take(_postponedRefreshSort)) {
|
||||
ranges::sort(_elements, ranges::greater(), &Element::started);
|
||||
}
|
||||
_refreshed.fire({});
|
||||
}
|
||||
|
||||
void Provider::trackItemSession(not_null<const HistoryItem*> item) {
|
||||
|
@ -213,10 +291,7 @@ bool Provider::isAfter(
|
|||
}
|
||||
|
||||
void Provider::itemRemoved(not_null<const HistoryItem*> item) {
|
||||
if (const auto i = _layouts.find(item); i != end(_layouts)) {
|
||||
_layoutRemoved.fire(i->second.item.get());
|
||||
_layouts.erase(i);
|
||||
}
|
||||
remove(item);
|
||||
}
|
||||
|
||||
BaseLayout *Provider::getLayout(
|
||||
|
|
|
@ -8,6 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "info/media/info_media_common.h"
|
||||
#include "base/weak_ptr.h"
|
||||
|
||||
namespace Data {
|
||||
struct DownloadedId;
|
||||
} // namespace Data
|
||||
|
||||
namespace Info {
|
||||
class AbstractController;
|
||||
|
@ -17,7 +22,8 @@ namespace Info::Downloads {
|
|||
|
||||
class Provider final
|
||||
: public Media::ListProvider
|
||||
, private Media::ListSectionDelegate {
|
||||
, private Media::ListSectionDelegate
|
||||
, public base::has_weak_ptr {
|
||||
public:
|
||||
explicit Provider(not_null<AbstractController*> controller);
|
||||
|
||||
|
@ -77,6 +83,11 @@ private:
|
|||
void markLayoutsStale();
|
||||
void clearStaleLayouts();
|
||||
|
||||
void refreshPostponed(bool added);
|
||||
void addPostponed(not_null<const Data::DownloadedId*> entry);
|
||||
void performRefresh();
|
||||
void performAdd();
|
||||
void remove(not_null<const HistoryItem*> item);
|
||||
void trackItemSession(not_null<const HistoryItem*> item);
|
||||
|
||||
[[nodiscard]] Media::BaseLayout *getLayout(
|
||||
|
@ -93,6 +104,8 @@ private:
|
|||
base::flat_set<not_null<const HistoryItem*>> _downloading;
|
||||
base::flat_set<not_null<const HistoryItem*>> _downloaded;
|
||||
|
||||
base::flat_map<not_null<HistoryItem*>, int64> _addPostponed;
|
||||
|
||||
std::unordered_map<
|
||||
not_null<const HistoryItem*>,
|
||||
Media::CachedItem> _layouts;
|
||||
|
@ -100,6 +113,8 @@ private:
|
|||
rpl::event_stream<> _refreshed;
|
||||
|
||||
base::flat_map<not_null<Main::Session*>, rpl::lifetime> _trackedSessions;
|
||||
bool _postponedRefreshSort = false;
|
||||
bool _postponedRefresh = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
|
|
|
@ -108,28 +108,6 @@ rpl::producer<QString> AbstractController::mediaSourceQueryValue() const {
|
|||
return rpl::single(QString());
|
||||
}
|
||||
|
||||
rpl::producer<DownloadsSlice> AbstractController::downloadsSource() const {
|
||||
const auto manager = &Core::App().downloadManager();
|
||||
return rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
manager->loadingListChanges()
|
||||
) | rpl::map([=] {
|
||||
auto result = DownloadsSlice();
|
||||
for (const auto &id : manager->loadingList()) {
|
||||
result.entries.push_back(DownloadsEntry{
|
||||
.item = id.object.item,
|
||||
.started = id.started,
|
||||
});
|
||||
}
|
||||
ranges::sort(
|
||||
result.entries,
|
||||
ranges::less(),
|
||||
&DownloadsEntry::started);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
AbstractController::AbstractController(
|
||||
not_null<Window::SessionController*> parent)
|
||||
: SessionNavigation(&parent->session())
|
||||
|
|
|
@ -113,14 +113,6 @@ private:
|
|||
|
||||
};
|
||||
|
||||
struct DownloadsEntry {
|
||||
not_null<HistoryItem*> item;
|
||||
int64 started = 0; // unixtime * 1000.
|
||||
};
|
||||
struct DownloadsSlice {
|
||||
std::vector<DownloadsEntry> entries;
|
||||
};
|
||||
|
||||
class AbstractController : public Window::SessionNavigation {
|
||||
public:
|
||||
AbstractController(not_null<Window::SessionController*> parent);
|
||||
|
@ -150,8 +142,6 @@ public:
|
|||
int limitAfter) const;
|
||||
virtual rpl::producer<QString> mediaSourceQueryValue() const;
|
||||
|
||||
[[nodiscard]] rpl::producer<DownloadsSlice> downloadsSource() const;
|
||||
|
||||
void showSection(
|
||||
std::shared_ptr<Window::SectionMemento> memento,
|
||||
const Window::SectionShow ¶ms = Window::SectionShow()) override;
|
||||
|
|
|
@ -243,8 +243,6 @@ void ListSection::paint(
|
|||
outerWidth);
|
||||
}
|
||||
auto localContext = context.layoutContext;
|
||||
localContext.isAfterDate = (header > 0);
|
||||
|
||||
if (!_mosaic.empty()) {
|
||||
auto paintItem = [&](not_null<BaseLayout*> item, QPoint point) {
|
||||
p.translate(point.x(), point.y());
|
||||
|
@ -266,8 +264,7 @@ void ListSection::paint(
|
|||
for (auto it = fromIt; it != tillIt; ++it) {
|
||||
auto item = *it;
|
||||
auto rect = findItemRect(item);
|
||||
localContext.isAfterDate = (header > 0)
|
||||
&& (rect.y() <= header + _itemsTop);
|
||||
localContext.skipBorder = (rect.y() <= header + _itemsTop);
|
||||
if (rect.intersects(clip)) {
|
||||
p.translate(rect.topLeft());
|
||||
item->paint(
|
||||
|
|
|
@ -1090,7 +1090,7 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
|
|||
datetop = st::linksBorder + _st.fileDateTop;
|
||||
|
||||
QRect border(style::rtlrect(nameleft, 0, _width - nameleft, st::linksBorder, _width));
|
||||
if (!context->isAfterDate && clip.intersects(border)) {
|
||||
if (!context->skipBorder && clip.intersects(border)) {
|
||||
p.fillRect(clip.intersected(border), st::linksBorderFg);
|
||||
}
|
||||
|
||||
|
@ -1661,7 +1661,7 @@ void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const P
|
|||
}
|
||||
|
||||
QRect border(style::rtlrect(left, 0, w, st::linksBorder, _width));
|
||||
if (!context->isAfterDate && clip.intersects(border)) {
|
||||
if (!context->skipBorder && clip.intersects(border)) {
|
||||
p.fillRect(clip.intersected(border), st::linksBorderFg);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class PaintContext : public PaintContextBase {
|
|||
public:
|
||||
PaintContext(crl::time ms, bool selecting) : PaintContextBase(ms, selecting) {
|
||||
}
|
||||
bool isAfterDate = false;
|
||||
bool skipBorder = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1ec9a0635231a37e18fbe6291a58c685cdf75d5b
|
||||
Subproject commit 3827b6186eab1e6f7ca335d88310bd9e3f6fe440
|
Loading…
Add table
Reference in a new issue