Update API scheme to layer 172.

This commit is contained in:
John Preston 2024-01-09 13:13:30 +04:00
parent c364383cf0
commit ca25ad57b1
16 changed files with 295 additions and 81 deletions

View File

@ -141,6 +141,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_status_last_week" = "last seen within a week";
"lng_status_last_month" = "last seen within a month";
"lng_status_lastseen_now" = "last seen just now";
"lng_status_lastseen_hidden" = "last seen hidden";
"lng_status_lastseen_show" = "show";
"lng_status_lastseen_minutes#one" = "last seen {count} minute ago";
"lng_status_lastseen_minutes#other" = "last seen {count} minutes ago";
"lng_status_lastseen_hours#one" = "last seen {count} hour ago";
@ -168,6 +170,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_remember" = "Remember this choice";
"lng_lastseen_show_title" = "Show your last seen";
"lng_lastseen_show_about" = "To see **{user}'s** Last Seen time, either start showing your own Last Seen time...";
"lng_lastseen_show_button" = "Show my Last Seen";
"lng_lastseen_or" = "or";
"lng_lastseen_premium_title" = "Upgrade to Premium";
"lng_lastseen_premium_about" = "Subscription will let you see **{user}'s** Last Seen status without showing yours.";
"lng_lastseen_premium_button" = "Subscribe to Telegram Premium";
"lng_lastseen_shown_toast" = "Your last seen time is now visible.";
"lng_readtime_show_title" = "Show your read date";
"lng_readtime_show_about" = "To see when **{user}** read the message, either start showing your own read time...";
"lng_readtime_show_button" = "Show my Read Time";
"lng_readtime_or" = "or";
"lng_readtime_premium_title" = "Upgrade to Premium";
"lng_readtime_premium_about" = "Subscription will let you see **{user}'s** read time without showing yours.";
"lng_readtime_premium_button" = "Subscribe to Telegram Premium";
"lng_readtime_shown_toast" = "Your read times are now visible.";
"lng_channels_limit_title" = "Too Many Communities";
"lng_channels_limit1#one" = "You are a member of **{count}** groups and channels.";
"lng_channels_limit1#other" = "You are a member of **{count}** groups and channels.";
@ -1086,6 +1106,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_lastseen_exceptions" = "These settings will override the values above.";
"lng_edit_privacy_lastseen_always_title" = "Always share with";
"lng_edit_privacy_lastseen_never_title" = "Never share with";
"lng_edit_lastseen_hide_read_time" = "Hide read time";
"lng_edit_lastseen_hide_read_time_about" = "Do not show the time when you read a message to people you hid your last seen from. If you turn this on, their read time will also be hidden from you. This does not affect group chats.";
"lng_edit_lastseen_subscribe" = "Subscribe to Telegram Premium";
"lng_edit_lastseen_subscribe_about" = "If you subscribe to Premium, you will see other users' last seen and read time even if you hid yours from them (unless they specifically restricted it).";
"lng_edit_privacy_groups_title" = "Group invite settings";
"lng_edit_privacy_groups_header" = "Who can invite you to groups and channels";
@ -2764,6 +2788,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_save_custom_sound" = "Save for notifications";
"lng_context_translate" = "Translate";
"lng_context_translate_selected" = "Translate Selected Text";
"lng_context_read_hidden" = "read";
"lng_context_read_show" = "show when";
"lng_context_animated_emoji" = "This message contains emoji from **{name} pack**.";
"lng_context_animated_emoji_many#one" = "This message contains emoji from **{count} pack**.";

View File

@ -84,18 +84,61 @@ void GlobalPrivacy::dismissArchiveAndMuteSuggestion() {
u"AUTOARCHIVE_POPULAR"_q);
}
void GlobalPrivacy::updateHideReadTime(bool hide) {
update(
archiveAndMuteCurrent(),
unarchiveOnNewMessageCurrent(),
hide,
newRequirePremiumCurrent());
}
bool GlobalPrivacy::hideReadTimeCurrent() const {
return _hideReadTime.current();
}
rpl::producer<bool> GlobalPrivacy::hideReadTime() const {
return _hideReadTime.value();
}
void GlobalPrivacy::updateNewRequirePremium(bool value) {
update(
archiveAndMuteCurrent(),
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
value);
}
bool GlobalPrivacy::newRequirePremiumCurrent() const {
return _newRequirePremium.current();
}
rpl::producer<bool> GlobalPrivacy::newRequirePremium() const {
return _newRequirePremium.value();
}
void GlobalPrivacy::updateArchiveAndMute(bool value) {
update(value, unarchiveOnNewMessageCurrent());
update(
value,
unarchiveOnNewMessageCurrent(),
hideReadTimeCurrent(),
newRequirePremiumCurrent());
}
void GlobalPrivacy::updateUnarchiveOnNewMessage(
UnarchiveOnNewMessage value) {
update(archiveAndMuteCurrent(), value);
update(
archiveAndMuteCurrent(),
value,
hideReadTimeCurrent(),
newRequirePremiumCurrent());
}
void GlobalPrivacy::update(
bool archiveAndMute,
UnarchiveOnNewMessage unarchiveOnNewMessage) {
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium) {
using Flag = MTPDglobalPrivacySettings::Flag;
_api.request(_requestId).cancel();
@ -108,17 +151,26 @@ void GlobalPrivacy::update(
: Flag())
| (unarchiveOnNewMessage != UnarchiveOnNewMessage::AnyUnmuted
? Flag::f_keep_archived_folders
: Flag())
| (hideReadTime ? Flag::f_hide_read_marks : Flag())
| ((newRequirePremium && _session->premium())
? Flag::f_new_noncontact_peers_require_premium
: Flag());
_requestId = _api.request(MTPaccount_SetGlobalPrivacySettings(
MTP_globalPrivacySettings(MTP_flags(flags))
)).done([=](const MTPGlobalPrivacySettings &result) {
_requestId = 0;
apply(result);
}).fail([=] {
}).fail([=](const MTP::Error &error) {
_requestId = 0;
if (error.type() == u"PREMIUM_ACCOUNT_REQUIRED"_q) {
update(archiveAndMute, unarchiveOnNewMessage, hideReadTime, {});
}
}).send();
_archiveAndMute = archiveAndMute;
_unarchiveOnNewMessage = unarchiveOnNewMessage;
_hideReadTime = hideReadTime;
_newRequirePremium = newRequirePremium;
}
void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &data) {
@ -129,6 +181,8 @@ void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &data) {
: data.is_keep_archived_folders()
? UnarchiveOnNewMessage::NotInFoldersUnmuted
: UnarchiveOnNewMessage::AnyUnmuted;
_hideReadTime = data.is_hide_read_marks();
_newRequirePremium = data.is_new_noncontact_peers_require_premium();
});
}

View File

@ -41,12 +41,22 @@ public:
[[nodiscard]] rpl::producer<> suggestArchiveAndMute() const;
void dismissArchiveAndMuteSuggestion();
void updateHideReadTime(bool hide);
[[nodiscard]] bool hideReadTimeCurrent() const;
[[nodiscard]] rpl::producer<bool> hideReadTime() const;
void updateNewRequirePremium(bool value);
[[nodiscard]] bool newRequirePremiumCurrent() const;
[[nodiscard]] rpl::producer<bool> newRequirePremium() const;
private:
void apply(const MTPGlobalPrivacySettings &data);
void update(
bool archiveAndMute,
UnarchiveOnNewMessage unarchiveOnNewMessage);
UnarchiveOnNewMessage unarchiveOnNewMessage,
bool hideReadTime,
bool newRequirePremium);
const not_null<Main::Session*> _session;
MTP::Sender _api;
@ -55,6 +65,8 @@ private:
rpl::variable<UnarchiveOnNewMessage> _unarchiveOnNewMessage
= UnarchiveOnNewMessage::None;
rpl::variable<bool> _showArchiveAndMute = false;
rpl::variable<bool> _hideReadTime = false;
rpl::variable<bool> _newRequirePremium = false;
std::vector<Fn<void()>> _callbacks;
};

View File

@ -162,7 +162,7 @@ bool SendProgressManager::skipRequest(const Key &key) const {
}
const auto recently = base::unixtime::now() - kSendTypingsToOfflineFor;
const auto online = user->onlineTill;
if (online == -2) { // last seen recently
if (online == kOnlineRecently) {
return false;
} else if (online < 0) {
return (-online < recently);

View File

@ -944,7 +944,8 @@ void Updates::updateOnline(crl::time lastNonIdleTime, bool gotOtherOffline) {
}
const auto self = session().user();
self->onlineTill = base::unixtime::now() + (isOnline ? (config.onlineUpdatePeriod / 1000) : -1);
self->onlineTill = base::unixtime::now()
+ (isOnline ? (config.onlineUpdatePeriod / 1000) : -1);
session().changes().peerUpdated(
self,
Data::PeerUpdate::Flag::OnlineStatus);
@ -1850,23 +1851,16 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateUserStatus: {
auto &d = update.c_updateUserStatus();
if (auto user = session().data().userLoaded(d.vuser_id())) {
switch (d.vstatus().type()) {
case mtpc_userStatusEmpty: user->onlineTill = 0; break;
case mtpc_userStatusRecently:
if (user->onlineTill > -10) { // don't modify pseudo-online
user->onlineTill = -2;
}
break;
case mtpc_userStatusLastWeek: user->onlineTill = -3; break;
case mtpc_userStatusLastMonth: user->onlineTill = -4; break;
case mtpc_userStatusOffline: user->onlineTill = d.vstatus().c_userStatusOffline().vwas_online().v; break;
case mtpc_userStatusOnline: user->onlineTill = d.vstatus().c_userStatusOnline().vexpires().v; break;
if (const auto user = session().data().userLoaded(d.vuser_id())) {
const auto value = OnlineTillFromMTP(
d.vstatus(),
user->onlineTill);
if (user->onlineTill != value) {
session().changes().peerUpdated(
user,
Data::PeerUpdate::Flag::OnlineStatus);
session().data().maybeStopWatchForOffline(user);
}
session().changes().peerUpdated(
user,
Data::PeerUpdate::Flag::OnlineStatus);
session().data().maybeStopWatchForOffline(user);
}
if (UserId(d.vuser_id()) == session().userId()) {
if (d.vstatus().type() == mtpc_userStatusOffline

View File

@ -1923,21 +1923,18 @@ void ApiWrap::saveDraftToCloudDelayed(not_null<Data::Thread*> thread) {
void ApiWrap::updatePrivacyLastSeens() {
const auto now = base::unixtime::now();
_session->data().enumerateUsers([&](UserData *user) {
if (user->isSelf() || !user->isLoaded()) {
return;
}
if (user->onlineTill <= 0) {
if (user->isSelf() || !user->isLoaded() || user->onlineTill <= 0) {
return;
}
if (user->onlineTill + 3 * 86400 >= now) {
user->onlineTill = -2; // recently
user->onlineTill = kOnlineRecently;
} else if (user->onlineTill + 7 * 86400 >= now) {
user->onlineTill = -3; // last week
user->onlineTill = kOnlineLastWeek;
} else if (user->onlineTill + 30 * 86400 >= now) {
user->onlineTill = -4; // last month
user->onlineTill = kOnlineLastMonth;
} else {
user->onlineTill = 0;
user->onlineTill = kOnlineEmpty;
}
session().changes().peerUpdated(
user,
@ -1955,12 +1952,11 @@ void ApiWrap::updatePrivacyLastSeens() {
Assert(item.type() == mtpc_contactStatus);
auto &data = item.c_contactStatus();
if (auto user = _session->data().userLoaded(data.vuser_id())) {
auto oldOnlineTill = user->onlineTill;
auto newOnlineTill = OnlineTillFromStatus(
auto value = OnlineTillFromMTP(
data.vstatus(),
oldOnlineTill);
if (oldOnlineTill != newOnlineTill) {
user->onlineTill = newOnlineTill;
user->onlineTill);
if (user->onlineTill != value) {
user->onlineTill = value;
session().changes().peerUpdated(
user,
Data::PeerUpdate::Flag::OnlineStatus);
@ -1973,22 +1969,6 @@ void ApiWrap::updatePrivacyLastSeens() {
}).send();
}
int ApiWrap::OnlineTillFromStatus(
const MTPUserStatus &status,
int currentOnlineTill) {
switch (status.type()) {
case mtpc_userStatusEmpty: return 0;
case mtpc_userStatusRecently:
// Don't modify pseudo-online.
return (currentOnlineTill > -10) ? -2 : currentOnlineTill;
case mtpc_userStatusLastWeek: return -3;
case mtpc_userStatusLastMonth: return -4;
case mtpc_userStatusOffline: return status.c_userStatusOffline().vwas_online().v;
case mtpc_userStatusOnline: return status.c_userStatusOnline().vexpires().v;
}
Unexpected("Bad UserStatus type.");
}
void ApiWrap::clearHistory(not_null<PeerData*> peer, bool revoke) {
deleteHistory(peer, true, revoke);
}

View File

@ -258,10 +258,6 @@ public:
void updateNotifySettingsDelayed(Data::DefaultNotify type);
void saveDraftToCloudDelayed(not_null<Data::Thread*> thread);
static int OnlineTillFromStatus(
const MTPUserStatus &status,
int currentOnlineTill);
void clearHistory(not_null<PeerData*> peer, bool revoke);
void deleteConversation(not_null<PeerData*> peer, bool revoke);

View File

@ -67,13 +67,13 @@ std::optional<QString> OnlineTextSpecial(not_null<UserData*> user) {
std::optional<QString> OnlineTextCommon(TimeId online, TimeId now) {
if (online <= 0) {
switch (online) {
case 0:
case -1: return tr::lng_status_offline(tr::now);
case -2: return tr::lng_status_recently(tr::now);
case -3: return tr::lng_status_last_week(tr::now);
case -4: return tr::lng_status_last_month(tr::now);
case kOnlineEmpty: return tr::lng_status_offline(tr::now);
case kOnlineRecently: return tr::lng_status_recently(tr::now);
case kOnlineLastWeek: return tr::lng_status_last_week(tr::now);
case kOnlineLastMonth: return tr::lng_status_last_month(tr::now);
case kOnlineHidden: return tr::lng_status_lastseen_hidden(tr::now);
}
return (-online > now)
return IsRecentOnline(online, now)
? tr::lng_status_online(tr::now)
: tr::lng_status_recently(tr::now);
} else if (online > now) {

View File

@ -519,6 +519,8 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
| Flag::BotInlineGeo
| Flag::Premium
| Flag::Support
| Flag::SomeRequirePremiumToWrite
| Flag::RequirePremiumToWriteKnown
| (!minimal
? Flag::Contact
| Flag::MutualContact
@ -539,10 +541,20 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
| (data.is_bot_inline_geo() ? Flag::BotInlineGeo : Flag())
| (data.is_premium() ? Flag::Premium : Flag())
| (data.is_support() ? Flag::Support : Flag())
| (data.is_contact_require_premium()
? (Flag::SomeRequirePremiumToWrite
| (result->someRequirePremiumToWrite()
? (result->requirePremiumToWriteKnown()
? Flag::RequirePremiumToWriteKnown
: Flag())
: Flag()))
: Flag())
| (!minimal
? (data.is_contact() ? Flag::Contact : Flag())
| (data.is_mutual_contact() ? Flag::MutualContact : Flag())
| (data.is_apply_min_photo() ? Flag() : Flag::DiscardMinPhoto)
| (data.is_apply_min_photo()
? Flag()
: Flag::DiscardMinPhoto)
| (data.is_stories_hidden() ? Flag::StoriesHidden : Flag())
: Flag());
result->setFlags((result->flags() & ~flagsMask) | flagsSet);
@ -718,12 +730,9 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
}
if (status && !minimal) {
const auto oldOnlineTill = result->onlineTill;
const auto newOnlineTill = ApiWrap::OnlineTillFromStatus(
*status,
oldOnlineTill);
if (oldOnlineTill != newOnlineTill) {
result->onlineTill = newOnlineTill;
const auto value = OnlineTillFromMTP(*status, result->onlineTill);
if (result->onlineTill != value) {
result->onlineTill = value;
flags |= UpdateFlag::OnlineStatus;
session().data().maybeStopWatchForOffline(result);
}

View File

@ -34,6 +34,40 @@ using UpdateFlag = Data::PeerUpdate::Flag;
BotInfo::BotInfo() = default;
int RecentOnlineAfter(TimeId when) {
return (when > 0) ? (-when - kSetOnlineAfterActivity) : 0;
}
bool IsRecentOnlineValue(int value) {
return (value < -kSetOnlineAfterActivity);
}
bool IsRecentOnline(int value, TimeId now) {
return IsRecentOnlineValue(value) && (now < -value);
}
int OnlineTillFromMTP(
const MTPUserStatus &status,
int currentOnlineTill) {
return status.match([](const MTPDuserStatusEmpty &) {
return kOnlineEmpty;
}, [&](const MTPDuserStatusRecently&) {
return IsRecentOnlineValue(currentOnlineTill)
? currentOnlineTill
: kOnlineRecently;
}, [](const MTPDuserStatusLastWeek &) {
return kOnlineLastWeek;
}, [](const MTPDuserStatusLastMonth &) {
return kOnlineLastMonth;
}, [](const MTPDuserStatusHidden &) {
return kOnlineHidden;
}, [](const MTPDuserStatusOnline& data) {
return data.vexpires().v;
}, [](const MTPDuserStatusOffline &data) {
return data.vwas_online().v;
});
}
UserData::UserData(not_null<Data::Session*> owner, PeerId id)
: PeerData(owner, id)
, _flags((id == owner->session().userPeerId()) ? Flag::Self : Flag(0)) {
@ -351,6 +385,22 @@ bool UserData::hasStoriesHidden() const {
return (flags() & UserDataFlag::StoriesHidden);
}
bool UserData::someRequirePremiumToWrite() const {
return (flags() & UserDataFlag::SomeRequirePremiumToWrite);
}
bool UserData::meRequiresPremiumToWrite() const {
return (flags() & UserDataFlag::MeRequiresPremiumToWrite);
}
bool UserData::requirePremiumToWriteKnown() const {
return (flags() & UserDataFlag::RequirePremiumToWriteKnown);
}
bool UserData::readDatesPrivate() const {
return (flags() & UserDataFlag::ReadDatesPrivate);
}
bool UserData::canAddContact() const {
return canShareThisContact() && !isContact();
}
@ -453,15 +503,25 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
| Flag::PhoneCallsPrivate
| Flag::CanReceiveGifts
| Flag::CanPinMessages
| Flag::VoiceMessagesForbidden;
| Flag::VoiceMessagesForbidden
| Flag::ReadDatesPrivate
| Flag::RequirePremiumToWriteKnown
| Flag::MeRequiresPremiumToWrite;
user->setFlags((user->flags() & ~mask)
| (update.is_phone_calls_private() ? Flag::PhoneCallsPrivate : Flag())
| (update.is_phone_calls_private()
? Flag::PhoneCallsPrivate
: Flag())
| (update.is_phone_calls_available() ? Flag::HasPhoneCalls : Flag())
| (canReceiveGifts ? Flag::CanReceiveGifts : Flag())
| (update.is_can_pin_message() ? Flag::CanPinMessages : Flag())
| (update.is_blocked() ? Flag::Blocked : Flag())
| (update.is_voice_messages_forbidden()
? Flag::VoiceMessagesForbidden
: Flag())
| (update.is_read_dates_private() ? Flag::ReadDatesPrivate : Flag())
| Flag::RequirePremiumToWriteKnown
| (update.is_contact_require_premium()
? Flag::MeRequiresPremiumToWrite
: Flag()));
user->setIsBlocked(update.is_blocked());
user->setCallsStatus(update.is_phone_calls_private()

View File

@ -65,10 +65,27 @@ enum class UserDataFlag {
StoriesHidden = (1 << 18),
HasActiveStories = (1 << 19),
HasUnreadStories = (1 << 20),
MeRequiresPremiumToWrite = (1 << 21),
SomeRequirePremiumToWrite = (1 << 22),
RequirePremiumToWriteKnown = (1 << 23),
ReadDatesPrivate = (1 << 24),
};
inline constexpr bool is_flag_type(UserDataFlag) { return true; };
using UserDataFlags = base::flags<UserDataFlag>;
inline constexpr auto kOnlineEmpty = 0;
inline constexpr auto kOnlineRecently = -2;
inline constexpr auto kOnlineLastWeek = -3;
inline constexpr auto kOnlineLastMonth = -4;
inline constexpr auto kOnlineHidden = -5;
[[nodiscard]] int RecentOnlineAfter(TimeId when);
[[nodiscard]] bool IsRecentOnlineValue(int value);
[[nodiscard]] bool IsRecentOnline(int value, TimeId now);
[[nodiscard]] int OnlineTillFromMTP(
const MTPUserStatus& status,
int currentOnlineTill);
class UserData final : public PeerData {
public:
using Flag = UserDataFlag;
@ -119,6 +136,10 @@ public:
[[nodiscard]] bool applyMinPhoto() const;
[[nodiscard]] bool hasPersonalPhoto() const;
[[nodiscard]] bool hasStoriesHidden() const;
[[nodiscard]] bool someRequirePremiumToWrite() const;
[[nodiscard]] bool meRequiresPremiumToWrite() const;
[[nodiscard]] bool requirePremiumToWriteKnown() const;
[[nodiscard]] bool readDatesPrivate() const;
[[nodiscard]] bool canShareThisContact() const;
[[nodiscard]] bool canAddContact() const;

View File

@ -82,7 +82,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
userEmpty#d3bc4b7a id:long = User;
user#215c4438 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?int color:flags2.8?PeerColor profile_color:flags2.9?PeerColor = User;
user#215c4438 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.6?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?int color:flags2.8?PeerColor profile_color:flags2.9?PeerColor = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
@ -93,6 +93,7 @@ userStatusOffline#8c703f was_online:int = UserStatus;
userStatusRecently#e26f42f1 = UserStatus;
userStatusLastWeek#7bf09fc = UserStatus;
userStatusLastMonth#77ebc742 = UserStatus;
userStatusHidden#cf7d64b1 = UserStatus;
chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
@ -226,7 +227,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
userFull#b9b12c6c flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories = UserFull;
userFull#b9b12c6c flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact;
@ -1259,7 +1260,7 @@ statsGroupTopInviter#535f779d user_id:long invitations:int = StatsGroupTopInvite
stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats;
globalPrivacySettings#734c4ccb flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true = GlobalPrivacySettings;
globalPrivacySettings#734c4ccb flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true hide_read_marks:flags.3?true new_noncontact_peers_require_premium:flags.4?true = GlobalPrivacySettings;
help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector<string> patterns:flags.1?Vector<string> = help.CountryCode;
@ -1649,6 +1650,8 @@ savedReactionTag#cb6ff828 flags:# reaction:Reaction title:flags.0?string count:i
messages.savedReactionTagsNotModified#889b59ef = messages.SavedReactionTags;
messages.savedReactionTags#3259950a tags:Vector<SavedReactionTag> hash:long = messages.SavedReactionTags;
outboxReadDate#3bb842ac date:int = OutboxReadDate;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1778,6 +1781,7 @@ account.getChannelRestrictedStatusEmojis#35a9e0d5 hash:long = EmojiList;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
//users.getIsPremiumRequiredToContact#75c9db9c id:Vector<InputUser> = Vector<Bool>;
contacts.getContactIDs#7adc669d hash:long = Vector<int>;
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
@ -2002,6 +2006,7 @@ messages.reorderPinnedSavedDialogs#8b716587 flags:# force:flags.0?true order:Vec
messages.getSavedReactionTags#761ddacf hash:long = messages.SavedReactionTags;
messages.updateSavedReactionTag#60297dec flags:# reaction:Reaction title:flags.0?string = Bool;
messages.getDefaultTagReactions#bdf93428 hash:long = messages.Reactions;
messages.getOutboxReadDate#8c4bfe5d peer:InputPeer msg_id:int = OutboxReadDate;
updates.getState#edd4882a = updates.State;
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
@ -2244,4 +2249,4 @@ premium.applyBoost#6b7da746 flags:# slots:flags.0?Vector<int> peer:InputPeer = p
premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus;
premium.getUserBoosts#39854d1f peer:InputPeer user_id:InputUser = premium.BoostsList;
// LAYER 171
// LAYER 172

View File

@ -141,7 +141,7 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
if (const auto user = peer->asUser()) {
if (!user->isServiceUser() && !user->isBot()) {
const auto onlineTill = user->onlineTill;
return (onlineTill <= -5)
return IsRecentOnlineValue(onlineTill)
? -onlineTill
: (onlineTill <= 0)
? 0

View File

@ -15,12 +15,14 @@ settingsButton: SettingsButton(infoProfileButton) {
padding: margins(60px, 10px, 22px, 10px);
iconLeft: 20px;
}
settingsButtonNoIcon: SettingsButton(settingsButton) {
padding: margins(22px, 10px, 22px, 8px);
}
settingsButtonLight: SettingsButton(settingsButton) {
textFg: lightButtonFg;
textFgOver: lightButtonFgOver;
}
settingsButtonNoIcon: SettingsButton(settingsButton) {
padding: margins(22px, 10px, 22px, 8px);
settingsButtonLightNoIcon: SettingsButton(settingsButtonLight, settingsButtonNoIcon) {
}
settingsButtonNoIconLocked : SettingsButton(settingsButtonNoIcon) {
toggle: Toggle(infoProfileToggle) {

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "settings/settings_privacy_controllers.h"
#include "api/api_global_privacy.h"
#include "api/api_peer_photo.h"
#include "apiwrap.h"
#include "base/call_delayed.h"
@ -36,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_message.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "settings/settings_premium.h"
#include "settings/settings_privacy_security.h"
#include "ui/boxes/confirm_box.h"
#include "ui/cached_round_corners.h"
@ -665,16 +667,64 @@ auto LastSeenPrivacyController::exceptionsDescription() const
return tr::lng_edit_privacy_lastseen_exceptions();
}
object_ptr<Ui::RpWidget> LastSeenPrivacyController::setupBelowWidget(
not_null<Window::SessionController*> controller,
not_null<QWidget*> parent) {
auto result = object_ptr<Ui::VerticalLayout>(parent);
const auto content = result.data();
Ui::AddSkip(content);
const auto privacy = &controller->session().api().globalPrivacy();
content->add(object_ptr<Ui::SettingsButton>(
content,
tr::lng_edit_lastseen_hide_read_time(),
st::settingsButtonNoIcon
))->toggleOn(privacy->hideReadTime())->toggledValue(
) | rpl::start_with_next([=](bool value) {
_hideReadTime = value;
}, content->lifetime());
Ui::AddSkip(content);
Ui::AddDividerText(
content,
tr::lng_edit_lastseen_hide_read_time_about());
if (!controller->session().premium()) {
Ui::AddSkip(content);
content->add(object_ptr<Ui::SettingsButton>(
content,
tr::lng_edit_lastseen_subscribe(),
st::settingsButtonLightNoIcon
))->setClickedCallback([=] {
Settings::ShowPremium(controller, u"lastseen"_q);
});
Ui::AddSkip(content);
Ui::AddDividerText(
content,
tr::lng_edit_lastseen_subscribe_about());
}
return result;
}
void LastSeenPrivacyController::confirmSave(
bool someAreDisallowed,
Fn<void()> saveCallback) {
const auto privacy = &_session->api().globalPrivacy();
const auto hideReadTime = _hideReadTime;
const auto save = [=, saveCallback = std::move(saveCallback)] {
if (privacy->hideReadTimeCurrent() != hideReadTime) {
privacy->updateHideReadTime(hideReadTime);
}
saveCallback();
};
if (someAreDisallowed && !Core::App().settings().lastSeenWarningSeen()) {
auto callback = [
=,
saveCallback = std::move(saveCallback)
save = std::move(save)
](Fn<void()> &&close) {
close();
saveCallback();
save();
Core::App().settings().setLastSeenWarningSeen(true);
Core::App().saveSettingsDelayed();
};
@ -685,7 +735,7 @@ void LastSeenPrivacyController::confirmSave(
});
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
} else {
saveCallback();
save();
}
}

View File

@ -109,12 +109,17 @@ public:
Exception exception) const override;
rpl::producer<QString> exceptionsDescription() const override;
object_ptr<Ui::RpWidget> setupBelowWidget(
not_null<Window::SessionController*> controller,
not_null<QWidget*> parent) override;
void confirmSave(
bool someAreDisallowed,
Fn<void()> saveCallback) override;
private:
const not_null<::Main::Session*> _session;
bool _hideReadTime = false;
};