Support free transcribes in groups.

This commit is contained in:
John Preston 2024-02-09 18:09:48 +04:00
parent cfaef4c441
commit fc6f2520b7
8 changed files with 41 additions and 22 deletions

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_transcribes.h" #include "api/api_transcribes.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "data/data_channel.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_peer.h" #include "data/data_peer.h"
#include "data/data_session.h" #include "data/data_session.h"
@ -25,6 +26,14 @@ Transcribes::Transcribes(not_null<ApiWrap*> api)
, _api(&api->instance()) { , _api(&api->instance()) {
} }
bool Transcribes::freeFor(not_null<HistoryItem*> item) const {
if (const auto channel = item->history()->peer->asMegagroup()) {
const auto owner = &channel->owner();
return channel->levelHint() >= owner->groupFreeTranscribeLevel();
}
return false;
}
bool Transcribes::trialsSupport() { bool Transcribes::trialsSupport() {
if (!_trialsSupport) { if (!_trialsSupport) {
const auto count = _session->account().appConfig().get<int>( const auto count = _session->account().appConfig().get<int>(

View file

@ -36,6 +36,8 @@ public:
void apply(const MTPDupdateTranscribedAudio &update); void apply(const MTPDupdateTranscribedAudio &update);
[[nodiscard]] bool freeFor(not_null<HistoryItem*> item) const;
[[nodiscard]] bool trialsSupport(); [[nodiscard]] bool trialsSupport();
[[nodiscard]] TimeId trialsRefreshAt(); [[nodiscard]] TimeId trialsRefreshAt();
[[nodiscard]] int trialsCount(); [[nodiscard]] int trialsCount();

View file

@ -1094,9 +1094,7 @@ void Controller::fillManageSection() {
&& (channel->hasAdminRights() || channel->amCreator()); && (channel->hasAdminRights() || channel->amCreator());
const auto canEditStickers = isChannel && channel->canEditStickers(); const auto canEditStickers = isChannel && channel->canEditStickers();
const auto canDeleteChannel = isChannel && channel->canDelete(); const auto canDeleteChannel = isChannel && channel->canDelete();
const auto canEditColorIndex = isChannel const auto canEditColorIndex = isChannel && channel->canEditEmoji();
&& (channel->amCreator()
|| (channel->adminRights() & ChatAdminRight::ChangeInfo));
const auto canViewOrEditLinkedChat = isChannel const auto canViewOrEditLinkedChat = isChannel
&& (channel->linkedChat() && (channel->linkedChat()
|| (channel->isBroadcast() && channel->canEditInformation())); || (channel->isBroadcast() && channel->canEditInformation()));

View file

@ -649,7 +649,7 @@ bool ChannelData::canEditStickers() const {
} }
bool ChannelData::canEditEmoji() const { bool ChannelData::canEditEmoji() const {
return amCreator(); AssertIsDebug(); return amCreator() || (adminRights() & ChatAdminRight::ChangeInfo);
} }
bool ChannelData::canDelete() const { bool ChannelData::canDelete() const {

View file

@ -238,6 +238,12 @@ Session::Session(not_null<Main::Session*> session)
, _bigFileCache(Core::App().databases().get( , _bigFileCache(Core::App().databases().get(
_session->local().cacheBigFilePath(), _session->local().cacheBigFilePath(),
_session->local().cacheBigFileSettings())) _session->local().cacheBigFileSettings()))
, _groupFreeTranscribeLevel(session->account().appConfig().value(
) | rpl::map([=] {
return session->account().appConfig().get<int>(
u"group_transcribe_level_min"_q,
6);
}))
, _chatsList( , _chatsList(
session, session,
FilterId(), FilterId(),
@ -2178,8 +2184,7 @@ rpl::producer<int> Session::maxPinnedChatsLimitValue(
// We always use premium limit in the MainList limit producer, // We always use premium limit in the MainList limit producer,
// because it slices the list to that limit. We don't want to slice // because it slices the list to that limit. We don't want to slice
// premium-ly added chats from the pinned list because of sync issues. // premium-ly added chats from the pinned list because of sync issues.
return rpl::single(rpl::empty_value()) | rpl::then( return _session->account().appConfig().value(
_session->account().appConfig().refreshed()
) | rpl::map([=] { ) | rpl::map([=] {
const auto limits = Data::PremiumLimits(_session); const auto limits = Data::PremiumLimits(_session);
return folder return folder
@ -2194,8 +2199,7 @@ rpl::producer<int> Session::maxPinnedChatsLimitValue(
// We always use premium limit in the MainList limit producer, // We always use premium limit in the MainList limit producer,
// because it slices the list to that limit. We don't want to slice // because it slices the list to that limit. We don't want to slice
// premium-ly added chats from the pinned list because of sync issues. // premium-ly added chats from the pinned list because of sync issues.
return rpl::single(rpl::empty_value()) | rpl::then( return _session->account().appConfig().value(
_session->account().appConfig().refreshed()
) | rpl::map([=] { ) | rpl::map([=] {
const auto limits = Data::PremiumLimits(_session); const auto limits = Data::PremiumLimits(_session);
return limits.dialogFiltersChatsPremium(); return limits.dialogFiltersChatsPremium();
@ -2204,8 +2208,7 @@ rpl::producer<int> Session::maxPinnedChatsLimitValue(
rpl::producer<int> Session::maxPinnedChatsLimitValue( rpl::producer<int> Session::maxPinnedChatsLimitValue(
not_null<Data::Forum*> forum) const { not_null<Data::Forum*> forum) const {
return rpl::single(rpl::empty_value()) | rpl::then( return _session->account().appConfig().value(
_session->account().appConfig().refreshed()
) | rpl::map([=] { ) | rpl::map([=] {
const auto limits = Data::PremiumLimits(_session); const auto limits = Data::PremiumLimits(_session);
return limits.topicsPinnedCurrent(); return limits.topicsPinnedCurrent();
@ -2218,14 +2221,17 @@ rpl::producer<int> Session::maxPinnedChatsLimitValue(
// We always use premium limit in the MainList limit producer, // We always use premium limit in the MainList limit producer,
// because it slices the list to that limit. We don't want to slice // because it slices the list to that limit. We don't want to slice
// premium-ly added chats from the pinned list because of sync issues. // premium-ly added chats from the pinned list because of sync issues.
return rpl::single(rpl::empty_value()) | rpl::then( return _session->account().appConfig().value(
_session->account().appConfig().refreshed()
) | rpl::map([=] { ) | rpl::map([=] {
const auto limits = Data::PremiumLimits(_session); const auto limits = Data::PremiumLimits(_session);
return limits.savedSublistsPinnedPremium(); return limits.savedSublistsPinnedPremium();
}); });
} }
int Session::groupFreeTranscribeLevel() const {
return _groupFreeTranscribeLevel.current();
}
const std::vector<Dialogs::Key> &Session::pinnedChatsOrder( const std::vector<Dialogs::Key> &Session::pinnedChatsOrder(
Data::Folder *folder) const { Data::Folder *folder) const {
return chatsList(folder)->pinned()->order(); return chatsList(folder)->pinned()->order();

View file

@ -367,6 +367,7 @@ public:
not_null<Forum*> forum) const; not_null<Forum*> forum) const;
[[nodiscard]] rpl::producer<int> maxPinnedChatsLimitValue( [[nodiscard]] rpl::producer<int> maxPinnedChatsLimitValue(
not_null<SavedMessages*> saved) const; not_null<SavedMessages*> saved) const;
[[nodiscard]] int groupFreeTranscribeLevel() const;
[[nodiscard]] const std::vector<Dialogs::Key> &pinnedChatsOrder( [[nodiscard]] const std::vector<Dialogs::Key> &pinnedChatsOrder(
Folder *folder) const; Folder *folder) const;
[[nodiscard]] const std::vector<Dialogs::Key> &pinnedChatsOrder( [[nodiscard]] const std::vector<Dialogs::Key> &pinnedChatsOrder(
@ -887,6 +888,7 @@ private:
QPointer<Ui::BoxContent> _exportSuggestion; QPointer<Ui::BoxContent> _exportSuggestion;
rpl::variable<bool> _contactsLoaded = false; rpl::variable<bool> _contactsLoaded = false;
rpl::variable<int> _groupFreeTranscribeLevel;
rpl::event_stream<Folder*> _chatsListLoadedEvents; rpl::event_stream<Folder*> _chatsListLoadedEvents;
rpl::event_stream<Folder*> _chatsListChanged; rpl::event_stream<Folder*> _chatsListChanged;
rpl::event_stream<not_null<UserData*>> _userIsBotChanges; rpl::event_stream<not_null<UserData*>> _userIsBotChanges;

View file

@ -221,14 +221,14 @@ void TranscribeButton::paint(
} }
bool TranscribeButton::hasLock() const { bool TranscribeButton::hasLock() const {
if (_item->history()->session().premium()) { const auto session = &_item->history()->session();
const auto transcribes = &session->api().transcribes();
if (session->premium()
|| transcribes->freeFor(_item)
|| transcribes->trialsCount()) {
return false; return false;
} }
if (_item->history()->session().api().transcribes().trialsCount()) { const auto until = transcribes->trialsRefreshAt();
return false;
}
const auto until = _item->history()->session().api().transcribes()
.trialsRefreshAt();
if (!until || base::unixtime::now() >= until) { if (!until || base::unixtime::now() >= until) {
return false; return false;
} }

View file

@ -439,10 +439,13 @@ QSize Document::countOptimalSize() {
auto hasTranscribe = false; auto hasTranscribe = false;
const auto voice = Get<HistoryDocumentVoice>(); const auto voice = Get<HistoryDocumentVoice>();
if (voice) { if (voice) {
const auto session = &_realParent->history()->session(); const auto history = _realParent->history();
const auto session = &history->session();
const auto transcribes = &session->api().transcribes();
if (_parent->data()->media()->ttlSeconds() if (_parent->data()->media()->ttlSeconds()
|| (!session->premium() || (!session->premium()
&& !session->api().transcribes().trialsSupport())) { && !transcribes->freeFor(_realParent)
&& !transcribes->trialsSupport())) {
voice->transcribe = nullptr; voice->transcribe = nullptr;
voice->transcribeText = {}; voice->transcribeText = {};
} else { } else {
@ -452,8 +455,7 @@ QSize Document::countOptimalSize() {
_realParent, _realParent,
false); false);
} }
const auto &entry = session->api().transcribes().entry( const auto &entry = transcribes->entry(_realParent);
_realParent);
const auto update = [=] { repaint(); }; const auto update = [=] { repaint(); };
voice->transcribe->setLoading( voice->transcribe->setLoading(
entry.shown && (entry.requestId || entry.pending), entry.shown && (entry.requestId || entry.pending),