Closed beta 10020002: Use default color theme link in Settings.

This commit is contained in:
John Preston 2016-12-20 16:03:51 +03:00
parent 0480e02b23
commit 177078b0af
70 changed files with 788 additions and 419 deletions

View file

@ -289,6 +289,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_settings_send_cmdenter" = "Send by Cmd+Enter"; "lng_settings_send_cmdenter" = "Send by Cmd+Enter";
"lng_settings_section_background" = "Chat background"; "lng_settings_section_background" = "Chat background";
"lng_settings_bg_use_default" = "Use default color theme";
"lng_settings_bg_from_gallery" = "Choose from gallery"; "lng_settings_bg_from_gallery" = "Choose from gallery";
"lng_settings_bg_from_file" = "Choose from file"; "lng_settings_bg_from_file" = "Choose from file";
"lng_settings_bg_tile" = "Tile background"; "lng_settings_bg_tile" = "Tile background";
@ -347,7 +348,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_passcode_enter_first" = "Enter a passcode"; "lng_passcode_enter_first" = "Enter a passcode";
"lng_passcode_enter_new" = "Enter new passcode"; "lng_passcode_enter_new" = "Enter new passcode";
"lng_passcode_confirm_new" = "Re-enter new passcode"; "lng_passcode_confirm_new" = "Re-enter new passcode";
"lng_passcode_about" = "When a local passcode is set, a lock icon appears in the top right corner of the window. Click it to lock the app.\n\nNote: if you forget your local passcode, you'll need to relogin in Telegram Desktop."; "lng_passcode_about" = "When a local passcode is set, a lock icon appears at the top of your chats list. Click it to lock the app.\n\nNote: if you forget your local passcode, you'll need to relogin in Telegram Desktop.";
"lng_passcode_differ" = "Passcodes are different"; "lng_passcode_differ" = "Passcodes are different";
"lng_passcode_wrong" = "Wrong passcode"; "lng_passcode_wrong" = "Wrong passcode";
"lng_passcode_is_same" = "Passcode was not changed"; "lng_passcode_is_same" = "Passcode was not changed";

View file

@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,20,1 FILEVERSION 0,10,20,2
PRODUCTVERSION 0,10,20,1 PRODUCTVERSION 0,10,20,2
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0" BLOCK "040904b0"
BEGIN BEGIN
VALUE "CompanyName", "Telegram Messenger LLP" VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.10.20.1" VALUE "FileVersion", "0.10.20.2"
VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.20.1" VALUE "ProductVersion", "0.10.20.2"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,20,1 FILEVERSION 0,10,20,2
PRODUCTVERSION 0,10,20,1 PRODUCTVERSION 0,10,20,2
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,10 +43,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Telegram Messenger LLP" VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Updater" VALUE "FileDescription", "Telegram Updater"
VALUE "FileVersion", "0.10.20.1" VALUE "FileVersion", "0.10.20.2"
VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.20.1" VALUE "ProductVersion", "0.10.20.2"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -2211,26 +2211,7 @@ namespace {
return MsgRadius; return MsgRadius;
} }
void initMedia() { void createCorners() {
if (!::monofont) {
QString family;
tryFontFamily(family, qsl("Consolas"));
tryFontFamily(family, qsl("Liberation Mono"));
tryFontFamily(family, qsl("Menlo"));
tryFontFamily(family, qsl("Courier"));
if (family.isEmpty()) family = QFontDatabase::systemFont(QFontDatabase::FixedFont).family();
::monofont = style::font(st::normalFont->f.pixelSize(), 0, family);
}
emojiInit();
if (!::emoji) {
::emoji = new QPixmap(QLatin1String(EName));
if (cRetina()) ::emoji->setDevicePixelRatio(cRetinaFactor());
}
if (!::emojiLarge) {
::emojiLarge = new QPixmap(QLatin1String(EmojiNames[EIndex + 1]));
if (cRetina()) ::emojiLarge->setDevicePixelRatio(cRetinaFactor());
}
style::color white = { 255, 255, 255, 255 }; style::color white = { 255, 255, 255, 255 };
QImage mask[4]; QImage mask[4];
prepareCorners(LargeMaskCorners, msgRadius(), white, nullptr, mask); prepareCorners(LargeMaskCorners, msgRadius(), white, nullptr, mask);
@ -2272,22 +2253,69 @@ namespace {
prepareCorners(MessageInSelectedCorners, msgRadius(), st::msgInBgSelected, &st::msgInShadowSelected); prepareCorners(MessageInSelectedCorners, msgRadius(), st::msgInBgSelected, &st::msgInShadowSelected);
prepareCorners(MessageOutCorners, msgRadius(), st::msgOutBg, &st::msgOutShadow); prepareCorners(MessageOutCorners, msgRadius(), st::msgOutBg, &st::msgOutShadow);
prepareCorners(MessageOutSelectedCorners, msgRadius(), st::msgOutBgSelected, &st::msgOutShadowSelected); prepareCorners(MessageOutSelectedCorners, msgRadius(), st::msgOutBgSelected, &st::msgOutShadowSelected);
}
static auto subscription = Window::Theme::Background()->add_subscription([](const Window::Theme::BackgroundUpdate &update) { void clearCorners() {
if (update.type != Window::Theme::BackgroundUpdate::Type::New) { for (int j = 0; j < 4; ++j) {
return; for (int i = 0; i < RoundCornersCount; ++i) {
delete ::corners[i].p[j]; ::corners[i].p[j] = nullptr;
} }
for (int i = 0; i < 4; ++i) { delete ::cornersMaskSmall[j]; ::cornersMaskSmall[j] = nullptr;
delete ::corners[StickerCorners].p[i]; ::corners[StickerCorners].p[i] = nullptr; delete ::cornersMaskLarge[j]; ::cornersMaskLarge[j] = nullptr;
delete ::corners[StickerSelectedCorners].p[i]; ::corners[StickerSelectedCorners].p[i] = nullptr; }
for (auto i = ::cornersMap.cbegin(), e = ::cornersMap.cend(); i != e; ++i) {
for (int j = 0; j < 4; ++j) {
delete i->p[j];
} }
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg); }
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg); ::cornersMap.clear();
}
if (App::main()) { void initMedia() {
App::main()->updateScrollColors(); if (!::monofont) {
QString family;
tryFontFamily(family, qsl("Consolas"));
tryFontFamily(family, qsl("Liberation Mono"));
tryFontFamily(family, qsl("Menlo"));
tryFontFamily(family, qsl("Courier"));
if (family.isEmpty()) family = QFontDatabase::systemFont(QFontDatabase::FixedFont).family();
::monofont = style::font(st::normalFont->f.pixelSize(), 0, family);
}
emojiInit();
if (!::emoji) {
::emoji = new QPixmap(QLatin1String(EName));
if (cRetina()) ::emoji->setDevicePixelRatio(cRetinaFactor());
}
if (!::emojiLarge) {
::emojiLarge = new QPixmap(QLatin1String(EmojiNames[EIndex + 1]));
if (cRetina()) ::emojiLarge->setDevicePixelRatio(cRetinaFactor());
}
createCorners();
using Update = Window::Theme::BackgroundUpdate;
static auto subscription = Window::Theme::Background()->add_subscription([](const Update &update) {
if (update.type == Update::Type::TestingTheme) {
clearCorners();
createCorners();
if (App::main()) {
App::main()->updateScrollColors();
}
HistoryLayout::serviceColorsUpdated();
} else if (update.type == Update::Type::New) {
for (int i = 0; i < 4; ++i) {
delete ::corners[StickerCorners].p[i]; ::corners[StickerCorners].p[i] = nullptr;
delete ::corners[StickerSelectedCorners].p[i]; ::corners[StickerSelectedCorners].p[i] = nullptr;
}
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg);
if (App::main()) {
App::main()->updateScrollColors();
}
HistoryLayout::serviceColorsUpdated();
} }
HistoryLayout::serviceColorsUpdated();
}); });
} }
@ -2305,22 +2333,12 @@ namespace {
void deinitMedia() { void deinitMedia() {
delete ::emoji; delete ::emoji;
::emoji = 0; ::emoji = nullptr;
delete ::emojiLarge; delete ::emojiLarge;
::emojiLarge = 0; ::emojiLarge = nullptr;
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < RoundCornersCount; ++i) { clearCorners();
delete ::corners[i].p[j]; ::corners[i].p[j] = nullptr;
}
delete ::cornersMaskSmall[j]; ::cornersMaskSmall[j] = nullptr;
delete ::cornersMaskLarge[j]; ::cornersMaskLarge[j] = nullptr;
}
for (auto i = ::cornersMap.cbegin(), e = ::cornersMap.cend(); i != e; ++i) {
for (int j = 0; j < 4; ++j) {
delete i->p[j];
}
}
::cornersMap.clear();
mainEmojiMap.clear(); mainEmojiMap.clear();
otherEmojiMap.clear(); otherEmojiMap.clear();

View file

@ -40,58 +40,60 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_location_manager.h" #include "history/history_location_manager.h"
namespace { namespace {
void mtpStateChanged(int32 dc, int32 state) {
if (App::wnd()) {
App::wnd()->mtpStateChanged(dc, state);
}
}
void mtpSessionReset(int32 dc) { void mtpStateChanged(int32 dc, int32 state) {
if (App::main() && dc == MTP::maindc()) { if (App::wnd()) {
App::main()->getDifference(); App::wnd()->mtpStateChanged(dc, state);
}
}
QChar _toHex(ushort v) {
v = v & 0x000F;
return QChar::fromLatin1((v >= 10) ? ('a' + (v - 10)) : ('0' + v));
}
ushort _fromHex(QChar c) {
return ((c.unicode() >= uchar('a')) ? (c.unicode() - uchar('a') + 10) : (c.unicode() - uchar('0'))) & 0x000F;
}
QString _escapeTo7bit(const QString &str) {
QString result;
result.reserve(str.size() * 2);
for (int i = 0, l = str.size(); i != l; ++i) {
QChar ch(str.at(i));
ushort uch(ch.unicode());
if (uch < 32 || uch > 127 || uch == ushort(uchar('%'))) {
result.append('%').append(_toHex(uch >> 12)).append(_toHex(uch >> 8)).append(_toHex(uch >> 4)).append(_toHex(uch));
} else {
result.append(ch);
}
}
return result;
}
QString _escapeFrom7bit(const QString &str) {
QString result;
result.reserve(str.size());
for (int i = 0, l = str.size(); i != l; ++i) {
QChar ch(str.at(i));
if (ch == QChar::fromLatin1('%') && i + 4 < l) {
result.append(QChar(ushort((_fromHex(str.at(i + 1)) << 12) | (_fromHex(str.at(i + 2)) << 8) | (_fromHex(str.at(i + 3)) << 4) | _fromHex(str.at(i + 4)))));
i += 4;
} else {
result.append(ch);
}
}
return result;
} }
} }
AppClass *AppObject = 0; void mtpSessionReset(int32 dc) {
if (App::main() && dc == MTP::maindc()) {
App::main()->getDifference();
}
}
QChar _toHex(ushort v) {
v = v & 0x000F;
return QChar::fromLatin1((v >= 10) ? ('a' + (v - 10)) : ('0' + v));
}
ushort _fromHex(QChar c) {
return ((c.unicode() >= uchar('a')) ? (c.unicode() - uchar('a') + 10) : (c.unicode() - uchar('0'))) & 0x000F;
}
QString _escapeTo7bit(const QString &str) {
QString result;
result.reserve(str.size() * 2);
for (int i = 0, l = str.size(); i != l; ++i) {
QChar ch(str.at(i));
ushort uch(ch.unicode());
if (uch < 32 || uch > 127 || uch == ushort(uchar('%'))) {
result.append('%').append(_toHex(uch >> 12)).append(_toHex(uch >> 8)).append(_toHex(uch >> 4)).append(_toHex(uch));
} else {
result.append(ch);
}
}
return result;
}
QString _escapeFrom7bit(const QString &str) {
QString result;
result.reserve(str.size());
for (int i = 0, l = str.size(); i != l; ++i) {
QChar ch(str.at(i));
if (ch == QChar::fromLatin1('%') && i + 4 < l) {
result.append(QChar(ushort((_fromHex(str.at(i + 1)) << 12) | (_fromHex(str.at(i + 2)) << 8) | (_fromHex(str.at(i + 3)) << 4) | _fromHex(str.at(i + 4)))));
i += 4;
} else {
result.append(ch);
}
}
return result;
}
} // namespace
AppClass *AppObject = nullptr;
Application::Application(int &argc, char **argv) : QApplication(argc, argv) { Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath())); QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath()));
@ -468,6 +470,8 @@ void Application::stopUpdate() {
} }
void Application::startUpdateCheck(bool forceWait) { void Application::startUpdateCheck(bool forceWait) {
if (!Sandbox::started()) return;
_updateCheckTimer.stop(); _updateCheckTimer.stop();
if (_updateThread || _updateReply || !cAutoUpdate()) return; if (_updateThread || _updateReply || !cAutoUpdate()) return;

View file

@ -53,17 +53,9 @@ void BoxContent::setInner(object_ptr<TWidget> inner, const style::ScrollArea &st
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
_topShadow.create(this, object_ptr<BoxLayerTitleShadow>(this)); _topShadow.create(this, object_ptr<BoxLayerTitleShadow>(this));
if (_innerTopSkip > 0) { _bottomShadow.create(this, object_ptr<BoxLayerTitleShadow>(this));
_topShadow->showFast();
} else {
_topShadow->hideFast();
}
_bottomShadow.create(this);
_bottomShadow->show();
} else {
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), 0);
} }
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), 0);
_scroll->setOwnedWidget(std_::move(inner)); _scroll->setOwnedWidget(std_::move(inner));
updateScrollAreaGeometry(); updateScrollAreaGeometry();
} else { } else {
@ -99,17 +91,28 @@ void BoxContent::onDraggingScrollTimer() {
_scroll->scrollToY(_scroll->scrollTop() + delta); _scroll->scrollToY(_scroll->scrollTop() + delta);
} }
void BoxContent::updateInnerVisibleTopBottom() {
if (auto widget = static_cast<TWidget*>(_scroll->widget())) {
auto top = _scroll->scrollTop();
widget->setVisibleTopBottom(top, top + _scroll->height());
}
}
void BoxContent::onScroll() { void BoxContent::onScroll() {
if (_scroll) { if (_scroll) {
updateInnerVisibleTopBottom();
auto top = _scroll->scrollTop(); auto top = _scroll->scrollTop();
if (auto widget = static_cast<TWidget*>(_scroll->widget())) {
widget->setVisibleTopBottom(top, top + _scroll->height());
}
if (top > 0 || _innerTopSkip > 0) { if (top > 0 || _innerTopSkip > 0) {
_topShadow->showAnimated(); _topShadow->showAnimated();
} else { } else {
_topShadow->hideAnimated(); _topShadow->hideAnimated();
} }
if (top < _scroll->scrollTopMax()) {
_bottomShadow->showAnimated();
} else {
_bottomShadow->hideAnimated();
}
} }
} }
@ -123,11 +126,6 @@ void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) {
if (scrollBottomFixed) { if (scrollBottomFixed) {
_scroll->scrollToY(scrollTopWas + delta); _scroll->scrollToY(scrollTopWas + delta);
} }
if (_innerTopSkip > 0) {
_topShadow->showFast();
} else {
_topShadow->hideFast();
}
} }
} }
} }
@ -161,10 +159,22 @@ void BoxContent::updateScrollAreaGeometry() {
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), newScrollHeight); _scroll->setGeometryToLeft(0, _innerTopSkip, width(), newScrollHeight);
_topShadow->entity()->resize(width(), st::lineWidth); _topShadow->entity()->resize(width(), st::lineWidth);
_topShadow->moveToLeft(0, _innerTopSkip); _topShadow->moveToLeft(0, _innerTopSkip);
_bottomShadow->resize(width(), st::lineWidth); _bottomShadow->entity()->resize(width(), st::lineWidth);
_bottomShadow->moveToLeft(0, height() - st::lineWidth); _bottomShadow->moveToLeft(0, height() - st::lineWidth);
if (changed) { if (changed) {
onScroll(); updateInnerVisibleTopBottom();
auto top = _scroll->scrollTop();
if (top > 0 || _innerTopSkip > 0) {
_topShadow->showFast();
} else {
_topShadow->hideFast();
}
if (top < _scroll->scrollTopMax()) {
_bottomShadow->showFast();
} else {
_bottomShadow->hideFast();
}
} }
} }
@ -182,8 +192,8 @@ void BoxContent::paintEvent(QPaintEvent *e) {
} }
} }
AbstractBox::AbstractBox(object_ptr<BoxContent> content) AbstractBox::AbstractBox(QWidget *parent, object_ptr<BoxContent> content) : LayerWidget(parent)
: _content(std_::move(content)) { , _content(std_::move(content)) {
_content->setParent(this); _content->setParent(this);
_content->setDelegate(this); _content->setDelegate(this);
} }

View file

@ -65,6 +65,7 @@ public:
void setDelegate(BoxContentDelegate *newDelegate) { void setDelegate(BoxContentDelegate *newDelegate) {
_delegate = newDelegate; _delegate = newDelegate;
prepare(); prepare();
setInnerFocus();
} }
virtual void setInnerFocus() { virtual void setInnerFocus() {
setFocus(); setFocus();
@ -121,16 +122,16 @@ protected:
template <typename Widget> template <typename Widget>
QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, const style::ScrollArea &st, int topSkip = 0) { QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, const style::ScrollArea &st, int topSkip = 0) {
auto result = QPointer<Widget>(inner.data()); auto result = QPointer<Widget>(inner.data());
setInner(std_::move(inner), st);
setInnerTopSkip(topSkip); setInnerTopSkip(topSkip);
setInner(std_::move(inner), st);
return result; return result;
} }
template <typename Widget> template <typename Widget>
QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, int topSkip = 0) { QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, int topSkip = 0) {
auto result = QPointer<Widget>(inner.data()); auto result = QPointer<Widget>(inner.data());
setInner(std_::move(inner));
setInnerTopSkip(topSkip); setInnerTopSkip(topSkip);
setInner(std_::move(inner));
return result; return result;
} }
@ -154,6 +155,7 @@ private:
void setInner(object_ptr<TWidget> inner); void setInner(object_ptr<TWidget> inner);
void setInner(object_ptr<TWidget> inner, const style::ScrollArea &st); void setInner(object_ptr<TWidget> inner, const style::ScrollArea &st);
void updateScrollAreaGeometry(); void updateScrollAreaGeometry();
void updateInnerVisibleTopBottom();
object_ptr<TWidget> doTakeInnerWidget(); object_ptr<TWidget> doTakeInnerWidget();
BoxContentDelegate *getDelegate() const { BoxContentDelegate *getDelegate() const {
@ -166,7 +168,7 @@ private:
int _innerTopSkip = 0; int _innerTopSkip = 0;
object_ptr<Ui::ScrollArea> _scroll = { nullptr }; object_ptr<Ui::ScrollArea> _scroll = { nullptr };
object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _topShadow = { nullptr }; object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _topShadow = { nullptr };
object_ptr<BoxLayerTitleShadow> _bottomShadow = { nullptr }; object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _bottomShadow = { nullptr };
object_ptr<QTimer> _draggingScrollTimer = { nullptr }; object_ptr<QTimer> _draggingScrollTimer = { nullptr };
int _draggingScrollDelta = 0; int _draggingScrollDelta = 0;
@ -175,7 +177,7 @@ private:
class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber { class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber {
public: public:
AbstractBox(object_ptr<BoxContent> content); AbstractBox(QWidget *parent, object_ptr<BoxContent> content);
void parentResized() override; void parentResized() override;

View file

@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/toast/toast.h"
#include "ui/buttons/peer_avatar_button.h" #include "ui/buttons/peer_avatar_button.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -74,21 +75,15 @@ void AddContactBox::prepare() {
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_phone, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_phone, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) {
(_invertOrder ? _last : _first)->setDisplayFocused(true);
_phone->finishAnimations();
} else {
_phone->setDisplayFocused(true);
}
setDimensions(st::boxWideWidth, st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom()); setDimensions(st::boxWideWidth, st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom());
} }
void AddContactBox::setInnerFocus() { void AddContactBox::setInnerFocus() {
if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) { if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) {
(_invertOrder ? _last : _first)->setFocus(); (_invertOrder ? _last : _first)->setFocusFast();
_phone->finishAnimations();
} else { } else {
_phone->setFocus(); _phone->setFocusFast();
} }
} }
@ -284,13 +279,11 @@ void GroupInfoBox::prepare() {
notifyFileQueryUpdated(update); notifyFileQueryUpdated(update);
}); });
_title->setDisplayFocused(true);
updateMaxHeight(); updateMaxHeight();
} }
void GroupInfoBox::setInnerFocus() { void GroupInfoBox::setInnerFocus() {
_title->setFocus(); _title->setFocusFast();
} }
void GroupInfoBox::resizeEvent(QResizeEvent *e) { void GroupInfoBox::resizeEvent(QResizeEvent *e) {
@ -465,7 +458,7 @@ void SetupChannelBox::setInnerFocus() {
if (_link->isHidden()) { if (_link->isHidden()) {
setFocus(); setFocus();
} else { } else {
_link->setFocus(); _link->setFocusFast();
} }
} }
@ -517,16 +510,6 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
p.setFont(_linkOver ? st::boxTextFont->underline() : st::boxTextFont); p.setFont(_linkOver ? st::boxTextFont->underline() : st::boxTextFont);
p.setPen(st::defaultLinkButton.color); p.setPen(st::defaultLinkButton.color);
p.drawText(_invitationLink, _channel->inviteLink(), option); p.drawText(_invitationLink, _channel->inviteLink(), option);
if (!_goodTextLink.isEmpty()) {
auto opacity = _a_goodOpacity.current(getms(), 0.);
if (opacity > 0.) {
p.setOpacity(opacity);
p.setPen(st::boxTextFgGood);
p.setFont(st::boxTextFont);
p.drawTextRight(st::boxPadding.right(), _link->y() - st::newGroupLinkPadding.top() + st::newGroupLinkTop + st::newGroupLinkFont->ascent - st::boxTextFont->ascent, width(), _goodTextLink);
p.setOpacity(1);
}
}
} }
} else { } else {
if (!_errorText.isEmpty()) { if (!_errorText.isEmpty()) {
@ -559,9 +542,10 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
void SetupChannelBox::mousePressEvent(QMouseEvent *e) { void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
if (_linkOver) { if (_linkOver) {
Application::clipboard()->setText(_channel->inviteLink()); Application::clipboard()->setText(_channel->inviteLink());
_goodTextLink = lang(lng_create_channel_link_copied);
_a_goodOpacity.finish(); Ui::Toast::Config toast;
_a_goodOpacity.start([this] { update(); }, 1., 0., st::newGroupLinkFadeDuration); toast.text = lang(lng_create_channel_link_copied);
Ui::Toast::Show(App::wnd(), toast);
} }
} }
@ -669,6 +653,7 @@ void SetupChannelBox::onPrivacyChange() {
return; return;
} }
_link->show(); _link->show();
_link->setDisplayFocused(true);
_link->setFocus(); _link->setFocus();
} else { } else {
_link->hide(); _link->hide();
@ -812,12 +797,10 @@ void EditNameTitleBox::prepare() {
connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
_last->setVisible(!_peer->isChat()); _last->setVisible(!_peer->isChat());
(_invertOrder ? _last : _first)->setDisplayFocused(true);
} }
void EditNameTitleBox::setInnerFocus() { void EditNameTitleBox::setInnerFocus() {
(_invertOrder ? _last : _first)->setFocus(); (_invertOrder ? _last : _first)->setFocusFast();
} }
void EditNameTitleBox::onSubmit() { void EditNameTitleBox::onSubmit() {
@ -967,13 +950,11 @@ void EditChannelBox::prepare() {
_publicLink->setVisible(_channel->canEditUsername()); _publicLink->setVisible(_channel->canEditUsername());
_sign->setVisible(!_channel->isMegagroup()); _sign->setVisible(!_channel->isMegagroup());
_title->setDisplayFocused(true);
updateMaxHeight(); updateMaxHeight();
} }
void EditChannelBox::setInnerFocus() { void EditChannelBox::setInnerFocus() {
_title->setFocus(); _title->setFocusFast();
} }
void EditChannelBox::keyPressEvent(QKeyEvent *e) { void EditChannelBox::keyPressEvent(QKeyEvent *e) {
@ -1207,7 +1188,7 @@ void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
p.translate(0, _rowsTop); p.translate(0, _rowsTop);
for_const (auto &row, _rows) { for_const (auto &row, _rows) {
paintChat(p, row, (row.peer == _selected), (row.peer == _pressed)); paintChat(p, row, (row.peer == _selected));
p.translate(0, _rowHeight); p.translate(0, _rowHeight);
} }
} }
@ -1218,7 +1199,7 @@ void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) {
_aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); _aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
} }
void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const { void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected) const {
auto peer = row.peer; auto peer = row.peer;
peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width()); peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
@ -1234,7 +1215,7 @@ void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selecte
row.name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width()); row.name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width());
p.setFont(selected ? st::linkOverFont : st::linkFont); p.setFont(selected ? st::linkOverFont : st::linkFont);
p.setPen(pressed ? st::defaultLinkButton.downColor : st::defaultLinkButton.color); p.setPen(selected ? st::defaultLinkButton.overColor : st::defaultLinkButton.color);
p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), lang(lng_channels_too_much_public_revoke), _revokeWidth); p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), lang(lng_channels_too_much_public_revoke), _revokeWidth);
p.setPen(st::contactsStatusFg); p.setPen(st::contactsStatusFg);

View file

@ -98,6 +98,9 @@ private slots:
void onNext(); void onNext();
void onNameSubmit(); void onNameSubmit();
void onDescriptionResized(); void onDescriptionResized();
void onClose() {
closeBox();
}
private: private:
void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update); void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update);
@ -184,9 +187,6 @@ private:
mtpRequestId _checkRequestId = 0; mtpRequestId _checkRequestId = 0;
QString _sentUsername, _checkUsername, _errorText, _goodText; QString _sentUsername, _checkUsername, _errorText, _goodText;
QString _goodTextLink;
Animation _a_goodOpacity;
QTimer _checkTimer; QTimer _checkTimer;
}; };
@ -245,6 +245,9 @@ private slots:
void onSave(); void onSave();
void onDescriptionResized(); void onDescriptionResized();
void onPublicLink(); void onPublicLink();
void onClose() {
closeBox();
}
private: private:
void updateMaxHeight(); void updateMaxHeight();
@ -294,7 +297,7 @@ private:
PeerData *peer; PeerData *peer;
Text name, status; Text name, status;
}; };
void paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const; void paintChat(Painter &p, const ChatRow &row, bool selected) const;
void getPublicDone(const MTPmessages_Chats &result); void getPublicDone(const MTPmessages_Chats &result);
bool getPublicFail(const RPCError &error); bool getPublicFail(const RPCError &error);

View file

@ -65,6 +65,13 @@ BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
} }
subscribe(FileDownload::ImageLoaded(), [this] { update(); }); subscribe(FileDownload::ImageLoaded(), [this] { update(); });
using Update = Window::Theme::BackgroundUpdate;
subscribe(Window::Theme::Background(), [this](const Update &update) {
if (update.type == Update::Type::TestingTheme
|| update.type == Update::Type::RevertingTheme) {
_check->invalidateCache();
}
});
setMouseTracking(true); setMouseTracking(true);
} }

View file

@ -68,6 +68,6 @@ private:
int _rows = 0; int _rows = 0;
int _over = -1; int _over = -1;
int _overDown = -1; int _overDown = -1;
std_::unique_ptr<Ui::RoundCheckbox> _check; // this not a widget std_::unique_ptr<Ui::RoundCheckbox> _check; // this is not a widget
}; };

View file

@ -91,17 +91,14 @@ boxTitleClose: IconButton(defaultIconButton) {
icon: boxTitleCloseIcon; icon: boxTitleCloseIcon;
iconOver: boxTitleCloseIconOver; iconOver: boxTitleCloseIconOver;
rippleAreaPosition: point(4px, 4px); rippleAreaPosition: point(6px, 6px);
rippleAreaSize: 48px; rippleAreaSize: 44px;
ripple: RippleAnimation(defaultRippleAnimation) { ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver; color: windowBgOver;
} }
} }
boxLinkButton: LinkButton { boxLinkButton: LinkButton(defaultLinkButton) {
color: #0080c0;
overColor: #0080c0;
downColor: #0073ad;
font: boxTextFont; font: boxTextFont;
overFont: font(boxFontSize underline); overFont: font(boxFontSize underline);
} }
@ -114,7 +111,7 @@ boxVerticalMargin: 10px;
boxWidth: 320px; boxWidth: 320px;
boxWideWidth: 364px; boxWideWidth: 364px;
boxPadding: margins(23px, 30px, 23px, 8px); boxPadding: margins(23px, 30px, 23px, 8px);
boxMaxListHeight: 600px; boxMaxListHeight: 492px;
boxLittleSkip: 10px; boxLittleSkip: 10px;
boxMediumSkip: 20px; boxMediumSkip: 20px;
@ -145,7 +142,7 @@ boxTextStyle: TextStyle(defaultTextStyle) {
} }
boxPhotoTitleFont: font(16px semibold); boxPhotoTitleFont: font(16px semibold);
boxPhotoTitlePosition: point(28px, 26px); boxPhotoTitlePosition: point(28px, 20px);
boxPhotoPadding: margins(28px, 28px, 28px, 18px); boxPhotoPadding: margins(28px, 28px, 28px, 18px);
boxPhotoCompressedSkip: 20px; boxPhotoCompressedSkip: 20px;
boxPhotoCaptionSkip: 8px; boxPhotoCaptionSkip: 8px;
@ -173,7 +170,7 @@ confirmInviteTitleTop: 106px;
confirmInvitePhotoSize: 76px; confirmInvitePhotoSize: 76px;
confirmInvitePhotoTop: 20px; confirmInvitePhotoTop: 20px;
confirmInviteStatusTop: 136px; confirmInviteStatusTop: 136px;
confirmInviteUserHeight: 80px; confirmInviteUserHeight: 84px;
confirmInviteUserPhotoSize: 56px; confirmInviteUserPhotoSize: 56px;
confirmInviteUserPhotoTop: 166px; confirmInviteUserPhotoTop: 166px;
confirmInviteUserName: FlatLabel(defaultFlatLabel) { confirmInviteUserName: FlatLabel(defaultFlatLabel) {
@ -406,9 +403,8 @@ sessionTerminate: IconButton {
} }
} }
sessionTerminateAllButton: LinkButton(boxLinkButton) { sessionTerminateAllButton: LinkButton(boxLinkButton) {
color: #d15948; color: attentionButtonFg;
overColor: #d15948; overColor: attentionButtonFg;
downColor: #db6352;
} }
passcodeHeaderFont: font(19px); passcodeHeaderFont: font(19px);
@ -453,7 +449,6 @@ setupChannelLink: InputField(defaultInputField) {
} }
newGroupPublicLinkPadding: margins(0px, 20px, 0px, 5px); newGroupPublicLinkPadding: margins(0px, 20px, 0px, 5px);
newGroupLinkFadeDuration: 5000;
themeWarningWidth: boxWideWidth; themeWarningWidth: boxWideWidth;
themeWarningHeight: 150px; themeWarningHeight: 150px;
@ -462,9 +457,8 @@ themeWarningTextTop: 60px;
aboutWidth: 390px; aboutWidth: 390px;
aboutVersionTop: -3px; aboutVersionTop: -3px;
aboutVersionLink: LinkButton(defaultLinkButton) { aboutVersionLink: LinkButton(defaultLinkButton) {
color: #999999; color: windowSubTextFg;
overColor: #999999; overColor: windowSubTextFg;
downColor: #999999;
} }
aboutTextTop: 34px; aboutTextTop: 34px;
aboutSkip: 14px; aboutSkip: 14px;
@ -477,7 +471,8 @@ aboutTextStyle: TextStyle(defaultTextStyle) {
lineHeight: 22px; lineHeight: 22px;
} }
autoDownloadTitlePosition: point(23px, 28px); autoDownloadTopDelta: 10px;
autoDownloadTitlePosition: point(23px, 18px);
autoDownloadTitleFont: font(15px semibold); autoDownloadTitleFont: font(15px semibold);
editTextArea: InputField(defaultInputField) { editTextArea: InputField(defaultInputField) {

View file

@ -96,11 +96,20 @@ ConfirmBox::ConfirmBox(const InformBoxTag &, const QString &text, const QString
, _confirmStyle(st::defaultBoxButton) , _confirmStyle(st::defaultBoxButton)
, _informative(true) , _informative(true)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) , _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(base::lambda_copy<void()>(closedCallback)) , _confirmedCallback(generateInformCallback(closedCallback))
, _cancelledCallback(base::lambda_copy<void()>(closedCallback)) { , _cancelledCallback(generateInformCallback(closedCallback)) {
init(text); init(text);
} }
base::lambda<void()> ConfirmBox::generateInformCallback(const base::lambda_copy<void()> &closedCallback) {
return base::lambda_guarded(this, [this, closedCallback] {
closeBox();
if (closedCallback) {
closedCallback();
}
});
}
void ConfirmBox::init(const QString &text) { void ConfirmBox::init(const QString &text) {
textstyleSet(&st::boxTextStyle); textstyleSet(&st::boxTextStyle);
_text.setText(st::boxTextFont, text, _informative ? _confirmBoxTextOptions : _textPlainOptions); _text.setText(st::boxTextFont, text, _informative ? _confirmBoxTextOptions : _textPlainOptions);
@ -210,6 +219,12 @@ void ConfirmBox::paintEvent(QPaintEvent *e) {
textstyleRestore(); textstyleRestore();
} }
InformBox::InformBox(QWidget*, const QString &text, base::lambda_copy<void()> &&closedCallback) : ConfirmBox(ConfirmBox::InformBoxTag(), text, lang(lng_box_ok), std_::move(closedCallback)) {
}
InformBox::InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback) : ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, std_::move(closedCallback)) {
}
MaxInviteBox::MaxInviteBox(QWidget*, const QString &link) MaxInviteBox::MaxInviteBox(QWidget*, const QString &link)
: _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) : _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _link(link) { , _link(link) {
@ -495,11 +510,11 @@ void ConfirmInviteBox::prepare() {
auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom(); auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom();
if (!_participants.isEmpty()) { if (!_participants.isEmpty()) {
int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5; int skip = (st::boxWideWidth - 4 * st::confirmInviteUserPhotoSize) / 5;
int padding = skip / 2; int padding = skip / 2;
_userWidth = (st::confirmInviteUserPhotoSize + 2 * padding); _userWidth = (st::confirmInviteUserPhotoSize + 2 * padding);
int sumWidth = _participants.size() * _userWidth; int sumWidth = _participants.size() * _userWidth;
int left = (width() - sumWidth) / 2; int left = (st::boxWideWidth - sumWidth) / 2;
for_const (auto user, _participants) { for_const (auto user, _participants) {
auto name = new Ui::FlatLabel(this, st::confirmInviteUserName); auto name = new Ui::FlatLabel(this, st::confirmInviteUserName);
name->resizeToWidth(st::confirmInviteUserPhotoSize + padding); name->resizeToWidth(st::confirmInviteUserPhotoSize + padding);

View file

@ -63,6 +63,7 @@ private:
struct InformBoxTag { struct InformBoxTag {
}; };
ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback); ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback);
base::lambda<void()> generateInformCallback(const base::lambda_copy<void()> &closedCallback);
friend class InformBox; friend class InformBox;
void confirmed(); void confirmed();
@ -92,10 +93,8 @@ private:
class InformBox : public ConfirmBox { class InformBox : public ConfirmBox {
public: public:
InformBox(QWidget*, const QString &text, base::lambda_copy<void()> &&closedCallback = base::lambda_copy<void()>()) : ConfirmBox(ConfirmBox::InformBoxTag(), text, QString(), std_::move(closedCallback)) { InformBox(QWidget*, const QString &text, base::lambda_copy<void()> &&closedCallback = base::lambda_copy<void()>());
} InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback = base::lambda_copy<void()>());
InformBox(QWidget*, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback = base::lambda_copy<void()>()) : ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, std_::move(closedCallback)) {
}
}; };

View file

@ -55,7 +55,6 @@ void ConfirmPhoneBox::checkPhoneAndHash() {
if (_sendCodeRequestId) { if (_sendCodeRequestId) {
return; return;
} }
MTPaccount_SendConfirmPhoneCode::Flags flags = 0; MTPaccount_SendConfirmPhoneCode::Flags flags = 0;
_sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(flags), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail)); _sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(flags), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail));
} }
@ -310,7 +309,7 @@ void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) {
} }
void ConfirmPhoneBox::setInnerFocus() { void ConfirmPhoneBox::setInnerFocus() {
_code->setFocus(); _code->setFocusFast();
} }
ConfirmPhoneBox::~ConfirmPhoneBox() { ConfirmPhoneBox::~ConfirmPhoneBox() {

View file

@ -80,8 +80,10 @@ void ConnectionBox::updateControlsVisibility() {
} }
void ConnectionBox::setInnerFocus() { void ConnectionBox::setInnerFocus() {
if (!_hostInput->isHidden()) { if (_hostInput->isHidden()) {
_hostInput->setFocus(); setFocus();
} else {
_hostInput->setFocusFast();
} }
} }
@ -120,9 +122,12 @@ void ConnectionBox::updateControlsPosition() {
void ConnectionBox::onChange() { void ConnectionBox::onChange() {
updateControlsVisibility(); updateControlsVisibility();
if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) { if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) {
_hostInput->setFocus(); if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() && !_passwordInput->hasFocus()) {
_hostInput->setFocusFast();
}
if (_httpProxyRadio->checked() && !_portInput->getLastText().toInt()) { if (_httpProxyRadio->checked() && !_portInput->getLastText().toInt()) {
_portInput->setText(qsl("80")); _portInput->setText(qsl("80"));
_portInput->finishAnimations();
} }
} }
update(); update();
@ -217,7 +222,7 @@ void AutoDownloadBox::prepare() {
addButton(lang(lng_connection_save), [this] { onSave(); }); addButton(lang(lng_connection_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); }); addButton(lang(lng_cancel), [this] { closeBox(); });
setDimensions(st::boxWidth, 3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip); setDimensions(st::boxWidth, 3 * _sectionHeight - st::autoDownloadTopDelta + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip);
} }
void AutoDownloadBox::paintEvent(QPaintEvent *e) { void AutoDownloadBox::paintEvent(QPaintEvent *e) {
@ -235,13 +240,14 @@ void AutoDownloadBox::paintEvent(QPaintEvent *e) {
void AutoDownloadBox::resizeEvent(QResizeEvent *e) { void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e); BoxContent::resizeEvent(e);
_photoPrivate->moveToLeft(st::boxTitlePosition.x(), st::boxTitleHeight + st::setLittleSkip); auto top = st::boxTitleHeight - st::autoDownloadTopDelta;
_photoPrivate->moveToLeft(st::boxTitlePosition.x(), top + st::setLittleSkip);
_photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip); _photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip);
_audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitleHeight + st::setLittleSkip); _audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + top + st::setLittleSkip);
_audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip); _audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip);
_gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitleHeight + st::setLittleSkip); _gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + top + st::setLittleSkip);
_gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip); _gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip);
_gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip); _gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip);
} }

View file

@ -40,6 +40,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "boxes/photocropbox.h" #include "boxes/photocropbox.h"
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
#include "window/window_theme.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -636,6 +637,32 @@ void ContactsBox::Inner::init() {
connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData *))); connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData *)));
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&))); connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)));
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*))); connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
using Update = Window::Theme::BackgroundUpdate;
subscribe(Window::Theme::Background(), [this](const Update &update) {
if (update.type == Update::Type::TestingTheme
|| update.type == Update::Type::RevertingTheme) {
invalidateCache();
}
});
}
void ContactsBox::Inner::invalidateCache() {
for_const (auto data, _contactsData) {
if (data->checkbox) {
data->checkbox->invalidateCache();
}
}
for_const (auto data, _byUsernameDatas) {
if (data->checkbox) {
data->checkbox->invalidateCache();
}
}
for_const (auto data, d_byUsername) {
if (data->checkbox) {
data->checkbox->invalidateCache();
}
}
} }
void ContactsBox::Inner::initList() { void ContactsBox::Inner::initList() {
@ -894,17 +921,18 @@ ContactsBox::Inner::ContactData *ContactsBox::Inner::contactData(Dialogs::Row *r
return data; return data;
} }
bool ContactsBox::Inner::isRowDisabled(PeerData *peer, ContactData *data) const {
if (_chat && _membersFilter == MembersFilter::Admins) {
return (_saving || _allAdmins->checked() || peer->id == peerFromUser(_chat->creator));
}
return (data->disabledChecked || selectedCount() >= Global::MegagroupSizeMax());
}
void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, ContactData *data, bool selected) { void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, ContactData *data, bool selected) {
auto user = peer->asUser(); auto user = peer->asUser();
if (_chat && _membersFilter == MembersFilter::Admins) { if (isRowDisabled(peer, data)) {
if (_allAdmins->checked() || peer->id == peerFromUser(_chat->creator) || _saving) { selected = false;
selected = false;
}
} else {
if (data->disabledChecked || selectedCount() >= Global::MegagroupSizeMax()) {
selected = false;
}
} }
auto paintDisabledCheck = data->disabledChecked; auto paintDisabledCheck = data->disabledChecked;
@ -1229,15 +1257,15 @@ void ContactsBox::Inner::mousePressEvent(QMouseEvent *e) {
setPressed(_selected); setPressed(_selected);
setFilteredPressed(_filteredSelected); setFilteredPressed(_filteredSelected);
setSearchedPressed(_searchedSelected); setSearchedPressed(_searchedSelected);
if (_pressed) { if (_selected) {
addRipple(contactData(_selected)); addRipple(_selected->history()->peer, contactData(_selected));
} else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) { } else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) {
addRipple(contactData(_filtered[_filteredSelected])); addRipple(_filtered[_filteredSelected]->history()->peer, contactData(_filtered[_filteredSelected]));
} else if (_searchedSelected >= 0) { } else if (_searchedSelected >= 0) {
if (_filter.isEmpty() && _searchedSelected < d_byUsername.size()) { if (_filter.isEmpty() && _searchedSelected < d_byUsername.size()) {
addRipple(d_byUsername[_searchedSelected]); addRipple(_byUsername[_searchedSelected], d_byUsername[_searchedSelected]);
} else if (!_filter.isEmpty() && _searchedSelected < d_byUsernameFiltered.size()) { } else if (!_filter.isEmpty() && _searchedSelected < d_byUsernameFiltered.size()) {
addRipple(d_byUsernameFiltered[_searchedSelected]); addRipple(_byUsernameFiltered[_searchedSelected], d_byUsernameFiltered[_searchedSelected]);
} }
} }
} }
@ -1261,7 +1289,9 @@ void ContactsBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
} }
} }
void ContactsBox::Inner::addRipple(ContactData *data) { void ContactsBox::Inner::addRipple(PeerData *peer, ContactData *data) {
if (isRowDisabled(peer, data)) return;
auto rowTop = getSelectedRowTop(); auto rowTop = getSelectedRowTop();
if (!data->ripple) { if (!data->ripple) {
auto mask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight)); auto mask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight));
@ -1420,7 +1450,7 @@ void ContactsBox::Inner::changeCheckState(Dialogs::Row *row) {
void ContactsBox::Inner::changeCheckState(ContactData *data, PeerData *peer) { void ContactsBox::Inner::changeCheckState(ContactData *data, PeerData *peer) {
t_assert(usingMultiSelect()); t_assert(usingMultiSelect());
if (_chat && _membersFilter == MembersFilter::Admins && _allAdmins->checked()) { if (isRowDisabled(peer, data)) {
} else if (data->checkbox->checked()) { } else if (data->checkbox->checked()) {
changePeerCheckState(data, peer, false); changePeerCheckState(data, peer, false);
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) { } else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {

View file

@ -224,18 +224,20 @@ private:
bool statusHasOnlineColor = false; bool statusHasOnlineColor = false;
bool disabledChecked = false; bool disabledChecked = false;
}; };
void addRipple(ContactData *data); void addRipple(PeerData *peer, ContactData *data);
void stopLastRipple(ContactData *data); void stopLastRipple(ContactData *data);
void setPressed(Dialogs::Row *pressed); void setPressed(Dialogs::Row *pressed);
void setFilteredPressed(int pressed); void setFilteredPressed(int pressed);
void setSearchedPressed(int pressed); void setSearchedPressed(int pressed);
void clearSearchedContactDatas(); void clearSearchedContactDatas();
bool isRowDisabled(PeerData *peer, ContactData *data) const;
void loadProfilePhotos(); void loadProfilePhotos();
void addBot(); void addBot();
void init(); void init();
void initList(); void initList();
void invalidateCache();
void updateRowWithTop(int rowTop); void updateRowWithTop(int rowTop);
int getSelectedRowTop() const; int getSelectedRowTop() const;

View file

@ -130,20 +130,9 @@ MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter fi
, _channel(channel) , _channel(channel)
, _filter(filter) , _filter(filter)
, _kickText(lang(lng_profile_kick)) , _kickText(lang(lng_profile_kick))
, _time(0)
, _kickWidth(st::normalFont->width(_kickText)) , _kickWidth(st::normalFont->width(_kickText))
, _sel(-1)
, _kickSel(-1)
, _kickDown(-1)
, _mouseSel(false)
, _kickConfirm(0)
, _kickRequestId(0)
, _kickBox(0)
, _loading(true)
, _loadingRequestId(0)
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right()) , _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
, _about(_aboutWidth) , _about(_aboutWidth) {
, _aboutHeight(0) {
subscribe(FileDownload::ImageLoaded(), [this] { update(); }); subscribe(FileDownload::ImageLoaded(), [this] { update(); });
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&))); connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
@ -167,6 +156,7 @@ void MembersBox::Inner::paintEvent(QPaintEvent *e) {
_time = unixtime(); _time = unixtime();
p.fillRect(r, st::contactsBg); p.fillRect(r, st::contactsBg);
auto ms = getms();
auto yFrom = r.y() - st::membersMarginTop; auto yFrom = r.y() - st::membersMarginTop;
auto yTo = r.y() + r.height() - st::membersMarginTop; auto yTo = r.y() + r.height() - st::membersMarginTop;
p.translate(0, st::membersMarginTop); p.translate(0, st::membersMarginTop);
@ -179,10 +169,9 @@ void MembersBox::Inner::paintEvent(QPaintEvent *e) {
int32 to = ceilclamp(yTo, _rowHeight, 0, _rows.size()); int32 to = ceilclamp(yTo, _rowHeight, 0, _rows.size());
p.translate(0, from * _rowHeight); p.translate(0, from * _rowHeight);
for (; from < to; ++from) { for (; from < to; ++from) {
bool sel = (from == _sel); auto selected = (_pressed >= 0) ? (from == _pressed) : (from == _selected);
bool kickSel = (from == _kickSel && (_kickDown < 0 || from == _kickDown)); auto kickSelected = (_pressed >= 0) ? (from == _kickPressed && from == _kickSelected) : (from == _kickSelected);
bool kickDown = kickSel && (from == _kickDown); paintDialog(p, ms, _rows[from], data(from), selected, kickSelected);
paintDialog(p, _rows[from], data(from), sel, kickSel, kickDown);
p.translate(0, _rowHeight); p.translate(0, _rowHeight);
} }
if (to == _rows.size() && _filter == MembersFilter::Recent && (_rows.size() < _channel->membersCount() || _rows.size() >= Global::ChatSizeMax())) { if (to == _rows.size() && _filter == MembersFilter::Recent && (_rows.size() < _channel->membersCount() || _rows.size() >= Global::ChatSizeMax())) {
@ -197,53 +186,91 @@ void MembersBox::Inner::enterEvent(QEvent *e) {
} }
void MembersBox::Inner::leaveEvent(QEvent *e) { void MembersBox::Inner::leaveEvent(QEvent *e) {
_mouseSel = false; _mouseSelection = false;
setMouseTracking(false); setMouseTracking(false);
if (_sel >= 0) { if (_selected >= 0) {
clearSel(); clearSel();
} }
} }
void MembersBox::Inner::mouseMoveEvent(QMouseEvent *e) { void MembersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
_mouseSel = true; _mouseSelection = true;
_lastMousePos = e->globalPos(); _lastMousePos = e->globalPos();
updateSel(); updateSelection();
} }
void MembersBox::Inner::mousePressEvent(QMouseEvent *e) { void MembersBox::Inner::mousePressEvent(QMouseEvent *e) {
_mouseSel = true; _mouseSelection = true;
_lastMousePos = e->globalPos(); _lastMousePos = e->globalPos();
updateSel(); updateSelection();
if (e->button() == Qt::LeftButton && _kickSel < 0) { setPressed(_selected);
chooseParticipant(); _kickPressed = _kickSelected;
if (_selected >= 0 && _selected < _datas.size() && _kickSelected < 0) {
addRipple(_datas[_selected]);
} }
_kickDown = _kickSel;
update();
} }
void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) { void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
_mouseSel = true; auto pressed = _pressed;
_lastMousePos = e->globalPos(); auto kickPressed = _kickPressed;
updateSel(); setPressed(-1);
if (_kickDown >= 0 && _kickDown == _kickSel && !_kickRequestId) { if (e->button() == Qt::LeftButton) {
_kickConfirm = _rows.at(_kickSel); if (pressed == _selected && kickPressed == _kickSelected) {
if (_kickBox) _kickBox->deleteLater(); if (kickPressed >= 0) {
auto text = (_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName); if (!_kickRequestId) {
_kickBox = Ui::show(Box<ConfirmBox>(text, base::lambda_guarded(this, [this] { _kickConfirm = _rows.at(_kickSelected);
if (_filter == MembersFilter::Recent) { if (_kickBox) _kickBox->deleteLater();
_kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail)); auto text = (_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName);
} else { _kickBox = Ui::show(Box<ConfirmBox>(text, base::lambda_guarded(this, [this] {
_kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail)); if (_filter == MembersFilter::Recent) {
_kickRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _kickConfirm->inputUser, MTP_bool(true)), rpcDone(&Inner::kickDone), rpcFail(&Inner::kickFail));
} else {
_kickRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _kickConfirm->inputUser, MTP_channelRoleEmpty()), rpcDone(&Inner::kickAdminDone), rpcFail(&Inner::kickFail));
}
})), KeepOtherLayers);
}
} else if (pressed >= 0) {
chooseParticipant();
} }
})), KeepOtherLayers); }
} }
_kickDown = -1;
} }
void MembersBox::Inner::paintDialog(Painter &p, PeerData *peer, MemberData *data, bool sel, bool kickSel, bool kickDown) { void MembersBox::Inner::addRipple(MemberData *data) {
auto rowTop = getSelectedRowTop();
if (!data->ripple) {
auto mask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight));
data->ripple = std_::make_unique<Ui::RippleAnimation>(st::contactsRipple, std_::move(mask), [this, data] {
updateRowWithTop(data->rippleRowTop);
});
}
data->rippleRowTop = rowTop;
data->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(0, rowTop));
}
void MembersBox::Inner::stopLastRipple(MemberData *data) {
if (data->ripple) {
data->ripple->lastStop();
}
}
void MembersBox::Inner::setPressed(int pressed) {
if (_pressed >= 0 && _pressed < _datas.size()) {
stopLastRipple(_datas[_pressed]);
}
_pressed = pressed;
}
void MembersBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, MemberData *data, bool selected, bool kickSelected) {
UserData *user = peer->asUser(); UserData *user = peer->asUser();
p.fillRect(0, 0, width(), _rowHeight, sel ? st::contactsBgOver : st::contactsBg); p.fillRect(0, 0, width(), _rowHeight, selected ? st::contactsBgOver : st::contactsBg);
if (data->ripple) {
data->ripple->paint(p, 0, 0, width(), ms);
if (data->ripple->empty()) {
data->ripple.reset();
}
}
peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width()); peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
p.setPen(st::contactsNameFg); p.setPen(st::contactsNameFg);
@ -258,43 +285,43 @@ void MembersBox::Inner::paintDialog(Painter &p, PeerData *peer, MemberData *data
data->name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width()); data->name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width());
if (data->canKick) { if (data->canKick) {
p.setFont((kickSel ? st::linkOverFont : st::linkFont)->f); p.setFont(kickSelected ? st::linkOverFont : st::linkFont);
p.setPen(kickDown ? st::defaultLinkButton.downColor : st::defaultLinkButton.color); p.setPen(kickSelected ? st::defaultLinkButton.overColor : st::defaultLinkButton.color);
p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), _kickText, _kickWidth); p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), _kickText, _kickWidth);
} }
p.setFont(st::contactsStatusFont->f); p.setFont(st::contactsStatusFont->f);
p.setPen(data->onlineColor ? st::contactsStatusFgOnline : (sel ? st::contactsStatusFgOver : st::contactsStatusFg)); p.setPen(data->onlineColor ? st::contactsStatusFgOnline : (selected ? st::contactsStatusFgOver : st::contactsStatusFg));
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), data->online); p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), data->online);
} }
void MembersBox::Inner::selectSkip(int32 dir) { void MembersBox::Inner::selectSkip(int32 dir) {
_time = unixtime(); _time = unixtime();
_mouseSel = false; _mouseSelection = false;
int cur = -1; int cur = -1;
if (_sel >= 0) { if (_selected >= 0) {
cur = _sel; cur = _selected;
} }
cur += dir; cur += dir;
if (cur <= 0) { if (cur <= 0) {
_sel = _rows.isEmpty() ? -1 : 0; _selected = _rows.isEmpty() ? -1 : 0;
} else if (cur >= _rows.size()) { } else if (cur >= _rows.size()) {
_sel = -1; _selected = -1;
} else { } else {
_sel = cur; _selected = cur;
} }
if (dir > 0) { if (dir > 0) {
if (_sel < 0 || _sel >= _rows.size()) { if (_selected < 0 || _selected >= _rows.size()) {
_sel = -1; _selected = -1;
} }
} else { } else {
if (!_rows.isEmpty()) { if (!_rows.isEmpty()) {
if (_sel < 0) _sel = _rows.size() - 1; if (_selected < 0) _selected = _rows.size() - 1;
} }
} }
if (_sel >= 0) { if (_selected >= 0) {
emit mustScrollTo(_sel * _rowHeight, (_sel + 1) * _rowHeight); emit mustScrollTo(st::membersMarginTop + _selected * _rowHeight, st::membersMarginTop + (_selected + 1) * _rowHeight);
} }
update(); update();
@ -306,6 +333,10 @@ void MembersBox::Inner::selectSkipPage(int32 h, int32 dir) {
selectSkip(points * dir); selectSkip(points * dir);
} }
MembersBox::Inner::MemberData::MemberData() = default;
MembersBox::Inner::MemberData::~MemberData() = default;
void MembersBox::Inner::loadProfilePhotos() { void MembersBox::Inner::loadProfilePhotos() {
if (_visibleTop >= _visibleBottom) return; if (_visibleTop >= _visibleBottom) return;
@ -331,8 +362,8 @@ void MembersBox::Inner::loadProfilePhotos() {
} }
void MembersBox::Inner::chooseParticipant() { void MembersBox::Inner::chooseParticipant() {
if (_sel < 0 || _sel >= _rows.size()) return; if (_selected < 0 || _selected >= _rows.size()) return;
if (PeerData *peer = _rows[_sel]) { if (auto peer = _rows[_selected]) {
Ui::hideLayer(); Ui::hideLayer();
Ui::showPeerProfile(peer); Ui::showPeerProfile(peer);
} }
@ -379,9 +410,9 @@ void MembersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void MembersBox::Inner::clearSel() { void MembersBox::Inner::clearSel() {
updateSelectedRow(); updateSelectedRow();
_sel = _kickSel = _kickDown = -1; _selected = _kickSelected = -1;
_lastMousePos = QCursor::pos(); _lastMousePos = QCursor::pos();
updateSel(); updateSelection();
} }
MembersBox::Inner::MemberData *MembersBox::Inner::data(int32 index) { MembersBox::Inner::MemberData *MembersBox::Inner::data(int32 index) {
@ -419,23 +450,23 @@ MembersBox::Inner::~Inner() {
clear(); clear();
} }
void MembersBox::Inner::updateSel() { void MembersBox::Inner::updateSelection() {
if (!_mouseSel) return; if (!_mouseSelection) return;
QPoint p(mapFromGlobal(_lastMousePos)); QPoint p(mapFromGlobal(_lastMousePos));
p.setY(p.y() - st::membersMarginTop); p.setY(p.y() - st::membersMarginTop);
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
int32 newSel = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1; auto selected = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
int32 newKickSel = newSel; auto kickSelected = selected;
if (newSel >= 0 && (!data(newSel)->canKick || !QRect(width() - _kickWidth - st::contactsPadding.right() - st::contactsCheckPosition.x(), newSel * _rowHeight + st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, _kickWidth, st::normalFont->height).contains(p))) { if (selected >= 0 && (!data(selected)->canKick || !QRect(width() - _kickWidth - st::contactsPadding.right() - st::contactsCheckPosition.x(), selected * _rowHeight + st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, _kickWidth, st::normalFont->height).contains(p))) {
newKickSel = -1; kickSelected = -1;
} }
if (newSel != _sel || newKickSel != _kickSel) { if (_selected != selected || _kickSelected != kickSelected) {
updateSelectedRow(); updateSelectedRow();
_sel = newSel; _selected = selected;
_kickSel = newKickSel; _kickSelected = kickSelected;
updateSelectedRow(); updateSelectedRow();
setCursor(_kickSel >= 0 ? style::cur_pointer : style::cur_default); setCursor(_kickSelected >= 0 ? style::cur_pointer : style::cur_default);
} }
} }
@ -443,9 +474,21 @@ void MembersBox::Inner::peerUpdated(PeerData *peer) {
update(); update();
} }
int MembersBox::Inner::getSelectedRowTop() const {
if (_selected >= 0) {
return st::membersMarginTop + _selected * _rowHeight;
}
return -1;
}
void MembersBox::Inner::updateRowWithTop(int rowTop) {
update(0, rowTop, width(), _rowHeight);
}
void MembersBox::Inner::updateSelectedRow() { void MembersBox::Inner::updateSelectedRow() {
if (_sel >= 0) { auto rowTop = getSelectedRowTop();
update(0, st::membersMarginTop + _sel * _rowHeight, width(), _rowHeight); if (rowTop >= 0) {
updateRowWithTop(rowTop);
} }
} }

View file

@ -113,7 +113,6 @@ signals:
public slots: public slots:
void load(); void load();
void updateSel();
void peerUpdated(PeerData *peer); void peerUpdated(PeerData *peer);
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
@ -127,18 +126,29 @@ protected:
private: private:
struct MemberData { struct MemberData {
MemberData();
~MemberData();
std_::unique_ptr<Ui::RippleAnimation> ripple;
int rippleRowTop = 0;
Text name; Text name;
QString online; QString online;
bool onlineColor; bool onlineColor;
bool canKick; bool canKick;
}; };
void addRipple(MemberData *data);
void stopLastRipple(MemberData *data);
void setPressed(int pressed);
void updateSelection();
void loadProfilePhotos(); void loadProfilePhotos();
void updateRowWithTop(int rowTop);
int getSelectedRowTop() const;
void updateSelectedRow(); void updateSelectedRow();
MemberData *data(int32 index); MemberData *data(int32 index);
void paintDialog(Painter &p, PeerData *peer, MemberData *data, bool sel, bool kickSel, bool kickDown); void paintDialog(Painter &p, TimeMs ms, PeerData *peer, MemberData *data, bool selected, bool kickSelected);
void membersReceived(const MTPchannels_ChannelParticipants &result, mtpRequestId req); void membersReceived(const MTPchannels_ChannelParticipants &result, mtpRequestId req);
bool membersFailed(const RPCError &error, mtpRequestId req); bool membersFailed(const RPCError &error, mtpRequestId req);
@ -150,21 +160,25 @@ private:
void clear(); void clear();
int _rowHeight; int _rowHeight = 0;
int _visibleTop = 0; int _visibleTop = 0;
int _visibleBottom = 0; int _visibleBottom = 0;
ChannelData *_channel; ChannelData *_channel = nullptr;
MembersFilter _filter; MembersFilter _filter;
QString _kickText; QString _kickText;
int32 _time, _kickWidth; TimeId _time = 0;
int _kickWidth = 0;
int32 _sel, _kickSel, _kickDown; int _selected = -1;
bool _mouseSel; int _pressed = -1;
int _kickSelected = -1;
int _kickPressed = -1;
bool _mouseSelection = false;
UserData *_kickConfirm; UserData *_kickConfirm = nullptr;
mtpRequestId _kickRequestId; mtpRequestId _kickRequestId = 0;
QPointer<ConfirmBox> _kickBox; QPointer<ConfirmBox> _kickBox;
@ -177,8 +191,8 @@ private:
Kicked Kicked
}; };
bool _loading; bool _loading = true;
mtpRequestId _loadingRequestId; mtpRequestId _loadingRequestId = 0;
typedef QVector<UserData*> MemberRows; typedef QVector<UserData*> MemberRows;
typedef QVector<QDateTime> MemberDates; typedef QVector<QDateTime> MemberDates;
typedef QVector<MemberRole> MemberRoles; typedef QVector<MemberRole> MemberRoles;
@ -188,9 +202,9 @@ private:
MemberRoles _roles; MemberRoles _roles;
MemberDatas _datas; MemberDatas _datas;
int32 _aboutWidth; int _aboutWidth = 0;
Text _about; Text _about;
int32 _aboutHeight; int _aboutHeight = 0;
QPoint _lastMousePos; QPoint _lastMousePos;

View file

@ -198,11 +198,11 @@ void PasscodeBox::resizeEvent(QResizeEvent *e) {
void PasscodeBox::setInnerFocus() { void PasscodeBox::setInnerFocus() {
if (_skipEmailWarning && !_recoverEmail->isHidden()) { if (_skipEmailWarning && !_recoverEmail->isHidden()) {
_recoverEmail->setFocus(); _recoverEmail->setFocusFast();
} else if (_oldPasscode->isHidden()) { } else if (_oldPasscode->isHidden()) {
_newPasscode->setFocus(); _newPasscode->setFocusFast();
} else { } else {
_oldPasscode->setFocus(); _oldPasscode->setFocusFast();
} }
} }
@ -469,7 +469,7 @@ void RecoverBox::resizeEvent(QResizeEvent *e) {
} }
void RecoverBox::setInnerFocus() { void RecoverBox::setInnerFocus() {
_recoverCode->setFocus(); _recoverCode->setFocusFast();
} }
void RecoverBox::onSubmit() { void RecoverBox::onSubmit() {

View file

@ -78,7 +78,7 @@ void ReportBox::onChange() {
connect(_reasonOtherText, SIGNAL(submitted(bool)), this, SLOT(onReport())); connect(_reasonOtherText, SIGNAL(submitted(bool)), this, SLOT(onReport()));
connect(_reasonOtherText, SIGNAL(cancelled()), this, SLOT(onClose())); connect(_reasonOtherText, SIGNAL(cancelled()), this, SLOT(onClose()));
} }
_reasonOtherText->setFocus(); _reasonOtherText->setFocusFast();
} else if (_reasonOtherText) { } else if (_reasonOtherText) {
_reasonOtherText.destroy(); _reasonOtherText.destroy();
updateMaxHeight(); updateMaxHeight();
@ -87,7 +87,7 @@ void ReportBox::onChange() {
void ReportBox::setInnerFocus() { void ReportBox::setInnerFocus() {
if (_reasonOtherText) { if (_reasonOtherText) {
_reasonOtherText->setFocus(); _reasonOtherText->setFocusFast();
} else { } else {
setFocus(); setFocus();
} }

View file

@ -37,6 +37,9 @@ private slots:
void onReport(); void onReport();
void onChange(); void onChange();
void onDescriptionResized(); void onDescriptionResized();
void onClose() {
closeBox();
}
protected: protected:
void prepare() override; void prepare() override;

View file

@ -181,12 +181,12 @@ void SendFilesBox::onCaptionResized() {
} }
void SendFilesBox::updateTitleText() { void SendFilesBox::updateTitleText() {
setTitle((_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size())); _titleText = (_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size());
update(); update();
} }
void SendFilesBox::updateBoxSize() { void SendFilesBox::updateBoxSize() {
auto newHeight = 0; auto newHeight = _titleText.isEmpty() ? 0 : st::boxTitleHeight;
if (!_preview.isNull()) { if (!_preview.isNull()) {
newHeight += st::boxPhotoPadding.top() + _previewHeight; newHeight += st::boxPhotoPadding.top() + _previewHeight;
} else if (!_fileThumb.isNull()) { } else if (!_fileThumb.isNull()) {
@ -319,7 +319,7 @@ void SendFilesBox::setInnerFocus() {
if (!_caption || _caption->isHidden()) { if (!_caption || _caption->isHidden()) {
setFocus(); setFocus();
} else { } else {
_caption->setFocus(); _caption->setFocusFast();
} }
} }
@ -609,7 +609,7 @@ void EditCaptionBox::resizeEvent(QResizeEvent *e) {
} }
void EditCaptionBox::setInnerFocus() { void EditCaptionBox::setInnerFocus() {
_field->setFocus(); _field->setFocusFast();
} }
void EditCaptionBox::onSave(bool ctrlShiftEnter) { void EditCaptionBox::onSave(bool ctrlShiftEnter) {

View file

@ -58,6 +58,9 @@ private slots:
void onCompressedChange(); void onCompressedChange();
void onSend(bool ctrlShiftEnter = false); void onSend(bool ctrlShiftEnter = false);
void onCaptionResized(); void onCaptionResized();
void onClose() {
closeBox();
}
private: private:
void updateTitleText(); void updateTitleText();
@ -108,6 +111,9 @@ public:
public slots: public slots:
void onCaptionResized(); void onCaptionResized();
void onSave(bool ctrlShiftEnter = false); void onSave(bool ctrlShiftEnter = false);
void onClose() {
closeBox();
}
protected: protected:
void prepare() override; void prepare() override;

View file

@ -304,7 +304,7 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
} }
void SessionsBox::Inner::onTerminate() { void SessionsBox::Inner::onTerminate() {
for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) { for (auto i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) {
if (i.value()->isOver()) { if (i.value()->isOver()) {
if (_terminateBox) _terminateBox->deleteLater(); if (_terminateBox) _terminateBox->deleteLater();
_terminateBox = Ui::show(Box<ConfirmBox>(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton, base::lambda_guarded(this, [this, terminating = i.key()] { _terminateBox = Ui::show(Box<ConfirmBox>(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton, base::lambda_guarded(this, [this, terminating = i.key()] {
@ -313,7 +313,7 @@ void SessionsBox::Inner::onTerminate() {
_terminateBox = nullptr; _terminateBox = nullptr;
} }
MTP::send(MTPaccount_ResetAuthorization(MTP_long(terminating)), rpcDone(&Inner::terminateDone, terminating), rpcFail(&Inner::terminateFail, terminating)); MTP::send(MTPaccount_ResetAuthorization(MTP_long(terminating)), rpcDone(&Inner::terminateDone, terminating), rpcFail(&Inner::terminateFail, terminating));
TerminateButtons::iterator i = _terminateButtons.find(terminating); auto i = _terminateButtons.find(terminating);
if (i != _terminateButtons.cend()) { if (i != _terminateButtons.cend()) {
i.value()->clearState(); i.value()->clearState();
i.value()->hide(); i.value()->hide();
@ -330,7 +330,7 @@ void SessionsBox::Inner::onTerminateAll() {
_terminateBox->closeBox(); _terminateBox->closeBox();
_terminateBox = nullptr; _terminateBox = nullptr;
} }
MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail)); // MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
emit terminateAll(); emit terminateAll();
})), KeepOtherLayers); })), KeepOtherLayers);
} }

View file

@ -37,6 +37,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_media_types.h" #include "history/history_media_types.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "window/window_theme.h"
#include "boxes/contactsbox.h" #include "boxes/contactsbox.h"
ShareBox::ShareBox(QWidget*, CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback) ShareBox::ShareBox(QWidget*, CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback)
@ -294,6 +295,20 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac
notifyPeerUpdated(update); notifyPeerUpdated(update);
})); }));
subscribe(FileDownload::ImageLoaded(), [this] { update(); }); subscribe(FileDownload::ImageLoaded(), [this] { update(); });
using Update = Window::Theme::BackgroundUpdate;
subscribe(Window::Theme::Background(), [this](const Update &update) {
if (update.type == Update::Type::TestingTheme
|| update.type == Update::Type::RevertingTheme) {
invalidateCache();
}
});
}
void ShareBox::Inner::invalidateCache() {
for_const (auto data, _dataMap) {
data->checkbox.invalidateCache();
}
} }
void ShareBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) { void ShareBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {

View file

@ -149,6 +149,7 @@ protected:
private: private:
// Observed notifications. // Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update); void notifyPeerUpdated(const Notify::PeerUpdate &update);
void invalidateCache();
int displayedChatsCount() const; int displayedChatsCount() const;

View file

@ -412,6 +412,8 @@ void StickersBox::switchTab() {
auto slideLeft = wasIndex > nowIndex; auto slideLeft = wasIndex > nowIndex;
_slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration); _slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration);
setInnerVisible(false); setInnerVisible(false);
setFocus();
update(); update();
} }
} }

View file

@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h" #include "mainwindow.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/toast/toast.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
UsernameBox::UsernameBox(QWidget*) UsernameBox::UsernameBox(QWidget*)
@ -60,7 +61,7 @@ void UsernameBox::prepare() {
} }
void UsernameBox::setInnerFocus() { void UsernameBox::setInnerFocus() {
_username->setFocus(); _username->setFocusFast();
} }
void UsernameBox::paintEvent(QPaintEvent *e) { void UsernameBox::paintEvent(QPaintEvent *e) {
@ -69,10 +70,7 @@ void UsernameBox::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
p.setFont(st::boxTextFont); p.setFont(st::boxTextFont);
if (!_copiedTextLink.isEmpty()) { if (!_errorText.isEmpty()) {
p.setPen(st::usernameDefaultFg);
p.drawTextLeft(st::usernamePadding.left(), _username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _copiedTextLink);
} else if (!_errorText.isEmpty()) {
p.setPen(st::boxTextFgError); p.setPen(st::boxTextFgError);
p.drawTextLeft(st::usernamePadding.left(), _username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _errorText); p.drawTextLeft(st::usernamePadding.left(), _username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), _errorText);
} else if (!_goodText.isEmpty()) { } else if (!_goodText.isEmpty()) {
@ -134,7 +132,7 @@ void UsernameBox::onChanged() {
QString name = getName(); QString name = getName();
if (name.isEmpty()) { if (name.isEmpty()) {
if (!_errorText.isEmpty() || !_goodText.isEmpty()) { if (!_errorText.isEmpty() || !_goodText.isEmpty()) {
_copiedTextLink = _errorText = _goodText = QString(); _errorText = _goodText = QString();
update(); update();
} }
_checkTimer->stop(); _checkTimer->stop();
@ -143,8 +141,7 @@ void UsernameBox::onChanged() {
for (int32 i = 0; i < len; ++i) { for (int32 i = 0; i < len; ++i) {
QChar ch = name.at(i); QChar ch = name.at(i);
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '_' && (ch != '@' || i > 0)) { if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '_' && (ch != '@' || i > 0)) {
if (_errorText != lang(lng_username_bad_symbols) || !_copiedTextLink.isEmpty()) { if (_errorText != lang(lng_username_bad_symbols)) {
_copiedTextLink = QString();
_errorText = lang(lng_username_bad_symbols); _errorText = lang(lng_username_bad_symbols);
update(); update();
} }
@ -153,15 +150,14 @@ void UsernameBox::onChanged() {
} }
} }
if (name.size() < MinUsernameLength) { if (name.size() < MinUsernameLength) {
if (_errorText != lang(lng_username_too_short) || !_copiedTextLink.isEmpty()) { if (_errorText != lang(lng_username_too_short)) {
_copiedTextLink = QString();
_errorText = lang(lng_username_too_short); _errorText = lang(lng_username_too_short);
update(); update();
} }
_checkTimer->stop(); _checkTimer->stop();
} else { } else {
if (!_errorText.isEmpty() || !_goodText.isEmpty() || !_copiedTextLink.isEmpty()) { if (!_errorText.isEmpty() || !_goodText.isEmpty()) {
_copiedTextLink = _errorText = _goodText = QString(); _errorText = _goodText = QString();
update(); update();
} }
_checkTimer->start(UsernameCheckTimeout); _checkTimer->start(UsernameCheckTimeout);
@ -171,8 +167,10 @@ void UsernameBox::onChanged() {
void UsernameBox::onLinkClick() { void UsernameBox::onLinkClick() {
Application::clipboard()->setText(qsl("https://telegram.me/") + getName()); Application::clipboard()->setText(qsl("https://telegram.me/") + getName());
_copiedTextLink = lang(lng_username_copied);
update(); Ui::Toast::Config toast;
toast.text = lang(lng_username_copied);
Ui::Toast::Show(App::wnd(), toast);
} }
void UsernameBox::onUpdateDone(const MTPUser &user) { void UsernameBox::onUpdateDone(const MTPUser &user) {
@ -192,14 +190,12 @@ bool UsernameBox::onUpdateFail(const RPCError &error) {
} else if (err == qstr("USERNAME_INVALID")) { } else if (err == qstr("USERNAME_INVALID")) {
_username->setFocus(); _username->setFocus();
_username->showError(); _username->showError();
_copiedTextLink = QString();
_errorText = lang(lng_username_invalid); _errorText = lang(lng_username_invalid);
update(); update();
return true; return true;
} else if (err == qstr("USERNAME_OCCUPIED") || err == qstr("USERNAMES_UNAVAILABLE")) { } else if (err == qstr("USERNAME_OCCUPIED") || err == qstr("USERNAMES_UNAVAILABLE")) {
_username->setFocus(); _username->setFocus();
_username->showError(); _username->showError();
_copiedTextLink = QString();
_errorText = lang(lng_username_occupied); _errorText = lang(lng_username_occupied);
update(); update();
return true; return true;
@ -212,10 +208,9 @@ void UsernameBox::onCheckDone(const MTPBool &result) {
_checkRequestId = 0; _checkRequestId = 0;
QString newError = (mtpIsTrue(result) || _checkUsername == App::self()->username) ? QString() : lang(lng_username_occupied); QString newError = (mtpIsTrue(result) || _checkUsername == App::self()->username) ? QString() : lang(lng_username_occupied);
QString newGood = newError.isEmpty() ? lang(lng_username_available) : QString(); QString newGood = newError.isEmpty() ? lang(lng_username_available) : QString();
if (_errorText != newError || _goodText != newGood || !_copiedTextLink.isEmpty()) { if (_errorText != newError || _goodText != newGood) {
_errorText = newError; _errorText = newError;
_goodText = newGood; _goodText = newGood;
_copiedTextLink = QString();
update(); update();
} }
} }
@ -235,7 +230,6 @@ bool UsernameBox::onCheckFail(const RPCError &error) {
return true; return true;
} }
_goodText = QString(); _goodText = QString();
_copiedTextLink = QString();
_username->setFocus(); _username->setFocus();
return true; return true;
} }

View file

@ -63,7 +63,7 @@ private:
mtpRequestId _saveRequestId = 0; mtpRequestId _saveRequestId = 0;
mtpRequestId _checkRequestId = 0; mtpRequestId _checkRequestId = 0;
QString _sentUsername, _checkUsername, _errorText, _goodText, _copiedTextLink; QString _sentUsername, _checkUsername, _errorText, _goodText;
Text _about; Text _about;
object_ptr<QTimer> _checkTimer; object_ptr<QTimer> _checkTimer;

View file

@ -442,6 +442,10 @@ public:\n\
bool load(const QByteArray &cache);\n\ bool load(const QByteArray &cache);\n\
bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\ bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
bool setColor(QLatin1String name, QLatin1String from);\n\ bool setColor(QLatin1String name, QLatin1String from);\n\
void reset() {\n\
clear();\n\
finalize();\n\
}\n\
\n\ \n\
// Created not inited, should be finalized before usage.\n\ // Created not inited, should be finalized before usage.\n\
void finalize();\n\ void finalize();\n\
@ -486,18 +490,24 @@ public:\n\
static int32 Checksum();\n\ static int32 Checksum();\n\
\n\ \n\
~palette() {\n\ ~palette() {\n\
clear();\n\
}\n\
\n\
private:\n\
void clear() {\n\
for (int i = 0; i != " << count << "; ++i) {\n\ for (int i = 0; i != " << count << "; ++i) {\n\
if (_status[i] != Status::Initial) {\n\ if (_status[i] != Status::Initial) {\n\
data(i)->~ColorData();\n\ data(i)->~ColorData();\n\
_status[i] = Status::Initial;\n\
_ready = false;\n\
}\n\ }\n\
}\n\ }\n\
}\n\ }\n\
\n\ \n\
private:\n\
struct TempColorData { uchar r, g, b, a; };\n\ struct TempColorData { uchar r, g, b, a; };\n\
void compute(int index, int fallbackIndex, TempColorData value) {\n\ void compute(int index, int fallbackIndex, TempColorData value) {\n\
if (_status[index] == Status::Initial) {\n\ if (_status[index] == Status::Initial) {\n\
if (fallbackIndex >= 0 && _status[fallbackIndex] != Status::Initial) {\n\ if (fallbackIndex >= 0 && _status[fallbackIndex] == Status::Loaded) {\n\
_status[index] = Status::Loaded;\n\ _status[index] = Status::Loaded;\n\
new (data(index)) internal::ColorData(*data(fallbackIndex));\n\ new (data(index)) internal::ColorData(*data(fallbackIndex));\n\
} else {\n\ } else {\n\
@ -550,6 +560,7 @@ bool load(const QByteArray &cache);\n\
bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\ bool setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\
bool setColor(QLatin1String name, QLatin1String from);\n\ bool setColor(QLatin1String name, QLatin1String from);\n\
void apply(const palette &other);\n\ void apply(const palette &other);\n\
void reset();\n\
\n\ \n\
} // namespace main_palette\n"; } // namespace main_palette\n";
@ -872,6 +883,11 @@ void apply(const palette &other) {\n\
style::internal::resetIcons();\n\ style::internal::resetIcons();\n\
}\n\ }\n\
\n\ \n\
void reset() {\n\
_palette.reset();\n\
style::internal::resetIcons();\n\
}\n\
\n\
} // namespace main_palette\n\ } // namespace main_palette\n\
\n"; \n";

View file

@ -40,7 +40,11 @@ QString tryConvertUrlToLocal(QString url) {
using namespace qthelp; using namespace qthelp;
auto matchOptions = RegExOption::CaseInsensitive; auto matchOptions = RegExOption::CaseInsensitive;
if (auto telegramMeMatch = regex_match(qsl("https?://(www\\.)?telegram\\.me/(.+)$"), url, matchOptions)) { auto telegramMeMatch = regex_match(qsl("https?://(www\\.)?telegram\\.me/(.+)$"), url, matchOptions);
if (!telegramMeMatch) {
telegramMeMatch = regex_match(qsl("https?://(www\\.)?t\\.me/(.+)$"), url, matchOptions);
}
if (telegramMeMatch) {
auto query = telegramMeMatch->capturedRef(2); auto query = telegramMeMatch->capturedRef(2);
if (auto joinChatMatch = regex_match(qsl("^joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), query, matchOptions)) { if (auto joinChatMatch = regex_match(qsl("^joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), query, matchOptions)) {
return qsl("tg://join?invite=") + url_encode(joinChatMatch->captured(1)); return qsl("tg://join?invite=") + url_encode(joinChatMatch->captured(1));
@ -103,13 +107,15 @@ TextWithEntities UrlClickHandler::getExpandedLinkTextWithEntities(ExpandLinksMod
return result; return result;
} }
void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const { void HiddenUrlClickHandler::doOpen(QString url) {
auto urlText = tryConvertUrlToLocal(url()); auto urlText = tryConvertUrlToLocal(url);
if (urlText.startsWith(qstr("tg://"))) { if (urlText.startsWith(qstr("tg://"))) {
App::openLocalUrl(urlText); App::openLocalUrl(urlText);
} else { } else {
Ui::show(Box<ConfirmBox>(lang(lng_open_this_link) + qsl("\n\n") + urlText, lang(lng_open_link), [urlText] { auto parsedUrl = QUrl::fromUserInput(urlText);
auto displayUrl = parsedUrl.isValid() ? parsedUrl.toDisplayString() : urlText;
Ui::show(Box<ConfirmBox>(lang(lng_open_this_link) + qsl("\n\n") + displayUrl, lang(lng_open_link), [urlText] {
Ui::hideLayer(); Ui::hideLayer();
UrlClickHandler::doOpen(urlText); UrlClickHandler::doOpen(urlText);
})); }));

View file

@ -115,7 +115,13 @@ class HiddenUrlClickHandler : public UrlClickHandler {
public: public:
HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) { HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) {
} }
void onClick(Qt::MouseButton button) const override;
static void doOpen(QString url);
void onClick(Qt::MouseButton button) const override {
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
doOpen(url());
}
}
QString getExpandedLinkText(ExpandLinksMode mode, const QStringRef &textPart) const override; QString getExpandedLinkText(ExpandLinksMode mode, const QStringRef &textPart) const override;
TextWithEntities getExpandedLinkTextWithEntities(ExpandLinksMode mode, int entityOffset, const QStringRef &textPart) const override; TextWithEntities getExpandedLinkTextWithEntities(ExpandLinksMode mode, int entityOffset, const QStringRef &textPart) const override;

View file

@ -28,6 +28,14 @@ public:
} }
RegularExpressionMatch(RegularExpressionMatch &&other) : data_(std_::move(other.data_)) { RegularExpressionMatch(RegularExpressionMatch &&other) : data_(std_::move(other.data_)) {
} }
RegularExpressionMatch &operator=(QRegularExpressionMatch &&match) {
data_ = std_::move(match);
return *this;
}
RegularExpressionMatch &operator=(RegularExpressionMatch &&other) {
data_ = std_::move(other.data_);
return *this;
}
QRegularExpressionMatch *operator->() { QRegularExpressionMatch *operator->() {
return &data_; return &data_;
} }

View file

@ -43,7 +43,10 @@ QMap<QString, QString> url_parse_params(const QString &params, UrlParamNameTrans
paramName = param.mid(0, separatorPosition); paramName = param.mid(0, separatorPosition);
paramValue = url_decode(param.mid(separatorPosition + 1)); paramValue = url_decode(param.mid(separatorPosition + 1));
} }
result.insert(transformParamName(paramName), paramValue); paramName = transformParamName(paramName);
if (!result.contains(paramName)) {
result.insert(paramName, paramValue);
}
} }
} }
return result; return result;

View file

@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/utils.h" #include "core/utils.h"
#define BETA_VERSION_MACRO (10020001ULL) #define BETA_VERSION_MACRO (10020002ULL)
constexpr int AppVersion = 10020; constexpr int AppVersion = 10020;
constexpr str_const AppVersionStr = "0.10.20"; constexpr str_const AppVersionStr = "0.10.20";

View file

@ -859,7 +859,7 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
_menu = new Ui::PopupMenu(); _menu = new Ui::PopupMenu();
App::main()->fillPeerMenu(_menuPeer, [this](const QString &text, base::lambda<void()> &&callback) { App::main()->fillPeerMenu(_menuPeer, [this](const QString &text, base::lambda<void()> &&callback) {
return _menu->addAction(text, std_::move(callback)); return _menu->addAction(text, std_::move(callback));
}); }, true);
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroyed(QObject*))); connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroyed(QObject*)));
_menu->popup(e->globalPos()); _menu->popup(e->globalPos());
e->accept(); e->accept();

View file

@ -94,7 +94,17 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
case ButtonType::Url: { case ButtonType::Url: {
auto url = QString::fromUtf8(button->data); auto url = QString::fromUtf8(button->data);
HiddenUrlClickHandler(url).onClick(Qt::LeftButton); auto skipConfirmation = false;
if (auto bot = msg->getMessageBot()) {
if (bot->isVerified()) {
skipConfirmation = true;
}
}
if (skipConfirmation) {
UrlClickHandler::doOpen(url);
} else {
HiddenUrlClickHandler::doOpen(url);
}
} break; } break;
case ButtonType::RequestLocation: { case ButtonType::RequestLocation: {
@ -539,9 +549,13 @@ void start() {
} }
} }
bool started() {
return (SandboxData != nullptr);
}
void finish() { void finish() {
delete SandboxData; delete SandboxData;
SandboxData = 0; SandboxData = nullptr;
} }
uint64 UserTag() { uint64 UserTag() {

View file

@ -226,6 +226,7 @@ bool CheckBetaVersionDir();
void WorkingDirReady(); void WorkingDirReady();
void start(); void start();
bool started();
void finish(); void finish();
uint64 UserTag(); uint64 UserTag();

View file

@ -4217,6 +4217,9 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
destroyUnreadBar(); destroyUnreadBar();
destroyPinnedBar(); destroyPinnedBar();
_history = _migrated = nullptr; _history = _migrated = nullptr;
_peer = nullptr;
_channel = NoChannel;
_canSendMessages = false;
updateBotKeyboard(); updateBotKeyboard();
} }
@ -4239,10 +4242,11 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
_showAtMsgId = showAtMsgId; _showAtMsgId = showAtMsgId;
_histInited = false; _histInited = false;
_peer = peerId ? App::peer(peerId) : nullptr; if (peerId) {
_channel = _peer ? peerToChannel(_peer->id) : NoChannel; _peer = App::peer(peerId);
_canSendMessages = canSendMessages(_peer); _channel = peerToChannel(_peer->id);
_canSendMessages = canSendMessages(_peer);
}
updateTopBarSelection(); updateTopBarSelection();
if (_peer && _peer->isChannel()) { if (_peer && _peer->isChannel()) {

View file

@ -414,7 +414,10 @@ void LayerStackWidget::setCacheImages() {
} }
void LayerStackWidget::onLayerClosed(LayerWidget *layer) { void LayerStackWidget::onLayerClosed(LayerWidget *layer) {
layer->closing(); if (!layer->setClosing()) {
// This layer is already closing.
return;
}
layer->deleteLater(); layer->deleteLater();
if (layer == _specialLayer) { if (layer == _specialLayer) {
hideAll(); hideAll();
@ -523,7 +526,7 @@ void LayerStackWidget::showBox(object_ptr<BoxContent> box) {
auto removingLayer = _layers.front(); auto removingLayer = _layers.front();
_layers.pop_front(); _layers.pop_front();
removingLayer->closing(); removingLayer->setClosing();
removingLayer->hide(); removingLayer->hide();
removingLayer->deleteLater(); removingLayer->deleteLater();
} }
@ -615,7 +618,7 @@ LayerWidget *LayerStackWidget::pushBox(object_ptr<BoxContent> box) {
if (oldLayer) { if (oldLayer) {
oldLayer->hide(); oldLayer->hide();
} }
auto layer = object_ptr<AbstractBox>(std_::move(box)); auto layer = object_ptr<AbstractBox>(this, std_::move(box));
_layers.push_back(layer); _layers.push_back(layer);
initChildLayer(layer); initChildLayer(layer);
@ -637,7 +640,7 @@ void LayerStackWidget::prependBox(object_ptr<BoxContent> box) {
if (_layers.empty()) { if (_layers.empty()) {
return showBox(std_::move(box)); return showBox(std_::move(box));
} }
auto layer = object_ptr<AbstractBox>(std_::move(box)); auto layer = object_ptr<AbstractBox>(this, std_::move(box));
layer->hide(); layer->hide();
_layers.push_front(layer); _layers.push_front(layer);
initChildLayer(layer); initChildLayer(layer);
@ -645,7 +648,7 @@ void LayerStackWidget::prependBox(object_ptr<BoxContent> box) {
void LayerStackWidget::clearLayers() { void LayerStackWidget::clearLayers() {
for (auto layer : base::take(_layers)) { for (auto layer : base::take(_layers)) {
layer->closing(); layer->setClosing();
layer->hide(); layer->hide();
layer->deleteLater(); layer->deleteLater();
} }
@ -653,7 +656,7 @@ void LayerStackWidget::clearLayers() {
void LayerStackWidget::clearSpecialLayer() { void LayerStackWidget::clearSpecialLayer() {
if (_specialLayer) { if (_specialLayer) {
_specialLayer->closing(); _specialLayer->setClosing();
_specialLayer.destroyDelayed(); _specialLayer.destroyDelayed();
} }
} }

View file

@ -34,11 +34,13 @@ public:
virtual void showFinished() { virtual void showFinished() {
} }
void setInnerFocus(); void setInnerFocus();
void closing() { bool setClosing() {
if (!_closing) { if (!_closing) {
_closing = true; _closing = true;
closeHook(); closeHook();
return true;
} }
return false;
} }
bool overlaps(const QRect &globalRect); bool overlaps(const QRect &globalRect);

View file

@ -3725,6 +3725,14 @@ bool readThemeUsingKey(FileKey key) {
} }
void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache) { void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache) {
if (content.isEmpty()) {
if (_themeKey) {
clearKey(_themeKey);
_themeKey = 0;
writeSettings();
}
return;
}
if (!_themeKey) { if (!_themeKey) {
_themeKey = genKey(); _themeKey = genKey();
writeSettings(); writeSettings();
@ -3743,14 +3751,20 @@ void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const
file.writeEncrypted(data, _settingsKey); file.writeEncrypted(data, _settingsKey);
} }
void clearTheme() {
writeTheme(QString(), QString(), QByteArray(), Window::Theme::Cached());
}
void readTheme() { void readTheme() {
if (_themeKey && !readThemeUsingKey(_themeKey)) { if (_themeKey && !readThemeUsingKey(_themeKey)) {
clearKey(_themeKey); clearTheme();
_themeKey = 0;
writeSettings();
} }
} }
bool hasTheme() {
return (_themeKey != 0);
}
uint32 _peerSize(PeerData *peer) { uint32 _peerSize(PeerData *peer) {
uint32 result = sizeof(quint64) + sizeof(quint64) + Serialize::storageImageLocationSize(); uint32 result = sizeof(quint64) + sizeof(quint64) + Serialize::storageImageLocationSize();
if (peer->isUser()) { if (peer->isUser()) {

View file

@ -151,6 +151,8 @@ void writeBackground(int32 id, const QImage &img);
bool readBackground(); bool readBackground();
void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache); void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache);
void clearTheme();
bool hasTheme();
void writeRecentHashtagsAndBots(); void writeRecentHashtagsAndBots();
void readRecentHashtagsAndBots(); void readRecentHashtagsAndBots();

View file

@ -1975,33 +1975,34 @@ void MainWidget::scheduleViewIncrement(HistoryItem *item) {
j.value().insert(item->id, true); j.value().insert(item->id, true);
} }
void MainWidget::fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QString &text, base::lambda<void()> &&handler)> &&callback) { void MainWidget::fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QString &text, base::lambda<void()> &&handler)> &&callback, bool pinToggle) {
auto isPinned = false; if (pinToggle) {
if (auto history = App::historyLoaded(peer)) { auto isPinned = false;
isPinned = history->isPinnedDialog(); if (auto history = App::historyLoaded(peer)) {
} isPinned = history->isPinnedDialog();
auto pinSubscription = MakeShared<base::Subscription>();
auto pinAction = callback(lang(isPinned ? lng_context_unpin_from_top : lng_context_pin_to_top), [peer, pinSubscription] {
auto history = App::history(peer);
auto isPinned = !history->isPinnedDialog();
history->setPinnedDialog(isPinned);
auto flags = MTPmessages_ToggleDialogPin::Flags(0);
if (isPinned) {
flags |= MTPmessages_ToggleDialogPin::Flag::f_pinned;
} }
MTP::send(MTPmessages_ToggleDialogPin(MTP_flags(flags), peer->input)); auto pinSubscription = MakeShared<base::Subscription>();
if (isPinned) { auto pinAction = callback(lang(isPinned ? lng_context_unpin_from_top : lng_context_pin_to_top), [peer, pinSubscription] {
if (auto main = App::main()) { auto history = App::history(peer);
main->dialogsToUp(); auto isPinned = !history->isPinnedDialog();
history->setPinnedDialog(isPinned);
auto flags = MTPmessages_ToggleDialogPin::Flags(0);
if (isPinned) {
flags |= MTPmessages_ToggleDialogPin::Flag::f_pinned;
} }
} MTP::send(MTPmessages_ToggleDialogPin(MTP_flags(flags), peer->input));
}); if (isPinned) {
auto pinChangedHandler = Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::PinnedChanged, [pinAction, peer](const Notify::PeerUpdate &update) { if (auto main = App::main()) {
if (update.peer != peer) return; main->dialogsToUp();
pinAction->setText(lang(App::history(peer)->isPinnedDialog() ? lng_context_unpin_from_top : lng_context_pin_to_top)); }
}); }
*pinSubscription = Notify::PeerUpdated().add_subscription(std_::move(pinChangedHandler)); });
auto pinChangedHandler = Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::PinnedChanged, [pinAction, peer](const Notify::PeerUpdate &update) {
if (update.peer != peer) return;
pinAction->setText(lang(App::history(peer)->isPinnedDialog() ? lng_context_unpin_from_top : lng_context_pin_to_top));
});
*pinSubscription = Notify::PeerUpdated().add_subscription(std_::move(pinChangedHandler));
}
callback(lang((peer->isChat() || peer->isMegagroup()) ? lng_context_view_group : (peer->isUser() ? lng_context_view_profile : lng_context_view_channel)), [peer] { callback(lang((peer->isChat() || peer->isMegagroup()) ? lng_context_view_group : (peer->isUser() ? lng_context_view_profile : lng_context_view_channel)), [peer] {
Ui::showPeerProfile(peer); Ui::showPeerProfile(peer);
}); });

View file

@ -360,7 +360,7 @@ public:
void scheduleViewIncrement(HistoryItem *item); void scheduleViewIncrement(HistoryItem *item);
void fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QString &text, base::lambda<void()> &&handler)> &&callback); void fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QString &text, base::lambda<void()> &&handler)> &&callback, bool pinToggle);
void gotRangeDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff); void gotRangeDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff);
void onSelfParticipantUpdated(ChannelData *channel); void onSelfParticipantUpdated(ChannelData *channel);

View file

@ -115,7 +115,6 @@ mediaviewFileIconSize: 80px;
mediaviewFileLink: LinkButton(defaultLinkButton) { mediaviewFileLink: LinkButton(defaultLinkButton) {
color: #4595d3; color: #4595d3;
overColor: #4595d3; overColor: #4595d3;
downColor: #4595d3;
} }
mediaviewTransparentBg: #ffffff; mediaviewTransparentBg: #ffffff;

View file

@ -149,6 +149,10 @@ public:
void setActive(bool active); void setActive(bool active);
void setPressed(bool pressed); void setPressed(bool pressed);
void invalidateCache() {
_check.invalidateCache();
}
private: private:
void startAnimation(); void startAnimation();
@ -283,6 +287,12 @@ void Photo::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool press
} }
} }
void Photo::invalidateCache() {
if (_check) {
_check->invalidateCache();
}
}
Video::Video(DocumentData *video, HistoryItem *parent) : RadialProgressItem(parent) Video::Video(DocumentData *video, HistoryItem *parent) : RadialProgressItem(parent)
, _data(video) , _data(video)
, _duration(formatDurationText(_data->duration())) , _duration(formatDurationText(_data->duration()))
@ -431,6 +441,12 @@ void Video::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool press
} }
} }
void Video::invalidateCache() {
if (_check) {
_check->invalidateCache();
}
}
void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const { void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
bool loaded = _data->loaded(); bool loaded = _data->loaded();

View file

@ -59,6 +59,9 @@ public:
return item ? item->id : 0; return item ? item->id : 0;
} }
virtual void invalidateCache() {
}
}; };
class ItemBase : public AbstractItem { class ItemBase : public AbstractItem {
@ -186,6 +189,8 @@ public:
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override; void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override; void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
void invalidateCache() override;
private: private:
void ensureCheckboxCreated(); void ensureCheckboxCreated();
@ -211,6 +216,8 @@ public:
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override; void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override; void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
void invalidateCache() override;
protected: protected:
float64 dataProgress() const override { float64 dataProgress() const override {
return _data->progress(); return _data->progress();

View file

@ -85,6 +85,14 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
_searchTimer.setSingleShot(true); _searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages())); connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages()));
using Update = Window::Theme::BackgroundUpdate;
subscribe(Window::Theme::Background(), [this](const Update &update) {
if (update.type == Update::Type::TestingTheme
|| update.type == Update::Type::RevertingTheme) {
invalidateCache();
}
});
if (_type == OverviewLinks || _type == OverviewFiles) { if (_type == OverviewLinks || _type == OverviewFiles) {
_search->show(); _search->show();
} else { } else {
@ -92,6 +100,15 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
} }
} }
void OverviewInner::invalidateCache() {
for_const (auto item, _layoutItems) {
item->invalidateCache();
}
for_const (auto item, _layoutDates) {
item->invalidateCache();
}
}
bool OverviewInner::event(QEvent *e) { bool OverviewInner::event(QEvent *e) {
if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) {
QTouchEvent *ev = static_cast<QTouchEvent*>(e); QTouchEvent *ev = static_cast<QTouchEvent*>(e);

View file

@ -128,6 +128,7 @@ public slots:
private: private:
void saveDocumentToFile(DocumentData *document); void saveDocumentToFile(DocumentData *document);
void invalidateCache();
void itemRemoved(HistoryItem *item); void itemRemoved(HistoryItem *item);
MsgId complexMsgId(const HistoryItem *item) const; MsgId complexMsgId(const HistoryItem *item) const;

View file

@ -482,11 +482,17 @@ void psRegisterCustomScheme() {
QFile f(file); QFile f(file);
if (f.open(QIODevice::WriteOnly)) { if (f.open(QIODevice::WriteOnly)) {
QString icon = icons + qsl("telegram.png"); QString icon = icons + qsl("telegram.png");
if (!QFile(icon).exists()) { auto iconExists = QFile(icon).exists();
if (Local::oldSettingsVersion() < 10021 && iconExists) {
// Icon was changed.
if (QFile(icon).remove()) {
iconExists = false;
}
}
if (!iconExists) {
if (QFile(qsl(":/gui/art/icon256.png")).copy(icon)) { if (QFile(qsl(":/gui/art/icon256.png")).copy(icon)) {
DEBUG_LOG(("App Info: Icon copied to 'tdata'")); DEBUG_LOG(("App Info: Icon copied to 'tdata'"));
} }
} }
QTextStream s(&f); QTextStream s(&f);

View file

@ -42,6 +42,26 @@ BackgroundRow::BackgroundRow(QWidget *parent) : TWidget(parent)
connect(_chooseFromGallery, SIGNAL(clicked()), this, SIGNAL(chooseFromGallery())); connect(_chooseFromGallery, SIGNAL(clicked()), this, SIGNAL(chooseFromGallery()));
connect(_chooseFromFile, SIGNAL(clicked()), this, SIGNAL(chooseFromFile())); connect(_chooseFromFile, SIGNAL(clicked()), this, SIGNAL(chooseFromFile()));
checkNonDefaultTheme();
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
if (update.type == Window::Theme::BackgroundUpdate::Type::ApplyingTheme) {
checkNonDefaultTheme();
}
});
}
void BackgroundRow::checkNonDefaultTheme() {
if (Local::hasTheme()) {
if (!_useDefault) {
_useDefault.create(this, lang(lng_settings_bg_use_default), st::boxLinkButton);
_useDefault->show();
connect(_useDefault, SIGNAL(clicked()), this, SIGNAL(useDefault()));
resizeToWidth(width());
}
} else if (_useDefault) {
_useDefault.destroy();
resizeToWidth(width());
}
} }
void BackgroundRow::paintEvent(QPaintEvent *e) { void BackgroundRow::paintEvent(QPaintEvent *e) {
@ -83,13 +103,19 @@ void BackgroundRow::paintEvent(QPaintEvent *e) {
} }
int BackgroundRow::resizeGetHeight(int newWidth) { int BackgroundRow::resizeGetHeight(int newWidth) {
int linkLeft = st::settingsBackgroundSize + st::settingsSmallSkip; auto linkTop = 0;
int linkWidth = newWidth - linkLeft; auto linkLeft = st::settingsBackgroundSize + st::settingsSmallSkip;
auto linkWidth = newWidth - linkLeft;
_chooseFromGallery->resizeToWidth(qMin(linkWidth, _chooseFromGallery->naturalWidth())); _chooseFromGallery->resizeToWidth(qMin(linkWidth, _chooseFromGallery->naturalWidth()));
_chooseFromFile->resizeToWidth(qMin(linkWidth, _chooseFromFile->naturalWidth())); _chooseFromFile->resizeToWidth(qMin(linkWidth, _chooseFromFile->naturalWidth()));
if (_useDefault) {
_chooseFromGallery->moveToLeft(linkLeft, 0, newWidth); _useDefault->resizeToWidth(qMin(linkWidth, _useDefault->naturalWidth()));
_chooseFromFile->moveToLeft(linkLeft, _chooseFromGallery->height() + st::settingsSmallSkip, newWidth); _useDefault->moveToLeft(linkLeft, linkTop, newWidth);
linkTop += _useDefault->height() + st::settingsSmallSkip;
}
_chooseFromGallery->moveToLeft(linkLeft, linkTop, newWidth);
linkTop += _chooseFromGallery->height() + st::settingsSmallSkip;
_chooseFromFile->moveToLeft(linkLeft, linkTop, newWidth);
return st::settingsBackgroundSize; return st::settingsBackgroundSize;
} }
@ -194,6 +220,7 @@ void BackgroundWidget::createControls() {
addChildRow(_background, margin); addChildRow(_background, margin);
connect(_background, SIGNAL(chooseFromGallery()), this, SLOT(onChooseFromGallery())); connect(_background, SIGNAL(chooseFromGallery()), this, SLOT(onChooseFromGallery()));
connect(_background, SIGNAL(chooseFromFile()), this, SLOT(onChooseFromFile())); connect(_background, SIGNAL(chooseFromFile()), this, SLOT(onChooseFromFile()));
connect(_background, SIGNAL(useDefault()), this, SLOT(onUseDefault()));
addChildRow(_tile, margin, lang(lng_settings_bg_tile), SLOT(onTile()), Window::Theme::Background()->tile()); addChildRow(_tile, margin, lang(lng_settings_bg_tile), SLOT(onTile()), Window::Theme::Background()->tile());
addChildRow(_adaptive, margin, slidedPadding, lang(lng_settings_adaptive_wide), SLOT(onAdaptive()), Global::AdaptiveForWide()); addChildRow(_adaptive, margin, slidedPadding, lang(lng_settings_adaptive_wide), SLOT(onAdaptive()), Global::AdaptiveForWide());
@ -213,13 +240,16 @@ void BackgroundWidget::needBackgroundUpdate(bool tile) {
void BackgroundWidget::onChooseFromFile() { void BackgroundWidget::onChooseFromFile() {
auto imgExtensions = cImgExtensions(); auto imgExtensions = cImgExtensions();
auto filters = QStringList(qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(")")); auto filters = QStringList(qsl("Theme files (*.tdesktop-theme *") + imgExtensions.join(qsl(" *")) + qsl(")"));
filters.push_back(qsl("Theme files (*.tdesktop-theme)"));
filters.push_back(filedialogAllFilesFilter()); filters.push_back(filedialogAllFilesFilter());
_chooseFromFileQueryId = FileDialog::queryReadFile(lang(lng_choose_image), filters.join(qsl(";;"))); _chooseFromFileQueryId = FileDialog::queryReadFile(lang(lng_choose_image), filters.join(qsl(";;")));
} }
void BackgroundWidget::onUseDefault() {
Window::Theme::ApplyDefault();
}
void BackgroundWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) { void BackgroundWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) {
if (_chooseFromFileQueryId != update.queryId) { if (_chooseFromFileQueryId != update.queryId) {
return; return;

View file

@ -26,7 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Settings { namespace Settings {
class BackgroundRow : public TWidget { class BackgroundRow : public TWidget, private base::Subscriber {
Q_OBJECT Q_OBJECT
public: public:
@ -42,8 +42,11 @@ protected:
signals: signals:
void chooseFromGallery(); void chooseFromGallery();
void chooseFromFile(); void chooseFromFile();
void useDefault();
private: private:
void checkNonDefaultTheme();
float64 radialProgress() const; float64 radialProgress() const;
bool radialLoading() const; bool radialLoading() const;
QRect radialRect() const; QRect radialRect() const;
@ -52,6 +55,7 @@ private:
void step_radial(TimeMs ms, bool timer); void step_radial(TimeMs ms, bool timer);
QPixmap _background; QPixmap _background;
object_ptr<Ui::LinkButton> _useDefault = { nullptr };
object_ptr<Ui::LinkButton> _chooseFromGallery; object_ptr<Ui::LinkButton> _chooseFromGallery;
object_ptr<Ui::LinkButton> _chooseFromFile; object_ptr<Ui::LinkButton> _chooseFromFile;
@ -68,6 +72,7 @@ public:
private slots: private slots:
void onChooseFromGallery(); void onChooseFromGallery();
void onChooseFromFile(); void onChooseFromFile();
void onUseDefault();
void onTile(); void onTile();
void onAdaptive(); void onAdaptive();

View file

@ -144,6 +144,15 @@ void RoundCheckbox::setChecked(bool newChecked, SetStyle speed) {
} }
} }
void RoundCheckbox::invalidateCache() {
if (!_wideCheckBgCache.isNull() || !_wideCheckFullCache.isNull()) {
prepareCheckCaches(&_st, _displayInactive, _wideCheckBgCache, _wideCheckFullCache);
}
if (!_inactiveCacheBg.isNull() || !_inactiveCacheFg.isNull()) {
prepareInactiveCache();
}
}
void RoundCheckbox::setDisplayInactive(bool displayInactive) { void RoundCheckbox::setDisplayInactive(bool displayInactive) {
if (_displayInactive != displayInactive) { if (_displayInactive != displayInactive) {
_displayInactive = displayInactive; _displayInactive = displayInactive;

View file

@ -40,6 +40,8 @@ public:
}; };
void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated); void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated);
void invalidateCache();
private: private:
struct Icon { struct Icon {
Animation fadeIn; Animation fadeIn;
@ -79,6 +81,10 @@ public:
using SetStyle = RoundCheckbox::SetStyle; using SetStyle = RoundCheckbox::SetStyle;
void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated); void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated);
void invalidateCache() {
_check.invalidateCache();
}
private: private:
void prepareWideCache(); void prepareWideCache();

View file

@ -74,7 +74,7 @@ QPixmap myGrab(TWidget *target, QRect rect, QColor bg) {
} }
target->grabStart(); target->grabStart();
target->render(&result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask); target->render(&result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask);
target->grabFinish(); target->grabFinish();
return std_::move(result); return std_::move(result);

View file

@ -41,7 +41,7 @@ int LinkButton::naturalWidth() const {
void LinkButton::paintEvent(QPaintEvent *e) { void LinkButton::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
auto &font = (isOver() ? _st.overFont : _st.font); auto &font = (isOver() ? _st.overFont : _st.font);
auto &pen = (isDown() ? _st.downColor : (isOver() ? _st.overColor : _st.color)); auto &pen = (isOver() ? _st.overColor : _st.color);
p.setFont(font); p.setFont(font);
p.setPen(pen); p.setPen(pen);
if (_textWidth > width()) { if (_textWidth > width()) {

View file

@ -1830,7 +1830,7 @@ void InputArea::paintEvent(QPaintEvent *e) {
p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg); p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg);
} }
auto errorDegree = _a_error.current(ms, _error ? 1. : 0.); auto errorDegree = _a_error.current(ms, _error ? 1. : 0.);
auto focusedDegree = _a_focused.current(ms, hasFocus() ? 1. : 0.); auto focusedDegree = _a_focused.current(ms, _focused ? 1. : 0.);
auto borderShownDegree = _a_borderShown.current(ms, 1.); auto borderShownDegree = _a_borderShown.current(ms, 1.);
auto borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 0.); auto borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 0.);
if (_st.borderActive && (borderOpacity > 0.)) { if (_st.borderActive && (borderOpacity > 0.)) {
@ -2547,7 +2547,7 @@ void InputField::paintEvent(QPaintEvent *e) {
p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg); p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg);
} }
auto errorDegree = _a_error.current(ms, _error ? 1. : 0.); auto errorDegree = _a_error.current(ms, _error ? 1. : 0.);
auto focusedDegree = _a_focused.current(ms, hasFocus() ? 1. : 0.); auto focusedDegree = _a_focused.current(ms, _focused ? 1. : 0.);
auto borderShownDegree = _a_borderShown.current(ms, 1.); auto borderShownDegree = _a_borderShown.current(ms, 1.);
auto borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 0.); auto borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 0.);
if (_st.borderActive && (borderOpacity > 0.)) { if (_st.borderActive && (borderOpacity > 0.)) {
@ -3307,7 +3307,7 @@ void MaskedInputField::paintEvent(QPaintEvent *e) {
p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg->b); p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg->b);
} }
auto errorDegree = _a_error.current(ms, _error ? 1. : 0.); auto errorDegree = _a_error.current(ms, _error ? 1. : 0.);
auto focusedDegree = _a_focused.current(ms, hasFocus() ? 1. : 0.); auto focusedDegree = _a_focused.current(ms, _focused ? 1. : 0.);
auto borderShownDegree = _a_borderShown.current(ms, 1.); auto borderShownDegree = _a_borderShown.current(ms, 1.);
auto borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 0.); auto borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 0.);
if (_st.borderActive && (borderOpacity > 0.)) { if (_st.borderActive && (borderOpacity > 0.)) {

View file

@ -344,6 +344,10 @@ public:
} }
void setDisplayFocused(bool focused); void setDisplayFocused(bool focused);
void finishAnimations(); void finishAnimations();
void setFocusFast() {
setDisplayFocused(true);
setFocus();
}
QSize sizeHint() const override; QSize sizeHint() const override;
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
@ -517,6 +521,10 @@ public:
void setPlaceholderHidden(bool forcePlaceholderHidden); void setPlaceholderHidden(bool forcePlaceholderHidden);
void setDisplayFocused(bool focused); void setDisplayFocused(bool focused);
void finishAnimations(); void finishAnimations();
void setFocusFast() {
setDisplayFocused(true);
setFocus();
}
QSize sizeHint() const override; QSize sizeHint() const override;
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
@ -698,6 +706,10 @@ public:
void setPlaceholderHidden(bool forcePlaceholderHidden); void setPlaceholderHidden(bool forcePlaceholderHidden);
void setDisplayFocused(bool focused); void setDisplayFocused(bool focused);
void finishAnimations(); void finishAnimations();
void setFocusFast() {
setDisplayFocused(true);
setFocus();
}
void setText(const QString &text) { void setText(const QString &text) {
QLineEdit::setText(text); QLineEdit::setText(text);

View file

@ -460,7 +460,7 @@ bool MultiSelect::Inner::setInnerFocus() {
if (_active >= 0) { if (_active >= 0) {
setFocus(); setFocus();
} else if (!_field->hasFocus()) { } else if (!_field->hasFocus()) {
_field->setFocus(); _field->setFocusFast();
return true; return true;
} }
return false; return false;

View file

@ -39,7 +39,6 @@ FlatLabel {
LinkButton { LinkButton {
color: color; color: color;
overColor: color; overColor: color;
downColor: color;
font: font; font: font;
overFont: font; overFont: font;
} }
@ -441,7 +440,6 @@ defaultFlatLabel: FlatLabel {
defaultLinkButton: LinkButton { defaultLinkButton: LinkButton {
color: windowActiveTextFg; color: windowActiveTextFg;
overColor: windowActiveTextFg; overColor: windowActiveTextFg;
downColor: windowActiveTextFg;
font: linkFont; font: linkFont;
overFont: linkOverFont; overFont: linkOverFont;
} }

View file

@ -32,9 +32,10 @@ MainWindow::MainWindow() : QWidget()
, _positionUpdatedTimer(this) , _positionUpdatedTimer(this)
, _body(this) , _body(this)
, _titleText(qsl("Telegram")) { , _titleText(qsl("Telegram")) {
subscribe(Theme::Background(), [this](const Theme::BackgroundUpdate &data) { using Update = Theme::BackgroundUpdate;
using Type = Theme::BackgroundUpdate::Type; subscribe(Theme::Background(), [this](const Update &data) {
if (data.type == Type::TestingTheme || data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) { if (data.type == Update::Type::TestingTheme
|| data.type == Update::Type::RevertingTheme) {
if (_title) { if (_title) {
_title->update(); _title->update();
} }

View file

@ -62,6 +62,10 @@ void Manager::notificationActivated(PeerId peerId, MsgId msgId) {
if (auto window = App::wnd()) { if (auto window = App::wnd()) {
auto history = App::history(peerId); auto history = App::history(peerId);
window->showFromTray(); window->showFromTray();
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
window->onReActivate();
QTimer::singleShot(200, window, SLOT(onReActivate()));
#endif
if (App::passcoded()) { if (App::passcoded()) {
window->setInnerFocus(); window->setInnerFocus();
window->notifyClear(); window->notifyClear();

View file

@ -126,7 +126,7 @@ void TopBarWidget::showMenu() {
_menuToggle->installEventFilter(_menu); _menuToggle->installEventFilter(_menu);
App::main()->fillPeerMenu(peer, [this](const QString &text, base::lambda<void()> &&callback) { App::main()->fillPeerMenu(peer, [this](const QString &text, base::lambda<void()> &&callback) {
return _menu->addAction(text, std_::move(callback)); return _menu->addAction(text, std_::move(callback));
}); }, false);
_menu->moveToRight(st::topBarMenuPosition.x(), st::topBarMenuPosition.y()); _menu->moveToRight(st::topBarMenuPosition.x(), st::topBarMenuPosition.y());
_menu->showAnimated(Ui::PanelAnimation::Origin::TopRight); _menu->showAnimated(Ui::PanelAnimation::Origin::TopRight);
} }

View file

@ -539,6 +539,16 @@ void ChatBackground::setTestingTheme(Instance &&theme) {
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, _tile), true); notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, _tile), true);
} }
void ChatBackground::setTestingDefaultTheme() {
style::main_palette::reset();
if (_id != kDefaultBackground) {
saveForRevert();
setImage(internal::kTestingDefaultBackground);
setTile(false);
}
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, _tile), true);
}
void ChatBackground::keepApplied() { void ChatBackground::keepApplied() {
if (_id == internal::kTestingThemeBackground) { if (_id == internal::kTestingThemeBackground) {
_id = kThemeBackground; _id = kThemeBackground;
@ -613,13 +623,24 @@ bool Apply(const QString &filepath) {
return true; return true;
} }
void ApplyDefault() {
instance.createIfNull();
instance->applying.path = QString();
instance->applying.content = QByteArray();
instance->applying.cached = Cached();
if (instance->applying.paletteForRevert.isEmpty()) {
instance->applying.paletteForRevert = style::main_palette::save();
}
Background()->setTestingDefaultTheme();
}
void KeepApplied() { void KeepApplied() {
auto filepath = instance ? instance->applying.path : QString(); if (!instance) {
if (filepath.isEmpty()) {
return; return;
} }
auto pathRelative = QDir().relativeFilePath(filepath); auto filepath = instance->applying.path;
auto pathAbsolute = QFileInfo(filepath).absoluteFilePath(); auto pathRelative = filepath.isEmpty() ? QString() : QDir().relativeFilePath(filepath);
auto pathAbsolute = filepath.isEmpty() ? QString() : QFileInfo(filepath).absoluteFilePath();
Local::writeTheme(pathRelative, pathAbsolute, instance->applying.content, instance->applying.cached); Local::writeTheme(pathRelative, pathAbsolute, instance->applying.content, instance->applying.cached);
instance->applying = Data::Applying(); instance->applying = Data::Applying();
Background()->keepApplied(); Background()->keepApplied();

View file

@ -46,6 +46,7 @@ bool Load(const QString &pathRelative, const QString &pathAbsolute, const QByteA
void Unload(); void Unload();
bool Apply(const QString &filepath); bool Apply(const QString &filepath);
void ApplyDefault();
void KeepApplied(); void KeepApplied();
void Revert(); void Revert();
@ -85,6 +86,7 @@ public:
void reset(); void reset();
void setTestingTheme(Instance &&theme); void setTestingTheme(Instance &&theme);
void setTestingDefaultTheme();
void keepApplied(); void keepApplied();
void revert(); void revert();

View file

@ -45,9 +45,15 @@ set "DeployPath=%ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStrFull%"
set "SignPath=%HomePath%\..\..\TelegramPrivate\Sign.bat" set "SignPath=%HomePath%\..\..\TelegramPrivate\Sign.bat"
set "BinaryName=Telegram" set "BinaryName=Telegram"
set "DropboxSymbolsPath=X:\Telegram\symbols" set "DropboxSymbolsPath=X:\Telegram\symbols"
set "FinalReleasePath=Y:\TBuild\tother\tsetup"
if not exist %DropboxSymbolsPath% ( if not exist %DropboxSymbolsPath% (
echo Dropbox path not found! echo Dropbox path %DropboxSymbolsPath% not found!
exit /b 1
)
if not exist %FinalReleasePath% (
echo Release path %FinalReleasePath% not found!
exit /b 1 exit /b 1
) )
@ -176,7 +182,6 @@ echo .
echo Version %AppVersionStrFull% is ready for deploy! echo Version %AppVersionStrFull% is ready for deploy!
echo . echo .
set "FinalReleasePath=Y:\TBuild\tother\tsetup"
set "FinalDeployPath=%FinalReleasePath%\%AppVersionStrMajor%\%AppVersionStrFull%" set "FinalDeployPath=%FinalReleasePath%\%AppVersionStrMajor%\%AppVersionStrFull%"
if not exist "%DeployPath%\%UpdateFile%" goto error if not exist "%DeployPath%\%UpdateFile%" goto error

View file

@ -3,4 +3,4 @@ AppVersionStrMajor 0.10
AppVersionStrSmall 0.10.20 AppVersionStrSmall 0.10.20
AppVersionStr 0.10.20 AppVersionStr 0.10.20
AlphaChannel 0 AlphaChannel 0
BetaVersion 10020001 BetaVersion 10020002