Show limit toasts and boxes.

This commit is contained in:
John Preston 2022-05-09 17:09:46 +04:00
parent d11f1c22be
commit dd05fb4d14
25 changed files with 363 additions and 69 deletions

View File

@ -204,14 +204,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_fave_sticker_limit_title#one" = "The Limit of {count} Stickers Reached";
"lng_fave_sticker_limit_title#other" = "The Limit of {count} Stickers Reached";
"lng_fave_sticker_limit_more#one" = "An older sticker was replaced with this one. You can {link} to {count} sticker.";
"lng_fave_sticker_limit_more#other" = "An older sticker was replaced with this one. You can {link} to {count} stickers.";
"lng_fave_sticker_limit_more#one" = "An older sticker was replaced with this one.\nYou can {link} to {count} sticker.";
"lng_fave_sticker_limit_more#other" = "An older sticker was replaced with this one.\nYou can {link} to {count} stickers.";
"lng_fave_sticker_limit_link" = "increase the limit";
"lng_saved_gif_limit_title#one" = "The Limit of {count} GIF Reached";
"lng_saved_gif_limit_title#other" = "The Limit of {count} GIFs Reached";
"lng_saved_gif_limit_more#one" = "An older GIF was replaced with this one. You can {link} to {count} GIF.";
"lng_saved_gif_limit_more#other" = "An older GIF was replaced with this one. You can {link} to {count} GIFs.";
"lng_saved_gif_limit_more#one" = "An older GIF was replaced with this one.\nYou can {link} to {count} GIF.";
"lng_saved_gif_limit_more#other" = "An older GIF was replaced with this one.\nYou can {link} to {count} GIFs.";
"lng_saved_gif_limit_link" = "increase the limit";
"lng_limits_increase" = "Increase Limit";

View File

@ -21,9 +21,7 @@ void SaveNewFilterPinned(
nullptr,
filterId);
auto &filters = session->data().chatsFilters();
const auto &filter = filters.applyUpdatedPinned(
filterId,
order);
const auto &filter = filters.applyUpdatedPinned(filterId, order);
session->api().request(MTPmessages_UpdateDialogFilter(
MTP_flags(MTPmessages_UpdateDialogFilter::Flag::f_filter),
MTP_int(filterId),

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h"
#include "data/data_session.h"
#include "data/stickers/data_stickers.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
namespace Api {
@ -47,28 +48,35 @@ void ToggleExistingMedia(
} // namespace
void ToggleFavedSticker(
not_null<Window::SessionController*> controller,
not_null<DocumentData*> document,
Data::FileOrigin origin) {
ToggleFavedSticker(
controller,
document,
std::move(origin),
!document->owner().stickers().isFaved(document));
}
void ToggleFavedSticker(
not_null<Window::SessionController*> controller,
not_null<DocumentData*> document,
Data::FileOrigin origin,
bool faved) {
if (faved && !document->sticker()) {
return;
}
const auto weak = base::make_weak(controller.get());
auto done = [=] {
document->owner().stickers().setFaved(weak.get(), document, faved);
};
ToggleExistingMedia(
document,
std::move(origin),
[=, d = document] {
return MTPmessages_FaveSticker(d->mtpInput(), MTP_bool(!faved));
},
[=] { document->owner().stickers().setFaved(document, faved); });
std::move(done));
}
void ToggleRecentSticker(
@ -96,15 +104,17 @@ void ToggleRecentSticker(
}
void ToggleSavedGif(
Window::SessionController *controller,
not_null<DocumentData*> document,
Data::FileOrigin origin,
bool saved) {
if (saved && !document->isGifv()) {
return;
}
const auto weak = base::make_weak(controller);
auto done = [=] {
if (saved) {
document->owner().stickers().addSavedGif(document);
document->owner().stickers().addSavedGif(weak.get(), document);
}
};
ToggleExistingMedia(

View File

@ -7,13 +7,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Window {
class SessionController;
} // namespace Window
namespace Api {
void ToggleFavedSticker(
not_null<Window::SessionController*> controller,
not_null<DocumentData*> document,
Data::FileOrigin origin);
void ToggleFavedSticker(
not_null<Window::SessionController*> controller,
not_null<DocumentData*> document,
Data::FileOrigin origin,
bool faved);
@ -24,6 +30,7 @@ void ToggleRecentSticker(
bool saved);
void ToggleSavedGif(
Window::SessionController *controller,
not_null<DocumentData*> document,
Data::FileOrigin origin,
bool saved);

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/choose_filter_box.h"
#include "apiwrap.h"
#include "boxes/premium_limits_box.h"
#include "core/application.h" // primaryWindow
#include "data/data_chat_filters.h"
#include "data/data_session.h"
@ -116,6 +117,15 @@ bool ChooseFilterValidator::canRemove(FilterId filterId) const {
return false;
}
bool ChooseFilterValidator::limitReached(FilterId filterId) const {
const auto list = _history->owner().chatsFilters().list();
const auto i = ranges::find(list, filterId, &Data::ChatFilter::id);
const auto limit = _history->owner().pinnedChatsLimit(nullptr, filterId);
return (i != end(list))
&& !ranges::contains(i->always(), _history)
&& (i->always().size() >= limit);
}
void ChooseFilterValidator::add(FilterId filterId) const {
ChangeFilterById(filterId, _history, true);
}
@ -125,8 +135,10 @@ void ChooseFilterValidator::remove(FilterId filterId) const {
}
void FillChooseFilterMenu(
not_null<Window::SessionController*> controller,
not_null<Ui::PopupMenu*> menu,
not_null<History*> history) {
const auto weak = base::make_weak(controller.get());
const auto validator = ChooseFilterValidator(history);
for (const auto &filter : history->owner().chatsFilters().list()) {
const auto id = filter.id();
@ -136,10 +148,11 @@ void FillChooseFilterMenu(
if (validator.canRemove(id)) {
validator.remove(id);
}
} else {
if (validator.canAdd()) {
validator.add(id);
}
} else if (validator.limitReached(id)) {
controller->show(
Box(FilterChatsLimitBox, &controller->session()));
} else if (validator.canAdd()) {
validator.add(id);
}
}, contains ? &st::mediaPlayerMenuCheck : nullptr);
action->setEnabled(contains

View File

@ -11,6 +11,10 @@ namespace Ui {
class PopupMenu;
} // namespace Ui
namespace Window {
class SessionController;
} // namespace Window
class History;
class ChooseFilterValidator final {
@ -19,6 +23,7 @@ public:
[[nodiscard]] bool canAdd() const;
[[nodiscard]] bool canRemove(FilterId filterId) const;
[[nodiscard]] bool limitReached(FilterId filterId) const;
void add(FilterId filterId) const;
void remove(FilterId filterId) const;
@ -29,5 +34,6 @@ private:
};
void FillChooseFilterMenu(
not_null<Window::SessionController*> controller,
not_null<Ui::PopupMenu*> menu,
not_null<History*> history);

View File

@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include "styles/style_info.h"
namespace {
@ -243,8 +244,8 @@ std::unique_ptr<PeerListRow> InactiveController::createRow(
[[nodiscard]] float64 Limit(
not_null<Main::Session*> session,
const QString &key,
double fallback) {
return session->account().appConfig().get<double>(key, fallback);
int fallback) {
return 1. * AppConfigLimit(session, key, fallback);
}
void SimpleLimitBox(
@ -277,6 +278,19 @@ void SimpleLimitBox(
st::changePhoneDescription)),
st::changePhoneDescriptionPadding);
box->setNoContentMargin(true);
const auto close = Ui::CreateChild<Ui::IconButton>(
box.get(),
st::infoLayerTopBarClose);
close->addClickHandler([=] { box->closeBox(); });
box->widthValue() | rpl::start_with_next([=](int width) {
close->moveToRight(0, 0, width);
}, close->lifetime());
box->setFocusCallback([=] {
close->raise();
});
if (premium) {
box->addButton(tr::lng_box_ok(), [=] {
box->closeBox();
@ -531,9 +545,21 @@ void FilterPinsLimitBox(
SimplePinsLimitBox(
box,
session,
"dialog_filters_pinned_limit_default",
"dialog_filters_chats_limit_default",
100,
"dialog_filters_pinned_limit_premium",
"dialog_filters_chats_limit_premium",
200);
}
void FolderPinsLimitBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session) {
SimplePinsLimitBox(
box,
session,
"dialog_filters_chats_limit_default",
100,
"dialog_filters_chats_limit_premium",
200);
}
@ -548,3 +574,24 @@ void PinsLimitBox(
"dialogs_pinned_limit_premium",
10);
}
int AppConfigLimit(
not_null<Main::Session*> session,
const QString &key,
int fallback) {
return int(base::SafeRound(
session->account().appConfig().get<double>(key, 1. * fallback)));
}
int CurrentPremiumLimit(
not_null<Main::Session*> session,
const QString &keyDefault,
int limitDefault,
const QString &keyPremium,
int limitPremium) {
const auto premium = session->user()->isPremium();
return AppConfigLimit(
session,
premium ? keyPremium : keyDefault,
premium ? limitPremium : limitDefault);
}

View File

@ -28,6 +28,20 @@ void FiltersLimitBox(
void FilterPinsLimitBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session);
void FolderPinsLimitBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session);
void PinsLimitBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session);
[[nodiscard]] int AppConfigLimit(
not_null<Main::Session*> session,
const QString &key,
int fallback);
[[nodiscard]] int CurrentPremiumLimit(
not_null<Main::Session*> session,
const QString &keyDefault,
int limitDefault,
const QString &keyPremium,
int limitPremium);

View File

@ -699,8 +699,10 @@ void StickerSetBox::Inner::contextMenuEvent(QContextMenuEvent *e) {
SendMenu::DefaultSilentCallback(sendSelected),
SendMenu::DefaultScheduleCallback(this, type, sendSelected));
const auto controller = _controller;
const auto toggleFavedSticker = [=] {
Api::ToggleFavedSticker(
controller,
document,
Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0));
};

View File

@ -52,6 +52,7 @@ constexpr auto kMinAfterScrollDelay = crl::time(33);
void AddGifAction(
Fn<void(QString, Fn<void()> &&, const style::icon*)> callback,
Window::SessionController *controller,
not_null<DocumentData*> document) {
if (!document->isGifv()) {
return;
@ -64,6 +65,7 @@ void AddGifAction(
: tr::lng_context_save_gif)(tr::now);
callback(text, [=] {
Api::ToggleSavedGif(
controller,
document,
Data::FileOriginSavedGifs(),
!saved);
@ -396,7 +398,7 @@ void GifsListWidget::fillContextMenu(
const style::icon *icon) {
menu->addAction(text, std::move(done), icon);
};
AddGifAction(std::move(callback), document);
AddGifAction(std::move(callback), controller(), document);
}
};
}

View File

@ -42,6 +42,7 @@ namespace ChatHelpers {
void AddGifAction(
Fn<void(QString, Fn<void()> &&, const style::icon*)> callback,
Window::SessionController *controller,
not_null<DocumentData*> document);
class GifsListWidget

View File

@ -2509,8 +2509,10 @@ void StickersListWidget::fillContextMenu(
SendMenu::DefaultSilentCallback(send),
SendMenu::DefaultScheduleCallback(this, type, send));
const auto window = controller();
const auto toggleFavedSticker = [=] {
Api::ToggleFavedSticker(
window,
document,
Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0));
};
@ -2683,8 +2685,9 @@ void StickersListWidget::removeFavedSticker(int section, int index) {
clearSelection();
const auto &sticker = _mySets[section].stickers[index];
const auto document = sticker.document;
session().data().stickers().setFaved(document, false);
session().data().stickers().setFaved(controller(), document, false);
Api::ToggleFavedSticker(
controller(),
document,
Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0),
false);

View File

@ -16,9 +16,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_folder.h"
#include "data/data_histories.h"
#include "dialogs/dialogs_main_list.h"
#include "history/history.h"
#include "history/history_unread_things.h"
#include "ui/ui_utility.h"
#include "main/main_session.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "apiwrap.h"
namespace Data {
@ -225,10 +228,15 @@ ChatFilters::~ChatFilters() = default;
not_null<Dialogs::MainList*> ChatFilters::chatsList(FilterId filterId) {
auto &pointer = _chatsLists[filterId];
if (!pointer) {
auto limit = rpl::single(rpl::empty_value()) | rpl::then(
_owner->session().account().appConfig().refreshed()
) | rpl::map([=] {
return _owner->pinnedChatsLimit(nullptr, filterId);
});
pointer = std::make_unique<Dialogs::MainList>(
&_owner->session(),
filterId,
rpl::single(ChatFilter::kPinnedLimit));
_owner->maxPinnedChatsLimitValue(nullptr, filterId));
}
return pointer.get();
}
@ -450,6 +458,7 @@ const ChatFilter &ChatFilters::applyUpdatedPinned(
const auto i = ranges::find(_list, id, &ChatFilter::id);
Assert(i != end(_list));
const auto limit = _owner->pinnedChatsLimit(nullptr, id);
auto always = i->always();
auto pinned = std::vector<not_null<History*>>();
pinned.reserve(dialogs.size());
@ -457,7 +466,7 @@ const ChatFilter &ChatFilters::applyUpdatedPinned(
if (const auto history = row.history()) {
if (always.contains(history)) {
pinned.push_back(history);
} else if (always.size() < ChatFilter::kPinnedLimit) {
} else if (always.size() < limit) {
always.insert(history);
pinned.push_back(history);
}

View File

@ -35,8 +35,6 @@ public:
friend constexpr inline bool is_flag_type(Flag) { return true; };
using Flags = base::flags<Flag>;
static constexpr int kPinnedLimit = 100;
ChatFilter() = default;
ChatFilter(
FilterId id,

View File

@ -38,7 +38,7 @@ Folder::Folder(not_null<Data::Session*> owner, FolderId id)
, _chatsList(
&owner->session(),
FilterId(),
owner->session().serverConfig().pinnedDialogsInFolderMax.value())
owner->maxPinnedChatsLimitValue(this, FilterId()))
, _name(tr::lng_archived_name(tr::now))
, _chatListNameSortKey(owner->nameSortKey(_name)) {
indexNameParts();

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "api/api_text_entities.h"
@ -33,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/player/media_player_instance.h" // instance()->play()
#include "media/audio/media_audio.h"
#include "boxes/abstract_box.h"
#include "boxes/premium_limits_box.h"
#include "passport/passport_form_controller.h"
#include "lang/lang_keys.h" // tr::lng_deleted(tr::now) in user name
#include "data/stickers/data_stickers.h"
@ -225,7 +227,7 @@ Session::Session(not_null<Main::Session*> session)
, _chatsList(
session,
FilterId(),
session->serverConfig().pinnedDialogsCountMax.value())
maxPinnedChatsLimitValue(nullptr, FilterId()))
, _contactsList(Dialogs::SortMode::Name)
, _contactsNoChatsList(Dialogs::SortMode::Name)
, _ttlCheckTimer([=] { checkTTLs(); })
@ -1832,20 +1834,54 @@ int Session::pinnedCanPin(
FilterId filterId,
not_null<History*> history) const {
if (!filterId) {
const auto limit = pinnedChatsLimit(folder);
const auto limit = pinnedChatsLimit(folder, filterId);
return pinnedChatsOrder(folder, FilterId()).size() < limit;
}
const auto &list = chatsFilters().list();
const auto i = ranges::find(list, filterId, &Data::ChatFilter::id);
return (i == end(list))
|| (i->always().contains(history))
|| (i->always().size() < Data::ChatFilter::kPinnedLimit);
|| (i->always().size() < pinnedChatsLimit(folder, filterId));
}
int Session::pinnedChatsLimit(Data::Folder *folder) const {
return folder
? session().serverConfig().pinnedDialogsInFolderMax.current()
: session().serverConfig().pinnedDialogsCountMax.current();
int Session::pinnedChatsLimit(
Data::Folder *folder,
FilterId filterId) const {
return CurrentPremiumLimit(
_session,
(filterId
? "dialog_filters_chats_limit_default"
: folder
? "dialog_filters_chats_limit_default"
: "dialogs_pinned_limit_default"),
(filterId || folder) ? 100 : 5,
(filterId
? "dialog_filters_chats_limit_premium"
: folder
? "dialog_filters_chats_limit_premium"
: "dialogs_pinned_limit_premium"),
(filterId || folder) ? 200 : 10);
}
rpl::producer<int> Session::maxPinnedChatsLimitValue(
Data::Folder *folder,
FilterId filterId) const {
// Premium limit from appconfig.
// We always use premium limit in the MainList limit producer,
// 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.
return rpl::single(rpl::empty_value()) | rpl::then(
_session->account().appConfig().refreshed()
) | rpl::map([=] {
return AppConfigLimit(
_session,
(filterId
? "dialog_filters_chats_limit_premium"
: folder
? "dialog_filters_chats_limit_premium"
: "dialogs_pinned_limit_premium"),
(filterId || folder) ? 200 : 10);
});
}
const std::vector<Dialogs::Key> &Session::pinnedChatsOrder(

View File

@ -329,7 +329,12 @@ public:
Data::Folder *folder,
FilterId filterId,
not_null<History*> history) const;
int pinnedChatsLimit(Data::Folder *folder) const;
int pinnedChatsLimit(
Data::Folder *folder,
FilterId filterId) const;
rpl::producer<int> maxPinnedChatsLimitValue(
Data::Folder *folder,
FilterId filterId) const;
const std::vector<Dialogs::Key> &pinnedChatsOrder(
Data::Folder *folder,
FilterId filterId) const;

View File

@ -12,7 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_user.h"
#include "ui/boxes/confirm_box.h"
#include "ui/text/text_utilities.h"
#include "lang/lang_keys.h"
#include "boxes/premium_limits_box.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_components.h"
@ -23,7 +25,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h"
#include "ui/image/image_location_factory.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h"
#include "mainwindow.h"
#include "base/unixtime.h"
#include "boxes/abstract_box.h" // Ui::show().
#include "styles/style_chat_helpers.h"
@ -31,8 +37,81 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data {
namespace {
constexpr auto kPremiumToastDuration = 5 * crl::time(1000);
using SetFlag = StickersSetFlag;
[[nodiscard]] TextWithEntities SavedGifsToast(
not_null<Main::Session*> session) {
const auto defaultLimit = AppConfigLimit(
session,
"saved_gifs_limit_default",
200);
const auto premiumLimit = AppConfigLimit(
session,
"saved_gifs_limit_premium",
400);
return Ui::Text::Bold(
tr::lng_saved_gif_limit_title(tr::now, lt_count, defaultLimit)
).append('\n').append(
tr::lng_saved_gif_limit_more(
tr::now,
lt_count,
premiumLimit,
lt_link,
Ui::Text::Link(tr::lng_saved_gif_limit_link(tr::now)),
Ui::Text::WithEntities));
}
[[nodiscard]] TextWithEntities FaveStickersToast(
not_null<Main::Session*> session) {
const auto defaultLimit = AppConfigLimit(
session,
"stickers_faved_limit_default",
5);
const auto premiumLimit = AppConfigLimit(
session,
"stickers_faved_limit_premium",
200);
return Ui::Text::Bold(
tr::lng_fave_sticker_limit_title(tr::now, lt_count, defaultLimit)
).append('\n').append(
tr::lng_fave_sticker_limit_more(
tr::now,
lt_count,
premiumLimit,
lt_link,
Ui::Text::Link(tr::lng_fave_sticker_limit_link(tr::now)),
Ui::Text::WithEntities));
}
void MaybeShowPremiumToast(
Window::SessionController *controller,
TextWithEntities text) {
if (!controller) {
return;
}
const auto session = &controller->session();
if (session->user()->isPremium()) {
return;
}
const auto widget = QPointer<Ui::RpWidget>(
controller->window().widget()->bodyWidget());
const auto filter = [=](const auto ...) {
Ui::ShowMultilineToast({
.parentOverride = widget,
.text = { u"Premium!"_q },
});
return false;
};
Ui::ShowMultilineToast({
.parentOverride = widget,
.text = std::move(text),
.duration = kPremiumToastDuration,
.filter = filter,
});
}
void RemoveFromSet(
StickersSets &sets,
not_null<DocumentData*> document,
@ -225,7 +304,9 @@ void Stickers::incrementSticker(not_null<DocumentData*> document) {
notifyRecentUpdated();
}
void Stickers::addSavedGif(not_null<DocumentData*> document) {
void Stickers::addSavedGif(
Window::SessionController *controller,
not_null<DocumentData*> document) {
const auto index = _savedGifs.indexOf(document);
if (!index) {
return;
@ -234,14 +315,22 @@ void Stickers::addSavedGif(not_null<DocumentData*> document) {
_savedGifs.remove(index);
}
_savedGifs.push_front(document);
if (_savedGifs.size() > session().serverConfig().savedGifsLimit) {
const auto session = &document->session();
const auto limit = CurrentPremiumLimit(
session,
"saved_gifs_limit_default",
200,
"saved_gifs_limit_premium",
400);
if (_savedGifs.size() > limit) {
_savedGifs.pop_back();
MaybeShowPremiumToast(controller, SavedGifsToast(session));
}
session().local().writeSavedGifs();
session->local().writeSavedGifs();
notifySavedGifsUpdated();
setLastSavedGifsUpdate(0);
session().api().updateStickers();
session->api().updateStickers();
}
void Stickers::checkSavedGif(not_null<HistoryItem*> item) {
@ -253,7 +342,7 @@ void Stickers::checkSavedGif(not_null<HistoryItem*> item) {
if (const auto media = item->media()) {
if (const auto document = media->document()) {
if (document->isGifv()) {
addSavedGif(document);
addSavedGif(nullptr, document);
}
}
}
@ -421,8 +510,17 @@ bool Stickers::isFaved(not_null<const DocumentData*> document) {
return false;
}
void Stickers::checkFavedLimit(StickersSet &set) {
if (set.stickers.size() <= session().serverConfig().stickersFavedLimit) {
void Stickers::checkFavedLimit(
StickersSet &set,
Window::SessionController *controller) {
const auto session = &_owner->session();
const auto limit = CurrentPremiumLimit(
session,
"stickers_faved_limit_default",
5,
"stickers_faved_limit_premium",
200);
if (set.stickers.size() <= limit) {
return;
}
auto removing = set.stickers.back();
@ -438,17 +536,19 @@ void Stickers::checkFavedLimit(StickersSet &set) {
}
++i;
}
MaybeShowPremiumToast(controller, FaveStickersToast(session));
}
void Stickers::pushFavedToFront(
StickersSet &set,
Window::SessionController *controller,
not_null<DocumentData*> document,
const std::vector<not_null<EmojiPtr>> &emojiList) {
set.stickers.push_front(document);
for (auto emoji : emojiList) {
set.emoji[emoji].push_front(document);
}
checkFavedLimit(set);
checkFavedLimit(set, controller);
}
void Stickers::moveFavedToFront(StickersSet &set, int index) {
@ -471,6 +571,7 @@ void Stickers::moveFavedToFront(StickersSet &set, int index) {
}
void Stickers::setIsFaved(
Window::SessionController *controller,
not_null<DocumentData*> document,
std::optional<std::vector<not_null<EmojiPtr>>> emojiList) {
auto &sets = setsRef();
@ -495,11 +596,11 @@ void Stickers::setIsFaved(
if (index > 0) {
moveFavedToFront(*set, index);
} else if (emojiList) {
pushFavedToFront(*set, document, *emojiList);
pushFavedToFront(*set, controller, document, *emojiList);
} else if (auto list = getEmojiListFromSet(document)) {
pushFavedToFront(*set, document, *list);
pushFavedToFront(*set, controller, document, *list);
} else {
requestSetToPushFaved(document);
requestSetToPushFaved(controller, document);
return;
}
session().local().writeFavedStickers();
@ -507,7 +608,11 @@ void Stickers::setIsFaved(
notifyStickerSetInstalled(FavedSetId);
}
void Stickers::requestSetToPushFaved(not_null<DocumentData*> document) {
void Stickers::requestSetToPushFaved(
Window::SessionController *controller,
not_null<DocumentData*> document) {
controller = nullptr;
const auto weak = base::make_weak(controller);
auto addAnyway = [=](std::vector<not_null<EmojiPtr>> list) {
if (list.empty()) {
if (auto sticker = document->sticker()) {
@ -516,7 +621,7 @@ void Stickers::requestSetToPushFaved(not_null<DocumentData*> document) {
}
}
}
setIsFaved(document, std::move(list));
setIsFaved(weak.get(), document, std::move(list));
};
session().api().request(MTPmessages_GetStickerSet(
Data::InputStickerSet(document->sticker()->set),
@ -558,9 +663,12 @@ void Stickers::setIsNotFaved(not_null<DocumentData*> document) {
notifyUpdated();
}
void Stickers::setFaved(not_null<DocumentData*> document, bool faved) {
void Stickers::setFaved(
Window::SessionController *controller,
not_null<DocumentData*> document,
bool faved) {
if (faved) {
setIsFaved(document);
setIsFaved(controller, document);
} else {
setIsNotFaved(document);
}

View File

@ -18,6 +18,10 @@ namespace Main {
class Session;
} // namespace Main
namespace Window {
class SessionController;
} // namespace Window
namespace Data {
class Session;
@ -167,7 +171,9 @@ public:
}
void removeFromRecentSet(not_null<DocumentData*> document);
void addSavedGif(not_null<DocumentData*> document);
void addSavedGif(
Window::SessionController *controller,
not_null<DocumentData*> document);
void checkSavedGif(not_null<HistoryItem*> item);
void applyArchivedResult(
@ -175,7 +181,10 @@ public:
void installLocally(uint64 setId);
void undoInstallLocally(uint64 setId);
bool isFaved(not_null<const DocumentData*> document);
void setFaved(not_null<DocumentData*> document, bool faved);
void setFaved(
Window::SessionController *controller,
not_null<DocumentData*> document,
bool faved);
void setsReceived(const QVector<MTPStickerSet> &data, uint64 hash);
void masksReceived(const QVector<MTPStickerSet> &data, uint64 hash);
@ -212,18 +221,24 @@ private:
return (lastUpdate == 0)
|| (now >= lastUpdate + kUpdateTimeout);
}
void checkFavedLimit(StickersSet &set);
void checkFavedLimit(
StickersSet &set,
Window::SessionController *controller = nullptr);
void setIsFaved(
Window::SessionController *controller,
not_null<DocumentData*> document,
std::optional<std::vector<not_null<EmojiPtr>>> emojiList
= std::nullopt);
void setIsNotFaved(not_null<DocumentData*> document);
void pushFavedToFront(
StickersSet &set,
Window::SessionController *controller,
not_null<DocumentData*> document,
const std::vector<not_null<EmojiPtr>> &emojiList);
void moveFavedToFront(StickersSet &set, int index);
void requestSetToPushFaved(not_null<DocumentData*> document);
void requestSetToPushFaved(
Window::SessionController *controller,
not_null<DocumentData*> document);
void setPackAndEmoji(
StickersSet &set,
StickersPack &&pack,

View File

@ -2251,7 +2251,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
}, &st::menuIconStickers);
const auto isFaved = session->data().stickers().isFaved(document);
_menu->addAction(isFaved ? tr::lng_faved_stickers_remove(tr::now) : tr::lng_faved_stickers_add(tr::now), [=] {
Api::ToggleFavedSticker(document, itemId);
Api::ToggleFavedSticker(controller, document, itemId);
}, isFaved ? &st::menuIconUnfave : &st::menuIconFave);
}
if (!hasCopyRestriction(item)) {
@ -2492,7 +2492,11 @@ void HistoryInner::saveContextGif(FullMsgId itemId) {
if (!hasCopyRestriction(item)) {
if (const auto media = item->media()) {
if (const auto document = media->document()) {
Api::ToggleSavedGif(document, item->fullId(), true);
Api::ToggleSavedGif(
_controller,
document,
item->fullId(),
true);
}
}
}

View File

@ -129,9 +129,10 @@ void ShowStickerPackInfo(
}
void ToggleFavedSticker(
not_null<Window::SessionController*> controller,
not_null<DocumentData*> document,
FullMsgId contextId) {
Api::ToggleFavedSticker(document, contextId);
Api::ToggleFavedSticker(controller, document, contextId);
}
void AddPhotoActions(
@ -174,7 +175,11 @@ void SaveGif(
if (const auto item = controller->session().data().message(itemId)) {
if (const auto media = item->media()) {
if (const auto document = media->document()) {
Api::ToggleSavedGif(document, item->fullId(), true);
Api::ToggleSavedGif(
controller,
document,
item->fullId(),
true);
}
}
}
@ -243,6 +248,7 @@ void AddDocumentActions(
}, &st::menuIconCancel);
return;
}
const auto controller = list->controller();
const auto contextId = item ? item->fullId() : FullMsgId();
const auto session = &document->session();
if (item && document->isGifv()) {
@ -273,7 +279,7 @@ void AddDocumentActions(
(isFaved
? tr::lng_faved_stickers_remove(tr::now)
: tr::lng_faved_stickers_add(tr::now)),
[=] { ToggleFavedSticker(document, contextId); },
[=] { ToggleFavedSticker(controller, document, contextId); },
isFaved ? &st::menuIconUnfave : &st::menuIconFave);
}
if (!document->filepath(true).isEmpty()) {

View File

@ -130,6 +130,7 @@ void Gif::setPosition(int32 position) {
void DeleteSavedGifClickHandler::onClickImpl() const {
ChatHelpers::AddGifAction(
[](QString, Fn<void()> &&done, const style::icon*) { done(); },
nullptr,
_data);
}

View File

@ -353,7 +353,10 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) {
const style::icon *icon) {
_menu->addAction(text, std::move(done), icon);
};
ChatHelpers::AddGifAction(std::move(callback), previewDocument);
ChatHelpers::AddGifAction(
std::move(callback),
_controller,
previewDocument);
}
if (!_menu->empty()) {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_folders.h"
#include "apiwrap.h"
#include "boxes/premium_limits_box.h"
#include "boxes/filters/edit_filter_box.h"
#include "core/application.h"
#include "data/data_chat_filters.h"
@ -39,8 +40,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Settings {
namespace {
constexpr auto kFiltersLimit = 10;
using Flag = Data::ChatFilter::Flag;
using Flags = Data::ChatFilter::Flags;
@ -327,6 +326,14 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
auto &lifetime = container->lifetime();
const auto session = &controller->session();
const auto limit = [=] {
return CurrentPremiumLimit(
session,
"dialog_filters_limit_default",
10,
"dialog_filters_limit_premium",
20);
};
AddSkip(container, st::settingsSectionSkip);
AddSubsectionTitle(container, tr::lng_filters_subtitle());
@ -339,10 +346,10 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
};
const auto showLimitReached = [=] {
const auto removed = ranges::count_if(*rows, &FilterRow::removed);
if (rows->size() < kFiltersLimit + removed) {
if (rows->size() < limit() + removed) {
return false;
}
controller->window().showToast(tr::lng_filters_limit(tr::now));
controller->show(Box(FiltersLimitBox, session));
return true;
};
const auto wrap = container->add(object_ptr<Ui::VerticalLayout>(
@ -487,7 +494,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
auto showSuggestions = rpl::combine(
suggested->value(),
rowsCount->value()
) | rpl::map(rpl::mappers::_1 > 0 && rpl::mappers::_2 < kFiltersLimit);
) | rpl::map(rpl::mappers::_1 > 0 && rpl::mappers::_2 < limit());
nonEmptyAbout->toggleOn(std::move(showSuggestions));
const auto prepareGoodIdsForNewFilters = [=] {

View File

@ -249,13 +249,11 @@ bool PinnedLimitReached(
owner->setChatPinned(history, FilterId(), true);
history->session().api().savePinnedOrder(folder);
} else if (filterId) {
controller->show(
Box(FilterPinsLimitBox, &history->session()),
Ui::LayerOption::CloseOther);
controller->show(Box(FilterPinsLimitBox, &history->session()));
} else if (folder) {
controller->show(Box(FolderPinsLimitBox, &history->session()));
} else {
controller->show(
Box(PinsLimitBox, &history->session()),
Ui::LayerOption::CloseOther);
controller->show(Box(PinsLimitBox, &history->session()));
}
return true;
}
@ -419,6 +417,7 @@ void Filler::addInfo() {
}
void Filler::addToggleFolder() {
const auto controller = _controller;
const auto history = _request.key.history();
if (!history || history->owner().chatsFilters().list().empty()) {
return;
@ -428,7 +427,7 @@ void Filler::addToggleFolder() {
.handler = nullptr,
.icon = &st::menuIconAddToFolder,
.fillSubmenu = [=](not_null<Ui::PopupMenu*> menu) {
FillChooseFilterMenu(menu, history);
FillChooseFilterMenu(controller, menu, history);
},
});
}