mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Track all required sessions notifications.
This commit is contained in:
parent
93c6038992
commit
e6294f48de
9 changed files with 194 additions and 78 deletions
|
@ -13,7 +13,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_download_manager.h"
|
#include "data/data_download_manager.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_media_types.h"
|
#include "data/data_media_types.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "main/main_account.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
|
#include "history/history.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
#include "layout/layout_selection.h"
|
#include "layout/layout_selection.h"
|
||||||
|
@ -47,6 +51,20 @@ rpl::producer<bool> Provider::hasSelectRestrictionChanges() {
|
||||||
return rpl::never<bool>();
|
return rpl::never<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Provider::sectionHasFloatingHeader() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Provider::sectionTitle(not_null<const BaseLayout*> item) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Provider::sectionItemBelongsHere(
|
||||||
|
not_null<const BaseLayout*> item,
|
||||||
|
not_null<const BaseLayout*> previous) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Provider::isPossiblyMyItem(not_null<const HistoryItem*> item) {
|
bool Provider::isPossiblyMyItem(not_null<const HistoryItem*> item) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -85,6 +103,7 @@ void Provider::refreshViewer() {
|
||||||
added = true;
|
added = true;
|
||||||
_downloading.emplace(item);
|
_downloading.emplace(item);
|
||||||
_elements.push_back(Element{ item, id.started });
|
_elements.push_back(Element{ item, id.started });
|
||||||
|
trackItemSession(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,6 +123,24 @@ void Provider::refreshViewer() {
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Provider::trackItemSession(not_null<const HistoryItem*> item) {
|
||||||
|
const auto session = &item->history()->session();
|
||||||
|
if (_trackedSessions.contains(session)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto &lifetime = _trackedSessions.emplace(session).first->second;
|
||||||
|
|
||||||
|
session->data().itemRemoved(
|
||||||
|
) | rpl::start_with_next([this](auto item) {
|
||||||
|
itemRemoved(item);
|
||||||
|
}, lifetime);
|
||||||
|
|
||||||
|
session->account().sessionChanges(
|
||||||
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||||
|
_trackedSessions.remove(session);
|
||||||
|
}, lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<> Provider::refreshed() {
|
rpl::producer<> Provider::refreshed() {
|
||||||
return _refreshed.events();
|
return _refreshed.events();
|
||||||
}
|
}
|
||||||
|
@ -117,7 +154,9 @@ std::vector<ListSection> Provider::fillSections(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = std::vector<ListSection>(1, ListSection(Type::File));
|
auto result = std::vector<ListSection>(
|
||||||
|
1,
|
||||||
|
ListSection(Type::File, sectionDelegate()));
|
||||||
auto §ion = result.back();
|
auto §ion = result.back();
|
||||||
for (const auto &element : _elements) {
|
for (const auto &element : _elements) {
|
||||||
if (auto layout = getLayout(element, delegate)) {
|
if (auto layout = getLayout(element, delegate)) {
|
||||||
|
@ -172,6 +211,13 @@ bool Provider::isAfter(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BaseLayout *Provider::getLayout(
|
BaseLayout *Provider::getLayout(
|
||||||
Element element,
|
Element element,
|
||||||
not_null<Overview::Layout::Delegate*> delegate) {
|
not_null<Overview::Layout::Delegate*> delegate) {
|
||||||
|
|
|
@ -15,7 +15,9 @@ class AbstractController;
|
||||||
|
|
||||||
namespace Info::Downloads {
|
namespace Info::Downloads {
|
||||||
|
|
||||||
class Provider final : public Media::ListProvider {
|
class Provider final
|
||||||
|
: public Media::ListProvider
|
||||||
|
, private Media::ListSectionDelegate {
|
||||||
public:
|
public:
|
||||||
explicit Provider(not_null<AbstractController*> controller);
|
explicit Provider(not_null<AbstractController*> controller);
|
||||||
|
|
||||||
|
@ -65,10 +67,18 @@ private:
|
||||||
int64 started = 0; // unixtime * 1000
|
int64 started = 0; // unixtime * 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool sectionHasFloatingHeader() override;
|
||||||
|
QString sectionTitle(not_null<const Media::BaseLayout*> item) override;
|
||||||
|
bool sectionItemBelongsHere(
|
||||||
|
not_null<const Media::BaseLayout*> item,
|
||||||
|
not_null<const Media::BaseLayout*> previous) override;
|
||||||
|
|
||||||
void itemRemoved(not_null<const HistoryItem*> item);
|
void itemRemoved(not_null<const HistoryItem*> item);
|
||||||
void markLayoutsStale();
|
void markLayoutsStale();
|
||||||
void clearStaleLayouts();
|
void clearStaleLayouts();
|
||||||
|
|
||||||
|
void trackItemSession(not_null<const HistoryItem*> item);
|
||||||
|
|
||||||
[[nodiscard]] Media::BaseLayout *getLayout(
|
[[nodiscard]] Media::BaseLayout *getLayout(
|
||||||
Element element,
|
Element element,
|
||||||
not_null<Overview::Layout::Delegate*> delegate);
|
not_null<Overview::Layout::Delegate*> delegate);
|
||||||
|
@ -83,10 +93,14 @@ private:
|
||||||
base::flat_set<not_null<const HistoryItem*>> _downloading;
|
base::flat_set<not_null<const HistoryItem*>> _downloading;
|
||||||
base::flat_set<not_null<const HistoryItem*>> _downloaded;
|
base::flat_set<not_null<const HistoryItem*>> _downloaded;
|
||||||
|
|
||||||
std::unordered_map<not_null<HistoryItem*>, Media::CachedItem> _layouts;
|
std::unordered_map<
|
||||||
|
not_null<const HistoryItem*>,
|
||||||
|
Media::CachedItem> _layouts;
|
||||||
rpl::event_stream<not_null<Media::BaseLayout*>> _layoutRemoved;
|
rpl::event_stream<not_null<Media::BaseLayout*>> _layoutRemoved;
|
||||||
rpl::event_stream<> _refreshed;
|
rpl::event_stream<> _refreshed;
|
||||||
|
|
||||||
|
base::flat_map<not_null<Main::Session*>, rpl::lifetime> _trackedSessions;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,6 +85,20 @@ bool ChangeItemSelection(
|
||||||
not_null<const HistoryItem*> item,
|
not_null<const HistoryItem*> item,
|
||||||
TextSelection selection);
|
TextSelection selection);
|
||||||
|
|
||||||
|
class ListSectionDelegate {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] virtual bool sectionHasFloatingHeader() = 0;
|
||||||
|
[[nodiscard]] virtual QString sectionTitle(
|
||||||
|
not_null<const BaseLayout*> item) = 0;
|
||||||
|
[[nodiscard]] virtual bool sectionItemBelongsHere(
|
||||||
|
not_null<const BaseLayout*> item,
|
||||||
|
not_null<const BaseLayout*> previous) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] not_null<ListSectionDelegate*> sectionDelegate() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ListProvider {
|
class ListProvider {
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] virtual Type type() = 0;
|
[[nodiscard]] virtual Type type() = 0;
|
||||||
|
@ -133,7 +147,6 @@ public:
|
||||||
Fn<void(ListScrollTopState)> restoreScrollState) = 0;
|
Fn<void(ListScrollTopState)> restoreScrollState) = 0;
|
||||||
|
|
||||||
virtual ~ListProvider() = default;
|
virtual ~ListProvider() = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Info::Media
|
} // namespace Info::Media
|
||||||
|
|
|
@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/media/info_media_list_section.h"
|
#include "info/media/info_media_list_section.h"
|
||||||
|
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
#include "lang/lang_keys.h"
|
|
||||||
#include "layout/layout_selection.h"
|
#include "layout/layout_selection.h"
|
||||||
#include "styles/style_info.h"
|
#include "styles/style_info.h"
|
||||||
|
|
||||||
|
@ -17,27 +16,12 @@ namespace {
|
||||||
|
|
||||||
constexpr auto kFloatingHeaderAlpha = 0.9;
|
constexpr auto kFloatingHeaderAlpha = 0.9;
|
||||||
|
|
||||||
[[nodiscard]] bool HasFloatingHeader(Type type) {
|
|
||||||
switch (type) {
|
|
||||||
case Type::Photo:
|
|
||||||
case Type::GIF:
|
|
||||||
case Type::Video:
|
|
||||||
case Type::RoundFile:
|
|
||||||
case Type::RoundVoiceFile:
|
|
||||||
case Type::MusicFile:
|
|
||||||
return false;
|
|
||||||
case Type::File:
|
|
||||||
case Type::Link:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Unexpected("Type in HasFloatingHeader()");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ListSection::ListSection(Type type)
|
ListSection::ListSection(Type type, not_null<ListSectionDelegate*> delegate)
|
||||||
: _type(type)
|
: _type(type)
|
||||||
, _hasFloatingHeader(HasFloatingHeader(type))
|
, _delegate(delegate)
|
||||||
|
, _hasFloatingHeader(delegate->sectionHasFloatingHeader())
|
||||||
, _mosaic(st::emojiPanWidth - st::inlineResultsLeft) {
|
, _mosaic(st::emojiPanWidth - st::inlineResultsLeft) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,54 +71,14 @@ void ListSection::finishSection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListSection::setHeader(not_null<BaseLayout*> item) {
|
void ListSection::setHeader(not_null<BaseLayout*> item) {
|
||||||
auto text = [&] {
|
_header.setText(st::infoMediaHeaderStyle, _delegate->sectionTitle(item));
|
||||||
auto date = item->dateTime().date();
|
|
||||||
switch (_type) {
|
|
||||||
case Type::Photo:
|
|
||||||
case Type::GIF:
|
|
||||||
case Type::Video:
|
|
||||||
case Type::RoundFile:
|
|
||||||
case Type::RoundVoiceFile:
|
|
||||||
case Type::File:
|
|
||||||
return langMonthFull(date);
|
|
||||||
|
|
||||||
case Type::Link:
|
|
||||||
return langDayOfMonthFull(date);
|
|
||||||
|
|
||||||
case Type::MusicFile:
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
Unexpected("Type in ListSection::setHeader()");
|
|
||||||
}();
|
|
||||||
_header.setText(st::infoMediaHeaderStyle, text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ListSection::belongsHere(
|
bool ListSection::belongsHere(
|
||||||
not_null<BaseLayout*> item) const {
|
not_null<BaseLayout*> item) const {
|
||||||
Expects(!_items.empty());
|
Expects(!_items.empty());
|
||||||
|
|
||||||
auto date = item->dateTime().date();
|
return _delegate->sectionItemBelongsHere(item, _items.back());
|
||||||
auto myDate = _items.back()->dateTime().date();
|
|
||||||
|
|
||||||
switch (_type) {
|
|
||||||
case Type::Photo:
|
|
||||||
case Type::GIF:
|
|
||||||
case Type::Video:
|
|
||||||
case Type::RoundFile:
|
|
||||||
case Type::RoundVoiceFile:
|
|
||||||
case Type::File:
|
|
||||||
return date.year() == myDate.year()
|
|
||||||
&& date.month() == myDate.month();
|
|
||||||
|
|
||||||
case Type::Link:
|
|
||||||
return date.year() == myDate.year()
|
|
||||||
&& date.month() == myDate.month()
|
|
||||||
&& date.day() == myDate.day();
|
|
||||||
|
|
||||||
case Type::MusicFile:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Unexpected("Type in ListSection::belongsHere()");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListSection::appendItem(not_null<BaseLayout*> item) {
|
void ListSection::appendItem(not_null<BaseLayout*> item) {
|
||||||
|
@ -279,6 +223,10 @@ auto ListSection::findItemAfterBottom(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ListSection::Items &ListSection::items() const {
|
||||||
|
return _items;
|
||||||
|
}
|
||||||
|
|
||||||
void ListSection::paint(
|
void ListSection::paint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const ListContext &context,
|
const ListContext &context,
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Info::Media {
|
||||||
|
|
||||||
class ListSection {
|
class ListSection {
|
||||||
public:
|
public:
|
||||||
ListSection(Type type);
|
ListSection(Type type, not_null<ListSectionDelegate*> delegate);
|
||||||
|
|
||||||
bool addItem(not_null<BaseLayout*> item);
|
bool addItem(not_null<BaseLayout*> item);
|
||||||
void finishSection();
|
void finishSection();
|
||||||
|
@ -40,6 +40,9 @@ public:
|
||||||
not_null<BaseLayout*> item) const;
|
not_null<BaseLayout*> item) const;
|
||||||
[[nodiscard]] ListFoundItem findItemByPoint(QPoint point) const;
|
[[nodiscard]] ListFoundItem findItemByPoint(QPoint point) const;
|
||||||
|
|
||||||
|
using Items = std::vector<not_null<BaseLayout*>>;
|
||||||
|
const Items &items() const;
|
||||||
|
|
||||||
void paint(
|
void paint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const ListContext &context,
|
const ListContext &context,
|
||||||
|
@ -49,8 +52,6 @@ public:
|
||||||
void paintFloatingHeader(Painter &p, int visibleTop, int outerWidth);
|
void paintFloatingHeader(Painter &p, int visibleTop, int outerWidth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Items = std::vector<not_null<BaseLayout*>>;
|
|
||||||
|
|
||||||
[[nodiscard]] int headerHeight() const;
|
[[nodiscard]] int headerHeight() const;
|
||||||
void appendItem(not_null<BaseLayout*> item);
|
void appendItem(not_null<BaseLayout*> item);
|
||||||
void setHeader(not_null<BaseLayout*> item);
|
void setHeader(not_null<BaseLayout*> item);
|
||||||
|
@ -72,6 +73,8 @@ private:
|
||||||
void refreshHeight();
|
void refreshHeight();
|
||||||
|
|
||||||
Type _type = Type{};
|
Type _type = Type{};
|
||||||
|
not_null<ListSectionDelegate*> _delegate;
|
||||||
|
|
||||||
bool _hasFloatingHeader = false;
|
bool _hasFloatingHeader = false;
|
||||||
Ui::Text::String _header;
|
Ui::Text::String _header;
|
||||||
Items _items;
|
Items _items;
|
||||||
|
|
|
@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/inactive_press.h"
|
#include "ui/inactive_press.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
#include "main/main_account.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
|
@ -158,7 +159,7 @@ void ListWidget::start() {
|
||||||
if (_controller->isDownloads()) {
|
if (_controller->isDownloads()) {
|
||||||
_provider->refreshViewer();
|
_provider->refreshViewer();
|
||||||
} else {
|
} else {
|
||||||
subscribeToSession(&session());
|
subscribeToSession(&session(), lifetime());
|
||||||
|
|
||||||
_controller->mediaSourceQueryValue(
|
_controller->mediaSourceQueryValue(
|
||||||
) | rpl::start_with_next([this] {
|
) | rpl::start_with_next([this] {
|
||||||
|
@ -169,26 +170,28 @@ void ListWidget::start() {
|
||||||
setupSelectRestriction();
|
setupSelectRestriction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::subscribeToSession(not_null<Main::Session*> session) {
|
void ListWidget::subscribeToSession(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
rpl::lifetime &lifetime) {
|
||||||
session->downloaderTaskFinished(
|
session->downloaderTaskFinished(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
update();
|
update();
|
||||||
}, lifetime());
|
}, lifetime);
|
||||||
|
|
||||||
session->data().itemLayoutChanged(
|
session->data().itemLayoutChanged(
|
||||||
) | rpl::start_with_next([this](auto item) {
|
) | rpl::start_with_next([this](auto item) {
|
||||||
itemLayoutChanged(item);
|
itemLayoutChanged(item);
|
||||||
}, lifetime());
|
}, lifetime);
|
||||||
|
|
||||||
session->data().itemRemoved(
|
session->data().itemRemoved(
|
||||||
) | rpl::start_with_next([this](auto item) {
|
) | rpl::start_with_next([this](auto item) {
|
||||||
itemRemoved(item);
|
itemRemoved(item);
|
||||||
}, lifetime());
|
}, lifetime);
|
||||||
|
|
||||||
session->data().itemRepaintRequest(
|
session->data().itemRepaintRequest(
|
||||||
) | rpl::start_with_next([this](auto item) {
|
) | rpl::start_with_next([this](auto item) {
|
||||||
repaintItem(item);
|
repaintItem(item);
|
||||||
}, lifetime());
|
}, lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::setupSelectRestriction() {
|
void ListWidget::setupSelectRestriction() {
|
||||||
|
@ -416,12 +419,30 @@ void ListWidget::openDocument(
|
||||||
showInMediaView);
|
showInMediaView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::trackSession(not_null<Main::Session*> session) {
|
||||||
|
if (_trackedSessions.contains(session)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto &lifetime = _trackedSessions.emplace(session).first->second;
|
||||||
|
subscribeToSession(session, lifetime);
|
||||||
|
session->account().sessionChanges(
|
||||||
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||||
|
_trackedSessions.remove(session);
|
||||||
|
}, lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::refreshRows() {
|
void ListWidget::refreshRows() {
|
||||||
saveScrollState();
|
saveScrollState();
|
||||||
|
|
||||||
_sections.clear();
|
_sections.clear();
|
||||||
_sections = _provider->fillSections(this);
|
_sections = _provider->fillSections(this);
|
||||||
|
|
||||||
|
if (_controller->isDownloads() && !_sections.empty()) {
|
||||||
|
for (const auto &item : _sections.back().items()) {
|
||||||
|
trackSession(&item->getItem()->history()->session());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (const auto count = _provider->fullCount()) {
|
if (const auto count = _provider->fullCount()) {
|
||||||
if (*count > kMediaCountForSearch) {
|
if (*count > kMediaCountForSearch) {
|
||||||
_controller->setSearchEnabledByContent(true);
|
_controller->setSearchEnabledByContent(true);
|
||||||
|
|
|
@ -145,7 +145,9 @@ private:
|
||||||
void start();
|
void start();
|
||||||
int recountHeight();
|
int recountHeight();
|
||||||
void refreshHeight();
|
void refreshHeight();
|
||||||
void subscribeToSession(not_null<Main::Session*> session);
|
void subscribeToSession(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
rpl::lifetime &lifetime);
|
||||||
|
|
||||||
void setupSelectRestriction();
|
void setupSelectRestriction();
|
||||||
|
|
||||||
|
@ -162,6 +164,7 @@ private:
|
||||||
|
|
||||||
void refreshViewer();
|
void refreshViewer();
|
||||||
void refreshRows();
|
void refreshRows();
|
||||||
|
void trackSession(not_null<Main::Session*> session);
|
||||||
|
|
||||||
[[nodiscard]] SelectedItems collectSelectedItems() const;
|
[[nodiscard]] SelectedItems collectSelectedItems() const;
|
||||||
[[nodiscard]] MessageIdsList collectSelectedIds() const;
|
[[nodiscard]] MessageIdsList collectSelectedIds() const;
|
||||||
|
@ -283,6 +286,7 @@ private:
|
||||||
bool _wasSelectedText = false; // was some text selected in current drag action
|
bool _wasSelectedText = false; // was some text selected in current drag action
|
||||||
|
|
||||||
const std::unique_ptr<DateBadge> _dateBadge;
|
const std::unique_ptr<DateBadge> _dateBadge;
|
||||||
|
base::flat_map<not_null<Main::Session*>, rpl::lifetime> _trackedSessions;
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> _contextMenu;
|
base::unique_qptr<Ui::PopupMenu> _contextMenu;
|
||||||
rpl::event_stream<> _checkForHide;
|
rpl::event_stream<> _checkForHide;
|
||||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "layout/layout_selection.h"
|
#include "layout/layout_selection.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -121,6 +122,66 @@ rpl::producer<bool> Provider::hasSelectRestrictionChanges() {
|
||||||
}) | rpl::distinct_until_changed() | rpl::skip(1);
|
}) | rpl::distinct_until_changed() | rpl::skip(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Provider::sectionHasFloatingHeader() {
|
||||||
|
switch (_type) {
|
||||||
|
case Type::Photo:
|
||||||
|
case Type::GIF:
|
||||||
|
case Type::Video:
|
||||||
|
case Type::RoundFile:
|
||||||
|
case Type::RoundVoiceFile:
|
||||||
|
case Type::MusicFile:
|
||||||
|
return false;
|
||||||
|
case Type::File:
|
||||||
|
case Type::Link:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Unexpected("Type in HasFloatingHeader()");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Provider::sectionTitle(not_null<const BaseLayout*> item) {
|
||||||
|
switch (_type) {
|
||||||
|
case Type::Photo:
|
||||||
|
case Type::GIF:
|
||||||
|
case Type::Video:
|
||||||
|
case Type::RoundFile:
|
||||||
|
case Type::RoundVoiceFile:
|
||||||
|
case Type::File:
|
||||||
|
return langMonthFull(item->dateTime().date());
|
||||||
|
|
||||||
|
case Type::Link:
|
||||||
|
return langDayOfMonthFull(item->dateTime().date());
|
||||||
|
|
||||||
|
case Type::MusicFile:
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
Unexpected("Type in ListSection::setHeader()");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Provider::sectionItemBelongsHere(
|
||||||
|
not_null<const BaseLayout*> item,
|
||||||
|
not_null<const BaseLayout*> previous) {
|
||||||
|
const auto date = item->dateTime().date();
|
||||||
|
const auto sectionDate = previous->dateTime().date();
|
||||||
|
|
||||||
|
switch (_type) {
|
||||||
|
case Type::Photo:
|
||||||
|
case Type::GIF:
|
||||||
|
case Type::Video:
|
||||||
|
case Type::RoundFile:
|
||||||
|
case Type::RoundVoiceFile:
|
||||||
|
case Type::File:
|
||||||
|
return date.year() == sectionDate.year()
|
||||||
|
&& date.month() == sectionDate.month();
|
||||||
|
|
||||||
|
case Type::Link:
|
||||||
|
return date == sectionDate;
|
||||||
|
|
||||||
|
case Type::MusicFile:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Unexpected("Type in ListSection::belongsHere()");
|
||||||
|
}
|
||||||
|
|
||||||
bool Provider::isPossiblyMyItem(not_null<const HistoryItem*> item) {
|
bool Provider::isPossiblyMyItem(not_null<const HistoryItem*> item) {
|
||||||
return isPossiblyMyPeerId(item->history()->peer->id);
|
return isPossiblyMyPeerId(item->history()->peer->id);
|
||||||
}
|
}
|
||||||
|
@ -221,7 +282,7 @@ std::vector<ListSection> Provider::fillSections(
|
||||||
const auto guard = gsl::finally([&] { clearStaleLayouts(); });
|
const auto guard = gsl::finally([&] { clearStaleLayouts(); });
|
||||||
|
|
||||||
auto result = std::vector<ListSection>();
|
auto result = std::vector<ListSection>();
|
||||||
auto section = ListSection(_type);
|
auto section = ListSection(_type, sectionDelegate());
|
||||||
auto count = _slice.size();
|
auto count = _slice.size();
|
||||||
for (auto i = count; i != 0;) {
|
for (auto i = count; i != 0;) {
|
||||||
auto universalId = GetUniversalId(_slice[--i]);
|
auto universalId = GetUniversalId(_slice[--i]);
|
||||||
|
@ -229,7 +290,7 @@ std::vector<ListSection> Provider::fillSections(
|
||||||
if (!section.addItem(layout)) {
|
if (!section.addItem(layout)) {
|
||||||
section.finishSection();
|
section.finishSection();
|
||||||
result.push_back(std::move(section));
|
result.push_back(std::move(section));
|
||||||
section = ListSection(_type);
|
section = ListSection(_type, sectionDelegate());
|
||||||
section.addItem(layout);
|
section.addItem(layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class AbstractController;
|
||||||
|
|
||||||
namespace Info::Media {
|
namespace Info::Media {
|
||||||
|
|
||||||
class Provider final : public ListProvider {
|
class Provider final : public ListProvider, private ListSectionDelegate {
|
||||||
public:
|
public:
|
||||||
explicit Provider(not_null<AbstractController*> controller);
|
explicit Provider(not_null<AbstractController*> controller);
|
||||||
|
|
||||||
|
@ -64,6 +64,12 @@ private:
|
||||||
static constexpr auto kMinimalIdsLimit = 16;
|
static constexpr auto kMinimalIdsLimit = 16;
|
||||||
static constexpr auto kDefaultAroundId = (ServerMaxMsgId - 1);
|
static constexpr auto kDefaultAroundId = (ServerMaxMsgId - 1);
|
||||||
|
|
||||||
|
bool sectionHasFloatingHeader() override;
|
||||||
|
QString sectionTitle(not_null<const BaseLayout*> item) override;
|
||||||
|
bool sectionItemBelongsHere(
|
||||||
|
not_null<const BaseLayout*> item,
|
||||||
|
not_null<const BaseLayout*> previous) override;
|
||||||
|
|
||||||
[[nodiscard]] bool isPossiblyMyPeerId(PeerId peerId) const;
|
[[nodiscard]] bool isPossiblyMyPeerId(PeerId peerId) const;
|
||||||
[[nodiscard]] FullMsgId computeFullId(UniversalMsgId universalId) const;
|
[[nodiscard]] FullMsgId computeFullId(UniversalMsgId universalId) const;
|
||||||
[[nodiscard]] BaseLayout *getLayout(
|
[[nodiscard]] BaseLayout *getLayout(
|
||||||
|
|
Loading…
Add table
Reference in a new issue