Merge tag 'v4.14.2' into dev

# Conflicts:
#	Telegram/Resources/winrc/Telegram.rc
#	Telegram/Resources/winrc/Updater.rc
#	Telegram/SourceFiles/core/version.h
#	Telegram/lib_ui
This commit is contained in:
ZavaruKitsu 2024-01-03 15:00:00 +03:00
commit b1e91ab746
39 changed files with 193 additions and 51 deletions

View file

@ -2087,6 +2087,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_premium_gifts_about_paid_below#one" = "They now have access to additional features."; "lng_premium_gifts_about_paid_below#one" = "They now have access to additional features.";
"lng_premium_gifts_about_paid_below#other" = "They now have access to additional features."; "lng_premium_gifts_about_paid_below#other" = "They now have access to additional features.";
"lng_premium_gifts_summary_subtitle" = "What's Included"; "lng_premium_gifts_summary_subtitle" = "What's Included";
"lng_premium_gifts_terms" = "By gifting Telegram Premium, you agree to the Telegram {link} and {policy}.";
"lng_premium_gifts_terms_policy" = "Privacy Policy";
"lng_boost_channel_button" = "Boost Channel"; "lng_boost_channel_button" = "Boost Channel";
"lng_boost_again_button" = "Boost Again"; "lng_boost_again_button" = "Boost Again";

View file

@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop" <Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE" ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.14.1.0" /> Version="4.14.2.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName> <PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View file

@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,14,1,0 FILEVERSION 4,14,2,0
PRODUCTVERSION 4,14,1,0 PRODUCTVERSION 4,14,2,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -62,10 +62,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop" VALUE "FileDescription", "AyuGram Desktop"
VALUE "FileVersion", "4.14.1.0" VALUE "FileVersion", "4.14.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.14.1.0" VALUE "ProductVersion", "4.14.2.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,14,1,0 FILEVERSION 4,14,2,0
PRODUCTVERSION 4,14,1,0 PRODUCTVERSION 4,14,2,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -53,10 +53,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Radolyn Labs" VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater" VALUE "FileDescription", "AyuGram Desktop Updater"
VALUE "FileVersion", "4.14.1.0" VALUE "FileVersion", "4.14.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2024" VALUE "LegalCopyright", "Copyright (C) 2014-2024"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.14.1.0" VALUE "ProductVersion", "4.14.2.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -603,7 +603,20 @@ void GiftsBox(
box, box,
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
box, box,
session->api().premium().statusTextValue(), // TODO. tr::lng_premium_gifts_terms(
lt_link,
tr::lng_payments_terms_link(
) | rpl::map([](const QString &t) {
using namespace Ui::Text;
return Link(t, u"https://telegram.org/tos"_q);
}),
lt_policy,
tr::lng_premium_gifts_terms_policy(
) | rpl::map([](const QString &t) {
using namespace Ui::Text;
return Link(t, u"https://telegram.org/privacy"_q);
}),
Ui::Text::RichLangValue),
st::premiumGiftTerms), st::premiumGiftTerms),
st::defaultBoxDividerLabelPadding), st::defaultBoxDividerLabelPadding),
{}); {});
@ -903,9 +916,13 @@ void GiftPremiumValidator::showChoosePeerBox(const QString &ref) {
protected: protected:
std::unique_ptr<PeerListRow> createRow( std::unique_ptr<PeerListRow> createRow(
not_null<UserData*> user) override { not_null<UserData*> user) override {
return !user->isSelf() if (user->isSelf()
? ContactsBoxController::createRow(user) || user->isBot()
: nullptr; || user->isServiceUser()
|| user->isInaccessible()) {
return nullptr;
}
return ContactsBoxController::createRow(user);
} }
void rowClicked(not_null<PeerListRow*> row) override { void rowClicked(not_null<PeerListRow*> row) override {
@ -1037,7 +1054,7 @@ void GiftCodeBox(
state->data = session->api().premium().giftCodeValue(slug); state->data = session->api().premium().giftCodeValue(slug);
state->used = state->data.value( state->used = state->data.value(
) | rpl::map([=](const Api::GiftCode &data) { ) | rpl::map([=](const Api::GiftCode &data) {
return data.used; return data.used != 0;
}); });
box->setWidth(st::boxWideWidth); box->setWidth(st::boxWideWidth);

View file

@ -1265,7 +1265,7 @@ void Settings::resetOnLastLogout() {
_tabbedReplacedWithInfo = false; // per-window _tabbedReplacedWithInfo = false; // per-window
_systemDarkModeEnabled = false; _systemDarkModeEnabled = false;
_hiddenGroupCallTooltips = 0; _hiddenGroupCallTooltips = 0;
_storiesClickTooltipHidden = 0; _storiesClickTooltipHidden = false;
_recentEmojiPreload.clear(); _recentEmojiPreload.clear();
_recentEmoji.clear(); _recentEmoji.clear();

View file

@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
constexpr auto AppNameOld = "AyuGram for Windows"_cs; constexpr auto AppNameOld = "AyuGram for Windows"_cs;
constexpr auto AppName = "AyuGram Desktop"_cs; constexpr auto AppName = "AyuGram Desktop"_cs;
constexpr auto AppFile = "AyuGram"_cs; constexpr auto AppFile = "AyuGram"_cs;
constexpr auto AppVersion = 4014001; constexpr auto AppVersion = 4014002;
constexpr auto AppVersionStr = "4.14.1"; constexpr auto AppVersionStr = "4.14.2";
constexpr auto AppBetaVersion = false; constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View file

@ -624,7 +624,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
bool selected, bool selected,
bool mayBeActive) { bool mayBeActive) {
const auto key = row->key(); const auto key = row->key();
const auto active = mayBeActive && (activeEntry.key == key); const auto active = mayBeActive && isRowActive(row, activeEntry);
const auto forum = key.history() && key.history()->isForum(); const auto forum = key.history() && key.history()->isForum();
if (forum && !_topicJumpCache) { if (forum && !_topicJumpCache) {
_topicJumpCache = std::make_unique<Ui::TopicJumpCache>(); _topicJumpCache = std::make_unique<Ui::TopicJumpCache>();
@ -977,6 +977,14 @@ void InnerWidget::paintCollapsedRow(
}); });
} }
bool InnerWidget::isRowActive(
not_null<Row*> row,
const RowDescriptor &entry) const {
const auto key = row->key();
return (entry.key == key)
|| (entry.key.sublist() && key.peer() && key.peer()->isSelf());
}
bool InnerWidget::isSearchResultActive( bool InnerWidget::isSearchResultActive(
not_null<FakeRow*> result, not_null<FakeRow*> result,
const RowDescriptor &entry) const { const RowDescriptor &entry) const {

View file

@ -231,6 +231,7 @@ private:
void switchToFilter(FilterId filterId); void switchToFilter(FilterId filterId);
bool chooseHashtag(); bool chooseHashtag();
ChosenRow computeChosenRow() const; ChosenRow computeChosenRow() const;
bool isRowActive(not_null<Row*> row, const RowDescriptor &entry) const;
bool isSearchResultActive( bool isSearchResultActive(
not_null<FakeRow*> result, not_null<FakeRow*> result,
const RowDescriptor &entry) const; const RowDescriptor &entry) const;

View file

@ -522,7 +522,7 @@ AVRational ValidateAspectRatio(AVRational aspect) {
QSize CorrectByAspect(QSize size, AVRational aspect) { QSize CorrectByAspect(QSize size, AVRational aspect) {
Expects(IsValidAspectRatio(aspect)); Expects(IsValidAspectRatio(aspect));
return QSize(size.width() * aspect.num / aspect.den, size.height()); return QSize(size.width() * av_q2d(aspect), size.height());
} }
bool RotationSwapWidthHeight(int rotation) { bool RotationSwapWidthHeight(int rotation) {

View file

@ -1267,6 +1267,22 @@ uint8 HistoryItem::colorIndex() const {
Unexpected("No displayFrom and no displayHiddenSenderInfo."); Unexpected("No displayFrom and no displayHiddenSenderInfo.");
} }
PeerData *HistoryItem::contentColorsFrom() const {
if (const auto forwarded = Get<HistoryMessageForwarded>()) {
return forwarded->originalSender;
}
return displayFrom();
}
uint8 HistoryItem::contentColorIndex() const {
if (const auto forwarded = Get<HistoryMessageForwarded>()) {
return forwarded->originalSender
? forwarded->originalSender->colorIndex()
: forwarded->originalHiddenSenderInfo->colorIndex;
}
return colorIndex();
}
std::unique_ptr<HistoryView::Element> HistoryItem::createView( std::unique_ptr<HistoryView::Element> HistoryItem::createView(
not_null<HistoryView::ElementDelegate*> delegate, not_null<HistoryView::ElementDelegate*> delegate,
HistoryView::Element *replacing) { HistoryView::Element *replacing) {

View file

@ -517,6 +517,11 @@ public:
[[nodiscard]] PeerData *displayFrom() const; [[nodiscard]] PeerData *displayFrom() const;
[[nodiscard]] uint8 colorIndex() const; [[nodiscard]] uint8 colorIndex() const;
// In forwards we show name in sender's color, but the message
// content uses the color of the original sender.
[[nodiscard]] PeerData *contentColorsFrom() const;
[[nodiscard]] uint8 contentColorIndex() const;
[[nodiscard]] std::unique_ptr<HistoryView::Element> createView( [[nodiscard]] std::unique_ptr<HistoryView::Element> createView(
not_null<HistoryView::ElementDelegate*> delegate, not_null<HistoryView::ElementDelegate*> delegate,
HistoryView::Element *replacing = nullptr); HistoryView::Element *replacing = nullptr);

View file

@ -495,6 +495,10 @@ uint8 Element::colorIndex() const {
return data()->colorIndex(); return data()->colorIndex();
} }
uint8 Element::contentColorIndex() const {
return data()->contentColorIndex();
}
QDateTime Element::dateTime() const { QDateTime Element::dateTime() const {
return _dateTime; return _dateTime;
} }

View file

@ -317,6 +317,7 @@ public:
void refreshDataId(); void refreshDataId();
[[nodiscard]] uint8 colorIndex() const; [[nodiscard]] uint8 colorIndex() const;
[[nodiscard]] uint8 contentColorIndex() const;
[[nodiscard]] QDateTime dateTime() const; [[nodiscard]] QDateTime dateTime() const;
[[nodiscard]] int y() const; [[nodiscard]] int y() const;

View file

@ -1670,7 +1670,7 @@ void Message::paintText(
.availableWidth = trect.width(), .availableWidth = trect.width(),
.palette = &stm->textPalette, .palette = &stm->textPalette,
.pre = stm->preCache.get(), .pre = stm->preCache.get(),
.blockquote = context.quoteCache(colorIndex()), .blockquote = context.quoteCache(contentColorIndex()),
.colors = context.st->highlightColors(), .colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now, .now = context.now,

View file

@ -205,7 +205,7 @@ void Reply::update(
} }
} }
_colorPeer = message _colorPeer = message
? message->displayFrom() ? message->contentColorsFrom()
: story : story
? story->peer().get() ? story->peer().get()
: _externalSender : _externalSender
@ -412,7 +412,10 @@ void Reply::updateName(
std::optional<PeerData*> resolvedSender) const { std::optional<PeerData*> resolvedSender) const {
auto viaBotUsername = QString(); auto viaBotUsername = QString();
const auto message = data->resolvedMessage.get(); const auto message = data->resolvedMessage.get();
if (message && !message->Has<HistoryMessageForwarded>()) { const auto forwarded = message
? message->Get<HistoryMessageForwarded>()
: nullptr;
if (message && !forwarded) {
if (const auto bot = message->viaBot()) { if (const auto bot = message->viaBot()) {
viaBotUsername = bot->username(); viaBotUsername = bot->username();
} }
@ -428,7 +431,15 @@ void Reply::updateName(
&& externalPeer && externalPeer
&& (externalPeer != sender) && (externalPeer != sender)
&& (externalPeer->isChat() || externalPeer->isMegagroup()); && (externalPeer->isChat() || externalPeer->isMegagroup());
const auto shorten = !viaBotUsername.isEmpty() || groupNameAdded; const auto originalNameAdded = !displayAsExternal
&& forwarded
&& !message->isDiscussionPost()
&& (forwarded->forwardOfForward()
|| (!message->showForwardsFromSender(forwarded)
&& !view->data()->Has<HistoryMessageForwarded>()));
const auto shorten = !viaBotUsername.isEmpty()
|| groupNameAdded
|| originalNameAdded;
const auto name = sender const auto name = sender
? senderName(sender, shorten) ? senderName(sender, shorten)
: senderName(view, data, shorten); : senderName(view, data, shorten);
@ -447,6 +458,11 @@ void Reply::updateName(
if (groupNameAdded) { if (groupNameAdded) {
nameFull.append(' ').append(PeerEmoji(history, externalPeer)); nameFull.append(' ').append(PeerEmoji(history, externalPeer));
nameFull.append(externalPeer->name()); nameFull.append(externalPeer->name());
} else if (originalNameAdded) {
nameFull.append(' ').append(ForwardEmoji(&history->owner()));
nameFull.append(forwarded->originalSender
? forwarded->originalSender->name()
: forwarded->originalHiddenSenderInfo->name);
} }
if (!viaBotUsername.isEmpty()) { if (!viaBotUsername.isEmpty()) {
nameFull.append(u" @"_q).append(viaBotUsername); nameFull.append(u" @"_q).append(viaBotUsername);
@ -844,6 +860,13 @@ TextWithEntities Reply::PeerEmoji(
icon.second)); icon.second));
} }
TextWithEntities Reply::ForwardEmoji(not_null<Data::Session*> owner) {
return Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
st::historyReplyForward,
st::historyReplyForwardPadding));
}
TextWithEntities Reply::ComposePreviewName( TextWithEntities Reply::ComposePreviewName(
not_null<History*> history, not_null<History*> history,
not_null<HistoryItem*> to, not_null<HistoryItem*> to,

View file

@ -105,6 +105,8 @@ public:
[[nodiscard]] static TextWithEntities PeerEmoji( [[nodiscard]] static TextWithEntities PeerEmoji(
not_null<Data::Session*> owner, not_null<Data::Session*> owner,
PeerData *peer); PeerData *peer);
[[nodiscard]] static TextWithEntities ForwardEmoji(
not_null<Data::Session*> owner);
[[nodiscard]] static TextWithEntities ComposePreviewName( [[nodiscard]] static TextWithEntities ComposePreviewName(
not_null<History*> history, not_null<History*> history,
not_null<HistoryItem*> to, not_null<HistoryItem*> to,

View file

@ -259,7 +259,7 @@ not_null<Data::SavedSublist*> SublistWidget::sublist() const {
Dialogs::RowDescriptor SublistWidget::activeChat() const { Dialogs::RowDescriptor SublistWidget::activeChat() const {
return { return {
_history, _sublist,
FullMsgId(_history->peer->id, ShowAtUnreadMsgId) FullMsgId(_history->peer->id, ShowAtUnreadMsgId)
}; };
} }
@ -293,6 +293,10 @@ bool SublistWidget::showInternal(
return false; return false;
} }
bool SublistWidget::sameTypeAs(not_null<Window::SectionMemento*> memento) {
return dynamic_cast<SublistMemento*>(memento.get()) != nullptr;
}
void SublistWidget::setInternalState( void SublistWidget::setInternalState(
const QRect &geometry, const QRect &geometry,
not_null<SublistMemento*> memento) { not_null<SublistMemento*> memento) {

View file

@ -58,6 +58,8 @@ public:
bool showInternal( bool showInternal(
not_null<Window::SectionMemento*> memento, not_null<Window::SectionMemento*> memento,
const Window::SectionShow &params) override; const Window::SectionShow &params) override;
bool sameTypeAs(not_null<Window::SectionMemento*> memento) override;
std::shared_ptr<Window::SectionMemento> createMemento() override; std::shared_ptr<Window::SectionMemento> createMemento() override;
bool showMessage( bool showMessage(
PeerId peerId, PeerId peerId,

View file

@ -80,6 +80,19 @@ inline bool HasGroupCallMenu(const not_null<PeerData*> &peer) {
|| (peer->isChat() && peer->asChat()->amCreator())); || (peer->isChat() && peer->asChat()->amCreator()));
} }
QString TopBarNameText(
not_null<PeerData*> peer,
Dialogs::EntryState::Section section) {
if (section == Dialogs::EntryState::Section::SavedSublist) {
if (peer->isSelf()) {
return tr::lng_my_notes(tr::now);
} else if (peer->isSavedHiddenAuthor()) {
return tr::lng_hidden_author_messages(tr::now);
}
}
return peer->topBarNameText();
}
} // namespace } // namespace
struct TopBarWidget::EmojiInteractionSeenAnimation { struct TopBarWidget::EmojiInteractionSeenAnimation {
@ -559,7 +572,7 @@ void TopBarWidget::paintTopBar(Painter &p) {
_titleNameVersion = namePeer->nameVersion(); _titleNameVersion = namePeer->nameVersion();
_title.setText( _title.setText(
st::msgNameStyle, st::msgNameStyle,
namePeer->topBarNameText(), TopBarNameText(namePeer, _activeChat.section),
Ui::NameTextOptions()); Ui::NameTextOptions());
} }
const auto badgeWidth = _titleBadge.drawGetWidth( const auto badgeWidth = _titleBadge.drawGetWidth(

View file

@ -888,7 +888,7 @@ void Document::draw(
.availableWidth = captionw, .availableWidth = captionw,
.palette = &stm->textPalette, .palette = &stm->textPalette,
.pre = stm->preCache.get(), .pre = stm->preCache.get(),
.blockquote = context.quoteCache(parent()->colorIndex()), .blockquote = context.quoteCache(parent()->contentColorIndex()),
.colors = context.st->highlightColors(), .colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now, .now = context.now,

View file

@ -237,7 +237,7 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw, .availableWidth = captionw,
.palette = &stm->textPalette, .palette = &stm->textPalette,
.pre = stm->preCache.get(), .pre = stm->preCache.get(),
.blockquote = context.quoteCache(parent()->colorIndex()), .blockquote = context.quoteCache(parent()->contentColorIndex()),
.colors = context.st->highlightColors(), .colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now, .now = context.now,

View file

@ -219,7 +219,7 @@ void Game::draw(Painter &p, const PaintContext &context) const {
auto tshift = inner.top(); auto tshift = inner.top();
auto paintw = inner.width(); auto paintw = inner.width();
const auto colorIndex = parent()->colorIndex(); const auto colorIndex = parent()->contentColorIndex();
const auto selected = context.selected(); const auto selected = context.selected();
const auto cache = context.outbg const auto cache = context.outbg
? stm->replyCache[st->colorPatternIndex(colorIndex)].get() ? stm->replyCache[st->colorPatternIndex(colorIndex)].get()

View file

@ -724,7 +724,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw, .availableWidth = captionw,
.palette = &stm->textPalette, .palette = &stm->textPalette,
.pre = stm->preCache.get(), .pre = stm->preCache.get(),
.blockquote = context.quoteCache(parent()->colorIndex()), .blockquote = context.quoteCache(parent()->contentColorIndex()),
.colors = context.st->highlightColors(), .colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now, .now = context.now,

View file

@ -405,7 +405,7 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw, .availableWidth = captionw,
.palette = &stm->textPalette, .palette = &stm->textPalette,
.pre = stm->preCache.get(), .pre = stm->preCache.get(),
.blockquote = context.quoteCache(parent()->colorIndex()), .blockquote = context.quoteCache(parent()->contentColorIndex()),
.colors = context.st->highlightColors(), .colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now, .now = context.now,

View file

@ -433,7 +433,7 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw, .availableWidth = captionw,
.palette = &stm->textPalette, .palette = &stm->textPalette,
.pre = stm->preCache.get(), .pre = stm->preCache.get(),
.blockquote = context.quoteCache(parent()->colorIndex()), .blockquote = context.quoteCache(parent()->contentColorIndex()),
.colors = context.st->highlightColors(), .colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(), .spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now, .now = context.now,

View file

@ -588,11 +588,11 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
const auto selected = context.selected(); const auto selected = context.selected();
const auto view = parent(); const auto view = parent();
const auto colorIndex = view->colorIndex(); const auto from = view->data()->contentColorsFrom();
const auto colorIndex = from ? from->colorIndex() : view->colorIndex();
const auto cache = context.outbg const auto cache = context.outbg
? stm->replyCache[st->colorPatternIndex(colorIndex)].get() ? stm->replyCache[st->colorPatternIndex(colorIndex)].get()
: st->coloredReplyCache(selected, colorIndex).get(); : st->coloredReplyCache(selected, colorIndex).get();
const auto from = view->data()->displayFrom();
const auto backgroundEmojiId = from const auto backgroundEmojiId = from
? from->backgroundEmojiId() ? from->backgroundEmojiId()
: DocumentId(); : DocumentId();

View file

@ -203,12 +203,7 @@ TextWithEntities AboutWithEntities(
const auto stripExternal = peer->isChat() const auto stripExternal = peer->isChat()
|| peer->isMegagroup() || peer->isMegagroup()
|| (user && !isBot && !isPremium); || (user && !isBot && !isPremium);
const auto limit = Data::PremiumLimits(&peer->session()) auto result = TextWithEntities{ value };
.aboutLengthDefault();
const auto used = (!user || isPremium || value.size() <= limit)
? value
: value.mid(0, limit) + "...";
auto result = TextWithEntities{ used };
TextUtilities::ParseEntities(result, flags); TextUtilities::ParseEntities(result, flags);
if (stripExternal) { if (stripExternal) {
StripExternalLinks(result); StripExternalLinks(result);

View file

@ -60,9 +60,12 @@ SublistsWidget::SublistsWidget(
_list->chosenRow() | rpl::start_with_next([=](Dialogs::ChosenRow row) { _list->chosenRow() | rpl::start_with_next([=](Dialogs::ChosenRow row) {
if (const auto sublist = row.key.sublist()) { if (const auto sublist = row.key.sublist()) {
using namespace Window;
auto params = SectionShow(SectionShow::Way::Forward);
params.dropSameFromStack = true;
controller->showSection( controller->showSection(
std::make_shared<HistoryView::SublistMemento>(sublist), std::make_shared<HistoryView::SublistMemento>(sublist),
Window::SectionShow::Way::Forward); params);
} }
}, _list->lifetime()); }, _list->lifetime());

View file

@ -1379,7 +1379,7 @@ void MainWidget::showHistory(
if (!back && (way != Way::ClearStack)) { if (!back && (way != Way::ClearStack)) {
// This may modify the current section, for example remove its contents. // This may modify the current section, for example remove its contents.
saveSectionInStack(); saveSectionInStack(params);
} }
if (_history->peer() if (_history->peer()
@ -1501,13 +1501,23 @@ Ui::ChatTheme *MainWidget::customChatTheme() const {
return _history->customChatTheme(); return _history->customChatTheme();
} }
void MainWidget::saveSectionInStack() { bool MainWidget::saveSectionInStack(
const SectionShow &params,
Window::SectionWidget *newMainSection) {
if (_mainSection) { if (_mainSection) {
if (auto memento = _mainSection->createMemento()) { if (auto memento = _mainSection->createMemento()) {
if (params.dropSameFromStack
&& newMainSection
&& newMainSection->sameTypeAs(memento.get())) {
// When choosing saved sublist we want to save the original
// "Saved Messages" in the stack, but don't save every
// sublist in a new stack entry when clicking them through.
return false;
}
_stack.push_back(std::make_unique<StackItemSection>( _stack.push_back(std::make_unique<StackItemSection>(
std::move(memento))); std::move(memento)));
} else { } else {
return; return false;
} }
} else if (const auto history = _history->history()) { } else if (const auto history = _history->history()) {
_stack.push_back(std::make_unique<StackItemHistory>( _stack.push_back(std::make_unique<StackItemHistory>(
@ -1515,7 +1525,7 @@ void MainWidget::saveSectionInStack() {
_history->msgId(), _history->msgId(),
_history->replyReturns())); _history->replyReturns()));
} else { } else {
return; return false;
} }
const auto raw = _stack.back().get(); const auto raw = _stack.back().get();
raw->setThirdSectionWeak(_thirdSection.data()); raw->setThirdSectionWeak(_thirdSection.data());
@ -1528,6 +1538,7 @@ void MainWidget::saveSectionInStack() {
} }
} }
}, raw->lifetime()); }, raw->lifetime());
return true;
} }
void MainWidget::showSection( void MainWidget::showSection(
@ -1730,7 +1741,11 @@ void MainWidget::showNewSection(
if (saveInStack) { if (saveInStack) {
// This may modify the current section, for example remove its contents. // This may modify the current section, for example remove its contents.
saveSectionInStack(); if (!saveSectionInStack(params, newMainSection)) {
saveInStack = false;
animatedShow = false;
animationParams = Window::SectionSlideParams();
}
} }
auto &settingSection = newThirdSection auto &settingSection = newThirdSection
? _thirdSection ? _thirdSection
@ -2446,6 +2461,10 @@ auto MainWidget::thirdSectionForCurrentMainSection(
return std::make_shared<Info::Memento>( return std::make_shared<Info::Memento>(
peer, peer,
Info::Memento::DefaultSection(peer)); Info::Memento::DefaultSection(peer));
} else if (const auto sublist = key.sublist()) {
return std::make_shared<Info::Memento>(
session().user(),
Info::Memento::DefaultSection(session().user()));
} }
Unexpected("Key in MainWidget::thirdSectionForCurrentMainSection()."); Unexpected("Key in MainWidget::thirdSectionForCurrentMainSection().");
} }

View file

@ -286,7 +286,9 @@ private:
Window::SectionSlideParams prepareHistoryAnimation(PeerId historyPeerId); Window::SectionSlideParams prepareHistoryAnimation(PeerId historyPeerId);
Window::SectionSlideParams prepareDialogsAnimation(); Window::SectionSlideParams prepareDialogsAnimation();
void saveSectionInStack(); bool saveSectionInStack(
const SectionShow &params,
Window::SectionWidget *newMainSection = nullptr);
int getMainSectionTop() const; int getMainSectionTop() const;
int getThirdSectionTop() const; int getThirdSectionTop() const;

View file

@ -20,10 +20,21 @@ OverlayWidget::RendererSW::RendererSW(not_null<OverlayWidget*> owner)
, _transparentBrush(style::TransparentPlaceholder()) { , _transparentBrush(style::TransparentPlaceholder()) {
} }
bool OverlayWidget::RendererSW::handleHideWorkaround() {
// This is needed on Windows or Linux,
// because on reopen it blinks with the last shown content.
return _owner->_hideWorkaround != nullptr;
}
void OverlayWidget::RendererSW::paintFallback( void OverlayWidget::RendererSW::paintFallback(
Painter &&p, Painter &&p,
const QRegion &clip, const QRegion &clip,
Ui::GL::Backend backend) { Ui::GL::Backend backend) {
if (handleHideWorkaround()) {
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(clip.boundingRect(), Qt::transparent);
return;
}
_p = &p; _p = &p;
_clip = &clip; _clip = &clip;
_clipOuter = clip.boundingRect(); _clipOuter = clip.boundingRect();

View file

@ -59,6 +59,7 @@ private:
QRect rect, QRect rect,
float64 opacity = 1.) override; float64 opacity = 1.) override;
bool handleHideWorkaround();
void validateOverControlImage(); void validateOverControlImage();
[[nodiscard]] static QRect TransformRect(QRectF geometry, int rotation); [[nodiscard]] static QRect TransformRect(QRectF geometry, int rotation);

View file

@ -38,6 +38,8 @@ historyReplyGroup: icon {{ "chat/reply_type_group", windowFg }};
historyReplyGroupPadding: margins(0px, 4px, 4px, 0px); historyReplyGroupPadding: margins(0px, 4px, 4px, 0px);
historyReplyChannel: icon {{ "chat/reply_type_channel", windowFg }}; historyReplyChannel: icon {{ "chat/reply_type_channel", windowFg }};
historyReplyChannelPadding: margins(0px, 5px, 4px, 0px); historyReplyChannelPadding: margins(0px, 5px, 4px, 0px);
historyReplyForward: icon {{ "mini_forward", windowFg }};
historyReplyForwardPadding: margins(0px, 2px, 2px, 0px);
msgReplyPadding: margins(6px, 6px, 11px, 6px); msgReplyPadding: margins(6px, 6px, 11px, 6px);
msgReplyBarPos: point(1px, 0px); msgReplyBarPos: point(1px, 0px);

View file

@ -138,6 +138,9 @@ public:
virtual bool showInternal( virtual bool showInternal(
not_null<SectionMemento*> memento, not_null<SectionMemento*> memento,
const SectionShow &params) = 0; const SectionShow &params) = 0;
virtual bool sameTypeAs(not_null<SectionMemento*> memento) {
return false;
}
virtual bool showMessage( virtual bool showMessage(
PeerId peerId, PeerId peerId,

View file

@ -162,6 +162,7 @@ struct SectionShow {
bool childColumn = false; bool childColumn = false;
bool forbidLayer = false; bool forbidLayer = false;
bool reapplyLocalDraft = false; bool reapplyLocalDraft = false;
bool dropSameFromStack = false;
Origin origin; Origin origin;
}; };

View file

@ -1,7 +1,7 @@
AppVersion 4014001 AppVersion 4014002
AppVersionStrMajor 4.14 AppVersionStrMajor 4.14
AppVersionStrSmall 4.14.1 AppVersionStrSmall 4.14.2
AppVersionStr 4.14.1 AppVersionStr 4.14.2
BetaChannel 0 BetaChannel 0
AlphaVersion 0 AlphaVersion 0
AppVersionOriginal 4.14.1 AppVersionOriginal 4.14.2

@ -1 +1 @@
Subproject commit 1bb91474c2337396673dd8a7c68e65ea317b6db5 Subproject commit 63e4ba48fd8540fa3c2949d123160a2ce3411d70

View file

@ -1,3 +1,10 @@
4.14.2 (02.01.24)
- Show original senders name in reply to forward information.
- Use original senders color / emoji pattern in forwards.
- Highlight active saved messages chat in list.
- Fix chats list scrolling on X11 (Linux).
4.14.1 (01.01.24) 4.14.1 (01.01.24)
- Fix crash in "Author Hidden" chat in "Saved Messages". - Fix crash in "Author Hidden" chat in "Saved Messages".