Merge remote-tracking branch 'tdesktop/dev' into dev
This commit is contained in:
commit
9e0e5b8f66
76 changed files with 1133 additions and 779 deletions
4
.github/workflows/linux.yml
vendored
4
.github/workflows/linux.yml
vendored
|
|
@ -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 ../
|
||||||
|
|
|
||||||
10
.github/workflows/master_updater.yml
vendored
10
.github/workflows/master_updater.yml
vendored
|
|
@ -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
3
.gitmodules
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ namespace Notifications {
|
||||||
|
|
||||||
enum class ChangeType {
|
enum class ChangeType {
|
||||||
SoundEnabled,
|
SoundEnabled,
|
||||||
|
FlashBounceEnabled,
|
||||||
IncludeMuted,
|
IncludeMuted,
|
||||||
CountMessages,
|
CountMessages,
|
||||||
DesktopEnabled,
|
DesktopEnabled,
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
1
Telegram/ThirdParty/fcitx5-qt
vendored
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7561f994a79320a4940a1f95c884004c4dd178f4
|
||||||
2
Telegram/ThirdParty/libtgvoip
vendored
2
Telegram/ThirdParty/libtgvoip
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit a045c9eea47b371c0c514c72c76172a211c894cb
|
Subproject commit 2a05b22490c79ab4000f759069a2442797af6e9a
|
||||||
2
Telegram/ThirdParty/rlottie
vendored
2
Telegram/ThirdParty/rlottie
vendored
|
|
@ -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
2
cmake
|
|
@ -1 +1 @@
|
||||||
Subproject commit 81a0fc7970a62e8c1b194bd8eb85890528366ca7
|
Subproject commit 4ea254886efd273cd4b01eb5128fe67d47959e4e
|
||||||
|
|
@ -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 ..
|
||||||
|
|
|
||||||
|
|
@ -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 ..
|
||||||
|
|
|
||||||
|
|
@ -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 ..
|
||||||
|
|
|
||||||
|
|
@ -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 ..
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue