diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml
index 65aaca6cc..990e326bf 100644
--- a/Telegram/Resources/uwp/AppX/AppxManifest.xml
+++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml
@@ -10,7 +10,7 @@
+ Version="5.12.3.0" />
Telegram Desktop
Telegram Messenger LLP
diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc
index 21f7f0286..26296ddc6 100644
--- a/Telegram/Resources/winrc/Telegram.rc
+++ b/Telegram/Resources/winrc/Telegram.rc
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,12,1,0
- PRODUCTVERSION 5,12,1,0
+ FILEVERSION 5,12,3,0
+ PRODUCTVERSION 5,12,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop"
- VALUE "FileVersion", "5.12.1.0"
+ VALUE "FileVersion", "5.12.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "5.12.1.0"
+ VALUE "ProductVersion", "5.12.3.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc
index 6f72c4477..a52f9c841 100644
--- a/Telegram/Resources/winrc/Updater.rc
+++ b/Telegram/Resources/winrc/Updater.rc
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,12,1,0
- PRODUCTVERSION 5,12,1,0
+ FILEVERSION 5,12,3,0
+ PRODUCTVERSION 5,12,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Radolyn Labs"
VALUE "FileDescription", "AyuGram Desktop Updater"
- VALUE "FileVersion", "5.12.1.0"
+ VALUE "FileVersion", "5.12.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
VALUE "ProductName", "AyuGram Desktop"
- VALUE "ProductVersion", "5.12.1.0"
+ VALUE "ProductVersion", "5.12.3.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp
index 5313a2ae3..fdc31618f 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp
@@ -363,15 +363,17 @@ object_ptr AddReactionsSelector(
const auto customEmojiPaused = [controller = args.controller] {
return controller->isGifPausedAtLeastFor(PauseReason::Layer);
};
- auto context = Core::TextContext({
+ auto simpleContext = Core::TextContext({
.session = session,
+ .repaint = [=] { raw->update(); },
});
+ auto context = simpleContext;
context.customEmojiFactory = [=](
QStringView data,
const Ui::Text::MarkedContext &context
) -> std::unique_ptr {
const auto id = Data::ParseCustomEmojiData(data);
- auto result = Ui::Text::MakeCustomEmoji(data, context);
+ auto result = Ui::Text::MakeCustomEmoji(data, simpleContext);
if (state->unifiedFactoryOwner->lookupReactionId(id).custom()) {
return std::make_unique(
std::move(result),
diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h
index 3a8011d57..a2770d570 100644
--- a/Telegram/SourceFiles/core/version.h
+++ b/Telegram/SourceFiles/core/version.h
@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
constexpr auto AppNameOld = "AyuGram for Windows"_cs;
constexpr auto AppName = "AyuGram Desktop"_cs;
constexpr auto AppFile = "AyuGram"_cs;
-constexpr auto AppVersion = 5012001;
-constexpr auto AppVersionStr = "5.12.1";
+constexpr auto AppVersion = 5012003;
+constexpr auto AppVersionStr = "5.12.3";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
diff --git a/Telegram/SourceFiles/countries/countries_instance.cpp b/Telegram/SourceFiles/countries/countries_instance.cpp
index ba159016d..d9ef7c3c7 100644
--- a/Telegram/SourceFiles/countries/countries_instance.cpp
+++ b/Telegram/SourceFiles/countries/countries_instance.cpp
@@ -322,6 +322,9 @@ QString CountriesInstance::flagEmojiByISO2(const QString &iso) const {
|| iso.back() < 'A'
|| iso.back() > 'Z') {
return QString();
+ } else if (iso == u"FT"_q) {
+ return QString::fromUtf8(
+ "\xF0\x9F\x8F\xB4\xE2\x80\x8D\xE2\x98\xA0\xEF\xB8\x8F");
}
auto result = QString(4, QChar(0xD83C));
result[1] = QChar(iso.front().unicode() - 'A' + 0xDDE6);
diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
index f43ff0077..e636b0a9d 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
@@ -4905,33 +4905,14 @@ void InnerWidget::setupShortcuts() {
});
}
- const auto nearFolder = [=](bool isNext) {
- const auto id = _controller->activeChatsFilterCurrent();
- const auto list = &session().data().chatsFilters().list();
- const auto index = int(ranges::find(
- *list,
- id,
- &Data::ChatFilter::id
- ) - begin(*list));
- if (index == list->size() && id != 0) {
- return false;
- }
- const auto changed = index + (isNext ? 1 : -1);
- if (changed >= int(list->size()) || changed < 0) {
- return false;
- }
- _controller->setActiveChatsFilter((changed >= 0)
- ? (*list)[changed].id()
- : 0);
- return true;
- };
-
request->check(Command::FolderNext) && request->handle([=] {
- return nearFolder(true);
+ using namespace Window;
+ return CheckAndJumpToNearChatsFilter(_controller, true, true);
});
request->check(Command::FolderPrevious) && request->handle([=] {
- return nearFolder(false);
+ using namespace Window;
+ return CheckAndJumpToNearChatsFilter(_controller, false, true);
});
request->check(Command::ReadChat) && request->handle([=] {
diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp
index 6a16476f4..9dfd18067 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp
@@ -1334,6 +1334,9 @@ void Widget::toggleFiltersMenu(bool enabled) {
if (_layout == Layout::Child) {
enabled = false;
}
+ if (const auto id = controller()->windowId(); id.forum() || id.folder()) {
+ enabled = false;
+ }
if (!enabled == !_chatFilters) {
return;
} else if (enabled) {
diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp
index fdb61a799..bc25b6039 100644
--- a/Telegram/SourceFiles/export/view/export_view_settings.cpp
+++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp
@@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h"
#include "ui/boxes/calendar_box.h"
+#include "ui/boxes/choose_time.h"
#include "platform/platform_specific.h"
#include "core/application.h"
#include "core/file_utilities.h"
@@ -388,7 +389,7 @@ void SettingsWidget::addFormatAndLocationLabel(
void SettingsWidget::addLimitsLabel(
not_null container) {
- auto fromLink = value() | rpl::map([](const Settings &data) {
+ auto fromDateLink = value() | rpl::map([](const Settings &data) {
return data.singlePeerFrom;
}) | rpl::distinct_until_changed(
) | rpl::map([](TimeId from) {
@@ -399,7 +400,34 @@ void SettingsWidget::addLimitsLabel(
) | Ui::Text::ToLink(u"internal:edit_from"_q);
}) | rpl::flatten_latest();
- auto tillLink = value() | rpl::map([](const Settings &data) {
+ const auto mapToTime = [](TimeId id, const QString &link) {
+ return rpl::single(id
+ ? QLocale().toString(
+ base::unixtime::parse(id).time(),
+ QLocale::ShortFormat)
+ : QString()
+ ) | Ui::Text::ToLink(link);
+ };
+
+ const auto concat = [](TextWithEntities date, TextWithEntities link) {
+ return link.text.isEmpty()
+ ? date
+ : date.append(u", "_q).append(std::move(link));
+ };
+
+ auto fromTimeLink = value() | rpl::map([](const Settings &data) {
+ return data.singlePeerFrom;
+ }) | rpl::distinct_until_changed(
+ ) | rpl::map([=](TimeId from) {
+ return mapToTime(from, u"internal:edit_from_time"_q);
+ }) | rpl::flatten_latest();
+
+ auto fromLink = rpl::combine(
+ std::move(fromDateLink),
+ std::move(fromTimeLink)
+ ) | rpl::map(concat);
+
+ auto tillDateLink = value() | rpl::map([](const Settings &data) {
return data.singlePeerTill;
}) | rpl::distinct_until_changed(
) | rpl::map([](TimeId till) {
@@ -410,6 +438,18 @@ void SettingsWidget::addLimitsLabel(
) | Ui::Text::ToLink(u"internal:edit_till"_q);
}) | rpl::flatten_latest();
+ auto tillTimeLink = value() | rpl::map([](const Settings &data) {
+ return data.singlePeerTill;
+ }) | rpl::distinct_until_changed(
+ ) | rpl::map([=](TimeId till) {
+ return mapToTime(till, u"internal:edit_till_time"_q);
+ }) | rpl::flatten_latest();
+
+ auto tillLink = rpl::combine(
+ std::move(tillDateLink),
+ std::move(tillTimeLink)
+ ) | rpl::map(concat);
+
auto datesText = tr::lng_export_limits(
lt_from,
std::move(fromLink),
@@ -424,8 +464,47 @@ void SettingsWidget::addLimitsLabel(
object_ptr(
container,
std::move(datesText),
- st::exportLocationLabel),
+ st::boxLabel),
st::exportLimitsPadding);
+
+ const auto removeTime = [](TimeId dateTime) {
+ return base::unixtime::serialize(
+ QDateTime(
+ base::unixtime::parse(dateTime).date(),
+ QTime()));
+ };
+
+ const auto editTimeLimit = [=](Fn now, Fn done) {
+ _showBoxCallback(Box([=](not_null box) {
+ auto result = Ui::ChooseTimeWidget(
+ box->verticalLayout(),
+ [&] {
+ const auto time = base::unixtime::parse(now()).time();
+ return time.hour() * 3600
+ + time.minute() * 60
+ + time.second();
+ }(),
+ true);
+ const auto widget = box->addRow(std::move(result.widget));
+ const auto toSave = widget->lifetime().make_state(0);
+ std::move(
+ result.secondsValue
+ ) | rpl::start_with_next([=](TimeId t) {
+ *toSave = t;
+ }, box->lifetime());
+ box->addButton(tr::lng_settings_save(), [=] {
+ done(*toSave);
+ box->closeBox();
+ });
+ box->addButton(tr::lng_cancel(), [=] {
+ box->closeBox();
+ });
+ box->setTitle(tr::lng_settings_ttl_after_custom());
+ }));
+ };
+
+ constexpr auto kOffset = 600;
+
label->overrideLinkClickHandler([=](const QString &url) {
if (url == u"internal:edit_from"_q) {
const auto done = [=](TimeId limit) {
@@ -439,10 +518,38 @@ void SettingsWidget::addLimitsLabel(
readData().singlePeerTill,
tr::lng_export_from_beginning(),
done);
+ } else if (url == u"internal:edit_from_time"_q) {
+ const auto now = [=] {
+ auto result = TimeId(0);
+ changeData([&](Settings &settings) {
+ result = settings.singlePeerFrom;
+ });
+ return result;
+ };
+ const auto done = [=](TimeId time) {
+ changeData([&](Settings &settings) {
+ const auto result = time
+ + removeTime(settings.singlePeerFrom);
+ if (result >= settings.singlePeerTill
+ && settings.singlePeerTill) {
+ settings.singlePeerFrom = settings.singlePeerTill
+ - kOffset;
+ } else {
+ settings.singlePeerFrom = result;
+ }
+ });
+ };
+ editTimeLimit(now, done);
} else if (url == u"internal:edit_till"_q) {
const auto done = [=](TimeId limit) {
changeData([&](Settings &settings) {
- settings.singlePeerTill = limit;
+ if (limit <= settings.singlePeerFrom
+ && settings.singlePeerFrom) {
+ settings.singlePeerTill = settings.singlePeerFrom
+ + kOffset;
+ } else {
+ settings.singlePeerTill = limit;
+ }
});
};
editDateLimit(
@@ -451,6 +558,28 @@ void SettingsWidget::addLimitsLabel(
0,
tr::lng_export_till_end(),
done);
+ } else if (url == u"internal:edit_till_time"_q) {
+ const auto now = [=] {
+ auto result = TimeId(0);
+ changeData([&](Settings &settings) {
+ result = settings.singlePeerTill;
+ });
+ return result;
+ };
+ const auto done = [=](TimeId time) {
+ changeData([&](Settings &settings) {
+ const auto result = time
+ + removeTime(settings.singlePeerTill);
+ if (result <= settings.singlePeerFrom
+ && settings.singlePeerFrom) {
+ settings.singlePeerTill = settings.singlePeerFrom
+ + kOffset;
+ } else {
+ settings.singlePeerTill = result;
+ }
+ });
+ };
+ editTimeLimit(now, done);
} else {
Unexpected("Click handler URL in export limits edit.");
}
diff --git a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp
index 677fee209..9f2173262 100644
--- a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp
+++ b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp
@@ -1567,7 +1567,7 @@ void VoiceRecordBar::init() {
if (value == 0. && !show) {
_lock->hide();
} else if (value == 1. && show) {
- computeAndSetLockProgress(QCursor::pos());
+ _lock->requestPaintProgress(calcLockProgress(QCursor::pos()));
}
if (_fullRecord && !show) {
updateTTLGeometry(TTLAnimationType::RightLeft, 1.);
@@ -1872,6 +1872,52 @@ void VoiceRecordBar::startRecording() {
_inField = true;
+ struct FloatingState {
+ Ui::Animations::Basic animation;
+ float64 animationProgress = 0;
+ float64 cursorProgress = 0;
+ bool lockCapturedByInput = false;
+ float64 frameCounter = 0;
+ rpl::lifetime lifetime;
+ };
+ const auto stateOwned
+ = _recordingLifetime.make_state>(
+ std::make_unique());
+ const auto state = stateOwned->get();
+
+ _lock->locks() | rpl::start_with_next([=] {
+ stateOwned->reset();
+ }, state->lifetime);
+
+ constexpr auto kAnimationThreshold = 0.35;
+ const auto calcStateRatio = [=](float64 counter) {
+ return (1 - std::cos(std::fmod(counter, 2 * M_PI))) * 0.5;
+ };
+ state->animation.init([=](crl::time now) {
+ if (state->cursorProgress > kAnimationThreshold) {
+ state->lockCapturedByInput = true;
+ }
+ if (state->lockCapturedByInput) {
+ if (state->cursorProgress < 0.01) {
+ state->lockCapturedByInput = false;
+ state->frameCounter = 0;
+ } else {
+ _lock->requestPaintProgress(state->cursorProgress);
+ return;
+ }
+ }
+ const auto progress = anim::interpolateF(
+ state->cursorProgress,
+ kAnimationThreshold,
+ calcStateRatio(state->frameCounter));
+ state->frameCounter += 0.01;
+ _lock->requestPaintProgress(progress);
+ });
+ state->animation.start();
+ if (hasDuration()) {
+ stateOwned->reset();
+ }
+
_send->events(
) | rpl::filter([=](not_null e) {
return (e->type() == QEvent::MouseMove
@@ -1892,7 +1938,10 @@ void VoiceRecordBar::startRecording() {
if (_showLockAnimation.animating() || !hasDuration()) {
return;
}
- computeAndSetLockProgress(mouse->globalPos());
+ const auto inputProgress = calcLockProgress(mouse->globalPos());
+ if (inputProgress > state->animationProgress) {
+ state->cursorProgress = inputProgress;
+ }
} else if (type == QEvent::MouseButtonRelease) {
checkTipRequired();
stop(_inField.current());
@@ -2328,10 +2377,14 @@ float64 VoiceRecordBar::showListenAnimationRatio() const {
}
void VoiceRecordBar::computeAndSetLockProgress(QPoint globalPos) {
+ _lock->requestPaintProgress(calcLockProgress(globalPos));
+}
+
+float64 VoiceRecordBar::calcLockProgress(QPoint globalPos) {
const auto localPos = mapFromGlobal(globalPos);
const auto lower = _lock->height();
const auto higher = 0;
- _lock->requestPaintProgress(Progress(localPos.y(), higher - lower));
+ return Progress(localPos.y(), higher - lower);
}
bool VoiceRecordBar::peekTTLState() const {
diff --git a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h
index c1a9ff4a7..7a01c8563 100644
--- a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h
+++ b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h
@@ -156,6 +156,7 @@ private:
[[nodiscard]] float64 activeAnimationRatio() const;
void computeAndSetLockProgress(QPoint globalPos);
+ [[nodiscard]] float64 calcLockProgress(QPoint globalPos);
[[nodiscard]] bool peekTTLState() const;
[[nodiscard]] bool takeTTLState() const;
diff --git a/Telegram/SourceFiles/history/view/history_view_about_view.cpp b/Telegram/SourceFiles/history/view/history_view_about_view.cpp
index d2ad1b735..486bcd984 100644
--- a/Telegram/SourceFiles/history/view/history_view_about_view.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_about_view.cpp
@@ -748,6 +748,7 @@ AdminLog::OwnedItem AboutView::makeNewPeerInfo(not_null user) {
owned.get(),
GenerateNewPeerInfo(owned.get(), _item.get(), user, _commonGroups),
HistoryView::MediaGenericDescriptor{
+ .maxWidth = st::newPeerWidth,
.service = true,
.hideServiceText = true,
}));
diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp
index 71e711ad0..13e5ce678 100644
--- a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp
@@ -308,6 +308,9 @@ void ContactStatus::Bar::showState(
_emojiStatusInfo->entity()->overrideLinkClickHandler([=] {
_emojiStatusClicks.fire({});
});
+ _emojiStatusInfo->entity()->setAnimationsPausedCallback([] {
+ return Ui::FlatLabel::WhichAnimationsPaused::CustomEmoji;
+ });
}
_emojiStatusInfo->setVisible(has);
_add->setText((type == Type::Add)
diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp
index 3b70d6282..d27ef8816 100644
--- a/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp
+++ b/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp
@@ -304,7 +304,7 @@ QSize MediaGenericTextPart::countCurrentSize(int newWidth) {
const auto size = CountOptimalTextSize(
_text,
st::msgMinWidth,
- newWidth - skip);
+ std::max(st::msgMinWidth, newWidth - skip));
return {
size.width() + skip,
_margins.top() + size.height() + _margins.bottom(),
diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp
index 6bbde5e05..683501acf 100644
--- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp
+++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp
@@ -274,7 +274,10 @@ void InnerWidget::markUnpinned(std::vector::iterator i) {
}
++after;
}
- if (after == _entries.size()) {
+ if (after == _entries.size() && !_allLoaded) {
+ // We don't know if the correct position is exactly in the end
+ // of the loaded part or later, so we hide it for now, let it
+ // be loaded later while scrolling.
_entries.erase(i);
} else if (after > index + 1) {
std::rotate(i, i + 1, begin(_entries) + after);
diff --git a/Telegram/SourceFiles/platform/linux/integration_linux.cpp b/Telegram/SourceFiles/platform/linux/integration_linux.cpp
index e8696772e..e3e331cd7 100644
--- a/Telegram/SourceFiles/platform/linux/integration_linux.cpp
+++ b/Telegram/SourceFiles/platform/linux/integration_linux.cpp
@@ -12,6 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/linux/base_linux_xdp_utilities.h"
#include "core/sandbox.h"
#include "core/application.h"
+#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
+#include "core/core_settings.h"
+#endif
#include "base/random.h"
#include
diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
index b41d0e4a9..47b92fb72 100644
--- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
+++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
@@ -423,7 +423,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
for (const auto &[key, notifications] : _notifications) {
for (const auto &[msgId, notification] : notifications) {
- if (id == v::get(notification->id)) {
+ const auto &nid = notification->id;
+ if (v::is(nid) && v::get(nid) == id) {
if (actionName == "default") {
_manager->notificationActivated({ key, msgId });
} else if (actionName == "mail-mark-read") {
@@ -447,7 +448,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
for (const auto &[key, notifications] : _notifications) {
for (const auto &[msgId, notification] : notifications) {
- if (id == v::get(notification->id)) {
+ const auto &nid = notification->id;
+ if (v::is(nid) && v::get(nid) == id) {
_manager->notificationReplied(
{ key, msgId },
{ QString::fromStdString(text), {} });
@@ -468,7 +470,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
std::string token) {
for (const auto &[key, notifications] : _notifications) {
for (const auto &[msgId, notification] : notifications) {
- if (id == v::get(notification->id)) {
+ const auto &nid = notification->id;
+ if (v::is(nid) && v::get(nid) == id) {
GLib::setenv("XDG_ACTIVATION_TOKEN", token, true);
return;
}
@@ -501,7 +504,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
* In all other cases we keep the notification reference so that we may clear the notification later from history,
* if the message for that notification is read (e.g. chat is opened or read from another device).
*/
- if (id == v::get(notification->id) && reason == 2) {
+ const auto &nid = notification->id;
+ if (v::is(nid) && v::get(nid) == id && reason == 2) {
clearNotification({ key, msgId });
return;
}
diff --git a/Telegram/SourceFiles/ui/boxes/choose_time.cpp b/Telegram/SourceFiles/ui/boxes/choose_time.cpp
index 488c1c0d3..aa7f2836e 100644
--- a/Telegram/SourceFiles/ui/boxes/choose_time.cpp
+++ b/Telegram/SourceFiles/ui/boxes/choose_time.cpp
@@ -18,7 +18,8 @@ namespace Ui {
ChooseTimeResult ChooseTimeWidget(
not_null parent,
- TimeId startSeconds) {
+ TimeId startSeconds,
+ bool hiddenDaysInput) {
using TimeField = Ui::TimePartWithPlaceholder;
const auto putNext = [](not_null field, QChar ch) {
field->setCursorPosition(0);
@@ -79,6 +80,10 @@ ChooseTimeResult ChooseTimeWidget(
const auto hour = Ui::MakeWeak(state->hour);
const auto minute = Ui::MakeWeak(state->minute);
+ if (hiddenDaysInput) {
+ day->setVisible(false);
+ }
+
day->setPhrase(tr::lng_days);
day->setMaxValue(31);
day->setWheelStep(1);
@@ -105,13 +110,16 @@ ChooseTimeResult ChooseTimeWidget(
content->sizeValue(
) | rpl::start_with_next([=](const QSize &s) {
- const auto inputWidth = s.width() / 3;
+ const auto inputWidth = s.width() / (hiddenDaysInput ? 2 : 3);
auto rect = QRect(
0,
(s.height() - day->height()) / 2,
inputWidth,
day->height());
for (const auto &input : { day, hour, minute }) {
+ if (input->isHidden()) {
+ continue;
+ }
input->setGeometry(rect - st::muteBoxTimeFieldPadding);
rect.translate(inputWidth, 0);
}
diff --git a/Telegram/SourceFiles/ui/boxes/choose_time.h b/Telegram/SourceFiles/ui/boxes/choose_time.h
index ca25710cf..d2f7f1ee7 100644
--- a/Telegram/SourceFiles/ui/boxes/choose_time.h
+++ b/Telegram/SourceFiles/ui/boxes/choose_time.h
@@ -20,6 +20,7 @@ struct ChooseTimeResult {
ChooseTimeResult ChooseTimeWidget(
not_null parent,
- TimeId startSeconds);
+ TimeId startSeconds,
+ bool hiddenDaysInput = false);
} // namespace Ui
diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style
index eb3f80bf1..19229f937 100644
--- a/Telegram/SourceFiles/ui/chat/chat.style
+++ b/Telegram/SourceFiles/ui/chat/chat.style
@@ -1244,3 +1244,4 @@ newPeerUserpics: GroupCallUserpics {
align: align(left);
}
newPeerUserpicsPadding: margins(0px, 3px, 0px, 0px);
+newPeerWidth: 320px;
diff --git a/Telegram/SourceFiles/ui/controls/send_button.cpp b/Telegram/SourceFiles/ui/controls/send_button.cpp
index 67c74b81f..14e8e1192 100644
--- a/Telegram/SourceFiles/ui/controls/send_button.cpp
+++ b/Telegram/SourceFiles/ui/controls/send_button.cpp
@@ -72,8 +72,8 @@ void SendButton::setState(State state) {
st::universalDuration);
setPointerCursor(_state.type != Type::Slowmode);
updateSize();
- update();
}
+ update();
}
void SendButton::finishAnimating() {
diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp
index f91148357..9e1249f6b 100644
--- a/Telegram/SourceFiles/window/window_session_controller.cpp
+++ b/Telegram/SourceFiles/window/window_session_controller.cpp
@@ -49,6 +49,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat_filters.h"
#include "data/data_replies_list.h"
#include "data/data_peer_values.h"
+#include "data/data_premium_limits.h"
#include "data/data_web_page.h"
#include "passport/passport_form_controller.h"
#include "chat_helpers/tabbed_selector.h"
@@ -3252,4 +3253,34 @@ SessionController::~SessionController() {
resetFakeUnreadWhileOpened();
}
+bool CheckAndJumpToNearChatsFilter(
+ not_null controller,
+ bool isNext,
+ bool jump) {
+ const auto id = controller->activeChatsFilterCurrent();
+ const auto session = &controller->session();
+ const auto list = &session->data().chatsFilters().list();
+ const auto index = int(ranges::find(
+ *list,
+ id,
+ &Data::ChatFilter::id
+ ) - begin(*list));
+ if (index == list->size() && id != 0) {
+ return false;
+ }
+ const auto changed = index + (isNext ? 1 : -1);
+ if (changed >= int(list->size()) || changed < 0) {
+ return false;
+ }
+ if (changed > Data::PremiumLimits(session).dialogFiltersCurrent()) {
+ return false;
+ }
+ if (jump) {
+ controller->setActiveChatsFilter((changed >= 0)
+ ? (*list)[changed].id()
+ : 0);
+ }
+ return true;
+}
+
} // namespace Window
diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h
index e4a53672e..afc847e3f 100644
--- a/Telegram/SourceFiles/window/window_session_controller.h
+++ b/Telegram/SourceFiles/window/window_session_controller.h
@@ -757,4 +757,9 @@ void ActivateWindow(not_null controller);
not_null controller,
GifPauseReason level);
+bool CheckAndJumpToNearChatsFilter(
+ not_null controller,
+ bool isNext,
+ bool jump);
+
} // namespace Window
diff --git a/Telegram/build/prepare/prepare.py b/Telegram/build/prepare/prepare.py
index b78a14b66..b9ffb8acd 100644
--- a/Telegram/build/prepare/prepare.py
+++ b/Telegram/build/prepare/prepare.py
@@ -1148,10 +1148,19 @@ depends:yasm/yasm
""")
stage('liblcms2', """
-mac:
git clone -b lcms2.16 https://github.com/mm2/Little-CMS.git liblcms2
cd liblcms2
-
+win:
+depends:python/Scripts/activate.bat
+ %THIRDPARTY_DIR%\\python\\Scripts\\activate.bat
+ meson setup --default-library=static --buildtype=debug -Db_vscrt=mtd out/Debug
+ meson compile -C out/Debug
+release:
+ meson setup --default-library=static --buildtype=release -Db_vscrt=mt out/Release
+ meson compile -C out/Release
+win:
+ deactivate
+mac:
buildOneArch() {
arch=$1
folder=`pwd`/$2
@@ -1689,6 +1698,7 @@ win:
SET OPENSSL_LIBS_DIR=%OPENSSL_DIR%\\out
SET ZLIB_LIBS_DIR=%LIBS_DIR%\\zlib
SET WEBP_DIR=%LIBS_DIR%\\libwebp
+ SET LCMS2_DIR=%LIBS_DIR%\\liblcms2
configure -prefix "%LIBS_DIR%\\Qt-%QT%" ^
%CONFIGURATIONS% ^
-force-debug-info ^
@@ -1726,7 +1736,10 @@ win:
-D WebP_mux_INCLUDE_DIR="%WEBP_DIR%\\src" ^
-D WebP_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webp.lib" ^
-D WebP_demux_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webpdemux.lib" ^
- -D WebP_mux_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webpmux.lib"
+ -D WebP_mux_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webpmux.lib" ^
+ -D LCMS2_FOUND=1 ^
+ -D LCMS2_INCLUDE_DIR="%LCMS2_DIR%\\include" ^
+ -D LCMS2_LIBRARIES="%LCMS2_DIR%\\out\Release\\src\\liblcms2.a"
cmake --build . --config Debug --parallel
cmake --install . --config Debug
diff --git a/Telegram/build/version b/Telegram/build/version
index eac8b2553..c1be45cdc 100644
--- a/Telegram/build/version
+++ b/Telegram/build/version
@@ -1,7 +1,7 @@
-AppVersion 5012001
+AppVersion 5012003
AppVersionStrMajor 5.12
-AppVersionStrSmall 5.12.1
-AppVersionStr 5.12.1
+AppVersionStrSmall 5.12.3
+AppVersionStr 5.12.3
BetaChannel 0
AlphaVersion 0
-AppVersionOriginal 5.12.1
+AppVersionOriginal 5.12.3
diff --git a/changelog.txt b/changelog.txt
index 9793a1e23..d3d5d42d0 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,13 @@
+5.12.3 (10.03.25)
+
+- Fix a couple more crashes.
+- Fix gift disappearing on unpin.
+- Fix country emoji for Fragment numbers.
+
+5.12.2 (09.03.25)
+
+- Fix some crashes.
+
5.12.1 (08.03.25)
- Fix a crash in some chat switchings.
diff --git a/cmake b/cmake
index 8c146a3ec..90e6d7310 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit 8c146a3ec6f4475e5083eee84d126960495a7e1d
+Subproject commit 90e6d73100a9fd2dc4c30a270c3bbc1d35924f32