Merge remote-tracking branch 'tdesktop/dev' into dev

This commit is contained in:
Eric Kotato 2020-05-13 00:49:52 +03:00
commit 9e0e5b8f66
76 changed files with 1133 additions and 779 deletions

View file

@ -418,8 +418,8 @@ jobs:
git clone -b v5.12.8 --depth=1 git://code.qt.io/qt/qt5.git qt_${QT} git clone -b v5.12.8 --depth=1 git://code.qt.io/qt/qt5.git qt_${QT}
cd qt_${QT} cd qt_${QT}
perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg,qtx11extras
git submodule update qtbase qtwayland qtimageformats qtsvg git submodule update qtbase qtwayland qtimageformats qtsvg qtx11extras
cd qtbase cd qtbase
git apply ../../patches/qtbase_${QT}.diff git apply ../../patches/qtbase_${QT}.diff
cd ../ cd ../

View file

@ -12,9 +12,17 @@ jobs:
to_branch: "master" to_branch: "master"
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
if: env.SKIP == '0'
- name: Push the code to the master branch. - name: Push the code to the master branch.
if: env.SKIP == '0'
run: | run: |
url=https://x-access-token:${{ secrets.WORKFLOW_TOKEN }}@github.com/$GITHUB_REPOSITORY token=${{ secrets.WORKFLOW_TOKEN }}
if [ -z "${token}" ]; then
echo "Token is unset. Nothing to do."
exit 0
fi
url=https://x-access-token:$token@github.com/$GITHUB_REPOSITORY
latest_tag=$(git describe --tags --abbrev=0) latest_tag=$(git describe --tags --abbrev=0)
echo "Latest tag: $latest_tag" echo "Latest tag: $latest_tag"

3
.gitmodules vendored
View file

@ -91,3 +91,6 @@
[submodule "Telegram/ThirdParty/libqtxdg"] [submodule "Telegram/ThirdParty/libqtxdg"]
path = Telegram/ThirdParty/libqtxdg path = Telegram/ThirdParty/libqtxdg
url = https://github.com/lxqt/libqtxdg.git url = https://github.com/lxqt/libqtxdg.git
[submodule "Telegram/ThirdParty/fcitx5-qt"]
path = Telegram/ThirdParty/fcitx5-qt
url = https://github.com/fcitx/fcitx5-qt.git

View file

@ -90,7 +90,7 @@ if (LINUX)
PRIVATE PRIVATE
desktop-app::external_statusnotifieritem desktop-app::external_statusnotifieritem
desktop-app::external_dbusmenu_qt desktop-app::external_dbusmenu_qt
desktop-app::external_fcitx_qt5 desktop-app::external_fcitx5_qt5
desktop-app::external_hime_qt desktop-app::external_hime_qt
) )
endif() endif()
@ -138,7 +138,7 @@ endif()
if (DESKTOP_APP_USE_PACKAGED) if (DESKTOP_APP_USE_PACKAGED)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads) find_package(Threads REQUIRED)
target_link_libraries(Telegram target_link_libraries(Telegram
PRIVATE PRIVATE
@ -1232,6 +1232,10 @@ if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR NOT LINUX) AND NOT build_macstore AND
set_target_properties(Updater PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder}) set_target_properties(Updater PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
if (WIN32 AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_link_options(Updater PRIVATE -municode)
endif()
if (LINUX) if (LINUX)
target_link_options(Updater PRIVATE -static-libstdc++) target_link_options(Updater PRIVATE -static-libstdc++)
endif() endif()

View file

@ -300,6 +300,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_notifications_position" = "Location on the screen"; "lng_settings_notifications_position" = "Location on the screen";
"lng_settings_notifications_count" = "Notifications count"; "lng_settings_notifications_count" = "Notifications count";
"lng_settings_sound_notify" = "Play sound"; "lng_settings_sound_notify" = "Play sound";
"lng_settings_alert_windows" = "Flash the taskbar icon";
"lng_settings_alert_mac" = "Bounce the dock icon";
"lng_settings_alert_linux" = "Draw attention to the window";
"lng_settings_badge_title" = "Badge counter"; "lng_settings_badge_title" = "Badge counter";
"lng_settings_include_muted" = "Include muted chats in unread count"; "lng_settings_include_muted" = "Include muted chats in unread count";
"lng_settings_count_unread" = "Count unread messages"; "lng_settings_count_unread" = "Count unread messages";

View file

@ -6,7 +6,18 @@
// //
// Generated from the TEXTINCLUDE 2 resource. // Generated from the TEXTINCLUDE 2 resource.
// //
#include "winres.h" #if defined(__MINGW64__) || defined(__MINGW32__)
// MinGW-w64, MinGW
#if defined(__has_include) && __has_include(<winres.h>)
#include <winres.h>
#else
#include <afxres.h>
#include <winresrc.h>
#endif
#else
// MSVC, Windows SDK
#include <winres.h>
#endif
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS

View file

@ -6,7 +6,18 @@
// //
// Generated from the TEXTINCLUDE 2 resource. // Generated from the TEXTINCLUDE 2 resource.
// //
#include "winres.h" #if defined(__MINGW64__) || defined(__MINGW32__)
// MinGW-w64, MinGW
#if defined(__has_include) && __has_include(<winres.h>)
#include <winres.h>
#else
#include <afxres.h>
#include <winresrc.h>
#endif
#else
// MSVC, Windows SDK
#include <winres.h>
#endif
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS

View file

@ -268,7 +268,7 @@ int main(int argc, char *argv[])
cout << "Compression start, size: " << resultSize << "\n"; cout << "Compression start, size: " << resultSize << "\n";
QByteArray compressed, resultCheck; QByteArray compressed, resultCheck;
#ifdef Q_OS_WIN // use Lzma SDK for win #if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size

View file

@ -27,7 +27,7 @@ extern "C" {
#include <openssl/evp.h> #include <openssl/evp.h>
} // extern "C" } // extern "C"
#ifdef Q_OS_WIN // use Lzma SDK for win #if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
#include <LzmaLib.h> #include <LzmaLib.h>
#else #else
#include <lzma.h> #include <lzma.h>

View file

@ -83,7 +83,7 @@ private:
void show(anim::type animated); void show(anim::type animated);
void destroy(FnMut<void()> done); void destroy(FnMut<void()> done);
[[nodisacrd]] bool hasShadow() const; [[nodiscard]] bool hasShadow() const;
void createShadow(); void createShadow();
void destroyShadow(); void destroyShadow();

View file

@ -463,6 +463,8 @@ void Panel::toggleOpacityAnimation(bool visible) {
_visible ? 1. : 0., _visible ? 1. : 0.,
st::callPanelDuration, st::callPanelDuration,
_visible ? anim::easeOutCirc : anim::easeInCirc); _visible ? anim::easeOutCirc : anim::easeInCirc);
} else if (!isHidden() && !_visible) {
hide();
} }
if (isHidden() && _visible) { if (isHidden() && _visible) {
show(); show();

View file

@ -20,9 +20,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "main/main_session.h"
#include "chat_helpers/stickers.h" #include "chat_helpers/stickers.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "window/window_session_controller.h"
#include "facades.h" #include "facades.h"
#include "app.h" #include "app.h"
#include "styles/style_history.h" #include "styles/style_history.h"
@ -33,14 +33,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
FieldAutocomplete::FieldAutocomplete( FieldAutocomplete::FieldAutocomplete(
QWidget *parent, QWidget *parent,
not_null<Main::Session*> session) not_null<Window::SessionController*> controller)
: RpWidget(parent) : RpWidget(parent)
, _session(session) , _controller(controller)
, _scroll(this, st::mentionScroll) { , _scroll(this, st::mentionScroll) {
_scroll->setGeometry(rect()); _scroll->setGeometry(rect());
_inner = _scroll->setOwnedWidget( _inner = _scroll->setOwnedWidget(
object_ptr<internal::FieldAutocompleteInner>( object_ptr<internal::FieldAutocompleteInner>(
_controller,
this, this,
&_mrows, &_mrows,
&_hrows, &_hrows,
@ -169,7 +170,7 @@ inline int indexOfInFirstN(const T &v, const U &elem, int last) {
internal::StickerRows FieldAutocomplete::getStickerSuggestions() { internal::StickerRows FieldAutocomplete::getStickerSuggestions() {
const auto list = Stickers::GetListByEmoji( const auto list = Stickers::GetListByEmoji(
_session, &_controller->session(),
_emoji, _emoji,
_stickersSeed _stickersSeed
); );
@ -588,12 +589,14 @@ bool FieldAutocomplete::eventFilter(QObject *obj, QEvent *e) {
namespace internal { namespace internal {
FieldAutocompleteInner::FieldAutocompleteInner( FieldAutocompleteInner::FieldAutocompleteInner(
not_null<Window::SessionController*> controller,
not_null<FieldAutocomplete*> parent, not_null<FieldAutocomplete*> parent,
not_null<MentionRows*> mrows, not_null<MentionRows*> mrows,
not_null<HashtagRows*> hrows, not_null<HashtagRows*> hrows,
not_null<BotCommandRows*> brows, not_null<BotCommandRows*> brows,
not_null<StickerRows*> srows) not_null<StickerRows*> srows)
: _parent(parent) : _controller(controller)
, _parent(parent)
, _mrows(mrows) , _mrows(mrows)
, _hrows(hrows) , _hrows(hrows)
, _brows(brows) , _brows(brows)
@ -669,7 +672,6 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
} }
if (sticker.animated && sticker.animated->ready()) { if (sticker.animated && sticker.animated->ready()) {
const auto frame = sticker.animated->frame(); const auto frame = sticker.animated->frame();
sticker.animated->markFrameShown();
const auto size = frame.size() / cIntRetinaFactor(); const auto size = frame.size() / cIntRetinaFactor();
const auto ppos = pos + QPoint( const auto ppos = pos + QPoint(
(st::stickerPanSize.width() - size.width()) / 2, (st::stickerPanSize.width() - size.width()) / 2,
@ -677,6 +679,11 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
p.drawImage( p.drawImage(
QRect(ppos, size), QRect(ppos, size),
frame); frame);
const auto paused = _controller->isGifPausedAtLeastFor(
Window::GifPauseReason::SavedGifs);
if (!paused) {
sticker.animated->markFrameShown();
}
} else if (const auto image = document->getStickerSmall()) { } else if (const auto image = document->getStickerSmall()) {
QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2); QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2);
p.drawPixmapLeft(ppos, width(), image->pix(document->stickerSetOrigin(), w, h)); p.drawPixmapLeft(ppos, width(), image->pix(document->stickerSetOrigin(), w, h));

View file

@ -22,9 +22,9 @@ class SinglePlayer;
class FrameRenderer; class FrameRenderer;
} // namespace Lottie; } // namespace Lottie;
namespace Main { namespace Window {
class Session; class SessionController;
} // namespace Main } // namespace Window
namespace internal { namespace internal {
@ -46,7 +46,9 @@ class FieldAutocomplete final : public Ui::RpWidget {
Q_OBJECT Q_OBJECT
public: public:
FieldAutocomplete(QWidget *parent, not_null<Main::Session*> session); FieldAutocomplete(
QWidget *parent,
not_null<Window::SessionController*> controller);
~FieldAutocomplete(); ~FieldAutocomplete();
bool clearFilteredBotCommands(); bool clearFilteredBotCommands();
@ -112,7 +114,7 @@ private:
void recount(bool resetScroll = false); void recount(bool resetScroll = false);
internal::StickerRows getStickerSuggestions(); internal::StickerRows getStickerSuggestions();
const not_null<Main::Session*> _session; const not_null<Window::SessionController*> _controller;
QPixmap _cache; QPixmap _cache;
internal::MentionRows _mrows; internal::MentionRows _mrows;
internal::HashtagRows _hrows; internal::HashtagRows _hrows;
@ -163,6 +165,7 @@ class FieldAutocompleteInner final
public: public:
FieldAutocompleteInner( FieldAutocompleteInner(
not_null<Window::SessionController*> controller,
not_null<FieldAutocomplete*> parent, not_null<FieldAutocomplete*> parent,
not_null<MentionRows*> mrows, not_null<MentionRows*> mrows,
not_null<HashtagRows*> hrows, not_null<HashtagRows*> hrows,
@ -207,11 +210,12 @@ private:
void repaintSticker(not_null<DocumentData*> document); void repaintSticker(not_null<DocumentData*> document);
std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer(); std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
not_null<FieldAutocomplete*> _parent; const not_null<Window::SessionController*> _controller;
not_null<MentionRows*> _mrows; const not_null<FieldAutocomplete*> _parent;
not_null<HashtagRows*> _hrows; const not_null<MentionRows*> _mrows;
not_null<BotCommandRows*> _brows; const not_null<HashtagRows*> _hrows;
not_null<StickerRows*> _srows; const not_null<BotCommandRows*> _brows;
const not_null<StickerRows*> _srows;
rpl::lifetime _stickersLifetime; rpl::lifetime _stickersLifetime;
std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer; std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
int _stickersPerRow = 1; int _stickersPerRow = 1;

View file

@ -543,6 +543,21 @@ void Application::switchTestMode() {
App::restart(); App::restart();
} }
void Application::switchFreeType() {
if (cUseFreeType()) {
QFile(cWorkingDir() + qsl("tdata/withfreetype")).remove();
cSetUseFreeType(false);
} else {
QFile f(cWorkingDir() + qsl("tdata/withfreetype"));
if (f.open(QIODevice::WriteOnly)) {
f.write("1");
f.close();
}
cSetUseFreeType(true);
}
App::restart();
}
void Application::writeInstallBetaVersionsSetting() { void Application::writeInstallBetaVersionsSetting() {
_launcher->writeInstallBetaVersionsSetting(); _launcher->writeInstallBetaVersionsSetting();
} }

View file

@ -231,6 +231,7 @@ public:
void switchDebugMode(); void switchDebugMode();
void switchTestMode(); void switchTestMode();
void switchFreeType();
void writeInstallBetaVersionsSetting(); void writeInstallBetaVersionsSetting();
void call_handleUnreadCounterUpdate(); void call_handleUnreadCounterUpdate();

View file

@ -34,26 +34,47 @@ private:
static constexpr auto kForwardArgumentCount = 1; static constexpr auto kForwardArgumentCount = 1;
int _count = 0; int _count = 0;
char *_arguments[kForwardArgumentCount + 1] = { nullptr }; std::vector<QByteArray> _owned;
std::vector<char*> _arguments;
void pushArgument(const char *text);
}; };
FilteredCommandLineArguments::FilteredCommandLineArguments( FilteredCommandLineArguments::FilteredCommandLineArguments(
int argc, int argc,
char **argv) char **argv) {
: _count(std::clamp(argc, 0, kForwardArgumentCount)) {
// For now just pass only the first argument, the executable path. // For now just pass only the first argument, the executable path.
for (auto i = 0; i != _count; ++i) { for (auto i = 0; i != kForwardArgumentCount; ++i) {
_arguments[i] = argv[i]; pushArgument(argv[i]);
} }
#if defined Q_OS_WIN || defined Q_OS_MAC
if (cUseFreeType()) {
pushArgument("-platform");
#ifdef Q_OS_WIN
pushArgument("windows:fontengine=freetype");
#else // Q_OS_WIN
pushArgument("cocoa:fontengine=freetype");
#endif // !Q_OS_WIN
}
#endif // Q_OS_WIN || Q_OS_MAC
pushArgument(nullptr);
} }
int &FilteredCommandLineArguments::count() { int &FilteredCommandLineArguments::count() {
_count = _arguments.size() - 1;
return _count; return _count;
} }
char **FilteredCommandLineArguments::values() { char **FilteredCommandLineArguments::values() {
return _arguments; return _arguments.data();
}
void FilteredCommandLineArguments::pushArgument(const char *text) {
_owned.emplace_back(text);
_arguments.push_back(_owned.back().data());
} }
QString DebugModeSettingPath() { QString DebugModeSettingPath() {
@ -82,6 +103,12 @@ void ComputeTestMode() {
} }
} }
void ComputeFreeType() {
if (QFile(cWorkingDir() + qsl("tdata/withfreetype")).exists()) {
cSetUseFreeType(true);
}
}
QString InstallBetaVersionsSettingPath() { QString InstallBetaVersionsSettingPath() {
return cWorkingDir() + qsl("tdata/devversion"); return cWorkingDir() + qsl("tdata/devversion");
} }
@ -301,6 +328,7 @@ void Launcher::workingFolderReady() {
ComputeTestMode(); ComputeTestMode();
ComputeDebugMode(); ComputeDebugMode();
ComputeFreeType();
ComputeInstallBetaVersions(); ComputeInstallBetaVersions();
ComputeInstallationTag(); ComputeInstallationTag();
} }
@ -382,6 +410,7 @@ void Launcher::processArguments() {
auto parseMap = std::map<QByteArray, KeyFormat> { auto parseMap = std::map<QByteArray, KeyFormat> {
{ "-testmode" , KeyFormat::NoValues }, { "-testmode" , KeyFormat::NoValues },
{ "-debug" , KeyFormat::NoValues }, { "-debug" , KeyFormat::NoValues },
{ "-freetype" , KeyFormat::NoValues },
{ "-many" , KeyFormat::NoValues }, { "-many" , KeyFormat::NoValues },
{ "-key" , KeyFormat::OneValue }, { "-key" , KeyFormat::OneValue },
{ "-autostart" , KeyFormat::NoValues }, { "-autostart" , KeyFormat::NoValues },
@ -423,6 +452,7 @@ void Launcher::processArguments() {
SetUpdaterDisabledAtStartup(); SetUpdaterDisabledAtStartup();
} }
gTestMode = parseResult.contains("-testmode"); gTestMode = parseResult.contains("-testmode");
gUseFreeType = parseResult.contains("-freetype");
Logs::SetDebugEnabled(parseResult.contains("-debug")); Logs::SetDebugEnabled(parseResult.contains("-debug"));
gManyInstance = parseResult.contains("-many"); gManyInstance = parseResult.contains("-many");
gKeyFile = parseResult.value("-key", {}).join(QString()).toLower(); gKeyFile = parseResult.value("-key", {}).join(QString()).toLower();

View file

@ -373,11 +373,8 @@ void Sandbox::readClients() {
toSend.append(_escapeFrom7bit(cmds.mid(from + 5, to - from - 5))); toSend.append(_escapeFrom7bit(cmds.mid(from + 5, to - from - 5)));
} }
} else if (cmd.startsWith(qsl("OPEN:"))) { } else if (cmd.startsWith(qsl("OPEN:"))) {
auto activateRequired = true; startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)).mid(0, 8192);
if (cStartUrl().isEmpty()) { auto activateRequired = StartUrlRequiresActivate(startUrl);
startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)).mid(0, 8192);
activateRequired = StartUrlRequiresActivate(startUrl);
}
if (activateRequired) { if (activateRequired) {
execExternal("show"); execExternal("show");
} }

View file

@ -33,11 +33,11 @@ extern "C" {
#include <openssl/err.h> #include <openssl/err.h>
} // extern "C" } // extern "C"
#ifdef Q_OS_WIN // use Lzma SDK for win #if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
#include <LzmaLib.h> #include <LzmaLib.h>
#else // Q_OS_WIN #else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
#include <lzma.h> #include <lzma.h>
#endif // else of Q_OS_WIN #endif // else of Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
namespace Core { namespace Core {
namespace { namespace {
@ -252,11 +252,11 @@ bool UnpackUpdate(const QString &filepath) {
return false; return false;
} }
#ifdef Q_OS_WIN // use Lzma SDK for win #if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
#else // Q_OS_WIN #else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header
#endif // Q_OS_WIN #endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
QByteArray compressed = input.readAll(); QByteArray compressed = input.readAll();
int32 compressedLen = compressed.size() - hSize; int32 compressedLen = compressed.size() - hSize;
@ -311,14 +311,14 @@ bool UnpackUpdate(const QString &filepath) {
uncompressed.resize(uncompressedLen); uncompressed.resize(uncompressedLen);
size_t resultLen = uncompressed.size(); size_t resultLen = uncompressed.size();
#ifdef Q_OS_WIN // use Lzma SDK for win #if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
SizeT srcLen = compressedLen; SizeT srcLen = compressedLen;
int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE); int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE);
if (uncompressRes != SZ_OK) { if (uncompressRes != SZ_OK) {
LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes)); LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes));
return false; return false;
} }
#else // Q_OS_WIN #else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
lzma_stream stream = LZMA_STREAM_INIT; lzma_stream stream = LZMA_STREAM_INIT;
lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED); lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED);
@ -361,7 +361,7 @@ bool UnpackUpdate(const QString &filepath) {
LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res)); LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res));
return false; return false;
} }
#endif // Q_OS_WIN #endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
tempDir.mkdir(tempDir.absolutePath()); tempDir.mkdir(tempDir.absolutePath());

View file

@ -66,23 +66,32 @@ void Histories::clearAll() {
} }
void Histories::readInbox(not_null<History*> history) { void Histories::readInbox(not_null<History*> history) {
DEBUG_LOG(("Reading: readInbox called."));
if (history->lastServerMessageKnown()) { if (history->lastServerMessageKnown()) {
const auto last = history->lastServerMessage(); const auto last = history->lastServerMessage();
DEBUG_LOG(("Reading: last known, reading till %1."
).arg(last ? last->id : 0));
readInboxTill(history, last ? last->id : 0); readInboxTill(history, last ? last->id : 0);
return; return;
} else if (history->loadedAtBottom()) { } else if (history->loadedAtBottom()) {
if (const auto lastId = history->maxMsgId()) { if (const auto lastId = history->maxMsgId()) {
DEBUG_LOG(("Reading: loaded at bottom, maxMsgId %1."
).arg(lastId));
readInboxTill(history, lastId); readInboxTill(history, lastId);
return; return;
} else if (history->loadedAtTop()) { } else if (history->loadedAtTop()) {
DEBUG_LOG(("Reading: loaded at bottom, loaded at top."));
readInboxTill(history, 0); readInboxTill(history, 0);
return; return;
} }
DEBUG_LOG(("Reading: loaded at bottom, but requesting entry."));
} }
requestDialogEntry(history, [=] { requestDialogEntry(history, [=] {
Expects(history->lastServerMessageKnown()); Expects(history->lastServerMessageKnown());
const auto last = history->lastServerMessage(); const auto last = history->lastServerMessage();
DEBUG_LOG(("Reading: got entry, reading till %1."
).arg(last ? last->id : 0));
readInboxTill(history, last ? last->id : 0); readInboxTill(history, last ? last->id : 0);
}); });
} }
@ -135,10 +144,20 @@ void Histories::readInboxTill(
bool force) { bool force) {
Expects(IsServerMsgId(tillId) || (!tillId && !force)); Expects(IsServerMsgId(tillId) || (!tillId && !force));
DEBUG_LOG(("Reading: readInboxTill %1, force %2."
).arg(tillId
).arg(Logs::b(force)));
const auto syncGuard = gsl::finally([&] { const auto syncGuard = gsl::finally([&] {
DEBUG_LOG(("Reading: in guard, unread %1."
).arg(history->unreadCount()));
if (history->unreadCount() > 0) { if (history->unreadCount() > 0) {
if (const auto last = history->lastServerMessage()) { if (const auto last = history->lastServerMessage()) {
DEBUG_LOG(("Reading: checking last %1 and %2."
).arg(last->id
).arg(tillId));
if (last->id == tillId) { if (last->id == tillId) {
DEBUG_LOG(("Reading: locally marked as read."));
history->setUnreadCount(0); history->setUnreadCount(0);
history->updateChatListEntry(); history->updateChatListEntry();
} }
@ -150,14 +169,21 @@ void Histories::readInboxTill(
const auto needsRequest = history->readInboxTillNeedsRequest(tillId); const auto needsRequest = history->readInboxTillNeedsRequest(tillId);
if (!needsRequest && !force) { if (!needsRequest && !force) {
DEBUG_LOG(("Reading: readInboxTill finish 1."));
return; return;
} else if (!history->trackUnreadMessages()) { } else if (!history->trackUnreadMessages()) {
DEBUG_LOG(("Reading: readInboxTill finish 2."));
return; return;
} }
const auto maybeState = lookup(history); const auto maybeState = lookup(history);
if (maybeState && maybeState->sentReadTill >= tillId) { if (maybeState && maybeState->sentReadTill >= tillId) {
DEBUG_LOG(("Reading: readInboxTill finish 3 with %1."
).arg(maybeState->sentReadTill));
return; return;
} else if (maybeState && maybeState->willReadTill >= tillId) { } else if (maybeState && maybeState->willReadTill >= tillId) {
DEBUG_LOG(("Reading: readInboxTill finish 4 with %1 and force %2."
).arg(maybeState->sentReadTill
).arg(Logs::b(force)));
if (force) { if (force) {
sendPendingReadInbox(history); sendPendingReadInbox(history);
} }
@ -171,23 +197,35 @@ void Histories::readInboxTill(
&& stillUnread && stillUnread
&& history->unreadCountKnown() && history->unreadCountKnown()
&& *stillUnread == history->unreadCount()) { && *stillUnread == history->unreadCount()) {
DEBUG_LOG(("Reading: count didn't change so just update till %1"
).arg(tillId));
history->setInboxReadTill(tillId); history->setInboxReadTill(tillId);
return; return;
} }
auto &state = maybeState ? *maybeState : _states[history]; auto &state = maybeState ? *maybeState : _states[history];
state.willReadTill = tillId; state.willReadTill = tillId;
if (force || !stillUnread || !*stillUnread) { if (force || !stillUnread || !*stillUnread) {
DEBUG_LOG(("Reading: will read till %1 with still unread %2"
).arg(tillId
).arg(stillUnread.value_or(-666)));
state.willReadWhen = 0; state.willReadWhen = 0;
sendReadRequests(); sendReadRequests();
if (!stillUnread) { if (!stillUnread) {
return; return;
} }
} else if (!state.willReadWhen) { } else if (!state.willReadWhen) {
DEBUG_LOG(("Reading: will read till %1 with postponed").arg(tillId));
state.willReadWhen = crl::now() + kReadRequestTimeout; state.willReadWhen = crl::now() + kReadRequestTimeout;
if (!_readRequestsTimer.isActive()) { if (!_readRequestsTimer.isActive()) {
_readRequestsTimer.callOnce(kReadRequestTimeout); _readRequestsTimer.callOnce(kReadRequestTimeout);
} }
} else {
DEBUG_LOG(("Reading: will read till %1 postponed already"
).arg(tillId));
} }
DEBUG_LOG(("Reading: marking now with till %1 and still %2"
).arg(tillId
).arg(*stillUnread));
history->setInboxReadTill(tillId); history->setInboxReadTill(tillId);
history->setUnreadCount(*stillUnread); history->setUnreadCount(*stillUnread);
history->updateChatListEntry(); history->updateChatListEntry();
@ -399,6 +437,9 @@ void Histories::requestFakeChatListMessage(
void Histories::sendPendingReadInbox(not_null<History*> history) { void Histories::sendPendingReadInbox(not_null<History*> history) {
if (const auto state = lookup(history)) { if (const auto state = lookup(history)) {
DEBUG_LOG(("Reading: send pending now with till %1 and when %2"
).arg(state->willReadTill
).arg(state->willReadWhen));
if (state->willReadTill && state->willReadWhen) { if (state->willReadTill && state->willReadWhen) {
state->willReadWhen = 0; state->willReadWhen = 0;
sendReadRequests(); sendReadRequests();
@ -407,6 +448,7 @@ void Histories::sendPendingReadInbox(not_null<History*> history) {
} }
void Histories::sendReadRequests() { void Histories::sendReadRequests() {
DEBUG_LOG(("Reading: send requests with count %1.").arg(_states.size()));
if (_states.empty()) { if (_states.empty()) {
return; return;
} }
@ -414,10 +456,14 @@ void Histories::sendReadRequests() {
auto next = std::optional<crl::time>(); auto next = std::optional<crl::time>();
for (auto &[history, state] : _states) { for (auto &[history, state] : _states) {
if (!state.willReadTill) { if (!state.willReadTill) {
DEBUG_LOG(("Reading: skipping zero till."));
continue; continue;
} else if (state.willReadWhen <= now) { } else if (state.willReadWhen <= now) {
DEBUG_LOG(("Reading: sending with till %1."
).arg(state.willReadTill));
sendReadRequest(history, state); sendReadRequest(history, state);
} else if (!next || *next > state.willReadWhen) { } else if (!next || *next > state.willReadWhen) {
DEBUG_LOG(("Reading: scheduling for later send."));
next = state.willReadWhen; next = state.willReadWhen;
} }
} }
@ -434,7 +480,11 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
const auto tillId = state.sentReadTill = base::take(state.willReadTill); const auto tillId = state.sentReadTill = base::take(state.willReadTill);
state.willReadWhen = 0; state.willReadWhen = 0;
state.sentReadDone = false; state.sentReadDone = false;
DEBUG_LOG(("Reading: sending request now with till %1."
).arg(tillId));
sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> finish) { sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> finish) {
DEBUG_LOG(("Reading: sending request invoked with till %1."
).arg(tillId));
const auto finished = [=] { const auto finished = [=] {
const auto state = lookup(history); const auto state = lookup(history);
Assert(state != nullptr); Assert(state != nullptr);

View file

@ -797,7 +797,7 @@ int PeerData::slowmodeSecondsLeft() const {
bool PeerData::canSendPolls() const { bool PeerData::canSendPolls() const {
if (const auto user = asUser()) { if (const auto user = asUser()) {
return user->isBot(); return user->isBot() && !user->isSupport();
} else if (const auto chat = asChat()) { } else if (const auto chat = asChat()) {
return chat->canSendPolls(); return chat->canSendPolls();
} else if (const auto channel = asChannel()) { } else if (const auto channel = asChannel()) {

View file

@ -1580,6 +1580,17 @@ void InnerWidget::repaintDialogRow(RowDescriptor row) {
updateDialogRow(row); updateDialogRow(row);
} }
void InnerWidget::refreshDialogRow(RowDescriptor row) {
if (row.fullId) {
for (const auto &result : _searchResults) {
if (result->item()->fullId() == row.fullId) {
result->invalidateCache();
}
}
}
repaintDialogRow(row);
}
void InnerWidget::updateSearchResult(not_null<PeerData*> peer) { void InnerWidget::updateSearchResult(not_null<PeerData*> peer) {
if (_state == WidgetState::Filtered) { if (_state == WidgetState::Filtered) {
if (!_peerSearchResults.empty()) { if (!_peerSearchResults.empty()) {

View file

@ -92,6 +92,7 @@ public:
void removeDialog(Key key); void removeDialog(Key key);
void repaintDialogRow(FilterId filterId, not_null<Row*> row); void repaintDialogRow(FilterId filterId, not_null<Row*> row);
void repaintDialogRow(RowDescriptor row); void repaintDialogRow(RowDescriptor row);
void refreshDialogRow(RowDescriptor row);
void dragLeft(); void dragLeft();

View file

@ -121,6 +121,11 @@ public:
return _item; return _item;
} }
void invalidateCache() {
_cacheFor = nullptr;
_cache = Ui::Text::String();
}
private: private:
friend class Layout::RowPainter; friend class Layout::RowPainter;

View file

@ -549,6 +549,10 @@ void Widget::repaintDialogRow(RowDescriptor row) {
_inner->repaintDialogRow(row); _inner->repaintDialogRow(row);
} }
void Widget::refreshDialogRow(RowDescriptor row) {
_inner->refreshDialogRow(row);
}
void Widget::jumpToTop() { void Widget::jumpToTop() {
if (session().supportMode()) { if (session().supportMode()) {
return; return;
@ -674,7 +678,6 @@ void Widget::animationCallback() {
updateControlsVisibility(true); updateControlsVisibility(true);
applyFilterUpdate();
if (!_filter->hasFocus()) { if (!_filter->hasFocus()) {
if (App::wnd()) App::wnd()->setInnerFocus(); if (App::wnd()) App::wnd()->setInnerFocus();
} }

View file

@ -64,6 +64,7 @@ public:
void removeDialog(Key key); void removeDialog(Key key);
void repaintDialogRow(FilterId filterId, not_null<Row*> row); void repaintDialogRow(FilterId filterId, not_null<Row*> row);
void repaintDialogRow(RowDescriptor row); void repaintDialogRow(RowDescriptor row);
void refreshDialogRow(RowDescriptor row);
void jumpToTop(); void jumpToTop();

View file

@ -386,7 +386,9 @@ struct Data {
bool VoiceMsgPlaybackDoubled = false; bool VoiceMsgPlaybackDoubled = false;
bool SoundNotify = true; bool SoundNotify = true;
bool DesktopNotify = true; bool DesktopNotify = true;
bool FlashBounceNotify = true;
bool RestoreSoundNotifyFromTray = false; bool RestoreSoundNotifyFromTray = false;
bool RestoreFlashBounceNotifyFromTray = false;
DBINotifyView NotifyView = dbinvShowPreview; DBINotifyView NotifyView = dbinvShowPreview;
bool NativeNotifications = false; bool NativeNotifications = false;
int NotificationsCount = 3; int NotificationsCount = 3;
@ -515,7 +517,9 @@ DefineRefVar(Global, base::Observable<void>, DownloadPathChanged);
DefineVar(Global, bool, VoiceMsgPlaybackDoubled); DefineVar(Global, bool, VoiceMsgPlaybackDoubled);
DefineVar(Global, bool, SoundNotify); DefineVar(Global, bool, SoundNotify);
DefineVar(Global, bool, DesktopNotify); DefineVar(Global, bool, DesktopNotify);
DefineVar(Global, bool, FlashBounceNotify);
DefineVar(Global, bool, RestoreSoundNotifyFromTray); DefineVar(Global, bool, RestoreSoundNotifyFromTray);
DefineVar(Global, bool, RestoreFlashBounceNotifyFromTray);
DefineVar(Global, DBINotifyView, NotifyView); DefineVar(Global, DBINotifyView, NotifyView);
DefineVar(Global, bool, NativeNotifications); DefineVar(Global, bool, NativeNotifications);
DefineVar(Global, int, NotificationsCount); DefineVar(Global, int, NotificationsCount);

View file

@ -211,7 +211,9 @@ DeclareRefVar(base::Observable<void>, DownloadPathChanged);
DeclareVar(bool, VoiceMsgPlaybackDoubled); DeclareVar(bool, VoiceMsgPlaybackDoubled);
DeclareVar(bool, SoundNotify); DeclareVar(bool, SoundNotify);
DeclareVar(bool, DesktopNotify); DeclareVar(bool, DesktopNotify);
DeclareVar(bool, FlashBounceNotify);
DeclareVar(bool, RestoreSoundNotifyFromTray); DeclareVar(bool, RestoreSoundNotifyFromTray);
DeclareVar(bool, RestoreFlashBounceNotifyFromTray);
DeclareVar(DBINotifyView, NotifyView); DeclareVar(DBINotifyView, NotifyView);
DeclareVar(bool, NativeNotifications); DeclareVar(bool, NativeNotifications);
DeclareVar(int, NotificationsCount); DeclareVar(int, NotificationsCount);

View file

@ -1622,6 +1622,9 @@ bool History::readInboxTillNeedsRequest(MsgId tillId) {
if (unreadMark()) { if (unreadMark()) {
owner().histories().changeDialogUnreadMark(this, false); owner().histories().changeDialogUnreadMark(this, false);
} }
DEBUG_LOG(("Reading: readInboxTillNeedsRequest is_server %1, before %2."
).arg(Logs::b(IsServerMsgId(tillId))
).arg(_inboxReadBefore.value_or(-666)));
return IsServerMsgId(tillId) && (_inboxReadBefore.value_or(1) <= tillId); return IsServerMsgId(tillId) && (_inboxReadBefore.value_or(1) <= tillId);
} }
@ -1639,10 +1642,17 @@ bool History::unreadCountRefreshNeeded(MsgId readTillId) const {
std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const { std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
if (isEmpty() || !folderKnown()) { if (isEmpty() || !folderKnown()) {
DEBUG_LOG(("Reading: countStillUnreadLocal unknown %1 and %2."
).arg(Logs::b(isEmpty())
).arg(Logs::b(folderKnown())));
return std::nullopt; return std::nullopt;
} }
if (_inboxReadBefore) { if (_inboxReadBefore) {
const auto before = *_inboxReadBefore; const auto before = *_inboxReadBefore;
DEBUG_LOG(("Reading: check before %1 with min %2 and max %3."
).arg(before
).arg(minMsgId()
).arg(maxMsgId()));
if (minMsgId() <= before && maxMsgId() >= readTillId) { if (minMsgId() <= before && maxMsgId() >= readTillId) {
auto result = 0; auto result = 0;
for (const auto &block : blocks) { for (const auto &block : blocks) {
@ -1658,12 +1668,19 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
} }
} }
} }
DEBUG_LOG(("Reading: check before result %1 with existing %2"
).arg(result
).arg(_unreadCount.value_or(-666)));
if (_unreadCount) { if (_unreadCount) {
return std::max(*_unreadCount - result, 0); return std::max(*_unreadCount - result, 0);
} }
} }
} }
const auto minimalServerId = minMsgId(); const auto minimalServerId = minMsgId();
DEBUG_LOG(("Reading: check at end loaded from %1 loaded %2 - %3"
).arg(minimalServerId
).arg(Logs::b(loadedAtBottom())
).arg(Logs::b(loadedAtTop())));
if (!loadedAtBottom() if (!loadedAtBottom()
|| (!loadedAtTop() && !minimalServerId) || (!loadedAtTop() && !minimalServerId)
|| minimalServerId > readTillId) { || minimalServerId > readTillId) {
@ -1682,6 +1699,7 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
} }
} }
} }
DEBUG_LOG(("Reading: check at end counted %1").arg(result));
return result; return result;
} }

View file

@ -267,7 +267,7 @@ PeerData *HistoryItem::displayFrom() const {
void HistoryItem::invalidateChatListEntry() { void HistoryItem::invalidateChatListEntry() {
if (const auto main = App::main()) { if (const auto main = App::main()) {
// #TODO feeds search results // #TODO feeds search results
main->repaintDialogRow({ history(), fullId() }); main->refreshDialogRow({ history(), fullId() });
} }
// invalidate cache for drawInDialog // invalidate cache for drawInDialog

View file

@ -265,7 +265,7 @@ HistoryWidget::HistoryWidget(
, _scroll(this, st::historyScroll, false) , _scroll(this, st::historyScroll, false)
, _historyDown(_scroll, st::historyToDown) , _historyDown(_scroll, st::historyToDown)
, _unreadMentions(_scroll, st::historyUnreadMentions) , _unreadMentions(_scroll, st::historyUnreadMentions)
, _fieldAutocomplete(this, &session()) , _fieldAutocomplete(this, controller)
, _supportAutocomplete(session().supportMode() , _supportAutocomplete(session().supportMode()
? object_ptr<Support::Autocomplete>(this, &session()) ? object_ptr<Support::Autocomplete>(this, &session())
: nullptr) : nullptr)
@ -1489,8 +1489,7 @@ bool HistoryWidget::notify_switchInlineBotButtonReceived(const QString &query, U
if (_history) { if (_history) {
TextWithTags textWithTags = { '@' + samePeerBot->username + ' ' + query, TextWithTags::Tags() }; TextWithTags textWithTags = { '@' + samePeerBot->username + ' ' + query, TextWithTags::Tags() };
MessageCursor cursor = { textWithTags.text.size(), textWithTags.text.size(), QFIXED_MAX }; MessageCursor cursor = { textWithTags.text.size(), textWithTags.text.size(), QFIXED_MAX };
auto replyTo = _history->peer->isUser() ? 0 : samePeerReplyTo; _history->setLocalDraft(std::make_unique<Data::Draft>(textWithTags, 0, cursor, false));
_history->setLocalDraft(std::make_unique<Data::Draft>(textWithTags, replyTo, cursor, false));
applyDraft(); applyDraft();
return true; return true;
} }

View file

@ -104,7 +104,9 @@ class HistoryWidget final
public: public:
using FieldHistoryAction = Ui::InputField::HistoryAction; using FieldHistoryAction = Ui::InputField::HistoryAction;
HistoryWidget(QWidget *parent, not_null<Window::SessionController*> controller); HistoryWidget(
QWidget *parent,
not_null<Window::SessionController*> controller);
void start(); void start();

View file

@ -1480,6 +1480,12 @@ int Message::plainMaxWidth() const {
+ st::msgPadding.right(); + st::msgPadding.right();
} }
int Message::monospaceMaxWidth() const {
return st::msgPadding.left()
+ (hasVisibleText() ? message()->_text.countMaxMonospaceWidth() : 0)
+ st::msgPadding.right();
}
void Message::initLogEntryOriginal() { void Message::initLogEntryOriginal() {
if (const auto log = message()->Get<HistoryMessageLogEntryOriginal>()) { if (const auto log = message()->Get<HistoryMessageLogEntryOriginal>()) {
AddComponents(LogEntryOriginal::Bit()); AddComponents(LogEntryOriginal::Bit());
@ -1804,7 +1810,7 @@ QRect Message::countGeometry() const {
} }
accumulate_min(contentWidth, maxWidth()); accumulate_min(contentWidth, maxWidth());
if (!AdaptiveBubbles()) { if (!AdaptiveBubbles()) {
accumulate_min(contentWidth, st::msgMaxWidth); accumulate_min(contentWidth, _bubbleWidthLimit);
} }
if (mediaWidth < contentWidth) { if (mediaWidth < contentWidth) {
const auto textualWidth = plainMaxWidth(); const auto textualWidth = plainMaxWidth();
@ -1847,8 +1853,9 @@ int Message::resizeContentGetHeight(int newWidth) {
contentWidth -= st::msgPhotoSkip; contentWidth -= st::msgPhotoSkip;
} }
accumulate_min(contentWidth, maxWidth()); accumulate_min(contentWidth, maxWidth());
_bubbleWidthLimit = std::max(st::msgMaxWidth, monospaceMaxWidth());
if (!AdaptiveBubbles()) { if (!AdaptiveBubbles()) {
accumulate_min(contentWidth, st::msgMaxWidth); accumulate_min(contentWidth, _bubbleWidthLimit);
} }
if (mediaDisplayed) { if (mediaDisplayed) {
media->resizeGetHeight(contentWidth); media->resizeGetHeight(contentWidth);

View file

@ -158,7 +158,9 @@ private:
const HistoryMessageEdited *displayedEditBadge() const; const HistoryMessageEdited *displayedEditBadge() const;
HistoryMessageEdited *displayedEditBadge(); HistoryMessageEdited *displayedEditBadge();
void initTime(); void initTime();
int timeLeft() const; [[nodiscard]] int timeLeft() const;
[[nodiscard]] int plainMaxWidth() const;
[[nodiscard]] int monospaceMaxWidth() const;
WebPage *logEntryOriginal() const; WebPage *logEntryOriginal() const;
@ -167,6 +169,7 @@ private:
mutable ClickHandlerPtr _rightActionLink; mutable ClickHandlerPtr _rightActionLink;
mutable ClickHandlerPtr _fastReplyLink; mutable ClickHandlerPtr _fastReplyLink;
int _bubbleWidthLimit = 0;
}; };

View file

@ -40,6 +40,7 @@ void PrepareSupportMode() {
Global::SetDesktopNotify(false); Global::SetDesktopNotify(false);
Global::SetSoundNotify(false); Global::SetSoundNotify(false);
Global::SetFlashBounceNotify(false);
Auth().settings().autoDownload() = Full::FullDisabled(); Auth().settings().autoDownload() = Full::FullDisabled();
Local::writeUserSettings(); Local::writeUserSettings();
} }

View file

@ -2198,6 +2198,10 @@ void MainWidget::repaintDialogRow(Dialogs::RowDescriptor row) {
_dialogs->repaintDialogRow(row); _dialogs->repaintDialogRow(row);
} }
void MainWidget::refreshDialogRow(Dialogs::RowDescriptor row) {
_dialogs->refreshDialogRow(row);
}
void MainWidget::windowShown() { void MainWidget::windowShown() {
_history->windowShown(); _history->windowShown();
} }

View file

@ -138,6 +138,7 @@ public:
void removeDialog(Dialogs::Key key); void removeDialog(Dialogs::Key key);
void repaintDialogRow(FilterId filterId, not_null<Dialogs::Row*> row); void repaintDialogRow(FilterId filterId, not_null<Dialogs::Row*> row);
void repaintDialogRow(Dialogs::RowDescriptor row); void repaintDialogRow(Dialogs::RowDescriptor row);
void refreshDialogRow(Dialogs::RowDescriptor row);
void windowShown(); void windowShown();

View file

@ -776,7 +776,8 @@ void MainWindow::toggleDisplayNotifyFromTray() {
return; return;
} }
bool soundNotifyChanged = false; auto soundNotifyChanged = false;
auto flashBounceNotifyChanged = false;
Global::SetDesktopNotify(!Global::DesktopNotify()); Global::SetDesktopNotify(!Global::DesktopNotify());
if (Global::DesktopNotify()) { if (Global::DesktopNotify()) {
if (Global::RestoreSoundNotifyFromTray() && !Global::SoundNotify()) { if (Global::RestoreSoundNotifyFromTray() && !Global::SoundNotify()) {
@ -784,6 +785,12 @@ void MainWindow::toggleDisplayNotifyFromTray() {
Global::SetRestoreSoundNotifyFromTray(false); Global::SetRestoreSoundNotifyFromTray(false);
soundNotifyChanged = true; soundNotifyChanged = true;
} }
if (Global::RestoreFlashBounceNotifyFromTray()
&& !Global::FlashBounceNotify()) {
Global::SetFlashBounceNotify(true);
Global::SetRestoreFlashBounceNotifyFromTray(false);
flashBounceNotifyChanged = true;
}
} else { } else {
if (Global::SoundNotify()) { if (Global::SoundNotify()) {
Global::SetSoundNotify(false); Global::SetSoundNotify(false);
@ -792,13 +799,23 @@ void MainWindow::toggleDisplayNotifyFromTray() {
} else { } else {
Global::SetRestoreSoundNotifyFromTray(false); Global::SetRestoreSoundNotifyFromTray(false);
} }
if (Global::FlashBounceNotify()) {
Global::SetFlashBounceNotify(false);
Global::SetRestoreFlashBounceNotifyFromTray(true);
flashBounceNotifyChanged = true;
} else {
Global::SetRestoreFlashBounceNotifyFromTray(false);
}
} }
Local::writeUserSettings(); Local::writeUserSettings();
account().session().notifications().settingsChanged().notify( using Change = Window::Notifications::ChangeType;
Window::Notifications::ChangeType::DesktopEnabled); auto &changes = account().session().notifications().settingsChanged();
changes.notify(Change::DesktopEnabled);
if (soundNotifyChanged) { if (soundNotifyChanged) {
account().session().notifications().settingsChanged().notify( changes.notify(Change::SoundEnabled);
Window::Notifications::ChangeType::SoundEnabled); }
if (flashBounceNotifyChanged) {
changes.notify(Change::FlashBounceEnabled);
} }
} }

View file

@ -37,8 +37,8 @@ public:
void process(std::vector<FFmpeg::Packet> &&packets); void process(std::vector<FFmpeg::Packet> &&packets);
[[nodisacrd]] rpl::producer<> checkNextFrame() const; [[nodiscard]] rpl::producer<> checkNextFrame() const;
[[nodisacrd]] rpl::producer<> waitingForData() const; [[nodiscard]] rpl::producer<> waitingForData() const;
void pause(crl::time time); void pause(crl::time time);
void resume(crl::time time); void resume(crl::time time);

View file

@ -40,6 +40,7 @@ constexpr auto kTestModeDcIdShift = 10000;
constexpr auto kCheckSentRequestsEach = 1 * crl::time(1000); constexpr auto kCheckSentRequestsEach = 1 * crl::time(1000);
constexpr auto kKeyOldEnoughForDestroy = 60 * crl::time(1000); constexpr auto kKeyOldEnoughForDestroy = 60 * crl::time(1000);
constexpr auto kSentContainerLives = 600 * crl::time(1000); constexpr auto kSentContainerLives = 600 * crl::time(1000);
constexpr auto kFastRequestDuration = crl::time(500);
// If we can't connect for this time we will ask _instance to update config. // If we can't connect for this time we will ask _instance to update config.
constexpr auto kRequestConfigTimeout = 8 * crl::time(1000); constexpr auto kRequestConfigTimeout = 8 * crl::time(1000);
@ -57,6 +58,8 @@ constexpr auto kSendStateRequestWaiting = crl::time(1000);
// How much time to wait for some more requests, when sending msg acks. // How much time to wait for some more requests, when sending msg acks.
constexpr auto kAckSendWaiting = 10 * crl::time(1000); constexpr auto kAckSendWaiting = 10 * crl::time(1000);
auto SyncTimeRequestDuration = kFastRequestDuration;
using namespace details; using namespace details;
[[nodiscard]] QString LogIdsVector(const QVector<MTPlong> &ids) { [[nodiscard]] QString LogIdsVector(const QVector<MTPlong> &ids) {
@ -1467,8 +1470,12 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
return badTime ? HandleResult::Ignored : HandleResult::Success; return badTime ? HandleResult::Ignored : HandleResult::Success;
} }
if (badTime && !requestsFixTimeSalt(ids, serverTime, serverSalt)) { if (badTime) {
return HandleResult::Ignored; if (!requestsFixTimeSalt(ids, serverTime, serverSalt)) {
return HandleResult::Ignored;
}
} else {
correctUnixtimeByFastRequest(ids, serverTime);
} }
requestsAcked(ids); requestsAcked(ids);
} return HandleResult::Success; } return HandleResult::Success;
@ -1520,7 +1527,8 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
if (serverSalt) { if (serverSalt) {
_sessionSalt = serverSalt; _sessionSalt = serverSalt;
} }
base::unixtime::update(serverTime, true);
correctUnixtimeWithBadLocal(serverTime);
DEBUG_LOG(("Message Info: unixtime updated, now %1, resending in container...").arg(serverTime)); DEBUG_LOG(("Message Info: unixtime updated, now %1, resending in container...").arg(serverTime));
@ -1530,7 +1538,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
if (serverSalt) { if (serverSalt) {
_sessionSalt = serverSalt; _sessionSalt = serverSalt;
} }
base::unixtime::update(serverTime, true); correctUnixtimeWithBadLocal(serverTime);
badTime = false; badTime = false;
} }
LOG(("Message Info: bad message notification received, msgId %1, error_code %2").arg(data.vbad_msg_id().v).arg(errorCode)); LOG(("Message Info: bad message notification received, msgId %1, error_code %2").arg(data.vbad_msg_id().v).arg(errorCode));
@ -1580,7 +1588,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
} }
_sessionSalt = data.vnew_server_salt().v; _sessionSalt = data.vnew_server_salt().v;
base::unixtime::update(serverTime); correctUnixtimeWithBadLocal(serverTime);
if (setState(ConnectedState, ConnectingState)) { if (setState(ConnectedState, ConnectingState)) {
resendAll(); resendAll();
@ -1612,7 +1620,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
if (serverSalt) { if (serverSalt) {
_sessionSalt = serverSalt; // requestsFixTimeSalt with no lookup _sessionSalt = serverSalt; // requestsFixTimeSalt with no lookup
} }
base::unixtime::update(serverTime, true); correctUnixtimeWithBadLocal(serverTime);
DEBUG_LOG(("Message Info: unixtime updated from mtpc_msgs_state_info, now %1").arg(serverTime)); DEBUG_LOG(("Message Info: unixtime updated from mtpc_msgs_state_info, now %1").arg(serverTime));
@ -1956,20 +1964,48 @@ mtpBuffer SessionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) cons
} }
bool SessionPrivate::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt) { bool SessionPrivate::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt) {
uint32 idsCount = ids.size(); for (const auto &id : ids) {
if (wasSent(id.v)) {
for (uint32 i = 0; i < idsCount; ++i) { // Found such msg_id in recent acked or in recent sent requests.
if (wasSent(ids[i].v)) {// found such msg_id in recent acked requests or in recent sent requests
if (serverSalt) { if (serverSalt) {
_sessionSalt = serverSalt; _sessionSalt = serverSalt;
} }
base::unixtime::update(serverTime, true); correctUnixtimeWithBadLocal(serverTime);
return true; return true;
} }
} }
return false; return false;
} }
void SessionPrivate::correctUnixtimeByFastRequest(
const QVector<MTPlong> &ids,
TimeId serverTime) {
const auto now = crl::now();
QReadLocker locker(_sessionData->haveSentMutex());
const auto &haveSent = _sessionData->haveSentMap();
for (const auto &id : ids) {
const auto i = haveSent.find(id.v);
if (i == haveSent.end()) {
continue;
}
const auto duration = (now - i->second->lastSentTime);
if (duration < 0 || duration > SyncTimeRequestDuration) {
continue;
}
locker.unlock();
SyncTimeRequestDuration = duration;
base::unixtime::update(serverTime, true);
return;
}
}
void SessionPrivate::correctUnixtimeWithBadLocal(TimeId serverTime) {
SyncTimeRequestDuration = kFastRequestDuration;
base::unixtime::update(serverTime, true);
}
void SessionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) { void SessionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) {
uint32 idsCount = ids.size(); uint32 idsCount = ids.size();

View file

@ -139,6 +139,12 @@ private:
// if badTime received - search for ids in sessionData->haveSent and sessionData->wereAcked and sync time/salt, return true if found // if badTime received - search for ids in sessionData->haveSent and sessionData->wereAcked and sync time/salt, return true if found
bool requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt); bool requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt);
// if we had a confirmed fast request use its unixtime as a correct one.
void correctUnixtimeByFastRequest(
const QVector<MTPlong> &ids,
TimeId serverTime);
void correctUnixtimeWithBadLocal(TimeId serverTime);
// remove msgs with such ids from sessionData->haveSent, add to sessionData->wereAcked // remove msgs with such ids from sessionData->haveSent, add to sessionData->wereAcked
void requestsAcked(const QVector<MTPlong> &ids, bool byResponse = false); void requestsAcked(const QVector<MTPlong> &ids, bool byResponse = false);

View file

@ -457,15 +457,11 @@ bool SkipAudio() {
} }
bool SkipToast() { bool SkipToast() {
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION return SkipAudio();
if (Supported() }
&& GetCapabilities().contains(qsl("inhibitions"))
&& !InhibitedNotSupported) {
return Inhibited();
}
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return false; bool SkipFlashBounce() {
return SkipAudio();
} }
bool Supported() { bool Supported() {

View file

@ -19,9 +19,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
inline void FlashBounce() {
}
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
class NotificationData : public QObject { class NotificationData : public QObject {
Q_OBJECT Q_OBJECT

View file

@ -13,9 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
bool SkipAudio();
bool SkipToast();
class Manager : public Window::Notifications::NativeManager, public base::has_weak_ptr { class Manager : public Window::Notifications::NativeManager, public base::has_weak_ptr {
public: public:
Manager(Window::Notifications::System *system); Manager(Window::Notifications::System *system);

View file

@ -143,6 +143,10 @@ bool SkipToast() {
return DoNotDisturbEnabled; return DoNotDisturbEnabled;
} }
bool SkipFlashBounce() {
return SkipAudio();
}
bool Supported() { bool Supported() {
return Platform::IsMac10_8OrGreater(); return Platform::IsMac10_8OrGreater();
} }
@ -154,10 +158,6 @@ std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::Sy
return nullptr; return nullptr;
} }
void FlashBounce() {
[NSApp requestUserAttention:NSInformationalRequest];
}
class Manager::Private : public QObject, private base::Subscriber { class Manager::Private : public QObject, private base::Subscriber {
public: public:
Private(Manager *manager); Private(Manager *manager);

View file

@ -12,12 +12,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
bool SkipAudio(); [[nodiscard]] bool SkipAudio();
bool SkipToast(); [[nodiscard]] bool SkipToast();
[[nodiscard]] bool SkipFlashBounce();
bool Supported(); [[nodiscard]] bool Supported();
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system); [[nodiscard]] std::unique_ptr<Window::Notifications::Manager> Create(
void FlashBounce(); Window::Notifications::System *system);
} // namespace Notifications } // namespace Notifications
} // namespace Platform } // namespace Platform

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/win/windows_dlls.h" #include "platform/win/windows_dlls.h"
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
#include <initguid.h>
#include <mmdeviceapi.h> #include <mmdeviceapi.h>
#include <audioclient.h> #include <audioclient.h>

View file

@ -117,7 +117,13 @@ void UnsafeOpenEmailLink(const QString &email) {
auto wstringUrl = url.toString(QUrl::FullyEncoded).toStdWString(); auto wstringUrl = url.toString(QUrl::FullyEncoded).toStdWString();
if (Dlls::SHOpenWithDialog) { if (Dlls::SHOpenWithDialog) {
OPENASINFO info; OPENASINFO info;
info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT | OAIF_EXEC | OAIF_FILE_IS_URI | OAIF_URL_PROTOCOL; info.oaifInFlags = OAIF_ALLOW_REGISTRATION
| OAIF_REGISTER_EXT
| OAIF_EXEC
#if WINVER >= 0x0602
| OAIF_FILE_IS_URI
#endif // WINVER >= 0x602
| OAIF_URL_PROTOCOL;
info.pcszClass = NULL; info.pcszClass = NULL;
info.pcszFile = wstringUrl.c_str(); info.pcszFile = wstringUrl.c_str();
Dlls::SHOpenWithDialog(0, &info); Dlls::SHOpenWithDialog(0, &info);

View file

@ -35,8 +35,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <roapi.h> #include <roapi.h>
#include <wrl/client.h> #include <wrl/client.h>
#include "platform/win/wrapper_wrl_implements_h.h"
#include <windows.ui.notifications.h>
#include <Windowsx.h> #include <Windowsx.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
@ -47,10 +45,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#undef min #undef min
#undef max #undef max
// WM_POINTER support from Windows 8 onwards (WINVER >= 0x0602)
#ifndef WM_POINTERUPDATE
# define WM_NCPOINTERUPDATE 0x0241
# define WM_NCPOINTERDOWN 0x0242
# define WM_NCPOINTERUP 0x0243
# define WM_POINTERUPDATE 0x0245
# define WM_POINTERDOWN 0x0246
# define WM_POINTERUP 0x0247
# define WM_POINTERENTER 0x0249
# define WM_POINTERLEAVE 0x024A
# define WM_POINTERACTIVATE 0x024B
# define WM_POINTERCAPTURECHANGED 0x024C
# define WM_POINTERWHEEL 0x024E
# define WM_POINTERHWHEEL 0x024F
#endif // WM_POINTERUPDATE
HICON qt_pixmapToWinHICON(const QPixmap &); HICON qt_pixmapToWinHICON(const QPixmap &);
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
Q_DECLARE_METATYPE(QMargins);
namespace Platform { namespace Platform {
namespace { namespace {
@ -226,7 +242,7 @@ public:
destroy(); destroy();
return false; return false;
} }
SetWindowLong(hwnds[i], GWL_HWNDPARENT, (LONG)hwnd); SetWindowLongPtr(hwnds[i], GWLP_HWNDPARENT, (LONG)hwnd);
dcs[i] = CreateCompatibleDC(screenDC); dcs[i] = CreateCompatibleDC(screenDC);
if (!dcs[i]) { if (!dcs[i]) {
@ -714,18 +730,18 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
switch (mode) { switch (mode) {
case dbiwmWindowAndTray: { case dbiwmWindowAndTray: {
psSetupTrayIcon(); psSetupTrayIcon();
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT); HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
if (psOwner) { if (psOwner) {
SetWindowLong(ps_hWnd, GWL_HWNDPARENT, 0); SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, 0);
psRefreshTaskbarIcon(); psRefreshTaskbarIcon();
} }
} break; } break;
case dbiwmTrayOnly: { case dbiwmTrayOnly: {
psSetupTrayIcon(); psSetupTrayIcon();
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT); HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
if (!psOwner) { if (!psOwner) {
SetWindowLong(ps_hWnd, GWL_HWNDPARENT, (LONG)ps_tbHider_hWnd); SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, (LONG)ps_tbHider_hWnd);
} }
} break; } break;
@ -736,9 +752,9 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
} }
trayIcon = 0; trayIcon = 0;
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT); HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
if (psOwner) { if (psOwner) {
SetWindowLong(ps_hWnd, GWL_HWNDPARENT, 0); SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, 0);
psRefreshTaskbarIcon(); psRefreshTaskbarIcon();
} }
} break; } break;
@ -876,7 +892,6 @@ void MainWindow::updateSystemMenu(Qt::WindowState state) {
} }
} }
Q_DECLARE_METATYPE(QMargins);
void MainWindow::psUpdateMargins() { void MainWindow::psUpdateMargins() {
if (!ps_hWnd || _inUpdateMargins) return; if (!ps_hWnd || _inUpdateMargins) return;
@ -887,7 +902,7 @@ void MainWindow::psUpdateMargins() {
GetClientRect(ps_hWnd, &r); GetClientRect(ps_hWnd, &r);
a = r; a = r;
LONG style = GetWindowLong(ps_hWnd, GWL_STYLE), styleEx = GetWindowLong(ps_hWnd, GWL_EXSTYLE); LONG style = GetWindowLongPtr(ps_hWnd, GWL_STYLE), styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE);
AdjustWindowRectEx(&a, style, false, styleEx); AdjustWindowRectEx(&a, style, false, styleEx);
QMargins margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom); QMargins margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom);
if (style & WS_MAXIMIZE) { if (style & WS_MAXIMIZE) {

View file

@ -20,6 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <roapi.h> #include <roapi.h>
#include <wrl/client.h> #include <wrl/client.h>
#ifndef __MINGW32__
#include "platform/win/wrapper_wrl_implements_h.h" #include "platform/win/wrapper_wrl_implements_h.h"
#include <windows.ui.notifications.h> #include <windows.ui.notifications.h>
@ -32,9 +34,12 @@ using namespace Microsoft::WRL;
using namespace ABI::Windows::UI::Notifications; using namespace ABI::Windows::UI::Notifications;
using namespace ABI::Windows::Data::Xml::Dom; using namespace ABI::Windows::Data::Xml::Dom;
using namespace Windows::Foundation; using namespace Windows::Foundation;
#endif // !__MINGW32__
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
#ifndef __MINGW32__
namespace { namespace {
class StringReferenceWrapper { class StringReferenceWrapper {
@ -302,40 +307,33 @@ void Check() {
} }
} // namespace } // namespace
#endif // !__MINGW32__
bool Supported() { bool Supported() {
#ifndef __MINGW32__
if (!Checked) { if (!Checked) {
Checked = true; Checked = true;
Check(); Check();
} }
return InitSucceeded; return InitSucceeded;
#endif // !__MINGW32__
return false;
} }
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) { std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) {
#ifndef __MINGW32__
if (Global::NativeNotifications() && Supported()) { if (Global::NativeNotifications() && Supported()) {
auto result = std::make_unique<Manager>(system); auto result = std::make_unique<Manager>(system);
if (result->init()) { if (result->init()) {
return std::move(result); return std::move(result);
} }
} }
#endif // !__MINGW32__
return nullptr; return nullptr;
} }
void FlashBounce() { #ifndef __MINGW32__
auto window = App::wnd();
if (!window || GetForegroundWindow() == window->psHwnd()) {
return;
}
FLASHWINFO info;
info.cbSize = sizeof(info);
info.hwnd = window->psHwnd();
info.dwFlags = FLASHW_ALL;
info.dwTimeout = 0;
info.uCount = 1;
FlashWindowEx(&info);
}
class Manager::Private { class Manager::Private {
public: public:
using Type = Window::Notifications::CachedUserpics::Type; using Type = Window::Notifications::CachedUserpics::Type;
@ -612,6 +610,7 @@ void Manager::onBeforeNotificationActivated(PeerId peerId, MsgId msgId) {
void Manager::onAfterNotificationActivated(PeerId peerId, MsgId msgId) { void Manager::onAfterNotificationActivated(PeerId peerId, MsgId msgId) {
_private->afterNotificationActivated(peerId, msgId); _private->afterNotificationActivated(peerId, msgId);
} }
#endif // !__MINGW32__
namespace { namespace {
@ -723,5 +722,9 @@ bool SkipToast() {
return false; return false;
} }
bool SkipFlashBounce() {
return SkipToast();
}
} // namespace Notifications } // namespace Notifications
} // namespace Platform } // namespace Platform

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
#ifndef __MINGW32__
class Manager : public Window::Notifications::NativeManager { class Manager : public Window::Notifications::NativeManager {
public: public:
Manager(Window::Notifications::System *system); Manager(Window::Notifications::System *system);
@ -41,6 +42,7 @@ private:
const std::unique_ptr<Private> _private; const std::unique_ptr<Private> _private;
}; };
#endif // !__MINGW32__
} // namespace Notifications } // namespace Notifications
} // namespace Platform } // namespace Platform

View file

@ -29,8 +29,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <roapi.h> #include <roapi.h>
#include <wrl/client.h> #include <wrl/client.h>
#include "platform/win/wrapper_wrl_implements_h.h"
#include <windows.ui.notifications.h>
#include <openssl/conf.h> #include <openssl/conf.h>
#include <openssl/engine.h> #include <openssl/engine.h>
@ -65,9 +63,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#endif #endif
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
using namespace ABI::Windows::UI::Notifications;
using namespace ABI::Windows::Data::Xml::Dom;
using namespace Windows::Foundation;
using namespace Platform; using namespace Platform;
namespace { namespace {
@ -435,7 +430,7 @@ namespace {
WCHAR defaultStr[bufSize] = { 0 }; WCHAR defaultStr[bufSize] = { 0 };
if (RegQueryValueEx(rkey, value, 0, &defaultType, (BYTE*)defaultStr, &defaultSize) != ERROR_SUCCESS || defaultType != REG_SZ || defaultSize != (v.size() + 1) * 2 || QString::fromStdWString(defaultStr) != v) { if (RegQueryValueEx(rkey, value, 0, &defaultType, (BYTE*)defaultStr, &defaultSize) != ERROR_SUCCESS || defaultType != REG_SZ || defaultSize != (v.size() + 1) * 2 || QString::fromStdWString(defaultStr) != v) {
WCHAR tmp[bufSize] = { 0 }; WCHAR tmp[bufSize] = { 0 };
if (!v.isEmpty()) wsprintf(tmp, v.replace(QChar('%'), qsl("%%")).toStdWString().c_str()); if (!v.isEmpty()) StringCbPrintf(tmp, bufSize, v.replace(QChar('%'), qsl("%%")).toStdWString().c_str());
LSTATUS status = RegSetValueEx(rkey, value, 0, REG_SZ, (BYTE*)tmp, (wcslen(tmp) + 1) * sizeof(WCHAR)); LSTATUS status = RegSetValueEx(rkey, value, 0, REG_SZ, (BYTE*)tmp, (wcslen(tmp) + 1) * sizeof(WCHAR));
if (status != ERROR_SUCCESS) { if (status != ERROR_SUCCESS) {
QString msg = qsl("App Error: could not set %1, error %2").arg(value ? ('\'' + QString::fromStdWString(value) + '\'') : qsl("(Default)")).arg("%1: %2"); QString msg = qsl("App Error: could not set %1, error %2").arg(value ? ('\'' + QString::fromStdWString(value) + '\'') : qsl("(Default)")).arg("%1: %2");

View file

@ -13,8 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <roapi.h> #include <roapi.h>
#include <wrl/client.h> #include <wrl/client.h>
#include "platform/win/wrapper_wrl_implements_h.h"
#include <windows.ui.notifications.h>
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
@ -287,6 +285,7 @@ bool validateShortcut() {
PropVariantClear(&appIdPropVar); PropVariantClear(&appIdPropVar);
if (!SUCCEEDED(hr)) return false; if (!SUCCEEDED(hr)) return false;
#if WINVER >= 0x602
PROPVARIANT startPinPropVar; PROPVARIANT startPinPropVar;
hr = InitPropVariantFromUInt32(APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL, &startPinPropVar); hr = InitPropVariantFromUInt32(APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL, &startPinPropVar);
if (!SUCCEEDED(hr)) return false; if (!SUCCEEDED(hr)) return false;
@ -294,6 +293,7 @@ bool validateShortcut() {
hr = propertyStore->SetValue(pkey_AppUserModel_StartPinOption, startPinPropVar); hr = propertyStore->SetValue(pkey_AppUserModel_StartPinOption, startPinPropVar);
PropVariantClear(&startPinPropVar); PropVariantClear(&startPinPropVar);
if (!SUCCEEDED(hr)) return false; if (!SUCCEEDED(hr)) return false;
#endif // WINVER >= 0x602
hr = propertyStore->Commit(); hr = propertyStore->Commit();
if (!SUCCEEDED(hr)) return false; if (!SUCCEEDED(hr)) return false;

View file

@ -15,6 +15,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <RestartManager.h> #include <RestartManager.h>
#include <psapi.h> #include <psapi.h>
#ifdef __MINGW32__
#define __in
#endif
namespace Platform { namespace Platform {
namespace Dlls { namespace Dlls {

View file

@ -191,7 +191,7 @@ bool EventFilter::mainWindowEvent(
} return false; } return false;
case WM_SHOWWINDOW: { case WM_SHOWWINDOW: {
LONG style = GetWindowLong(hWnd, GWL_STYLE); LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
auto changes = ShadowsChange::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? ShadowsChange::Shown : ShadowsChange::Hidden); auto changes = ShadowsChange::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? ShadowsChange::Shown : ShadowsChange::Hidden);
_window->shadowsUpdate(changes); _window->shadowsUpdate(changes);
} return false; } return false;

View file

@ -39,6 +39,7 @@ bool gStartInTray = false;
bool gAutoStart = false; bool gAutoStart = false;
bool gSendToMenu = false; bool gSendToMenu = false;
bool gUseExternalVideoPlayer = false; bool gUseExternalVideoPlayer = false;
bool gUseFreeType = false;
bool gAutoUpdate = true; bool gAutoUpdate = true;
TWindowPos gWindowPos; TWindowPos gWindowPos;
LaunchMode gLaunchMode = LaunchModeNormal; LaunchMode gLaunchMode = LaunchModeNormal;

View file

@ -42,6 +42,7 @@ DeclareSetting(bool, StartMinimized);
DeclareSetting(bool, StartInTray); DeclareSetting(bool, StartInTray);
DeclareSetting(bool, SendToMenu); DeclareSetting(bool, SendToMenu);
DeclareSetting(bool, UseExternalVideoPlayer); DeclareSetting(bool, UseExternalVideoPlayer);
DeclareSetting(bool, UseFreeType);
enum LaunchMode { enum LaunchMode {
LaunchModeNormal = 0, LaunchModeNormal = 0,
LaunchModeAutoStart, LaunchModeAutoStart,

View file

@ -126,6 +126,21 @@ auto GenerateCodes() {
codes.emplace(qsl("export"), [](SessionController *window) { codes.emplace(qsl("export"), [](SessionController *window) {
window->session().data().startExport(); window->session().data().startExport();
}); });
#if defined Q_OS_WIN || defined Q_OS_MAC
codes.emplace(qsl("freetype"), [](SessionController *window) {
auto text = cUseFreeType()
#ifdef Q_OS_WIN
? qsl("Switch font engine to GDI?")
#else // Q_OS_WIN
? qsl("Switch font engine to Cocoa?")
#endif // !Q_OS_WIN
: qsl("Switch font engine to FreeType?");
Ui::show(Box<ConfirmBox>(text, [] {
Core::App().switchFreeType();
}));
});
#endif // Q_OS_WIN || Q_OS_MAC
auto audioFilters = qsl("Audio files (*.wav *.mp3);;") + FileDialog::AllFilesFilter(); auto audioFilters = qsl("Audio files (*.wav *.mp3);;") + FileDialog::AllFilesFilter();
auto audioKeys = { auto audioKeys = {

View file

@ -568,6 +568,13 @@ void SetupNotificationsContent(
const auto sound = addCheckbox( const auto sound = addCheckbox(
tr::lng_settings_sound_notify(tr::now), tr::lng_settings_sound_notify(tr::now),
Global::SoundNotify()); Global::SoundNotify());
const auto flashbounce = addCheckbox(
(Platform::IsWindows()
? tr::lng_settings_alert_windows
: Platform::IsMac()
? tr::lng_settings_alert_mac
: tr::lng_settings_alert_linux)(tr::now),
Global::FlashBounceNotify());
AddSkip(container, st::settingsCheckboxesSkip); AddSkip(container, st::settingsCheckboxesSkip);
AddDivider(container); AddDivider(container);
@ -714,6 +721,14 @@ void SetupNotificationsContent(
changed(Change::SoundEnabled); changed(Change::SoundEnabled);
}, sound->lifetime()); }, sound->lifetime());
flashbounce->checkedChanges(
) | rpl::filter([](bool checked) {
return (checked != Global::FlashBounceNotify());
}) | rpl::start_with_next([=](bool checked) {
Global::SetFlashBounceNotify(checked);
changed(Change::FlashBounceEnabled);
}, flashbounce->lifetime());
muted->checkedChanges( muted->checkedChanges(
) | rpl::filter([=](bool checked) { ) | rpl::filter([=](bool checked) {
return (checked != session->settings().includeMutedCounter()); return (checked != session->settings().includeMutedCounter());
@ -743,6 +758,8 @@ void SetupNotificationsContent(
preview->toggle(name->entity()->checked(), anim::type::normal); preview->toggle(name->entity()->checked(), anim::type::normal);
} else if (change == Change::SoundEnabled) { } else if (change == Change::SoundEnabled) {
sound->setChecked(Global::SoundNotify()); sound->setChecked(Global::SoundNotify());
} else if (change == Change::FlashBounceEnabled) {
flashbounce->setChecked(Global::FlashBounceNotify());
} }
}, desktop->lifetime()); }, desktop->lifetime());

View file

@ -649,7 +649,7 @@ enum {
dbiSendKeyOld = 0x05, dbiSendKeyOld = 0x05,
dbiAutoStart = 0x06, dbiAutoStart = 0x06,
dbiStartMinimized = 0x07, dbiStartMinimized = 0x07,
dbiSoundNotify = 0x08, dbiSoundFlashBounceNotify = 0x08,
dbiWorkMode = 0x09, dbiWorkMode = 0x09,
dbiSeenTrayTooltip = 0x0a, dbiSeenTrayTooltip = 0x0a,
dbiDesktopNotify = 0x0b, dbiDesktopNotify = 0x0b,
@ -1190,13 +1190,13 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
anim::SetDisabled(disabled == 1); anim::SetDisabled(disabled == 1);
} break; } break;
case dbiSoundNotify: { case dbiSoundFlashBounceNotify: {
qint32 v; qint32 v;
stream >> v; stream >> v;
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
Global::SetSoundNotify(v == 1); Global::SetSoundNotify((v & 0x01) == 0x01);
if (App::wnd()) App::wnd()->updateTrayMenu(); Global::SetFlashBounceNotify((v & 0x02) == 0x00);
} break; } break;
case dbiAutoDownloadOld: { case dbiAutoDownloadOld: {
@ -2204,6 +2204,9 @@ void _writeUserSettings() {
} }
size += sizeof(quint32) + Serialize::bytearraySize(callSettings); size += sizeof(quint32) + Serialize::bytearraySize(callSettings);
const auto soundFlashBounce = (Global::SoundNotify() ? 0x01 : 0x00)
| (Global::FlashBounceNotify() ? 0x00 : 0x02);
EncryptedDescriptor data(size); EncryptedDescriptor data(size);
data.stream data.stream
<< quint32(dbiTileBackground) << quint32(dbiTileBackground)
@ -2211,7 +2214,7 @@ void _writeUserSettings() {
<< qint32(Window::Theme::Background()->tileNight() ? 1 : 0); << qint32(Window::Theme::Background()->tileNight() ? 1 : 0);
data.stream << quint32(dbiAdaptiveForWide) << qint32(Global::AdaptiveForWide() ? 1 : 0); data.stream << quint32(dbiAdaptiveForWide) << qint32(Global::AdaptiveForWide() ? 1 : 0);
data.stream << quint32(dbiAutoLock) << qint32(Global::AutoLock()); data.stream << quint32(dbiAutoLock) << qint32(Global::AutoLock());
data.stream << quint32(dbiSoundNotify) << qint32(Global::SoundNotify()); data.stream << quint32(dbiSoundFlashBounceNotify) << qint32(soundFlashBounce);
data.stream << quint32(dbiDesktopNotify) << qint32(Global::DesktopNotify()); data.stream << quint32(dbiDesktopNotify) << qint32(Global::DesktopNotify());
data.stream << quint32(dbiNotifyView) << qint32(Global::NotifyView()); data.stream << quint32(dbiNotifyView) << qint32(Global::NotifyView());
data.stream << quint32(dbiNativeNotifications) << qint32(Global::NativeNotifications()); data.stream << quint32(dbiNativeNotifications) << qint32(Global::NativeNotifications());

View file

@ -27,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "facades.h" #include "facades.h"
#include "app.h" #include "app.h"
#include <QtGui/QWindow>
namespace Window { namespace Window {
namespace Notifications { namespace Notifications {
namespace { namespace {
@ -290,7 +292,14 @@ void System::showNext() {
} }
} }
if (alert) { if (alert) {
Platform::Notifications::FlashBounce(); if (Global::FlashBounceNotify() && !Platform::Notifications::SkipFlashBounce()) {
if (const auto widget = App::wnd()) {
if (const auto window = widget->windowHandle()) {
window->alert(0);
// (window, SLOT(_q_clearAlert())); in the future.
}
}
}
if (Global::SoundNotify() && !Platform::Notifications::SkipAudio()) { if (Global::SoundNotify() && !Platform::Notifications::SkipAudio()) {
ensureSoundCreated(); ensureSoundCreated();
_soundTrack->playOnce(); _soundTrack->playOnce();

View file

@ -32,6 +32,7 @@ namespace Notifications {
enum class ChangeType { enum class ChangeType {
SoundEnabled, SoundEnabled,
FlashBounceEnabled,
IncludeMuted, IncludeMuted,
CountMessages, CountMessages,
DesktopEnabled, DesktopEnabled,

View file

@ -43,7 +43,7 @@ struct ParsedTheme {
const QByteArray &value); const QByteArray &value);
[[nodiscard]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud); [[nodiscard]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud);
[[nodiscard]] Data::CloudTheme ReadCloudFromText(const QByteArray &text); [[nodiscard]] Data::CloudTheme ReadCloudFromText(const QByteArray &text);
[[nodisacrd]] QByteArray StripCloudTextFields(const QByteArray &text); [[nodiscard]] QByteArray StripCloudTextFields(const QByteArray &text);
class Editor : public TWidget { class Editor : public TWidget {
public: public:

View file

@ -263,6 +263,9 @@ bool SessionController::uniqueChatsInSearchResults() const {
} }
void SessionController::openFolder(not_null<Data::Folder*> folder) { void SessionController::openFolder(not_null<Data::Folder*> folder) {
if (_openedFolder.current() != folder) {
resetFakeUnreadWhileOpened();
}
setActiveChatsFilter(0); setActiveChatsFilter(0);
_openedFolder = folder.get(); _openedFolder = folder.get();
} }
@ -295,6 +298,12 @@ void SessionController::setActiveChatEntry(Dialogs::RowDescriptor row) {
} }
} }
void SessionController::resetFakeUnreadWhileOpened() {
if (const auto history = _activeChatEntry.current().key.history()) {
history->setFakeUnreadWhileOpened(false);
}
}
bool SessionController::chatEntryHistoryMove(int steps) { bool SessionController::chatEntryHistoryMove(int steps) {
if (_chatEntryHistory.empty()) { if (_chatEntryHistory.empty()) {
return false; return false;
@ -807,6 +816,9 @@ FilterId SessionController::activeChatsFilterCurrent() const {
} }
void SessionController::setActiveChatsFilter(FilterId id) { void SessionController::setActiveChatsFilter(FilterId id) {
if (activeChatsFilterCurrent() != id) {
resetFakeUnreadWhileOpened();
}
_activeChatsFilter.force_assign(id); _activeChatsFilter.force_assign(id);
if (id) { if (id) {
closeFolder(true); closeFolder(true);

View file

@ -329,6 +329,7 @@ private:
void pushToChatEntryHistory(Dialogs::RowDescriptor row); void pushToChatEntryHistory(Dialogs::RowDescriptor row);
bool chatEntryHistoryMove(int steps); bool chatEntryHistoryMove(int steps);
void resetFakeUnreadWhileOpened();
const not_null<Controller*> _window; const not_null<Controller*> _window;

1
Telegram/ThirdParty/fcitx5-qt vendored Submodule

@ -0,0 +1 @@
Subproject commit 7561f994a79320a4940a1f95c884004c4dd178f4

@ -1 +1 @@
Subproject commit a045c9eea47b371c0c514c72c76172a211c894cb Subproject commit 2a05b22490c79ab4000f759069a2442797af6e9a

@ -1 +1 @@
Subproject commit 3c280ce86f649c1ea07c7ace5ed58162607c0edd Subproject commit e0ea6af518345c4a46195c4951e023e621a9eb8f

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit 9e01ede6661e2a74697283c7836d4fae433f50ce Subproject commit b376282b656b13c54cd892e3c2742bb26acf42fe

@ -1 +1 @@
Subproject commit 626ff13ec31b041c1d6481a32814998397fd3b61 Subproject commit 661ac4f6bdf8991e7d6cac176d32338ac025b637

@ -1 +1 @@
Subproject commit 2e6262d1d460a723fba61b18e48b54fe45de3551 Subproject commit 1da7b32a3f392eddc1d08075e35ffbe41436034d

2
cmake

@ -1 +1 @@
Subproject commit 81a0fc7970a62e8c1b194bd8eb85890528366ca7 Subproject commit 4ea254886efd273cd4b01eb5128fe67d47959e4e

View file

@ -54,7 +54,7 @@ Go to ***BuildPath*** and run
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout e036126 git checkout b08b497
cd ../ cd ../
git clone https://github.com/xiph/opus git clone https://github.com/xiph/opus
@ -228,12 +228,9 @@ Go to ***BuildPath*** and run
git clone git://code.qt.io/qt/qt5.git qt_5_12_8 git clone git://code.qt.io/qt/qt5.git qt_5_12_8
cd qt_5_12_8 cd qt_5_12_8
perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg,qtx11extras
git checkout v5.12.8 git checkout v5.12.8
git submodule update qtbase git submodule update qtbase qtwayland qtimageformats qtsvg qtx11extras
git submodule update qtwayland
git submodule update qtimageformats
git submodule update qtsvg
cd qtbase cd qtbase
git apply ../../patches/qtbase_5_12_8.diff git apply ../../patches/qtbase_5_12_8.diff
cd .. cd ..

View file

@ -32,7 +32,7 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
cd ThirdParty cd ThirdParty
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout e036126 git checkout b08b497
cd ../ cd ../
git clone https://chromium.googlesource.com/external/gyp git clone https://chromium.googlesource.com/external/gyp
cd gyp cd gyp
@ -64,7 +64,7 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout e036126 git checkout b08b497
cd .. cd ..
git clone https://github.com/desktop-app/lzma.git git clone https://github.com/desktop-app/lzma.git
@ -151,8 +151,7 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
cd qt_5_12_8 cd qt_5_12_8
perl init-repository --module-subset=qtbase,qtimageformats perl init-repository --module-subset=qtbase,qtimageformats
git checkout v5.12.8 git checkout v5.12.8
git submodule update qtbase git submodule update qtbase qtimageformats
git submodule update qtimageformats
cd qtbase cd qtbase
git apply ../../patches/qtbase_5_12_8.diff git apply ../../patches/qtbase_5_12_8.diff
cd .. cd ..

View file

@ -35,7 +35,7 @@ Go to ***BuildPath*** and run
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout 395b620 git checkout b08b497
cd ../ cd ../
git clone https://chromium.googlesource.com/external/gyp git clone https://chromium.googlesource.com/external/gyp
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
@ -52,7 +52,7 @@ Go to ***BuildPath*** and run
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout 395b620 git checkout b08b497
cd ../ cd ../
cd xz-5.0.5 cd xz-5.0.5
@ -235,8 +235,7 @@ Go to ***BuildPath*** and run
cd qt5_6_2 cd qt5_6_2
perl init-repository --module-subset=qtbase,qtimageformats perl init-repository --module-subset=qtbase,qtimageformats
git checkout v5.6.2 git checkout v5.6.2
git submodule update qtbase git submodule update qtbase qtimageformats
git submodule update qtimageformats
cd qtbase cd qtbase
git apply ../../patches/qtbase_5_6_2.diff git apply ../../patches/qtbase_5_6_2.diff
cd .. cd ..

View file

@ -29,7 +29,7 @@ Go to ***BuildPath*** and run
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout e036126 git checkout b08b497
cd ../ cd ../
git clone https://chromium.googlesource.com/external/gyp git clone https://chromium.googlesource.com/external/gyp
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
@ -47,7 +47,7 @@ Go to ***BuildPath*** and run
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout e036126 git checkout b08b497
cd .. cd ..
xz_ver=5.2.4 xz_ver=5.2.4
@ -238,8 +238,7 @@ Go to ***BuildPath*** and run
cd qt5_12_8 cd qt5_12_8
perl init-repository --module-subset=qtbase,qtimageformats perl init-repository --module-subset=qtbase,qtimageformats
git checkout v5.12.8 git checkout v5.12.8
git submodule update qtbase git submodule update qtbase qtimageformats
git submodule update qtimageformats
cd qtbase cd qtbase
git apply ../../patches/qtbase_5_12_8.diff git apply ../../patches/qtbase_5_12_8.diff
cd .. cd ..