mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Extend pinned messages support.
Support them in saved messages and normal groups.
This commit is contained in:
parent
6d65cf2382
commit
78da810114
12 changed files with 122 additions and 99 deletions
|
@ -881,6 +881,11 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
|||
}
|
||||
chat->setUserpicPhoto(f.vchat_photo);
|
||||
chat->setInviteLink((f.vexported_invite.type() == mtpc_chatInviteExported) ? qs(f.vexported_invite.c_chatInviteExported().vlink) : QString());
|
||||
if (f.has_pinned_msg_id()) {
|
||||
chat->setPinnedMessageId(f.vpinned_msg_id.v);
|
||||
} else {
|
||||
chat->clearPinnedMessage();
|
||||
}
|
||||
chat->fullUpdated();
|
||||
|
||||
notifySettingReceived(MTP_inputNotifyPeer(peer->input), f.vnotify_settings);
|
||||
|
@ -1019,6 +1024,11 @@ void ApiWrap::gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestI
|
|||
} else {
|
||||
user->setBotInfoVersion(-1);
|
||||
}
|
||||
if (d.has_pinned_msg_id()) {
|
||||
user->setPinnedMessageId(d.vpinned_msg_id.v);
|
||||
} else {
|
||||
user->clearPinnedMessage();
|
||||
}
|
||||
user->setBlockStatus(d.is_blocked() ? UserData::BlockStatus::Blocked : UserData::BlockStatus::NotBlocked);
|
||||
user->setCallsStatus(d.is_phone_calls_private() ? UserData::CallsStatus::Private : d.is_phone_calls_available() ? UserData::CallsStatus::Enabled : UserData::CallsStatus::Disabled);
|
||||
user->setAbout(d.has_about() ? qs(d.vabout) : QString());
|
||||
|
|
|
@ -403,8 +403,11 @@ void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) {
|
|||
_note.drawLeft(p, st::boxPadding.left(), _textHeight + st::boxPadding.bottom(), _textWidth, width());
|
||||
}
|
||||
|
||||
PinMessageBox::PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId)
|
||||
: _channel(channel)
|
||||
PinMessageBox::PinMessageBox(
|
||||
QWidget*,
|
||||
not_null<PeerData*> peer,
|
||||
MsgId msgId)
|
||||
: _peer(peer)
|
||||
, _msgId(msgId)
|
||||
, _text(this, lang(lng_pinned_pin_sure), Ui::FlatLabel::InitType::Simple, st::boxLabel) {
|
||||
}
|
||||
|
@ -413,7 +416,7 @@ void PinMessageBox::prepare() {
|
|||
addButton(langFactory(lng_pinned_pin), [this] { pinMessage(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
|
||||
if (_channel->isMegagroup()) {
|
||||
if (_peer->isChat() || _peer->isMegagroup()) {
|
||||
_notify.create(this, lang(lng_pinned_notify), true, st::defaultBoxCheckbox);
|
||||
}
|
||||
|
||||
|
@ -443,14 +446,14 @@ void PinMessageBox::keyPressEvent(QKeyEvent *e) {
|
|||
void PinMessageBox::pinMessage() {
|
||||
if (_requestId) return;
|
||||
|
||||
auto flags = MTPchannels_UpdatePinnedMessage::Flags(0);
|
||||
auto flags = MTPmessages_UpdatePinnedMessage::Flags(0);
|
||||
if (_notify && !_notify->checked()) {
|
||||
flags |= MTPchannels_UpdatePinnedMessage::Flag::f_silent;
|
||||
flags |= MTPmessages_UpdatePinnedMessage::Flag::f_silent;
|
||||
}
|
||||
_requestId = MTP::send(
|
||||
MTPchannels_UpdatePinnedMessage(
|
||||
MTPmessages_UpdatePinnedMessage(
|
||||
MTP_flags(flags),
|
||||
_channel->inputChannel,
|
||||
_peer->input,
|
||||
MTP_int(_msgId)),
|
||||
rpcDone(&PinMessageBox::pinDone),
|
||||
rpcFail(&PinMessageBox::pinFail));
|
||||
|
|
|
@ -142,7 +142,7 @@ private:
|
|||
|
||||
class PinMessageBox : public BoxContent, public RPCSender {
|
||||
public:
|
||||
PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId);
|
||||
PinMessageBox(QWidget*, not_null<PeerData*> peer, MsgId msgId);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -155,7 +155,7 @@ private:
|
|||
void pinDone(const MTPUpdates &updates);
|
||||
bool pinFail(const RPCError &error);
|
||||
|
||||
ChannelData *_channel;
|
||||
not_null<PeerData*> _peer;
|
||||
MsgId _msgId;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _text;
|
||||
|
|
|
@ -330,6 +330,39 @@ void PeerData::setUserpicChecked(
|
|||
}
|
||||
}
|
||||
|
||||
bool PeerData::canPinMessages() const {
|
||||
if (const auto user = asUser()) {
|
||||
return user->isSelf();
|
||||
} else if (const auto chat = asChat()) {
|
||||
return chat->adminsEnabled() ? chat->amAdmin() : chat->amIn();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
using AdminRight = ChannelData::AdminRight;
|
||||
if (channel->isMegagroup()) {
|
||||
return (channel->adminRights() & AdminRight::f_pin_messages)
|
||||
|| channel->amCreator();
|
||||
}
|
||||
return (channel->adminRights() & AdminRight::f_edit_messages)
|
||||
|| channel->amCreator();
|
||||
}
|
||||
Unexpected("Peer type in PeerData::canPinMessages.");
|
||||
}
|
||||
|
||||
void PeerData::setPinnedMessageId(MsgId messageId) {
|
||||
const auto min = [&] {
|
||||
if (const auto channel = asChannel()) {
|
||||
return channel->availableMinId();
|
||||
}
|
||||
return MsgId(0);
|
||||
}();
|
||||
messageId = (messageId > min) ? messageId : MsgId(0);
|
||||
if (_pinnedMessageId != messageId) {
|
||||
_pinnedMessageId = messageId;
|
||||
Notify::peerUpdatedDelayed(
|
||||
this,
|
||||
Notify::PeerUpdate::Flag::PinnedMessageChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerData::fillNames() {
|
||||
_nameWords.clear();
|
||||
_nameFirstLetters.clear();
|
||||
|
@ -872,25 +905,12 @@ void ChannelData::setAvailableMinId(MsgId availableMinId) {
|
|||
if (auto history = App::historyLoaded(this)) {
|
||||
history->clearUpTill(availableMinId);
|
||||
}
|
||||
if (_pinnedMessageId <= _availableMinId) {
|
||||
_pinnedMessageId = MsgId(0);
|
||||
Notify::peerUpdatedDelayed(
|
||||
this,
|
||||
Notify::PeerUpdate::Flag::ChannelPinnedChanged);
|
||||
if (pinnedMessageId() <= _availableMinId) {
|
||||
clearPinnedMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelData::setPinnedMessageId(MsgId messageId) {
|
||||
messageId = (messageId > _availableMinId) ? messageId : MsgId(0);
|
||||
if (_pinnedMessageId != messageId) {
|
||||
_pinnedMessageId = messageId;
|
||||
Notify::peerUpdatedDelayed(
|
||||
this,
|
||||
Notify::PeerUpdate::Flag::ChannelPinnedChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelData::setFeed(not_null<Data::Feed*> feed) {
|
||||
setFeedPointer(feed);
|
||||
}
|
||||
|
@ -948,15 +968,6 @@ bool ChannelData::canAddAdmins() const {
|
|||
|| amCreator();
|
||||
}
|
||||
|
||||
bool ChannelData::canPinMessages() const {
|
||||
if (isMegagroup()) {
|
||||
return (adminRights() & AdminRight::f_pin_messages)
|
||||
|| amCreator();
|
||||
}
|
||||
return (adminRights() & AdminRight::f_edit_messages)
|
||||
|| amCreator();
|
||||
}
|
||||
|
||||
bool ChannelData::canPublish() const {
|
||||
return (adminRights() & AdminRight::f_post_messages)
|
||||
|| amCreator();
|
||||
|
|
|
@ -210,6 +210,15 @@ public:
|
|||
|
||||
ImagePtr currentUserpic() const;
|
||||
|
||||
bool canPinMessages() const;
|
||||
MsgId pinnedMessageId() const {
|
||||
return _pinnedMessageId;
|
||||
}
|
||||
void setPinnedMessageId(MsgId messageId);
|
||||
void clearPinnedMessage() {
|
||||
setPinnedMessageId(0);
|
||||
}
|
||||
|
||||
protected:
|
||||
void updateNameDelayed(
|
||||
const QString &newName,
|
||||
|
@ -242,6 +251,7 @@ private:
|
|||
base::flat_set<QChar> _nameFirstLetters;
|
||||
|
||||
TimeMs _lastFullUpdate = 0;
|
||||
MsgId _pinnedMessageId = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -918,7 +928,6 @@ public:
|
|||
bool hiddenPreHistory() const;
|
||||
bool canAddMembers() const;
|
||||
bool canAddAdmins() const;
|
||||
bool canPinMessages() const;
|
||||
bool canPublish() const;
|
||||
bool canWrite() const;
|
||||
bool canViewMembers() const;
|
||||
|
@ -999,14 +1008,6 @@ public:
|
|||
}
|
||||
void setAvailableMinId(MsgId availableMinId);
|
||||
|
||||
MsgId pinnedMessageId() const {
|
||||
return _pinnedMessageId;
|
||||
}
|
||||
void setPinnedMessageId(MsgId messageId);
|
||||
void clearPinnedMessage() {
|
||||
setPinnedMessageId(0);
|
||||
}
|
||||
|
||||
void setFeed(not_null<Data::Feed*> feed);
|
||||
void clearFeed();
|
||||
|
||||
|
@ -1031,7 +1032,6 @@ private:
|
|||
int _restrictedCount = 0;
|
||||
int _kickedCount = 0;
|
||||
MsgId _availableMinId = 0;
|
||||
MsgId _pinnedMessageId = 0;
|
||||
|
||||
AdminRightFlags _adminRights;
|
||||
RestrictionFlags _restrictions;
|
||||
|
|
|
@ -121,12 +121,12 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
|
|||
});
|
||||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
auto changes = UpdateFlag::PinnedChanged
|
||||
auto changes = UpdateFlag::ChatPinnedChanged
|
||||
| UpdateFlag::NameChanged
|
||||
| UpdateFlag::PhotoChanged
|
||||
| UpdateFlag::UserIsContact;
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(changes, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.flags & UpdateFlag::PinnedChanged) {
|
||||
if (update.flags & UpdateFlag::ChatPinnedChanged) {
|
||||
stopReorderPinned();
|
||||
}
|
||||
if (update.flags & UpdateFlag::NameChanged) {
|
||||
|
|
|
@ -323,10 +323,8 @@ void History::itemVanished(not_null<HistoryItem*> item) {
|
|||
&& unreadCount() > 0) {
|
||||
changeUnreadCount(-1);
|
||||
}
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
if (channel->pinnedMessageId() == item->id) {
|
||||
channel->clearPinnedMessage();
|
||||
}
|
||||
if (peer->pinnedMessageId() == item->id) {
|
||||
peer->clearPinnedMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1216,9 +1214,7 @@ void History::applyServiceChanges(
|
|||
|
||||
case mtpc_messageActionPinMessage: {
|
||||
if (data.has_reply_to_msg_id() && item) {
|
||||
if (auto channel = item->history()->peer->asChannel()) {
|
||||
channel->setPinnedMessageId(data.vreply_to_msg_id.v);
|
||||
}
|
||||
item->history()->peer->setPinnedMessageId(data.vreply_to_msg_id.v);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -2764,7 +2760,7 @@ void History::changedInChatListHook(Dialogs::Mode list, bool added) {
|
|||
void History::changedChatListPinHook() {
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::PinnedChanged);
|
||||
Notify::PeerUpdate::Flag::ChatPinnedChanged);
|
||||
}
|
||||
|
||||
void History::removeBlock(not_null<HistoryBlock*> block) {
|
||||
|
|
|
@ -321,20 +321,14 @@ void HistoryItem::setRealId(MsgId newId) {
|
|||
}
|
||||
|
||||
bool HistoryItem::isPinned() const {
|
||||
if (auto channel = _history->peer->asChannel()) {
|
||||
return (channel->pinnedMessageId() == id);
|
||||
}
|
||||
return false;
|
||||
return (_history->peer->pinnedMessageId() == id);
|
||||
}
|
||||
|
||||
bool HistoryItem::canPin() const {
|
||||
if (id < 0 || !toHistoryMessage()) {
|
||||
return false;
|
||||
}
|
||||
if (auto channel = _history->peer->asChannel()) {
|
||||
return channel->canPinMessages();
|
||||
}
|
||||
return false;
|
||||
return _history->peer->canPinMessages();
|
||||
}
|
||||
|
||||
bool HistoryItem::allowsForward() const {
|
||||
|
|
|
@ -658,7 +658,7 @@ HistoryWidget::HistoryWidget(
|
|||
| UpdateFlag::UnreadViewChanged
|
||||
| UpdateFlag::MigrationChanged
|
||||
| UpdateFlag::RestrictionReasonChanged
|
||||
| UpdateFlag::ChannelPinnedChanged
|
||||
| UpdateFlag::PinnedMessageChanged
|
||||
| UpdateFlag::UserIsBlocked
|
||||
| UpdateFlag::AdminsChanged
|
||||
| UpdateFlag::MembersChanged
|
||||
|
@ -695,7 +695,7 @@ HistoryWidget::HistoryWidget(
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (update.flags & UpdateFlag::ChannelPinnedChanged) {
|
||||
if (update.flags & UpdateFlag::PinnedMessageChanged) {
|
||||
if (pinnedMsgVisibilityUpdated()) {
|
||||
updateHistoryGeometry();
|
||||
updateControlsVisibility();
|
||||
|
@ -5635,13 +5635,8 @@ void HistoryWidget::updatePinnedBar(bool force) {
|
|||
|
||||
bool HistoryWidget::pinnedMsgVisibilityUpdated() {
|
||||
auto result = false;
|
||||
auto pinnedId = [&] {
|
||||
if (auto channel = _peer ? _peer->asChannel() : nullptr) {
|
||||
return channel->pinnedMessageId();
|
||||
}
|
||||
return 0;
|
||||
}();
|
||||
if (pinnedId && !_peer->asChannel()->canPinMessages()) {
|
||||
auto pinnedId = _peer->pinnedMessageId();
|
||||
if (pinnedId && !_peer->canPinMessages()) {
|
||||
auto it = Global::HiddenPinnedMessages().constFind(_peer->id);
|
||||
if (it != Global::HiddenPinnedMessages().cend()) {
|
||||
if (it.value() == pinnedId) {
|
||||
|
@ -5972,27 +5967,25 @@ void HistoryWidget::editMessage(not_null<HistoryItem*> item) {
|
|||
void HistoryWidget::pinMessage(FullMsgId itemId) {
|
||||
if (const auto item = App::histItemById(itemId)) {
|
||||
if (item->canPin()) {
|
||||
const auto channel = item->history()->peer->asChannel();
|
||||
Assert(channel != nullptr);
|
||||
Ui::show(Box<PinMessageBox>(channel, item->id));
|
||||
Ui::show(Box<PinMessageBox>(item->history()->peer, item->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::unpinMessage(FullMsgId itemId) {
|
||||
const auto channel = _peer ? _peer->asChannel() : nullptr;
|
||||
if (!channel) {
|
||||
const auto peer = _peer;
|
||||
if (!peer) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ui::show(Box<ConfirmBox>(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin), crl::guard(this, [=] {
|
||||
channel->clearPinnedMessage();
|
||||
peer->clearPinnedMessage();
|
||||
|
||||
Ui::hideLayer();
|
||||
MTP::send(
|
||||
MTPchannels_UpdatePinnedMessage(
|
||||
MTPmessages_UpdatePinnedMessage(
|
||||
MTP_flags(0),
|
||||
channel->inputChannel,
|
||||
peer->input,
|
||||
MTP_int(0)),
|
||||
rpcDone(&HistoryWidget::unpinDone));
|
||||
})));
|
||||
|
@ -6005,8 +5998,7 @@ void HistoryWidget::unpinDone(const MTPUpdates &updates) {
|
|||
}
|
||||
|
||||
void HistoryWidget::onPinnedHide() {
|
||||
const auto channel = _peer ? _peer->asChannel() : nullptr;
|
||||
const auto pinnedId = channel ? channel->pinnedMessageId() : MsgId(0);
|
||||
const auto pinnedId = _peer ? _peer->pinnedMessageId() : MsgId(0);
|
||||
if (!pinnedId) {
|
||||
if (pinnedMsgVisibilityUpdated()) {
|
||||
updateControlsGeometry();
|
||||
|
@ -6015,10 +6007,12 @@ void HistoryWidget::onPinnedHide() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (channel->canPinMessages()) {
|
||||
unpinMessage(FullMsgId(peerToChannel(channel->id), pinnedId));
|
||||
if (_peer->canPinMessages()) {
|
||||
unpinMessage(FullMsgId(
|
||||
_peer->isChannel() ? peerToChannel(_peer->id) : NoChannel,
|
||||
pinnedId));
|
||||
} else {
|
||||
Global::RefHiddenPinnedMessages().insert(channel->id, pinnedId);
|
||||
Global::RefHiddenPinnedMessages().insert(_peer->id, pinnedId);
|
||||
Local::writeUserSettings();
|
||||
if (pinnedMsgVisibilityUpdated()) {
|
||||
updateControlsGeometry();
|
||||
|
|
|
@ -4705,13 +4705,6 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateChannelPinnedMessage: {
|
||||
auto &d = update.c_updateChannelPinnedMessage();
|
||||
if (auto channel = App::channelLoaded(d.vchannel_id.v)) {
|
||||
channel->setPinnedMessageId(d.vid.v);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateChannelTooLong: {
|
||||
auto &d = update.c_updateChannelTooLong();
|
||||
if (auto channel = App::channelLoaded(d.vchannel_id.v)) {
|
||||
|
@ -4735,6 +4728,28 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
}
|
||||
} break;
|
||||
|
||||
// Pinned message.
|
||||
case mtpc_updateUserPinnedMessage: {
|
||||
const auto &d = update.c_updateUserPinnedMessage();
|
||||
if (const auto user = App::userLoaded(d.vuser_id.v)) {
|
||||
user->setPinnedMessageId(d.vid.v);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateChatPinnedMessage: {
|
||||
const auto &d = update.c_updateChatPinnedMessage();
|
||||
if (const auto chat = App::chatLoaded(d.vchat_id.v)) {
|
||||
chat->setPinnedMessageId(d.vid.v);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateChannelPinnedMessage: {
|
||||
const auto &d = update.c_updateChannelPinnedMessage();
|
||||
if (const auto channel = App::channelLoaded(d.vchannel_id.v)) {
|
||||
channel->setPinnedMessageId(d.vid.v);
|
||||
}
|
||||
} break;
|
||||
|
||||
////// Cloud sticker sets
|
||||
case mtpc_updateNewStickerSet: {
|
||||
auto &d = update.c_updateNewStickerSet();
|
||||
|
|
|
@ -35,16 +35,17 @@ struct PeerUpdate {
|
|||
AboutChanged = (1 << 3),
|
||||
NotificationsEnabled = (1 << 4),
|
||||
MigrationChanged = (1 << 6),
|
||||
PinnedChanged = (1 << 7),
|
||||
ChatPinnedChanged = (1 << 7),
|
||||
RestrictionReasonChanged = (1 << 8),
|
||||
UnreadViewChanged = (1 << 9),
|
||||
PinnedMessageChanged = (1 << 10),
|
||||
|
||||
// For chats and channels
|
||||
InviteLinkChanged = (1 << 10),
|
||||
MembersChanged = (1 << 11),
|
||||
AdminsChanged = (1 << 12),
|
||||
BannedUsersChanged = (1 << 13),
|
||||
UnreadMentionsChanged = (1 << 14),
|
||||
InviteLinkChanged = (1 << 11),
|
||||
MembersChanged = (1 << 12),
|
||||
AdminsChanged = (1 << 13),
|
||||
BannedUsersChanged = (1 << 14),
|
||||
UnreadMentionsChanged = (1 << 15),
|
||||
|
||||
// For users
|
||||
UserCanShareContact = (1 << 16),
|
||||
|
@ -64,8 +65,7 @@ struct PeerUpdate {
|
|||
ChannelAmIn = (1 << 16),
|
||||
ChannelRightsChanged = (1 << 17),
|
||||
ChannelStickersChanged = (1 << 18),
|
||||
ChannelPinnedChanged = (1 << 19),
|
||||
ChannelPromotedChanged = (1 << 20),
|
||||
ChannelPromotedChanged = (1 << 19),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
|
|
@ -202,7 +202,7 @@ void Filler::addPinToggle() {
|
|||
|
||||
auto lifetime = Notify::PeerUpdateViewer(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::PinnedChanged
|
||||
Notify::PeerUpdate::Flag::ChatPinnedChanged
|
||||
) | rpl::start_with_next([peer, pinAction, pinText] {
|
||||
auto isPinned = App::history(peer)->isPinnedDialog();
|
||||
pinAction->setText(pinText(isPinned));
|
||||
|
|
Loading…
Add table
Reference in a new issue