Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a71c24f803 | ||
|
|
758ec52b91 | ||
|
|
96418bb9f1 | ||
|
|
f750d94b2d | ||
|
|
6eb9695e1e | ||
|
|
33bbad8053 | ||
|
|
3ea34461b2 | ||
|
|
b6a202b721 | ||
|
|
4d8cb022c5 | ||
|
|
3046318de5 | ||
|
|
c351598f13 | ||
|
|
02084be583 | ||
|
|
e117d08b2c | ||
|
|
58783170cd | ||
|
|
9ba2426c02 | ||
|
|
2cbaa7b03d | ||
|
|
836a0f3a73 | ||
|
|
e9977f551f | ||
|
|
78abe362cd | ||
|
|
47c2922d55 | ||
|
|
690f3fecbb | ||
|
|
d9242db7b3 | ||
|
|
a9b5e22b37 | ||
|
|
7b8f1704dc | ||
|
|
de88ddf42b |
@@ -1058,8 +1058,6 @@ PRIVATE
|
||||
info/profile/info_profile_members_controllers.h
|
||||
info/profile/info_profile_phone_menu.cpp
|
||||
info/profile/info_profile_phone_menu.h
|
||||
info/profile/info_profile_text.cpp
|
||||
info/profile/info_profile_text.h
|
||||
info/profile/info_profile_values.cpp
|
||||
info/profile/info_profile_values.h
|
||||
info/profile/info_profile_widget.cpp
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="6.2.2.0" />
|
||||
Version="6.2.4.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
||||
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 6,2,2,0
|
||||
PRODUCTVERSION 6,2,2,0
|
||||
FILEVERSION 6,2,4,0
|
||||
PRODUCTVERSION 6,2,4,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -62,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "6.2.2.0"
|
||||
VALUE "FileVersion", "6.2.4.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "6.2.2.0"
|
||||
VALUE "ProductVersion", "6.2.4.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 6,2,2,0
|
||||
PRODUCTVERSION 6,2,2,0
|
||||
FILEVERSION 6,2,4,0
|
||||
PRODUCTVERSION 6,2,4,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -53,10 +53,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "6.2.2.0"
|
||||
VALUE "FileVersion", "6.2.4.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "6.2.2.0"
|
||||
VALUE "ProductVersion", "6.2.4.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -449,25 +449,25 @@ void Controller::setupNotesField() {
|
||||
};
|
||||
const auto limitState = _notesField->lifetime().make_state<LimitState>();
|
||||
|
||||
const auto checkCharsLimitation = [=] {
|
||||
const auto checkCharsLimitation = [=, w = _notesField->window()] {
|
||||
const auto limit = Data::PremiumLimits(
|
||||
&_user->session()).contactNoteLengthCurrent();
|
||||
const auto remove = Ui::ComputeFieldCharacterCount(_notesField)
|
||||
- limit;
|
||||
if (!limitState->charsLimitation) {
|
||||
const auto border = _notesField->st().borderActive;
|
||||
limitState->charsLimitation = base::make_unique_q<Limit>(
|
||||
_box->verticalLayout(),
|
||||
emojiButton,
|
||||
style::al_top,
|
||||
QMargins{ 0, -st::lineWidth, 0, 0 });
|
||||
_notesField->heightValue(
|
||||
) | rpl::start_with_next([=](int height) {
|
||||
const auto &st = _notesField->st();
|
||||
const auto hasMultipleLines = height >
|
||||
(st.textMargins.top()
|
||||
+ st.style.font->height
|
||||
+ st.textMargins.bottom() * 2);
|
||||
limitState->charsLimitation->setVisible(hasMultipleLines);
|
||||
QMargins{ 0, -border - _notesField->st().border, 0, 0 });
|
||||
rpl::combine(
|
||||
limitState->charsLimitation->geometryValue(),
|
||||
_notesField->geometryValue()
|
||||
) | rpl::start_with_next([=](QRect limit, QRect field) {
|
||||
limitState->charsLimitation->setVisible(
|
||||
(w->mapToGlobal(limit.bottomLeft()).y() - border)
|
||||
< w->mapToGlobal(field.bottomLeft()).y());
|
||||
limitState->charsLimitation->raise();
|
||||
}, limitState->charsLimitation->lifetime());
|
||||
}
|
||||
@@ -484,7 +484,10 @@ void Controller::setupNotesField() {
|
||||
}
|
||||
|
||||
void Controller::setupPhotoButtons() {
|
||||
const auto iconSize = st::restoreUserpicIcon.size;
|
||||
if (!_user->isContact()) {
|
||||
return;
|
||||
}
|
||||
const auto iconPlaceholder = st::restoreUserpicIcon.size * 2;
|
||||
auto nameValue = _firstNameField
|
||||
? rpl::merge(
|
||||
rpl::single(_firstNameField->getLastText().trimmed()),
|
||||
@@ -515,7 +518,8 @@ void Controller::setupPhotoButtons() {
|
||||
.sessionWindow = base::make_weak(_window),
|
||||
}));
|
||||
});
|
||||
suggestBirthdayWrap->toggleOn(rpl::single(!_user->birthday().valid()));
|
||||
suggestBirthdayWrap->toggleOn(rpl::single(!_user->birthday().valid()
|
||||
&& !_user->starsPerMessageChecked()));
|
||||
|
||||
_suggestIcon = Ui::MakeAnimatedIcon({
|
||||
.generator = [] {
|
||||
@@ -524,7 +528,7 @@ void Controller::setupPhotoButtons() {
|
||||
QByteArray(),
|
||||
u":/animations/photo_suggest_icon.tgs"_q));
|
||||
},
|
||||
.sizeOverride = iconSize * style::DevicePixelRatio(),
|
||||
.sizeOverride = iconPlaceholder,
|
||||
.colorized = true,
|
||||
});
|
||||
|
||||
@@ -535,30 +539,36 @@ void Controller::setupPhotoButtons() {
|
||||
QByteArray(),
|
||||
u":/animations/camera_outline.tgs"_q));
|
||||
},
|
||||
.sizeOverride = iconSize * style::DevicePixelRatio(),
|
||||
.sizeOverride = iconPlaceholder,
|
||||
.colorized = true,
|
||||
});
|
||||
|
||||
const auto suggestButtonWrap = inner->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
inner,
|
||||
object_ptr<Ui::VerticalLayout>(inner)));
|
||||
suggestButtonWrap->toggleOn(
|
||||
rpl::single(!_user->starsPerMessageChecked()));
|
||||
|
||||
const auto suggestButton = Settings::AddButtonWithIcon(
|
||||
inner,
|
||||
suggestButtonWrap->entity(),
|
||||
tr::lng_suggest_photo_for(lt_user, rpl::duplicate(nameValue)),
|
||||
st::settingsButtonLight,
|
||||
{ nullptr });
|
||||
|
||||
_suggestIconWidget = Ui::CreateChild<Ui::RpWidget>(suggestButton);
|
||||
_suggestIconWidget->resize(iconSize * style::DevicePixelRatio());
|
||||
_suggestIconWidget->resize(iconPlaceholder);
|
||||
_suggestIconWidget->paintRequest() | rpl::start_with_next([=] {
|
||||
if (_suggestIcon && _suggestIcon->valid()) {
|
||||
auto p = QPainter(_suggestIconWidget);
|
||||
const auto frame = _suggestIcon->frame(st::lightButtonFg->c);
|
||||
const auto rect = _suggestIconWidget->rect();
|
||||
p.drawImage(rect, frame);
|
||||
p.drawImage(_suggestIconWidget->rect(), frame);
|
||||
}
|
||||
}, _suggestIconWidget->lifetime());
|
||||
|
||||
suggestButton->sizeValue() | rpl::start_with_next([=](QSize size) {
|
||||
_suggestIconWidget->move(
|
||||
st::settingsButtonLight.iconLeft - iconSize.width() / 2,
|
||||
st::settingsButtonLight.iconLeft - iconPlaceholder.width() / 4,
|
||||
(size.height() - _suggestIconWidget->height()) / 2);
|
||||
}, _suggestIconWidget->lifetime());
|
||||
|
||||
@@ -579,19 +589,18 @@ void Controller::setupPhotoButtons() {
|
||||
{ nullptr });
|
||||
|
||||
_cameraIconWidget = Ui::CreateChild<Ui::RpWidget>(setButton);
|
||||
_cameraIconWidget->resize(iconSize * style::DevicePixelRatio());
|
||||
_cameraIconWidget->resize(iconPlaceholder);
|
||||
_cameraIconWidget->paintRequest() | rpl::start_with_next([=] {
|
||||
if (_cameraIcon && _cameraIcon->valid()) {
|
||||
auto p = QPainter(_cameraIconWidget);
|
||||
const auto frame = _cameraIcon->frame(st::lightButtonFg->c);
|
||||
const auto rect = _cameraIconWidget->rect();
|
||||
p.drawImage(rect, frame);
|
||||
p.drawImage(_cameraIconWidget->rect(), frame);
|
||||
}
|
||||
}, _cameraIconWidget->lifetime());
|
||||
|
||||
setButton->sizeValue() | rpl::start_with_next([=](QSize size) {
|
||||
_cameraIconWidget->move(
|
||||
st::settingsButtonLight.iconLeft - iconSize.width() / 2,
|
||||
st::settingsButtonLight.iconLeft - iconPlaceholder.width() / 4,
|
||||
(size.height() - _cameraIconWidget->height()) / 2);
|
||||
}, _cameraIconWidget->lifetime());
|
||||
|
||||
@@ -634,7 +643,7 @@ void Controller::setupPhotoButtons() {
|
||||
resetButtonWrap->toggleOn(
|
||||
_user->session().changes().peerFlagsValue(
|
||||
_user,
|
||||
Data::PeerUpdate::Flag::FullInfo
|
||||
Data::PeerUpdate::Flag::FullInfo | Data::PeerUpdate::Flag::Photo
|
||||
) | rpl::map([=] {
|
||||
return _user->hasPersonalPhoto();
|
||||
}) | rpl::distinct_until_changed());
|
||||
@@ -645,8 +654,9 @@ void Controller::setupPhotoButtons() {
|
||||
tr::now,
|
||||
lt_user,
|
||||
_user->shortName()),
|
||||
.confirmed = [=] {
|
||||
.confirmed = [=](Fn<void()> close) {
|
||||
_window->session().api().peerPhoto().clearPersonal(_user);
|
||||
close();
|
||||
},
|
||||
.confirmText = tr::lng_profile_photo_reset(tr::now),
|
||||
}));
|
||||
@@ -810,11 +820,6 @@ void Controller::processChosenPhoto(QImage &&image, bool suggest) {
|
||||
Api::PeerPhoto::UserPhoto photo{
|
||||
.image = base::duplicate(image),
|
||||
};
|
||||
if (suggest && _suggestIcon && _suggestIcon->valid()) {
|
||||
_suggestIcon->animate([=] { _suggestIconWidget->update(); });
|
||||
} else if (!suggest && _cameraIcon && _cameraIcon->valid()) {
|
||||
_cameraIcon->animate([=] { _cameraIconWidget->update(); });
|
||||
}
|
||||
if (suggest) {
|
||||
_window->session().api().peerPhoto().suggest(_user, std::move(photo));
|
||||
_window->showPeerHistory(_user->id);
|
||||
@@ -831,11 +836,6 @@ void Controller::processChosenPhotoWithMarkup(
|
||||
.markupDocumentId = data.id,
|
||||
.markupColors = std::move(data.colors),
|
||||
};
|
||||
if (suggest && _suggestIcon && _suggestIcon->valid()) {
|
||||
_suggestIcon->animate([=] { _suggestIconWidget->update(); });
|
||||
} else if (!suggest && _cameraIcon && _cameraIcon->valid()) {
|
||||
_cameraIcon->animate([=] { _cameraIconWidget->update(); });
|
||||
}
|
||||
if (suggest) {
|
||||
_window->session().api().peerPhoto().suggest(_user, std::move(photo));
|
||||
_window->showPeerHistory(_user->id);
|
||||
|
||||
@@ -1734,7 +1734,8 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
||||
result,
|
||||
msgIds);
|
||||
const auto showRecentForwardsToSelf = result.size() == 1
|
||||
&& result.front()->peer()->isSelf();
|
||||
&& result.front()->peer()->isSelf()
|
||||
&& history->owner().session().premium();
|
||||
const auto requestType = Data::Histories::RequestType::Send;
|
||||
for (const auto thread : result) {
|
||||
if (!comment.text.isEmpty()) {
|
||||
|
||||
@@ -46,13 +46,9 @@ class Panel::Incoming::RendererGL final : public Ui::GL::Renderer {
|
||||
public:
|
||||
explicit RendererGL(not_null<Incoming*> owner);
|
||||
|
||||
void init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) override;
|
||||
void init(QOpenGLFunctions &f) override;
|
||||
|
||||
void deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) override;
|
||||
void deinit(QOpenGLFunctions *f) override;
|
||||
|
||||
void paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
@@ -100,7 +96,7 @@ public:
|
||||
explicit RendererSW(not_null<Incoming*> owner);
|
||||
|
||||
void paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override;
|
||||
|
||||
@@ -123,9 +119,7 @@ Panel::Incoming::RendererGL::RendererGL(not_null<Incoming*> owner)
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Panel::Incoming::RendererGL::init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
void Panel::Incoming::RendererGL::init(QOpenGLFunctions &f) {
|
||||
constexpr auto kQuads = 2;
|
||||
constexpr auto kQuadVertices = kQuads * 4;
|
||||
constexpr auto kQuadValues = kQuadVertices * 4;
|
||||
@@ -168,9 +162,7 @@ void Panel::Incoming::RendererGL::init(
|
||||
}));
|
||||
}
|
||||
|
||||
void Panel::Incoming::RendererGL::deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) {
|
||||
void Panel::Incoming::RendererGL::deinit(QOpenGLFunctions *f) {
|
||||
_textures.destroy(f);
|
||||
_imageProgram = std::nullopt;
|
||||
_texturedVertexShader = nullptr;
|
||||
@@ -437,7 +429,7 @@ Panel::Incoming::RendererSW::RendererSW(not_null<Incoming*> owner)
|
||||
}
|
||||
|
||||
void Panel::Incoming::RendererSW::paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) {
|
||||
const auto markGuard = gsl::finally([&] {
|
||||
|
||||
@@ -2483,7 +2483,8 @@ void Panel::updateButtonsGeometry() {
|
||||
}
|
||||
|
||||
const auto wideMenuShown = _call->canManage()
|
||||
|| _call->showChooseJoinAs();
|
||||
|| _call->showChooseJoinAs()
|
||||
|| (!rtmp && messagesEnabled); // Screen share there.
|
||||
toggle(_settings, !hidden && !wideMenuShown);
|
||||
toggle(_wideMenu, !hidden && wideMenuShown);
|
||||
|
||||
|
||||
@@ -312,9 +312,7 @@ Viewport::RendererGL::RendererGL(not_null<Viewport*> owner)
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Viewport::RendererGL::init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
void Viewport::RendererGL::init(QOpenGLFunctions &f) {
|
||||
_frameBuffer.emplace();
|
||||
_frameBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
|
||||
_frameBuffer->create();
|
||||
@@ -389,9 +387,7 @@ void Viewport::RendererGL::ensureARGB32Program() {
|
||||
}));
|
||||
}
|
||||
|
||||
void Viewport::RendererGL::deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) {
|
||||
void Viewport::RendererGL::deinit(QOpenGLFunctions *f) {
|
||||
_frameBuffer = std::nullopt;
|
||||
_frameVertexShader = nullptr;
|
||||
_imageProgram = std::nullopt;
|
||||
|
||||
@@ -28,13 +28,9 @@ class Viewport::RendererGL final : public Ui::GL::Renderer {
|
||||
public:
|
||||
explicit RendererGL(not_null<Viewport*> owner);
|
||||
|
||||
void init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) override;
|
||||
void init(QOpenGLFunctions &f) override;
|
||||
|
||||
void deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) override;
|
||||
void deinit(QOpenGLFunctions *f) override;
|
||||
|
||||
void paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
|
||||
@@ -37,7 +37,7 @@ Viewport::RendererSW::RendererSW(not_null<Viewport*> owner)
|
||||
}
|
||||
|
||||
void Viewport::RendererSW::paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) {
|
||||
auto bg = clip;
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
explicit RendererSW(not_null<Viewport*> owner);
|
||||
|
||||
void paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_download_manager.h"
|
||||
#include "base/battery_saving.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/invoke_queued.h"
|
||||
#include "base/concurrent_timer.h"
|
||||
#include "base/options.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
@@ -103,7 +104,6 @@ namespace {
|
||||
constexpr auto kQuitPreventTimeoutMs = crl::time(1500);
|
||||
constexpr auto kAutoLockTimeoutLateMs = crl::time(3000);
|
||||
constexpr auto kClearEmojiImageSourceTimeout = 10 * crl::time(1000);
|
||||
constexpr auto kFileOpenTimeoutMs = crl::time(1000);
|
||||
|
||||
LaunchState GlobalLaunchState/* = LaunchState::Running*/;
|
||||
|
||||
@@ -168,8 +168,7 @@ Application::Application()
|
||||
, _langCloudManager(std::make_unique<Lang::CloudManager>(langpack()))
|
||||
, _emojiKeywords(std::make_unique<ChatHelpers::EmojiKeywords>())
|
||||
, _tray(std::make_unique<Tray>())
|
||||
, _autoLockTimer([=] { checkAutoLock(); })
|
||||
, _fileOpenTimer([=] { checkFileOpen(); }) {
|
||||
, _autoLockTimer([=] { checkAutoLock(); }) {
|
||||
Ui::Integration::Set(&_private->uiIntegration);
|
||||
|
||||
_platformIntegration->init();
|
||||
@@ -693,9 +692,18 @@ bool Application::eventFilter(QObject *object, QEvent *e) {
|
||||
case QEvent::FileOpen: {
|
||||
if (object == QCoreApplication::instance()) {
|
||||
const auto event = static_cast<QFileOpenEvent*>(e);
|
||||
const auto flushQueued = [=] {
|
||||
if (_filesToOpen.isEmpty()) {
|
||||
InvokeQueued(this, [=] {
|
||||
cSetSendPaths(_filesToOpen);
|
||||
_filesToOpen.clear();
|
||||
checkSendPaths();
|
||||
});
|
||||
}
|
||||
};
|
||||
if (const auto file = event->file(); !file.isEmpty()) {
|
||||
flushQueued();
|
||||
_filesToOpen.append(file);
|
||||
_fileOpenTimer.callOnce(kFileOpenTimeoutMs);
|
||||
} else if (event->url().scheme() == u"tg"_q
|
||||
|| event->url().scheme() == u"tonsite"_q) {
|
||||
const auto url = QString::fromUtf8(
|
||||
@@ -707,8 +715,8 @@ bool Application::eventFilter(QObject *object, QEvent *e) {
|
||||
_lastActivePrimaryWindow->activate();
|
||||
}
|
||||
} else if (event->url().scheme() == u"interpret"_q) {
|
||||
flushQueued();
|
||||
_filesToOpen.append(event->url().toString());
|
||||
_fileOpenTimer.callOnce(kFileOpenTimeoutMs);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -1081,12 +1089,6 @@ bool Application::canApplyLangPackWithoutRestart() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::checkFileOpen() {
|
||||
cSetSendPaths(_filesToOpen);
|
||||
_filesToOpen.clear();
|
||||
checkSendPaths();
|
||||
}
|
||||
|
||||
void Application::checkSendPaths() {
|
||||
if (!cSendPaths().isEmpty()
|
||||
&& _lastActivePrimaryWindow
|
||||
|
||||
@@ -272,7 +272,6 @@ public:
|
||||
// Internal links.
|
||||
void checkStartUrl();
|
||||
void checkSendPaths();
|
||||
void checkFileOpen();
|
||||
bool openLocalUrl(const QString &url, QVariant context);
|
||||
bool openInternalUrl(const QString &url, QVariant context);
|
||||
[[nodiscard]] QString changelogLink() const;
|
||||
@@ -452,7 +451,6 @@ private:
|
||||
base::Timer _autoLockTimer;
|
||||
|
||||
QStringList _filesToOpen;
|
||||
base::Timer _fileOpenTimer;
|
||||
|
||||
std::optional<base::Timer> _saveSettingsTimer;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
|
||||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||
constexpr auto AppName = "Telegram Desktop"_cs;
|
||||
constexpr auto AppFile = "Telegram"_cs;
|
||||
constexpr auto AppVersion = 6002002;
|
||||
constexpr auto AppVersionStr = "6.2.2";
|
||||
constexpr auto AppVersion = 6002004;
|
||||
constexpr auto AppVersionStr = "6.2.4";
|
||||
constexpr auto AppBetaVersion = false;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
||||
@@ -23,9 +23,7 @@ class SendActionManager final {
|
||||
public:
|
||||
struct AnimationUpdate {
|
||||
not_null<Thread*> thread;
|
||||
int left = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
QRect rect;
|
||||
bool textUpdated = false;
|
||||
};
|
||||
explicit SendActionManager();
|
||||
|
||||
@@ -458,7 +458,7 @@ void Entry::updateChatListEntryHeight() {
|
||||
session().changes().entryUpdated(this, Data::EntryUpdate::Flag::Height);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Entry::hasChatsFilterTags(FilterId exclude) const {
|
||||
bool Entry::hasChatsFilterTags(FilterId exclude) const {
|
||||
if (!owner().chatsFilters().tagsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -336,10 +336,9 @@ InnerWidget::InnerWidget(
|
||||
) | rpl::start_with_next([=](
|
||||
const Data::SendActionManager::AnimationUpdate &update) {
|
||||
const auto updateRect = Ui::RowPainter::SendActionAnimationRect(
|
||||
_st,
|
||||
update.left,
|
||||
update.width,
|
||||
update.height,
|
||||
update.thread,
|
||||
_filterId,
|
||||
update.rect,
|
||||
width(),
|
||||
update.textUpdated);
|
||||
updateDialogRow(
|
||||
@@ -374,9 +373,6 @@ InnerWidget::InnerWidget(
|
||||
) | rpl::start_with_next([=](bool refreshHeight) {
|
||||
if (refreshHeight) {
|
||||
_chatsFilterTags.clear();
|
||||
}
|
||||
if (refreshHeight && _filterId) {
|
||||
// Height of the main list will be refreshed in other way.
|
||||
_shownList->updateHeights(_narrowRatio);
|
||||
}
|
||||
refreshWithCollapsedRows();
|
||||
|
||||
@@ -317,31 +317,32 @@ Row::~Row() {
|
||||
clearTopicJumpRipple();
|
||||
}
|
||||
|
||||
void Row::recountHeight(float64 narrowRatio, FilterId filterId) {
|
||||
if (const auto history = _id.history()) {
|
||||
const auto hasTags = _id.entry()->hasChatsFilterTags(filterId);
|
||||
const style::DialogRow &Row::ComputeSt(
|
||||
not_null<const Entry*> entry,
|
||||
FilterId filterId) {
|
||||
if (const auto history = entry->asHistory()) {
|
||||
const auto hasTags = entry->hasChatsFilterTags(filterId);
|
||||
const auto wideRow = history->isForum()
|
||||
|| history->amMonoforumAdmin();
|
||||
_height = wideRow
|
||||
? anim::interpolate(
|
||||
hasTags
|
||||
? st::taggedForumDialogRow.height
|
||||
: st::forumDialogRow.height,
|
||||
st::defaultDialogRow.height,
|
||||
narrowRatio)
|
||||
return wideRow
|
||||
? (hasTags ? st::taggedForumDialogRow : st::forumDialogRow)
|
||||
: hasTags
|
||||
? anim::interpolate(
|
||||
st::taggedDialogRow.height,
|
||||
st::defaultDialogRow.height,
|
||||
narrowRatio)
|
||||
: st::defaultDialogRow.height;
|
||||
} else if (_id.folder()) {
|
||||
_height = st::defaultDialogRow.height;
|
||||
} else if (_id.topic()) {
|
||||
_height = st::forumTopicRow.height;
|
||||
} else {
|
||||
_height = st::defaultDialogRow.height;
|
||||
? st::taggedDialogRow
|
||||
: st::defaultDialogRow;
|
||||
} else if (entry->asTopic()) {
|
||||
return st::forumTopicRow;
|
||||
}
|
||||
return st::defaultDialogRow;
|
||||
}
|
||||
|
||||
void Row::recountHeight(float64 narrowRatio, FilterId filterId) {
|
||||
const auto &st = ComputeSt(_id.entry(), filterId);
|
||||
_height = ((&st == &st::defaultDialogRow) || !_id.history())
|
||||
? st::defaultDialogRow.height
|
||||
: anim::interpolate(
|
||||
st.height,
|
||||
st::defaultDialogRow.height,
|
||||
narrowRatio);
|
||||
}
|
||||
|
||||
uint64 Row::sortKey(FilterId filterId) const {
|
||||
|
||||
@@ -87,6 +87,10 @@ public:
|
||||
Row(Key key, int index, int top);
|
||||
~Row();
|
||||
|
||||
[[nodiscard]] static const style::DialogRow &ComputeSt(
|
||||
not_null<const Entry*> entry,
|
||||
FilterId filterId);
|
||||
|
||||
[[nodiscard]] int top() const {
|
||||
return _top;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_saved_sublist.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_thread.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "dialogs/dialogs_list.h"
|
||||
@@ -1198,20 +1199,20 @@ void RowPainter::Paint(
|
||||
}
|
||||
|
||||
QRect RowPainter::SendActionAnimationRect(
|
||||
not_null<const style::DialogRow*> st,
|
||||
int animationLeft,
|
||||
int animationWidth,
|
||||
int animationHeight,
|
||||
not_null<const Data::Thread*> thread,
|
||||
FilterId filterId,
|
||||
QRect rect,
|
||||
int fullWidth,
|
||||
bool textUpdated) {
|
||||
const auto nameleft = st->nameLeft;
|
||||
const auto namewidth = fullWidth - nameleft - st->padding.right();
|
||||
const auto texttop = st->textTop;
|
||||
const auto &st = Row::ComputeSt(thread, filterId);
|
||||
const auto nameleft = st.nameLeft;
|
||||
const auto namewidth = fullWidth - nameleft - st.padding.right();
|
||||
const auto texttop = st.textTop;
|
||||
return QRect(
|
||||
nameleft + (textUpdated ? 0 : animationLeft),
|
||||
texttop,
|
||||
textUpdated ? namewidth : animationWidth,
|
||||
animationHeight);
|
||||
nameleft + (textUpdated ? 0 : rect.x()),
|
||||
texttop + rect.y(),
|
||||
textUpdated ? namewidth : rect.width(),
|
||||
rect.height());
|
||||
}
|
||||
|
||||
void PaintCollapsedRow(
|
||||
|
||||
@@ -22,6 +22,7 @@ extern const style::DialogRow &defaultDialogRow;
|
||||
namespace Data {
|
||||
class Forum;
|
||||
class Folder;
|
||||
class Thread;
|
||||
} // namespace Data
|
||||
|
||||
namespace Dialogs {
|
||||
@@ -95,10 +96,9 @@ public:
|
||||
not_null<const FakeRow*> row,
|
||||
const PaintContext &context);
|
||||
static QRect SendActionAnimationRect(
|
||||
not_null<const style::DialogRow*> st,
|
||||
int animationLeft,
|
||||
int animationWidth,
|
||||
int animationHeight,
|
||||
not_null<const Data::Thread*> thread,
|
||||
FilterId filterId,
|
||||
QRect rect,
|
||||
int fullWidth,
|
||||
bool textUpdated);
|
||||
};
|
||||
|
||||
@@ -7148,6 +7148,11 @@ void HistoryWidget::startItemRevealAnimations() {
|
||||
|
||||
void HistoryWidget::startMessageSendingAnimation(
|
||||
not_null<HistoryItem*> item) {
|
||||
if (_list->elementChatMode() == HistoryView::ElementChatMode::Default
|
||||
&& width() > st::columnMaximalWidthLeft
|
||||
&& !item->media()) {
|
||||
return;
|
||||
}
|
||||
auto &sendingAnimation = controller()->sendingAnimation();
|
||||
if (!sendingAnimation.checkExpectedType(item)) {
|
||||
return;
|
||||
|
||||
@@ -76,6 +76,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_window.h" // columnMaximalWidthLeft
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtCore/QMimeData>
|
||||
@@ -2019,6 +2020,11 @@ void ListWidget::startItemRevealAnimations() {
|
||||
|
||||
void ListWidget::startMessageSendingAnimation(
|
||||
not_null<HistoryItem*> item) {
|
||||
if (elementChatMode() == HistoryView::ElementChatMode::Default
|
||||
&& width() > st::columnMaximalWidthLeft
|
||||
&& !item->media()) {
|
||||
return;
|
||||
}
|
||||
const auto sendingAnimation = _delegate->listSendingAnimation();
|
||||
if (!sendingAnimation || !sendingAnimation->checkExpectedType(item)) {
|
||||
return;
|
||||
|
||||
@@ -903,10 +903,12 @@ void Reply::paint(
|
||||
if (namew > 0) {
|
||||
p.setPen(!inBubble
|
||||
? st->msgImgReplyBarColor()->c
|
||||
: FromNameFg(
|
||||
: (colorCollectible || colorIndexPlusOne)
|
||||
? FromNameFg(
|
||||
context,
|
||||
colorIndexPlusOne - 1,
|
||||
colorCollectible));
|
||||
colorCollectible)
|
||||
: stm->msgServiceFg->c);
|
||||
_name.drawLeftElided(
|
||||
p,
|
||||
x + st::historyReplyPadding.left() + previewSkip,
|
||||
|
||||
@@ -387,14 +387,17 @@ bool SendActionPainter::updateNeedsAnimating(crl::time now, bool force) {
|
||||
if (force
|
||||
|| sendActionChanged
|
||||
|| (sendActionResult && !anim::Disabled())) {
|
||||
const auto height = std::max(
|
||||
st::normalFont->height,
|
||||
st::dialogsMiniPreviewTop + st::dialogsMiniPreview);
|
||||
const auto left = 0;
|
||||
const auto top = Ui::Emoji::GetCustomSkipNormal();
|
||||
const auto width = _sendActionAnimation.width() + _animationLeft;
|
||||
const auto height = std::max({
|
||||
st::normalFont->height - top,
|
||||
st::dialogsMiniPreviewTop + st::dialogsMiniPreview - top,
|
||||
Ui::Emoji::GetCustomSizeNormal(),
|
||||
});
|
||||
_history->peer->owner().sendActionManager().updateAnimation({
|
||||
_topic ? ((Data::Thread*)_topic) : _history,
|
||||
0,
|
||||
_sendActionAnimation.width() + _animationLeft,
|
||||
height,
|
||||
{ left, top, width, height },
|
||||
(force || sendActionChanged)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -766,7 +766,8 @@ void DeleteContactNote(
|
||||
std::move(
|
||||
notesText
|
||||
) | rpl::start_with_next([=, raw = notesLine.text](
|
||||
const TextWithEntities ¬e) {
|
||||
TextWithEntities note) {
|
||||
TextUtilities::ParseEntities(note, TextParseLinks);
|
||||
raw->setMarkedText(note, context);
|
||||
}, notesLine.text->lifetime());
|
||||
|
||||
|
||||
@@ -43,6 +43,11 @@ MusicProvider::MusicProvider(not_null<AbstractController*> controller)
|
||||
: _controller(controller)
|
||||
, _peer(controller->key().musicPeer())
|
||||
, _history(_peer->owner().history(_peer)) {
|
||||
_controller->session().data().itemRemoved(
|
||||
) | rpl::start_with_next([this](auto item) {
|
||||
itemRemoved(item);
|
||||
}, _lifetime);
|
||||
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
for (auto &layout : _layouts) {
|
||||
@@ -214,6 +219,13 @@ std::vector<ListSection> MusicProvider::fillSections(
|
||||
return result;
|
||||
}
|
||||
|
||||
void MusicProvider::itemRemoved(not_null<const HistoryItem*> item) {
|
||||
if (const auto i = _layouts.find(item); i != end(_layouts)) {
|
||||
_layoutRemoved.fire(i->second.item.get());
|
||||
_layouts.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void MusicProvider::markLayoutsStale() {
|
||||
for (auto &layout : _layouts) {
|
||||
layout.second.stale = true;
|
||||
|
||||
@@ -96,6 +96,7 @@ private:
|
||||
not_null<const Media::BaseLayout*> item,
|
||||
not_null<const Media::BaseLayout*> previous) override;
|
||||
|
||||
void itemRemoved(not_null<const HistoryItem*> item);
|
||||
void markLayoutsStale();
|
||||
void clearStaleLayouts();
|
||||
void clear();
|
||||
@@ -115,7 +116,9 @@ private:
|
||||
int _idsLimit = kMinimalIdsLimit;
|
||||
Data::SavedMusicSlice _slice;
|
||||
|
||||
std::unordered_map<not_null<HistoryItem*>, Media::CachedItem> _layouts;
|
||||
std::unordered_map<
|
||||
not_null<const HistoryItem*>,
|
||||
Media::CachedItem> _layouts;
|
||||
rpl::event_stream<not_null<Media::BaseLayout*>> _layoutRemoved;
|
||||
rpl::event_stream<> _refreshed;
|
||||
|
||||
|
||||
@@ -137,9 +137,7 @@ OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
|
||||
});
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
void OverlayWidget::RendererGL::init(QOpenGLFunctions &f) {
|
||||
constexpr auto kQuads = 9;
|
||||
constexpr auto kQuadVertices = kQuads * 4;
|
||||
constexpr auto kQuadValues = kQuadVertices * 4;
|
||||
@@ -243,9 +241,7 @@ void OverlayWidget::RendererGL::init(
|
||||
renderer ? renderer : "[nullptr]");
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) {
|
||||
void OverlayWidget::RendererGL::deinit(QOpenGLFunctions *f) {
|
||||
_textures.destroy(f);
|
||||
_imageProgram = std::nullopt;
|
||||
_texturedVertexShader = nullptr;
|
||||
|
||||
@@ -21,13 +21,9 @@ class OverlayWidget::RendererGL final
|
||||
public:
|
||||
explicit RendererGL(not_null<OverlayWidget*> owner);
|
||||
|
||||
void init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) override;
|
||||
void init(QOpenGLFunctions &f) override;
|
||||
|
||||
void deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) override;
|
||||
void deinit(QOpenGLFunctions *f) override;
|
||||
|
||||
void paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
|
||||
@@ -27,7 +27,7 @@ bool OverlayWidget::RendererSW::handleHideWorkaround() {
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) {
|
||||
if (handleHideWorkaround()) {
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
explicit RendererSW(not_null<OverlayWidget*> owner);
|
||||
|
||||
void paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override;
|
||||
|
||||
|
||||
@@ -156,9 +156,7 @@ Pip::RendererGL::RendererGL(not_null<Pip*> owner)
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Pip::RendererGL::init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) {
|
||||
void Pip::RendererGL::init(QOpenGLFunctions &f) {
|
||||
constexpr auto kQuads = 8;
|
||||
constexpr auto kQuadVertices = kQuads * 4;
|
||||
constexpr auto kQuadValues = kQuadVertices * 4;
|
||||
@@ -233,9 +231,7 @@ void Pip::RendererGL::init(
|
||||
createShadowTexture();
|
||||
}
|
||||
|
||||
void Pip::RendererGL::deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) {
|
||||
void Pip::RendererGL::deinit(QOpenGLFunctions *f) {
|
||||
_textures.destroy(f);
|
||||
_imageProgram = std::nullopt;
|
||||
_texturedVertexShader = nullptr;
|
||||
|
||||
@@ -19,13 +19,9 @@ class Pip::RendererGL final : public Pip::Renderer {
|
||||
public:
|
||||
explicit RendererGL(not_null<Pip*> owner);
|
||||
|
||||
void init(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions &f) override;
|
||||
void init(QOpenGLFunctions &f) override;
|
||||
|
||||
void deinit(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
QOpenGLFunctions *f) override;
|
||||
void deinit(QOpenGLFunctions *f) override;
|
||||
|
||||
void paint(
|
||||
not_null<QOpenGLWidget*> widget,
|
||||
|
||||
@@ -70,7 +70,7 @@ Pip::RendererSW::RendererSW(not_null<Pip*> owner)
|
||||
}
|
||||
|
||||
void Pip::RendererSW::paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) {
|
||||
_p = &p;
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
explicit RendererSW(not_null<Pip*> owner);
|
||||
|
||||
void paintFallback(
|
||||
Painter &&p,
|
||||
Painter &p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override;
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ paymentsToProviderLabel: paymentsShippingPrice;
|
||||
paymentsToProviderPadding: margins(28px, 6px, 28px, 6px);
|
||||
|
||||
paymentsCriticalError: FlatLabel(boxLabel) {
|
||||
minWidth: 370px;
|
||||
minWidth: 340px;
|
||||
align: align(top);
|
||||
textFg: windowSubTextFg;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/power_saving.h"
|
||||
#include "ui/text/text_isolated_emoji.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_chat.h"
|
||||
@@ -144,7 +145,8 @@ Content::Content(
|
||||
const auto resultTo = _isText
|
||||
? _to + innerGeometry.topLeft()
|
||||
: _to + innerGeometry.topLeft() + _innerContentRect.topLeft();
|
||||
const auto x = anim::interpolate(resultFrom.x(), resultTo.x(), value);
|
||||
const auto xEase = anim::easeOutQuint(1.0, value);
|
||||
const auto x = anim::interpolate(resultFrom.x(), resultTo.x(), xEase);
|
||||
const auto y = anim::interpolate(resultFrom.y(), resultTo.y(), value);
|
||||
if (!_isText) {
|
||||
// Text-only messages are drawing only in _bubble.widget.
|
||||
@@ -358,6 +360,7 @@ void Content::createBubble() {
|
||||
(currentView->hasOutLayout() ? tailWidth : 0)
|
||||
+ (_isText && currentView->data()->isPost()
|
||||
? rect::m::sum::h(st::msgPadding)
|
||||
+ st::historyFastShareSize
|
||||
: 0),
|
||||
(hasCommentsButton || _isText) ? innerGeometry.y() : 0));
|
||||
_bubble.widget->show();
|
||||
@@ -365,8 +368,8 @@ void Content::createBubble() {
|
||||
_bubble.widget->stackUnder(this);
|
||||
|
||||
_bubble.widget->paintRequest(
|
||||
) | rpl::start_with_next([=](const QRect &r) {
|
||||
Painter p(_bubble.widget);
|
||||
) | rpl::start_with_next([=, raw = _bubble.widget.get()](const QRect &r) {
|
||||
auto p = Painter(raw);
|
||||
|
||||
p.fillRect(r, Qt::transparent);
|
||||
|
||||
@@ -393,7 +396,15 @@ void Content::createBubble() {
|
||||
context.skipDrawingParts = Context::SkipDrawingParts::Content;
|
||||
context.outbg = currentView->hasOutLayout();
|
||||
|
||||
context.translate(paintOffsetLeft, -context.viewport.y());
|
||||
const auto diff = context.viewport.height() - raw->height();
|
||||
auto bottom = anim::interpolate(_from.y(), _to.y(), progress);
|
||||
if (bottom > diff) {
|
||||
bottom = diff;
|
||||
}
|
||||
if (bottom < raw->height()) {
|
||||
bottom = raw->height();
|
||||
}
|
||||
context.translate(paintOffsetLeft, -context.viewport.y() - bottom);
|
||||
p.translate(-paintOffsetLeft, 0);
|
||||
|
||||
currentView->draw(p, context);
|
||||
@@ -438,7 +449,8 @@ void MessageSendingAnimationController::appendSending(
|
||||
}
|
||||
|
||||
void MessageSendingAnimationController::startAnimation(SendingInfoTo &&to) {
|
||||
if (anim::Disabled()) {
|
||||
if (anim::Disabled()
|
||||
|| PowerSaving::On(PowerSaving::Flag::kChatEffects)) {
|
||||
return;
|
||||
}
|
||||
const auto container = _controller->content();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
AppVersion 6002002
|
||||
AppVersion 6002004
|
||||
AppVersionStrMajor 6.2
|
||||
AppVersionStrSmall 6.2.2
|
||||
AppVersionStr 6.2.2
|
||||
AppVersionStrSmall 6.2.4
|
||||
AppVersionStr 6.2.4
|
||||
BetaChannel 0
|
||||
AlphaVersion 0
|
||||
AppVersionOriginal 6.2.2
|
||||
AppVersionOriginal 6.2.4
|
||||
|
||||
@@ -148,6 +148,8 @@ PRIVATE
|
||||
info/profile/info_profile_icon.h
|
||||
info/profile/info_profile_music_button.cpp
|
||||
info/profile/info_profile_music_button.h
|
||||
info/profile/info_profile_text.cpp
|
||||
info/profile/info_profile_text.h
|
||||
info/userpic/info_userpic_bubble_wrap.cpp
|
||||
info/userpic/info_userpic_bubble_wrap.h
|
||||
info/userpic/info_userpic_color_circle_button.cpp
|
||||
|
||||
Submodule Telegram/codegen updated: 7576bcd417...9bb72708a7
Submodule Telegram/lib_base updated: 42b01c4726...5266793487
Submodule Telegram/lib_ui updated: ba1417299f...bfbb6e0f9b
@@ -1,3 +1,19 @@
|
||||
6.2.4 (22.10.25)
|
||||
|
||||
- Highlight links in contact notes.
|
||||
- Show menu with screen share controls in wide group call mode.
|
||||
- Fix possible crash in saved music removing.
|
||||
- Fix crash in theme editor.
|
||||
|
||||
6.2.3 (12.10.25)
|
||||
|
||||
- Fix crash when viewing messages with hidden senders.
|
||||
- Fix possible crash when editing contacts.
|
||||
- Fix layout of character count warning in contact notes.
|
||||
- Fix icons when editing contacts.
|
||||
- Fix color of sending messages animation in complex themes.
|
||||
- Fix crash in chat open on Flatpak build.
|
||||
|
||||
6.2.2 (10.10.25)
|
||||
|
||||
- Fix layer.
|
||||
|
||||
Reference in New Issue
Block a user