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.
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 }}

View file

@ -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/*') }}

View file

@ -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/*') }}

View file

@ -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";

View file

@ -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>

View file

@ -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"

View file

@ -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"

View file

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

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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()

View file

@ -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();

View file

@ -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;

View file

@ -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
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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()) {

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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();

View file

@ -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

View file

@ -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>()

View file

@ -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;

View file

@ -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));
}

View file

@ -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();

View file

@ -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,

View file

@ -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(

View file

@ -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,

View file

@ -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() {

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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(

View file

@ -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() {

View file

@ -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"));

View file

@ -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()) {

View file

@ -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() {

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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());
}
}
}

View file

@ -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();
}

View file

@ -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(

View file

@ -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 &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(
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();

View file

@ -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(

View file

@ -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;
}

View file

@ -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()

View file

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

View file

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

View file

@ -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() {

View file

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

View file

@ -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(

View file

@ -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;

View file

@ -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);

View file

@ -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

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)
- Support for multiple accounts.