mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 23:27:09 +02:00
Closed beta 10020002: Use default color theme link in Settings.
This commit is contained in:
parent
0480e02b23
commit
177078b0af
70 changed files with 788 additions and 419 deletions
|
@ -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";
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()>());
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ private slots:
|
|||
void onReport();
|
||||
void onChange();
|
||||
void onDescriptionResized();
|
||||
void onClose() {
|
||||
closeBox();
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 &©Callback, 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) {
|
||||
|
|
|
@ -149,6 +149,7 @@ protected:
|
|||
private:
|
||||
// Observed notifications.
|
||||
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
||||
void invalidateCache();
|
||||
|
||||
int displayedChatsCount() const;
|
||||
|
||||
|
|
|
@ -412,6 +412,8 @@ void StickersBox::switchTab() {
|
|||
auto slideLeft = wasIndex > nowIndex;
|
||||
_slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration);
|
||||
setInnerVisible(false);
|
||||
|
||||
setFocus();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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);
|
||||
}));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,10 @@ QMap<QString, QString> url_parse_params(const QString ¶ms, 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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -226,6 +226,7 @@ bool CheckBetaVersionDir();
|
|||
void WorkingDirReady();
|
||||
|
||||
void start();
|
||||
bool started();
|
||||
void finish();
|
||||
|
||||
uint64 UserTag();
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -115,7 +115,6 @@ mediaviewFileIconSize: 80px;
|
|||
mediaviewFileLink: LinkButton(defaultLinkButton) {
|
||||
color: #4595d3;
|
||||
overColor: #4595d3;
|
||||
downColor: #4595d3;
|
||||
}
|
||||
|
||||
mediaviewTransparentBg: #ffffff;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -128,6 +128,7 @@ public slots:
|
|||
|
||||
private:
|
||||
void saveDocumentToFile(DocumentData *document);
|
||||
void invalidateCache();
|
||||
|
||||
void itemRemoved(HistoryItem *item);
|
||||
MsgId complexMsgId(const HistoryItem *item) const;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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.)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -460,7 +460,7 @@ bool MultiSelect::Inner::setInnerFocus() {
|
|||
if (_active >= 0) {
|
||||
setFocus();
|
||||
} else if (!_field->hasFocus()) {
|
||||
_field->setFocus();
|
||||
_field->setFocusFast();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -3,4 +3,4 @@ AppVersionStrMajor 0.10
|
|||
AppVersionStrSmall 0.10.20
|
||||
AppVersionStr 0.10.20
|
||||
AlphaChannel 0
|
||||
BetaVersion 10020001
|
||||
BetaVersion 10020002
|
||||
|
|
Loading…
Add table
Reference in a new issue