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

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

View file

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

View file

@ -12,9 +12,17 @@ jobs:
to_branch: "master"
steps:
- uses: actions/checkout@v1
if: env.SKIP == '0'
- name: Push the code to the master branch.
if: env.SKIP == '0'
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)
echo "Latest tag: $latest_tag"

3
.gitmodules vendored
View file

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

View file

@ -90,7 +90,7 @@ if (LINUX)
PRIVATE
desktop-app::external_statusnotifieritem
desktop-app::external_dbusmenu_qt
desktop-app::external_fcitx_qt5
desktop-app::external_fcitx5_qt5
desktop-app::external_hime_qt
)
endif()
@ -138,7 +138,7 @@ endif()
if (DESKTOP_APP_USE_PACKAGED)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads)
find_package(Threads REQUIRED)
target_link_libraries(Telegram
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})
if (WIN32 AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_link_options(Updater PRIVATE -municode)
endif()
if (LINUX)
target_link_options(Updater PRIVATE -static-libstdc++)
endif()

View file

@ -300,6 +300,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_notifications_position" = "Location on the screen";
"lng_settings_notifications_count" = "Notifications count";
"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_include_muted" = "Include muted chats in unread count";
"lng_settings_count_unread" = "Count unread messages";

View file

@ -6,7 +6,18 @@
//
// 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

View file

@ -6,7 +6,18 @@
//
// 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

View file

@ -268,7 +268,7 @@ int main(int argc, char *argv[])
cout << "Compression start, size: " << resultSize << "\n";
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
compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size

View file

@ -27,7 +27,7 @@ extern "C" {
#include <openssl/evp.h>
} // 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>
#else
#include <lzma.h>

View file

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

View file

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

View file

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

View file

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

View file

@ -543,6 +543,21 @@ void Application::switchTestMode() {
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() {
_launcher->writeInstallBetaVersionsSetting();
}

View file

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

View file

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

View file

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

View file

@ -33,11 +33,11 @@ extern "C" {
#include <openssl/err.h>
} // 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>
#else // Q_OS_WIN
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
#include <lzma.h>
#endif // else of Q_OS_WIN
#endif // else of Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
namespace Core {
namespace {
@ -252,11 +252,11 @@ bool UnpackUpdate(const QString &filepath) {
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
#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
#endif // Q_OS_WIN
#endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
QByteArray compressed = input.readAll();
int32 compressedLen = compressed.size() - hSize;
@ -311,14 +311,14 @@ bool UnpackUpdate(const QString &filepath) {
uncompressed.resize(uncompressedLen);
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;
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) {
LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes));
return false;
}
#else // Q_OS_WIN
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
lzma_stream stream = LZMA_STREAM_INIT;
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));
return false;
}
#endif // Q_OS_WIN
#endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
tempDir.mkdir(tempDir.absolutePath());

View file

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

View file

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

View file

@ -1580,6 +1580,17 @@ void InnerWidget::repaintDialogRow(RowDescriptor 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) {
if (_state == WidgetState::Filtered) {
if (!_peerSearchResults.empty()) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1622,6 +1622,9 @@ bool History::readInboxTillNeedsRequest(MsgId tillId) {
if (unreadMark()) {
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);
}
@ -1639,10 +1642,17 @@ bool History::unreadCountRefreshNeeded(MsgId readTillId) const {
std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
if (isEmpty() || !folderKnown()) {
DEBUG_LOG(("Reading: countStillUnreadLocal unknown %1 and %2."
).arg(Logs::b(isEmpty())
).arg(Logs::b(folderKnown())));
return std::nullopt;
}
if (_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) {
auto result = 0;
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) {
return std::max(*_unreadCount - result, 0);
}
}
}
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()
|| (!loadedAtTop() && !minimalServerId)
|| 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;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -40,6 +40,7 @@ constexpr auto kTestModeDcIdShift = 10000;
constexpr auto kCheckSentRequestsEach = 1 * crl::time(1000);
constexpr auto kKeyOldEnoughForDestroy = 60 * 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.
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.
constexpr auto kAckSendWaiting = 10 * crl::time(1000);
auto SyncTimeRequestDuration = kFastRequestDuration;
using namespace details;
[[nodiscard]] QString LogIdsVector(const QVector<MTPlong> &ids) {
@ -1467,8 +1470,12 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
return badTime ? HandleResult::Ignored : HandleResult::Success;
}
if (badTime && !requestsFixTimeSalt(ids, serverTime, serverSalt)) {
return HandleResult::Ignored;
if (badTime) {
if (!requestsFixTimeSalt(ids, serverTime, serverSalt)) {
return HandleResult::Ignored;
}
} else {
correctUnixtimeByFastRequest(ids, serverTime);
}
requestsAcked(ids);
} return HandleResult::Success;
@ -1520,7 +1527,8 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
if (serverSalt) {
_sessionSalt = serverSalt;
}
base::unixtime::update(serverTime, true);
correctUnixtimeWithBadLocal(serverTime);
DEBUG_LOG(("Message Info: unixtime updated, now %1, resending in container...").arg(serverTime));
@ -1530,7 +1538,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
if (serverSalt) {
_sessionSalt = serverSalt;
}
base::unixtime::update(serverTime, true);
correctUnixtimeWithBadLocal(serverTime);
badTime = false;
}
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;
base::unixtime::update(serverTime);
correctUnixtimeWithBadLocal(serverTime);
if (setState(ConnectedState, ConnectingState)) {
resendAll();
@ -1612,7 +1620,7 @@ SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
if (serverSalt) {
_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));
@ -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) {
uint32 idsCount = ids.size();
for (uint32 i = 0; i < idsCount; ++i) {
if (wasSent(ids[i].v)) {// found such msg_id in recent acked requests or in recent sent requests
for (const auto &id : ids) {
if (wasSent(id.v)) {
// Found such msg_id in recent acked or in recent sent requests.
if (serverSalt) {
_sessionSalt = serverSalt;
}
base::unixtime::update(serverTime, true);
correctUnixtimeWithBadLocal(serverTime);
return true;
}
}
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) {
uint32 idsCount = ids.size();

View file

@ -139,6 +139,12 @@ private:
// if badTime received - search for ids in sessionData->haveSent and sessionData->wereAcked and sync time/salt, return true if found
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
void requestsAcked(const QVector<MTPlong> &ids, bool byResponse = false);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -117,7 +117,13 @@ void UnsafeOpenEmailLink(const QString &email) {
auto wstringUrl = url.toString(QUrl::FullyEncoded).toStdWString();
if (Dlls::SHOpenWithDialog) {
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.pcszFile = wstringUrl.c_str();
Dlls::SHOpenWithDialog(0, &info);

View file

@ -35,8 +35,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <roapi.h>
#include <wrl/client.h>
#include "platform/win/wrapper_wrl_implements_h.h"
#include <windows.ui.notifications.h>
#include <Windowsx.h>
#include <VersionHelpers.h>
@ -47,10 +45,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#undef min
#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 &);
using namespace Microsoft::WRL;
Q_DECLARE_METATYPE(QMargins);
namespace Platform {
namespace {
@ -226,7 +242,7 @@ public:
destroy();
return false;
}
SetWindowLong(hwnds[i], GWL_HWNDPARENT, (LONG)hwnd);
SetWindowLongPtr(hwnds[i], GWLP_HWNDPARENT, (LONG)hwnd);
dcs[i] = CreateCompatibleDC(screenDC);
if (!dcs[i]) {
@ -714,18 +730,18 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
switch (mode) {
case dbiwmWindowAndTray: {
psSetupTrayIcon();
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT);
HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
if (psOwner) {
SetWindowLong(ps_hWnd, GWL_HWNDPARENT, 0);
SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, 0);
psRefreshTaskbarIcon();
}
} break;
case dbiwmTrayOnly: {
psSetupTrayIcon();
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT);
HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
if (!psOwner) {
SetWindowLong(ps_hWnd, GWL_HWNDPARENT, (LONG)ps_tbHider_hWnd);
SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, (LONG)ps_tbHider_hWnd);
}
} break;
@ -736,9 +752,9 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
}
trayIcon = 0;
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT);
HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
if (psOwner) {
SetWindowLong(ps_hWnd, GWL_HWNDPARENT, 0);
SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, 0);
psRefreshTaskbarIcon();
}
} break;
@ -876,7 +892,6 @@ void MainWindow::updateSystemMenu(Qt::WindowState state) {
}
}
Q_DECLARE_METATYPE(QMargins);
void MainWindow::psUpdateMargins() {
if (!ps_hWnd || _inUpdateMargins) return;
@ -887,7 +902,7 @@ void MainWindow::psUpdateMargins() {
GetClientRect(ps_hWnd, &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);
QMargins margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom);
if (style & WS_MAXIMIZE) {

View file

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

View file

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

View file

@ -29,8 +29,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <roapi.h>
#include <wrl/client.h>
#include "platform/win/wrapper_wrl_implements_h.h"
#include <windows.ui.notifications.h>
#include <openssl/conf.h>
#include <openssl/engine.h>
@ -65,9 +63,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#endif
using namespace Microsoft::WRL;
using namespace ABI::Windows::UI::Notifications;
using namespace ABI::Windows::Data::Xml::Dom;
using namespace Windows::Foundation;
using namespace Platform;
namespace {
@ -435,7 +430,7 @@ namespace {
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) {
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));
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");

View file

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

View file

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

View file

@ -191,7 +191,7 @@ bool EventFilter::mainWindowEvent(
} return false;
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);
_window->shadowsUpdate(changes);
} return false;

View file

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

View file

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

View file

@ -126,6 +126,21 @@ auto GenerateCodes() {
codes.emplace(qsl("export"), [](SessionController *window) {
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 audioKeys = {

View file

@ -568,6 +568,13 @@ void SetupNotificationsContent(
const auto sound = addCheckbox(
tr::lng_settings_sound_notify(tr::now),
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);
AddDivider(container);
@ -714,6 +721,14 @@ void SetupNotificationsContent(
changed(Change::SoundEnabled);
}, 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(
) | rpl::filter([=](bool checked) {
return (checked != session->settings().includeMutedCounter());
@ -743,6 +758,8 @@ void SetupNotificationsContent(
preview->toggle(name->entity()->checked(), anim::type::normal);
} else if (change == Change::SoundEnabled) {
sound->setChecked(Global::SoundNotify());
} else if (change == Change::FlashBounceEnabled) {
flashbounce->setChecked(Global::FlashBounceNotify());
}
}, desktop->lifetime());

View file

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

View file

@ -27,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "facades.h"
#include "app.h"
#include <QtGui/QWindow>
namespace Window {
namespace Notifications {
namespace {
@ -290,7 +292,14 @@ void System::showNext() {
}
}
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()) {
ensureSoundCreated();
_soundTrack->playOnce();

View file

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

View file

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

View file

@ -263,6 +263,9 @@ bool SessionController::uniqueChatsInSearchResults() const {
}
void SessionController::openFolder(not_null<Data::Folder*> folder) {
if (_openedFolder.current() != folder) {
resetFakeUnreadWhileOpened();
}
setActiveChatsFilter(0);
_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) {
if (_chatEntryHistory.empty()) {
return false;
@ -807,6 +816,9 @@ FilterId SessionController::activeChatsFilterCurrent() const {
}
void SessionController::setActiveChatsFilter(FilterId id) {
if (activeChatsFilterCurrent() != id) {
resetFakeUnreadWhileOpened();
}
_activeChatsFilter.force_assign(id);
if (id) {
closeFolder(true);

View file

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

1
Telegram/ThirdParty/fcitx5-qt vendored Submodule

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

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

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

File diff suppressed because it is too large Load diff

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

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

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

2
cmake

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

View file

@ -54,7 +54,7 @@ Go to ***BuildPath*** and run
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout e036126
git checkout b08b497
cd ../
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
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 submodule update qtbase
git submodule update qtwayland
git submodule update qtimageformats
git submodule update qtsvg
git submodule update qtbase qtwayland qtimageformats qtsvg qtx11extras
cd qtbase
git apply ../../patches/qtbase_5_12_8.diff
cd ..

View file

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

View file

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

View file

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