Support default forum topic icons.

This commit is contained in:
John Preston 2022-10-21 21:13:13 +04:00
parent 5314833c82
commit 0cba9e4a22
13 changed files with 187 additions and 18 deletions

View File

@ -473,6 +473,8 @@ PRIVATE
data/data_folder.h
data/data_forum.cpp
data/data_forum.h
data/data_forum_icons.cpp
data/data_forum_icons.h
data/data_forum_topic.cpp
data/data_forum_topic.h
data/data_file_click_handler.cpp

View File

@ -571,7 +571,7 @@ bool WhoReadExists(not_null<HistoryItem*> item) {
const auto peer = history->peer;
const auto chat = peer->asChat();
const auto megagroup = peer->asMegagroup();
if (!chat && !megagroup) {
if ((!chat && !megagroup) || peer->isForum()) {
return false;
}
const auto &appConfig = peer->session().account().appConfig();

View File

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h"
#include "data/data_document.h"
#include "data/data_forum.h"
#include "data/data_forum_icons.h"
#include "data/data_forum_topic.h"
#include "data/data_session.h"
#include "data/stickers/data_custom_emoji.h"
@ -222,7 +223,7 @@ struct IconSelector {
auto factory = [=](DocumentId id, Fn<void()> repaint)
-> std::unique_ptr<Ui::Text::CustomEmoji> {
const auto tag = Data::CustomEmojiManager::SizeTag::Large;
if (const auto colorId = kDefaultIconId) {
if (id == kDefaultIconId) {
return std::make_unique<DefaultIconEmoji>(
rpl::duplicate(defaultIcon),
repaint);
@ -230,7 +231,14 @@ struct IconSelector {
return manager->create(id, std::move(repaint), tag);
};
const auto icons = &controller->session().data().forumIcons();
const auto body = box->verticalLayout();
Settings::AddSkip(body);
const auto recent = [=] {
auto list = icons->list();
list.insert(begin(list), kDefaultIconId);
return list;
};
const auto selector = body->add(
object_ptr<EmojiListWidget>(body, EmojiListDescriptor{
.session = &controller->session(),
@ -239,12 +247,18 @@ struct IconSelector {
.paused = Window::PausedIn(
controller,
Window::GifPauseReason::Layer),
.customRecentList = { kDefaultIconId },
.customRecentList = recent(),
.customRecentFactory = std::move(factory),
.st = &st::reactPanelEmojiPan,
}),
st::reactPanelEmojiPan.padding);
icons->requestDefaultIfUnknown();
icons->defaultUpdates(
) | rpl::start_with_next([=] {
selector->provideRecent(recent());
}, selector->lifetime());
auto ownedFooter = selector->createFooter();
const auto footer = ownedFooter.data();
placeFooter(std::move(ownedFooter));
@ -278,8 +292,12 @@ struct IconSelector {
selector->customChosen(
) | rpl::start_with_next([=](ChatHelpers::FileChosen data) {
const auto owner = &controller->session().data();
const auto custom = (data.document->id != kDefaultIconId);
if (custom && !controller->session().premium()) {
const auto document = data.document;
const auto id = document->id;
const auto custom = (id != kDefaultIconId);
const auto premium = custom
&& !ranges::contains(document->owner().forumIcons().list(), id);
if (premium && !controller->session().premium()) {
// #TODO forum premium promo
ShowPremiumPreviewBox(controller, PremiumPreview::EmojiStatus);
return;
@ -288,7 +306,7 @@ struct IconSelector {
if (state->button && custom) {
const auto &from = data.messageSendingFrom;
auto args = Ui::ReactionFlyAnimationArgs{
.id = { { data.document->id } },
.id = { { id } },
.flyIcon = from.frame,
.flyFrom = body->mapFromGlobal(from.globalStartGeometry),
};
@ -299,7 +317,7 @@ struct IconSelector {
[=] { state->animation->repaint(); },
Data::CustomEmojiSizeTag::Large);
}
state->iconId = data.document->id;
state->iconId = id;
}, selector->lifetime());
auto paintIconFrame = [=](not_null<Ui::RpWidget*> button) {

View File

@ -50,6 +50,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session_settings.h"
#include "inline_bots/bot_attach_web_view.h"
#include "history/history.h"
#include "history/history_item.h"
#include "base/qt/qt_common_adapters.h"
#include "apiwrap.h"
@ -536,13 +537,14 @@ bool OpenMediaTimestamp(
MsgId(parts.value(2).toLongLong()));
const auto session = &controller->session();
const auto document = session->data().document(documentId);
const auto context = session->data().message(itemId);
const auto timeMs = time * crl::time(1000);
if (document->isVideoFile()) {
controller->window().openInMediaView(Media::View::OpenRequest(
controller,
document,
session->data().message(itemId),
MsgId(0), // #TODO forum shared media
context,
context ? context->topicRootId() : MsgId(0),
false,
timeMs));
} else if (document->isSong() || document->isVoiceMessage()) {

View File

@ -44,7 +44,6 @@ constexpr auto kMaxTimeout = 6 * 60 * 60 * crl::time(1000);
EmojiStatuses::EmojiStatuses(not_null<Session*> owner)
: _owner(owner)
, _defaultRefreshTimer([=] { refreshDefault(); })
, _clearingTimer([=] { processClearing(); }) {
refreshDefault();
refreshColored();

View File

@ -9,10 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h"
namespace Ui::Text {
class CustomEmoji;
} // namespace Ui::Text
namespace Main {
class Session;
} // namespace Main
@ -78,7 +74,6 @@ private:
bool _recentRequestScheduled = false;
uint64 _recentHash = 0;
base::Timer _defaultRefreshTimer;
mtpRequestId _defaultRequestId = 0;
uint64 _defaultHash = 0;

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h"
#include "data/data_histories.h"
#include "data/data_session.h"
#include "data/data_forum_icons.h"
#include "data/data_forum_topic.h"
#include "data/notify/data_notify_settings.h"
#include "history/history.h"
@ -45,6 +46,9 @@ Forum::Forum(not_null<History*> history)
if (_history->inChatList()) {
preloadTopics();
}
if (channel()->canCreateTopics()) {
owner().forumIcons().requestDefaultIfUnknown();
}
}
Forum::~Forum() {

View File

@ -0,0 +1,82 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/data_forum_icons.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "apiwrap.h"
namespace Data {
namespace {
constexpr auto kRefreshDefaultListEach = 60 * 60 * crl::time(1000);
constexpr auto kRecentRequestTimeout = 10 * crl::time(1000);
constexpr auto kMaxTimeout = 6 * 60 * 60 * crl::time(1000);
} // namespace
ForumIcons::ForumIcons(not_null<Session*> owner)
: _owner(owner) {
}
ForumIcons::~ForumIcons() = default;
Main::Session &ForumIcons::session() const {
return _owner->session();
}
void ForumIcons::requestDefaultIfUnknown() {
if (_default.empty()) {
requestDefault();
}
}
void ForumIcons::refreshDefault() {
requestDefault();
}
const std::vector<DocumentId> &ForumIcons::list() const {
return _default;
}
rpl::producer<> ForumIcons::defaultUpdates() const {
return _defaultUpdated.events();
}
void ForumIcons::requestDefault() {
if (_defaultRequestId) {
return;
}
auto &api = _owner->session().api();
_defaultRequestId = api.request(MTPmessages_GetStickerSet(
MTP_inputStickerSetEmojiDefaultTopicIcons(),
MTP_int(0) // hash
)).done([=](const MTPmessages_StickerSet &result) {
_defaultRequestId = 0;
result.match([&](const MTPDmessages_stickerSet &data) {
updateDefault(data);
}, [](const MTPDmessages_stickerSetNotModified &) {
LOG(("API Error: Unexpected messages.stickerSetNotModified."));
});
}).fail([=] {
_defaultRequestId = 0;
}).send();
}
void ForumIcons::updateDefault(const MTPDmessages_stickerSet &data) {
const auto &list = data.vdocuments().v;
_default.clear();
_default.reserve(list.size());
for (const auto &sticker : data.vdocuments().v) {
_default.push_back(_owner->processDocument(sticker)->id);
}
_defaultUpdated.fire({});
}
} // namespace Data

View File

@ -0,0 +1,52 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Main {
class Session;
} // namespace Main
namespace Data {
class DocumentMedia;
class Session;
class ForumIcons final {
public:
explicit ForumIcons(not_null<Session*> owner);
~ForumIcons();
[[nodiscard]] Session &owner() const {
return *_owner;
}
[[nodiscard]] Main::Session &session() const;
void refreshDefault();
void requestDefaultIfUnknown();
[[nodiscard]] const std::vector<DocumentId> &list() const;
[[nodiscard]] rpl::producer<> defaultUpdates() const;
private:
void requestDefault();
void updateDefault(const MTPDmessages_stickerSet &data);
const not_null<Session*> _owner;
std::vector<DocumentId> _default;
rpl::event_stream<> _defaultUpdated;
mtpRequestId _defaultRequestId = 0;
rpl::lifetime _lifetime;
};
} // namespace Data

View File

@ -62,6 +62,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_sponsored_messages.h"
#include "data/data_message_reactions.h"
#include "data/data_emoji_statuses.h"
#include "data/data_forum_icons.h"
#include "data/data_cloud_themes.h"
#include "data/data_streaming.h"
#include "data/data_media_rotation.h"
@ -257,6 +258,7 @@ Session::Session(not_null<Main::Session*> session)
, _sponsoredMessages(std::make_unique<SponsoredMessages>(this))
, _reactions(std::make_unique<Reactions>(this))
, _emojiStatuses(std::make_unique<EmojiStatuses>(this))
, _forumIcons(std::make_unique<ForumIcons>(this))
, _notifySettings(std::make_unique<NotifySettings>(this))
, _customEmojiManager(std::make_unique<CustomEmojiManager>(this)) {
_cache->open(_session->local().cacheKey());

View File

@ -53,6 +53,7 @@ class SendActionManager;
class SponsoredMessages;
class Reactions;
class EmojiStatuses;
class ForumIcons;
class ChatFilters;
class CloudThemes;
class Streaming;
@ -128,6 +129,9 @@ public:
[[nodiscard]] EmojiStatuses &emojiStatuses() const {
return *_emojiStatuses;
}
[[nodiscard]] ForumIcons &forumIcons() const {
return *_forumIcons;
}
[[nodiscard]] NotifySettings &notifySettings() const {
return *_notifySettings;
}
@ -986,6 +990,7 @@ private:
std::unique_ptr<SponsoredMessages> _sponsoredMessages;
const std::unique_ptr<Reactions> _reactions;
const std::unique_ptr<EmojiStatuses> _emojiStatuses;
const std::unique_ptr<ForumIcons> _forumIcons;
const std::unique_ptr<NotifySettings> _notifySettings;
const std::unique_ptr<CustomEmojiManager> _customEmojiManager;

View File

@ -502,7 +502,6 @@ void TopBarWidget::paintTopBar(Painter &p) {
|| history->peer->sharedMediaInfo()
|| (_activeChat.section == Section::Scheduled)
|| (_activeChat.section == Section::Pinned)) {
// #TODO forum name emoji.
auto text = (_activeChat.section == Section::Scheduled)
? ((history && history->peer->isSelf())
? tr::lng_reminder_messages(tr::now)
@ -929,7 +928,7 @@ void TopBarWidget::updateControlsGeometry() {
_leftTaken += _info->width();
} else if (_activeChat.key.topic()
|| _activeChat.section == Section::ChatsList) {
_leftTaken += st::topBarArrowPadding.right();
_leftTaken += st::normalFont->spacew;
}
_rightTaken = 0;

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_badge.h"
#include "info/profile/info_profile_emoji_status_panel.h"
#include "info/info_controller.h"
#include "boxes/peers/edit_forum_topic_box.h"
#include "history/view/media/history_view_sticker_player.h"
#include "lang/lang_keys.h"
#include "ui/widgets/labels.h"
@ -283,8 +284,16 @@ Cover::Cover(
_peer,
_userpic->takeResultImage());
}, _userpic->lifetime());
} else if (topic->canEdit()) {
_iconView->setClickedCallback([=] {
_controller->show(Box(
EditForumTopicBox,
_controller,
topic->history(),
topic->rootId()));
});
} else {
// #TODO forum icon change on click if possible
_iconView->setAttribute(Qt::WA_TransparentForMouseEvents);
}
}