mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-22 02:07:24 +00:00
Implement paid global search requests.
This commit is contained in:
parent
608481df38
commit
b5c1046dca
@ -2945,6 +2945,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_credits_small_balance_for_message" = "Buy **Stars** to send messages to {user}.";
|
||||
"lng_credits_small_balance_for_messages" = "Buy **Stars** to send messages.";
|
||||
"lng_credits_small_balance_for_suggest" = "Buy **Stars** to suggest post to {channel}.";
|
||||
"lng_credits_small_balance_for_search" = "Buy **Stars** to search through public posts.";
|
||||
"lng_credits_small_balance_fallback" = "Buy **Stars** to unlock content and services on Telegram.";
|
||||
"lng_credits_purchase_blocked" = "Sorry, you can't purchase this item with Telegram Stars.";
|
||||
"lng_credits_enough" = "You have enough stars at the moment. {link}";
|
||||
|
@ -841,13 +841,13 @@ postsSearchIntroTitle: FlatLabel(defaultFlatLabel) {
|
||||
}
|
||||
align: align(top);
|
||||
}
|
||||
postsSearchIntroTitleMargin: margins(20px, 0px, 20px, 12px);
|
||||
postsSearchIntroTitleMargin: margins(20px, 0px, 20px, 4px);
|
||||
postsSearchIntroSubtitle: FlatLabel(defaultFlatLabel) {
|
||||
textFg: windowSubTextFg;
|
||||
minWidth: 64px;
|
||||
align: align(top);
|
||||
}
|
||||
postsSearchIntroSubtitleMargin: margins(20px, 4px, 20px, 12px);
|
||||
postsSearchIntroSubtitleMargin: margins(20px, 4px, 20px, 16px);
|
||||
postsSearchIntroButton: RoundButton(defaultActiveButton) {
|
||||
width: 200px;
|
||||
height: 42px;
|
||||
|
@ -164,7 +164,8 @@ constexpr auto kPreviewPostsLimit = 3;
|
||||
: state.fromPeer;
|
||||
const auto waiting = trimmed.isEmpty()
|
||||
&& state.tags.empty()
|
||||
&& !fromPeer;
|
||||
&& !fromPeer
|
||||
&& state.tab != ChatSearchTab::PublicPosts;
|
||||
const auto suggestAllChats = !waiting
|
||||
&& state.tab == ChatSearchTab::MyMessages
|
||||
&& state.filter != ChatTypeFilter::All;
|
||||
|
@ -43,25 +43,38 @@ void PostsSearch::requestMore() {
|
||||
}
|
||||
|
||||
void PostsSearch::setQuery(const QString &query) {
|
||||
if (_query == query) {
|
||||
const auto words = TextUtilities::PrepareSearchWords(query);
|
||||
const auto prepared = words.isEmpty() ? QString() : words.join(' ');
|
||||
if (_query == prepared) {
|
||||
return;
|
||||
}
|
||||
_query = query;
|
||||
const auto i = _entries.find(query);
|
||||
_query = prepared;
|
||||
const auto i = _entries.find(prepared);
|
||||
if (i != end(_entries)) {
|
||||
pushStateUpdate(i->second);
|
||||
} else if (query.isEmpty()) {
|
||||
} else if (prepared.isEmpty()) {
|
||||
applyQuery();
|
||||
} else {
|
||||
_timer.callOnce(kQueryDelay);
|
||||
}
|
||||
}
|
||||
|
||||
void PostsSearch::setAllowedStars(int stars) {
|
||||
if (_query) {
|
||||
_entries[*_query].allowedStars = stars;
|
||||
requestSearch(*_query);
|
||||
int PostsSearch::setAllowedStars(int stars) {
|
||||
if (!_query) {
|
||||
return 0;
|
||||
} else if (_floodState) {
|
||||
if (_floodState->freeSearchesLeft > 0) {
|
||||
stars = 0;
|
||||
} else if (_floodState->nextFreeSearchTime > 0
|
||||
&& _floodState->nextFreeSearchTime <= base::unixtime::now()) {
|
||||
stars = 0;
|
||||
} else {
|
||||
stars = std::min(int(_floodState->starsPerPaidSearch), stars);
|
||||
}
|
||||
}
|
||||
_entries[*_query].allowedStars = stars;
|
||||
requestSearch(*_query);
|
||||
return stars;
|
||||
}
|
||||
|
||||
void PostsSearch::pushStateUpdate(const Entry &entry) {
|
||||
@ -118,17 +131,20 @@ void PostsSearch::requestSearch(const QString &query) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto useStars = entry.allowedStars;
|
||||
entry.allowedStars = 0;
|
||||
|
||||
using Flag = MTPchannels_SearchPosts::Flag;
|
||||
entry.searchId = _api.request(MTPchannels_SearchPosts(
|
||||
MTP_flags(Flag::f_query
|
||||
| (entry.allowedStars ? Flag::f_allow_paid_stars : Flag())),
|
||||
| (useStars ? Flag::f_allow_paid_stars : Flag())),
|
||||
MTP_string(), // hashtag
|
||||
MTP_string(query),
|
||||
MTP_int(entry.offsetRate),
|
||||
(entry.offsetPeer ? entry.offsetPeer->input : MTP_inputPeerEmpty()),
|
||||
MTP_int(entry.offsetId),
|
||||
MTP_int(kPerPage),
|
||||
MTP_long(entry.allowedStars)
|
||||
MTP_long(useStars)
|
||||
)).done([=](const MTPmessages_Messages &result) {
|
||||
auto &entry = _entries[query];
|
||||
entry.searchId = 0;
|
||||
@ -207,7 +223,11 @@ void PostsSearch::requestSearch(const QString &query) {
|
||||
entry.pages.clear();
|
||||
}
|
||||
entry.pages.push_back(std::move(messages));
|
||||
const auto count = int(entry.pages.size());
|
||||
const auto count = int(ranges::accumulate(
|
||||
entry.pages,
|
||||
size_type(),
|
||||
ranges::plus(),
|
||||
&std::vector<not_null<HistoryItem*>>::size));
|
||||
const auto full = entry.loaded ? count : std::max(count, totalCount);
|
||||
entry.totalCount = full;
|
||||
if (initial && _query == query) {
|
||||
@ -229,7 +249,7 @@ void PostsSearch::requestSearch(const QString &query) {
|
||||
|
||||
void PostsSearch::setFloodStateFrom(const MTPDsearchPostsFlood &data) {
|
||||
_recheckTimer.cancel();
|
||||
const auto left = data.vremains().v;
|
||||
const auto left = std::max(data.vremains().v, 0);
|
||||
const auto next = data.vwait_till().value_or_empty();
|
||||
if (!left && next > 0) {
|
||||
const auto now = base::unixtime::now();
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
[[nodiscard]] rpl::producer<PostsSearchState> stateUpdates() const;
|
||||
|
||||
void setQuery(const QString &query);
|
||||
void setAllowedStars(int stars);
|
||||
int setAllowedStars(int stars);
|
||||
void requestMore();
|
||||
|
||||
private:
|
||||
|
@ -38,11 +38,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "settings/settings_credits_graphics.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/controls/swipe_handler.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
@ -1821,8 +1823,9 @@ bool Suggestions::consumeSearchQuery(const QString &query) {
|
||||
const auto tab = key.tab;
|
||||
const auto type = (key.tab == Tab::Media) ? key.mediaType : Type::kCount;
|
||||
if (tab == Tab::Posts) {
|
||||
const auto changed = (_searchQuery != query);
|
||||
setPostsSearchQuery(query);
|
||||
return !query.isEmpty();
|
||||
return changed || !query.isEmpty();
|
||||
} else if (tab != Tab::Downloads
|
||||
&& type != Type::File
|
||||
&& type != Type::Link
|
||||
@ -1881,6 +1884,7 @@ void Suggestions::setPostsSearchQuery(const QString &query) {
|
||||
if (!_postsSearch) {
|
||||
setupPostsSearch();
|
||||
}
|
||||
_searchQuery = query;
|
||||
_searchQueryTimer.cancel();
|
||||
_postsSearch->setQuery(query);
|
||||
}
|
||||
@ -1938,8 +1942,32 @@ void Suggestions::setupPostsIntro(const PostsSearchIntroState &intro) {
|
||||
Settings::ShowPremium(
|
||||
_controller,
|
||||
u"posts_search"_q);
|
||||
} else if (!stars) {
|
||||
_postsSearch->setAllowedStars(0);
|
||||
} else {
|
||||
_postsSearch->setAllowedStars(stars);
|
||||
using namespace Settings;
|
||||
const auto done = [=](Settings::SmallBalanceResult result) {
|
||||
if (result == Settings::SmallBalanceResult::Success
|
||||
|| result == Settings::SmallBalanceResult::Already) {
|
||||
const auto spent = _postsSearch->setAllowedStars(stars);
|
||||
if (spent > 0) {
|
||||
_controller->showToast({
|
||||
.text = tr::lng_posts_paid_spent(
|
||||
tr::now,
|
||||
lt_count,
|
||||
spent,
|
||||
Ui::Text::RichLangValue),
|
||||
.attach = RectPart::Top,
|
||||
.duration = Ui::Toast::kDefaultDuration * 2,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
MaybeRequestBalanceIncrease(
|
||||
_controller->uiShow(),
|
||||
stars,
|
||||
SmallBalanceForSearch{},
|
||||
done);
|
||||
}
|
||||
}, _postsSearchIntro->lifetime());
|
||||
|
||||
|
@ -162,6 +162,7 @@ void PostsSearchIntro::setup() {
|
||||
st::resaleButtonTitle,
|
||||
st::resaleButtonSubtitle);
|
||||
}
|
||||
_content->resizeToWidth(width());
|
||||
}, _button->lifetime());
|
||||
}
|
||||
|
||||
|
@ -2493,7 +2493,7 @@ void SmallBalanceBox(
|
||||
return owner->peer(peerFromChannel(value.channelId))->name();
|
||||
}, [](SmallBalanceSubscription value) {
|
||||
return value.name;
|
||||
}, [](SmallBalanceDeepLink value) {
|
||||
}, [](SmallBalanceDeepLink) {
|
||||
return QString();
|
||||
}, [&](SmallBalanceStarGift value) {
|
||||
return owner->peer(value.recipientId)->shortName();
|
||||
@ -2505,6 +2505,8 @@ void SmallBalanceBox(
|
||||
return value.recipientId
|
||||
? owner->peer(value.recipientId)->shortName()
|
||||
: QString();
|
||||
}, [](SmallBalanceForSearch) {
|
||||
return QString();
|
||||
});
|
||||
|
||||
auto needed = show->session().credits().balanceValue(
|
||||
@ -2556,6 +2558,9 @@ void SmallBalanceBox(
|
||||
lt_channel,
|
||||
rpl::single(Ui::Text::Bold(name)),
|
||||
Ui::Text::RichLangValue)
|
||||
: v::is<SmallBalanceForSearch>(source)
|
||||
? tr::lng_credits_small_balance_for_search(
|
||||
Ui::Text::RichLangValue)
|
||||
: name.isEmpty()
|
||||
? tr::lng_credits_small_balance_fallback(
|
||||
Ui::Text::RichLangValue)
|
||||
|
@ -242,6 +242,8 @@ struct SmallBalanceForMessage {
|
||||
struct SmallBalanceForSuggest {
|
||||
PeerId recipientId;
|
||||
};
|
||||
struct SmallBalanceForSearch {
|
||||
};
|
||||
struct SmallBalanceSource : std::variant<
|
||||
SmallBalanceBot,
|
||||
SmallBalanceReaction,
|
||||
@ -249,7 +251,8 @@ struct SmallBalanceSource : std::variant<
|
||||
SmallBalanceDeepLink,
|
||||
SmallBalanceStarGift,
|
||||
SmallBalanceForMessage,
|
||||
SmallBalanceForSuggest> {
|
||||
SmallBalanceForSuggest,
|
||||
SmallBalanceForSearch> {
|
||||
using variant::variant;
|
||||
};
|
||||
|
||||
|
@ -22,10 +22,12 @@ void SetButtonTwoLabels(
|
||||
button,
|
||||
std::move(title),
|
||||
st);
|
||||
buttonTitle->show();
|
||||
const auto buttonSubtitle = Ui::CreateChild<Ui::FlatLabel>(
|
||||
button,
|
||||
std::move(subtitle),
|
||||
subst);
|
||||
buttonSubtitle->show();
|
||||
buttonSubtitle->setOpacity(0.6);
|
||||
if (textFg) {
|
||||
buttonTitle->setTextColorOverride((*textFg)->c);
|
||||
|
Loading…
x
Reference in New Issue
Block a user