mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Add stories outline to group participants list.
This commit is contained in:
parent
fad05e8b35
commit
f31b40f6ce
9 changed files with 287 additions and 156 deletions
|
@ -889,9 +889,11 @@ void PeerListRow::createCheckbox(
|
|||
}
|
||||
|
||||
void PeerListRow::setCheckedInternal(bool checked, anim::type animated) {
|
||||
Expects(_checkbox != nullptr);
|
||||
Expects(!checked || _checkbox != nullptr);
|
||||
|
||||
_checkbox->setChecked(checked, animated);
|
||||
if (_checkbox) {
|
||||
_checkbox->setChecked(checked, animated);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListRow::setCustomizedCheckSegments(
|
||||
|
|
|
@ -54,40 +54,6 @@ namespace {
|
|||
constexpr auto kSortByOnlineThrottle = 3 * crl::time(1000);
|
||||
constexpr auto kSearchPerPage = 50;
|
||||
|
||||
[[nodiscard]] std::vector<Ui::OutlineSegment> PrepareSegments(
|
||||
int count,
|
||||
int unread,
|
||||
const QBrush &unreadBrush) {
|
||||
Expects(unread <= count);
|
||||
Expects(count > 0);
|
||||
|
||||
auto result = std::vector<Ui::OutlineSegment>();
|
||||
const auto add = [&](bool unread) {
|
||||
result.push_back({
|
||||
.brush = unread ? unreadBrush : st::dialogsUnreadBgMuted->b,
|
||||
.width = (unread
|
||||
? st::dialogsStoriesFull.lineTwice / 2.
|
||||
: st::dialogsStoriesFull.lineReadTwice / 2.),
|
||||
});
|
||||
};
|
||||
result.reserve(count);
|
||||
for (auto i = 0, till = count - unread; i != till; ++i) {
|
||||
add(false);
|
||||
}
|
||||
for (auto i = 0; i != unread; ++i) {
|
||||
add(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] QBrush CreateStoriesGradient() {
|
||||
const auto &st = st::contactsWithStories.item;
|
||||
const auto left = st.photoPosition.x();
|
||||
const auto top = st.photoPosition.y();
|
||||
const auto size = st.photoSize;
|
||||
return Ui::UnreadStoryOutlineGradient(QRectF(left, top, size, size));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
object_ptr<Ui::BoxContent> PrepareContactsBox(
|
||||
|
@ -124,6 +90,39 @@ object_ptr<Ui::BoxContent> PrepareContactsBox(
|
|||
return Box<PeerListBox>(std::move(controller), std::move(init));
|
||||
}
|
||||
|
||||
QBrush PeerListStoriesGradient(const style::PeerList &st) {
|
||||
const auto left = st.item.photoPosition.x();
|
||||
const auto top = st.item.photoPosition.y();
|
||||
const auto size = st.item.photoSize;
|
||||
return Ui::UnreadStoryOutlineGradient(QRectF(left, top, size, size));
|
||||
}
|
||||
|
||||
std::vector<Ui::OutlineSegment> PeerListStoriesSegments(
|
||||
int count,
|
||||
int unread,
|
||||
const QBrush &unreadBrush) {
|
||||
Expects(unread <= count);
|
||||
Expects(count > 0);
|
||||
|
||||
auto result = std::vector<Ui::OutlineSegment>();
|
||||
const auto add = [&](bool unread) {
|
||||
result.push_back({
|
||||
.brush = unread ? unreadBrush : st::dialogsUnreadBgMuted->b,
|
||||
.width = (unread
|
||||
? st::dialogsStoriesFull.lineTwice / 2.
|
||||
: st::dialogsStoriesFull.lineReadTwice / 2.),
|
||||
});
|
||||
};
|
||||
result.reserve(count);
|
||||
for (auto i = 0, till = count - unread; i != till; ++i) {
|
||||
add(false);
|
||||
}
|
||||
for (auto i = 0; i != unread; ++i) {
|
||||
add(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PeerListRowWithLink::setActionLink(const QString &action) {
|
||||
_action = action;
|
||||
refreshActionLink();
|
||||
|
@ -359,6 +358,115 @@ bool ChatsListBoxController::appendRow(not_null<History*> history) {
|
|||
return false;
|
||||
}
|
||||
|
||||
PeerListStories::PeerListStories(
|
||||
not_null<PeerListController*> controller,
|
||||
not_null<Main::Session*> session)
|
||||
: _controller(controller)
|
||||
, _session(session) {
|
||||
}
|
||||
|
||||
void PeerListStories::updateColors() {
|
||||
for (auto i = begin(_counts); i != end(_counts); ++i) {
|
||||
if (const auto row = _delegate->peerListFindRow(i->first)) {
|
||||
if (i->second.count >= 0 && i->second.unread >= 0) {
|
||||
applyForRow(row, i->second.count, i->second.unread, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListStories::updateFor(
|
||||
uint64 id,
|
||||
int count,
|
||||
int unread) {
|
||||
if (const auto row = _delegate->peerListFindRow(id)) {
|
||||
applyForRow(row, count, unread);
|
||||
_delegate->peerListUpdateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListStories::process(not_null<PeerListRow*> row) {
|
||||
const auto user = row->peer()->asUser();
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
const auto stories = &_session->data().stories();
|
||||
const auto source = stories->source(user->id);
|
||||
const auto count = source
|
||||
? int(source->ids.size())
|
||||
: user->hasActiveStories()
|
||||
? 1
|
||||
: 0;
|
||||
const auto unread = source
|
||||
? source->info().unreadCount
|
||||
: user->hasUnreadStories()
|
||||
? 1
|
||||
: 0;
|
||||
applyForRow(row, count, unread, true);
|
||||
}
|
||||
|
||||
bool PeerListStories::handleClick(not_null<PeerData*> peer) {
|
||||
const auto point = _delegate->peerListLastRowMousePosition();
|
||||
const auto &st = _controller->listSt()->item;
|
||||
if (point && point->x() < st.photoPosition.x() + st.photoSize) {
|
||||
if (const auto window = peer->session().tryResolveWindow()) {
|
||||
if (const auto user = peer->asUser()) {
|
||||
if (user->hasActiveStories()) {
|
||||
window->openPeerStories(peer->id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PeerListStories::prepare(not_null<PeerListDelegate*> delegate) {
|
||||
_delegate = delegate;
|
||||
|
||||
_unreadBrush = PeerListStoriesGradient(*_controller->listSt());
|
||||
style::PaletteChanged() | rpl::start_with_next([=] {
|
||||
_unreadBrush = PeerListStoriesGradient(*_controller->listSt());
|
||||
updateColors();
|
||||
}, _lifetime);
|
||||
|
||||
_session->changes().peerUpdates(
|
||||
Data::PeerUpdate::Flag::StoriesState
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
const auto id = update.peer->id.value;
|
||||
if (const auto row = _delegate->peerListFindRow(id)) {
|
||||
process(row);
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
const auto stories = &_session->data().stories();
|
||||
stories->sourceChanged() | rpl::start_with_next([=](PeerId id) {
|
||||
const auto source = stories->source(id);
|
||||
const auto info = source
|
||||
? source->info()
|
||||
: Data::StoriesSourceInfo();
|
||||
updateFor(id.value, info.count, info.unreadCount);
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void PeerListStories::applyForRow(
|
||||
not_null<PeerListRow*> row,
|
||||
int count,
|
||||
int unread,
|
||||
bool force) {
|
||||
auto &counts = _counts[row->id()];
|
||||
if (!force && counts.count == count && counts.unread == unread) {
|
||||
return;
|
||||
}
|
||||
counts.count = count;
|
||||
counts.unread = unread;
|
||||
_delegate->peerListSetRowChecked(row, count > 0);
|
||||
if (count > 0) {
|
||||
row->setCustomizedCheckSegments(
|
||||
PeerListStoriesSegments(count, unread, _unreadBrush));
|
||||
}
|
||||
}
|
||||
|
||||
ContactsBoxController::ContactsBoxController(
|
||||
not_null<Main::Session*> session)
|
||||
: ContactsBoxController(
|
||||
|
@ -385,31 +493,8 @@ void ContactsBoxController::prepare() {
|
|||
|
||||
prepareViewHook();
|
||||
|
||||
if (_storiesShown) {
|
||||
_storiesUnread = CreateStoriesGradient();
|
||||
style::PaletteChanged() | rpl::start_with_next([=] {
|
||||
_storiesUnread = CreateStoriesGradient();
|
||||
for (auto &entry : _storiesCounts) {
|
||||
entry.second.count = entry.second.unread = -1;
|
||||
}
|
||||
updateStories();
|
||||
}, lifetime());
|
||||
|
||||
const auto stories = &session().data().stories();
|
||||
rpl::merge(
|
||||
rpl::single(rpl::empty),
|
||||
stories->sourcesChanged(Data::StorySourcesList::NotHidden),
|
||||
stories->sourcesChanged(Data::StorySourcesList::Hidden)
|
||||
) | rpl::start_with_next([=] {
|
||||
updateStories();
|
||||
}, lifetime());
|
||||
stories->sourceChanged() | rpl::start_with_next([=](PeerId id) {
|
||||
const auto source = stories->source(id);
|
||||
const auto info = source
|
||||
? source->info()
|
||||
: Data::StoriesSourceInfo();
|
||||
updateStoriesFor(id.value, info.count, info.unreadCount);
|
||||
}, lifetime());
|
||||
if (_stories) {
|
||||
_stories->prepare(delegate());
|
||||
}
|
||||
|
||||
session().data().contactsLoaded().value(
|
||||
|
@ -456,16 +541,10 @@ std::unique_ptr<PeerListRow> ContactsBoxController::createSearchRow(
|
|||
|
||||
void ContactsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
const auto peer = row->peer();
|
||||
if (const auto window = peer->session().tryResolveWindow()) {
|
||||
if (_storiesShown) {
|
||||
const auto point = delegate()->peerListLastRowMousePosition();
|
||||
const auto &st = st::contactsWithStories.item;
|
||||
if (point && point->x() < st.photoPosition.x() + st.photoSize) {
|
||||
window->openPeerStories(peer->id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
window->showPeerHistory(row->peer());
|
||||
if (_stories && _stories->handleClick(peer)) {
|
||||
return;
|
||||
} else if (const auto window = peer->session().tryResolveWindow()) {
|
||||
window->showPeerHistory(peer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,52 +570,7 @@ void ContactsBoxController::setSortMode(SortMode mode) {
|
|||
}
|
||||
|
||||
void ContactsBoxController::setStoriesShown(bool shown) {
|
||||
_storiesShown = shown;
|
||||
}
|
||||
|
||||
void ContactsBoxController::updateStories() {
|
||||
const auto stories = &_session->data().stories();
|
||||
const auto &a = stories->sources(Data::StorySourcesList::NotHidden);
|
||||
const auto &b = stories->sources(Data::StorySourcesList::Hidden);
|
||||
auto checked = base::flat_set<PeerListRowId>();
|
||||
for (const auto &info : ranges::views::concat(a, b)) {
|
||||
const auto id = info.id.value;
|
||||
checked.emplace(id);
|
||||
updateStoriesFor(id, info.count, info.unreadCount);
|
||||
}
|
||||
for (auto i = begin(_storiesCounts); i != end(_storiesCounts); ++i) {
|
||||
if (i->second.count && !checked.contains(i->first)) {
|
||||
updateStoriesFor(i->first, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBoxController::updateStoriesFor(
|
||||
uint64 id,
|
||||
int count,
|
||||
int unread) {
|
||||
if (const auto row = delegate()->peerListFindRow(id)) {
|
||||
applyRowStories(row, count, unread);
|
||||
delegate()->peerListUpdateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBoxController::applyRowStories(
|
||||
not_null<PeerListRow*> row,
|
||||
int count,
|
||||
int unread,
|
||||
bool force) {
|
||||
auto &counts = _storiesCounts[row->id()];
|
||||
if (!force && counts.count == count && counts.unread == unread) {
|
||||
return;
|
||||
}
|
||||
counts.count = count;
|
||||
counts.unread = unread;
|
||||
delegate()->peerListSetRowChecked(row, count > 0);
|
||||
if (count > 0) {
|
||||
row->setCustomizedCheckSegments(
|
||||
PrepareSegments(count, unread, _storiesUnread));
|
||||
}
|
||||
_stories = std::make_unique<PeerListStories>(this, _session);
|
||||
}
|
||||
|
||||
void ContactsBoxController::sort() {
|
||||
|
@ -586,12 +620,8 @@ bool ContactsBoxController::appendRow(not_null<UserData*> user) {
|
|||
if (auto row = createRow(user)) {
|
||||
const auto raw = row.get();
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
if (_storiesShown) {
|
||||
const auto stories = &session().data().stories();
|
||||
if (const auto source = stories->source(user->id)) {
|
||||
const auto info = source->info();
|
||||
applyRowStories(raw, info.count, info.unreadCount, true);
|
||||
}
|
||||
if (_stories) {
|
||||
_stories->process(raw);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,12 +20,21 @@ class Forum;
|
|||
class ForumTopic;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
struct OutlineSegment;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareContactsBox(
|
||||
not_null<Window::SessionController*> sessionController);
|
||||
[[nodiscard]] QBrush PeerListStoriesGradient(const style::PeerList &st);
|
||||
[[nodiscard]] std::vector<Ui::OutlineSegment> PeerListStoriesSegments(
|
||||
int count,
|
||||
int unread,
|
||||
const QBrush &unreadBrush);
|
||||
|
||||
class PeerListRowWithLink : public PeerListRow {
|
||||
public:
|
||||
|
@ -116,6 +125,41 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class PeerListStories final {
|
||||
public:
|
||||
PeerListStories(
|
||||
not_null<PeerListController*> controller,
|
||||
not_null<Main::Session*> session);
|
||||
|
||||
void prepare(not_null<PeerListDelegate*> delegate);
|
||||
|
||||
void process(not_null<PeerListRow*> row);
|
||||
bool handleClick(not_null<PeerData*> peer);
|
||||
|
||||
private:
|
||||
struct Counts {
|
||||
int count = 0;
|
||||
int unread = 0;
|
||||
};
|
||||
|
||||
void updateColors();
|
||||
void updateFor(uint64 id, int count, int unread);
|
||||
void applyForRow(
|
||||
not_null<PeerListRow*> row,
|
||||
int count,
|
||||
int unread,
|
||||
bool force = false);
|
||||
|
||||
const not_null<PeerListController*> _controller;
|
||||
const not_null<Main::Session*> _session;
|
||||
PeerListDelegate *_delegate = nullptr;
|
||||
|
||||
QBrush _unreadBrush;
|
||||
base::flat_map<uint64, Counts> _counts;
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
class ContactsBoxController : public PeerListController {
|
||||
public:
|
||||
explicit ContactsBoxController(not_null<Main::Session*> session);
|
||||
|
@ -129,7 +173,7 @@ public:
|
|||
not_null<PeerData*> peer) override final;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
bool trackSelectedList() override {
|
||||
return !_storiesShown;
|
||||
return !_stories;
|
||||
}
|
||||
|
||||
enum class SortMode {
|
||||
|
@ -147,32 +191,19 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
struct StoriesCount {
|
||||
int count = 0;
|
||||
int unread = 0;
|
||||
};
|
||||
void sort();
|
||||
void sortByName();
|
||||
void sortByOnline();
|
||||
void rebuildRows();
|
||||
void updateStories();
|
||||
void checkForEmptyRows();
|
||||
bool appendRow(not_null<UserData*> user);
|
||||
void updateStoriesFor(uint64 id, int count, int unread);
|
||||
void applyRowStories(
|
||||
not_null<PeerListRow*> row,
|
||||
int count,
|
||||
int unread,
|
||||
bool force = false);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
SortMode _sortMode = SortMode::Alphabet;
|
||||
base::Timer _sortByOnlineTimer;
|
||||
rpl::lifetime _sortByOnlineLifetime;
|
||||
|
||||
QBrush _storiesUnread;
|
||||
base::flat_map<uint64, StoriesCount> _storiesCounts;
|
||||
bool _storiesShown = false;
|
||||
std::unique_ptr<PeerListStories> _stories;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -25,11 +25,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_stories.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "ui/effects/outline_segments.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "info/profile/info_profile_values.h"
|
||||
|
@ -900,7 +902,11 @@ void ParticipantsBoxController::setupListChangeViewers() {
|
|||
return (row.peer() == user);
|
||||
});
|
||||
} else if (auto row = createRow(user)) {
|
||||
const auto raw = row.get();
|
||||
delegate()->peerListPrependRow(std::move(row));
|
||||
if (_stories) {
|
||||
_stories->process(raw);
|
||||
}
|
||||
refreshRows();
|
||||
if (_onlineSorter) {
|
||||
_onlineSorter->sort();
|
||||
|
@ -1160,8 +1166,14 @@ void ParticipantsBoxController::restoreState(
|
|||
loadMoreRows();
|
||||
}
|
||||
PeerListController::restoreState(std::move(state));
|
||||
if (delegate()->peerListFullRowsCount() > 0 || _allLoaded) {
|
||||
const auto count = delegate()->peerListFullRowsCount();
|
||||
if (count > 0 || _allLoaded) {
|
||||
refreshDescription();
|
||||
if (_stories) {
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
_stories->process(delegate()->peerListRowAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_onlineSorter) {
|
||||
_onlineSorter->sort();
|
||||
|
@ -1177,14 +1189,21 @@ rpl::producer<int> ParticipantsBoxController::fullCountValue() const {
|
|||
return _fullCountValue.value();
|
||||
}
|
||||
|
||||
void ParticipantsBoxController::setStoriesShown(bool shown) {
|
||||
_stories = std::make_unique<PeerListStories>(
|
||||
this,
|
||||
&_navigation->session());
|
||||
}
|
||||
|
||||
void ParticipantsBoxController::prepare() {
|
||||
auto title = [&] {
|
||||
switch (_role) {
|
||||
case Role::Admins: return tr::lng_channel_admins();
|
||||
case Role::Profile:
|
||||
case Role::Members: return (_peer->isChannel() && !_peer->isMegagroup()
|
||||
? tr::lng_profile_subscribers_section()
|
||||
: tr::lng_profile_participants_section());
|
||||
case Role::Members:
|
||||
return ((_peer->isChannel() && !_peer->isMegagroup())
|
||||
? tr::lng_profile_subscribers_section()
|
||||
: tr::lng_profile_participants_section());
|
||||
case Role::Restricted: return tr::lng_exceptions_list_title();
|
||||
case Role::Kicked: return tr::lng_removed_list_title();
|
||||
}
|
||||
|
@ -1207,6 +1226,10 @@ void ParticipantsBoxController::prepare() {
|
|||
setDescriptionText(tr::lng_contacts_loading(tr::now));
|
||||
setSearchNoResultsText(tr::lng_blocked_list_not_found(tr::now));
|
||||
|
||||
if (_stories) {
|
||||
_stories->prepare(delegate());
|
||||
}
|
||||
|
||||
if (_role == Role::Profile) {
|
||||
auto visible = _peer->isMegagroup()
|
||||
? Info::Profile::CanViewParticipantsValue(_peer->asMegagroup())
|
||||
|
@ -1319,7 +1342,11 @@ void ParticipantsBoxController::rebuildChatParticipants(
|
|||
}
|
||||
for (const auto &user : participants) {
|
||||
if (auto row = createRow(user)) {
|
||||
const auto raw = row.get();
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
if (_stories) {
|
||||
_stories->process(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
_onlineSorter->sort();
|
||||
|
@ -1373,7 +1400,11 @@ void ParticipantsBoxController::rebuildChatAdmins(
|
|||
}
|
||||
for (const auto user : list) {
|
||||
if (auto row = createRow(user)) {
|
||||
const auto raw = row.get();
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
if (_stories) {
|
||||
_stories->process(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1543,6 +1574,11 @@ bool ParticipantsBoxController::feedMegagroupLastParticipants() {
|
|||
void ParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
const auto participant = row->peer();
|
||||
const auto user = participant->asUser();
|
||||
|
||||
if (_stories && _stories->handleClick(participant)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_role == Role::Admins) {
|
||||
Assert(user != nullptr);
|
||||
showAdmin(user);
|
||||
|
@ -1890,7 +1926,11 @@ bool ParticipantsBoxController::appendRow(not_null<PeerData*> participant) {
|
|||
recomputeTypeFor(participant);
|
||||
return false;
|
||||
} else if (auto row = createRow(participant)) {
|
||||
const auto raw = row.get();
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
if (_stories) {
|
||||
_stories->process(raw);
|
||||
}
|
||||
if (_role != Role::Kicked) {
|
||||
setDescriptionText(QString());
|
||||
}
|
||||
|
@ -1906,10 +1946,17 @@ bool ParticipantsBoxController::prependRow(not_null<PeerData*> participant) {
|
|||
if (_role == Role::Admins) {
|
||||
// Perhaps we've added a new admin from search.
|
||||
delegate()->peerListPrependRowFromSearchResult(row);
|
||||
if (_stories) {
|
||||
_stories->process(row);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (auto row = createRow(participant)) {
|
||||
const auto raw = row.get();
|
||||
delegate()->peerListPrependRow(std::move(row));
|
||||
if (_stories) {
|
||||
_stories->process(raw);
|
||||
}
|
||||
if (_role != Role::Kicked) {
|
||||
setDescriptionText(QString());
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/weak_ptr.h"
|
||||
#include "info/profile/info_profile_members_controllers.h"
|
||||
|
||||
class PeerListStories;
|
||||
struct ChatAdminRightsInfo;
|
||||
struct ChatRestrictionsInfo;
|
||||
|
||||
|
@ -174,6 +175,9 @@ public:
|
|||
QWidget *parent,
|
||||
not_null<PeerListRow*> row) override;
|
||||
void loadMoreRows() override;
|
||||
bool trackSelectedList() override {
|
||||
return !_stories;
|
||||
}
|
||||
|
||||
void peerListSearchAddRow(not_null<PeerData*> peer) override;
|
||||
std::unique_ptr<PeerListRow> createSearchRow(
|
||||
|
@ -187,6 +191,8 @@ public:
|
|||
[[nodiscard]] rpl::producer<int> onlineCountValue() const;
|
||||
[[nodiscard]] rpl::producer<int> fullCountValue() const;
|
||||
|
||||
void setStoriesShown(bool shown);
|
||||
|
||||
protected:
|
||||
// Allow child controllers not providing navigation.
|
||||
// This is their responsibility to override all methods that use it.
|
||||
|
@ -288,6 +294,8 @@ private:
|
|||
Ui::BoxPointer _addBox;
|
||||
QPointer<Ui::BoxContent> _editParticipantBox;
|
||||
|
||||
std::unique_ptr<PeerListStories> _stories;
|
||||
|
||||
};
|
||||
|
||||
// Members, banned and restricted users server side search.
|
||||
|
|
|
@ -85,26 +85,27 @@ struct PeerUpdate {
|
|||
SupportInfo = (1ULL << 23),
|
||||
IsBot = (1ULL << 24),
|
||||
EmojiStatus = (1ULL << 25),
|
||||
StoriesState = (1ULL << 26),
|
||||
|
||||
// For chats and channels
|
||||
InviteLinks = (1ULL << 26),
|
||||
Members = (1ULL << 27),
|
||||
Admins = (1ULL << 28),
|
||||
BannedUsers = (1ULL << 29),
|
||||
Rights = (1ULL << 30),
|
||||
PendingRequests = (1ULL << 31),
|
||||
Reactions = (1ULL << 32),
|
||||
InviteLinks = (1ULL << 27),
|
||||
Members = (1ULL << 28),
|
||||
Admins = (1ULL << 29),
|
||||
BannedUsers = (1ULL << 30),
|
||||
Rights = (1ULL << 31),
|
||||
PendingRequests = (1ULL << 32),
|
||||
Reactions = (1ULL << 33),
|
||||
|
||||
// For channels
|
||||
ChannelAmIn = (1ULL << 33),
|
||||
StickersSet = (1ULL << 34),
|
||||
ChannelLinkedChat = (1ULL << 35),
|
||||
ChannelLocation = (1ULL << 36),
|
||||
Slowmode = (1ULL << 37),
|
||||
GroupCall = (1ULL << 38),
|
||||
ChannelAmIn = (1ULL << 34),
|
||||
StickersSet = (1ULL << 35),
|
||||
ChannelLinkedChat = (1ULL << 36),
|
||||
ChannelLocation = (1ULL << 37),
|
||||
Slowmode = (1ULL << 38),
|
||||
GroupCall = (1ULL << 39),
|
||||
|
||||
// For iteration
|
||||
LastUsedBit = (1ULL << 38),
|
||||
LastUsedBit = (1ULL << 39),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
|
|
@ -155,6 +155,7 @@ void UserData::setStoriesState(StoriesState state) {
|
|||
if (const auto history = owner().historyLoaded(this)) {
|
||||
history->updateChatListEntryPostponed();
|
||||
}
|
||||
session().changes().peerUpdated(this, UpdateFlag::StoriesState);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -488,6 +488,15 @@ infoMembersList: PeerList(defaultPeerList) {
|
|||
photoPosition: point(18px, 6px);
|
||||
namePosition: point(79px, 11px);
|
||||
statusPosition: point(79px, 31px);
|
||||
checkbox: RoundImageCheckbox(defaultPeerListCheckbox) {
|
||||
selectExtendTwice: 1px;
|
||||
imageRadius: 21px;
|
||||
imageSmallRadius: 19px;
|
||||
check: RoundCheckbox(defaultPeerListCheck) {
|
||||
size: 0px;
|
||||
}
|
||||
}
|
||||
nameFgChecked: contactsNameFg;
|
||||
}
|
||||
}
|
||||
infoMembersButtonPosition: point(12px, 0px);
|
||||
|
|
|
@ -50,6 +50,7 @@ Members::Members(
|
|||
, _controller(controller)
|
||||
, _peer(_controller->key().peer())
|
||||
, _listController(CreateMembersController(controller, _peer)) {
|
||||
_listController->setStoriesShown(true);
|
||||
setupHeader();
|
||||
setupList();
|
||||
setContent(_list.data());
|
||||
|
@ -232,6 +233,7 @@ void Members::setupButtons() {
|
|||
void Members::setupList() {
|
||||
auto topSkip = _header ? _header->height() : 0;
|
||||
_listController->setStyleOverrides(&st::infoMembersList);
|
||||
_listController->setStoriesShown(true);
|
||||
_list = object_ptr<ListWidget>(
|
||||
this,
|
||||
_listController.get());
|
||||
|
|
Loading…
Add table
Reference in a new issue