Optimize third column (create it only once).

Before historyPeer and historyPeerCanWrite were independent, so we
created a new Info section for both of them changing.

Now we use Data::CanWriteValue(peer) and rpl::flatten_latest().
This commit is contained in:
John Preston 2017-09-26 16:53:51 +03:00
parent ffc20e4492
commit 1a0e524b49
16 changed files with 363 additions and 106 deletions

View File

@ -394,7 +394,8 @@ namespace {
data->inputUser = MTP_inputUser(d.vid, MTP_long(0)); data->inputUser = MTP_inputUser(d.vid, MTP_long(0));
data->setName(lang(lng_deleted), QString(), QString(), QString()); data->setName(lang(lng_deleted), QString(), QString(), QString());
data->setPhoto(MTP_userProfilePhotoEmpty()); data->setPhoto(MTP_userProfilePhotoEmpty());
data->setFlags(MTPDuser_ClientFlag::f_inaccessible | 0); //data->setFlags(MTPDuser_ClientFlag::f_inaccessible | 0);
data->setFlags(MTPDuser::Flag::f_deleted);
data->setBotInfoVersion(-1); data->setBotInfoVersion(-1);
status = &emptyStatus; status = &emptyStatus;
data->contact = -1; data->contact = -1;
@ -412,7 +413,8 @@ namespace {
wasContact = data->isContact(); wasContact = data->isContact();
if (minimal) { if (minimal) {
auto mask = 0 auto mask = 0
| MTPDuser_ClientFlag::f_inaccessible; //| MTPDuser_ClientFlag::f_inaccessible
| MTPDuser::Flag::f_deleted;
data->setFlags((data->flags() & ~mask) | (d.vflags.v & mask)); data->setFlags((data->flags() & ~mask) | (d.vflags.v & mask));
} else { } else {
data->setFlags(d.vflags.v); data->setFlags(d.vflags.v);
@ -681,7 +683,7 @@ namespace {
} }
if (d.has_banned_rights()) { if (d.has_banned_rights()) {
cdata->setRestrictedRights(d.vbanned_rights); cdata->setRestrictedRights(d.vbanned_rights);
} else if (cdata->hasRestrictedRights()) { } else if (cdata->hasRestrictions()) {
cdata->setRestrictedRights(MTP_channelBannedRights(MTP_flags(0), MTP_int(0))); cdata->setRestrictedRights(MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
} }
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash); cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
@ -729,7 +731,7 @@ namespace {
if (cdata->hasAdminRights()) { if (cdata->hasAdminRights()) {
cdata->setAdminRights(MTP_channelAdminRights(MTP_flags(0))); cdata->setAdminRights(MTP_channelAdminRights(MTP_flags(0)));
} }
if (cdata->hasRestrictedRights()) { if (cdata->hasRestrictions()) {
cdata->setRestrictedRights(MTP_channelBannedRights(MTP_flags(0), MTP_int(0))); cdata->setRestrictedRights(MTP_channelBannedRights(MTP_flags(0), MTP_int(0)));
} }

View File

@ -222,7 +222,7 @@ void EditAdminBox::prepare() {
InvokeQueued(this, [this, control] { applyDependencies(control); }); InvokeQueued(this, [this, control] { applyDependencies(control); });
}); });
if (!channel()->amCreator()) { if (!channel()->amCreator()) {
if (!(channel()->adminRights().vflags.v & flags)) { if (!(channel()->adminRights() & flags)) {
control->setDisabled(true); // Grey out options that we don't have ourselves. control->setDisabled(true); // Grey out options that we don't have ourselves.
} }
} }
@ -272,7 +272,7 @@ void EditAdminBox::prepare() {
} }
if (!channel()->amCreator()) { if (!channel()->amCreator()) {
// Leave only rights that we have so we could save them. // Leave only rights that we have so we could save them.
newFlags &= channel()->adminRights().vflags.v; newFlags &= channel()->adminRights();
} }
_saveCallback(_oldRights, MTP_channelAdminRights(MTP_flags(newFlags))); _saveCallback(_oldRights, MTP_channelAdminRights(MTP_flags(newFlags)));
}); });

View File

@ -812,7 +812,7 @@ bool AddBotToGroupBoxController::needToCreateRow(not_null<PeerData*> peer) const
return false; return false;
} }
if (auto group = peer->asMegagroup()) { if (auto group = peer->asMegagroup()) {
if (group->restrictedRights().is_send_games()) { if (group->restricted(ChannelRestriction::f_send_games)) {
return false; return false;
} }
} }

View File

@ -535,8 +535,8 @@ void TabbedSelector::setCurrentPeer(PeerData *peer) {
void TabbedSelector::checkRestrictedPeer() { void TabbedSelector::checkRestrictedPeer() {
if (auto megagroup = _currentPeer ? _currentPeer->asMegagroup() : nullptr) { if (auto megagroup = _currentPeer ? _currentPeer->asMegagroup() : nullptr) {
auto restricted = (_currentTabType == SelectorTab::Stickers) ? megagroup->restrictedRights().is_send_stickers() : auto restricted = (_currentTabType == SelectorTab::Stickers) ? megagroup->restricted(ChannelRestriction::f_send_stickers) :
(_currentTabType == SelectorTab::Gifs) ? megagroup->restrictedRights().is_send_gifs() : false; (_currentTabType == SelectorTab::Gifs) ? megagroup->restricted(ChannelRestriction::f_send_gifs) : false;
if (restricted) { if (restricted) {
if (!_restrictedLabel) { if (!_restrictedLabel) {
auto text = (_currentTabType == SelectorTab::Stickers) ? lang(lng_restricted_send_stickers) : auto text = (_currentTabType == SelectorTab::Stickers) ? lang(lng_restricted_send_stickers) :

View File

@ -29,38 +29,44 @@ template <
typename FlagsType::Type kEssential = -1> typename FlagsType::Type kEssential = -1>
class Flags { class Flags {
public: public:
using Type = FlagsType;
using Enum = typename Type::Enum;
struct Change { struct Change {
Change(FlagsType diff, FlagsType value) using Type = FlagsType;
using Enum = typename Type::Enum;
Change(Type diff, Type value)
: diff(diff) : diff(diff)
, value(value) { , value(value) {
} }
FlagsType diff = 0; Type diff = 0;
FlagsType value = 0; Type value = 0;
}; };
Flags() = default; Flags() = default;
Flags(FlagsType value) : _value(value) { Flags(Type value) : _value(value) {
} }
void set(FlagsType which) { void set(Type which) {
if (auto diff = which ^ _value) { if (auto diff = which ^ _value) {
_value = which; _value = which;
updated(diff); updated(diff);
} }
} }
void add(FlagsType which) { void add(Type which) {
if (auto diff = which & ~_value) { if (auto diff = which & ~_value) {
_value |= which; _value |= which;
updated(diff); updated(diff);
} }
} }
void remove(FlagsType which) { void remove(Type which) {
if (auto diff = which & _value) { if (auto diff = which & _value) {
_value &= ~which; _value &= ~which;
updated(diff); updated(diff);
} }
} }
FlagsType current() const { Type current() const {
return _value; return _value;
} }
rpl::producer<Change> changes() const { rpl::producer<Change> changes() const {
@ -68,18 +74,18 @@ public:
} }
rpl::producer<Change> value() const { rpl::producer<Change> value() const {
return _changes.events_starting_with({ return _changes.events_starting_with({
FlagsType::from_raw(kEssential), Type::from_raw(kEssential),
_value }); _value });
} }
private: private:
void updated(FlagsType diff) { void updated(Type diff) {
if ((diff &= FlagsType::from_raw(kEssential))) { if ((diff &= Type::from_raw(kEssential))) {
_changes.fire({ diff, _value }); _changes.fire({ diff, _value });
} }
} }
FlagsType _value = 0; Type _value = 0;
rpl::event_stream<Change> _changes; rpl::event_stream<Change> _changes;
}; };

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include <rpl/filter.h> #include <rpl/filter.h>
#include <rpl/map.h> #include <rpl/map.h>
#include "data/data_peer_values.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "mainwidget.h" #include "mainwidget.h"
@ -609,7 +610,8 @@ void UserData::madeAction(TimeId when) {
void UserData::setAccessHash(uint64 accessHash) { void UserData::setAccessHash(uint64 accessHash) {
if (accessHash == kInaccessibleAccessHashOld) { if (accessHash == kInaccessibleAccessHashOld) {
_accessHash = 0; _accessHash = 0;
_flags.add(MTPDuser_ClientFlag::f_inaccessible | 0); // _flags.add(MTPDuser_ClientFlag::f_inaccessible | 0);
_flags.add(MTPDuser::Flag::f_deleted);
} else { } else {
_accessHash = accessHash; _accessHash = accessHash;
} }
@ -689,13 +691,7 @@ void ChatData::setInviteLink(const QString &newInviteLink) {
ChannelData::ChannelData(const PeerId &id) ChannelData::ChannelData(const PeerId &id)
: PeerData(id) : PeerData(id)
, inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))) { , inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))) {
flagsValue() Data::PeerFlagValue(this, MTPDchannel::Flag::f_megagroup)
| rpl::filter([](const Flags::Change &change) {
return change.diff & MTPDchannel::Flag::f_megagroup;
})
| rpl::map([](const Flags::Change &change) -> bool {
return change.value & MTPDchannel::Flag::f_megagroup;
})
| rpl::start([this](bool megagroup) { | rpl::start([this](bool megagroup) {
if (megagroup) { if (megagroup) {
if (!mgInfo) { if (!mgInfo) {
@ -947,7 +943,7 @@ bool ChannelData::canEditAdmin(not_null<UserData*> user) const {
} else if (canNotEditLastAdmin(user)) { } else if (canNotEditLastAdmin(user)) {
return false; return false;
} }
return adminRights().is_add_admins(); return adminRights() & AdminRight::f_add_admins;
} }
bool ChannelData::canRestrictUser(not_null<UserData*> user) const { bool ChannelData::canRestrictUser(not_null<UserData*> user) const {
@ -958,18 +954,18 @@ bool ChannelData::canRestrictUser(not_null<UserData*> user) const {
} else if (canNotEditLastAdmin(user)) { } else if (canNotEditLastAdmin(user)) {
return false; return false;
} }
return adminRights().is_ban_users(); return adminRights() & AdminRight::f_ban_users;
} }
void ChannelData::setAdminRights(const MTPChannelAdminRights &rights) { void ChannelData::setAdminRights(const MTPChannelAdminRights &rights) {
if (rights.c_channelAdminRights().vflags.v == _adminRights.c_channelAdminRights().vflags.v) { if (rights.c_channelAdminRights().vflags.v == adminRights()) {
return; return;
} }
_adminRights = rights; _adminRights.set(rights.c_channelAdminRights().vflags.v);
if (isMegagroup()) { if (isMegagroup()) {
if (hasAdminRights()) { if (hasAdminRights()) {
if (!amCreator()) { if (!amCreator()) {
auto me = MegagroupInfo::Admin { _adminRights }; auto me = MegagroupInfo::Admin { rights };
me.canEdit = false; me.canEdit = false;
mgInfo->lastAdmins.insert(App::self(), me); mgInfo->lastAdmins.insert(App::self(), me);
} }
@ -982,15 +978,16 @@ void ChannelData::setAdminRights(const MTPChannelAdminRights &rights) {
} }
void ChannelData::setRestrictedRights(const MTPChannelBannedRights &rights) { void ChannelData::setRestrictedRights(const MTPChannelBannedRights &rights) {
if (rights.c_channelBannedRights().vflags.v == _restrictedRights.c_channelBannedRights().vflags.v if (rights.c_channelBannedRights().vflags.v == restrictions()
&& rights.c_channelBannedRights().vuntil_date.v == _restrictedRights.c_channelBannedRights().vuntil_date.v) { && rights.c_channelBannedRights().vuntil_date.v == _restrictedUntill) {
return; return;
} }
_restrictedRights = rights; _restrictedUntill = rights.c_channelBannedRights().vuntil_date.v;
_restrictions.set(rights.c_channelBannedRights().vflags.v);
if (isMegagroup()) { if (isMegagroup()) {
if (hasRestrictedRights()) { if (hasRestrictions()) {
if (!amCreator()) { if (!amCreator()) {
auto me = MegagroupInfo::Restricted { _restrictedRights }; auto me = MegagroupInfo::Restricted { rights };
mgInfo->lastRestricted.insert(App::self(), me); mgInfo->lastRestricted.insert(App::self(), me);
} }
mgInfo->lastAdmins.remove(App::self()); mgInfo->lastAdmins.remove(App::self());

View File

@ -425,9 +425,13 @@ public:
return flags() & MTPDuser::Flag::f_bot_inline_geo; return flags() & MTPDuser::Flag::f_bot_inline_geo;
} }
bool isInaccessible() const { bool isInaccessible() const {
return flags() & MTPDuser_ClientFlag::f_inaccessible; constexpr auto inaccessible = 0
| MTPDuser::Flag::f_deleted;
// | MTPDuser_ClientFlag::f_inaccessible;
return flags() & inaccessible;
} }
bool canWrite() const { bool canWrite() const {
// Duplicated in Data::CanWriteValue().
return !isInaccessible(); return !isInaccessible();
} }
bool isContact() const { bool isContact() const {
@ -584,6 +588,7 @@ public:
|| (adminsEnabled() ? amAdmin() : amIn())); || (adminsEnabled() ? amAdmin() : amIn()));
} }
bool canWrite() const { bool canWrite() const {
// Duplicated in Data::CanWriteValue().
return !isDeactivated() && amIn(); return !isDeactivated() && amIn();
} }
bool haveLeft() const { bool haveLeft() const {
@ -752,6 +757,11 @@ struct MegagroupInfo {
}; };
using ChannelAdminRight = MTPDchannelAdminRights::Flag;
using ChannelRestriction = MTPDchannelBannedRights::Flag;
using ChannelAdminRights = MTPDchannelAdminRights::Flags;
using ChannelRestrictions = MTPDchannelBannedRights::Flags;
class ChannelData : public PeerData { class ChannelData : public PeerData {
public: public:
static constexpr auto kEssentialFlags = 0 static constexpr auto kEssentialFlags = 0
@ -906,63 +916,83 @@ public:
bool amCreator() const { bool amCreator() const {
return flags() & MTPDchannel::Flag::f_creator; return flags() & MTPDchannel::Flag::f_creator;
} }
const MTPChannelAdminRights &adminRightsBoxed() const {
return _adminRights; using AdminRight = ChannelAdminRight;
using Restriction = ChannelRestriction;
using AdminRights = ChannelAdminRights;
using Restrictions = ChannelRestrictions;
using AdminRightFlags = Data::Flags<AdminRights>;
using RestrictionFlags = Data::Flags<Restrictions>;
AdminRights adminRights() const {
return _adminRights.current();
} }
const MTPDchannelAdminRights &adminRights() const { rpl::producer<AdminRightFlags::Change> adminRightsValue() const {
return _adminRights.c_channelAdminRights(); return _adminRights.value();
} }
void setAdminRights(const MTPChannelAdminRights &rights); void setAdminRights(const MTPChannelAdminRights &rights);
bool hasAdminRights() const { bool hasAdminRights() const {
return (adminRights().vflags.v != 0); return (adminRights() != 0);
} }
const MTPChannelBannedRights &restrictedRightsBoxed() const { Restrictions restrictions() const {
return _restrictedRights; return _restrictions.current();
} }
const MTPDchannelBannedRights &restrictedRights() const { rpl::producer<RestrictionFlags::Change> restrictionsValue() const {
return _restrictedRights.c_channelBannedRights(); return _restrictions.value();
}
bool restricted(Restriction right) const {
return restrictions() & right;
}
TimeId restrictedUntil() const {
return _restrictedUntill;
} }
void setRestrictedRights(const MTPChannelBannedRights &rights); void setRestrictedRights(const MTPChannelBannedRights &rights);
bool hasRestrictedRights() const { bool hasRestrictions() const {
return (restrictedRights().vflags.v != 0); return (restrictions() != 0);
} }
bool hasRestrictedRights(int32 now) const { bool hasRestrictions(TimeId now) const {
return hasRestrictedRights() return hasRestrictions()
&& (restrictedRights().vuntil_date.v > now); && (restrictedUntil() > now);
} }
bool canBanMembers() const { bool canBanMembers() const {
return adminRights().is_ban_users() || amCreator(); return (adminRights() & AdminRight::f_ban_users)
|| amCreator();
} }
bool canEditMessages() const { bool canEditMessages() const {
return adminRights().is_edit_messages() || amCreator(); return (adminRights() & AdminRight::f_edit_messages)
|| amCreator();
} }
bool canDeleteMessages() const { bool canDeleteMessages() const {
return adminRights().is_delete_messages() || amCreator(); return (adminRights() & AdminRight::f_delete_messages)
|| amCreator();
} }
bool anyoneCanAddMembers() const { bool anyoneCanAddMembers() const {
return (flags() & MTPDchannel::Flag::f_democracy); return (flags() & MTPDchannel::Flag::f_democracy);
} }
bool canAddMembers() const { bool canAddMembers() const {
return adminRights().is_invite_users() return (adminRights() & AdminRight::f_invite_users)
|| amCreator() || amCreator()
|| (anyoneCanAddMembers() || (anyoneCanAddMembers()
&& amIn() && amIn()
&& !hasRestrictedRights()); && !hasRestrictions());
} }
bool canAddAdmins() const { bool canAddAdmins() const {
return adminRights().is_add_admins() || amCreator(); return (adminRights() & AdminRight::f_add_admins)
|| amCreator();
} }
bool canPinMessages() const { bool canPinMessages() const {
return adminRights().is_pin_messages() || amCreator(); return (adminRights() & AdminRight::f_pin_messages)
|| amCreator();
} }
bool canPublish() const { bool canPublish() const {
return adminRights().is_post_messages() || amCreator(); return (adminRights() & AdminRight::f_post_messages)
|| amCreator();
} }
bool canWrite() const { bool canWrite() const {
// Duplicated in Data::CanWriteValue().
return amIn() return amIn()
&& (canPublish() && (canPublish()
|| (!isBroadcast() || (!isBroadcast()
&& !restrictedRights().is_send_messages())); && !restricted(Restriction::f_send_messages)));
} }
bool canViewMembers() const { bool canViewMembers() const {
return fullFlags() return fullFlags()
@ -975,7 +1005,8 @@ public:
return (hasAdminRights() || amCreator()); return (hasAdminRights() || amCreator());
} }
bool canEditInformation() const { bool canEditInformation() const {
return adminRights().is_change_info() || amCreator(); return (adminRights() & AdminRight::f_change_info)
|| amCreator();
} }
bool canEditUsername() const { bool canEditUsername() const {
return amCreator() return amCreator()
@ -999,7 +1030,8 @@ public:
return _inviteLink; return _inviteLink;
} }
bool canHaveInviteLink() const { bool canHaveInviteLink() const {
return adminRights().is_invite_link() || amCreator(); return (adminRights() & AdminRight::f_invite_link)
|| amCreator();
} }
int32 inviter = 0; // > 0 - user who invited me to channel, < 0 - not in channel int32 inviter = 0; // > 0 - user who invited me to channel, < 0 - not in channel
@ -1069,10 +1101,9 @@ private:
int _restrictedCount = 0; int _restrictedCount = 0;
int _kickedCount = 0; int _kickedCount = 0;
MTPChannelAdminRights _adminRights AdminRightFlags _adminRights;
= MTP_channelAdminRights(MTP_flags(0)); RestrictionFlags _restrictions;
MTPChannelBannedRights _restrictedRights TimeId _restrictedUntill;
= MTP_channelBannedRights(MTP_flags(0), MTP_int(0));
QString _restrictionReason; QString _restrictionReason;
QString _about; QString _about;

View File

@ -0,0 +1,212 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <rpl/filter.h>
#include <rpl/map.h>
#include <rpl/combine.h>
#include "data/data_peer.h"
namespace Data {
template <typename ChangeType>
inline auto FlagsValueWithMask(
rpl::producer<ChangeType> &&value,
typename ChangeType::Type mask) {
return std::move(value)
| rpl::filter([mask](const ChangeType &change) {
return change.diff & mask;
})
| rpl::map([mask](const ChangeType &change) {
return change.value & mask;
});
}
template <typename ChangeType>
inline auto SingleFlagValue(
rpl::producer<ChangeType> &&value,
typename ChangeType::Enum flag) {
return FlagsValueWithMask(std::move(value), flag)
| rpl::map([flag](typename ChangeType::Type value) {
return !!value;
});
}
template <
typename PeerType,
typename ChangeType = typename PeerType::Flags::Change>
inline auto PeerFlagsValue(PeerType *peer) {
Expects(peer != nullptr);
return peer->flagsValue();
}
template <
typename PeerType,
typename ChangeType = typename PeerType::Flags::Change>
inline auto PeerFlagsValue(
PeerType *peer,
typename PeerType::Flags::Type mask) {
return FlagsValueWithMask(PeerFlagsValue(peer), mask);
}
template <
typename PeerType,
typename ChangeType = typename PeerType::Flags::Change>
inline auto PeerFlagValue(
PeerType *peer,
typename PeerType::Flags::Enum flag) {
return SingleFlagValue(PeerFlagsValue(peer), flag);
}
//
//inline auto PeerFlagValue(
// UserData *user,
// MTPDuser_ClientFlag flag) {
// return PeerFlagValue(user, static_cast<MTPDuser::Flag>(flag));
//}
inline auto PeerFlagValue(
ChatData *chat,
MTPDchat_ClientFlag flag) {
return PeerFlagValue(chat, static_cast<MTPDchat::Flag>(flag));
}
inline auto PeerFlagValue(
ChannelData *channel,
MTPDchannel_ClientFlag flag) {
return PeerFlagValue(channel, static_cast<MTPDchannel::Flag>(flag));
}
template <
typename PeerType,
typename = typename PeerType::FullFlags::Change>
inline auto PeerFullFlagsValue(PeerType *peer) {
Expects(peer != nullptr);
return peer->flagsValue();
}
template <
typename PeerType,
typename = typename PeerType::FullFlags::Change>
inline auto PeerFullFlagsValue(
PeerType *peer,
typename PeerType::FullFlags::Type mask) {
return FlagsValueWithMask(PeerFullFlagsValue(peer), mask);
}
template <
typename PeerType,
typename = typename PeerType::FullFlags::Change>
inline auto PeerFullFlagValue(
PeerType *peer,
typename PeerType::FullFlags::Enum flag) {
return SingleFlagValue(PeerFullFlagsValue(peer), flag);
}
inline auto AdminRightsValue(not_null<ChannelData*> channel) {
return channel->adminRightsValue();
}
inline auto AdminRightsValue(
not_null<ChannelData*> channel,
MTPDchannelAdminRights::Flags mask) {
return FlagsValueWithMask(AdminRightsValue(channel), mask);
}
inline auto AdminRightValue(
not_null<ChannelData*> channel,
MTPDchannelAdminRights::Flag flag) {
return SingleFlagValue(AdminRightsValue(channel), flag);
}
inline auto RestrictionsValue(not_null<ChannelData*> channel) {
return channel->restrictionsValue();
}
inline auto RestrictionsValue(
not_null<ChannelData*> channel,
MTPDchannelBannedRights::Flags mask) {
return FlagsValueWithMask(RestrictionsValue(channel), mask);
}
inline auto RestrictionValue(
not_null<ChannelData*> channel,
MTPDchannelBannedRights::Flag flag) {
return SingleFlagValue(RestrictionsValue(channel), flag);
}
inline auto CanWriteValue(UserData *user) {
using namespace rpl::mappers;
return PeerFlagValue(user, MTPDuser::Flag::f_deleted)
| rpl::map(!$1);
}
inline auto CanWriteValue(ChatData *chat) {
using namespace rpl::mappers;
auto mask = 0
| MTPDchat::Flag::f_deactivated
| MTPDchat_ClientFlag::f_forbidden
| MTPDchat::Flag::f_left
| MTPDchat::Flag::f_kicked;
return PeerFlagsValue(chat, mask)
| rpl::map(!$1);
}
inline rpl::producer<bool> CanWriteValue(ChannelData *channel) {
auto flagsMask = 0
| MTPDchannel::Flag::f_left
| MTPDchannel_ClientFlag::f_forbidden
| MTPDchannel::Flag::f_creator
| MTPDchannel::Flag::f_broadcast;
return rpl::combine(
PeerFlagsValue(channel, flagsMask),
AdminRightValue(
channel,
MTPDchannelAdminRights::Flag::f_post_messages),
RestrictionValue(
channel,
MTPDchannelBannedRights::Flag::f_send_messages),
[](
MTPDchannel::Flags flags,
bool postMessagesRight,
bool sendMessagesRestriction) {
auto notAmInFlags = 0
| MTPDchannel::Flag::f_left
| MTPDchannel_ClientFlag::f_forbidden;
return !(flags & notAmInFlags)
&& (postMessagesRight
|| (flags & MTPDchannel::Flag::f_creator)
|| (!(flags & MTPDchannel::Flag::f_broadcast)
&& !sendMessagesRestriction));
});
}
inline rpl::producer<bool> CanWriteValue(not_null<PeerData*> peer) {
if (auto user = peer->asUser()) {
return CanWriteValue(user);
} else if (auto chat = peer->asChat()) {
return CanWriteValue(chat);
} else if (auto channel = peer->asChannel()) {
return CanWriteValue(channel);
}
Unexpected("Bad peer value in CanWriteValue()");
}
} // namespace Data

View File

@ -91,7 +91,8 @@ MTPDmessage::Flags NewForwardedFlags(not_null<PeerData*> peer, UserId from, not_
if (auto media = fwd->getMedia()) { if (auto media = fwd->getMedia()) {
if (media->type() == MediaTypeWebPage) { if (media->type() == MediaTypeWebPage) {
// Drop web page if we're not allowed to send it. // Drop web page if we're not allowed to send it.
if (channel->restrictedRights().is_embed_links()) { if (channel->restricted(
ChannelRestriction::f_embed_links)) {
result &= MTPDmessage::Flag::f_media; result &= MTPDmessage::Flag::f_media;
} }
} }
@ -311,15 +312,15 @@ QString GetErrorTextForForward(not_null<PeerData*> peer, const SelectedItemSet &
} }
if (auto megagroup = peer->asMegagroup()) { if (auto megagroup = peer->asMegagroup()) {
if (megagroup->restrictedRights().is_send_media() && HasMediaItems(items)) { if (megagroup->restricted(ChannelRestriction::f_send_media) && HasMediaItems(items)) {
return lang(lng_restricted_send_media); return lang(lng_restricted_send_media);
} else if (megagroup->restrictedRights().is_send_stickers() && HasStickerItems(items)) { } else if (megagroup->restricted(ChannelRestriction::f_send_stickers) && HasStickerItems(items)) {
return lang(lng_restricted_send_stickers); return lang(lng_restricted_send_stickers);
} else if (megagroup->restrictedRights().is_send_gifs() && HasGifItems(items)) { } else if (megagroup->restricted(ChannelRestriction::f_send_gifs) && HasGifItems(items)) {
return lang(lng_restricted_send_gifs); return lang(lng_restricted_send_gifs);
} else if (megagroup->restrictedRights().is_send_games() && HasGameItems(items)) { } else if (megagroup->restricted(ChannelRestriction::f_send_games) && HasGameItems(items)) {
return lang(lng_restricted_send_inline); return lang(lng_restricted_send_inline);
} else if (megagroup->restrictedRights().is_send_inline() && HasInlineItems(items)) { } else if (megagroup->restricted(ChannelRestriction::f_send_inline) && HasInlineItems(items)) {
return lang(lng_restricted_send_inline); return lang(lng_restricted_send_inline);
} }
} }
@ -694,7 +695,7 @@ HistoryMessage::HistoryMessage(not_null<History*> history, MsgId id, MTPDmessage
auto cloneMedia = [this, history, mediaType] { auto cloneMedia = [this, history, mediaType] {
if (mediaType == MediaTypeWebPage) { if (mediaType == MediaTypeWebPage) {
if (auto channel = history->peer->asChannel()) { if (auto channel = history->peer->asChannel()) {
if (channel->restrictedRights().is_embed_links()) { if (channel->restricted(ChannelRestriction::f_embed_links)) {
return false; return false;
} }
} }

View File

@ -1820,7 +1820,6 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId); App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId);
emit historyShown(_history, _showAtMsgId); emit historyShown(_history, _showAtMsgId);
controller()->historyCanWrite = _canSendMessages;
controller()->historyPeer = _peer; controller()->historyPeer = _peer;
update(); update();
} }
@ -1979,7 +1978,8 @@ bool HistoryWidget::canWriteMessage() const {
bool HistoryWidget::isRestrictedWrite() const { bool HistoryWidget::isRestrictedWrite() const {
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) { if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
return megagroup->restrictedRights().is_send_messages(); return megagroup->restricted(
ChannelRestriction::f_send_messages);
} }
return false; return false;
} }
@ -3038,7 +3038,7 @@ void HistoryWidget::step_recording(float64 ms, bool timer) {
void HistoryWidget::chooseAttach() { void HistoryWidget::chooseAttach() {
if (!_peer || !_peer->canWrite()) return; if (!_peer || !_peer->canWrite()) return;
if (auto megagroup = _peer->asMegagroup()) { if (auto megagroup = _peer->asMegagroup()) {
if (megagroup->restrictedRights().is_send_media()) { if (megagroup->restricted(ChannelRestriction::f_send_media)) {
Ui::show(Box<InformBox>(lang(lng_restricted_send_media))); Ui::show(Box<InformBox>(lang(lng_restricted_send_media)));
return; return;
} }
@ -3142,7 +3142,7 @@ void HistoryWidget::recordStartCallback() {
return; return;
} }
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) { if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
if (megagroup->restrictedRights().is_send_media()) { if (megagroup->restricted(ChannelRestriction::f_send_media)) {
Ui::show(Box<InformBox>(lang(lng_restricted_send_media))); Ui::show(Box<InformBox>(lang(lng_restricted_send_media)));
return; return;
} }
@ -4128,7 +4128,7 @@ bool HistoryWidget::confirmSendingFiles(const QStringList &files, CompressConfir
bool HistoryWidget::confirmSendingFiles(const SendingFilesLists &lists, CompressConfirm compressed, const QString *addedComment) { bool HistoryWidget::confirmSendingFiles(const SendingFilesLists &lists, CompressConfirm compressed, const QString *addedComment) {
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) { if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
if (megagroup->restrictedRights().is_send_media()) { if (megagroup->restricted(ChannelRestriction::f_send_media)) {
Ui::show(Box<InformBox>(lang(lng_restricted_send_media))); Ui::show(Box<InformBox>(lang(lng_restricted_send_media)));
return false; return false;
} }
@ -5141,7 +5141,7 @@ void HistoryWidget::onFieldTabbed() {
bool HistoryWidget::onStickerSend(DocumentData *sticker) { bool HistoryWidget::onStickerSend(DocumentData *sticker) {
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) { if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
if (megagroup->restrictedRights().is_send_stickers()) { if (megagroup->restricted(ChannelRestriction::f_send_stickers)) {
Ui::show( Ui::show(
Box<InformBox>(lang(lng_restricted_send_stickers)), Box<InformBox>(lang(lng_restricted_send_stickers)),
LayerOption::KeepOther); LayerOption::KeepOther);
@ -5153,7 +5153,7 @@ bool HistoryWidget::onStickerSend(DocumentData *sticker) {
void HistoryWidget::onPhotoSend(PhotoData *photo) { void HistoryWidget::onPhotoSend(PhotoData *photo) {
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) { if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
if (megagroup->restrictedRights().is_send_media()) { if (megagroup->restricted(ChannelRestriction::f_send_media)) {
Ui::show( Ui::show(
Box<InformBox>(lang(lng_restricted_send_media)), Box<InformBox>(lang(lng_restricted_send_media)),
LayerOption::KeepOther); LayerOption::KeepOther);
@ -5769,7 +5769,7 @@ void HistoryWidget::onPreviewParse() {
void HistoryWidget::onPreviewCheck() { void HistoryWidget::onPreviewCheck() {
auto previewRestricted = [this] { auto previewRestricted = [this] {
if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) { if (auto megagroup = _peer ? _peer->asMegagroup() : nullptr) {
if (megagroup->restrictedRights().is_embed_links()) { if (megagroup->restricted(ChannelRestriction::f_embed_links)) {
return true; return true;
} }
} }
@ -5917,7 +5917,6 @@ void HistoryWidget::fullPeerUpdated(PeerData *peer) {
bool newCanSendMessages = canSendMessages(_peer); bool newCanSendMessages = canSendMessages(_peer);
if (newCanSendMessages != _canSendMessages) { if (newCanSendMessages != _canSendMessages) {
_canSendMessages = newCanSendMessages; _canSendMessages = newCanSendMessages;
controller()->historyCanWrite = _canSendMessages;
if (!_canSendMessages) { if (!_canSendMessages) {
cancelReply(); cancelReply();
} }
@ -5956,7 +5955,6 @@ void HistoryWidget::handlePeerUpdate() {
bool newCanSendMessages = canSendMessages(_peer); bool newCanSendMessages = canSendMessages(_peer);
if (newCanSendMessages != _canSendMessages) { if (newCanSendMessages != _canSendMessages) {
_canSendMessages = newCanSendMessages; _canSendMessages = newCanSendMessages;
controller()->historyCanWrite = _canSendMessages;
if (!_canSendMessages) { if (!_canSendMessages) {
cancelReply(); cancelReply();
} }

View File

@ -48,7 +48,7 @@ UserId viaBotId, MsgId replyToId, const QString &postAuthor, const MTPReplyMarku
QString SendDataCommon::getErrorOnSend(const Result *owner, History *history) const { QString SendDataCommon::getErrorOnSend(const Result *owner, History *history) const {
if (auto megagroup = history->peer->asMegagroup()) { if (auto megagroup = history->peer->asMegagroup()) {
if (megagroup->restrictedRights().is_send_messages()) { if (megagroup->restricted(ChannelRestriction::f_send_messages)) {
return lang(lng_restricted_send_message); return lang(lng_restricted_send_message);
} }
} }
@ -96,7 +96,7 @@ UserId viaBotId, MsgId replyToId, const QString &postAuthor, const MTPReplyMarku
QString SendPhoto::getErrorOnSend(const Result *owner, History *history) const { QString SendPhoto::getErrorOnSend(const Result *owner, History *history) const {
if (auto megagroup = history->peer->asMegagroup()) { if (auto megagroup = history->peer->asMegagroup()) {
if (megagroup->restrictedRights().is_send_media()) { if (megagroup->restricted(ChannelRestriction::f_send_media)) {
return lang(lng_restricted_send_media); return lang(lng_restricted_send_media);
} }
} }
@ -111,11 +111,11 @@ UserId viaBotId, MsgId replyToId, const QString &postAuthor, const MTPReplyMarku
QString SendFile::getErrorOnSend(const Result *owner, History *history) const { QString SendFile::getErrorOnSend(const Result *owner, History *history) const {
if (auto megagroup = history->peer->asMegagroup()) { if (auto megagroup = history->peer->asMegagroup()) {
if (megagroup->restrictedRights().is_send_media()) { if (megagroup->restricted(ChannelRestriction::f_send_media)) {
return lang(lng_restricted_send_media); return lang(lng_restricted_send_media);
} else if (megagroup->restrictedRights().is_send_stickers() && (_document->sticker() != nullptr)) { } else if (megagroup->restricted(ChannelRestriction::f_send_stickers) && (_document->sticker() != nullptr)) {
return lang(lng_restricted_send_stickers); return lang(lng_restricted_send_stickers);
} else if (megagroup->restrictedRights().is_send_gifs() && _document->isAnimation() && !_document->isRoundVideo()) { } else if (megagroup->restricted(ChannelRestriction::f_send_gifs) && _document->isAnimation() && !_document->isRoundVideo()) {
return lang(lng_restricted_send_gifs); return lang(lng_restricted_send_gifs);
} }
} }
@ -130,7 +130,7 @@ void SendGame::addToHistory(const Result *owner, History *history,
QString SendGame::getErrorOnSend(const Result *owner, History *history) const { QString SendGame::getErrorOnSend(const Result *owner, History *history) const {
if (auto megagroup = history->peer->asMegagroup()) { if (auto megagroup = history->peer->asMegagroup()) {
if (megagroup->restrictedRights().is_send_games()) { if (megagroup->restricted(ChannelRestriction::f_send_games)) {
return lang(lng_restricted_send_inline); return lang(lng_restricted_send_inline);
} }
} }

View File

@ -94,7 +94,7 @@ void Inner::visibleTopBottomUpdated(
void Inner::checkRestrictedPeer() { void Inner::checkRestrictedPeer() {
if (auto megagroup = _inlineQueryPeer ? _inlineQueryPeer->asMegagroup() : nullptr) { if (auto megagroup = _inlineQueryPeer ? _inlineQueryPeer->asMegagroup() : nullptr) {
if (megagroup->restrictedRights().is_send_inline()) { if (megagroup->restricted(ChannelRestriction::f_send_inline)) {
if (!_restrictedLabel) { if (!_restrictedLabel) {
_restrictedLabel.create(this, lang(lng_restricted_send_inline), Ui::FlatLabel::InitType::Simple, st::stickersRestrictedLabel); _restrictedLabel.create(this, lang(lng_restricted_send_inline), Ui::FlatLabel::InitType::Simple, st::stickersRestrictedLabel);
_restrictedLabel->show(); _restrictedLabel->show();

View File

@ -21,10 +21,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "mainwidget.h" #include "mainwidget.h"
#include <rpl/combine.h> #include <rpl/combine.h>
#include <rpl/flatten_latest.h>
#include "data/data_photo.h" #include "data/data_photo.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
#include "data/data_game.h" #include "data/data_game.h"
#include "data/data_peer_values.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_history.h" #include "styles/style_history.h"
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
@ -174,9 +176,17 @@ MainWidget::MainWidget(
subscribe(_controller->floatPlayerAreaUpdated(), [this] { subscribe(_controller->floatPlayerAreaUpdated(), [this] {
checkFloatPlayerVisibility(); checkFloatPlayerVisibility();
}); });
rpl::combine(
_controller->historyPeer.value(), using namespace rpl::mappers;
_controller->historyCanWrite.value()) _controller->historyPeer.value()
| rpl::map([](PeerData *peer) {
auto canWrite = peer
? Data::CanWriteValue(peer)
: rpl::single(false);
return std::move(canWrite)
| rpl::map(tuple(peer, $1));
})
| rpl::flatten_latest()
| rpl::start([this](PeerData *peer, bool canWrite) { | rpl::start([this](PeerData *peer, bool canWrite) {
updateThirdColumnToCurrentPeer(peer, canWrite); updateThirdColumnToCurrentPeer(peer, canWrite);
}, lifetime()); }, lifetime());
@ -759,7 +769,7 @@ bool MainWidget::onSendPaths(const PeerId &peerId) {
Ui::show(Box<InformBox>(lang(lng_forward_send_files_cant))); Ui::show(Box<InformBox>(lang(lng_forward_send_files_cant)));
return false; return false;
} else if (auto megagroup = peer->asMegagroup()) { } else if (auto megagroup = peer->asMegagroup()) {
if (megagroup->restrictedRights().is_send_media()) { if (megagroup->restricted(ChannelRestriction::f_send_media)) {
Ui::show(Box<InformBox>(lang(lng_restricted_send_media))); Ui::show(Box<InformBox>(lang(lng_restricted_send_media)));
return false; return false;
} }

View File

@ -122,14 +122,14 @@ enum class MTPDstickerSet_ClientFlag : uint32 {
}; };
DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet) DEFINE_MTP_CLIENT_FLAGS(MTPDstickerSet)
enum class MTPDuser_ClientFlag : uint32 { //enum class MTPDuser_ClientFlag : uint32 {
// forbidden constructor received // // forbidden constructor received
f_inaccessible = (1U << 31), // f_inaccessible = (1U << 31),
//
// update this when adding new client side flags // // update this when adding new client side flags
MIN_FIELD = (1U << 31), // MIN_FIELD = (1U << 31),
}; //};
DEFINE_MTP_CLIENT_FLAGS(MTPDuser) //DEFINE_MTP_CLIENT_FLAGS(MTPDuser)
enum class MTPDchat_ClientFlag : uint32 { enum class MTPDchat_ClientFlag : uint32 {
// forbidden constructor received // forbidden constructor received

View File

@ -60,7 +60,6 @@ public:
// for all histories we show in a window. Once each history is shown // for all histories we show in a window. Once each history is shown
// in its own HistoryWidget with its own TopBarWidget this can be removed. // in its own HistoryWidget with its own TopBarWidget this can be removed.
rpl::variable<PeerData*> historyPeer; rpl::variable<PeerData*> historyPeer;
rpl::variable<bool> historyCanWrite;
void enableGifPauseReason(GifPauseReason reason); void enableGifPauseReason(GifPauseReason reason);
void disableGifPauseReason(GifPauseReason reason); void disableGifPauseReason(GifPauseReason reason);

View File

@ -149,6 +149,7 @@
<(src_loc)/data/data_game.h <(src_loc)/data/data_game.h
<(src_loc)/data/data_peer.cpp <(src_loc)/data/data_peer.cpp
<(src_loc)/data/data_peer.h <(src_loc)/data/data_peer.h
<(src_loc)/data/data_peer_values.h
<(src_loc)/data/data_photo.cpp <(src_loc)/data/data_photo.cpp
<(src_loc)/data/data_photo.h <(src_loc)/data/data_photo.h
<(src_loc)/data/data_types.cpp <(src_loc)/data/data_types.cpp