Unify legacy and megagroups information edit.

This commit is contained in:
John Preston 2019-01-08 17:57:22 +04:00
parent ff728e2fc1
commit 18c6be0d3b
28 changed files with 273 additions and 759 deletions

View file

@ -878,11 +878,13 @@ void ApiWrap::changeDialogUnreadMark(
)).send();
}
void ApiWrap::requestFullPeer(PeerData *peer) {
if (!peer || _fullPeerRequests.contains(peer)) return;
void ApiWrap::requestFullPeer(not_null<PeerData*> peer) {
if (_fullPeerRequests.contains(peer)) {
return;
}
auto sendRequest = [this, peer] {
auto failHandler = [this, peer](const RPCError &error) {
const auto requestId = [&] {
const auto failHandler = [=](const RPCError &error) {
_fullPeerRequests.remove(peer);
};
if (const auto user = peer->asUser()) {
@ -897,32 +899,41 @@ void ApiWrap::requestFullPeer(PeerData *peer) {
} else if (const auto chat = peer->asChat()) {
return request(MTPmessages_GetFullChat(
chat->inputChat
)).done([=](const MTPmessages_ChatFull &result, mtpRequestId requestId) {
)).done([=](
const MTPmessages_ChatFull &result,
mtpRequestId requestId) {
gotChatFull(peer, result, requestId);
}).fail(failHandler).send();
} else if (const auto channel = peer->asChannel()) {
return request(MTPchannels_GetFullChannel(
channel->inputChannel
)).done([=](const MTPmessages_ChatFull &result, mtpRequestId requestId) {
)).done([=](
const MTPmessages_ChatFull &result,
mtpRequestId requestId) {
gotChatFull(peer, result, requestId);
}).fail(failHandler).send();
}
return 0;
};
if (auto requestId = sendRequest()) {
_fullPeerRequests.insert(peer, requestId);
}
Unexpected("Peer type in requestFullPeer.");
}();
_fullPeerRequests.insert(peer, requestId);
}
void ApiWrap::processFullPeer(PeerData *peer, const MTPmessages_ChatFull &result) {
void ApiWrap::processFullPeer(
not_null<PeerData*> peer,
const MTPmessages_ChatFull &result) {
gotChatFull(peer, result, mtpRequestId(0));
}
void ApiWrap::processFullPeer(UserData *user, const MTPUserFull &result) {
void ApiWrap::processFullPeer(
not_null<UserData*> user,
const MTPUserFull &result) {
gotUserFull(user, result, mtpRequestId(0));
}
void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req) {
void ApiWrap::gotChatFull(
not_null<PeerData*> peer,
const MTPmessages_ChatFull &result,
mtpRequestId req) {
auto &d = result.c_messages_chatFull();
auto &vc = d.vchats.v;
auto badVersion = false;
@ -940,9 +951,10 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
App::feedChats(d.vchats);
using UpdateFlag = Notify::PeerUpdate::Flag;
if (auto chat = peer->asChat()) {
if (const auto chat = peer->asChat()) {
if (d.vfull_chat.type() != mtpc_chatFull) {
LOG(("MTP Error: bad type in gotChatFull for chat: %1").arg(d.vfull_chat.type()));
LOG(("MTP Error: bad type in gotChatFull for chat: %1"
).arg(d.vfull_chat.type()));
return;
}
auto &f = d.vfull_chat.c_chatFull();
@ -957,6 +969,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
});
}
}
chat->setFullFlags(f.vflags.v);
chat->setUserpicPhoto(f.has_chat_photo()
? f.vchat_photo
: MTPPhoto(MTP_photoEmpty(MTP_long(0))));
@ -971,10 +984,13 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
}
chat->fullUpdated();
notifySettingReceived(MTP_inputNotifyPeer(peer->input), f.vnotify_settings);
} else if (auto channel = peer->asChannel()) {
notifySettingReceived(
MTP_inputNotifyPeer(peer->input),
f.vnotify_settings);
} else if (const auto channel = peer->asChannel()) {
if (d.vfull_chat.type() != mtpc_channelFull) {
LOG(("MTP Error: bad type in gotChatFull for channel: %1").arg(d.vfull_chat.type()));
LOG(("MTP Error: bad type in gotChatFull for channel: %1"
).arg(d.vfull_chat.type()));
return;
}
auto &f = d.vfull_chat.c_channelFull();
@ -1084,8 +1100,11 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
fullPeerUpdated().notify(peer);
}
void ApiWrap::gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req) {
auto &d = result.c_userFull();
void ApiWrap::gotUserFull(
not_null<UserData*> user,
const MTPUserFull &result,
mtpRequestId req) {
const auto &d = result.c_userFull();
if (user == _session->user() && !_session->validateSelf(d.vuser)) {
constexpr auto kRequestUserAgainTimeout = TimeMs(10000);
@ -1129,17 +1148,19 @@ void ApiWrap::gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestI
fullPeerUpdated().notify(user);
}
void ApiWrap::requestPeer(PeerData *peer) {
if (!peer || _fullPeerRequests.contains(peer) || _peerRequests.contains(peer)) return;
void ApiWrap::requestPeer(not_null<PeerData*> peer) {
if (_fullPeerRequests.contains(peer) || _peerRequests.contains(peer)) {
return;
}
auto sendRequest = [this, peer] {
auto failHandler = [this, peer](const RPCError &error) {
const auto requestId = [&] {
const auto failHandler = [=](const RPCError &error) {
_peerRequests.remove(peer);
};
auto chatHandler = [this, peer](const MTPmessages_Chats &result) {
const auto chatHandler = [=](const MTPmessages_Chats &result) {
_peerRequests.remove(peer);
if (auto chats = Api::getChatsFromMessagesChats(result)) {
if (const auto chats = Api::getChatsFromMessagesChats(result)) {
auto &v = chats->v;
bool badVersion = false;
if (const auto chat = peer->asChat()) {
@ -1151,12 +1172,12 @@ void ApiWrap::requestPeer(PeerData *peer) {
&& (v[0].type() == mtpc_channel)
&& (v[0].c_channel().vversion.v < channel->version);
}
auto chat = App::feedChats(*chats);
const auto chat = App::feedChats(*chats);
if (chat == peer) {
if (badVersion) {
if (auto chat = peer->asChat()) {
if (const auto chat = peer->asChat()) {
chat->version = v[0].c_chat().vversion.v;
} else if (auto channel = peer->asChannel()) {
} else if (const auto channel = peer->asChannel()) {
channel->version = v[0].c_channel().vversion.v;
}
requestPeer(peer);
@ -1164,21 +1185,25 @@ void ApiWrap::requestPeer(PeerData *peer) {
}
}
};
if (auto user = peer->asUser()) {
return request(MTPusers_GetUsers(MTP_vector<MTPInputUser>(1, user->inputUser))).done([this, user](const MTPVector<MTPUser> &result) {
if (const auto user = peer->asUser()) {
return request(MTPusers_GetUsers(
MTP_vector<MTPInputUser>(1, user->inputUser)
)).done([=](const MTPVector<MTPUser> &result) {
_peerRequests.remove(user);
App::feedUsers(result);
}).fail(failHandler).send();
} else if (auto chat = peer->asChat()) {
return request(MTPmessages_GetChats(MTP_vector<MTPint>(1, chat->inputChat))).done(chatHandler).fail(failHandler).send();
} else if (auto channel = peer->asChannel()) {
return request(MTPchannels_GetChannels(MTP_vector<MTPInputChannel>(1, channel->inputChannel))).done(chatHandler).fail(failHandler).send();
} else if (const auto chat = peer->asChat()) {
return request(MTPmessages_GetChats(
MTP_vector<MTPint>(1, chat->inputChat)
)).done(chatHandler).fail(failHandler).send();
} else if (const auto channel = peer->asChannel()) {
return request(MTPchannels_GetChannels(
MTP_vector<MTPInputChannel>(1, channel->inputChannel)
)).done(chatHandler).fail(failHandler).send();
}
return 0;
};
if (auto requestId = sendRequest()) {
_peerRequests.insert(peer, requestId);
}
Unexpected("Peer type in requestPeer.");
}();
_peerRequests.insert(peer, requestId);
}
void ApiWrap::markMediaRead(
@ -1629,7 +1654,7 @@ void ApiWrap::unblockParticipant(
} else {
channel->updateFullForced();
}
}).fail([this, kick](const RPCError &error) {
}).fail([=](const RPCError &error) {
_kickRequests.remove(kick);
}).send();

View file

@ -99,8 +99,8 @@ public:
void changeDialogUnreadMark(not_null<History*> history, bool unread);
//void changeDialogUnreadMark(not_null<Data::Feed*> feed, bool unread); // #feed
void requestFullPeer(PeerData *peer);
void requestPeer(PeerData *peer);
void requestFullPeer(not_null<PeerData*> peer);
void requestPeer(not_null<PeerData*> peer);
void requestPeers(const QList<PeerData*> &peers);
void requestLastParticipants(not_null<ChannelData*> channel);
void requestBots(not_null<ChannelData*> channel);
@ -138,8 +138,12 @@ public:
void requestChannelMembersForAdd(
not_null<ChannelData*> channel,
Fn<void(const MTPchannels_ChannelParticipants&)> callback);
void processFullPeer(PeerData *peer, const MTPmessages_ChatFull &result);
void processFullPeer(UserData *user, const MTPUserFull &result);
void processFullPeer(
not_null<PeerData*> peer,
const MTPmessages_ChatFull &result);
void processFullPeer(
not_null<UserData*> user,
const MTPUserFull &result);
void markMediaRead(const base::flat_set<not_null<HistoryItem*>> &items);
void markMediaRead(not_null<HistoryItem*> item);
@ -435,8 +439,14 @@ private:
not_null<Data::Feed*> feed,
const MTPmessages_Dialogs &dialogs);
void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req);
void gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req);
void gotChatFull(
not_null<PeerData*> peer,
const MTPmessages_ChatFull &result,
mtpRequestId req);
void gotUserFull(
not_null<UserData*> user,
const MTPUserFull &result,
mtpRequestId req);
void applyLastParticipantsList(
not_null<ChannelData*> channel,
int availableCount,

View file

@ -366,65 +366,6 @@ void MaxInviteBox::resizeEvent(QResizeEvent *e) {
_invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height, width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height);
}
ConvertToSupergroupBox::ConvertToSupergroupBox(QWidget*, ChatData *chat)
: _chat(chat)
, _text(100)
, _note(100) {
}
void ConvertToSupergroupBox::prepare() {
QStringList text;
text.push_back(lang(lng_profile_convert_feature1));
text.push_back(lang(lng_profile_convert_feature2));
text.push_back(lang(lng_profile_convert_feature3));
text.push_back(lang(lng_profile_convert_feature4));
setTitle(langFactory(lng_profile_convert_title));
addButton(langFactory(lng_profile_convert_confirm), [this] { convertToSupergroup(); });
addButton(langFactory(lng_cancel), [this] { closeBox(); });
_text.setText(st::boxLabelStyle, text.join('\n'), _confirmBoxTextOptions);
_note.setText(st::boxLabelStyle, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions);
_textWidth = st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right();
_textHeight = _text.countHeight(_textWidth);
setDimensions(st::boxWideWidth, _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth));
}
void ConvertToSupergroupBox::convertToSupergroup() {
MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail));
}
void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) {
Ui::hideLayer();
ConvertToSupergroupDone(updates);
}
bool ConvertToSupergroupBox::convertFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
Ui::hideLayer();
return true;
}
void ConvertToSupergroupBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
convertToSupergroup();
} else {
BoxContent::keyPressEvent(e);
}
}
void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) {
BoxContent::paintEvent(e);
Painter p(this);
// draw box title / text
p.setPen(st::boxTextFg);
_text.drawLeft(p, st::boxPadding.left(), 0, _textWidth, width());
_note.drawLeft(p, st::boxPadding.left(), _textHeight + st::boxPadding.bottom(), _textWidth, width());
}
PinMessageBox::PinMessageBox(
QWidget*,
not_null<PeerData*> peer,

View file

@ -119,27 +119,6 @@ private:
};
class ConvertToSupergroupBox : public BoxContent, public RPCSender {
public:
ConvertToSupergroupBox(QWidget*, ChatData *chat);
protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private:
void convertToSupergroup();
void convertDone(const MTPUpdates &updates);
bool convertFail(const RPCError &error);
ChatData *_chat;
Text _text, _note;
int32 _textWidth, _textHeight;
};
class PinMessageBox : public BoxContent, public RPCSender {
public:
PinMessageBox(QWidget*, not_null<PeerData*> peer, MsgId msgId);

View file

@ -132,44 +132,6 @@ bool InviteSelectedUsers(
// return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
//}
class EditChatAdminsBoxController::LabeledCheckbox : public Ui::RpWidget {
public:
LabeledCheckbox(
QWidget *parent,
const QString &text,
bool checked = false,
const style::Checkbox &st = st::defaultCheckbox,
const style::Check &checkSt = st::defaultCheck);
bool checked() const {
return _checkbox->checked();
}
rpl::producer<bool> checkedChanges() const {
return _checkbox->checkedChanges();
}
rpl::producer<bool> checkedValue() const {
return _checkbox->checkedValue();
}
void setLabelText(
bool checked,
const style::TextStyle &st,
const QString &text,
const TextParseOptions &options = _defaultOptions,
int minResizeWidth = QFIXED_MAX);
protected:
int resizeGetHeight(int newWidth) override;
void paintEvent(QPaintEvent *e) override;
private:
object_ptr<Ui::Checkbox> _checkbox;
Text _labelUnchecked;
Text _labelChecked;
int _labelWidth = 0;
};
void PeerListRowWithLink::setActionLink(const QString &action) {
_action = action;
refreshActionLink();
@ -595,191 +557,6 @@ void AddParticipantsBoxController::Start(not_null<ChannelData*> channel) {
Start(channel, {}, true);
}
EditChatAdminsBoxController::LabeledCheckbox::LabeledCheckbox(
QWidget *parent,
const QString &text,
bool checked,
const style::Checkbox &st,
const style::Check &checkSt)
: RpWidget(parent)
, _checkbox(this, text, checked, st, checkSt) {
}
void EditChatAdminsBoxController::LabeledCheckbox::setLabelText(
bool checked,
const style::TextStyle &st,
const QString &text,
const TextParseOptions &options,
int minResizeWidth) {
auto &label = (checked ? _labelChecked : _labelUnchecked);
label = Text(st, text, options, minResizeWidth);
}
int EditChatAdminsBoxController::LabeledCheckbox::resizeGetHeight(int newWidth) {
_labelWidth = newWidth - st::contactsPadding.left() - st::contactsPadding.right();
_checkbox->resizeToNaturalWidth(_labelWidth);
_checkbox->moveToLeft(st::contactsPadding.left(), st::contactsAllAdminsTop);
auto labelHeight = qMax(
_labelChecked.countHeight(_labelWidth),
_labelUnchecked.countHeight(_labelWidth));
return st::contactsAboutTop + labelHeight + st::contactsAboutBottom;
}
void EditChatAdminsBoxController::LabeledCheckbox::paintEvent(QPaintEvent *e) {
Painter p(this);
auto infoTop = _checkbox->bottomNoMargins() + st::contactsAllAdminsTop - st::lineWidth;
auto infoRect = rtlrect(0, infoTop, width(), height() - infoTop - st::contactsPadding.bottom(), width());
p.fillRect(infoRect, st::contactsAboutBg);
auto dividerFillTop = rtlrect(0, infoRect.y(), width(), st::profileDividerTop.height(), width());
st::profileDividerTop.fill(p, dividerFillTop);
auto dividerFillBottom = rtlrect(0, infoRect.y() + infoRect.height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height(), width());
st::profileDividerBottom.fill(p, dividerFillBottom);
p.setPen(st::contactsAboutFg);
(checked() ? _labelChecked : _labelUnchecked).draw(p, st::contactsPadding.left(), st::contactsAboutTop, _labelWidth);
}
EditChatAdminsBoxController::EditChatAdminsBoxController(not_null<ChatData*> chat)
: PeerListController()
, _chat(chat) {
}
bool EditChatAdminsBoxController::allAreAdmins() const {
return _allAdmins->checked();
}
void EditChatAdminsBoxController::prepare() {
createAllAdminsCheckbox();
setSearchNoResultsText(lang(lng_blocked_list_not_found));
delegate()->peerListSetSearchMode(allAreAdmins() ? PeerListSearchMode::Disabled : PeerListSearchMode::Enabled);
delegate()->peerListSetTitle(langFactory(lng_channel_admins));
rebuildRows();
if (!delegate()->peerListFullRowsCount()) {
Auth().api().requestFullPeer(_chat);
_adminsUpdatedSubscription = subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
Notify::PeerUpdate::Flag::AdminsChanged, [this](
const Notify::PeerUpdate &update) {
if (update.peer == _chat) {
rebuildRows();
if (delegate()->peerListFullRowsCount()) {
unsubscribe(_adminsUpdatedSubscription);
}
}
}));
}
_allAdmins->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
delegate()->peerListSetSearchMode(checked ? PeerListSearchMode::Disabled : PeerListSearchMode::Enabled);
for (auto i = 0, count = delegate()->peerListFullRowsCount(); i != count; ++i) {
auto row = delegate()->peerListRowAt(i);
auto user = row->peer()->asUser();
if (checked || user->id == peerFromUser(_chat->creator)) {
row->setDisabledState(PeerListRow::State::DisabledChecked);
} else {
row->setDisabledState(PeerListRow::State::Active);
}
}
}, _allAdmins->lifetime());
}
void EditChatAdminsBoxController::createAllAdminsCheckbox() {
// #TODO groups
auto labelWidth = st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right();
auto checkbox = object_ptr<LabeledCheckbox>(nullptr, lang(lng_chat_all_members_admins), /*!_chat->adminsEnabled()*/false, st::defaultBoxCheckbox);
checkbox->setLabelText(true, st::defaultTextStyle, lang(lng_chat_about_all_admins), _defaultOptions, labelWidth);
checkbox->setLabelText(false, st::defaultTextStyle, lang(lng_chat_about_admins), _defaultOptions, labelWidth);
_allAdmins = checkbox;
delegate()->peerListSetAboveWidget(std::move(checkbox));
}
void EditChatAdminsBoxController::rebuildRows() {
if (_chat->participants.empty()) {
return;
}
auto allAdmins = allAreAdmins();
auto admins = std::vector<not_null<UserData*>>();
auto others = admins;
admins.reserve(allAdmins ? _chat->participants.size() : _chat->admins.size());
others.reserve(_chat->participants.size());
for (const auto [user, version] : _chat->participants) {
if (user->id == peerFromUser(_chat->creator)) continue;
if (_chat->admins.contains(user)) {
admins.push_back(user);
} else {
others.push_back(user);
}
}
if (!admins.empty()) {
delegate()->peerListAddSelectedRows(admins);
}
if (allAdmins) {
admins.insert(admins.end(), others.begin(), others.end());
others.clear();
}
auto sortByName = [](not_null<UserData*> a, auto b) {
return (a->name.compare(b->name, Qt::CaseInsensitive) < 0);
};
ranges::sort(admins, sortByName);
ranges::sort(others, sortByName);
auto addOne = [this](not_null<UserData*> user) {
if (auto row = createRow(user)) {
delegate()->peerListAppendRow(std::move(row));
}
};
if (auto creator = App::userLoaded(_chat->creator)) {
if (_chat->participants.contains(creator)) {
addOne(creator);
}
}
ranges::for_each(admins, addOne);
ranges::for_each(others, addOne);
delegate()->peerListRefreshRows();
}
std::unique_ptr<PeerListRow> EditChatAdminsBoxController::createRow(not_null<UserData*> user) {
auto result = std::make_unique<PeerListRow>(user);
if (allAreAdmins() || user->id == peerFromUser(_chat->creator)) {
result->setDisabledState(PeerListRow::State::DisabledChecked);
}
return result;
}
void EditChatAdminsBoxController::rowClicked(not_null<PeerListRow*> row) {
delegate()->peerListSetRowChecked(row, !row->checked());
}
void EditChatAdminsBoxController::Start(not_null<ChatData*> chat) {
auto controller = std::make_unique<EditChatAdminsBoxController>(chat);
auto initBox = [chat, controller = controller.get()](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_settings_save), [box, chat, controller] {
auto rows = box->peerListCollectSelectedRows();
auto users = std::vector<not_null<UserData*>>();
for (auto peer : rows) {
auto user = peer->asUser();
Assert(user != nullptr);
Assert(!user->isSelf());
users.push_back(peer->asUser());
}
Auth().api().editChatAdmins(chat, !controller->allAreAdmins(), { users.cbegin(), users.cend() });
box->closeBox();
});
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
};
Ui::show(
Box<PeerListBox>(std::move(controller), std::move(initBox)),
LayerOption::KeepOther);
}
void AddBotToGroupBoxController::Start(not_null<UserData*> bot) {
auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });

View file

@ -136,30 +136,6 @@ private:
};
class EditChatAdminsBoxController : public PeerListController, private base::Subscriber {
public:
static void Start(not_null<ChatData*> chat);
EditChatAdminsBoxController(not_null<ChatData*> chat);
bool allAreAdmins() const;
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
private:
void createAllAdminsCheckbox();
void rebuildRows();
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
not_null<ChatData*> _chat;
int _adminsUpdatedSubscription = 0;
class LabeledCheckbox;
QPointer<LabeledCheckbox> _allAdmins;
};
class AddParticipantsBoxController : public ContactsBoxController {
public:
static void Start(not_null<ChatData*> chat);

View file

@ -291,20 +291,25 @@ void EditRestrictedBox::prepare() {
object_ptr<BoxContentDivider>(this),
st::rightsDividerMargin);
const auto prepareRights = _oldRights.c_chatBannedRights().vflags.v
const auto prepareRights = (_oldRights.c_chatBannedRights().vflags.v
? _oldRights
: Defaults(channel());
: Defaults(channel()));
const auto prepareFlags = prepareRights.c_chatBannedRights().vflags.v
| (channel()->defaultRestrictions()
| (channel()->isPublic()
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0)));
const auto disabledFlags = canSave()
? (channel()->defaultRestrictions()
/*| (channel()->isPublic()
| (channel()->isPublic()
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0))*/) // #TODO groups
: Flags(0))) // #TODO groups
: ~Flags(0);
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
this,
lng_rights_user_restrictions_header,
prepareRights.c_chatBannedRights().vflags.v,
prepareFlags,
disabledFlags);
addControl(std::move(checkboxes), QMargins());
@ -345,14 +350,7 @@ void EditRestrictedBox::prepare() {
MTPChatBannedRights EditRestrictedBox::Defaults(
not_null<ChannelData*> channel) {
const auto defaultRights = Flag::f_send_messages
| Flag::f_send_media
| Flag::f_embed_links
| Flag::f_send_stickers
| Flag::f_send_gifs
| Flag::f_send_games
| Flag::f_send_inline;
return MTP_chatBannedRights(MTP_flags(defaultRights), MTP_int(0));
return MTP_chatBannedRights(MTP_flags(0), MTP_int(0));
}
void EditRestrictedBox::showRestrictUntil() {

View file

@ -111,8 +111,6 @@ private:
object_ptr<Ui::RpWidget> createHistoryVisibilityEdit();
object_ptr<Ui::RpWidget> createSignaturesEdit();
object_ptr<Ui::RpWidget> createStickersEdit();
object_ptr<Ui::RpWidget> createManageAdminsButton();
object_ptr<Ui::RpWidget> createUpgradeButton();
object_ptr<Ui::RpWidget> createDeleteButton();
QString inviteLinkText() const;
@ -210,8 +208,6 @@ object_ptr<Ui::VerticalLayout> Controller::createContent() {
_wrap->add(createHistoryVisibilityEdit());
_wrap->add(createSignaturesEdit());
_wrap->add(createStickersEdit());
_wrap->add(createManageAdminsButton());
_wrap->add(createUpgradeButton());
_wrap->add(createDeleteButton());
return result;
@ -312,11 +308,6 @@ object_ptr<Ui::RpWidget> Controller::createTitleEdit() {
object_ptr<Ui::RpWidget> Controller::createDescriptionEdit() {
Expects(_wrap != nullptr);
auto channel = _peer->asChannel();
if (!channel || !channel->canEditInformation()) {
return nullptr;
}
auto result = object_ptr<Ui::PaddingWrap<Ui::InputField>>(
_wrap,
object_ptr<Ui::InputField>(
@ -324,7 +315,7 @@ object_ptr<Ui::RpWidget> Controller::createDescriptionEdit() {
st::editPeerDescription,
Ui::InputField::Mode::MultiLine,
langFactory(lng_create_group_description),
channel->about()),
_peer->about()),
st::editPeerDescriptionMargins);
result->entity()->setMaxLength(kMaxChannelDescription);
result->entity()->setInstantReplaces(Ui::InstantReplaces::Default());
@ -346,8 +337,15 @@ object_ptr<Ui::RpWidget> Controller::createDescriptionEdit() {
object_ptr<Ui::RpWidget> Controller::createPrivaciesEdit() {
Expects(_wrap != nullptr);
auto channel = _peer->asChannel();
if (!channel || !channel->canEditUsername()) {
const auto canEditUsername = [&] {
if (const auto chat = _peer->asChat()) {
return chat->canEditUsername();
} else if (const auto channel = _peer->asChannel()) {
return channel->canEditUsername();
}
Unexpected("Peer type in Controller::createPrivaciesEdit.");
}();
if (!canEditUsername) {
return nullptr;
}
auto result = object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>(
@ -356,8 +354,10 @@ object_ptr<Ui::RpWidget> Controller::createPrivaciesEdit() {
st::editPeerPrivaciesMargins);
auto container = result->entity();
const auto isPublic = _peer->isChannel()
&& _peer->asChannel()->isPublic();
_controls.privacy = std::make_shared<Ui::RadioenumGroup<Privacy>>(
channel->isPublic() ? Privacy::Public : Privacy::Private);
isPublic ? Privacy::Public : Privacy::Private);
auto addButton = [&](
Privacy value,
LangKey groupTextKey,
@ -401,7 +401,7 @@ object_ptr<Ui::RpWidget> Controller::createPrivaciesEdit() {
_controls.privacy->setChangedCallback([this](Privacy value) {
privacyChanged(value);
});
if (!channel->isPublic()) {
if (!isPublic) {
checkUsernameAvailability();
}
@ -411,8 +411,8 @@ object_ptr<Ui::RpWidget> Controller::createPrivaciesEdit() {
object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
Expects(_wrap != nullptr);
auto channel = _peer->asChannel();
Assert(channel != nullptr);
const auto channel = _peer->asChannel();
const auto username = channel ? channel->username : QString();
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_wrap,
@ -434,7 +434,7 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
container,
st::setupChannelLink,
Fn<QString()>(),
channel->username,
username,
true));
_controls.username->heightValue(
) | rpl::start_with_next([placeholder](int height) {
@ -506,9 +506,6 @@ void Controller::checkUsernameAvailability() {
if (!_controls.username) {
return;
}
auto channel = _peer->asChannel();
Assert(channel != nullptr);
auto initial = (_controls.privacy->value() != Privacy::Public);
auto checking = initial
? qsl(".bad.")
@ -519,15 +516,17 @@ void Controller::checkUsernameAvailability() {
if (_checkUsernameRequestId) {
request(_checkUsernameRequestId).cancel();
}
const auto channel = _peer->asChannel();
const auto username = channel ? channel->username : QString();
_checkUsernameRequestId = request(MTPchannels_CheckUsername(
channel->inputChannel,
channel ? channel->inputChannel : MTP_inputChannelEmpty(),
MTP_string(checking)
)).done([=](const MTPBool &result) {
_checkUsernameRequestId = 0;
if (initial) {
return;
}
if (!mtpIsTrue(result) && checking != channel->username) {
if (!mtpIsTrue(result) && checking != username) {
showUsernameError(
Lang::Viewer(lng_create_channel_link_occupied));
} else {
@ -555,7 +554,7 @@ void Controller::checkUsernameAvailability() {
showUsernameError(
Lang::Viewer(lng_create_channel_link_invalid));
} else if (type == qstr("USERNAME_OCCUPIED")
&& checking != channel->username) {
&& checking != username) {
showUsernameError(
Lang::Viewer(lng_create_channel_link_occupied));
}
@ -656,13 +655,13 @@ void Controller::exportInviteLink(const QString &confirmation) {
}
bool Controller::canEditInviteLink() const {
if (auto channel = _peer->asChannel()) {
if (const auto channel = _peer->asChannel()) {
if (channel->canEditUsername()) {
return true;
}
return (!channel->isPublic() && channel->canAddMembers());
} else if (auto chat = _peer->asChat()) {
return !chat->inviteLink().isEmpty() || chat->amCreator();
} else if (const auto chat = _peer->asChat()) {
return chat->amCreator() || !chat->inviteLink().isEmpty();
}
return false;
}
@ -673,9 +672,9 @@ bool Controller::inviteLinkShown() const {
}
QString Controller::inviteLinkText() const {
if (auto channel = _peer->asChannel()) {
if (const auto channel = _peer->asChannel()) {
return channel->inviteLink();
} else if (auto chat = _peer->asChat()) {
} else if (const auto chat = _peer->asChat()) {
return chat->inviteLink();
}
return QString();
@ -808,13 +807,19 @@ void Controller::refreshCreateInviteLink() {
object_ptr<Ui::RpWidget> Controller::createHistoryVisibilityEdit() {
Expects(_wrap != nullptr);
auto channel = _peer->asChannel();
if (!channel
|| !channel->canEditPreHistoryHidden()
|| !channel->isMegagroup()
|| (channel->isPublic() && !channel->canEditUsername())) {
const auto canEdit = [&] {
if (const auto chat = _peer->asChat()) {
return chat->canEditPreHistoryHidden();
} else if (const auto channel = _peer->asChannel()) {
return channel->canEditPreHistoryHidden();
}
Unexpected("User in Controller::createHistoryVisibilityEdit.");
}();
if (!canEdit) {
return nullptr;
}
const auto channel = _peer->asChannel();
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_wrap,
object_ptr<Ui::VerticalLayout>(_wrap),
@ -824,7 +829,7 @@ object_ptr<Ui::RpWidget> Controller::createHistoryVisibilityEdit() {
_controls.historyVisibility
= std::make_shared<Ui::RadioenumGroup<HistoryVisibility>>(
channel->hiddenPreHistory()
(!channel || channel->hiddenPreHistory())
? HistoryVisibility::Hidden
: HistoryVisibility::Visible);
auto addButton = [&](
@ -941,53 +946,13 @@ object_ptr<Ui::RpWidget> Controller::createStickersEdit() {
_wrap,
lang(lng_group_stickers_add),
st::editPeerInviteLinkButton)
)->addClickHandler([channel] {
)->addClickHandler([=] {
Ui::show(Box<StickersBox>(channel), LayerOption::KeepOther);
});
return std::move(result);
}
object_ptr<Ui::RpWidget> Controller::createManageAdminsButton() {
Expects(_wrap != nullptr);
auto chat = _peer->asChat();
if (!chat || !chat->amCreator() || chat->isDeactivated()) {
return nullptr;
}
auto result = object_ptr<Ui::PaddingWrap<Ui::LinkButton>>(
_wrap,
object_ptr<Ui::LinkButton>(
_wrap,
lang(lng_profile_manage_admins),
st::editPeerInviteLinkButton),
st::editPeerDeleteButtonMargins);
result->entity()->addClickHandler([=] {
EditChatAdminsBoxController::Start(chat);
});
return std::move(result);
}
object_ptr<Ui::RpWidget> Controller::createUpgradeButton() {
Expects(_wrap != nullptr);
auto chat = _peer->asChat();
if (!chat || !chat->amCreator() || chat->isDeactivated()) {
return nullptr;
}
auto result = object_ptr<Ui::PaddingWrap<Ui::LinkButton>>(
_wrap,
object_ptr<Ui::LinkButton>(
_wrap,
lang(lng_profile_migrate_button),
st::editPeerInviteLinkButton),
st::editPeerDeleteButtonMargins);
result->entity()->addClickHandler([=] {
Ui::show(Box<ConvertToSupergroupBox>(chat), LayerOption::KeepOther);
});
return std::move(result);
}
object_ptr<Ui::RpWidget> Controller::createDeleteButton() {
Expects(_wrap != nullptr);
@ -1139,12 +1104,15 @@ void Controller::cancelSave() {
}
void Controller::saveUsername() {
auto channel = _peer->asChannel();
if (!_savingData.username
|| !channel
|| *_savingData.username == channel->username) {
const auto channel = _peer->asChannel();
const auto username = (channel ? channel->username : QString());
if (!_savingData.username || *_savingData.username == username) {
return continueSave();
} else if (!channel) {
// #TODO groups convert and save.
return continueSave();
}
request(MTPchannels_UpdateUsername(
channel->inputChannel,
MTP_string(*_savingData.username)
@ -1154,7 +1122,7 @@ void Controller::saveUsername() {
*_savingData.username);
continueSave();
}).fail([=](const RPCError &error) {
auto type = error.type();
const auto type = error.type();
if (type == qstr("USERNAME_NOT_MODIFIED")) {
channel->setName(
TextUtilities::SingleLine(channel->name),
@ -1162,7 +1130,7 @@ void Controller::saveUsername() {
continueSave();
return;
}
auto errorKey = [&] {
const auto errorKey = [&] {
if (type == qstr("USERNAME_INVALID")) {
return lng_create_channel_link_invalid;
} else if (type == qstr("USERNAME_OCCUPIED")
@ -1183,17 +1151,17 @@ void Controller::saveTitle() {
return continueSave();
}
auto onDone = [this](const MTPUpdates &result) {
const auto onDone = [=](const MTPUpdates &result) {
Auth().api().applyUpdates(result);
continueSave();
};
auto onFail = [this](const RPCError &error) {
auto type = error.type();
const auto onFail = [=](const RPCError &error) {
const auto type = error.type();
if (type == qstr("CHAT_NOT_MODIFIED")
|| type == qstr("CHAT_TITLE_NOT_MODIFIED")) {
if (auto channel = _peer->asChannel()) {
if (const auto channel = _peer->asChannel()) {
channel->setName(*_savingData.title, channel->username);
} else if (auto chat = _peer->asChat()) {
} else if (const auto chat = _peer->asChat()) {
chat->setName(*_savingData.title);
}
continueSave();
@ -1206,14 +1174,14 @@ void Controller::saveTitle() {
cancelSave();
};
if (auto channel = _peer->asChannel()) {
if (const auto channel = _peer->asChannel()) {
request(MTPchannels_EditTitle(
channel->inputChannel,
MTP_string(*_savingData.title)
)).done(std::move(onDone)
).fail(std::move(onFail)
).send();
} else if (auto chat = _peer->asChat()) {
} else if (const auto chat = _peer->asChat()) {
request(MTPmessages_EditChatTitle(
chat->inputChat,
MTP_string(*_savingData.title)
@ -1226,18 +1194,17 @@ void Controller::saveTitle() {
}
void Controller::saveDescription() {
auto channel = _peer->asChannel();
const auto channel = _peer->asChannel();
if (!_savingData.description
|| !channel
|| *_savingData.description == channel->about()) {
|| *_savingData.description == _peer->about()) {
return continueSave();
}
auto successCallback = [=] {
channel->setAbout(*_savingData.description);
const auto successCallback = [=] {
_peer->setAbout(*_savingData.description);
continueSave();
};
request(MTPmessages_EditChatAbout(
channel->input,
_peer->input,
MTP_string(*_savingData.description)
)).done([=](const MTPBool &result) {
successCallback();
@ -1253,10 +1220,13 @@ void Controller::saveDescription() {
}
void Controller::saveHistoryVisibility() {
auto channel = _peer->asChannel();
const auto channel = _peer->asChannel();
const auto hidden = channel ? channel->hiddenPreHistory() : true;
if (!_savingData.hiddenPreHistory
|| !channel
|| *_savingData.hiddenPreHistory == channel->hiddenPreHistory()) {
|| *_savingData.hiddenPreHistory == hidden) {
return continueSave();
} else if (!channel) {
// #TODO groups convert and save.
return continueSave();
}
request(MTPchannels_TogglePreHistoryHidden(
@ -1280,7 +1250,7 @@ void Controller::saveHistoryVisibility() {
}
void Controller::saveSignatures() {
auto channel = _peer->asChannel();
const auto channel = _peer->asChannel();
if (!_savingData.signatures
|| !channel
|| *_savingData.signatures == channel->addsSignature()) {
@ -1315,21 +1285,25 @@ void Controller::deleteWithConfirmation() {
const auto channel = _peer->asChannel();
Assert(channel != nullptr);
auto text = lang(_isGroup
const auto text = lang(_isGroup
? lng_sure_delete_group
: lng_sure_delete_channel);
auto deleteCallback = crl::guard(this, [=] {
const auto deleteCallback = crl::guard(this, [=] {
deleteChannel();
});
Ui::show(Box<ConfirmBox>(
text,
lang(lng_box_delete),
st::attentionBoxButton,
std::move(deleteCallback)), LayerOption::KeepOther);
Ui::show(
Box<ConfirmBox>(
text,
lang(lng_box_delete),
st::attentionBoxButton,
deleteCallback),
LayerOption::KeepOther);
}
void Controller::deleteChannel() {
const auto channel = _peer->asChannel();
Assert(channel != nullptr);
const auto chat = channel->migrateFrom();
Ui::hideLayer();

View file

@ -189,7 +189,6 @@ auto ToPositiveNumberString() {
ChatRestrictions DisabledByAdminRights(not_null<PeerData*> peer) {
using Flag = ChatRestriction;
using Flags = ChatRestrictions;
using Admin = ChatAdminRight;
using Admins = ChatAdminRights;
@ -241,13 +240,13 @@ void EditPeerPermissionsBox::prepare() {
const auto restrictions = [&] {
if (const auto chat = _peer->asChat()) {
return chat->defaultRestrictions()
/*| disabledByAdminRights*/; // #TODO groups
| disabledByAdminRights; // #TODO groups
} else if (const auto channel = _peer->asChannel()) {
return (channel->defaultRestrictions()
/*| (channel->isPublic()
| (channel->isPublic()
? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0))
| disabledByAdminRights*/); // #TODO groups
| disabledByAdminRights); // #TODO groups
}
Unexpected("User in EditPeerPermissionsBox.");
}();

View file

@ -55,15 +55,6 @@ void ChannelData::setName(const QString &newName, const QString &newUsername) {
updateNameDelayed(newName.isEmpty() ? name : newName, QString(), newUsername);
}
bool ChannelData::setAbout(const QString &newAbout) {
if (_about == newAbout) {
return false;
}
_about = newAbout;
Notify::peerUpdatedDelayed(this, UpdateFlag::AboutChanged);
return true;
}
void ChannelData::setInviteLink(const QString &newInviteLink) {
if (newInviteLink != _inviteLink) {
_inviteLink = newInviteLink;
@ -365,7 +356,9 @@ bool ChannelData::canEditSignatures() const {
}
bool ChannelData::canEditPreHistoryHidden() const {
return canEditInformation();
return canEditInformation()
&& isMegagroup()
&& (!isPublic() || canEditUsername());
}
bool ChannelData::canEditUsername() const {

View file

@ -124,12 +124,6 @@ public:
return _fullFlags.value();
}
// Returns true if about text was changed.
bool setAbout(const QString &newAbout);
const QString &about() const {
return _about;
}
int membersCount() const {
return _membersCount;
}
@ -249,6 +243,8 @@ public:
bool canWrite() const;
bool canEditInformation() const;
bool canEditPermissions() const;
bool canEditUsername() const;
bool canEditPreHistoryHidden() const;
bool canAddMembers() const;
bool canBanMembers() const;
@ -262,8 +258,6 @@ public:
bool canViewAdmins() const;
bool canViewBanned() const;
bool canEditSignatures() const;
bool canEditPreHistoryHidden() const;
bool canEditUsername() const;
bool canEditStickers() const;
bool canDelete() const;
bool canEditAdmin(not_null<UserData*> user) const;
@ -346,9 +340,6 @@ public:
TimeId inviteDate = 0;
private:
void flagsUpdated(MTPDchannel::Flags diff);
void fullFlagsUpdated(MTPDchannelFull::Flags diff);
bool canEditLastAdmin(not_null<UserData*> user) const;
void setFeedPointer(Data::Feed *feed);
@ -369,7 +360,6 @@ private:
TimeId _restrictedUntil;
QString _unavailableReason;
QString _about;
QString _inviteLink;
Data::Feed *_feed = nullptr;

View file

@ -53,6 +53,15 @@ bool ChatData::canEditPermissions() const {
&& (amCreator() || hasAdminRights());
}
bool ChatData::canEditUsername() const {
return amCreator()
&& (fullFlags() & MTPDchatFull::Flag::f_can_set_username);
}
bool ChatData::canEditPreHistoryHidden() const {
return amCreator();
}
bool ChatData::canAddMembers() const {
return !actionsUnavailable()
&& !amRestricted(ChatRestriction::f_invite_users);

View file

@ -23,6 +23,12 @@ public:
MTPDchat::Flags,
kEssentialFlags>;
static constexpr auto kEssentialFullFlags = 0
| MTPDchatFull::Flag::f_can_set_username;
using FullFlags = Data::Flags<
MTPDchatFull::Flags,
kEssentialFullFlags>;
using AdminRight = ChatAdminRight;
using Restriction = ChatRestriction;
using AdminRights = ChatAdminRights;
@ -58,6 +64,22 @@ public:
return _flags.value();
}
void setFullFlags(MTPDchatFull::Flags which) {
_fullFlags.set(which);
}
void addFullFlags(MTPDchatFull::Flags which) {
_fullFlags.add(which);
}
void removeFullFlags(MTPDchatFull::Flags which) {
_fullFlags.remove(which);
}
auto fullFlags() const {
return _fullFlags.current();
}
auto fullFlagsValue() const {
return _fullFlags.value();
}
auto adminRights() const {
return _adminRights.current();
}
@ -103,6 +125,8 @@ public:
bool canWrite() const;
bool canEditInformation() const;
bool canEditPermissions() const;
bool canEditUsername() const;
bool canEditPreHistoryHidden() const;
bool canAddMembers() const;
void setInviteLink(const QString &newInviteLink);
@ -130,9 +154,9 @@ public:
private:
[[nodiscard]] bool actionsUnavailable() const;
void flagsUpdated(MTPDchat::Flags diff);
Flags _flags;
FullFlags _fullFlags;
QString _inviteLink;
RestrictionFlags _defaultRestrictions;

View file

@ -381,6 +381,15 @@ void PeerData::setPinnedMessageId(MsgId messageId) {
}
}
bool PeerData::setAbout(const QString &newAbout) {
if (_about == newAbout) {
return false;
}
_about = newAbout;
Notify::peerUpdatedDelayed(this, UpdateFlag::AboutChanged);
return true;
}
void PeerData::fillNames() {
_nameWords.clear();
_nameFirstLetters.clear();

View file

@ -224,6 +224,12 @@ public:
setPinnedMessageId(0);
}
// Returns true if about text was changed.
bool setAbout(const QString &newAbout);
const QString &about() const {
return _about;
}
protected:
void updateNameDelayed(
const QString &newName,
@ -260,4 +266,6 @@ private:
TimeMs _lastFullUpdate = 0;
MsgId _pinnedMessageId = 0;
QString _about;
};

View file

@ -82,15 +82,6 @@ void UserData::setPhoto(const MTPUserProfilePhoto &photo) {
}
}
bool UserData::setAbout(const QString &newAbout) {
if (_about == newAbout) {
return false;
}
_about = newAbout;
Notify::peerUpdatedDelayed(this, UpdateFlag::AboutChanged);
return true;
}
QString UserData::unavailableReason() const {
return _unavailableReason;
}

View file

@ -195,11 +195,6 @@ public:
bool hasCalls() const;
void setCallsStatus(CallsStatus callsStatus);
bool setAbout(const QString &newAbout);
const QString &about() const {
return _about;
}
std::unique_ptr<BotInfo> botInfo;
QString unavailableReason() const override;
@ -215,7 +210,6 @@ private:
FullFlags _fullFlags;
QString _unavailableReason;
QString _about;
QString _phone;
ContactStatus _contactStatus = ContactStatus::PhoneUnknown;
BlockStatus _blockStatus = BlockStatus::Unknown;

View file

@ -2738,8 +2738,8 @@ int HistoryInner::itemTop(const Element *view) const {
}
void HistoryInner::notifyIsBotChanged() {
const auto newinfo = (_history && _history->peer->isUser())
? _history->peer->asUser()->botInfo.get()
const auto newinfo = (_peer && _peer->isUser())
? _peer->asUser()->botInfo.get()
: nullptr;
if ((!newinfo && !_botAbout)
|| (newinfo && _botAbout && _botAbout->info == newinfo)) {

View file

@ -3686,7 +3686,7 @@ void HistoryWidget::setMembersShowAreaActive(bool active) {
void HistoryWidget::onMembersDropdownShow() {
if (!_membersDropdown) {
_membersDropdown.create(this, st::membersInnerDropdown);
_membersDropdown->setOwnedWidget(object_ptr<Profile::GroupMembersWidget>(this, _peer, Profile::GroupMembersWidget::TitleVisibility::Hidden, st::membersInnerItem));
_membersDropdown->setOwnedWidget(object_ptr<Profile::GroupMembersWidget>(this, _peer, st::membersInnerItem));
_membersDropdown->resizeToWidth(st::membersInnerWidth);
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax());

View file

@ -324,7 +324,7 @@ void Members::updateHeaderControlsGeometry(int newWidth) {
void Members::addMember() {
if (const auto chat = _peer->asChat()) {
if (chat->count >= Global::ChatSizeMax() && chat->amCreator()) {
Ui::show(Box<ConvertToSupergroupBox>(chat));
// #TODO convert and add inside AddParticipantsBoxController?
} else {
AddParticipantsBoxController::Start(chat);
}

View file

@ -46,8 +46,8 @@ rpl::producer<TextWithEntities> PhoneValue(not_null<UserData*> user) {
auto PlainBioValue(not_null<UserData*> user) {
return Notify::PeerUpdateValue(
user,
Notify::PeerUpdate::Flag::AboutChanged
user,
Notify::PeerUpdate::Flag::AboutChanged
) | rpl::map([user] { return user->about(); });
}
@ -77,20 +77,17 @@ rpl::producer<TextWithEntities> UsernameValue(not_null<UserData*> user) {
}
rpl::producer<QString> PlainAboutValue(not_null<PeerData*> peer) {
if (auto channel = peer->asChannel()) {
return Notify::PeerUpdateValue(
channel,
Notify::PeerUpdate::Flag::AboutChanged
) | rpl::map([channel] { return channel->about(); });
} else if (auto user = peer->asUser()) {
if (user->botInfo) {
return PlainBioValue(user);
if (const auto user = peer->asUser()) {
if (!user->botInfo) {
return rpl::single(QString());
}
}
return rpl::single(QString());
return Notify::PeerUpdateValue(
peer,
Notify::PeerUpdate::Flag::AboutChanged
) | rpl::map([=] { return peer->about(); });
}
rpl::producer<TextWithEntities> AboutValue(not_null<PeerData*> peer) {
auto flags = TextParseLinks
| TextParseMentions
@ -160,9 +157,9 @@ rpl::producer<bool> CanShareContactValue(not_null<UserData*> user) {
rpl::producer<bool> CanAddContactValue(not_null<UserData*> user) {
using namespace rpl::mappers;
return rpl::combine(
IsContactValue(user),
CanShareContactValue(user),
!_1 && _2);
IsContactValue(user),
CanShareContactValue(user),
!_1 && _2);
}
rpl::producer<bool> AmInChannelValue(not_null<ChannelData*> channel) {
@ -177,7 +174,7 @@ rpl::producer<int> MembersCountValue(not_null<PeerData*> peer) {
if (const auto chat = peer->asChat()) {
return Notify::PeerUpdateValue(
peer,
Notify::PeerUpdate::Flag::MembersChanged
Flag::MembersChanged
) | rpl::map([chat] {
return chat->amIn()
? std::max(chat->count, int(chat->participants.size()))
@ -185,8 +182,8 @@ rpl::producer<int> MembersCountValue(not_null<PeerData*> peer) {
});
} else if (const auto channel = peer->asChannel()) {
return Notify::PeerUpdateValue(
channel,
Notify::PeerUpdate::Flag::MembersChanged
channel,
Flag::MembersChanged
) | rpl::map([channel] {
return channel->membersCount();
});

View file

@ -3875,14 +3875,15 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
case mtpc_updateShortChatMessage: {
auto &d = updates.c_updateShortChatMessage();
bool noFrom = !App::userLoaded(d.vfrom_id.v);
if (!App::chatLoaded(d.vchat_id.v)
const auto chat = App::chatLoaded(d.vchat_id.v);
if (!chat
|| noFrom
|| (d.has_via_bot_id() && !App::userLoaded(d.vvia_bot_id.v))
|| (d.has_entities() && !mentionUsersLoaded(d.ventities))
|| (d.has_fwd_from() && !fwdInfoDataLoaded(d.vfwd_from))) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
if (noFrom) {
Auth().api().requestFullPeer(App::chatLoaded(d.vchat_id.v));
if (chat && noFrom) {
Auth().api().requestFullPeer(chat);
}
return getDifference();
}
@ -4240,8 +4241,13 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
Auth().api().requestPeer(chat);
}
} else if (const auto channel = peer->asChannel()) {
channel->setDefaultRestrictions(
data.vdefault_banned_rights);
if (data.vversion.v == channel->version + 1) {
channel->setDefaultRestrictions(
data.vdefault_banned_rights);
} else {
channel->version = data.vversion.v;
Auth().api().requestPeer(channel);
}
} else {
LOG(("API Error: "
"User received in updateChatDefaultBannedRights."));

View file

@ -108,13 +108,6 @@ profileInviteLinkText: FlatLabel(profileBlockTextPart) {
profileLimitReachedSkip: 6px;
profileMemberItem: PeerListItem(defaultPeerListItem) {
left: 8px;
bottom: profileBlockMarginBottom;
button: defaultLeftOutlineButton;
maximalWidth: profileBlockWideWidthMax;
statusFgOver: profileStatusFgOver;
}
profileMemberPaddingLeft: 16px;
profileMemberNameFg: windowBoldFg;
profileMemberCreatorIcon: icon {{ "profile_admin_star", profileAdminStartFg, point(4px, 3px) }};

View file

@ -40,13 +40,8 @@ UserData *GroupMembersWidget::Member::user() const {
GroupMembersWidget::GroupMembersWidget(
QWidget *parent,
PeerData *peer,
TitleVisibility titleVisibility,
const style::PeerListItem &st)
: PeerListWidget(parent
, peer
, (titleVisibility == TitleVisibility::Visible) ? lang(lng_profile_participants_section) : QString()
, st
, lang(lng_profile_kick)) {
: PeerListWidget(parent, peer, QString(), st, lang(lng_profile_kick)) {
_updateOnlineTimer.setSingleShot(true);
connect(&_updateOnlineTimer, SIGNAL(timeout()), this, SLOT(onUpdateOnlineDisplay()));
@ -203,83 +198,6 @@ void GroupMembersWidget::preloadMore() {
//}
}
int GroupMembersWidget::resizeGetHeight(int newWidth) {
if (_limitReachedInfo) {
int limitReachedInfoWidth = newWidth - getListLeft();
accumulate_min(limitReachedInfoWidth, st::profileBlockWideWidthMax);
_limitReachedInfo->resizeToWidth(limitReachedInfoWidth);
_limitReachedInfo->moveToLeft(getListLeft(), contentTop());
}
return PeerListWidget::resizeGetHeight(newWidth);
}
void GroupMembersWidget::paintContents(Painter &p) {
int left = getListLeft();
int top = getListTop();
int memberRowWidth = width() - left;
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
if (_limitReachedInfo) {
int infoTop = contentTop();
int infoHeight = top - infoTop - st::profileLimitReachedSkip;
paintOutlinedRect(p, left, infoTop, memberRowWidth, infoHeight);
}
_now = unixtime();
PeerListWidget::paintContents(p);
}
Ui::PopupMenu *GroupMembersWidget::fillPeerMenu(PeerData *selectedPeer) {
Expects(selectedPeer->isUser());
if (emptyTitle()) {
return nullptr;
}
auto user = selectedPeer->asUser();
auto result = new Ui::PopupMenu(this);
result->addAction(lang(lng_context_view_profile), [selectedPeer] {
Ui::showPeerProfile(selectedPeer);
});
auto chat = peer()->asChat();
auto channel = peer()->asMegagroup();
for_const (auto item, items()) {
if (item->peer == selectedPeer) {
auto canRemoveAdmin = [item, chat, channel] {
if ((item->adminState == Item::AdminState::Admin) && !item->peer->isSelf()) {
if (chat) {
// Adding of admins from context menu of chat participants
// is not supported, so the removing is also disabled.
return false;//chat->amCreator();
} else if (channel) {
return channel->amCreator();
}
}
return false;
};
if (channel) {
if (channel->canEditAdmin(user)) {
auto label = lang((item->adminState != Item::AdminState::None) ? lng_context_edit_permissions : lng_context_promote_admin);
result->addAction(label, crl::guard(this, [this, user] {
editAdmin(user);
}));
}
if (channel->canRestrictUser(user)) {
result->addAction(lang(lng_context_restrict_user), crl::guard(this, [this, user] {
restrictUser(user);
}));
result->addAction(lang(lng_context_remove_from_group), crl::guard(this, [this, selectedPeer] {
removePeer(selectedPeer);
}));
}
} else if (item->hasRemoveLink) {
result->addAction(lang(lng_context_remove_from_group), crl::guard(this, [this, selectedPeer] {
removePeer(selectedPeer);
}));
}
}
}
return result;
}
void GroupMembersWidget::updateItemStatusText(Item *item) {
auto member = getMember(item);
auto user = member->user();
@ -303,15 +221,6 @@ void GroupMembersWidget::updateItemStatusText(Item *item) {
}
}
int GroupMembersWidget::getListTop() const {
int result = contentTop();
if (_limitReachedInfo) {
result += _limitReachedInfo->height();
result += st::profileLimitReachedSkip;
}
return result;
}
void GroupMembersWidget::refreshMembers() {
_now = unixtime();
if (auto chat = peer()->asChat()) {
@ -320,7 +229,6 @@ void GroupMembersWidget::refreshMembers() {
Auth().api().requestFullPeer(chat);
}
fillChatMembers(chat);
refreshLimitReached();
} else if (auto megagroup = peer()->asMegagroup()) {
auto &megagroupInfo = megagroup->mgInfo;
if (megagroupInfo->lastParticipants.empty() || megagroup->lastParticipantsCountOutdated()) {
@ -333,27 +241,6 @@ void GroupMembersWidget::refreshMembers() {
refreshVisibility();
}
void GroupMembersWidget::refreshLimitReached() {
auto chat = peer()->asChat();
if (!chat) return;
bool limitReachedShown = (itemsCount() >= Global::ChatSizeMax()) && chat->amCreator() && !emptyTitle();
if (limitReachedShown && !_limitReachedInfo) {
_limitReachedInfo.create(this, st::profileLimitReachedLabel);
QString title = TextUtilities::EscapeForRichParsing(lng_profile_migrate_reached(lt_count, Global::ChatSizeMax()));
QString body = TextUtilities::EscapeForRichParsing(lang(lng_profile_migrate_body));
QString link = TextUtilities::EscapeForRichParsing(lang(lng_profile_migrate_learn_more));
QString text = qsl("%1%2%3\n%4 [a href=\"https://telegram.org/blog/supergroups5k\"]%5[/a]").arg(textcmdStartSemibold()).arg(title).arg(textcmdStopSemibold()).arg(body).arg(link);
_limitReachedInfo->setRichText(text);
_limitReachedInfo->setClickHandlerFilter([=](auto&&...) {
Ui::show(Box<ConvertToSupergroupBox>(peer()->asChat()));
return false;
});
} else if (!limitReachedShown && _limitReachedInfo) {
_limitReachedInfo.destroy();
}
}
void GroupMembersWidget::checkSelfAdmin(ChatData *chat) {
if (chat->participants.empty()) return;

View file

@ -24,11 +24,7 @@ class GroupMembersWidget : public PeerListWidget {
Q_OBJECT
public:
enum class TitleVisibility {
Visible,
Hidden,
};
GroupMembersWidget(QWidget *parent, PeerData *peer, TitleVisibility titleVisibility = TitleVisibility::Visible, const style::PeerListItem &st = st::profileMemberItem);
GroupMembersWidget(QWidget *parent, PeerData *peer, const style::PeerListItem &st);
int onlineCount() const {
return _onlineCount;
@ -36,14 +32,6 @@ public:
~GroupMembersWidget();
protected:
// Resizes content and counts natural widget height for the desired width.
int resizeGetHeight(int newWidth) override;
void paintContents(Painter &p) override;
Ui::PopupMenu *fillPeerMenu(PeerData *peer) override;
signals:
void onlineCountUpdated(int onlineCount);
@ -63,16 +51,10 @@ private:
void sortMembers();
void updateOnlineCount();
void checkSelfAdmin(ChatData *chat);
void refreshLimitReached();
void preloadMore();
bool limitReachedHook(const ClickHandlerPtr &handler, Qt::MouseButton button);
void refreshUserOnline(UserData *user);
int getListTop() const override;
struct Member : public Item {
explicit Member(UserData *user);
UserData *user() const;
@ -93,8 +75,6 @@ private:
void setItemFlags(Item *item, ChannelData *megagroup);
bool addUsersToEnd(ChannelData *megagroup);
object_ptr<Ui::FlatLabel> _limitReachedInfo = { nullptr };
QMap<UserData*, Member*> _membersByUser;
bool _sortByOnline = false;
TimeId _now = 0;

View file

@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "profile/profile_block_peer_list.h"
#include "ui/effects/ripple_animation.h"
#include "ui/widgets/popup_menu.h"
#include "ui/text_options.h"
#include "data/data_peer.h"
#include "auth_session.h"
@ -60,7 +59,7 @@ void PeerListWidget::paintContents(Painter &p) {
auto to = ceilclamp(_visibleBottom - top, _st.height, 0, _items.size());
for (auto i = from; i < to; ++i) {
auto y = top + i * _st.height;
auto selected = (_menuRowIndex >= 0) ? (i == _menuRowIndex) : (_pressed >= 0) ? (i == _pressed) : (i == _selected);
auto selected = (_pressed >= 0) ? (i == _pressed) : (i == _selected);
auto selectedRemove = selected && _selectedRemove;
if (_pressed >= 0 && !_pressedRemove) {
selectedRemove = false;
@ -182,46 +181,6 @@ void PeerListWidget::mousePressReleased(Qt::MouseButton button) {
repaintSelectedRow();
}
void PeerListWidget::contextMenuEvent(QContextMenuEvent *e) {
if (_menu) {
_menu->deleteLater();
_menu = nullptr;
}
if (_menuRowIndex >= 0) {
repaintRow(_menuRowIndex);
_menuRowIndex = -1;
}
if (e->reason() == QContextMenuEvent::Mouse) {
_mousePosition = e->globalPos();
updateSelection();
}
_menuRowIndex = _selected;
if (_pressButton != Qt::LeftButton) {
mousePressReleased(_pressButton);
}
if (_selected < 0 || _selected >= _items.size()) {
return;
}
_menu = fillPeerMenu(_items[_selected]->peer);
if (_menu) {
_menu->setDestroyedCallback(crl::guard(this, [this, menu = _menu] {
if (_menu == menu) {
_menu = nullptr;
}
repaintRow(_menuRowIndex);
_menuRowIndex = -1;
_mousePosition = QCursor::pos();
updateSelection();
}));
_menu->popup(e->globalPos());
e->accept();
}
}
void PeerListWidget::enterEventHook(QEvent *e) {
_mousePosition = QCursor::pos();
updateSelection();

View file

@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "profile/profile_block_widget.h"
#include "styles/style_profile.h"
namespace Ui {
class RippleAnimation;
@ -19,11 +18,15 @@ namespace Notify {
struct PeerUpdate;
} // namespace Notify
namespace style {
struct PeerListItem;
} // namespace style
namespace Profile {
class PeerListWidget : public BlockWidget {
public:
PeerListWidget(QWidget *parent, PeerData *peer, const QString &title, const style::PeerListItem &st = st::profileMemberItem, const QString &removeText = QString());
PeerListWidget(QWidget *parent, PeerData *peer, const QString &title, const style::PeerListItem &st, const QString &removeText);
struct Item {
explicit Item(PeerData *peer);
@ -42,7 +45,7 @@ public:
bool hasRemoveLink = false;
std::unique_ptr<Ui::RippleAnimation> ripple;
};
virtual int getListTop() const {
int getListTop() const {
return contentTop();
}
@ -98,7 +101,6 @@ protected:
void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void enterEventHook(QEvent *e) override;
void enterFromChildEvent(QEvent *e, QWidget *child) override {
enterEventHook(e);
@ -108,10 +110,6 @@ protected:
leaveEventHook(e);
}
virtual Ui::PopupMenu *fillPeerMenu(PeerData *peer) {
return nullptr;
}
private:
void mousePressReleased(Qt::MouseButton button);
void updateSelection();
@ -145,9 +143,6 @@ private:
QString _removeText;
int _removeWidth = 0;
Ui::PopupMenu *_menu = nullptr;
int _menuRowIndex = -1;
};
} // namespace Profile

View file

@ -109,7 +109,7 @@ History *FindWastedPin() {
void AddChatMembers(not_null<ChatData*> chat) {
if (chat->count >= Global::ChatSizeMax() && chat->amCreator()) {
Ui::show(Box<ConvertToSupergroupBox>(chat));
// #TODO convert and add inside AddParticipantsBoxController?
} else {
AddParticipantsBoxController::Start(chat);
}
@ -122,7 +122,7 @@ bool PinnedLimitReached(Dialogs::Key key) {
return false;
}
// Some old chat, that was converted, maybe is still pinned.
if (auto wasted = FindWastedPin()) {
if (const auto wasted = FindWastedPin()) {
Auth().data().setPinnedDialog(wasted, false);
Auth().data().setPinnedDialog(key, true);
Auth().api().savePinnedOrder();