mirror of https://github.com/procxx/kepka.git
channel edit, report spam, etc done
This commit is contained in:
parent
f9d3921136
commit
72d0271e4d
|
@ -358,15 +358,20 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_profile_actions_section" = "Actions";
|
||||
"lng_profile_bot_settings" = "Settings";
|
||||
"lng_profile_bot_help" = "Help";
|
||||
"lng_profile_create_public_link" = "Create public link";
|
||||
"lng_profile_edit_public_link" = "Edit link";
|
||||
"lng_profile_participants_section" = "Members";
|
||||
"lng_profile_info" = "Contact info";
|
||||
"lng_profile_group_info" = "Group info";
|
||||
"lng_profile_channel_info" = "Channel info";
|
||||
"lng_profile_add_contact" = "Add Contact";
|
||||
"lng_profile_edit_contact" = "Edit";
|
||||
"lng_profile_enable_notifications" = "Notifications";
|
||||
"lng_profile_clear_history" = "Clear history";
|
||||
"lng_profile_delete_conversation" = "Delete conversation";
|
||||
"lng_profile_clear_and_exit" = "Delete and exit";
|
||||
"lng_profile_leave_channel" = "Leave channel";
|
||||
"lng_profile_delete_channel" = "Delete channel";
|
||||
"lng_profile_search_messages" = "Search for messages";
|
||||
"lng_profile_block_user" = "Block user";
|
||||
"lng_profile_unblock_user" = "Unblock user";
|
||||
|
@ -399,8 +404,6 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_participant_filter" = "Search";
|
||||
"lng_participant_invite" = "Invite";
|
||||
"lng_create_new_group" = "New Group";
|
||||
"lng_create_new_channel" = "New Channel";
|
||||
"lng_create_group_back" = "Back";
|
||||
"lng_create_group_next" = "Next";
|
||||
"lng_create_group_create" = "Create";
|
||||
|
@ -429,17 +432,21 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_failed_add_participant" = "Could not add user. Try again later.";
|
||||
"lng_failed_add_not_mutual" = "Sorry, if a person left a group, only a\nmutual contact can bring them back\n(they need to have your phone\nnumber, and you need theirs).";
|
||||
"lng_failed_add_not_mutual_channel" = "Sorry, if a person left a channel, only a\nmutual contact can bring them back\n(they need to have your phone\nnumber, and you need theirs).";
|
||||
|
||||
"lng_sure_delete_contact" = "Are you sure, you want to delete {contact} from your contact list?";
|
||||
"lng_sure_delete_history" = "Are you sure, you want to delete all message history with {contact}?\n\nThis action cannot be undone.";
|
||||
"lng_sure_delete_group_history" = "Are you sure, you want to delete all message history in «{group}»?\n\nThis action cannot be undone.";
|
||||
|
||||
"lng_sure_delete_and_exit" = "Are you sure, you want to delete all message history and leave «{group}»?\n\nThis action cannot be undone.";
|
||||
"lng_sure_leave_channel" = "Are you sure, you want\nto leave this channel?";
|
||||
"lng_sure_delete_channel" = "Are you sure, you want\nto delete this channel?\n\nAll members will be removed\nand all messages will be lost.";
|
||||
|
||||
"lng_message_empty" = "Empty Message";
|
||||
"lng_media_unsupported" = "Media Unsupported";
|
||||
|
||||
"lng_action_add_user" = "{from} added {user}";
|
||||
"lng_action_add_you" = "{from} added you to this channel";
|
||||
"lng_action_you_joined" = "You joined this channel";
|
||||
"lng_action_kick_user" = "{from} kicked {user}";
|
||||
"lng_action_user_left" = "{from} left the group";
|
||||
"lng_action_user_left_channel" = "{from} left the channel";
|
||||
|
@ -459,9 +466,14 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_channel_comments_count" = "{count:_not_used_|# comment|# comments}";
|
||||
"lng_channel_hide_comments" = "Hide comments";
|
||||
"lng_channel_not_accessible" = "Sorry, this channel is not accessible.";
|
||||
|
||||
"lng_channels_too_much_public_existing" = "Sorry, you have created\ntoo many public channels.\n\nFirst you need to delete one of them.";
|
||||
"lng_channels_too_much_public" = "Sorry, you have created\ntoo many public channels.\n\nYou can either create a private channel\nor delete one of your public channels first.";
|
||||
|
||||
"lng_group_invite_bad_link" = "This invite link is broken\nor has expired.";
|
||||
"lng_group_invite_want_join" = "Do you want to join the group «{title}»?";
|
||||
"lng_group_invite_want_join" = "Do you want to join group «{title}»?";
|
||||
"lng_group_invite_want_join_channel" = "Do you want to join channel «{title}»?";
|
||||
"lng_group_invite_join" = "Join";
|
||||
|
||||
"lng_group_invite_link" = "Invite link";
|
||||
|
@ -473,6 +485,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_group_invite_copied" = "Invite link copied to clipboard.";
|
||||
"lng_group_invite_no_room" = "Unable to join this group because there are\ntoo many members in it already.";
|
||||
|
||||
"lng_channel_public_link_copied" = "Public channel link copied to clipboard.";
|
||||
|
||||
"lng_forwarded_from" = "Forwarded from";
|
||||
"lng_in_reply_to" = "In reply to";
|
||||
|
||||
|
@ -526,9 +540,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_report_spam_thanks" = "Thank you for your report!";
|
||||
"lng_report_spam_sure" = "Are you sure you want\nto report spam from this user?";
|
||||
"lng_report_spam_sure_group" = "Are you sure you want\nto report spam in this group?";
|
||||
"lng_report_spam_sure_channel" = "Are you sure you want\nto report spam in this channel?";
|
||||
"lng_report_spam_ok" = "Report";
|
||||
"lng_cant_send_to_not_contact" = "Sorry, you can only send messages to\nmutual contacts at the moment. {more_info}";
|
||||
"lng_cant_invite_not_contact" = "Sorry, you can only add mutual contacts\nto groups at the moment. {more_info}";
|
||||
"lng_cant_invite_not_contact_channel" = "Sorry, you can only add mutual contacts\nto channels at the moment. {more_info}";
|
||||
"lng_cant_more_info" = "More info »";
|
||||
|
||||
"lng_send_button" = "Send";
|
||||
|
@ -542,6 +558,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_from_you" = "You";
|
||||
"lng_bot_description" = "What can this bot do?";
|
||||
"lng_unblock_button" = "Unblock";
|
||||
"lng_channel_join" = "Join Channel";
|
||||
"lng_channel_mute" = "Mute";
|
||||
"lng_channel_unmute" = "Unmute";
|
||||
|
||||
"lng_open_this_link" = "Open this link?";
|
||||
"lng_open_link" = "Open";
|
||||
|
@ -644,6 +663,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_enter_contact_data" = "New Contact";
|
||||
"lng_edit_group_title" = "Edit group name";
|
||||
"lng_edit_contact_title" = "Edit contact name";
|
||||
"lng_edit_channel_title" = "Edit channel";
|
||||
"lng_edit_self_title" = "Edit your name";
|
||||
"lng_confirm_contact_data" = "New Contact";
|
||||
"lng_add_contact" = "Create";
|
||||
|
@ -692,6 +712,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_mediaview_files_all" = "View all files";
|
||||
"lng_mediaview_single_photo" = "Single Photo";
|
||||
"lng_mediaview_group_photo" = "Group Photo";
|
||||
"lng_mediaview_channel_photo" = "Channel Photo";
|
||||
"lng_mediaview_profile_photo" = "Profile Photo";
|
||||
"lng_mediaview_file_n_of_count" = "{file} {n} of {count}";
|
||||
"lng_mediaview_n_of_count" = "Photo {n} of {count}";
|
||||
|
@ -756,6 +777,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_mac_menu_contacts" = "Contacts";
|
||||
"lng_mac_menu_add_contact" = "Add Contact";
|
||||
"lng_mac_menu_new_group" = "New Group";
|
||||
"lng_mac_menu_new_channel" = "New Channel";
|
||||
"lng_mac_menu_show" = "Show Telegram";
|
||||
|
||||
// Keys finished
|
||||
|
|
|
@ -2036,7 +2036,7 @@ mediaviewLoader: size(78px, 33px);
|
|||
mediaviewLoaderPoint: size(9px, 9px);
|
||||
mediaviewLoaderSkip: 9px;
|
||||
|
||||
minPhotoSize: 90px;
|
||||
minPhotoSize: 100px;
|
||||
maxMediaSize: 420px;
|
||||
maxStickerSize: 256px;
|
||||
|
||||
|
|
|
@ -274,7 +274,17 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result) {
|
|||
} else {
|
||||
channel->photoId = 0;
|
||||
}
|
||||
channel->about = qs(f.vabout);
|
||||
channel->count = f.has_participants_count() ? f.vparticipants_count.v : 0;
|
||||
channel->invitationUrl = (f.vexported_invite.type() == mtpc_chatInviteExported) ? qs(f.vexported_invite.c_chatInviteExported().vlink) : QString();
|
||||
if (History *h = App::historyLoaded(channel->id)) {
|
||||
if (h->inboxReadBefore < f.vread_inbox_max_id.v + 1) {
|
||||
h->unreadCount = f.vunread_important_count.v;
|
||||
h->inboxReadBefore = f.vread_inbox_max_id.v + 1;
|
||||
h->asChannelHistory()->unreadCountAll = f.vunread_count.v;
|
||||
}
|
||||
}
|
||||
channel->fullUpdated();
|
||||
|
||||
App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), f.vnotify_settings);
|
||||
}
|
||||
|
@ -400,6 +410,60 @@ bool ApiWrap::gotPeerFailed(PeerData *peer, const RPCError &error) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ApiWrap::requestSelfParticipant(ChannelData *channel) {
|
||||
if (_selfParticipantRequests.contains(channel)) return;
|
||||
_selfParticipantRequests.insert(channel, MTP::send(MTPchannels_GetParticipant(channel->inputChannel, MTP_inputUserSelf()), rpcDone(&ApiWrap::gotSelfParticipant, channel), rpcFail(&ApiWrap::gotSelfParticipantFail, channel), 0, 5));
|
||||
}
|
||||
|
||||
void ApiWrap::gotSelfParticipant(ChannelData *channel, const MTPchannels_ChannelParticipant &result) {
|
||||
_selfParticipantRequests.remove(channel);
|
||||
if (result.type() != mtpc_channels_channelParticipant) {
|
||||
LOG(("API Error: unknown type in gotSelfParticipant (%1)").arg(result.type()));
|
||||
channel->inviter = -1;
|
||||
if (App::main()) App::main()->onSelfParticipantUpdated(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
const MTPDchannels_channelParticipant &p(result.c_channels_channelParticipant());
|
||||
App::feedUsers(p.vusers);
|
||||
|
||||
switch (p.vparticipant.type()) {
|
||||
case mtpc_channelParticipantSelf: {
|
||||
const MTPDchannelParticipantSelf &d(p.vparticipant.c_channelParticipantSelf());
|
||||
channel->inviter = d.vinviter_id.v;
|
||||
channel->inviteDate = date(d.vdate);
|
||||
} break;
|
||||
case mtpc_channelParticipantCreator: {
|
||||
const MTPDchannelParticipantCreator &d(p.vparticipant.c_channelParticipantCreator());
|
||||
channel->inviter = MTP::authedId();
|
||||
channel->inviteDate = date(MTP_int(channel->date));
|
||||
} break;
|
||||
case mtpc_channelParticipantModerator: {
|
||||
const MTPDchannelParticipantModerator &d(p.vparticipant.c_channelParticipantModerator());
|
||||
channel->inviter = d.vinviter_id.v;
|
||||
channel->inviteDate = date(d.vdate);
|
||||
} break;
|
||||
case mtpc_channelParticipantEditor: {
|
||||
const MTPDchannelParticipantEditor &d(p.vparticipant.c_channelParticipantEditor());
|
||||
channel->inviter = d.vinviter_id.v;
|
||||
channel->inviteDate = date(d.vdate);
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
if (App::main()) App::main()->onSelfParticipantUpdated(channel);
|
||||
}
|
||||
|
||||
bool ApiWrap::gotSelfParticipantFail(ChannelData *channel, const RPCError &error) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
|
||||
if (error.type() == qstr("USER_NOT_PARTICIPANT")) {
|
||||
channel->inviter = -1;
|
||||
}
|
||||
_selfParticipantRequests.remove(channel);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApiWrap::scheduleStickerSetRequest(uint64 setId, uint64 access) {
|
||||
if (!_stickerSetRequests.contains(setId)) {
|
||||
_stickerSetRequests.insert(setId, qMakePair(access, 0));
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
void requestPeer(PeerData *peer);
|
||||
void requestPeers(const QList<PeerData*> &peers);
|
||||
|
||||
void requestSelfParticipant(ChannelData *channel);
|
||||
|
||||
void requestWebPageDelayed(WebPageData *page);
|
||||
void clearWebPageRequest(WebPageData *page);
|
||||
void clearWebPageRequests();
|
||||
|
@ -83,6 +85,11 @@ private:
|
|||
bool gotPeerFailed(PeerData *peer, const RPCError &err);
|
||||
PeerRequests _peerRequests;
|
||||
|
||||
void gotSelfParticipant(ChannelData *channel, const MTPchannels_ChannelParticipant &result);
|
||||
bool gotSelfParticipantFail(ChannelData *channel, const RPCError &error);
|
||||
typedef QMap<ChannelData*, mtpRequestId> SelfParticipantRequests;
|
||||
SelfParticipantRequests _selfParticipantRequests;
|
||||
|
||||
void gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
typedef QMap<WebPageData*, mtpRequestId> WebPagesPending;
|
||||
WebPagesPending _webPagesPending;
|
||||
|
|
|
@ -490,8 +490,8 @@ namespace App {
|
|||
cdata->setPhoto(d.vphoto);
|
||||
cdata->date = d.vdate.v;
|
||||
cdata->count = d.vparticipants_count.v;
|
||||
cdata->left = (d.vflags.v & MTPDchat_flag_left);
|
||||
cdata->forbidden = (d.vflags.v & MTPDchat_flag_kicked);
|
||||
cdata->isForbidden = (d.vflags.v & MTPDchat_flag_kicked);
|
||||
cdata->haveLeft = (d.vflags.v & MTPDchat_flag_left);
|
||||
if (cdata->version < d.vversion.v) {
|
||||
cdata->version = d.vversion.v;
|
||||
cdata->participants = ChatData::Participants();
|
||||
|
@ -510,8 +510,8 @@ namespace App {
|
|||
cdata->setPhoto(MTP_chatPhotoEmpty());
|
||||
cdata->date = 0;
|
||||
cdata->count = -1;
|
||||
cdata->left = false;
|
||||
cdata->forbidden = true;
|
||||
cdata->isForbidden = true;
|
||||
cdata->haveLeft = false;
|
||||
} break;
|
||||
case mtpc_channel: {
|
||||
const MTPDchannel &d(chat.c_channel());
|
||||
|
@ -529,13 +529,9 @@ namespace App {
|
|||
cdata->access = d.vaccess_hash.v;
|
||||
cdata->setPhoto(d.vphoto);
|
||||
cdata->date = d.vdate.v;
|
||||
cdata->adminned = (d.vflags.v & MTPDchannel_flag_am_admin);
|
||||
|
||||
cdata->isBroadcast = (d.vflags.v & MTPDchannel_flag_is_broadcast);
|
||||
cdata->isPublic = d.has_username();
|
||||
cdata->flags = d.vflags.v;
|
||||
cdata->isForbidden = false;
|
||||
|
||||
cdata->left = (d.vflags.v & MTPDchannel_flag_have_left);
|
||||
cdata->forbidden = (d.vflags.v & MTPDchannel_flag_was_kicked);
|
||||
if (cdata->version < d.vversion.v) {
|
||||
cdata->version = d.vversion.v;
|
||||
}
|
||||
|
@ -555,14 +551,8 @@ namespace App {
|
|||
cdata->access = d.vaccess_hash.v;
|
||||
cdata->setPhoto(MTP_chatPhotoEmpty());
|
||||
cdata->date = 0;
|
||||
// cdata->count = -1;
|
||||
cdata->adminned = false;
|
||||
|
||||
cdata->isBroadcast = false;
|
||||
cdata->isPublic = false;
|
||||
|
||||
cdata->left = false;
|
||||
cdata->forbidden = true;
|
||||
cdata->count = 0;
|
||||
cdata->isForbidden = true;
|
||||
} break;
|
||||
}
|
||||
if (!data) continue;
|
||||
|
@ -591,7 +581,7 @@ namespace App {
|
|||
case mtpc_chatParticipants: {
|
||||
const MTPDchatParticipants &d(p.c_chatParticipants());
|
||||
chat = App::chat(d.vchat_id.v);
|
||||
chat->admin = d.vadmin_id.v;
|
||||
chat->creator = d.vadmin_id.v;
|
||||
if (!requestBotInfos || chat->version <= d.vversion.v) { // !requestBotInfos is true on getFullChat result
|
||||
chat->version = d.vversion.v;
|
||||
const QVector<MTPChatParticipant> &v(d.vparticipants.c_vector().v);
|
||||
|
@ -757,7 +747,7 @@ namespace App {
|
|||
existing->setText(qs(m.vmessage), m.has_entities() ? linksFromMTP(m.ventities.c_vector().v) : LinksInText());
|
||||
existing->initDimensions();
|
||||
if (App::main()) App::main()->itemResized(existing);
|
||||
if (existing->hasTextLinks()) {
|
||||
if (existing->hasTextLinks() && (!existing->history()->isChannel() || existing->fromChannel())) {
|
||||
existing->history()->addToOverview(existing, OverviewLinks);
|
||||
}
|
||||
}
|
||||
|
@ -2369,9 +2359,9 @@ namespace App {
|
|||
}
|
||||
}
|
||||
|
||||
void searchByHashtag(const QString &tag) {
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer) {
|
||||
if (App::main()) {
|
||||
App::main()->searchMessages(tag + ' ');
|
||||
App::main()->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ namespace App {
|
|||
|
||||
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
|
||||
void insertBotCommand(const QString &cmd);
|
||||
void searchByHashtag(const QString &tag);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
|
||||
void joinGroupByHash(const QString &hash);
|
||||
void stickersBox(const QString &name);
|
||||
|
|
|
@ -499,7 +499,7 @@ void Application::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId)
|
|||
int32 filesize = 0;
|
||||
QByteArray data;
|
||||
|
||||
ReadyLocalMedia ready(ToPreparePhoto, file, filename, filesize, data, id, id, qsl("jpg"), peerId, photo, MTP_audioEmpty(MTP_long(0)), photoThumbs, MTP_documentEmpty(MTP_long(0)), jpeg, false, 0);
|
||||
ReadyLocalMedia ready(ToPreparePhoto, file, filename, filesize, data, id, id, qsl("jpg"), peerId, photo, MTP_audioEmpty(MTP_long(0)), photoThumbs, MTP_documentEmpty(MTP_long(0)), jpeg, false, false, 0);
|
||||
|
||||
connect(App::uploader(), SIGNAL(photoReady(const FullMsgId&, const MTPInputFile&)), App::app(), SLOT(photoUpdated(const FullMsgId&, const MTPInputFile&)), Qt::UniqueConnection);
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ void AddContactBox::initBox() {
|
|||
setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 1 * _firstInput.height() + st::addContactPadding.bottom() + _addButton.height());
|
||||
} else if (_peer->isChannel()) {
|
||||
// CHANNELS_UX
|
||||
_boxTitle = lang(lng_edit_group_title);
|
||||
_boxTitle = lang(lng_edit_channel_title);
|
||||
setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 1 * _firstInput.height() + st::addContactPadding.bottom() + _addButton.height());
|
||||
}
|
||||
} else {
|
||||
|
@ -334,3 +334,236 @@ void AddContactBox::onRetry() {
|
|||
setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 3 * _firstInput.height() + 2 * st::addContactDelta + st::addContactPadding.bottom() + _addButton.height());
|
||||
update();
|
||||
}
|
||||
|
||||
EditChannelBox::EditChannelBox(ChannelData *channel) :
|
||||
_channel(channel),
|
||||
_saveButton(this, lang(lng_settings_save), st::btnSelectDone),
|
||||
_cancelButton(this, lang(lng_cancel), st::btnSelectCancel),
|
||||
_title(this, st::inpAddContact, lang(lng_dlg_new_channel_name), _channel->name),
|
||||
_descriptionOver(false),
|
||||
a_descriptionBg(st::newGroupName.bgColor->c, st::newGroupName.bgColor->c),
|
||||
a_descriptionBorder(st::newGroupName.borderColor->c, st::newGroupName.borderColor->c),
|
||||
a_description(animFunc(this, &EditChannelBox::descriptionAnimStep)),
|
||||
_description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about),
|
||||
_saveTitleRequestId(0), _saveDescriptionRequestId(0) {
|
||||
_boxTitle = lang(lng_edit_channel_title);
|
||||
|
||||
_description.installEventFilter(this);
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
_description.resize(width() - st::newGroupPadding.left() - st::newGroupPadding.right() - st::newGroupDescriptionPadding.left() - st::newGroupDescriptionPadding.right(), _title.height() - st::newGroupDescriptionPadding.top() - st::newGroupDescriptionPadding.bottom());
|
||||
_description.setMinHeight(_description.height());
|
||||
_description.setMaxHeight(3 * _description.height() + 2 * st::newGroupDescriptionPadding.top() + 2 * st::newGroupDescriptionPadding.bottom());
|
||||
|
||||
updateMaxHeight();
|
||||
_description.setMaxLength(MaxChannelDescription);
|
||||
connect(&_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
|
||||
connect(&_description, SIGNAL(submitted(bool)), this, SLOT(onSave()));
|
||||
connect(&_description, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||
|
||||
connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
void EditChannelBox::hideAll() {
|
||||
_title.hide();
|
||||
_description.hide();
|
||||
_saveButton.hide();
|
||||
_cancelButton.hide();
|
||||
}
|
||||
|
||||
void EditChannelBox::showAll() {
|
||||
_title.show();
|
||||
_description.show();
|
||||
_saveButton.show();
|
||||
_cancelButton.show();
|
||||
}
|
||||
|
||||
void EditChannelBox::showDone() {
|
||||
_title.setFocus();
|
||||
}
|
||||
|
||||
void EditChannelBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
|
||||
if (_title.hasFocus()) {
|
||||
onSave();
|
||||
}
|
||||
} else {
|
||||
AbstractBox::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void EditChannelBox::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (paint(p)) return;
|
||||
|
||||
paintTitle(p, _boxTitle, true);
|
||||
|
||||
QRect descRect(descriptionRect());
|
||||
if (descRect.intersects(e->rect())) {
|
||||
p.fillRect(descRect, a_descriptionBg.current());
|
||||
if (st::newGroupName.borderWidth) {
|
||||
QBrush b(a_descriptionBorder.current());
|
||||
p.fillRect(descRect.x(), descRect.y(), descRect.width() - st::newGroupName.borderWidth, st::newGroupName.borderWidth, b);
|
||||
p.fillRect(descRect.x() + descRect.width() - st::newGroupName.borderWidth, descRect.y(), st::newGroupName.borderWidth, descRect.height() - st::newGroupName.borderWidth, b);
|
||||
p.fillRect(descRect.x() + st::newGroupName.borderWidth, descRect.y() + descRect.height() - st::newGroupName.borderWidth, descRect.width() - st::newGroupName.borderWidth, st::newGroupName.borderWidth, b);
|
||||
p.fillRect(descRect.x(), descRect.y() + st::newGroupName.borderWidth, st::newGroupName.borderWidth, descRect.height() - st::newGroupName.borderWidth, b);
|
||||
}
|
||||
if (descRect.contains(e->rect())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// paint shadows
|
||||
p.fillRect(0, size().height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b);
|
||||
|
||||
// paint button sep
|
||||
p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b);
|
||||
}
|
||||
|
||||
bool EditChannelBox::descriptionAnimStep(float64 ms) {
|
||||
float dt = ms / st::newGroupName.phDuration;
|
||||
bool res = true;
|
||||
if (dt >= 1) {
|
||||
res = false;
|
||||
a_descriptionBg.finish();
|
||||
a_descriptionBorder.finish();
|
||||
} else {
|
||||
a_descriptionBg.update(dt, st::newGroupName.phColorFunc);
|
||||
a_descriptionBorder.update(dt, st::newGroupName.phColorFunc);
|
||||
}
|
||||
update(descriptionRect());
|
||||
return res;
|
||||
}
|
||||
|
||||
void EditChannelBox::onDescriptionResized() {
|
||||
updateMaxHeight();
|
||||
update();
|
||||
}
|
||||
|
||||
QRect EditChannelBox::descriptionRect() const {
|
||||
return rtlrect(_description.x() - st::newGroupDescriptionPadding.left(), _description.y() - st::newGroupDescriptionPadding.top(), _description.width() + st::newGroupDescriptionPadding.left() + st::newGroupDescriptionPadding.right(), _description.height() + st::newGroupDescriptionPadding.top() + st::newGroupDescriptionPadding.bottom(), width());
|
||||
}
|
||||
|
||||
void EditChannelBox::updateMaxHeight() {
|
||||
int32 h = st::boxTitleHeight + st::newGroupPadding.top() + _title.height() + st::newGroupPadding.bottom() + _saveButton.height();
|
||||
h += st::newGroupDescriptionSkip + st::newGroupDescriptionPadding.top() + _description.height() + st::newGroupDescriptionPadding.bottom();
|
||||
setMaxHeight(h);
|
||||
}
|
||||
|
||||
bool EditChannelBox::eventFilter(QObject *obj, QEvent *e) {
|
||||
if (obj == &_description) {
|
||||
if (e->type() == QEvent::FocusIn) {
|
||||
a_descriptionBorder.start(st::newGroupName.borderActive->c);
|
||||
a_descriptionBg.start(st::newGroupName.bgActive->c);
|
||||
a_description.start();
|
||||
} else if (e->type() == QEvent::FocusOut) {
|
||||
a_descriptionBorder.start(st::newGroupName.borderColor->c);
|
||||
a_descriptionBg.start(st::newGroupName.bgColor->c);
|
||||
a_description.start();
|
||||
}
|
||||
}
|
||||
return AbstractBox::eventFilter(obj, e);
|
||||
}
|
||||
|
||||
void EditChannelBox::resizeEvent(QResizeEvent *e) {
|
||||
_title.resize(width() - st::newGroupPadding.left() - st::newGroupPadding.right(), _title.height());
|
||||
_title.moveToLeft(st::newGroupPadding.left(), st::boxTitleHeight + st::newGroupPadding.top(), width());
|
||||
|
||||
_description.moveToLeft(st::newGroupPadding.left() + st::newGroupDescriptionPadding.left(), _title.y() + _title.height() + st::newGroupDescriptionSkip + st::newGroupDescriptionPadding.top(), width());
|
||||
|
||||
int32 buttonTop = _description.y() + _description.height() + st::newGroupDescriptionPadding.bottom();
|
||||
buttonTop += st::newGroupPadding.bottom();
|
||||
_cancelButton.move(0, buttonTop);
|
||||
_saveButton.move(width() - _saveButton.width(), buttonTop);
|
||||
}
|
||||
|
||||
void EditChannelBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
updateSelected(e->globalPos());
|
||||
}
|
||||
|
||||
void EditChannelBox::updateSelected(const QPoint &cursorGlobalPosition) {
|
||||
QPoint p(mapFromGlobal(cursorGlobalPosition));
|
||||
|
||||
bool descriptionOver = descriptionRect().contains(p);
|
||||
if (descriptionOver != _descriptionOver) {
|
||||
_descriptionOver = descriptionOver;
|
||||
}
|
||||
|
||||
setCursor(_descriptionOver ? style::cur_text : style::cur_default);
|
||||
}
|
||||
|
||||
void EditChannelBox::mousePressEvent(QMouseEvent *e) {
|
||||
mouseMoveEvent(e);
|
||||
if (_descriptionOver) {
|
||||
_description.setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void EditChannelBox::leaveEvent(QEvent *e) {
|
||||
updateSelected(QCursor::pos());
|
||||
}
|
||||
|
||||
void EditChannelBox::onSave() {
|
||||
if (_saveTitleRequestId || _saveDescriptionRequestId) return;
|
||||
|
||||
QString title = _title.text().trimmed(), description = _description.getLastText().trimmed();
|
||||
if (title.isEmpty()) {
|
||||
_title.setFocus();
|
||||
_title.notaBene();
|
||||
return;
|
||||
}
|
||||
_sentTitle = title;
|
||||
_sentDescription = description;
|
||||
_saveTitleRequestId = MTP::send(MTPchannels_EditTitle(_channel->inputChannel, MTP_string(_sentTitle)), rpcDone(&EditChannelBox::onSaveTitleDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
}
|
||||
|
||||
void EditChannelBox::saveDescription() {
|
||||
_saveDescriptionRequestId = MTP::send(MTPchannels_EditAbout(_channel->inputChannel, MTP_string(_sentDescription)), rpcDone(&EditChannelBox::onSaveDescriptionDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
}
|
||||
|
||||
bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
|
||||
QString err(error.type());
|
||||
if (req == _saveTitleRequestId) {
|
||||
_saveTitleRequestId = 0;
|
||||
if (err == qstr("CHAT_NOT_MODIFIED") || err == qstr("CHAT_TITLE_NOT_MODIFIED")) {
|
||||
_channel->setName(_sentTitle, _channel->username);
|
||||
saveDescription();
|
||||
return true;
|
||||
} else if (err == qstr("NO_CHAT_TITLE")) {
|
||||
_title.setFocus();
|
||||
_title.notaBene();
|
||||
return true;
|
||||
} else {
|
||||
_title.setFocus();
|
||||
}
|
||||
} else if (req == _saveDescriptionRequestId) {
|
||||
_saveDescriptionRequestId = 0;
|
||||
if (err == qstr("CHAT_ABOUT_NOT_MODIFIED")) {
|
||||
_channel->about = _sentDescription;
|
||||
emit App::api()->fullPeerUpdated(_channel);
|
||||
onClose();
|
||||
} else {
|
||||
_description.setFocus();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveTitleDone(const MTPUpdates &updates) {
|
||||
_saveTitleRequestId = 0;
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
saveDescription();
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveDescriptionDone(const MTPBool &result) {
|
||||
_saveDescriptionRequestId = 0;
|
||||
_channel->about = _sentDescription;
|
||||
emit App::api()->fullPeerUpdated(_channel);
|
||||
onClose();
|
||||
}
|
||||
|
|
|
@ -69,3 +69,64 @@ private:
|
|||
mtpRequestId _addRequest;
|
||||
QString _sentName;
|
||||
};
|
||||
|
||||
class EditChannelBox : public AbstractBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
EditChannelBox(ChannelData *channel);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void leaveEvent(QEvent *e);
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *e);
|
||||
|
||||
bool descriptionAnimStep(float64 ms);
|
||||
|
||||
void setInnerFocus() {
|
||||
if (!_description.hasFocus()) {
|
||||
_title.setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
void onSave();
|
||||
void onDescriptionResized();
|
||||
|
||||
protected:
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
void showDone();
|
||||
|
||||
private:
|
||||
|
||||
QRect descriptionRect() const;
|
||||
void updateMaxHeight();
|
||||
void updateSelected(const QPoint &cursorGlobalPosition);
|
||||
|
||||
void onSaveTitleDone(const MTPUpdates &updates);
|
||||
void onSaveDescriptionDone(const MTPBool &result);
|
||||
bool onSaveFail(const RPCError &e, mtpRequestId req);
|
||||
|
||||
void saveDescription();
|
||||
|
||||
ChannelData *_channel;
|
||||
QString _boxTitle;
|
||||
|
||||
FlatButton _saveButton, _cancelButton;
|
||||
FlatInput _title;
|
||||
|
||||
bool _descriptionOver;
|
||||
anim::cvalue a_descriptionBg, a_descriptionBorder;
|
||||
Animation a_description;
|
||||
FlatTextarea _description;
|
||||
|
||||
mtpRequestId _saveTitleRequestId, _saveDescriptionRequestId;
|
||||
QString _sentTitle, _sentDescription;
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@ _byUsernameSel(-1),
|
|||
_addContactLnk(this, lang(lng_add_contact_button)) {
|
||||
DialogsIndexed &v(App::main()->dialogsList());
|
||||
for (DialogRow *r = v.list.begin; r != v.list.end; r = r->next) {
|
||||
if (r->history->peer->isChat() && !r->history->peer->asChat()->forbidden && !r->history->peer->asChat()->left) {
|
||||
if (r->history->peer->isChat() && !r->history->peer->asChat()->isForbidden && !r->history->peer->asChat()->haveLeft) {
|
||||
_contacts->addToEnd(r->history);
|
||||
}
|
||||
}
|
||||
|
@ -94,10 +94,10 @@ void ContactsInner::init() {
|
|||
_filter = qsl("a");
|
||||
updateFilter();
|
||||
|
||||
connect(App::main(), SIGNAL(dialogRowReplaced(DialogRow *, DialogRow *)), this, SLOT(onDialogRowReplaced(DialogRow *, DialogRow *)));
|
||||
connect(App::main(), SIGNAL(dialogRowReplaced(DialogRow*,DialogRow*)), this, SLOT(onDialogRowReplaced(DialogRow*,DialogRow*)));
|
||||
connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData *)));
|
||||
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 *)));
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)));
|
||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
}
|
||||
|
||||
void ContactsInner::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
|
||||
|
@ -119,7 +119,7 @@ void ContactsInner::onAddBot() {
|
|||
|
||||
void ContactsInner::peerUpdated(PeerData *peer) {
|
||||
if (_chat && (!peer || peer == _chat)) {
|
||||
if (_chat->forbidden || _chat->left) {
|
||||
if (_chat->isForbidden || _chat->haveLeft) {
|
||||
App::wnd()->hideLayer();
|
||||
} else if (!_chat->participants.isEmpty() || _chat->count <= 0) {
|
||||
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
|
||||
|
@ -201,7 +201,7 @@ ContactsInner::ContactData *ContactsInner::contactData(DialogRow *row) {
|
|||
data->online = App::onlineText(peer->asUser(), _time);
|
||||
} else if (peer->isChat()) {
|
||||
ChatData *chat = peer->asChat();
|
||||
if (chat->forbidden || chat->left) {
|
||||
if (chat->isForbidden || chat->haveLeft) {
|
||||
data->online = lang(lng_chat_status_unaccessible);
|
||||
} else {
|
||||
data->online = lng_chat_status_members(lt_count, chat->count);
|
||||
|
@ -1096,6 +1096,7 @@ void ContactsBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId r
|
|||
switch (result.type()) {
|
||||
case mtpc_contacts_found: {
|
||||
App::feedUsers(result.c_contacts_found().vusers);
|
||||
App::feedChats(result.c_contacts_found().vchats);
|
||||
_inner.peopleReceived(q, result.c_contacts_found().vresults.c_vector().v);
|
||||
} break;
|
||||
}
|
||||
|
@ -1390,10 +1391,10 @@ void NewGroupBox::resizeEvent(QResizeEvent *e) {
|
|||
}
|
||||
|
||||
void NewGroupBox::onNext() {
|
||||
App::wnd()->replaceLayer(new GroupInfoBox(_group.checked() ? CreatingGroupGroup : CreatingGroupChannel));
|
||||
App::wnd()->replaceLayer(new GroupInfoBox(_group.checked() ? CreatingGroupGroup : CreatingGroupChannel, true));
|
||||
}
|
||||
|
||||
GroupInfoBox::GroupInfoBox(CreatingGroupType creating) : AbstractBox(),
|
||||
GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox(),
|
||||
_creating(creating),
|
||||
a_photoOver(0, 0),
|
||||
a_photo(animFunc(this, &GroupInfoBox::photoAnimStep)),
|
||||
|
@ -1406,7 +1407,7 @@ _name(this, st::newGroupName, lang(_creating == CreatingGroupChannel ? lng_dlg_n
|
|||
_photo(this, lang(lng_create_group_photo), st::newGroupPhoto),
|
||||
_description(this, st::newGroupDescription, lang(lng_create_group_description)),
|
||||
_next(this, lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), st::btnSelectDone),
|
||||
_cancel(this, lang(lng_create_group_back), st::btnSelectCancel),
|
||||
_cancel(this, lang(fromTypeChoose ? lng_create_group_back : lng_cancel), st::btnSelectCancel),
|
||||
_creationRequestId(0), _createdChannel(0) {
|
||||
|
||||
setMouseTracking(true);
|
||||
|
@ -1420,6 +1421,7 @@ _creationRequestId(0), _createdChannel(0) {
|
|||
connect(&_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
|
||||
connect(&_description, SIGNAL(submitted(bool)), this, SLOT(onNext()));
|
||||
connect(&_description, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||
_description.installEventFilter(this);
|
||||
|
||||
connect(&_photo, SIGNAL(clicked()), this, SLOT(onPhoto()));
|
||||
|
||||
|
@ -1523,7 +1525,6 @@ void GroupInfoBox::resizeEvent(QResizeEvent *e) {
|
|||
_photo.moveToLeft(_name.x(), _name.y() + st::newGroupPhotoSize - _photo.height(), width());
|
||||
|
||||
_description.moveToLeft(st::newGroupPadding.left() + st::newGroupDescriptionPadding.left(), _photo.y() + _photo.height() + st::newGroupDescriptionSkip + st::newGroupDescriptionPadding.top(), width());
|
||||
_description.installEventFilter(this);
|
||||
|
||||
int32 buttonTop = (_creating == CreatingGroupChannel) ? (_description.y() + _description.height() + st::newGroupDescriptionPadding.bottom()) : (_photo.y() + _photo.height());
|
||||
buttonTop += st::newGroupPadding.bottom();
|
||||
|
@ -1646,7 +1647,7 @@ bool GroupInfoBox::creationFail(const RPCError &error) {
|
|||
_name.notaBene();
|
||||
return true;
|
||||
} else if (error.type() == "PEER_FLOOD") {
|
||||
App::wnd()->replaceLayer(new ConfirmBox(lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)))));
|
||||
App::wnd()->replaceLayer(new ConfirmBox(lng_cant_invite_not_contact_channel(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)))));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1715,8 +1716,9 @@ void GroupInfoBox::onPhotoReady(const QImage &img) {
|
|||
_photoSmall.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
|
||||
SetupChannelBox::SetupChannelBox(ChannelData *channel) : AbstractBox(),
|
||||
SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox(),
|
||||
_channel(channel),
|
||||
_existing(existing),
|
||||
_public(this, qsl("channel_privacy"), 0, lang(lng_create_public_channel_title), true),
|
||||
_private(this, qsl("channel_privacy"), 1, lang(lng_create_private_channel_title)),
|
||||
_comments(this, lang(lng_create_channel_comments), false),
|
||||
|
@ -1725,14 +1727,17 @@ _aboutPublic(st::normalFont, lang(lng_create_public_channel_about), _defaultOpti
|
|||
_aboutPrivate(st::normalFont, lang(lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth),
|
||||
_aboutComments(st::normalFont, lang(lng_create_channel_comments_about), _defaultOptions, _aboutPublicWidth),
|
||||
_linkPlaceholder(qsl("telegram.me/")),
|
||||
_link(this, st::newGroupLink, QString()),
|
||||
_link(this, st::newGroupLink, QString(), channel->username),
|
||||
_linkOver(false),
|
||||
_save(this, lang(lng_create_group_save), st::btnSelectDone),
|
||||
_skip(this, lang(lng_create_group_skip), st::btnSelectCancel),
|
||||
_skip(this, lang(existing ? lng_cancel : lng_create_group_skip), st::btnSelectCancel),
|
||||
_tooMuchUsernames(false),
|
||||
_saveRequestId(0), _checkRequestId(0),
|
||||
a_goodOpacity(0, 0), a_good(animFunc(this, &SetupChannelBox::goodAnimStep)) {
|
||||
setMouseTracking(true);
|
||||
|
||||
_checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail));
|
||||
|
||||
_link.setTextMargin(style::margins(st::newGroupLink.textMrg.left() + st::newGroupLink.font->m.width(_linkPlaceholder), st::newGroupLink.textMrg.top(), st::newGroupLink.textMrg.right(), st::newGroupLink.textMrg.bottom()));
|
||||
|
||||
_aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth);
|
||||
|
@ -1902,15 +1907,22 @@ bool SetupChannelBox::goodAnimStep(float64 ms) {
|
|||
}
|
||||
|
||||
void SetupChannelBox::closePressed() {
|
||||
App::wnd()->showLayer(new ContactsBox(_channel), true);
|
||||
if (!_existing) {
|
||||
App::wnd()->showLayer(new ContactsBox(_channel), true);
|
||||
}
|
||||
}
|
||||
|
||||
void SetupChannelBox::onSave() {
|
||||
if (!_public.checked()) {
|
||||
if (_comments.checked()) {
|
||||
if (!_existing && !_comments.isHidden() && _comments.checked()) {
|
||||
MTP::send(MTPchannels_ToggleComments(_channel->inputChannel, MTP_bool(true)));
|
||||
}
|
||||
onClose();
|
||||
if (_existing) {
|
||||
_sentUsername = QString();
|
||||
_saveRequestId = MTP::send(MTPchannels_UpdateUsername(_channel->inputChannel, MTP_string(_sentUsername)), rpcDone(&SetupChannelBox::onUpdateDone), rpcFail(&SetupChannelBox::onUpdateFail));
|
||||
} else {
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
if (_saveRequestId) return;
|
||||
|
@ -1922,7 +1934,7 @@ void SetupChannelBox::onSave() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (_comments.checked()) {
|
||||
if (!_existing && !_comments.isHidden() && _comments.checked()) {
|
||||
MTP::send(MTPchannels_ToggleComments(_channel->inputChannel, MTP_bool(true)), RPCResponseHandler(), 0, 5);
|
||||
}
|
||||
_sentUsername = link;
|
||||
|
@ -1979,6 +1991,11 @@ void SetupChannelBox::onCheck() {
|
|||
|
||||
void SetupChannelBox::onPrivacyChange() {
|
||||
if (_public.checked()) {
|
||||
if (_tooMuchUsernames) {
|
||||
_private.setChecked(true);
|
||||
App::wnd()->replaceLayer(new ConfirmBox(lang(lng_channels_too_much_public)));
|
||||
return;
|
||||
}
|
||||
_link.show();
|
||||
_link.setFocus();
|
||||
} else {
|
||||
|
@ -2035,7 +2052,17 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
|
|||
|
||||
_checkRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == "USERNAME_INVALID") {
|
||||
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||
if (_existing) {
|
||||
App::wnd()->hideLayer(true);
|
||||
App::wnd()->showLayer(new ConfirmBox(lang(lng_channels_too_much_public_existing)), true);
|
||||
} else {
|
||||
_tooMuchUsernames = true;
|
||||
_private.setChecked(true);
|
||||
onPrivacyChange();
|
||||
}
|
||||
return true;
|
||||
} else if (err == "USERNAME_INVALID") {
|
||||
_errorText = lang(lng_create_channel_link_invalid);
|
||||
update();
|
||||
return true;
|
||||
|
@ -2048,3 +2075,24 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
|
|||
_link.setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
|
||||
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
|
||||
|
||||
_checkRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||
if (_existing) {
|
||||
App::wnd()->hideLayer(true);
|
||||
App::wnd()->showLayer(new ConfirmBox(lang(lng_channels_too_much_public_existing)), true);
|
||||
} else {
|
||||
_tooMuchUsernames = true;
|
||||
_private.setChecked(true);
|
||||
onPrivacyChange();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
_goodText = QString();
|
||||
_link.setFocus();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -245,7 +245,7 @@ class GroupInfoBox : public AbstractBox, public RPCSender {
|
|||
|
||||
public:
|
||||
|
||||
GroupInfoBox(CreatingGroupType creating);
|
||||
GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
@ -313,7 +313,7 @@ class SetupChannelBox : public AbstractBox, public RPCSender {
|
|||
|
||||
public:
|
||||
|
||||
SetupChannelBox(ChannelData *channel);
|
||||
SetupChannelBox(ChannelData *channel, bool existing = false);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
@ -350,6 +350,7 @@ private:
|
|||
bool goodAnimStep(float64 ms);
|
||||
|
||||
ChannelData *_channel;
|
||||
bool _existing;
|
||||
|
||||
FlatRadiobutton _public, _private;
|
||||
FlatCheckbox _comments;
|
||||
|
@ -366,6 +367,9 @@ private:
|
|||
|
||||
void onCheckDone(const MTPBool &result);
|
||||
bool onCheckFail(const RPCError &error);
|
||||
bool onFirstCheckFail(const RPCError &error);
|
||||
|
||||
bool _tooMuchUsernames;
|
||||
|
||||
mtpRequestId _saveRequestId, _checkRequestId;
|
||||
QString _sentUsername, _checkUsername, _errorText, _goodText;
|
||||
|
|
|
@ -335,6 +335,9 @@ enum {
|
|||
UpdateChunk = 100 * 1024, // 100kb parts when downloading the update
|
||||
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle
|
||||
|
||||
UpdateFullChannelTimeout = 5000, // not more than once in 5 seconds
|
||||
SendViewsTimeout = 1000, // send views each second
|
||||
|
||||
ForwardOnAdd = 100, // how many messages from chat history server should forward to user, that was added to this chat
|
||||
};
|
||||
|
||||
|
|
|
@ -419,7 +419,7 @@ void DialogsListWidget::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow
|
|||
}
|
||||
}
|
||||
|
||||
void DialogsListWidget::createDialogAtTop(History *history, int32 unreadCount) {
|
||||
void DialogsListWidget::createDialog(History *history) {
|
||||
if (history->dialogs.isEmpty()) {
|
||||
History::DialogLinks links = dialogs.addToEnd(history);
|
||||
int32 movedFrom = links[0]->pos * st::dlgHeight;
|
||||
|
@ -781,6 +781,13 @@ void DialogsListWidget::dialogsReceived(const QVector<MTPDialog> &added) {
|
|||
if (history->peer->isChannel()) {
|
||||
history->asChannelHistory()->unreadCountAll = d.vunread_count.v;
|
||||
history->peer->asChannel()->ptsReceived(d.vpts.v);
|
||||
if (!history->peer->asChannel()->amCreator()) {
|
||||
if (HistoryItem *top = App::histItemById(history->channelId(), d.vtop_important_message.v)) {
|
||||
if (top->date <= date(history->peer->asChannel()->date)) {
|
||||
App::api()->requestSelfParticipant(history->peer->asChannel());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (d.vtop_message.v > d.vtop_important_message.v) {
|
||||
history->setNotLoadedAtBottom();
|
||||
|
@ -1530,8 +1537,8 @@ void DialogsWidget::activate() {
|
|||
list.activate();
|
||||
}
|
||||
|
||||
void DialogsWidget::createDialogAtTop(History *history, int32 unreadCount) {
|
||||
list.createDialogAtTop(history, unreadCount);
|
||||
void DialogsWidget::createDialog(History *history) {
|
||||
list.createDialog(history);
|
||||
}
|
||||
|
||||
void DialogsWidget::dlgUpdated(DialogRow *row) {
|
||||
|
@ -1778,11 +1785,15 @@ void DialogsWidget::onChooseByDrag() {
|
|||
list.choosePeer();
|
||||
}
|
||||
|
||||
void DialogsWidget::searchMessages(const QString &query) {
|
||||
if (_filter.getLastText() != query) {
|
||||
void DialogsWidget::searchMessages(const QString &query, PeerData *inPeer) {
|
||||
if ((_filter.getLastText() != query) || (inPeer && inPeer != _searchInPeer)) {
|
||||
if (inPeer) {
|
||||
_searchInPeer = inPeer;
|
||||
list.searchInPeer(inPeer);
|
||||
}
|
||||
_filter.setText(query);
|
||||
_filter.updatePlaceholder();
|
||||
onFilterUpdate();
|
||||
onFilterUpdate(true);
|
||||
_searchTimer.stop();
|
||||
onSearchMessages();
|
||||
|
||||
|
@ -1905,6 +1916,7 @@ void DialogsWidget::peopleReceived(const MTPcontacts_Found &result, mtpRequestId
|
|||
switch (result.type()) {
|
||||
case mtpc_contacts_found: {
|
||||
App::feedUsers(result.c_contacts_found().vusers);
|
||||
App::feedChats(result.c_contacts_found().vchats);
|
||||
list.peopleReceived(q, result.c_contacts_found().vresults.c_vector().v);
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
void selectSkip(int32 direction);
|
||||
void selectSkipPage(int32 pixels, int32 direction);
|
||||
|
||||
void createDialogAtTop(History *history, int32 unreadCount);
|
||||
void createDialog(History *history);
|
||||
void moveDialogToTop(const History::DialogLinks &links);
|
||||
void dlgUpdated(DialogRow *row);
|
||||
void dlgUpdated(History *row);
|
||||
|
@ -194,7 +194,7 @@ public:
|
|||
void searchInPeer(PeerData *peer);
|
||||
|
||||
void loadDialogs();
|
||||
void createDialogAtTop(History *history, int32 unreadCount);
|
||||
void createDialog(History *history);
|
||||
void dlgUpdated(DialogRow *row);
|
||||
void dlgUpdated(History *row);
|
||||
|
||||
|
@ -217,7 +217,7 @@ public:
|
|||
|
||||
void enableShadow(bool enable = true);
|
||||
|
||||
void searchMessages(const QString &query);
|
||||
void searchMessages(const QString &query, PeerData *inPeer = 0);
|
||||
void onSearchMore(MsgId minMsgId);
|
||||
|
||||
void itemRemoved(HistoryItem *item);
|
||||
|
|
|
@ -21,11 +21,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
#include "flattextarea.h"
|
||||
#include "window.h"
|
||||
|
||||
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(v, parent),
|
||||
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(QString(), parent),
|
||||
_minHeight(-1), _maxHeight(-1), _maxLength(-1), _ctrlEnterSubmit(true),
|
||||
_ph(pholder), _oldtext(v), _phVisible(!v.length()),
|
||||
_oldtext(v), _phVisible(!v.length()),
|
||||
a_phLeft(_phVisible ? 0 : st.phShift), a_phAlpha(_phVisible ? 1 : 0), a_phColor(st.phColor->c),
|
||||
_st(st), _undoAvailable(false), _redoAvailable(false), _inDrop(false), _fakeMargin(0),
|
||||
_st(st), _undoAvailable(false), _redoAvailable(false), _inDrop(false), _inHeightCheck(false), _fakeMargin(0),
|
||||
_touchPress(false), _touchRightButton(false), _touchMove(false), _replacingEmojis(false) {
|
||||
setAcceptRichText(false);
|
||||
resize(_st.width, _st.font->height);
|
||||
|
@ -33,7 +33,7 @@ _touchPress(false), _touchRightButton(false), _touchMove(false), _replacingEmoji
|
|||
setFont(_st.font->f);
|
||||
setAlignment(_st.align);
|
||||
|
||||
_phelided = _st.font->m.elidedText(_ph, Qt::ElideRight, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1);
|
||||
setPlaceholder(pholder);
|
||||
|
||||
QPalette p(palette());
|
||||
p.setColor(QPalette::Text, _st.textColor->c);
|
||||
|
@ -63,6 +63,10 @@ _touchPress(false), _touchRightButton(false), _touchMove(false), _replacingEmoji
|
|||
connect(this, SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool)));
|
||||
connect(this, SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool)));
|
||||
if (App::wnd()) connect(this, SIGNAL(selectionChanged()), App::wnd(), SLOT(updateGlobalMenu()));
|
||||
|
||||
if (!v.isEmpty()) {
|
||||
setPlainText(v);
|
||||
}
|
||||
}
|
||||
|
||||
void FlatTextarea::setMaxLength(int32 maxLength) {
|
||||
|
@ -80,7 +84,11 @@ void FlatTextarea::setMaxHeight(int32 maxHeight) {
|
|||
}
|
||||
|
||||
bool FlatTextarea::heightAutoupdated() {
|
||||
if (_minHeight < 0 || _maxHeight < 0) return false;
|
||||
if (_minHeight < 0 || _maxHeight < 0 || _inHeightCheck) return false;
|
||||
_inHeightCheck = true;
|
||||
|
||||
myEnsureResized(this);
|
||||
|
||||
int newh = ceil(document()->size().height()) + 2 * fakeMargin();
|
||||
if (newh > _maxHeight) {
|
||||
newh = _maxHeight;
|
||||
|
@ -794,6 +802,12 @@ const QString &FlatTextarea::getLastText() const {
|
|||
return _oldtext;
|
||||
}
|
||||
|
||||
void FlatTextarea::setPlaceholder(const QString &ph) {
|
||||
_ph = ph;
|
||||
_phelided = _st.font->m.elidedText(_ph, Qt::ElideRight, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1);
|
||||
if (_phVisible) update();
|
||||
}
|
||||
|
||||
void FlatTextarea::updatePlaceholder() {
|
||||
bool vis = getLastText().isEmpty();
|
||||
if (vis == _phVisible) return;
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
void setMaxHeight(int32 maxHeight);
|
||||
|
||||
const QString &getLastText() const;
|
||||
void setPlaceholder(const QString &ph);
|
||||
void updatePlaceholder();
|
||||
|
||||
QRect getTextRect() const;
|
||||
|
@ -118,7 +119,7 @@ private:
|
|||
anim::cvalue a_phColor;
|
||||
style::flatTextarea _st;
|
||||
|
||||
bool _undoAvailable, _redoAvailable, _inDrop;
|
||||
bool _undoAvailable, _redoAvailable, _inDrop, _inHeightCheck;
|
||||
|
||||
int32 _fakeMargin;
|
||||
|
||||
|
|
|
@ -847,7 +847,7 @@ void MentionLink::onClick(Qt::MouseButton button) const {
|
|||
|
||||
void HashtagLink::onClick(Qt::MouseButton button) const {
|
||||
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
|
||||
App::searchByHashtag(_tag);
|
||||
App::searchByHashtag(_tag, App::mousedItem() ? App::mousedItem()->history()->peer : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ bool History::updateTyping(uint64 ms, uint32 dots, bool force) {
|
|||
newTypingStr += qsl("...");
|
||||
}
|
||||
if (typingStr != newTypingStr) {
|
||||
typingText.setText(st::dlgHistFont, (typingStr = newTypingStr), _textNameOptions);
|
||||
typingText.setText(st::dlgHistFont, (typingStr = newTypingStr), _textNameOptions);
|
||||
}
|
||||
}
|
||||
if (!typingStr.isEmpty()) {
|
||||
|
@ -422,7 +422,7 @@ ChannelHistory::ChannelHistory(const PeerId &peer) : History(peer),
|
|||
unreadCountAll(0),
|
||||
_onlyImportant(true),
|
||||
_otherOldLoaded(false), _otherNewLoaded(true),
|
||||
_collapse(0) {
|
||||
_collapseMessage(0), _joinedMessage(0) {
|
||||
}
|
||||
|
||||
bool ChannelHistory::isSwitchReadyFor(MsgId switchId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop) {
|
||||
|
@ -533,14 +533,14 @@ void ChannelHistory::insertCollapseItem(MsgId wasMinId) {
|
|||
if (_onlyImportant) return;
|
||||
|
||||
bool insertAfter = false;
|
||||
for (int32 blockIndex = 0, blocksCount = blocks.size(); blockIndex < blocksCount; ++blockIndex) {
|
||||
for (int32 blockIndex = 1, blocksCount = blocks.size(); blockIndex < blocksCount; ++blockIndex) { // skip first date block
|
||||
HistoryBlock *block = blocks.at(blockIndex);
|
||||
for (int32 itemIndex = 0, itemsCount = block->items.size(); itemIndex < itemsCount; ++itemIndex) {
|
||||
HistoryItem *item = block->items.at(itemIndex);
|
||||
if (insertAfter || item->id > wasMinId || (item->id == wasMinId && !item->isImportant())) {
|
||||
_collapse = new HistoryCollapse(this, block, wasMinId, item->date);
|
||||
if (!addNewInTheMiddle(_collapse, blockIndex, itemIndex)) {
|
||||
_collapse = 0;
|
||||
_collapseMessage = new HistoryCollapse(this, block, wasMinId, item->date);
|
||||
if (!addNewInTheMiddle(_collapseMessage, blockIndex, itemIndex)) {
|
||||
_collapseMessage = 0;
|
||||
}
|
||||
return;
|
||||
} else if (item->id == wasMinId && item->isImportant()) {
|
||||
|
@ -550,6 +550,296 @@ void ChannelHistory::insertCollapseItem(MsgId wasMinId) {
|
|||
}
|
||||
}
|
||||
|
||||
void ChannelHistory::getRangeDifference() {
|
||||
MsgId fromId = 0, toId = 0;
|
||||
for (int32 blockIndex = 0, blocksCount = blocks.size(); blockIndex < blocksCount; ++blockIndex) {
|
||||
HistoryBlock *block = blocks.at(blockIndex);
|
||||
for (int32 itemIndex = 0, itemsCount = block->items.size(); itemIndex < itemsCount; ++itemIndex) {
|
||||
HistoryItem *item = block->items.at(itemIndex);
|
||||
if (item->type() == HistoryItemMsg && item->id > 0) {
|
||||
fromId = item->id;
|
||||
break;
|
||||
} else if (item->type() == HistoryItemGroup) {
|
||||
fromId = static_cast<HistoryGroup*>(item)->minId() + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fromId) break;
|
||||
}
|
||||
if (!fromId) return;
|
||||
for (int32 blockIndex = blocks.size(); blockIndex > 0;) {
|
||||
HistoryBlock *block = blocks.at(--blockIndex);
|
||||
for (int32 itemIndex = block->items.size(); itemIndex > 0;) {
|
||||
HistoryItem *item = block->items.at(--itemIndex);
|
||||
if (item->type() == HistoryItemMsg && item->id > 0) {
|
||||
toId = item->id;
|
||||
break;
|
||||
} else if (item->type() == HistoryItemGroup) {
|
||||
toId = static_cast<HistoryGroup*>(item)->maxId() - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (toId) break;
|
||||
}
|
||||
if (fromId > 0 && peer->asChannel()->pts() > 0) {
|
||||
if (_rangeDifferenceRequestId) {
|
||||
MTP::cancel(_rangeDifferenceRequestId);
|
||||
}
|
||||
_rangeDifferenceFromId = fromId;
|
||||
_rangeDifferenceToId = toId;
|
||||
|
||||
MTP_LOG(0, ("getChannelDifference { good - after channelDifferenceTooLong was received, validating history part }%1").arg(cTestMode() ? " TESTMODE" : ""));
|
||||
getRangeDifferenceNext(peer->asChannel()->pts());
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelHistory::getRangeDifferenceNext(int32 pts) {
|
||||
if (!App::main() || _rangeDifferenceToId < _rangeDifferenceFromId) return;
|
||||
|
||||
int32 limit = _rangeDifferenceToId + 1 - _rangeDifferenceFromId;
|
||||
_rangeDifferenceRequestId = MTP::send(MTPupdates_GetChannelDifference(peer->asChannel()->inputChannel, MTP_channelMessagesFilter(MTP_int(0), MTP_vector<MTPMessageRange>(1, MTP_messageRange(MTP_int(_rangeDifferenceFromId), MTP_int(_rangeDifferenceToId)))), MTP_int(pts), MTP_int(limit)), App::main()->rpcDone(&MainWidget::gotRangeDifference, peer->asChannel()));
|
||||
}
|
||||
|
||||
void ChannelHistory::addNewGroup(const MTPMessageGroup &group) {
|
||||
if (group.type() != mtpc_messageGroup) return;
|
||||
const MTPDmessageGroup &d(group.c_messageGroup());
|
||||
|
||||
if (onlyImportant()) {
|
||||
_otherNewLoaded = false;
|
||||
} else if (_otherNewLoaded) {
|
||||
if (_otherList.isEmpty() || _otherList.back()->type() != HistoryItemGroup) {
|
||||
_otherList.push_back(regItem(new HistoryGroup(this, 0, d, _otherList.isEmpty() ? date(d.vdate) : _otherList.back()->date)));
|
||||
} else {
|
||||
static_cast<HistoryGroup*>(_otherList.back())->uniteWith(d.vmin_id.v, d.vmax_id.v, d.vcount.v);
|
||||
}
|
||||
}
|
||||
|
||||
if (onlyImportant()) {
|
||||
if (newLoaded) {
|
||||
HistoryItem *prev = blocks.isEmpty() ? 0 : blocks.back()->items.back();
|
||||
HistoryBlock *to = 0;
|
||||
bool newBlock = blocks.isEmpty();
|
||||
if (newBlock) {
|
||||
to = new HistoryBlock(this);
|
||||
to->y = height;
|
||||
} else {
|
||||
to = blocks.back();
|
||||
height -= to->height;
|
||||
}
|
||||
prev = addMessageGroupAfterPrevToBlock(d, prev, to);
|
||||
height += to->height;
|
||||
if (newBlock) {
|
||||
HistoryBlock *dateBlock = new HistoryBlock(this);
|
||||
HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, blocks.front()->items.front()->date);
|
||||
dateBlock->items.push_back(dayItem);
|
||||
int32 dh = dayItem->resize(width);
|
||||
dateBlock->height = dh;
|
||||
for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) {
|
||||
(*i)->y += dh;
|
||||
}
|
||||
blocks.push_front(dateBlock); // date block
|
||||
height += dh;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setNotLoadedAtBottom();
|
||||
}
|
||||
}
|
||||
|
||||
HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
|
||||
if (_joinedMessage || peer->asChannel()->haveLeft() || peer->asChannel()->wasKicked()) return _joinedMessage;
|
||||
|
||||
UserData *inviter = (peer->asChannel()->inviter > 0) ? App::userLoaded(peer->asChannel()->inviter) : 0;
|
||||
if (!inviter) return 0;
|
||||
|
||||
int32 flags = (unread ? MTPDmessage_flag_unread : 0);
|
||||
QDateTime inviteDate = peer->asChannel()->inviteDate;
|
||||
if (unread) _maxReadMessageDate = inviteDate;
|
||||
if (isEmpty()) {
|
||||
HistoryBlock *to = new HistoryBlock(this);
|
||||
bool newBlock = true;
|
||||
_joinedMessage = new HistoryJoined(this, to, inviteDate, inviter, flags);
|
||||
if (!addNewItem(to, newBlock, regItem(_joinedMessage), unread)) {
|
||||
_joinedMessage = 0;
|
||||
}
|
||||
return _joinedMessage;
|
||||
}
|
||||
HistoryItem *lastSeenDateItem = 0;
|
||||
for (int32 blockIndex = blocks.size(); blockIndex > 1;) {
|
||||
HistoryBlock *block = blocks.at(--blockIndex);
|
||||
for (int32 itemIndex = block->items.size(); itemIndex > 0;) {
|
||||
HistoryItem *item = block->items.at(--itemIndex);
|
||||
HistoryItemType type = item->type();
|
||||
if (type == HistoryItemMsg || type == HistoryItemGroup) {
|
||||
if (item->date <= inviteDate) {
|
||||
++itemIndex;
|
||||
if (item->date.date() != inviteDate.date()) {
|
||||
HistoryDateMsg *joinedDateItem = new HistoryDateMsg(this, block, inviteDate.date());
|
||||
if (addNewInTheMiddle(joinedDateItem, blockIndex, itemIndex)) {
|
||||
++itemIndex;
|
||||
}
|
||||
}
|
||||
_joinedMessage = new HistoryJoined(this, block, inviteDate, inviter, flags);
|
||||
if (!addNewInTheMiddle(_joinedMessage, blockIndex, itemIndex)) {
|
||||
_joinedMessage = 0;
|
||||
}
|
||||
if (lastSeenDateItem && lastSeenDateItem->date.date() == inviteDate.date()) {
|
||||
lastSeenDateItem->destroy();
|
||||
}
|
||||
if (!lastMsgDate.isNull() && inviteDate >= lastMsgDate) {
|
||||
setLastMessage(_joinedMessage);
|
||||
if (unread) {
|
||||
newItemAdded(_joinedMessage);
|
||||
}
|
||||
}
|
||||
return _joinedMessage;
|
||||
} else {
|
||||
lastSeenDateItem = 0;
|
||||
}
|
||||
} else if (type == HistoryItemDate) {
|
||||
lastSeenDateItem = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adding new item to new block
|
||||
int32 addToH = 0, skip = 0;
|
||||
if (!blocks.isEmpty()) { // remove date block
|
||||
if (width) addToH = -blocks.front()->height;
|
||||
delete blocks.front();
|
||||
blocks.pop_front();
|
||||
}
|
||||
HistoryItem *till = blocks.isEmpty() ? 0 : blocks.front()->items.front();
|
||||
|
||||
HistoryBlock *block = new HistoryBlock(this);
|
||||
|
||||
_joinedMessage = new HistoryJoined(this, block, inviteDate, inviter, flags);
|
||||
if (regItem(_joinedMessage)) {
|
||||
addItemAfterPrevToBlock(_joinedMessage, 0, block);
|
||||
} else {
|
||||
_joinedMessage = 0;
|
||||
}
|
||||
if (till && _joinedMessage && inviteDate.date() != till->date.date()) {
|
||||
HistoryItem *dayItem = createDayServiceMsg(this, block, till->date);
|
||||
block->items.push_back(dayItem);
|
||||
if (width) {
|
||||
dayItem->y = block->height;
|
||||
block->height += dayItem->resize(width);
|
||||
}
|
||||
}
|
||||
if (!block->items.isEmpty()) {
|
||||
blocks.push_front(block);
|
||||
if (width) {
|
||||
addToH += block->height;
|
||||
++skip;
|
||||
}
|
||||
} else {
|
||||
delete block;
|
||||
}
|
||||
if (!blocks.isEmpty()) {
|
||||
HistoryBlock *dateBlock = new HistoryBlock(this);
|
||||
HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, blocks.front()->items.front()->date);
|
||||
dateBlock->items.push_back(dayItem);
|
||||
if (width) {
|
||||
int32 dh = dayItem->resize(width);
|
||||
dateBlock->height = dh;
|
||||
if (skip) {
|
||||
blocks.front()->y += dh;
|
||||
}
|
||||
addToH += dh;
|
||||
++skip;
|
||||
}
|
||||
blocks.push_front(dateBlock); // date block
|
||||
}
|
||||
if (width && addToH) {
|
||||
for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) {
|
||||
if (skip) {
|
||||
--skip;
|
||||
} else {
|
||||
(*i)->y += addToH;
|
||||
}
|
||||
}
|
||||
height += addToH;
|
||||
}
|
||||
if (!lastMsgDate.isNull() && inviteDate >= lastMsgDate) {
|
||||
setLastMessage(_joinedMessage);
|
||||
if (unread) {
|
||||
newItemAdded(_joinedMessage);
|
||||
}
|
||||
}
|
||||
return _joinedMessage;
|
||||
}
|
||||
|
||||
void ChannelHistory::checkJoinedMessage() {
|
||||
if (_joinedMessage || peer->asChannel()->inviter <= 0) return;
|
||||
if (isEmpty()) {
|
||||
if (loadedAtTop() && loadedAtBottom()) {
|
||||
if (insertJoinedMessage(false)) {
|
||||
setLastMessage(_joinedMessage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime inviteDate = peer->asChannel()->inviteDate;
|
||||
QDateTime firstDate, lastDate;
|
||||
for (int32 blockIndex = 1, blocksCount = blocks.size(); blockIndex < blocksCount; ++blockIndex) {
|
||||
HistoryBlock *block = blocks.at(blockIndex);
|
||||
int32 itemIndex = 0, itemsCount = block->items.size();
|
||||
for (; itemIndex < itemsCount; ++itemIndex) {
|
||||
HistoryItem *item = block->items.at(itemIndex);
|
||||
HistoryItemType type = item->type();
|
||||
if (type == HistoryItemMsg || type == HistoryItemGroup) {
|
||||
firstDate = item->date;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itemIndex < itemsCount) break;
|
||||
}
|
||||
for (int32 blockIndex = blocks.size(); blockIndex > 1;) {
|
||||
HistoryBlock *block = blocks.at(--blockIndex);
|
||||
int32 itemIndex = block->items.size();
|
||||
for (; itemIndex > 0;) {
|
||||
HistoryItem *item = block->items.at(--itemIndex);
|
||||
HistoryItemType type = item->type();
|
||||
if (type == HistoryItemMsg || type == HistoryItemGroup) {
|
||||
lastDate = item->date;
|
||||
++itemIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itemIndex) break;
|
||||
}
|
||||
|
||||
if (!firstDate.isNull() && !lastDate.isNull() && (firstDate <= inviteDate || loadedAtTop()) && (lastDate > inviteDate || loadedAtBottom())) {
|
||||
if (insertJoinedMessage(false) && inviteDate >= lastDate) {
|
||||
setLastMessage(_joinedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelHistory::checkMaxReadMessageDate() {
|
||||
if (_maxReadMessageDate.isValid()) return;
|
||||
|
||||
for (int32 blockIndex = blocks.size(); blockIndex > 0;) {
|
||||
HistoryBlock *block = blocks.at(--blockIndex);
|
||||
for (int32 itemIndex = block->items.size(); itemIndex > 0;) {
|
||||
HistoryItem *item = block->items.at(--itemIndex);
|
||||
if (item->isImportant() && !item->unread()) {
|
||||
_maxReadMessageDate = item->date;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loadedAtTop()) {
|
||||
_maxReadMessageDate = date(MTP_int(peer->asChannel()->date));
|
||||
}
|
||||
}
|
||||
|
||||
const QDateTime &ChannelHistory::maxReadMessageDate() {
|
||||
return _maxReadMessageDate;
|
||||
}
|
||||
|
||||
HistoryItem *ChannelHistory::addNewChannelMessage(const MTPMessage &msg, NewMessageType type) {
|
||||
if (type == NewMessageExisting) return addToHistory(msg);
|
||||
|
||||
|
@ -559,8 +849,7 @@ HistoryItem *ChannelHistory::addNewChannelMessage(const MTPMessage &msg, NewMess
|
|||
}
|
||||
|
||||
HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageType type) {
|
||||
int32 flags = flagsFromMessage(msg);
|
||||
bool isImportant = isChannel() ? isImportantChannelMessage(flags) : true;
|
||||
bool isImportant = isChannel() ? isImportantChannelMessage(idFromMessage(msg), flagsFromMessage(msg)) : true;
|
||||
|
||||
if (!loadedAtBottom()) {
|
||||
HistoryItem *item = addToHistory(msg);
|
||||
|
@ -665,6 +954,13 @@ void ChannelHistory::switchMode() {
|
|||
_onlyImportant = !_onlyImportant;
|
||||
|
||||
lastWidth = 0;
|
||||
|
||||
checkJoinedMessage();
|
||||
}
|
||||
|
||||
void ChannelHistory::cleared() {
|
||||
_collapseMessage = 0;
|
||||
_joinedMessage = 0;
|
||||
}
|
||||
|
||||
HistoryGroup *ChannelHistory::findGroup(MsgId msgId) const { // find message group using binary search
|
||||
|
@ -790,8 +1086,10 @@ HistoryItem *ChannelHistory::findPrevItem(HistoryItem *item) const {
|
|||
}
|
||||
|
||||
void ChannelHistory::messageDetached(HistoryItem *msg) {
|
||||
if (_collapse == msg) {
|
||||
_collapse = 0;
|
||||
if (_collapseMessage == msg) {
|
||||
_collapseMessage = 0;
|
||||
} else if (_joinedMessage == msg) {
|
||||
_joinedMessage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1005,15 +1303,14 @@ void Histories::remove(const PeerId &peer) {
|
|||
}
|
||||
}
|
||||
|
||||
HistoryItem *Histories::addNewMessage(const MTPmessage &msg, NewMessageType type) {
|
||||
int32 flags = 0;
|
||||
HistoryItem *Histories::addNewMessage(const MTPMessage &msg, NewMessageType type) {
|
||||
PeerId peer = peerFromMessage(msg);
|
||||
if (!peer) return 0;
|
||||
|
||||
return findOrInsert(peer, 0, 0)->addNewMessage(msg, type);
|
||||
}
|
||||
|
||||
HistoryItem *History::createItem(HistoryBlock *block, const MTPmessage &msg, bool applyServiceAction, bool returnExisting) {
|
||||
HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, bool applyServiceAction, bool returnExisting) {
|
||||
HistoryItem *result = 0;
|
||||
|
||||
MsgId msgId = 0;
|
||||
|
@ -1227,7 +1524,7 @@ HistoryItem *History::addNewService(MsgId msgId, QDateTime date, const QString &
|
|||
return addNewItem(to, newBlock, regItem(new HistoryServiceMsg(this, to, msgId, date, text, flags, media)), newMsg);
|
||||
}
|
||||
|
||||
HistoryItem *History::addNewMessage(const MTPmessage &msg, NewMessageType type) {
|
||||
HistoryItem *History::addNewMessage(const MTPMessage &msg, NewMessageType type) {
|
||||
if (isChannel()) return asChannelHistory()->addNewChannelMessage(msg, type);
|
||||
|
||||
if (type == NewMessageExisting) return addToHistory(msg);
|
||||
|
@ -1252,7 +1549,7 @@ HistoryItem *History::addNewMessage(const MTPmessage &msg, NewMessageType type)
|
|||
return addNewItem(to, newBlock, createItem(to, msg, (type == NewMessageUnread)), (type == NewMessageUnread));
|
||||
}
|
||||
|
||||
HistoryItem *History::addToHistory(const MTPmessage &msg) {
|
||||
HistoryItem *History::addToHistory(const MTPMessage &msg) {
|
||||
return createItem(0, msg, false, true);
|
||||
}
|
||||
|
||||
|
@ -1345,20 +1642,22 @@ HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *a
|
|||
newItemAdded(adding);
|
||||
}
|
||||
|
||||
HistoryMedia *media = adding->getMedia(true);
|
||||
if (media) {
|
||||
HistoryMediaType mt = media->type();
|
||||
MediaOverviewType t = mediaToOverviewType(mt);
|
||||
if (t != OverviewCount) {
|
||||
if (mt == MediaTypeDocument && static_cast<HistoryDocument*>(media)->document()->song()) {
|
||||
addToOverview(adding, OverviewAudioDocuments);
|
||||
} else {
|
||||
addToOverview(adding, t);
|
||||
if (!isChannel() || adding->fromChannel()) {
|
||||
HistoryMedia *media = adding->getMedia(true);
|
||||
if (media) {
|
||||
HistoryMediaType mt = media->type();
|
||||
MediaOverviewType t = mediaToOverviewType(mt);
|
||||
if (t != OverviewCount) {
|
||||
if (mt == MediaTypeDocument && static_cast<HistoryDocument*>(media)->document()->song()) {
|
||||
addToOverview(adding, OverviewAudioDocuments);
|
||||
} else {
|
||||
addToOverview(adding, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (adding->hasTextLinks()) {
|
||||
addToOverview(adding, OverviewLinks);
|
||||
if (adding->hasTextLinks()) {
|
||||
addToOverview(adding, OverviewLinks);
|
||||
}
|
||||
}
|
||||
if (adding->from()->id) {
|
||||
if (peer->isChat() && adding->from()->isUser()) {
|
||||
|
@ -1374,7 +1673,7 @@ HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *a
|
|||
if (adding->hasReplyMarkup()) {
|
||||
int32 markupFlags = App::replyMarkup(channelId(), adding->id).flags;
|
||||
if (!(markupFlags & MTPDreplyKeyboardMarkup_flag_personal) || adding->notifyByFrom()) {
|
||||
if (peer->isChat()) { // CHANNELS_UX
|
||||
if (peer->isChat()) {
|
||||
peer->asChat()->markupSenders.insert(adding->from(), true);
|
||||
}
|
||||
if (markupFlags & MTPDreplyKeyboardMarkup_flag_ZERO) { // zero markup means replyKeyboardHide
|
||||
|
@ -1392,6 +1691,7 @@ HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *a
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return adding;
|
||||
}
|
||||
|
||||
|
@ -1465,7 +1765,7 @@ HistoryItem *History::addMessageGroupAfterPrev(HistoryItem *newItem, HistoryItem
|
|||
}
|
||||
|
||||
QDateTime date = prev ? prev->date : newItem->date;
|
||||
HistoryBlock *block = prev->block();
|
||||
HistoryBlock *block = prev ? prev->block() : 0;
|
||||
if (!block) {
|
||||
createInitialDateBlock(date);
|
||||
|
||||
|
@ -1479,11 +1779,16 @@ HistoryItem *History::addMessageGroupAfterPrev(HistoryItem *newItem, HistoryItem
|
|||
void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPMessageGroup> *collapsed) {
|
||||
if (slice.isEmpty()) {
|
||||
oldLoaded = true;
|
||||
if (!collapsed || collapsed->isEmpty() || !isChannel()) return;
|
||||
if (!collapsed || collapsed->isEmpty() || !isChannel()) {
|
||||
if (isChannel()) {
|
||||
asChannelHistory()->checkJoinedMessage();
|
||||
asChannelHistory()->checkMaxReadMessageDate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ChannelHistory *channel = collapsed ? asChannelHistory() : 0;
|
||||
const MTPMessageGroup *groupsBegin = channel ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = channel ? (groupsBegin + collapsed->size()) : 0;
|
||||
const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
|
||||
|
||||
int32 addToH = 0, skip = 0;
|
||||
if (!blocks.isEmpty()) { // remove date block
|
||||
|
@ -1543,10 +1848,13 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
|||
}
|
||||
|
||||
if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors
|
||||
bool channel = isChannel();
|
||||
int32 mask = 0;
|
||||
QList<UserData*> *lastAuthors = peer->isChat() ? &(peer->asChat()->lastAuthors) : 0;
|
||||
for (int32 i = block->items.size(); i > 0; --i) {
|
||||
HistoryItem *item = block->items[i - 1];
|
||||
if (channel && !item->fromChannel()) continue;
|
||||
|
||||
HistoryMedia *media = item->getMedia(true);
|
||||
if (media) {
|
||||
HistoryMediaType mt = media->type();
|
||||
|
@ -1635,16 +1943,25 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
|||
}
|
||||
height += addToH;
|
||||
}
|
||||
|
||||
if (isChannel()) {
|
||||
asChannelHistory()->checkJoinedMessage();
|
||||
asChannelHistory()->checkMaxReadMessageDate();
|
||||
}
|
||||
if (newLoaded && !lastMsg) setLastMessage(lastImportantMessage());
|
||||
}
|
||||
|
||||
void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPMessageGroup> *collapsed) {
|
||||
if (slice.isEmpty()) {
|
||||
newLoaded = true;
|
||||
if (!collapsed || collapsed->isEmpty() || !isChannel()) return;
|
||||
if (!lastMsg) setLastMessage(lastImportantMessage());
|
||||
if (!collapsed || collapsed->isEmpty() || !isChannel()) {
|
||||
if (isChannel()) asChannelHistory()->checkJoinedMessage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ChannelHistory *channel = collapsed ? asChannelHistory() : 0;
|
||||
const MTPMessageGroup *groupsBegin = channel ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = channel ? (groupsBegin + collapsed->size()) : 0;
|
||||
const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
|
||||
|
||||
bool wasEmpty = isEmpty();
|
||||
|
||||
|
@ -1681,7 +1998,7 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
|||
height += block->height;
|
||||
} else {
|
||||
newLoaded = true;
|
||||
fixLastMessage(true);
|
||||
setLastMessage(lastImportantMessage());
|
||||
delete block;
|
||||
}
|
||||
if (!wasLoadedAtBottom && loadedAtBottom()) { // add all loaded photos to overview
|
||||
|
@ -1694,10 +2011,13 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
|||
mask |= (1 << i);
|
||||
}
|
||||
}
|
||||
bool channel = isChannel();
|
||||
for (int32 i = 0; i < blocks.size(); ++i) {
|
||||
HistoryBlock *b = blocks[i];
|
||||
for (int32 j = 0; j < b->items.size(); ++j) {
|
||||
HistoryItem *item = b->items[j];
|
||||
if (channel && !item->fromChannel()) continue;
|
||||
|
||||
HistoryMedia *media = item->getMedia(true);
|
||||
if (media) {
|
||||
HistoryMediaType mt = media->type();
|
||||
|
@ -1745,6 +2065,8 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
|
|||
blocks.push_front(dateBlock); // date block
|
||||
height += dh;
|
||||
}
|
||||
|
||||
if (isChannel()) asChannelHistory()->checkJoinedMessage();
|
||||
}
|
||||
|
||||
int32 History::countUnread(MsgId upTo) {
|
||||
|
@ -1896,13 +2218,13 @@ HistoryItem *History::addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex,
|
|||
if (!regItem(newItem)) {
|
||||
return 0;
|
||||
}
|
||||
if (blockIndex < 0 || itemIndex < 0 || blockIndex >= blocks.size() || itemIndex >= blocks.at(blockIndex)->items.size()) {
|
||||
if (blockIndex < 0 || itemIndex < 0 || blockIndex >= blocks.size() || itemIndex > blocks.at(blockIndex)->items.size()) {
|
||||
delete newItem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HistoryBlock *block = blocks.at(blockIndex);
|
||||
newItem->y = block->items.at(itemIndex)->y;
|
||||
newItem->y = (itemIndex < block->items.size()) ? block->items.at(itemIndex)->y : block->height;
|
||||
block->items.insert(itemIndex, newItem);
|
||||
|
||||
if (width) {
|
||||
|
@ -1977,26 +2299,32 @@ inline uint64 dialogPosFromDate(const QDateTime &date) {
|
|||
return (uint64(date.toTime_t()) << 32) | (++_dialogsPosToTopShift);
|
||||
}
|
||||
|
||||
void History::setLastMessage(HistoryItem *msg, bool updatePosInDialogs) {
|
||||
void History::setLastMessage(HistoryItem *msg) {
|
||||
if (msg) {
|
||||
if (!lastMsg) Local::removeSavedPeer(peer);
|
||||
lastMsg = msg;
|
||||
if (updatePosInDialogs) setPosInDialogsDate(msg->date);
|
||||
setPosInDialogsDate(msg->date);
|
||||
} else {
|
||||
lastMsg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void History::setPosInDialogsDate(const QDateTime &date) {
|
||||
bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amCreator() || (!peer->asChannel()->haveLeft() && !peer->asChannel()->wasKicked())));
|
||||
if (!lastMsgDate.isNull() && lastMsgDate >= date) {
|
||||
if (!updateDialog || !dialogs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastMsgDate = date;
|
||||
posInDialogs = dialogPosFromDate(lastMsgDate);
|
||||
if (App::main()) {
|
||||
App::main()->createDialogAtTop(this, unreadCount);
|
||||
if (updateDialog) {
|
||||
App::main()->createDialog(this);
|
||||
}
|
||||
}
|
||||
|
||||
void History::fixLastMessage(bool wasAtBottom) {
|
||||
setLastMessage(wasAtBottom ? lastImportantMessage() : 0, false);
|
||||
setLastMessage(wasAtBottom ? lastImportantMessage() : 0);
|
||||
}
|
||||
|
||||
MsgId History::minMsgId() const {
|
||||
|
@ -2099,6 +2427,8 @@ void History::clear(bool leaveItems) {
|
|||
if (peer->isChat()) {
|
||||
peer->asChat()->lastAuthors.clear();
|
||||
peer->asChat()->markupSenders.clear();
|
||||
} else if (isChannel()) {
|
||||
asChannelHistory()->cleared();
|
||||
}
|
||||
if (leaveItems && App::main()) App::main()->historyCleared(this);
|
||||
}
|
||||
|
@ -5724,11 +6054,30 @@ HistoryItem(history, block, msgId, flags, date, from)
|
|||
setText(QString(), LinksInText());
|
||||
}
|
||||
|
||||
QString formatViewsCount(int32 views) {
|
||||
if (views > 999999) {
|
||||
views /= 100000;
|
||||
if (views % 10) {
|
||||
return QString::number(views / 10) + '.' + QString::number(views % 10) + 'M';
|
||||
}
|
||||
return QString::number(views / 10) + 'M';
|
||||
} else if (views > 9999) {
|
||||
views /= 100;
|
||||
if (views % 10) {
|
||||
return QString::number(views / 10) + '.' + QString::number(views % 10) + 'K';
|
||||
}
|
||||
return QString::number(views / 10) + 'K';
|
||||
} else if (views > 0) {
|
||||
return QString::number(views);
|
||||
}
|
||||
return qsl("1");
|
||||
}
|
||||
|
||||
void HistoryMessage::initTime() {
|
||||
_timeText = date.toString(cTimeFormat());// + qsl(" (%1)").arg(id);
|
||||
_timeText = date.toString(cTimeFormat());
|
||||
_timeWidth = st::msgDateFont->m.width(_timeText);
|
||||
|
||||
_viewsText = (_views >= 0) ? QString::number(_views ? _views : 1) : QString();
|
||||
_viewsText = (_views >= 0) ? formatViewsCount(_views) : QString();
|
||||
_viewsWidth = _viewsText.isEmpty() ? 0 : st::msgDateFont->m.width(_viewsText);
|
||||
}
|
||||
|
||||
|
@ -5999,7 +6348,7 @@ void HistoryMessage::setViewsCount(int32 count) {
|
|||
|
||||
int32 was = _viewsWidth;
|
||||
_views = count;
|
||||
_viewsText = (_views >= 0) ? QString::number(_views ? _views : 1) : QString();
|
||||
_viewsText = (_views >= 0) ? formatViewsCount(_views) : QString();
|
||||
_viewsWidth = _viewsText.isEmpty() ? 0 : st::msgDateFont->m.width(_viewsText);
|
||||
if (was == _viewsWidth) {
|
||||
if (App::main()) App::main()->msgUpdated(history()->peer->id, this);
|
||||
|
@ -6366,7 +6715,7 @@ HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, const
|
|||
fwdNameUpdated();
|
||||
}
|
||||
|
||||
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, QDateTime date, int32 from, HistoryMessage *msg) : HistoryMessage(history, block, id, newMessageFlags(history->peer) | (msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), date, from, msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->HistoryMessage::textLinks(), msg->getMedia())
|
||||
HistoryForwarded::HistoryForwarded(History *history, HistoryBlock *block, MsgId id, QDateTime date, int32 from, HistoryMessage *msg) : HistoryMessage(history, block, id, newMessageFlags(history->peer) | (!history->peer->isChannel() && msg->getMedia() && (msg->getMedia()->type() == MediaTypeAudio/* || msg->getMedia()->type() == MediaTypeVideo*/) ? MTPDmessage_flag_media_unread : 0), date, from, msg->justMedia() ? QString() : msg->HistoryMessage::selectedText(FullItemSel), msg->HistoryMessage::textLinks(), msg->getMedia())
|
||||
, fwdDate(msg->dateForwarded())
|
||||
, fwdFrom(msg->fromForwarded())
|
||||
, fwdFromVersion(fwdFrom->nameVersion)
|
||||
|
@ -7211,6 +7560,8 @@ void HistoryGroup::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x
|
|||
}
|
||||
|
||||
void HistoryGroup::uniteWith(MsgId minId, MsgId maxId, int32 count) {
|
||||
if (minId < 0 || maxId < 0) return;
|
||||
|
||||
if (minId == _minId && maxId == _maxId && count == _count) return;
|
||||
|
||||
if (minId < _minId) {
|
||||
|
@ -7265,6 +7616,16 @@ void HistoryCollapse::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3
|
|||
state = HistoryDefaultCursorState;
|
||||
}
|
||||
|
||||
HistoryJoined::HistoryJoined(History *history, HistoryBlock *block, const QDateTime &inviteDate, UserData *inviter, int32 flags) :
|
||||
HistoryServiceMsg(history, block, clientMsgId(), inviteDate, QString(), flags) {
|
||||
if (inviter->id == MTP::authedId()) {
|
||||
_text.setText(st::msgServiceFont, lang(lng_action_you_joined), _historySrvOptions);
|
||||
} else {
|
||||
_text.setText(st::msgServiceFont, lng_action_add_you(lt_from, textcmdLink(1, inviter->name)), _historySrvOptions);
|
||||
_text.setLink(1, TextLinkPtr(new PeerLink(inviter)));
|
||||
}
|
||||
}
|
||||
|
||||
HistoryUnreadBar::HistoryUnreadBar(History *history, HistoryBlock *block, int32 count, const QDateTime &date) : HistoryItem(history, block, clientMsgId(), 0, date, 0), freezed(false) {
|
||||
setCount(count);
|
||||
initDimensions();
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
unreadFull = unreadMuted = 0;
|
||||
}
|
||||
|
||||
HistoryItem *addNewMessage(const MTPmessage &msg, NewMessageType type);
|
||||
HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type);
|
||||
// HistoryItem *addToBack(const MTPgeoChatMessage &msg, bool newMsg = true);
|
||||
|
||||
typedef QMap<History*, uint64> TypingHistories; // when typing in this history started
|
||||
|
@ -193,13 +193,13 @@ public:
|
|||
clear();
|
||||
}
|
||||
|
||||
HistoryItem *createItem(HistoryBlock *block, const MTPmessage &msg, bool applyServiceAction, bool returnExisting = false);
|
||||
HistoryItem *createItem(HistoryBlock *block, const MTPMessage &msg, bool applyServiceAction, bool returnExisting = false);
|
||||
HistoryItem *createItemForwarded(HistoryBlock *block, MsgId id, QDateTime date, int32 from, HistoryMessage *msg);
|
||||
HistoryItem *createItemDocument(HistoryBlock *block, MsgId id, int32 flags, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc);
|
||||
|
||||
HistoryItem *addNewService(MsgId msgId, QDateTime date, const QString &text, int32 flags = 0, HistoryMedia *media = 0, bool newMsg = true);
|
||||
HistoryItem *addNewMessage(const MTPmessage &msg, NewMessageType type);
|
||||
HistoryItem *addToHistory(const MTPmessage &msg);
|
||||
HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type);
|
||||
HistoryItem *addToHistory(const MTPMessage &msg);
|
||||
HistoryItem *addNewForwarded(MsgId id, QDateTime date, int32 from, HistoryMessage *item);
|
||||
HistoryItem *addNewDocument(MsgId id, int32 flags, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc);
|
||||
|
||||
|
@ -232,7 +232,7 @@ public:
|
|||
bool isReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop); // has messages for showing history at msgId
|
||||
void getReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop);
|
||||
|
||||
void setLastMessage(HistoryItem *msg, bool updatePosInDialogs = true);
|
||||
void setLastMessage(HistoryItem *msg);
|
||||
void setPosInDialogsDate(const QDateTime &date);
|
||||
void fixLastMessage(bool wasAtBottom);
|
||||
|
||||
|
@ -355,6 +355,7 @@ private:
|
|||
|
||||
class HistoryGroup;
|
||||
class HistoryCollapse;
|
||||
class HistoryJoined;
|
||||
class ChannelHistory : public History {
|
||||
public:
|
||||
|
||||
|
@ -368,6 +369,10 @@ public:
|
|||
void getSwitchReadyFor(MsgId switchId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop);
|
||||
|
||||
void insertCollapseItem(MsgId wasMinId);
|
||||
void getRangeDifference();
|
||||
void getRangeDifferenceNext(int32 pts);
|
||||
|
||||
void addNewGroup(const MTPMessageGroup &group);
|
||||
|
||||
int32 unreadCountAll;
|
||||
bool onlyImportant() const {
|
||||
|
@ -375,7 +380,7 @@ public:
|
|||
}
|
||||
|
||||
HistoryCollapse *collapse() const {
|
||||
return _collapse;
|
||||
return _collapseMessage;
|
||||
}
|
||||
|
||||
void clearOther() {
|
||||
|
@ -384,6 +389,10 @@ public:
|
|||
_otherList.clear();
|
||||
}
|
||||
|
||||
HistoryJoined *insertJoinedMessage(bool unread);
|
||||
void checkJoinedMessage();
|
||||
const QDateTime &maxReadMessageDate();
|
||||
|
||||
private:
|
||||
|
||||
friend class History;
|
||||
|
@ -391,19 +400,30 @@ private:
|
|||
HistoryItem *addNewToBlocks(const MTPMessage &msg, NewMessageType type);
|
||||
void addNewToOther(HistoryItem *item, NewMessageType type);
|
||||
|
||||
void checkMaxReadMessageDate();
|
||||
|
||||
HistoryGroup *findGroup(MsgId msgId) const;
|
||||
HistoryBlock *findGroupBlock(MsgId msgId) const;
|
||||
HistoryGroup *findGroupInOther(MsgId msgId) const;
|
||||
HistoryItem *findPrevItem(HistoryItem *item) const;
|
||||
void switchMode();
|
||||
|
||||
void cleared();
|
||||
|
||||
bool _onlyImportant;
|
||||
|
||||
QDateTime _maxReadMessageDate;
|
||||
|
||||
typedef QList<HistoryItem*> OtherList;
|
||||
OtherList _otherList;
|
||||
bool _otherOldLoaded, _otherNewLoaded;
|
||||
|
||||
HistoryCollapse *_collapse;
|
||||
HistoryCollapse *_collapseMessage;
|
||||
HistoryJoined *_joinedMessage;
|
||||
|
||||
void switchMode();
|
||||
MsgId _rangeDifferenceFromId, _rangeDifferenceToId;
|
||||
int32 _rangeDifferencePts;
|
||||
mtpRequestId _rangeDifferenceRequestId;
|
||||
|
||||
};
|
||||
|
||||
|
@ -755,9 +775,8 @@ enum InfoDisplayType {
|
|||
InfoDisplayOverImage,
|
||||
};
|
||||
|
||||
inline bool isImportantChannelMessage(int32 flags) {
|
||||
/**/
|
||||
return (flags & MTPDmessage_flag_out) || (flags & MTPDmessage_flag_notify_by_from) || (!(flags & MTPDmessage::flag_from_id) && (flags != 0)); // always has_from_id || has_views
|
||||
inline bool isImportantChannelMessage(MsgId id, int32 flags) { // client-side important msgs always has_views or has_from_id
|
||||
return (flags & MTPDmessage_flag_out) || (flags & MTPDmessage_flag_notify_by_from) || ((id > 0 || flags != 0) && !(flags & MTPDmessage::flag_from_id));
|
||||
}
|
||||
|
||||
enum HistoryItemType {
|
||||
|
@ -765,7 +784,8 @@ enum HistoryItemType {
|
|||
HistoryItemDate,
|
||||
HistoryItemUnreadBar,
|
||||
HistoryItemGroup,
|
||||
HistoryItemCollapse
|
||||
HistoryItemCollapse,
|
||||
HistoryItemJoined
|
||||
};
|
||||
|
||||
class HistoryMedia;
|
||||
|
@ -813,7 +833,7 @@ public:
|
|||
return _flags & MTPDmessage_flag_notify_by_from;
|
||||
}
|
||||
bool isMediaUnread() const {
|
||||
return (_flags & MTPDmessage_flag_media_unread) && (channelId() == NoChannel); // CHANNELS_UI
|
||||
return (_flags & MTPDmessage_flag_media_unread) && (channelId() == NoChannel);
|
||||
}
|
||||
void markMediaRead() {
|
||||
_flags &= ~MTPDmessage_flag_media_unread;
|
||||
|
@ -824,11 +844,14 @@ public:
|
|||
bool hasTextLinks() const {
|
||||
return _flags & MTPDmessage_flag_HAS_TEXT_LINKS;
|
||||
}
|
||||
bool hasViews() const {
|
||||
return _flags & MTPDmessage::flag_views;
|
||||
}
|
||||
bool fromChannel() const {
|
||||
return _from->isChannel();
|
||||
}
|
||||
bool isImportant() const {
|
||||
return _history->isChannel() && isImportantChannelMessage(_flags);
|
||||
return _history->isChannel() && isImportantChannelMessage(id, _flags);
|
||||
}
|
||||
virtual bool needCheck() const {
|
||||
return out();
|
||||
|
@ -877,6 +900,19 @@ public:
|
|||
}
|
||||
virtual QString notificationText() const = 0;
|
||||
|
||||
bool canDelete() const {
|
||||
ChannelData *channel = _history->peer->asChannel();
|
||||
if (!channel) return true;
|
||||
|
||||
if (id == 1) return false;
|
||||
if (channel->amCreator()) return true;
|
||||
if (fromChannel()) {
|
||||
if (channel->amEditor() && out()) return true;
|
||||
return false;
|
||||
}
|
||||
return (channel->amEditor() || channel->amModerator() || out());
|
||||
}
|
||||
|
||||
int32 y;
|
||||
MsgId id;
|
||||
QDateTime date;
|
||||
|
@ -1811,6 +1847,15 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class HistoryJoined : public HistoryServiceMsg {
|
||||
public:
|
||||
|
||||
HistoryJoined(History *history, HistoryBlock *block, const QDateTime &date, UserData *from, int32 flags);
|
||||
HistoryItemType type() const {
|
||||
return HistoryItemJoined;
|
||||
}
|
||||
};
|
||||
|
||||
HistoryItem *createDayServiceMsg(History *history, HistoryBlock *block, QDateTime date);
|
||||
|
||||
class HistoryUnreadBar : public HistoryItem {
|
||||
|
|
|
@ -96,6 +96,8 @@ void HistoryList::updateMsg(const HistoryItem *msg) {
|
|||
}
|
||||
|
||||
void HistoryList::paintEvent(QPaintEvent *e) {
|
||||
if (!App::main()) return;
|
||||
|
||||
QRect r(e->rect());
|
||||
bool trivial = (rect() == r);
|
||||
|
||||
|
@ -151,6 +153,11 @@ void HistoryList::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
item->draw(p, sel);
|
||||
|
||||
if (item->hasViews()) {
|
||||
App::main()->scheduleViewIncrement(item);
|
||||
}
|
||||
|
||||
p.translate(0, h);
|
||||
++iItem;
|
||||
if (iItem == block->items.size()) {
|
||||
|
@ -822,7 +829,7 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
if (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem()) && App::hoveredLinkItem()->id > 0) {
|
||||
_menu->addAction(lang(lng_context_forward_msg), historyWidget, SLOT(forwardMessage()))->setEnabled(true);
|
||||
}
|
||||
if ((!hist->peer->isChannel() || hist->peer->asChannel()->adminned || App::hoveredLinkItem()->out())) {
|
||||
if (App::hoveredLinkItem()->canDelete()) {
|
||||
_menu->addAction(lang(lng_context_delete_msg), historyWidget, SLOT(deleteMessage()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
@ -832,7 +839,7 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
App::contextItem(App::hoveredLinkItem());
|
||||
}
|
||||
} else { // maybe cursor on some text history item?
|
||||
bool canDelete = (item && item->type() == HistoryItemMsg) && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned || item->out());
|
||||
bool canDelete = (item && item->type() == HistoryItemMsg) && item->canDelete();
|
||||
bool canForward = (item && item->type() == HistoryItemMsg) && (item->id > 0) && !item->serviceMsg();
|
||||
|
||||
HistoryMessage *msg = dynamic_cast<HistoryMessage*>(item);
|
||||
|
@ -1322,9 +1329,7 @@ void HistoryList::getSelectionState(int32 &selectedForForward, int32 &selectedFo
|
|||
selectedForForward = selectedForDelete = 0;
|
||||
for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
|
||||
if (i.key()->type() == HistoryItemMsg && i.value() == FullItemSel) {
|
||||
if (!hist || !hist->peer || !hist->peer->isChannel() || hist->peer->asChannel()->adminned) {
|
||||
++selectedForDelete;
|
||||
} else if (i.key()->out()) {
|
||||
if (i.key()->canDelete()) {
|
||||
++selectedForDelete;
|
||||
}
|
||||
++selectedForForward;
|
||||
|
@ -1710,9 +1715,10 @@ void ReportSpamPanel::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
void ReportSpamPanel::setReported(bool reported) {
|
||||
void ReportSpamPanel::setReported(bool reported, PeerData *onPeer) {
|
||||
if (reported) {
|
||||
_report.hide();
|
||||
_clear.setText(lang(onPeer->isChannel() ? lng_profile_leave_channel : lng_profile_delete_conversation));
|
||||
_clear.show();
|
||||
} else {
|
||||
_report.show();
|
||||
|
@ -2321,6 +2327,8 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
, _send(this, lang(lng_send_button), st::btnSend)
|
||||
, _unblock(this, lang(lng_unblock_button), st::btnUnblock)
|
||||
, _botStart(this, lang(lng_bot_start), st::btnSend)
|
||||
, _joinChannel(this, lang(lng_channel_join), st::btnSend)
|
||||
, _muteUnmute(this, lang(lng_channel_mute), st::btnSend)
|
||||
, _unblockRequest(0)
|
||||
, _reportSpamRequest(0)
|
||||
, _attachDocument(this, st::btnAttachDocument)
|
||||
|
@ -2372,6 +2380,9 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
|
||||
connect(&_unblock, SIGNAL(clicked()), this, SLOT(onUnblock()));
|
||||
connect(&_botStart, SIGNAL(clicked()), this, SLOT(onBotStart()));
|
||||
connect(&_joinChannel, SIGNAL(clicked()), this, SLOT(onJoinChannel()));
|
||||
connect(&_muteUnmute, SIGNAL(clicked()), this, SLOT(onMuteUnmute()));
|
||||
connect(&_broadcast, SIGNAL(changed()), this, SLOT(onBroadcastChange()));
|
||||
connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
|
||||
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
|
||||
connect(&_field, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
||||
|
@ -2439,6 +2450,8 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
_send.hide();
|
||||
_unblock.hide();
|
||||
_botStart.hide();
|
||||
_joinChannel.hide();
|
||||
_muteUnmute.hide();
|
||||
|
||||
_reportSpamPanel.move(0, 0);
|
||||
_reportSpamPanel.hide();
|
||||
|
@ -2486,7 +2499,9 @@ void HistoryWidget::onMentionHashtagOrBotCommandInsert(QString str) {
|
|||
}
|
||||
|
||||
void HistoryWidget::onTextChange() {
|
||||
updateSendAction(_history, SendActionTyping);
|
||||
if (_peer && (!_peer->isChannel() || !_peer->asChannel()->canPublish() || (!_peer->asChannel()->isBroadcast() && !_broadcast.checked()))) {
|
||||
updateSendAction(_history, SendActionTyping);
|
||||
}
|
||||
|
||||
if (cHasAudioCapture()) {
|
||||
if (!_field.hasSendText() && !readyToForward()) {
|
||||
|
@ -2640,7 +2655,7 @@ void HistoryWidget::onRecordDone(QByteArray result, qint32 samples) {
|
|||
|
||||
App::wnd()->activateWindow();
|
||||
int32 duration = samples / AudioVoiceMsgFrequency;
|
||||
_imageLoader.append(result, duration, _peer->id, replyToId(), ToPrepareAudio);
|
||||
_imageLoader.append(result, duration, _peer->id, _broadcast.checked(), replyToId(), ToPrepareAudio);
|
||||
cancelReply(lastForceReplyReplied());
|
||||
}
|
||||
|
||||
|
@ -2656,7 +2671,9 @@ void HistoryWidget::onRecordUpdate(qint16 level, qint32 samples) {
|
|||
stopRecording(_peer && samples > 0 && _inField);
|
||||
}
|
||||
updateField();
|
||||
updateSendAction(_history, SendActionRecordAudio);
|
||||
if (_peer && (!_peer->isChannel() || !_peer->asChannel()->canPublish() || (!_peer->asChannel()->isBroadcast() && !_broadcast.checked()))) {
|
||||
updateSendAction(_history, SendActionRecordAudio);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::updateStickers() {
|
||||
|
@ -2872,7 +2889,9 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
|
|||
update();
|
||||
return;
|
||||
}
|
||||
if (_history->mySendActions.contains(SendActionTyping)) updateSendAction(_history, SendActionTyping, -1);
|
||||
if (_history->mySendActions.contains(SendActionTyping)) {
|
||||
updateSendAction(_history, SendActionTyping, -1);
|
||||
}
|
||||
}
|
||||
|
||||
stopGif();
|
||||
|
@ -2926,6 +2945,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
|
|||
_peer = peerId ? App::peer(peerId) : 0;
|
||||
_channel = _peer ? peerToChannel(_peer->id) : NoChannel;
|
||||
_canSendMessages = canSendMessages(_peer);
|
||||
if (_peer && _peer->isChannel()) _peer->asChannel()->updateFull();
|
||||
|
||||
_unblockRequest = _reportSpamRequest = 0;
|
||||
|
||||
|
@ -2954,6 +2974,8 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
|
|||
}
|
||||
_history = App::history(_peer->id);
|
||||
|
||||
if (_channel) updateNotifySettings();
|
||||
|
||||
if (_showAtMsgId == ShowAtUnreadMsgId) {
|
||||
if (_history->lastWidth) {
|
||||
_showAtMsgId = _history->lastShowAtMsgId;
|
||||
|
@ -3055,6 +3077,12 @@ void HistoryWidget::ctrlEnterSubmitUpdated() {
|
|||
_field.setCtrlEnterSubmit(cCtrlEnter());
|
||||
}
|
||||
|
||||
void HistoryWidget::updateNotifySettings() {
|
||||
if (!_peer || !_peer->isChannel()) return;
|
||||
|
||||
_muteUnmute.setText(lang(_history->mute ? lng_channel_unmute : lng_channel_mute));
|
||||
}
|
||||
|
||||
void HistoryWidget::updateReportSpamStatus() {
|
||||
if (!_peer || (_peer->isUser() && (peerToUser(_peer->id) == MTP::authedId() || isNotificationsUser(_peer->id) || isServiceUser(_peer->id) || _peer->asUser()->botInfo))) {
|
||||
_reportSpamStatus = dbiprsNoButton;
|
||||
|
@ -3063,7 +3091,7 @@ void HistoryWidget::updateReportSpamStatus() {
|
|||
ReportSpamStatuses::const_iterator i = cReportSpamStatuses().constFind(_peer->id);
|
||||
if (i != cReportSpamStatuses().cend()) {
|
||||
_reportSpamStatus = i.value();
|
||||
_reportSpamPanel.setReported(_reportSpamStatus == dbiprsReportSent);
|
||||
_reportSpamPanel.setReported(_reportSpamStatus == dbiprsReportSent, _peer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -3105,10 +3133,21 @@ void HistoryWidget::updateReportSpamStatus() {
|
|||
_reportSpamStatus = dbiprsNoButton;
|
||||
}
|
||||
} else if (_peer->isChannel()) {
|
||||
_reportSpamStatus = dbiprsUnknown;
|
||||
if (!_peer->asChannel()->inviter || _history->asChannelHistory()->maxReadMessageDate().isNull()) {
|
||||
_reportSpamStatus = dbiprsUnknown;
|
||||
} else if (_peer->asChannel()->inviter > 0) {
|
||||
UserData *user = App::userLoaded(_peer->asChannel()->inviter);
|
||||
if ((user && user->contact > 0) || (_peer->asChannel()->inviter == MTP::authedId()) || _history->asChannelHistory()->maxReadMessageDate() > _peer->asChannel()->inviteDate) {
|
||||
_reportSpamStatus = dbiprsNoButton;
|
||||
} else {
|
||||
_reportSpamStatus = dbiprsShowButton;
|
||||
}
|
||||
} else {
|
||||
_reportSpamStatus = dbiprsNoButton;
|
||||
}
|
||||
}
|
||||
if (_reportSpamStatus == dbiprsShowButton || _reportSpamStatus == dbiprsNoButton) {
|
||||
_reportSpamPanel.setReported(false);
|
||||
_reportSpamPanel.setReported(false, _peer);
|
||||
cRefReportSpamStatuses().insert(_peer->id, _reportSpamStatus);
|
||||
Local::writeReportSpamStatuses();
|
||||
}
|
||||
|
@ -3122,6 +3161,8 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_send.hide();
|
||||
_unblock.hide();
|
||||
_botStart.hide();
|
||||
_joinChannel.hide();
|
||||
_muteUnmute.hide();
|
||||
_attachMention.hide();
|
||||
_field.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
|
@ -3150,33 +3191,64 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
} else {
|
||||
_reportSpamPanel.hide();
|
||||
}
|
||||
if (_canSendMessages) {
|
||||
checkMentionDropdown();
|
||||
if (isBlocked() || isJoinChannel() || isMuteUnmute()) {
|
||||
if (isBlocked()) {
|
||||
_botStart.hide();
|
||||
_joinChannel.hide();
|
||||
_muteUnmute.hide();
|
||||
if (_unblock.isHidden()) {
|
||||
_unblock.clearState();
|
||||
_unblock.show();
|
||||
_kbShown = false;
|
||||
}
|
||||
_send.hide();
|
||||
_field.hide();
|
||||
_attachEmoji.hide();
|
||||
_kbShow.hide();
|
||||
_kbHide.hide();
|
||||
_cmdStart.hide();
|
||||
_attachDocument.hide();
|
||||
_attachPhoto.hide();
|
||||
_broadcast.hide();
|
||||
_kbScroll.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
} else if (isBotStart()) {
|
||||
} else if (isJoinChannel()) {
|
||||
_unblock.hide();
|
||||
if (_botStart.isHidden()) {
|
||||
_botStart.clearState();
|
||||
_botStart.show();
|
||||
_kbShown = false;
|
||||
_muteUnmute.hide();
|
||||
if (_joinChannel.isHidden()) {
|
||||
_joinChannel.clearState();
|
||||
_joinChannel.show();
|
||||
}
|
||||
} else if (isMuteUnmute()) {
|
||||
_unblock.hide();
|
||||
_joinChannel.hide();
|
||||
if (_muteUnmute.isHidden()) {
|
||||
_muteUnmute.clearState();
|
||||
_muteUnmute.show();
|
||||
}
|
||||
}
|
||||
_kbShown = false;
|
||||
_attachMention.hide();
|
||||
_send.hide();
|
||||
_botStart.hide();
|
||||
_attachDocument.hide();
|
||||
_attachPhoto.hide();
|
||||
_broadcast.hide();
|
||||
_kbScroll.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_attachDocument.hide();
|
||||
_attachPhoto.hide();
|
||||
_attachEmoji.hide();
|
||||
_kbShow.hide();
|
||||
_kbHide.hide();
|
||||
_cmdStart.hide();
|
||||
_attachType.hide();
|
||||
_emojiPan.hide();
|
||||
if (!_field.isHidden()) {
|
||||
_field.hide();
|
||||
resizeEvent(0);
|
||||
update();
|
||||
}
|
||||
} else if (_canSendMessages) {
|
||||
checkMentionDropdown();
|
||||
if (isBotStart()) {
|
||||
if (isBotStart()) {
|
||||
_unblock.hide();
|
||||
_joinChannel.hide();
|
||||
_muteUnmute.hide();
|
||||
if (_botStart.isHidden()) {
|
||||
_botStart.clearState();
|
||||
_botStart.show();
|
||||
}
|
||||
}
|
||||
_kbShown = false;
|
||||
_send.hide();
|
||||
_field.hide();
|
||||
_attachEmoji.hide();
|
||||
|
@ -3191,6 +3263,8 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
} else {
|
||||
_unblock.hide();
|
||||
_botStart.hide();
|
||||
_joinChannel.hide();
|
||||
_muteUnmute.hide();
|
||||
if (cHasAudioCapture() && !_field.hasSendText() && !readyToForward()) {
|
||||
_send.hide();
|
||||
setMouseTracking(true);
|
||||
|
@ -3255,8 +3329,10 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
}
|
||||
if (hasBroadcastToggle()) {
|
||||
_broadcast.show();
|
||||
_field.setPlaceholder(lang(_broadcast.checked() ? lng_broadcast_ph : lng_comment_ph));
|
||||
} else {
|
||||
_broadcast.hide();
|
||||
_field.setPlaceholder(lang((_history && _history->peer->isChannel()) ? (_history->peer->asChannel()->canPublish() ? lng_broadcast_ph : lng_comment_ph) : lng_message_ph));
|
||||
}
|
||||
}
|
||||
if (_replyToId || readyToForward() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) {
|
||||
|
@ -3274,6 +3350,8 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_send.hide();
|
||||
_unblock.hide();
|
||||
_botStart.hide();
|
||||
_joinChannel.hide();
|
||||
_muteUnmute.hide();
|
||||
_attachDocument.hide();
|
||||
_attachPhoto.hide();
|
||||
_broadcast.hide();
|
||||
|
@ -3337,6 +3415,12 @@ void HistoryWidget::historyCleared(History *history) {
|
|||
bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId) {
|
||||
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
|
||||
|
||||
if (error.type() == qstr("CHANNEL_PRIVATE")) {
|
||||
App::wnd()->showLayer(new ConfirmBox(lang(lng_channel_not_accessible), true));
|
||||
App::main()->showDialogs();
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG(("RPC Error: %1 %2: %3").arg(error.code()).arg(error.type()).arg(error.description()));
|
||||
if (_preloadRequest == requestId) {
|
||||
_preloadRequest = 0;
|
||||
|
@ -3703,7 +3787,7 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
|
|||
} else if (readyToForward()) {
|
||||
App::main()->readServerHistory(_history, false);
|
||||
fastShowAtEnd(_history);
|
||||
App::main()->finishForwarding(_history);
|
||||
App::main()->finishForwarding(_history, _broadcast.checked());
|
||||
}
|
||||
if (replyTo < 0) cancelReply(lastKeyboardUsed);
|
||||
if (_previewData && _previewData->pendingTill) previewCancel();
|
||||
|
@ -3722,17 +3806,17 @@ void HistoryWidget::onUnblock() {
|
|||
_unblockRequest = MTP::send(MTPcontacts_Unblock(_peer->asUser()->inputUser), rpcDone(&HistoryWidget::unblockDone, _peer), rpcFail(&HistoryWidget::unblockFail));
|
||||
}
|
||||
|
||||
void HistoryWidget::unblockDone(PeerData *peer, const MTPBool &result) {
|
||||
void HistoryWidget::unblockDone(PeerData *peer, const MTPBool &result, mtpRequestId req) {
|
||||
if (!peer->isUser()) return;
|
||||
_unblockRequest = 0;
|
||||
if (_unblockRequest == req) _unblockRequest = 0;
|
||||
peer->asUser()->blocked = UserIsNotBlocked;
|
||||
emit App::main()->peerUpdated(peer);
|
||||
}
|
||||
|
||||
bool HistoryWidget::unblockFail(const RPCError &error) {
|
||||
bool HistoryWidget::unblockFail(const RPCError &error, mtpRequestId req) {
|
||||
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
|
||||
|
||||
_unblockRequest = 0;
|
||||
if (_unblockRequest == req) _unblockRequest = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3768,6 +3852,36 @@ void HistoryWidget::onBotStart() {
|
|||
resizeEvent(0);
|
||||
}
|
||||
|
||||
void HistoryWidget::onJoinChannel() {
|
||||
if (_unblockRequest) return;
|
||||
if (!_peer || !_peer->isChannel() || !isJoinChannel()) {
|
||||
updateControlsVisibility();
|
||||
return;
|
||||
}
|
||||
|
||||
_unblockRequest = MTP::send(MTPchannels_JoinChannel(_peer->asChannel()->inputChannel), rpcDone(&HistoryWidget::joinDone), rpcFail(&HistoryWidget::joinFail));
|
||||
}
|
||||
|
||||
void HistoryWidget::joinDone(const MTPUpdates &result, mtpRequestId req) {
|
||||
if (_unblockRequest == req) _unblockRequest = 0;
|
||||
if (App::main()) App::main()->sentUpdatesReceived(result);
|
||||
}
|
||||
|
||||
bool HistoryWidget::joinFail(const RPCError &error, mtpRequestId req) {
|
||||
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
|
||||
|
||||
if (_unblockRequest == req) _unblockRequest = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void HistoryWidget::onMuteUnmute() {
|
||||
App::main()->updateNotifySetting(_peer, _history->mute);
|
||||
}
|
||||
|
||||
void HistoryWidget::onBroadcastChange() {
|
||||
_field.setPlaceholder(lang(_broadcast.checked() ? lng_broadcast_ph : lng_comment_ph));
|
||||
}
|
||||
|
||||
void HistoryWidget::onShareContact(const PeerId &peer, UserData *contact) {
|
||||
if (!contact || contact->phone.isEmpty()) return;
|
||||
|
||||
|
@ -3797,7 +3911,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const
|
|||
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
|
||||
}
|
||||
|
||||
bool fromChannelName = p->isChannel() && p->asChannel()->adminned && _broadcast.checked();
|
||||
bool fromChannelName = p->isChannel() && p->asChannel()->canPublish() && (p->asChannel()->isBroadcast() || _broadcast.checked());
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
|
||||
flags |= MTPDmessage::flag_views;
|
||||
|
@ -3809,7 +3923,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const
|
|||
|
||||
App::historyRegRandom(randomId, newId);
|
||||
|
||||
App::main()->finishForwarding(h);
|
||||
App::main()->finishForwarding(h, _broadcast.checked());
|
||||
cancelReply(lastKeyboardUsed);
|
||||
}
|
||||
|
||||
|
@ -3861,6 +3975,8 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
|
|||
_send.hide();
|
||||
_unblock.hide();
|
||||
_botStart.hide();
|
||||
_joinChannel.hide();
|
||||
_muteUnmute.hide();
|
||||
a_coord = back ? anim::ivalue(-st::introSlideShift, 0) : anim::ivalue(st::introSlideShift, 0);
|
||||
a_alpha = anim::fvalue(0, 1);
|
||||
a_bgCoord = back ? anim::ivalue(0, st::introSlideShift) : anim::ivalue(0, -st::introSlideShift);
|
||||
|
@ -4084,7 +4200,9 @@ void HistoryWidget::stopRecording(bool send) {
|
|||
|
||||
_recording = false;
|
||||
_recordingSamples = 0;
|
||||
updateSendAction(_history, SendActionRecordAudio, -1);
|
||||
if (_peer && (!_peer->isChannel() || !_peer->asChannel()->canPublish() || (!_peer->asChannel()->isBroadcast() && !_broadcast.checked()))) {
|
||||
updateSendAction(_history, SendActionRecordAudio, -1);
|
||||
}
|
||||
|
||||
updateControlsVisibility();
|
||||
activate();
|
||||
|
@ -4236,9 +4354,9 @@ bool HistoryWidget::canSendMessages(PeerData *peer) const {
|
|||
if (peer->isUser()) {
|
||||
return peer->asUser()->access != UserNoAccess;
|
||||
} else if (peer->isChat()) {
|
||||
return !peer->asChat()->forbidden && !peer->asChat()->left;
|
||||
return !peer->asChat()->isForbidden && !peer->asChat()->haveLeft;
|
||||
} else if (peer->isChannel()) {
|
||||
return !peer->asChannel()->forbidden && !peer->asChannel()->left && (peer->asChannel()->adminned || !peer->asChannel()->isBroadcast);
|
||||
return !peer->asChannel()->isForbidden && !peer->asChannel()->haveLeft() && !peer->asChannel()->wasKicked() && (peer->asChannel()->canPublish() || !peer->asChannel()->isBroadcast());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -4249,7 +4367,7 @@ bool HistoryWidget::readyToForward() const {
|
|||
}
|
||||
|
||||
bool HistoryWidget::hasBroadcastToggle() const {
|
||||
return _history && _history->peer->isChannel() && _history->peer->asChannel()->adminned && !_history->peer->asChannel()->isBroadcast;
|
||||
return _history && _history->peer->isChannel() && _history->peer->asChannel()->canPublish() && !_history->peer->asChannel()->isBroadcast();
|
||||
}
|
||||
|
||||
bool HistoryWidget::isBotStart() const {
|
||||
|
@ -4261,6 +4379,14 @@ bool HistoryWidget::isBlocked() const {
|
|||
return _peer && _peer->isUser() && _peer->asUser()->blocked == UserIsBlocked;
|
||||
}
|
||||
|
||||
bool HistoryWidget::isJoinChannel() const {
|
||||
return _peer && _peer->isChannel() && !_peer->asChannel()->amParticipant();
|
||||
}
|
||||
|
||||
bool HistoryWidget::isMuteUnmute() const {
|
||||
return _peer && _peer->isChannel() && _peer->asChannel()->isBroadcast() && !_peer->asChannel()->canPublish();
|
||||
}
|
||||
|
||||
bool HistoryWidget::updateCmdStartShown() {
|
||||
bool cmdStartShown = false;
|
||||
if (_history && _peer && ((_peer->isChat() && _peer->asChat()->botStatus > 0) || (_peer->isChannel() && _peer->asChannel()->botStatus > 0) || (_peer->isUser() && _peer->asUser()->botInfo))) {
|
||||
|
@ -4478,7 +4604,7 @@ void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) {
|
|||
text = App::onlineText(_peer->asUser(), t);
|
||||
} else if (_peer->isChat()) {
|
||||
ChatData *chat = _peer->asChat();
|
||||
if (chat->forbidden || chat->left) {
|
||||
if (chat->isForbidden || chat->haveLeft) {
|
||||
text = lang(lng_chat_status_unaccessible);
|
||||
} else if (chat->participants.isEmpty()) {
|
||||
text = _titlePeerText.isEmpty() ? lng_chat_status_members(lt_count, chat->count < 0 ? 0 : chat->count) : _titlePeerText;
|
||||
|
@ -4498,7 +4624,7 @@ void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) {
|
|||
}
|
||||
}
|
||||
} else if (_peer->isChannel()) {
|
||||
text = lang(lng_channel_status);
|
||||
text = _peer->asChannel()->count ? lng_chat_status_members(lt_count, _peer->asChannel()->count) : lang(lng_channel_status);
|
||||
}
|
||||
if (_titlePeerText != text) {
|
||||
_titlePeerText = text;
|
||||
|
@ -4527,7 +4653,6 @@ void HistoryWidget::updateOnlineDisplayTimer() {
|
|||
}
|
||||
}
|
||||
} else if (_peer->isChannel()) {
|
||||
// CHANNELS_UI
|
||||
}
|
||||
App::main()->updateOnlineDisplayIn(minIn * 1000);
|
||||
}
|
||||
|
@ -4548,6 +4673,8 @@ void HistoryWidget::onFieldResize() {
|
|||
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
|
||||
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
|
||||
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
|
||||
_joinChannel.setGeometry(0, _attachDocument.y(), width(), _joinChannel.height());
|
||||
_muteUnmute.setGeometry(0, _attachDocument.y(), width(), _muteUnmute.height());
|
||||
_send.move(width() - _send.width(), _attachDocument.y());
|
||||
_broadcast.move(_send.x() - _broadcast.width(), height() - kbh - _broadcast.height());
|
||||
_attachEmoji.move((hasBroadcastToggle() ? _broadcast.x() : _send.x()) - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
|
||||
|
@ -4593,7 +4720,7 @@ void HistoryWidget::uploadImage(const QImage &img, bool withText, const QString
|
|||
_confirmImage = img;
|
||||
_confirmWithText = withText;
|
||||
_confirmSource = source;
|
||||
_confirmImageId = _imageLoader.append(img, _peer->id, replyToId(), ToPreparePhoto);
|
||||
_confirmImageId = _imageLoader.append(img, _peer->id, _broadcast.checked(), replyToId(), ToPreparePhoto);
|
||||
}
|
||||
|
||||
void HistoryWidget::uploadFile(const QString &file, bool withText) {
|
||||
|
@ -4601,7 +4728,7 @@ void HistoryWidget::uploadFile(const QString &file, bool withText) {
|
|||
|
||||
App::wnd()->activateWindow();
|
||||
_confirmWithText = withText;
|
||||
_confirmImageId = _imageLoader.append(file, _peer->id, replyToId(), ToPrepareDocument);
|
||||
_confirmImageId = _imageLoader.append(file, _peer->id, _broadcast.checked(), replyToId(), ToPrepareDocument);
|
||||
}
|
||||
|
||||
void HistoryWidget::shareContactConfirmation(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, bool withText) {
|
||||
|
@ -4622,7 +4749,7 @@ void HistoryWidget::uploadConfirmImageUncompressed(bool ctrlShiftEnter, MsgId re
|
|||
onSend(ctrlShiftEnter, replyTo);
|
||||
}
|
||||
bool lastKeyboardUsed = lastForceReplyReplied(FullMsgId(_channel, replyTo));
|
||||
_imageLoader.append(_confirmImage, peerId, replyTo, ToPrepareDocument, ctrlShiftEnter);
|
||||
_imageLoader.append(_confirmImage, peerId, _broadcast.checked(), replyTo, ToPrepareDocument, ctrlShiftEnter);
|
||||
_confirmImageId = 0;
|
||||
_confirmWithText = false;
|
||||
_confirmImage = QImage();
|
||||
|
@ -4633,7 +4760,7 @@ void HistoryWidget::uploadMedias(const QStringList &files, ToPrepareMediaType ty
|
|||
if (!_history) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
_imageLoader.append(files, _peer->id, replyToId(), type);
|
||||
_imageLoader.append(files, _peer->id, _broadcast.checked(), replyToId(), type);
|
||||
cancelReply(lastForceReplyReplied());
|
||||
}
|
||||
|
||||
|
@ -4641,7 +4768,7 @@ void HistoryWidget::uploadMedia(const QByteArray &fileContent, ToPrepareMediaTyp
|
|||
if (!peer && !_history) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
_imageLoader.append(fileContent, peer ? peer : _peer->id, replyToId(), type);
|
||||
_imageLoader.append(fileContent, peer ? peer : _peer->id, _broadcast.checked(), replyToId(), type);
|
||||
cancelReply(lastForceReplyReplied());
|
||||
}
|
||||
|
||||
|
@ -4721,7 +4848,7 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
|||
|
||||
int32 flags = newMessageFlags(h->peer) | MTPDmessage::flag_media; // unread, out
|
||||
if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id;
|
||||
bool fromChannelName = h->peer->isChannel() && h->peer->asChannel()->adminned && _broadcast.checked();
|
||||
bool fromChannelName = h->peer->isChannel() && h->peer->asChannel()->canPublish() && (h->peer->asChannel()->isBroadcast() || img.broadcast);
|
||||
if (fromChannelName) {
|
||||
flags |= MTPDmessage::flag_views;
|
||||
} else {
|
||||
|
@ -4732,7 +4859,9 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
|||
} else if (img.type == ToPrepareDocument) {
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(img.peer), MTPPeer(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
} else if (img.type == ToPrepareAudio) {
|
||||
flags |= MTPDmessage_flag_media_unread;
|
||||
if (!h->peer->isChannel()) {
|
||||
flags |= MTPDmessage_flag_media_unread;
|
||||
}
|
||||
h->addNewMessage(MTP_message(MTP_int(flags), MTP_int(newId.msg), MTP_int(fromChannelName ? 0 : MTP::authedId()), peerToMTP(img.peer), MTPPeer(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup, MTPnullEntities, MTP_int(1)), NewMessageUnread);
|
||||
}
|
||||
|
||||
|
@ -4763,7 +4892,7 @@ void HistoryWidget::onPhotoUploaded(const FullMsgId &newId, const MTPInputFile &
|
|||
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
|
||||
}
|
||||
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->adminned && item->fromChannel();
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->canPublish() && item->fromChannel();
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
|
||||
}
|
||||
|
@ -4808,7 +4937,7 @@ void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, const MTPInputFil
|
|||
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
|
||||
}
|
||||
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->adminned && item->fromChannel();
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->canPublish() && item->fromChannel();
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
|
||||
}
|
||||
|
@ -4837,7 +4966,7 @@ void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, const MTPInp
|
|||
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
|
||||
}
|
||||
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->adminned && item->fromChannel();
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->canPublish() && item->fromChannel();
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
|
||||
}
|
||||
|
@ -4864,7 +4993,7 @@ void HistoryWidget::onAudioUploaded(const FullMsgId &newId, const MTPInputFile &
|
|||
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
|
||||
}
|
||||
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->adminned && item->fromChannel();
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->canPublish() && item->fromChannel();
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
|
||||
}
|
||||
|
@ -4875,30 +5004,33 @@ void HistoryWidget::onAudioUploaded(const FullMsgId &newId, const MTPInputFile &
|
|||
|
||||
void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
|
||||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
if (HistoryItem *item = App::histItemById(newId)) {
|
||||
PhotoData *photo = (item->getMedia() && item->getMedia()->type() == MediaTypePhoto) ? static_cast<HistoryPhoto*>(item->getMedia())->photo() : 0;
|
||||
updateSendAction(item->history(), SendActionUploadPhoto, 0);
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadPhoto, 0);
|
||||
}
|
||||
// msgUpdated(item->history()->peer->id, item);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
|
||||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
if (HistoryItem *item = App::histItemById(newId)) {
|
||||
DocumentData *doc = (item->getMedia() && item->getMedia()->type() == MediaTypeDocument) ? static_cast<HistoryDocument*>(item->getMedia())->document() : 0;
|
||||
updateSendAction(item->history(), SendActionUploadFile, doc ? doc->uploadOffset : 0);
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadFile, doc ? doc->uploadOffset : 0);
|
||||
}
|
||||
msgUpdated(item->history()->peer->id, item);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onAudioProgress(const FullMsgId &newId) {
|
||||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
if (HistoryItem *item = App::histItemById(newId)) {
|
||||
AudioData *audio = (item->getMedia() && item->getMedia()->type() == MediaTypeAudio) ? static_cast<HistoryAudio*>(item->getMedia())->audio() : 0;
|
||||
updateSendAction(item->history(), SendActionUploadAudio, audio ? audio->uploadOffset : 0);
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadAudio, audio ? audio->uploadOffset : 0);
|
||||
}
|
||||
msgUpdated(item->history()->peer->id, item);
|
||||
}
|
||||
}
|
||||
|
@ -4907,7 +5039,9 @@ void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
|
|||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
updateSendAction(item->history(), SendActionUploadPhoto, -1);
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadPhoto, -1);
|
||||
}
|
||||
// msgUpdated(item->history()->peer->id, item);
|
||||
}
|
||||
}
|
||||
|
@ -4916,7 +5050,9 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
|
|||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
updateSendAction(item->history(), SendActionUploadFile, -1);
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadFile, -1);
|
||||
}
|
||||
msgUpdated(item->history()->peer->id, item);
|
||||
}
|
||||
}
|
||||
|
@ -4925,13 +5061,15 @@ void HistoryWidget::onAudioFailed(const FullMsgId &newId) {
|
|||
if (!MTP::authedId()) return;
|
||||
HistoryItem *item = App::histItemById(newId);
|
||||
if (item) {
|
||||
updateSendAction(item->history(), SendActionUploadAudio, -1);
|
||||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadAudio, -1);
|
||||
}
|
||||
msgUpdated(item->history()->peer->id, item);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onReportSpamClicked() {
|
||||
ConfirmBox *box = new ConfirmBox(lang(_peer->isUser() ? lng_report_spam_sure : lng_report_spam_sure_group), lang(lng_report_spam_ok));
|
||||
ConfirmBox *box = new ConfirmBox(lang(_peer->isUser() ? lng_report_spam_sure : (_peer->isChat() ? lng_report_spam_sure_group : lng_report_spam_sure_channel)), lang(lng_report_spam_ok));
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onReportSpamSure()));
|
||||
App::wnd()->showLayer(box);
|
||||
_clearPeer = _peer;
|
||||
|
@ -4954,7 +5092,7 @@ void HistoryWidget::reportSpamDone(PeerData *peer, const MTPBool &result, mtpReq
|
|||
Local::writeReportSpamStatuses();
|
||||
}
|
||||
_reportSpamStatus = dbiprsReportSent;
|
||||
_reportSpamPanel.setReported(_reportSpamStatus == dbiprsReportSent);
|
||||
_reportSpamPanel.setReported(_reportSpamStatus == dbiprsReportSent, peer);
|
||||
}
|
||||
|
||||
bool HistoryWidget::reportSpamFail(const RPCError &error, mtpRequestId req) {
|
||||
|
@ -4976,21 +5114,15 @@ void HistoryWidget::onReportSpamHide() {
|
|||
}
|
||||
|
||||
void HistoryWidget::onReportSpamClear() {
|
||||
ConfirmBox *box = new ConfirmBox(_peer->isUser() ? lng_sure_delete_history(lt_contact, _peer->name) : lng_sure_delete_and_exit(lt_group, _peer->name));
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onReportSpamClearSure()));
|
||||
App::wnd()->showLayer(box);
|
||||
_clearPeer = _peer;
|
||||
}
|
||||
|
||||
void HistoryWidget::onReportSpamClearSure() {
|
||||
App::wnd()->hideLayer();
|
||||
if (_clearPeer->isUser()) {
|
||||
App::main()->deleteConversation(_clearPeer);
|
||||
} else if (_clearPeer->isChat()) {
|
||||
App::main()->showDialogs();
|
||||
MTP::send(MTPmessages_DeleteChatUser(_clearPeer->asChat()->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _clearPeer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _clearPeer));
|
||||
} else if (_clearPeer->isChannel()) { // CHANNELS_UX
|
||||
|
||||
} else if (_clearPeer->isChannel()) {
|
||||
App::main()->showDialogs();
|
||||
MTP::send(MTPchannels_LeaveChannel(_clearPeer->asChannel()->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4998,9 +5130,16 @@ void HistoryWidget::peerMessagesUpdated(PeerId peer) {
|
|||
if (_peer && _list && peer == _peer->id) {
|
||||
updateListSize();
|
||||
updateBotKeyboard();
|
||||
if (!_scroll.isHidden() && !isBlocked() && _botStart.isHidden() == isBotStart()) {
|
||||
updateControlsVisibility();
|
||||
resizeEvent(0);
|
||||
if (!_scroll.isHidden()) {
|
||||
bool unblock = isBlocked(), botStart = isBotStart(), joinChannel = isJoinChannel(), muteUnmute = isMuteUnmute();
|
||||
bool upd = (_unblock.isHidden() == unblock);
|
||||
if (!upd && !unblock) upd = (_botStart.isHidden() == botStart);
|
||||
if (!upd && !unblock && !botStart) upd = (_joinChannel.isHidden() == joinChannel);
|
||||
if (!upd && !unblock && !botStart && !joinChannel) upd = (_muteUnmute.isHidden() == muteUnmute);
|
||||
if (upd) {
|
||||
updateControlsVisibility();
|
||||
resizeEvent(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5043,6 +5182,8 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
|
|||
_send.move(width() - _send.width(), _attachDocument.y());
|
||||
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
|
||||
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
|
||||
_joinChannel.setGeometry(0, _attachDocument.y(), width(), _joinChannel.height());
|
||||
_muteUnmute.setGeometry(0, _attachDocument.y(), width(), _muteUnmute.height());
|
||||
_broadcast.move(_send.x() - _broadcast.width(), height() - kbh - _broadcast.height());
|
||||
_attachEmoji.move((hasBroadcastToggle() ? _broadcast.x() : _send.x()) - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
|
||||
_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
|
||||
|
@ -5113,10 +5254,8 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
|
|||
}
|
||||
|
||||
int32 newScrollHeight = height();
|
||||
if (isBlocked()) {
|
||||
if (isBlocked() || isBotStart() || isJoinChannel() || isMuteUnmute()) {
|
||||
newScrollHeight -= _unblock.height();
|
||||
} else if (isBotStart()) {
|
||||
newScrollHeight -= _botStart.height();
|
||||
} else {
|
||||
if (_canSendMessages) {
|
||||
newScrollHeight -= (_field.height() + 2 * st::sendPadding);
|
||||
|
@ -5469,7 +5608,7 @@ void HistoryWidget::onStickerSend(DocumentData *sticker) {
|
|||
flags |= MTPDmessage::flag_reply_to_msg_id;
|
||||
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
|
||||
}
|
||||
bool fromChannelName = _history->peer->isChannel() && _history->peer->asChannel()->adminned && _broadcast.checked();
|
||||
bool fromChannelName = _history->peer->isChannel() && _history->peer->asChannel()->canPublish() && (_history->peer->asChannel()->isBroadcast() || _broadcast.checked());
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
|
||||
} else {
|
||||
|
@ -5478,7 +5617,7 @@ void HistoryWidget::onStickerSend(DocumentData *sticker) {
|
|||
_history->addNewDocument(newId.msg, flags, replyToId(), date(MTP_int(unixtime())), fromChannelName ? 0 : MTP::authedId(), sticker);
|
||||
|
||||
_history->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), _peer->input, MTP_int(replyToId()), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, _history->sendRequestId);
|
||||
App::main()->finishForwarding(_history);
|
||||
App::main()->finishForwarding(_history, _broadcast.checked());
|
||||
cancelReply(lastKeyboardUsed);
|
||||
|
||||
if (sticker->sticker()) App::main()->incrementSticker(sticker);
|
||||
|
@ -5755,11 +5894,12 @@ void HistoryWidget::peerUpdated(PeerData *data) {
|
|||
if (data && data == _peer) {
|
||||
updateListSize();
|
||||
if (!_showAnim.animating()) updateControlsVisibility();
|
||||
if (_peer->isChannel()) updateReportSpamStatus();
|
||||
if (data->isChat() && data->asChat()->count > 0 && data->asChat()->participants.isEmpty()) {
|
||||
App::api()->requestFullPeer(data);
|
||||
} else if (data->isUser() && data->asUser()->blocked == UserBlockUnknown) {
|
||||
App::api()->requestFullPeer(data);
|
||||
} else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) {
|
||||
} else if (!_scroll.isHidden() && (_unblock.isHidden() == isBlocked() || (!isBlocked() && _joinChannel.isHidden() == isJoinChannel()))) {
|
||||
updateControlsVisibility();
|
||||
resizeEvent(0);
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ public:
|
|||
void resizeEvent(QResizeEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
|
||||
void setReported(bool reported);
|
||||
void setReported(bool reported, PeerData *onPeer);
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -533,6 +533,8 @@ public:
|
|||
void setInnerFocus();
|
||||
bool canSendMessages(PeerData *peer) const;
|
||||
|
||||
void updateNotifySettings();
|
||||
|
||||
~HistoryWidget();
|
||||
|
||||
signals:
|
||||
|
@ -574,14 +576,17 @@ public slots:
|
|||
void onReportSpamSure();
|
||||
void onReportSpamHide();
|
||||
void onReportSpamClear();
|
||||
void onReportSpamClearSure();
|
||||
|
||||
void onListScroll();
|
||||
void onHistoryToEnd();
|
||||
void onCollapseComments();
|
||||
void onSend(bool ctrlShiftEnter = false, MsgId replyTo = -1);
|
||||
|
||||
void onUnblock();
|
||||
void onBotStart();
|
||||
void onJoinChannel();
|
||||
void onMuteUnmute();
|
||||
void onBroadcastChange();
|
||||
|
||||
void onPhotoSelect();
|
||||
void onDocumentSelect();
|
||||
|
@ -673,10 +678,13 @@ private:
|
|||
void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
|
||||
bool reportSpamFail(const RPCError &error, mtpRequestId request);
|
||||
|
||||
void unblockDone(PeerData *peer, const MTPBool &result);
|
||||
bool unblockFail(const RPCError &error);
|
||||
void unblockDone(PeerData *peer, const MTPBool &result, mtpRequestId req);
|
||||
bool unblockFail(const RPCError &error, mtpRequestId req);
|
||||
void blockDone(PeerData *peer, const MTPBool &result);
|
||||
|
||||
void joinDone(const MTPUpdates &result, mtpRequestId req);
|
||||
bool joinFail(const RPCError &error, mtpRequestId req);
|
||||
|
||||
void countHistoryShowFrom();
|
||||
|
||||
void stickersGot(const MTPmessages_AllStickers &stickers);
|
||||
|
@ -719,11 +727,13 @@ private:
|
|||
|
||||
bool isBotStart() const;
|
||||
bool isBlocked() const;
|
||||
bool isJoinChannel() const;
|
||||
bool isMuteUnmute() const;
|
||||
bool updateCmdStartShown();
|
||||
|
||||
ReportSpamPanel _reportSpamPanel;
|
||||
|
||||
FlatButton _send, _unblock, _botStart;
|
||||
FlatButton _send, _unblock, _botStart, _joinChannel, _muteUnmute;
|
||||
mtpRequestId _unblockRequest, _reportSpamRequest;
|
||||
IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide, _cmdStart;
|
||||
FlatCheckbox _broadcast;
|
||||
|
|
|
@ -42,6 +42,7 @@ void LocalImageLoaderPrivate::prepareImages() {
|
|||
QString thumbExt = "jpg";
|
||||
ToPrepareMediaType type;
|
||||
bool animated = false;
|
||||
bool broadcast = false;
|
||||
bool ctrlShiftEnter = false;
|
||||
MsgId replyTo;
|
||||
{
|
||||
|
@ -56,6 +57,7 @@ void LocalImageLoaderPrivate::prepareImages() {
|
|||
id = list.front().id;
|
||||
type = list.front().type;
|
||||
duration = list.front().duration;
|
||||
broadcast = list.front().broadcast;
|
||||
ctrlShiftEnter = list.front().ctrlShiftEnter;
|
||||
replyTo = list.front().replyTo;
|
||||
}
|
||||
|
@ -262,7 +264,7 @@ void LocalImageLoaderPrivate::prepareImages() {
|
|||
|
||||
{
|
||||
QMutexLocker lock(loader->readyMutex());
|
||||
loader->readyList().push_back(ReadyLocalMedia(type, file, filename, filesize, data, id, thumbId, thumbExt, peer, photo, audio, photoThumbs, document, jpeg, ctrlShiftEnter, replyTo));
|
||||
loader->readyList().push_back(ReadyLocalMedia(type, file, filename, filesize, data, id, thumbId, thumbExt, peer, photo, audio, photoThumbs, document, jpeg, broadcast, ctrlShiftEnter, replyTo));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -284,11 +286,11 @@ LocalImageLoaderPrivate::~LocalImageLoaderPrivate() {
|
|||
LocalImageLoader::LocalImageLoader(QObject *parent) : QObject(parent), thread(0), priv(0) {
|
||||
}
|
||||
|
||||
void LocalImageLoader::append(const QStringList &files, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t) {
|
||||
void LocalImageLoader::append(const QStringList &files, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
for (QStringList::const_iterator i = files.cbegin(), e = files.cend(); i != e; ++i) {
|
||||
toPrepare.push_back(ToPrepareMedia(*i, peer, t, false, replyTo));
|
||||
toPrepare.push_back(ToPrepareMedia(*i, peer, t, broadcast, false, replyTo));
|
||||
}
|
||||
}
|
||||
if (!thread) {
|
||||
|
@ -299,11 +301,11 @@ void LocalImageLoader::append(const QStringList &files, const PeerId &peer, MsgI
|
|||
emit needToPrepare();
|
||||
}
|
||||
|
||||
PhotoId LocalImageLoader::append(const QByteArray &img, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t) {
|
||||
PhotoId LocalImageLoader::append(const QByteArray &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
PhotoId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
toPrepare.push_back(ToPrepareMedia(img, peer, t, false, replyTo));
|
||||
toPrepare.push_back(ToPrepareMedia(img, peer, t, broadcast, false, replyTo));
|
||||
result = toPrepare.back().id;
|
||||
}
|
||||
if (!thread) {
|
||||
|
@ -315,11 +317,11 @@ PhotoId LocalImageLoader::append(const QByteArray &img, const PeerId &peer, MsgI
|
|||
return result;
|
||||
}
|
||||
|
||||
AudioId LocalImageLoader::append(const QByteArray &audio, int32 duration, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t) {
|
||||
AudioId LocalImageLoader::append(const QByteArray &audio, int32 duration, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
AudioId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
toPrepare.push_back(ToPrepareMedia(audio, duration, peer, t, false, replyTo));
|
||||
toPrepare.push_back(ToPrepareMedia(audio, duration, peer, t, broadcast, false, replyTo));
|
||||
result = toPrepare.back().id;
|
||||
}
|
||||
if (!thread) {
|
||||
|
@ -331,11 +333,11 @@ AudioId LocalImageLoader::append(const QByteArray &audio, int32 duration, const
|
|||
return result;
|
||||
}
|
||||
|
||||
PhotoId LocalImageLoader::append(const QImage &img, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t, bool ctrlShiftEnter) {
|
||||
PhotoId LocalImageLoader::append(const QImage &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t, bool ctrlShiftEnter) {
|
||||
PhotoId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
toPrepare.push_back(ToPrepareMedia(img, peer, t, ctrlShiftEnter, replyTo));
|
||||
toPrepare.push_back(ToPrepareMedia(img, peer, t, broadcast, ctrlShiftEnter, replyTo));
|
||||
result = toPrepare.back().id;
|
||||
}
|
||||
if (!thread) {
|
||||
|
@ -347,11 +349,11 @@ PhotoId LocalImageLoader::append(const QImage &img, const PeerId &peer, MsgId re
|
|||
return result;
|
||||
}
|
||||
|
||||
PhotoId LocalImageLoader::append(const QString &file, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t) {
|
||||
PhotoId LocalImageLoader::append(const QString &file, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t) {
|
||||
PhotoId result = 0;
|
||||
{
|
||||
QMutexLocker lock(toPrepareMutex());
|
||||
toPrepare.push_back(ToPrepareMedia(file, peer, t, false, replyTo));
|
||||
toPrepare.push_back(ToPrepareMedia(file, peer, t, broadcast, false, replyTo));
|
||||
result = toPrepare.back().id;
|
||||
}
|
||||
if (!thread) {
|
||||
|
|
|
@ -26,13 +26,13 @@ enum ToPrepareMediaType {
|
|||
};
|
||||
|
||||
struct ToPrepareMedia {
|
||||
ToPrepareMedia(const QString &file, const PeerId &peer, ToPrepareMediaType t, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), file(file), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QString &file, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), file(file), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
ToPrepareMedia(const QImage &img, const PeerId &peer, ToPrepareMediaType t, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), img(img), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QImage &img, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), img(img), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
ToPrepareMedia(const QByteArray &data, const PeerId &peer, ToPrepareMediaType t, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QByteArray &data, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(0), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
ToPrepareMedia(const QByteArray &data, int32 duration, const PeerId &peer, ToPrepareMediaType t, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(duration), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
ToPrepareMedia(const QByteArray &data, int32 duration, const PeerId &peer, ToPrepareMediaType t, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) : id(MTP::nonce<PhotoId>()), data(data), peer(peer), type(t), duration(duration), ctrlShiftEnter(ctrlShiftEnter), replyTo(replyTo) {
|
||||
}
|
||||
PhotoId id;
|
||||
QString file;
|
||||
|
@ -41,6 +41,7 @@ struct ToPrepareMedia {
|
|||
PeerId peer;
|
||||
ToPrepareMediaType type;
|
||||
int32 duration;
|
||||
bool broadcast;
|
||||
bool ctrlShiftEnter;
|
||||
MsgId replyTo;
|
||||
};
|
||||
|
@ -48,8 +49,8 @@ typedef QList<ToPrepareMedia> ToPrepareMedias;
|
|||
|
||||
typedef QMap<int32, QByteArray> LocalFileParts;
|
||||
struct ReadyLocalMedia {
|
||||
ReadyLocalMedia(ToPrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const MTPAudio &audio, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool ctrlShiftEnter, MsgId replyTo) :
|
||||
replyTo(replyTo), type(type), file(file), filename(filename), filesize(filesize), data(data), thumbExt(thumbExt), id(id), thumbId(thumbId), peer(peer), photo(photo), document(document), audio(audio), photoThumbs(photoThumbs), ctrlShiftEnter(ctrlShiftEnter) {
|
||||
ReadyLocalMedia(ToPrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const MTPAudio &audio, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool broadcast, bool ctrlShiftEnter, MsgId replyTo) :
|
||||
replyTo(replyTo), type(type), file(file), filename(filename), filesize(filesize), data(data), thumbExt(thumbExt), id(id), thumbId(thumbId), peer(peer), photo(photo), document(document), audio(audio), photoThumbs(photoThumbs), broadcast(broadcast), ctrlShiftEnter(ctrlShiftEnter) {
|
||||
if (!jpeg.isEmpty()) {
|
||||
int32 size = jpeg.size();
|
||||
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
||||
|
@ -75,6 +76,7 @@ struct ReadyLocalMedia {
|
|||
LocalFileParts parts;
|
||||
QByteArray jpeg_md5;
|
||||
|
||||
bool broadcast;
|
||||
bool ctrlShiftEnter;
|
||||
};
|
||||
typedef QList<ReadyLocalMedia> ReadyLocalMedias;
|
||||
|
@ -110,11 +112,11 @@ class LocalImageLoader : public QObject {
|
|||
public:
|
||||
|
||||
LocalImageLoader(QObject *parent);
|
||||
void append(const QStringList &files, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t);
|
||||
PhotoId append(const QByteArray &img, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t);
|
||||
AudioId append(const QByteArray &audio, int32 duration, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t);
|
||||
PhotoId append(const QImage &img, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t, bool ctrlShiftEnter = false);
|
||||
PhotoId append(const QString &file, const PeerId &peer, MsgId replyTo, ToPrepareMediaType t);
|
||||
void append(const QStringList &files, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
PhotoId append(const QByteArray &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
AudioId append(const QByteArray &audio, int32 duration, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
PhotoId append(const QImage &img, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t, bool ctrlShiftEnter = false);
|
||||
PhotoId append(const QString &file, const PeerId &peer, bool broadcast, MsgId replyTo, ToPrepareMediaType t);
|
||||
|
||||
QMutex *readyMutex();
|
||||
ReadyLocalMedias &readyList();
|
||||
|
|
|
@ -2861,13 +2861,13 @@ namespace Local {
|
|||
} else if (peer->isChat()) {
|
||||
ChatData *chat = peer->asChat();
|
||||
|
||||
stream << chat->name << qint32(chat->count) << qint32(chat->date) << qint32(chat->version) << qint32(chat->admin);
|
||||
stream << qint32(chat->forbidden ? 1 : 0) << qint32(chat->left ? 1 : 0) << chat->invitationUrl;
|
||||
stream << chat->name << qint32(chat->count) << qint32(chat->date) << qint32(chat->version) << qint32(chat->creator);
|
||||
stream << qint32(chat->isForbidden ? 1 : 0) << qint32(chat->haveLeft ? 1 : 0) << chat->invitationUrl;
|
||||
} else if (peer->isChannel()) {
|
||||
ChannelData *channel = peer->asChannel();
|
||||
|
||||
stream << channel->name << quint64(channel->access) << qint32(channel->date) << qint32(channel->version) << qint32(channel->adminned ? 1 : 0);
|
||||
stream << qint32(channel->forbidden ? 1 : 0) << qint32(channel->left ? 1 : 0) << channel->invitationUrl;
|
||||
stream << channel->name << quint64(channel->access) << qint32(channel->date) << qint32(channel->version);
|
||||
stream << qint32(channel->isForbidden ? 1 : 0) << qint32(channel->flags) << channel->invitationUrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2911,16 +2911,16 @@ namespace Local {
|
|||
ChatData *chat = result->asChat();
|
||||
|
||||
QString name, invitationUrl;
|
||||
qint32 count, date, version, admin, forbidden, left;
|
||||
from.stream >> name >> count >> date >> version >> admin >> forbidden >> left >> invitationUrl;
|
||||
qint32 count, date, version, creator, forbidden, left;
|
||||
from.stream >> name >> count >> date >> version >> creator >> forbidden >> left >> invitationUrl;
|
||||
|
||||
chat->updateName(name, QString(), QString());
|
||||
chat->count = count;
|
||||
chat->date = date;
|
||||
chat->version = version;
|
||||
chat->admin = admin;
|
||||
chat->forbidden = (forbidden == 1);
|
||||
chat->left = (left == 1);
|
||||
chat->creator = creator;
|
||||
chat->isForbidden = (forbidden == 1);
|
||||
chat->haveLeft = (left == 1);
|
||||
chat->invitationUrl = invitationUrl;
|
||||
|
||||
chat->input = MTP_inputPeerChat(MTP_int(peerToChat(chat->id)));
|
||||
|
@ -2932,16 +2932,15 @@ namespace Local {
|
|||
|
||||
QString name, invitationUrl;
|
||||
quint64 access;
|
||||
qint32 date, version, adminned, forbidden, left;
|
||||
from.stream >> name >> access >> date >> version >> adminned >> forbidden >> left >> invitationUrl;
|
||||
qint32 date, version, adminned, forbidden, flags;
|
||||
from.stream >> name >> access >> date >> version >> forbidden >> flags >> invitationUrl;
|
||||
|
||||
channel->updateName(name, QString(), QString());
|
||||
channel->access = access;
|
||||
channel->date = date;
|
||||
channel->version = version;
|
||||
channel->adminned = (adminned == 1);
|
||||
channel->forbidden = (forbidden == 1);
|
||||
channel->left = (left == 1);
|
||||
channel->isForbidden = (forbidden == 1);
|
||||
channel->flags = flags;
|
||||
channel->invitationUrl = invitationUrl;
|
||||
|
||||
channel->input = MTP_inputPeerChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access));
|
||||
|
|
|
@ -83,7 +83,13 @@ void TopBarWidget::onAddContact() {
|
|||
|
||||
void TopBarWidget::onEdit() {
|
||||
PeerData *p = App::main() ? App::main()->profilePeer() : 0;
|
||||
if (p) App::wnd()->showLayer(new AddContactBox(p));
|
||||
if (p) {
|
||||
if (p->isChannel()) {
|
||||
App::wnd()->showLayer(new EditChannelBox(p->asChannel()));
|
||||
} else {
|
||||
App::wnd()->showLayer(new AddContactBox(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TopBarWidget::onDeleteContact() {
|
||||
|
@ -286,7 +292,7 @@ void TopBarWidget::showAll() {
|
|||
PeerData *p = App::main() ? App::main()->profilePeer() : 0, *h = App::main() ? App::main()->historyPeer() : 0, *o = App::main() ? App::main()->overviewPeer() : 0;
|
||||
if (p && (p->isChat() || (p->isUser() && (p->asUser()->contact >= 0 || !App::phoneFromSharedContact(peerToUser(p->id)).isEmpty())))) {
|
||||
if (p->isChat()) {
|
||||
if (p->asChat()->forbidden) {
|
||||
if (p->asChat()->isForbidden) {
|
||||
_edit.hide();
|
||||
} else {
|
||||
_edit.show();
|
||||
|
@ -311,7 +317,7 @@ void TopBarWidget::showAll() {
|
|||
_forward.hide();
|
||||
_mediaType.hide();
|
||||
} else {
|
||||
if (p && p->isChannel() && p->asChannel()->adminned) {
|
||||
if (p && p->isChannel() && p->asChannel()->amCreator()) {
|
||||
_edit.show();
|
||||
} else {
|
||||
_edit.hide();
|
||||
|
@ -373,9 +379,10 @@ _forwardConfirm(0), _hider(0), _peerInStack(0), _msgIdInStack(0),
|
|||
_playerHeight(0), _contentScrollAddToY(0), _mediaType(this), _mediaTypeMask(0),
|
||||
updDate(0), updQts(-1), updSeq(0), _getDifferenceTimeByPts(0), _getDifferenceTimeAfterFail(0),
|
||||
_onlineRequest(0), _lastWasOnline(false), _lastSetOnline(0), _isIdle(false),
|
||||
_failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _background(0), _api(new ApiWrap(this)) {
|
||||
_failDifferenceTimeout(1), _lastUpdateTime(0), _handlingChannelDifference(false), _cachedX(0), _cachedY(0), _background(0), _api(new ApiWrap(this)) {
|
||||
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
|
||||
|
||||
MTP::setGlobalDoneHandler(rpcDone(&MainWidget::updateReceived));
|
||||
_ptsWaiter.setRequesting(true);
|
||||
updateScrollColors();
|
||||
|
||||
|
@ -390,7 +397,7 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr
|
|||
connect(&_bySeqTimer, SIGNAL(timeout()), this, SLOT(getDifference()));
|
||||
connect(&_byPtsTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeByPts()));
|
||||
connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeAfterFail()));
|
||||
connect(_api, SIGNAL(fullPeerUpdated(PeerData*)), this, SIGNAL(peerUpdated(PeerData*)));
|
||||
connect(_api, SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
|
||||
connect(this, SIGNAL(peerUpdated(PeerData*)), &history, SLOT(peerUpdated(PeerData*)));
|
||||
connect(&_topBar, SIGNAL(clicked()), this, SLOT(onTopBarClick()));
|
||||
connect(&history, SIGNAL(peerShown(PeerData*)), this, SLOT(onPeerShown(PeerData*)));
|
||||
|
@ -403,6 +410,7 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr
|
|||
connect(audioPlayer(), SIGNAL(stopped(const SongMsgId&)), this, SLOT(documentPlayProgress(const SongMsgId&)));
|
||||
}
|
||||
connect(&_updateMutedTimer, SIGNAL(timeout()), this, SLOT(onUpdateMuted()));
|
||||
connect(&_viewsIncrementTimer, SIGNAL(timeout()), this, SLOT(onViewsIncrement()));
|
||||
|
||||
_webPageUpdater.setSingleShot(true);
|
||||
connect(&_webPageUpdater, SIGNAL(timeout()), this, SLOT(webPagesUpdate()));
|
||||
|
@ -435,7 +443,7 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr
|
|||
|
||||
bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) {
|
||||
PeerData *p = App::peer(peer);
|
||||
if (!peer || (p->isChannel() && !p->asChannel()->adminned) || (p->isChat() && p->asChat()->forbidden) || (p->isUser() && p->asUser()->access == UserNoAccess)) {
|
||||
if (!peer || (p->isChannel() && !p->asChannel()->canPublish() && p->asChannel()->isBroadcast()) || (p->isChat() && (p->asChat()->haveLeft || p->asChat()->isForbidden)) || (p->isUser() && p->asUser()->access == UserNoAccess)) {
|
||||
App::wnd()->showLayer(new ConfirmBox(lang(lng_forward_cant), true));
|
||||
return false;
|
||||
}
|
||||
|
@ -528,8 +536,10 @@ void MainWidget::cancelForwarding() {
|
|||
history.cancelForwarding();
|
||||
}
|
||||
|
||||
void MainWidget::finishForwarding(History *hist) {
|
||||
void MainWidget::finishForwarding(History *hist, bool broadcast) {
|
||||
if (!hist) return;
|
||||
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->canPublish() && (hist->peer->asChannel()->isBroadcast() || broadcast);
|
||||
if (!_toForward.isEmpty()) {
|
||||
bool genClientSideMessage = (_toForward.size() < 2);
|
||||
PeerData *forwardFrom = _toForward.cbegin().value()->history()->peer;
|
||||
|
@ -544,7 +554,7 @@ void MainWidget::finishForwarding(History *hist) {
|
|||
if (genClientSideMessage) {
|
||||
FullMsgId newId(peerToChannel(hist->peer->id), clientMsgId());
|
||||
HistoryMessage *msg = static_cast<HistoryMessage*>(_toForward.cbegin().value());
|
||||
hist->addNewForwarded(newId.msg, date(MTP_int(unixtime())), hist->peer->isChannel() ? 0 : MTP::authedId(), msg);
|
||||
hist->addNewForwarded(newId.msg, date(MTP_int(unixtime())), fromChannelName ? 0 : MTP::authedId(), msg);
|
||||
if (HistorySticker *sticker = dynamic_cast<HistorySticker*>(msg->getMedia())) {
|
||||
App::main()->incrementSticker(sticker->document());
|
||||
}
|
||||
|
@ -553,7 +563,7 @@ void MainWidget::finishForwarding(History *hist) {
|
|||
ids.push_back(MTP_int(i.key()));
|
||||
randomIds.push_back(MTP_long(randomId));
|
||||
}
|
||||
int32 flags = hist->peer->isChannel() ? MTPmessages_ForwardMessages_flag_broadcast : 0;
|
||||
int32 flags = fromChannelName ? MTPmessages_ForwardMessages_flag_broadcast : 0;
|
||||
hist->sendRequestId = MTP::send(MTPmessages_ForwardMessages(MTP_int(flags), forwardFrom->input, MTP_vector<MTPint>(ids), MTP_vector<MTPlong>(randomIds), hist->peer->input), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
|
||||
|
||||
if (history.peer() == hist->peer) history.peerMessagesUpdated();
|
||||
|
@ -756,7 +766,7 @@ DragState MainWidget::getDragState(const QMimeData *mime) {
|
|||
bool MainWidget::leaveChatFailed(PeerData *peer, const RPCError &error) {
|
||||
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
|
||||
|
||||
if (error.type() == "CHAT_ID_INVALID") { // left this chat already
|
||||
if (error.type() == qstr("USER_NOT_PARTICIPANT") || error.type() == qstr("CHAT_ID_INVALID")) { // left this chat already
|
||||
if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) {
|
||||
showDialogs();
|
||||
}
|
||||
|
@ -880,7 +890,7 @@ bool MainWidget::addParticipantsFail(const RPCError &error) {
|
|||
QString text = lang(lng_failed_add_participant);
|
||||
if (error.type() == "USER_LEFT_CHAT") { // trying to return banned user to his group
|
||||
} else if (error.type() == "USER_NOT_MUTUAL_CONTACT") { // trying to return user who does not have me in contacts
|
||||
text = lang(lng_failed_add_not_mutual);
|
||||
text = lang(lng_failed_add_not_mutual_channel);
|
||||
} else if (error.type() == "PEER_FLOOD") {
|
||||
text = lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)));
|
||||
}
|
||||
|
@ -911,6 +921,7 @@ void MainWidget::checkPeerHistory(PeerData *peer) {
|
|||
|
||||
void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &result) {
|
||||
const QVector<MTPMessage> *v = 0;
|
||||
const QVector<MTPMessageGroup> *collapsed = 0;
|
||||
switch (result.type()) {
|
||||
case mtpc_messages_messages: {
|
||||
const MTPDmessages_messages &d(result.c_messages_messages());
|
||||
|
@ -934,7 +945,7 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu
|
|||
LOG(("API Error: received messages.channelMessages when no channel was passed! (MainWidget::checkedHistory)"));
|
||||
}
|
||||
|
||||
// CHANNELS_TODO use collapsed to remove last important messages from not important after History::addNewMessage
|
||||
collapsed = &d.vcollapsed.c_vector().v;
|
||||
App::feedUsers(d.vusers);
|
||||
App::feedChats(d.vchats);
|
||||
v = &d.vmessages.c_vector().v;
|
||||
|
@ -943,19 +954,50 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu
|
|||
if (!v) return;
|
||||
|
||||
if (v->isEmpty()) {
|
||||
if (peer->isChat() && peer->asChat()->left) {
|
||||
if (peer->isChat() && peer->asChat()->haveLeft) {
|
||||
dialogs.removePeer(peer);
|
||||
if (history.peer() == peer) {
|
||||
showDialogs();
|
||||
}
|
||||
} else { // CHANNELS_TODO
|
||||
} else if (peer->isChannel()) {
|
||||
if (peer->asChannel()->inviter > 0) {
|
||||
if (!peer->asChannel()->isForbidden && !peer->asChannel()->haveLeft() && !peer->asChannel()->wasKicked()) {
|
||||
if (UserData *from = App::userLoaded(peer->asChannel()->inviter)) {
|
||||
History *h = App::history(peer->id);
|
||||
h->clear(true);
|
||||
h->addNewerSlice(QVector<MTPMessage>(), 0);
|
||||
h->asChannelHistory()->insertJoinedMessage(true);
|
||||
history.peerMessagesUpdated(h->peer->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
History *h = App::historyLoaded(peer->id);
|
||||
if (h) Local::addSavedPeer(peer, h->lastMsgDate);
|
||||
}
|
||||
} else {
|
||||
History *h = App::historyLoaded(peer->id);
|
||||
History *h = App::history(peer->id);
|
||||
if (!h->lastMsg) {
|
||||
h->addNewMessage((*v)[0], NewMessageLast);
|
||||
HistoryItem *item = h->addNewMessage((*v)[0], NewMessageLast);
|
||||
if (collapsed && !collapsed->isEmpty() && collapsed->at(0).type() == mtpc_messageGroup && h->isChannel()) {
|
||||
if (collapsed->at(0).c_messageGroup().vmax_id.v > item->id) {
|
||||
if (h->asChannelHistory()->onlyImportant()) {
|
||||
h->asChannelHistory()->clearOther();
|
||||
} else {
|
||||
h->setNotLoadedAtBottom();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!h->lastMsgDate.isNull() && h->loadedAtBottom()) {
|
||||
if (peer->isChannel() && peer->asChannel()->inviter > 0 && h->lastMsgDate <= peer->asChannel()->inviteDate) {
|
||||
if (!peer->asChannel()->isForbidden && !peer->asChannel()->haveLeft() && !peer->asChannel()->wasKicked()) {
|
||||
if (UserData *from = App::userLoaded(peer->asChannel()->inviter)) {
|
||||
h->asChannelHistory()->insertJoinedMessage(true);
|
||||
history.peerMessagesUpdated(h->peer->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1168,7 +1210,7 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
|
|||
media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill)));
|
||||
flags |= MTPDmessage::flag_media;
|
||||
}
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->adminned && broadcast;
|
||||
bool fromChannelName = hist->peer->isChannel() && hist->peer->asChannel()->canPublish() && (hist->peer->asChannel()->isBroadcast() || broadcast);
|
||||
if (fromChannelName) {
|
||||
sendFlags |= MTPmessages_SendMessage_flag_broadcast;
|
||||
flags |= MTPDmessage::flag_views;
|
||||
|
@ -1180,7 +1222,7 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
|
|||
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, localEntities), rpcDone(&MainWidget::sentUpdatesReceived, randomId), rpcFail(&MainWidget::sendMessageFail), 0, 0, hist->sendRequestId);
|
||||
}
|
||||
|
||||
finishForwarding(hist);
|
||||
finishForwarding(hist, broadcast);
|
||||
}
|
||||
|
||||
void MainWidget::sendMessage(History *hist, const QString &text, MsgId replyTo, bool broadcast) {
|
||||
|
@ -1252,10 +1294,14 @@ void MainWidget::insertBotCommand(const QString &cmd) {
|
|||
history.insertBotCommand(cmd);
|
||||
}
|
||||
|
||||
void MainWidget::searchMessages(const QString &query) {
|
||||
void MainWidget::searchMessages(const QString &query, PeerData *inPeer) {
|
||||
App::wnd()->hideMediaview();
|
||||
dialogs.searchMessages(query);
|
||||
if (!cWideMode()) showDialogs();
|
||||
dialogs.searchMessages(query, inPeer);
|
||||
if (!cWideMode()) {
|
||||
showDialogs();
|
||||
} else {
|
||||
dialogs.activate();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::preloadOverviews(PeerData *peer) {
|
||||
|
@ -1470,7 +1516,7 @@ void MainWidget::loadMediaBack(PeerData *peer, MediaOverviewType type, bool many
|
|||
|
||||
void MainWidget::peerUsernameChanged(PeerData *peer) {
|
||||
if (profile && profile->peer() == peer) {
|
||||
profile->update();
|
||||
profile->peerUsernameChanged();
|
||||
}
|
||||
if (App::settings() && peer == App::self()) {
|
||||
App::settings()->usernameChanged();
|
||||
|
@ -2164,12 +2210,84 @@ void MainWidget::setInnerFocus() {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::scheduleViewIncrement(HistoryItem *item) {
|
||||
PeerData *peer = item->history()->peer;
|
||||
ViewsIncrement::iterator i = _viewsIncremented.find(peer);
|
||||
if (i != _viewsIncremented.cend()) {
|
||||
if (i.value().contains(item->id)) return;
|
||||
} else {
|
||||
i = _viewsIncremented.insert(peer, ViewsIncrementMap());
|
||||
}
|
||||
i.value().insert(item->id, true);
|
||||
ViewsIncrement::iterator j = _viewsToIncrement.find(peer);
|
||||
if (j == _viewsToIncrement.cend()) {
|
||||
j = _viewsToIncrement.insert(peer, ViewsIncrementMap());
|
||||
_viewsIncrementTimer.start(SendViewsTimeout);
|
||||
}
|
||||
j.value().insert(item->id, true);
|
||||
}
|
||||
|
||||
void MainWidget::onViewsIncrement() {
|
||||
for (ViewsIncrement::iterator i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) {
|
||||
if (_viewsIncrementRequests.contains(i.key())) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
QVector<MTPint> ids;
|
||||
ids.reserve(i.value().size());
|
||||
for (ViewsIncrementMap::const_iterator j = i.value().cbegin(), end = i.value().cend(); j != end; ++j) {
|
||||
ids.push_back(MTP_int(j.key()));
|
||||
}
|
||||
mtpRequestId req = MTP::send(MTPmessages_GetMessagesViews(i.key()->input, MTP_vector<MTPint>(ids), MTP_bool(true)), rpcDone(&MainWidget::viewsIncrementDone, ids), rpcFail(&MainWidget::viewsIncrementFail), 0, 5);
|
||||
_viewsIncrementRequests.insert(i.key(), req);
|
||||
i = _viewsToIncrement.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req) {
|
||||
const QVector<MTPint> &v(result.c_vector().v);
|
||||
if (ids.size() == v.size()) {
|
||||
for (ViewsIncrementRequests::iterator i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) {
|
||||
if (i.value() == req) {
|
||||
PeerData *peer = i.key();
|
||||
ChannelId channel = peerToChannel(peer->id);
|
||||
for (int32 j = 0, l = ids.size(); j < l; ++j) {
|
||||
if (HistoryItem *item = App::histItemById(channel, ids.at(j).v)) {
|
||||
item->setViewsCount(v.at(j).v);
|
||||
}
|
||||
}
|
||||
_viewsIncrementRequests.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_viewsToIncrement.isEmpty() && !_viewsIncrementTimer.isActive()) {
|
||||
_viewsIncrementTimer.start(SendViewsTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWidget::viewsIncrementFail(const RPCError &error, mtpRequestId req) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
|
||||
for (ViewsIncrementRequests::iterator i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) {
|
||||
if (i.value() == req) {
|
||||
_viewsIncrementRequests.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!_viewsToIncrement.isEmpty() && !_viewsIncrementTimer.isActive()) {
|
||||
_viewsIncrementTimer.start(SendViewsTimeout);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HistoryItem *MainWidget::atTopImportantMsg(int32 &bottomUnderScrollTop) const {
|
||||
return history.atTopImportantMsg(bottomUnderScrollTop);
|
||||
}
|
||||
|
||||
void MainWidget::createDialogAtTop(History *history, int32 unreadCount) {
|
||||
dialogs.createDialogAtTop(history, unreadCount);
|
||||
void MainWidget::createDialog(History *history) {
|
||||
dialogs.createDialog(history);
|
||||
}
|
||||
|
||||
void MainWidget::choosePeer(PeerId peerId, MsgId showAtMsgId) {
|
||||
|
@ -2274,8 +2392,11 @@ void MainWidget::showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back)
|
|||
if (noPeer) {
|
||||
_topBar.hide();
|
||||
resizeEvent(0);
|
||||
} else if (wasActivePeer != activePeer() && activePeer()->isChannel()) {
|
||||
activePeer()->asChannel()->ptsWaitingForShortPoll(WaitForChannelGetDifference);
|
||||
} else if (wasActivePeer != activePeer()) {
|
||||
if (activePeer()->isChannel()) {
|
||||
activePeer()->asChannel()->ptsWaitingForShortPoll(WaitForChannelGetDifference);
|
||||
}
|
||||
_viewsIncremented.remove(activePeer());
|
||||
}
|
||||
if (!cWideMode() && !dialogs.isHidden()) dialogs.hide();
|
||||
if (!animating()) {
|
||||
|
@ -2526,7 +2647,7 @@ void MainWidget::windowShown() {
|
|||
}
|
||||
|
||||
void MainWidget::sentUpdatesReceived(uint64 randomId, const MTPUpdates &result) {
|
||||
handleUpdates(result, randomId);
|
||||
feedUpdates(result, randomId);
|
||||
App::emitPeerUpdated();
|
||||
}
|
||||
|
||||
|
@ -2829,7 +2950,7 @@ void MainWidget::onUpdateNotifySettings() {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::feedUpdates(const MTPVector<MTPUpdate> &updates, bool skipMessageIds) {
|
||||
void MainWidget::feedUpdateVector(const MTPVector<MTPUpdate> &updates, bool skipMessageIds) {
|
||||
const QVector<MTPUpdate> &v(updates.c_vector().v);
|
||||
for (QVector<MTPUpdate>::const_iterator i = v.cbegin(), e = v.cend(); i != e; ++i) {
|
||||
if (skipMessageIds && i->type() == mtpc_updateMessageID) continue;
|
||||
|
@ -2868,7 +2989,7 @@ void MainWidget::updSetState(int32 pts, int32 date, int32 qts, int32 seq) {
|
|||
MTPUpdates v = i.value();
|
||||
i = _bySeqUpdates.erase(i);
|
||||
if (s == seq + 1) {
|
||||
return handleUpdates(v);
|
||||
return feedUpdates(v);
|
||||
}
|
||||
} else {
|
||||
if (!_bySeqTimer.isActive()) _bySeqTimer.start(WaitForSkippedTimeout);
|
||||
|
@ -2915,8 +3036,9 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
|
|||
}
|
||||
if (history.peer() == channel) {
|
||||
history.updateToEndVisibility();
|
||||
history.onListScroll();
|
||||
}
|
||||
// h->asChannelHistory()->getRangeDifference();
|
||||
h->asChannelHistory()->getRangeDifference();
|
||||
}
|
||||
|
||||
if (d.has_timeout()) timeout = d.vtimeout.v;
|
||||
|
@ -2929,9 +3051,56 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
|
|||
|
||||
App::feedUsers(d.vusers);
|
||||
App::feedChats(d.vchats, false);
|
||||
|
||||
_handlingChannelDifference = true;
|
||||
feedMessageIds(d.vother_updates);
|
||||
App::feedMsgs(d.vnew_messages, NewMessageUnread);
|
||||
feedUpdates(d.vother_updates, true);
|
||||
|
||||
// feed messages and groups, copy from App::feedMsgs
|
||||
History *h = App::history(channel->id);
|
||||
const QVector<MTPMessage> &vmsgs(d.vnew_messages.c_vector().v);
|
||||
QMap<uint64, int32> msgsIds;
|
||||
for (int32 i = 0, l = vmsgs.size(); i < l; ++i) {
|
||||
const MTPMessage &msg(vmsgs.at(i));
|
||||
switch (msg.type()) {
|
||||
case mtpc_message: {
|
||||
const MTPDmessage &d(msg.c_message());
|
||||
msgsIds.insert((uint64(uint32(d.vid.v)) << 32) | uint64(i), i + 1);
|
||||
App::checkEntitiesAndViewsUpdate(d); // new message, index my forwarded messages to links overview
|
||||
} break;
|
||||
case mtpc_messageEmpty: msgsIds.insert((uint64(uint32(msg.c_messageEmpty().vid.v)) << 32) | uint64(i), i + 1); break;
|
||||
case mtpc_messageService: msgsIds.insert((uint64(uint32(msg.c_messageService().vid.v)) << 32) | uint64(i), i + 1); break;
|
||||
}
|
||||
}
|
||||
const QVector<MTPUpdate> &vother(d.vother_updates.c_vector().v);
|
||||
for (int32 i = 0, l = vother.size(); i < l; ++i) {
|
||||
if (vother.at(i).type() == mtpc_updateChannelGroup) {
|
||||
const MTPDupdateChannelGroup &updateGroup(vother.at(i).c_updateChannelGroup());
|
||||
if (updateGroup.vgroup.type() == mtpc_messageGroup) {
|
||||
const MTPDmessageGroup &group(updateGroup.vgroup.c_messageGroup());
|
||||
if (updateGroup.vchannel_id.v != peerToChannel(channel->id)) {
|
||||
LOG(("API Error: updateChannelGroup with invalid channel_id returned in channelDifference, channelId: %1, channel_id: %2").arg(peerToChannel(channel->id)).arg(updateGroup.vchannel_id.v));
|
||||
continue;
|
||||
}
|
||||
msgsIds.insert((uint64((uint32(group.vmin_id.v) + uint32(group.vmax_id.v)) / 2) << 32), -i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (QMap<uint64, int32>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
|
||||
if (i.value() > 0) { // add message
|
||||
const MTPMessage &msg(vmsgs.at(i.value() - 1));
|
||||
if (channel->id != peerFromMessage(msg)) {
|
||||
LOG(("API Error: message with invalid peer returned in channelDifference, channelId: %1, peer: %2").arg(peerToChannel(channel->id)).arg(peerFromMessage(msg)));
|
||||
continue; // wtf
|
||||
}
|
||||
h->addNewMessage(msg, NewMessageUnread);
|
||||
} else { // add group
|
||||
const MTPDupdateChannelGroup &updateGroup(vother.at(-i.value() - 1).c_updateChannelGroup());
|
||||
h->asChannelHistory()->addNewGroup(updateGroup.vgroup);
|
||||
}
|
||||
}
|
||||
|
||||
feedUpdateVector(d.vother_updates, true);
|
||||
_handlingChannelDifference = false;
|
||||
|
||||
if (d.has_timeout()) timeout = d.vtimeout.v;
|
||||
flags = d.vflags.v;
|
||||
|
@ -2951,6 +3120,52 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
|
|||
App::emitPeerUpdated();
|
||||
}
|
||||
|
||||
void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff) {
|
||||
int32 flags = 0, nextRequestPts = 0;
|
||||
switch (diff.type()) {
|
||||
case mtpc_updates_channelDifferenceEmpty: {
|
||||
const MTPDupdates_channelDifferenceEmpty &d(diff.c_updates_channelDifferenceEmpty());
|
||||
flags = d.vflags.v;
|
||||
nextRequestPts = d.vpts.v;
|
||||
} break;
|
||||
|
||||
case mtpc_updates_channelDifferenceTooLong: {
|
||||
const MTPDupdates_channelDifferenceTooLong &d(diff.c_updates_channelDifferenceTooLong());
|
||||
|
||||
App::feedUsers(d.vusers);
|
||||
App::feedChats(d.vchats);
|
||||
|
||||
flags = d.vflags.v;
|
||||
nextRequestPts = d.vpts.v;
|
||||
} break;
|
||||
|
||||
case mtpc_updates_channelDifference: {
|
||||
const MTPDupdates_channelDifference &d(diff.c_updates_channelDifference());
|
||||
|
||||
App::feedUsers(d.vusers);
|
||||
App::feedChats(d.vchats, false);
|
||||
|
||||
_handlingChannelDifference = true;
|
||||
feedMessageIds(d.vother_updates);
|
||||
App::feedMsgs(d.vnew_messages, NewMessageUnread);
|
||||
feedUpdateVector(d.vother_updates, true);
|
||||
_handlingChannelDifference = false;
|
||||
|
||||
flags = d.vflags.v;
|
||||
nextRequestPts = d.vpts.v;
|
||||
} break;
|
||||
}
|
||||
|
||||
if (!(flags & MTPupdates_ChannelDifference_flag_final)) {
|
||||
if (History *h = App::historyLoaded(channel->id)) {
|
||||
MTP_LOG(0, ("getChannelDifference { good - after not final channelDifference was received, validating history part }%1").arg(cTestMode() ? " TESTMODE" : ""));
|
||||
h->asChannelHistory()->getRangeDifferenceNext(nextRequestPts);
|
||||
}
|
||||
}
|
||||
|
||||
App::emitPeerUpdated();
|
||||
}
|
||||
|
||||
bool MainWidget::failChannelDifference(ChannelData *channel, const RPCError &error) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
|
||||
|
@ -2963,7 +3178,6 @@ void MainWidget::gotState(const MTPupdates_State &state) {
|
|||
const MTPDupdates_state &d(state.c_updates_state());
|
||||
updSetState(d.vpts.v, d.vdate.v, d.vqts.v, d.vseq.v);
|
||||
|
||||
MTP::setGlobalDoneHandler(rpcDone(&MainWidget::updateReceived));
|
||||
_lastUpdateTime = getms(true);
|
||||
noUpdatesTimer.start(NoUpdatesTimeout);
|
||||
_ptsWaiter.setRequesting(false);
|
||||
|
@ -2982,7 +3196,6 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
|
|||
const MTPDupdates_differenceEmpty &d(diff.c_updates_differenceEmpty());
|
||||
updSetState(_ptsWaiter.current(), d.vdate.v, updQts, d.vseq.v);
|
||||
|
||||
MTP::setGlobalDoneHandler(rpcDone(&MainWidget::updateReceived));
|
||||
_lastUpdateTime = getms(true);
|
||||
noUpdatesTimer.start(NoUpdatesTimeout);
|
||||
|
||||
|
@ -3104,7 +3317,7 @@ void MainWidget::feedDifference(const MTPVector<MTPUser> &users, const MTPVector
|
|||
App::feedChats(chats, false);
|
||||
feedMessageIds(other);
|
||||
App::feedMsgs(msgs, NewMessageUnread);
|
||||
feedUpdates(other, true);
|
||||
feedUpdateVector(other, true);
|
||||
history.peerMessagesUpdated();
|
||||
}
|
||||
|
||||
|
@ -3188,7 +3401,6 @@ void MainWidget::getDifference() {
|
|||
|
||||
LOG(("Getting difference for %1, %2").arg(_ptsWaiter.current()).arg(updDate));
|
||||
_ptsWaiter.setRequesting(true);
|
||||
MTP::setGlobalDoneHandler(RPCDoneHandlerPtr(0));
|
||||
MTP::send(MTPupdates_GetDifference(MTP_int(_ptsWaiter.current()), MTP_int(updDate), MTP_int(updQts)), rpcDone(&MainWidget::gotDifference), rpcFail(&MainWidget::failDifference));
|
||||
}
|
||||
|
||||
|
@ -3213,7 +3425,7 @@ void MainWidget::getChannelDifference(ChannelData *channel, GetChannelDifference
|
|||
if (activePeer() == channel) {
|
||||
filter = MTP_channelMessagesFilterEmpty();
|
||||
} else {
|
||||
filter = MTP_channelMessagesFilterCollapsed();
|
||||
filter = MTP_channelMessagesFilterEmpty(); //MTP_channelMessagesFilterCollapsed(); - not supported
|
||||
if (History *history = App::historyLoaded(channel->id)) {
|
||||
if (!history->asChannelHistory()->onlyImportant()) {
|
||||
MsgId fixInScrollMsgId = 0;
|
||||
|
@ -3225,7 +3437,7 @@ void MainWidget::getChannelDifference(ChannelData *channel, GetChannelDifference
|
|||
}
|
||||
}
|
||||
}
|
||||
MTP::send(MTPupdates_GetChannelDifference(channel->inputChannel, filter, MTP_int(channel->pts()), MTP_int(3/*MTPChannelGetDifferenceLimit*/)), rpcDone(&MainWidget::gotChannelDifference, channel), rpcFail(&MainWidget::failChannelDifference, channel));
|
||||
MTP::send(MTPupdates_GetChannelDifference(channel->inputChannel, filter, MTP_int(channel->pts()), MTP_int(MTPChannelGetDifferenceLimit)), rpcDone(&MainWidget::gotChannelDifference, channel), rpcFail(&MainWidget::failChannelDifference, channel));
|
||||
}
|
||||
|
||||
void MainWidget::mtpPing() {
|
||||
|
@ -3327,6 +3539,26 @@ void MainWidget::onStickersInstalled(uint64 setId) {
|
|||
history.stickersInstalled(setId);
|
||||
}
|
||||
|
||||
void MainWidget::onFullPeerUpdated(PeerData *peer) {
|
||||
emit peerUpdated(peer);
|
||||
}
|
||||
|
||||
void MainWidget::onSelfParticipantUpdated(ChannelData *channel) {
|
||||
History *h = App::historyLoaded(channel->id);
|
||||
if (_updatedChannels.contains(channel)) {
|
||||
_updatedChannels.remove(channel);
|
||||
if ((h ? h : App::history(channel->id))->isEmpty()) {
|
||||
checkPeerHistory(channel);
|
||||
} else {
|
||||
h->asChannelHistory()->checkJoinedMessage();
|
||||
history.peerMessagesUpdated(channel->id);
|
||||
}
|
||||
} else if (h) {
|
||||
h->asChannelHistory()->checkJoinedMessage();
|
||||
history.peerMessagesUpdated(channel->id);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPcontacts_ResolvedPeer &result) {
|
||||
App::wnd()->hideLayer();
|
||||
if (result.type() != mtpc_contacts_resolvedPeer) return;
|
||||
|
@ -3370,7 +3602,8 @@ void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) {
|
|||
switch (invite.type()) {
|
||||
case mtpc_chatInvite: {
|
||||
const MTPDchatInvite &d(invite.c_chatInvite());
|
||||
ConfirmBox *box = new ConfirmBox(lng_group_invite_want_join(lt_title, qs(d.vtitle)), lang(lng_group_invite_join));
|
||||
bool isChannel = (d.vflags.v & MTPDchatInvite_flag_is_channel);
|
||||
ConfirmBox *box = new ConfirmBox((isChannel ? lng_group_invite_want_join_channel : lng_group_invite_want_join)(lt_title, qs(d.vtitle)), lang(lng_group_invite_join));
|
||||
_inviteHash = hash;
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onInviteImport()));
|
||||
App::wnd()->showLayer(box);
|
||||
|
@ -3380,7 +3613,7 @@ void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) {
|
|||
const MTPDchatInviteAlready &d(invite.c_chatInviteAlready());
|
||||
PeerData *chat = App::feedChats(MTP_vector<MTPChat>(1, d.vchat));
|
||||
if (chat) {
|
||||
if ((chat->isChat() && chat->asChat()->left) || (chat->isChannel() && chat->asChannel()->left)) {
|
||||
if (chat->isChat() && chat->asChat()->haveLeft) {
|
||||
ConfirmBox *box = new ConfirmBox(lng_group_invite_want_join(lt_title, chat->name), lang(lng_group_invite_join));
|
||||
_inviteHash = '/' + QString::number(chat->id);
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onInviteImport()));
|
||||
|
@ -3431,8 +3664,12 @@ void MainWidget::inviteImportDone(const MTPUpdates &updates) {
|
|||
case mtpc_updatesTooLong: {
|
||||
} break;
|
||||
}
|
||||
if (v && !v->isEmpty() && v->front().type() == mtpc_chat) {
|
||||
App::main()->showPeerHistory(peerFromChat(v->front().c_chat().vid.v), ShowAtTheEndMsgId);
|
||||
if (v && !v->isEmpty()) {
|
||||
if (v->front().type() == mtpc_chat) {
|
||||
App::main()->showPeerHistory(peerFromChat(v->front().c_chat().vid.v), ShowAtTheEndMsgId);
|
||||
} else if (v->front().type() == mtpc_channel) {
|
||||
App::main()->showPeerHistory(peerFromChannel(v->front().c_channel().vid.v), ShowAtTheEndMsgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3453,7 +3690,7 @@ void MainWidget::startFull(const MTPVector<MTPUser> &users) {
|
|||
start(v[0]);
|
||||
}
|
||||
|
||||
void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *history) {
|
||||
void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *h) {
|
||||
switch (settings.type()) {
|
||||
case mtpc_peerNotifySettingsEmpty:
|
||||
switch (peer.type()) {
|
||||
|
@ -3468,8 +3705,11 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti
|
|||
}
|
||||
data->notify = EmptyNotifySettings;
|
||||
App::unregMuted(data);
|
||||
History *h = App::history(data->id);
|
||||
if (!h) h = App::history(data->id);
|
||||
h->setMute(false);
|
||||
if (history.peer() == data) {
|
||||
history.updateNotifySettings();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -3499,14 +3739,17 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti
|
|||
setTo->previews = d.vshow_previews.v;
|
||||
setTo->events = d.vevents_mask.v;
|
||||
if (data) {
|
||||
if (!history) history = App::history(data->id);
|
||||
if (!h) h = App::history(data->id);
|
||||
int32 changeIn = 0;
|
||||
if (isNotifyMuted(setTo, &changeIn)) {
|
||||
App::wnd()->notifyClear(history);
|
||||
history->setMute(true);
|
||||
App::wnd()->notifyClear(h);
|
||||
h->setMute(true);
|
||||
App::regMuted(data, changeIn);
|
||||
} else {
|
||||
history->setMute(false);
|
||||
h->setMute(false);
|
||||
}
|
||||
if (history.peer() == data) {
|
||||
history.updateNotifySettings();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -3528,6 +3771,7 @@ void MainWidget::gotNotifySetting(MTPInputNotifyPeer peer, const MTPPeerNotifySe
|
|||
case mtpc_inputPeerSelf: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(MTP::authedId()))), settings); break;
|
||||
case mtpc_inputPeerUser: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerUser().vuser_id)), settings); break;
|
||||
case mtpc_inputPeerChat: applyNotifySetting(MTP_notifyPeer(MTP_peerChat(peer.c_inputNotifyPeer().vpeer.c_inputPeerChat().vchat_id)), settings); break;
|
||||
case mtpc_inputPeerChannel: applyNotifySetting(MTP_notifyPeer(MTP_peerChannel(peer.c_inputNotifyPeer().vpeer.c_inputPeerChannel().vchannel_id)), settings); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3563,6 +3807,7 @@ void MainWidget::updateNotifySetting(PeerData *peer, bool enabled) {
|
|||
App::unregMuted(peer);
|
||||
}
|
||||
App::history(peer->id)->setMute(!enabled);
|
||||
if (history.peer() == peer) history.updateNotifySettings();
|
||||
updateNotifySettingTimer.start(NotifySettingSaveTimeout);
|
||||
}
|
||||
|
||||
|
@ -3759,7 +4004,7 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
|
|||
if (end <= from || !MTP::authedId()) return;
|
||||
|
||||
App::wnd()->checkAutoLock();
|
||||
|
||||
|
||||
if (mtpTypeId(*from) == mtpc_new_session_created) {
|
||||
MTPNewSession newSession(from, end);
|
||||
updSeq = 0;
|
||||
|
@ -3771,8 +4016,9 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
|
|||
|
||||
_lastUpdateTime = getms(true);
|
||||
noUpdatesTimer.start(NoUpdatesTimeout);
|
||||
|
||||
handleUpdates(updates);
|
||||
if (!_ptsWaiter.requesting()) {
|
||||
feedUpdates(updates);
|
||||
}
|
||||
App::emitPeerUpdated();
|
||||
} catch (mtpErrorUnexpected &e) { // just some other type
|
||||
}
|
||||
|
@ -3780,7 +4026,7 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
|
|||
update();
|
||||
}
|
||||
|
||||
void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) {
|
||||
void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
||||
switch (updates.type()) {
|
||||
case mtpc_updates: {
|
||||
const MTPDupdates &d(updates.c_updates());
|
||||
|
@ -3794,7 +4040,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
|
||||
App::feedUsers(d.vusers, false);
|
||||
App::feedChats(d.vchats, false);
|
||||
feedUpdates(d.vupdates);
|
||||
feedUpdateVector(d.vupdates);
|
||||
|
||||
updSetState(0, d.vdate.v, updQts, d.vseq.v);
|
||||
} break;
|
||||
|
@ -3811,7 +4057,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
|
||||
App::feedUsers(d.vusers, false);
|
||||
App::feedChats(d.vchats, false);
|
||||
feedUpdates(d.vupdates);
|
||||
feedUpdateVector(d.vupdates);
|
||||
|
||||
updSetState(0, d.vdate.v, updQts, d.vseq.v);
|
||||
} break;
|
||||
|
@ -3891,7 +4137,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
item->setText(text, d.has_entities() ? linksFromMTP(d.ventities.c_vector().v) : LinksInText());
|
||||
item->initDimensions();
|
||||
itemResized(item);
|
||||
if (!was && item->hasTextLinks()) {
|
||||
if (!was && item->hasTextLinks() && (!item->history()->isChannel() || item->fromChannel())) {
|
||||
item->history()->addToOverview(item, OverviewLinks);
|
||||
}
|
||||
}
|
||||
|
@ -4255,15 +4501,40 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
|
||||
case mtpc_updateChannel: {
|
||||
const MTPDupdateChannel &d(update.c_updateChannel());
|
||||
App::markPeerUpdated(App::channelLoaded(d.vchannel_id.v));
|
||||
if (ChannelData *channel = App::channelLoaded(d.vchannel_id.v)) {
|
||||
App::markPeerUpdated(channel);
|
||||
if (channel->isForbidden || channel->wasKicked() || channel->haveLeft()) {
|
||||
dialogs.removePeer(channel);
|
||||
if (History *h = App::historyLoaded(channel->id)) {
|
||||
h->clear(true);
|
||||
h->asChannelHistory()->clearOther();
|
||||
}
|
||||
channel->ptsWaitingForShortPoll(-1);
|
||||
channel->inviter = 0;
|
||||
if (activePeer() == channel) {
|
||||
showDialogs();
|
||||
}
|
||||
} else if (!channel->amCreator() && App::history(channel->id)) { // create history
|
||||
_updatedChannels.insert(channel, true);
|
||||
if (channel->inviter) {
|
||||
checkPeerHistory(channel);
|
||||
} else {
|
||||
App::api()->requestSelfParticipant(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateNewChannelMessage: {
|
||||
const MTPDupdateNewChannelMessage &d(update.c_updateNewChannelMessage());
|
||||
ChannelData *channel = App::channelLoaded(peerToChannel(peerFromMessage(d.vmessage)));
|
||||
|
||||
if (channel && !channel->ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
|
||||
return;
|
||||
if (channel && !_handlingChannelDifference) {
|
||||
if (channel->ptsRequesting()) { // skip global updates while getting channel difference
|
||||
return;
|
||||
} else if (!channel->ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// update before applying skipped
|
||||
|
@ -4275,13 +4546,14 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
history.peerMessagesUpdated(item->history()->peer->id);
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
if (channel && !_handlingChannelDifference) {
|
||||
channel->ptsApplySkippedUpdates();
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateReadChannelInbox: {
|
||||
const MTPDupdateReadChannelInbox &d(update.c_updateReadChannelInbox());
|
||||
ChannelData *channel = App::channelLoaded(d.vchannel_id.v);
|
||||
App::feedInboxRead(peerFromChannel(d.vchannel_id.v), d.vmax_id.v);
|
||||
} break;
|
||||
|
||||
|
@ -4289,27 +4561,26 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
const MTPDupdateDeleteChannelMessages &d(update.c_updateDeleteChannelMessages());
|
||||
ChannelData *channel = App::channelLoaded(d.vchannel_id.v);
|
||||
|
||||
if (channel && !channel->ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
|
||||
return;
|
||||
if (channel && !_handlingChannelDifference) {
|
||||
if (channel->ptsRequesting()) { // skip global updates while getting channel difference
|
||||
return;
|
||||
} else if (!channel->ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// update before applying skipped
|
||||
App::feedWereDeleted(d.vchannel_id.v, d.vmessages.c_vector().v);
|
||||
history.peerMessagesUpdated();
|
||||
|
||||
if (channel) {
|
||||
if (channel && !_handlingChannelDifference) {
|
||||
channel->ptsApplySkippedUpdates();
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateChannelGroup: {
|
||||
const MTPDupdateChannelGroup &d(update.c_updateChannelGroup());
|
||||
ChannelData *channel = App::channelLoaded(d.vchannel_id.v);
|
||||
if (channel) {
|
||||
if (d.vgroup.type() == mtpc_messageGroup) {
|
||||
const MTPDmessageGroup &data(d.vgroup.c_messageGroup());
|
||||
// CHANNELS_FULL
|
||||
}
|
||||
if (!_handlingChannelDifference) {
|
||||
LOG(("API Error: got updateChannelGroup not in channelDifference!"));
|
||||
}
|
||||
} break;
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ public:
|
|||
|
||||
void activate();
|
||||
|
||||
void createDialogAtTop(History *history, int32 unreadCount);
|
||||
void createDialog(History *history);
|
||||
void dlgUpdated(DialogRow *row);
|
||||
void dlgUpdated(History *row);
|
||||
|
||||
|
@ -324,7 +324,7 @@ public:
|
|||
void sendBotCommand(const QString &cmd, MsgId msgId);
|
||||
void insertBotCommand(const QString &cmd);
|
||||
|
||||
void searchMessages(const QString &query);
|
||||
void searchMessages(const QString &query, PeerData *inPeer);
|
||||
void preloadOverviews(PeerData *peer);
|
||||
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||
|
@ -365,7 +365,7 @@ public:
|
|||
void fillForwardingInfo(Text *&from, Text *&text, bool &serviceColor, ImagePtr &preview);
|
||||
void updateForwardingTexts();
|
||||
void cancelForwarding();
|
||||
void finishForwarding(History *hist); // send them
|
||||
void finishForwarding(History *hist, bool broadcast); // send them
|
||||
|
||||
void audioMarkRead(AudioData *data);
|
||||
void videoMarkRead(VideoData *data);
|
||||
|
@ -383,15 +383,20 @@ public:
|
|||
void contactsReceived();
|
||||
|
||||
void ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer
|
||||
void handleUpdates(const MTPUpdates &updates, uint64 randomId = 0);
|
||||
void feedUpdates(const MTPUpdates &updates, uint64 randomId = 0);
|
||||
void feedUpdate(const MTPUpdate &update);
|
||||
void updateAfterDrag();
|
||||
|
||||
void ctrlEnterSubmitUpdated();
|
||||
void setInnerFocus();
|
||||
|
||||
void scheduleViewIncrement(HistoryItem *item);
|
||||
|
||||
HistoryItem *atTopImportantMsg(int32 &bottomUnderScrollTop) const;
|
||||
|
||||
void gotRangeDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff);
|
||||
void onSelfParticipantUpdated(ChannelData *channel);
|
||||
|
||||
~MainWidget();
|
||||
|
||||
signals:
|
||||
|
@ -459,6 +464,9 @@ public slots:
|
|||
void onUpdateMuted();
|
||||
|
||||
void onStickersInstalled(uint64 setId);
|
||||
void onFullPeerUpdated(PeerData *peer);
|
||||
|
||||
void onViewsIncrement();
|
||||
|
||||
private:
|
||||
|
||||
|
@ -503,7 +511,7 @@ private:
|
|||
bool failChannelDifference(ChannelData *channel, const RPCError &err);
|
||||
void failDifferenceStartTimerFor(ChannelData *channel);
|
||||
|
||||
void feedUpdates(const MTPVector<MTPUpdate> &updates, bool skipMessageIds = false);
|
||||
void feedUpdateVector(const MTPVector<MTPUpdate> &updates, bool skipMessageIds = false);
|
||||
void feedMessageIds(const MTPVector<MTPUpdate> &updates);
|
||||
|
||||
void updateReceived(const mtpPrime *from, const mtpPrime *end);
|
||||
|
@ -591,12 +599,27 @@ private:
|
|||
SingleTimer _failDifferenceTimer;
|
||||
|
||||
uint64 _lastUpdateTime;
|
||||
bool _handlingChannelDifference;
|
||||
|
||||
QPixmap _cachedBackground;
|
||||
QRect _cachedFor, _willCacheFor;
|
||||
int _cachedX, _cachedY;
|
||||
SingleTimer _cacheBackgroundTimer;
|
||||
|
||||
typedef QMap<ChannelData*, bool> UpdatedChannels;
|
||||
UpdatedChannels _updatedChannels;
|
||||
|
||||
typedef QMap<MsgId, bool> ViewsIncrementMap;
|
||||
typedef QMap<PeerData*, ViewsIncrementMap> ViewsIncrement;
|
||||
ViewsIncrement _viewsIncremented, _viewsToIncrement;
|
||||
typedef QMap<PeerData*, mtpRequestId> ViewsIncrementRequests;
|
||||
ViewsIncrementRequests _viewsIncrementRequests;
|
||||
typedef QMap<mtpRequestId, PeerData*> ViewsIncrementByRequest;
|
||||
ViewsIncrementByRequest _viewsIncrementByRequest;
|
||||
SingleTimer _viewsIncrementTimer;
|
||||
void viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req);
|
||||
bool viewsIncrementFail(const RPCError &error, mtpRequestId req);
|
||||
|
||||
App::WallPaper *_background;
|
||||
|
||||
ApiWrap *_api;
|
||||
|
|
|
@ -661,8 +661,8 @@ void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) {
|
|||
_index = -1;
|
||||
_msgid = context ? context->id : 0;
|
||||
_channel = context ? context->channelId() : NoChannel;
|
||||
_canForward = _msgid > 0 && (_channel == NoChannel);
|
||||
_canDelete = (_channel == NoChannel) || context->history()->peer->asChannel()->adminned;
|
||||
_canForward = _msgid > 0;
|
||||
_canDelete = context ? context->canDelete() : false;
|
||||
_photo = photo;
|
||||
if (_history) {
|
||||
_overview = OverviewPhotos;
|
||||
|
@ -734,8 +734,8 @@ void MediaView::showDocument(DocumentData *doc, HistoryItem *context) {
|
|||
_index = -1;
|
||||
_msgid = context ? context->id : 0;
|
||||
_channel = context ? context->channelId() : NoChannel;
|
||||
_canForward = _msgid > 0 && (_channel == NoChannel);
|
||||
_canDelete = (_channel == NoChannel) || context->history()->peer->asChannel()->adminned;
|
||||
_canForward = _msgid > 0;
|
||||
_canDelete = context ? context->canDelete() : false;
|
||||
if (_history) {
|
||||
_overview = OverviewDocuments;
|
||||
|
||||
|
@ -1396,8 +1396,8 @@ void MediaView::moveToNext(int32 delta) {
|
|||
if (HistoryItem *item = App::histItemById(_history->channelId(), _history->overview[_overview][_index])) {
|
||||
_msgid = item->id;
|
||||
_channel = item->channelId();
|
||||
_canForward = _msgid > 0 && (_channel == NoChannel);
|
||||
_canDelete = (_channel == NoChannel) || item->history()->peer->asChannel()->adminned;
|
||||
_canForward = _msgid > 0;
|
||||
_canDelete = item->canDelete();
|
||||
if (item->getMedia()) {
|
||||
switch (item->getMedia()->type()) {
|
||||
case MediaTypePhoto: displayPhoto(static_cast<HistoryPhoto*>(item->getMedia())->photo(), item); preloadData(delta); break;
|
||||
|
@ -1661,10 +1661,21 @@ void MediaView::updateOver(QPoint pos) {
|
|||
|
||||
void MediaView::mouseReleaseEvent(QMouseEvent *e) {
|
||||
updateOver(e->pos());
|
||||
if (textlnkDown() && textlnkOver() == textlnkDown()) {
|
||||
textlnkDown()->onClick(e->button());
|
||||
}
|
||||
TextLinkPtr lnk = textlnkDown();
|
||||
textlnkDown(TextLinkPtr());
|
||||
if (lnk && textlnkOver() == lnk) {
|
||||
if (reHashtag().match(lnk->encoded()).hasMatch() && _history && _history->isChannel()) {
|
||||
App::wnd()->hideMediaview();
|
||||
App::searchByHashtag(lnk->encoded(), _history->peer);
|
||||
} else {
|
||||
if (reBotCommand().match(lnk->encoded()).hasMatch() && _history->peer->isUser() && _history->peer->asUser()->botInfo) {
|
||||
App::wnd()->hideMediaview();
|
||||
App::main()->showPeerHistory(_history->peer->id, ShowAtTheEndMsgId);
|
||||
}
|
||||
lnk->onClick(e->button());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (_over == OverName && _down == OverName) {
|
||||
if (App::wnd() && _from) {
|
||||
close();
|
||||
|
@ -1924,8 +1935,10 @@ void MediaView::updateHeader() {
|
|||
_headerText = _doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name;
|
||||
} else if (_user) {
|
||||
_headerText = lang(lng_mediaview_profile_photo);
|
||||
} else if (_peer) {
|
||||
} else if (_channel) {
|
||||
_headerText = lang(lng_mediaview_group_photo);
|
||||
} else if (_peer) {
|
||||
_headerText = lang(lng_mediaview_channel_photo);
|
||||
} else {
|
||||
_headerText = lang(lng_mediaview_single_photo);
|
||||
}
|
||||
|
|
|
@ -54,17 +54,24 @@ enum {
|
|||
MTPDstickerSet_flag_official = (1 << 2),
|
||||
MTPDstickerSet_flag_NOT_LOADED = (1 << 31), // client side flag for not yet loaded set
|
||||
|
||||
MTPDchannel_flag_am_admin = (1 << 0),
|
||||
MTPDchannel_flag_am_creator = (1 << 0),
|
||||
MTPDchannel_flag_was_kicked = (1 << 1),
|
||||
MTPDchannel_flag_have_left = (1 << 2),
|
||||
MTPDchannel_flag_am_publisher = (1 << 3),
|
||||
MTPDchannel_flag_am_editor = (1 << 3),
|
||||
MTPDchannel_flag_am_moderator = (1 << 4),
|
||||
MTPDchannel_flag_is_broadcast = (1 << 5),
|
||||
MTPDchannel_flag_is_verified = (1 << 7),
|
||||
|
||||
MTPDchannelFull_flag_can_view_participants = (1 << 3),
|
||||
|
||||
MTPDchat_flag_creator = (1 << 0),
|
||||
MTPDchat_flag_kicked = (1 << 1),
|
||||
MTPDchat_flag_left = (1 << 2),
|
||||
|
||||
MTPDchatInvite_flag_is_channel = (1 << 0),
|
||||
MTPDchatInvite_flag_is_broadcast = (1 << 1),
|
||||
MTPDchatInvite_flag_is_public = (1 << 2),
|
||||
|
||||
MTPupdates_ChannelDifference_flag_final = (1 << 0),
|
||||
|
||||
MTPDchannelMessagesFilter_flag_only_important = (1 << 0),
|
||||
|
|
|
@ -4202,7 +4202,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
|
|||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
break;
|
||||
|
@ -5358,6 +5359,21 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
|
|||
}
|
||||
break;
|
||||
|
||||
case mtpc_channels_reportSpam:
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ channels_reportSpam");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" channel: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" user_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 2: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_int); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case mtpc_channels_editAbout:
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -6044,6 +6060,20 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
|
|||
}
|
||||
break;
|
||||
|
||||
case mtpc_channels_deleteUserHistory:
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ channels_deleteUserHistory");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" channel: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" user_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case mtpc_messages_deleteMessages:
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
|
|
@ -371,7 +371,7 @@ enum {
|
|||
mtpc_chatInviteEmpty = 0x69df3769,
|
||||
mtpc_chatInviteExported = 0xfc2e05bc,
|
||||
mtpc_chatInviteAlready = 0x5a686d7c,
|
||||
mtpc_chatInvite = 0xce917dcd,
|
||||
mtpc_chatInvite = 0x93e99b60,
|
||||
mtpc_inputStickerSetEmpty = 0xffb62b95,
|
||||
mtpc_inputStickerSetID = 0x9de7a269,
|
||||
mtpc_inputStickerSetShortName = 0x861cc8a0,
|
||||
|
@ -547,6 +547,8 @@ enum {
|
|||
mtpc_channels_getImportantHistory = 0xddb929cb,
|
||||
mtpc_channels_readHistory = 0xcc104937,
|
||||
mtpc_channels_deleteMessages = 0x84c1fd4e,
|
||||
mtpc_channels_deleteUserHistory = 0xd10dd71b,
|
||||
mtpc_channels_reportSpam = 0xfe087810,
|
||||
mtpc_channels_getMessages = 0x93d7b347,
|
||||
mtpc_channels_getParticipants = 0x24d98f92,
|
||||
mtpc_channels_getParticipant = 0x546dd7a6,
|
||||
|
@ -7631,7 +7633,7 @@ private:
|
|||
explicit MTPchatInvite(MTPDchatInvite *_data);
|
||||
|
||||
friend MTPchatInvite MTP_chatInviteAlready(const MTPChat &_chat);
|
||||
friend MTPchatInvite MTP_chatInvite(const MTPstring &_title);
|
||||
friend MTPchatInvite MTP_chatInvite(MTPint _flags, const MTPstring &_title);
|
||||
|
||||
mtpTypeId _type;
|
||||
};
|
||||
|
@ -11816,9 +11818,10 @@ class MTPDchatInvite : public mtpDataImpl<MTPDchatInvite> {
|
|||
public:
|
||||
MTPDchatInvite() {
|
||||
}
|
||||
MTPDchatInvite(const MTPstring &_title) : vtitle(_title) {
|
||||
MTPDchatInvite(MTPint _flags, const MTPstring &_title) : vflags(_flags), vtitle(_title) {
|
||||
}
|
||||
|
||||
MTPint vflags;
|
||||
MTPstring vtitle;
|
||||
};
|
||||
|
||||
|
@ -17853,6 +17856,93 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MTPchannels_deleteUserHistory { // RPC method 'channels.deleteUserHistory'
|
||||
public:
|
||||
MTPInputChannel vchannel;
|
||||
MTPInputUser vuser_id;
|
||||
|
||||
MTPchannels_deleteUserHistory() {
|
||||
}
|
||||
MTPchannels_deleteUserHistory(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_channels_deleteUserHistory) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPchannels_deleteUserHistory(const MTPInputChannel &_channel, const MTPInputUser &_user_id) : vchannel(_channel), vuser_id(_user_id) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
return vchannel.innerLength() + vuser_id.innerLength();
|
||||
}
|
||||
mtpTypeId type() const {
|
||||
return mtpc_channels_deleteUserHistory;
|
||||
}
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_channels_deleteUserHistory) {
|
||||
vchannel.read(from, end);
|
||||
vuser_id.read(from, end);
|
||||
}
|
||||
void write(mtpBuffer &to) const {
|
||||
vchannel.write(to);
|
||||
vuser_id.write(to);
|
||||
}
|
||||
|
||||
typedef MTPmessages_AffectedHistory ResponseType;
|
||||
};
|
||||
class MTPchannels_DeleteUserHistory : public MTPBoxed<MTPchannels_deleteUserHistory> {
|
||||
public:
|
||||
MTPchannels_DeleteUserHistory() {
|
||||
}
|
||||
MTPchannels_DeleteUserHistory(const MTPchannels_deleteUserHistory &v) : MTPBoxed<MTPchannels_deleteUserHistory>(v) {
|
||||
}
|
||||
MTPchannels_DeleteUserHistory(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPchannels_deleteUserHistory>(from, end, cons) {
|
||||
}
|
||||
MTPchannels_DeleteUserHistory(const MTPInputChannel &_channel, const MTPInputUser &_user_id) : MTPBoxed<MTPchannels_deleteUserHistory>(MTPchannels_deleteUserHistory(_channel, _user_id)) {
|
||||
}
|
||||
};
|
||||
|
||||
class MTPchannels_reportSpam { // RPC method 'channels.reportSpam'
|
||||
public:
|
||||
MTPInputChannel vchannel;
|
||||
MTPInputUser vuser_id;
|
||||
MTPVector<MTPint> vid;
|
||||
|
||||
MTPchannels_reportSpam() {
|
||||
}
|
||||
MTPchannels_reportSpam(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_channels_reportSpam) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPchannels_reportSpam(const MTPInputChannel &_channel, const MTPInputUser &_user_id, const MTPVector<MTPint> &_id) : vchannel(_channel), vuser_id(_user_id), vid(_id) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
return vchannel.innerLength() + vuser_id.innerLength() + vid.innerLength();
|
||||
}
|
||||
mtpTypeId type() const {
|
||||
return mtpc_channels_reportSpam;
|
||||
}
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_channels_reportSpam) {
|
||||
vchannel.read(from, end);
|
||||
vuser_id.read(from, end);
|
||||
vid.read(from, end);
|
||||
}
|
||||
void write(mtpBuffer &to) const {
|
||||
vchannel.write(to);
|
||||
vuser_id.write(to);
|
||||
vid.write(to);
|
||||
}
|
||||
|
||||
typedef MTPBool ResponseType;
|
||||
};
|
||||
class MTPchannels_ReportSpam : public MTPBoxed<MTPchannels_reportSpam> {
|
||||
public:
|
||||
MTPchannels_ReportSpam() {
|
||||
}
|
||||
MTPchannels_ReportSpam(const MTPchannels_reportSpam &v) : MTPBoxed<MTPchannels_reportSpam>(v) {
|
||||
}
|
||||
MTPchannels_ReportSpam(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPchannels_reportSpam>(from, end, cons) {
|
||||
}
|
||||
MTPchannels_ReportSpam(const MTPInputChannel &_channel, const MTPInputUser &_user_id, const MTPVector<MTPint> &_id) : MTPBoxed<MTPchannels_reportSpam>(MTPchannels_reportSpam(_channel, _user_id, _id)) {
|
||||
}
|
||||
};
|
||||
|
||||
class MTPchannels_getMessages { // RPC method 'channels.getMessages'
|
||||
public:
|
||||
MTPInputChannel vchannel;
|
||||
|
@ -27150,7 +27240,7 @@ inline uint32 MTPchatInvite::innerLength() const {
|
|||
}
|
||||
case mtpc_chatInvite: {
|
||||
const MTPDchatInvite &v(c_chatInvite());
|
||||
return v.vtitle.innerLength();
|
||||
return v.vflags.innerLength() + v.vtitle.innerLength();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -27170,6 +27260,7 @@ inline void MTPchatInvite::read(const mtpPrime *&from, const mtpPrime *end, mtpT
|
|||
case mtpc_chatInvite: _type = cons; {
|
||||
if (!data) setData(new MTPDchatInvite());
|
||||
MTPDchatInvite &v(_chatInvite());
|
||||
v.vflags.read(from, end);
|
||||
v.vtitle.read(from, end);
|
||||
} break;
|
||||
default: throw mtpErrorUnexpected(cons, "MTPchatInvite");
|
||||
|
@ -27183,6 +27274,7 @@ inline void MTPchatInvite::write(mtpBuffer &to) const {
|
|||
} break;
|
||||
case mtpc_chatInvite: {
|
||||
const MTPDchatInvite &v(c_chatInvite());
|
||||
v.vflags.write(to);
|
||||
v.vtitle.write(to);
|
||||
} break;
|
||||
}
|
||||
|
@ -27201,8 +27293,8 @@ inline MTPchatInvite::MTPchatInvite(MTPDchatInvite *_data) : mtpDataOwner(_data)
|
|||
inline MTPchatInvite MTP_chatInviteAlready(const MTPChat &_chat) {
|
||||
return MTPchatInvite(new MTPDchatInviteAlready(_chat));
|
||||
}
|
||||
inline MTPchatInvite MTP_chatInvite(const MTPstring &_title) {
|
||||
return MTPchatInvite(new MTPDchatInvite(_title));
|
||||
inline MTPchatInvite MTP_chatInvite(MTPint _flags, const MTPstring &_title) {
|
||||
return MTPchatInvite(new MTPDchatInvite(_flags, _title));
|
||||
}
|
||||
|
||||
inline uint32 MTPinputStickerSet::innerLength() const {
|
||||
|
|
|
@ -544,7 +544,7 @@ chatInviteEmpty#69df3769 = ExportedChatInvite;
|
|||
chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
|
||||
|
||||
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
|
||||
chatInvite#ce917dcd title:string = ChatInvite;
|
||||
chatInvite#93e99b60 flags:# title:string = ChatInvite;
|
||||
|
||||
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
|
||||
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
||||
|
@ -754,6 +754,8 @@ channels.getDialogs#a9d3d249 offset:int limit:int = messages.Dialogs;
|
|||
channels.getImportantHistory#ddb929cb channel:InputChannel offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
|
||||
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
|
||||
channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = messages.AffectedHistory;
|
||||
channels.reportSpam#fe087810 channel:InputChannel user_id:InputUser id:Vector<int> = Bool;
|
||||
channels.getMessages#93d7b347 channel:InputChannel id:Vector<int> = messages.Messages;
|
||||
channels.getParticipants#24d98f92 channel:InputChannel filter:ChannelParticipantsFilter offset:int limit:int = channels.ChannelParticipants;
|
||||
channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channels.ChannelParticipant;
|
||||
|
|
|
@ -1799,7 +1799,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
if (App::hoveredLinkItem()->toHistoryMessage()) {
|
||||
_menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true);
|
||||
}
|
||||
if (!_peer->isChannel() || _peer->asChannel()->adminned || App::hoveredLinkItem()->out()) {
|
||||
if (App::hoveredLinkItem()->canDelete()) {
|
||||
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
@ -1839,7 +1839,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
if (App::mousedItem()->toHistoryMessage()) {
|
||||
_menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true);
|
||||
}
|
||||
if (!_peer->isChannel() || _peer->asChannel()->adminned || App::mousedItem()->out()) {
|
||||
if (App::mousedItem()->canDelete()) {
|
||||
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
@ -2100,10 +2100,8 @@ void OverviewInner::getSelectionState(int32 &selectedForForward, int32 &selected
|
|||
selectedForForward = selectedForDelete = 0;
|
||||
for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
|
||||
if (i.value() == FullItemSel) {
|
||||
if (!_peer || !_peer->isChannel() || _peer->asChannel()->adminned) {
|
||||
++selectedForDelete;
|
||||
} else if (HistoryItem *item = App::histItemById(_channel, i.key())) {
|
||||
if (item->out()) {
|
||||
if (HistoryItem *item = App::histItemById(_channel, i.key())) {
|
||||
if (item->canDelete()) {
|
||||
++selectedForDelete;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const PeerData *peer) : TWidget(0),
|
||||
_profile(profile), _scroll(scroll), _peer(App::peer(peer->id)),
|
||||
_peerUser(_peer->asUser()), _peerChat(_peer->asChat()), _peerChannel(_peer->asChannel()), _hist(App::history(peer->id)),
|
||||
_isAdmin(_peerChat ? (_peerChat->admin == MTP::authedId()) : (_peerChannel ? _peerChannel->adminned : false)),
|
||||
_amCreator(_peerChat ? (_peerChat->creator == MTP::authedId()) : (_peerChannel ? _peerChannel->amCreator() : false)),
|
||||
|
||||
_width(0), _left(0), _addToHeight(0),
|
||||
|
||||
|
@ -47,6 +47,8 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||
_invitationLink(this, qsl("telegram.me/joinchat/")),
|
||||
_botSettings(this, lang(lng_profile_bot_settings)),
|
||||
_botHelp(this, lang(lng_profile_bot_help)),
|
||||
_editLink(this, lang((_peerChannel && _peerChannel->isPublic()) ? lng_profile_edit_public_link : lng_profile_create_public_link)),
|
||||
_username(this, qsl("https://telegram.me/") + (_peerChannel ? _peerChannel->username : QString())),
|
||||
|
||||
// about
|
||||
_about(st::wndMinWidth - st::profilePadding.left() - st::profilePadding.right()),
|
||||
|
@ -64,10 +66,11 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||
// actions
|
||||
_searchInPeer(this, lang(lng_profile_search_messages)),
|
||||
_clearHistory(this, lang(lng_profile_clear_history)),
|
||||
_deleteConversation(this, lang(_peer->isUser() ? lng_profile_delete_conversation : lng_profile_clear_and_exit)),
|
||||
_deleteConversation(this, lang(_peer->isUser() ? lng_profile_delete_conversation : (_peer->isChat() ? lng_profile_clear_and_exit : lng_profile_leave_channel))),
|
||||
_wasBlocked(_peerUser ? _peerUser->blocked : UserBlockUnknown),
|
||||
_blockRequest(0),
|
||||
_blockUser(this, lang((_peerUser && _peerUser->botInfo) ? lng_profile_block_bot : lng_profile_block_user), st::btnRedLink),
|
||||
_deleteChannel(this, lang(lng_profile_delete_channel), st::btnRedLink),
|
||||
|
||||
// participants
|
||||
_pHeight(st::profileListPhotoSize + st::profileListPadding.height() * 2),
|
||||
|
@ -104,9 +107,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||
if (chatPhoto && chatPhoto->date) {
|
||||
_photoLink = TextLinkPtr(new PhotoLink(chatPhoto, _peer));
|
||||
}
|
||||
if (_peerChannel->photoId == UnknownPeerPhotoId || (_peerChannel->invitationUrl.isEmpty() && _peerChannel->adminned)) {
|
||||
App::api()->requestFullPeer(_peer);
|
||||
}
|
||||
_peerChannel->updateFull();
|
||||
}
|
||||
|
||||
// profile
|
||||
|
@ -119,7 +120,9 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||
connect(&_cancelPhoto, SIGNAL(clicked()), this, SLOT(onUpdatePhotoCancel()));
|
||||
connect(&_createInvitationLink, SIGNAL(clicked()), this, SLOT(onCreateInvitationLink()));
|
||||
connect(&_invitationLink, SIGNAL(clicked()), this, SLOT(onInvitationLink()));
|
||||
connect(&_username, SIGNAL(clicked()), this, SLOT(onPublicLink()));
|
||||
_invitationLink.setAcceptBoth(true);
|
||||
_username.setAcceptBoth(true);
|
||||
updateInvitationLink();
|
||||
|
||||
if (_peerChat) {
|
||||
|
@ -142,6 +145,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||
|
||||
connect(&_botSettings, SIGNAL(clicked()), this, SLOT(onBotSettings()));
|
||||
connect(&_botHelp, SIGNAL(clicked()), this, SLOT(onBotHelp()));
|
||||
connect(&_editLink, SIGNAL(clicked()), this, SLOT(onEditPublicLink()));
|
||||
|
||||
connect(App::app(), SIGNAL(peerPhotoDone(PeerId)), this, SLOT(onPhotoUpdateDone(PeerId)));
|
||||
connect(App::app(), SIGNAL(peerPhotoFail(PeerId)), this, SLOT(onPhotoUpdateFail(PeerId)));
|
||||
|
@ -157,6 +161,9 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||
}
|
||||
updateBotLinksVisibility();
|
||||
} else {
|
||||
if (_peerChannel && !_peerChannel->about.isEmpty()) {
|
||||
_about.setText(st::linkFont, _peerChannel->about, _historyTextOptions);
|
||||
}
|
||||
_botSettings.hide();
|
||||
_botHelp.hide();
|
||||
}
|
||||
|
@ -177,6 +184,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||
connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory()));
|
||||
connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation()));
|
||||
connect(&_blockUser, SIGNAL(clicked()), this, SLOT(onBlockUser()));
|
||||
connect(&_deleteChannel, SIGNAL(clicked()), this, SLOT(onDeleteChannel()));
|
||||
|
||||
App::contextItem(0);
|
||||
|
||||
|
@ -263,6 +271,7 @@ void ProfileInner::onUpdatePhoto() {
|
|||
}
|
||||
|
||||
void ProfileInner::onClearHistory() {
|
||||
if (_peerChannel) return;
|
||||
ConfirmBox *box = new ConfirmBox(_peer->isUser() ? lng_sure_delete_history(lt_contact, _peer->name) : lng_sure_delete_group_history(lt_group, _peer->name));
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onClearHistorySure()));
|
||||
App::wnd()->showLayer(box);
|
||||
|
@ -274,7 +283,7 @@ void ProfileInner::onClearHistorySure() {
|
|||
}
|
||||
|
||||
void ProfileInner::onDeleteConversation() {
|
||||
ConfirmBox *box = new ConfirmBox(_peer->isUser() ? lng_sure_delete_history(lt_contact, _peer->name) : lng_sure_delete_and_exit(lt_group, _peer->name));
|
||||
ConfirmBox *box = new ConfirmBox(_peer->isUser() ? lng_sure_delete_history(lt_contact, _peer->name) : (_peer->isChat() ? lng_sure_delete_and_exit(lt_group, _peer->name) : lang(lng_sure_leave_channel)));
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteConversationSure()));
|
||||
App::wnd()->showLayer(box);
|
||||
}
|
||||
|
@ -286,10 +295,27 @@ void ProfileInner::onDeleteConversationSure() {
|
|||
App::wnd()->hideLayer();
|
||||
App::main()->showDialogs();
|
||||
MTP::send(MTPmessages_DeleteChatUser(_peerChat->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _peer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _peer));
|
||||
} else if (_peerChannel) { // CHANNELS_UX
|
||||
} else if (_peerChannel) {
|
||||
App::wnd()->hideLayer();
|
||||
App::main()->showDialogs();
|
||||
MTP::send(MTPchannels_LeaveChannel(_peerChannel->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileInner::onDeleteChannel() {
|
||||
if (!_peerChannel) return;
|
||||
ConfirmBox *box = new ConfirmBox(lang(lng_sure_delete_channel), lang(lng_selected_delete_confirm), QString(), st::btnRedDone);
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteChannelSure()));
|
||||
App::wnd()->showLayer(box);
|
||||
}
|
||||
|
||||
void ProfileInner::onDeleteChannelSure() {
|
||||
if (_peerChannel) {
|
||||
App::wnd()->hideLayer();
|
||||
App::main()->showDialogs();
|
||||
MTP::send(MTPchannels_DeleteChannel(_peerChannel->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
|
||||
}
|
||||
}
|
||||
void ProfileInner::onBlockUser() {
|
||||
if (!_peerUser || _blockRequest) return;
|
||||
if (_peerUser->blocked == UserIsBlocked) {
|
||||
|
@ -371,6 +397,13 @@ void ProfileInner::onInvitationLink() {
|
|||
App::wnd()->showLayer(new ConfirmBox(lang(lng_group_invite_copied), true));
|
||||
}
|
||||
|
||||
void ProfileInner::onPublicLink() {
|
||||
if (!_peerChannel || !_peerChannel->isPublic()) return;
|
||||
|
||||
QApplication::clipboard()->setText(qsl("https://telegram.me/") + _peerChannel->username);
|
||||
App::wnd()->showLayer(new ConfirmBox(lang(lng_channel_public_link_copied), true));
|
||||
}
|
||||
|
||||
void ProfileInner::onCreateInvitationLink() {
|
||||
if (!_peerChat && !_peerChannel) return;
|
||||
|
||||
|
@ -426,6 +459,11 @@ void ProfileInner::onFullPeerUpdated(PeerData *peer) {
|
|||
resizeEvent(0);
|
||||
} else if (_peerChannel) {
|
||||
updateInvitationLink();
|
||||
if (_peerChannel->about.isEmpty()) {
|
||||
_about = Text(st::wndMinWidth - st::profilePadding.left() - st::profilePadding.right());
|
||||
} else {
|
||||
_about.setText(st::linkFont, _peerChannel->about, _historyTextOptions);
|
||||
}
|
||||
showAll();
|
||||
resizeEvent(0);
|
||||
}
|
||||
|
@ -459,6 +497,10 @@ void ProfileInner::onBotHelp() {
|
|||
updateBotLinksVisibility();
|
||||
}
|
||||
|
||||
void ProfileInner::onEditPublicLink() {
|
||||
App::wnd()->showLayer(new SetupChannelBox(_peerChannel, true), true);
|
||||
}
|
||||
|
||||
void ProfileInner::peerUpdated(PeerData *data) {
|
||||
if (data == _peer) {
|
||||
PhotoData *photo = 0;
|
||||
|
@ -473,6 +515,9 @@ void ProfileInner::peerUpdated(PeerData *data) {
|
|||
if (_peerChat->photoId && _peerChat->photoId != UnknownPeerPhotoId) photo = App::photo(_peerChat->photoId);
|
||||
} else if (_peerChannel) {
|
||||
if (_peerChannel->photoId && _peerChannel->photoId != UnknownPeerPhotoId) photo = App::photo(_peerChannel->photoId);
|
||||
if (_peerChannel->isPublic() != _invitationLink.isHidden()) {
|
||||
peerUsernameChanged();
|
||||
}
|
||||
}
|
||||
_photoLink = (photo && photo->date) ? TextLinkPtr(new PhotoLink(photo, _peer)) : TextLinkPtr();
|
||||
if (_peer->name != _nameCache) {
|
||||
|
@ -509,7 +554,7 @@ void ProfileInner::updateOnlineDisplayTimer() {
|
|||
|
||||
void ProfileInner::reorderParticipants() {
|
||||
int32 was = _participants.size(), t = unixtime(), onlineCount = 0;
|
||||
if (_peerChat && !_peerChat->forbidden) {
|
||||
if (_peerChat && !_peerChat->isForbidden) {
|
||||
if (_peerChat->count <= 0 || !_peerChat->participants.isEmpty()) {
|
||||
_participants.clear();
|
||||
for (ParticipantsData::iterator i = _participantsData.begin(), e = _participantsData.end(); i != e; ++i) {
|
||||
|
@ -555,7 +600,7 @@ void ProfileInner::reorderParticipants() {
|
|||
if (_peerUser) {
|
||||
_onlineText = App::onlineText(_peerUser, t, true);
|
||||
} else if (_peerChannel) {
|
||||
_onlineText = lang(lng_channel_status);
|
||||
_onlineText = _peerChannel->count ? lng_chat_status_members(lt_count, _peerChannel->count) : lang(lng_channel_status);
|
||||
} else {
|
||||
_onlineText = lang(lng_chat_status_unaccessible);
|
||||
}
|
||||
|
@ -568,6 +613,20 @@ void ProfileInner::reorderParticipants() {
|
|||
void ProfileInner::start() {
|
||||
}
|
||||
|
||||
void ProfileInner::peerUsernameChanged() {
|
||||
if (_peerChannel) {
|
||||
if (_peerChannel->isPublic()) {
|
||||
_username.setText(qsl("https://telegram.me/") + _peerChannel->username);
|
||||
_editLink.setText(lang(lng_profile_edit_public_link));
|
||||
} else {
|
||||
_editLink.setText(lang(lng_profile_create_public_link));
|
||||
}
|
||||
resizeEvent(0);
|
||||
showAll();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
bool ProfileInner::event(QEvent *e) {
|
||||
if (e->type() == QEvent::MouseMove) {
|
||||
_lastPos = static_cast<QMouseEvent*>(e)->globalPos();
|
||||
|
@ -586,7 +645,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
|
|||
|
||||
// profile
|
||||
top += st::profilePadding.top();
|
||||
if (_photoLink || !_peerChat || _peerChat->forbidden) {
|
||||
if (_photoLink || !_peerChat || _peerChat->isForbidden) {
|
||||
p.drawPixmap(_left, top, _peer->photo->pix(st::profilePhotoSize));
|
||||
} else {
|
||||
if (a_photo.current() < 1) {
|
||||
|
@ -610,9 +669,11 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
p.setPen((_peerUser && App::onlineColorUse(_peerUser, l_time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
|
||||
p.drawText(_left + st::profilePhotoSize + st::profileStatusLeft, top + addbyname + st::profileStatusTop + st::linkFont->ascent, _onlineText);
|
||||
if (_isAdmin && ((_peerChat && !_peerChat->invitationUrl.isEmpty()) || (_peerChannel && !_peerChannel->invitationUrl.isEmpty()))) {
|
||||
p.setPen(st::black->p);
|
||||
p.drawText(_left + st::profilePhotoSize + st::profilePhoneLeft, _createInvitationLink.y() + st::linkFont->ascent, lang(lng_group_invite_link));
|
||||
if (_amCreator && ((_peerChat && !_peerChat->invitationUrl.isEmpty()) || (_peerChannel && !_peerChannel->invitationUrl.isEmpty()))) {
|
||||
if (!_peerChannel || !_peerChannel->isPublic()) {
|
||||
p.setPen(st::black->p);
|
||||
p.drawText(_left + st::profilePhotoSize + st::profilePhoneLeft, _createInvitationLink.y() + st::linkFont->ascent, lang(lng_group_invite_link));
|
||||
}
|
||||
}
|
||||
if (!_cancelPhoto.isHidden()) {
|
||||
p.setPen(st::profileOfflineColor->p);
|
||||
|
@ -632,15 +693,23 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
|
|||
top += st::profilePhotoSize;
|
||||
top += st::profileButtonTop;
|
||||
|
||||
if (_peerChat && _peerChat->forbidden) {
|
||||
if (_peerChat && _peerChat->isForbidden) {
|
||||
int32 w = st::btnShareContact.font->m.width(lang(lng_profile_chat_unaccessible));
|
||||
p.setFont(st::btnShareContact.font->f);
|
||||
p.setPen(st::profileOfflineColor->p);
|
||||
p.drawText(_left + (_width - w) / 2, top + st::btnShareContact.textTop + st::btnShareContact.font->ascent, lang(lng_profile_chat_unaccessible));
|
||||
}
|
||||
if (!_peerChannel || _isAdmin) {
|
||||
if (!_peerChannel || _amCreator) {
|
||||
top += _shareContact.height();
|
||||
}
|
||||
if (_peerChannel && (_amCreator || _peerChannel->isPublic())) {
|
||||
if (!_amCreator) {
|
||||
top += st::setLittleSkip;
|
||||
} else {
|
||||
top += st::setSectionSkip;
|
||||
}
|
||||
top += _editLink.height();
|
||||
}
|
||||
|
||||
// about
|
||||
if (!_about.isEmpty()) {
|
||||
|
@ -691,8 +760,18 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
|
|||
p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
|
||||
top += st::profileHeaderSkip;
|
||||
|
||||
top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height();
|
||||
if (_peerUser && peerToUser(_peerUser->id) != MTP::authedId()) top += st::setSectionSkip + _blockUser.height();
|
||||
top += _searchInPeer.height();
|
||||
if (_peerUser || _peerChat) {
|
||||
top += st::setLittleSkip + _clearHistory.height();
|
||||
}
|
||||
if (_peerUser || _peerChat || !_amCreator) {
|
||||
top += st::setLittleSkip + _deleteConversation.height();
|
||||
}
|
||||
if (_peerUser && peerToUser(_peerUser->id) != MTP::authedId()) {
|
||||
top += st::setSectionSkip + _blockUser.height();
|
||||
} else if (_peerChannel && _amCreator) {
|
||||
top += st::setSectionSkip + _deleteChannel.height();
|
||||
}
|
||||
|
||||
// participants
|
||||
if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) {
|
||||
|
@ -729,7 +808,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
|
|||
} else {
|
||||
data->online = App::onlineText(user, l_time);
|
||||
}
|
||||
data->cankick = (user != App::self()) && (_isAdmin || (_peerChat->cankick.constFind(user) != _peerChat->cankick.cend()));
|
||||
data->cankick = (user != App::self()) && (_amCreator || (_peerChat->cankick.constFind(user) != _peerChat->cankick.cend()));
|
||||
}
|
||||
p.setPen(st::profileListNameColor->p);
|
||||
p.setFont(st::linkFont->f);
|
||||
|
@ -764,12 +843,12 @@ void ProfileInner::mouseMoveEvent(QMouseEvent *e) {
|
|||
bool photoOver = QRect(_left, st::profilePadding.top(), st::setPhotoSize, st::setPhotoSize).contains(e->pos());
|
||||
if (photoOver != _photoOver) {
|
||||
_photoOver = photoOver;
|
||||
if (!_photoLink && _peerChat && !_peerChat->forbidden) {
|
||||
if (!_photoLink && _peerChat && !_peerChat->isForbidden) {
|
||||
a_photo.start(_photoOver ? 1 : 0);
|
||||
anim::start(this);
|
||||
}
|
||||
}
|
||||
if (!_photoLink && (!_peerChat || _peerChat->forbidden)) {
|
||||
if (!_photoLink && (!_peerChat || _peerChat->isForbidden)) {
|
||||
setCursor((_kickOver || _kickDown || textlnkOver()) ? style::cur_pointer : style::cur_default);
|
||||
} else {
|
||||
setCursor((_kickOver || _kickDown || _photoOver || textlnkOver()) ? style::cur_pointer : style::cur_default);
|
||||
|
@ -791,7 +870,14 @@ void ProfileInner::updateSelected() {
|
|||
update(QRect(_left, _aboutTop, _width, _aboutHeight));
|
||||
}
|
||||
|
||||
int32 partfrom = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
|
||||
int32 partfrom = _searchInPeer.y() + _searchInPeer.height();
|
||||
if (_peerUser || _peerChat) {
|
||||
partfrom = _clearHistory.y() + _clearHistory.height();
|
||||
}
|
||||
if (_peerUser || _peerChat || !_amCreator) {
|
||||
partfrom = _deleteConversation.y() + _deleteConversation.height();
|
||||
}
|
||||
partfrom += st::profileHeaderSkip;
|
||||
int32 newSelected = (lp.x() >= _left - st::profileListPadding.width() && lp.x() < _left + _width + st::profileListPadding.width() && lp.y() >= partfrom) ? (lp.y() - partfrom) / _pHeight : -1;
|
||||
|
||||
UserData *newKickOver = 0;
|
||||
|
@ -828,7 +914,7 @@ void ProfileInner::mousePressEvent(QMouseEvent *e) {
|
|||
} else if (QRect(_left, st::profilePadding.top(), st::setPhotoSize, st::setPhotoSize).contains(e->pos())) {
|
||||
if (_photoLink) {
|
||||
_photoLink->onClick(e->button());
|
||||
} else if (_peerChat && !_peerChat->forbidden) {
|
||||
} else if (_peerChat && !_peerChat->isForbidden) {
|
||||
onUpdatePhoto();
|
||||
}
|
||||
}
|
||||
|
@ -849,10 +935,14 @@ void ProfileInner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
TextLinkPtr lnk = textlnkDown();
|
||||
textlnkDown(TextLinkPtr());
|
||||
if (lnk == textlnkOver()) {
|
||||
if (reBotCommand().match(lnk->encoded()).hasMatch()) {
|
||||
App::main()->showPeerHistory(_peer->id, ShowAtTheEndMsgId);
|
||||
if (reHashtag().match(lnk->encoded()).hasMatch() && _peerChannel) {
|
||||
App::searchByHashtag(lnk->encoded(), _peerChannel);
|
||||
} else {
|
||||
if (reBotCommand().match(lnk->encoded()).hasMatch()) {
|
||||
App::main()->showPeerHistory(_peer->id, ShowAtTheEndMsgId);
|
||||
}
|
||||
lnk->onClick(e->button());
|
||||
}
|
||||
lnk->onClick(e->button());
|
||||
}
|
||||
}
|
||||
_kickDown = 0;
|
||||
|
@ -981,7 +1071,7 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
// profile
|
||||
top += st::profilePadding.top();
|
||||
if (_isAdmin) {
|
||||
if (_amCreator) {
|
||||
if ((_peerChat && _peerChat->invitationUrl.isEmpty()) || (_peerChannel && _peerChannel->invitationUrl.isEmpty())) {
|
||||
_createInvitationLink.move(_left + st::profilePhotoSize + st::profilePhoneLeft, top + st::profilePhoneTop);
|
||||
} else {
|
||||
|
@ -1008,9 +1098,23 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
|
|||
_shareContact.setGeometry(_left + _width - btnWidth, top, btnWidth, _shareContact.height());
|
||||
_inviteToGroup.setGeometry(_left + _width - btnWidth, top, btnWidth, _inviteToGroup.height());
|
||||
|
||||
if (!_peerChannel || _isAdmin) {
|
||||
if (!_peerChannel || _amCreator) {
|
||||
top += _shareContact.height();
|
||||
}
|
||||
if (_peerChannel && (_amCreator || _peerChannel->isPublic())) {
|
||||
if (!_amCreator) {
|
||||
top += st::setLittleSkip;
|
||||
} else {
|
||||
top += st::setSectionSkip;
|
||||
}
|
||||
if (_peerChannel->isPublic()) {
|
||||
_username.move(_left, top);
|
||||
_editLink.move(_left + _width - _editLink.width(), top);
|
||||
} else {
|
||||
_editLink.move(_left, top);
|
||||
}
|
||||
top += _editLink.height();
|
||||
}
|
||||
|
||||
// about
|
||||
if (!_about.isEmpty()) {
|
||||
|
@ -1046,11 +1150,18 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
|
|||
// actions
|
||||
top += st::profileHeaderSkip;
|
||||
_searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip;
|
||||
_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
|
||||
_deleteConversation.move(_left, top); top += _deleteConversation.height();
|
||||
if (_peerUser || _peerChat) {
|
||||
_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
|
||||
}
|
||||
if (_peerUser || _peerChat || !_amCreator) {
|
||||
_deleteConversation.move(_left, top); top += _deleteConversation.height();
|
||||
}
|
||||
if (_peerUser && peerToUser(_peerUser->id) != MTP::authedId()) {
|
||||
top += st::setSectionSkip;
|
||||
_blockUser.move(_left, top); top += _blockUser.height();
|
||||
} else if (_peerChannel && _amCreator) {
|
||||
top += st::setSectionSkip;
|
||||
_deleteChannel.move(_left, top); top += _deleteChannel.height();
|
||||
}
|
||||
|
||||
// participants
|
||||
|
@ -1140,6 +1251,7 @@ int32 ProfileInner::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type)
|
|||
int32 result = 0;
|
||||
if (peer == _peer) {
|
||||
if (updateMediaLinks(&result)) {
|
||||
showAll();
|
||||
resizeEvent(0);
|
||||
update();
|
||||
}
|
||||
|
@ -1154,6 +1266,31 @@ void ProfileInner::requestHeight(int32 newHeight) {
|
|||
}
|
||||
}
|
||||
|
||||
int32 ProfileInner::countMinHeight() {
|
||||
int32 h = 0;
|
||||
if (_peerUser) {
|
||||
if (peerToUser(_peerUser->id) == MTP::authedId()) {
|
||||
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
|
||||
} else {
|
||||
h = _blockUser.y() + _blockUser.height() + st::profileHeaderSkip;
|
||||
}
|
||||
} else if (_peerChat) {
|
||||
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
|
||||
if (!_participants.isEmpty()) {
|
||||
h += st::profileHeaderSkip + _participants.size() * _pHeight;
|
||||
} else if (_peerChat->count > 0) {
|
||||
h += st::profileHeaderSkip;
|
||||
}
|
||||
} else if (_peerChannel) {
|
||||
if (_amCreator) {
|
||||
h = _deleteChannel.y() + _deleteChannel.height() + st::profileHeaderSkip;
|
||||
} else {
|
||||
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void ProfileInner::allowDecreaseHeight(int32 decreaseBy) {
|
||||
if (decreaseBy > 0 && _addToHeight > 0) {
|
||||
_addToHeight -= qMin(decreaseBy, _addToHeight);
|
||||
|
@ -1163,8 +1300,16 @@ void ProfileInner::allowDecreaseHeight(int32 decreaseBy) {
|
|||
|
||||
void ProfileInner::showAll() {
|
||||
_searchInPeer.show();
|
||||
_clearHistory.show();
|
||||
_deleteConversation.show();
|
||||
if (_peerUser || _peerChat) {
|
||||
_clearHistory.show();
|
||||
} else {
|
||||
_clearHistory.hide();
|
||||
}
|
||||
if (_peerUser || _peerChat || !_amCreator) {
|
||||
_deleteConversation.show();
|
||||
} else {
|
||||
_deleteConversation.hide();
|
||||
}
|
||||
if (_peerUser) {
|
||||
_uploadPhoto.hide();
|
||||
_cancelPhoto.hide();
|
||||
|
@ -1189,11 +1334,14 @@ void ProfileInner::showAll() {
|
|||
} else {
|
||||
_blockUser.hide();
|
||||
}
|
||||
_deleteChannel.hide();
|
||||
_editLink.hide();
|
||||
_username.hide();
|
||||
} else if (_peerChat) {
|
||||
_sendMessage.hide();
|
||||
_shareContact.hide();
|
||||
_inviteToGroup.hide();
|
||||
if (_peerChat->forbidden) {
|
||||
if (_peerChat->isForbidden) {
|
||||
_uploadPhoto.hide();
|
||||
_cancelPhoto.hide();
|
||||
_addParticipant.hide();
|
||||
|
@ -1207,9 +1355,9 @@ void ProfileInner::showAll() {
|
|||
_uploadPhoto.show();
|
||||
_cancelPhoto.hide();
|
||||
}
|
||||
if (_isAdmin) {
|
||||
if (_amCreator) {
|
||||
_createInvitationLink.show();
|
||||
if (_peerChat && _peerChat->invitationUrl.isEmpty()) {
|
||||
if (_peerChat->invitationUrl.isEmpty()) {
|
||||
_invitationLink.hide();
|
||||
} else {
|
||||
_invitationLink.show();
|
||||
|
@ -1225,11 +1373,14 @@ void ProfileInner::showAll() {
|
|||
}
|
||||
}
|
||||
_blockUser.hide();
|
||||
_deleteChannel.hide();
|
||||
_editLink.hide();
|
||||
_username.hide();
|
||||
} else if (_peerChannel) {
|
||||
_sendMessage.hide();
|
||||
_shareContact.hide();
|
||||
_inviteToGroup.hide();
|
||||
if (_peerChannel->forbidden) {
|
||||
if (_peerChannel->isForbidden) {
|
||||
_uploadPhoto.hide();
|
||||
_cancelPhoto.hide();
|
||||
_addParticipant.hide();
|
||||
|
@ -1240,14 +1391,14 @@ void ProfileInner::showAll() {
|
|||
_uploadPhoto.hide();
|
||||
_cancelPhoto.show();
|
||||
} else {
|
||||
if (_isAdmin) {
|
||||
if (_amCreator) {
|
||||
_uploadPhoto.show();
|
||||
} else {
|
||||
_uploadPhoto.hide();
|
||||
}
|
||||
_cancelPhoto.hide();
|
||||
}
|
||||
if (_isAdmin) {
|
||||
if (_amCreator && !_peerChannel->isPublic()) {
|
||||
_createInvitationLink.show();
|
||||
if (_peerChannel->invitationUrl.isEmpty()) {
|
||||
_invitationLink.hide();
|
||||
|
@ -1261,30 +1412,25 @@ void ProfileInner::showAll() {
|
|||
_addParticipant.hide();
|
||||
}
|
||||
_blockUser.hide();
|
||||
if (_amCreator) {
|
||||
_deleteChannel.show();
|
||||
_editLink.show();
|
||||
} else {
|
||||
_deleteChannel.hide();
|
||||
_editLink.hide();
|
||||
}
|
||||
if (_peerChannel->isPublic()) {
|
||||
_username.show();
|
||||
} else {
|
||||
_username.hide();
|
||||
}
|
||||
}
|
||||
_enableNotifications.show();
|
||||
updateNotifySettings();
|
||||
|
||||
// participants
|
||||
reorderParticipants();
|
||||
int32 h;
|
||||
if (_peerUser) {
|
||||
if (peerToUser(_peerUser->id) == MTP::authedId()) {
|
||||
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
|
||||
} else {
|
||||
h = _blockUser.y() + _blockUser.height() + st::profileHeaderSkip;
|
||||
}
|
||||
} else if (_peerChat) {
|
||||
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
|
||||
if (!_participants.isEmpty()) {
|
||||
h += st::profileHeaderSkip + _participants.size() * _pHeight;
|
||||
} else if (_peerChat->count > 0) {
|
||||
h += st::profileHeaderSkip;
|
||||
}
|
||||
} else if (_peerChannel) {
|
||||
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
|
||||
}
|
||||
resize(width(), h + _addToHeight);
|
||||
resize(width(), countMinHeight() + _addToHeight);
|
||||
}
|
||||
|
||||
void ProfileInner::updateInvitationLink() {
|
||||
|
@ -1398,7 +1544,7 @@ void ProfileWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth)
|
|||
p.drawPixmap(QPoint(st::topBarBackPadding.left(), (st::topBarHeight - st::topBarBackImg.pxHeight()) / 2), App::sprite(), st::topBarBackImg);
|
||||
p.setFont(st::topBarBackFont->f);
|
||||
p.setPen(st::topBarBackColor->p);
|
||||
p.drawText(st::topBarBackPadding.left() + st::topBarBackImg.pxWidth() + st::topBarBackPadding.right(), (st::topBarHeight - st::topBarBackFont->height) / 2 + st::topBarBackFont->ascent, lang(peer()->isUser() ? lng_profile_info : lng_profile_group_info));
|
||||
p.drawText(st::topBarBackPadding.left() + st::topBarBackImg.pxWidth() + st::topBarBackPadding.right(), (st::topBarHeight - st::topBarBackFont->height) / 2 + st::topBarBackFont->ascent, lang(peer()->isUser() ? lng_profile_info : (peer()->isChat() ? lng_profile_group_info : lng_profile_channel_info)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1477,6 +1623,10 @@ void ProfileWidget::updateOnlineDisplayTimer() {
|
|||
_inner.updateOnlineDisplayTimer();
|
||||
}
|
||||
|
||||
void ProfileWidget::peerUsernameChanged() {
|
||||
_inner.peerUsernameChanged();
|
||||
}
|
||||
|
||||
void ProfileWidget::updateNotifySettings() {
|
||||
_inner.updateNotifySettings();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ public:
|
|||
|
||||
void start();
|
||||
|
||||
void peerUsernameChanged();
|
||||
|
||||
bool event(QEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
|
@ -56,6 +58,7 @@ public:
|
|||
int32 mediaOverviewUpdated(PeerData *peer, MediaOverviewType type); // returns scroll shift
|
||||
|
||||
void requestHeight(int32 newHeight);
|
||||
int32 countMinHeight();
|
||||
void allowDecreaseHeight(int32 decreaseBy);
|
||||
|
||||
~ProfileInner();
|
||||
|
@ -78,6 +81,8 @@ public slots:
|
|||
void onClearHistorySure();
|
||||
void onDeleteConversation();
|
||||
void onDeleteConversationSure();
|
||||
void onDeleteChannel();
|
||||
void onDeleteChannelSure();
|
||||
void onBlockUser();
|
||||
void onAddParticipant();
|
||||
|
||||
|
@ -103,11 +108,13 @@ public slots:
|
|||
void onInvitationLink();
|
||||
void onCreateInvitationLink();
|
||||
void onCreateInvitationLinkSure();
|
||||
void onPublicLink();
|
||||
|
||||
void onFullPeerUpdated(PeerData *peer);
|
||||
|
||||
void onBotSettings();
|
||||
void onBotHelp();
|
||||
void onEditPublicLink();
|
||||
|
||||
private:
|
||||
|
||||
|
@ -126,7 +133,7 @@ private:
|
|||
ChatData *_peerChat;
|
||||
ChannelData *_peerChannel;
|
||||
History *_hist;
|
||||
bool _isAdmin;
|
||||
bool _amCreator;
|
||||
|
||||
int32 _width, _left, _addToHeight;
|
||||
|
||||
|
@ -139,7 +146,7 @@ private:
|
|||
FlatButton _sendMessage, _shareContact, _inviteToGroup;
|
||||
LinkButton _cancelPhoto, _createInvitationLink, _invitationLink;
|
||||
QString _invitationText;
|
||||
LinkButton _botSettings, _botHelp;
|
||||
LinkButton _botSettings, _botHelp, _username, _editLink;
|
||||
|
||||
Text _about;
|
||||
int32 _aboutTop, _aboutHeight;
|
||||
|
@ -161,7 +168,7 @@ private:
|
|||
LinkButton _searchInPeer, _clearHistory, _deleteConversation;
|
||||
UserBlockedStatus _wasBlocked;
|
||||
mtpRequestId _blockRequest;
|
||||
LinkButton _blockUser;
|
||||
LinkButton _blockUser, _deleteChannel;
|
||||
|
||||
// participants
|
||||
int32 _pHeight;
|
||||
|
@ -215,6 +222,8 @@ public:
|
|||
void updateOnlineDisplay();
|
||||
void updateOnlineDisplayTimer();
|
||||
|
||||
void peerUsernameChanged();
|
||||
|
||||
void updateNotifySettings();
|
||||
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||
|
||||
|
|
|
@ -347,6 +347,7 @@ void PsMainWindow::psFirstShow() {
|
|||
psAddContact = window->addAction(lang(lng_mac_menu_add_contact), App::wnd(), SLOT(onShowAddContact()));
|
||||
window->addSeparator();
|
||||
psNewGroup = window->addAction(lang(lng_mac_menu_new_group), App::wnd(), SLOT(onShowNewGroup()));
|
||||
psNewChannel = window->addAction(lang(lng_mac_menu_new_channel), App::wnd(), SLOT(onShowNewChannel()));
|
||||
window->addSeparator();
|
||||
psShowTelegram = window->addAction(lang(lng_mac_menu_show), App::wnd(), SLOT(showFromTray()));
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
#include "window.h"
|
||||
#include "gui/filedialog.h"
|
||||
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
#include "audio.h"
|
||||
#include "localstorage.h"
|
||||
|
||||
|
@ -372,12 +374,28 @@ void ChannelData::setName(const QString &newName, const QString &usern) {
|
|||
|
||||
updateName(newName.isEmpty() ? name : newName, QString(), usern);
|
||||
if (updUsername) {
|
||||
if (usern.isEmpty()) {
|
||||
flags &= ~MTPDchannel::flag_username;
|
||||
} else {
|
||||
flags |= MTPDchannel::flag_username;
|
||||
}
|
||||
if (App::main()) {
|
||||
App::main()->peerUsernameChanged(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelData::updateFull() {
|
||||
if (!_lastFullUpdate || getms(true) > _lastFullUpdate + UpdateFullChannelTimeout) {
|
||||
App::api()->requestFullPeer(this);
|
||||
if (!amCreator() && !inviter) App::api()->requestSelfParticipant(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelData::fullUpdated() {
|
||||
_lastFullUpdate = getms(true);
|
||||
}
|
||||
|
||||
uint64 PtsWaiter::ptsKey(PtsSkippedQueue queue) {
|
||||
return _queue.insert(uint64(uint32(_last)) << 32 | uint64(uint32(_count)), queue).key();
|
||||
}
|
||||
|
@ -423,7 +441,7 @@ void PtsWaiter::applySkippedUpdates(ChannelData *channel) {
|
|||
for (QMap<uint64, PtsSkippedQueue>::const_iterator i = _queue.cbegin(), e = _queue.cend(); i != e; ++i) {
|
||||
switch (i.value()) {
|
||||
case SkippedUpdate: App::main()->feedUpdate(_updateQueue.value(i.key())); break;
|
||||
case SkippedUpdates: App::main()->handleUpdates(_updatesQueue.value(i.key())); break;
|
||||
case SkippedUpdates: App::main()->feedUpdates(_updatesQueue.value(i.key())); break;
|
||||
}
|
||||
}
|
||||
--_applySkippedLevel;
|
||||
|
@ -437,13 +455,45 @@ void PtsWaiter::clearSkippedUpdates() {
|
|||
_applySkippedLevel = 0;
|
||||
}
|
||||
|
||||
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 count) { // return false if need to save that update and apply later
|
||||
if (_requesting || _applySkippedLevel) return true;
|
||||
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 count) {
|
||||
if (_requesting || _applySkippedLevel) {
|
||||
return true;
|
||||
} else if (pts <= _good) {
|
||||
return false;
|
||||
}
|
||||
return check(channel, pts, count);
|
||||
}
|
||||
|
||||
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 ptsCount, const MTPUpdates &updates) {
|
||||
if (_requesting || _applySkippedLevel) {
|
||||
return true;
|
||||
} else if (pts <= _good) {
|
||||
return false;
|
||||
} else if (check(channel, pts, ptsCount)) {
|
||||
return true;
|
||||
}
|
||||
_updatesQueue.insert(ptsKey(SkippedUpdates), updates);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 ptsCount, const MTPUpdate &update) {
|
||||
if (_requesting || _applySkippedLevel) {
|
||||
return true;
|
||||
} else if (pts <= _good) {
|
||||
return false;
|
||||
} else if (check(channel, pts, ptsCount)) {
|
||||
return true;
|
||||
}
|
||||
_updateQueue.insert(ptsKey(SkippedUpdate), update);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PtsWaiter::check(ChannelData *channel, int32 pts, int32 count) { // return false if need to save that update and apply later
|
||||
if (!inited()) {
|
||||
init(pts);
|
||||
return true;
|
||||
}
|
||||
|
||||
_last = qMax(_last, pts);
|
||||
_count += count;
|
||||
if (_last == _count) {
|
||||
|
@ -457,22 +507,6 @@ bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 count) { // retur
|
|||
return !count;
|
||||
}
|
||||
|
||||
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 ptsCount, const MTPUpdates &updates) {
|
||||
if (!updated(channel, pts, ptsCount)) {
|
||||
_updatesQueue.insert(ptsKey(SkippedUpdates), updates);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 ptsCount, const MTPUpdate &update) {
|
||||
if (!updated(channel, pts, ptsCount)) {
|
||||
_updateQueue.insert(ptsKey(SkippedUpdate), update);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PhotoLink::onClick(Qt::MouseButton button) const {
|
||||
if (button == Qt::LeftButton) {
|
||||
App::wnd()->showPhoto(this, App::hoveredLinkItem());
|
||||
|
@ -915,7 +949,11 @@ id(id), type(type), url(url), displayUrl(displayUrl), siteName(siteName), title(
|
|||
void PeerLink::onClick(Qt::MouseButton button) const {
|
||||
if (button == Qt::LeftButton && App::main()) {
|
||||
if (peer() && peer()->isChannel() && App::main()->historyPeer() != peer()) {
|
||||
App::main()->showPeerHistory(peer()->id, ShowAtUnreadMsgId);
|
||||
if (!peer()->asChannel()->isPublic() && (peer()->asChannel()->isForbidden || peer()->asChannel()->haveLeft() || peer()->asChannel()->wasKicked())) {
|
||||
App::wnd()->showLayer(new ConfirmBox(lang(lng_channel_not_accessible), true));
|
||||
} else {
|
||||
App::main()->showPeerHistory(peer()->id, ShowAtUnreadMsgId);
|
||||
}
|
||||
} else {
|
||||
App::main()->showPeerProfile(peer());
|
||||
}
|
||||
|
|
|
@ -107,6 +107,14 @@ inline int32 flagsFromMessage(const MTPmessage &msg) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
inline int32 idFromMessage(const MTPmessage &msg) {
|
||||
switch (msg.type()) {
|
||||
case mtpc_messageEmpty: return msg.c_messageEmpty().vid.v;
|
||||
case mtpc_message: return msg.c_message().vid.v;
|
||||
case mtpc_messageService: return msg.c_messageService().vid.v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef uint64 PhotoId;
|
||||
typedef uint64 VideoId;
|
||||
|
@ -351,7 +359,7 @@ public:
|
|||
class ChatData : public PeerData {
|
||||
public:
|
||||
|
||||
ChatData(const PeerId &id) : PeerData(id), inputChat(MTP_int(bareId())), count(0), date(0), version(0), admin(0), inviterForSpamReport(0), left(false), forbidden(true), botStatus(0) {
|
||||
ChatData(const PeerId &id) : PeerData(id), inputChat(MTP_int(bareId())), count(0), date(0), version(0), creator(0), inviterForSpamReport(0), isForbidden(false), haveLeft(true), botStatus(0) {
|
||||
}
|
||||
void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId);
|
||||
|
||||
|
@ -360,10 +368,11 @@ public:
|
|||
int32 count;
|
||||
int32 date;
|
||||
int32 version;
|
||||
int32 admin;
|
||||
int32 creator;
|
||||
int32 inviterForSpamReport; // > 0 - user who invited me to chat in unread service msg, < 0 - have outgoing message
|
||||
bool left;
|
||||
bool forbidden;
|
||||
|
||||
bool isForbidden;
|
||||
bool haveLeft;
|
||||
typedef QMap<UserData*, int32> Participants;
|
||||
Participants participants;
|
||||
typedef QMap<UserData*, bool> CanKick;
|
||||
|
@ -427,6 +436,7 @@ public:
|
|||
void clearSkippedUpdates();
|
||||
|
||||
private:
|
||||
bool check(ChannelData *channel, int32 pts, int32 count); // return false if need to save that update and apply later
|
||||
uint64 ptsKey(PtsSkippedQueue queue);
|
||||
void checkForWaiting(ChannelData *channel);
|
||||
QMap<uint64, PtsSkippedQueue> _queue;
|
||||
|
@ -440,28 +450,61 @@ private:
|
|||
class ChannelData : public PeerData {
|
||||
public:
|
||||
|
||||
ChannelData(const PeerId &id) : PeerData(id), access(0), inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))), date(0), version(0), isBroadcast(false), isPublic(false), adminned(false), left(false), forbidden(true), botStatus(-1) {
|
||||
ChannelData(const PeerId &id) : PeerData(id), access(0), inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))), count(0), date(0), version(0), isForbidden(true), botStatus(-1), inviter(0), _lastFullUpdate(0) {
|
||||
setName(QString(), QString());
|
||||
}
|
||||
void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId);
|
||||
void setName(const QString &name, const QString &username);
|
||||
|
||||
void updateFull();
|
||||
void fullUpdated();
|
||||
|
||||
uint64 access;
|
||||
|
||||
MTPinputChannel inputChannel;
|
||||
|
||||
QString username;
|
||||
QString username, about;
|
||||
|
||||
int32 count;
|
||||
int32 date;
|
||||
int32 version;
|
||||
bool isBroadcast, isPublic;
|
||||
bool adminned;
|
||||
bool left;
|
||||
bool forbidden;
|
||||
int32 flags;
|
||||
bool isBroadcast() const {
|
||||
return flags & MTPDchannel_flag_is_broadcast;
|
||||
}
|
||||
bool isPublic() const {
|
||||
return flags & MTPDchannel::flag_username;
|
||||
}
|
||||
bool amCreator() const {
|
||||
return flags & MTPDchannel_flag_am_creator;
|
||||
}
|
||||
bool amEditor() const {
|
||||
return flags & MTPDchannel_flag_am_editor;
|
||||
}
|
||||
bool amModerator() const {
|
||||
return flags & MTPDchannel_flag_am_moderator;
|
||||
}
|
||||
bool haveLeft() const {
|
||||
return flags & MTPDchannel_flag_have_left;
|
||||
}
|
||||
bool wasKicked() const {
|
||||
return flags & MTPDchannel_flag_was_kicked;
|
||||
}
|
||||
bool canPublish() const {
|
||||
return amCreator() || amEditor();
|
||||
}
|
||||
bool amParticipant() const {
|
||||
return canPublish() || (!haveLeft() && !wasKicked());
|
||||
}
|
||||
bool isForbidden;
|
||||
|
||||
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
|
||||
// ImagePtr photoFull;
|
||||
QString invitationUrl;
|
||||
|
||||
int32 inviter; // > 0 - user who invited me to channel, < 0 - not in channel
|
||||
QDateTime inviteDate;
|
||||
|
||||
void ptsInit(int32 pts) {
|
||||
_ptsWaiter.init(pts);
|
||||
}
|
||||
|
@ -498,6 +541,7 @@ public:
|
|||
private:
|
||||
|
||||
PtsWaiter _ptsWaiter;
|
||||
uint64 _lastFullUpdate;
|
||||
};
|
||||
|
||||
inline UserData *PeerData::asUser() {
|
||||
|
|
|
@ -30,6 +30,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
#include "layerwidget.h"
|
||||
#include "settingswidget.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
|
||||
#include "mediaview.h"
|
||||
#include "localstorage.h"
|
||||
|
@ -1030,7 +1031,13 @@ void Window::onShowAddContact() {
|
|||
void Window::onShowNewGroup() {
|
||||
if (isHidden()) showFromTray();
|
||||
|
||||
if (main) main->showNewGroup();
|
||||
if (main) replaceLayer(new GroupInfoBox(CreatingGroupGroup, false));
|
||||
}
|
||||
|
||||
void Window::onShowNewChannel() {
|
||||
if (isHidden()) showFromTray();
|
||||
|
||||
if (main) replaceLayer(new GroupInfoBox(CreatingGroupChannel, false));
|
||||
}
|
||||
|
||||
void Window::onLogout() {
|
||||
|
|
|
@ -264,6 +264,7 @@ public slots:
|
|||
|
||||
void onShowAddContact();
|
||||
void onShowNewGroup();
|
||||
void onShowNewChannel();
|
||||
void onLogout();
|
||||
void onLogoutSure();
|
||||
void updateGlobalMenu(); // for OS X top menu
|
||||
|
|
Loading…
Reference in New Issue