Added initial very limited implementation of peer list with widgets.

This commit is contained in:
23rd 2024-11-12 20:08:01 +03:00 committed by John Preston
parent 36fa455aad
commit 3042fb7299
3 changed files with 501 additions and 0 deletions

View File

@ -294,6 +294,8 @@ PRIVATE
boxes/peer_list_box.h
boxes/peer_list_controllers.cpp
boxes/peer_list_controllers.h
boxes/peer_list_widgets.cpp
boxes/peer_list_widgets.h
boxes/peer_lists_box.cpp
boxes/peer_lists_box.h
boxes/passcode_box.cpp

View File

@ -0,0 +1,389 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/peer_list_widgets.h"
#include "ui/painter.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h"
#include "styles/style_boxes.h"
namespace {
using State = std::unique_ptr<PeerListState>;
} // namespace
PeerListWidgets::PeerListWidgets(
not_null<Ui::RpWidget*> parent,
not_null<PeerListController*> controller)
: Ui::RpWidget(parent)
, _controller(controller)
, _st(controller->computeListSt()) {
_content = base::make_unique_q<Ui::VerticalLayout>(this);
parent->sizeValue() | rpl::start_with_next([this](const QSize &size) {
_content->resizeToWidth(size.width());
resize(size.width(), _content->height());
}, lifetime());
}
crl::time PeerListWidgets::paintRow(
Painter &p,
crl::time now,
bool selected,
not_null<PeerListRow*> row) {
const auto &st = row->computeSt(_st.item);
row->lazyInitialize(st);
const auto outerWidth = _content->width();
const auto w = outerWidth;
auto refreshStatusAt = row->refreshStatusTime();
if (refreshStatusAt > 0 && now >= refreshStatusAt) {
row->refreshStatus();
refreshStatusAt = row->refreshStatusTime();
}
const auto refreshStatusIn = (refreshStatusAt > 0)
? std::max(refreshStatusAt - now, crl::time(1))
: 0;
const auto peer = row->special() ? nullptr : row->peer().get();
row->paintUserpic(
p,
st,
st.photoPosition.x(),
st.photoPosition.y(),
outerWidth);
p.setPen(st::contactsNameFg);
const auto skipRight = st.photoPosition.x();
const auto rightActionSize = row->rightActionSize();
const auto rightActionMargins = rightActionSize.isEmpty()
? QMargins()
: row->rightActionMargins();
const auto &name = row->name();
const auto namePosition = st.namePosition;
const auto namex = namePosition.x();
const auto namey = namePosition.y();
auto namew = outerWidth - namex - skipRight;
if (!rightActionSize.isEmpty()
&& (namey < rightActionMargins.top() + rightActionSize.height())
&& (namey + st.nameStyle.font->height
> rightActionMargins.top())) {
namew -= rightActionMargins.left()
+ rightActionSize.width()
+ rightActionMargins.right()
- skipRight;
}
const auto statusx = st.statusPosition.x();
const auto statusy = st.statusPosition.y();
auto statusw = outerWidth - statusx - skipRight;
if (!rightActionSize.isEmpty()
&& (statusy < rightActionMargins.top() + rightActionSize.height())
&& (statusy + st::contactsStatusFont->height
> rightActionMargins.top())) {
statusw -= rightActionMargins.left()
+ rightActionSize.width()
+ rightActionMargins.right()
- skipRight;
}
namew -= row->paintNameIconGetWidth(
p,
[=] { updateRow(row); },
now,
namex,
namey,
name.maxWidth(),
namew,
w,
selected);
auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
p.setPen(anim::pen(st.nameFg, st.nameFgChecked, nameCheckedRatio));
name.drawLeftElided(p, namex, namey, namew, w);
p.setFont(st::contactsStatusFont);
row->paintStatusText(p, st, statusx, statusy, statusw, w, selected);
row->elementsPaint(p, outerWidth, selected, 0);
return refreshStatusIn;
}
void PeerListWidgets::appendRow(std::unique_ptr<PeerListRow> row) {
Expects(row != nullptr);
if (_rowsById.find(row->id()) == _rowsById.cend()) {
const auto raw = row.get();
const auto &st = raw->computeSt(_st.item);
raw->setAbsoluteIndex(_rows.size());
_rows.push_back(std::move(row));
const auto widget = _content->add(
object_ptr<Ui::AbstractButton>::fromRaw(
Ui::CreateSimpleSettingsButton(
_content.get(),
st.button.ripple,
st.button.textBgOver)));
widget->resize(widget->width(), st.height);
widget->paintRequest() | rpl::start_with_next([=, this] {
auto p = Painter(widget);
const auto selected = widget->isOver() || widget->isDown();
paintRow(p, crl::now(), selected, raw);
}, widget->lifetime());
widget->setClickedCallback([this, raw] {
_controller->rowClicked(raw);
});
}
}
PeerListRow *PeerListWidgets::findRow(PeerListRowId id) {
const auto it = _rowsById.find(id);
return (it == _rowsById.cend()) ? nullptr : it->second.get();
}
void PeerListWidgets::updateRow(not_null<PeerListRow*> row) {
const auto it = ranges::find_if(
_rows,
[row](const auto &r) { return r.get() == row; });
if (it != _rows.end()) {
const auto index = std::distance(_rows.begin(), it);
if (const auto widget = _content->widgetAt(index)) {
widget->update();
}
}
}
int PeerListWidgets::fullRowsCount() {
return _rows.size();
}
[[nodiscard]] not_null<PeerListRow*> PeerListWidgets::rowAt(int index) {
Expects(index >= 0 && index < _rows.size());
return _rows[index].get();
}
void PeerListWidgets::refreshRows() {
_content->resizeToWidth(width());
resize(width(), _content->height());
}
void PeerListWidgetsDelegate::setContent(PeerListWidgets *content) {
_content = content;
}
void PeerListWidgetsDelegate::setUiShow(
std::shared_ptr<Main::SessionShow> uiShow) {
_uiShow = std::move(uiShow);
}
void PeerListWidgetsDelegate::peerListSetHideEmpty(bool hide) {
Unexpected("...PeerListWidgetsDelegate::peerListSetHideEmpty");
}
void PeerListWidgetsDelegate::peerListAppendRow(
std::unique_ptr<PeerListRow> row) {
_content->appendRow(std::move(row));
}
void PeerListWidgetsDelegate::peerListAppendSearchRow(
std::unique_ptr<PeerListRow> row) {
Unexpected("...PeerListWidgetsDelegate::peerListAppendSearchRow");
}
void PeerListWidgetsDelegate::peerListAppendFoundRow(
not_null<PeerListRow*> row) {
Unexpected("...PeerListWidgetsDelegate::peerListAppendFoundRow");
}
void PeerListWidgetsDelegate::peerListPrependRow(
std::unique_ptr<PeerListRow> row) {
Unexpected("...PeerListWidgetsDelegate::peerListPrependRow");
}
void PeerListWidgetsDelegate::peerListPrependRowFromSearchResult(
not_null<PeerListRow*> row) {
Unexpected(
"...PeerListWidgetsDelegate::peerListPrependRowFromSearchResult");
}
PeerListRow* PeerListWidgetsDelegate::peerListFindRow(PeerListRowId id) {
return _content->findRow(id);
}
auto PeerListWidgetsDelegate::peerListLastRowMousePosition()
-> std::optional<QPoint> {
Unexpected("...PeerListWidgetsDelegate::peerListLastRowMousePosition");
}
void PeerListWidgetsDelegate::peerListUpdateRow(not_null<PeerListRow*> row) {
_content->updateRow(row);
}
void PeerListWidgetsDelegate::peerListRemoveRow(not_null<PeerListRow*> row) {
Unexpected("...PeerListWidgetsDelegate::peerListRemoveRow");
}
void PeerListWidgetsDelegate::peerListConvertRowToSearchResult(
not_null<PeerListRow*> row) {
Unexpected(
"...PeerListWidgetsDelegate::peerListConvertRowToSearchResult");
}
void PeerListWidgetsDelegate::peerListSetRowChecked(
not_null<PeerListRow*> row,
bool checked) {
Unexpected("...PeerListWidgetsDelegate::peerListSetRowChecked");
}
void PeerListWidgetsDelegate::peerListSetRowHidden(
not_null<PeerListRow*> row,
bool hidden) {
Unexpected("...PeerListWidgetsDelegate::peerListSetRowHidden");
}
void PeerListWidgetsDelegate::peerListSetForeignRowChecked(
not_null<PeerListRow*> row,
bool checked,
anim::type animated) {
}
int PeerListWidgetsDelegate::peerListFullRowsCount() {
return _content->fullRowsCount();
}
not_null<PeerListRow*> PeerListWidgetsDelegate::peerListRowAt(int index) {
return _content->rowAt(index);
}
int PeerListWidgetsDelegate::peerListSearchRowsCount() {
Unexpected("...PeerListWidgetsDelegate::peerListSearchRowsCount");
}
not_null<PeerListRow*> PeerListWidgetsDelegate::peerListSearchRowAt(int) {
Unexpected("...PeerListWidgetsDelegate::peerListSearchRowAt");
}
void PeerListWidgetsDelegate::peerListRefreshRows() {
_content->refreshRows();
}
void PeerListWidgetsDelegate::peerListSetDescription(
object_ptr<Ui::FlatLabel>) {
Unexpected("...PeerListWidgetsDelegate::peerListSetDescription");
}
void PeerListWidgetsDelegate::peerListSetSearchNoResults(
object_ptr<Ui::FlatLabel>) {
Unexpected("...PeerListWidgetsDelegate::peerListSetSearchNoResults");
}
void PeerListWidgetsDelegate::peerListSetAboveWidget(
object_ptr<Ui::RpWidget>) {
Unexpected("...PeerListWidgetsDelegate::peerListSetAboveWidget");
}
void PeerListWidgetsDelegate::peerListSetAboveSearchWidget(
object_ptr<Ui::RpWidget>) {
Unexpected("...PeerListWidgetsDelegate::peerListSetAboveSearchWidget");
}
void PeerListWidgetsDelegate::peerListSetBelowWidget(
object_ptr<Ui::RpWidget>) {
Unexpected("...PeerListWidgetsDelegate::peerListSetBelowWidget");
}
void PeerListWidgetsDelegate::peerListSetSearchMode(PeerListSearchMode mode) {
Unexpected("...PeerListWidgetsDelegate::peerListSetSearchMode");
}
void PeerListWidgetsDelegate::peerListMouseLeftGeometry() {
Unexpected("...PeerListWidgetsDelegate::peerListMouseLeftGeometry");
}
void PeerListWidgetsDelegate::peerListSortRows(
Fn<bool(const PeerListRow &, const PeerListRow &)>) {
Unexpected("...PeerListWidgetsDelegate::peerListSortRows");
}
int PeerListWidgetsDelegate::peerListPartitionRows(
Fn<bool(const PeerListRow &a)> border) {
Unexpected("...PeerListWidgetsDelegate::peerListPartitionRows");
}
State PeerListWidgetsDelegate::peerListSaveState() const {
Unexpected("...PeerListWidgetsDelegate::peerListSaveState");
return nullptr;
}
void PeerListWidgetsDelegate::peerListRestoreState(
std::unique_ptr<PeerListState> state) {
Unexpected("...PeerListWidgetsDelegate::peerListRestoreState");
}
void PeerListWidgetsDelegate::peerListShowRowMenu(
not_null<PeerListRow*> row,
bool highlightRow,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed) {
}
void PeerListWidgetsDelegate::peerListSelectSkip(int direction) {
// _content->selectSkip(direction);
}
void PeerListWidgetsDelegate::peerListPressLeftToContextMenu(bool shown) {
Unexpected("...PeerListWidgetsDelegate::peerListPressLeftToContextMenu");
}
bool PeerListWidgetsDelegate::peerListTrackRowPressFromGlobal(QPoint) {
return false;
}
std::shared_ptr<Main::SessionShow> PeerListWidgetsDelegate::peerListUiShow() {
Expects(_uiShow != nullptr);
return _uiShow;
}
void PeerListWidgetsDelegate::peerListAddSelectedPeerInBunch(
not_null<PeerData*> peer) {
Unexpected("...PeerListWidgetsDelegate::peerListAddSelectedPeerInBunch");
}
void PeerListWidgetsDelegate::peerListAddSelectedRowInBunch(
not_null<PeerListRow*> row) {
Unexpected("...PeerListWidgetsDelegate::peerListAddSelectedRowInBunch");
}
void PeerListWidgetsDelegate::peerListFinishSelectedRowsBunch() {
Unexpected("...PeerListWidgetsDelegate::peerListFinishSelectedRowsBunch");
}
void PeerListWidgetsDelegate::peerListSetTitle(rpl::producer<QString> title) {
Unexpected("...PeerListWidgetsDelegate::peerListSetTitle");
}
void PeerListWidgetsDelegate::peerListSetAdditionalTitle(
rpl::producer<QString> title) {
Unexpected("...PeerListWidgetsDelegate::peerListSetAdditionalTitle");
}
bool PeerListWidgetsDelegate::peerListIsRowChecked(
not_null<PeerListRow*> row) {
Unexpected("...PeerListWidgetsDelegate::peerListIsRowChecked");
return false;
}
void PeerListWidgetsDelegate::peerListScrollToTop() {
Unexpected("...PeerListWidgetsDelegate::peerListScrollToTop");
}
int PeerListWidgetsDelegate::peerListSelectedRowsCount() {
Unexpected("...PeerListWidgetsDelegate::peerListSelectedRowsCount");
return 0;
}

View File

@ -0,0 +1,110 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/peer_list_box.h"
namespace Ui {
class VerticalLayout;
} // namespace Ui
class PeerListWidgets : public Ui::RpWidget {
public:
PeerListWidgets(
not_null<Ui::RpWidget*> parent,
not_null<PeerListController*> controller);
crl::time paintRow(
Painter &p,
crl::time now,
bool selected,
not_null<PeerListRow*> row);
void appendRow(std::unique_ptr<PeerListRow> row);
PeerListRow* findRow(PeerListRowId id);
void updateRow(not_null<PeerListRow*> row);
int fullRowsCount();
[[nodiscard]] not_null<PeerListRow*> rowAt(int index);
void refreshRows();
private:
const not_null<PeerListController*> _controller;
const style::PeerList &_st;
base::unique_qptr<Ui::VerticalLayout> _content;
std::vector<std::unique_ptr<PeerListRow>> _rows;
std::map<PeerListRowId, not_null<PeerListRow*>> _rowsById;
std::map<PeerData*, std::vector<not_null<PeerListRow*>>> _rowsByPeer;
};
class PeerListWidgetsDelegate : public PeerListDelegate {
public:
void setContent(PeerListWidgets *content);
void setUiShow(std::shared_ptr<Main::SessionShow> uiShow);
void peerListSetHideEmpty(bool hide) override;
void peerListAppendRow(std::unique_ptr<PeerListRow> row) override;
void peerListAppendSearchRow(std::unique_ptr<PeerListRow> row) override;
void peerListAppendFoundRow(not_null<PeerListRow*> row) override;
void peerListPrependRow(std::unique_ptr<PeerListRow> row) override;
void peerListPrependRowFromSearchResult(
not_null<PeerListRow*> row) override;
PeerListRow *peerListFindRow(PeerListRowId id) override;
std::optional<QPoint> peerListLastRowMousePosition() override;
void peerListUpdateRow(not_null<PeerListRow*> row) override;
void peerListRemoveRow(not_null<PeerListRow*> row) override;
void peerListConvertRowToSearchResult(
not_null<PeerListRow*> row) override;
void peerListSetRowChecked(
not_null<PeerListRow*> row,
bool checked) override;
void peerListSetRowHidden(
not_null<PeerListRow*> row,
bool hidden) override;
void peerListSetForeignRowChecked(
not_null<PeerListRow*> row,
bool checked,
anim::type animated) override;
int peerListFullRowsCount() override;
not_null<PeerListRow*> peerListRowAt(int index) override;
int peerListSearchRowsCount() override;
not_null<PeerListRow*> peerListSearchRowAt(int index) override;
void peerListRefreshRows() override;
void peerListSetDescription(object_ptr<Ui::FlatLabel>) override;
void peerListSetSearchNoResults(object_ptr<Ui::FlatLabel>) override;
void peerListSetAboveWidget(object_ptr<Ui::RpWidget>) override;
void peerListSetAboveSearchWidget(object_ptr<Ui::RpWidget>) override;
void peerListSetBelowWidget(object_ptr<Ui::RpWidget>) override;
void peerListSetSearchMode(PeerListSearchMode mode) override;
void peerListMouseLeftGeometry() override;
void peerListSortRows(
Fn<bool(const PeerListRow &, const PeerListRow &)>) override;
int peerListPartitionRows(Fn<bool(const PeerListRow &a)> border) override;
std::unique_ptr<PeerListState> peerListSaveState() const override;
void peerListRestoreState(std::unique_ptr<PeerListState> state) override;
void peerListShowRowMenu(
not_null<PeerListRow*> row,
bool highlightRow,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) override;
void peerListSelectSkip(int direction) override;
void peerListPressLeftToContextMenu(bool shown) override;
bool peerListTrackRowPressFromGlobal(QPoint globalPosition) override;
std::shared_ptr<Main::SessionShow> peerListUiShow() override;
void peerListAddSelectedPeerInBunch(not_null<PeerData*> peer) override;
void peerListAddSelectedRowInBunch(not_null<PeerListRow*> row) override;
void peerListFinishSelectedRowsBunch() override;
void peerListSetTitle(rpl::producer<QString> title) override;
void peerListSetAdditionalTitle(rpl::producer<QString> title) override;
bool peerListIsRowChecked(not_null<PeerListRow*> row) override;
void peerListScrollToTop() override;
int peerListSelectedRowsCount() override;
private:
PeerListWidgets *_content = nullptr;
std::shared_ptr<Main::SessionShow> _uiShow;
};