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_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_file" = "Choose from file";
"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_new" = "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_wrong" = "Wrong passcode";
"lng_passcode_is_same" = "Passcode was not changed";

View file

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

View file

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

View file

@ -2211,26 +2211,7 @@ namespace {
return MsgRadius;
}
void initMedia() {
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());
}
void createCorners() {
style::color white = { 255, 255, 255, 255 };
QImage mask[4];
prepareCorners(LargeMaskCorners, msgRadius(), white, nullptr, mask);
@ -2272,22 +2253,69 @@ namespace {
prepareCorners(MessageInSelectedCorners, msgRadius(), st::msgInBgSelected, &st::msgInShadowSelected);
prepareCorners(MessageOutCorners, msgRadius(), st::msgOutBg, &st::msgOutShadow);
prepareCorners(MessageOutSelectedCorners, msgRadius(), st::msgOutBgSelected, &st::msgOutShadowSelected);
}
static auto subscription = Window::Theme::Background()->add_subscription([](const Window::Theme::BackgroundUpdate &update) {
if (update.type != Window::Theme::BackgroundUpdate::Type::New) {
return;
void clearCorners() {
for (int j = 0; j < 4; ++j) {
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 ::corners[StickerCorners].p[i]; ::corners[StickerCorners].p[i] = nullptr;
delete ::corners[StickerSelectedCorners].p[i]; ::corners[StickerSelectedCorners].p[i] = 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];
}
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg);
}
::cornersMap.clear();
}
if (App::main()) {
App::main()->updateScrollColors();
void initMedia() {
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() {
delete ::emoji;
::emoji = 0;
::emoji = nullptr;
delete ::emojiLarge;
::emojiLarge = 0;
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < RoundCornersCount; ++i) {
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();
::emojiLarge = nullptr;
clearCorners();
mainEmojiMap.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"
namespace {
void mtpStateChanged(int32 dc, int32 state) {
if (App::wnd()) {
App::wnd()->mtpStateChanged(dc, state);
}
}
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;
void mtpStateChanged(int32 dc, int32 state) {
if (App::wnd()) {
App::wnd()->mtpStateChanged(dc, state);
}
}
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) {
QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath()));
@ -468,6 +470,8 @@ void Application::stopUpdate() {
}
void Application::startUpdateCheck(bool forceWait) {
if (!Sandbox::started()) return;
_updateCheckTimer.stop();
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()));
_topShadow.create(this, object_ptr<BoxLayerTitleShadow>(this));
if (_innerTopSkip > 0) {
_topShadow->showFast();
} else {
_topShadow->hideFast();
}
_bottomShadow.create(this);
_bottomShadow->show();
} else {
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), 0);
_bottomShadow.create(this, object_ptr<BoxLayerTitleShadow>(this));
}
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), 0);
_scroll->setOwnedWidget(std_::move(inner));
updateScrollAreaGeometry();
} else {
@ -99,17 +91,28 @@ void BoxContent::onDraggingScrollTimer() {
_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() {
if (_scroll) {
updateInnerVisibleTopBottom();
auto top = _scroll->scrollTop();
if (auto widget = static_cast<TWidget*>(_scroll->widget())) {
widget->setVisibleTopBottom(top, top + _scroll->height());
}
if (top > 0 || _innerTopSkip > 0) {
_topShadow->showAnimated();
} else {
_topShadow->hideAnimated();
}
if (top < _scroll->scrollTopMax()) {
_bottomShadow->showAnimated();
} else {
_bottomShadow->hideAnimated();
}
}
}
@ -123,11 +126,6 @@ void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) {
if (scrollBottomFixed) {
_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);
_topShadow->entity()->resize(width(), st::lineWidth);
_topShadow->moveToLeft(0, _innerTopSkip);
_bottomShadow->resize(width(), st::lineWidth);
_bottomShadow->entity()->resize(width(), st::lineWidth);
_bottomShadow->moveToLeft(0, height() - st::lineWidth);
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)
: _content(std_::move(content)) {
AbstractBox::AbstractBox(QWidget *parent, object_ptr<BoxContent> content) : LayerWidget(parent)
, _content(std_::move(content)) {
_content->setParent(this);
_content->setDelegate(this);
}

View file

@ -65,6 +65,7 @@ public:
void setDelegate(BoxContentDelegate *newDelegate) {
_delegate = newDelegate;
prepare();
setInnerFocus();
}
virtual void setInnerFocus() {
setFocus();
@ -121,16 +122,16 @@ protected:
template <typename Widget>
QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, const style::ScrollArea &st, int topSkip = 0) {
auto result = QPointer<Widget>(inner.data());
setInner(std_::move(inner), st);
setInnerTopSkip(topSkip);
setInner(std_::move(inner), st);
return result;
}
template <typename Widget>
QPointer<Widget> setInnerWidget(object_ptr<Widget> inner, int topSkip = 0) {
auto result = QPointer<Widget>(inner.data());
setInner(std_::move(inner));
setInnerTopSkip(topSkip);
setInner(std_::move(inner));
return result;
}
@ -154,6 +155,7 @@ private:
void setInner(object_ptr<TWidget> inner);
void setInner(object_ptr<TWidget> inner, const style::ScrollArea &st);
void updateScrollAreaGeometry();
void updateInnerVisibleTopBottom();
object_ptr<TWidget> doTakeInnerWidget();
BoxContentDelegate *getDelegate() const {
@ -166,7 +168,7 @@ private:
int _innerTopSkip = 0;
object_ptr<Ui::ScrollArea> _scroll = { 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 };
int _draggingScrollDelta = 0;
@ -175,7 +177,7 @@ private:
class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber {
public:
AbstractBox(object_ptr<BoxContent> content);
AbstractBox(QWidget *parent, object_ptr<BoxContent> content);
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/input_fields.h"
#include "ui/widgets/labels.h"
#include "ui/toast/toast.h"
#include "ui/buttons/peer_avatar_button.h"
#include "mainwidget.h"
#include "mainwindow.h"
@ -74,21 +75,15 @@ void AddContactBox::prepare() {
connect(_last, 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());
}
void AddContactBox::setInnerFocus() {
if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) {
(_invertOrder ? _last : _first)->setFocus();
(_invertOrder ? _last : _first)->setFocusFast();
_phone->finishAnimations();
} else {
_phone->setFocus();
_phone->setFocusFast();
}
}
@ -284,13 +279,11 @@ void GroupInfoBox::prepare() {
notifyFileQueryUpdated(update);
});
_title->setDisplayFocused(true);
updateMaxHeight();
}
void GroupInfoBox::setInnerFocus() {
_title->setFocus();
_title->setFocusFast();
}
void GroupInfoBox::resizeEvent(QResizeEvent *e) {
@ -465,7 +458,7 @@ void SetupChannelBox::setInnerFocus() {
if (_link->isHidden()) {
setFocus();
} else {
_link->setFocus();
_link->setFocusFast();
}
}
@ -517,16 +510,6 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
p.setFont(_linkOver ? st::boxTextFont->underline() : st::boxTextFont);
p.setPen(st::defaultLinkButton.color);
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 {
if (!_errorText.isEmpty()) {
@ -559,9 +542,10 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
if (_linkOver) {
Application::clipboard()->setText(_channel->inviteLink());
_goodTextLink = lang(lng_create_channel_link_copied);
_a_goodOpacity.finish();
_a_goodOpacity.start([this] { update(); }, 1., 0., st::newGroupLinkFadeDuration);
Ui::Toast::Config toast;
toast.text = lang(lng_create_channel_link_copied);
Ui::Toast::Show(App::wnd(), toast);
}
}
@ -669,6 +653,7 @@ void SetupChannelBox::onPrivacyChange() {
return;
}
_link->show();
_link->setDisplayFocused(true);
_link->setFocus();
} else {
_link->hide();
@ -812,12 +797,10 @@ void EditNameTitleBox::prepare() {
connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
_last->setVisible(!_peer->isChat());
(_invertOrder ? _last : _first)->setDisplayFocused(true);
}
void EditNameTitleBox::setInnerFocus() {
(_invertOrder ? _last : _first)->setFocus();
(_invertOrder ? _last : _first)->setFocusFast();
}
void EditNameTitleBox::onSubmit() {
@ -967,13 +950,11 @@ void EditChannelBox::prepare() {
_publicLink->setVisible(_channel->canEditUsername());
_sign->setVisible(!_channel->isMegagroup());
_title->setDisplayFocused(true);
updateMaxHeight();
}
void EditChannelBox::setInnerFocus() {
_title->setFocus();
_title->setFocusFast();
}
void EditChannelBox::keyPressEvent(QKeyEvent *e) {
@ -1207,7 +1188,7 @@ void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
Painter p(this);
p.translate(0, _rowsTop);
for_const (auto &row, _rows) {
paintChat(p, row, (row.peer == _selected), (row.peer == _pressed));
paintChat(p, row, (row.peer == _selected));
p.translate(0, _rowHeight);
}
}
@ -1218,7 +1199,7 @@ void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) {
_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;
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());
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.setPen(st::contactsStatusFg);

View file

@ -98,6 +98,9 @@ private slots:
void onNext();
void onNameSubmit();
void onDescriptionResized();
void onClose() {
closeBox();
}
private:
void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update);
@ -184,9 +187,6 @@ private:
mtpRequestId _checkRequestId = 0;
QString _sentUsername, _checkUsername, _errorText, _goodText;
QString _goodTextLink;
Animation _a_goodOpacity;
QTimer _checkTimer;
};
@ -245,6 +245,9 @@ private slots:
void onSave();
void onDescriptionResized();
void onPublicLink();
void onClose() {
closeBox();
}
private:
void updateMaxHeight();
@ -294,7 +297,7 @@ private:
PeerData *peer;
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);
bool getPublicFail(const RPCError &error);

View file

@ -65,6 +65,13 @@ BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
}
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);
}

View file

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

View file

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

View file

@ -63,6 +63,7 @@ private:
struct InformBoxTag {
};
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;
void confirmed();
@ -92,10 +93,8 @@ private:
class InformBox : public ConfirmBox {
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, const QString &doneText, base::lambda_copy<void()> &&closedCallback = base::lambda_copy<void()>()) : ConfirmBox(ConfirmBox::InformBoxTag(), text, doneText, 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()>());
};

View file

@ -55,7 +55,6 @@ void ConfirmPhoneBox::checkPhoneAndHash() {
if (_sendCodeRequestId) {
return;
}
MTPaccount_SendConfirmPhoneCode::Flags flags = 0;
_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() {
_code->setFocus();
_code->setFocusFast();
}
ConfirmPhoneBox::~ConfirmPhoneBox() {

View file

@ -80,8 +80,10 @@ void ConnectionBox::updateControlsVisibility() {
}
void ConnectionBox::setInnerFocus() {
if (!_hostInput->isHidden()) {
_hostInput->setFocus();
if (_hostInput->isHidden()) {
setFocus();
} else {
_hostInput->setFocusFast();
}
}
@ -120,9 +122,12 @@ void ConnectionBox::updateControlsPosition() {
void ConnectionBox::onChange() {
updateControlsVisibility();
if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) {
_hostInput->setFocus();
if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() && !_passwordInput->hasFocus()) {
_hostInput->setFocusFast();
}
if (_httpProxyRadio->checked() && !_portInput->getLastText().toInt()) {
_portInput->setText(qsl("80"));
_portInput->finishAnimations();
}
}
update();
@ -217,7 +222,7 @@ void AutoDownloadBox::prepare() {
addButton(lang(lng_connection_save), [this] { onSave(); });
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) {
@ -235,13 +240,14 @@ void AutoDownloadBox::paintEvent(QPaintEvent *e) {
void AutoDownloadBox::resizeEvent(QResizeEvent *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);
_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);
_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);
_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 "boxes/photocropbox.h"
#include "boxes/confirmbox.h"
#include "window/window_theme.h"
#include "observer_peer.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(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*)));
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() {
@ -894,17 +921,18 @@ ContactsBox::Inner::ContactData *ContactsBox::Inner::contactData(Dialogs::Row *r
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) {
auto user = peer->asUser();
if (_chat && _membersFilter == MembersFilter::Admins) {
if (_allAdmins->checked() || peer->id == peerFromUser(_chat->creator) || _saving) {
selected = false;
}
} else {
if (data->disabledChecked || selectedCount() >= Global::MegagroupSizeMax()) {
selected = false;
}
if (isRowDisabled(peer, data)) {
selected = false;
}
auto paintDisabledCheck = data->disabledChecked;
@ -1229,15 +1257,15 @@ void ContactsBox::Inner::mousePressEvent(QMouseEvent *e) {
setPressed(_selected);
setFilteredPressed(_filteredSelected);
setSearchedPressed(_searchedSelected);
if (_pressed) {
addRipple(contactData(_selected));
if (_selected) {
addRipple(_selected->history()->peer, contactData(_selected));
} else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) {
addRipple(contactData(_filtered[_filteredSelected]));
addRipple(_filtered[_filteredSelected]->history()->peer, contactData(_filtered[_filteredSelected]));
} else if (_searchedSelected >= 0) {
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()) {
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();
if (!data->ripple) {
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) {
t_assert(usingMultiSelect());
if (_chat && _membersFilter == MembersFilter::Admins && _allAdmins->checked()) {
if (isRowDisabled(peer, data)) {
} else if (data->checkbox->checked()) {
changePeerCheckState(data, peer, false);
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {

View file

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

View file

@ -130,20 +130,9 @@ MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter fi
, _channel(channel)
, _filter(filter)
, _kickText(lang(lng_profile_kick))
, _time(0)
, _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())
, _about(_aboutWidth)
, _aboutHeight(0) {
, _about(_aboutWidth) {
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&)));
@ -167,6 +156,7 @@ void MembersBox::Inner::paintEvent(QPaintEvent *e) {
_time = unixtime();
p.fillRect(r, st::contactsBg);
auto ms = getms();
auto yFrom = r.y() - st::membersMarginTop;
auto yTo = r.y() + r.height() - 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());
p.translate(0, from * _rowHeight);
for (; from < to; ++from) {
bool sel = (from == _sel);
bool kickSel = (from == _kickSel && (_kickDown < 0 || from == _kickDown));
bool kickDown = kickSel && (from == _kickDown);
paintDialog(p, _rows[from], data(from), sel, kickSel, kickDown);
auto selected = (_pressed >= 0) ? (from == _pressed) : (from == _selected);
auto kickSelected = (_pressed >= 0) ? (from == _kickPressed && from == _kickSelected) : (from == _kickSelected);
paintDialog(p, ms, _rows[from], data(from), selected, kickSelected);
p.translate(0, _rowHeight);
}
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) {
_mouseSel = false;
_mouseSelection = false;
setMouseTracking(false);
if (_sel >= 0) {
if (_selected >= 0) {
clearSel();
}
}
void MembersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
_mouseSel = true;
_mouseSelection = true;
_lastMousePos = e->globalPos();
updateSel();
updateSelection();
}
void MembersBox::Inner::mousePressEvent(QMouseEvent *e) {
_mouseSel = true;
_mouseSelection = true;
_lastMousePos = e->globalPos();
updateSel();
if (e->button() == Qt::LeftButton && _kickSel < 0) {
chooseParticipant();
updateSelection();
setPressed(_selected);
_kickPressed = _kickSelected;
if (_selected >= 0 && _selected < _datas.size() && _kickSelected < 0) {
addRipple(_datas[_selected]);
}
_kickDown = _kickSel;
update();
}
void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
_mouseSel = true;
_lastMousePos = e->globalPos();
updateSel();
if (_kickDown >= 0 && _kickDown == _kickSel && !_kickRequestId) {
_kickConfirm = _rows.at(_kickSel);
if (_kickBox) _kickBox->deleteLater();
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);
_kickBox = Ui::show(Box<ConfirmBox>(text, base::lambda_guarded(this, [this] {
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));
auto pressed = _pressed;
auto kickPressed = _kickPressed;
setPressed(-1);
if (e->button() == Qt::LeftButton) {
if (pressed == _selected && kickPressed == _kickSelected) {
if (kickPressed >= 0) {
if (!_kickRequestId) {
_kickConfirm = _rows.at(_kickSelected);
if (_kickBox) _kickBox->deleteLater();
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);
_kickBox = Ui::show(Box<ConfirmBox>(text, base::lambda_guarded(this, [this] {
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();
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());
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());
if (data->canKick) {
p.setFont((kickSel ? st::linkOverFont : st::linkFont)->f);
p.setPen(kickDown ? st::defaultLinkButton.downColor : st::defaultLinkButton.color);
p.setFont(kickSelected ? st::linkOverFont : st::linkFont);
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.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);
}
void MembersBox::Inner::selectSkip(int32 dir) {
_time = unixtime();
_mouseSel = false;
_mouseSelection = false;
int cur = -1;
if (_sel >= 0) {
cur = _sel;
if (_selected >= 0) {
cur = _selected;
}
cur += dir;
if (cur <= 0) {
_sel = _rows.isEmpty() ? -1 : 0;
_selected = _rows.isEmpty() ? -1 : 0;
} else if (cur >= _rows.size()) {
_sel = -1;
_selected = -1;
} else {
_sel = cur;
_selected = cur;
}
if (dir > 0) {
if (_sel < 0 || _sel >= _rows.size()) {
_sel = -1;
if (_selected < 0 || _selected >= _rows.size()) {
_selected = -1;
}
} else {
if (!_rows.isEmpty()) {
if (_sel < 0) _sel = _rows.size() - 1;
if (_selected < 0) _selected = _rows.size() - 1;
}
}
if (_sel >= 0) {
emit mustScrollTo(_sel * _rowHeight, (_sel + 1) * _rowHeight);
if (_selected >= 0) {
emit mustScrollTo(st::membersMarginTop + _selected * _rowHeight, st::membersMarginTop + (_selected + 1) * _rowHeight);
}
update();
@ -306,6 +333,10 @@ void MembersBox::Inner::selectSkipPage(int32 h, int32 dir) {
selectSkip(points * dir);
}
MembersBox::Inner::MemberData::MemberData() = default;
MembersBox::Inner::MemberData::~MemberData() = default;
void MembersBox::Inner::loadProfilePhotos() {
if (_visibleTop >= _visibleBottom) return;
@ -331,8 +362,8 @@ void MembersBox::Inner::loadProfilePhotos() {
}
void MembersBox::Inner::chooseParticipant() {
if (_sel < 0 || _sel >= _rows.size()) return;
if (PeerData *peer = _rows[_sel]) {
if (_selected < 0 || _selected >= _rows.size()) return;
if (auto peer = _rows[_selected]) {
Ui::hideLayer();
Ui::showPeerProfile(peer);
}
@ -379,9 +410,9 @@ void MembersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
void MembersBox::Inner::clearSel() {
updateSelectedRow();
_sel = _kickSel = _kickDown = -1;
_selected = _kickSelected = -1;
_lastMousePos = QCursor::pos();
updateSel();
updateSelection();
}
MembersBox::Inner::MemberData *MembersBox::Inner::data(int32 index) {
@ -419,23 +450,23 @@ MembersBox::Inner::~Inner() {
clear();
}
void MembersBox::Inner::updateSel() {
if (!_mouseSel) return;
void MembersBox::Inner::updateSelection() {
if (!_mouseSelection) return;
QPoint p(mapFromGlobal(_lastMousePos));
p.setY(p.y() - st::membersMarginTop);
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
int32 newSel = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
int32 newKickSel = newSel;
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))) {
newKickSel = -1;
auto selected = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
auto kickSelected = selected;
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))) {
kickSelected = -1;
}
if (newSel != _sel || newKickSel != _kickSel) {
if (_selected != selected || _kickSelected != kickSelected) {
updateSelectedRow();
_sel = newSel;
_kickSel = newKickSel;
_selected = selected;
_kickSelected = kickSelected;
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();
}
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() {
if (_sel >= 0) {
update(0, st::membersMarginTop + _sel * _rowHeight, width(), _rowHeight);
auto rowTop = getSelectedRowTop();
if (rowTop >= 0) {
updateRowWithTop(rowTop);
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -181,12 +181,12 @@ void SendFilesBox::onCaptionResized() {
}
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();
}
void SendFilesBox::updateBoxSize() {
auto newHeight = 0;
auto newHeight = _titleText.isEmpty() ? 0 : st::boxTitleHeight;
if (!_preview.isNull()) {
newHeight += st::boxPhotoPadding.top() + _previewHeight;
} else if (!_fileThumb.isNull()) {
@ -319,7 +319,7 @@ void SendFilesBox::setInnerFocus() {
if (!_caption || _caption->isHidden()) {
setFocus();
} else {
_caption->setFocus();
_caption->setFocusFast();
}
}
@ -609,7 +609,7 @@ void EditCaptionBox::resizeEvent(QResizeEvent *e) {
}
void EditCaptionBox::setInnerFocus() {
_field->setFocus();
_field->setFocusFast();
}
void EditCaptionBox::onSave(bool ctrlShiftEnter) {

View file

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

View file

@ -304,7 +304,7 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
}
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 (_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()] {
@ -313,7 +313,7 @@ void SessionsBox::Inner::onTerminate() {
_terminateBox = nullptr;
}
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()) {
i.value()->clearState();
i.value()->hide();
@ -330,7 +330,7 @@ void SessionsBox::Inner::onTerminateAll() {
_terminateBox->closeBox();
_terminateBox = nullptr;
}
MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
// MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
emit terminateAll();
})), KeepOtherLayers);
}

View file

@ -37,6 +37,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_media_types.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h"
#include "window/window_theme.h"
#include "boxes/contactsbox.h"
ShareBox::ShareBox(QWidget*, CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback)
@ -294,6 +295,20 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac
notifyPeerUpdated(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) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -40,7 +40,11 @@ QString tryConvertUrlToLocal(QString url) {
using namespace qthelp;
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);
if (auto joinChatMatch = regex_match(qsl("^joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), query, matchOptions)) {
return qsl("tg://join?invite=") + url_encode(joinChatMatch->captured(1));
@ -103,13 +107,15 @@ TextWithEntities UrlClickHandler::getExpandedLinkTextWithEntities(ExpandLinksMod
return result;
}
void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const {
auto urlText = tryConvertUrlToLocal(url());
void HiddenUrlClickHandler::doOpen(QString url) {
auto urlText = tryConvertUrlToLocal(url);
if (urlText.startsWith(qstr("tg://"))) {
App::openLocalUrl(urlText);
} 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();
UrlClickHandler::doOpen(urlText);
}));

View file

@ -115,7 +115,13 @@ class HiddenUrlClickHandler : public UrlClickHandler {
public:
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;
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 &operator=(QRegularExpressionMatch &&match) {
data_ = std_::move(match);
return *this;
}
RegularExpressionMatch &operator=(RegularExpressionMatch &&other) {
data_ = std_::move(other.data_);
return *this;
}
QRegularExpressionMatch *operator->() {
return &data_;
}

View file

@ -43,7 +43,10 @@ QMap<QString, QString> url_parse_params(const QString &params, UrlParamNameTrans
paramName = param.mid(0, separatorPosition);
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;

View file

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

View file

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

View file

@ -94,7 +94,17 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
case ButtonType::Url: {
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;
case ButtonType::RequestLocation: {
@ -539,9 +549,13 @@ void start() {
}
}
bool started() {
return (SandboxData != nullptr);
}
void finish() {
delete SandboxData;
SandboxData = 0;
SandboxData = nullptr;
}
uint64 UserTag() {

View file

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

View file

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

View file

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

View file

@ -34,11 +34,13 @@ public:
virtual void showFinished() {
}
void setInnerFocus();
void closing() {
bool setClosing() {
if (!_closing) {
_closing = true;
closeHook();
return true;
}
return false;
}
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) {
if (content.isEmpty()) {
if (_themeKey) {
clearKey(_themeKey);
_themeKey = 0;
writeSettings();
}
return;
}
if (!_themeKey) {
_themeKey = genKey();
writeSettings();
@ -3743,14 +3751,20 @@ void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const
file.writeEncrypted(data, _settingsKey);
}
void clearTheme() {
writeTheme(QString(), QString(), QByteArray(), Window::Theme::Cached());
}
void readTheme() {
if (_themeKey && !readThemeUsingKey(_themeKey)) {
clearKey(_themeKey);
_themeKey = 0;
writeSettings();
clearTheme();
}
}
bool hasTheme() {
return (_themeKey != 0);
}
uint32 _peerSize(PeerData *peer) {
uint32 result = sizeof(quint64) + sizeof(quint64) + Serialize::storageImageLocationSize();
if (peer->isUser()) {

View file

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

View file

@ -1975,33 +1975,34 @@ void MainWidget::scheduleViewIncrement(HistoryItem *item) {
j.value().insert(item->id, true);
}
void MainWidget::fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QString &text, base::lambda<void()> &&handler)> &&callback) {
auto isPinned = false;
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;
void MainWidget::fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QString &text, base::lambda<void()> &&handler)> &&callback, bool pinToggle) {
if (pinToggle) {
auto isPinned = false;
if (auto history = App::historyLoaded(peer)) {
isPinned = history->isPinnedDialog();
}
MTP::send(MTPmessages_ToggleDialogPin(MTP_flags(flags), peer->input));
if (isPinned) {
if (auto main = App::main()) {
main->dialogsToUp();
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;
}
}
});
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));
MTP::send(MTPmessages_ToggleDialogPin(MTP_flags(flags), peer->input));
if (isPinned) {
if (auto main = App::main()) {
main->dialogsToUp();
}
}
});
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] {
Ui::showPeerProfile(peer);
});

View file

@ -360,7 +360,7 @@ public:
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 onSelfParticipantUpdated(ChannelData *channel);

View file

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

View file

@ -149,6 +149,10 @@ public:
void setActive(bool active);
void setPressed(bool pressed);
void invalidateCache() {
_check.invalidateCache();
}
private:
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)
, _data(video)
, _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 {
bool loaded = _data->loaded();

View file

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

View file

@ -85,6 +85,14 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
_searchTimer.setSingleShot(true);
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) {
_search->show();
} 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) {
if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) {
QTouchEvent *ev = static_cast<QTouchEvent*>(e);

View file

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

View file

@ -482,11 +482,17 @@ void psRegisterCustomScheme() {
QFile f(file);
if (f.open(QIODevice::WriteOnly)) {
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)) {
DEBUG_LOG(("App Info: Icon copied to 'tdata'"));
}
}
QTextStream s(&f);

View file

@ -42,6 +42,26 @@ BackgroundRow::BackgroundRow(QWidget *parent) : TWidget(parent)
connect(_chooseFromGallery, SIGNAL(clicked()), this, SIGNAL(chooseFromGallery()));
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) {
@ -83,13 +103,19 @@ void BackgroundRow::paintEvent(QPaintEvent *e) {
}
int BackgroundRow::resizeGetHeight(int newWidth) {
int linkLeft = st::settingsBackgroundSize + st::settingsSmallSkip;
int linkWidth = newWidth - linkLeft;
auto linkTop = 0;
auto linkLeft = st::settingsBackgroundSize + st::settingsSmallSkip;
auto linkWidth = newWidth - linkLeft;
_chooseFromGallery->resizeToWidth(qMin(linkWidth, _chooseFromGallery->naturalWidth()));
_chooseFromFile->resizeToWidth(qMin(linkWidth, _chooseFromFile->naturalWidth()));
_chooseFromGallery->moveToLeft(linkLeft, 0, newWidth);
_chooseFromFile->moveToLeft(linkLeft, _chooseFromGallery->height() + st::settingsSmallSkip, newWidth);
if (_useDefault) {
_useDefault->resizeToWidth(qMin(linkWidth, _useDefault->naturalWidth()));
_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;
}
@ -194,6 +220,7 @@ void BackgroundWidget::createControls() {
addChildRow(_background, margin);
connect(_background, SIGNAL(chooseFromGallery()), this, SLOT(onChooseFromGallery()));
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(_adaptive, margin, slidedPadding, lang(lng_settings_adaptive_wide), SLOT(onAdaptive()), Global::AdaptiveForWide());
@ -213,13 +240,16 @@ void BackgroundWidget::needBackgroundUpdate(bool tile) {
void BackgroundWidget::onChooseFromFile() {
auto imgExtensions = cImgExtensions();
auto filters = QStringList(qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(")"));
filters.push_back(qsl("Theme files (*.tdesktop-theme)"));
auto filters = QStringList(qsl("Theme files (*.tdesktop-theme *") + imgExtensions.join(qsl(" *")) + qsl(")"));
filters.push_back(filedialogAllFilesFilter());
_chooseFromFileQueryId = FileDialog::queryReadFile(lang(lng_choose_image), filters.join(qsl(";;")));
}
void BackgroundWidget::onUseDefault() {
Window::Theme::ApplyDefault();
}
void BackgroundWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) {
if (_chooseFromFileQueryId != update.queryId) {
return;

View file

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

View file

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

View file

@ -74,7 +74,7 @@ QPixmap myGrab(TWidget *target, QRect rect, QColor bg) {
}
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();
return std_::move(result);

View file

@ -41,7 +41,7 @@ int LinkButton::naturalWidth() const {
void LinkButton::paintEvent(QPaintEvent *e) {
Painter p(this);
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.setPen(pen);
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);
}
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 borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 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);
}
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 borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 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);
}
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 borderOpacity = _a_borderOpacity.current(ms, _borderVisible ? 1. : 0.);
if (_st.borderActive && (borderOpacity > 0.)) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -539,6 +539,16 @@ void ChatBackground::setTestingTheme(Instance &&theme) {
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() {
if (_id == internal::kTestingThemeBackground) {
_id = kThemeBackground;
@ -613,13 +623,24 @@ bool Apply(const QString &filepath) {
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() {
auto filepath = instance ? instance->applying.path : QString();
if (filepath.isEmpty()) {
if (!instance) {
return;
}
auto pathRelative = QDir().relativeFilePath(filepath);
auto pathAbsolute = QFileInfo(filepath).absoluteFilePath();
auto filepath = instance->applying.path;
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);
instance->applying = Data::Applying();
Background()->keepApplied();

View file

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

View file

@ -45,9 +45,15 @@ set "DeployPath=%ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStrFull%"
set "SignPath=%HomePath%\..\..\TelegramPrivate\Sign.bat"
set "BinaryName=Telegram"
set "DropboxSymbolsPath=X:\Telegram\symbols"
set "FinalReleasePath=Y:\TBuild\tother\tsetup"
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
)
@ -176,7 +182,6 @@ echo .
echo Version %AppVersionStrFull% is ready for deploy!
echo .
set "FinalReleasePath=Y:\TBuild\tother\tsetup"
set "FinalDeployPath=%FinalReleasePath%\%AppVersionStrMajor%\%AppVersionStrFull%"
if not exist "%DeployPath%\%UpdateFile%" goto error

View file

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