2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-31 14:38:15 +00:00

Allow enabling direct messages in channels.

This commit is contained in:
John Preston
2025-05-06 17:48:18 +04:00
parent 23eedb468f
commit d3f9a84a0a
39 changed files with 685 additions and 242 deletions

View File

@@ -1168,12 +1168,13 @@ rpl::producer<int> SetupChargeSlider(
struct State {
rpl::variable<int> stars;
};
const auto group = !peer->isUser();
const auto broadcast = peer->isBroadcast();
const auto group = !broadcast && !peer->isUser();
const auto state = container->lifetime().make_state<State>();
const auto chargeStars = savedValue ? savedValue : kDefaultChargeStars;
state->stars = chargeStars;
Ui::AddSubsectionTitle(container, group
Ui::AddSubsectionTitle(container, (group || broadcast)
? tr::lng_rights_charge_price()
: tr::lng_messages_privacy_price());
@@ -1225,7 +1226,9 @@ rpl::producer<int> SetupChargeSlider(
const auto percent = peer->session().appConfig().paidMessageCommission();
Ui::AddDividerText(
container,
(group
(broadcast
? tr::lng_manage_monoforum_price_about
: group
? tr::lng_rights_charge_price_about
: tr::lng_messages_privacy_price_about)(
lt_percent,
@@ -1235,3 +1238,54 @@ rpl::producer<int> SetupChargeSlider(
return state->stars.value();
}
void EditDirectMessagesPriceBox(
not_null<Ui::GenericBox*> box,
not_null<ChannelData*> channel,
std::optional<int> savedValue,
Fn<void(std::optional<int>)> callback) {
box->setTitle(tr::lng_manage_monoforum());
const auto toggle = box->addRow(object_ptr<Ui::SettingsButton>(
box,
tr::lng_manage_monoforum_allow(),
st::settingsButtonNoIcon
), {})->toggleOn(rpl::single(savedValue.has_value()));
Ui::AddSkip(box->verticalLayout());
Ui::AddDividerText(
box->verticalLayout(),
tr::lng_manage_monoforum_about());
const auto wrap = box->addRow(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
box,
object_ptr<Ui::VerticalLayout>(box)),
{});
wrap->toggle(savedValue.has_value(), anim::type::instant);
wrap->toggleOn(toggle->toggledChanges());
const auto result = box->lifetime().make_state<int>(
savedValue.value_or(0));
const auto inner = wrap->entity();
Ui::AddSkip(inner);
SetupChargeSlider(
inner,
channel,
savedValue.value_or(0)
) | rpl::start_with_next([=](int stars) {
*result = stars;
}, box->lifetime());
box->addButton(tr::lng_settings_save(), [=] {
const auto weak = Ui::MakeWeak(box);
callback(toggle->toggled() ? *result : std::optional<int>());
if (const auto strong = weak.data()) {
strong->closeBox();
}
});
box->addButton(tr::lng_cancel(), [=] {
box->closeBox();
});
}

View File

@@ -174,3 +174,9 @@ void EditMessagesPrivacyBox(
not_null<Ui::VerticalLayout*> container,
not_null<PeerData*> peer,
int savedValue);
void EditDirectMessagesPriceBox(
not_null<Ui::GenericBox*> box,
not_null<ChannelData*> channel,
std::optional<int> savedValue,
Fn<void(std::optional<int>)> callback);

View File

@@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/replace_boost_box.h"
#include "boxes/peers/verify_peers_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/edit_privacy_box.h" // EditDirectMessagesPriceBox
#include "boxes/stickers_box.h"
#include "boxes/username_box.h"
#include "chat_helpers/emoji_suggestions_widget.h"
@@ -220,28 +221,41 @@ void SaveSlowmodeSeconds(
}
void SaveStarsPerMessage(
std::shared_ptr<Ui::Show> show,
not_null<ChannelData*> channel,
int starsPerMessage,
Fn<void()> done) {
Fn<void(bool)> done) {
const auto api = &channel->session().api();
const auto key = Api::RequestKey("stars_per_message", channel->id);
const auto broadcast = channel->isBroadcast();
using Flag = MTPchannels_UpdatePaidMessagesPrice::Flag;
const auto broadcastAllowed = broadcast && (starsPerMessage >= 0);
const auto requestId = api->request(MTPchannels_UpdatePaidMessagesPrice(
MTP_flags(0), // #TODO Support broadcast_messages_allowed flag in UI
MTP_flags(broadcastAllowed
? Flag::f_broadcast_messages_allowed
: Flag(0)),
channel->inputChannel,
MTP_long(starsPerMessage)
)).done([=](const MTPUpdates &result) {
api->clearModifyRequest(key);
api->applyUpdates(result);
channel->setStarsPerMessage(starsPerMessage);
done();
if (!broadcast) {
channel->setStarsPerMessage(starsPerMessage);
}
done(true);
}).fail([=](const MTP::Error &error) {
api->clearModifyRequest(key);
if (error.type() != u"CHAT_NOT_MODIFIED"_q) {
return;
show->showToast(error.type());
done(false);
} else {
if (!broadcast) {
channel->setStarsPerMessage(starsPerMessage);
}
done(true);
}
channel->setStarsPerMessage(starsPerMessage);
done();
}).send();
api->registerModifyRequest(key, requestId);
@@ -281,6 +295,7 @@ void SaveBoostsUnrestrict(
void ShowEditPermissions(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer) {
const auto show = navigation->uiShow();
auto createBox = [=](not_null<Ui::GenericBox*> box) {
const auto saving = box->lifetime().make_state<int>(0);
const auto save = [=](
@@ -299,7 +314,10 @@ void ShowEditPermissions(
channel,
result.boostsUnrestrict,
close);
SaveStarsPerMessage(channel, result.starsPerMessage, close);
const auto price = result.starsPerMessage;
SaveStarsPerMessage(show, channel, price, [=](bool ok) {
close();
});
}
};
auto done = [=](EditPeerPermissionsBoxResult result) {
@@ -366,6 +384,7 @@ private:
std::optional<bool> joinToWrite;
std::optional<bool> requestToJoin;
std::optional<ChannelData*> discussionLink;
std::optional<int> starsPerDirectMessage;
};
[[nodiscard]] object_ptr<Ui::RpWidget> createPhotoAndTitleEdit();
@@ -382,8 +401,10 @@ private:
void showEditPeerTypeBox(
std::optional<rpl::producer<QString>> error = {});
void showEditDiscussionLinkBox();
void showEditDirectMessagesBox();
void fillPrivacyTypeButton();
void fillDiscussionLinkButton();
void fillDirectMessagesButton();
//void fillInviteLinkButton();
void fillForumButton();
void fillColorIndexButton();
@@ -412,6 +433,7 @@ private:
[[nodiscard]] bool validateUsernamesOrder(Saving &to) const;
[[nodiscard]] bool validateUsername(Saving &to) const;
[[nodiscard]] bool validateDiscussionLink(Saving &to) const;
[[nodiscard]] bool validateDirectMessagesPrice(Saving &to) const;
[[nodiscard]] bool validateTitle(Saving &to) const;
[[nodiscard]] bool validateDescription(Saving &to) const;
[[nodiscard]] bool validateHistoryVisibility(Saving &to) const;
@@ -426,6 +448,7 @@ private:
void saveUsernamesOrder();
void saveUsername();
void saveDiscussionLink();
void saveDirectMessagesPrice();
void saveTitle();
void saveDescription();
void saveHistoryVisibility();
@@ -454,6 +477,7 @@ private:
std::optional<ChannelData*> _discussionLinkSavedValue;
ChannelData *_discussionLinkOriginalValue = nullptr;
bool _channelHasLocationOriginalValue = false;
std::optional<rpl::variable<int>> _starsPerDirectMessageSavedValue;
std::optional<HistoryVisibility> _historyVisibilitySavedValue;
std::optional<EditPeerTypeData> _typeDataSavedValue;
std::optional<bool> _forumSavedValue;
@@ -918,6 +942,20 @@ void Controller::showEditDiscussionLinkBox() {
}).send();
}
void Controller::showEditDirectMessagesBox() {
Expects(_peer->isBroadcast());
Expects(_starsPerDirectMessageSavedValue.has_value());
const auto stars = _starsPerDirectMessageSavedValue->current();
_navigation->parentController()->show(Box(
EditDirectMessagesPriceBox,
_peer->asChannel(),
(stars >= 0) ? stars : std::optional<int>(),
[=](std::optional<int> value) {
*_starsPerDirectMessageSavedValue = value.value_or(-1);
}));
}
void Controller::fillPrivacyTypeButton() {
Expects(_controls.buttonsLayout != nullptr);
@@ -983,9 +1021,11 @@ void Controller::fillPrivacyTypeButton() {
void Controller::fillDiscussionLinkButton() {
Expects(_controls.buttonsLayout != nullptr);
_discussionLinkSavedValue = _discussionLinkOriginalValue = _peer->isChannel()
? _peer->asChannel()->discussionLink()
: nullptr;
_discussionLinkSavedValue
= _discussionLinkOriginalValue
= (_peer->isChannel()
? _peer->asChannel()->discussionLink()
: nullptr);
const auto isGroup = (_peer->isChat() || _peer->isMegagroup());
auto text = !isGroup
@@ -1019,6 +1059,33 @@ void Controller::fillDiscussionLinkButton() {
{ isGroup ? &st::menuIconChannel : &st::menuIconGroups });
_discussionLinkUpdates.fire_copy(*_discussionLinkSavedValue);
}
void Controller::fillDirectMessagesButton() {
Expects(_controls.buttonsLayout != nullptr);
if (!_peer->isBroadcast() || !_peer->asChannel()->canEditInformation()) {
return;
}
const auto monoforumLink = _peer->asChannel()->monoforumLink();
_starsPerDirectMessageSavedValue = rpl::variable<int>(
monoforumLink ? monoforumLink->starsPerMessage() : -1);
auto label = _starsPerDirectMessageSavedValue->value(
) | rpl::map([](int starsPerMessage) {
return (starsPerMessage < 0)
? tr::lng_manage_monoforum_off()
: !starsPerMessage
? tr::lng_manage_monoforum_free()
: rpl::single(Lang::FormatCountDecimal(starsPerMessage));
}) | rpl::flatten_latest();
AddButtonWithText(
_controls.buttonsLayout,
tr::lng_manage_monoforum(),
std::move(label),
[=] { showEditDirectMessagesBox(); },
{ &st::menuIconChatBubble });
}
//
//void Controller::fillInviteLinkButton() {
// Expects(_controls.buttonsLayout != nullptr);
@@ -1359,6 +1426,8 @@ void Controller::fillManageSection() {
const auto canViewOrEditDiscussionLink = isChannel
&& (channel->discussionLink()
|| (channel->isBroadcast() && channel->canEditInformation()));
const auto canEditDirectMessages = isChannel
&& (channel->isBroadcast() && channel->canEditInformation());
::AddSkip(_controls.buttonsLayout, 0);
@@ -1370,6 +1439,9 @@ void Controller::fillManageSection() {
if (canViewOrEditDiscussionLink) {
fillDiscussionLinkButton();
}
if (canEditDirectMessages) {
fillDirectMessagesButton();
}
if (canEditPreHistoryHidden) {
fillHistoryVisibilityButton();
}
@@ -1973,6 +2045,7 @@ std::optional<Controller::Saving> Controller::validate() const {
if (validateUsernamesOrder(result)
&& validateUsername(result)
&& validateDiscussionLink(result)
&& validateDirectMessagesPrice(result)
&& validateTitle(result)
&& validateDescription(result)
&& validateHistoryVisibility(result)
@@ -2022,6 +2095,14 @@ bool Controller::validateDiscussionLink(Saving &to) const {
return true;
}
bool Controller::validateDirectMessagesPrice(Saving &to) const {
if (!_starsPerDirectMessageSavedValue) {
return true;
}
to.starsPerDirectMessage = _starsPerDirectMessageSavedValue->current();
return true;
}
bool Controller::validateTitle(Saving &to) const {
if (!_controls.title) {
return true;
@@ -2120,6 +2201,7 @@ void Controller::save() {
pushSaveStage([=] { saveUsernamesOrder(); });
pushSaveStage([=] { saveUsername(); });
pushSaveStage([=] { saveDiscussionLink(); });
pushSaveStage([=] { saveDirectMessagesPrice(); });
pushSaveStage([=] { saveTitle(); });
pushSaveStage([=] { saveDescription(); });
pushSaveStage([=] { saveHistoryVisibility(); });
@@ -2277,6 +2359,30 @@ void Controller::saveDiscussionLink() {
}).send();
}
void Controller::saveDirectMessagesPrice() {
const auto channel = _peer->asChannel();
if (!channel) {
return continueSave();
}
const auto monoforumLink = channel->monoforumLink();
const auto current = monoforumLink ? monoforumLink->starsPerMessage() : -1;
const auto desired = _savingData.starsPerDirectMessage
? *_savingData.starsPerDirectMessage
: current;
if (desired == current) {
return continueSave();
}
const auto show = _navigation->uiShow();
const auto done = [=](bool ok) {
if (ok) {
continueSave();
} else {
cancelSave();
}
};
SaveStarsPerMessage(show, channel, desired, crl::guard(this, done));
}
void Controller::saveTitle() {
if (!_savingData.title || *_savingData.title == _peer->name()) {
return continueSave();

View File

@@ -907,6 +907,7 @@ void PinsLimitBox(
limits.dialogsPinnedPremium(),
PinsCount(session->data().chatsList()));
}
void SublistsPinsLimitBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session) {