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

This commit is contained in:
Eric Kotato 2020-07-01 06:33:36 +03:00
commit b3e4d0b32a
61 changed files with 681 additions and 308 deletions

View file

@ -164,7 +164,7 @@ jobs:
- name: Opus cache. - name: Opus cache.
id: cache-opus id: cache-opus
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/opus path: ${{ env.LibrariesPath }}/opus
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
@ -209,7 +209,7 @@ jobs:
- name: FFmpeg cache. - name: FFmpeg cache.
id: cache-ffmpeg id: cache-ffmpeg
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/ffmpeg-cache path: ${{ env.LibrariesPath }}/ffmpeg-cache
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}
@ -363,7 +363,7 @@ jobs:
- name: OpenSSL cache. - name: OpenSSL cache.
id: cache-openssl id: cache-openssl
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/openssl-cache path: ${{ env.LibrariesPath }}/openssl-cache
key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }}
@ -419,7 +419,7 @@ jobs:
- name: Qt 5.12.8 cache. - name: Qt 5.12.8 cache.
id: cache-qt id: cache-qt
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/qt-cache path: ${{ env.LibrariesPath }}/qt-cache
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qt*_5_12_8/*') }} key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qt*_5_12_8/*') }}
@ -468,7 +468,7 @@ jobs:
- name: Breakpad cache. - name: Breakpad cache.
id: cache-breakpad id: cache-breakpad
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/breakpad-cache path: ${{ env.LibrariesPath }}/breakpad-cache
key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }}

View file

@ -140,7 +140,7 @@ jobs:
- name: OpenSSL cache. - name: OpenSSL cache.
id: cache-openssl id: cache-openssl
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }} path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }}
key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }}
@ -170,7 +170,7 @@ jobs:
- name: Opus cache. - name: Opus cache.
id: cache-opus id: cache-opus
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/opus path: ${{ env.LibrariesPath }}/opus
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
@ -192,7 +192,7 @@ jobs:
- name: Libiconv cache. - name: Libiconv cache.
id: cache-libiconv id: cache-libiconv
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/${{ env.LIBICONV_VER }} path: ${{ env.LibrariesPath }}/${{ env.LIBICONV_VER }}
key: ${{ runner.OS }}-${{ env.LIBICONV_VER }}-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-${{ env.LIBICONV_VER }}-${{ env.CACHE_KEY }}
@ -213,7 +213,7 @@ jobs:
- name: FFmpeg cache. - name: FFmpeg cache.
id: cache-ffmpeg id: cache-ffmpeg
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/ffmpeg-cache path: ${{ env.LibrariesPath }}/ffmpeg-cache
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}
@ -369,7 +369,7 @@ jobs:
- name: Crashpad cache. - name: Crashpad cache.
id: cache-crashpad id: cache-crashpad
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/crashpad path: ${{ env.LibrariesPath }}/crashpad
key: ${{ runner.OS }}-crashpad-${{ env.CACHE_KEY }}-${{ hashFiles('**/crashpad.diff') }}-${{ hashFiles('**/mini_chromium.diff') }} key: ${{ runner.OS }}-crashpad-${{ env.CACHE_KEY }}-${{ hashFiles('**/crashpad.diff') }}-${{ hashFiles('**/mini_chromium.diff') }}
@ -408,7 +408,7 @@ jobs:
- name: Qt 5.12.8 cache. - name: Qt 5.12.8 cache.
id: cache-qt id: cache-qt
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/qt-cache path: ${{ env.LibrariesPath }}/qt-cache
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }} key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}

View file

@ -140,7 +140,7 @@ jobs:
- name: OpenSSL cache. - name: OpenSSL cache.
id: cache-openssl id: cache-openssl
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }} path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }}
key: ${{ runner.OS }}-${{ env.CACHE_KEY }}-${{ env.OPENSSL_VER }} key: ${{ runner.OS }}-${{ env.CACHE_KEY }}-${{ env.OPENSSL_VER }}
@ -184,7 +184,7 @@ jobs:
- name: OpenAL Soft cache. - name: OpenAL Soft cache.
id: cache-openal id: cache-openal
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/openal-soft path: ${{ env.LibrariesPath }}/openal-soft
key: ${{ runner.OS }}-openal-soft-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-openal-soft-${{ env.CACHE_KEY }}
@ -208,7 +208,7 @@ jobs:
- name: Breakpad cache. - name: Breakpad cache.
id: cache-breakpad id: cache-breakpad
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/breakpad path: ${{ env.LibrariesPath }}/breakpad
key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }}-${{ hashFiles('**/breakpad.diff') }} key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }}-${{ hashFiles('**/breakpad.diff') }}
@ -257,7 +257,7 @@ jobs:
- name: Opus cache. - name: Opus cache.
id: cache-opus id: cache-opus
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/opus path: ${{ env.LibrariesPath }}/opus
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }} key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
@ -276,7 +276,7 @@ jobs:
- name: FFmpeg cache. - name: FFmpeg cache.
id: cache-ffmpeg id: cache-ffmpeg
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/ffmpeg path: ${{ env.LibrariesPath }}/ffmpeg
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}-2-${{ hashFiles('**/build_ffmpeg_win.sh') }} key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}-2-${{ hashFiles('**/build_ffmpeg_win.sh') }}
@ -298,7 +298,7 @@ jobs:
- name: Qt 5.12.8 cache. - name: Qt 5.12.8 cache.
id: cache-qt id: cache-qt
uses: actions/cache@v1 uses: actions/cache@v2
with: with:
path: ${{ env.LibrariesPath }}/Qt-5.12.8 path: ${{ env.LibrariesPath }}/Qt-5.12.8
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }} key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_menu_back" = "Back"; "lng_menu_back" = "Back";
"lng_menu_night_mode" = "Night Mode"; "lng_menu_night_mode" = "Night Mode";
"lng_menu_add_account" = "Add Account"; "lng_menu_add_account" = "Add Account";
"lng_menu_activate" = "Activate";
"lng_disable_notifications_from_tray" = "Disable notifications"; "lng_disable_notifications_from_tray" = "Disable notifications";
"lng_enable_notifications_from_tray" = "Enable notifications"; "lng_enable_notifications_from_tray" = "Enable notifications";
@ -291,6 +292,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_empty_bio" = "None"; "lng_settings_empty_bio" = "None";
"lng_settings_section_notify" = "Notifications"; "lng_settings_section_notify" = "Notifications";
"lng_settings_show_from" = "Show notifications from";
"lng_settings_notify_all" = "All accounts";
"lng_settings_notify_all_about" = "Turn this off if you want to receive notifications only from the account you are currently using.";
"lng_settings_notify_title" = "Notifications for chats"; "lng_settings_notify_title" = "Notifications for chats";
"lng_settings_desktop_notify" = "Desktop notifications"; "lng_settings_desktop_notify" = "Desktop notifications";
"lng_settings_show_name" = "Show sender's name"; "lng_settings_show_name" = "Show sender's name";

View file

@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop" <Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE" ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="2.1.14.0" /> Version="2.1.16.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName> <PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>

View file

@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,1,14,0 FILEVERSION 2,1,16,0
PRODUCTVERSION 2,1,14,0 PRODUCTVERSION 2,1,16,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -62,10 +62,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Telegram FZ-LLC" VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop" VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "2.1.14.0" VALUE "FileVersion", "2.1.16.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "LegalCopyright", "Copyright (C) 2014-2020"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.1.14.0" VALUE "ProductVersion", "2.1.16.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,1,14,0 FILEVERSION 2,1,16,0
PRODUCTVERSION 2,1,14,0 PRODUCTVERSION 2,1,16,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -53,10 +53,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Telegram FZ-LLC" VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater" VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "2.1.14.0" VALUE "FileVersion", "2.1.16.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "LegalCopyright", "Copyright (C) 2014-2020"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.1.14.0" VALUE "ProductVersion", "2.1.16.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -368,7 +368,6 @@ public:
not_null<PeerData*> peer, not_null<PeerData*> peer,
const std::vector<not_null<UserData*>> &users); const std::vector<not_null<UserData*>> &users);
rpl::producer<SendAction> sendActions() const { rpl::producer<SendAction> sendActions() const {
return _sendActions.events(); return _sendActions.events();
} }

View file

@ -781,12 +781,12 @@ bool BackgroundPreviewBox::Start(
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now))); Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
return false; return false;
} }
controller->session().api().requestWallPaper(slug, [=]( controller->session().api().requestWallPaper(slug, crl::guard(controller, [=](
const Data::WallPaper &result) { const Data::WallPaper &result) {
Ui::show(Box<BackgroundPreviewBox>( Ui::show(Box<BackgroundPreviewBox>(
controller, controller,
result.withUrlParams(params))); result.withUrlParams(params)));
}, [](const RPCError &error) { }), [](const RPCError &error) {
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now))); Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
}); });
return true; return true;

View file

@ -171,7 +171,7 @@ private:
}; };
class ProxyBox : public Ui::BoxContent { class ProxyBox final : public Ui::BoxContent {
public: public:
ProxyBox( ProxyBox(
QWidget*, QWidget*,
@ -179,12 +179,14 @@ public:
Fn<void(ProxyData)> callback, Fn<void(ProxyData)> callback,
Fn<void(ProxyData)> shareCallback); Fn<void(ProxyData)> shareCallback);
protected:
void prepare() override;
private: private:
using Type = ProxyData::Type; using Type = ProxyData::Type;
void prepare() override;
void setInnerFocus() override {
_host->setFocusFast();
}
void refreshButtons(); void refreshButtons();
ProxyData collectData(); ProxyData collectData();
void save(); void save();
@ -693,8 +695,8 @@ void ProxiesBox::applyView(View &&view) {
setupButtons(id, i->second.get()); setupButtons(id, i->second.get());
if (_noRows) { if (_noRows) {
_noRows.reset(); _noRows.reset();
wrap->resizeToWidth(width());
} }
wrap->resizeToWidth(width());
} else if (view.host.isEmpty()) { } else if (view.host.isEmpty()) {
_rows.erase(i); _rows.erase(i);
} else { } else {
@ -765,6 +767,31 @@ ProxyBox::ProxyBox(
void ProxyBox::prepare() { void ProxyBox::prepare() {
setTitle(tr::lng_proxy_edit()); setTitle(tr::lng_proxy_edit());
connect(_host.data(), &Ui::InputField::changed, [=] {
Ui::PostponeCall(_host, [=] {
const auto host = _host->getLastText().trimmed();
static const auto mask = u"^\\d+\\.\\d+\\.\\d+\\.\\d+:(\\d*)$"_q;
const auto match = QRegularExpression(mask).match(host);
if (_host->textCursor().position() == host.size()
&& match.hasMatch()) {
const auto port = match.captured(1);
_port->setText(port);
_port->setCursorPosition(port.size());
_port->setFocus();
_host->setText(host.mid(0, host.size() - port.size() - 1));
}
});
});
_port.data()->events(
) | rpl::start_with_next([=](not_null<QEvent*> e) {
if (e->type() == QEvent::KeyPress
&& (static_cast<QKeyEvent*>(e.get())->key() == Qt::Key_Backspace)
&& _port->cursorPosition() == 0) {
_host->setCursorPosition(_host->getLastText().size());
_host->setFocus();
}
}, _port->lifetime());
refreshButtons(); refreshButtons();
setDimensionsToContent(st::boxWideWidth, _content); setDimensionsToContent(st::boxWideWidth, _content);
} }

View file

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "base/timer.h" #include "base/timer.h"
#include "base/object_ptr.h" #include "base/object_ptr.h"
#include "data/stickers/data_stickers.h"
namespace Ui { namespace Ui {
class ScrollArea; class ScrollArea;

View file

@ -2512,7 +2512,11 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
externalLayout, externalLayout,
std::move(recentPack)); std::move(recentPack));
if (recentIt == _mySets.end()) { if (recentIt == _mySets.end()) {
_mySets.push_back(std::move(set)); const auto where = (_mySets.empty()
|| _mySets.begin()->id != Data::Stickers::FavedSetId)
? _mySets.begin()
: (_mySets.begin() + 1);
_mySets.insert(where, std::move(set));
} else { } else {
std::swap(*recentIt, set); std::swap(*recentIt, set);
takeHeavyData(*recentIt, set); takeHeavyData(*recentIt, set);
@ -2537,7 +2541,7 @@ void StickersListWidget::refreshFavedStickers() {
const auto set = it->second.get(); const auto set = it->second.get();
const auto externalLayout = false; const auto externalLayout = false;
const auto shortName = QString(); const auto shortName = QString();
_mySets.emplace_back( _mySets.insert(_mySets.begin(), Set{
Data::Stickers::FavedSetId, Data::Stickers::FavedSetId,
nullptr, nullptr,
(MTPDstickerSet::Flag::f_official (MTPDstickerSet::Flag::f_official
@ -2546,7 +2550,8 @@ void StickersListWidget::refreshFavedStickers() {
shortName, shortName,
set->count, set->count,
externalLayout, externalLayout,
PrepareStickers(set->stickers)); PrepareStickers(set->stickers)
});
_favedStickersMap = base::flat_set<not_null<DocumentData*>> { _favedStickersMap = base::flat_set<not_null<DocumentData*>> {
set->stickers.begin(), set->stickers.begin(),
set->stickers.end() set->stickers.end()

View file

@ -174,6 +174,7 @@ Application::~Application() {
_window = nullptr; _window = nullptr;
_mediaView = nullptr; _mediaView = nullptr;
_notifications->clearAllFast();
_domain->finish(); _domain->finish();
Local::finish(); Local::finish();
@ -206,6 +207,7 @@ void Application::run() {
refreshGlobalProxy(); // Depends on Global::start(). refreshGlobalProxy(); // Depends on Global::start().
// Depends on OpenSSL on macOS, so on ThirdParty::start(). // Depends on OpenSSL on macOS, so on ThirdParty::start().
// Depends on notifications settings.
_notifications = std::make_unique<Window::Notifications::System>(); _notifications = std::make_unique<Window::Notifications::System>();
startLocalStorage(); startLocalStorage();

View file

@ -347,6 +347,11 @@ private:
base::Timer _clearEmojiImageLoaderTimer; base::Timer _clearEmojiImageLoaderTimer;
const std::unique_ptr<Media::Audio::Instance> _audio; const std::unique_ptr<Media::Audio::Instance> _audio;
mutable std::unique_ptr<MTP::Config> _fallbackProductionConfig; mutable std::unique_ptr<MTP::Config> _fallbackProductionConfig;
// Notifications should be destroyed before _audio, after _domain.
// Mutable because is created in run() after OpenSSL is inited.
std::unique_ptr<Window::Notifications::System> _notifications;
const std::unique_ptr<Main::Domain> _domain; const std::unique_ptr<Main::Domain> _domain;
const std::unique_ptr<Export::Manager> _exportManager; const std::unique_ptr<Export::Manager> _exportManager;
const std::unique_ptr<Calls::Instance> _calls; const std::unique_ptr<Calls::Instance> _calls;
@ -363,10 +368,6 @@ private:
Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr; Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr;
Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr; Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr;
// Notifications should be destroyed before _audio.
// Mutable because is created in run() after OpenSSL is inited.
std::unique_ptr<Window::Notifications::System> _notifications;
const QImage _logo; const QImage _logo;
const QImage _logoBlue; const QImage _logoBlue;
const QImage _logoGreen; const QImage _logoGreen;

View file

@ -94,7 +94,18 @@ QByteArray Settings::serialize() const {
} }
stream stream
<< qint32(_autoDownloadDictionaries.current() ? 1 : 0) << qint32(_autoDownloadDictionaries.current() ? 1 : 0)
<< qint32(_mainMenuAccountsShown.current() ? 1 : 0); << qint32(_mainMenuAccountsShown.current() ? 1 : 0)
<< qint32(_tabbedSelectorSectionEnabled ? 1 : 0)
<< qint32(_floatPlayerColumn)
<< qint32(_floatPlayerCorner)
<< qint32(_thirdSectionInfoEnabled ? 1 : 0)
<< qint32(snap(
qRound(_dialogsWidthRatio.current() * 1000000),
0,
1000000))
<< qint32(_thirdColumnWidth.current())
<< qint32(_thirdSectionExtendedBy)
<< qint32(_notifyFromAll ? 1 : 0);
} }
return result; return result;
} }
@ -150,6 +161,14 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
std::vector<int> dictionariesEnabled; std::vector<int> dictionariesEnabled;
qint32 autoDownloadDictionaries = _autoDownloadDictionaries.current() ? 1 : 0; qint32 autoDownloadDictionaries = _autoDownloadDictionaries.current() ? 1 : 0;
qint32 mainMenuAccountsShown = _mainMenuAccountsShown.current() ? 1 : 0; qint32 mainMenuAccountsShown = _mainMenuAccountsShown.current() ? 1 : 0;
qint32 tabbedSelectorSectionEnabled = 1;
qint32 floatPlayerColumn = static_cast<qint32>(Window::Column::Second);
qint32 floatPlayerCorner = static_cast<qint32>(RectPart::TopRight);
qint32 thirdSectionInfoEnabled = 0;
float64 dialogsWidthRatio = _dialogsWidthRatio.current();
qint32 thirdColumnWidth = _thirdColumnWidth.current();
qint32 thirdSectionExtendedBy = _thirdSectionExtendedBy;
qint32 notifyFromAll = _notifyFromAll ? 1 : 0;
stream >> themesAccentColors; stream >> themesAccentColors;
if (!stream.atEnd()) { if (!stream.atEnd()) {
@ -211,6 +230,19 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
>> autoDownloadDictionaries >> autoDownloadDictionaries
>> mainMenuAccountsShown; >> mainMenuAccountsShown;
} }
if (!stream.atEnd()) {
auto dialogsWidthRatioInt = qint32();
stream
>> tabbedSelectorSectionEnabled
>> floatPlayerColumn
>> floatPlayerCorner
>> thirdSectionInfoEnabled
>> dialogsWidthRatioInt
>> thirdColumnWidth
>> thirdSectionExtendedBy
>> notifyFromAll;
dialogsWidthRatio = snap(dialogsWidthRatioInt / 1000000., 0., 1.);
}
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("App Error: " LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()")); "Bad data for Core::Settings::constructFromSerialized()"));
@ -281,6 +313,28 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
_dictionariesEnabled = std::move(dictionariesEnabled); _dictionariesEnabled = std::move(dictionariesEnabled);
_autoDownloadDictionaries = (autoDownloadDictionaries == 1); _autoDownloadDictionaries = (autoDownloadDictionaries == 1);
_mainMenuAccountsShown = (mainMenuAccountsShown == 1); _mainMenuAccountsShown = (mainMenuAccountsShown == 1);
_tabbedSelectorSectionEnabled = (tabbedSelectorSectionEnabled == 1);
auto uncheckedColumn = static_cast<Window::Column>(floatPlayerColumn);
switch (uncheckedColumn) {
case Window::Column::First:
case Window::Column::Second:
case Window::Column::Third: _floatPlayerColumn = uncheckedColumn; break;
}
auto uncheckedCorner = static_cast<RectPart>(floatPlayerCorner);
switch (uncheckedCorner) {
case RectPart::TopLeft:
case RectPart::TopRight:
case RectPart::BottomLeft:
case RectPart::BottomRight: _floatPlayerCorner = uncheckedCorner; break;
}
_thirdSectionInfoEnabled = thirdSectionInfoEnabled;
_dialogsWidthRatio = dialogsWidthRatio;
_thirdColumnWidth = thirdColumnWidth;
_thirdSectionExtendedBy = thirdSectionExtendedBy;
if (_thirdSectionInfoEnabled) {
_tabbedSelectorSectionEnabled = false;
}
_notifyFromAll = (notifyFromAll == 1);
} }
bool Settings::chatWide() const { bool Settings::chatWide() const {
@ -412,6 +466,7 @@ void Settings::resetOnLastLogout() {
_thirdSectionExtendedBy = -1; // per-window _thirdSectionExtendedBy = -1; // per-window
_dialogsWidthRatio = DefaultDialogsWidthRatio(); // per-window _dialogsWidthRatio = DefaultDialogsWidthRatio(); // per-window
_thirdColumnWidth = kDefaultThirdColumnWidth; // p-w _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w
_notifyFromAll = true;
_tabbedReplacedWithInfo = false; // per-window _tabbedReplacedWithInfo = false; // per-window
} }

View file

@ -401,6 +401,12 @@ public:
void setThirdColumnWidth(int width); void setThirdColumnWidth(int width);
[[nodiscard]] int thirdColumnWidth() const; [[nodiscard]] int thirdColumnWidth() const;
[[nodiscard]] rpl::producer<int> thirdColumnWidthChanges() const; [[nodiscard]] rpl::producer<int> thirdColumnWidthChanges() const;
void setNotifyFromAll(bool value) {
_notifyFromAll = value;
}
[[nodiscard]] bool notifyFromAll() const {
return _notifyFromAll;
}
[[nodiscard]] static bool ThirdColumnByDefault(); [[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] float64 DefaultDialogsWidthRatio(); [[nodiscard]] float64 DefaultDialogsWidthRatio();
@ -467,6 +473,7 @@ private:
int _thirdSectionExtendedBy = -1; // per-window int _thirdSectionExtendedBy = -1; // per-window
rpl::variable<float64> _dialogsWidthRatio; // per-window rpl::variable<float64> _dialogsWidthRatio; // per-window
rpl::variable<int> _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w rpl::variable<int> _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w
bool _notifyFromAll = true;
bool _tabbedReplacedWithInfo = false; // per-window bool _tabbedReplacedWithInfo = false; // per-window
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window

View file

@ -304,16 +304,13 @@ bool ResolveUsername(
} }
const auto clickFromMessageId = context.value<FullMsgId>(); const auto clickFromMessageId = context.value<FullMsgId>();
const auto searchParam = params.value(qsl("query")); const auto searchParam = params.value(qsl("query"));
if (const auto controller = App::wnd()->sessionController()) { controller->content()->openPeerByName(
controller->content()->openPeerByName( domain,
domain, post,
post, startToken,
startToken, clickFromMessageId,
clickFromMessageId, searchParam);
searchParam); return true;
return true;
}
return false;
} }
bool ResolvePrivatePost( bool ResolvePrivatePost(
@ -331,12 +328,12 @@ bool ResolvePrivatePost(
if (!channelId || !IsServerMsgId(msgId)) { if (!channelId || !IsServerMsgId(msgId)) {
return false; return false;
} }
const auto done = [=](not_null<PeerData*> peer) { const auto done = crl::guard(controller, [=](not_null<PeerData*> peer) {
App::wnd()->sessionController()->showPeerHistory( controller->showPeerHistory(
peer->id, peer->id,
Window::SectionShow::Way::Forward, Window::SectionShow::Way::Forward,
msgId); msgId);
}; });
const auto fail = [=] { const auto fail = [=] {
Ui::show(Box<InformBox>(tr::lng_error_post_link_invalid(tr::now))); Ui::show(Box<InformBox>(tr::lng_error_post_link_invalid(tr::now)));
}; };
@ -400,7 +397,7 @@ bool HandleUnknown(
return false; return false;
} }
const auto request = match->captured(1); const auto request = match->captured(1);
const auto callback = [=](const MTPDhelp_deepLinkInfo &result) { const auto callback = crl::guard(controller, [=](const MTPDhelp_deepLinkInfo &result) {
const auto text = TextWithEntities{ const auto text = TextWithEntities{
qs(result.vmessage()), qs(result.vmessage()),
Api::EntitiesFromMTP( Api::EntitiesFromMTP(
@ -420,7 +417,7 @@ bool HandleUnknown(
} else { } else {
Ui::show(Box<InformBox>(text)); Ui::show(Box<InformBox>(text));
} }
}; });
controller->session().api().requestDeepLinkInfo(request, callback); controller->session().api().requestDeepLinkInfo(request, callback);
return true; return true;
} }

View file

@ -23,7 +23,7 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs; constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Kotatogram Desktop"_cs; constexpr auto AppName = "Kotatogram Desktop"_cs;
constexpr auto AppFile = "Kotatogram"_cs; constexpr auto AppFile = "Kotatogram"_cs;
constexpr auto AppVersion = 2001014; constexpr auto AppVersion = 2001016;
constexpr auto AppVersionStr = "2.1.14"; constexpr auto AppVersionStr = "2.1.16";
constexpr auto AppBetaVersion = true; constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View file

@ -226,7 +226,7 @@ bool ChatFilter::contains(not_null<History*> history) const {
} }
ChatFilters::ChatFilters(not_null<Session*> owner) : _owner(owner) { ChatFilters::ChatFilters(not_null<Session*> owner) : _owner(owner) {
load(); crl::on_main(&owner->session(), [=] { load(); });
} }
ChatFilters::~ChatFilters() = default; ChatFilters::~ChatFilters() = default;
@ -242,6 +242,16 @@ not_null<Dialogs::MainList*> ChatFilters::chatsList(FilterId filterId) {
return pointer.get(); return pointer.get();
} }
void ChatFilters::setPreloaded(const QVector<MTPDialogFilter> &result) {
_loadRequestId = -1;
received(result);
crl::on_main(&_owner->session(), [=] {
if (_loadRequestId == -1) {
_loadRequestId = 0;
}
});
}
void ChatFilters::load() { void ChatFilters::load() {
load(false); load(false);
} }
@ -254,40 +264,44 @@ void ChatFilters::load(bool force) {
api.request(_loadRequestId).cancel(); api.request(_loadRequestId).cancel();
_loadRequestId = api.request(MTPmessages_GetDialogFilters( _loadRequestId = api.request(MTPmessages_GetDialogFilters(
)).done([=](const MTPVector<MTPDialogFilter> &result) { )).done([=](const MTPVector<MTPDialogFilter> &result) {
auto position = 0; received(result.v);
auto changed = false;
for (const auto &filter : result.v) {
auto parsed = ChatFilter::FromTL(filter, _owner);
const auto b = begin(_list) + position, e = end(_list);
const auto i = ranges::find(b, e, parsed.id(), &ChatFilter::id);
if (i == e) {
applyInsert(std::move(parsed), position);
changed = true;
} else if (i == b) {
if (applyChange(*b, std::move(parsed))) {
changed = true;
}
} else {
std::swap(*i, *b);
applyChange(*b, std::move(parsed));
changed = true;
}
++position;
}
while (position < _list.size()) {
applyRemove(position);
changed = true;
}
if (changed || !_loaded) {
_loaded = true;
_listChanged.fire({});
}
_loadRequestId = 0; _loadRequestId = 0;
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_loadRequestId = 0; _loadRequestId = 0;
}).send(); }).send();
} }
void ChatFilters::received(const QVector<MTPDialogFilter> &list) {
auto position = 0;
auto changed = false;
for (const auto &filter : list) {
auto parsed = ChatFilter::FromTL(filter, _owner);
const auto b = begin(_list) + position, e = end(_list);
const auto i = ranges::find(b, e, parsed.id(), &ChatFilter::id);
if (i == e) {
applyInsert(std::move(parsed), position);
changed = true;
} else if (i == b) {
if (applyChange(*b, std::move(parsed))) {
changed = true;
}
} else {
std::swap(*i, *b);
applyChange(*b, std::move(parsed));
changed = true;
}
++position;
}
while (position < _list.size()) {
applyRemove(position);
changed = true;
}
if (changed || !_loaded) {
_loaded = true;
_listChanged.fire({});
}
}
void ChatFilters::apply(const MTPUpdate &update) { void ChatFilters::apply(const MTPUpdate &update) {
update.match([&](const MTPDupdateDialogFilter &data) { update.match([&](const MTPDupdateDialogFilter &data) {
if (const auto filter = data.vfilter()) { if (const auto filter = data.vfilter()) {

View file

@ -99,6 +99,8 @@ public:
explicit ChatFilters(not_null<Session*> owner); explicit ChatFilters(not_null<Session*> owner);
~ChatFilters(); ~ChatFilters();
void setPreloaded(const QVector<MTPDialogFilter> &result);
void load(); void load();
void apply(const MTPUpdate &update); void apply(const MTPUpdate &update);
void set(ChatFilter filter); void set(ChatFilter filter);
@ -129,6 +131,7 @@ public:
private: private:
void load(bool force); void load(bool force);
void received(const QVector<MTPDialogFilter> &list);
bool applyOrder(const QVector<MTPint> &order); bool applyOrder(const QVector<MTPint> &order);
bool applyChange(ChatFilter &filter, ChatFilter &&updated); bool applyChange(ChatFilter &filter, ChatFilter &&updated);
void applyInsert(ChatFilter filter, int position); void applyInsert(ChatFilter filter, int position);

View file

@ -462,9 +462,6 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
: QString()) : QString())
: result->nameOrPhone; : result->nameOrPhone;
if (!minimal && data.is_self() && uname != result->username) {
CrashReports::SetAnnotation("Username", uname);
}
result->setName(fname, lname, pname, uname); result->setName(fname, lname, pname, uname);
if (const auto photo = data.vphoto()) { if (const auto photo = data.vphoto()) {
result->setPhoto(*photo); result->setPhoto(*photo);
@ -2559,6 +2556,7 @@ not_null<WebPageData*> Session::processWebpage(const MTPWebPage &data) {
const auto result = webpage(data.c_webPageEmpty().vid().v); const auto result = webpage(data.c_webPageEmpty().vid().v);
if (result->pendingTill > 0) { if (result->pendingTill > 0) {
result->pendingTill = -1; // failed result->pendingTill = -1; // failed
notifyWebPageUpdateDelayed(result);
} }
return result; return result;
} break; } break;

View file

@ -892,7 +892,7 @@ void Stickers::gifsReceived(const QVector<MTPDocument> &items, int32 hash) {
const auto document = owner().processDocument(item); const auto document = owner().processDocument(item);
if (!document->isGifv()) { if (!document->isGifv()) {
LOG(("API Error: " LOG(("API Error: "
"bad document returned in HistoryWidget::savedGifsGot!")); "bad document returned in Stickers::gifsReceived!"));
continue; continue;
} }

View file

@ -3056,7 +3056,7 @@ void InnerWidget::setupShortcuts() {
}) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) { }) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) {
using Command = Shortcuts::Command; using Command = Shortcuts::Command;
if (_controller->content()->selectingPeer()) { if (_controller->selectingPeer()) {
return; return;
} }
const auto row = _controller->activeChatEntryCurrent(); const auto row = _controller->activeChatEntryCurrent();

View file

@ -212,7 +212,7 @@ Widget::Widget(
}); });
_inner->chosenRow( _inner->chosenRow(
) | rpl::start_with_next([=](const ChosenRow &row) { ) | rpl::start_with_next([=](const ChosenRow &row) {
const auto openSearchResult = !controller->content()->selectingPeer() const auto openSearchResult = !controller->selectingPeer()
&& row.filteredRow; && row.filteredRow;
if (const auto history = row.key.history()) { if (const auto history = row.key.history()) {
controller->content()->choosePeer( controller->content()->choosePeer(
@ -701,7 +701,7 @@ void Widget::escape() {
} else if (controller()->activeChatsFilterCurrent() != cDefaultFilterId()) { } else if (controller()->activeChatsFilterCurrent() != cDefaultFilterId()) {
controller()->setActiveChatsFilter(cDefaultFilterId()); controller()->setActiveChatsFilter(cDefaultFilterId());
} }
} else if (!_searchInChat && !controller()->content()->selectingPeer()) { } else if (!_searchInChat && !controller()->selectingPeer()) {
if (controller()->activeChatEntryCurrent().key) { if (controller()->activeChatEntryCurrent().key) {
emit cancelled(); emit cancelled();
} }
@ -1267,7 +1267,7 @@ void Widget::peopleFailed(const RPCError &error, mtpRequestId requestId) {
void Widget::dragEnterEvent(QDragEnterEvent *e) { void Widget::dragEnterEvent(QDragEnterEvent *e) {
using namespace Storage; using namespace Storage;
if (controller()->content()->selectingPeer()) { if (controller()->selectingPeer()) {
return; return;
} }
@ -1616,7 +1616,7 @@ void Widget::updateControlsGeometry() {
} }
void Widget::updateForwardBar() { void Widget::updateForwardBar() {
auto selecting = controller()->content()->selectingPeer(); auto selecting = controller()->selectingPeer();
auto oneColumnSelecting = (Adaptive::OneColumn() && selecting); auto oneColumnSelecting = (Adaptive::OneColumn() && selecting);
if (!oneColumnSelecting == !_forwardCancel) { if (!oneColumnSelecting == !_forwardCancel) {
return; return;
@ -1759,7 +1759,7 @@ bool Widget::onCancelSearch() {
void Widget::onCancelSearchInChat() { void Widget::onCancelSearchInChat() {
cancelSearchRequest(); cancelSearchRequest();
if (_searchInChat) { if (_searchInChat) {
if (Adaptive::OneColumn() && !controller()->content()->selectingPeer()) { if (Adaptive::OneColumn() && !controller()->selectingPeer()) {
if (const auto peer = _searchInChat.peer()) { if (const auto peer = _searchInChat.peer()) {
Ui::showPeerHistory(peer, ShowAtUnreadMsgId); Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
//} else if (const auto feed = _searchInChat.feed()) { // #feed //} else if (const auto feed = _searchInChat.feed()) { // #feed
@ -1774,7 +1774,7 @@ void Widget::onCancelSearchInChat() {
_filter->clear(); _filter->clear();
_filter->updatePlaceholder(); _filter->updatePlaceholder();
applyFilterUpdate(); applyFilterUpdate();
if (!Adaptive::OneColumn() && !controller()->content()->selectingPeer()) { if (!Adaptive::OneColumn() && !controller()->selectingPeer()) {
emit cancelled(); emit cancelled();
} }
} }
@ -1786,6 +1786,8 @@ void Widget::onDialogMoved(int movedFrom, int movedTo) {
} }
} }
Widget::~Widget() = default; Widget::~Widget() {
cancelSearchRequest();
}
} // namespace Dialogs } // namespace Dialogs

View file

@ -46,6 +46,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_scheduled_messages.h" #include "data/data_scheduled_messages.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/stickers/data_stickers.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history_message.h" #include "history/history_message.h"
@ -260,6 +261,7 @@ HistoryWidget::HistoryWidget(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Window::AbstractSectionWidget(parent, controller) : Window::AbstractSectionWidget(parent, controller)
, _api(&controller->session().mtp())
, _updateEditTimeLeftDisplay([=] { updateField(); }) , _updateEditTimeLeftDisplay([=] { updateField(); })
, _fieldBarCancel(this, st::historyReplyCancel) , _fieldBarCancel(this, st::historyReplyCancel)
, _previewTimer([=] { requestPreview(); }) , _previewTimer([=] { requestPreview(); })
@ -1219,14 +1221,14 @@ void HistoryWidget::updateInlineBotQuery() {
if (_inlineBotUsername != query.username) { if (_inlineBotUsername != query.username) {
_inlineBotUsername = query.username; _inlineBotUsername = query.username;
if (_inlineBotResolveRequestId) { if (_inlineBotResolveRequestId) {
session().api().request(_inlineBotResolveRequestId).cancel(); _api.request(_inlineBotResolveRequestId).cancel();
_inlineBotResolveRequestId = 0; _inlineBotResolveRequestId = 0;
} }
if (query.lookingUpBot) { if (query.lookingUpBot) {
_inlineBot = nullptr; _inlineBot = nullptr;
_inlineLookingUpBot = true; _inlineLookingUpBot = true;
const auto username = _inlineBotUsername; const auto username = _inlineBotUsername;
_inlineBotResolveRequestId = session().api().request(MTPcontacts_ResolveUsername( _inlineBotResolveRequestId = _api.request(MTPcontacts_ResolveUsername(
MTP_string(username) MTP_string(username)
)).done([=](const MTPcontacts_ResolvedPeer &result) { )).done([=](const MTPcontacts_ResolvedPeer &result) {
inlineBotResolveDone(result); inlineBotResolveDone(result);
@ -1477,7 +1479,7 @@ void HistoryWidget::cancelSendAction(
SendAction::Type type) { SendAction::Type type) {
const auto i = _sendActionRequests.find({ history, type }); const auto i = _sendActionRequests.find({ history, type });
if (i != _sendActionRequests.end()) { if (i != _sendActionRequests.end()) {
session().api().request(i->second).cancel(); _api.request(i->second).cancel();
_sendActionRequests.erase(i); _sendActionRequests.erase(i);
} }
} }
@ -1518,7 +1520,7 @@ void HistoryWidget::updateSendAction(
case Type::ChooseContact: action = MTP_sendMessageChooseContactAction(); break; case Type::ChooseContact: action = MTP_sendMessageChooseContactAction(); break;
case Type::PlayGame: action = MTP_sendMessageGamePlayAction(); break; case Type::PlayGame: action = MTP_sendMessageGamePlayAction(); break;
} }
const auto requestId = session().api().request(MTPmessages_SetTyping( const auto requestId = _api.request(MTPmessages_SetTyping(
peer->input, peer->input,
action action
)).done([=](const MTPBool &result, mtpRequestId requestId) { )).done([=](const MTPBool &result, mtpRequestId requestId) {
@ -3155,6 +3157,7 @@ void HistoryWidget::saveEditMsg() {
sendFlags |= MTPmessages_EditMessage::Flag::f_entities; sendFlags |= MTPmessages_EditMessage::Flag::f_entities;
} }
const auto weak = Ui::MakeWeak(this);
const auto history = _history; const auto history = _history;
_saveEditMsgRequestId = history->session().api().request( _saveEditMsgRequestId = history->session().api().request(
MTPmessages_EditMessage( MTPmessages_EditMessage(
@ -3166,55 +3169,60 @@ void HistoryWidget::saveEditMsg() {
MTPReplyMarkup(), MTPReplyMarkup(),
sentEntities, sentEntities,
MTP_int(0) MTP_int(0)
)).done([=](const MTPUpdates &result, mtpRequestId requestId) { )).done([history, weak](const MTPUpdates &result, mtpRequestId requestId) {
saveEditMsgDone(history, result, requestId); SaveEditMsgDone(history, result, requestId);
}).fail([=](const RPCError &error, mtpRequestId requestId) { if (const auto strong = weak.data()) {
saveEditMsgFail(history, error, requestId); if (requestId == strong->_saveEditMsgRequestId) {
strong->_saveEditMsgRequestId = 0;
strong->cancelEdit();
}
}
}).fail([history, weak](const RPCError &error, mtpRequestId requestId) {
SaveEditMsgFail(history, error, requestId);
if (const auto strong = weak.data()) {
if (requestId == strong->_saveEditMsgRequestId) {
strong->_saveEditMsgRequestId = 0;
}
const auto &err = error.type();
if (err == qstr("MESSAGE_ID_INVALID")
|| err == qstr("CHAT_ADMIN_REQUIRED")
|| err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
strong->cancelEdit();
} else if (err == qstr("MESSAGE_EMPTY")) {
strong->_field->selectAll();
strong->_field->setFocus();
} else {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
}
strong->update();
}
}).send(); }).send();
} }
void HistoryWidget::saveEditMsgDone( void HistoryWidget::SaveEditMsgDone(
not_null<History*> history, not_null<History*> history,
const MTPUpdates &updates, const MTPUpdates &updates,
mtpRequestId requestId) { mtpRequestId requestId) {
session().api().applyUpdates(updates); history->session().api().applyUpdates(updates);
if (requestId == _saveEditMsgRequestId) {
_saveEditMsgRequestId = 0;
cancelEdit();
}
if (auto editDraft = history->editDraft()) { if (auto editDraft = history->editDraft()) {
if (editDraft->saveRequestId == requestId) { if (editDraft->saveRequestId == requestId) {
history->clearEditDraft(); history->clearEditDraft();
session().local().writeDrafts(history); history->session().local().writeDrafts(history);
} }
} }
} }
void HistoryWidget::saveEditMsgFail( void HistoryWidget::SaveEditMsgFail(
not_null<History*> history, not_null<History*> history,
const RPCError &error, const RPCError &error,
mtpRequestId requestId) { mtpRequestId requestId) {
if (requestId == _saveEditMsgRequestId) {
_saveEditMsgRequestId = 0;
}
if (auto editDraft = history->editDraft()) { if (auto editDraft = history->editDraft()) {
if (editDraft->saveRequestId == requestId) { if (editDraft->saveRequestId == requestId) {
editDraft->saveRequestId = 0; editDraft->saveRequestId = 0;
} }
} }
const auto &err = error.type();
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
cancelEdit();
} else if (err == qstr("MESSAGE_EMPTY")) {
_field->selectAll();
_field->setFocus();
} else {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
}
update();
} }
void HistoryWidget::hideSelectorControlsAnimated() { void HistoryWidget::hideSelectorControlsAnimated() {
@ -3775,6 +3783,7 @@ void HistoryWidget::app_sendBotCallback(
using ButtonType = HistoryMessageMarkupButton::Type; using ButtonType = HistoryMessageMarkupButton::Type;
BotCallbackInfo info = { BotCallbackInfo info = {
&session(),
bot, bot,
msg->fullId(), msg->fullId(),
row, row,
@ -3789,15 +3798,24 @@ void HistoryWidget::app_sendBotCallback(
flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_data; flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_data;
sendData = button->data; sendData = button->data;
} }
const auto weak = Ui::MakeWeak(this);
button->requestId = session().api().request(MTPmessages_GetBotCallbackAnswer( button->requestId = session().api().request(MTPmessages_GetBotCallbackAnswer(
MTP_flags(flags), MTP_flags(flags),
_peer->input, _peer->input,
MTP_int(msg->id), MTP_int(msg->id),
MTP_bytes(sendData) MTP_bytes(sendData)
)).done([=](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) { )).done([info, weak](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) {
botCallbackDone(info, result, requestId); BotCallbackDone(info, result, requestId);
}).fail([=](const RPCError &error, mtpRequestId requestId) { result.match([&](const MTPDmessages_botCallbackAnswer &data) {
botCallbackFail(info, error, requestId); const auto item = info.session->data().message(info.msgId);
if (!data.vmessage() && data.vurl() && info.game && item) {
if (const auto strong = weak.data()) {
strong->updateSendAction(item->history(), SendAction::Type::PlayGame);
}
}
});
}).fail([info](const RPCError &error, mtpRequestId requestId) {
BotCallbackFail(info, error, requestId);
}).send(); }).send();
session().data().requestItemRepaint(msg); session().data().requestItemRepaint(msg);
@ -3810,19 +3828,20 @@ void HistoryWidget::app_sendBotCallback(
} }
} }
void HistoryWidget::botCallbackDone( void HistoryWidget::BotCallbackDone(
BotCallbackInfo info, BotCallbackInfo info,
const MTPmessages_BotCallbackAnswer &answer, const MTPmessages_BotCallbackAnswer &answer,
mtpRequestId req) { mtpRequestId req) {
const auto item = session().data().message(info.msgId); const auto session = info.session;
const auto item = session->data().message(info.msgId);
const auto button = HistoryMessageMarkupButton::Get( const auto button = HistoryMessageMarkupButton::Get(
&session().data(), &session->data(),
info.msgId, info.msgId,
info.row, info.row,
info.col); info.col);
if (button && button->requestId == req) { if (button && button->requestId == req) {
button->requestId = 0; button->requestId = 0;
session().data().requestItemRepaint(item); session->data().requestItemRepaint(item);
} }
answer.match([&](const MTPDmessages_botCallbackAnswer &data) { answer.match([&](const MTPDmessages_botCallbackAnswer &data) {
if (const auto message = data.vmessage()) { if (const auto message = data.vmessage()) {
@ -3834,11 +3853,8 @@ void HistoryWidget::botCallbackDone(
} else if (const auto url = data.vurl()) { } else if (const auto url = data.vurl()) {
auto link = qs(*url); auto link = qs(*url);
if (info.game) { if (info.game) {
link = AppendShareGameScoreUrl(&session(), link, info.msgId); link = AppendShareGameScoreUrl(session, link, info.msgId);
BotGameUrlClickHandler(info.bot, link).onClick({}); BotGameUrlClickHandler(info.bot, link).onClick({});
if (item) {
updateSendAction(item->history(), SendAction::Type::PlayGame);
}
} else { } else {
UrlClickHandler::Open(link); UrlClickHandler::Open(link);
} }
@ -3846,21 +3862,21 @@ void HistoryWidget::botCallbackDone(
}); });
} }
bool HistoryWidget::botCallbackFail( void HistoryWidget::BotCallbackFail(
BotCallbackInfo info, BotCallbackInfo info,
const RPCError &error, const RPCError &error,
mtpRequestId req) { mtpRequestId req) {
// show error? // show error?
const auto owner = &info.session->data();
const auto button = HistoryMessageMarkupButton::Get( const auto button = HistoryMessageMarkupButton::Get(
&session().data(), owner,
info.msgId, info.msgId,
info.row, info.row,
info.col); info.col);
if (button && button->requestId == req) { if (button && button->requestId == req) {
button->requestId = 0; button->requestId = 0;
session().data().requestItemRepaint(session().data().message(info.msgId)); owner->requestItemRepaint(owner->message(info.msgId));
} }
return true;
} }
bool HistoryWidget::insertBotCommand(const QString &cmd) { bool HistoryWidget::insertBotCommand(const QString &cmd) {
@ -5037,12 +5053,11 @@ void HistoryWidget::updateControlsGeometry() {
} }
void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) { void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
if (item == _replyEditMsg) { if (item == _replyEditMsg && _editMsgId) {
if (_editMsgId) { cancelEdit();
cancelEdit(); }
} else { if (item == _replyEditMsg && _replyToId) {
cancelReply(); cancelReply();
}
} }
while (item == _replyReturn) { while (item == _replyReturn) {
calcNextReplyReturn(); calcNextReplyReturn();
@ -6129,7 +6144,13 @@ void HistoryWidget::pinMessage(FullMsgId itemId) {
} }
void HistoryWidget::unpinMessage(FullMsgId itemId) { void HistoryWidget::unpinMessage(FullMsgId itemId) {
const auto peer = _peer; if (!_peer) {
return;
}
UnpinMessage(_peer);
}
void HistoryWidget::UnpinMessage(not_null<PeerData*> peer) {
if (!peer) { if (!peer) {
return; return;
} }
@ -6291,7 +6312,7 @@ void HistoryWidget::cancelFieldAreaState() {
} }
void HistoryWidget::previewCancel() { void HistoryWidget::previewCancel() {
session().api().request(base::take(_previewRequest)).cancel(); _api.request(base::take(_previewRequest)).cancel();
_previewData = nullptr; _previewData = nullptr;
_previewLinks.clear(); _previewLinks.clear();
updatePreview(); updatePreview();
@ -6307,7 +6328,7 @@ void HistoryWidget::checkPreview() {
} }
const auto links = _parsedLinks.join(' '); const auto links = _parsedLinks.join(' ');
if (_previewLinks != links) { if (_previewLinks != links) {
session().api().request(base::take(_previewRequest)).cancel(); _api.request(base::take(_previewRequest)).cancel();
_previewLinks = links; _previewLinks = links;
if (_previewLinks.isEmpty()) { if (_previewLinks.isEmpty()) {
if (_previewData && _previewData->pendingTill >= 0) { if (_previewData && _previewData->pendingTill >= 0) {
@ -6316,7 +6337,7 @@ void HistoryWidget::checkPreview() {
} else { } else {
const auto i = _previewCache.constFind(links); const auto i = _previewCache.constFind(links);
if (i == _previewCache.cend()) { if (i == _previewCache.cend()) {
_previewRequest = session().api().request(MTPmessages_GetWebPagePreview( _previewRequest = _api.request(MTPmessages_GetWebPagePreview(
MTP_flags(0), MTP_flags(0),
MTP_string(links), MTP_string(links),
MTPVector<MTPMessageEntity>() MTPVector<MTPMessageEntity>()
@ -6340,7 +6361,7 @@ void HistoryWidget::requestPreview() {
return; return;
} }
const auto links = _previewLinks; const auto links = _previewLinks;
_previewRequest = session().api().request(MTPmessages_GetWebPagePreview( _previewRequest = _api.request(MTPmessages_GetWebPagePreview(
MTP_flags(0), MTP_flags(0),
MTP_string(links), MTP_string(links),
MTPVector<MTPMessageEntity>() MTPVector<MTPMessageEntity>()

View file

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "mtproto/sender.h"
#include "base/flags.h" #include "base/flags.h"
#include "base/timer.h" #include "base/timer.h"
@ -339,6 +340,7 @@ private:
using TabbedSelector = ChatHelpers::TabbedSelector; using TabbedSelector = ChatHelpers::TabbedSelector;
using DragState = Storage::MimeDataState; using DragState = Storage::MimeDataState;
struct BotCallbackInfo { struct BotCallbackInfo {
not_null<Main::Session*> session;
UserData *bot; UserData *bot;
FullMsgId msgId; FullMsgId msgId;
int row, col; int row, col;
@ -571,8 +573,8 @@ private:
void createUnreadBarAndResize(); void createUnreadBarAndResize();
void saveEditMsg(); void saveEditMsg();
void saveEditMsgDone(not_null<History*> history, const MTPUpdates &updates, mtpRequestId requestId); static void SaveEditMsgDone(not_null<History*> history, const MTPUpdates &updates, mtpRequestId requestId);
void saveEditMsgFail(not_null<History*> history, const RPCError &error, mtpRequestId requestId); static void SaveEditMsgFail(not_null<History*> history, const RPCError &error, mtpRequestId requestId);
void checkPreview(); void checkPreview();
void requestPreview(); void requestPreview();
@ -582,8 +584,10 @@ private:
void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages); void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages);
void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages); void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages);
void botCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req); static void UnpinMessage(not_null<PeerData*> peer);
bool botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req);
static void BotCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req);
static void BotCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req);
void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 }); void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
void updateListSize(); void updateListSize();
@ -648,6 +652,7 @@ private:
void setupScheduledToggle(); void setupScheduledToggle();
void refreshScheduledToggle(); void refreshScheduledToggle();
MTP::Sender _api;
MsgId _replyToId = 0; MsgId _replyToId = 0;
Ui::Text::String _replyToName; Ui::Text::String _replyToName;
int _replyToNameVersion = 0; int _replyToNameVersion = 0;

View file

@ -27,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/slide_animation.h" #include "ui/effects/slide_animation.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_auto_download.h" #include "data/data_auto_download.h"
#include "data/data_session.h"
#include "data/data_chat_filters.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "app.h" #include "app.h"
@ -160,6 +162,18 @@ void Step::finish(const MTPUser &user, QImage &&photo) {
} }
} }
api().request(MTPmessages_GetDialogFilters(
)).done([=](const MTPVector<MTPDialogFilter> &result) {
createSession(user, photo, result.v);
}).fail([=](const RPCError &error) {
createSession(user, photo, QVector<MTPDialogFilter>());
}).send();
}
void Step::createSession(
const MTPUser &user,
QImage photo,
const QVector<MTPDialogFilter> &filters) {
// Save the default language if we've suggested some other and user ignored it. // Save the default language if we've suggested some other and user ignored it.
const auto currentId = Lang::Current().id(); const auto currentId = Lang::Current().id();
const auto defaultId = Lang::DefaultLanguageId(); const auto defaultId = Lang::DefaultLanguageId();
@ -168,12 +182,20 @@ void Step::finish(const MTPUser &user, QImage &&photo) {
Lang::Current().switchToId(Lang::DefaultLanguage()); Lang::Current().switchToId(Lang::DefaultLanguage());
Local::writeLangPack(); Local::writeLangPack();
} }
auto settings = std::make_unique<Main::SessionSettings>();
settings->setDialogsFiltersEnabled(!filters.isEmpty());
const auto account = _account; const auto account = _account;
account->createSession(user); account->createSession(user, std::move(settings));
// "this" is already deleted here by creating the main widget. // "this" is already deleted here by creating the main widget.
account->local().writeMtpData(); account->local().writeMtpData();
auto &session = account->session(); auto &session = account->session();
session.data().chatsFilters().setPreloaded(filters);
if (!filters.isEmpty()) {
session.saveSettingsDelayed();
}
if (!photo.isNull()) { if (!photo.isNull()) {
session.api().uploadPeerPhoto(session.user(), std::move(photo)); session.api().uploadPeerPhoto(session.user(), std::move(photo));
} }

View file

@ -106,6 +106,10 @@ protected:
return _data; return _data;
} }
void finish(const MTPUser &user, QImage &&photo = QImage()); void finish(const MTPUser &user, QImage &&photo = QImage());
void createSession(
const MTPUser &user,
QImage photo,
const QVector<MTPDialogFilter> &filters);
void goBack(); void goBack();

View file

@ -426,7 +426,7 @@ void SetupKotatoSystem(
AddSkip(container); AddSkip(container);
AddSubsectionTitle(container, tr::ktg_settings_system()); AddSubsectionTitle(container, tr::ktg_settings_system());
#if defined Q_OS_WIN || defined Q_OS_MAC #if defined Q_OS_WIN || defined Q_OS_MAC || QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
const auto useNativeDecorationsToggled = Ui::CreateChild<rpl::event_stream<bool>>( const auto useNativeDecorationsToggled = Ui::CreateChild<rpl::event_stream<bool>>(
container.get()); container.get());
AddButton( AddButton(
@ -453,7 +453,7 @@ void SetupKotatoSystem(
confirmed, confirmed,
cancelled)); cancelled));
}, container->lifetime()); }, container->lifetime());
#endif // Q_OS_WIN || Q_OS_MAC #endif // Q_OS_WIN || Q_OS_MAC || Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
AddButton( AddButton(
container, container,

View file

@ -131,8 +131,14 @@ uint64 Account::willHaveSessionUniqueId(MTP::Config *config) const {
| (config && config->isTestMode() ? 0x0100'0000'0000'0000ULL : 0ULL); | (config && config->isTestMode() ? 0x0100'0000'0000'0000ULL : 0ULL);
} }
void Account::createSession(const MTPUser &user) { void Account::createSession(
createSession(user, QByteArray(), 0, std::make_unique<SessionSettings>()); const MTPUser &user,
std::unique_ptr<SessionSettings> settings) {
createSession(
user,
QByteArray(),
0,
settings ? std::move(settings) : std::make_unique<SessionSettings>());
} }
void Account::createSession( void Account::createSession(

View file

@ -49,7 +49,9 @@ public:
void start(std::unique_ptr<MTP::Config> config); void start(std::unique_ptr<MTP::Config> config);
[[nodiscard]] uint64 willHaveSessionUniqueId(MTP::Config *config) const; [[nodiscard]] uint64 willHaveSessionUniqueId(MTP::Config *config) const;
void createSession(const MTPUser &user); void createSession(
const MTPUser &user,
std::unique_ptr<SessionSettings> settings = nullptr);
void createSession( void createSession(
UserId id, UserId id,
QByteArray serialized, QByteArray serialized,

View file

@ -24,6 +24,13 @@ AppConfig::AppConfig(not_null<Account*> account) : _account(account) {
_api.emplace(instance); _api.emplace(instance);
refresh(); refresh();
}, _lifetime); }, _lifetime);
account->sessionChanges(
) | rpl::filter([=](Session *session) {
return (session != nullptr);
}) | rpl::start_with_next([=] {
refresh();
}, _lifetime);
} }
void AppConfig::refresh() { void AppConfig::refresh() {

View file

@ -9,15 +9,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "core/shortcuts.h" #include "core/shortcuts.h"
#include "core/crash_reports.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_changes.h"
#include "data/data_user.h"
#include "mtproto/mtproto_config.h" #include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "storage/storage_domain.h" #include "storage/storage_domain.h"
#include "storage/storage_account.h" #include "storage/storage_account.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "export/export_settings.h" #include "export/export_settings.h"
#include "window/notifications_manager.h"
#include "facades.h" #include "facades.h"
namespace Main { namespace Main {
@ -28,6 +32,22 @@ Domain::Domain(const QString &dataName)
_active.changes( _active.changes(
) | rpl::take(1) | rpl::start_with_next([] { ) | rpl::take(1) | rpl::start_with_next([] {
Local::rewriteSettingsIfNeeded(); Local::rewriteSettingsIfNeeded();
Core::App().notifications().createManager();
}, _lifetime);
_active.changes(
) | rpl::map([](Main::Account *account) {
return account ? account->sessionValue() : rpl::never<Session*>();
}) | rpl::flatten_latest(
) | rpl::map([](Main::Session *session) {
return session
? session->changes().peerFlagsValue(
session->user(),
Data::PeerUpdate::Flag::Username)
: rpl::never<Data::PeerUpdate>();
}) | rpl::flatten_latest(
) | rpl::start_with_next([](const Data::PeerUpdate &update) {
CrashReports::SetAnnotation("Username", update.peer->userName());
}, _lifetime); }, _lifetime);
} }
@ -253,6 +273,20 @@ not_null<Main::Account*> Domain::add(MTP::Environment environment) {
return account; return account;
} }
void Domain::addActivated(MTP::Environment environment) {
if (accounts().size() < Main::Domain::kMaxAccounts) {
activate(add(environment));
} else {
for (auto &[index, account] : accounts()) {
if (!account->sessionExists()
&& account->mtp().environment() == environment) {
activate(account.get());
break;
}
}
}
}
void Domain::watchSession(not_null<Account*> account) { void Domain::watchSession(not_null<Account*> account) {
account->sessionValue( account->sessionValue(
) | rpl::filter([=](Session *session) { ) | rpl::filter([=](Session *session) {

View file

@ -64,6 +64,7 @@ public:
[[nodiscard]] not_null<Main::Account*> add(MTP::Environment environment); [[nodiscard]] not_null<Main::Account*> add(MTP::Environment environment);
void activate(not_null<Main::Account*> account); void activate(not_null<Main::Account*> account);
void addActivated(MTP::Environment environment);
// Interface for Storage::Domain. // Interface for Storage::Domain.
void accountAddedInStorage(AccountWithIndex accountWithIndex); void accountAddedInStorage(AccountWithIndex accountWithIndex);

View file

@ -230,6 +230,7 @@ MainWidget::MainWidget(
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: RpWidget(parent) : RpWidget(parent)
, _controller(controller) , _controller(controller)
, _api(&controller->session().mtp())
, _dialogsWidth(st::columnMinimalWidthLeft) , _dialogsWidth(st::columnMinimalWidthLeft)
, _thirdColumnWidth(st::columnMinimalWidthThird) , _thirdColumnWidth(st::columnMinimalWidthThird)
, _sideShadow(this) , _sideShadow(this)
@ -370,8 +371,6 @@ MainWidget::MainWidget(
cSetOtherOnline(0); cSetOtherOnline(0);
_history->start(); _history->start();
Core::App().checkStartUrl();
} }
MainWidget::~MainWidget() = default; MainWidget::~MainWidget() = default;
@ -621,6 +620,8 @@ void MainWidget::clearHider(not_null<Window::HistoryHider*> instance) {
return; return;
} }
_hider.release(); _hider.release();
controller()->setSelectingPeer(false);
if (Adaptive::OneColumn()) { if (Adaptive::OneColumn()) {
if (_mainSection || (_history->peer() && _history->peer()->id)) { if (_mainSection || (_history->peer() && _history->peer()->id)) {
auto animationParams = ([=] { auto animationParams = ([=] {
@ -646,6 +647,8 @@ void MainWidget::hiderLayer(base::unique_qptr<Window::HistoryHider> hider) {
} }
_hider = std::move(hider); _hider = std::move(hider);
controller()->setSelectingPeer(true);
_hider->setParent(this); _hider->setParent(this);
_hider->hidden( _hider->hidden(
@ -1274,7 +1277,6 @@ void MainWidget::scheduleViewIncrement(HistoryItem *item) {
} }
void MainWidget::viewsIncrement() { void MainWidget::viewsIncrement() {
const auto api = &session().api();
for (auto i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) { for (auto i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) {
if (_viewsIncrementRequests.contains(i->first)) { if (_viewsIncrementRequests.contains(i->first)) {
++i; ++i;
@ -1286,7 +1288,7 @@ void MainWidget::viewsIncrement() {
for (const auto msgId : i->second) { for (const auto msgId : i->second) {
ids.push_back(MTP_int(msgId)); ids.push_back(MTP_int(msgId));
} }
const auto requestId = api->request(MTPmessages_GetMessagesViews( const auto requestId = _api.request(MTPmessages_GetMessagesViews(
i->first->input, i->first->input,
MTP_vector<MTPint>(ids), MTP_vector<MTPint>(ids),
MTP_bool(true) MTP_bool(true)
@ -1417,6 +1419,7 @@ void MainWidget::ui_showPeerHistory(
if (_hider) { if (_hider) {
_hider->startHide(); _hider->startHide();
_hider.release(); _hider.release();
controller()->setSelectingPeer(false);
} }
auto animatedShow = [&] { auto animatedShow = [&] {
@ -2648,7 +2651,7 @@ void MainWidget::openPeerByName(
}); });
} }
} else { } else {
session().api().request(MTPcontacts_ResolveUsername( _api.request(MTPcontacts_ResolveUsername(
MTP_string(username) MTP_string(username)
)).done([=](const MTPcontacts_ResolvedPeer &result) { )).done([=](const MTPcontacts_ResolvedPeer &result) {
usernameResolveDone(result, msgId, startToken); usernameResolveDone(result, msgId, startToken);

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "media/player/media_player_float.h" #include "media/player/media_player_float.h"
#include "mtproto/sender.h"
#include "data/data_pts_waiter.h" #include "data/data_pts_waiter.h"
class RPCError; class RPCError;
@ -355,6 +356,7 @@ private:
void handleHistoryBack(); void handleHistoryBack();
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
MTP::Sender _api;
Ui::Animations::Simple _a_show; Ui::Animations::Simple _a_show;
bool _showBack = false; bool _showBack = false;

View file

@ -39,7 +39,7 @@ VolumeController::VolumeController(
Core::App().settings().setRememberedSongVolume(volume); Core::App().settings().setRememberedSongVolume(volume);
} }
applyVolumeChange(volume); applyVolumeChange(volume);
controller->session().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
}); });
Core::App().settings().songVolumeChanges( Core::App().settings().songVolumeChanges(
) | rpl::start_with_next([=](float64 volume) { ) | rpl::start_with_next([=](float64 volume) {

View file

@ -132,6 +132,7 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
? 0. ? 0.
: Core::App().settings().rememberedSongVolume(); : Core::App().settings().rememberedSongVolume();
Core::App().settings().setSongVolume(volume); Core::App().settings().setSongVolume(volume);
Core::App().saveSettingsDelayed();
mixer()->setSongVolume(volume); mixer()->setSongVolume(volume);
}); });
Core::App().settings().songVolumeChanges( Core::App().settings().songVolumeChanges(

View file

@ -2655,10 +2655,8 @@ void OverlayWidget::playbackControlsSeekFinished(crl::time position) {
void OverlayWidget::playbackControlsVolumeChanged(float64 volume) { void OverlayWidget::playbackControlsVolumeChanged(float64 volume) {
Core::App().settings().setVideoVolume(volume); Core::App().settings().setVideoVolume(volume);
Core::App().saveSettingsDelayed();
updateMixerVideoVolume(); updateMixerVideoVolume();
if (_document) {
_document->session().saveSettingsDelayed();
}
} }
float64 OverlayWidget::playbackControlsCurrentVolume() { float64 OverlayWidget::playbackControlsCurrentVolume() {

View file

@ -253,11 +253,10 @@ void start() {
// change the icon theme only if it isn't already set by a platformtheme plugin // change the icon theme only if it isn't already set by a platformtheme plugin
// if QT_QPA_PLATFORMTHEME=(gtk2|gtk3), then force-apply the icon theme // if QT_QPA_PLATFORMTHEME=(gtk2|gtk3), then force-apply the icon theme
if ((((QIcon::themeName() == qstr("hicolor") // QGenericUnixTheme if (((QIcon::themeName() == qstr("hicolor") // QGenericUnixTheme
&& QIcon::fallbackThemeName() == qstr("hicolor")) && QIcon::fallbackThemeName() == qstr("hicolor"))
|| (QIcon::themeName() == qstr("Adwaita") // QGnomeTheme || (QIcon::themeName() == qstr("Adwaita") // QGnomeTheme
&& QIcon::fallbackThemeName() == qstr("gnome"))) && QIcon::fallbackThemeName() == qstr("gnome")))
&& DesktopEnvironment::IsGtkBased())
|| IsGtkIntegrationForced()) { || IsGtkIntegrationForced()) {
DEBUG_LOG(("Set GTK icon theme")); DEBUG_LOG(("Set GTK icon theme"));
QIcon::setThemeName(gtkSetting("gtk-icon-theme-name")); QIcon::setThemeName(gtkSetting("gtk-icon-theme-name"));

View file

@ -582,7 +582,9 @@ void Manager::Private::showNotification(
const QString &msg, const QString &msg,
bool hideNameAndPhoto, bool hideNameAndPhoto,
bool hideReplyButton) { bool hideReplyButton) {
if (!Supported()) return; if (!Supported()) {
return;
}
const auto key = FullPeer{ const auto key = FullPeer{
.sessionId = peer->session().uniqueId(), .sessionId = peer->session().uniqueId(),
@ -630,7 +632,9 @@ void Manager::Private::showNotification(
} }
void Manager::Private::clearAll() { void Manager::Private::clearAll() {
if (!Supported()) return; if (!Supported()) {
return;
}
for (const auto &[key, notifications] : base::take(_notifications)) { for (const auto &[key, notifications] : base::take(_notifications)) {
for (const auto &[msgId, notification] : notifications) { for (const auto &[msgId, notification] : notifications) {
@ -640,7 +644,9 @@ void Manager::Private::clearAll() {
} }
void Manager::Private::clearFromHistory(not_null<History*> history) { void Manager::Private::clearFromHistory(not_null<History*> history) {
if (!Supported()) return; if (!Supported()) {
return;
}
const auto key = FullPeer{ const auto key = FullPeer{
.sessionId = history->session().uniqueId(), .sessionId = history->session().uniqueId(),
@ -658,23 +664,29 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
} }
void Manager::Private::clearFromSession(not_null<Main::Session*> session) { void Manager::Private::clearFromSession(not_null<Main::Session*> session) {
if (!Supported()) return; if (!Supported()) {
return;
}
const auto sessionId = session->uniqueId(); const auto sessionId = session->uniqueId();
for (auto i = _notifications.begin(); i != _notifications.end();) { for (auto i = _notifications.begin(); i != _notifications.end();) {
if (i->first.sessionId == sessionId) { if (i->first.sessionId != sessionId) {
const auto temp = base::take(i->second); ++i;
i = _notifications.erase(i); continue;
}
const auto temp = base::take(i->second);
i = _notifications.erase(i);
for (const auto &[msgId, notification] : temp) { for (const auto &[msgId, notification] : temp) {
notification->close(); notification->close();
}
} }
} }
} }
void Manager::Private::clearNotification(NotificationId id) { void Manager::Private::clearNotification(NotificationId id) {
if (!Supported()) return; if (!Supported()) {
return;
}
auto i = _notifications.find(id.full); auto i = _notifications.find(id.full);
if (i != _notifications.cend()) { if (i != _notifications.cend()) {

View file

@ -520,6 +520,7 @@ QString GetIconName() {
} }
bool GtkClipboardSupported() { bool GtkClipboardSupported() {
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
return (Libs::gtk_clipboard_get != nullptr) return (Libs::gtk_clipboard_get != nullptr)
&& (Libs::gtk_clipboard_wait_for_contents != nullptr) && (Libs::gtk_clipboard_wait_for_contents != nullptr)
&& (Libs::gtk_clipboard_wait_for_image != nullptr) && (Libs::gtk_clipboard_wait_for_image != nullptr)
@ -531,6 +532,9 @@ bool GtkClipboardSupported() {
&& (Libs::gdk_pixbuf_get_rowstride != nullptr) && (Libs::gdk_pixbuf_get_rowstride != nullptr)
&& (Libs::gdk_pixbuf_get_has_alpha != nullptr) && (Libs::gdk_pixbuf_get_has_alpha != nullptr)
&& (Libs::gdk_atom_intern != nullptr); && (Libs::gdk_atom_intern != nullptr);
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
return false;
} }
QImage GetImageFromClipboard() { QImage GetImageFromClipboard() {

View file

@ -1,10 +1,13 @@
/* /*
This file is part of Telegram Desktop, This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service. the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once
#ifndef OS_OSX
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
@ -12,13 +15,15 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
namespace Platform { namespace Platform {
enum class TouchBarType { enum class TouchBarType {
None, None,
Main, Main,
AudioPlayer, AudioPlayer,
AudioPlayerForce, AudioPlayerForce,
}; };
} // namespace
} // namespace Platform
@interface TouchBar : NSTouchBar @interface TouchBar : NSTouchBar
@ -31,3 +36,5 @@ enum class TouchBarType {
- (void) showInputFieldItem:(bool)show; - (void) showInputFieldItem:(bool)show;
@end @end
#endif // OS_OSX

View file

@ -1,13 +1,13 @@
/* /*
This file is part of Telegram Desktop, This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service. the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "platform/mac/mac_touchbar.h"
#import "mac_touchbar.h" #ifndef OS_OSX
#import <QuartzCore/QuartzCore.h>
#include "api/api_sending.h" #include "api/api_sending.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -49,6 +49,8 @@
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#import <QuartzCore/QuartzCore.h>
namespace { namespace {
//https://developer.apple.com/design/human-interface-guidelines/macos/touch-bar/touch-bar-icons-and-images/ //https://developer.apple.com/design/human-interface-guidelines/macos/touch-bar/touch-bar-icons-and-images/
constexpr auto kIdealIconSize = 36; constexpr auto kIdealIconSize = 36;
@ -1905,3 +1907,5 @@ void AppendEmojiPacks(
} }
@end // @implementation TouchBar @end // @implementation TouchBar
#endif // OS_OSX

View file

@ -144,9 +144,9 @@ public:
void didExitFullScreen(); void didExitFullScreen();
bool clipboardHasText(); bool clipboardHasText();
#ifndef OS_OSX
TouchBar *_touchBar = nil; TouchBar *_touchBar = nil;
#endif // OS_OSX
~Private(); ~Private();
private: private:
@ -197,7 +197,9 @@ private:
} }
- (void) darkModeChanged:(NSNotification *)aNotification { - (void) darkModeChanged:(NSNotification *)aNotification {
Core::App().domain().notifyUnreadBadgeChanged(); Core::Sandbox::Instance().customEnterFromEventLoop([&] {
Core::App().domain().notifyUnreadBadgeChanged();
});
} }
- (void) screenIsLocked:(NSNotification *)aNotification { - (void) screenIsLocked:(NSNotification *)aNotification {
@ -486,6 +488,7 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
} }
void MainWindow::initTouchBar() { void MainWindow::initTouchBar() {
#ifndef OS_OSX
if (!IsMac10_13OrGreater()) { if (!IsMac10_13OrGreater()) {
return; return;
} }
@ -513,14 +516,17 @@ void MainWindow::initTouchBar() {
destroyCurrentTouchBar(); destroyCurrentTouchBar();
} }
}, lifetime()); }, lifetime());
#endif // OS_OSX
} }
void MainWindow::destroyCurrentTouchBar() { void MainWindow::destroyCurrentTouchBar() {
#ifndef OS_OSX
if (_private->_touchBar) { if (_private->_touchBar) {
[_private->_touchBar setTouchBar:Platform::TouchBarType::None]; [_private->_touchBar setTouchBar:Platform::TouchBarType::None];
[_private->_touchBar release]; [_private->_touchBar release];
} }
_private->_touchBar = nil; _private->_touchBar = nil;
#endif // OS_OSX
} }
void MainWindow::closeWithoutDestroy() { void MainWindow::closeWithoutDestroy() {
@ -844,9 +850,13 @@ void MainWindow::updateGlobalMenuHook() {
canCopy = list->canCopySelected(); canCopy = list->canCopySelected();
canDelete = list->canDeleteSelected(); canDelete = list->canDeleteSelected();
} }
#ifndef OS_OSX
if (_private->_touchBar) { if (_private->_touchBar) {
[_private->_touchBar showInputFieldItem:showTouchBarItem]; [_private->_touchBar showInputFieldItem:showTouchBarItem];
} }
#endif // OS_OSX
App::wnd()->updateIsActive(); App::wnd()->updateIsActive();
const auto logged = (sessionController() != nullptr); const auto logged = (sessionController() != nullptr);
const auto inactive = !logged || controller().locked(); const auto inactive = !logged || controller().locked();

View file

@ -415,7 +415,9 @@ Manager::Private::~Private() {
} }
void Manager::Private::clearAll() { void Manager::Private::clearAll() {
if (!_notifier) return; if (!_notifier) {
return;
}
auto temp = base::take(_notifications); auto temp = base::take(_notifications);
for (const auto &[key, notifications] : base::take(_notifications)) { for (const auto &[key, notifications] : base::take(_notifications)) {
@ -426,7 +428,9 @@ void Manager::Private::clearAll() {
} }
void Manager::Private::clearFromHistory(not_null<History*> history) { void Manager::Private::clearFromHistory(not_null<History*> history) {
if (!_notifier) return; if (!_notifier) {
return;
}
auto i = _notifications.find(FullPeer{ auto i = _notifications.find(FullPeer{
.sessionId = history->session().uniqueId(), .sessionId = history->session().uniqueId(),
@ -443,17 +447,21 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
} }
void Manager::Private::clearFromSession(not_null<Main::Session*> session) { void Manager::Private::clearFromSession(not_null<Main::Session*> session) {
if (!_notifier) return; if (!_notifier) {
return;
}
const auto sessionId = session->uniqueId(); const auto sessionId = session->uniqueId();
for (auto i = _notifications.begin(); i != _notifications.end();) { for (auto i = _notifications.begin(); i != _notifications.end();) {
if (i->first.sessionId == sessionId) { if (i->first.sessionId != sessionId) {
const auto temp = base::take(i->second); ++i;
_notifications.erase(i); continue;
}
const auto temp = base::take(i->second);
_notifications.erase(i);
for (const auto &[msgId, notification] : temp) { for (const auto &[msgId, notification] : temp) {
_notifier->Hide(notification.p.Get()); _notifier->Hide(notification.p.Get());
}
} }
} }
} }

View file

@ -52,7 +52,7 @@ Calls::Calls(
Calls::~Calls() { Calls::~Calls() {
if (_needWriteSettings) { if (_needWriteSettings) {
_controller->session().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
} }
} }
@ -134,7 +134,7 @@ void Calls::setupContent() {
: "default"; : "default";
Core::App().settings().setCallOutputDeviceID( Core::App().settings().setCallOutputDeviceID(
QString::fromStdString(deviceId)); QString::fromStdString(deviceId));
_controller->session().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
if (const auto call = Core::App().calls().currentCall()) { if (const auto call = Core::App().calls().currentCall()) {
call->setCurrentAudioDevice(false, deviceId); call->setCurrentAudioDevice(false, deviceId);
} }
@ -210,7 +210,7 @@ void Calls::setupContent() {
: "default"; : "default";
Core::App().settings().setCallInputDeviceID( Core::App().settings().setCallInputDeviceID(
QString::fromStdString(deviceId)); QString::fromStdString(deviceId));
_controller->session().saveSettingsDelayed(); Core::App().saveSettingsDelayed();
if (_micTester) { if (_micTester) {
stopTestingMicrophone(); stopTestingMicrophone();
} }

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_folders.h" #include "settings/settings_folders.h"
#include "settings/settings_calls.h" #include "settings/settings_calls.h"
#include "kotato/settings_menu.h" #include "kotato/settings_menu.h"
#include "core/application.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
@ -30,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h" #include "mainwindow.h"
#include "app.h" #include "app.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_domain.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
@ -200,6 +202,12 @@ void FillMenu(
tr::lng_settings_bg_theme_create(tr::now), tr::lng_settings_bg_theme_create(tr::now),
[=] { window->show(Box(Window::Theme::CreateBox, window)); }); [=] { window->show(Box(Window::Theme::CreateBox, window)); });
} else { } else {
const auto &list = Core::App().domain().accounts();
if (list.size() < ::Main::Domain::kMaxAccounts) {
addAction(tr::lng_menu_add_account(tr::now), [=] {
Core::App().domain().addActivated(MTP::Environment{});
});
}
const auto customSettingsFile = cWorkingDir() + "tdata/kotato-settings-custom.json"; const auto customSettingsFile = cWorkingDir() + "tdata/kotato-settings-custom.json";
if (type != Type::Kotato && !controller->session().supportMode()) { if (type != Type::Kotato && !controller->session().supportMode()) {
addAction( addAction(

View file

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h" #include "mainwindow.h"
#include "core/application.h" #include "core/application.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_account.h"
#include "main/main_domain.h" #include "main/main_domain.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "facades.h" #include "facades.h"
@ -540,9 +541,49 @@ void SetupAdvancedNotifications(
AddSkip(container, st::settingsCheckboxesSkip); AddSkip(container, st::settingsCheckboxesSkip);
} }
void SetupMultiAccountNotifications(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
if (Core::App().domain().accounts().size() < 2) {
return;
}
AddSubsectionTitle(container, tr::lng_settings_show_from());
const auto fromAll = container->add(
object_ptr<Ui::Checkbox>(
container,
tr::lng_settings_notify_all(tr::now),
Core::App().settings().notifyFromAll(),
st::settingsCheckbox),
st::settingsCheckboxPadding);
fromAll->checkedChanges(
) | rpl::filter([](bool checked) {
return (checked != Core::App().settings().notifyFromAll());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setNotifyFromAll(checked);
Core::App().saveSettingsDelayed();
if (!checked) {
auto &notifications = Core::App().notifications();
const auto &list = Core::App().domain().accounts();
for (const auto &[index, account] : list) {
if (account.get() == &Core::App().domain().active()) {
continue;
} else if (const auto session = account->maybeSession()) {
notifications.clearFromSession(session);
}
}
}
}, fromAll->lifetime());
AddSkip(container);
AddDividerText(container, tr::lng_settings_notify_all_about());
}
void SetupNotificationsContent( void SetupNotificationsContent(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container) {
SetupMultiAccountNotifications(controller, container);
AddSubsectionTitle(container, tr::lng_settings_notify_title()); AddSubsectionTitle(container, tr::lng_settings_notify_title());
const auto session = &controller->session(); const auto session = &controller->session();

View file

@ -204,8 +204,9 @@ PeerData *readPeer(
const auto loaded = (peerId == selfId) const auto loaded = (peerId == selfId)
? session->user().get() ? session->user().get()
: session->data().peerLoaded(peerId); : session->data().peerLoaded(peerId);
const auto apply = !loaded || (loaded->loadedStatus != PeerData::FullLoaded);
const auto result = loaded ? loaded : session->data().peer(peerId).get(); const auto result = loaded ? loaded : session->data().peer(peerId).get();
if (!loaded) { if (apply) {
result->loadedStatus = PeerData::FullLoaded; result->loadedStatus = PeerData::FullLoaded;
} }
if (const auto user = result->asUser()) { if (const auto user = result->asUser()) {
@ -230,7 +231,7 @@ PeerData *readPeer(
? App::formatPhone(phone) ? App::formatPhone(phone)
: QString(); : QString();
if (!loaded) { if (apply) {
user->setPhone(phone); user->setPhone(phone);
user->setName(first, last, pname, username); user->setName(first, last, pname, username);
@ -268,7 +269,7 @@ PeerData *readPeer(
if (oldForbidden) { if (oldForbidden) {
flags |= quint32(MTPDchat_ClientFlag::f_forbidden); flags |= quint32(MTPDchat_ClientFlag::f_forbidden);
} }
if (!loaded) { if (apply) {
chat->setName(name); chat->setName(name);
chat->count = count; chat->count = count;
chat->date = date; chat->date = date;
@ -296,7 +297,7 @@ PeerData *readPeer(
if (oldForbidden) { if (oldForbidden) {
flags |= quint32(MTPDchannel_ClientFlag::f_forbidden); flags |= quint32(MTPDchannel_ClientFlag::f_forbidden);
} }
if (!loaded) { if (apply) {
channel->setName(name, QString()); channel->setName(name, QString());
channel->access = access; channel->access = access;
channel->date = date; channel->date = date;
@ -312,7 +313,7 @@ PeerData *readPeer(
channel->inputChannel = MTP_inputChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access)); channel->inputChannel = MTP_inputChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access));
} }
} }
if (!loaded) { if (apply) {
using LocationType = StorageFileLocation::Type; using LocationType = StorageFileLocation::Type;
const auto location = (userpic->valid() && userpic->isLegacy()) const auto location = (userpic->valid() && userpic->isLegacy())
? userpic->convertToModern( ? userpic->convertToModern(

View file

@ -286,7 +286,6 @@ std::optional<PreparedList> PreparedList::PreparedFileFromFilesDialog(
} }
if (!result.remoteContent.isEmpty()) { if (!result.remoteContent.isEmpty()) {
auto list = Storage::PrepareMediaFromImage( auto list = Storage::PrepareMediaFromImage(
QImage(), QImage(),
std::move(result.remoteContent), std::move(result.remoteContent),
@ -311,7 +310,7 @@ std::optional<PreparedList> PreparedList::PreparedFileFromFilesDialog(
} }
} }
Expects(list.files.size() == 1); Expects(list.files.size() == 1);
return std::move(list); return list;
} else if (!result.paths.isEmpty()) { } else if (!result.paths.isEmpty()) {
const auto isSingleFile = (result.paths.size() == 1); const auto isSingleFile = (result.paths.size() == 1);
auto temp = Storage::PrepareMediaList(result.paths, previewWidth); auto temp = Storage::PrepareMediaList(result.paths, previewWidth);
@ -366,7 +365,7 @@ std::optional<PreparedList> PreparedList::PreparedFileFromFilesDialog(
list.allFilesForCompress = temp.allFilesForCompress; list.allFilesForCompress = temp.allFilesForCompress;
list.files = std::move(filteredFiles); list.files = std::move(filteredFiles);
return std::move(list); return list;
} }
return std::nullopt; return std::nullopt;
} }

View file

@ -52,8 +52,6 @@ constexpr auto kSystemAlertDuration = crl::time(0);
System::System() System::System()
: _waitTimer([=] { showNext(); }) : _waitTimer([=] { showNext(); })
, _waitForAllGroupedTimer([=] { showGrouped(); }) { , _waitForAllGroupedTimer([=] { showGrouped(); }) {
createManager();
subscribe(settingsChanged(), [=](ChangeType type) { subscribe(settingsChanged(), [=](ChangeType type) {
if (type == ChangeType::DesktopEnabled) { if (type == ChangeType::DesktopEnabled) {
App::wnd()->updateTrayMenu(); App::wnd()->updateTrayMenu();
@ -93,6 +91,9 @@ System::SkipState System::skipNotification(
const auto notifyBy = item->specialNotificationPeer(); const auto notifyBy = item->specialNotificationPeer();
if (App::quitting() || !history->currentNotification()) { if (App::quitting() || !history->currentNotification()) {
return { SkipState::Skip }; return { SkipState::Skip };
} else if (!Core::App().settings().notifyFromAll()
&& &history->session().account() != &Core::App().domain().active()) {
return { SkipState::Skip };
} }
const auto scheduled = item->out() && item->isFromScheduled(); const auto scheduled = item->out() && item->isFromScheduled();
@ -176,7 +177,9 @@ void System::schedule(not_null<HistoryItem*> item) {
} }
void System::clearAll() { void System::clearAll() {
_manager->clearAll(); if (_manager) {
_manager->clearAll();
}
for (auto i = _whenMaps.cbegin(), e = _whenMaps.cend(); i != e; ++i) { for (auto i = _whenMaps.cbegin(), e = _whenMaps.cend(); i != e; ++i) {
i->first->clearNotifications(); i->first->clearNotifications();
@ -188,7 +191,9 @@ void System::clearAll() {
} }
void System::clearFromHistory(not_null<History*> history) { void System::clearFromHistory(not_null<History*> history) {
_manager->clearFromHistory(history); if (_manager) {
_manager->clearFromHistory(history);
}
history->clearNotifications(); history->clearNotifications();
_whenMaps.remove(history); _whenMaps.remove(history);
@ -201,19 +206,21 @@ void System::clearFromHistory(not_null<History*> history) {
} }
void System::clearFromSession(not_null<Main::Session*> session) { void System::clearFromSession(not_null<Main::Session*> session) {
_manager->clearFromSession(session); if (_manager) {
_manager->clearFromSession(session);
}
for (auto i = _whenMaps.begin(); i != _whenMaps.end();) { for (auto i = _whenMaps.begin(); i != _whenMaps.end();) {
const auto history = i->first; const auto history = i->first;
if (&history->session() == session) { if (&history->session() != session) {
history->clearNotifications();
i = _whenMaps.erase(i);
_whenAlerts.remove(history);
_waiters.remove(history);
_settingWaiters.remove(history);
} else {
++i; ++i;
continue;
} }
history->clearNotifications();
i = _whenMaps.erase(i);
_whenAlerts.remove(history);
_waiters.remove(history);
_settingWaiters.remove(history);
} }
const auto clearFrom = [&](auto &map) { const auto clearFrom = [&](auto &map) {
for (auto i = map.begin(); i != map.end();) { for (auto i = map.begin(); i != map.end();) {
@ -230,17 +237,23 @@ void System::clearFromSession(not_null<Main::Session*> session) {
} }
void System::clearIncomingFromHistory(not_null<History*> history) { void System::clearIncomingFromHistory(not_null<History*> history) {
_manager->clearFromHistory(history); if (_manager) {
_manager->clearFromHistory(history);
}
history->clearIncomingNotifications(); history->clearIncomingNotifications();
_whenAlerts.remove(history); _whenAlerts.remove(history);
} }
void System::clearFromItem(not_null<HistoryItem*> item) { void System::clearFromItem(not_null<HistoryItem*> item) {
_manager->clearFromItem(item); if (_manager) {
_manager->clearFromItem(item);
}
} }
void System::clearAllFast() { void System::clearAllFast() {
_manager->clearAllFast(); if (_manager) {
_manager->clearAllFast();
}
_whenMaps.clear(); _whenMaps.clear();
_whenAlerts.clear(); _whenAlerts.clear();
@ -295,6 +308,8 @@ void System::checkDelayed() {
} }
void System::showGrouped() { void System::showGrouped() {
Expects(_manager != nullptr);
if (const auto session = findSession(_lastHistorySessionId)) { if (const auto session = findSession(_lastHistorySessionId)) {
if (const auto lastItem = session->data().message(_lastHistoryItemId)) { if (const auto lastItem = session->data().message(_lastHistoryItemId)) {
_waitForAllGroupedTimer.cancel(); _waitForAllGroupedTimer.cancel();
@ -307,7 +322,11 @@ void System::showGrouped() {
} }
void System::showNext() { void System::showNext() {
if (App::quitting()) return; Expects(_manager != nullptr);
if (App::quitting()) {
return;
}
const auto isSameGroup = [=](HistoryItem *item) { const auto isSameGroup = [=](HistoryItem *item) {
if (!_lastHistorySessionId || !_lastHistoryItemId || !item) { if (!_lastHistorySessionId || !_lastHistoryItemId || !item) {
@ -538,7 +557,9 @@ void System::ensureSoundCreated() {
} }
void System::updateAll() { void System::updateAll() {
_manager->updateAll(); if (_manager) {
_manager->updateAll();
}
} }
Manager::DisplayOptions Manager::GetNotificationOptions(HistoryItem *item) { Manager::DisplayOptions Manager::GetNotificationOptions(HistoryItem *item) {
@ -561,7 +582,17 @@ Manager::DisplayOptions Manager::GetNotificationOptions(HistoryItem *item) {
QString Manager::addTargetAccountName( QString Manager::addTargetAccountName(
const QString &title, const QString &title,
not_null<Main::Session*> session) { not_null<Main::Session*> session) {
return (Core::App().domain().accounts().size() > 1) const auto add = [&] {
for (const auto &[index, account] : Core::App().domain().accounts()) {
if (const auto other = account->maybeSession()) {
if (other != session) {
return true;
}
}
}
return false;
}();
return add
? (title ? (title
+ accountNameSeparator() + accountNameSeparator()
+ (session->user()->username.isEmpty() + (session->user()->username.isEmpty()

View file

@ -192,7 +192,7 @@ void Manager::showNextFromQueue() {
return; return;
} }
int count = Core::App().settings().notificationsCount(); int count = Core::App().settings().notificationsCount();
for_const (auto &notification, _notifications) { for (const auto &notification : _notifications) {
if (notification->isUnlinked()) continue; if (notification->isUnlinked()) continue;
--count; --count;
} }

View file

@ -85,9 +85,6 @@ void Controller::showAccount(not_null<Main::Account*> account) {
setupIntro(); setupIntro();
_widget.updateGlobalMenu(); _widget.updateGlobalMenu();
} }
if (was) {
was->session().updates().updateOnline();
}
}, _accountLifetime); }, _accountLifetime);
} }

View file

@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "base/qt_signal_producer.h" #include "base/qt_signal_producer.h"
#include "boxes/about_box.h" #include "boxes/about_box.h"
#include "boxes/confirm_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "calls/calls_box_controller.h" #include "calls/calls_box_controller.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -53,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <QtGui/QScreen> #include <QtGui/QScreen>
@ -100,13 +102,15 @@ public:
private: private:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void paintUserpic(Painter &p); void paintUserpic(Painter &p);
const not_null<Main::Account*> _account; const not_null<Main::Session*> _session;
const style::Menu &_st; const style::Menu &_st;
std::shared_ptr<Data::CloudImageView> _userpicView; std::shared_ptr<Data::CloudImageView> _userpicView;
InMemoryKey _userpicKey = {}; InMemoryKey _userpicKey = {};
QImage _userpicCache; QImage _userpicCache;
base::unique_qptr<Ui::PopupMenu> _menu;
Dialogs::Layout::UnreadBadgeStyle _unreadSt; Dialogs::Layout::UnreadBadgeStyle _unreadSt;
int _unreadBadge = 0; int _unreadBadge = 0;
@ -154,7 +158,7 @@ MainMenu::AccountButton::AccountButton(
QWidget *parent, QWidget *parent,
not_null<Main::Account*> account) not_null<Main::Account*> account)
: RippleButton(parent, st::defaultRippleAnimation) : RippleButton(parent, st::defaultRippleAnimation)
, _account(account) , _session(&account->session())
, _st(st::mainMenu){ , _st(st::mainMenu){
const auto height = _st.itemPadding.top() const auto height = _st.itemPadding.top()
+ _st.itemStyle.font->height + _st.itemStyle.font->height
@ -168,33 +172,27 @@ MainMenu::AccountButton::AccountButton(
} }
}); });
_account->sessionValue( rpl::single(
) | rpl::filter([=](Main::Session *session) { rpl::empty_value()
return (session != nullptr); ) | rpl::then(
}) | rpl::start_with_next([=](not_null<Main::Session*> session) { _session->data().unreadBadgeChanges()
rpl::single( ) | rpl::start_with_next([=] {
rpl::empty_value() _unreadBadge = _session->data().unreadBadge();
) | rpl::then( _unreadBadgeMuted = _session->data().unreadBadgeMuted();
session->data().unreadBadgeChanges() update();
) | rpl::start_with_next([=] {
_unreadBadge = session->data().unreadBadge();
_unreadBadgeMuted = session->data().unreadBadgeMuted();
update();
}, lifetime());
}, lifetime()); }, lifetime());
} }
void MainMenu::AccountButton::paintUserpic(Painter &p) { void MainMenu::AccountButton::paintUserpic(Painter &p) {
Expects(_account->sessionExists());
const auto size = st::mainMenuAccountSize; const auto size = st::mainMenuAccountSize;
const auto iconSize = height() - 2 * _st.itemIconPosition.y(); const auto iconSize = height() - 2 * _st.itemIconPosition.y();
const auto shift = (size - iconSize) / 2; const auto shift = (size - iconSize) / 2;
const auto x = _st.itemIconPosition.x() - shift; const auto x = _st.itemIconPosition.x() - shift;
const auto y = (height() - size) / 2; const auto y = (height() - size) / 2;
const auto check = (_account == &Core::App().domain().active()); const auto check = (&_session->account()
const auto user = _account->session().user(); == &Core::App().domain().active());
const auto user = _session->user();
if (!check) { if (!check) {
user->paintUserpicLeft(p, _userpicView, x, y, width(), size); user->paintUserpicLeft(p, _userpicView, x, y, width(), size);
return; return;
@ -235,8 +233,6 @@ void MainMenu::AccountButton::paintUserpic(Painter &p) {
} }
void MainMenu::AccountButton::paintEvent(QPaintEvent *e) { void MainMenu::AccountButton::paintEvent(QPaintEvent *e) {
Expects(_account->sessionExists());
auto p = Painter(this); auto p = Painter(this);
const auto over = isOver(); const auto over = isOver();
p.fillRect(rect(), over ? _st.itemBgOver : _st.itemBg); p.fillRect(rect(), over ? _st.itemBgOver : _st.itemBg);
@ -245,7 +241,8 @@ void MainMenu::AccountButton::paintEvent(QPaintEvent *e) {
paintUserpic(p); paintUserpic(p);
auto available = width() - _st.itemPadding.left(); auto available = width() - _st.itemPadding.left();
if (_unreadBadge && _account != &Core::App().activeAccount()) { if (_unreadBadge
&& (&_session->account() != &Core::App().activeAccount())) {
_unreadSt.muted = _unreadBadgeMuted; _unreadSt.muted = _unreadBadgeMuted;
const auto string = (_unreadBadge > 99) const auto string = (_unreadBadge > 99)
? "99+" ? "99+"
@ -268,13 +265,39 @@ void MainMenu::AccountButton::paintEvent(QPaintEvent *e) {
} }
p.setPen(over ? _st.itemFgOver : _st.itemFg); p.setPen(over ? _st.itemFgOver : _st.itemFg);
_account->session().user()->nameText().drawElided( _session->user()->nameText().drawElided(
p, p,
_st.itemPadding.left(), _st.itemPadding.left(),
_st.itemPadding.top(), _st.itemPadding.top(),
available); available);
} }
void MainMenu::AccountButton::contextMenuEvent(QContextMenuEvent *e) {
if (&_session->account() == &Core::App().activeAccount() || _menu) {
return;
}
_menu = base::make_unique_q<Ui::PopupMenu>(this);
_menu->addAction(tr::lng_menu_activate(tr::now), crl::guard(this, [=] {
Core::App().domain().activate(&_session->account());
}));
_menu->addAction(tr::lng_settings_logout(tr::now), crl::guard(this, [=] {
const auto session = _session;
const auto box = std::make_shared<QPointer<ConfirmBox>>();
const auto callback = [=] {
if (*box) {
(*box)->closeBox();
}
Core::App().logout(&session->account());
};
*box = Ui::show(Box<ConfirmBox>(
tr::lng_sure_logout(tr::now),
tr::lng_settings_logout(tr::now),
st::attentionBoxButton,
crl::guard(session, callback)));
}));
_menu->popup(QCursor::pos());
}
MainMenu::ToggleAccountsButton::ToggleAccountsButton(QWidget *parent) MainMenu::ToggleAccountsButton::ToggleAccountsButton(QWidget *parent)
: AbstractButton(parent) { : AbstractButton(parent) {
rpl::single( rpl::single(
@ -642,14 +665,17 @@ void MainMenu::setupCloudButton() {
} }
void MainMenu::setupUserpicButton() { void MainMenu::setupUserpicButton() {
_userpicButton->setClickedCallback([=] { _userpicButton->setClickedCallback([=] { toggleAccounts(); });
_controller->content()->choosePeer(
_controller->session().userPeerId(),
ShowAtUnreadMsgId);
});
_userpicButton->show(); _userpicButton->show();
} }
void MainMenu::toggleAccounts() {
auto &settings = Core::App().settings();
const auto shown = !settings.mainMenuAccountsShown();
settings.setMainMenuAccountsShown(shown);
Core::App().saveSettingsDelayed();
}
void MainMenu::setupAccounts() { void MainMenu::setupAccounts() {
const auto inner = _accounts->entity(); const auto inner = _accounts->entity();
@ -688,7 +714,6 @@ void MainMenu::setupAccounts() {
rebuildAccounts(); rebuildAccounts();
}, lifetime()); }, lifetime());
_accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue());
_accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue()); _accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue());
_accounts->finishAnimating(); _accounts->finishAnimating();
@ -772,18 +797,7 @@ not_null<Ui::SlideWrap<Ui::RippleButton>*> MainMenu::setupAddAccount(
}, button->lifetime()); }, button->lifetime());
const auto add = [=](MTP::Environment environment) { const auto add = [=](MTP::Environment environment) {
auto &domain = Core::App().domain(); Core::App().domain().addActivated(environment);
if (domain.accounts().size() < Main::Domain::kMaxAccounts) {
domain.activate(domain.add(environment));
} else {
for (auto &[index, account] : domain.accounts()) {
if (!account->sessionExists()
&& account->mtp().environment() == environment) {
domain.activate(account.get());
break;
}
}
}
}; };
button->setAcceptBoth(true); button->setAcceptBoth(true);
@ -812,12 +826,7 @@ not_null<Ui::SlideWrap<Ui::RippleButton>*> MainMenu::setupAddAccount(
void MainMenu::setupAccountsToggle() { void MainMenu::setupAccountsToggle() {
_toggleAccounts->show(); _toggleAccounts->show();
_toggleAccounts->setClickedCallback([=] { _toggleAccounts->setClickedCallback([=] { toggleAccounts(); });
auto &settings = Core::App().settings();
const auto shown = !settings.mainMenuAccountsShown();
settings.setMainMenuAccountsShown(shown);
Core::App().saveSettingsDelayed();
});
} }
void MainMenu::parentResized() { void MainMenu::parentResized() {

View file

@ -68,6 +68,7 @@ private:
void initResetScaleButton(); void initResetScaleButton();
void refreshMenu(); void refreshMenu();
void refreshBackground(); void refreshBackground();
void toggleAccounts();
const not_null<SessionController*> _controller; const not_null<SessionController*> _controller;
object_ptr<Ui::UserpicButton> _userpicButton; object_ptr<Ui::UserpicButton> _userpicButton;

View file

@ -1245,7 +1245,7 @@ void PeerMenuAddChannelMembers(
return; return;
} }
const auto api = &channel->session().api(); const auto api = &channel->session().api();
api->requestChannelMembersForAdd(channel, [=]( api->requestChannelMembersForAdd(channel, crl::guard(navigation, [=](
const MTPchannels_ChannelParticipants &result) { const MTPchannels_ChannelParticipants &result) {
api->parseChannelParticipants(channel, result, [&]( api->parseChannelParticipants(channel, result, [&](
int availableCount, int availableCount,
@ -1267,7 +1267,7 @@ void PeerMenuAddChannelMembers(
channel, channel,
{ already.begin(), already.end() }); { already.begin(), already.end() });
}); });
}); }));
} }
void PeerMenuAddMuteAction( void PeerMenuAddMuteAction(

View file

@ -116,7 +116,7 @@ struct SectionShow {
class SessionController; class SessionController;
class SessionNavigation { class SessionNavigation : public base::has_weak_ptr {
public: public:
explicit SessionNavigation(not_null<Main::Session*> session); explicit SessionNavigation(not_null<Main::Session*> session);
@ -156,10 +156,7 @@ private:
}; };
class SessionController class SessionController : public SessionNavigation, private base::Subscriber {
: public SessionNavigation
, public base::has_weak_ptr
, private base::Subscriber {
public: public:
SessionController( SessionController(
not_null<Main::Session*> session, not_null<Main::Session*> session,
@ -171,6 +168,15 @@ public:
[[nodiscard]] not_null<::MainWindow*> widget() const; [[nodiscard]] not_null<::MainWindow*> widget() const;
[[nodiscard]] not_null<MainWidget*> content() const; [[nodiscard]] not_null<MainWidget*> content() const;
// We need access to this from MainWidget::MainWidget, where
// we can't call content() yet.
void setSelectingPeer(bool selecting) {
_selectingPeer = selecting;
}
[[nodiscard]] bool selectingPeer() const {
return _selectingPeer;
}
[[nodiscard]] auto tabbedSelector() const [[nodiscard]] auto tabbedSelector() const
-> not_null<ChatHelpers::TabbedSelector*>; -> not_null<ChatHelpers::TabbedSelector*>;
void takeTabbedSelectorOwnershipFrom(not_null<QWidget*> parent); void takeTabbedSelectorOwnershipFrom(not_null<QWidget*> parent);
@ -335,6 +341,7 @@ private:
base::Variable<bool> _dialogsListDisplayForced = { false }; base::Variable<bool> _dialogsListDisplayForced = { false };
std::deque<Dialogs::RowDescriptor> _chatEntryHistory; std::deque<Dialogs::RowDescriptor> _chatEntryHistory;
int _chatEntryHistoryPosition = -1; int _chatEntryHistoryPosition = -1;
bool _selectingPeer = false;
rpl::variable<FilterId> _activeChatsFilter; rpl::variable<FilterId> _activeChatsFilter;

View file

@ -116,6 +116,12 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
return startResize(mouseEvent->windowPos().toPoint()); return startResize(mouseEvent->windowPos().toPoint());
} }
} }
} else if (e->type() == QEvent::Leave) {
if (window() == static_cast<QWidget*>(obj)) {
while (QGuiApplication::overrideCursor()) {
QGuiApplication::restoreOverrideCursor();
}
}
} }
return TitleWidget::eventFilter(obj, e); return TitleWidget::eventFilter(obj, e);

View file

@ -1,7 +1,7 @@
AppVersion 2001014 AppVersion 2001016
AppVersionStrMajor 2.1 AppVersionStrMajor 2.1
AppVersionStrSmall 2.1.14 AppVersionStrSmall 2.1.16
AppVersionStr 2.1.14 AppVersionStr 2.1.16
BetaChannel 1 BetaChannel 1
AlphaVersion 0 AlphaVersion 0
AppVersionOriginal 2.1.14.beta AppVersionOriginal 2.1.16.beta

View file

@ -1,3 +1,13 @@
2.1.16 beta (01.07.20)
- Crash fix.
2.1.15 beta (30.06.20)
- Receive notifications only from the active account in Settings > Notifications.
- Fix saving chats list width between application relaunches.
- Multiple crash fixes.
2.1.14 beta (29.06.20) 2.1.14 beta (29.06.20)
- Support for multiple accounts. - Support for multiple accounts.