608 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			608 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
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-2016 John Preston, https://desktop.telegram.org
 | 
						|
*/
 | 
						|
#include "stdafx.h"
 | 
						|
#include "boxes/members_box.h"
 | 
						|
 | 
						|
#include "styles/style_boxes.h"
 | 
						|
#include "styles/style_dialogs.h"
 | 
						|
#include "lang.h"
 | 
						|
#include "mainwidget.h"
 | 
						|
#include "mainwindow.h"
 | 
						|
#include "boxes/contactsbox.h"
 | 
						|
#include "boxes/confirmbox.h"
 | 
						|
#include "observer_peer.h"
 | 
						|
 | 
						|
MembersBox::MembersBox(ChannelData *channel, MembersFilter filter) : ItemListBox(st::boxScroll)
 | 
						|
, _inner(this, channel, filter) {
 | 
						|
	ItemListBox::init(_inner);
 | 
						|
 | 
						|
	connect(_inner, SIGNAL(addRequested()), this, SLOT(onAdd()));
 | 
						|
 | 
						|
	connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
 | 
						|
	connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int)));
 | 
						|
 | 
						|
	connect(&_loadTimer, SIGNAL(timeout()), _inner, SLOT(load()));
 | 
						|
 | 
						|
	prepare();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::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(scrollArea()->height(), 1);
 | 
						|
	} else if (e->key() == Qt::Key_PageUp) {
 | 
						|
		_inner->selectSkipPage(scrollArea()->height(), -1);
 | 
						|
	} else {
 | 
						|
		ItemListBox::keyPressEvent(e);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::paintEvent(QPaintEvent *e) {
 | 
						|
	Painter p(this);
 | 
						|
	if (paint(p)) return;
 | 
						|
 | 
						|
	QString title(lang(_inner->filter() == MembersFilter::Recent ? lng_channel_members : lng_channel_admins));
 | 
						|
	paintTitle(p, title);
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::resizeEvent(QResizeEvent *e) {
 | 
						|
	ItemListBox::resizeEvent(e);
 | 
						|
	_inner->resize(width(), _inner->height());
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::onScroll() {
 | 
						|
	_inner->loadProfilePhotos(scrollArea()->scrollTop());
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::onAdd() {
 | 
						|
	if (_inner->filter() == MembersFilter::Recent && _inner->channel()->membersCount() >= (_inner->channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
 | 
						|
		Ui::showLayer(new MaxInviteBox(_inner->channel()->inviteLink()), KeepOtherLayers);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	ContactsBox *box = new ContactsBox(_inner->channel(), _inner->filter(), _inner->already());
 | 
						|
	if (_inner->filter() == MembersFilter::Recent) {
 | 
						|
		Ui::showLayer(box);
 | 
						|
	} else {
 | 
						|
		_addBox = box;
 | 
						|
		connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded()));
 | 
						|
		Ui::showLayer(_addBox, KeepOtherLayers);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::onAdminAdded() {
 | 
						|
	if (!_addBox) return;
 | 
						|
	_addBox->onClose();
 | 
						|
	_addBox = 0;
 | 
						|
	_loadTimer.start(ReloadChannelMembersTimeout);
 | 
						|
}
 | 
						|
 | 
						|
MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter filter) : ScrolledWidget(parent)
 | 
						|
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
 | 
						|
, _newItemHeight((channel->amCreator() && (channel->membersCount() < (channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilter::Admins)) ? st::contactsNewItemHeight : 0)
 | 
						|
, _newItemSel(false)
 | 
						|
, _channel(channel)
 | 
						|
, _filter(filter)
 | 
						|
, _kickText(lang(lng_profile_kick))
 | 
						|
, _time(0)
 | 
						|
, _kickWidth(st::normalFont->width(_kickText))
 | 
						|
, _sel(-1)
 | 
						|
, _kickSel(-1)
 | 
						|
, _kickDown(-1)
 | 
						|
, _mouseSel(false)
 | 
						|
, _kickConfirm(0)
 | 
						|
, _kickRequestId(0)
 | 
						|
, _kickBox(0)
 | 
						|
, _loading(true)
 | 
						|
, _loadingRequestId(0)
 | 
						|
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
 | 
						|
, _about(_aboutWidth)
 | 
						|
, _aboutHeight(0) {
 | 
						|
	subscribe(FileDownload::ImageLoaded(), [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*)));
 | 
						|
 | 
						|
	refresh();
 | 
						|
 | 
						|
	load();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::load() {
 | 
						|
	if (!_loadingRequestId) {
 | 
						|
		_loadingRequestId = MTP::send(MTPchannels_GetParticipants(_channel->inputChannel, (_filter == MembersFilter::Recent) ? MTP_channelParticipantsRecent() : MTP_channelParticipantsAdmins(), MTP_int(0), MTP_int(Global::ChatSizeMax())), rpcDone(&Inner::membersReceived), rpcFail(&Inner::membersFailed));
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::paintEvent(QPaintEvent *e) {
 | 
						|
	QRect r(e->rect());
 | 
						|
	Painter p(this);
 | 
						|
 | 
						|
	_time = unixtime();
 | 
						|
	p.fillRect(r, st::white->b);
 | 
						|
 | 
						|
	int32 yFrom = r.y() - st::membersPadding.top(), yTo = r.y() + r.height() - st::membersPadding.top();
 | 
						|
	p.translate(0, st::membersPadding.top());
 | 
						|
	if (_rows.isEmpty()) {
 | 
						|
		p.setFont(st::noContactsFont->f);
 | 
						|
		p.setPen(st::noContactsColor->p);
 | 
						|
		p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
 | 
						|
	} else {
 | 
						|
		if (_newItemHeight) {
 | 
						|
			p.fillRect(0, 0, width(), _newItemHeight, (_newItemSel ? st::contactsBgOver : st::white)->b);
 | 
						|
			st::contactsNewItemIcon.paint(p, 0, 0, width());
 | 
						|
			p.setFont(st::contactsNameFont);
 | 
						|
			p.setPen(st::contactsNewItemFg);
 | 
						|
			p.drawTextLeft(st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(), st::contactsNewItemTop, width(), lang(_filter == MembersFilter::Admins ? lng_channel_add_admins : lng_channel_add_members));
 | 
						|
 | 
						|
			yFrom -= _newItemHeight;
 | 
						|
			yTo -= _newItemHeight;
 | 
						|
			p.translate(0, _newItemHeight);
 | 
						|
		}
 | 
						|
		int32 from = floorclamp(yFrom, _rowHeight, 0, _rows.size());
 | 
						|
		int32 to = ceilclamp(yTo, _rowHeight, 0, _rows.size());
 | 
						|
		p.translate(0, from * _rowHeight);
 | 
						|
		for (; from < to; ++from) {
 | 
						|
			bool sel = (from == _sel);
 | 
						|
			bool kickSel = (from == _kickSel && (_kickDown < 0 || from == _kickDown));
 | 
						|
			bool kickDown = kickSel && (from == _kickDown);
 | 
						|
			paintDialog(p, _rows[from], data(from), sel, kickSel, kickDown);
 | 
						|
			p.translate(0, _rowHeight);
 | 
						|
		}
 | 
						|
		if (to == _rows.size() && _filter == MembersFilter::Recent && (_rows.size() < _channel->membersCount() || _rows.size() >= Global::ChatSizeMax())) {
 | 
						|
			p.setPen(st::stickersReorderFg);
 | 
						|
			_about.draw(p, st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::enterEvent(QEvent *e) {
 | 
						|
	setMouseTracking(true);
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::leaveEvent(QEvent *e) {
 | 
						|
	_mouseSel = false;
 | 
						|
	setMouseTracking(false);
 | 
						|
	if (_sel >= 0) {
 | 
						|
		clearSel();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
 | 
						|
	_mouseSel = true;
 | 
						|
	_lastMousePos = e->globalPos();
 | 
						|
	updateSel();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::mousePressEvent(QMouseEvent *e) {
 | 
						|
	_mouseSel = true;
 | 
						|
	_lastMousePos = e->globalPos();
 | 
						|
	updateSel();
 | 
						|
	if (e->button() == Qt::LeftButton && _kickSel < 0) {
 | 
						|
		chooseParticipant();
 | 
						|
	}
 | 
						|
	_kickDown = _kickSel;
 | 
						|
	update();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
 | 
						|
	_mouseSel = true;
 | 
						|
	_lastMousePos = e->globalPos();
 | 
						|
	updateSel();
 | 
						|
	if (_kickDown >= 0 && _kickDown == _kickSel && !_kickRequestId) {
 | 
						|
		_kickConfirm = _rows.at(_kickSel);
 | 
						|
		if (_kickBox) _kickBox->deleteLater();
 | 
						|
		_kickBox = new ConfirmBox((_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName));
 | 
						|
		connect(_kickBox, SIGNAL(confirmed()), this, SLOT(onKickConfirm()));
 | 
						|
		connect(_kickBox, SIGNAL(destroyed(QObject*)), this, SLOT(onKickBoxDestroyed(QObject*)));
 | 
						|
		Ui::showLayer(_kickBox, KeepOtherLayers);
 | 
						|
	}
 | 
						|
	_kickDown = -1;
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::onKickBoxDestroyed(QObject *obj) {
 | 
						|
	if (_kickBox == obj) {
 | 
						|
		_kickBox = 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::onKickConfirm() {
 | 
						|
	if (_filter == MembersFilter::Recent) {
 | 
						|
		_kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail));
 | 
						|
	} else {
 | 
						|
		_kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail));
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::paintDialog(Painter &p, PeerData *peer, MemberData *data, bool sel, bool kickSel, bool kickDown) {
 | 
						|
	UserData *user = peer->asUser();
 | 
						|
 | 
						|
	p.fillRect(0, 0, width(), _rowHeight, (sel ? st::contactsBgOver : st::white)->b);
 | 
						|
	peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
 | 
						|
 | 
						|
	p.setPen(st::black);
 | 
						|
 | 
						|
	int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
 | 
						|
	int32 namew = width() - namex - st::contactsPadding.right() - (data->canKick ? (_kickWidth + st::contactsCheckPosition.x() * 2) : 0);
 | 
						|
	if (peer->isVerified()) {
 | 
						|
		auto icon = &st::dialogsVerifiedIcon;
 | 
						|
		namew -= icon->width();
 | 
						|
		icon->paint(p, namex + qMin(data->name.maxWidth(), namew), st::contactsPadding.top() + st::contactsNameTop, width());
 | 
						|
	}
 | 
						|
	data->name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width());
 | 
						|
 | 
						|
	if (data->canKick) {
 | 
						|
		p.setFont((kickSel ? st::linkOverFont : st::linkFont)->f);
 | 
						|
		if (kickDown) {
 | 
						|
			p.setPen(st::btnDefLink.downColor->p);
 | 
						|
		} else {
 | 
						|
			p.setPen(st::btnDefLink.color->p);
 | 
						|
		}
 | 
						|
		p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), _kickText, _kickWidth);
 | 
						|
	}
 | 
						|
 | 
						|
	p.setFont(st::contactsStatusFont->f);
 | 
						|
	p.setPen(data->onlineColor ? st::contactsStatusFgOnline : (sel ? st::contactsStatusFgOver : st::contactsStatusFg));
 | 
						|
	p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), data->online);
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::selectSkip(int32 dir) {
 | 
						|
	_time = unixtime();
 | 
						|
	_mouseSel = false;
 | 
						|
 | 
						|
	int cur = -1;
 | 
						|
	if (_newItemHeight && _newItemSel) {
 | 
						|
		cur = 0;
 | 
						|
	} else if (_sel >= 0) {
 | 
						|
		cur = _sel + (_newItemHeight ? 1 : 0);
 | 
						|
	}
 | 
						|
	cur += dir;
 | 
						|
	if (cur <= 0) {
 | 
						|
		_newItemSel = _newItemHeight ? true : false;
 | 
						|
		_sel = (_newItemSel || _rows.isEmpty()) ? -1 : 0;
 | 
						|
	} else if (cur >= _rows.size() + (_newItemHeight ? 1 : 0)) {
 | 
						|
		_sel = -1;
 | 
						|
	} else {
 | 
						|
		_sel = cur - (_newItemHeight ? 1 : 0);
 | 
						|
	}
 | 
						|
	if (dir > 0) {
 | 
						|
		if (_sel < 0 || _sel >= _rows.size()) {
 | 
						|
			_sel = -1;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (!_rows.isEmpty()) {
 | 
						|
			if (_sel < 0 && !_newItemSel) _sel = _rows.size() - 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (_newItemSel) {
 | 
						|
		emit mustScrollTo(0, _newItemHeight);
 | 
						|
	} else if (_sel >= 0) {
 | 
						|
		emit mustScrollTo(_newItemHeight + _sel * _rowHeight, _newItemHeight + (_sel + 1) * _rowHeight);
 | 
						|
	}
 | 
						|
 | 
						|
	update();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::selectSkipPage(int32 h, int32 dir) {
 | 
						|
	int32 points = h / _rowHeight;
 | 
						|
	if (!points) return;
 | 
						|
	selectSkip(points * dir);
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::loadProfilePhotos(int32 yFrom) {
 | 
						|
	int32 yTo = yFrom + (parentWidget() ? parentWidget()->height() : App::wnd()->height()) * 5;
 | 
						|
	MTP::clearLoaderPriorities();
 | 
						|
 | 
						|
	if (yTo < 0) return;
 | 
						|
	if (yFrom < 0) yFrom = 0;
 | 
						|
 | 
						|
	if (!_rows.isEmpty()) {
 | 
						|
		int32 from = (yFrom - _newItemHeight) / _rowHeight;
 | 
						|
		if (from < 0) from = 0;
 | 
						|
		if (from < _rows.size()) {
 | 
						|
			int32 to = ((yTo - _newItemHeight) / _rowHeight) + 1;
 | 
						|
			if (to > _rows.size()) to = _rows.size();
 | 
						|
 | 
						|
			for (; from < to; ++from) {
 | 
						|
				_rows[from]->loadUserpic();
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::chooseParticipant() {
 | 
						|
	if (_newItemSel) {
 | 
						|
		emit addRequested();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (_sel < 0 || _sel >= _rows.size()) return;
 | 
						|
	if (PeerData *peer = _rows[_sel]) {
 | 
						|
		Ui::hideLayer();
 | 
						|
		Ui::showPeerProfile(peer);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::refresh() {
 | 
						|
	if (_rows.isEmpty()) {
 | 
						|
		resize(width(), st::membersPadding.top() + st::noContactsHeight + st::membersPadding.bottom());
 | 
						|
		_aboutHeight = 0;
 | 
						|
	} else {
 | 
						|
		_about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size()));
 | 
						|
		_aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom();
 | 
						|
		if (_filter != MembersFilter::Recent || (_rows.size() >= _channel->membersCount() && _rows.size() < Global::ChatSizeMax())) {
 | 
						|
			_aboutHeight = 0;
 | 
						|
		}
 | 
						|
		resize(width(), st::membersPadding.top() + _newItemHeight + _rows.size() * _rowHeight + st::membersPadding.bottom() + _aboutHeight);
 | 
						|
	}
 | 
						|
	update();
 | 
						|
}
 | 
						|
 | 
						|
ChannelData *MembersBox::Inner::channel() const {
 | 
						|
	return _channel;
 | 
						|
}
 | 
						|
 | 
						|
MembersFilter MembersBox::Inner::filter() const {
 | 
						|
	return _filter;
 | 
						|
}
 | 
						|
 | 
						|
MembersAlreadyIn MembersBox::Inner::already() const {
 | 
						|
	MembersAlreadyIn result;
 | 
						|
	for_const (auto peer, _rows) {
 | 
						|
		if (peer->isUser()) {
 | 
						|
			result.insert(peer->asUser());
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::clearSel() {
 | 
						|
	updateSelectedRow();
 | 
						|
	_newItemSel = false;
 | 
						|
	_sel = _kickSel = _kickDown = -1;
 | 
						|
	_lastMousePos = QCursor::pos();
 | 
						|
	updateSel();
 | 
						|
}
 | 
						|
 | 
						|
MembersBox::Inner::MemberData *MembersBox::Inner::data(int32 index) {
 | 
						|
	if (MemberData *result = _datas.at(index)) {
 | 
						|
		return result;
 | 
						|
	}
 | 
						|
	MemberData *result = _datas[index] = new MemberData();
 | 
						|
	result->name.setText(st::contactsNameFont, _rows[index]->name, _textNameOptions);
 | 
						|
	int32 t = unixtime();
 | 
						|
	result->online = App::onlineText(_rows[index], t);// lng_mediaview_date_time(lt_date, _dates[index].date().toString(qsl("dd.MM.yy")), lt_time, _dates[index].time().toString(cTimeFormat()));
 | 
						|
	result->onlineColor = App::onlineColorUse(_rows[index], t);
 | 
						|
	if (_filter == MembersFilter::Recent) {
 | 
						|
		result->canKick = (_channel->amCreator() || _channel->amEditor() || _channel->amModerator()) ? (_roles[index] == MemberRole::None) : false;
 | 
						|
	} else if (_filter == MembersFilter::Admins) {
 | 
						|
		result->canKick = _channel->amCreator() ? (_roles[index] == MemberRole::Editor || _roles[index] == MemberRole::Moderator) : false;
 | 
						|
	} else {
 | 
						|
		result->canKick = false;
 | 
						|
	}
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::clear() {
 | 
						|
	for (int32 i = 0, l = _datas.size(); i < l; ++i) {
 | 
						|
		delete _datas.at(i);
 | 
						|
	}
 | 
						|
	_datas.clear();
 | 
						|
	_rows.clear();
 | 
						|
	_dates.clear();
 | 
						|
	_roles.clear();
 | 
						|
	if (_kickBox) _kickBox->deleteLater();
 | 
						|
	clearSel();
 | 
						|
}
 | 
						|
 | 
						|
MembersBox::Inner::~Inner() {
 | 
						|
	clear();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::updateSel() {
 | 
						|
	if (!_mouseSel) return;
 | 
						|
 | 
						|
	QPoint p(mapFromGlobal(_lastMousePos));
 | 
						|
	p.setY(p.y() - st::membersPadding.top());
 | 
						|
	bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
 | 
						|
	bool newItemSel = (in && p.y() >= 0 && p.y() < _newItemHeight);
 | 
						|
	int32 newSel = (in && !newItemSel && p.y() >= _newItemHeight && p.y() < _newItemHeight + _rows.size() * _rowHeight) ? ((p.y() - _newItemHeight) / _rowHeight) : -1;
 | 
						|
	int32 newKickSel = newSel;
 | 
						|
	if (newSel >= 0 && (!data(newSel)->canKick || !QRect(width() - _kickWidth - st::contactsPadding.right() - st::contactsCheckPosition.x(), _newItemHeight + newSel * _rowHeight + st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, _kickWidth, st::normalFont->height).contains(p))) {
 | 
						|
		newKickSel = -1;
 | 
						|
	}
 | 
						|
	if (newSel != _sel || newKickSel != _kickSel || newItemSel != _newItemSel) {
 | 
						|
		updateSelectedRow();
 | 
						|
		_newItemSel = newItemSel;
 | 
						|
		_sel = newSel;
 | 
						|
		_kickSel = newKickSel;
 | 
						|
		updateSelectedRow();
 | 
						|
		setCursor(_kickSel >= 0 ? style::cur_pointer : style::cur_default);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::peerUpdated(PeerData *peer) {
 | 
						|
	update();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::updateSelectedRow() {
 | 
						|
	if (_newItemSel) {
 | 
						|
		update(0, st::membersPadding.top(), width(), _newItemHeight);
 | 
						|
	}
 | 
						|
	if (_sel >= 0) {
 | 
						|
		update(0, st::membersPadding.top() + _newItemHeight + _sel * _rowHeight, width(), _rowHeight);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
 | 
						|
	for (int32 i = 0, l = _rows.size(); i < l; ++i) {
 | 
						|
		if (_rows.at(i) == peer) {
 | 
						|
			if (_datas.at(i)) {
 | 
						|
				_datas.at(i)->name.setText(st::contactsNameFont, peer->name, _textNameOptions);
 | 
						|
				update(0, st::membersPadding.top() + i * _rowHeight, width(), _rowHeight);
 | 
						|
			} else {
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::membersReceived(const MTPchannels_ChannelParticipants &result, mtpRequestId req) {
 | 
						|
	clear();
 | 
						|
	_loadingRequestId = 0;
 | 
						|
 | 
						|
	if (result.type() == mtpc_channels_channelParticipants) {
 | 
						|
		const auto &d(result.c_channels_channelParticipants());
 | 
						|
		const auto &v(d.vparticipants.c_vector().v);
 | 
						|
		_rows.reserve(v.size());
 | 
						|
		_datas.reserve(v.size());
 | 
						|
		_dates.reserve(v.size());
 | 
						|
		_roles.reserve(v.size());
 | 
						|
 | 
						|
		if (_filter == MembersFilter::Recent && _channel->membersCount() < d.vcount.v) {
 | 
						|
			_channel->setMembersCount(d.vcount.v);
 | 
						|
			if (App::main()) emit App::main()->peerUpdated(_channel);
 | 
						|
		} else if (_filter == MembersFilter::Admins && _channel->adminsCount() < d.vcount.v) {
 | 
						|
			_channel->setAdminsCount(d.vcount.v);
 | 
						|
			if (App::main()) emit App::main()->peerUpdated(_channel);
 | 
						|
		}
 | 
						|
		App::feedUsers(d.vusers);
 | 
						|
 | 
						|
		for (QVector<MTPChannelParticipant>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
 | 
						|
			int32 userId = 0, addedTime = 0;
 | 
						|
			MemberRole role = MemberRole::None;
 | 
						|
			switch (i->type()) {
 | 
						|
			case mtpc_channelParticipant:
 | 
						|
				userId = i->c_channelParticipant().vuser_id.v;
 | 
						|
				addedTime = i->c_channelParticipant().vdate.v;
 | 
						|
				break;
 | 
						|
			case mtpc_channelParticipantSelf:
 | 
						|
				role = MemberRole::Self;
 | 
						|
				userId = i->c_channelParticipantSelf().vuser_id.v;
 | 
						|
				addedTime = i->c_channelParticipantSelf().vdate.v;
 | 
						|
				break;
 | 
						|
			case mtpc_channelParticipantModerator:
 | 
						|
				role = MemberRole::Moderator;
 | 
						|
				userId = i->c_channelParticipantModerator().vuser_id.v;
 | 
						|
				addedTime = i->c_channelParticipantModerator().vdate.v;
 | 
						|
				break;
 | 
						|
			case mtpc_channelParticipantEditor:
 | 
						|
				role = MemberRole::Editor;
 | 
						|
				userId = i->c_channelParticipantEditor().vuser_id.v;
 | 
						|
				addedTime = i->c_channelParticipantEditor().vdate.v;
 | 
						|
				break;
 | 
						|
			case mtpc_channelParticipantKicked:
 | 
						|
				userId = i->c_channelParticipantKicked().vuser_id.v;
 | 
						|
				addedTime = i->c_channelParticipantKicked().vdate.v;
 | 
						|
				role = MemberRole::Kicked;
 | 
						|
				break;
 | 
						|
			case mtpc_channelParticipantCreator:
 | 
						|
				userId = i->c_channelParticipantCreator().vuser_id.v;
 | 
						|
				addedTime = _channel->date;
 | 
						|
				role = MemberRole::Creator;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			if (UserData *user = App::userLoaded(userId)) {
 | 
						|
				_rows.push_back(user);
 | 
						|
				_dates.push_back(date(addedTime));
 | 
						|
				_roles.push_back(role);
 | 
						|
				_datas.push_back(0);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		// update admins if we got all of them
 | 
						|
		if (_filter == MembersFilter::Admins && _channel->isMegagroup() && _rows.size() < Global::ChatSizeMax()) {
 | 
						|
			_channel->mgInfo->lastAdmins.clear();
 | 
						|
			for (int32 i = 0, l = _rows.size(); i != l; ++i) {
 | 
						|
				if (_roles.at(i) == MemberRole::Creator || _roles.at(i) == MemberRole::Editor) {
 | 
						|
					_channel->mgInfo->lastAdmins.insert(_rows.at(i));
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			Notify::peerUpdatedDelayed(_channel, Notify::PeerUpdate::Flag::AdminsChanged);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (_rows.isEmpty()) {
 | 
						|
		_rows.push_back(App::self());
 | 
						|
		_dates.push_back(date(MTP_int(_channel->date)));
 | 
						|
		_roles.push_back(MemberRole::Self);
 | 
						|
		_datas.push_back(0);
 | 
						|
	}
 | 
						|
 | 
						|
	clearSel();
 | 
						|
	_loading = false;
 | 
						|
	refresh();
 | 
						|
 | 
						|
	emit loaded();
 | 
						|
}
 | 
						|
 | 
						|
bool MembersBox::Inner::membersFailed(const RPCError &error, mtpRequestId req) {
 | 
						|
	if (MTP::isDefaultHandledError(error)) return false;
 | 
						|
 | 
						|
	Ui::hideLayer();
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::kickDone(const MTPUpdates &result, mtpRequestId req) {
 | 
						|
	App::main()->sentUpdatesReceived(result);
 | 
						|
 | 
						|
	if (_kickRequestId != req) return;
 | 
						|
	removeKicked();
 | 
						|
	if (_kickBox) _kickBox->onClose();
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::kickAdminDone(const MTPUpdates &result, mtpRequestId req) {
 | 
						|
	if (_kickRequestId != req) return;
 | 
						|
	if (App::main()) App::main()->sentUpdatesReceived(result);
 | 
						|
	removeKicked();
 | 
						|
	if (_kickBox) _kickBox->onClose();
 | 
						|
}
 | 
						|
 | 
						|
bool MembersBox::Inner::kickFail(const RPCError &error, mtpRequestId req) {
 | 
						|
	if (MTP::isDefaultHandledError(error)) return false;
 | 
						|
 | 
						|
	if (_kickBox) _kickBox->onClose();
 | 
						|
	load();
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
void MembersBox::Inner::removeKicked() {
 | 
						|
	_kickRequestId = 0;
 | 
						|
	int32 index = _rows.indexOf(_kickConfirm);
 | 
						|
	if (index >= 0) {
 | 
						|
		_rows.removeAt(index);
 | 
						|
		delete _datas.at(index);
 | 
						|
		_datas.removeAt(index);
 | 
						|
		_dates.removeAt(index);
 | 
						|
		_roles.removeAt(index);
 | 
						|
		clearSel();
 | 
						|
		if (_filter == MembersFilter::Recent && _channel->membersCount() > 1) {
 | 
						|
			_channel->setMembersCount(_channel->membersCount() - 1);
 | 
						|
			if (App::main()) emit App::main()->peerUpdated(_channel);
 | 
						|
		} else if (_filter == MembersFilter::Admins && _channel->adminsCount() > 1) {
 | 
						|
			_channel->setAdminsCount(_channel->adminsCount() - 1);
 | 
						|
			if (App::main()) emit App::main()->peerUpdated(_channel);
 | 
						|
		}
 | 
						|
		refresh();
 | 
						|
	}
 | 
						|
	_kickConfirm = 0;
 | 
						|
}
 |