mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 23:53:58 +02:00
Implement personal channel selector.
This commit is contained in:
parent
ab74ed0fa7
commit
280d69d346
8 changed files with 238 additions and 26 deletions
|
@ -672,7 +672,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_birthday_contacts" = "Only your contacts can see your birthday. {link}";
|
"lng_settings_birthday_contacts" = "Only your contacts can see your birthday. {link}";
|
||||||
"lng_settings_birthday_contacts_link" = "Change >";
|
"lng_settings_birthday_contacts_link" = "Change >";
|
||||||
"lng_settings_birthday_saved" = "Your date of birth was updated.";
|
"lng_settings_birthday_saved" = "Your date of birth was updated.";
|
||||||
"lng_settings_birthday_reset" = "Reset";
|
"lng_settings_birthday_reset" = "Remove";
|
||||||
|
"lng_settings_channel_label" = "Personal channel";
|
||||||
|
"lng_settings_channel_add" = "Add";
|
||||||
|
"lng_settings_channel_remove" = "Remove";
|
||||||
|
"lng_settings_channel_no_yet" = "You don't have any channels yet.";
|
||||||
|
"lng_settings_channel_start" = "Start a Channel";
|
||||||
|
"lng_settings_channel_saved" = "Your personal channel was updated.";
|
||||||
|
"lng_settings_channel_removed" = "Your personal channel was removed.";
|
||||||
"lng_settings_add_account_about" = "You can add up to four accounts with different phone numbers.";
|
"lng_settings_add_account_about" = "You can add up to four accounts with different phone numbers.";
|
||||||
"lng_settings_peer_to_peer_about" = "Disabling peer-to-peer will relay all calls through Telegram servers to avoid revealing your IP address, but may slightly decrease audio quality.";
|
"lng_settings_peer_to_peer_about" = "Disabling peer-to-peer will relay all calls through Telegram servers to avoid revealing your IP address, but may slightly decrease audio quality.";
|
||||||
"lng_settings_advanced" = "Advanced";
|
"lng_settings_advanced" = "Advanced";
|
||||||
|
|
|
@ -69,6 +69,102 @@ namespace {
|
||||||
|
|
||||||
using Match = qthelp::RegularExpressionMatch;
|
using Match = qthelp::RegularExpressionMatch;
|
||||||
|
|
||||||
|
class PersonalChannelController final : public PeerListController {
|
||||||
|
public:
|
||||||
|
explicit PersonalChannelController(not_null<Main::Session*> session);
|
||||||
|
~PersonalChannelController();
|
||||||
|
|
||||||
|
Main::Session &session() const override;
|
||||||
|
void prepare() override;
|
||||||
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
[[nodiscard]] rpl::producer<not_null<ChannelData*>> chosen() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const not_null<Main::Session*> _session;
|
||||||
|
rpl::event_stream<not_null<ChannelData*>> _chosen;
|
||||||
|
mtpRequestId _requestId = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
PersonalChannelController::PersonalChannelController(
|
||||||
|
not_null<Main::Session*> session)
|
||||||
|
: _session(session) {
|
||||||
|
}
|
||||||
|
|
||||||
|
PersonalChannelController::~PersonalChannelController() {
|
||||||
|
if (_requestId) {
|
||||||
|
_session->api().request(_requestId).cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Main::Session &PersonalChannelController::session() const {
|
||||||
|
return *_session;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersonalChannelController::prepare() {
|
||||||
|
using Flag = MTPchannels_GetAdminedPublicChannels::Flag;
|
||||||
|
_requestId = _session->api().request(
|
||||||
|
MTPchannels_GetAdminedPublicChannels(
|
||||||
|
MTP_flags(Flag::f_for_personal))
|
||||||
|
).done([=](const MTPmessages_Chats &result) {
|
||||||
|
_requestId = 0;
|
||||||
|
|
||||||
|
const auto &chats = result.match([](const auto &data) {
|
||||||
|
return data.vchats().v;
|
||||||
|
});
|
||||||
|
for (const auto &chat : chats) {
|
||||||
|
if (const auto peer = _session->data().processChat(chat)) {
|
||||||
|
if (!delegate()->peerListFindRow(peer->id.value)) {
|
||||||
|
delegate()->peerListAppendRow(
|
||||||
|
std::make_unique<PeerListRow>(peer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersonalChannelController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
if (const auto channel = row->peer()->asChannel()) {
|
||||||
|
_chosen.fire_copy(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PersonalChannelController::chosen() const
|
||||||
|
-> rpl::producer<not_null<ChannelData*>> {
|
||||||
|
return _chosen.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SavePersonalChannel(
|
||||||
|
not_null<Window::SessionController*> window,
|
||||||
|
ChannelData *channel) {
|
||||||
|
const auto self = window->session().user();
|
||||||
|
const auto history = channel
|
||||||
|
? channel->owner().history(channel->id).get()
|
||||||
|
: nullptr;
|
||||||
|
const auto item = history
|
||||||
|
? history->lastServerMessage()
|
||||||
|
: nullptr;
|
||||||
|
const auto channelId = channel
|
||||||
|
? peerToChannel(channel->id)
|
||||||
|
: ChannelId();
|
||||||
|
const auto messageId = item ? item->id : MsgId();
|
||||||
|
if (self->personalChannelId() != channelId
|
||||||
|
|| (messageId
|
||||||
|
&& self->personalChannelMessageId() != messageId)) {
|
||||||
|
self->setPersonalChannel(channelId, messageId);
|
||||||
|
self->session().api().request(MTPaccount_UpdatePersonalChannel(
|
||||||
|
channel ? channel->inputChannel : MTP_inputChannelEmpty()
|
||||||
|
)).done(crl::guard(window, [=] {
|
||||||
|
window->showToast((channel
|
||||||
|
? tr::lng_settings_channel_saved
|
||||||
|
: tr::lng_settings_channel_removed)(tr::now));
|
||||||
|
})).fail(crl::guard(window, [=](const MTP::Error &error) {
|
||||||
|
window->showToast(u"Error: "_q + error.type());
|
||||||
|
})).send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool JoinGroupByHash(
|
bool JoinGroupByHash(
|
||||||
Window::SessionController *controller,
|
Window::SessionController *controller,
|
||||||
const Match &match,
|
const Match &match,
|
||||||
|
@ -730,6 +826,45 @@ bool ShowEditBirthdayPrivacy(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShowEditPersonalChannel(
|
||||||
|
Window::SessionController *controller,
|
||||||
|
const Match &match,
|
||||||
|
const QVariant &context) {
|
||||||
|
if (!controller) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto listController = std::make_unique<PersonalChannelController>(
|
||||||
|
&controller->session());
|
||||||
|
const auto rawController = listController.get();
|
||||||
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
|
box->setTitle(tr::lng_settings_channel_label());
|
||||||
|
box->addButton(tr::lng_box_done(), [=] {
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto save = [=](ChannelData *channel) {
|
||||||
|
SavePersonalChannel(controller, channel);
|
||||||
|
box->closeBox();
|
||||||
|
};
|
||||||
|
|
||||||
|
rawController->chosen(
|
||||||
|
) | rpl::start_with_next([=](not_null<ChannelData*> channel) {
|
||||||
|
save(channel);
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
if (controller->session().user()->personalChannelId()) {
|
||||||
|
box->addLeftButton(tr::lng_settings_channel_remove(), [=] {
|
||||||
|
save(nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
controller->show(Box<PeerListBox>(
|
||||||
|
std::move(listController),
|
||||||
|
std::move(initBox)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ExportTestChatTheme(
|
void ExportTestChatTheme(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<const Data::CloudTheme*> theme) {
|
not_null<const Data::CloudTheme*> theme) {
|
||||||
|
@ -1128,6 +1263,10 @@ const std::vector<LocalUrlHandler> &InternalUrlHandlers() {
|
||||||
u"^edit_privacy_birthday$"_q,
|
u"^edit_privacy_birthday$"_q,
|
||||||
ShowEditBirthdayPrivacy,
|
ShowEditBirthdayPrivacy,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
u"^edit_personal_channel$"_q,
|
||||||
|
ShowEditPersonalChannel,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,27 +90,28 @@ struct PeerUpdate {
|
||||||
EmojiStatus = (1ULL << 28),
|
EmojiStatus = (1ULL << 28),
|
||||||
BusinessDetails = (1ULL << 29),
|
BusinessDetails = (1ULL << 29),
|
||||||
Birthday = (1ULL << 30),
|
Birthday = (1ULL << 30),
|
||||||
|
PersonalChannel = (1ULL << 31),
|
||||||
|
|
||||||
// For chats and channels
|
// For chats and channels
|
||||||
InviteLinks = (1ULL << 31),
|
InviteLinks = (1ULL << 32),
|
||||||
Members = (1ULL << 32),
|
Members = (1ULL << 33),
|
||||||
Admins = (1ULL << 33),
|
Admins = (1ULL << 34),
|
||||||
BannedUsers = (1ULL << 34),
|
BannedUsers = (1ULL << 35),
|
||||||
Rights = (1ULL << 35),
|
Rights = (1ULL << 36),
|
||||||
PendingRequests = (1ULL << 36),
|
PendingRequests = (1ULL << 37),
|
||||||
Reactions = (1ULL << 37),
|
Reactions = (1ULL << 38),
|
||||||
|
|
||||||
// For channels
|
// For channels
|
||||||
ChannelAmIn = (1ULL << 38),
|
ChannelAmIn = (1ULL << 39),
|
||||||
StickersSet = (1ULL << 39),
|
StickersSet = (1ULL << 40),
|
||||||
EmojiSet = (1ULL << 40),
|
EmojiSet = (1ULL << 41),
|
||||||
ChannelLinkedChat = (1ULL << 41),
|
ChannelLinkedChat = (1ULL << 42),
|
||||||
ChannelLocation = (1ULL << 42),
|
ChannelLocation = (1ULL << 43),
|
||||||
Slowmode = (1ULL << 43),
|
Slowmode = (1ULL << 44),
|
||||||
GroupCall = (1ULL << 44),
|
GroupCall = (1ULL << 45),
|
||||||
|
|
||||||
// For iteration
|
// For iteration
|
||||||
LastUsedBit = (1ULL << 44),
|
LastUsedBit = (1ULL << 45),
|
||||||
};
|
};
|
||||||
using Flags = base::flags<Flag>;
|
using Flags = base::flags<Flag>;
|
||||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||||
|
|
|
@ -195,6 +195,23 @@ void UserData::setBusinessDetails(Data::BusinessDetails details) {
|
||||||
session().changes().peerUpdated(this, UpdateFlag::BusinessDetails);
|
session().changes().peerUpdated(this, UpdateFlag::BusinessDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChannelId UserData::personalChannelId() const {
|
||||||
|
return _personalChannelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
MsgId UserData::personalChannelMessageId() const {
|
||||||
|
return _personalChannelMessageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserData::setPersonalChannel(ChannelId channelId, MsgId messageId) {
|
||||||
|
if (_personalChannelId != channelId
|
||||||
|
|| _personalChannelMessageId != messageId) {
|
||||||
|
_personalChannelId = channelId;
|
||||||
|
_personalChannelMessageId = messageId;
|
||||||
|
session().changes().peerUpdated(this, UpdateFlag::PersonalChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UserData::setName(const QString &newFirstName, const QString &newLastName, const QString &newPhoneName, const QString &newUsername) {
|
void UserData::setName(const QString &newFirstName, const QString &newLastName, const QString &newPhoneName, const QString &newUsername) {
|
||||||
bool changeName = !newFirstName.isEmpty() || !newLastName.isEmpty();
|
bool changeName = !newFirstName.isEmpty() || !newLastName.isEmpty();
|
||||||
|
|
||||||
|
@ -623,6 +640,9 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
||||||
update.vbusiness_location(),
|
update.vbusiness_location(),
|
||||||
update.vbusiness_intro()));
|
update.vbusiness_intro()));
|
||||||
user->setBirthday(update.vbirthday());
|
user->setBirthday(update.vbirthday());
|
||||||
|
user->setPersonalChannel(
|
||||||
|
update.vpersonal_channel_id().value_or_empty(),
|
||||||
|
update.vpersonal_channel_message().value_or_empty());
|
||||||
if (user->isSelf()) {
|
if (user->isSelf()) {
|
||||||
user->owner().businessInfo().applyAwaySettings(
|
user->owner().businessInfo().applyAwaySettings(
|
||||||
FromMTP(&user->owner(), update.vbusiness_away_message()));
|
FromMTP(&user->owner(), update.vbusiness_away_message()));
|
||||||
|
|
|
@ -205,6 +205,10 @@ public:
|
||||||
[[nodiscard]] const Data::BusinessDetails &businessDetails() const;
|
[[nodiscard]] const Data::BusinessDetails &businessDetails() const;
|
||||||
void setBusinessDetails(Data::BusinessDetails details);
|
void setBusinessDetails(Data::BusinessDetails details);
|
||||||
|
|
||||||
|
[[nodiscard]] ChannelId personalChannelId() const;
|
||||||
|
[[nodiscard]] MsgId personalChannelMessageId() const;
|
||||||
|
void setPersonalChannel(ChannelId channelId, MsgId messageId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto unavailableReasons() const
|
auto unavailableReasons() const
|
||||||
-> const std::vector<Data::UnavailableReason> & override;
|
-> const std::vector<Data::UnavailableReason> & override;
|
||||||
|
@ -223,6 +227,9 @@ private:
|
||||||
QString _phone;
|
QString _phone;
|
||||||
QString _privateForwardName;
|
QString _privateForwardName;
|
||||||
|
|
||||||
|
ChannelId _personalChannelId = 0;
|
||||||
|
MsgId _personalChannelMessageId = 0;
|
||||||
|
|
||||||
uint64 _accessHash = 0;
|
uint64 _accessHash = 0;
|
||||||
static constexpr auto kInaccessibleAccessHashOld
|
static constexpr auto kInaccessibleAccessHashOld
|
||||||
= 0xFFFFFFFFFFFFFFFFULL;
|
= 0xFFFFFFFFFFFFFFFFULL;
|
||||||
|
|
|
@ -352,6 +352,16 @@ rpl::producer<Data::Birthday> BirthdayValue(not_null<UserData*> user) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<ChannelData*> PersonalChannelValue(not_null<UserData*> user) {
|
||||||
|
return user->session().changes().peerFlagsValue(
|
||||||
|
user,
|
||||||
|
UpdateFlag::PersonalChannel
|
||||||
|
) | rpl::map([=] {
|
||||||
|
const auto channelId = user->personalChannelId();
|
||||||
|
return channelId ? user->owner().channel(channelId).get() : nullptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<bool> AmInChannelValue(not_null<ChannelData*> channel) {
|
rpl::producer<bool> AmInChannelValue(not_null<ChannelData*> channel) {
|
||||||
return channel->session().changes().peerFlagsValue(
|
return channel->session().changes().peerFlagsValue(
|
||||||
channel,
|
channel,
|
||||||
|
|
|
@ -86,6 +86,8 @@ rpl::producer<not_null<PeerData*>> MigratedOrMeValue(
|
||||||
not_null<UserData*> user);
|
not_null<UserData*> user);
|
||||||
[[nodiscard]] rpl::producer<Data::Birthday> BirthdayValue(
|
[[nodiscard]] rpl::producer<Data::Birthday> BirthdayValue(
|
||||||
not_null<UserData*> user);
|
not_null<UserData*> user);
|
||||||
|
[[nodiscard]] rpl::producer<ChannelData*> PersonalChannelValue(
|
||||||
|
not_null<UserData*> user);
|
||||||
[[nodiscard]] rpl::producer<bool> AmInChannelValue(
|
[[nodiscard]] rpl::producer<bool> AmInChannelValue(
|
||||||
not_null<ChannelData*> channel);
|
not_null<ChannelData*> channel);
|
||||||
[[nodiscard]] rpl::producer<int> MembersCountValue(not_null<PeerData*> peer);
|
[[nodiscard]] rpl::producer<int> MembersCountValue(not_null<PeerData*> peer);
|
||||||
|
|
|
@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
#include "data/data_premium_limits.h"
|
#include "data/data_premium_limits.h"
|
||||||
#include "info/profile/info_profile_values.h"
|
#include "info/profile/info_profile_values.h"
|
||||||
#include "info/profile/info_profile_badge.h"
|
#include "info/profile/info_profile_badge.h"
|
||||||
|
@ -368,16 +369,7 @@ void SetupBirthday(
|
||||||
tr::lng_settings_birthday_add()
|
tr::lng_settings_birthday_add()
|
||||||
) | rpl::map([](Data::Birthday birthday, const QString &add) {
|
) | rpl::map([](Data::Birthday birthday, const QString &add) {
|
||||||
const auto text = Data::BirthdayText(birthday);
|
const auto text = Data::BirthdayText(birthday);
|
||||||
if (!text.isEmpty()) {
|
return TextWithEntities{ !text.isEmpty() ? text : add };
|
||||||
return TextWithEntities{ text };
|
|
||||||
}
|
|
||||||
auto result = TextWithEntities{ add };
|
|
||||||
result.entities.push_back({
|
|
||||||
EntityType::CustomUrl,
|
|
||||||
0,
|
|
||||||
int(add.size()),
|
|
||||||
"internal:edit_username" });
|
|
||||||
return result;
|
|
||||||
});
|
});
|
||||||
const auto edit = [=] {
|
const auto edit = [=] {
|
||||||
Core::App().openInternalUrl(
|
Core::App().openInternalUrl(
|
||||||
|
@ -419,6 +411,39 @@ void SetupBirthday(
|
||||||
Ui::Text::WithEntities)));
|
Ui::Text::WithEntities)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetupPersonalChannel(
|
||||||
|
not_null<Ui::VerticalLayout*> container,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<UserData*> self) {
|
||||||
|
const auto session = &self->session();
|
||||||
|
|
||||||
|
Ui::AddSkip(container);
|
||||||
|
|
||||||
|
auto value = rpl::combine(
|
||||||
|
Info::Profile::PersonalChannelValue(self),
|
||||||
|
tr::lng_settings_channel_add()
|
||||||
|
) | rpl::map([](ChannelData *channel, const QString &add) {
|
||||||
|
return TextWithEntities{ channel ? channel->name() : add };
|
||||||
|
});
|
||||||
|
const auto edit = [=] {
|
||||||
|
Core::App().openInternalUrl(
|
||||||
|
u"internal:edit_personal_channel"_q,
|
||||||
|
QVariant::fromValue(ClickHandlerContext{
|
||||||
|
.sessionWindow = base::make_weak(controller),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
AddRow(
|
||||||
|
container,
|
||||||
|
tr::lng_settings_channel_label(),
|
||||||
|
std::move(value),
|
||||||
|
tr::lng_mediaview_copy(tr::now),
|
||||||
|
edit,
|
||||||
|
{ &st::menuIconChannel });
|
||||||
|
|
||||||
|
Ui::AddSkip(container);
|
||||||
|
Ui::AddDivider(container);
|
||||||
|
}
|
||||||
|
|
||||||
void SetupRows(
|
void SetupRows(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
|
@ -1020,6 +1045,7 @@ void Information::setupContent(
|
||||||
SetupPhoto(content, controller, self);
|
SetupPhoto(content, controller, self);
|
||||||
SetupBio(content, self);
|
SetupBio(content, self);
|
||||||
SetupRows(content, controller, self);
|
SetupRows(content, controller, self);
|
||||||
|
SetupPersonalChannel(content, controller, self);
|
||||||
SetupBirthday(content, controller, self);
|
SetupBirthday(content, controller, self);
|
||||||
SetupAccountsWrap(content, controller);
|
SetupAccountsWrap(content, controller);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue