Merge tag 'v7.0.4' into dev

This commit is contained in:
AlexeyZavar
2026-07-23 06:48:00 +03:00
1335 changed files with 217894 additions and 24157 deletions
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_cloud_password.h"
#include "api/api_text_entities.h"
#include "boxes/peers/add_bot_to_chat_box.h"
#include "boxes/peers/community_box.h"
#include "boxes/peers/edit_peer_info_box.h"
#include "boxes/peers/replace_boost_box.h"
#include "boxes/add_contact_box.h"
@@ -20,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_chat_switch_process.h"
#include "window/window_controller.h"
#include "window/window_filters_menu.h"
#include "window/section_widget.h"
#include "window/window_separate_id.h"
#include "info/channel_statistics/earn/info_channel_earn_list.h"
#include "info/peer_gifts/info_peer_gifts_widget.h"
@@ -113,6 +115,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/download_manager_mtproto.h"
#include "storage/storage_account.h"
#include "window/themes/window_theme.h"
#include "window/themes/window_themes_chat.h"
#include "window/window_peer_menu.h"
#include "window/window_session_controller_link_info.h"
#include "settings/cloud_password/settings_cloud_password_input.h"
@@ -122,6 +125,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_chat.h"
#include "settings/sections/settings_premium.h"
#include "settings/sections/settings_privacy_security.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_window.h"
#include "styles/style_boxes.h"
#include "styles/style_dialogs.h"
@@ -183,20 +187,6 @@ private:
};
[[nodiscard]] Ui::ChatThemeBubblesData PrepareBubblesData(
const Data::CloudTheme &theme,
Data::CloudThemeType type) {
const auto i = theme.settings.find(type);
return {
.colors = (i != end(theme.settings)
? i->second.outgoingMessagesColors
: std::vector<QColor>()),
.accent = (i != end(theme.settings)
? i->second.outgoingAccentColor
: std::optional<QColor>()),
};
}
[[nodiscard]] bool DownloadingDocument(not_null<DocumentData*> document) {
for (const auto id : Core::App().downloadManager().loadingList()) {
if (id->object.document == document.get()) {
@@ -301,6 +291,9 @@ SendMenu::Details MainWindowShow::sendMenuDetails() const {
if (!window) {
return SendMenu::Details();
}
if (const auto section = window->activeLayerSection()) {
return section->sendMenuDetails();
}
return window->content()->sendMenuDetails();
}
@@ -322,7 +315,11 @@ void MainWindowShow::processChosenSticker(
ChatHelpers::FileChosen &&chosen) const {
if (const auto window = _window.get()) {
Ui::PostponeCall(window, [=, chosen = std::move(chosen)]() mutable {
window->stickerOrEmojiChosen(std::move(chosen));
if (const auto section = window->activeLayerSection()) {
section->processChosenSticker(std::move(chosen));
} else {
window->content()->processChosenSticker(std::move(chosen));
}
});
}
}
@@ -802,6 +799,7 @@ void SessionNavigation::showPeerByLinkResolved(
.context = {
.controller = parentController(),
.fullscreen = info.botAppFullScreen,
.maySkipConfirmation = !info.botAppForceConfirmation,
},
.button = { .startCommand = startCommand },
.source = InlineBots::WebViewSourceLinkBotProfile{
@@ -1437,6 +1435,12 @@ void SessionNavigation::showByInitialId(
clearSectionStack(instant);
parent->showForum(id.forum(), instant);
break;
case SeparateType::Community:
clearSectionStack(instant);
if (const auto info = id.community()) {
parent->openCommunity(info);
}
break;
case SeparateType::Primary:
clearSectionStack(instant);
break;
@@ -1565,6 +1569,7 @@ SessionController::SessionController(
, _invitePeekTimer([=] { checkInvitePeek(); })
, _activeChatsFilter(session->data().chatsFilters().defaultId())
, _openedFolder(window->id().folder())
, _openedCommunity(window->id().community())
, _defaultChatTheme(std::make_shared<Ui::ChatTheme>())
, _chatStyle(std::make_unique<Ui::ChatStyle>(session->colorIndicesValue())) {
init();
@@ -1578,8 +1583,18 @@ SessionController::SessionController(
if (update.type == Theme::BackgroundUpdate::Type::New
|| update.type == Theme::BackgroundUpdate::Type::Changed) {
pushDefaultChatBackground();
} else if (update.type
== Theme::BackgroundUpdate::Type::ApplyingTheme) {
if (_isPrimary) {
Theme::CheckChatThemeWallPaper(this);
}
}
}, _lifetime);
if (_isPrimary) {
crl::on_main(base::make_weak(this), [=] {
Theme::CheckChatThemeWallPaper(this);
});
}
style::PaletteChanged(
) | rpl::on_next([=] {
for (auto &[key, value] : _customChatThemes) {
@@ -1589,6 +1604,15 @@ SessionController::SessionController(
}
}, _lifetime);
if (_isPrimary) {
session->data().communityAdminPromotions(
) | rpl::on_next([=](not_null<ChannelData*> community) {
crl::on_main(this, [=] {
ShowCommunityAdminBox(this, community);
});
}, _lifetime);
}
_authedName = session->user()->name();
session->changes().peerUpdates(
Data::PeerUpdate::Flag::FullInfo
@@ -1845,6 +1869,10 @@ not_null<::MainWindow*> SessionController::widget() const {
return _window->widget();
}
rpl::producer<> SessionController::imeCompositionStarts() const {
return widget()->imeCompositionStarts();
}
auto SessionController::sendingAnimation() const
-> Ui::MessageSendingAnimationController & {
return *_sendingAnimation;
@@ -1896,7 +1924,8 @@ void SessionController::setupShortcuts() {
return !window().locked()
&& (_chatSwitchProcess
|| (request.started
&& (Core::App().activeWindow() == &window())));
&& (Core::App().activeWindow() == &window())
&& !isLayerShown()));
}) | rpl::on_next([=](const ChatSwitchRequest &request) {
if (!_chatSwitchProcess) {
_chatSwitchProcess = std::make_unique<ChatSwitchProcess>(
@@ -2019,7 +2048,9 @@ void SessionController::activateFirstChatsFilter() {
bool SessionController::uniqueChatsInSearchResults(
const Dialogs::SearchState &state) const {
const auto global = (state.tab == Dialogs::ChatSearchTab::MyMessages)
|| (state.tab == Dialogs::ChatSearchTab::PublicPosts);
|| (state.tab == Dialogs::ChatSearchTab::PublicPosts)
|| (state.tab == Dialogs::ChatSearchTab::Archive)
|| (state.tab == Dialogs::ChatSearchTab::ThisCommunity);
return session().supportMode()
&& !session().settings().supportAllSearchResults()
&& (global || !state.inChat);
@@ -2063,6 +2094,78 @@ void SessionController::closeFolder() {
_openedFolder = nullptr;
}
bool SessionController::openCommunityInDifferentWindow(
not_null<Data::CommunityInfo*> info) {
const auto history = session().data().history(info->channel());
const auto id = SeparateId(SeparateType::Community, history);
if (const auto separate = Core::App().separateWindowFor(id)) {
if (separate == _window) {
return false;
}
separate->sessionController()->showByInitialId();
separate->activate();
return true;
}
return false;
}
void SessionController::openCommunity(not_null<Data::CommunityInfo*> info) {
if (openCommunityInDifferentWindow(info)) {
return;
} else if (_openedCommunity.current() != info) {
resetFakeUnreadWhileOpened();
}
if (activeChatsFilterCurrent() != 0) {
setActiveChatsFilter(0);
} else if (adaptive().isOneColumn()) {
clearSectionStack(SectionShow::Way::ClearStack);
}
closeForum();
closeFolder();
_openedCommunity = info.get();
const auto community = info->channel();
if (!community->wasFullUpdated()) {
community->session().api().requestFullPeer(community);
}
_openedCommunityLifetime.destroy();
if (windowId().type != SeparateType::Community) {
using FlagChange = Data::Flags<ChannelDataFlags>::Change;
info->channel()->flagsValue(
) | rpl::on_next([=](FlagChange change) {
if (change.diff & ChannelDataFlag::CommunityCollapsed) {
if (!info->collapsedInDialogs()) {
closeCommunity();
}
}
}, _openedCommunityLifetime);
info->chatsList()->fullSize().value(
) | rpl::skip(
1
) | rpl::filter(
rpl::mappers::_1 == 0
) | rpl::on_next([=] {
closeCommunity();
}, _openedCommunityLifetime);
}
}
void SessionController::closeCommunity() {
if (_openedCommunity.current()
&& windowId().type == SeparateType::Community) {
Core::App().closeWindow(_window);
return;
}
_openedCommunityLifetime.destroy();
_openedCommunity = nullptr;
}
const rpl::variable<Data::CommunityInfo*> &
SessionController::openedCommunity() const {
return _openedCommunity;
}
bool SessionController::showForumInDifferentWindow(
not_null<Data::Forum*> forum,
const SectionShow &params,
@@ -2195,6 +2298,8 @@ void SessionController::setupPremiumToast() {
}) | rpl::on_next([=] {
MainWindowShow(this).showToast({
.text = { tr::lng_premium_success(tr::now) },
.iconLottie = u"toast/star_premium_2"_q,
.iconLottieSize = st::toastLottieIconSize,
.adaptive = true,
});
}, _lifetime);
@@ -2696,6 +2801,12 @@ bool SessionController::canShowSeparateWindow(SeparateId id) const {
}
void SessionController::showPeer(not_null<PeerData*> peer, MsgId msgId) {
if (const auto channel = peer->asChannel()) {
if (channel->isCommunity()) {
showPeerInfo(channel, SectionShow());
return;
}
}
const auto currentPeer = activeChatCurrent().peer();
if (peer && peer->isChannel() && currentPeer != peer) {
const auto clickedChannel = peer->asChannel();
@@ -3021,6 +3132,14 @@ void SessionController::showPeerHistory(
PeerId peerId,
const SectionShow &params,
MsgId msgId) {
if (const auto peer = session().data().peerLoaded(peerId)) {
if (const auto channel = peer->asChannel()) {
if (channel->isCommunity()) {
showPeerInfo(channel, SectionShow());
return;
}
}
}
content()->showHistory(peerId, params, msgId);
}
@@ -3127,6 +3246,24 @@ bool SessionController::isLayerShown() const {
return _window->isLayerShown();
}
rpl::producer<bool> SessionController::boxShownValue() const {
return _window->boxShownValue();
}
void SessionController::registerActiveLayerSection(SectionWidget *section) {
_activeLayerSection = section;
}
void SessionController::unregisterActiveLayerSection(SectionWidget *section) {
if (_activeLayerSection == section) {
_activeLayerSection = nullptr;
}
}
SectionWidget *SessionController::activeLayerSection() const {
return _activeLayerSection.data();
}
not_null<MainWidget*> SessionController::content() const {
return widget()->sessionContent();
}
@@ -3167,6 +3304,7 @@ void SessionController::setActiveChatsFilter(
if (id || !changed) {
closeForum();
closeFolder();
closeCommunity();
}
if (adaptive().isOneColumn()) {
clearSectionStack(params);
@@ -3512,6 +3650,22 @@ void SessionController::pushDefaultChatBackground() {
.isPattern = paper.isPattern(),
.tile = background->tile(),
});
const auto &cloud = background->themeObject().cloud;
auto bubbles = Ui::ChatThemeBubblesData();
if (!cloud.emoticon.isEmpty()) {
const auto variant = Theme::ChatThemeVariant(
cloud,
Theme::IsNightMode());
if (variant) {
bubbles = Theme::PrepareBubblesData(cloud, *variant);
}
}
if (bubbles.colors != _defaultChatThemeBubblesColors) {
_defaultChatThemeBubblesColors = bubbles.colors;
_defaultChatTheme->setBubblesBackground(
Ui::PrepareBubblesBackground(bubbles));
_defaultChatTheme->finishCreateOnMain();
}
}
void SessionController::cacheChatTheme(
@@ -3579,7 +3733,7 @@ void SessionController::cacheChatTheme(
? Theme::PreparePaletteCallback(dark, i->second.accentColor)
: Theme::PrepareCurrentPaletteCallback()),
.backgroundData = backgroundData(theme),
.bubblesData = PrepareBubblesData(data, type),
.bubblesData = Theme::PrepareBubblesData(data, type),
.basedOnDark = dark,
};
crl::async([