Merge remote-tracking branch 'tdesktop/dev' into dev
This commit is contained in:
commit
b3e4d0b32a
61 changed files with 681 additions and 308 deletions
10
.github/workflows/linux.yml
vendored
10
.github/workflows/linux.yml
vendored
|
|
@ -164,7 +164,7 @@ jobs:
|
|||
|
||||
- name: Opus cache.
|
||||
id: cache-opus
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/opus
|
||||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
|
|
@ -209,7 +209,7 @@ jobs:
|
|||
|
||||
- name: FFmpeg cache.
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/ffmpeg-cache
|
||||
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}
|
||||
|
|
@ -363,7 +363,7 @@ jobs:
|
|||
|
||||
- name: OpenSSL cache.
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openssl-cache
|
||||
key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }}
|
||||
|
|
@ -419,7 +419,7 @@ jobs:
|
|||
|
||||
- name: Qt 5.12.8 cache.
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/qt-cache
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qt*_5_12_8/*') }}
|
||||
|
|
@ -468,7 +468,7 @@ jobs:
|
|||
|
||||
- name: Breakpad cache.
|
||||
id: cache-breakpad
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/breakpad-cache
|
||||
key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }}
|
||||
|
|
|
|||
12
.github/workflows/mac.yml
vendored
12
.github/workflows/mac.yml
vendored
|
|
@ -140,7 +140,7 @@ jobs:
|
|||
|
||||
- name: OpenSSL cache.
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }}
|
||||
|
|
@ -170,7 +170,7 @@ jobs:
|
|||
|
||||
- name: Opus cache.
|
||||
id: cache-opus
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/opus
|
||||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
|
|
@ -192,7 +192,7 @@ jobs:
|
|||
|
||||
- name: Libiconv cache.
|
||||
id: cache-libiconv
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/${{ env.LIBICONV_VER }}
|
||||
key: ${{ runner.OS }}-${{ env.LIBICONV_VER }}-${{ env.CACHE_KEY }}
|
||||
|
|
@ -213,7 +213,7 @@ jobs:
|
|||
|
||||
- name: FFmpeg cache.
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/ffmpeg-cache
|
||||
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}
|
||||
|
|
@ -369,7 +369,7 @@ jobs:
|
|||
|
||||
- name: Crashpad cache.
|
||||
id: cache-crashpad
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/crashpad
|
||||
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.
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/qt-cache
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}
|
||||
|
|
|
|||
12
.github/workflows/win.yml
vendored
12
.github/workflows/win.yml
vendored
|
|
@ -140,7 +140,7 @@ jobs:
|
|||
|
||||
- name: OpenSSL cache.
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.OS }}-${{ env.CACHE_KEY }}-${{ env.OPENSSL_VER }}
|
||||
|
|
@ -184,7 +184,7 @@ jobs:
|
|||
|
||||
- name: OpenAL Soft cache.
|
||||
id: cache-openal
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openal-soft
|
||||
key: ${{ runner.OS }}-openal-soft-${{ env.CACHE_KEY }}
|
||||
|
|
@ -208,7 +208,7 @@ jobs:
|
|||
|
||||
- name: Breakpad cache.
|
||||
id: cache-breakpad
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/breakpad
|
||||
key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }}-${{ hashFiles('**/breakpad.diff') }}
|
||||
|
|
@ -257,7 +257,7 @@ jobs:
|
|||
|
||||
- name: Opus cache.
|
||||
id: cache-opus
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/opus
|
||||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
|
|
@ -276,7 +276,7 @@ jobs:
|
|||
|
||||
- name: FFmpeg cache.
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/ffmpeg
|
||||
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}-2-${{ hashFiles('**/build_ffmpeg_win.sh') }}
|
||||
|
|
@ -298,7 +298,7 @@ jobs:
|
|||
|
||||
- name: Qt 5.12.8 cache.
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/Qt-5.12.8
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_menu_back" = "Back";
|
||||
"lng_menu_night_mode" = "Night Mode";
|
||||
"lng_menu_add_account" = "Add Account";
|
||||
"lng_menu_activate" = "Activate";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Disable 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_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_desktop_notify" = "Desktop notifications";
|
||||
"lng_settings_show_name" = "Show sender's name";
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="2.1.14.0" />
|
||||
Version="2.1.16.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,14,0
|
||||
PRODUCTVERSION 2,1,14,0
|
||||
FILEVERSION 2,1,16,0
|
||||
PRODUCTVERSION 2,1,16,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
|
@ -62,10 +62,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "2.1.14.0"
|
||||
VALUE "FileVersion", "2.1.16.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.14.0"
|
||||
VALUE "ProductVersion", "2.1.16.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,14,0
|
||||
PRODUCTVERSION 2,1,14,0
|
||||
FILEVERSION 2,1,16,0
|
||||
PRODUCTVERSION 2,1,16,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
|
@ -53,10 +53,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "2.1.14.0"
|
||||
VALUE "FileVersion", "2.1.16.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.14.0"
|
||||
VALUE "ProductVersion", "2.1.16.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
|||
|
|
@ -368,7 +368,6 @@ public:
|
|||
not_null<PeerData*> peer,
|
||||
const std::vector<not_null<UserData*>> &users);
|
||||
|
||||
|
||||
rpl::producer<SendAction> sendActions() const {
|
||||
return _sendActions.events();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -781,12 +781,12 @@ bool BackgroundPreviewBox::Start(
|
|||
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
|
||||
return false;
|
||||
}
|
||||
controller->session().api().requestWallPaper(slug, [=](
|
||||
controller->session().api().requestWallPaper(slug, crl::guard(controller, [=](
|
||||
const Data::WallPaper &result) {
|
||||
Ui::show(Box<BackgroundPreviewBox>(
|
||||
controller,
|
||||
result.withUrlParams(params)));
|
||||
}, [](const RPCError &error) {
|
||||
}), [](const RPCError &error) {
|
||||
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
|
||||
});
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class ProxyBox : public Ui::BoxContent {
|
||||
class ProxyBox final : public Ui::BoxContent {
|
||||
public:
|
||||
ProxyBox(
|
||||
QWidget*,
|
||||
|
|
@ -179,12 +179,14 @@ public:
|
|||
Fn<void(ProxyData)> callback,
|
||||
Fn<void(ProxyData)> shareCallback);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
using Type = ProxyData::Type;
|
||||
|
||||
void prepare() override;
|
||||
void setInnerFocus() override {
|
||||
_host->setFocusFast();
|
||||
}
|
||||
|
||||
void refreshButtons();
|
||||
ProxyData collectData();
|
||||
void save();
|
||||
|
|
@ -693,8 +695,8 @@ void ProxiesBox::applyView(View &&view) {
|
|||
setupButtons(id, i->second.get());
|
||||
if (_noRows) {
|
||||
_noRows.reset();
|
||||
wrap->resizeToWidth(width());
|
||||
}
|
||||
wrap->resizeToWidth(width());
|
||||
} else if (view.host.isEmpty()) {
|
||||
_rows.erase(i);
|
||||
} else {
|
||||
|
|
@ -765,6 +767,31 @@ ProxyBox::ProxyBox(
|
|||
void ProxyBox::prepare() {
|
||||
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();
|
||||
setDimensionsToContent(st::boxWideWidth, _content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/rp_widget.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/object_ptr.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
|
||||
namespace Ui {
|
||||
class ScrollArea;
|
||||
|
|
|
|||
|
|
@ -2512,7 +2512,11 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
|
|||
externalLayout,
|
||||
std::move(recentPack));
|
||||
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 {
|
||||
std::swap(*recentIt, set);
|
||||
takeHeavyData(*recentIt, set);
|
||||
|
|
@ -2537,7 +2541,7 @@ void StickersListWidget::refreshFavedStickers() {
|
|||
const auto set = it->second.get();
|
||||
const auto externalLayout = false;
|
||||
const auto shortName = QString();
|
||||
_mySets.emplace_back(
|
||||
_mySets.insert(_mySets.begin(), Set{
|
||||
Data::Stickers::FavedSetId,
|
||||
nullptr,
|
||||
(MTPDstickerSet::Flag::f_official
|
||||
|
|
@ -2546,7 +2550,8 @@ void StickersListWidget::refreshFavedStickers() {
|
|||
shortName,
|
||||
set->count,
|
||||
externalLayout,
|
||||
PrepareStickers(set->stickers));
|
||||
PrepareStickers(set->stickers)
|
||||
});
|
||||
_favedStickersMap = base::flat_set<not_null<DocumentData*>> {
|
||||
set->stickers.begin(),
|
||||
set->stickers.end()
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ Application::~Application() {
|
|||
|
||||
_window = nullptr;
|
||||
_mediaView = nullptr;
|
||||
_notifications->clearAllFast();
|
||||
_domain->finish();
|
||||
|
||||
Local::finish();
|
||||
|
|
@ -206,6 +207,7 @@ void Application::run() {
|
|||
refreshGlobalProxy(); // Depends on Global::start().
|
||||
|
||||
// Depends on OpenSSL on macOS, so on ThirdParty::start().
|
||||
// Depends on notifications settings.
|
||||
_notifications = std::make_unique<Window::Notifications::System>();
|
||||
|
||||
startLocalStorage();
|
||||
|
|
|
|||
|
|
@ -347,6 +347,11 @@ private:
|
|||
base::Timer _clearEmojiImageLoaderTimer;
|
||||
const std::unique_ptr<Media::Audio::Instance> _audio;
|
||||
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<Export::Manager> _exportManager;
|
||||
const std::unique_ptr<Calls::Instance> _calls;
|
||||
|
|
@ -363,10 +368,6 @@ private:
|
|||
Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = 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 _logoBlue;
|
||||
const QImage _logoGreen;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,18 @@ QByteArray Settings::serialize() const {
|
|||
}
|
||||
stream
|
||||
<< 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;
|
||||
}
|
||||
|
|
@ -150,6 +161,14 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
std::vector<int> dictionariesEnabled;
|
||||
qint32 autoDownloadDictionaries = _autoDownloadDictionaries.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;
|
||||
if (!stream.atEnd()) {
|
||||
|
|
@ -211,6 +230,19 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
>> autoDownloadDictionaries
|
||||
>> 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) {
|
||||
LOG(("App Error: "
|
||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||
|
|
@ -281,6 +313,28 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
_dictionariesEnabled = std::move(dictionariesEnabled);
|
||||
_autoDownloadDictionaries = (autoDownloadDictionaries == 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 {
|
||||
|
|
@ -412,6 +466,7 @@ void Settings::resetOnLastLogout() {
|
|||
_thirdSectionExtendedBy = -1; // per-window
|
||||
_dialogsWidthRatio = DefaultDialogsWidthRatio(); // per-window
|
||||
_thirdColumnWidth = kDefaultThirdColumnWidth; // p-w
|
||||
_notifyFromAll = true;
|
||||
_tabbedReplacedWithInfo = false; // per-window
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -401,6 +401,12 @@ public:
|
|||
void setThirdColumnWidth(int width);
|
||||
[[nodiscard]] int thirdColumnWidth() const;
|
||||
[[nodiscard]] rpl::producer<int> thirdColumnWidthChanges() const;
|
||||
void setNotifyFromAll(bool value) {
|
||||
_notifyFromAll = value;
|
||||
}
|
||||
[[nodiscard]] bool notifyFromAll() const {
|
||||
return _notifyFromAll;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool ThirdColumnByDefault();
|
||||
[[nodiscard]] float64 DefaultDialogsWidthRatio();
|
||||
|
|
@ -467,6 +473,7 @@ private:
|
|||
int _thirdSectionExtendedBy = -1; // per-window
|
||||
rpl::variable<float64> _dialogsWidthRatio; // per-window
|
||||
rpl::variable<int> _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w
|
||||
bool _notifyFromAll = true;
|
||||
|
||||
bool _tabbedReplacedWithInfo = false; // per-window
|
||||
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
||||
|
|
|
|||
|
|
@ -304,16 +304,13 @@ bool ResolveUsername(
|
|||
}
|
||||
const auto clickFromMessageId = context.value<FullMsgId>();
|
||||
const auto searchParam = params.value(qsl("query"));
|
||||
if (const auto controller = App::wnd()->sessionController()) {
|
||||
controller->content()->openPeerByName(
|
||||
domain,
|
||||
post,
|
||||
startToken,
|
||||
clickFromMessageId,
|
||||
searchParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
controller->content()->openPeerByName(
|
||||
domain,
|
||||
post,
|
||||
startToken,
|
||||
clickFromMessageId,
|
||||
searchParam);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResolvePrivatePost(
|
||||
|
|
@ -331,12 +328,12 @@ bool ResolvePrivatePost(
|
|||
if (!channelId || !IsServerMsgId(msgId)) {
|
||||
return false;
|
||||
}
|
||||
const auto done = [=](not_null<PeerData*> peer) {
|
||||
App::wnd()->sessionController()->showPeerHistory(
|
||||
const auto done = crl::guard(controller, [=](not_null<PeerData*> peer) {
|
||||
controller->showPeerHistory(
|
||||
peer->id,
|
||||
Window::SectionShow::Way::Forward,
|
||||
msgId);
|
||||
};
|
||||
});
|
||||
const auto fail = [=] {
|
||||
Ui::show(Box<InformBox>(tr::lng_error_post_link_invalid(tr::now)));
|
||||
};
|
||||
|
|
@ -400,7 +397,7 @@ bool HandleUnknown(
|
|||
return false;
|
||||
}
|
||||
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{
|
||||
qs(result.vmessage()),
|
||||
Api::EntitiesFromMTP(
|
||||
|
|
@ -420,7 +417,7 @@ bool HandleUnknown(
|
|||
} else {
|
||||
Ui::show(Box<InformBox>(text));
|
||||
}
|
||||
};
|
||||
});
|
||||
controller->session().api().requestDeepLinkInfo(request, callback);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
|
|||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||
constexpr auto AppName = "Kotatogram Desktop"_cs;
|
||||
constexpr auto AppFile = "Kotatogram"_cs;
|
||||
constexpr auto AppVersion = 2001014;
|
||||
constexpr auto AppVersionStr = "2.1.14";
|
||||
constexpr auto AppVersion = 2001016;
|
||||
constexpr auto AppVersionStr = "2.1.16";
|
||||
constexpr auto AppBetaVersion = true;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ bool ChatFilter::contains(not_null<History*> history) const {
|
|||
}
|
||||
|
||||
ChatFilters::ChatFilters(not_null<Session*> owner) : _owner(owner) {
|
||||
load();
|
||||
crl::on_main(&owner->session(), [=] { load(); });
|
||||
}
|
||||
|
||||
ChatFilters::~ChatFilters() = default;
|
||||
|
|
@ -242,6 +242,16 @@ not_null<Dialogs::MainList*> ChatFilters::chatsList(FilterId filterId) {
|
|||
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() {
|
||||
load(false);
|
||||
}
|
||||
|
|
@ -254,40 +264,44 @@ void ChatFilters::load(bool force) {
|
|||
api.request(_loadRequestId).cancel();
|
||||
_loadRequestId = api.request(MTPmessages_GetDialogFilters(
|
||||
)).done([=](const MTPVector<MTPDialogFilter> &result) {
|
||||
auto position = 0;
|
||||
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({});
|
||||
}
|
||||
received(result.v);
|
||||
_loadRequestId = 0;
|
||||
}).fail([=](const RPCError &error) {
|
||||
_loadRequestId = 0;
|
||||
}).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) {
|
||||
update.match([&](const MTPDupdateDialogFilter &data) {
|
||||
if (const auto filter = data.vfilter()) {
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@ public:
|
|||
explicit ChatFilters(not_null<Session*> owner);
|
||||
~ChatFilters();
|
||||
|
||||
void setPreloaded(const QVector<MTPDialogFilter> &result);
|
||||
|
||||
void load();
|
||||
void apply(const MTPUpdate &update);
|
||||
void set(ChatFilter filter);
|
||||
|
|
@ -129,6 +131,7 @@ public:
|
|||
|
||||
private:
|
||||
void load(bool force);
|
||||
void received(const QVector<MTPDialogFilter> &list);
|
||||
bool applyOrder(const QVector<MTPint> &order);
|
||||
bool applyChange(ChatFilter &filter, ChatFilter &&updated);
|
||||
void applyInsert(ChatFilter filter, int position);
|
||||
|
|
|
|||
|
|
@ -462,9 +462,6 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
|
|||
: QString())
|
||||
: result->nameOrPhone;
|
||||
|
||||
if (!minimal && data.is_self() && uname != result->username) {
|
||||
CrashReports::SetAnnotation("Username", uname);
|
||||
}
|
||||
result->setName(fname, lname, pname, uname);
|
||||
if (const auto photo = data.vphoto()) {
|
||||
result->setPhoto(*photo);
|
||||
|
|
@ -2559,6 +2556,7 @@ not_null<WebPageData*> Session::processWebpage(const MTPWebPage &data) {
|
|||
const auto result = webpage(data.c_webPageEmpty().vid().v);
|
||||
if (result->pendingTill > 0) {
|
||||
result->pendingTill = -1; // failed
|
||||
notifyWebPageUpdateDelayed(result);
|
||||
}
|
||||
return result;
|
||||
} break;
|
||||
|
|
|
|||
|
|
@ -892,7 +892,7 @@ void Stickers::gifsReceived(const QVector<MTPDocument> &items, int32 hash) {
|
|||
const auto document = owner().processDocument(item);
|
||||
if (!document->isGifv()) {
|
||||
LOG(("API Error: "
|
||||
"bad document returned in HistoryWidget::savedGifsGot!"));
|
||||
"bad document returned in Stickers::gifsReceived!"));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3056,7 +3056,7 @@ void InnerWidget::setupShortcuts() {
|
|||
}) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) {
|
||||
using Command = Shortcuts::Command;
|
||||
|
||||
if (_controller->content()->selectingPeer()) {
|
||||
if (_controller->selectingPeer()) {
|
||||
return;
|
||||
}
|
||||
const auto row = _controller->activeChatEntryCurrent();
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ Widget::Widget(
|
|||
});
|
||||
_inner->chosenRow(
|
||||
) | rpl::start_with_next([=](const ChosenRow &row) {
|
||||
const auto openSearchResult = !controller->content()->selectingPeer()
|
||||
const auto openSearchResult = !controller->selectingPeer()
|
||||
&& row.filteredRow;
|
||||
if (const auto history = row.key.history()) {
|
||||
controller->content()->choosePeer(
|
||||
|
|
@ -701,7 +701,7 @@ void Widget::escape() {
|
|||
} else if (controller()->activeChatsFilterCurrent() != cDefaultFilterId()) {
|
||||
controller()->setActiveChatsFilter(cDefaultFilterId());
|
||||
}
|
||||
} else if (!_searchInChat && !controller()->content()->selectingPeer()) {
|
||||
} else if (!_searchInChat && !controller()->selectingPeer()) {
|
||||
if (controller()->activeChatEntryCurrent().key) {
|
||||
emit cancelled();
|
||||
}
|
||||
|
|
@ -1267,7 +1267,7 @@ void Widget::peopleFailed(const RPCError &error, mtpRequestId requestId) {
|
|||
void Widget::dragEnterEvent(QDragEnterEvent *e) {
|
||||
using namespace Storage;
|
||||
|
||||
if (controller()->content()->selectingPeer()) {
|
||||
if (controller()->selectingPeer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1616,7 +1616,7 @@ void Widget::updateControlsGeometry() {
|
|||
}
|
||||
|
||||
void Widget::updateForwardBar() {
|
||||
auto selecting = controller()->content()->selectingPeer();
|
||||
auto selecting = controller()->selectingPeer();
|
||||
auto oneColumnSelecting = (Adaptive::OneColumn() && selecting);
|
||||
if (!oneColumnSelecting == !_forwardCancel) {
|
||||
return;
|
||||
|
|
@ -1759,7 +1759,7 @@ bool Widget::onCancelSearch() {
|
|||
void Widget::onCancelSearchInChat() {
|
||||
cancelSearchRequest();
|
||||
if (_searchInChat) {
|
||||
if (Adaptive::OneColumn() && !controller()->content()->selectingPeer()) {
|
||||
if (Adaptive::OneColumn() && !controller()->selectingPeer()) {
|
||||
if (const auto peer = _searchInChat.peer()) {
|
||||
Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
|
||||
//} else if (const auto feed = _searchInChat.feed()) { // #feed
|
||||
|
|
@ -1774,7 +1774,7 @@ void Widget::onCancelSearchInChat() {
|
|||
_filter->clear();
|
||||
_filter->updatePlaceholder();
|
||||
applyFilterUpdate();
|
||||
if (!Adaptive::OneColumn() && !controller()->content()->selectingPeer()) {
|
||||
if (!Adaptive::OneColumn() && !controller()->selectingPeer()) {
|
||||
emit cancelled();
|
||||
}
|
||||
}
|
||||
|
|
@ -1786,6 +1786,8 @@ void Widget::onDialogMoved(int movedFrom, int movedTo) {
|
|||
}
|
||||
}
|
||||
|
||||
Widget::~Widget() = default;
|
||||
Widget::~Widget() {
|
||||
cancelSearchRequest();
|
||||
}
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_message.h"
|
||||
|
|
@ -260,6 +261,7 @@ HistoryWidget::HistoryWidget(
|
|||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: Window::AbstractSectionWidget(parent, controller)
|
||||
, _api(&controller->session().mtp())
|
||||
, _updateEditTimeLeftDisplay([=] { updateField(); })
|
||||
, _fieldBarCancel(this, st::historyReplyCancel)
|
||||
, _previewTimer([=] { requestPreview(); })
|
||||
|
|
@ -1219,14 +1221,14 @@ void HistoryWidget::updateInlineBotQuery() {
|
|||
if (_inlineBotUsername != query.username) {
|
||||
_inlineBotUsername = query.username;
|
||||
if (_inlineBotResolveRequestId) {
|
||||
session().api().request(_inlineBotResolveRequestId).cancel();
|
||||
_api.request(_inlineBotResolveRequestId).cancel();
|
||||
_inlineBotResolveRequestId = 0;
|
||||
}
|
||||
if (query.lookingUpBot) {
|
||||
_inlineBot = nullptr;
|
||||
_inlineLookingUpBot = true;
|
||||
const auto username = _inlineBotUsername;
|
||||
_inlineBotResolveRequestId = session().api().request(MTPcontacts_ResolveUsername(
|
||||
_inlineBotResolveRequestId = _api.request(MTPcontacts_ResolveUsername(
|
||||
MTP_string(username)
|
||||
)).done([=](const MTPcontacts_ResolvedPeer &result) {
|
||||
inlineBotResolveDone(result);
|
||||
|
|
@ -1477,7 +1479,7 @@ void HistoryWidget::cancelSendAction(
|
|||
SendAction::Type type) {
|
||||
const auto i = _sendActionRequests.find({ history, type });
|
||||
if (i != _sendActionRequests.end()) {
|
||||
session().api().request(i->second).cancel();
|
||||
_api.request(i->second).cancel();
|
||||
_sendActionRequests.erase(i);
|
||||
}
|
||||
}
|
||||
|
|
@ -1518,7 +1520,7 @@ void HistoryWidget::updateSendAction(
|
|||
case Type::ChooseContact: action = MTP_sendMessageChooseContactAction(); 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,
|
||||
action
|
||||
)).done([=](const MTPBool &result, mtpRequestId requestId) {
|
||||
|
|
@ -3155,6 +3157,7 @@ void HistoryWidget::saveEditMsg() {
|
|||
sendFlags |= MTPmessages_EditMessage::Flag::f_entities;
|
||||
}
|
||||
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
const auto history = _history;
|
||||
_saveEditMsgRequestId = history->session().api().request(
|
||||
MTPmessages_EditMessage(
|
||||
|
|
@ -3166,55 +3169,60 @@ void HistoryWidget::saveEditMsg() {
|
|||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(0)
|
||||
)).done([=](const MTPUpdates &result, mtpRequestId requestId) {
|
||||
saveEditMsgDone(history, result, requestId);
|
||||
}).fail([=](const RPCError &error, mtpRequestId requestId) {
|
||||
saveEditMsgFail(history, error, requestId);
|
||||
)).done([history, weak](const MTPUpdates &result, mtpRequestId requestId) {
|
||||
SaveEditMsgDone(history, result, requestId);
|
||||
if (const auto strong = weak.data()) {
|
||||
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();
|
||||
}
|
||||
|
||||
void HistoryWidget::saveEditMsgDone(
|
||||
void HistoryWidget::SaveEditMsgDone(
|
||||
not_null<History*> history,
|
||||
const MTPUpdates &updates,
|
||||
mtpRequestId requestId) {
|
||||
session().api().applyUpdates(updates);
|
||||
if (requestId == _saveEditMsgRequestId) {
|
||||
_saveEditMsgRequestId = 0;
|
||||
cancelEdit();
|
||||
}
|
||||
history->session().api().applyUpdates(updates);
|
||||
if (auto editDraft = history->editDraft()) {
|
||||
if (editDraft->saveRequestId == requestId) {
|
||||
history->clearEditDraft();
|
||||
session().local().writeDrafts(history);
|
||||
history->session().local().writeDrafts(history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::saveEditMsgFail(
|
||||
void HistoryWidget::SaveEditMsgFail(
|
||||
not_null<History*> history,
|
||||
const RPCError &error,
|
||||
mtpRequestId requestId) {
|
||||
if (requestId == _saveEditMsgRequestId) {
|
||||
_saveEditMsgRequestId = 0;
|
||||
}
|
||||
if (auto editDraft = history->editDraft()) {
|
||||
if (editDraft->saveRequestId == requestId) {
|
||||
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() {
|
||||
|
|
@ -3775,6 +3783,7 @@ void HistoryWidget::app_sendBotCallback(
|
|||
|
||||
using ButtonType = HistoryMessageMarkupButton::Type;
|
||||
BotCallbackInfo info = {
|
||||
&session(),
|
||||
bot,
|
||||
msg->fullId(),
|
||||
row,
|
||||
|
|
@ -3789,15 +3798,24 @@ void HistoryWidget::app_sendBotCallback(
|
|||
flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_data;
|
||||
sendData = button->data;
|
||||
}
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
button->requestId = session().api().request(MTPmessages_GetBotCallbackAnswer(
|
||||
MTP_flags(flags),
|
||||
_peer->input,
|
||||
MTP_int(msg->id),
|
||||
MTP_bytes(sendData)
|
||||
)).done([=](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) {
|
||||
botCallbackDone(info, result, requestId);
|
||||
}).fail([=](const RPCError &error, mtpRequestId requestId) {
|
||||
botCallbackFail(info, error, requestId);
|
||||
)).done([info, weak](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) {
|
||||
BotCallbackDone(info, result, requestId);
|
||||
result.match([&](const MTPDmessages_botCallbackAnswer &data) {
|
||||
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();
|
||||
session().data().requestItemRepaint(msg);
|
||||
|
||||
|
|
@ -3810,19 +3828,20 @@ void HistoryWidget::app_sendBotCallback(
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::botCallbackDone(
|
||||
void HistoryWidget::BotCallbackDone(
|
||||
BotCallbackInfo info,
|
||||
const MTPmessages_BotCallbackAnswer &answer,
|
||||
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(
|
||||
&session().data(),
|
||||
&session->data(),
|
||||
info.msgId,
|
||||
info.row,
|
||||
info.col);
|
||||
if (button && button->requestId == req) {
|
||||
button->requestId = 0;
|
||||
session().data().requestItemRepaint(item);
|
||||
session->data().requestItemRepaint(item);
|
||||
}
|
||||
answer.match([&](const MTPDmessages_botCallbackAnswer &data) {
|
||||
if (const auto message = data.vmessage()) {
|
||||
|
|
@ -3834,11 +3853,8 @@ void HistoryWidget::botCallbackDone(
|
|||
} else if (const auto url = data.vurl()) {
|
||||
auto link = qs(*url);
|
||||
if (info.game) {
|
||||
link = AppendShareGameScoreUrl(&session(), link, info.msgId);
|
||||
link = AppendShareGameScoreUrl(session, link, info.msgId);
|
||||
BotGameUrlClickHandler(info.bot, link).onClick({});
|
||||
if (item) {
|
||||
updateSendAction(item->history(), SendAction::Type::PlayGame);
|
||||
}
|
||||
} else {
|
||||
UrlClickHandler::Open(link);
|
||||
}
|
||||
|
|
@ -3846,21 +3862,21 @@ void HistoryWidget::botCallbackDone(
|
|||
});
|
||||
}
|
||||
|
||||
bool HistoryWidget::botCallbackFail(
|
||||
void HistoryWidget::BotCallbackFail(
|
||||
BotCallbackInfo info,
|
||||
const RPCError &error,
|
||||
mtpRequestId req) {
|
||||
// show error?
|
||||
const auto owner = &info.session->data();
|
||||
const auto button = HistoryMessageMarkupButton::Get(
|
||||
&session().data(),
|
||||
owner,
|
||||
info.msgId,
|
||||
info.row,
|
||||
info.col);
|
||||
if (button && button->requestId == req) {
|
||||
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) {
|
||||
|
|
@ -5037,12 +5053,11 @@ void HistoryWidget::updateControlsGeometry() {
|
|||
}
|
||||
|
||||
void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
|
||||
if (item == _replyEditMsg) {
|
||||
if (_editMsgId) {
|
||||
cancelEdit();
|
||||
} else {
|
||||
cancelReply();
|
||||
}
|
||||
if (item == _replyEditMsg && _editMsgId) {
|
||||
cancelEdit();
|
||||
}
|
||||
if (item == _replyEditMsg && _replyToId) {
|
||||
cancelReply();
|
||||
}
|
||||
while (item == _replyReturn) {
|
||||
calcNextReplyReturn();
|
||||
|
|
@ -6129,7 +6144,13 @@ void HistoryWidget::pinMessage(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) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -6291,7 +6312,7 @@ void HistoryWidget::cancelFieldAreaState() {
|
|||
}
|
||||
|
||||
void HistoryWidget::previewCancel() {
|
||||
session().api().request(base::take(_previewRequest)).cancel();
|
||||
_api.request(base::take(_previewRequest)).cancel();
|
||||
_previewData = nullptr;
|
||||
_previewLinks.clear();
|
||||
updatePreview();
|
||||
|
|
@ -6307,7 +6328,7 @@ void HistoryWidget::checkPreview() {
|
|||
}
|
||||
const auto links = _parsedLinks.join(' ');
|
||||
if (_previewLinks != links) {
|
||||
session().api().request(base::take(_previewRequest)).cancel();
|
||||
_api.request(base::take(_previewRequest)).cancel();
|
||||
_previewLinks = links;
|
||||
if (_previewLinks.isEmpty()) {
|
||||
if (_previewData && _previewData->pendingTill >= 0) {
|
||||
|
|
@ -6316,7 +6337,7 @@ void HistoryWidget::checkPreview() {
|
|||
} else {
|
||||
const auto i = _previewCache.constFind(links);
|
||||
if (i == _previewCache.cend()) {
|
||||
_previewRequest = session().api().request(MTPmessages_GetWebPagePreview(
|
||||
_previewRequest = _api.request(MTPmessages_GetWebPagePreview(
|
||||
MTP_flags(0),
|
||||
MTP_string(links),
|
||||
MTPVector<MTPMessageEntity>()
|
||||
|
|
@ -6340,7 +6361,7 @@ void HistoryWidget::requestPreview() {
|
|||
return;
|
||||
}
|
||||
const auto links = _previewLinks;
|
||||
_previewRequest = session().api().request(MTPmessages_GetWebPagePreview(
|
||||
_previewRequest = _api.request(MTPmessages_GetWebPagePreview(
|
||||
MTP_flags(0),
|
||||
MTP_string(links),
|
||||
MTPVector<MTPMessageEntity>()
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "base/flags.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
|
|
@ -339,6 +340,7 @@ private:
|
|||
using TabbedSelector = ChatHelpers::TabbedSelector;
|
||||
using DragState = Storage::MimeDataState;
|
||||
struct BotCallbackInfo {
|
||||
not_null<Main::Session*> session;
|
||||
UserData *bot;
|
||||
FullMsgId msgId;
|
||||
int row, col;
|
||||
|
|
@ -571,8 +573,8 @@ private:
|
|||
void createUnreadBarAndResize();
|
||||
|
||||
void saveEditMsg();
|
||||
void saveEditMsgDone(not_null<History*> history, const MTPUpdates &updates, mtpRequestId requestId);
|
||||
void saveEditMsgFail(not_null<History*> history, const RPCError &error, mtpRequestId requestId);
|
||||
static void SaveEditMsgDone(not_null<History*> history, const MTPUpdates &updates, mtpRequestId requestId);
|
||||
static void SaveEditMsgFail(not_null<History*> history, const RPCError &error, mtpRequestId requestId);
|
||||
|
||||
void checkPreview();
|
||||
void requestPreview();
|
||||
|
|
@ -582,8 +584,10 @@ private:
|
|||
void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages);
|
||||
void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages);
|
||||
|
||||
void botCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req);
|
||||
bool botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req);
|
||||
static void UnpinMessage(not_null<PeerData*> peer);
|
||||
|
||||
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 updateListSize();
|
||||
|
|
@ -648,6 +652,7 @@ private:
|
|||
void setupScheduledToggle();
|
||||
void refreshScheduledToggle();
|
||||
|
||||
MTP::Sender _api;
|
||||
MsgId _replyToId = 0;
|
||||
Ui::Text::String _replyToName;
|
||||
int _replyToNameVersion = 0;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/effects/slide_animation.h"
|
||||
#include "data/data_user.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/themes/window_theme.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.
|
||||
const auto currentId = Lang::Current().id();
|
||||
const auto defaultId = Lang::DefaultLanguageId();
|
||||
|
|
@ -168,12 +182,20 @@ void Step::finish(const MTPUser &user, QImage &&photo) {
|
|||
Lang::Current().switchToId(Lang::DefaultLanguage());
|
||||
Local::writeLangPack();
|
||||
}
|
||||
|
||||
auto settings = std::make_unique<Main::SessionSettings>();
|
||||
settings->setDialogsFiltersEnabled(!filters.isEmpty());
|
||||
|
||||
const auto account = _account;
|
||||
account->createSession(user);
|
||||
account->createSession(user, std::move(settings));
|
||||
|
||||
// "this" is already deleted here by creating the main widget.
|
||||
account->local().writeMtpData();
|
||||
auto &session = account->session();
|
||||
session.data().chatsFilters().setPreloaded(filters);
|
||||
if (!filters.isEmpty()) {
|
||||
session.saveSettingsDelayed();
|
||||
}
|
||||
if (!photo.isNull()) {
|
||||
session.api().uploadPeerPhoto(session.user(), std::move(photo));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ protected:
|
|||
return _data;
|
||||
}
|
||||
void finish(const MTPUser &user, QImage &&photo = QImage());
|
||||
void createSession(
|
||||
const MTPUser &user,
|
||||
QImage photo,
|
||||
const QVector<MTPDialogFilter> &filters);
|
||||
|
||||
void goBack();
|
||||
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ void SetupKotatoSystem(
|
|||
AddSkip(container);
|
||||
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>>(
|
||||
container.get());
|
||||
AddButton(
|
||||
|
|
@ -453,7 +453,7 @@ void SetupKotatoSystem(
|
|||
confirmed,
|
||||
cancelled));
|
||||
}, container->lifetime());
|
||||
#endif // Q_OS_WIN || Q_OS_MAC
|
||||
#endif // Q_OS_WIN || Q_OS_MAC || Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
|
||||
|
||||
AddButton(
|
||||
container,
|
||||
|
|
|
|||
|
|
@ -131,8 +131,14 @@ uint64 Account::willHaveSessionUniqueId(MTP::Config *config) const {
|
|||
| (config && config->isTestMode() ? 0x0100'0000'0000'0000ULL : 0ULL);
|
||||
}
|
||||
|
||||
void Account::createSession(const MTPUser &user) {
|
||||
createSession(user, QByteArray(), 0, std::make_unique<SessionSettings>());
|
||||
void Account::createSession(
|
||||
const MTPUser &user,
|
||||
std::unique_ptr<SessionSettings> settings) {
|
||||
createSession(
|
||||
user,
|
||||
QByteArray(),
|
||||
0,
|
||||
settings ? std::move(settings) : std::make_unique<SessionSettings>());
|
||||
}
|
||||
|
||||
void Account::createSession(
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ public:
|
|||
void start(std::unique_ptr<MTP::Config> config);
|
||||
|
||||
[[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(
|
||||
UserId id,
|
||||
QByteArray serialized,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ AppConfig::AppConfig(not_null<Account*> account) : _account(account) {
|
|||
_api.emplace(instance);
|
||||
refresh();
|
||||
}, _lifetime);
|
||||
|
||||
account->sessionChanges(
|
||||
) | rpl::filter([=](Session *session) {
|
||||
return (session != nullptr);
|
||||
}) | rpl::start_with_next([=] {
|
||||
refresh();
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void AppConfig::refresh() {
|
||||
|
|
|
|||
|
|
@ -9,15 +9,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "core/application.h"
|
||||
#include "core/shortcuts.h"
|
||||
#include "core/crash_reports.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_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_dc_options.h"
|
||||
#include "storage/storage_domain.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "export/export_settings.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "facades.h"
|
||||
|
||||
namespace Main {
|
||||
|
|
@ -28,6 +32,22 @@ Domain::Domain(const QString &dataName)
|
|||
_active.changes(
|
||||
) | rpl::take(1) | rpl::start_with_next([] {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +273,20 @@ not_null<Main::Account*> Domain::add(MTP::Environment environment) {
|
|||
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) {
|
||||
account->sessionValue(
|
||||
) | rpl::filter([=](Session *session) {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ public:
|
|||
|
||||
[[nodiscard]] not_null<Main::Account*> add(MTP::Environment environment);
|
||||
void activate(not_null<Main::Account*> account);
|
||||
void addActivated(MTP::Environment environment);
|
||||
|
||||
// Interface for Storage::Domain.
|
||||
void accountAddedInStorage(AccountWithIndex accountWithIndex);
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ MainWidget::MainWidget(
|
|||
not_null<Window::SessionController*> controller)
|
||||
: RpWidget(parent)
|
||||
, _controller(controller)
|
||||
, _api(&controller->session().mtp())
|
||||
, _dialogsWidth(st::columnMinimalWidthLeft)
|
||||
, _thirdColumnWidth(st::columnMinimalWidthThird)
|
||||
, _sideShadow(this)
|
||||
|
|
@ -370,8 +371,6 @@ MainWidget::MainWidget(
|
|||
cSetOtherOnline(0);
|
||||
|
||||
_history->start();
|
||||
|
||||
Core::App().checkStartUrl();
|
||||
}
|
||||
|
||||
MainWidget::~MainWidget() = default;
|
||||
|
|
@ -621,6 +620,8 @@ void MainWidget::clearHider(not_null<Window::HistoryHider*> instance) {
|
|||
return;
|
||||
}
|
||||
_hider.release();
|
||||
controller()->setSelectingPeer(false);
|
||||
|
||||
if (Adaptive::OneColumn()) {
|
||||
if (_mainSection || (_history->peer() && _history->peer()->id)) {
|
||||
auto animationParams = ([=] {
|
||||
|
|
@ -646,6 +647,8 @@ void MainWidget::hiderLayer(base::unique_qptr<Window::HistoryHider> hider) {
|
|||
}
|
||||
|
||||
_hider = std::move(hider);
|
||||
controller()->setSelectingPeer(true);
|
||||
|
||||
_hider->setParent(this);
|
||||
|
||||
_hider->hidden(
|
||||
|
|
@ -1274,7 +1277,6 @@ void MainWidget::scheduleViewIncrement(HistoryItem *item) {
|
|||
}
|
||||
|
||||
void MainWidget::viewsIncrement() {
|
||||
const auto api = &session().api();
|
||||
for (auto i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) {
|
||||
if (_viewsIncrementRequests.contains(i->first)) {
|
||||
++i;
|
||||
|
|
@ -1286,7 +1288,7 @@ void MainWidget::viewsIncrement() {
|
|||
for (const auto msgId : i->second) {
|
||||
ids.push_back(MTP_int(msgId));
|
||||
}
|
||||
const auto requestId = api->request(MTPmessages_GetMessagesViews(
|
||||
const auto requestId = _api.request(MTPmessages_GetMessagesViews(
|
||||
i->first->input,
|
||||
MTP_vector<MTPint>(ids),
|
||||
MTP_bool(true)
|
||||
|
|
@ -1417,6 +1419,7 @@ void MainWidget::ui_showPeerHistory(
|
|||
if (_hider) {
|
||||
_hider->startHide();
|
||||
_hider.release();
|
||||
controller()->setSelectingPeer(false);
|
||||
}
|
||||
|
||||
auto animatedShow = [&] {
|
||||
|
|
@ -2648,7 +2651,7 @@ void MainWidget::openPeerByName(
|
|||
});
|
||||
}
|
||||
} else {
|
||||
session().api().request(MTPcontacts_ResolveUsername(
|
||||
_api.request(MTPcontacts_ResolveUsername(
|
||||
MTP_string(username)
|
||||
)).done([=](const MTPcontacts_ResolvedPeer &result) {
|
||||
usernameResolveDone(result, msgId, startToken);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/rp_widget.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "media/player/media_player_float.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "data/data_pts_waiter.h"
|
||||
|
||||
class RPCError;
|
||||
|
|
@ -355,6 +356,7 @@ private:
|
|||
void handleHistoryBack();
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
MTP::Sender _api;
|
||||
|
||||
Ui::Animations::Simple _a_show;
|
||||
bool _showBack = false;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ VolumeController::VolumeController(
|
|||
Core::App().settings().setRememberedSongVolume(volume);
|
||||
}
|
||||
applyVolumeChange(volume);
|
||||
controller->session().saveSettingsDelayed();
|
||||
Core::App().saveSettingsDelayed();
|
||||
});
|
||||
Core::App().settings().songVolumeChanges(
|
||||
) | rpl::start_with_next([=](float64 volume) {
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
|
|||
? 0.
|
||||
: Core::App().settings().rememberedSongVolume();
|
||||
Core::App().settings().setSongVolume(volume);
|
||||
Core::App().saveSettingsDelayed();
|
||||
mixer()->setSongVolume(volume);
|
||||
});
|
||||
Core::App().settings().songVolumeChanges(
|
||||
|
|
|
|||
|
|
@ -2655,10 +2655,8 @@ void OverlayWidget::playbackControlsSeekFinished(crl::time position) {
|
|||
|
||||
void OverlayWidget::playbackControlsVolumeChanged(float64 volume) {
|
||||
Core::App().settings().setVideoVolume(volume);
|
||||
Core::App().saveSettingsDelayed();
|
||||
updateMixerVideoVolume();
|
||||
if (_document) {
|
||||
_document->session().saveSettingsDelayed();
|
||||
}
|
||||
}
|
||||
|
||||
float64 OverlayWidget::playbackControlsCurrentVolume() {
|
||||
|
|
|
|||
|
|
@ -253,11 +253,10 @@ void start() {
|
|||
|
||||
// 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 ((((QIcon::themeName() == qstr("hicolor") // QGenericUnixTheme
|
||||
if (((QIcon::themeName() == qstr("hicolor") // QGenericUnixTheme
|
||||
&& QIcon::fallbackThemeName() == qstr("hicolor"))
|
||||
|| (QIcon::themeName() == qstr("Adwaita") // QGnomeTheme
|
||||
&& QIcon::fallbackThemeName() == qstr("gnome")))
|
||||
&& DesktopEnvironment::IsGtkBased())
|
||||
|| IsGtkIntegrationForced()) {
|
||||
DEBUG_LOG(("Set GTK icon theme"));
|
||||
QIcon::setThemeName(gtkSetting("gtk-icon-theme-name"));
|
||||
|
|
|
|||
|
|
@ -582,7 +582,9 @@ void Manager::Private::showNotification(
|
|||
const QString &msg,
|
||||
bool hideNameAndPhoto,
|
||||
bool hideReplyButton) {
|
||||
if (!Supported()) return;
|
||||
if (!Supported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto key = FullPeer{
|
||||
.sessionId = peer->session().uniqueId(),
|
||||
|
|
@ -630,7 +632,9 @@ void Manager::Private::showNotification(
|
|||
}
|
||||
|
||||
void Manager::Private::clearAll() {
|
||||
if (!Supported()) return;
|
||||
if (!Supported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &[key, notifications] : base::take(_notifications)) {
|
||||
for (const auto &[msgId, notification] : notifications) {
|
||||
|
|
@ -640,7 +644,9 @@ void Manager::Private::clearAll() {
|
|||
}
|
||||
|
||||
void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||
if (!Supported()) return;
|
||||
if (!Supported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto key = FullPeer{
|
||||
.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) {
|
||||
if (!Supported()) return;
|
||||
if (!Supported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto sessionId = session->uniqueId();
|
||||
for (auto i = _notifications.begin(); i != _notifications.end();) {
|
||||
if (i->first.sessionId == sessionId) {
|
||||
const auto temp = base::take(i->second);
|
||||
i = _notifications.erase(i);
|
||||
if (i->first.sessionId != sessionId) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
const auto temp = base::take(i->second);
|
||||
i = _notifications.erase(i);
|
||||
|
||||
for (const auto &[msgId, notification] : temp) {
|
||||
notification->close();
|
||||
}
|
||||
for (const auto &[msgId, notification] : temp) {
|
||||
notification->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::Private::clearNotification(NotificationId id) {
|
||||
if (!Supported()) return;
|
||||
if (!Supported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto i = _notifications.find(id.full);
|
||||
if (i != _notifications.cend()) {
|
||||
|
|
|
|||
|
|
@ -520,6 +520,7 @@ QString GetIconName() {
|
|||
}
|
||||
|
||||
bool GtkClipboardSupported() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
return (Libs::gtk_clipboard_get != nullptr)
|
||||
&& (Libs::gtk_clipboard_wait_for_contents != nullptr)
|
||||
&& (Libs::gtk_clipboard_wait_for_image != nullptr)
|
||||
|
|
@ -531,6 +532,9 @@ bool GtkClipboardSupported() {
|
|||
&& (Libs::gdk_pixbuf_get_rowstride != nullptr)
|
||||
&& (Libs::gdk_pixbuf_get_has_alpha != nullptr)
|
||||
&& (Libs::gdk_atom_intern != nullptr);
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QImage GetImageFromClipboard() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef OS_OSX
|
||||
|
||||
#include "platform/platform_specific.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
|
|
@ -12,13 +15,15 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
namespace Platform {
|
||||
|
||||
enum class TouchBarType {
|
||||
None,
|
||||
Main,
|
||||
AudioPlayer,
|
||||
AudioPlayerForce,
|
||||
};
|
||||
} // namespace
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
@interface TouchBar : NSTouchBar
|
||||
|
||||
|
|
@ -31,3 +36,5 @@ enum class TouchBarType {
|
|||
- (void) showInputFieldItem:(bool)show;
|
||||
|
||||
@end
|
||||
|
||||
#endif // OS_OSX
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "platform/mac/mac_touchbar.h"
|
||||
|
||||
#import "mac_touchbar.h"
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#ifndef OS_OSX
|
||||
|
||||
#include "api/api_sending.h"
|
||||
#include "apiwrap.h"
|
||||
|
|
@ -49,6 +49,8 @@
|
|||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
namespace {
|
||||
//https://developer.apple.com/design/human-interface-guidelines/macos/touch-bar/touch-bar-icons-and-images/
|
||||
constexpr auto kIdealIconSize = 36;
|
||||
|
|
@ -1905,3 +1907,5 @@ void AppendEmojiPacks(
|
|||
}
|
||||
|
||||
@end // @implementation TouchBar
|
||||
|
||||
#endif // OS_OSX
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ public:
|
|||
void didExitFullScreen();
|
||||
|
||||
bool clipboardHasText();
|
||||
|
||||
#ifndef OS_OSX
|
||||
TouchBar *_touchBar = nil;
|
||||
|
||||
#endif // OS_OSX
|
||||
~Private();
|
||||
|
||||
private:
|
||||
|
|
@ -197,7 +197,9 @@ private:
|
|||
}
|
||||
|
||||
- (void) darkModeChanged:(NSNotification *)aNotification {
|
||||
Core::App().domain().notifyUnreadBadgeChanged();
|
||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||
Core::App().domain().notifyUnreadBadgeChanged();
|
||||
});
|
||||
}
|
||||
|
||||
- (void) screenIsLocked:(NSNotification *)aNotification {
|
||||
|
|
@ -486,6 +488,7 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
|||
}
|
||||
|
||||
void MainWindow::initTouchBar() {
|
||||
#ifndef OS_OSX
|
||||
if (!IsMac10_13OrGreater()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -513,14 +516,17 @@ void MainWindow::initTouchBar() {
|
|||
destroyCurrentTouchBar();
|
||||
}
|
||||
}, lifetime());
|
||||
#endif // OS_OSX
|
||||
}
|
||||
|
||||
void MainWindow::destroyCurrentTouchBar() {
|
||||
#ifndef OS_OSX
|
||||
if (_private->_touchBar) {
|
||||
[_private->_touchBar setTouchBar:Platform::TouchBarType::None];
|
||||
[_private->_touchBar release];
|
||||
}
|
||||
_private->_touchBar = nil;
|
||||
#endif // OS_OSX
|
||||
}
|
||||
|
||||
void MainWindow::closeWithoutDestroy() {
|
||||
|
|
@ -844,9 +850,13 @@ void MainWindow::updateGlobalMenuHook() {
|
|||
canCopy = list->canCopySelected();
|
||||
canDelete = list->canDeleteSelected();
|
||||
}
|
||||
|
||||
#ifndef OS_OSX
|
||||
if (_private->_touchBar) {
|
||||
[_private->_touchBar showInputFieldItem:showTouchBarItem];
|
||||
}
|
||||
#endif // OS_OSX
|
||||
|
||||
App::wnd()->updateIsActive();
|
||||
const auto logged = (sessionController() != nullptr);
|
||||
const auto inactive = !logged || controller().locked();
|
||||
|
|
|
|||
|
|
@ -415,7 +415,9 @@ Manager::Private::~Private() {
|
|||
}
|
||||
|
||||
void Manager::Private::clearAll() {
|
||||
if (!_notifier) return;
|
||||
if (!_notifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto temp = 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) {
|
||||
if (!_notifier) return;
|
||||
if (!_notifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto i = _notifications.find(FullPeer{
|
||||
.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) {
|
||||
if (!_notifier) return;
|
||||
if (!_notifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto sessionId = session->uniqueId();
|
||||
for (auto i = _notifications.begin(); i != _notifications.end();) {
|
||||
if (i->first.sessionId == sessionId) {
|
||||
const auto temp = base::take(i->second);
|
||||
_notifications.erase(i);
|
||||
if (i->first.sessionId != sessionId) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
const auto temp = base::take(i->second);
|
||||
_notifications.erase(i);
|
||||
|
||||
for (const auto &[msgId, notification] : temp) {
|
||||
_notifier->Hide(notification.p.Get());
|
||||
}
|
||||
for (const auto &[msgId, notification] : temp) {
|
||||
_notifier->Hide(notification.p.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ Calls::Calls(
|
|||
|
||||
Calls::~Calls() {
|
||||
if (_needWriteSettings) {
|
||||
_controller->session().saveSettingsDelayed();
|
||||
Core::App().saveSettingsDelayed();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ void Calls::setupContent() {
|
|||
: "default";
|
||||
Core::App().settings().setCallOutputDeviceID(
|
||||
QString::fromStdString(deviceId));
|
||||
_controller->session().saveSettingsDelayed();
|
||||
Core::App().saveSettingsDelayed();
|
||||
if (const auto call = Core::App().calls().currentCall()) {
|
||||
call->setCurrentAudioDevice(false, deviceId);
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ void Calls::setupContent() {
|
|||
: "default";
|
||||
Core::App().settings().setCallInputDeviceID(
|
||||
QString::fromStdString(deviceId));
|
||||
_controller->session().saveSettingsDelayed();
|
||||
Core::App().saveSettingsDelayed();
|
||||
if (_micTester) {
|
||||
stopTestingMicrophone();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "settings/settings_folders.h"
|
||||
#include "settings/settings_calls.h"
|
||||
#include "kotato/settings_menu.h"
|
||||
#include "core/application.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
|
|
@ -30,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwindow.h"
|
||||
#include "app.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_domain.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
|
|
@ -200,6 +202,12 @@ void FillMenu(
|
|||
tr::lng_settings_bg_theme_create(tr::now),
|
||||
[=] { window->show(Box(Window::Theme::CreateBox, window)); });
|
||||
} 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";
|
||||
if (type != Type::Kotato && !controller->session().supportMode()) {
|
||||
addAction(
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwindow.h"
|
||||
#include "core/application.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_domain.h"
|
||||
#include "apiwrap.h"
|
||||
#include "facades.h"
|
||||
|
|
@ -540,9 +541,49 @@ void SetupAdvancedNotifications(
|
|||
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 ¬ifications = 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(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container) {
|
||||
SetupMultiAccountNotifications(controller, container);
|
||||
|
||||
AddSubsectionTitle(container, tr::lng_settings_notify_title());
|
||||
|
||||
const auto session = &controller->session();
|
||||
|
|
|
|||
|
|
@ -204,8 +204,9 @@ PeerData *readPeer(
|
|||
const auto loaded = (peerId == selfId)
|
||||
? session->user().get()
|
||||
: session->data().peerLoaded(peerId);
|
||||
const auto apply = !loaded || (loaded->loadedStatus != PeerData::FullLoaded);
|
||||
const auto result = loaded ? loaded : session->data().peer(peerId).get();
|
||||
if (!loaded) {
|
||||
if (apply) {
|
||||
result->loadedStatus = PeerData::FullLoaded;
|
||||
}
|
||||
if (const auto user = result->asUser()) {
|
||||
|
|
@ -230,7 +231,7 @@ PeerData *readPeer(
|
|||
? App::formatPhone(phone)
|
||||
: QString();
|
||||
|
||||
if (!loaded) {
|
||||
if (apply) {
|
||||
user->setPhone(phone);
|
||||
user->setName(first, last, pname, username);
|
||||
|
||||
|
|
@ -268,7 +269,7 @@ PeerData *readPeer(
|
|||
if (oldForbidden) {
|
||||
flags |= quint32(MTPDchat_ClientFlag::f_forbidden);
|
||||
}
|
||||
if (!loaded) {
|
||||
if (apply) {
|
||||
chat->setName(name);
|
||||
chat->count = count;
|
||||
chat->date = date;
|
||||
|
|
@ -296,7 +297,7 @@ PeerData *readPeer(
|
|||
if (oldForbidden) {
|
||||
flags |= quint32(MTPDchannel_ClientFlag::f_forbidden);
|
||||
}
|
||||
if (!loaded) {
|
||||
if (apply) {
|
||||
channel->setName(name, QString());
|
||||
channel->access = access;
|
||||
channel->date = date;
|
||||
|
|
@ -312,7 +313,7 @@ PeerData *readPeer(
|
|||
channel->inputChannel = MTP_inputChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access));
|
||||
}
|
||||
}
|
||||
if (!loaded) {
|
||||
if (apply) {
|
||||
using LocationType = StorageFileLocation::Type;
|
||||
const auto location = (userpic->valid() && userpic->isLegacy())
|
||||
? userpic->convertToModern(
|
||||
|
|
|
|||
|
|
@ -286,7 +286,6 @@ std::optional<PreparedList> PreparedList::PreparedFileFromFilesDialog(
|
|||
}
|
||||
|
||||
if (!result.remoteContent.isEmpty()) {
|
||||
|
||||
auto list = Storage::PrepareMediaFromImage(
|
||||
QImage(),
|
||||
std::move(result.remoteContent),
|
||||
|
|
@ -311,7 +310,7 @@ std::optional<PreparedList> PreparedList::PreparedFileFromFilesDialog(
|
|||
}
|
||||
}
|
||||
Expects(list.files.size() == 1);
|
||||
return std::move(list);
|
||||
return list;
|
||||
} else if (!result.paths.isEmpty()) {
|
||||
const auto isSingleFile = (result.paths.size() == 1);
|
||||
auto temp = Storage::PrepareMediaList(result.paths, previewWidth);
|
||||
|
|
@ -366,7 +365,7 @@ std::optional<PreparedList> PreparedList::PreparedFileFromFilesDialog(
|
|||
list.allFilesForCompress = temp.allFilesForCompress;
|
||||
list.files = std::move(filteredFiles);
|
||||
|
||||
return std::move(list);
|
||||
return list;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,8 +52,6 @@ constexpr auto kSystemAlertDuration = crl::time(0);
|
|||
System::System()
|
||||
: _waitTimer([=] { showNext(); })
|
||||
, _waitForAllGroupedTimer([=] { showGrouped(); }) {
|
||||
createManager();
|
||||
|
||||
subscribe(settingsChanged(), [=](ChangeType type) {
|
||||
if (type == ChangeType::DesktopEnabled) {
|
||||
App::wnd()->updateTrayMenu();
|
||||
|
|
@ -93,6 +91,9 @@ System::SkipState System::skipNotification(
|
|||
const auto notifyBy = item->specialNotificationPeer();
|
||||
if (App::quitting() || !history->currentNotification()) {
|
||||
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();
|
||||
|
||||
|
|
@ -176,7 +177,9 @@ void System::schedule(not_null<HistoryItem*> item) {
|
|||
}
|
||||
|
||||
void System::clearAll() {
|
||||
_manager->clearAll();
|
||||
if (_manager) {
|
||||
_manager->clearAll();
|
||||
}
|
||||
|
||||
for (auto i = _whenMaps.cbegin(), e = _whenMaps.cend(); i != e; ++i) {
|
||||
i->first->clearNotifications();
|
||||
|
|
@ -188,7 +191,9 @@ void System::clearAll() {
|
|||
}
|
||||
|
||||
void System::clearFromHistory(not_null<History*> history) {
|
||||
_manager->clearFromHistory(history);
|
||||
if (_manager) {
|
||||
_manager->clearFromHistory(history);
|
||||
}
|
||||
|
||||
history->clearNotifications();
|
||||
_whenMaps.remove(history);
|
||||
|
|
@ -201,19 +206,21 @@ void System::clearFromHistory(not_null<History*> history) {
|
|||
}
|
||||
|
||||
void System::clearFromSession(not_null<Main::Session*> session) {
|
||||
_manager->clearFromSession(session);
|
||||
if (_manager) {
|
||||
_manager->clearFromSession(session);
|
||||
}
|
||||
|
||||
for (auto i = _whenMaps.begin(); i != _whenMaps.end();) {
|
||||
const auto history = i->first;
|
||||
if (&history->session() == session) {
|
||||
history->clearNotifications();
|
||||
i = _whenMaps.erase(i);
|
||||
_whenAlerts.remove(history);
|
||||
_waiters.remove(history);
|
||||
_settingWaiters.remove(history);
|
||||
} else {
|
||||
if (&history->session() != session) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
history->clearNotifications();
|
||||
i = _whenMaps.erase(i);
|
||||
_whenAlerts.remove(history);
|
||||
_waiters.remove(history);
|
||||
_settingWaiters.remove(history);
|
||||
}
|
||||
const auto clearFrom = [&](auto &map) {
|
||||
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) {
|
||||
_manager->clearFromHistory(history);
|
||||
if (_manager) {
|
||||
_manager->clearFromHistory(history);
|
||||
}
|
||||
history->clearIncomingNotifications();
|
||||
_whenAlerts.remove(history);
|
||||
}
|
||||
|
||||
void System::clearFromItem(not_null<HistoryItem*> item) {
|
||||
_manager->clearFromItem(item);
|
||||
if (_manager) {
|
||||
_manager->clearFromItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void System::clearAllFast() {
|
||||
_manager->clearAllFast();
|
||||
if (_manager) {
|
||||
_manager->clearAllFast();
|
||||
}
|
||||
|
||||
_whenMaps.clear();
|
||||
_whenAlerts.clear();
|
||||
|
|
@ -295,6 +308,8 @@ void System::checkDelayed() {
|
|||
}
|
||||
|
||||
void System::showGrouped() {
|
||||
Expects(_manager != nullptr);
|
||||
|
||||
if (const auto session = findSession(_lastHistorySessionId)) {
|
||||
if (const auto lastItem = session->data().message(_lastHistoryItemId)) {
|
||||
_waitForAllGroupedTimer.cancel();
|
||||
|
|
@ -307,7 +322,11 @@ void System::showGrouped() {
|
|||
}
|
||||
|
||||
void System::showNext() {
|
||||
if (App::quitting()) return;
|
||||
Expects(_manager != nullptr);
|
||||
|
||||
if (App::quitting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto isSameGroup = [=](HistoryItem *item) {
|
||||
if (!_lastHistorySessionId || !_lastHistoryItemId || !item) {
|
||||
|
|
@ -538,7 +557,9 @@ void System::ensureSoundCreated() {
|
|||
}
|
||||
|
||||
void System::updateAll() {
|
||||
_manager->updateAll();
|
||||
if (_manager) {
|
||||
_manager->updateAll();
|
||||
}
|
||||
}
|
||||
|
||||
Manager::DisplayOptions Manager::GetNotificationOptions(HistoryItem *item) {
|
||||
|
|
@ -561,7 +582,17 @@ Manager::DisplayOptions Manager::GetNotificationOptions(HistoryItem *item) {
|
|||
QString Manager::addTargetAccountName(
|
||||
const QString &title,
|
||||
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
|
||||
+ accountNameSeparator()
|
||||
+ (session->user()->username.isEmpty()
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ void Manager::showNextFromQueue() {
|
|||
return;
|
||||
}
|
||||
int count = Core::App().settings().notificationsCount();
|
||||
for_const (auto ¬ification, _notifications) {
|
||||
for (const auto ¬ification : _notifications) {
|
||||
if (notification->isUnlinked()) continue;
|
||||
--count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,9 +85,6 @@ void Controller::showAccount(not_null<Main::Account*> account) {
|
|||
setupIntro();
|
||||
_widget.updateGlobalMenu();
|
||||
}
|
||||
if (was) {
|
||||
was->session().updates().updateOnline();
|
||||
}
|
||||
}, _accountLifetime);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "settings/settings_common.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
#include "boxes/about_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "calls/calls_box_controller.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_settings.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QScreen>
|
||||
|
|
@ -100,13 +102,15 @@ public:
|
|||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||
void paintUserpic(Painter &p);
|
||||
|
||||
const not_null<Main::Account*> _account;
|
||||
const not_null<Main::Session*> _session;
|
||||
const style::Menu &_st;
|
||||
std::shared_ptr<Data::CloudImageView> _userpicView;
|
||||
InMemoryKey _userpicKey = {};
|
||||
QImage _userpicCache;
|
||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||
|
||||
Dialogs::Layout::UnreadBadgeStyle _unreadSt;
|
||||
int _unreadBadge = 0;
|
||||
|
|
@ -154,7 +158,7 @@ MainMenu::AccountButton::AccountButton(
|
|||
QWidget *parent,
|
||||
not_null<Main::Account*> account)
|
||||
: RippleButton(parent, st::defaultRippleAnimation)
|
||||
, _account(account)
|
||||
, _session(&account->session())
|
||||
, _st(st::mainMenu){
|
||||
const auto height = _st.itemPadding.top()
|
||||
+ _st.itemStyle.font->height
|
||||
|
|
@ -168,33 +172,27 @@ MainMenu::AccountButton::AccountButton(
|
|||
}
|
||||
});
|
||||
|
||||
_account->sessionValue(
|
||||
) | rpl::filter([=](Main::Session *session) {
|
||||
return (session != nullptr);
|
||||
}) | rpl::start_with_next([=](not_null<Main::Session*> session) {
|
||||
rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
session->data().unreadBadgeChanges()
|
||||
) | rpl::start_with_next([=] {
|
||||
_unreadBadge = session->data().unreadBadge();
|
||||
_unreadBadgeMuted = session->data().unreadBadgeMuted();
|
||||
update();
|
||||
}, lifetime());
|
||||
rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
_session->data().unreadBadgeChanges()
|
||||
) | rpl::start_with_next([=] {
|
||||
_unreadBadge = _session->data().unreadBadge();
|
||||
_unreadBadgeMuted = _session->data().unreadBadgeMuted();
|
||||
update();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void MainMenu::AccountButton::paintUserpic(Painter &p) {
|
||||
Expects(_account->sessionExists());
|
||||
|
||||
const auto size = st::mainMenuAccountSize;
|
||||
const auto iconSize = height() - 2 * _st.itemIconPosition.y();
|
||||
const auto shift = (size - iconSize) / 2;
|
||||
const auto x = _st.itemIconPosition.x() - shift;
|
||||
const auto y = (height() - size) / 2;
|
||||
|
||||
const auto check = (_account == &Core::App().domain().active());
|
||||
const auto user = _account->session().user();
|
||||
const auto check = (&_session->account()
|
||||
== &Core::App().domain().active());
|
||||
const auto user = _session->user();
|
||||
if (!check) {
|
||||
user->paintUserpicLeft(p, _userpicView, x, y, width(), size);
|
||||
return;
|
||||
|
|
@ -235,8 +233,6 @@ void MainMenu::AccountButton::paintUserpic(Painter &p) {
|
|||
}
|
||||
|
||||
void MainMenu::AccountButton::paintEvent(QPaintEvent *e) {
|
||||
Expects(_account->sessionExists());
|
||||
|
||||
auto p = Painter(this);
|
||||
const auto over = isOver();
|
||||
p.fillRect(rect(), over ? _st.itemBgOver : _st.itemBg);
|
||||
|
|
@ -245,7 +241,8 @@ void MainMenu::AccountButton::paintEvent(QPaintEvent *e) {
|
|||
paintUserpic(p);
|
||||
|
||||
auto available = width() - _st.itemPadding.left();
|
||||
if (_unreadBadge && _account != &Core::App().activeAccount()) {
|
||||
if (_unreadBadge
|
||||
&& (&_session->account() != &Core::App().activeAccount())) {
|
||||
_unreadSt.muted = _unreadBadgeMuted;
|
||||
const auto string = (_unreadBadge > 99)
|
||||
? "99+"
|
||||
|
|
@ -268,13 +265,39 @@ void MainMenu::AccountButton::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
p.setPen(over ? _st.itemFgOver : _st.itemFg);
|
||||
_account->session().user()->nameText().drawElided(
|
||||
_session->user()->nameText().drawElided(
|
||||
p,
|
||||
_st.itemPadding.left(),
|
||||
_st.itemPadding.top(),
|
||||
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)
|
||||
: AbstractButton(parent) {
|
||||
rpl::single(
|
||||
|
|
@ -642,14 +665,17 @@ void MainMenu::setupCloudButton() {
|
|||
}
|
||||
|
||||
void MainMenu::setupUserpicButton() {
|
||||
_userpicButton->setClickedCallback([=] {
|
||||
_controller->content()->choosePeer(
|
||||
_controller->session().userPeerId(),
|
||||
ShowAtUnreadMsgId);
|
||||
});
|
||||
_userpicButton->setClickedCallback([=] { toggleAccounts(); });
|
||||
_userpicButton->show();
|
||||
}
|
||||
|
||||
void MainMenu::toggleAccounts() {
|
||||
auto &settings = Core::App().settings();
|
||||
const auto shown = !settings.mainMenuAccountsShown();
|
||||
settings.setMainMenuAccountsShown(shown);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}
|
||||
|
||||
void MainMenu::setupAccounts() {
|
||||
const auto inner = _accounts->entity();
|
||||
|
||||
|
|
@ -688,7 +714,6 @@ void MainMenu::setupAccounts() {
|
|||
rebuildAccounts();
|
||||
}, lifetime());
|
||||
|
||||
_accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue());
|
||||
_accounts->toggleOn(Core::App().settings().mainMenuAccountsShownValue());
|
||||
_accounts->finishAnimating();
|
||||
|
||||
|
|
@ -772,18 +797,7 @@ not_null<Ui::SlideWrap<Ui::RippleButton>*> MainMenu::setupAddAccount(
|
|||
}, button->lifetime());
|
||||
|
||||
const auto add = [=](MTP::Environment environment) {
|
||||
auto &domain = Core::App().domain();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Core::App().domain().addActivated(environment);
|
||||
};
|
||||
|
||||
button->setAcceptBoth(true);
|
||||
|
|
@ -812,12 +826,7 @@ not_null<Ui::SlideWrap<Ui::RippleButton>*> MainMenu::setupAddAccount(
|
|||
|
||||
void MainMenu::setupAccountsToggle() {
|
||||
_toggleAccounts->show();
|
||||
_toggleAccounts->setClickedCallback([=] {
|
||||
auto &settings = Core::App().settings();
|
||||
const auto shown = !settings.mainMenuAccountsShown();
|
||||
settings.setMainMenuAccountsShown(shown);
|
||||
Core::App().saveSettingsDelayed();
|
||||
});
|
||||
_toggleAccounts->setClickedCallback([=] { toggleAccounts(); });
|
||||
}
|
||||
|
||||
void MainMenu::parentResized() {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ private:
|
|||
void initResetScaleButton();
|
||||
void refreshMenu();
|
||||
void refreshBackground();
|
||||
void toggleAccounts();
|
||||
|
||||
const not_null<SessionController*> _controller;
|
||||
object_ptr<Ui::UserpicButton> _userpicButton;
|
||||
|
|
|
|||
|
|
@ -1245,7 +1245,7 @@ void PeerMenuAddChannelMembers(
|
|||
return;
|
||||
}
|
||||
const auto api = &channel->session().api();
|
||||
api->requestChannelMembersForAdd(channel, [=](
|
||||
api->requestChannelMembersForAdd(channel, crl::guard(navigation, [=](
|
||||
const MTPchannels_ChannelParticipants &result) {
|
||||
api->parseChannelParticipants(channel, result, [&](
|
||||
int availableCount,
|
||||
|
|
@ -1267,7 +1267,7 @@ void PeerMenuAddChannelMembers(
|
|||
channel,
|
||||
{ already.begin(), already.end() });
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
void PeerMenuAddMuteAction(
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ struct SectionShow {
|
|||
|
||||
class SessionController;
|
||||
|
||||
class SessionNavigation {
|
||||
class SessionNavigation : public base::has_weak_ptr {
|
||||
public:
|
||||
explicit SessionNavigation(not_null<Main::Session*> session);
|
||||
|
||||
|
|
@ -156,10 +156,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class SessionController
|
||||
: public SessionNavigation
|
||||
, public base::has_weak_ptr
|
||||
, private base::Subscriber {
|
||||
class SessionController : public SessionNavigation, private base::Subscriber {
|
||||
public:
|
||||
SessionController(
|
||||
not_null<Main::Session*> session,
|
||||
|
|
@ -171,6 +168,15 @@ public:
|
|||
[[nodiscard]] not_null<::MainWindow*> widget() 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
|
||||
-> not_null<ChatHelpers::TabbedSelector*>;
|
||||
void takeTabbedSelectorOwnershipFrom(not_null<QWidget*> parent);
|
||||
|
|
@ -335,6 +341,7 @@ private:
|
|||
base::Variable<bool> _dialogsListDisplayForced = { false };
|
||||
std::deque<Dialogs::RowDescriptor> _chatEntryHistory;
|
||||
int _chatEntryHistoryPosition = -1;
|
||||
bool _selectingPeer = false;
|
||||
|
||||
rpl::variable<FilterId> _activeChatsFilter;
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,12 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
AppVersion 2001014
|
||||
AppVersion 2001016
|
||||
AppVersionStrMajor 2.1
|
||||
AppVersionStrSmall 2.1.14
|
||||
AppVersionStr 2.1.14
|
||||
AppVersionStrSmall 2.1.16
|
||||
AppVersionStr 2.1.16
|
||||
BetaChannel 1
|
||||
AlphaVersion 0
|
||||
AppVersionOriginal 2.1.14.beta
|
||||
AppVersionOriginal 2.1.16.beta
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
- Support for multiple accounts.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue