mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Add blocked users box to Settings.
Start a general PeerListBox, it should replace both ContactsBox and MembersBox in the future. Show blocked users list in it.
This commit is contained in:
parent
6873d53993
commit
b1ee91b06b
12 changed files with 1051 additions and 69 deletions
|
@ -403,6 +403,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
"lng_connection_user_ph" = "Username";
|
||||
"lng_connection_password_ph" = "Password";
|
||||
"lng_connection_save" = "Save";
|
||||
|
||||
"lng_settings_blocked_users" = "Blocked users";
|
||||
"lng_settings_show_sessions" = "Show all sessions";
|
||||
"lng_settings_reset" = "Terminate all other sessions";
|
||||
"lng_settings_reset_sure" = "Are you sure you want to terminate\nall other sessions?";
|
||||
|
@ -428,6 +430,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
"lng_sessions_other_desc" = "You can log in to Telegram from other mobile, tablet and desktop devices, using the same phone number. All your data will be instantly synchronized.";
|
||||
"lng_sessions_terminate_all" = "Terminate all other sessions";
|
||||
|
||||
"lng_blocked_list_title" = "Blocked users";
|
||||
"lng_blocked_list_unknown_phone" = "unknown phone";
|
||||
"lng_blocked_list_unblock" = "Unblock";
|
||||
"lng_blocked_list_add" = "Block user";
|
||||
"lng_blocked_list_about" = "Blocked users can't send you messages or add you to groups. They will not see your profile pictures, online and last seen status.";
|
||||
|
||||
"lng_preview_loading" = "Getting Link Info...";
|
||||
|
||||
"lng_profile_chat_unaccessible" = "Group is inaccessible";
|
||||
|
|
|
@ -62,17 +62,6 @@ public:
|
|||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
}
|
||||
|
||||
void setDelegate(BoxContentDelegate *newDelegate) {
|
||||
_delegate = newDelegate;
|
||||
prepare();
|
||||
setInnerFocus();
|
||||
}
|
||||
virtual void setInnerFocus() {
|
||||
setFocus();
|
||||
}
|
||||
virtual void closeHook() {
|
||||
}
|
||||
|
||||
bool isBoxShown() const {
|
||||
return getDelegate()->isBoxShown();
|
||||
}
|
||||
|
@ -80,17 +69,6 @@ public:
|
|||
getDelegate()->closeBox();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void onScrollToY(int top, int bottom = -1);
|
||||
|
||||
void onDraggingScrollDelta(int delta);
|
||||
|
||||
protected:
|
||||
virtual void prepare() = 0;
|
||||
|
||||
void setLayerType(bool layerType) {
|
||||
getDelegate()->setLayerType(layerType);
|
||||
}
|
||||
void setTitle(const QString &title, const QString &additional = QString()) {
|
||||
getDelegate()->setTitle(title, additional);
|
||||
}
|
||||
|
@ -107,6 +85,30 @@ protected:
|
|||
getDelegate()->updateButtonsPositions();
|
||||
}
|
||||
|
||||
virtual void setInnerFocus() {
|
||||
setFocus();
|
||||
}
|
||||
virtual void closeHook() {
|
||||
}
|
||||
|
||||
void setDelegate(BoxContentDelegate *newDelegate) {
|
||||
_delegate = newDelegate;
|
||||
prepare();
|
||||
setInnerFocus();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void onScrollToY(int top, int bottom = -1);
|
||||
|
||||
void onDraggingScrollDelta(int delta);
|
||||
|
||||
protected:
|
||||
virtual void prepare() = 0;
|
||||
|
||||
void setLayerType(bool layerType) {
|
||||
getDelegate()->setLayerType(layerType);
|
||||
}
|
||||
|
||||
void setNoContentMargin(bool noContentMargin) {
|
||||
if (_noContentMargin != noContentMargin) {
|
||||
_noContentMargin = noContentMargin;
|
||||
|
|
|
@ -34,31 +34,33 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "auth_session.h"
|
||||
#include "storage/file_download.h"
|
||||
|
||||
MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||
, _st(st) {
|
||||
resize(_st.width, _st.height);
|
||||
setCursor(style::cur_pointer);
|
||||
}
|
||||
|
||||
void MembersAddButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
auto ms = getms();
|
||||
auto over = isOver();
|
||||
auto down = isDown();
|
||||
|
||||
((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||
}
|
||||
|
||||
QImage MembersAddButton::prepareRippleMask() const {
|
||||
return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||
}
|
||||
|
||||
QPoint MembersAddButton::prepareRippleStartPosition() const {
|
||||
return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||
}
|
||||
// Not used for now.
|
||||
//
|
||||
//MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||
//, _st(st) {
|
||||
// resize(_st.width, _st.height);
|
||||
// setCursor(style::cur_pointer);
|
||||
//}
|
||||
//
|
||||
//void MembersAddButton::paintEvent(QPaintEvent *e) {
|
||||
// Painter p(this);
|
||||
//
|
||||
// auto ms = getms();
|
||||
// auto over = isOver();
|
||||
// auto down = isDown();
|
||||
//
|
||||
// ((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||
// paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
// ((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||
//}
|
||||
//
|
||||
//QImage MembersAddButton::prepareRippleMask() const {
|
||||
// return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||
//}
|
||||
//
|
||||
//QPoint MembersAddButton::prepareRippleStartPosition() const {
|
||||
// return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||
//}
|
||||
|
||||
MembersBox::MembersBox(QWidget*, ChannelData *channel, MembersFilter filter)
|
||||
: _channel(channel)
|
||||
|
|
|
@ -34,20 +34,22 @@ enum class MembersFilter {
|
|||
};
|
||||
using MembersAlreadyIn = OrderedSet<UserData*>;
|
||||
|
||||
class MembersAddButton : public Ui::RippleButton {
|
||||
public:
|
||||
MembersAddButton(QWidget *parent, const style::TwoIconButton &st);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
QPoint prepareRippleStartPosition() const override;
|
||||
|
||||
private:
|
||||
const style::TwoIconButton &_st;
|
||||
|
||||
};
|
||||
// Not used for now.
|
||||
//
|
||||
//class MembersAddButton : public Ui::RippleButton {
|
||||
//public:
|
||||
// MembersAddButton(QWidget *parent, const style::TwoIconButton &st);
|
||||
//
|
||||
//protected:
|
||||
// void paintEvent(QPaintEvent *e) override;
|
||||
//
|
||||
// QImage prepareRippleMask() const override;
|
||||
// QPoint prepareRippleStartPosition() const override;
|
||||
//
|
||||
//private:
|
||||
// const style::TwoIconButton &_st;
|
||||
//
|
||||
//};
|
||||
|
||||
class MembersBox : public BoxContent {
|
||||
Q_OBJECT
|
||||
|
|
518
Telegram/SourceFiles/boxes/peer_list_box.cpp
Normal file
518
Telegram/SourceFiles/boxes/peer_list_box.cpp
Normal file
|
@ -0,0 +1,518 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "boxes/peer_list_box.h"
|
||||
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "observer_peer.h"
|
||||
#include "auth_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "storage/file_download.h"
|
||||
|
||||
PeerListBox::PeerListBox(QWidget*, std::unique_ptr<Controller> controller)
|
||||
: _controller(std::move(controller)) {
|
||||
}
|
||||
|
||||
void PeerListBox::prepare() {
|
||||
_inner = setInnerWidget(object_ptr<Inner>(this, _controller.get()), st::boxLayerScroll);
|
||||
|
||||
_controller->setView(this);
|
||||
|
||||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||
|
||||
connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int)));
|
||||
}
|
||||
|
||||
void PeerListBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Down) {
|
||||
_inner->selectSkip(1);
|
||||
} else if (e->key() == Qt::Key_Up) {
|
||||
_inner->selectSkip(-1);
|
||||
} else if (e->key() == Qt::Key_PageDown) {
|
||||
_inner->selectSkipPage(height(), 1);
|
||||
} else if (e->key() == Qt::Key_PageUp) {
|
||||
_inner->selectSkipPage(height(), -1);
|
||||
} else {
|
||||
BoxContent::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_inner->resize(width(), _inner->height());
|
||||
}
|
||||
|
||||
void PeerListBox::appendRow(std::unique_ptr<Row> row) {
|
||||
_inner->appendRow(std::move(row));
|
||||
}
|
||||
|
||||
void PeerListBox::prependRow(std::unique_ptr<Row> row) {
|
||||
_inner->prependRow(std::move(row));
|
||||
}
|
||||
|
||||
PeerListBox::Row *PeerListBox::findRow(PeerData *peer) {
|
||||
return _inner->findRow(peer);
|
||||
}
|
||||
|
||||
void PeerListBox::updateRow(Row *row) {
|
||||
_inner->updateRow(row);
|
||||
}
|
||||
|
||||
void PeerListBox::removeRow(Row *row) {
|
||||
_inner->removeRow(row);
|
||||
}
|
||||
|
||||
void PeerListBox::setAboutText(const QString &aboutText) {
|
||||
_inner->setAboutText(aboutText);
|
||||
}
|
||||
|
||||
void PeerListBox::refreshRows() {
|
||||
_inner->refreshRows();
|
||||
}
|
||||
|
||||
PeerListBox::Row::Row(PeerData *peer) : _peer(peer) {
|
||||
}
|
||||
|
||||
void PeerListBox::Row::setDisabled(bool disabled) {
|
||||
_disabled = disabled;
|
||||
}
|
||||
|
||||
void PeerListBox::Row::setActionLink(const QString &action) {
|
||||
_action = action;
|
||||
refreshActionLink();
|
||||
}
|
||||
|
||||
void PeerListBox::Row::refreshActionLink() {
|
||||
if (!_initialized) return;
|
||||
_actionWidth = _action.isEmpty() ? 0 : st::normalFont->width(_action);
|
||||
}
|
||||
|
||||
void PeerListBox::Row::setCustomStatus(const QString &status) {
|
||||
_status = status;
|
||||
_statusType = StatusType::Custom;
|
||||
}
|
||||
|
||||
void PeerListBox::Row::clearCustomStatus() {
|
||||
_statusType = StatusType::Online;
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
void PeerListBox::Row::refreshStatus() {
|
||||
if (!_initialized || _statusType == StatusType::Custom) {
|
||||
return;
|
||||
}
|
||||
if (auto user = peer()->asUser()) {
|
||||
auto time = unixtime();
|
||||
_status = App::onlineText(user, time);
|
||||
_statusType = App::onlineColorUse(user, time) ? StatusType::Online : StatusType::LastSeen;
|
||||
}
|
||||
}
|
||||
|
||||
PeerListBox::Row::StatusType PeerListBox::Row::statusType() const {
|
||||
return _statusType;
|
||||
}
|
||||
|
||||
void PeerListBox::Row::refreshName() {
|
||||
if (!_initialized) {
|
||||
return;
|
||||
}
|
||||
_name.setText(st::contactsNameStyle, peer()->name, _textNameOptions);
|
||||
}
|
||||
|
||||
QString PeerListBox::Row::status() const {
|
||||
return _status;
|
||||
}
|
||||
|
||||
QString PeerListBox::Row::action() const {
|
||||
return _action;
|
||||
}
|
||||
|
||||
int PeerListBox::Row::actionWidth() const {
|
||||
return _actionWidth;
|
||||
}
|
||||
|
||||
PeerListBox::Row::~Row() = default;
|
||||
|
||||
template <typename UpdateCallback>
|
||||
void PeerListBox::Row::addRipple(QSize size, QPoint point, UpdateCallback updateCallback) {
|
||||
if (!_ripple) {
|
||||
auto mask = Ui::RippleAnimation::rectMask(size);
|
||||
_ripple = std::make_unique<Ui::RippleAnimation>(st::contactsRipple, std::move(mask), std::move(updateCallback));
|
||||
}
|
||||
_ripple->add(point);
|
||||
}
|
||||
|
||||
void PeerListBox::Row::stopLastRipple() {
|
||||
if (_ripple) {
|
||||
_ripple->lastStop();
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Row::paintRipple(Painter &p, int x, int y, int outerWidth, TimeMs ms) {
|
||||
if (_ripple) {
|
||||
_ripple->paint(p, x, y, outerWidth, ms);
|
||||
if (_ripple->empty()) {
|
||||
_ripple.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Row::lazyInitialize() {
|
||||
if (_initialized) {
|
||||
return;
|
||||
}
|
||||
_initialized = true;
|
||||
refreshActionLink();
|
||||
refreshName();
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
PeerListBox::Inner::Inner(QWidget *parent, Controller *controller) : TWidget(parent)
|
||||
, _controller(controller)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
|
||||
, _about(_aboutWidth) {
|
||||
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::appendRow(std::unique_ptr<Row> row) {
|
||||
if (!_rowsByPeer.contains(row->peer())) {
|
||||
row->setIndex(_rows.size());
|
||||
_rowsByPeer.insert(row->peer(), row.get());
|
||||
_rows.push_back(std::move(row));
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::prependRow(std::unique_ptr<Row> row) {
|
||||
if (!_rowsByPeer.contains(row->peer())) {
|
||||
_rowsByPeer.insert(row->peer(), row.get());
|
||||
_rows.insert(_rows.begin(), std::move(row));
|
||||
auto index = 0;
|
||||
for (auto &row : _rows) {
|
||||
row->setIndex(index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PeerListBox::Row *PeerListBox::Inner::findRow(PeerData *peer) {
|
||||
return _rowsByPeer.value(peer, nullptr);
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::updateRow(Row *row) {
|
||||
updateRowWithIndex(row->index());
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::removeRow(Row *row) {
|
||||
auto index = row->index();
|
||||
t_assert(index >= 0 && index < _rows.size());
|
||||
t_assert(_rows[index].get() == row);
|
||||
|
||||
clearSelection();
|
||||
|
||||
_rowsByPeer.remove(row->peer());
|
||||
_rows.erase(_rows.begin() + index);
|
||||
for (auto i = index, count = int(_rows.size()); i != count; ++i) {
|
||||
_rows[i]->setIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::setAboutText(const QString &aboutText) {
|
||||
_about.setText(st::boxLabelStyle, aboutText);
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::refreshRows() {
|
||||
if (!_about.isEmpty()) {
|
||||
_aboutHeight = st::membersAboutLimitPadding.top() + _about.countHeight(_aboutWidth) + st::membersAboutLimitPadding.bottom();
|
||||
} else {
|
||||
_aboutHeight = 0;
|
||||
}
|
||||
if (_rows.empty()) {
|
||||
resize(width(), st::membersMarginTop + _rowHeight + _aboutHeight + st::membersMarginBottom);
|
||||
} else {
|
||||
resize(width(), st::membersMarginTop + _rows.size() * _rowHeight + _aboutHeight + st::membersMarginBottom);
|
||||
}
|
||||
if (_visibleBottom > 0) {
|
||||
checkScrollForPreload();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::paintEvent(QPaintEvent *e) {
|
||||
QRect r(e->rect());
|
||||
Painter p(this);
|
||||
|
||||
p.fillRect(r, st::contactsBg);
|
||||
|
||||
auto ms = getms();
|
||||
auto yFrom = r.y() - st::membersMarginTop;
|
||||
auto yTo = r.y() + r.height() - st::membersMarginTop;
|
||||
p.translate(0, st::membersMarginTop);
|
||||
if (_rows.empty()) {
|
||||
if (!_about.isEmpty()) {
|
||||
p.setPen(st::membersAboutLimitFg);
|
||||
_about.draw(p, st::contactsPadding.left(), _rowHeight + st::membersAboutLimitPadding.top(), _aboutWidth, style::al_center);
|
||||
}
|
||||
} else {
|
||||
auto from = floorclamp(yFrom, _rowHeight, 0, _rows.size());
|
||||
auto to = ceilclamp(yTo, _rowHeight, 0, _rows.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (auto index = from; index != to; ++index) {
|
||||
paintRow(p, ms, index);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
if (!_about.isEmpty() && to == _rows.size()) {
|
||||
p.setPen(st::membersAboutLimitFg);
|
||||
_about.draw(p, st::contactsPadding.left(), st::membersAboutLimitPadding.top(), _aboutWidth, style::al_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::enterEventHook(QEvent *e) {
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::leaveEventHook(QEvent *e) {
|
||||
_mouseSelection = false;
|
||||
setMouseTracking(false);
|
||||
if (_selected.index >= 0) {
|
||||
clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
_mouseSelection = true;
|
||||
_lastMousePosition = e->globalPos();
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||
_mouseSelection = true;
|
||||
_lastMousePosition = e->globalPos();
|
||||
updateSelection();
|
||||
setPressed(_selected);
|
||||
if (_selected.index >= 0 && _selected.index < _rows.size() && !_selected.action) {
|
||||
auto size = QSize(width(), _rowHeight);
|
||||
auto point = mapFromGlobal(QCursor::pos()) - QPoint(0, getRowTop(_selected.index));
|
||||
auto row = _rows[_selected.index].get();
|
||||
row->addRipple(size, point, [this, row] {
|
||||
updateRow(row);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
updateRowWithIndex(_pressed.index);
|
||||
updateRowWithIndex(_selected.index);
|
||||
auto pressed = _pressed;
|
||||
setPressed(SelectedRow());
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
if (pressed == _selected && pressed.index >= 0) {
|
||||
if (pressed.action) {
|
||||
_controller->rowActionClicked(_rows[pressed.index]->peer());
|
||||
} else {
|
||||
_controller->rowClicked(_rows[pressed.index]->peer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::setPressed(SelectedRow pressed) {
|
||||
if (_pressed.index >= 0 && _pressed.index < _rows.size()) {
|
||||
_rows[_pressed.index]->stopLastRipple();
|
||||
}
|
||||
_pressed = pressed;
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::paintRow(Painter &p, TimeMs ms, int index) {
|
||||
t_assert(index >= 0 && index < _rows.size());
|
||||
auto row = _rows[index].get();
|
||||
row->lazyInitialize();
|
||||
|
||||
auto peer = row->peer();
|
||||
auto user = peer->asUser();
|
||||
auto active = (_pressed.index >= 0) ? _pressed : _selected;
|
||||
auto selected = (active.index == index);
|
||||
auto actionSelected = (selected && active.action);
|
||||
|
||||
p.fillRect(0, 0, width(), _rowHeight, selected ? st::contactsBgOver : st::contactsBg);
|
||||
row->paintRipple(p, 0, 0, width(), ms);
|
||||
peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize);
|
||||
|
||||
p.setPen(st::contactsNameFg);
|
||||
|
||||
auto actionWidth = row->actionWidth();
|
||||
auto &name = row->name();
|
||||
auto namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
auto namew = width() - namex - st::contactsPadding.right() - (actionWidth ? (actionWidth + st::contactsCheckPosition.x() * 2) : 0);
|
||||
if (peer->isVerified()) {
|
||||
auto icon = &st::dialogsVerifiedIcon;
|
||||
namew -= icon->width();
|
||||
icon->paint(p, namex + qMin(name.maxWidth(), namew), st::contactsPadding.top() + st::contactsNameTop, width());
|
||||
}
|
||||
name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width());
|
||||
|
||||
if (actionWidth) {
|
||||
p.setFont(actionSelected ? st::linkOverFont : st::linkFont);
|
||||
p.setPen(actionSelected ? st::defaultLinkButton.overColor : st::defaultLinkButton.color);
|
||||
auto actionRight = st::contactsPadding.right() + st::contactsCheckPosition.x();
|
||||
auto actionTop = (_rowHeight - st::normalFont->height) / 2;
|
||||
p.drawTextRight(actionRight, actionTop, width(), row->action(), actionWidth);
|
||||
}
|
||||
|
||||
auto statusHasOnlineColor = (row->statusType() == Row::StatusType::Online);
|
||||
p.setFont(st::contactsStatusFont);
|
||||
p.setPen(statusHasOnlineColor ? st::contactsStatusFgOnline : (selected ? st::contactsStatusFgOver : st::contactsStatusFg));
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), row->status());
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::selectSkip(int32 dir) {
|
||||
_mouseSelection = false;
|
||||
|
||||
auto newSelectedIndex = _selected.index + dir;
|
||||
if (newSelectedIndex <= 0) {
|
||||
newSelectedIndex = _rows.empty() ? -1 : 0;
|
||||
} else if (newSelectedIndex >= _rows.size()) {
|
||||
newSelectedIndex = -1;
|
||||
}
|
||||
if (dir > 0) {
|
||||
if (newSelectedIndex < 0 || newSelectedIndex >= _rows.size()) {
|
||||
newSelectedIndex = -1;
|
||||
}
|
||||
} else if (!_rows.empty()) {
|
||||
if (newSelectedIndex < 0) {
|
||||
newSelectedIndex = _rows.size() - 1;
|
||||
}
|
||||
}
|
||||
_selected.index = newSelectedIndex;
|
||||
_selected.action = false;
|
||||
if (newSelectedIndex >= 0) {
|
||||
emit mustScrollTo(st::membersMarginTop + newSelectedIndex * _rowHeight, st::membersMarginTop + (newSelectedIndex + 1) * _rowHeight);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::selectSkipPage(int32 h, int32 dir) {
|
||||
auto rowsToSkip = h / _rowHeight;
|
||||
if (!rowsToSkip) return;
|
||||
selectSkip(rowsToSkip * dir);
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::loadProfilePhotos() {
|
||||
if (_visibleTop >= _visibleBottom) return;
|
||||
|
||||
auto yFrom = _visibleTop;
|
||||
auto yTo = _visibleBottom + (_visibleBottom - _visibleTop) * PreloadHeightsCount;
|
||||
AuthSession::Current().downloader()->clearPriorities();
|
||||
|
||||
if (yTo < 0) return;
|
||||
if (yFrom < 0) yFrom = 0;
|
||||
|
||||
if (!_rows.empty()) {
|
||||
auto from = yFrom / _rowHeight;
|
||||
if (from < 0) from = 0;
|
||||
if (from < _rows.size()) {
|
||||
auto to = (yTo / _rowHeight) + 1;
|
||||
if (to > _rows.size()) to = _rows.size();
|
||||
|
||||
for (auto index = from; index != to; ++index) {
|
||||
_rows[index]->peer()->loadUserpic();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::checkScrollForPreload() {
|
||||
if (_visibleBottom + PreloadHeightsCount * (_visibleBottom - _visibleTop) > height()) {
|
||||
_controller->preloadRows();
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
||||
_visibleTop = visibleTop;
|
||||
_visibleBottom = visibleBottom;
|
||||
loadProfilePhotos();
|
||||
checkScrollForPreload();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::clearSelection() {
|
||||
updateRowWithIndex(_selected.index);
|
||||
_selected = SelectedRow();
|
||||
_lastMousePosition = QCursor::pos();
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::updateSelection() {
|
||||
if (!_mouseSelection) return;
|
||||
|
||||
auto point = mapFromGlobal(_lastMousePosition);
|
||||
point.setY(point.y() - st::membersMarginTop);
|
||||
auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePosition));
|
||||
auto selected = SelectedRow();
|
||||
selected.index = (in && point.y() >= 0 && point.y() < _rows.size() * _rowHeight) ? (point.y() / _rowHeight) : -1;
|
||||
if (selected.index >= 0) {
|
||||
auto actionRight = st::contactsPadding.right() + st::contactsCheckPosition.x();
|
||||
auto actionTop = (_rowHeight - st::normalFont->height) / 2;
|
||||
auto actionWidth = _rows[selected.index]->actionWidth();
|
||||
auto actionLeft = width() - actionWidth - actionRight;
|
||||
auto rowTop = selected.index * _rowHeight;
|
||||
auto actionRect = myrtlrect(actionLeft, rowTop + actionTop, actionWidth, st::normalFont->height);
|
||||
if (actionRect.contains(point)) {
|
||||
selected.action = true;
|
||||
}
|
||||
}
|
||||
if (_selected != selected) {
|
||||
updateRowWithIndex(_selected.index);
|
||||
_selected = selected;
|
||||
updateRowWithIndex(_selected.index);
|
||||
setCursor(_selected.action ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::peerUpdated(PeerData *peer) {
|
||||
update();
|
||||
}
|
||||
|
||||
int PeerListBox::Inner::getRowTop(int index) const {
|
||||
if (index >= 0) {
|
||||
return st::membersMarginTop + index * _rowHeight;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::updateRowWithIndex(int index) {
|
||||
if (index >= 0) {
|
||||
update(0, getRowTop(index), width(), _rowHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||
if (auto row = findRow(peer)) {
|
||||
row->refreshName();
|
||||
update(0, st::membersMarginTop + row->index() * _rowHeight, width(), _rowHeight);
|
||||
}
|
||||
}
|
232
Telegram/SourceFiles/boxes/peer_list_box.h
Normal file
232
Telegram/SourceFiles/boxes/peer_list_box.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstractbox.h"
|
||||
|
||||
namespace Ui {
|
||||
class RippleAnimation;
|
||||
} // namespace Ui
|
||||
|
||||
class PeerListBox : public BoxContent {
|
||||
Q_OBJECT
|
||||
|
||||
class Inner;
|
||||
|
||||
public:
|
||||
class Row {
|
||||
public:
|
||||
Row(PeerData *peer);
|
||||
|
||||
void setDisabled(bool disabled);
|
||||
|
||||
void setActionLink(const QString &action);
|
||||
PeerData *peer() const {
|
||||
return _peer;
|
||||
}
|
||||
|
||||
void setCustomStatus(const QString &status);
|
||||
void clearCustomStatus();
|
||||
|
||||
virtual ~Row();
|
||||
|
||||
private:
|
||||
// Inner interface.
|
||||
friend class Inner;
|
||||
|
||||
void refreshName();
|
||||
const Text &name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
enum class StatusType {
|
||||
Online,
|
||||
LastSeen,
|
||||
Custom,
|
||||
};
|
||||
void refreshStatus();
|
||||
StatusType statusType() const;
|
||||
QString status() const;
|
||||
|
||||
void refreshActionLink();
|
||||
QString action() const;
|
||||
int actionWidth() const;
|
||||
|
||||
void setIndex(int index) {
|
||||
_index = index;
|
||||
}
|
||||
int index() const {
|
||||
return _index;
|
||||
}
|
||||
|
||||
template <typename UpdateCallback>
|
||||
void addRipple(QSize size, QPoint point, UpdateCallback updateCallback);
|
||||
void stopLastRipple();
|
||||
void paintRipple(Painter &p, int x, int y, int outerWidth, TimeMs ms);
|
||||
|
||||
void lazyInitialize();
|
||||
|
||||
private:
|
||||
PeerData *_peer = nullptr;
|
||||
bool _initialized = false;
|
||||
std::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||
Text _name;
|
||||
QString _status;
|
||||
StatusType _statusType = StatusType::Online;
|
||||
QString _action;
|
||||
int _actionWidth = 0;
|
||||
bool _disabled = false;
|
||||
int _index = -1;
|
||||
|
||||
};
|
||||
|
||||
class Controller {
|
||||
public:
|
||||
virtual void prepare() = 0;
|
||||
virtual void rowClicked(PeerData *peer) = 0;
|
||||
virtual void rowActionClicked(PeerData *peer) {
|
||||
}
|
||||
virtual void preloadRows() {
|
||||
}
|
||||
|
||||
virtual ~Controller() = default;
|
||||
|
||||
protected:
|
||||
PeerListBox *view() const {
|
||||
return _view;
|
||||
}
|
||||
|
||||
private:
|
||||
void setView(PeerListBox *box) {
|
||||
_view = box;
|
||||
prepare();
|
||||
}
|
||||
|
||||
PeerListBox *_view = nullptr;
|
||||
|
||||
friend class PeerListBox;
|
||||
|
||||
};
|
||||
PeerListBox(QWidget*, std::unique_ptr<Controller> controller);
|
||||
|
||||
// Interface for the controller.
|
||||
void appendRow(std::unique_ptr<Row> row);
|
||||
void prependRow(std::unique_ptr<Row> row);
|
||||
Row *findRow(PeerData *peer);
|
||||
void updateRow(Row *row);
|
||||
void removeRow(Row *row);
|
||||
void setAboutText(const QString &aboutText);
|
||||
void refreshRows();
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
class Inner;
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
std::unique_ptr<Controller> _controller;
|
||||
|
||||
};
|
||||
|
||||
// This class is hold in header because it requires Qt preprocessing.
|
||||
class PeerListBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Inner(QWidget *parent, Controller *controller);
|
||||
|
||||
void selectSkip(int32 dir);
|
||||
void selectSkipPage(int32 h, int32 dir);
|
||||
|
||||
void clearSelection();
|
||||
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
|
||||
// Interface for the controller.
|
||||
void appendRow(std::unique_ptr<Row> row);
|
||||
void prependRow(std::unique_ptr<Row> row);
|
||||
Row *findRow(PeerData *peer);
|
||||
void updateRow(Row *row);
|
||||
void removeRow(Row *row);
|
||||
void setAboutText(const QString &aboutText);
|
||||
void refreshRows();
|
||||
|
||||
signals:
|
||||
void mustScrollTo(int ymin, int ymax);
|
||||
|
||||
public slots:
|
||||
void peerUpdated(PeerData *peer);
|
||||
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void enterEventHook(QEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
struct SelectedRow {
|
||||
int index = -1;
|
||||
bool action = false;
|
||||
};
|
||||
friend inline bool operator==(SelectedRow a, SelectedRow b) {
|
||||
return (a.index == b.index) && (a.action == b.action);
|
||||
}
|
||||
friend inline bool operator!=(SelectedRow a, SelectedRow b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
void setPressed(SelectedRow pressed);
|
||||
|
||||
void updateSelection();
|
||||
void loadProfilePhotos();
|
||||
void checkScrollForPreload();
|
||||
|
||||
void updateRowWithIndex(int index);
|
||||
int getRowTop(int index) const;
|
||||
|
||||
void paintRow(Painter &p, TimeMs ms, int index);
|
||||
|
||||
Controller *_controller = nullptr;
|
||||
int _rowHeight = 0;
|
||||
int _visibleTop = 0;
|
||||
int _visibleBottom = 0;
|
||||
|
||||
SelectedRow _selected;
|
||||
SelectedRow _pressed;
|
||||
bool _mouseSelection = false;
|
||||
|
||||
std::vector<std::unique_ptr<Row>> _rows;
|
||||
QMap<PeerData*, Row*> _rowsByPeer;
|
||||
|
||||
int _aboutWidth = 0;
|
||||
int _aboutHeight = 0;
|
||||
Text _about;
|
||||
|
||||
QPoint _lastMousePosition;
|
||||
|
||||
};
|
|
@ -185,18 +185,18 @@ public:
|
|||
TypeData &operator=(const TypeData &other) = delete;
|
||||
TypeData &operator=(TypeData &&other) = delete;
|
||||
|
||||
void incrementCounter() const {
|
||||
_counter.ref();
|
||||
}
|
||||
|
||||
bool decrementCounter() const {
|
||||
return _counter.deref();
|
||||
}
|
||||
|
||||
virtual ~TypeData() {
|
||||
}
|
||||
|
||||
private:
|
||||
void incrementCounter() const {
|
||||
_counter.ref();
|
||||
}
|
||||
bool decrementCounter() const {
|
||||
return _counter.deref();
|
||||
}
|
||||
friend class TypeDataOwner;
|
||||
|
||||
mutable QAtomicInt _counter = { 1 };
|
||||
|
||||
};
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "settings/settings_blocked_box_controller.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "apiwrap.h"
|
||||
#include "observer_peer.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
constexpr auto kPerPage = 40;
|
||||
|
||||
} // namespace
|
||||
|
||||
void BlockedBoxController::prepare() {
|
||||
view()->setTitle(lang(lng_blocked_list_title));
|
||||
view()->addButton(lang(lng_close), [this] { view()->closeBox(); });
|
||||
view()->setAboutText(lang(lng_contacts_loading));
|
||||
view()->refreshRows();
|
||||
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::UserIsBlocked, [this](const Notify::PeerUpdate &update) {
|
||||
if (!update.peer->isUser()) {
|
||||
return;
|
||||
}
|
||||
handleBlockedEvent(update.peer->asUser());
|
||||
}));
|
||||
|
||||
preloadRows();
|
||||
}
|
||||
|
||||
void BlockedBoxController::preloadRows() {
|
||||
if (_loadRequestId || _allLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
_loadRequestId = MTP::send(MTPcontacts_GetBlocked(MTP_int(_offset), MTP_int(kPerPage)), rpcDone(base::lambda_guarded(this, [this](const MTPcontacts_Blocked &result) {
|
||||
_loadRequestId = 0;
|
||||
|
||||
if (!_offset) {
|
||||
view()->setAboutText(lang(lng_blocked_list_about));
|
||||
}
|
||||
|
||||
auto handleContactsBlocked = [](auto &list) {
|
||||
App::feedUsers(list.vusers);
|
||||
return list.vblocked.v;
|
||||
};
|
||||
switch (result.type()) {
|
||||
case mtpc_contacts_blockedSlice: {
|
||||
receivedUsers(handleContactsBlocked(result.c_contacts_blockedSlice()));
|
||||
} break;
|
||||
case mtpc_contacts_blocked: {
|
||||
_allLoaded = true;
|
||||
receivedUsers(handleContactsBlocked(result.c_contacts_blocked()));
|
||||
} break;
|
||||
default: t_assert(!"Bad type() in MTPcontacts_GetBlocked() result.");
|
||||
}
|
||||
})), rpcFail(base::lambda_guarded(this, [this](const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
}
|
||||
_loadRequestId = 0;
|
||||
return true;
|
||||
})));
|
||||
}
|
||||
|
||||
void BlockedBoxController::rowClicked(PeerData *peer) {
|
||||
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId);
|
||||
}
|
||||
|
||||
void BlockedBoxController::rowActionClicked(PeerData *peer) {
|
||||
auto user = peer->asUser();
|
||||
t_assert(user != nullptr);
|
||||
|
||||
App::api()->unblockUser(user);
|
||||
}
|
||||
|
||||
void BlockedBoxController::receivedUsers(const QVector<MTPContactBlocked> &result) {
|
||||
if (result.empty()) {
|
||||
_allLoaded = true;
|
||||
}
|
||||
|
||||
for_const (auto &item, result) {
|
||||
++_offset;
|
||||
if (item.type() != mtpc_contactBlocked) {
|
||||
continue;
|
||||
}
|
||||
auto &contactBlocked = item.c_contactBlocked();
|
||||
auto userId = contactBlocked.vuser_id.v;
|
||||
if (auto user = App::userLoaded(userId)) {
|
||||
appendRow(user);
|
||||
user->setBlockStatus(UserData::BlockStatus::Blocked);
|
||||
}
|
||||
}
|
||||
view()->refreshRows();
|
||||
}
|
||||
|
||||
void BlockedBoxController::handleBlockedEvent(UserData *user) {
|
||||
if (user->isBlocked()) {
|
||||
if (prependRow(user)) {
|
||||
view()->refreshRows();
|
||||
}
|
||||
} else if (auto row = view()->findRow(user)) {
|
||||
view()->removeRow(row);
|
||||
view()->refreshRows();
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockedBoxController::appendRow(UserData *user) {
|
||||
if (view()->findRow(user)) {
|
||||
return false;
|
||||
}
|
||||
view()->appendRow(createRow(user));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockedBoxController::prependRow(UserData *user) {
|
||||
if (view()->findRow(user)) {
|
||||
return false;
|
||||
}
|
||||
view()->prependRow(createRow(user));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListBox::Row> BlockedBoxController::createRow(UserData *user) const {
|
||||
auto row = std::make_unique<PeerListBox::Row>(user);
|
||||
row->setActionLink(lang(lng_blocked_list_unblock));
|
||||
auto status = [user]() -> QString {
|
||||
if (user->botInfo) {
|
||||
return lang(lng_status_bot);
|
||||
} else if (user->phone().isEmpty()) {
|
||||
return lang(lng_blocked_list_unknown_phone);
|
||||
}
|
||||
return App::formatPhone(user->phone());
|
||||
};
|
||||
row->setCustomStatus(status());
|
||||
return row;
|
||||
}
|
||||
|
||||
} // namespace Settings
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "boxes/peer_list_box.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
class BlockedBoxController : public QObject, public PeerListBox::Controller, private base::Subscriber {
|
||||
public:
|
||||
void prepare() override;
|
||||
void rowClicked(PeerData *peer) override;
|
||||
void rowActionClicked(PeerData *peer) override;
|
||||
void preloadRows() override;
|
||||
|
||||
private:
|
||||
void receivedUsers(const QVector<MTPContactBlocked> &result);
|
||||
void handleBlockedEvent(UserData *user);
|
||||
bool appendRow(UserData *user);
|
||||
bool prependRow(UserData *user);
|
||||
std::unique_ptr<PeerListBox::Row> createRow(UserData *user) const;
|
||||
|
||||
int _offset = 0;
|
||||
mtpRequestId _loadRequestId = 0;
|
||||
bool _allLoaded = false;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Settings
|
|
@ -28,7 +28,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/sessionsbox.h"
|
||||
#include "boxes/passcodebox.h"
|
||||
#include "boxes/autolockbox.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "settings/settings_blocked_box_controller.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
|
@ -170,6 +172,7 @@ void PrivacyWidget::createControls() {
|
|||
style::margins marginSkip(0, 0, 0, st::settingsSkip);
|
||||
style::margins slidedPadding(0, marginSmall.bottom() / 2, 0, marginSmall.bottom() - (marginSmall.bottom() / 2));
|
||||
|
||||
addChildRow(_blockedUsers, marginSmall, lang(lng_settings_blocked_users), SLOT(onBlockedUsers()));
|
||||
addChildRow(_localPasscodeState, marginSmall);
|
||||
auto label = lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive);
|
||||
auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600);
|
||||
|
@ -192,6 +195,10 @@ void PrivacyWidget::autoLockUpdated() {
|
|||
}
|
||||
}
|
||||
|
||||
void PrivacyWidget::onBlockedUsers() {
|
||||
Ui::show(Box<PeerListBox>(std::make_unique<BlockedBoxController>()));
|
||||
}
|
||||
|
||||
void PrivacyWidget::onAutoLock() {
|
||||
Ui::show(Box<AutoLockBox>());
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ public:
|
|||
PrivacyWidget(QWidget *parent, UserData *self);
|
||||
|
||||
private slots:
|
||||
void onBlockedUsers();
|
||||
void onAutoLock();
|
||||
void onShowSessions();
|
||||
|
||||
|
@ -92,6 +93,7 @@ private:
|
|||
void createControls();
|
||||
void autoLockUpdated();
|
||||
|
||||
object_ptr<Ui::LinkButton> _blockedUsers = { nullptr };
|
||||
object_ptr<LocalPasscodeState> _localPasscodeState = { nullptr };
|
||||
object_ptr<Ui::WidgetSlideWrap<LabeledLink>> _autoLock = { nullptr };
|
||||
object_ptr<CloudPasswordState> _cloudPasswordState = { nullptr };
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
<(src_loc)/boxes/members_box.h
|
||||
<(src_loc)/boxes/notifications_box.cpp
|
||||
<(src_loc)/boxes/notifications_box.h
|
||||
<(src_loc)/boxes/peer_list_box.cpp
|
||||
<(src_loc)/boxes/peer_list_box.h
|
||||
<(src_loc)/boxes/passcodebox.cpp
|
||||
<(src_loc)/boxes/passcodebox.h
|
||||
<(src_loc)/boxes/photocropbox.cpp
|
||||
|
@ -295,6 +297,8 @@
|
|||
<(src_loc)/settings/settings_advanced_widget.h
|
||||
<(src_loc)/settings/settings_background_widget.cpp
|
||||
<(src_loc)/settings/settings_background_widget.h
|
||||
<(src_loc)/settings/settings_blocked_box_controller.cpp
|
||||
<(src_loc)/settings/settings_blocked_box_controller.h
|
||||
<(src_loc)/settings/settings_block_widget.cpp
|
||||
<(src_loc)/settings/settings_block_widget.h
|
||||
<(src_loc)/settings/settings_chat_settings_widget.cpp
|
||||
|
|
Loading…
Add table
Reference in a new issue