mirror of
https://github.com/vale981/tdesktop
synced 2025-03-08 19:21:39 -05:00
328 lines
8.8 KiB
C++
328 lines
8.8 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-2017 John Preston, https://desktop.telegram.org
|
|
*/
|
|
#include "window/window_peer_menu.h"
|
|
|
|
#include "lang/lang_keys.h"
|
|
#include "boxes/confirm_box.h"
|
|
#include "boxes/mute_settings_box.h"
|
|
#include "auth_session.h"
|
|
#include "apiwrap.h"
|
|
#include "mainwidget.h"
|
|
#include "observer_peer.h"
|
|
#include "styles/style_boxes.h"
|
|
|
|
namespace Window {
|
|
namespace{
|
|
|
|
class Filler {
|
|
public:
|
|
Filler(
|
|
not_null<PeerData*> peer,
|
|
const PeerMenuCallback &callback,
|
|
const PeerMenuOptions &options);
|
|
void fill();
|
|
|
|
private:
|
|
void addPinToggle();
|
|
void addInfo();
|
|
void addNotifications();
|
|
void addSearch();
|
|
void addUserActions(not_null<UserData*> user);
|
|
void addBlockUser(not_null<UserData*> user);
|
|
void addChatActions(not_null<ChatData*> chat);
|
|
void addChannelActions(not_null<ChannelData*> channel);
|
|
|
|
not_null<PeerData*> _peer;
|
|
const PeerMenuCallback &_callback;
|
|
const PeerMenuOptions &_options;
|
|
|
|
};
|
|
|
|
History *FindWastedPin() {
|
|
auto order = App::histories().getPinnedOrder();
|
|
for_const (auto pinned, order) {
|
|
if (pinned->peer->isChat()
|
|
&& pinned->peer->asChat()->isDeactivated()
|
|
&& !pinned->inChatList(Dialogs::Mode::All)) {
|
|
return pinned;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
auto ClearHistoryHandler(not_null<PeerData*> peer) {
|
|
return [peer] {
|
|
auto text = peer->isUser() ? lng_sure_delete_history(lt_contact, peer->name) : lng_sure_delete_group_history(lt_group, peer->name);
|
|
Ui::show(Box<ConfirmBox>(text, lang(lng_box_delete), st::attentionBoxButton, [peer] {
|
|
if (!App::main()) return;
|
|
|
|
Ui::hideLayer();
|
|
App::main()->clearHistory(peer);
|
|
}));
|
|
};
|
|
}
|
|
|
|
auto DeleteAndLeaveHandler(not_null<PeerData*> peer) {
|
|
return [peer] {
|
|
auto warningText = peer->isUser() ? lng_sure_delete_history(lt_contact, peer->name) :
|
|
peer->isChat() ? lng_sure_delete_and_exit(lt_group, peer->name) :
|
|
lang(peer->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel);
|
|
auto confirmText = lang(peer->isUser() ? lng_box_delete : lng_box_leave);
|
|
auto &confirmStyle = peer->isChannel() ? st::defaultBoxButton : st::attentionBoxButton;
|
|
Ui::show(Box<ConfirmBox>(warningText, confirmText, confirmStyle, [peer] {
|
|
if (!App::main()) return;
|
|
|
|
Ui::hideLayer();
|
|
Ui::showChatsList();
|
|
if (peer->isUser()) {
|
|
App::main()->deleteConversation(peer);
|
|
} else if (auto chat = peer->asChat()) {
|
|
App::main()->deleteAndExit(chat);
|
|
} else if (auto channel = peer->asChannel()) {
|
|
if (auto migrateFrom = channel->migrateFrom()) {
|
|
App::main()->deleteConversation(migrateFrom);
|
|
}
|
|
Auth().api().leaveChannel(channel);
|
|
}
|
|
}));
|
|
};
|
|
}
|
|
|
|
Filler::Filler(
|
|
not_null<PeerData*> peer,
|
|
const PeerMenuCallback &callback,
|
|
const PeerMenuOptions &options)
|
|
: _peer(peer)
|
|
, _callback(callback)
|
|
, _options(options) {
|
|
}
|
|
|
|
void Filler::addPinToggle() {
|
|
auto peer = _peer;
|
|
auto isPinned = false;
|
|
if (auto history = App::historyLoaded(peer)) {
|
|
isPinned = history->isPinnedDialog();
|
|
}
|
|
auto pinText = [](bool isPinned) {
|
|
return lang(isPinned
|
|
? lng_context_unpin_from_top
|
|
: lng_context_pin_to_top);
|
|
};
|
|
auto pinToggle = [peer] {
|
|
auto history = App::history(peer);
|
|
auto isPinned = !history->isPinnedDialog();
|
|
auto pinnedCount = App::histories().pinnedCount();
|
|
auto pinnedMax = Global::PinnedDialogsCountMax();
|
|
if (isPinned && pinnedCount >= pinnedMax) {
|
|
// Some old chat, that was converted to supergroup, maybe is still pinned.
|
|
if (auto wasted = FindWastedPin()) {
|
|
wasted->setPinnedDialog(false);
|
|
history->setPinnedDialog(isPinned);
|
|
App::histories().savePinnedToServer();
|
|
} else {
|
|
auto errorText = lng_error_pinned_max(
|
|
lt_count,
|
|
pinnedMax);
|
|
Ui::show(Box<InformBox>(errorText));
|
|
}
|
|
return;
|
|
}
|
|
|
|
history->setPinnedDialog(isPinned);
|
|
auto flags = MTPmessages_ToggleDialogPin::Flags(0);
|
|
if (isPinned) {
|
|
flags |= MTPmessages_ToggleDialogPin::Flag::f_pinned;
|
|
}
|
|
MTP::send(MTPmessages_ToggleDialogPin(MTP_flags(flags), peer->input));
|
|
if (isPinned) {
|
|
if (auto main = App::main()) {
|
|
main->dialogsToUp();
|
|
}
|
|
}
|
|
};
|
|
auto pinAction = _callback(pinText(isPinned), pinToggle);
|
|
|
|
auto lifetime = Notify::PeerUpdateViewer(
|
|
peer,
|
|
Notify::PeerUpdate::Flag::PinnedChanged)
|
|
| rpl::start_with_next([peer, pinAction, pinText] {
|
|
auto isPinned = App::history(peer)->isPinnedDialog();
|
|
pinAction->setText(pinText(isPinned));
|
|
});
|
|
|
|
Ui::AttachAsChild(pinAction, std::move(lifetime));
|
|
}
|
|
|
|
void Filler::addInfo() {
|
|
auto infoKey = (_peer->isChat() || _peer->isMegagroup())
|
|
? lng_context_view_group
|
|
: (_peer->isUser()
|
|
? lng_context_view_profile
|
|
: lng_context_view_channel);
|
|
_callback(lang(infoKey), [peer = _peer] {
|
|
Ui::showPeerProfile(peer);
|
|
});
|
|
}
|
|
|
|
void Filler::addNotifications() {
|
|
auto peer = _peer;
|
|
auto muteText = [](bool isMuted) {
|
|
return lang(isMuted
|
|
? lng_enable_notifications_from_tray
|
|
: lng_disable_notifications_from_tray);
|
|
};
|
|
auto muteAction = _callback(muteText(peer->isMuted()), [peer] {
|
|
if (!peer->isMuted()) {
|
|
Ui::show(Box<MuteSettingsBox>(peer));
|
|
} else {
|
|
App::main()->updateNotifySetting(
|
|
peer,
|
|
NotifySettingSetNotify);
|
|
}
|
|
});
|
|
|
|
auto lifetime = Notify::PeerUpdateViewer(
|
|
_peer,
|
|
Notify::PeerUpdate::Flag::NotificationsEnabled)
|
|
| rpl::start_with_next([=] {
|
|
muteAction->setText(muteText(peer->isMuted()));
|
|
});
|
|
|
|
Ui::AttachAsChild(muteAction, std::move(lifetime));
|
|
}
|
|
|
|
void Filler::addSearch() {
|
|
_callback(lang(lng_profile_search_messages), [peer = _peer] {
|
|
App::main()->searchInPeer(peer);
|
|
});
|
|
}
|
|
|
|
void Filler::addBlockUser(not_null<UserData*> user) {
|
|
auto blockText = [](not_null<UserData*> user) {
|
|
return lang(user->isBlocked()
|
|
? (user->botInfo
|
|
? lng_profile_unblock_bot
|
|
: lng_profile_unblock_user)
|
|
: (user->botInfo
|
|
? lng_profile_block_bot
|
|
: lng_profile_block_user));
|
|
};
|
|
auto blockAction = _callback(blockText(user), [user] {
|
|
auto willBeBlocked = !user->isBlocked();
|
|
auto handler = ::rpcDone([user, willBeBlocked](const MTPBool &result) {
|
|
user->setBlockStatus(willBeBlocked
|
|
? UserData::BlockStatus::Blocked
|
|
: UserData::BlockStatus::NotBlocked);
|
|
});
|
|
if (willBeBlocked) {
|
|
MTP::send(
|
|
MTPcontacts_Block(user->inputUser),
|
|
std::move(handler));
|
|
} else {
|
|
MTP::send(
|
|
MTPcontacts_Unblock(user->inputUser),
|
|
std::move(handler));
|
|
}
|
|
});
|
|
|
|
auto lifetime = Notify::PeerUpdateViewer(
|
|
_peer,
|
|
Notify::PeerUpdate::Flag::UserIsBlocked)
|
|
| rpl::start_with_next([=] {
|
|
blockAction->setText(blockText(user));
|
|
});
|
|
|
|
Ui::AttachAsChild(blockAction, std::move(lifetime));
|
|
|
|
if (user->blockStatus() == UserData::BlockStatus::Unknown) {
|
|
Auth().api().requestFullPeer(user);
|
|
}
|
|
}
|
|
|
|
void Filler::addUserActions(not_null<UserData*> user) {
|
|
if (user->isContact()) {
|
|
// edit contact
|
|
// share contact
|
|
} else if (user->canShareThisContact()) {
|
|
// add contact
|
|
// share contact
|
|
}
|
|
_callback(
|
|
lang(lng_profile_delete_conversation),
|
|
DeleteAndLeaveHandler(user));
|
|
_callback(
|
|
lang(lng_profile_clear_history),
|
|
ClearHistoryHandler(user));
|
|
if (!user->isInaccessible() && user != App::self()) {
|
|
addBlockUser(user);
|
|
}
|
|
}
|
|
|
|
void Filler::addChatActions(not_null<ChatData*> chat) {
|
|
_callback(
|
|
lang(lng_profile_clear_and_exit),
|
|
DeleteAndLeaveHandler(_peer));
|
|
_callback(
|
|
lang(lng_profile_clear_history),
|
|
ClearHistoryHandler(_peer));
|
|
}
|
|
|
|
void Filler::addChannelActions(not_null<ChannelData*> channel) {
|
|
if (channel->amIn() && !channel->amCreator()) {
|
|
auto leaveText = lang(channel->isMegagroup()
|
|
? lng_profile_leave_group
|
|
: lng_profile_leave_channel);
|
|
_callback(leaveText, DeleteAndLeaveHandler(channel));
|
|
}
|
|
}
|
|
|
|
void Filler::fill() {
|
|
if (_options.pinToggle) {
|
|
addPinToggle();
|
|
}
|
|
if (_options.showInfo) {
|
|
addInfo();
|
|
}
|
|
addNotifications();
|
|
if (_options.search) {
|
|
addSearch();
|
|
}
|
|
|
|
if (auto user = _peer->asUser()) {
|
|
addUserActions(user);
|
|
} else if (auto chat = _peer->asChat()) {
|
|
addChatActions(chat);
|
|
} else if (auto channel = _peer->asChannel()) {
|
|
addChannelActions(channel);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void FillPeerMenu(
|
|
not_null<PeerData*> peer,
|
|
const PeerMenuCallback &callback,
|
|
const PeerMenuOptions &options) {
|
|
Filler filler(peer, callback, options);
|
|
filler.fill();
|
|
}
|
|
|
|
} // namespace Window
|