2016-05-31 19:27:11 +00:00
|
|
|
/*
|
|
|
|
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
|
2017-01-11 18:31:31 +00:00
|
|
|
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
2016-05-31 19:27:11 +00:00
|
|
|
*/
|
2016-10-23 21:03:10 +00:00
|
|
|
#include "profile/profile_block_actions.h"
|
2016-05-31 19:27:11 +00:00
|
|
|
|
|
|
|
#include "styles/style_profile.h"
|
2016-11-15 11:56:49 +00:00
|
|
|
#include "styles/style_boxes.h"
|
2016-11-16 16:04:25 +00:00
|
|
|
#include "ui/widgets/buttons.h"
|
2017-04-06 14:38:10 +00:00
|
|
|
#include "boxes/confirm_box.h"
|
2016-06-06 10:29:51 +00:00
|
|
|
#include "boxes/report_box.h"
|
2016-06-01 20:05:37 +00:00
|
|
|
#include "mainwidget.h"
|
|
|
|
#include "observer_peer.h"
|
|
|
|
#include "apiwrap.h"
|
2017-02-23 09:32:28 +00:00
|
|
|
#include "auth_session.h"
|
2017-04-13 08:27:10 +00:00
|
|
|
#include "lang/lang_keys.h"
|
2017-07-11 18:39:09 +00:00
|
|
|
#include "profile/profile_channel_controllers.h"
|
2017-10-03 13:05:58 +00:00
|
|
|
#include "mainwindow.h"
|
2016-05-31 19:27:11 +00:00
|
|
|
|
|
|
|
namespace Profile {
|
|
|
|
|
2017-07-11 18:39:09 +00:00
|
|
|
constexpr auto kEnableSearchMembersAfterCount = 50;
|
2017-07-13 16:12:20 +00:00
|
|
|
constexpr auto kMaxChannelMembersDeleteAllowed = 1000;
|
2017-07-11 18:39:09 +00:00
|
|
|
|
2016-06-01 20:05:37 +00:00
|
|
|
using UpdateFlag = Notify::PeerUpdate::Flag;
|
|
|
|
|
|
|
|
ActionsWidget::ActionsWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, peer, lang(lng_profile_actions_section)) {
|
2016-06-02 13:02:55 +00:00
|
|
|
auto observeEvents = UpdateFlag::ChannelAmIn
|
|
|
|
| UpdateFlag::UserIsBlocked
|
|
|
|
| UpdateFlag::BotCommandsChanged
|
|
|
|
| UpdateFlag::MembersChanged;
|
2016-09-26 18:33:34 +00:00
|
|
|
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
2016-09-26 13:57:08 +00:00
|
|
|
notifyPeerUpdated(update);
|
2016-09-26 18:33:34 +00:00
|
|
|
}));
|
2016-06-01 20:05:37 +00:00
|
|
|
|
|
|
|
validateBlockStatus();
|
|
|
|
refreshButtons();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
|
|
|
|
if (update.peer != peer()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto needFullRefresh = [&update, this]() {
|
|
|
|
if (update.flags & UpdateFlag::BotCommandsChanged) {
|
|
|
|
if (_hasBotHelp != hasBotCommand(qsl("help")) || _hasBotSettings != hasBotCommand(qsl("settings"))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2017-07-23 09:17:23 +00:00
|
|
|
if (update.flags & UpdateFlag::MembersChanged) {
|
|
|
|
if (peer()->isMegagroup()) {
|
|
|
|
// Search members button could change.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2016-06-01 20:05:37 +00:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
if (needFullRefresh()) {
|
|
|
|
refreshButtons();
|
|
|
|
} else {
|
2016-06-02 13:02:55 +00:00
|
|
|
if (update.flags & UpdateFlag::MembersChanged) {
|
|
|
|
refreshDeleteChannel();
|
|
|
|
}
|
2016-06-01 20:05:37 +00:00
|
|
|
if (update.flags & UpdateFlag::ChannelAmIn) {
|
|
|
|
refreshLeaveChannel();
|
|
|
|
}
|
|
|
|
if (update.flags & UpdateFlag::UserIsBlocked) {
|
|
|
|
refreshBlockUser();
|
|
|
|
}
|
|
|
|
refreshVisibility();
|
|
|
|
}
|
|
|
|
|
|
|
|
contentSizeUpdated();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::validateBlockStatus() const {
|
|
|
|
auto needFullPeer = [this]() {
|
|
|
|
if (auto user = peer()->asUser()) {
|
|
|
|
if (user->blockStatus() == UserData::BlockStatus::Unknown) {
|
|
|
|
return true;
|
|
|
|
} else if (user->botInfo && !user->botInfo->inited) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
if (needFullPeer()) {
|
2017-08-04 14:54:32 +00:00
|
|
|
Auth().api().requestFullPeer(peer());
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ui::LeftOutlineButton *ActionsWidget::addButton(const QString &text, const char *slot, const style::OutlineButton &st, int skipHeight) {
|
|
|
|
auto result = new Ui::LeftOutlineButton(this, text, st);
|
|
|
|
connect(result, SIGNAL(clicked()), this, slot);
|
|
|
|
result->show();
|
|
|
|
|
|
|
|
int top = buttonsBottom() + skipHeight;
|
2016-09-02 01:37:30 +00:00
|
|
|
resizeButton(result, width(), top);
|
2016-06-01 20:05:37 +00:00
|
|
|
|
|
|
|
_buttons.push_back(result);
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
2016-09-02 01:37:30 +00:00
|
|
|
void ActionsWidget::resizeButton(Ui::LeftOutlineButton *button, int newWidth, int top) {
|
2016-06-02 13:02:55 +00:00
|
|
|
int left = defaultOutlineButtonLeft();
|
2016-09-02 01:37:30 +00:00
|
|
|
int availableWidth = newWidth - left - st::profileBlockMarginRight;
|
2016-06-01 20:05:37 +00:00
|
|
|
accumulate_min(availableWidth, st::profileBlockOneLineWidthMax);
|
|
|
|
button->resizeToWidth(availableWidth);
|
2016-06-02 13:02:55 +00:00
|
|
|
button->moveToLeft(left, top);
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::refreshButtons() {
|
2016-10-07 16:45:45 +00:00
|
|
|
auto buttons = base::take(_buttons);
|
2016-06-01 20:05:37 +00:00
|
|
|
for_const (auto &button, buttons) {
|
|
|
|
delete button;
|
|
|
|
}
|
|
|
|
_blockUser = _leaveChannel = nullptr;
|
|
|
|
|
|
|
|
if (auto user = peer()->asUser()) {
|
|
|
|
if ((_hasBotHelp = hasBotCommand(qsl("help")))) {
|
|
|
|
addButton(lang(lng_profile_bot_help), SLOT(onBotHelp()));
|
|
|
|
}
|
|
|
|
if ((_hasBotSettings = hasBotCommand(qsl("settings")))) {
|
|
|
|
addButton(lang(lng_profile_bot_settings), SLOT(onBotSettings()));
|
|
|
|
}
|
|
|
|
addButton(lang(lng_profile_clear_history), SLOT(onClearHistory()));
|
|
|
|
addButton(lang(lng_profile_delete_conversation), SLOT(onDeleteConversation()));
|
2016-12-09 06:19:55 +00:00
|
|
|
if (user->botInfo) {
|
|
|
|
addButton(lang(lng_profile_report), SLOT(onReport()), st::defaultLeftOutlineButton, st::profileBlockOneLineSkip);
|
|
|
|
}
|
2016-06-01 20:05:37 +00:00
|
|
|
refreshBlockUser();
|
|
|
|
} else if (auto chat = peer()->asChat()) {
|
|
|
|
if (chat->amCreator()) {
|
|
|
|
addButton(lang(lng_profile_migrate_button), SLOT(onUpgradeToSupergroup()));
|
|
|
|
}
|
|
|
|
addButton(lang(lng_profile_clear_history), SLOT(onClearHistory()));
|
|
|
|
addButton(lang(lng_profile_clear_and_exit), SLOT(onDeleteConversation()));
|
|
|
|
} else if (auto channel = peer()->asChannel()) {
|
2017-07-11 18:39:09 +00:00
|
|
|
if (channel->isMegagroup() && channel->membersCount() > kEnableSearchMembersAfterCount) {
|
|
|
|
addButton(lang(lng_profile_search_members), SLOT(onSearchMembers()));
|
|
|
|
}
|
2016-12-09 06:19:55 +00:00
|
|
|
if (!channel->amCreator() && (!channel->isMegagroup() || channel->isPublic())) {
|
2016-06-06 10:29:51 +00:00
|
|
|
addButton(lang(lng_profile_report), SLOT(onReport()));
|
|
|
|
}
|
2016-06-02 13:02:55 +00:00
|
|
|
refreshDeleteChannel();
|
2016-06-01 20:05:37 +00:00
|
|
|
refreshLeaveChannel();
|
|
|
|
}
|
|
|
|
|
|
|
|
refreshVisibility();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::refreshVisibility() {
|
|
|
|
setVisible(!_buttons.isEmpty());
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ActionsWidget::getBlockButtonText() const {
|
|
|
|
auto user = peer()->asUser();
|
2017-08-04 14:54:32 +00:00
|
|
|
if (!user || (user->id == Auth().userPeerId())) return QString();
|
2016-06-01 20:05:37 +00:00
|
|
|
if (user->blockStatus() == UserData::BlockStatus::Unknown) return QString();
|
|
|
|
|
|
|
|
if (user->isBlocked()) {
|
|
|
|
if (user->botInfo) {
|
|
|
|
return lang(lng_profile_unblock_bot);
|
|
|
|
}
|
|
|
|
return lang(lng_profile_unblock_user);
|
|
|
|
} else if (user->botInfo) {
|
|
|
|
return lang(lng_profile_block_bot);
|
|
|
|
}
|
|
|
|
return lang(lng_profile_block_user);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ActionsWidget::hasBotCommand(const QString &command) const {
|
|
|
|
auto user = peer()->asUser();
|
|
|
|
if (!user || !user->botInfo || user->botInfo->commands.isEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for_const (auto &cmd, user->botInfo->commands) {
|
|
|
|
if (!cmd.command.compare(command, Qt::CaseInsensitive)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::sendBotCommand(const QString &command) {
|
|
|
|
auto user = peer()->asUser();
|
|
|
|
if (user && user->botInfo && !user->botInfo->commands.isEmpty()) {
|
|
|
|
for_const (auto &cmd, user->botInfo->commands) {
|
|
|
|
if (!cmd.command.compare(command, Qt::CaseInsensitive)) {
|
|
|
|
Ui::showPeerHistory(user, ShowAtTheEndMsgId);
|
|
|
|
App::sendBotCommand(user, user, '/' + cmd.command);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Command was not found.
|
|
|
|
refreshButtons();
|
|
|
|
contentSizeUpdated();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::refreshBlockUser() {
|
|
|
|
if (auto user = peer()->asUser()) {
|
|
|
|
auto blockText = getBlockButtonText();
|
|
|
|
if (_blockUser) {
|
|
|
|
if (blockText.isEmpty()) {
|
|
|
|
_buttons.removeOne(_blockUser);
|
|
|
|
delete _blockUser;
|
|
|
|
_blockUser = nullptr;
|
|
|
|
} else {
|
|
|
|
_blockUser->setText(blockText);
|
|
|
|
}
|
|
|
|
} else if (!blockText.isEmpty()) {
|
|
|
|
_blockUser = addButton(blockText, SLOT(onBlockUser()), st::attentionLeftOutlineButton, st::profileBlockOneLineSkip);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-02 13:02:55 +00:00
|
|
|
void ActionsWidget::refreshDeleteChannel() {
|
|
|
|
if (auto channel = peer()->asChannel()) {
|
|
|
|
if (channel->canDelete() && !_deleteChannel) {
|
|
|
|
_deleteChannel = addButton(lang(channel->isMegagroup() ? lng_profile_delete_group : lng_profile_delete_channel), SLOT(onDeleteChannel()), st::attentionLeftOutlineButton);
|
|
|
|
} else if (!channel->canDelete() && _deleteChannel) {
|
|
|
|
_buttons.removeOne(_deleteChannel);
|
|
|
|
delete _deleteChannel;
|
|
|
|
_deleteChannel = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-01 20:05:37 +00:00
|
|
|
void ActionsWidget::refreshLeaveChannel() {
|
|
|
|
if (auto channel = peer()->asChannel()) {
|
|
|
|
if (!channel->amCreator()) {
|
|
|
|
if (channel->amIn() && !_leaveChannel) {
|
|
|
|
_leaveChannel = addButton(lang(channel->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel), SLOT(onLeaveChannel()));
|
|
|
|
} else if (!channel->amIn() && _leaveChannel) {
|
|
|
|
_buttons.removeOne(_leaveChannel);
|
|
|
|
delete _leaveChannel;
|
|
|
|
_leaveChannel = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-31 19:27:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ActionsWidget::resizeGetHeight(int newWidth) {
|
2016-06-01 20:05:37 +00:00
|
|
|
for_const (auto button, _buttons) {
|
2016-09-02 01:37:30 +00:00
|
|
|
resizeButton(button, newWidth, button->y());
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
return buttonsBottom();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ActionsWidget::buttonsBottom() const {
|
|
|
|
if (_buttons.isEmpty()) {
|
|
|
|
return contentTop();
|
|
|
|
}
|
|
|
|
auto lastButton = _buttons.back();
|
|
|
|
return lastButton->y() + lastButton->height();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onBotHelp() {
|
|
|
|
sendBotCommand(qsl("help"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onBotSettings() {
|
|
|
|
sendBotCommand(qsl("settings"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onClearHistory() {
|
|
|
|
QString confirmation;
|
|
|
|
if (auto user = peer()->asUser()) {
|
|
|
|
confirmation = lng_sure_delete_history(lt_contact, App::peerName(peer()));
|
|
|
|
} else if (auto chat = peer()->asChat()) {
|
|
|
|
confirmation = lng_sure_delete_group_history(lt_group, App::peerName(peer()));
|
|
|
|
}
|
|
|
|
if (!confirmation.isEmpty()) {
|
2016-12-13 17:07:56 +00:00
|
|
|
Ui::show(Box<ConfirmBox>(confirmation, lang(lng_box_delete), st::attentionBoxButton, base::lambda_guarded(this, [this] {
|
|
|
|
Ui::hideLayer();
|
|
|
|
App::main()->clearHistory(peer());
|
|
|
|
Ui::showPeerHistory(peer(), ShowAtUnreadMsgId);
|
|
|
|
})));
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onDeleteConversation() {
|
|
|
|
QString confirmation, confirmButton;
|
|
|
|
if (auto user = peer()->asUser()) {
|
|
|
|
confirmation = lng_sure_delete_history(lt_contact, App::peerName(peer()));
|
|
|
|
confirmButton = lang(lng_box_delete);
|
|
|
|
} else if (auto chat = peer()->asChat()) {
|
|
|
|
confirmation = lng_sure_delete_and_exit(lt_group, App::peerName(peer()));
|
|
|
|
confirmButton = lang(lng_box_leave);
|
|
|
|
}
|
|
|
|
if (!confirmation.isEmpty()) {
|
2016-12-13 17:07:56 +00:00
|
|
|
Ui::show(Box<ConfirmBox>(confirmation, confirmButton, st::attentionBoxButton, base::lambda_guarded(this, [this] {
|
|
|
|
Ui::hideLayer();
|
|
|
|
Ui::showChatsList();
|
|
|
|
if (auto user = peer()->asUser()) {
|
|
|
|
App::main()->deleteConversation(peer());
|
|
|
|
} else if (auto chat = peer()->asChat()) {
|
|
|
|
App::main()->deleteAndExit(chat);
|
|
|
|
}
|
|
|
|
})));
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onBlockUser() {
|
|
|
|
if (auto user = peer()->asUser()) {
|
|
|
|
if (user->isBlocked()) {
|
2017-08-04 14:54:32 +00:00
|
|
|
Auth().api().unblockUser(user);
|
2016-06-01 20:05:37 +00:00
|
|
|
} else {
|
2017-08-04 14:54:32 +00:00
|
|
|
Auth().api().blockUser(user);
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onUpgradeToSupergroup() {
|
|
|
|
if (auto chat = peer()->asChat()) {
|
2016-12-13 17:07:56 +00:00
|
|
|
Ui::show(Box<ConvertToSupergroupBox>(chat));
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onDeleteChannel() {
|
2016-12-13 17:07:56 +00:00
|
|
|
auto text = lang(peer()->isMegagroup() ? lng_sure_delete_group : lng_sure_delete_channel);
|
|
|
|
Ui::show(Box<ConfirmBox>(text, lang(lng_box_delete), st::attentionBoxButton, base::lambda_guarded(this, [this] {
|
|
|
|
Ui::hideLayer();
|
|
|
|
Ui::showChatsList();
|
|
|
|
if (auto chat = peer()->migrateFrom()) {
|
|
|
|
App::main()->deleteAndExit(chat);
|
|
|
|
}
|
|
|
|
if (auto channel = peer()->asChannel()) {
|
|
|
|
MTP::send(MTPchannels_DeleteChannel(channel->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::deleteChannelFailed));
|
|
|
|
}
|
|
|
|
})));
|
2016-06-01 20:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ActionsWidget::onLeaveChannel() {
|
|
|
|
auto channel = peer()->asChannel();
|
|
|
|
if (!channel) return;
|
|
|
|
|
2016-12-13 17:07:56 +00:00
|
|
|
auto text = lang(channel->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel);
|
|
|
|
Ui::show(Box<ConfirmBox>(text, lang(lng_box_leave), base::lambda_guarded(this, [this] {
|
2017-08-04 14:54:32 +00:00
|
|
|
Auth().api().leaveChannel(peer()->asChannel());
|
2016-12-13 17:07:56 +00:00
|
|
|
})));
|
2016-05-31 19:27:11 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 18:39:09 +00:00
|
|
|
void ActionsWidget::onSearchMembers() {
|
|
|
|
if (auto channel = peer()->asChannel()) {
|
2017-10-03 13:05:58 +00:00
|
|
|
ParticipantsBoxController::Start(
|
|
|
|
App::wnd()->controller(),
|
|
|
|
channel,
|
|
|
|
ParticipantsBoxController::Role::Members);
|
2017-07-11 18:39:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-06 10:29:51 +00:00
|
|
|
void ActionsWidget::onReport() {
|
2016-12-13 17:07:56 +00:00
|
|
|
Ui::show(Box<ReportBox>(peer()));
|
2016-06-06 10:29:51 +00:00
|
|
|
}
|
|
|
|
|
2016-05-31 19:27:11 +00:00
|
|
|
} // namespace Profile
|