Boxes redesigned. Common groups moved to Shared Media.

Also transparent images sending fixed.
This commit is contained in:
John Preston 2016-12-13 20:07:56 +03:00
parent 85b434bee4
commit 2436ad74bd
231 changed files with 4233 additions and 4235 deletions

View file

@ -36,11 +36,6 @@ emojiPadding: 1px;
lineWidth: 1px; lineWidth: 1px;
defaultDropdownDuration: 150;
defaultDropdownPadding: margins(10px, 10px, 10px, 10px);
defaultDropdownShadow: icon {{ "dropdown_shadow", windowShadowFg }};
defaultDropdownShadowShift: 1px;
defaultTooltip: Tooltip { defaultTooltip: Tooltip {
textBg: #eef2f5; textBg: #eef2f5;
textFg: #5d6c80; textFg: #5d6c80;
@ -309,8 +304,6 @@ simpleCloseIcon: icon {{ "simple_close", #c7c7c7 }};
simpleCloseIconOver: icon {{ "simple_close", #a3a3a3 }}; simpleCloseIconOver: icon {{ "simple_close", #a3a3a3 }};
dialogsForwardCancelIcon: icon {{ "simple_close", dialogsForwardFg }}; dialogsForwardCancelIcon: icon {{ "simple_close", dialogsForwardFg }};
membersPadding: margins(0px, 10px, 0px, 10px);
forwardMargins: margins(30px, 10px, 30px, 10px); forwardMargins: margins(30px, 10px, 30px, 10px);
forwardFont: font(16px); forwardFont: font(16px);
forwardBg: #0000004c; forwardBg: #0000004c;
@ -450,8 +443,8 @@ historyReplyCancelIcon: icon {{ "box_button_close", historyReplyCancelFg }};
historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }}; historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }};
boxSearchCancelIcon: icon {{ "box_button_close", boxSearchCancelIconFg }}; boxSearchCancelIcon: icon {{ "box_button_close", boxSearchCancelIconFg }};
boxSearchCancelIconOver: icon {{ "box_button_close", boxSearchCancelIconFgOver }}; boxSearchCancelIconOver: icon {{ "box_button_close", boxSearchCancelIconFgOver }};
boxBlockTitleCloseIcon: icon {{ "box_button_close", boxBlockTitleCloseFg }}; boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }};
boxBlockTitleCloseIconOver: icon {{ "box_button_close", boxBlockTitleCloseFgOver }}; boxTitleCloseIconOver: icon {{ "box_button_close", boxTitleCloseFgOver }};
notifyFadeRight: icon {{ "fade_horizontal", notificationBg }}; notifyFadeRight: icon {{ "fade_horizontal", notificationBg }};

View file

@ -86,8 +86,8 @@ trayCounterFgMacInvert: #ffffff01;
// layers // layers
layerBg: #0000007f; layerBg: #0000007f;
cancelIconFg: #a2a2a2; cancelIconFg: menuIconFg;
cancelIconFgOver: #808080; cancelIconFgOver: menuIconFgOver;
// boxes // boxes
boxBg: windowBg; boxBg: windowBg;
@ -99,11 +99,9 @@ boxSearchBg: boxBg;
boxSearchCancelIconFg: cancelIconFg; boxSearchCancelIconFg: cancelIconFg;
boxSearchCancelIconFgOver: cancelIconFgOver; boxSearchCancelIconFgOver: cancelIconFgOver;
boxBlockTitleBg: boxBg; boxTitleAdditionalFg: #808080;
boxBlockTitleFg: boxTitleFg; boxTitleCloseFg: cancelIconFg;
boxBlockTitleAdditionalFg: #808080; boxTitleCloseFgOver: cancelIconFgOver;
boxBlockTitleCloseFg: cancelIconFg;
boxBlockTitleCloseFgOver: cancelIconFgOver;
membersAboutLimitFg: windowSubTextFgOver; membersAboutLimitFg: windowSubTextFgOver;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

View file

@ -296,7 +296,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_backgrounds_header" = "Choose your new chat background"; "lng_backgrounds_header" = "Choose your new chat background";
"lng_theme_sure_keep" = "Keep this color theme?"; "lng_theme_sure_keep" = "Keep this color theme?";
"lng_theme_reverting" = "Reverting to previous color theme in {count:_not_used_|# second|# seconds}."; "lng_theme_reverting" = "Reverting to the old color theme in {count:_not_used_|# second|# seconds}.";
"lng_theme_keep_changes" = "Keep changes"; "lng_theme_keep_changes" = "Keep changes";
"lng_theme_revert" = "Revert"; "lng_theme_revert" = "Revert";

View file

@ -74,8 +74,8 @@ trayCounterFg: #ffffff;
trayCounterBgMacInvert: #ffffff; trayCounterBgMacInvert: #ffffff;
trayCounterFgMacInvert: #ffffff01; trayCounterFgMacInvert: #ffffff01;
layerBg: #0000007f; layerBg: #0000007f;
cancelIconFg: #a2a2a2; cancelIconFg: menuIconFg;
cancelIconFgOver: #808080; cancelIconFgOver: menuIconFgOver;
boxBg: windowBg; boxBg: windowBg;
boxTextFg: windowFg; boxTextFg: windowFg;
boxTextFgGood: #4ab44a; boxTextFgGood: #4ab44a;
@ -84,11 +84,9 @@ boxTitleFg: #404040;
boxSearchBg: boxBg; boxSearchBg: boxBg;
boxSearchCancelIconFg: cancelIconFg; boxSearchCancelIconFg: cancelIconFg;
boxSearchCancelIconFgOver: cancelIconFgOver; boxSearchCancelIconFgOver: cancelIconFgOver;
boxBlockTitleBg: boxBg; boxTitleAdditionalFg: #808080;
boxBlockTitleFg: boxTitleFg; boxTitleCloseFg: cancelIconFg;
boxBlockTitleAdditionalFg: #808080; boxTitleCloseFgOver: cancelIconFgOver;
boxBlockTitleCloseFg: cancelIconFg;
boxBlockTitleCloseFgOver: cancelIconFgOver;
membersAboutLimitFg: windowSubTextFgOver; membersAboutLimitFg: windowSubTextFgOver;
contactsBg: windowBg; contactsBg: windowBg;
contactsBgOver: windowBgOver; contactsBgOver: windowBgOver;

View file

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

View file

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

View file

@ -830,7 +830,7 @@ bool ApiWrap::channelAmInFail(ChannelData *channel, const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
if (error.type() == qstr("CHANNELS_TOO_MUCH")) { if (error.type() == qstr("CHANNELS_TOO_MUCH")) {
Ui::showLayer(new InformBox(lang(lng_join_channel_error))); Ui::show(Box<InformBox>(lang(lng_join_channel_error)));
} }
_channelAmInRequests.remove(channel); _channelAmInRequests.remove(channel);
return true; return true;

View file

@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_mediaview.h" #include "styles/style_mediaview.h"
#include "styles/style_stickers.h" #include "styles/style_stickers.h"
#include "styles/style_history.h" #include "styles/style_history.h"
#include "styles/style_boxes.h"
#include "lang.h" #include "lang.h"
#include "data/data_abstract_structure.h" #include "data/data_abstract_structure.h"
#include "history/history_service_layout.h" #include "history/history_service_layout.h"
@ -2243,6 +2244,7 @@ namespace {
::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor()); ::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor());
} }
prepareCorners(MenuCorners, st::buttonRadius, st::menuBg); prepareCorners(MenuCorners, st::buttonRadius, st::menuBg);
prepareCorners(BoxCorners, st::boxRadius, st::boxBg);
prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBg); prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBg);
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg); prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg); prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceSelectBg);

View file

@ -32,32 +32,35 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "platform/platform_file_dialog.h" #include "platform/platform_file_dialog.h"
AboutBox::AboutBox() : AbstractBox(st::aboutWidth, qsl("Telegram Desktop")) AboutBox::AboutBox(QWidget *parent)
, _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? " alpha" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink) : _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? " alpha" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink)
, _text1(this, lang(lng_about_text_1), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle) , _text1(this, lang(lng_about_text_1), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle)
, _text2(this, lang(lng_about_text_2), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle) , _text2(this, lang(lng_about_text_2), Ui::FlatLabel::InitType::Rich, st::aboutLabel, st::aboutTextStyle)
, _text3(this,st::aboutLabel, st::aboutTextStyle) , _text3(this, st::aboutLabel, st::aboutTextStyle) {
, _done(this, lang(lng_close), st::defaultBoxButton) { }
void AboutBox::prepare() {
setTitle(qsl("Telegram Desktop"));
addButton(lang(lng_close), [this] { closeBox(); });
_text3->setRichText(lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]"))); _text3->setRichText(lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]")));
setMaxHeight(titleHeight() + st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() + st::aboutSkip + _text3->height() + st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom()); _version->setClickedCallback([this] { showVersionHistory(); });
connect(_version, SIGNAL(clicked()), this, SLOT(onVersion())); setDimensions(st::aboutWidth, st::aboutTextTop + _text1->height() + st::aboutSkip + _text2->height() + st::aboutSkip + _text3->height());
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
setAcceptDrops(true);
} }
void AboutBox::resizeEvent(QResizeEvent *e) { void AboutBox::resizeEvent(QResizeEvent *e) {
_version->moveToLeft(st::boxPadding.left(), titleHeight() + st::aboutVersionTop); BoxContent::resizeEvent(e);
_text1->moveToLeft(st::boxPadding.left(), titleHeight() + st::aboutTextTop);
_version->moveToLeft(st::boxPadding.left(), st::aboutVersionTop);
_text1->moveToLeft(st::boxPadding.left(), st::aboutTextTop);
_text2->moveToLeft(st::boxPadding.left(), _text1->y() + _text1->height() + st::aboutSkip); _text2->moveToLeft(st::boxPadding.left(), _text1->y() + _text1->height() + st::aboutSkip);
_text3->moveToLeft(st::boxPadding.left(), _text2->y() + _text2->height() + st::aboutSkip); _text3->moveToLeft(st::boxPadding.left(), _text2->y() + _text2->height() + st::aboutSkip);
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
AbstractBox::resizeEvent(e);
} }
void AboutBox::onVersion() { void AboutBox::showVersionHistory() {
if (cRealBetaVersion()) { if (cRealBetaVersion()) {
auto url = qsl("https://tdesktop.com/"); auto url = qsl("https://tdesktop.com/");
switch (cPlatform()) { switch (cPlatform()) {
@ -71,7 +74,7 @@ void AboutBox::onVersion() {
Application::clipboard()->setText(url); Application::clipboard()->setText(url);
Ui::showLayer(new InformBox("The link to the current private beta version of Telegram Desktop was copied to the clipboard.")); Ui::show(Box<InformBox>("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
} else { } else {
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog")); QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog"));
} }
@ -79,9 +82,9 @@ void AboutBox::onVersion() {
void AboutBox::keyPressEvent(QKeyEvent *e) { void AboutBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onClose(); closeBox();
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }

View file

@ -23,32 +23,29 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h" #include "boxes/abstractbox.h"
namespace Ui { namespace Ui {
class RoundButton;
class LinkButton; class LinkButton;
class FlatLabel; class FlatLabel;
} // namespace Ui } // namespace Ui
class AboutBox : public AbstractBox { class AboutBox : public BoxContent {
Q_OBJECT
public: public:
AboutBox(); AboutBox(QWidget*);
public slots:
void onVersion();
protected: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void dragEnterEvent(QDragEnterEvent *e) override; void dragEnterEvent(QDragEnterEvent *e) override;
void dropEvent(QDropEvent *e) override; void dropEvent(QDropEvent *e) override;
private: private:
ChildWidget<Ui::LinkButton> _version; void showVersionHistory();
ChildWidget<Ui::FlatLabel> _text1;
ChildWidget<Ui::FlatLabel> _text2; object_ptr<Ui::LinkButton> _version;
ChildWidget<Ui::FlatLabel> _text3; object_ptr<Ui::FlatLabel> _text1;
ChildWidget<Ui::RoundButton> _done; object_ptr<Ui::FlatLabel> _text2;
object_ptr<Ui::FlatLabel> _text3;
}; };

View file

@ -24,187 +24,341 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "localstorage.h" #include "localstorage.h"
#include "lang.h" #include "lang.h"
#include "ui/effects/widget_fade_wrap.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
AbstractBox::AbstractBox(int w, const QString &title) : LayerWidget(App::wnd()->bodyWidget()) BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) {
, _title(title) {
setAttribute(Qt::WA_OpaquePaintEvent);
resize((w > 0) ? w : st::boxWideWidth, 0);
} }
void AbstractBox::setTitleText(const QString &title) { QPointer<Ui::RoundButton> BoxContent::addButton(const QString &text, base::lambda<void()> &&clickCallback) {
_title = title; return addButton(text, std_::move(clickCallback), st::defaultBoxButton);
update();
} }
void AbstractBox::setAdditionalTitle(const QString &additionalTitle) { QPointer<Ui::RoundButton> BoxContent::addLeftButton(const QString &text, base::lambda<void()> &&clickCallback) {
_additionalTitle = additionalTitle; return getDelegate()->addLeftButton(text, std_::move(clickCallback), st::defaultBoxButton);
update();
} }
void AbstractBox::keyPressEvent(QKeyEvent *e) { void BoxContent::setInner(object_ptr<TWidget> inner) {
if (e->key() == Qt::Key_Escape) { setInner(std_::move(inner), st::boxLayerScroll);
onClose(); }
void BoxContent::setInner(object_ptr<TWidget> inner, const style::ScrollArea &st) {
if (inner) {
getDelegate()->setLayerType(true);
if (!_scroll) {
_scroll.create(this, 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);
}
_scroll->setOwnedWidget(std_::move(inner));
updateScrollAreaGeometry();
} else { } else {
LayerWidget::keyPressEvent(e); getDelegate()->setLayerType(false);
_scroll.destroyDelayed();
_topShadow.destroyDelayed();
_bottomShadow.destroyDelayed();
} }
} }
void AbstractBox::resizeEvent(QResizeEvent *e) { void BoxContent::onScrollToY(int top, int bottom) {
updateBlockTitleGeometry(); if (_scroll) {
LayerWidget::resizeEvent(e); _scroll->scrollToY(top, bottom);
}
} }
void AbstractBox::updateBlockTitleGeometry() { void BoxContent::onDraggingScrollDelta(int delta) {
if (_blockClose) { _draggingScrollDelta = _scroll ? delta : 0;
_blockClose->moveToRight(0, 0); if (_draggingScrollDelta) {
if (!_draggingScrollTimer) {
_draggingScrollTimer.create(this);
_draggingScrollTimer->setSingleShot(false);
connect(_draggingScrollTimer, SIGNAL(timeout()), this, SLOT(onDraggingScrollTimer()));
}
_draggingScrollTimer->start(15);
} else {
_draggingScrollTimer.destroy();
} }
if (_blockShadow) { }
_blockShadow->setGeometry(0, st::boxBlockTitleHeight, width(), st::boxBlockTitleShadow.height());
void BoxContent::onDraggingScrollTimer() {
auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed));
_scroll->scrollToY(_scroll->scrollTop() + delta);
}
void BoxContent::onScroll() {
if (_scroll) {
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();
}
}
}
void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) {
if (_innerTopSkip != innerTopSkip) {
auto delta = innerTopSkip - _innerTopSkip;
_innerTopSkip = innerTopSkip;
if (_scroll) {
auto scrollTopWas = _scroll->scrollTop();
updateScrollAreaGeometry();
if (scrollBottomFixed) {
_scroll->scrollToY(scrollTopWas + delta);
}
if (_innerTopSkip > 0) {
_topShadow->showFast();
} else {
_topShadow->hideFast();
}
}
}
}
void BoxContent::setInnerVisible(bool scrollAreaVisible) {
if (_scroll) {
_scroll->setVisible(scrollAreaVisible);
}
}
QPixmap BoxContent::grabInnerCache() {
auto isTopShadowVisible = !_topShadow->isHidden();
auto isBottomShadowVisible = !_bottomShadow->isHidden();
if (isTopShadowVisible) _topShadow->hide();
if (isBottomShadowVisible) _bottomShadow->hide();
auto result = myGrab(this, _scroll->geometry());
if (isTopShadowVisible) _topShadow->show();
if (isBottomShadowVisible) _bottomShadow->show();
return std_::move(result);
}
void BoxContent::resizeEvent(QResizeEvent *e) {
if (_scroll) {
updateScrollAreaGeometry();
}
}
void BoxContent::updateScrollAreaGeometry() {
auto newScrollHeight = height() - _innerTopSkip;
auto changed = (_scroll->height() != newScrollHeight);
_scroll->setGeometryToLeft(0, _innerTopSkip, width(), newScrollHeight);
_topShadow->entity()->resize(width(), st::lineWidth);
_topShadow->moveToLeft(0, _innerTopSkip);
_bottomShadow->resize(width(), st::lineWidth);
_bottomShadow->moveToLeft(0, height() - st::lineWidth);
if (changed) {
onScroll();
}
}
object_ptr<TWidget> BoxContent::doTakeInnerWidget() {
return _scroll->takeWidget<TWidget>();
}
void BoxContent::paintEvent(QPaintEvent *e) {
Painter p(this);
if (testAttribute(Qt::WA_OpaquePaintEvent)) {
for_const (auto rect, e->region().rects()) {
p.fillRect(rect, st::boxBg);
}
}
}
AbstractBox::AbstractBox(object_ptr<BoxContent> content)
: _content(std_::move(content)) {
_content->setParent(this);
_content->setDelegate(this);
}
void AbstractBox::setLayerType(bool layerType) {
_layerType = layerType;
}
int AbstractBox::titleHeight() const {
return _layerType ? st::boxLayerTitleHeight : st::boxTitleHeight;
}
int AbstractBox::buttonsHeight() const {
auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding;
return padding.top() + st::defaultBoxButton.height + padding.bottom();
}
int AbstractBox::buttonsTop() const {
auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding;
return height() - padding.bottom() - st::defaultBoxButton.height;
}
void AbstractBox::paintEvent(QPaintEvent *e) {
Painter p(this);
auto clip = e->rect();
auto paintTopRounded = clip.intersects(QRect(0, 0, width(), st::boxRadius));
auto paintBottomRounded = clip.intersects(QRect(0, height() - st::boxRadius, width(), st::boxRadius));
if (paintTopRounded || paintBottomRounded) {
auto parts = qFlags(App::RectPart::None);
if (paintTopRounded) parts |= App::RectPart::TopFull;
if (paintBottomRounded) parts |= App::RectPart::BottomFull;
App::roundRect(p, rect(), st::boxBg, BoxCorners, nullptr, parts);
}
auto other = e->region().intersected(QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius));
if (!other.isEmpty()) {
for_const (auto rect, other.rects()) {
p.fillRect(rect, st::boxBg);
}
}
if (!_title.isEmpty() && clip.intersects(QRect(0, 0, width(), titleHeight()))) {
paintTitle(p, _title, _additionalTitle);
}
}
void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) {
p.setFont(st::boxTitleFont);
p.setPen(st::boxTitleFg);
if (_layerType) {
auto titleWidth = st::boxTitleFont->width(title);
p.drawTextLeft(st::boxLayerTitlePosition.x(), st::boxLayerTitlePosition.y(), width(), title, titleWidth);
if (!additional.isEmpty()) {
p.setFont(st::boxLayerTitleAdditionalFont);
p.setPen(st::boxTitleAdditionalFg);
p.drawTextLeft(st::boxLayerTitlePosition.x() + titleWidth + st::boxLayerTitleAdditionalSkip, st::boxLayerTitlePosition.y() + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), additional);
}
} else {
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), title);
} }
} }
void AbstractBox::parentResized() { void AbstractBox::parentResized() {
auto newHeight = countHeight(); auto newHeight = countRealHeight();
auto parentSize = parentWidget()->size(); auto parentSize = parentWidget()->size();
setGeometry((parentSize.width() - width()) / 2, (parentSize.height() - newHeight) / 2, width(), newHeight); setGeometry((parentSize.width() - width()) / 2, (parentSize.height() - newHeight) / 2, width(), newHeight);
update(); update();
} }
int AbstractBox::titleHeight() const { void AbstractBox::setTitle(const QString &title, const QString &additional) {
return _blockTitle ? st::boxBlockTitleHeight : st::boxTitleHeight; auto wasTitle = hasTitle();
_title = title;
_additionalTitle = additional;
update();
if (wasTitle != hasTitle()) {
updateSize();
}
} }
void AbstractBox::paintTitle(Painter &p, const QString &title, const QString &additional) { bool AbstractBox::hasTitle() const {
if (_blockTitle) { return !_title.isEmpty() || !_additionalTitle.isEmpty();
p.fillRect(0, 0, width(), titleHeight(), st::boxBlockTitleBg); }
p.setFont(st::boxBlockTitleFont); void AbstractBox::updateSize() {
p.setPen(st::boxBlockTitleFg); setDimensions(width(), _maxContentHeight);
}
auto titleWidth = st::boxBlockTitleFont->width(title); void AbstractBox::updateButtonsPositions() {
p.drawTextLeft(st::boxBlockTitlePosition.x(), st::boxBlockTitlePosition.y(), width(), title, titleWidth); if (!_buttons.isEmpty() || _leftButton) {
auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding;
if (!additional.isEmpty()) { auto right = padding.right();
p.setFont(st::boxBlockTitleAdditionalFont); auto top = buttonsTop();
p.setPen(st::boxBlockTitleAdditionalFg); if (_leftButton) {
p.drawTextLeft(st::boxBlockTitlePosition.x() + titleWidth + st::boxBlockTitleAdditionalSkip, st::boxBlockTitlePosition.y(), width(), additional); _leftButton->moveToLeft(right, top);
}
for_const (auto &button, _buttons) {
button->moveToRight(right, top);
right += button->width() + padding.left();
} }
} else {
p.setFont(st::boxTitleFont);
p.setPen(st::boxTitleFg);
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), title);
} }
} }
void AbstractBox::paintEvent(QPaintEvent *e) { void AbstractBox::clearButtons() {
Painter p(this); for (auto &button : base::take(_buttons)) {
p.fillRect(e->rect(), st::boxBg); button.destroy();
if (!_title.isEmpty()) {
paintTitle(p, _title, _additionalTitle);
} }
_leftButton.destroy();
} }
void AbstractBox::setMaxHeight(int32 maxHeight) { QPointer<Ui::RoundButton> AbstractBox::addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) {
resizeMaxHeight(width(), maxHeight); _buttons.push_back(object_ptr<Ui::RoundButton>(this, text, st));
auto result = QPointer<Ui::RoundButton>(_buttons.back());
result->setClickedCallback(std_::move(clickCallback));
result->show();
updateButtonsPositions();
return result;
} }
void AbstractBox::resizeMaxHeight(int32 newWidth, int32 maxHeight) { QPointer<Ui::RoundButton> AbstractBox::addLeftButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) {
if (width() != newWidth || _maxHeight != maxHeight) { _leftButton = object_ptr<Ui::RoundButton>(this, text, st);
QRect g(geometry()); auto result = QPointer<Ui::RoundButton>(_leftButton);
_maxHeight = maxHeight; result->setClickedCallback(std_::move(clickCallback));
resize(newWidth, countHeight()); result->show();
updateButtonsPositions();
return result;
}
void AbstractBox::setDimensions(int newWidth, int maxHeight) {
_maxContentHeight = maxHeight;
auto fullHeight = countFullHeight();
if (width() != newWidth || _fullHeight != fullHeight) {
_fullHeight = fullHeight;
if (parentWidget()) { if (parentWidget()) {
QRect r = geometry(); auto oldGeometry = geometry();
int32 parenth = parentWidget()->height(); resize(newWidth, countRealHeight());
if (r.top() + r.height() + st::boxVerticalMargin > parenth) { auto newGeometry = geometry();
int32 newTop = qMax(parenth - int(st::boxVerticalMargin) - r.height(), (parenth - r.height()) / 2); auto parentHeight = parentWidget()->height();
if (newTop != r.top()) { if (newGeometry.top() + newGeometry.height() + st::boxVerticalMargin > parentHeight) {
move(r.left(), newTop); auto newTop = qMax(parentHeight - int(st::boxVerticalMargin) - newGeometry.height(), (parentHeight - newGeometry.height()) / 2);
if (newTop != newGeometry.top()) {
move(newGeometry.left(), newTop);
} }
} }
parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.width(), st::boxShadow.height(), st::boxShadow.width(), st::boxShadow.height()))); parentWidget()->update(oldGeometry.united(geometry()).marginsAdded(st::boxRoundShadow.extend));
} else {
resize(newWidth, 0);
} }
} }
} }
int AbstractBox::countHeight() const { int AbstractBox::countRealHeight() const {
return qMin(_maxHeight, parentWidget()->height() - 2 * st::boxVerticalMargin); return qMin(_fullHeight, parentWidget()->height() - 2 * st::boxVerticalMargin);
} }
void AbstractBox::onClose() { int AbstractBox::countFullHeight() const {
if (!_closed) { return contentTop() + _maxContentHeight + buttonsHeight();
_closed = true;
closePressed();
}
emit closed(this);
} }
void AbstractBox::setBlockTitle(bool block, bool withClose, bool withShadow) { int AbstractBox::contentTop() const {
_blockTitle = block; return hasTitle() ? titleHeight() : (_noContentMargin ? 0 : st::boxTopMargin);
if (withClose) { }
_blockClose.create(this, st::boxBlockTitleClose);
_blockClose->setClickedCallback([this] { onClose(); }); void AbstractBox::resizeEvent(QResizeEvent *e) {
_blockClose->show(); updateButtonsPositions();
auto top = contentTop();
_content->resize(width(), height() - top - buttonsHeight());
_content->moveToLeft(0, top);
LayerWidget::resizeEvent(e);
}
void AbstractBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) {
closeBox();
} else { } else {
_blockClose.destroy(); LayerWidget::keyPressEvent(e);
}
if (withShadow) {
_blockShadow.create(this, st::boxBlockTitleShadow);
_blockShadow->show();
} else {
_blockShadow.destroy();
}
updateBlockTitleGeometry();
}
void AbstractBox::raiseShadow() {
if (_blockShadow) {
_blockShadow->raise();
} }
} }
ScrollableBoxShadow::ScrollableBoxShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxScrollShadowBg) {
}
ScrollableBox::ScrollableBox(const style::FlatScroll &scroll, int32 w) : AbstractBox(w)
, _scroll(this, scroll)
, _topSkip(st::boxBlockTitleHeight)
, _bottomSkip(st::boxScrollSkip) {
setBlockTitle(true);
}
void ScrollableBox::resizeEvent(QResizeEvent *e) {
updateScrollGeometry();
AbstractBox::resizeEvent(e);
}
void ScrollableBox::init(TWidget *inner, int bottomSkip, int topSkip) {
if (bottomSkip < 0) bottomSkip = st::boxScrollSkip;
if (topSkip < 0) topSkip = st::boxBlockTitleHeight;
_bottomSkip = bottomSkip;
_topSkip = topSkip;
_scroll->setOwnedWidget(inner);
updateScrollGeometry();
}
void ScrollableBox::setScrollSkips(int bottomSkip, int topSkip) {
if (bottomSkip < 0) bottomSkip = st::boxScrollSkip;
if (topSkip < 0) topSkip = st::boxBlockTitleHeight;
if (_topSkip != topSkip || _bottomSkip != bottomSkip) {
_topSkip = topSkip;
_bottomSkip = bottomSkip;
updateScrollGeometry();
}
}
void ScrollableBox::updateScrollGeometry() {
_scroll->setGeometry(0, _topSkip, width(), height() - _topSkip - _bottomSkip);
}
ItemListBox::ItemListBox(const style::FlatScroll &scroll, int32 w) : ScrollableBox(scroll, w) {
setMaxHeight(st::boxMaxListHeight);
}

View file

@ -24,88 +24,229 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/shadow.h" #include "ui/widgets/shadow.h"
namespace Ui { namespace Ui {
class RoundButton;
class IconButton; class IconButton;
class GradientShadow;
class ScrollArea; class ScrollArea;
template <typename Widget>
class WidgetFadeWrap;
} // namespace Ui } // namespace Ui
class AbstractBox : public LayerWidget, protected base::Subscriber { class BoxLayerTitleShadow : public Ui::PlainShadow {
public:
BoxLayerTitleShadow(QWidget *parent);
};
class BoxContentDelegate {
public:
virtual void setLayerType(bool layerType) = 0;
virtual void setTitle(const QString &title, const QString &additional) = 0;
virtual void clearButtons() = 0;
virtual QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) = 0;
virtual QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) = 0;
virtual void updateButtonsPositions() = 0;
virtual void setDimensions(int newWidth, int maxHeight) = 0;
virtual void setNoContentMargin(bool noContentMargin) = 0;
virtual bool isBoxShown() const = 0;
virtual void closeBox() = 0;
};
class BoxContent : public TWidget, protected base::Subscriber {
Q_OBJECT Q_OBJECT
public: public:
AbstractBox(int w = 0, const QString &title = QString()); BoxContent() {
void parentResized() override; setAttribute(Qt::WA_OpaquePaintEvent);
}
void setTitleText(const QString &title); void setDelegate(BoxContentDelegate *newDelegate) {
void setAdditionalTitle(const QString &additionalTitle); _delegate = newDelegate;
void setBlockTitle(bool block, bool withClose = true, bool withShadow = true); prepare();
}
virtual void setInnerFocus() {
setFocus();
}
virtual void closeHook() {
}
bool isBoxShown() const {
return getDelegate()->isBoxShown();
}
void closeBox() {
getDelegate()->closeBox();
}
public slots: public slots:
void onClose(); void onScrollToY(int top, int bottom = -1);
void onDraggingScrollDelta(int delta);
protected:
virtual void prepare() = 0;
void setLayerType(bool layerType) {
getDelegate()->setLayerType(layerType);
}
void setTitle(const QString &title, const QString &additional = QString()) {
getDelegate()->setTitle(title, additional);
}
void clearButtons() {
getDelegate()->clearButtons();
}
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback);
QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> &&clickCallback);
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) {
return getDelegate()->addButton(text, std_::move(clickCallback), st);
}
void updateButtonsGeometry() {
getDelegate()->updateButtonsPositions();
}
void setNoContentMargin(bool noContentMargin) {
if (_noContentMargin != noContentMargin) {
_noContentMargin = noContentMargin;
setAttribute(Qt::WA_OpaquePaintEvent, !_noContentMargin);
}
getDelegate()->setNoContentMargin(noContentMargin);
}
void setDimensions(int newWidth, int maxHeight) {
getDelegate()->setDimensions(newWidth, maxHeight);
}
void setInnerTopSkip(int topSkip, bool scrollBottomFixed = false);
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);
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);
return result;
}
template <typename Widget>
object_ptr<Widget> takeInnerWidget() {
return static_object_cast<Widget>(doTakeInnerWidget());
}
void setInnerVisible(bool scrollAreaVisible);
QPixmap grabInnerCache();
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private slots:
void onScroll();
void onDraggingScrollTimer();
private:
void setInner(object_ptr<TWidget> inner);
void setInner(object_ptr<TWidget> inner, const style::ScrollArea &st);
void updateScrollAreaGeometry();
object_ptr<TWidget> doTakeInnerWidget();
BoxContentDelegate *getDelegate() const {
t_assert(_delegate != nullptr);
return _delegate;
}
BoxContentDelegate *_delegate = nullptr;
bool _noContentMargin = false;
int _innerTopSkip = 0;
object_ptr<Ui::ScrollArea> _scroll = { nullptr };
object_ptr<Ui::WidgetFadeWrap<BoxLayerTitleShadow>> _topShadow = { nullptr };
object_ptr<BoxLayerTitleShadow> _bottomShadow = { nullptr };
object_ptr<QTimer> _draggingScrollTimer = { nullptr };
int _draggingScrollDelta = 0;
};
class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber {
public:
AbstractBox(object_ptr<BoxContent> content);
void parentResized() override;
void setLayerType(bool layerType) override;
void setTitle(const QString &title, const QString &additional) override;
void clearButtons() override;
QPointer<Ui::RoundButton> addButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) override;
QPointer<Ui::RoundButton> addLeftButton(const QString &text, base::lambda<void()> &&clickCallback, const style::RoundButton &st) override;
void updateButtonsPositions() override;
void setDimensions(int newWidth, int maxHeight) override;
void setNoContentMargin(bool noContentMargin) override {
if (_noContentMargin != noContentMargin) {
_noContentMargin = noContentMargin;
updateSize();
}
}
bool isBoxShown() const override {
return !isHidden();
}
void closeBox() override {
closeLayer();
}
protected: protected:
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void raiseShadow(); void doSetInnerFocus() override {
int titleHeight() const; _content->setInnerFocus();
void paintTitle(Painter &p, const QString &title, const QString &additional = QString()); }
void setMaxHeight(int32 maxHeight); void closeHook() override {
void resizeMaxHeight(int32 newWidth, int32 maxHeight); _content->closeHook();
virtual void closePressed() {
} }
private: private:
void updateBlockTitleGeometry(); void paintTitle(Painter &p, const QString &title, const QString &additional = QString());
int countHeight() const;
int _maxHeight = 0; bool hasTitle() const;
int titleHeight() const;
int buttonsHeight() const;
int buttonsTop() const;
int contentTop() const;
int countFullHeight() const;
int countRealHeight() const;
void updateSize();
bool _closed = false; int _fullHeight = 0;
bool _noContentMargin = false;
int _maxContentHeight = 0;
object_ptr<BoxContent> _content;
QString _title; QString _title;
QString _additionalTitle; QString _additionalTitle;
bool _blockTitle = false; bool _layerType = false;
ChildWidget<Ui::IconButton> _blockClose = { nullptr };
ChildWidget<Ui::GradientShadow> _blockShadow = { nullptr }; std_::vector_of_moveable<object_ptr<Ui::RoundButton>> _buttons;
object_ptr<Ui::RoundButton> _leftButton = { nullptr };
}; };
class ScrollableBoxShadow : public Ui::PlainShadow { template <typename BoxType, typename ...Args>
public: inline object_ptr<BoxType> Box(Args&&... args) {
ScrollableBoxShadow(QWidget *parent); auto parent = static_cast<QWidget*>(nullptr);
return object_ptr<BoxType>(parent, std_::forward<Args>(args)...);
}; }
class ScrollableBox : public AbstractBox {
public:
ScrollableBox(const style::FlatScroll &scroll, int w = 0);
protected:
void init(TWidget *inner, int bottomSkip = -1, int topSkip = -1);
void setScrollSkips(int bottomSkip = -1, int topSkip = -1);
void resizeEvent(QResizeEvent *e) override;
Ui::ScrollArea *scrollArea() {
return _scroll;
}
private:
void updateScrollGeometry();
ChildWidget<Ui::ScrollArea> _scroll;
int _topSkip, _bottomSkip;
};
class ItemListBox : public ScrollableBox {
public:
ItemListBox(const style::FlatScroll &scroll, int32 w = 0);
};
enum CreatingGroupType { enum CreatingGroupType {
CreatingGroupNone, CreatingGroupNone,

View file

@ -39,57 +39,52 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "apiwrap.h" #include "apiwrap.h"
#include "observer_peer.h" #include "observer_peer.h"
AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : AbstractBox(st::boxWidth) AddContactBox::AddContactBox(QWidget*, QString fname, QString lname, QString phone)
, _first(this, st::defaultInputField, lang(lng_signup_firstname), fname) : _first(this, st::defaultInputField, lang(lng_signup_firstname), fname)
, _last(this, st::defaultInputField, lang(lng_signup_lastname), lname) , _last(this, st::defaultInputField, lang(lng_signup_lastname), lname)
, _phone(this, st::defaultInputField, lang(lng_contact_phone), phone) , _phone(this, st::defaultInputField, lang(lng_contact_phone), phone)
, _save(this, lang(lng_add_contact), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _retry(this, lang(lng_try_other_contact), st::defaultBoxButton)
, _invertOrder(langFirstNameGoesSecond()) { , _invertOrder(langFirstNameGoesSecond()) {
if (!phone.isEmpty()) { if (!phone.isEmpty()) {
_phone->setDisabled(true); _phone->setDisabled(true);
} }
initBox();
} }
AddContactBox::AddContactBox(UserData *user) : AbstractBox(st::boxWidth) AddContactBox::AddContactBox(QWidget*, UserData *user)
, _user(user) : _user(user)
, _first(this, st::defaultInputField, lang(lng_signup_firstname), user->firstName) , _first(this, st::defaultInputField, lang(lng_signup_firstname), user->firstName)
, _last(this, st::defaultInputField, lang(lng_signup_lastname), user->lastName) , _last(this, st::defaultInputField, lang(lng_signup_lastname), user->lastName)
, _phone(this, st::defaultInputField, lang(lng_contact_phone), user->phone()) , _phone(this, st::defaultInputField, lang(lng_contact_phone), user->phone())
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _retry(this, lang(lng_try_other_contact), st::defaultBoxButton)
, _invertOrder(langFirstNameGoesSecond()) { , _invertOrder(langFirstNameGoesSecond()) {
_phone->setDisabled(true); _phone->setDisabled(true);
initBox();
} }
void AddContactBox::initBox() { void AddContactBox::prepare() {
if (_invertOrder) { if (_invertOrder) {
setTabOrder(_last, _first); setTabOrder(_last, _first);
} }
if (_user) { if (_user) {
setTitleText(lang(lng_edit_contact_title)); setTitle(lang(lng_edit_contact_title));
} else { } else {
bool readyToAdd = !_phone->getLastText().isEmpty() && (!_first->getLastText().isEmpty() || !_last->getLastText().isEmpty()); bool readyToAdd = !_phone->getLastText().isEmpty() && (!_first->getLastText().isEmpty() || !_last->getLastText().isEmpty());
setTitleText(lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data)); setTitle(lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data));
} }
setMaxHeight(titleHeight() + st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); updateButtons();
_retry->hide();
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_retry, SIGNAL(clicked()), this, SLOT(onRetry()));
connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_phone, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_phone, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) {
(_invertOrder ? _last : _first)->setDisplayFocused(true);
_phone->finishAnimations();
} else {
_phone->setDisplayFocused(true);
}
setDimensions(st::boxWideWidth, st::contactPadding.top() + _first->height() + st::contactSkip + _last->height() + st::contactPhoneSkip + _phone->height() + st::contactPadding.bottom() + st::boxPadding.bottom());
} }
void AddContactBox::doSetInnerFocus() { void AddContactBox::setInnerFocus() {
if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) { if ((_first->getLastText().isEmpty() && _last->getLastText().isEmpty()) || !_phone->isEnabled()) {
(_invertOrder ? _last : _first)->setFocus(); (_invertOrder ? _last : _first)->setFocus();
} else { } else {
@ -98,38 +93,35 @@ void AddContactBox::doSetInnerFocus() {
} }
void AddContactBox::paintEvent(QPaintEvent *e) { void AddContactBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
if (_retry->isHidden()) { if (_retrying) {
st::contactUserIcon.paint(p, st::boxPadding.left(), _first->y() + st::contactIconTop, width());
st::contactPhoneIcon.paint(p, st::boxPadding.left(), _phone->y() + st::contactIconTop, width());
} else {
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
p.setFont(st::boxTextFont); p.setFont(st::boxTextFont);
int32 h = height() - titleHeight() - st::contactPadding.top() - st::contactPadding.bottom() - st::boxPadding.bottom() - st::boxButtonPadding.top() - _retry->height() - st::boxButtonPadding.bottom(); auto textHeight = height() - st::contactPadding.top() - st::contactPadding.bottom() - st::boxPadding.bottom();
p.drawText(QRect(st::boxPadding.left(), titleHeight() + st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), h), lng_contact_not_joined(lt_name, _sentName), style::al_topleft); p.drawText(QRect(st::boxPadding.left(), st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), textHeight), lng_contact_not_joined(lt_name, _sentName), style::al_topleft);
} else {
st::contactUserIcon.paint(p, st::boxPadding.left(), _first->y() + st::contactIconTop, width());
st::contactPhoneIcon.paint(p, st::boxPadding.left(), _phone->y() + st::contactIconTop, width());
} }
} }
void AddContactBox::resizeEvent(QResizeEvent *e) { void AddContactBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_first->resize(width() - st::boxPadding.left() - st::contactPadding.left() - st::boxPadding.right(), _first->height()); _first->resize(width() - st::boxPadding.left() - st::contactPadding.left() - st::boxPadding.right(), _first->height());
_last->resize(_first->width(), _last->height()); _last->resize(_first->width(), _last->height());
_phone->resize(_first->width(), _last->height()); _phone->resize(_first->width(), _last->height());
if (_invertOrder) { if (_invertOrder) {
_last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), titleHeight() + st::contactPadding.top()); _last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), st::contactPadding.top());
_first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactSkip); _first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactSkip);
_phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactPhoneSkip); _phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactPhoneSkip);
} else { } else {
_first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), titleHeight() + st::contactPadding.top()); _first->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), st::contactPadding.top());
_last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactSkip); _last->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _first->y() + _first->height() + st::contactSkip);
_phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactPhoneSkip); _phone->moveToLeft(st::boxPadding.left() + st::contactPadding.left(), _last->y() + _last->height() + st::contactPhoneSkip);
} }
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_retry->moveToRight(st::boxButtonPadding.right(), _save->y());
_cancel->moveToRight(st::boxButtonPadding.right() + (_retry->isHidden() ? _save->width() : _retry->width()) + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void AddContactBox::onSubmit() { void AddContactBox::onSubmit() {
@ -190,7 +182,7 @@ bool AddContactBox::onSaveUserFail(const RPCError &error) {
QString firstName = _first->getLastText().trimmed(), lastName = _last->getLastText().trimmed(); QString firstName = _first->getLastText().trimmed(), lastName = _last->getLastText().trimmed();
if (err == "CHAT_TITLE_NOT_MODIFIED") { if (err == "CHAT_TITLE_NOT_MODIFIED") {
_user->setName(firstName, lastName, _user->nameOrPhone, _user->username); _user->setName(firstName, lastName, _user->nameOrPhone, _user->username);
onClose(); closeBox();
return true; return true;
} else if (err == "NO_CHAT_TITLE") { } else if (err == "NO_CHAT_TITLE") {
_first->setFocus(); _first->setFocus();
@ -202,12 +194,12 @@ bool AddContactBox::onSaveUserFail(const RPCError &error) {
} }
void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
if (isHidden() || !App::main()) return; if (!isBoxShown() || !App::main()) return;
const auto &d(res.c_contacts_importedContacts()); auto &d = res.c_contacts_importedContacts();
App::feedUsers(d.vusers); App::feedUsers(d.vusers);
const auto &v(d.vimported.c_vector().v); auto &v = d.vimported.c_vector().v;
UserData *user = nullptr; UserData *user = nullptr;
if (!v.isEmpty()) { if (!v.isEmpty()) {
const auto &c(v.front().c_importedContact()); const auto &c(v.front().c_importedContact());
@ -220,8 +212,8 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
Ui::hideLayer(); Ui::hideLayer();
} else { } else {
hideChildren(); hideChildren();
_retry->show(); _retrying = true;
resizeEvent(0); updateButtons();
update(); update();
} }
} }
@ -229,15 +221,15 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
void AddContactBox::onSaveUserDone(const MTPcontacts_ImportedContacts &res) { void AddContactBox::onSaveUserDone(const MTPcontacts_ImportedContacts &res) {
auto &d = res.c_contacts_importedContacts(); auto &d = res.c_contacts_importedContacts();
App::feedUsers(d.vusers); App::feedUsers(d.vusers);
onClose(); closeBox();
} }
void AddContactBox::onRetry() { void AddContactBox::onRetry() {
_addRequest = 0; _addRequest = 0;
_contactId = 0; _contactId = 0;
showChildren(); showChildren();
_retry->hide(); _retrying = false;
resizeEvent(0); updateButtons();
_first->setText(QString()); _first->setText(QString());
_last->setText(QString()); _last->setText(QString());
_phone->clearText(); _phone->clearText();
@ -246,31 +238,42 @@ void AddContactBox::onRetry() {
update(); update();
} }
GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox() void AddContactBox::updateButtons() {
, _creating(creating) clearButtons();
, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition) if (_retrying) {
, _title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) addButton(lang(lng_try_other_contact), [this] { onRetry(); });
, _description(this, st::newGroupDescription, lang(lng_create_group_description)) } else {
, _next(this, lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), st::defaultBoxButton) addButton(lang(_user ? lng_settings_save : lng_add_contact), [this] { onSave(); });
, _cancel(this, lang(fromTypeChoose ? lng_create_group_back : lng_cancel), st::cancelBoxButton) { addButton(lang(lng_cancel), [this] { closeBox(); });
}
}
GroupInfoBox::GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose)
: _creating(creating)
, _fromTypeChoose(fromTypeChoose)
, _photo(this, st::newGroupPhotoSize, st::newGroupPhotoIconPosition)
, _title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)) {
}
void GroupInfoBox::prepare() {
setMouseTracking(true); setMouseTracking(true);
_title->setMaxLength(MaxGroupChannelTitle); _title->setMaxLength(MaxGroupChannelTitle);
_description->setMaxLength(MaxChannelDescription); if (_creating == CreatingGroupChannel) {
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height()); _description.create(this, st::newGroupDescription, lang(lng_create_group_description));
_description->setVisible(_creating == CreatingGroupChannel); _description->show();
_description->setMaxLength(MaxChannelDescription);
updateMaxHeight(); connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized())); connect(_description, SIGNAL(submitted(bool)), this, SLOT(onNext()));
connect(_description, SIGNAL(submitted(bool)), this, SLOT(onNext())); connect(_description, SIGNAL(cancelled()), this, SLOT(onClose()));
connect(_description, SIGNAL(cancelled()), this, SLOT(onClose())); }
connect(_title, SIGNAL(submitted(bool)), this, SLOT(onNameSubmit())); connect(_title, SIGNAL(submitted(bool)), this, SLOT(onNameSubmit()));
connect(_next, SIGNAL(clicked()), this, SLOT(onNext())); addButton(lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), [this] { onNext(); });
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); addButton(lang(_fromTypeChoose ? lng_create_group_back : lng_cancel), [this] { closeBox(); });
_photo->setClickedCallback(App::LambdaDelayed(st::defaultActiveButton.ripple.hideDuration, this, [this] { _photo->setClickedCallback(App::LambdaDelayed(st::defaultActiveButton.ripple.hideDuration, this, [this] {
auto imgExtensions = cImgExtensions(); auto imgExtensions = cImgExtensions();
@ -280,48 +283,53 @@ GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : Ab
subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) { subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) {
notifyFileQueryUpdated(update); notifyFileQueryUpdated(update);
}); });
_title->setDisplayFocused(true);
updateMaxHeight();
} }
void GroupInfoBox::doSetInnerFocus() { void GroupInfoBox::setInnerFocus() {
_title->setFocus(); _title->setFocus();
} }
void GroupInfoBox::resizeEvent(QResizeEvent *e) { void GroupInfoBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_photo->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top()); _photo->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top());
int32 nameLeft = st::newGroupPhotoSize + st::newGroupNamePosition.x(); auto nameLeft = st::newGroupPhotoSize + st::newGroupNamePosition.x();
_title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right() - nameLeft, _title->height()); _title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right() - nameLeft, _title->height());
_title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left() + nameLeft, st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y()); _title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left() + nameLeft, st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y());
if (_description) {
_description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::newGroupDescriptionPadding.top()); _description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
_description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::newGroupDescriptionPadding.top());
_next->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _next->height()); }
_cancel->moveToRight(st::boxButtonPadding.right() + _next->width() + st::boxButtonPadding.left(), _next->y());
AbstractBox::resizeEvent(e);
} }
void GroupInfoBox::onNameSubmit() { void GroupInfoBox::onNameSubmit() {
if (_title->getLastText().trimmed().isEmpty()) { if (_title->getLastText().trimmed().isEmpty()) {
_title->setFocus(); _title->setFocus();
_title->showError(); _title->showError();
} else if (_description->isHidden()) { } else if (_description) {
onNext();
} else {
_description->setFocus(); _description->setFocus();
} else {
onNext();
} }
} }
void GroupInfoBox::onNext() { void GroupInfoBox::onNext() {
if (_creationRequestId) return; if (_creationRequestId) return;
QString title = prepareText(_title->getLastText()), description = prepareText(_description->getLastText(), true); auto title = prepareText(_title->getLastText());
auto description = _description ? prepareText(_description->getLastText(), true) : QString();
if (title.isEmpty()) { if (title.isEmpty()) {
_title->setFocus(); _title->setFocus();
_title->showError(); _title->showError();
return; return;
} }
if (_creating == CreatingGroupGroup) { if (_creating == CreatingGroupGroup) {
Ui::showLayer(new ContactsBox(title, _photoImage), KeepOtherLayers); Ui::show(Box<ContactsBox>(title, _photoImage), KeepOtherLayers);
} else { } else {
bool mega = false; bool mega = false;
MTPchannels_CreateChannel::Flags flags = mega ? MTPchannels_CreateChannel::Flag::f_megagroup : MTPchannels_CreateChannel::Flag::f_broadcast; MTPchannels_CreateChannel::Flags flags = mega ? MTPchannels_CreateChannel::Flag::f_megagroup : MTPchannels_CreateChannel::Flag::f_broadcast;
@ -354,7 +362,7 @@ void GroupInfoBox::creationDone(const MTPUpdates &updates) {
LOG(("API Error: channel not found in updates (GroupInfoBox::creationDone)")); LOG(("API Error: channel not found in updates (GroupInfoBox::creationDone)"));
} }
onClose(); closeBox();
} }
bool GroupInfoBox::creationFail(const RPCError &error) { bool GroupInfoBox::creationFail(const RPCError &error) {
@ -366,7 +374,7 @@ bool GroupInfoBox::creationFail(const RPCError &error) {
_title->showError(); _title->showError();
return true; return true;
} else if (error.type() == qstr("USER_RESTRICTED")) { } else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this))); Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
return true; return true;
} }
return false; return false;
@ -377,7 +385,7 @@ void GroupInfoBox::exportDone(const MTPExportedChatInvite &result) {
if (result.type() == mtpc_chatInviteExported) { if (result.type() == mtpc_chatInviteExported) {
_createdChannel->setInviteLink(qs(result.c_chatInviteExported().vlink)); _createdChannel->setInviteLink(qs(result.c_chatInviteExported().vlink));
} }
Ui::showLayer(new SetupChannelBox(_createdChannel)); Ui::show(Box<SetupChannelBox>(_createdChannel));
} }
void GroupInfoBox::onDescriptionResized() { void GroupInfoBox::onDescriptionResized() {
@ -386,11 +394,11 @@ void GroupInfoBox::onDescriptionResized() {
} }
void GroupInfoBox::updateMaxHeight() { void GroupInfoBox::updateMaxHeight() {
int32 h = st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom(); auto newHeight = st::boxPadding.top() + st::newGroupInfoPadding.top() + st::newGroupPhotoSize + st::boxPadding.bottom() + st::newGroupInfoPadding.bottom();
if (_creating == CreatingGroupChannel) { if (_description) {
h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
} }
setMaxHeight(h); setDimensions(st::boxWideWidth, newHeight);
} }
void GroupInfoBox::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) { void GroupInfoBox::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update) {
@ -411,9 +419,8 @@ void GroupInfoBox::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update)
if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) { if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) {
return; return;
} }
auto box = new PhotoCropBox(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0)); auto box = Ui::show(Box<PhotoCropBox>(img, (_creating == CreatingGroupChannel) ? peerFromChannel(0) : peerFromChat(0)), KeepOtherLayers);
connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&))); connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
Ui::showLayer(box, KeepOtherLayers);
} }
void GroupInfoBox::onPhotoReady(const QImage &img) { void GroupInfoBox::onPhotoReady(const QImage &img) {
@ -421,27 +428,26 @@ void GroupInfoBox::onPhotoReady(const QImage &img) {
_photo->setImage(_photoImage); _photo->setImage(_photoImage);
} }
SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox() SetupChannelBox::SetupChannelBox(QWidget*, ChannelData *channel, bool existing)
, _channel(channel) : _channel(channel)
, _existing(existing) , _existing(existing)
, _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true, st::defaultBoxCheckbox) , _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true, st::defaultBoxCheckbox)
, _private(this, qsl("channel_privacy"), 1, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title), false, st::defaultBoxCheckbox) , _private(this, qsl("channel_privacy"), 1, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title), false, st::defaultBoxCheckbox)
, _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultBoxCheckbox.textPosition.x()) , _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultBoxCheckbox.textPosition.x())
, _aboutPublic(st::normalFont, lang(channel->isMegagroup() ? lng_create_public_group_about : lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth) , _aboutPublic(st::normalFont, lang(channel->isMegagroup() ? lng_create_public_group_about : lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth)
, _aboutPrivate(st::normalFont, lang(channel->isMegagroup() ? lng_create_private_group_about : lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth) , _aboutPrivate(st::normalFont, lang(channel->isMegagroup() ? lng_create_private_group_about : lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth)
, _link(this, st::setupChannelLink, QString(), channel->username, true) , _link(this, st::setupChannelLink, QString(), channel->username, true) {
, _linkOver(false) }
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _skip(this, lang(existing ? lng_cancel : lng_create_group_skip), st::cancelBoxButton) { void SetupChannelBox::prepare() {
_aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth);
setMouseTracking(true); setMouseTracking(true);
_checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail)); _checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail));
_aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth); addButton(lang(lng_settings_save), [this] { onSave(); });
updateMaxHeight(); addButton(lang(_existing ? lng_cancel : lng_create_group_skip), [this] { closeBox(); });
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_skip, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_link, SIGNAL(changed()), this, SLOT(onChange())); connect(_link, SIGNAL(changed()), this, SLOT(onChange()));
_link->setVisible(_public->checked()); _link->setVisible(_public->checked());
@ -451,9 +457,11 @@ SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : Abstract
connect(_public, SIGNAL(changed()), this, SLOT(onPrivacyChange())); connect(_public, SIGNAL(changed()), this, SLOT(onPrivacyChange()));
connect(_private, SIGNAL(changed()), this, SLOT(onPrivacyChange())); connect(_private, SIGNAL(changed()), this, SLOT(onPrivacyChange()));
updateMaxHeight();
} }
void SetupChannelBox::doSetInnerFocus() { void SetupChannelBox::setInnerFocus() {
if (_link->isHidden()) { if (_link->isHidden()) {
setFocus(); setFocus();
} else { } else {
@ -462,11 +470,11 @@ void SetupChannelBox::doSetInnerFocus() {
} }
void SetupChannelBox::updateMaxHeight() { void SetupChannelBox::updateMaxHeight() {
auto newHeight = st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom();
if (!_channel->isMegagroup() || _public->checked()) { if (!_channel->isMegagroup() || _public->checked()) {
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); newHeight += st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom();
} else {
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom());
} }
setDimensions(st::boxWideWidth, newHeight);
} }
void SetupChannelBox::keyPressEvent(QKeyEvent *e) { void SetupChannelBox::keyPressEvent(QKeyEvent *e) {
@ -480,7 +488,7 @@ void SetupChannelBox::keyPressEvent(QKeyEvent *e) {
} }
} }
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
@ -534,16 +542,14 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
} }
void SetupChannelBox::resizeEvent(QResizeEvent *e) { void SetupChannelBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_public->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top()); _public->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top());
_private->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _public->bottomNoMargins() + _aboutPublicHeight + st::newGroupSkip); _private->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _public->bottomNoMargins() + _aboutPublicHeight + st::newGroupSkip);
_link->resize(width() - st::boxPadding.left() - st::newGroupLinkPadding.left() - st::boxPadding.right(), _link->height()); _link->resize(width() - st::boxPadding.left() - st::newGroupLinkPadding.left() - st::boxPadding.right(), _link->height());
_link->moveToLeft(st::boxPadding.left() + st::newGroupLinkPadding.left(), _private->bottomNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top()); _link->moveToLeft(st::boxPadding.left() + st::newGroupLinkPadding.left(), _private->bottomNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top());
_invitationLink = QRect(_link->x(), _link->y() + (_link->height() / 2) - st::boxTextFont->height, _link->width(), 2 * st::boxTextFont->height); _invitationLink = QRect(_link->x(), _link->y() + (_link->height() / 2) - st::boxTextFont->height, _link->width(), 2 * st::boxTextFont->height);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_skip->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) { void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
@ -574,9 +580,9 @@ void SetupChannelBox::updateSelected(const QPoint &cursorGlobalPosition) {
} }
} }
void SetupChannelBox::closePressed() { void SetupChannelBox::closeHook() {
if (!_existing) { if (!_existing) {
Ui::showLayer(new ContactsBox(_channel)); Ui::show(Box<ContactsBox>(_channel));
} }
} }
@ -586,7 +592,7 @@ void SetupChannelBox::onSave() {
_sentUsername = QString(); _sentUsername = QString();
_saveRequestId = MTP::send(MTPchannels_UpdateUsername(_channel->inputChannel, MTP_string(_sentUsername)), rpcDone(&SetupChannelBox::onUpdateDone), rpcFail(&SetupChannelBox::onUpdateFail)); _saveRequestId = MTP::send(MTPchannels_UpdateUsername(_channel->inputChannel, MTP_string(_sentUsername)), rpcDone(&SetupChannelBox::onUpdateDone), rpcFail(&SetupChannelBox::onUpdateFail));
} else { } else {
onClose(); closeBox();
} }
} }
@ -655,7 +661,7 @@ void SetupChannelBox::onPrivacyChange() {
if (_public->checked()) { if (_public->checked()) {
if (_tooMuchUsernames) { if (_tooMuchUsernames) {
_private->setChecked(true); _private->setChecked(true);
Ui::showLayer(new RevokePublicLinkBox(base::lambda_guarded(this, [this] { Ui::show(Box<RevokePublicLinkBox>(base::lambda_guarded(this, [this] {
_tooMuchUsernames = false; _tooMuchUsernames = false;
_public->setChecked(true); _public->setChecked(true);
onCheck(); onCheck();
@ -676,7 +682,7 @@ void SetupChannelBox::onPrivacyChange() {
void SetupChannelBox::onUpdateDone(const MTPBool &result) { void SetupChannelBox::onUpdateDone(const MTPBool &result) {
_channel->setName(textOneLine(_channel->name), _sentUsername); _channel->setName(textOneLine(_channel->name), _sentUsername);
onClose(); closeBox();
} }
bool SetupChannelBox::onUpdateFail(const RPCError &error) { bool SetupChannelBox::onUpdateFail(const RPCError &error) {
@ -686,7 +692,7 @@ bool SetupChannelBox::onUpdateFail(const RPCError &error) {
QString err(error.type()); QString err(error.type());
if (err == "USERNAME_NOT_MODIFIED" || _sentUsername == _channel->username) { if (err == "USERNAME_NOT_MODIFIED" || _sentUsername == _channel->username) {
_channel->setName(textOneLine(_channel->name), textOneLine(_sentUsername)); _channel->setName(textOneLine(_channel->name), textOneLine(_sentUsername));
onClose(); closeBox();
return true; return true;
} else if (err == "USERNAME_INVALID") { } else if (err == "USERNAME_INVALID") {
_link->setFocus(); _link->setFocus();
@ -748,9 +754,9 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
} }
void SetupChannelBox::showRevokePublicLinkBoxForEdit() { void SetupChannelBox::showRevokePublicLinkBoxForEdit() {
onClose(); closeBox();
Ui::showLayer(new RevokePublicLinkBox([channel = _channel, existing = _existing]() { Ui::show(Box<RevokePublicLinkBox>([channel = _channel, existing = _existing]() {
Ui::showLayer(new SetupChannelBox(channel, existing), KeepOtherLayers); Ui::show(Box<SetupChannelBox>(channel, existing), KeepOtherLayers);
}), KeepOtherLayers); }), KeepOtherLayers);
} }
@ -777,38 +783,40 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
return true; return true;
} }
EditNameTitleBox::EditNameTitleBox(PeerData *peer) : EditNameTitleBox::EditNameTitleBox(QWidget*, PeerData *peer)
_peer(peer), : _peer(peer)
_first(this, st::defaultInputField, lang(peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), peer->isUser() ? peer->asUser()->firstName : peer->name), , _first(this, st::defaultInputField, lang(peer->isUser() ? lng_signup_firstname : lng_dlg_new_group_name), peer->isUser() ? peer->asUser()->firstName : peer->name)
_last(this, st::defaultInputField, lang(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString()), , _last(this, st::defaultInputField, lang(lng_signup_lastname), peer->isUser() ? peer->asUser()->lastName : QString())
_save(this, lang(lng_settings_save), st::defaultBoxButton), , _invertOrder(!peer->isChat() && langFirstNameGoesSecond()) {
_cancel(this, lang(lng_cancel), st::cancelBoxButton), }
_invertOrder(!peer->isChat() && langFirstNameGoesSecond()) {
void EditNameTitleBox::prepare() {
auto newHeight = st::contactPadding.top() + _first->height();
if (_peer->isUser()) {
setTitle(lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title));
newHeight += st::contactSkip + _last->height();
} else if (_peer->isChat()) {
setTitle(lang(lng_edit_group_title));
}
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
setDimensions(st::boxWideWidth, newHeight);
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
if (_invertOrder) { if (_invertOrder) {
setTabOrder(_last, _first); setTabOrder(_last, _first);
} }
_first->setMaxLength(MaxGroupChannelTitle); _first->setMaxLength(MaxGroupChannelTitle);
_last->setMaxLength(MaxGroupChannelTitle); _last->setMaxLength(MaxGroupChannelTitle);
int32 h = titleHeight() + st::contactPadding.top() + _first->height();
if (_peer->isUser()) {
setTitleText(lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title));
h += st::contactSkip + _last->height();
} else if (_peer->isChat()) {
setTitleText(lang(lng_edit_group_title));
}
h += st::boxPadding.bottom() + st::contactPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom();
setMaxHeight(h);
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_first, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_last, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
_last->setVisible(!_peer->isChat()); _last->setVisible(!_peer->isChat());
(_invertOrder ? _last : _first)->setDisplayFocused(true);
} }
void EditNameTitleBox::doSetInnerFocus() { void EditNameTitleBox::setInnerFocus() {
(_invertOrder ? _last : _first)->setFocus(); (_invertOrder ? _last : _first)->setFocus();
} }
@ -838,19 +846,17 @@ void EditNameTitleBox::onSubmit() {
} }
void EditNameTitleBox::resizeEvent(QResizeEvent *e) { void EditNameTitleBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_first->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _first->height()); _first->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _first->height());
_last->resize(_first->size()); _last->resize(_first->size());
if (_invertOrder) { if (_invertOrder) {
_last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::contactPadding.top()); _last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::contactPadding.top());
_first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _last->y() + _last->height() + st::contactSkip); _first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _last->y() + _last->height() + st::contactSkip);
} else { } else {
_first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::contactPadding.top()); _first->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::contactPadding.top());
_last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _first->y() + _first->height() + st::contactSkip); _last->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _first->y() + _first->height() + st::contactSkip);
} }
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void EditNameTitleBox::onSave() { void EditNameTitleBox::onSave() {
@ -882,7 +888,7 @@ void EditNameTitleBox::onSave() {
void EditNameTitleBox::onSaveSelfDone(const MTPUser &user) { void EditNameTitleBox::onSaveSelfDone(const MTPUser &user) {
App::feedUsers(MTP_vector<MTPUser>(1, user)); App::feedUsers(MTP_vector<MTPUser>(1, user));
onClose(); closeBox();
} }
bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) { bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) {
@ -892,7 +898,7 @@ bool EditNameTitleBox::onSaveSelfFail(const RPCError &error) {
QString first = textOneLine(_first->getLastText().trimmed()), last = textOneLine(_last->getLastText().trimmed()); QString first = textOneLine(_first->getLastText().trimmed()), last = textOneLine(_last->getLastText().trimmed());
if (err == "NAME_NOT_MODIFIED") { if (err == "NAME_NOT_MODIFIED") {
App::self()->setName(first, last, QString(), textOneLine(App::self()->username)); App::self()->setName(first, last, QString(), textOneLine(App::self()->username));
onClose(); closeBox();
return true; return true;
} else if (err == "FIRSTNAME_INVALID") { } else if (err == "FIRSTNAME_INVALID") {
_first->setFocus(); _first->setFocus();
@ -916,7 +922,7 @@ bool EditNameTitleBox::onSaveChatFail(const RPCError &error) {
if (auto chatData = _peer->asChat()) { if (auto chatData = _peer->asChat()) {
chatData->setName(_sentName); chatData->setName(_sentName);
} }
onClose(); closeBox();
return true; return true;
} else if (err == qstr("NO_CHAT_TITLE")) { } else if (err == qstr("NO_CHAT_TITLE")) {
_first->setFocus(); _first->setFocus();
@ -929,42 +935,44 @@ bool EditNameTitleBox::onSaveChatFail(const RPCError &error) {
void EditNameTitleBox::onSaveChatDone(const MTPUpdates &updates) { void EditNameTitleBox::onSaveChatDone(const MTPUpdates &updates) {
App::main()->sentUpdatesReceived(updates); App::main()->sentUpdatesReceived(updates);
onClose(); closeBox();
} }
EditChannelBox::EditChannelBox(ChannelData *channel) : AbstractBox() EditChannelBox::EditChannelBox(QWidget*, ChannelData *channel)
, _channel(channel) : _channel(channel)
, _title(this, st::defaultInputField, lang(lng_dlg_new_channel_name), _channel->name) , _title(this, st::defaultInputField, lang(lng_dlg_new_channel_name), _channel->name)
, _description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about()) , _description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about())
, _sign(this, lang(lng_edit_sign_messages), channel->addsSignature(), st::defaultBoxCheckbox) , _sign(this, lang(lng_edit_sign_messages), channel->addsSignature(), st::defaultBoxCheckbox)
, _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::boxLinkButton) , _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::boxLinkButton) {
, _save(this, lang(lng_settings_save), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
setTitleText(lang(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title)); void EditChannelBox::prepare() {
setTitle(lang(_channel->isMegagroup() ? lng_edit_group : lng_edit_channel_title));
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
setMouseTracking(true); setMouseTracking(true);
_title->setMaxLength(MaxGroupChannelTitle); _title->setMaxLength(MaxGroupChannelTitle);
_description->setMaxLength(MaxChannelDescription); _description->setMaxLength(MaxChannelDescription);
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
myEnsureResized(_description);
updateMaxHeight();
connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized())); connect(_description, SIGNAL(resized()), this, SLOT(onDescriptionResized()));
connect(_description, SIGNAL(submitted(bool)), this, SLOT(onSave())); connect(_description, SIGNAL(submitted(bool)), this, SLOT(onSave()));
connect(_description, SIGNAL(cancelled()), this, SLOT(onClose())); connect(_description, SIGNAL(cancelled()), this, SLOT(onClose()));
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_publicLink, SIGNAL(clicked()), this, SLOT(onPublicLink())); connect(_publicLink, SIGNAL(clicked()), this, SLOT(onPublicLink()));
_publicLink->setVisible(_channel->canEditUsername()); _publicLink->setVisible(_channel->canEditUsername());
_sign->setVisible(!_channel->isMegagroup()); _sign->setVisible(!_channel->isMegagroup());
_title->setDisplayFocused(true);
updateMaxHeight();
} }
void EditChannelBox::doSetInnerFocus() { void EditChannelBox::setInnerFocus() {
_title->setFocus(); _title->setFocus();
} }
@ -974,7 +982,7 @@ void EditChannelBox::keyPressEvent(QKeyEvent *e) {
onSave(); onSave();
} }
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
@ -991,22 +999,25 @@ void EditChannelBox::onDescriptionResized() {
} }
void EditChannelBox::updateMaxHeight() { void EditChannelBox::updateMaxHeight() {
int32 h = titleHeight() + st::newGroupInfoPadding.top() + _title->height(); auto newHeight = st::newGroupInfoPadding.top() + _title->height();
h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); newHeight += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
if (!_channel->isMegagroup()) { if (!_channel->isMegagroup()) {
h += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom(); newHeight += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom();
} }
if (_channel->canEditUsername()) { if (_channel->canEditUsername()) {
h += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom(); newHeight += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom();
} }
h += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); newHeight += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom();
setMaxHeight(h); setDimensions(st::boxWideWidth, newHeight);
} }
void EditChannelBox::resizeEvent(QResizeEvent *e) { void EditChannelBox::resizeEvent(QResizeEvent *e) {
_title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _title->height()); BoxContent::resizeEvent(e);
_title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), titleHeight() + st::newGroupInfoPadding.top() + st::newGroupNamePosition.y());
_title->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _title->height());
_title->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), st::newGroupInfoPadding.top() + st::newGroupNamePosition.y());
_description->resize(width() - st::boxPadding.left() - st::newGroupInfoPadding.left() - st::boxPadding.right(), _description->height());
_description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _title->y() + _title->height() + st::newGroupDescriptionPadding.top()); _description->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _title->y() + _title->height() + st::newGroupDescriptionPadding.top());
_sign->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); _sign->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
@ -1016,10 +1027,6 @@ void EditChannelBox::resizeEvent(QResizeEvent *e) {
} else { } else {
_publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign->bottomNoMargins() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); _publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign->bottomNoMargins() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
} }
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void EditChannelBox::onSave() { void EditChannelBox::onSave() {
@ -1041,7 +1048,7 @@ void EditChannelBox::onSave() {
} }
void EditChannelBox::onPublicLink() { void EditChannelBox::onPublicLink() {
Ui::showLayer(new SetupChannelBox(_channel, true), KeepOtherLayers); Ui::show(Box<SetupChannelBox>(_channel, true), KeepOtherLayers);
} }
void EditChannelBox::saveDescription() { void EditChannelBox::saveDescription() {
@ -1054,7 +1061,7 @@ void EditChannelBox::saveDescription() {
void EditChannelBox::saveSign() { void EditChannelBox::saveSign() {
if (_channel->isMegagroup() || _channel->addsSignature() == _sign->checked()) { if (_channel->isMegagroup() || _channel->addsSignature() == _sign->checked()) {
onClose(); closeBox();
} else { } else {
_saveSignRequestId = MTP::send(MTPchannels_ToggleSignatures(_channel->inputChannel, MTP_bool(_sign->checked())), rpcDone(&EditChannelBox::onSaveSignDone), rpcFail(&EditChannelBox::onSaveFail)); _saveSignRequestId = MTP::send(MTPchannels_ToggleSignatures(_channel->inputChannel, MTP_bool(_sign->checked())), rpcDone(&EditChannelBox::onSaveSignDone), rpcFail(&EditChannelBox::onSaveFail));
} }
@ -1093,7 +1100,7 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
} else if (req == _saveSignRequestId) { } else if (req == _saveSignRequestId) {
_saveSignRequestId = 0; _saveSignRequestId = 0;
if (err == qstr("CHAT_NOT_MODIFIED")) { if (err == qstr("CHAT_NOT_MODIFIED")) {
onClose(); closeBox();
return true; return true;
} }
} }
@ -1123,28 +1130,31 @@ void EditChannelBox::onSaveSignDone(const MTPUpdates &updates) {
if (App::main()) { if (App::main()) {
App::main()->sentUpdatesReceived(updates); App::main()->sentUpdatesReceived(updates);
} }
onClose(); closeBox();
} }
RevokePublicLinkBox::RevokePublicLinkBox(base::lambda<void()> &&revokeCallback) : AbstractBox() RevokePublicLinkBox::RevokePublicLinkBox(QWidget*, base::lambda<void()> &&revokeCallback)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) : _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _revokeWidth(st::normalFont->width(lang(lng_channels_too_much_public_revoke))) , _revokeWidth(st::normalFont->width(lang(lng_channels_too_much_public_revoke)))
, _aboutRevoke(this, lang(lng_channels_too_much_public_about), Ui::FlatLabel::InitType::Simple, st::aboutRevokePublicLabel) , _aboutRevoke(this, lang(lng_channels_too_much_public_about), Ui::FlatLabel::InitType::Simple, st::aboutRevokePublicLabel)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _revokeCallback(std_::move(revokeCallback)) { , _revokeCallback(std_::move(revokeCallback)) {
}
void RevokePublicLinkBox::prepare() {
setMouseTracking(true); setMouseTracking(true);
MTP::send(MTPchannels_GetAdminedPublicChannels(), rpcDone(&RevokePublicLinkBox::getPublicDone), rpcFail(&RevokePublicLinkBox::getPublicFail)); MTP::send(MTPchannels_GetAdminedPublicChannels(), rpcDone(&RevokePublicLinkBox::getPublicDone), rpcFail(&RevokePublicLinkBox::getPublicFail));
updateMaxHeight(); addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
subscribe(FileDownload::ImageLoaded(), [this] { update(); }); subscribe(FileDownload::ImageLoaded(), [this] { update(); });
updateMaxHeight();
} }
void RevokePublicLinkBox::updateMaxHeight() { void RevokePublicLinkBox::updateMaxHeight() {
_rowsTop = st::boxPadding.top() + _aboutRevoke->height() + st::boxPadding.top(); _rowsTop = st::boxPadding.top() + _aboutRevoke->height() + st::boxPadding.top();
setMaxHeight(_rowsTop + (5 * _rowHeight) + st::boxButtonPadding.top() + _cancel->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWideWidth, _rowsTop + (5 * _rowHeight));
} }
void RevokePublicLinkBox::mouseMoveEvent(QMouseEvent *e) { void RevokePublicLinkBox::mouseMoveEvent(QMouseEvent *e) {
@ -1183,23 +1193,16 @@ void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) {
if (pressed && pressed == _selected) { if (pressed && pressed == _selected) {
auto text_method = pressed->isMegagroup() ? lng_channels_too_much_public_revoke_confirm_group : lng_channels_too_much_public_revoke_confirm_channel; auto text_method = pressed->isMegagroup() ? lng_channels_too_much_public_revoke_confirm_group : lng_channels_too_much_public_revoke_confirm_channel;
auto text = text_method(lt_link, qsl("telegram.me/") + pressed->userName(), lt_group, pressed->name); auto text = text_method(lt_link, qsl("telegram.me/") + pressed->userName(), lt_group, pressed->name);
weakRevokeConfirmBox = new ConfirmBox(text, lang(lng_channels_too_much_public_revoke)); auto confirmText = lang(lng_channels_too_much_public_revoke);
struct Data { _weakRevokeConfirmBox = Ui::show(Box<ConfirmBox>(text, confirmText, base::lambda_guarded(this, [this, pressed]() {
Data(QPointer<TWidget> &&weakThis, PeerData *pressed) : weakThis(std_::move(weakThis)), pressed(pressed) {
}
QPointer<TWidget> weakThis;
PeerData *pressed;
};
weakRevokeConfirmBox->setConfirmedCallback(base::lambda_guarded(this, [this, pressed]() {
if (_revokeRequestId) return; if (_revokeRequestId) return;
_revokeRequestId = MTP::send(MTPchannels_UpdateUsername(pressed->asChannel()->inputChannel, MTP_string("")), rpcDone(&RevokePublicLinkBox::revokeLinkDone), rpcFail(&RevokePublicLinkBox::revokeLinkFail)); _revokeRequestId = MTP::send(MTPchannels_UpdateUsername(pressed->asChannel()->inputChannel, MTP_string("")), rpcDone(&RevokePublicLinkBox::revokeLinkDone), rpcFail(&RevokePublicLinkBox::revokeLinkFail));
})); })), KeepOtherLayers);
Ui::showLayer(weakRevokeConfirmBox, KeepOtherLayers);
} }
} }
void RevokePublicLinkBox::paintEvent(QPaintEvent *e) { void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
p.translate(0, _rowsTop); p.translate(0, _rowsTop);
@ -1210,9 +1213,9 @@ void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
} }
void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) { void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); _aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_cancel->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _cancel->height());
AbstractBox::resizeEvent(e);
} }
void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const { void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const {
@ -1268,10 +1271,10 @@ bool RevokePublicLinkBox::getPublicFail(const RPCError &error) {
} }
void RevokePublicLinkBox::revokeLinkDone(const MTPBool &result) { void RevokePublicLinkBox::revokeLinkDone(const MTPBool &result) {
if (weakRevokeConfirmBox) { if (_weakRevokeConfirmBox) {
weakRevokeConfirmBox->onClose(); _weakRevokeConfirmBox->closeBox();
} }
onClose(); closeBox();
if (_revokeCallback) { if (_revokeCallback) {
_revokeCallback(); _revokeCallback();
} }

View file

@ -34,114 +34,110 @@ class UsernameInput;
class Checkbox; class Checkbox;
class Radiobutton; class Radiobutton;
class LinkButton; class LinkButton;
class RoundButton;
class NewAvatarButton; class NewAvatarButton;
} // namespace Ui } // namespace Ui
class AddContactBox : public AbstractBox, public RPCSender { class AddContactBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
AddContactBox(QString fname = QString(), QString lname = QString(), QString phone = QString()); AddContactBox(QWidget*, QString fname = QString(), QString lname = QString(), QString phone = QString());
AddContactBox(UserData *user); AddContactBox(QWidget*, UserData *user);
public slots: protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void setInnerFocus() override;
private slots:
void onSubmit(); void onSubmit();
void onSave(); void onSave();
void onRetry(); void onRetry();
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void updateButtons();
void onImportDone(const MTPcontacts_ImportedContacts &res); void onImportDone(const MTPcontacts_ImportedContacts &res);
void onSaveUserDone(const MTPcontacts_ImportedContacts &res); void onSaveUserDone(const MTPcontacts_ImportedContacts &res);
bool onSaveUserFail(const RPCError &e); bool onSaveUserFail(const RPCError &e);
void initBox();
UserData *_user = nullptr; UserData *_user = nullptr;
ChildWidget<Ui::InputField> _first; object_ptr<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last; object_ptr<Ui::InputField> _last;
ChildWidget<Ui::PhoneInput> _phone; object_ptr<Ui::PhoneInput> _phone;
ChildWidget<Ui::RoundButton> _save; bool _retrying = false;
ChildWidget<Ui::RoundButton> _cancel; bool _invertOrder = false;
ChildWidget<Ui::RoundButton> _retry;
bool _invertOrder;
uint64 _contactId = 0; uint64 _contactId = 0;
mtpRequestId _addRequest = 0; mtpRequestId _addRequest = 0;
QString _sentName; QString _sentName;
}; };
class GroupInfoBox : public AbstractBox, public RPCSender { class GroupInfoBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose); GroupInfoBox(QWidget*, CreatingGroupType creating, bool fromTypeChoose);
public slots: protected:
void prepare() override;
void setInnerFocus() override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onPhotoReady(const QImage &img); void onPhotoReady(const QImage &img);
void onNext(); void onNext();
void onNameSubmit(); void onNameSubmit();
void onDescriptionResized(); void onDescriptionResized();
protected:
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update); void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update);
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
void exportDone(const MTPExportedChatInvite &result);
void updateMaxHeight(); void updateMaxHeight();
void updateSelected(const QPoint &cursorGlobalPosition); void updateSelected(const QPoint &cursorGlobalPosition);
CreatingGroupType _creating;
ChildWidget<Ui::NewAvatarButton> _photo; CreatingGroupType _creating;
ChildWidget<Ui::InputField> _title; bool _fromTypeChoose = false;
ChildWidget<Ui::InputArea> _description;
object_ptr<Ui::NewAvatarButton> _photo;
object_ptr<Ui::InputField> _title;
object_ptr<Ui::InputArea> _description = { nullptr };
QImage _photoImage; QImage _photoImage;
ChildWidget<Ui::RoundButton> _next;
ChildWidget<Ui::RoundButton> _cancel;
// channel creation // channel creation
mtpRequestId _creationRequestId = 0; mtpRequestId _creationRequestId = 0;
ChannelData *_createdChannel = nullptr; ChannelData *_createdChannel = nullptr;
FileDialog::QueryId _setPhotoFileQueryId = 0; FileDialog::QueryId _setPhotoFileQueryId = 0;
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
void exportDone(const MTPExportedChatInvite &result);
}; };
class SetupChannelBox : public AbstractBox, public RPCSender { class SetupChannelBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
SetupChannelBox(ChannelData *channel, bool existing = false); SetupChannelBox(QWidget*, ChannelData *channel, bool existing = false);
public slots: void setInnerFocus() override;
void onSave(); void closeHook() override;
void onChange();
void onCheck();
void onPrivacyChange();
protected: protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
@ -149,8 +145,12 @@ protected:
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override; void leaveEvent(QEvent *e) override;
void closePressed() override; private slots:
void doSetInnerFocus() override; void onSave();
void onChange();
void onCheck();
void onPrivacyChange();
private: private:
void updateSelected(const QPoint &cursorGlobalPosition); void updateSelected(const QPoint &cursorGlobalPosition);
@ -166,22 +166,18 @@ private:
void showRevokePublicLinkBoxForEdit(); void showRevokePublicLinkBoxForEdit();
ChannelData *_channel; ChannelData *_channel = nullptr;
bool _existing; bool _existing = false;
ChildWidget<Ui::Radiobutton> _public; object_ptr<Ui::Radiobutton> _public;
ChildWidget<Ui::Radiobutton> _private; object_ptr<Ui::Radiobutton> _private;
int32 _aboutPublicWidth, _aboutPublicHeight; int32 _aboutPublicWidth, _aboutPublicHeight;
Text _aboutPublic, _aboutPrivate; Text _aboutPublic, _aboutPrivate;
ChildWidget<Ui::UsernameInput> _link; object_ptr<Ui::UsernameInput> _link;
QRect _invitationLink; QRect _invitationLink;
bool _linkOver; bool _linkOver = false;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _skip;
bool _tooMuchUsernames = false; bool _tooMuchUsernames = false;
mtpRequestId _saveRequestId = 0; mtpRequestId _saveRequestId = 0;
@ -195,20 +191,21 @@ private:
}; };
class EditNameTitleBox : public AbstractBox, public RPCSender { class EditNameTitleBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
EditNameTitleBox(PeerData *peer); EditNameTitleBox(QWidget*, PeerData *peer);
public slots:
void onSave();
void onSubmit();
protected: protected:
void setInnerFocus() override;
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override; private slots:
void onSave();
void onSubmit();
private: private:
void onSaveSelfDone(const MTPUser &user); void onSaveSelfDone(const MTPUser &user);
@ -219,11 +216,8 @@ private:
PeerData *_peer; PeerData *_peer;
ChildWidget<Ui::InputField> _first; object_ptr<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last; object_ptr<Ui::InputField> _last;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
bool _invertOrder = false; bool _invertOrder = false;
@ -232,25 +226,26 @@ private:
}; };
class EditChannelBox : public AbstractBox, public RPCSender { class EditChannelBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
EditChannelBox(ChannelData *channel); EditChannelBox(QWidget*, ChannelData *channel);
public slots: protected:
void prepare() override;
void setInnerFocus() override;
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void peerUpdated(PeerData *peer); void peerUpdated(PeerData *peer);
void onSave(); void onSave();
void onDescriptionResized(); void onDescriptionResized();
void onPublicLink(); void onPublicLink();
protected:
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void updateMaxHeight(); void updateMaxHeight();
@ -264,14 +259,11 @@ private:
ChannelData *_channel; ChannelData *_channel;
ChildWidget<Ui::InputField> _title; object_ptr<Ui::InputField> _title;
ChildWidget<Ui::InputArea> _description; object_ptr<Ui::InputArea> _description;
ChildWidget<Ui::Checkbox> _sign; object_ptr<Ui::Checkbox> _sign;
ChildWidget<Ui::LinkButton> _publicLink; object_ptr<Ui::LinkButton> _publicLink;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
mtpRequestId _saveTitleRequestId = 0; mtpRequestId _saveTitleRequestId = 0;
mtpRequestId _saveDescriptionRequestId = 0; mtpRequestId _saveDescriptionRequestId = 0;
@ -281,13 +273,13 @@ private:
}; };
class RevokePublicLinkBox : public AbstractBox, public RPCSender { class RevokePublicLinkBox : public BoxContent, public RPCSender {
Q_OBJECT
public: public:
RevokePublicLinkBox(base::lambda<void()> &&revokeCallback); RevokePublicLinkBox(QWidget*, base::lambda<void()> &&revokeCallback);
protected: protected:
void prepare() override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
@ -319,11 +311,10 @@ private:
int _rowHeight = 0; int _rowHeight = 0;
int _revokeWidth = 0; int _revokeWidth = 0;
ChildWidget<Ui::FlatLabel> _aboutRevoke; object_ptr<Ui::FlatLabel> _aboutRevoke;
ChildWidget<Ui::RoundButton> _cancel;
base::lambda<void()> _revokeCallback; base::lambda<void()> _revokeCallback;
mtpRequestId _revokeRequestId = 0; mtpRequestId _revokeRequestId = 0;
QPointer<ConfirmBox> weakRevokeConfirmBox; QPointer<ConfirmBox> _weakRevokeConfirmBox;
}; };

View file

@ -30,32 +30,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
AutoLockBox::AutoLockBox() : _close(this, lang(lng_box_ok), st::defaultBoxButton) { void AutoLockBox::prepare() {
setTitleText(lang(lng_passcode_autolock)); setTitle(lang(lng_passcode_autolock));
bool haveTestLang = (cLang() == languageTest); addButton(lang(lng_box_ok), [this] { closeBox(); });
int32 opts[] = { 60, 300, 3600, 18000 }, cnt = sizeof(opts) / sizeof(opts[0]); int opts[] = { 60, 300, 3600, 18000 }, cnt = sizeof(opts) / sizeof(opts[0]);
auto y = st::boxOptionListPadding.top();
resizeMaxHeight(st::langsWidth, titleHeight() + cnt * (st::boxOptionListPadding.top() + st::langsButton.height) + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom());
int32 y = titleHeight() + st::boxOptionListPadding.top();
_options.reserve(cnt); _options.reserve(cnt);
for (int32 i = 0; i < cnt; ++i) { for (auto i = 0; i != cnt; ++i) {
int32 v = opts[i]; auto v = opts[i];
_options.push_back(new Ui::Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (Global::AutoLock() == v), st::langsButton)); _options.push_back(new Ui::Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (Global::AutoLock() == v), st::langsButton));
_options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); _options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _options.back()->heightNoMargins() + st::boxOptionListPadding.top(); y += _options.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange())); connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange()));
} }
connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); setDimensions(st::langsWidth, st::boxOptionListPadding.top() + cnt * st::langsButton.height + (cnt - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
} }
void AutoLockBox::onChange() { void AutoLockBox::onChange() {
if (isHidden()) return; if (!isBoxShown()) return;
for (int32 i = 0, l = _options.size(); i < l; ++i) { for (int32 i = 0, l = _options.size(); i < l; ++i) {
int32 v = _options[i]->val(); int32 v = _options[i]->val();
@ -66,5 +61,5 @@ void AutoLockBox::onChange() {
} }
} }
App::wnd()->checkAutoLock(); App::wnd()->checkAutoLock();
onClose(); closeBox();
} }

View file

@ -24,20 +24,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class Radiobutton; class Radiobutton;
class RoundButton;
} // namespace Ui } // namespace Ui
class AutoLockBox : public AbstractBox { class AutoLockBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
AutoLockBox(); AutoLockBox(QWidget*) {
}
public slots: protected:
void prepare() override;
private slots:
void onChange(); void onChange();
private: private:
QVector<Ui::Radiobutton*> _options; QVector<Ui::Radiobutton*> _options;
ChildWidget<Ui::RoundButton> _close;
}; };

View file

@ -29,25 +29,29 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "ui/effects/round_checkbox.h" #include "ui/effects/round_checkbox.h"
BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll) BackgroundBox::BackgroundBox(QWidget*) {
, _inner(this) {
init(_inner);
setTitleText(lang(lng_backgrounds_header));
connect(_inner, SIGNAL(backgroundChosen(int)), this, SLOT(onBackgroundChosen(int)));
raiseShadow();
} }
void BackgroundBox::onBackgroundChosen(int index) { void BackgroundBox::prepare() {
setTitle(lang(lng_backgrounds_header));
addButton(lang(lng_close), [this] { closeBox(); });
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
_inner = setInnerWidget(object_ptr<Inner>(this), st::backgroundScroll);
_inner->setBackgroundChosenCallback([this](int index) { backgroundChosen(index); });
}
void BackgroundBox::backgroundChosen(int index) {
if (index >= 0 && index < App::cServerBackgrounds().size()) { if (index >= 0 && index < App::cServerBackgrounds().size()) {
const App::WallPaper &paper(App::cServerBackgrounds().at(index)); auto &paper = App::cServerBackgrounds()[index];
if (App::main()) App::main()->setChatBackground(paper); if (App::main()) App::main()->setChatBackground(paper);
using Update = Window::Theme::BackgroundUpdate; using Update = Window::Theme::BackgroundUpdate;
Window::Theme::Background()->notify(Update(Update::Type::Start, !paper.id)); Window::Theme::Background()->notify(Update(Update::Type::Start, !paper.id));
} }
onClose(); closeBox();
} }
BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent) BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
@ -163,8 +167,8 @@ void BackgroundBox::Inner::paintEvent(QPaintEvent *e) {
} }
} }
} else { } else {
p.setFont(st::noContactsFont->f); p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor->p); p.setPen(st::noContactsColor);
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center); p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
} }
} }
@ -191,7 +195,9 @@ void BackgroundBox::Inner::mousePressEvent(QMouseEvent *e) {
void BackgroundBox::Inner::mouseReleaseEvent(QMouseEvent *e) { void BackgroundBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
if (_overDown == _over && _over >= 0) { if (_overDown == _over && _over >= 0) {
emit backgroundChosen(_over); if (_backgroundChosenCallback) {
_backgroundChosenCallback(_over);
}
} else if (_over < 0) { } else if (_over < 0) {
setCursor(style::cur_default); setCursor(style::cur_default);
} }

View file

@ -26,31 +26,31 @@ namespace Ui {
class RoundCheckbox; class RoundCheckbox;
} // namespace Ui } // namespace Ui
class BackgroundBox : public ItemListBox { class BackgroundBox : public BoxContent {
Q_OBJECT
public: public:
BackgroundBox(); BackgroundBox(QWidget*);
public slots: protected:
void onBackgroundChosen(int index); void prepare() override;
private: private:
void backgroundChosen(int index);
class Inner; class Inner;
ChildWidget<Inner> _inner; QPointer<Inner> _inner;
}; };
// This class is hold in header because it requires Qt preprocessing. // This class is hold in header because it requires Qt preprocessing.
class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Subscriber { class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
Q_OBJECT
public: public:
Inner(QWidget *parent); Inner(QWidget *parent);
~Inner();
signals: void setBackgroundChosenCallback(base::lambda<void(int index)> &&callback) {
void backgroundChosen(int index); _backgroundChosenCallback = std_::move(callback);
}
~Inner();
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
@ -62,10 +62,12 @@ private:
void gotWallpapers(const MTPVector<MTPWallPaper> &result); void gotWallpapers(const MTPVector<MTPWallPaper> &result);
void updateWallpapers(); void updateWallpapers();
base::lambda<void(int index)> _backgroundChosenCallback;
int _bgCount = 0; int _bgCount = 0;
int _rows = 0; int _rows = 0;
int _over = -1; int _over = -1;
int _overDown = -1; int _overDown = -1;
std_::unique_ptr<Ui::RoundCheckbox> _check; std_::unique_ptr<Ui::RoundCheckbox> _check; // this not a widget
}; };

View file

@ -24,16 +24,10 @@ using "ui/widgets/widgets.style";
using "intro/intro.style"; using "intro/intro.style";
boxDuration: 200; boxDuration: 200;
boxRadius: 3px;
boxButtonFont: font(boxFontSize semibold); boxButtonFont: font(boxFontSize semibold);
defaultBoxButton: RoundButton { defaultBoxButton: RoundButton(defaultLightButton) {
textFg: #2f9fea;
textFgOver: #2f9fea;
secondaryTextFg: #2f9fea;
secondaryTextFgOver: #2f9fea;
textBg: boxBg;
textBgOver: lightButtonBgOver;
width: -24px; width: -24px;
height: 36px; height: 36px;
padding: margins(0px, 0px, 0px, 0px); padding: margins(0px, 0px, 0px, 0px);
@ -47,9 +41,7 @@ defaultBoxButton: RoundButton {
} }
} }
cancelBoxButton: RoundButton(defaultBoxButton) { cancelBoxButton: defaultBoxButton;
textFg: #aeaeae;
}
attentionBoxButton: RoundButton(defaultBoxButton) { attentionBoxButton: RoundButton(defaultBoxButton) {
textFg: attentionButtonFg; textFg: attentionButtonFg;
@ -67,22 +59,40 @@ defaultBoxCheckbox: Checkbox(defaultCheckbox) {
font: boxTextFont; font: boxTextFont;
} }
boxBlockTitleHeight: 48px; boxRoundShadow: Shadow {
boxBlockTitlePosition: point(18px, 14px); left: icon {{ "round_shadow_box_left", windowShadowFg }};
boxBlockTitleFont: font(boxFontSize semibold); topLeft: icon {{ "round_shadow_box_top_left", windowShadowFg }};
boxBlockTitleAdditionalSkip: 6px; top: icon {{ "round_shadow_box_top", windowShadowFg }};
boxBlockTitleAdditionalFont: normalFont; topRight: icon {{ "round_shadow_box_top_left-flip_horizontal", windowShadowFg }};
boxBlockTitleShadow: icon {{ "box_title_shadow", windowShadowFg }}; right: icon {{ "round_shadow_box_left-flip_horizontal", windowShadowFg }};
bottomRight: icon {{ "round_shadow_box_bottom_left-flip_horizontal", windowShadowFg }};
bottom: icon {{ "round_shadow_box_bottom", windowShadowFg }};
bottomLeft: icon {{ "round_shadow_box_bottom_left", windowShadowFg }};
extend: margins(10px, 10px, 10px, 10px);
fallback: windowShadowFgFallback;
}
boxBlockTitleClose: IconButton(defaultIconButton) { boxTitleFont: font(17px semibold);
width: boxBlockTitleHeight; boxTitlePosition: point(23px, 20px);
height: boxBlockTitleHeight; boxTitleHeight: 56px;
boxLayerTitlePosition: point(23px, 16px);
boxLayerTitleHeight: 56px;
boxLayerTitleAdditionalSkip: 9px;
boxLayerTitleAdditionalFont: normalFont;
boxLayerTitleShadow: #0000001a;
boxLayerScroll: defaultSolidScroll;
icon: boxBlockTitleCloseIcon; boxTopMargin: 6px;
iconOver: boxBlockTitleCloseIconOver;
boxTitleClose: IconButton(defaultIconButton) {
width: boxTitleHeight;
height: boxTitleHeight;
icon: boxTitleCloseIcon;
iconOver: boxTitleCloseIconOver;
rippleAreaPosition: point(4px, 4px); rippleAreaPosition: point(4px, 4px);
rippleAreaSize: 40px; rippleAreaSize: 48px;
ripple: RippleAnimation(defaultRippleAnimation) { ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver; color: windowBgOver;
} }
@ -96,34 +106,25 @@ boxLinkButton: LinkButton {
overFont: font(boxFontSize underline); overFont: font(boxFontSize underline);
} }
boxOptionListPadding: margins(2px, 20px, 2px, 2px); boxOptionListPadding: margins(0px, 0px, 0px, 0px);
boxOptionListSkip: 20px;
boxOptionInputSkip: 6px; boxOptionInputSkip: 6px;
boxVerticalMargin: 10px; boxVerticalMargin: 10px;
boxWidth: 320px; boxWidth: 320px;
boxWideWidth: 364px; boxWideWidth: 364px;
boxPadding: margins(26px, 30px, 34px, 8px); boxPadding: margins(23px, 30px, 23px, 8px);
boxMaxListHeight: 600px; boxMaxListHeight: 600px;
boxLittleSkip: 10px; boxLittleSkip: 10px;
boxMediumSkip: 20px; boxMediumSkip: 20px;
boxTitleFont: font(boxFontSize bold); boxButtonPadding: margins(8px, 12px, 13px, 12px);
boxTitlePosition: point(26px, 28px); boxLayerButtonPadding: margins(8px, 8px, 8px, 8px);
boxTitleHeight: 54px;
boxButtonPadding: margins(12px, 16px, 22px, 16px);
boxLabel: FlatLabel(defaultFlatLabel) { boxLabel: FlatLabel(defaultFlatLabel) {
font: font(boxFontSize); font: font(boxFontSize);
align: align(topleft); align: align(topleft);
} }
boxScroll: defaultSolidScroll;
boxScrollSkip: 6px;
boxScrollShadowBg: #00000012;
boxShadow: icon {{ "box_shadow", windowShadowFg }};
boxShadowShift: 2px;
countryRowHeight: 36px; countryRowHeight: 36px;
countryRowNameFont: semiboldFont; countryRowNameFont: semiboldFont;
countryRowNameFg: boxTextFg; countryRowNameFg: boxTextFg;
@ -134,7 +135,7 @@ countryRowBgOver: windowBgOver;
countryRowCodeFg: windowSubTextFg; countryRowCodeFg: windowSubTextFg;
countryRowCodeFgOver: windowSubTextFgOver; countryRowCodeFgOver: windowSubTextFgOver;
countriesSkip: 12px; countriesSkip: 12px;
countriesScroll: FlatScroll(boxScroll) { countriesScroll: ScrollArea(boxLayerScroll) {
deltat: 9px; deltat: 9px;
deltab: 3px; deltab: 3px;
} }
@ -145,7 +146,7 @@ boxTextStyle: TextStyle(defaultTextStyle) {
boxPhotoTitleFont: font(16px semibold); boxPhotoTitleFont: font(16px semibold);
boxPhotoTitlePosition: point(28px, 26px); boxPhotoTitlePosition: point(28px, 26px);
boxPhotoPadding: margins(28px, 28px, 28px, 0px); boxPhotoPadding: margins(28px, 28px, 28px, 18px);
boxPhotoCompressedSkip: 20px; boxPhotoCompressedSkip: 20px;
boxPhotoCaptionSkip: 8px; boxPhotoCaptionSkip: 8px;
boxPhotoTextFg: #808080; boxPhotoTextFg: #808080;
@ -223,7 +224,7 @@ contactsAdd: TwoIconButton {
} }
contactsAddPosition: point(14px, 8px); contactsAddPosition: point(14px, 8px);
contactPadding: margins(49px, 2px, 0px, 6px); contactPadding: margins(49px, 2px, 0px, 12px);
contactSkip: 6px; contactSkip: 6px;
contactPhoneSkip: 30px; contactPhoneSkip: 30px;
@ -240,15 +241,12 @@ contactsAboutFg: windowSubTextFgOver;
contactsAboutShadow: #0000001F; contactsAboutShadow: #0000001F;
contactsAboutTop: 60px; contactsAboutTop: 60px;
contactsAboutBottom: 19px; contactsAboutBottom: 19px;
contactsScroll: FlatScroll(boxScroll) {
deltab: 0px;
}
contactsMultiSelect: MultiSelect { contactsMultiSelect: MultiSelect {
bg: boxSearchBg; bg: boxSearchBg;
padding: margins(8px, 8px, 8px, 8px); padding: margins(8px, 6px, 8px, 6px);
maxHeight: 104px; maxHeight: 104px;
scroll: FlatScroll(defaultSolidScroll) { scroll: ScrollArea(defaultSolidScroll) {
deltat: 3px; deltat: 3px;
deltab: 3px; deltab: 3px;
round: 1px; round: 1px;
@ -302,17 +300,17 @@ contactsMultiSelect: MultiSelect {
fieldIconSkip: 36px; fieldIconSkip: 36px;
fieldCancel: CrossButton { fieldCancel: CrossButton {
width: boxBlockTitleHeight; width: 44px;
height: boxBlockTitleHeight; height: 44px;
cross: CrossAnimation { cross: CrossAnimation {
size: 40px; size: 36px;
skip: 14px; skip: 12px;
stroke: 2px; stroke: 2px;
minScale: 0.3; minScale: 0.3;
} }
crossFg: boxBlockTitleCloseFg; crossFg: boxTitleCloseFg;
crossFgOver: boxBlockTitleCloseFgOver; crossFgOver: boxTitleCloseFgOver;
crossPosition: point(4px, 4px); crossPosition: point(4px, 4px);
duration: 150; duration: 150;
@ -338,6 +336,11 @@ contactsPhotoDisabledCheckFg: #bbbbbb;
contactsNameCheckedFg: #2b88b8; contactsNameCheckedFg: #2b88b8;
contactsRipple: defaultRippleAnimation; contactsRipple: defaultRippleAnimation;
contactsMarginTop: 4px;
contactsMarginBottom: 4px;
membersMarginTop: 10px;
membersMarginBottom: 10px;
localStorageBoxSkip: 10px; localStorageBoxSkip: 10px;
shareRowsTop: 12px; shareRowsTop: 12px;
@ -355,7 +358,7 @@ shareColumnSkip: 6px;
shareActivateDuration: 150; shareActivateDuration: 150;
shareScrollDuration: 300; shareScrollDuration: 300;
notificationsBoxHeight: 450px; notificationsBoxHeight: 420px;
notificationsBoxMonitorTop: 63px; notificationsBoxMonitorTop: 63px;
notificationsBoxMonitor: icon {{ "monitor", notificationsBoxMonitorFg }}; notificationsBoxMonitor: icon {{ "monitor", notificationsBoxMonitorFg }};
notificationsBoxScreenTop: 10px; notificationsBoxScreenTop: 10px;
@ -374,8 +377,8 @@ notificationSampleSize: size(64px, 16px);
membersAboutLimitPadding: margins(0px, 12px, 0px, 12px); membersAboutLimitPadding: margins(0px, 12px, 0px, 12px);
sessionsScroll: boxScroll; sessionsScroll: boxLayerScroll;
sessionsHeight: 440px; sessionsHeight: 350px;
sessionHeight: 70px; sessionHeight: 70px;
sessionCurrentPadding: margins(0px, 7px, 0px, 4px); sessionCurrentPadding: margins(0px, 7px, 0px, 4px);
sessionCurrentHeight: 118px; sessionCurrentHeight: 118px;
@ -417,9 +420,10 @@ passcodeSubmit: RoundButton(introNextButton) {
width: 225px; width: 225px;
} }
passcodeSubmitSkip: 40px; passcodeSubmitSkip: 40px;
passcodePadding: margins(0px, 6px, 0px, 13px); passcodePadding: margins(0px, 0px, 0px, 12px);
passcodeTextLine: 28px; passcodeTextLine: 28px;
passcodeSkip: 21px; passcodeLittleSkip: 5px;
passcodeSkip: 20px;
newGroupAboutFg: #808080; newGroupAboutFg: #808080;
newGroupPadding: margins(4px, 6px, 4px, 3px); newGroupPadding: margins(4px, 6px, 4px, 3px);
@ -453,8 +457,6 @@ newGroupLinkFadeDuration: 5000;
themeWarningWidth: boxWideWidth; themeWarningWidth: boxWideWidth;
themeWarningHeight: 150px; themeWarningHeight: 150px;
themeWarningShadow: boxShadow;
themeWarningShadowShift: boxShadowShift;
themeWarningTextTop: 60px; themeWarningTextTop: 60px;
aboutWidth: 390px; aboutWidth: 390px;
@ -475,6 +477,9 @@ aboutTextStyle: TextStyle(defaultTextStyle) {
lineHeight: 22px; lineHeight: 22px;
} }
autoDownloadTitlePosition: point(23px, 28px);
autoDownloadTitleFont: font(15px semibold);
editTextArea: InputField(defaultInputField) { editTextArea: InputField(defaultInputField) {
textMargins: margins(1px, 26px, 1px, 4px); textMargins: margins(1px, 26px, 1px, 4px);
heightMax: 276px; heightMax: 276px;
@ -509,9 +514,11 @@ langsButton: Checkbox(defaultBoxCheckbox) {
backgroundPadding: 10px; backgroundPadding: 10px;
backgroundSize: size(108px, 193px); backgroundSize: size(108px, 193px);
backgroundScroll: FlatScroll(boxScroll) { backgroundScroll: ScrollArea(boxLayerScroll) {
deltax: 3px;
width: 10px;
deltat: 10px; deltat: 10px;
deltab: 0px; deltab: 10px;
} }
usernamePadding: margins(23px, 6px, 21px, 12px); usernamePadding: margins(23px, 6px, 21px, 12px);

View file

@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/toast/toast.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "localstorage.h" #include "localstorage.h"
@ -40,54 +41,103 @@ TextParseOptions _confirmBoxTextOptions = {
Qt::LayoutDirectionAuto, // dir Qt::LayoutDirectionAuto, // dir
}; };
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, const QString &cancelText, const style::RoundButton &cancelStyle) : AbstractBox(st::boxWidth) ConfirmBox::ConfirmBox(QWidget*, const QString &text, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
, _informative(false) : _confirmText(lang(lng_box_ok))
, _text(100) , _cancelText(lang(lng_cancel))
, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle) , _confirmStyle(st::defaultBoxButton)
, _cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, cancelStyle) { , _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text); init(text);
} }
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, bool informative) : AbstractBox(st::boxWidth) ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(lang(lng_cancel))
, _confirmStyle(st::defaultBoxButton)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(lang(lng_cancel))
, _confirmStyle(confirmStyle)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const QString &cancelText, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(cancelText)
, _confirmStyle(st::defaultBoxButton)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, const QString &cancelText, base::lambda<void()> &&confirmedCallback, base::lambda<void()> &&cancelledCallback)
: _confirmText(confirmText)
, _cancelText(cancelText)
, _confirmStyle(st::defaultBoxButton)
, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirmedCallback(std_::move(confirmedCallback))
, _cancelledCallback(std_::move(cancelledCallback)) {
init(text);
}
ConfirmBox::ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback)
: _confirmText(doneText)
, _confirmStyle(st::defaultBoxButton)
, _informative(true) , _informative(true)
, _text(100) , _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle) , _confirmedCallback(base::lambda_copy<void()>(closedCallback))
, _cancel(this, QString(), st::cancelBoxButton) { , _cancelledCallback(base::lambda_copy<void()>(closedCallback)) {
init(text); init(text);
} }
void ConfirmBox::init(const QString &text) { void ConfirmBox::init(const QString &text) {
textstyleSet(&st::boxTextStyle);
_text.setText(st::boxTextFont, text, _informative ? _confirmBoxTextOptions : _textPlainOptions); _text.setText(st::boxTextFont, text, _informative ? _confirmBoxTextOptions : _textPlainOptions);
textstyleRestore();
connect(_confirm, SIGNAL(clicked()), this, SLOT(onConfirmPressed()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
if (_informative) {
_cancel->hide();
connect(this, SIGNAL(confirmed()), this, SLOT(onCancel()));
}
onTextUpdated();
} }
void ConfirmBox::onConfirmPressed() { void ConfirmBox::prepare() {
if (_confirmedCallback) { addButton(_confirmText, [this] { confirmed(); }, _confirmStyle);
_confirmedCallback(); if (!_informative) {
addButton(_cancelText, [this] { _cancelled = true; closeBox(); });
} }
emit confirmed(); textUpdated();
} }
void ConfirmBox::onTextUpdated() { void ConfirmBox::textUpdated() {
textstyleSet(&st::boxTextStyle); textstyleSet(&st::boxTextStyle);
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right(); _textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
_textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight)); _textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight));
setMaxHeight(st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + st::boxButtonPadding.top() + _confirm->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxPadding.bottom());
textstyleRestore(); textstyleRestore();
setMouseTracking(_text.hasLinks()); setMouseTracking(_text.hasLinks());
} }
void ConfirmBox::onCancel() { void ConfirmBox::closeHook() {
emit cancelPressed(); if (!_confirmed && (!_strictCancel || _cancelled) && _cancelledCallback) {
onClose(); _cancelledCallback();
}
}
void ConfirmBox::confirmed() {
if (!_confirmed) {
_confirmed = true;
if (_confirmedCallback) {
_confirmedCallback();
}
}
} }
void ConfirmBox::mouseMoveEvent(QMouseEvent *e) { void ConfirmBox::mouseMoveEvent(QMouseEvent *e) {
@ -99,7 +149,7 @@ void ConfirmBox::mousePressEvent(QMouseEvent *e) {
_lastMousePos = e->globalPos(); _lastMousePos = e->globalPos();
updateHover(); updateHover();
ClickHandler::pressed(); ClickHandler::pressed();
return LayerWidget::mousePressEvent(e); return BoxContent::mousePressEvent(e);
} }
void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) { void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
@ -109,6 +159,7 @@ void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
Ui::hideLayer(); Ui::hideLayer();
App::activateClickHandler(activated, e->button()); App::activateClickHandler(activated, e->button());
} }
return BoxContent::mouseReleaseEvent(e);
} }
void ConfirmBox::leaveEvent(QEvent *e) { void ConfirmBox::leaveEvent(QEvent *e) {
@ -139,20 +190,16 @@ void ConfirmBox::updateHover() {
ClickHandler::setActive(state.link, this); ClickHandler::setActive(state.link, this);
} }
void ConfirmBox::closePressed() {
emit cancelled();
}
void ConfirmBox::keyPressEvent(QKeyEvent *e) { void ConfirmBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onConfirmPressed(); confirmed();
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void ConfirmBox::paintEvent(QPaintEvent *e) { void ConfirmBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -163,55 +210,19 @@ void ConfirmBox::paintEvent(QPaintEvent *e) {
textstyleRestore(); textstyleRestore();
} }
void ConfirmBox::resizeEvent(QResizeEvent *e) { MaxInviteBox::MaxInviteBox(QWidget*, const QString &link)
_confirm->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _confirm->height()); : _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
_cancel->moveToRight(st::boxButtonPadding.right() + _confirm->width() + st::boxButtonPadding.left(), _confirm->y());
AbstractBox::resizeEvent(e);
}
SharePhoneConfirmBox::SharePhoneConfirmBox(PeerData *recipient)
: ConfirmBox(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm))
, _recipient(recipient) {
connect(this, SIGNAL(confirmed()), this, SLOT(onConfirm()));
}
void SharePhoneConfirmBox::onConfirm() {
emit confirmed(_recipient);
}
ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_this_link) + qsl("\n\n") + url, lang(lng_open_link))
, _url(url) {
connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink()));
}
void ConfirmLinkBox::onOpenLink() {
Ui::hideLayer();
UrlClickHandler::doOpen(_url);
}
ConfirmBotGameBox::ConfirmBotGameBox(UserData *bot, const QString &url) : ConfirmBox(lng_allow_bot_pass(lt_bot_name, bot->name), lang(lng_allow_bot))
, _bot(bot)
, _url(url) {
connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink()));
}
void ConfirmBotGameBox::onOpenLink() {
Ui::hideLayer();
Local::makeBotTrusted(_bot);
UrlClickHandler::doOpen(_url);
}
MaxInviteBox::MaxInviteBox(const QString &link) : AbstractBox(st::boxWidth)
, _close(this, lang(lng_box_ok), st::defaultBoxButton)
, _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
, _link(link) { , _link(link) {
}
void MaxInviteBox::prepare() {
setMouseTracking(true); setMouseTracking(true);
addButton(lang(lng_box_ok), [this] { closeBox(); });
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right(); _textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
_textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight)); _textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight));
setMaxHeight(st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom());
connect(_close, SIGNAL(clicked()), this, SLOT(onClose()));
} }
void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) { void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) {
@ -222,9 +233,10 @@ void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
mouseMoveEvent(e); mouseMoveEvent(e);
if (_linkOver) { if (_linkOver) {
Application::clipboard()->setText(_link); Application::clipboard()->setText(_link);
_goodTextLink = lang(lng_create_channel_link_copied);
_a_goodOpacity.finish(); Ui::Toast::Config toast;
_a_goodOpacity.start([this] { update(); }, 1., 0., st::newGroupLinkFadeDuration); toast.text = lang(lng_create_channel_link_copied);
Ui::Toast::Show(App::wnd(), toast);
} }
} }
@ -244,7 +256,7 @@ void MaxInviteBox::updateSelected(const QPoint &cursorGlobalPosition) {
} }
void MaxInviteBox::paintEvent(QPaintEvent *e) { void MaxInviteBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -257,49 +269,41 @@ void MaxInviteBox::paintEvent(QPaintEvent *e) {
p.setFont(_linkOver ? st::defaultInputField.font->underline() : st::defaultInputField.font); p.setFont(_linkOver ? st::defaultInputField.font->underline() : st::defaultInputField.font);
p.setPen(st::defaultLinkButton.color); p.setPen(st::defaultLinkButton.color);
p.drawText(_invitationLink, _link, option); p.drawText(_invitationLink, _link, 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.drawTextLeft(st::boxPadding.left(), height() - st::boxButtonPadding.bottom() - _close->height() + st::defaultBoxButton.textTop + st::defaultBoxButton.font->ascent - st::boxTextFont->ascent, width(), _goodTextLink);
p.setOpacity(1);
}
}
} }
void MaxInviteBox::resizeEvent(QResizeEvent *e) { void MaxInviteBox::resizeEvent(QResizeEvent *e) {
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height()); BoxContent::resizeEvent(e);
_invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height, width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height); _invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height, width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height);
AbstractBox::resizeEvent(e);
} }
ConvertToSupergroupBox::ConvertToSupergroupBox(ChatData *chat) : AbstractBox(st::boxWideWidth, lang(lng_profile_convert_title)) ConvertToSupergroupBox::ConvertToSupergroupBox(QWidget*, ChatData *chat)
, _chat(chat) : _chat(chat)
, _text(100) , _text(100)
, _note(100) , _note(100) {
, _convert(this, lang(lng_profile_convert_confirm), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
void ConvertToSupergroupBox::prepare() {
QStringList text; QStringList text;
text.push_back(lang(lng_profile_convert_feature1)); text.push_back(lang(lng_profile_convert_feature1));
text.push_back(lang(lng_profile_convert_feature2)); text.push_back(lang(lng_profile_convert_feature2));
text.push_back(lang(lng_profile_convert_feature3)); text.push_back(lang(lng_profile_convert_feature3));
text.push_back(lang(lng_profile_convert_feature4)); text.push_back(lang(lng_profile_convert_feature4));
setTitle(lang(lng_profile_convert_title));
addButton(lang(lng_profile_convert_confirm), [this] { convertToSupergroup(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
textstyleSet(&st::boxTextStyle); textstyleSet(&st::boxTextStyle);
_text.setText(st::boxTextFont, text.join('\n'), _confirmBoxTextOptions); _text.setText(st::boxTextFont, text.join('\n'), _confirmBoxTextOptions);
_note.setText(st::boxTextFont, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions); _note.setText(st::boxTextFont, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions);
_textWidth = st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right(); _textWidth = st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right();
_textHeight = _text.countHeight(_textWidth); _textHeight = _text.countHeight(_textWidth);
setMaxHeight(titleHeight() + _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth) + st::boxButtonPadding.top() + _convert->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWideWidth, _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth));
textstyleRestore(); textstyleRestore();
connect(_convert, SIGNAL(clicked()), this, SLOT(onConvert()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
} }
void ConvertToSupergroupBox::onConvert() { void ConvertToSupergroupBox::convertToSupergroup() {
MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail)); MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail));
} }
@ -336,54 +340,48 @@ bool ConvertToSupergroupBox::convertFail(const RPCError &error) {
void ConvertToSupergroupBox::keyPressEvent(QKeyEvent *e) { void ConvertToSupergroupBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onConvert(); convertToSupergroup();
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) { void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
// draw box title / text // draw box title / text
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
textstyleSet(&st::boxTextStyle); textstyleSet(&st::boxTextStyle);
_text.drawLeft(p, st::boxPadding.left(), titleHeight(), _textWidth, width()); _text.drawLeft(p, st::boxPadding.left(), 0, _textWidth, width());
_note.drawLeft(p, st::boxPadding.left(), titleHeight() + _textHeight + st::boxPadding.bottom(), _textWidth, width()); _note.drawLeft(p, st::boxPadding.left(), _textHeight + st::boxPadding.bottom(), _textWidth, width());
textstyleRestore(); textstyleRestore();
} }
void ConvertToSupergroupBox::resizeEvent(QResizeEvent *e) { PinMessageBox::PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId)
_convert->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _convert->height()); : _channel(channel)
_cancel->moveToRight(st::boxButtonPadding.right() + _convert->width() + st::boxButtonPadding.left(), _convert->y());
AbstractBox::resizeEvent(e);
}
PinMessageBox::PinMessageBox(ChannelData *channel, MsgId msgId) : AbstractBox(st::boxWidth)
, _channel(channel)
, _msgId(msgId) , _msgId(msgId)
, _text(this, lang(lng_pinned_pin_sure), Ui::FlatLabel::InitType::Simple, st::boxLabel) , _text(this, lang(lng_pinned_pin_sure), Ui::FlatLabel::InitType::Simple, st::boxLabel)
, _notify(this, lang(lng_pinned_notify), true, st::defaultBoxCheckbox) , _notify(this, lang(lng_pinned_notify), true, st::defaultBoxCheckbox) {
, _pin(this, lang(lng_pinned_pin), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _pin->height() + st::boxButtonPadding.bottom());
connect(_pin, SIGNAL(clicked()), this, SLOT(onPin())); void PinMessageBox::prepare() {
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
addButton(lang(lng_pinned_pin), [this] { pinMessage(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom());
} }
void PinMessageBox::resizeEvent(QResizeEvent *e) { void PinMessageBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_text->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); _text->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_notify->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip); _notify->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip);
_pin->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _pin->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _pin->width() + st::boxButtonPadding.left(), _pin->y());
AbstractBox::resizeEvent(e);
} }
void PinMessageBox::onPin() { void PinMessageBox::pinMessage() {
if (_requestId) return; if (_requestId) return;
MTPchannels_UpdatePinnedMessage::Flags flags = 0; MTPchannels_UpdatePinnedMessage::Flags flags = 0;
@ -406,36 +404,35 @@ bool PinMessageBox::pinFail(const RPCError &error) {
return true; return true;
} }
RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId) : AbstractBox(st::boxWidth) RichDeleteMessageBox::RichDeleteMessageBox(QWidget*, ChannelData *channel, UserData *from, MsgId msgId)
, _channel(channel) : _channel(channel)
, _from(from) , _from(from)
, _msgId(msgId) , _msgId(msgId)
, _text(this, lang(lng_selected_delete_sure_this), Ui::FlatLabel::InitType::Simple, st::boxLabel) , _text(this, lang(lng_selected_delete_sure_this), Ui::FlatLabel::InitType::Simple, st::boxLabel)
, _banUser(this, lang(lng_ban_user), false, st::defaultBoxCheckbox) , _banUser(this, lang(lng_ban_user), false, st::defaultBoxCheckbox)
, _reportSpam(this, lang(lng_report_spam), false, st::defaultBoxCheckbox) , _reportSpam(this, lang(lng_report_spam), false, st::defaultBoxCheckbox)
, _deleteAll(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox) , _deleteAll(this, lang(lng_delete_all_from), false, st::defaultBoxCheckbox) {
, _delete(this, lang(lng_box_delete), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
void RichDeleteMessageBox::prepare() {
t_assert(_channel != nullptr); t_assert(_channel != nullptr);
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); addButton(lang(lng_box_delete), [this] { deleteAndClear(); });
setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _delete->height() + st::boxButtonPadding.bottom()); addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_delete, SIGNAL(clicked()), this, SLOT(onDelete())); _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); setDimensions(st::boxWidth, st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins() + st::boxPadding.bottom());
} }
void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) { void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_text->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); _text->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_banUser->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip); _banUser->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip);
_reportSpam->moveToLeft(st::boxPadding.left(), _banUser->bottomNoMargins() + st::boxLittleSkip); _reportSpam->moveToLeft(st::boxPadding.left(), _banUser->bottomNoMargins() + st::boxLittleSkip);
_deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->bottomNoMargins() + st::boxLittleSkip); _deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->bottomNoMargins() + st::boxLittleSkip);
_delete->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _delete->width() + st::boxButtonPadding.left(), _delete->y());
AbstractBox::resizeEvent(e);
} }
void RichDeleteMessageBox::onDelete() { void RichDeleteMessageBox::deleteAndClear() {
if (_banUser->checked()) { if (_banUser->checked()) {
MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), App::main()->rpcDone(&MainWidget::sentUpdatesReceived)); MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
} }
@ -445,7 +442,7 @@ void RichDeleteMessageBox::onDelete() {
if (_deleteAll->checked()) { if (_deleteAll->checked()) {
App::main()->deleteAllFromUser(_channel, _from); App::main()->deleteAllFromUser(_channel, _from);
} }
if (HistoryItem *item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) { if (auto item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) {
bool wasLast = (item->history()->lastMsg == item); bool wasLast = (item->history()->lastMsg == item);
item->destroy(); item->destroy();
@ -458,33 +455,11 @@ void RichDeleteMessageBox::onDelete() {
Ui::hideLayer(); Ui::hideLayer();
} }
KickMemberBox::KickMemberBox(PeerData *chat, UserData *member) ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
: ConfirmBox(lng_profile_sure_kick(lt_user, member->firstName), lang(lng_box_remove)) : _title(this, st::confirmInviteTitle)
, _chat(chat)
, _member(member) {
connect(this, SIGNAL(confirmed()), this, SLOT(onConfirm()));
}
void KickMemberBox::onConfirm() {
Ui::hideLayer();
if (auto chat = _chat->asChat()) {
App::main()->kickParticipant(chat, _member);
} else if (auto channel = _chat->asChannel()) {
App::api()->kickParticipant(channel, _member);
}
}
ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants) : AbstractBox()
, _title(this, st::confirmInviteTitle)
, _status(this, st::confirmInviteStatus) , _status(this, st::confirmInviteStatus)
, _photo(chatDefPhoto(0)) , _photo(chatDefPhoto(0))
, _participants(participants) , _participants(participants) {
, _join(this, lang(lng_group_invite_join), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
if (_participants.size() > 4) {
_participants.resize(4);
}
_title->setText(title); _title->setText(title);
QString status; QString status;
if (_participants.isEmpty() || _participants.size() >= count) { if (_participants.isEmpty() || _participants.size() >= count) {
@ -504,8 +479,21 @@ ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &pho
} }
} }
} }
}
int h = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _join->height() + st::boxButtonPadding.bottom(); void ConfirmInviteBox::prepare() {
addButton(lang(lng_group_invite_join), [this] {
if (auto main = App::main()) {
main->onInviteImport();
}
});
addButton(lang(lng_cancel), [this] { closeBox(); });
if (_participants.size() > 4) {
_participants.resize(4);
}
auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom();
if (!_participants.isEmpty()) { if (!_participants.isEmpty()) {
int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5; int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5;
int padding = skip / 2; int padding = skip / 2;
@ -520,24 +508,19 @@ ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &pho
left += _userWidth; left += _userWidth;
} }
h += st::confirmInviteUserHeight; newHeight += st::confirmInviteUserHeight;
} }
setMaxHeight(h); setDimensions(st::boxWideWidth, newHeight);
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_join, SIGNAL(clicked()), App::main(), SLOT(onInviteImport()));
} }
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) { void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop); _title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop);
_status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop); _status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop);
_join->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _join->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _join->width() + st::boxButtonPadding.left(), _join->y());
AbstractBox::resizeEvent(e);
} }
void ConfirmInviteBox::paintEvent(QPaintEvent *e) { void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);

View file

@ -24,138 +24,88 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class Checkbox; class Checkbox;
class RoundButton;
class FlatLabel; class FlatLabel;
} // namespace Ui } // namespace Ui
namespace st {
extern const style::RoundButton &defaultBoxButton;
extern const style::RoundButton &cancelBoxButton;
} // namespace style
class InformBox; class InformBox;
class ConfirmBox : public AbstractBox, public ClickHandlerHost { class ConfirmBox : public BoxContent, public ClickHandlerHost {
Q_OBJECT
public: public:
ConfirmBox(const QString &text, const QString &doneText = QString(), const style::RoundButton &doneStyle = st::defaultBoxButton, const QString &cancelText = QString(), const style::RoundButton &cancelStyle = st::cancelBoxButton); ConfirmBox(QWidget*, const QString &text, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const QString &cancelText, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
ConfirmBox(QWidget*, const QString &text, const QString &confirmText, const style::RoundButton &confirmStyle, const QString &cancelText, base::lambda<void()> &&confirmedCallback = base::lambda<void()>(), base::lambda<void()> &&cancelledCallback = base::lambda<void()>());
void updateLink(); void updateLink();
// You can use this instead of connecting to "confirmed()" signal. // If strict cancel is set the cancelledCallback is only called if the cancel button was pressed.
void setConfirmedCallback(base::lambda<void()> &&callback) { void setStrictCancel(bool strictCancel) {
_confirmedCallback = std_::move(callback); _strictCancel = strictCancel;
} }
// ClickHandlerHost interface // ClickHandlerHost interface
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override; void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
public slots: void closeHook() override;
void onCancel();
signals:
void confirmed();
void cancelled();
void cancelPressed();
protected: protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
void leaveEvent(QEvent *e) override; void leaveEvent(QEvent *e) override;
void closePressed() override;
private slots:
void onConfirmPressed();
private: private:
ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, bool informative); struct InformBoxTag {
};
ConfirmBox(const InformBoxTag &, const QString &text, const QString &doneText, base::lambda_copy<void()> &&closedCallback);
friend class InformBox; friend class InformBox;
void confirmed();
void init(const QString &text); void init(const QString &text);
void onTextUpdated(); void textUpdated();
bool _informative; QString _confirmText;
QString _cancelText;
const style::RoundButton &_confirmStyle;
bool _informative = false;
Text _text; Text _text;
int32 _textWidth, _textHeight; int _textWidth = 0;
int _textHeight = 0;
void updateHover(); void updateHover();
QPoint _lastMousePos; QPoint _lastMousePos;
ChildWidget<Ui::RoundButton> _confirm; bool _confirmed = false;
ChildWidget<Ui::RoundButton> _cancel; bool _cancelled = false;
bool _strictCancel = false;
base::lambda<void()> _confirmedCallback; base::lambda<void()> _confirmedCallback;
base::lambda<void()> _cancelledCallback;
}; };
class InformBox : public ConfirmBox { class InformBox : public ConfirmBox {
public: public:
InformBox(const QString &text, const QString &doneText = QString(), const style::RoundButton &doneStyle = st::defaultBoxButton) : ConfirmBox(text, doneText, doneStyle, true) { 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)) {
} }
}; };
class SharePhoneConfirmBox : public ConfirmBox { class MaxInviteBox : public BoxContent {
Q_OBJECT
public: public:
SharePhoneConfirmBox(PeerData *recipient); MaxInviteBox(QWidget*, const QString &link);
signals:
void confirmed(PeerData *recipient);
private slots:
void onConfirm();
private:
PeerData *_recipient;
};
class ConfirmLinkBox : public ConfirmBox {
Q_OBJECT
public:
ConfirmLinkBox(const QString &url);
public slots:
void onOpenLink();
private:
QString _url;
};
class ConfirmBotGameBox : public ConfirmBox {
Q_OBJECT
public:
ConfirmBotGameBox(UserData *bot, const QString &url);
public slots:
void onOpenLink();
private:
UserData *_bot;
QString _url;
};
class MaxInviteBox : public AbstractBox {
Q_OBJECT
public:
MaxInviteBox(const QString &link);
protected: protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
@ -165,8 +115,6 @@ protected:
private: private:
void updateSelected(const QPoint &cursorGlobalPosition); void updateSelected(const QPoint &cursorGlobalPosition);
ChildWidget<Ui::RoundButton> _close;
Text _text; Text _text;
int32 _textWidth, _textHeight; int32 _textWidth, _textHeight;
@ -176,26 +124,20 @@ private:
QPoint _lastMousePos; QPoint _lastMousePos;
QString _goodTextLink;
Animation _a_goodOpacity;
}; };
class ConvertToSupergroupBox : public AbstractBox, public RPCSender { class ConvertToSupergroupBox : public BoxContent, public RPCSender {
Q_OBJECT
public: public:
ConvertToSupergroupBox(ChatData *chat); ConvertToSupergroupBox(QWidget*, ChatData *chat);
public slots:
void onConvert();
protected: protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private: private:
void convertToSupergroup();
void convertDone(const MTPUpdates &updates); void convertDone(const MTPUpdates &updates);
bool convertFail(const RPCError &error); bool convertFail(const RPCError &error);
@ -203,100 +145,71 @@ private:
Text _text, _note; Text _text, _note;
int32 _textWidth, _textHeight; int32 _textWidth, _textHeight;
ChildWidget<Ui::RoundButton> _convert;
ChildWidget<Ui::RoundButton> _cancel;
}; };
class PinMessageBox : public AbstractBox, public RPCSender { class PinMessageBox : public BoxContent, public RPCSender {
Q_OBJECT
public: public:
PinMessageBox(ChannelData *channel, MsgId msgId); PinMessageBox(QWidget*, ChannelData *channel, MsgId msgId);
public slots:
void onPin();
protected: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private: private:
void pinMessage();
void pinDone(const MTPUpdates &updates); void pinDone(const MTPUpdates &updates);
bool pinFail(const RPCError &error); bool pinFail(const RPCError &error);
ChannelData *_channel; ChannelData *_channel;
MsgId _msgId; MsgId _msgId;
ChildWidget<Ui::FlatLabel> _text; object_ptr<Ui::FlatLabel> _text;
ChildWidget<Ui::Checkbox> _notify; object_ptr<Ui::Checkbox> _notify;
ChildWidget<Ui::RoundButton> _pin;
ChildWidget<Ui::RoundButton> _cancel;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
}; };
class RichDeleteMessageBox : public AbstractBox, public RPCSender { class RichDeleteMessageBox : public BoxContent, public RPCSender {
Q_OBJECT
public: public:
RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId); RichDeleteMessageBox(QWidget*, ChannelData *channel, UserData *from, MsgId msgId);
public slots:
void onDelete();
protected: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private: private:
void deleteAndClear();
ChannelData *_channel; ChannelData *_channel;
UserData *_from; UserData *_from;
MsgId _msgId; MsgId _msgId;
ChildWidget<Ui::FlatLabel> _text; object_ptr<Ui::FlatLabel> _text;
ChildWidget<Ui::Checkbox> _banUser; object_ptr<Ui::Checkbox> _banUser;
ChildWidget<Ui::Checkbox> _reportSpam; object_ptr<Ui::Checkbox> _reportSpam;
ChildWidget<Ui::Checkbox> _deleteAll; object_ptr<Ui::Checkbox> _deleteAll;
ChildWidget<Ui::RoundButton> _delete;
ChildWidget<Ui::RoundButton> _cancel;
}; };
class KickMemberBox : public ConfirmBox { class ConfirmInviteBox : public BoxContent, public RPCSender {
Q_OBJECT
public: public:
KickMemberBox(PeerData *chat, UserData *member); ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
private slots:
void onConfirm();
private:
PeerData *_chat;
UserData *_member;
};
class ConfirmInviteBox : public AbstractBox, public RPCSender {
Q_OBJECT
public:
ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
protected: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
private: private:
ChildWidget<Ui::FlatLabel> _title; object_ptr<Ui::FlatLabel> _title;
ChildWidget<Ui::FlatLabel> _status; object_ptr<Ui::FlatLabel> _status;
ImagePtr _photo; ImagePtr _photo;
QVector<UserData*> _participants; QVector<UserData*> _participants;
ChildWidget<Ui::RoundButton> _join;
ChildWidget<Ui::RoundButton> _cancel;
int _userWidth = 0; int _userWidth = 0;
}; };

View file

@ -31,24 +31,30 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace { namespace {
QPointer<ConfirmPhoneBox> CurrentConfirmPhoneBox = nullptr; object_ptr<ConfirmPhoneBox> CurrentConfirmPhoneBox = { nullptr };
} // namespace } // namespace
void ConfirmPhoneBox::start(const QString &phone, const QString &hash) { void ConfirmPhoneBox::start(const QString &phone, const QString &hash) {
if (CurrentConfirmPhoneBox) { if (CurrentConfirmPhoneBox && CurrentConfirmPhoneBox->getPhone() != phone) {
if (CurrentConfirmPhoneBox->getPhone() == phone) return; CurrentConfirmPhoneBox.destroyDelayed();
delete CurrentConfirmPhoneBox;
} }
if (auto main = App::main()) { if (!CurrentConfirmPhoneBox) {
CurrentConfirmPhoneBox = new ConfirmPhoneBox(main, phone, hash); CurrentConfirmPhoneBox = Box<ConfirmPhoneBox>(phone, hash);
} }
CurrentConfirmPhoneBox->checkPhoneAndHash();
} }
ConfirmPhoneBox::ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash) : AbstractBox(st::boxWidth, lang(lng_confirm_phone_title)) ConfirmPhoneBox::ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash)
, _phone(phone) : _phone(phone)
, _hash(hash) { , _hash(hash)
setParent(parent); , _callTimer(this) {
}
void ConfirmPhoneBox::checkPhoneAndHash() {
if (_sendCodeRequestId) {
return;
}
MTPaccount_SendConfirmPhoneCode::Flags flags = 0; MTPaccount_SendConfirmPhoneCode::Flags flags = 0;
_sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(flags), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail)); _sendCodeRequestId = MTP::send(MTPaccount_SendConfirmPhoneCode(MTP_flags(flags), MTP_string(_hash), MTPBool()), rpcDone(&ConfirmPhoneBox::sendCodeDone), rpcFail(&ConfirmPhoneBox::sendCodeFail));
@ -83,20 +89,28 @@ bool ConfirmPhoneBox::sendCodeFail(const RPCError &error) {
errorText = lang(lng_confirm_phone_link_invalid); errorText = lang(lng_confirm_phone_link_invalid);
} }
_sendCodeRequestId = 0; _sendCodeRequestId = 0;
Ui::showLayer(new InformBox(errorText)); Ui::show(Box<InformBox>(errorText));
deleteLater(); if (this == CurrentConfirmPhoneBox) {
CurrentConfirmPhoneBox.destroyDelayed();
} else {
deleteLater();
}
return true; return true;
} }
void ConfirmPhoneBox::setCallStatus(const CallStatus &status) { void ConfirmPhoneBox::setCallStatus(const CallStatus &status) {
_callStatus = status; _callStatus = status;
if (_callStatus.state == CallState::Waiting) { if (_callStatus.state == CallState::Waiting) {
_callTimer.start(1000); _callTimer->start(1000);
} }
} }
void ConfirmPhoneBox::launch() { void ConfirmPhoneBox::launch() {
setBlockTitle(true); if (!CurrentConfirmPhoneBox) return;
Ui::show(std_::move(CurrentConfirmPhoneBox));
}
void ConfirmPhoneBox::prepare() {
_about.create(this, st::confirmPhoneAboutLabel); _about.create(this, st::confirmPhoneAboutLabel);
TextWithEntities aboutText; TextWithEntities aboutText;
@ -110,30 +124,26 @@ void ConfirmPhoneBox::launch() {
_code.create(this, st::confirmPhoneCodeField, lang(lng_code_ph)); _code.create(this, st::confirmPhoneCodeField, lang(lng_code_ph));
_send.create(this, lang(lng_confirm_phone_send), st::defaultBoxButton); setTitle(lang(lng_confirm_phone_title));
_cancel.create(this, lang(lng_cancel), st::cancelBoxButton);
setMaxHeight(titleHeight() + st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip + _send->height() + st::boxButtonPadding.bottom()); addButton(lang(lng_confirm_phone_send), [this] { onSendCode(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_send, SIGNAL(clicked()), this, SLOT(onSendCode())); setDimensions(st::boxWidth, st::usernamePadding.top() + _code->height() + st::usernameSkip + _about->height() + st::usernameSkip);
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_code, SIGNAL(changed()), this, SLOT(onCodeChanged())); connect(_code, SIGNAL(changed()), this, SLOT(onCodeChanged()));
connect(_code, SIGNAL(submitted(bool)), this, SLOT(onSendCode())); connect(_code, SIGNAL(submitted(bool)), this, SLOT(onSendCode()));
connect(&_callTimer, SIGNAL(timeout()), this, SLOT(onCallStatusTimer())); connect(_callTimer, SIGNAL(timeout()), this, SLOT(onCallStatusTimer()));
showChildren(); showChildren();
raiseShadow();
Ui::showLayer(this);
} }
void ConfirmPhoneBox::onCallStatusTimer() { void ConfirmPhoneBox::onCallStatusTimer() {
if (_callStatus.state == CallState::Waiting) { if (_callStatus.state == CallState::Waiting) {
if (--_callStatus.timeout <= 0) { if (--_callStatus.timeout <= 0) {
_callStatus.state = CallState::Calling; _callStatus.state = CallState::Calling;
_callTimer.stop(); _callTimer->stop();
MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_phoneHash)), rpcDone(&ConfirmPhoneBox::callDone)); MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_phoneHash)), rpcDone(&ConfirmPhoneBox::callDone));
} }
} }
@ -167,7 +177,7 @@ void ConfirmPhoneBox::onSendCode() {
void ConfirmPhoneBox::confirmDone(const MTPBool &result) { void ConfirmPhoneBox::confirmDone(const MTPBool &result) {
_sendCodeRequestId = 0; _sendCodeRequestId = 0;
Ui::showLayer(new InformBox(lng_confirm_phone_success(lt_phone, App::formatPhone(_phone)))); Ui::show(Box<InformBox>(lng_confirm_phone_success(lt_phone, App::formatPhone(_phone))));
} }
bool ConfirmPhoneBox::confirmFail(const RPCError &error) { bool ConfirmPhoneBox::confirmFail(const RPCError &error) {
@ -248,7 +258,7 @@ void ConfirmPhoneBox::showError(const QString &error) {
} }
void ConfirmPhoneBox::paintEvent(QPaintEvent *e) { void ConfirmPhoneBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -291,18 +301,15 @@ QString ConfirmPhoneBox::getCallText() const {
} }
void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) { void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_code->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _code->height()); _code->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _code->height());
_code->moveToLeft(st::usernamePadding.left(), titleHeight() + st::usernamePadding.top()); _code->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
_about->moveToLeft(st::usernamePadding.left(), _code->y() + _code->height() + st::usernameSkip); _about->moveToLeft(st::usernamePadding.left(), _code->y() + _code->height() + st::usernameSkip);
_send->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _send->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y());
AbstractBox::resizeEvent(e);
} }
void ConfirmPhoneBox::doSetInnerFocus() { void ConfirmPhoneBox::setInnerFocus() {
_code->setFocus(); _code->setFocus();
} }

View file

@ -24,11 +24,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class InputField; class InputField;
class RoundButton;
class FlatLabel; class FlatLabel;
} // namespace Ui } // namespace Ui
class ConfirmPhoneBox : public AbstractBox, public RPCSender { class ConfirmPhoneBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
@ -42,12 +41,18 @@ private slots:
void onCodeChanged(); void onCodeChanged();
protected: protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash); ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash);
friend class object_ptr<ConfirmPhoneBox>;
void checkPhoneAndHash();
void sendCodeDone(const MTPauth_SentCode &result); void sendCodeDone(const MTPauth_SentCode &result);
bool sendCodeFail(const RPCError &error); bool sendCodeFail(const RPCError &error);
@ -88,16 +93,14 @@ private:
mtpRequestId _checkCodeRequestId = 0; mtpRequestId _checkCodeRequestId = 0;
ChildWidget<Ui::FlatLabel> _about = { nullptr }; object_ptr<Ui::FlatLabel> _about = { nullptr };
ChildWidget<Ui::RoundButton> _send = { nullptr }; object_ptr<Ui::InputField> _code = { nullptr };
ChildWidget<Ui::RoundButton> _cancel = { nullptr };
ChildWidget<Ui::InputField> _code = { nullptr };
// Flag for not calling onTextChanged() recursively. // Flag for not calling onTextChanged() recursively.
bool _fixing = false; bool _fixing = false;
QString _error; QString _error;
CallStatus _callStatus; CallStatus _callStatus;
QTimer _callTimer; object_ptr<QTimer> _callTimer;
}; };

View file

@ -31,20 +31,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_location_manager.h" #include "history/history_location_manager.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_header)) ConnectionBox::ConnectionBox(QWidget *parent)
, _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host) : _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host)
, _portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port)) , _portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port))
, _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), Global::ConnectionProxy().user) , _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), Global::ConnectionProxy().user)
, _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), Global::ConnectionProxy().password) , _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), Global::ConnectionProxy().password)
, _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (Global::ConnectionType() == dbictAuto), st::defaultBoxCheckbox) , _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (Global::ConnectionType() == dbictAuto), st::defaultBoxCheckbox)
, _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (Global::ConnectionType() == dbictHttpProxy), st::defaultBoxCheckbox) , _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (Global::ConnectionType() == dbictHttpProxy), st::defaultBoxCheckbox)
, _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (Global::ConnectionType() == dbictTcpProxy), st::defaultBoxCheckbox) , _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (Global::ConnectionType() == dbictTcpProxy), st::defaultBoxCheckbox)
, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) , _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) {
, _save(this, lang(lng_connection_save), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); void ConnectionBox::prepare() {
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); setTitle(lang(lng_connection_header));
addButton(lang(lng_connection_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_autoRadio, SIGNAL(changed()), this, SLOT(onChange())); connect(_autoRadio, SIGNAL(changed()), this, SLOT(onChange()));
connect(_httpProxyRadio, SIGNAL(changed()), this, SLOT(onChange())); connect(_httpProxyRadio, SIGNAL(changed()), this, SLOT(onChange()));
@ -59,9 +61,9 @@ ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_h
} }
void ConnectionBox::updateControlsVisibility() { void ConnectionBox::updateControlsVisibility() {
int32 h = titleHeight() + st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListPadding.top() + _httpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + _tcpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); auto newHeight = st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListSkip + _httpProxyRadio->heightNoMargins() + st::boxOptionListSkip + _tcpProxyRadio->heightNoMargins() + st::boxOptionListSkip + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) { if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) {
h += 2 * st::boxOptionInputSkip + 2 * _hostInput->height(); newHeight += 2 * st::boxOptionInputSkip + 2 * _hostInput->height();
_hostInput->show(); _hostInput->show();
_portInput->show(); _portInput->show();
_userInput->show(); _userInput->show();
@ -73,26 +75,32 @@ void ConnectionBox::updateControlsVisibility() {
_passwordInput->hide(); _passwordInput->hide();
} }
setMaxHeight(h); setDimensions(st::boxWidth, newHeight);
resizeEvent(0); updateControlsPosition();
} }
void ConnectionBox::doSetInnerFocus() { void ConnectionBox::setInnerFocus() {
if (!_hostInput->isHidden()) { if (!_hostInput->isHidden()) {
_hostInput->setFocus(); _hostInput->setFocus();
} }
} }
void ConnectionBox::resizeEvent(QResizeEvent *e) { void ConnectionBox::resizeEvent(QResizeEvent *e) {
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); BoxContent::resizeEvent(e);
_httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListPadding.top());
updateControlsPosition();
}
void ConnectionBox::updateControlsPosition() {
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
_httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListSkip);
int32 inputy = 0; int32 inputy = 0;
if (_httpProxyRadio->checked()) { if (_httpProxyRadio->checked()) {
inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip; inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListPadding.top()); _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip);
} else { } else {
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListPadding.top()); _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListSkip);
if (_tcpProxyRadio->checked()) { if (_tcpProxyRadio->checked()) {
inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip; inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
} }
@ -105,13 +113,8 @@ void ConnectionBox::resizeEvent(QResizeEvent *e) {
_passwordInput->moveToRight(st::boxPadding.right(), _userInput->y()); _passwordInput->moveToRight(st::boxPadding.right(), _userInput->y());
} }
int32 tryipv6y = (_tcpProxyRadio->checked() ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListPadding.top() + st::connectionIPv6Skip; auto tryipv6y = (_tcpProxyRadio->checked() ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListSkip + st::connectionIPv6Skip;
_tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y); _tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void ConnectionBox::onChange() { void ConnectionBox::onChange() {
@ -195,55 +198,52 @@ void ConnectionBox::onSave() {
MTP::restart(); MTP::restart();
reinitLocationManager(); reinitLocationManager();
reinitWebLoadManager(); reinitWebLoadManager();
onClose(); closeBox();
} }
} }
AutoDownloadBox::AutoDownloadBox() : AbstractBox(st::boxWidth) AutoDownloadBox::AutoDownloadBox(QWidget *parent)
, _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox) : _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox)
, _photoGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadPhoto() & dbiadNoGroups), st::defaultBoxCheckbox) , _photoGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadPhoto() & dbiadNoGroups), st::defaultBoxCheckbox)
, _audioPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadAudio() & dbiadNoPrivate), st::defaultBoxCheckbox) , _audioPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadAudio() & dbiadNoPrivate), st::defaultBoxCheckbox)
, _audioGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadAudio() & dbiadNoGroups), st::defaultBoxCheckbox) , _audioGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadAudio() & dbiadNoGroups), st::defaultBoxCheckbox)
, _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate), st::defaultBoxCheckbox) , _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate), st::defaultBoxCheckbox)
, _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups), st::defaultBoxCheckbox) , _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups), st::defaultBoxCheckbox)
, _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif(), st::defaultBoxCheckbox) , _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif(), st::defaultBoxCheckbox)
, _sectionHeight(titleHeight() + 2 * (st::defaultBoxCheckbox.height + st::setLittleSkip)) , _sectionHeight(st::boxTitleHeight + 2 * (st::defaultBoxCheckbox.height + st::setLittleSkip)) {
, _save(this, lang(lng_connection_save), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
setMaxHeight(3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); void AutoDownloadBox::prepare() {
addButton(lang(lng_connection_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); setDimensions(st::boxWidth, 3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip);
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
} }
void AutoDownloadBox::paintEvent(QPaintEvent *e) { void AutoDownloadBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
p.setPen(st::boxTextFg); p.setPen(st::boxTitleFg);
p.setFont(st::semiboldFont); p.setFont(st::autoDownloadTitleFont);
p.drawTextLeft(st::boxTitlePosition.x(), st::boxTitlePosition.y(), width(), lang(lng_media_auto_photo)); p.drawTextLeft(st::autoDownloadTitlePosition.x(), st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_photo));
p.drawTextLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_audio)); p.drawTextLeft(st::autoDownloadTitlePosition.x(), _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_audio));
p.drawTextLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitlePosition.y(), width(), lang(lng_media_auto_gif)); p.drawTextLeft(st::autoDownloadTitlePosition.x(), 2 * _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_gif));
} }
void AutoDownloadBox::resizeEvent(QResizeEvent *e) { void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
_photoPrivate->moveToLeft(st::boxTitlePosition.x(), titleHeight() + st::setLittleSkip); BoxContent::resizeEvent(e);
_photoPrivate->moveToLeft(st::boxTitlePosition.x(), st::boxTitleHeight + st::setLittleSkip);
_photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip); _photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip);
_audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + titleHeight() + st::setLittleSkip); _audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + st::boxTitleHeight + st::setLittleSkip);
_audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip); _audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip);
_gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + titleHeight() + st::setLittleSkip); _gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + st::boxTitleHeight + st::setLittleSkip);
_gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip); _gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip);
_gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip); _gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void AutoDownloadBox::onSave() { void AutoDownloadBox::onSave() {
@ -299,5 +299,5 @@ void AutoDownloadBox::onSave() {
changed = true; changed = true;
} }
if (changed) Local::writeUserSettings(); if (changed) Local::writeUserSettings();
onClose(); closeBox();
} }

View file

@ -28,67 +28,64 @@ class PortInput;
class PasswordInput; class PasswordInput;
class Checkbox; class Checkbox;
class Radiobutton; class Radiobutton;
class RoundButton;
} // namespace Ui } // namespace Ui
class ConnectionBox : public AbstractBox { class ConnectionBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
ConnectionBox(); ConnectionBox(QWidget *parent);
public slots: protected:
void prepare() override;
void setInnerFocus() override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onChange(); void onChange();
void onSubmit(); void onSubmit();
void onSave(); void onSave();
protected:
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void updateControlsVisibility(); void updateControlsVisibility();
void updateControlsPosition();
ChildWidget<Ui::InputField> _hostInput; object_ptr<Ui::InputField> _hostInput;
ChildWidget<Ui::PortInput> _portInput; object_ptr<Ui::PortInput> _portInput;
ChildWidget<Ui::InputField> _userInput; object_ptr<Ui::InputField> _userInput;
ChildWidget<Ui::PasswordInput> _passwordInput; object_ptr<Ui::PasswordInput> _passwordInput;
ChildWidget<Ui::Radiobutton> _autoRadio; object_ptr<Ui::Radiobutton> _autoRadio;
ChildWidget<Ui::Radiobutton> _httpProxyRadio; object_ptr<Ui::Radiobutton> _httpProxyRadio;
ChildWidget<Ui::Radiobutton> _tcpProxyRadio; object_ptr<Ui::Radiobutton> _tcpProxyRadio;
ChildWidget<Ui::Checkbox> _tryIPv6; object_ptr<Ui::Checkbox> _tryIPv6;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
}; };
class AutoDownloadBox : public AbstractBox { class AutoDownloadBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
AutoDownloadBox(); AutoDownloadBox(QWidget *parent);
public slots:
void onSave();
protected: protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private slots:
void onSave();
private: private:
ChildWidget<Ui::Checkbox> _photoPrivate; object_ptr<Ui::Checkbox> _photoPrivate;
ChildWidget<Ui::Checkbox> _photoGroups; object_ptr<Ui::Checkbox> _photoGroups;
ChildWidget<Ui::Checkbox> _audioPrivate; object_ptr<Ui::Checkbox> _audioPrivate;
ChildWidget<Ui::Checkbox> _audioGroups; object_ptr<Ui::Checkbox> _audioGroups;
ChildWidget<Ui::Checkbox> _gifPrivate; object_ptr<Ui::Checkbox> _gifPrivate;
ChildWidget<Ui::Checkbox> _gifGroups; object_ptr<Ui::Checkbox> _gifGroups;
ChildWidget<Ui::Checkbox> _gifPlay; object_ptr<Ui::Checkbox> _gifPlay;
int _sectionHeight; int _sectionHeight = 0;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
}; };

View file

@ -47,76 +47,84 @@ QString cantInviteError() {
return lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info))); return lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info)));
} }
ContactsBox::ContactsBox() : ItemListBox(st::contactsScroll) ContactsBox::ContactsBox(QWidget*, ChatData *chat, MembersFilter filter)
, _inner(this, CreatingGroupNone) : _chat(chat)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) , _membersFilter(filter)
, _next(this, lang(lng_create_group_next), st::defaultBoxButton) , _select(createMultiSelect())
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) , _searchTimer(this) {
, _topShadow(this) {
init();
} }
ContactsBox::ContactsBox(const QString &name, const QImage &photo) : ItemListBox(st::boxScroll) ContactsBox::ContactsBox(QWidget*, ChannelData *channel)
, _inner(this, CreatingGroupGroup) : _creating(CreatingGroupChannel)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) , _channel(channel)
, _next(this, lang(lng_create_group_create), st::defaultBoxButton) , _select(createMultiSelect())
, _cancel(this, lang(lng_create_group_back), st::cancelBoxButton) , _searchTimer(this) {
, _topShadow(this) }
ContactsBox::ContactsBox(QWidget*, ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already)
: _channel(channel)
, _membersFilter(filter)
, _alreadyIn(already)
, _select(createMultiSelect())
, _searchTimer(this) {
}
ContactsBox::ContactsBox(QWidget*, UserData *bot)
: _bot(bot)
, _select(createMultiSelect())
, _searchTimer(this) {
}
ContactsBox::ContactsBox(QWidget*, const QString &name, const QImage &photo)
: _creating(CreatingGroupGroup)
, _select(createMultiSelect())
, _searchTimer(this)
, _creationName(name) , _creationName(name)
, _creationPhoto(photo) { , _creationPhoto(photo) {
init();
} }
ContactsBox::ContactsBox(ChannelData *channel) : ItemListBox(st::boxScroll) ContactsBox::ContactsBox(QWidget*)
, _inner(this, channel, MembersFilter::Recent, MembersAlreadyIn()) : _select(createMultiSelect())
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); }) , _searchTimer(this) {
, _next(this, lang(lng_participant_invite), st::defaultBoxButton)
, _cancel(this, lang(lng_create_group_skip), st::cancelBoxButton)
, _topShadow(this) {
init();
} }
ContactsBox::ContactsBox(ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already) : ItemListBox((filter == MembersFilter::Admins) ? st::contactsScroll : st::boxScroll) void ContactsBox::prepare() {
, _inner(this, channel, filter, already)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang(lng_participant_invite), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) {
init();
}
ContactsBox::ContactsBox(ChatData *chat, MembersFilter filter) : ItemListBox(st::boxScroll)
, _inner(this, chat, filter)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang((filter == MembersFilter::Admins) ? lng_settings_save : lng_participant_invite), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) {
init();
}
ContactsBox::ContactsBox(UserData *bot) : ItemListBox(st::contactsScroll)
, _inner(this, bot)
, _select(this, new Ui::MultiSelect(this, st::contactsMultiSelect, lang(lng_participant_filter)), QMargins(0, 0, 0, 0), [this] { updateScrollSkips(); })
, _next(this, lang(lng_create_group_next), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) {
init();
}
void ContactsBox::init() {
_select->resizeToWidth(st::boxWideWidth); _select->resizeToWidth(st::boxWideWidth);
myEnsureResized(_select); myEnsureResized(_select);
auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat(); auto createInner = [this] {
auto topSkip = getTopScrollSkip(); if (_chat) {
auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip; return object_ptr<Inner>(this, _chat, _membersFilter);
ItemListBox::init(_inner, bottomSkip, topSkip); } else if (_channel) {
return object_ptr<Inner>(this, _channel, _membersFilter, _alreadyIn);
} else if (_bot) {
return object_ptr<Inner>(this, _bot);
}
return object_ptr<Inner>(this, _creating);
};
_inner = setInnerWidget(createInner(), getTopScrollSkip());
if (_inner->creating() == CreatingGroupNone && !_inner->chat() && !_inner->channel() && !_inner->bot()) { updateTitle();
_add.create(this, st::contactsAdd); if (_chat) {
_add->setClickedCallback([] { if (_membersFilter == MembersFilter::Admins) {
App::wnd()->onShowAddContact(); addButton(lang(lng_settings_save), [this] { saveChatAdmins(); });
}); } else {
addButton(lang(lng_participant_invite), [this] { inviteParticipants(); });
}
addButton(lang(lng_cancel), [this] { closeBox(); });
} else if (_channel) {
if (_membersFilter != MembersFilter::Admins) {
addButton(lang(lng_participant_invite), [this] { inviteParticipants(); });
}
addButton(lang((_creating == CreatingGroupChannel) ? lng_create_group_skip : lng_cancel), [this] { closeBox(); });
} else if (_bot) {
addButton(lang(lng_close), [this] { closeBox(); });
} else if (_creating == CreatingGroupGroup) {
addButton(lang(lng_create_group_create), [this] { createGroup(); });
addButton(lang(lng_create_group_back), [this] { closeBox(); });
} else {
addButton(lang(lng_close), [this] { closeBox(); });
addLeftButton(lang(lng_profile_add_contact), [] { App::wnd()->onShowAddContact(); });
} }
_inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) { _inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) {
@ -141,24 +149,6 @@ void ContactsBox::init() {
} else { } else {
_select->showFast(); _select->showFast();
} }
if (_inner->channel() && _inner->membersFilter() == MembersFilter::Admins) {
_next->hide();
_cancel->hide();
} else if (_inner->chat() && _inner->membersFilter() == MembersFilter::Admins) {
connect(_next, SIGNAL(clicked()), this, SLOT(onSaveAdmins()));
_bottomShadow.create(this);
} else if (_inner->chat() || _inner->channel()) {
connect(_next, SIGNAL(clicked()), this, SLOT(onInvite()));
_bottomShadow.create(this);
} else if (_inner->creating() != CreatingGroupNone) {
connect(_next, SIGNAL(clicked()), this, SLOT(onCreate()));
_bottomShadow.create(this);
} else {
_next->hide();
_cancel->hide();
}
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
_select->entity()->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); }); _select->entity()->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
_select->entity()->setItemRemovedCallback([this](uint64 itemId) { _select->entity()->setItemRemovedCallback([this](uint64 itemId) {
if (auto peer = App::peerLoaded(itemId)) { if (auto peer = App::peerLoaded(itemId)) {
@ -167,14 +157,16 @@ void ContactsBox::init() {
} }
}); });
_select->entity()->setSubmittedCallback([this](bool) { onSubmit(); }); _select->entity()->setSubmittedCallback([this](bool) { onSubmit(); });
connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int))); connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int)));
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername())); connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
connect(_inner, SIGNAL(adminAdded()), this, SIGNAL(adminAdded())); connect(_inner, SIGNAL(adminAdded()), this, SIGNAL(adminAdded()));
_searchTimer.setSingleShot(true); _searchTimer->setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
raiseShadow(); setDimensions(st::boxWideWidth, st::boxMaxListHeight);
_select->raise();
} }
bool ContactsBox::onSearchByUsername(bool searchCache) { bool ContactsBox::onSearchByUsername(bool searchCache) {
@ -204,9 +196,26 @@ bool ContactsBox::onSearchByUsername(bool searchCache) {
return false; return false;
} }
void ContactsBox::updateTitle() {
if (_chat && _membersFilter == MembersFilter::Admins) {
setTitle(lang(lng_channel_admins));
} else if (_chat || _creating != CreatingGroupNone) {
auto addingAdmin = _channel && (_membersFilter == MembersFilter::Admins);
auto title = lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant);
auto additional = (addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax());
setTitle(title, additional);
} else if (_inner->sharingBotGame()) {
setTitle(lang(lng_bot_choose_chat));
} else if (_inner->bot()) {
setTitle(lang(lng_bot_choose_group));
} else {
setTitle(lang(lng_contacts_header));
}
}
void ContactsBox::onNeedSearchByUsername() { void ContactsBox::onNeedSearchByUsername() {
if (!onSearchByUsername(true)) { if (!onSearchByUsername(true)) {
_searchTimer.start(AutoSearchTimeout); _searchTimer->start(AutoSearchTimeout);
} }
} }
@ -231,7 +240,6 @@ void ContactsBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId r
_peopleRequest = 0; _peopleRequest = 0;
_inner->updateSelection(); _inner->updateSelection();
onScroll();
} }
} }
@ -245,7 +253,7 @@ bool ContactsBox::peopleFailed(const RPCError &error, mtpRequestId req) {
return true; return true;
} }
void ContactsBox::doSetInnerFocus() { void ContactsBox::setInnerFocus() {
if (_select->isHidden()) { if (_select->isHidden()) {
_inner->setFocus(); _inner->setFocus();
} else { } else {
@ -265,40 +273,26 @@ void ContactsBox::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Up) { } else if (e->key() == Qt::Key_Up) {
_inner->selectSkip(-1); _inner->selectSkip(-1);
} else if (e->key() == Qt::Key_PageDown) { } else if (e->key() == Qt::Key_PageDown) {
_inner->selectSkipPage(scrollArea()->height(), 1); _inner->selectSkipPage(height() - getTopScrollSkip(), 1);
} else if (e->key() == Qt::Key_PageUp) { } else if (e->key() == Qt::Key_PageUp) {
_inner->selectSkipPage(scrollArea()->height(), -1); _inner->selectSkipPage(height() - getTopScrollSkip(), -1);
} else { } else {
ItemListBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} else { } else {
ItemListBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void ContactsBox::paintEvent(QPaintEvent *e) { object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> ContactsBox::createMultiSelect() {
AbstractBox::paintEvent(e); auto entity = object_ptr<Ui::MultiSelect>(this, st::contactsMultiSelect, lang(lng_participant_filter));
auto margins = style::margins(0, 0, 0, 0);
Painter p(this); auto callback = [this] { updateScrollSkips(); };
return object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>>(this, std_::move(entity), margins, std_::move(callback));
bool addingAdmin = _inner->channel() && _inner->membersFilter() == MembersFilter::Admins;
if (_inner->chat() && _inner->membersFilter() == MembersFilter::Admins) {
paintTitle(p, lang(lng_channel_admins));
} else if (_inner->chat() || _inner->creating() != CreatingGroupNone) {
QString title(lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant));
QString additional((addingAdmin || (_inner->channel() && !_inner->channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner->selectedCount()).arg(Global::MegagroupSizeMax()));
paintTitle(p, title, additional);
} else if (_inner->sharingBotGame()) {
paintTitle(p, lang(lng_bot_choose_chat));
} else if (_inner->bot()) {
paintTitle(p, lang(lng_bot_choose_group));
} else {
paintTitle(p, lang(lng_contacts_header));
}
} }
int ContactsBox::getTopScrollSkip() const { int ContactsBox::getTopScrollSkip() const {
auto result = titleHeight(); auto result = 0;
if (!_select->isHidden()) { if (!_select->isHidden()) {
result += _select->height(); result += _select->height();
} }
@ -306,45 +300,28 @@ int ContactsBox::getTopScrollSkip() const {
} }
void ContactsBox::updateScrollSkips() { void ContactsBox::updateScrollSkips() {
auto oldScrollHeight = scrollArea()->height(); setInnerTopSkip(getTopScrollSkip(), true);
auto inviting = (_inner->creating() == CreatingGroupGroup) || (_inner->channel() && _inner->membersFilter() == MembersFilter::Recent) || _inner->chat();
auto topSkip = getTopScrollSkip();
auto bottomSkip = inviting ? (st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom()) : st::boxScrollSkip;
setScrollSkips(bottomSkip, topSkip);
auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight;
if (scrollHeightDelta) {
scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta);
}
_topShadow->setGeometry(0, topSkip, width(), st::lineWidth);
} }
void ContactsBox::resizeEvent(QResizeEvent *e) { void ContactsBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e); BoxContent::resizeEvent(e);
_select->resizeToWidth(width()); _select->resizeToWidth(width());
_select->moveToLeft(0, titleHeight()); _select->moveToLeft(0, 0);
updateScrollSkips(); updateScrollSkips();
if (_add) {
_add->moveToRight(st::contactsAddPosition.x(), height() - st::contactsAddPosition.y() - _add->height());
}
_inner->resize(width(), _inner->height()); _inner->resize(width(), _inner->height());
_next->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _next->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _next->width() + st::boxButtonPadding.left(), _next->y());
if (_bottomShadow) _bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _next->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
} }
void ContactsBox::closePressed() { void ContactsBox::closeHook() {
if (_inner->channel() && !_inner->hasAlreadyMembersInChannel()) { if (_channel && _creating == CreatingGroupChannel) {
Ui::showPeerHistory(_inner->channel(), ShowAtTheEndMsgId); Ui::showPeerHistory(_channel, ShowAtTheEndMsgId);
} }
} }
void ContactsBox::onFilterUpdate(const QString &filter) { void ContactsBox::onFilterUpdate(const QString &filter) {
scrollArea()->scrollToY(0); onScrollToY(0);
_inner->updateFilter(filter); _inner->updateFilter(filter);
} }
@ -361,10 +338,10 @@ void ContactsBox::onPeerSelectedChanged(PeerData *peer, bool checked) {
} else { } else {
_select->entity()->removeItem(peer->id); _select->entity()->removeItem(peer->id);
} }
update(); updateTitle();
} }
void ContactsBox::onInvite() { void ContactsBox::inviteParticipants() {
QVector<UserData*> users(_inner->selected()); QVector<UserData*> users(_inner->selected());
if (users.isEmpty()) { if (users.isEmpty()) {
_select->entity()->setInnerFocus(); _select->entity()->setInnerFocus();
@ -376,11 +353,11 @@ void ContactsBox::onInvite() {
Ui::hideLayer(); Ui::hideLayer();
Ui::showPeerHistory(_inner->chat(), ShowAtTheEndMsgId); Ui::showPeerHistory(_inner->chat(), ShowAtTheEndMsgId);
} else { } else {
onClose(); closeBox();
} }
} }
void ContactsBox::onCreate() { void ContactsBox::createGroup() {
if (_saveRequestId) return; if (_saveRequestId) return;
auto users = _inner->selectedInputs(); auto users = _inner->selectedInputs();
@ -391,7 +368,7 @@ void ContactsBox::onCreate() {
_saveRequestId = MTP::send(MTPmessages_CreateChat(MTP_vector<MTPInputUser>(users), MTP_string(_creationName)), rpcDone(&ContactsBox::creationDone), rpcFail(&ContactsBox::creationFail)); _saveRequestId = MTP::send(MTPmessages_CreateChat(MTP_vector<MTPInputUser>(users), MTP_string(_creationName)), rpcDone(&ContactsBox::creationDone), rpcFail(&ContactsBox::creationFail));
} }
void ContactsBox::onSaveAdmins() { void ContactsBox::saveChatAdmins() {
if (_saveRequestId) return; if (_saveRequestId) return;
_inner->saving(true); _inner->saving(true);
@ -405,7 +382,7 @@ void ContactsBox::saveAdminsDone(const MTPUpdates &result) {
void ContactsBox::saveSelectedAdmins() { void ContactsBox::saveSelectedAdmins() {
if (_inner->allAdmins() && !_inner->chat()->participants.isEmpty()) { if (_inner->allAdmins() && !_inner->chat()->participants.isEmpty()) {
onClose(); closeBox();
} else { } else {
_saveRequestId = MTP::send(MTPmessages_GetFullChat(_inner->chat()->inputChat), rpcDone(&ContactsBox::getAdminsDone), rpcFail(&ContactsBox::saveAdminsFail)); _saveRequestId = MTP::send(MTPmessages_GetFullChat(_inner->chat()->inputChat), rpcDone(&ContactsBox::getAdminsDone), rpcFail(&ContactsBox::saveAdminsFail));
} }
@ -414,7 +391,7 @@ void ContactsBox::saveSelectedAdmins() {
void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) { void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
App::api()->processFullPeer(_inner->chat(), result); App::api()->processFullPeer(_inner->chat(), result);
if (_inner->allAdmins()) { if (_inner->allAdmins()) {
onClose(); closeBox();
return; return;
} }
ChatData::Admins curadmins = _inner->chat()->admins; ChatData::Admins curadmins = _inner->chat()->admins;
@ -444,7 +421,7 @@ void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
_saveRequestId = curadmins.size() + appoint.size(); _saveRequestId = curadmins.size() + appoint.size();
if (!_saveRequestId) { if (!_saveRequestId) {
onClose(); closeBox();
} }
} }
@ -459,7 +436,7 @@ void ContactsBox::setAdminDone(UserData *user, const MTPBool &result) {
--_saveRequestId; --_saveRequestId;
if (!_saveRequestId) { if (!_saveRequestId) {
emit App::main()->peerUpdated(_inner->chat()); emit App::main()->peerUpdated(_inner->chat());
onClose(); closeBox();
} }
} }
@ -470,7 +447,7 @@ void ContactsBox::removeAdminDone(UserData *user, const MTPBool &result) {
--_saveRequestId; --_saveRequestId;
if (!_saveRequestId) { if (!_saveRequestId) {
emit App::main()->peerUpdated(_inner->chat()); emit App::main()->peerUpdated(_inner->chat());
onClose(); closeBox();
} }
} }
@ -490,18 +467,14 @@ bool ContactsBox::editAdminFail(const RPCError &error) {
_inner->chat()->invalidateParticipants(); _inner->chat()->invalidateParticipants();
if (!_saveRequestId) { if (!_saveRequestId) {
if (error.type() == qstr("USER_RESTRICTED")) { if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this))); Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
return true; return true;
} }
onClose(); closeBox();
} }
return false; return false;
} }
void ContactsBox::onScroll() {
_inner->loadProfilePhotos(scrollArea()->scrollTop());
}
void ContactsBox::creationDone(const MTPUpdates &updates) { void ContactsBox::creationDone(const MTPUpdates &updates) {
Ui::hideLayer(); Ui::hideLayer();
@ -532,16 +505,16 @@ bool ContactsBox::creationFail(const RPCError &error) {
_saveRequestId = 0; _saveRequestId = 0;
if (error.type() == "NO_CHAT_TITLE") { if (error.type() == "NO_CHAT_TITLE") {
onClose(); closeBox();
return true; return true;
} else if (error.type() == "USERS_TOO_FEW") { } else if (error.type() == "USERS_TOO_FEW") {
_select->entity()->setInnerFocus(); _select->entity()->setInnerFocus();
return true; return true;
} else if (error.type() == "PEER_FLOOD") { } else if (error.type() == "PEER_FLOOD") {
Ui::showLayer(new InformBox(cantInviteError()), KeepOtherLayers); Ui::show(Box<InformBox>(cantInviteError()), KeepOtherLayers);
return true; return true;
} else if (error.type() == qstr("USER_RESTRICTED")) { } else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this))); Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
return true; return true;
} }
return false; return false;
@ -649,6 +622,7 @@ void ContactsBox::Inner::init() {
connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
connect(_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged())); connect(_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged()));
_rowsTop = st::contactsMarginTop;
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
for_const (auto row, _contacts->all()) { for_const (auto row, _contacts->all()) {
@ -706,7 +680,7 @@ void ContactsBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names
peerUpdated(peer); peerUpdated(peer);
} }
void ContactsBox::Inner::onAddBot() { void ContactsBox::Inner::addBot() {
if (auto &info = _bot->botInfo) { if (auto &info = _bot->botInfo) {
if (!info->shareGameShortName.isEmpty()) { if (!info->shareGameShortName.isEmpty()) {
MTPmessages_SendMedia::Flags sendFlags = 0; MTPmessages_SendMedia::Flags sendFlags = 0;
@ -730,17 +704,6 @@ void ContactsBox::Inner::onAddBot() {
Ui::showPeerHistory(_addToPeer, ShowAtUnreadMsgId); Ui::showPeerHistory(_addToPeer, ShowAtUnreadMsgId);
} }
void ContactsBox::Inner::onAddAdmin() {
if (_addAdminRequestId) return;
_addAdminRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _addAdmin->inputUser, MTP_channelRoleEditor()), rpcDone(&Inner::addAdminDone), rpcFail(&Inner::addAdminFail));
}
void ContactsBox::Inner::onNoAddAdminBox(QObject *obj) {
if (obj == _addAdminBox) {
_addAdminBox = 0;
}
}
void ContactsBox::Inner::onAllAdminsChanged() { void ContactsBox::Inner::onAllAdminsChanged() {
if (_saving && _allAdmins->checked() != _allAdminsChecked) { if (_saving && _allAdmins->checked() != _allAdminsChecked) {
_allAdmins->setChecked(_allAdminsChecked); _allAdmins->setChecked(_allAdminsChecked);
@ -771,7 +734,7 @@ void ContactsBox::Inner::addAdminDone(const MTPUpdates &result, mtpRequestId req
} }
Notify::peerUpdatedDelayed(update); Notify::peerUpdatedDelayed(update);
} }
if (_addAdminBox) _addAdminBox->onClose(); if (_addAdminBox) _addAdminBox->closeBox();
emit adminAdded(); emit adminAdded();
} }
@ -781,13 +744,13 @@ bool ContactsBox::Inner::addAdminFail(const RPCError &error, mtpRequestId req) {
if (req != _addAdminRequestId) return true; if (req != _addAdminRequestId) return true;
_addAdminRequestId = 0; _addAdminRequestId = 0;
if (_addAdminBox) _addAdminBox->onClose(); if (_addAdminBox) _addAdminBox->closeBox();
if (error.type() == "USERS_TOO_MUCH") { if (error.type() == "USERS_TOO_MUCH") {
Ui::showLayer(new MaxInviteBox(_channel->inviteLink()), KeepOtherLayers); Ui::show(Box<MaxInviteBox>(_channel->inviteLink()), KeepOtherLayers);
} else if (error.type() == "ADMINS_TOO_MUCH") { } else if (error.type() == "ADMINS_TOO_MUCH") {
Ui::showLayer(new InformBox(lang(lng_channel_admins_too_much)), KeepOtherLayers); Ui::show(Box<InformBox>(lang(lng_channel_admins_too_much)), KeepOtherLayers);
} else if (error.type() == qstr("USER_RESTRICTED")) { } else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this)), KeepOtherLayers); Ui::show(Box<InformBox>(lang(lng_cant_do_this)), KeepOtherLayers);
} else { } else {
emit adminAdded(); emit adminAdded();
} }
@ -834,14 +797,14 @@ void ContactsBox::Inner::peerUpdated(PeerData *peer) {
for_const (auto row, _contacts->all()) { for_const (auto row, _contacts->all()) {
if (row->attached == i.value()) { if (row->attached == i.value()) {
row->attached = nullptr; row->attached = nullptr;
update(0, _aboutHeight + _rowHeight * row->pos(), width(), _rowHeight); update(0, _rowsTop + _aboutHeight + _rowHeight * row->pos(), width(), _rowHeight);
} }
} }
if (!_filter.isEmpty()) { if (!_filter.isEmpty()) {
for (int32 j = 0, s = _filtered.size(); j < s; ++j) { for (int32 j = 0, s = _filtered.size(); j < s; ++j) {
if (_filtered[j]->attached == i.value()) { if (_filtered[j]->attached == i.value()) {
_filtered[j]->attached = 0; _filtered[j]->attached = 0;
update(0, _rowHeight * j, width(), _rowHeight); update(0, _rowsTop + _rowHeight * j, width(), _rowHeight);
} }
} }
} }
@ -851,9 +814,11 @@ void ContactsBox::Inner::peerUpdated(PeerData *peer) {
} }
} }
void ContactsBox::Inner::loadProfilePhotos(int32 yFrom) { void ContactsBox::Inner::loadProfilePhotos() {
if (!parentWidget()) return; if (_visibleTop >= _visibleBottom) return;
int32 yTo = yFrom + parentWidget()->height() * 5;
auto yFrom = _visibleTop - _rowsTop;
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
MTP::clearLoaderPriorities(); MTP::clearLoaderPriorities();
if (yTo < 0) return; if (yTo < 0) return;
@ -870,10 +835,10 @@ void ContactsBox::Inner::loadProfilePhotos(int32 yFrom) {
} }
} }
} else if (!_filtered.isEmpty()) { } else if (!_filtered.isEmpty()) {
int32 from = yFrom / _rowHeight; auto from = yFrom / _rowHeight;
if (from < 0) from = 0; if (from < 0) from = 0;
if (from < _filtered.size()) { if (from < _filtered.size()) {
int32 to = (yTo / _rowHeight) + 1; auto to = (yTo / _rowHeight) + 1;
if (to > _filtered.size()) to = _filtered.size(); if (to > _filtered.size()) to = _filtered.size();
for (; from < to; ++from) { for (; from < to; ++from) {
@ -1047,8 +1012,10 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
p.fillRect(r, st::contactsBg); p.fillRect(r, st::contactsBg);
auto ms = getms(); auto ms = getms();
int32 yFrom = r.y(), yTo = r.y() + r.height(); auto yFrom = r.y(), yTo = r.y() + r.height();
auto skip = _rowsTop;
if (_filter.isEmpty()) { if (_filter.isEmpty()) {
skip += _aboutHeight;
if (!_contacts->isEmpty() || !_byUsername.isEmpty()) { if (!_contacts->isEmpty() || !_byUsername.isEmpty()) {
if (_aboutHeight) { if (_aboutHeight) {
auto infoTop = _allAdmins->bottomNoMargins() + st::contactsAllAdminsTop - st::lineWidth; auto infoTop = _allAdmins->bottomNoMargins() + st::contactsAllAdminsTop - st::lineWidth;
@ -1063,11 +1030,10 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
int aboutw = width() - st::contactsPadding.left() - st::contactsPadding.right(); int aboutw = width() - st::contactsPadding.left() - st::contactsPadding.right();
p.setPen(st::contactsAboutFg); p.setPen(st::contactsAboutFg);
(_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutTop, aboutw); (_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutTop, aboutw);
yFrom -= _aboutHeight;
yTo -= _aboutHeight;
p.translate(0, _aboutHeight);
} }
yFrom -= skip;
yTo -= skip;
p.translate(0, skip);
if (!_contacts->isEmpty()) { if (!_contacts->isEmpty()) {
auto i = _contacts->cfind(yFrom, _rowHeight); auto i = _contacts->cfind(yFrom, _rowHeight);
p.translate(0, (*i)->pos() * _rowHeight); p.translate(0, (*i)->pos() * _rowHeight);
@ -1103,7 +1069,7 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
} }
} else { } else {
QString text; QString text;
int32 skip = 0; skip = 0;
if (bot()) { if (bot()) {
text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups) : lng_contacts_loading); text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups) : lng_contacts_loading);
} else if (_chat && _membersFilter == MembersFilter::Admins) { } else if (_chat && _membersFilter == MembersFilter::Admins) {
@ -1126,8 +1092,8 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
} }
} else { } else {
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) {
p.setFont(st::noContactsFont->f); p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor->p); p.setPen(st::noContactsColor);
QString text; QString text;
if (bot()) { if (bot()) {
text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found) : lng_contacts_loading); text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found) : lng_contacts_loading);
@ -1138,6 +1104,9 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
} }
p.drawText(QRect(0, 0, width(), st::noContactsHeight), text, style::al_center); p.drawText(QRect(0, 0, width(), st::noContactsHeight), text, style::al_center);
} else { } else {
yFrom -= skip;
yTo -= skip;
p.translate(0, skip);
if (!_filtered.isEmpty()) { if (!_filtered.isEmpty()) {
int32 from = floorclamp(yFrom, _rowHeight, 0, _filtered.size()); int32 from = floorclamp(yFrom, _rowHeight, 0, _filtered.size());
int32 to = ceilclamp(yTo, _rowHeight, 0, _filtered.size()); int32 to = ceilclamp(yTo, _rowHeight, 0, _filtered.size());
@ -1177,15 +1146,15 @@ void ContactsBox::Inner::enterEvent(QEvent *e) {
int ContactsBox::Inner::getSelectedRowTop() const { int ContactsBox::Inner::getSelectedRowTop() const {
if (_filter.isEmpty()) { if (_filter.isEmpty()) {
if (_selected) { if (_selected) {
return _aboutHeight + (_selected->pos() * _rowHeight); return _rowsTop + _aboutHeight + (_selected->pos() * _rowHeight);
} else if (_searchedSelected >= 0) { } else if (_searchedSelected >= 0) {
return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_searchedSelected * _rowHeight); return _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_searchedSelected * _rowHeight);
} }
} else { } else {
if (_filteredSelected >= 0) { if (_filteredSelected >= 0) {
return (_filteredSelected * _rowHeight); return _rowsTop + (_filteredSelected * _rowHeight);
} else if (_searchedSelected >= 0) { } else if (_searchedSelected >= 0) {
return (_filtered.size() * _rowHeight + st::searchedBarHeight + _searchedSelected * _rowHeight); return _rowsTop + (_filtered.size() * _rowHeight + st::searchedBarHeight + _searchedSelected * _rowHeight);
} }
} }
return -1; return -1;
@ -1206,23 +1175,23 @@ int ContactsBox::Inner::getRowTopWithPeer(PeerData *peer) const {
if (_filter.isEmpty()) { if (_filter.isEmpty()) {
for (auto i = _contacts->cbegin(), end = _contacts->cend(); i != end; ++i) { for (auto i = _contacts->cbegin(), end = _contacts->cend(); i != end; ++i) {
if ((*i)->history()->peer == peer) { if ((*i)->history()->peer == peer) {
return _aboutHeight + ((*i)->pos() * _rowHeight); return _rowsTop + _aboutHeight + ((*i)->pos() * _rowHeight);
} }
} }
for (auto i = 0, count = _byUsername.size(); i != count; ++i) { for (auto i = 0, count = _byUsername.size(); i != count; ++i) {
if (_byUsername[i] == peer) { if (_byUsername[i] == peer) {
return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight); return _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight);
} }
} }
} else { } else {
for (auto i = 0, count = _filtered.size(); i != count; ++i) { for (auto i = 0, count = _filtered.size(); i != count; ++i) {
if (_filtered[i]->history()->peer == peer) { if (_filtered[i]->history()->peer == peer) {
return (i * _rowHeight); return _rowsTop + (i * _rowHeight);
} }
} }
for (auto i = 0, count = _byUsernameFiltered.size(); i != count; ++i) { for (auto i = 0, count = _byUsernameFiltered.size(); i != count; ++i) {
if (_byUsernameFiltered[i] == peer) { if (_byUsernameFiltered[i] == peer) {
return (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight); return _rowsTop + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (i * _rowHeight);
} }
} }
} }
@ -1415,10 +1384,10 @@ void ContactsBox::Inner::chooseParticipant() {
_addAdminRequestId = 0; _addAdminRequestId = 0;
} }
if (_addAdminBox) _addAdminBox->deleteLater(); if (_addAdminBox) _addAdminBox->deleteLater();
_addAdminBox = new ConfirmBox(lng_channel_admin_sure(lt_user, _addAdmin->firstName)); _addAdminBox = Ui::show(Box<ConfirmBox>(lng_channel_admin_sure(lt_user, _addAdmin->firstName), base::lambda_guarded(this, [this] {
connect(_addAdminBox, SIGNAL(confirmed()), this, SLOT(onAddAdmin())); if (_addAdminRequestId) return;
connect(_addAdminBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoAddAdminBox(QObject*))); _addAdminRequestId = MTP::send(MTPchannels_EditAdmin(_channel->inputChannel, _addAdmin->inputUser, MTP_channelRoleEditor()), rpcDone(&Inner::addAdminDone), rpcFail(&Inner::addAdminFail));
Ui::showLayer(_addAdminBox, KeepOtherLayers); })), KeepOtherLayers);
} else if (sharingBotGame()) { } else if (sharingBotGame()) {
_addToPeer = peer; _addToPeer = peer;
auto confirmText = [peer] { auto confirmText = [peer] {
@ -1427,14 +1396,14 @@ void ContactsBox::Inner::chooseParticipant() {
} }
return lng_bot_sure_share_game_group(lt_group, peer->name); return lng_bot_sure_share_game_group(lt_group, peer->name);
}; };
auto box = std_::make_unique<ConfirmBox>(confirmText()); Ui::show(Box<ConfirmBox>(confirmText(), base::lambda_guarded(this, [this] {
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot())); addBot();
Ui::showLayer(box.release(), KeepOtherLayers); })), KeepOtherLayers);
} else if (bot() && (peer->isChat() || peer->isMegagroup())) { } else if (bot() && (peer->isChat() || peer->isMegagroup())) {
_addToPeer = peer; _addToPeer = peer;
auto box = std_::make_unique<ConfirmBox>(lng_bot_sure_invite(lt_group, peer->name)); Ui::show(Box<ConfirmBox>(lng_bot_sure_invite(lt_group, peer->name), base::lambda_guarded(this, [this] {
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot())); addBot();
Ui::showLayer(box.release(), KeepOtherLayers); })), KeepOtherLayers);
} else { } else {
Ui::hideSettingsAndLayer(true); Ui::hideSettingsAndLayer(true);
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId); App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
@ -1457,9 +1426,9 @@ void ContactsBox::Inner::changeCheckState(ContactData *data, PeerData *peer) {
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) { } else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
changePeerCheckState(data, peer, true); changePeerCheckState(data, peer, true);
} else if (_channel && !_channel->isMegagroup()) { } else if (_channel && !_channel->isMegagroup()) {
Ui::showLayer(new MaxInviteBox(_channel->inviteLink()), KeepOtherLayers); Ui::show(Box<MaxInviteBox>(_channel->inviteLink()), KeepOtherLayers);
} else if (!_channel && selectedCount() >= Global::ChatSizeMax() && selectedCount() < Global::MegagroupSizeMax()) { } else if (!_channel && selectedCount() >= Global::ChatSizeMax() && selectedCount() < Global::MegagroupSizeMax()) {
Ui::showLayer(new InformBox(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers); Ui::show(Box<InformBox>(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers);
} }
} }
@ -1487,7 +1456,7 @@ void ContactsBox::Inner::changePeerCheckState(ContactData *data, PeerData *peer,
} }
} }
int32 ContactsBox::Inner::selectedCount() const { int ContactsBox::Inner::selectedCount() const {
auto result = _checkedContacts.size(); auto result = _checkedContacts.size();
if (_chat) { if (_chat) {
result += qMax(_chat->count, 1); result += qMax(_chat->count, 1);
@ -1499,11 +1468,18 @@ int32 ContactsBox::Inner::selectedCount() const {
return result; return result;
} }
void ContactsBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadProfilePhotos();
}
void ContactsBox::Inner::updateSelection() { void ContactsBox::Inner::updateSelection() {
if (!_mouseSelection) return; if (!_mouseSelection) return;
auto p = mapFromGlobal(_lastMousePos); auto p = mapFromGlobal(_lastMousePos);
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
p.setY(p.y() - _rowsTop);
if (_filter.isEmpty()) { if (_filter.isEmpty()) {
_filteredSelected = -1; _filteredSelected = -1;
setFilteredPressed(-1); setFilteredPressed(-1);
@ -1511,7 +1487,7 @@ void ContactsBox::Inner::updateSelection() {
p.setY(p.y() - _aboutHeight); p.setY(p.y() - _aboutHeight);
} }
auto selected = (in && (p.y() >= 0) && (p.y() < _contacts->size() * _rowHeight)) ? _contacts->rowAtY(p.y(), _rowHeight) : nullptr; auto selected = (in && (p.y() >= 0) && (p.y() < _contacts->size() * _rowHeight)) ? _contacts->rowAtY(p.y(), _rowHeight) : nullptr;
auto searchedSelected = (in && p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1; auto searchedSelected = (in && (p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight)) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
if (searchedSelected >= _byUsername.size()) searchedSelected = -1; if (searchedSelected >= _byUsername.size()) searchedSelected = -1;
if (_selected != selected || _searchedSelected != searchedSelected) { if (_selected != selected || _searchedSelected != searchedSelected) {
updateSelectedRow(); updateSelectedRow();
@ -1522,8 +1498,8 @@ void ContactsBox::Inner::updateSelection() {
} else { } else {
_selected = nullptr; _selected = nullptr;
setPressed(nullptr); setPressed(nullptr);
auto filteredSelected = (in && p.y() >= 0 && p.y() < _filtered.size() * _rowHeight) ? (p.y() / _rowHeight) : -1; auto filteredSelected = (in && (p.y() >= 0) && (p.y() < _filtered.size() * _rowHeight)) ? (p.y() / _rowHeight) : -1;
auto searchedSelected = (in && p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1; auto searchedSelected = (in && (p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight)) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
if (searchedSelected >= _byUsernameFiltered.size()) searchedSelected = -1; if (searchedSelected >= _byUsernameFiltered.size()) searchedSelected = -1;
if (_filteredSelected != filteredSelected || _searchedSelected != searchedSelected) { if (_filteredSelected != filteredSelected || _searchedSelected != searchedSelected) {
updateSelectedRow(); updateSelectedRow();
@ -1653,7 +1629,7 @@ void ContactsBox::Inner::updateFilter(QString filter) {
} }
} }
update(); update();
loadProfilePhotos(0); loadProfilePhotos();
} }
} }
@ -1760,10 +1736,10 @@ void ContactsBox::Inner::refresh() {
} }
if (!_contacts->isEmpty() || !_byUsername.isEmpty()) { if (!_contacts->isEmpty() || !_byUsername.isEmpty()) {
if (!_addContactLnk->isHidden()) _addContactLnk->hide(); if (!_addContactLnk->isHidden()) _addContactLnk->hide();
resize(width(), _aboutHeight + (_contacts->size() * _rowHeight) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * _rowHeight))); resize(width(), _rowsTop + _aboutHeight + (_contacts->size() * _rowHeight) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * _rowHeight)) + st::contactsMarginBottom);
} else if (_chat && _membersFilter == MembersFilter::Admins) { } else if (_chat && _membersFilter == MembersFilter::Admins) {
if (!_addContactLnk->isHidden()) _addContactLnk->hide(); if (!_addContactLnk->isHidden()) _addContactLnk->hide();
resize(width(), _aboutHeight + st::noContactsHeight); resize(width(), _rowsTop + _aboutHeight + st::noContactsHeight + st::contactsMarginBottom);
} else { } else {
if (cContactsReceived() && !bot()) { if (cContactsReceived() && !bot()) {
if (_addContactLnk->isHidden()) _addContactLnk->show(); if (_addContactLnk->isHidden()) _addContactLnk->show();
@ -1778,9 +1754,10 @@ void ContactsBox::Inner::refresh() {
if (!_addContactLnk->isHidden()) _addContactLnk->hide(); if (!_addContactLnk->isHidden()) _addContactLnk->hide();
resize(width(), st::noContactsHeight); resize(width(), st::noContactsHeight);
} else { } else {
resize(width(), (_filtered.size() * _rowHeight) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * _rowHeight))); resize(width(), _rowsTop + (_filtered.size() * _rowHeight) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * _rowHeight)) + st::contactsMarginBottom);
} }
} }
loadProfilePhotos();
update(); update();
} }
@ -1902,9 +1879,9 @@ void ContactsBox::Inner::selectSkip(int32 dir) {
} }
} }
if (_selected) { if (_selected) {
emit mustScrollTo(_aboutHeight + _selected->pos() * _rowHeight, _aboutHeight + (_selected->pos() + 1) * _rowHeight); emit mustScrollTo(_rowsTop + _aboutHeight + _selected->pos() * _rowHeight, _rowsTop + _aboutHeight + (_selected->pos() + 1) * _rowHeight);
} else if (_searchedSelected >= 0) { } else if (_searchedSelected >= 0) {
emit mustScrollTo(_aboutHeight + (_contacts->size() + _searchedSelected) * _rowHeight + st::searchedBarHeight, _aboutHeight + (_contacts->size() + _searchedSelected + 1) * _rowHeight + st::searchedBarHeight); emit mustScrollTo(_rowsTop + _aboutHeight + (_contacts->size() + _searchedSelected) * _rowHeight + st::searchedBarHeight, _rowsTop + _aboutHeight + (_contacts->size() + _searchedSelected + 1) * _rowHeight + st::searchedBarHeight);
} }
} else { } else {
int cur = (_filteredSelected >= 0) ? _filteredSelected : ((_searchedSelected >= 0) ? (_filtered.size() + _searchedSelected) : -1); int cur = (_filteredSelected >= 0) ? _filteredSelected : ((_searchedSelected >= 0) ? (_filtered.size() + _searchedSelected) : -1);
@ -1948,10 +1925,10 @@ void ContactsBox::Inner::selectSkip(int32 dir) {
} }
} }
if (_filteredSelected >= 0) { if (_filteredSelected >= 0) {
emit mustScrollTo(_filteredSelected * _rowHeight, (_filteredSelected + 1) * _rowHeight); emit mustScrollTo(_rowsTop + _filteredSelected * _rowHeight, _rowsTop + (_filteredSelected + 1) * _rowHeight);
} else if (_searchedSelected >= 0) { } else if (_searchedSelected >= 0) {
int skip = _filtered.size() * _rowHeight + st::searchedBarHeight; int skip = _filtered.size() * _rowHeight + st::searchedBarHeight;
emit mustScrollTo(skip + _searchedSelected * _rowHeight, skip + (_searchedSelected + 1) * _rowHeight); emit mustScrollTo(_rowsTop + skip + _searchedSelected * _rowHeight, _rowsTop + skip + (_searchedSelected + 1) * _rowHeight);
} }
} }
update(); update();

View file

@ -32,7 +32,6 @@ class IndexedList;
namespace Ui { namespace Ui {
class RippleAnimation; class RippleAnimation;
class RoundButton;
class LinkButton; class LinkButton;
class Checkbox; class Checkbox;
class MultiSelect; class MultiSelect;
@ -48,64 +47,79 @@ inline Ui::RoundImageCheckbox::PaintRoundImage PaintUserpicCallback(PeerData *pe
}; };
} }
class ContactsBox : public ItemListBox, public RPCSender { class ContactsBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
ContactsBox(); ContactsBox(QWidget*);
ContactsBox(const QString &name, const QImage &photo); // group creation ContactsBox(QWidget*, const QString &name, const QImage &photo); // group creation
ContactsBox(ChannelData *channel); // channel setup ContactsBox(QWidget*, ChannelData *channel); // channel setup
ContactsBox(ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already); ContactsBox(QWidget*, ChannelData *channel, MembersFilter filter, const MembersAlreadyIn &already);
ContactsBox(ChatData *chat, MembersFilter filter); ContactsBox(QWidget*, ChatData *chat, MembersFilter filter);
ContactsBox(UserData *bot); ContactsBox(QWidget*, UserData *bot);
void closeHook() override;
signals: signals:
void adminAdded(); void adminAdded();
private slots: private slots:
void onScroll();
void onInvite();
void onCreate();
void onSaveAdmins();
void onSubmit(); void onSubmit();
bool onSearchByUsername(bool searchCache = false); bool onSearchByUsername(bool searchCache = false);
void onNeedSearchByUsername(); void onNeedSearchByUsername();
protected: protected:
void prepare() override;
void setInnerFocus() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void closePressed() override;
void doSetInnerFocus() override;
private: private:
void init(); object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> createMultiSelect();
void updateTitle();
int getTopScrollSkip() const; int getTopScrollSkip() const;
void updateScrollSkips(); void updateScrollSkips();
void onFilterUpdate(const QString &filter); void onFilterUpdate(const QString &filter);
void onPeerSelectedChanged(PeerData *peer, bool checked); void onPeerSelectedChanged(PeerData *peer, bool checked);
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false); void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
class Inner; void saveChatAdmins();
ChildWidget<Inner> _inner; void inviteParticipants();
ChildWidget<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select; void createGroup();
ChildWidget<MembersAddButton> _add = { nullptr };
ChildWidget<Ui::RoundButton> _next;
ChildWidget<Ui::RoundButton> _cancel;
MembersFilter _membersFilter;
ChildWidget<ScrollableBoxShadow> _topShadow;
ChildWidget<ScrollableBoxShadow> _bottomShadow = { nullptr };
// global search
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req); void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
bool peopleFailed(const RPCError &error, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req);
QTimer _searchTimer; // saving admins
void saveAdminsDone(const MTPUpdates &result);
void saveSelectedAdmins();
void getAdminsDone(const MTPmessages_ChatFull &result);
void setAdminDone(UserData *user, const MTPBool &result);
void removeAdminDone(UserData *user, const MTPBool &result);
bool saveAdminsFail(const RPCError &error);
bool editAdminFail(const RPCError &error);
// group creation
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
ChatData *_chat = nullptr;
ChannelData *_channel = nullptr;
MembersFilter _membersFilter = MembersFilter::Recent;
UserData *_bot = nullptr;
CreatingGroupType _creating = CreatingGroupNone;
MembersAlreadyIn _alreadyIn;
object_ptr<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select;
class Inner;
QPointer<Inner> _inner;
object_ptr<QTimer> _searchTimer;
QString _peopleQuery; QString _peopleQuery;
bool _peopleFull; bool _peopleFull;
mtpRequestId _peopleRequest; mtpRequestId _peopleRequest;
@ -118,22 +132,9 @@ private:
mtpRequestId _saveRequestId = 0; mtpRequestId _saveRequestId = 0;
// saving admins
void saveAdminsDone(const MTPUpdates &result);
void saveSelectedAdmins();
void getAdminsDone(const MTPmessages_ChatFull &result);
void setAdminDone(UserData *user, const MTPBool &result);
void removeAdminDone(UserData *user, const MTPBool &result);
bool saveAdminsFail(const RPCError &error);
bool editAdminFail(const RPCError &error);
// group creation
QString _creationName; QString _creationName;
QImage _creationPhoto; QImage _creationPhoto;
void creationDone(const MTPUpdates &updates);
bool creationFail(const RPCError &e);
}; };
// This class is hold in header because it requires Qt preprocessing. // This class is hold in header because it requires Qt preprocessing.
@ -162,7 +163,6 @@ public:
_allAdminsChangedCallback = std_::move(allAdminsChangedCallback); _allAdminsChangedCallback = std_::move(allAdminsChangedCallback);
} }
void loadProfilePhotos(int32 yFrom);
void chooseParticipant(); void chooseParticipant();
void peopleReceived(const QString &query, const QVector<MTPPeer> &people); void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
@ -177,13 +177,15 @@ public:
bool sharingBotGame() const; bool sharingBotGame() const;
int32 selectedCount() const; int selectedCount() const;
bool hasAlreadyMembersInChannel() const { bool hasAlreadyMembersInChannel() const {
return !_already.isEmpty(); return !_already.isEmpty();
} }
void saving(bool flag); void saving(bool flag);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
~Inner(); ~Inner();
signals: signals:
@ -197,10 +199,6 @@ private slots:
void peerUpdated(PeerData *peer); void peerUpdated(PeerData *peer);
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void onAddBot();
void onAddAdmin();
void onNoAddAdminBox(QObject *obj);
void onAllAdminsChanged(); void onAllAdminsChanged();
protected: protected:
@ -233,6 +231,9 @@ private:
void setSearchedPressed(int pressed); void setSearchedPressed(int pressed);
void clearSearchedContactDatas(); void clearSearchedContactDatas();
void loadProfilePhotos();
void addBot();
void init(); void init();
void initList(); void initList();
@ -264,7 +265,10 @@ private:
base::lambda<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback; base::lambda<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
int _rowHeight; int _visibleTop = 0;
int _visibleBottom = 0;
int _rowHeight = 0;
int _rowsTop = 0;
int _aboutHeight = 0; int _aboutHeight = 0;
ChatData *_chat = nullptr; ChatData *_chat = nullptr;
@ -274,7 +278,7 @@ private:
CreatingGroupType _creating = CreatingGroupNone; CreatingGroupType _creating = CreatingGroupNone;
MembersAlreadyIn _already; MembersAlreadyIn _already;
ChildWidget<Ui::Checkbox> _allAdmins; object_ptr<Ui::Checkbox> _allAdmins;
int32 _aboutWidth; int32 _aboutWidth;
Text _aboutAllAdmins, _aboutAdmins; Text _aboutAllAdmins, _aboutAdmins;
base::lambda<void()> _allAdminsChangedCallback; base::lambda<void()> _allAdminsChangedCallback;
@ -282,7 +286,7 @@ private:
PeerData *_addToPeer = nullptr; PeerData *_addToPeer = nullptr;
UserData *_addAdmin = nullptr; UserData *_addAdmin = nullptr;
mtpRequestId _addAdminRequestId = 0; mtpRequestId _addAdminRequestId = 0;
ConfirmBox *_addAdminBox = nullptr; QPointer<ConfirmBox> _addAdminBox;
int32 _time; int32 _time;
@ -315,7 +319,7 @@ private:
int _searchedPressed = -1; int _searchedPressed = -1;
QPoint _lastMousePos; QPoint _lastMousePos;
ChildWidget<Ui::LinkButton> _addContactLnk; object_ptr<Ui::LinkButton> _addContactLnk;
bool _saving = false; bool _saving = false;
bool _allAdminsChecked = false; bool _allAdminsChecked = false;

View file

@ -29,19 +29,20 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "pspecific.h" #include "pspecific.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
DownloadPathBox::DownloadPathBox() : AbstractBox() DownloadPathBox::DownloadPathBox(QWidget *parent)
, _path(Global::DownloadPath()) : _path(Global::DownloadPath())
, _pathBookmark(Global::DownloadPathBookmark()) , _pathBookmark(Global::DownloadPathBookmark())
, _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty(), st::defaultBoxCheckbox) , _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty(), st::defaultBoxCheckbox)
, _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), (_path == qsl("tmp")), st::defaultBoxCheckbox) , _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), (_path == qsl("tmp")), st::defaultBoxCheckbox)
, _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), (!_path.isEmpty() && _path != qsl("tmp")), st::defaultBoxCheckbox) , _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), (!_path.isEmpty() && _path != qsl("tmp")), st::defaultBoxCheckbox)
, _pathLink(this, QString(), st::boxLinkButton) , _pathLink(this, QString(), st::boxLinkButton) {
, _save(this, lang(lng_connection_save), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
setTitleText(lang(lng_download_path_header));
connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); void DownloadPathBox::prepare() {
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); addButton(lang(lng_connection_save), [this] { save(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
setTitle(lang(lng_download_path_header));
connect(_default, SIGNAL(changed()), this, SLOT(onChange())); connect(_default, SIGNAL(changed()), this, SLOT(onChange()));
connect(_temp, SIGNAL(changed()), this, SLOT(onChange())); connect(_temp, SIGNAL(changed()), this, SLOT(onChange()));
@ -57,25 +58,25 @@ DownloadPathBox::DownloadPathBox() : AbstractBox()
void DownloadPathBox::updateControlsVisibility() { void DownloadPathBox::updateControlsVisibility() {
_pathLink->setVisible(_dir->checked()); _pathLink->setVisible(_dir->checked());
int32 h = titleHeight() + st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListPadding.top() + _temp->heightNoMargins() + st::boxOptionListPadding.top() + _dir->heightNoMargins(); auto newHeight = st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
if (_dir->checked()) h += st::downloadPathSkip + _pathLink->height(); if (_dir->checked()) {
h += st::boxOptionListPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); newHeight += st::downloadPathSkip + _pathLink->height();
}
newHeight += st::boxOptionListPadding.bottom();
setMaxHeight(h); setDimensions(st::boxWideWidth, newHeight);
} }
void DownloadPathBox::resizeEvent(QResizeEvent *e) { void DownloadPathBox::resizeEvent(QResizeEvent *e) {
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); BoxContent::resizeEvent(e);
_temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListPadding.top());
_dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListPadding.top()); _default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
int32 inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x(); _temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListSkip);
int32 inputy = _dir->bottomNoMargins() + st::downloadPathSkip; _dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListSkip);
auto inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x();
auto inputy = _dir->bottomNoMargins() + st::downloadPathSkip;
_pathLink->moveToLeft(inputx, inputy); _pathLink->moveToLeft(inputx, inputy);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void DownloadPathBox::onChange() { void DownloadPathBox::onChange() {
@ -114,15 +115,15 @@ void DownloadPathBox::onEditPath() {
cSetDialogLastPath(lastPath); cSetDialogLastPath(lastPath);
} }
void DownloadPathBox::onSave() { void DownloadPathBox::save() {
Global::SetDownloadPath(_default->checked() ? QString() : (_temp->checked() ? qsl("tmp") : _path)); Global::SetDownloadPath(_default->checked() ? QString() : (_temp->checked() ? qsl("tmp") : _path));
Global::SetDownloadPathBookmark((_default->checked() || _temp->checked()) ? QByteArray() : _pathBookmark); Global::SetDownloadPathBookmark((_default->checked() || _temp->checked()) ? QByteArray() : _pathBookmark);
Local::writeUserSettings(); Local::writeUserSettings();
Global::RefDownloadPathChanged().notify(); Global::RefDownloadPathChanged().notify();
onClose(); closeBox();
} }
void DownloadPathBox::setPathText(const QString &text) { void DownloadPathBox::setPathText(const QString &text) {
int32 availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right(); auto availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right();
_pathLink->setText(st::boxTextFont->elided(text, availw)); _pathLink->setText(st::boxTextFont->elided(text, availw));
} }

View file

@ -26,36 +26,34 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class Radiobutton; class Radiobutton;
class LinkButton; class LinkButton;
class RoundButton;
} // namespace Ui } // namespace Ui
class DownloadPathBox : public AbstractBox { class DownloadPathBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
DownloadPathBox(); DownloadPathBox(QWidget *parent);
public slots:
void onChange();
void onEditPath();
void onSave();
protected: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private slots:
void onChange();
void onEditPath();
private: private:
void save();
void updateControlsVisibility(); void updateControlsVisibility();
void setPathText(const QString &text); void setPathText(const QString &text);
QString _path; QString _path;
QByteArray _pathBookmark; QByteArray _pathBookmark;
ChildWidget<Ui::Radiobutton> _default; object_ptr<Ui::Radiobutton> _default;
ChildWidget<Ui::Radiobutton> _temp; object_ptr<Ui::Radiobutton> _temp;
ChildWidget<Ui::Radiobutton> _dir; object_ptr<Ui::Radiobutton> _dir;
ChildWidget<Ui::LinkButton> _pathLink; object_ptr<Ui::LinkButton> _pathLink;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
}; };

View file

@ -71,17 +71,18 @@ namespace {
const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace), replacesInRow = 7; const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace), replacesInRow = 7;
} }
EmojiBox::EmojiBox() : _esize(EmojiSizes[EIndex + 1]) { EmojiBox::EmojiBox(QWidget*) : _esize(EmojiSizes[EIndex + 1]) {
setTitleText(lang(lng_settings_emoji_list)); }
setBlockTitle(true);
void EmojiBox::prepare() {
setTitle(lang(lng_settings_emoji_list));
fillBlocks(); fillBlocks();
addButton(lang(lng_close), [this] { closeBox(); });
_blockHeight = st::emojiReplaceInnerHeight; _blockHeight = st::emojiReplaceInnerHeight;
resizeMaxHeight(_blocks[0].size() * st::emojiReplaceWidth + 2 * st::emojiReplacePadding, titleHeight() + st::emojiReplacePadding + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + st::emojiReplacePadding); setDimensions(_blocks[0].size() * st::emojiReplaceWidth + 2 * st::emojiReplacePadding, st::emojiReplacePadding + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + st::emojiReplacePadding);
raiseShadow();
} }
void EmojiBox::fillBlocks() { void EmojiBox::fillBlocks() {
@ -116,20 +117,20 @@ void EmojiBox::fillBlocks() {
void EmojiBox::keyPressEvent(QKeyEvent *e) { void EmojiBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onClose(); closeBox();
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void EmojiBox::paintEvent(QPaintEvent *e) { void EmojiBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
p.setFont(st::emojiTextFont); p.setFont(st::emojiTextFont);
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
int32 top = titleHeight() + st::emojiReplacePadding + (st::emojiReplaceHeight - _blockHeight) / 2; auto top = st::emojiReplacePadding + (st::emojiReplaceHeight - _blockHeight) / 2;
for (Blocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) { for (Blocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2; int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2;
for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) { for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) {

View file

@ -22,13 +22,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h" #include "boxes/abstractbox.h"
class EmojiBox : public AbstractBox { class EmojiBox : public BoxContent {
Q_OBJECT
public: public:
EmojiBox(); EmojiBox(QWidget*);
protected: protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;

View file

@ -31,21 +31,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "langloaderplain.h" #include "langloaderplain.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
LanguageBox::LanguageBox() : void LanguageBox::prepare() {
_close(this, lang(lng_box_ok), st::defaultBoxButton) { addButton(lang(lng_box_ok), [this] { closeBox(); });
setTitleText(lang(lng_languages));
bool haveTestLang = (cLang() == languageTest); setTitle(lang(lng_languages));
int32 y = titleHeight() + st::boxOptionListPadding.top(); auto haveTestLang = (cLang() == languageTest);
auto y = st::boxOptionListPadding.top();
_langs.reserve(languageCount + (haveTestLang ? 1 : 0)); _langs.reserve(languageCount + (haveTestLang ? 1 : 0));
if (haveTestLang) { if (haveTestLang) {
_langs.push_back(new Ui::Radiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langsButton)); _langs.push_back(new Ui::Radiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langsButton));
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top(); y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange())); connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
} }
for (int32 i = 0; i < languageCount; ++i) { for (auto i = 0; i != languageCount; ++i) {
LangLoaderResult result; LangLoaderResult result;
if (i) { if (i) {
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lng_language_name)); LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lng_language_name));
@ -55,15 +56,12 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) {
} }
_langs.push_back(new Ui::Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), (cLang() == i), st::langsButton)); _langs.push_back(new Ui::Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), (cLang() == i), st::langsButton));
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top(); y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange())); connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
} }
resizeMaxHeight(st::langsWidth, titleHeight() + (languageCount + (haveTestLang ? 1 : 0)) * (st::boxOptionListPadding.top() + st::langsButton.height) + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); auto optionsCount = languageCount + (haveTestLang ? 1 : 0);
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + optionsCount * st::langsButton.height + (optionsCount - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
connect(_close, SIGNAL(clicked()), this, SLOT(onClose()));
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
} }
void LanguageBox::mousePressEvent(QMouseEvent *e) { void LanguageBox::mousePressEvent(QMouseEvent *e) {
@ -71,21 +69,21 @@ void LanguageBox::mousePressEvent(QMouseEvent *e) {
for (int32 i = 1; i < languageCount; ++i) { for (int32 i = 1; i < languageCount; ++i) {
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lngkeys_cnt)); LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), langLoaderRequest(lngkeys_cnt));
if (!loader.errors().isEmpty()) { if (!loader.errors().isEmpty()) {
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors())); Ui::show(Box<InformBox>(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors()));
return; return;
} else if (!loader.warnings().isEmpty()) { } else if (!loader.warnings().isEmpty()) {
QString warn = loader.warnings(); QString warn = loader.warnings();
if (warn.size() > 256) warn = warn.mid(0, 253) + qsl("..."); if (warn.size() > 256) warn = warn.mid(0, 253) + qsl("...");
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn)); Ui::show(Box<InformBox>(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn));
return; return;
} }
} }
Ui::showLayer(new InformBox(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1))); Ui::show(Box<InformBox>(qsl("Everything seems great in all %1 languages!").arg(languageCount - 1)));
} }
} }
void LanguageBox::onChange() { void LanguageBox::onChange() {
if (isHidden()) return; if (!isBoxShown()) return;
for (int32 i = 0, l = _langs.size(); i < l; ++i) { for (int32 i = 0, l = _langs.size(); i < l; ++i) {
int32 langId = _langs[i]->val(); int32 langId = _langs[i]->val();
@ -98,27 +96,28 @@ void LanguageBox::onChange() {
LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok)); LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found(); result = loader.found();
} }
QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)), auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_box_ok, langOriginal(lng_box_ok)), save = result.value(lng_box_ok, langOriginal(lng_box_ok)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel)); cancel = result.value(lng_cancel, langOriginal(lng_cancel));
ConfirmBox *box = new ConfirmBox(text, save, st::defaultBoxButton, cancel); Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this] {
connect(box, SIGNAL(confirmed()), this, SLOT(onSave())); saveLanguage();
connect(box, SIGNAL(cancelled()), this, SLOT(onRestore())); }), base::lambda_guarded(this, [this] {
Ui::showLayer(box, KeepOtherLayers); restoreLanguage();
})), KeepOtherLayers);
} }
} }
} }
void LanguageBox::onRestore() { void LanguageBox::restoreLanguage() {
for (int32 i = 0, l = _langs.size(); i < l; ++i) { for (auto i = 0, l = _langs.size(); i != l; ++i) {
if (_langs[i]->val() == cLang()) { if (_langs[i]->val() == cLang()) {
_langs[i]->setChecked(true); _langs[i]->setChecked(true);
} }
} }
} }
void LanguageBox::onSave() { void LanguageBox::saveLanguage() {
for (int32 i = 0, l = _langs.size(); i < l; ++i) { for (auto i = 0, l = _langs.size(); i != l; ++i) {
if (_langs[i]->checked()) { if (_langs[i]->checked()) {
cSetLang(_langs[i]->val()); cSetLang(_langs[i]->val());
Local::writeSettings(); Local::writeSettings();

View file

@ -24,25 +24,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class Radiobutton; class Radiobutton;
class RoundButton;
} // namespace Ui } // namespace Ui
class LanguageBox : public AbstractBox { class LanguageBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
LanguageBox(); LanguageBox(QWidget*) {
}
public slots:
void onChange();
void onRestore();
void onSave();
protected: protected:
void prepare() override;
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
private slots:
void onChange();
private: private:
void saveLanguage();
void restoreLanguage();
QVector<Ui::Radiobutton*> _langs; QVector<Ui::Radiobutton*> _langs;
ChildWidget<Ui::RoundButton> _close;
}; };

View file

@ -27,13 +27,16 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "lang.h" #include "lang.h"
#include "mainwindow.h" #include "mainwindow.h"
LocalStorageBox::LocalStorageBox() : AbstractBox() LocalStorageBox::LocalStorageBox(QWidget *parent)
, _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) : _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) {
, _close(this, lang(lng_box_ok), st::defaultBoxButton) { }
setTitleText(lang(lng_local_storage_title));
connect(_clear, SIGNAL(clicked()), this, SLOT(onClear())); void LocalStorageBox::prepare() {
connect(_close, SIGNAL(clicked()), this, SLOT(onClose())); setTitle(lang(lng_local_storage_title));
addButton(lang(lng_box_ok), [this] { closeBox(); });
_clear->setClickedCallback([this] { clearStorage(); });
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int))); connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
@ -46,16 +49,15 @@ LocalStorageBox::LocalStorageBox() : AbstractBox()
} }
void LocalStorageBox::updateControls() { void LocalStorageBox::updateControls() {
int rowsHeight = 0; auto rowsHeight = 0;
if (_imagesCount > 0 && _audiosCount > 0) { if (_imagesCount > 0 && _audiosCount > 0) {
rowsHeight = 2 * (st::linkFont->height + st::localStorageBoxSkip); rowsHeight = 2 * (st::linkFont->height + st::localStorageBoxSkip);
} else { } else {
rowsHeight = st::linkFont->height + st::localStorageBoxSkip; rowsHeight = st::linkFont->height + st::localStorageBoxSkip;
} }
_clear->setVisible(_imagesCount > 0 || _audiosCount > 0); _clear->setVisible(_imagesCount > 0 || _audiosCount > 0);
setMaxHeight(titleHeight() + st::localStorageBoxSkip + rowsHeight + _clear->height() + st::boxButtonPadding.top() + _close->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWidth, st::localStorageBoxSkip + rowsHeight + _clear->height());
_clear->moveToLeft(st::boxPadding.left(), titleHeight() + st::localStorageBoxSkip + rowsHeight); _clear->moveToLeft(st::boxPadding.left(), st::localStorageBoxSkip + rowsHeight);
_close->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close->height());
update(); update();
} }
@ -73,14 +75,14 @@ void LocalStorageBox::checkLocalStoredCounts() {
} }
void LocalStorageBox::paintEvent(QPaintEvent *e) { void LocalStorageBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
p.setFont(st::boxTextFont); p.setFont(st::boxTextFont);
p.setPen(st::windowFg); p.setPen(st::windowFg);
checkLocalStoredCounts(); checkLocalStoredCounts();
int top = titleHeight() + st::localStorageBoxSkip; auto top = st::localStorageBoxSkip;
if (_imagesCount > 0) { if (_imagesCount > 0) {
auto text = lng_settings_images_cached(lt_count, _imagesCount, lt_size, formatSizeText(Local::storageImagesSize() + Local::storageStickersSize() + Local::storageWebFilesSize())); auto text = lng_settings_images_cached(lt_count, _imagesCount, lt_size, formatSizeText(Local::storageImagesSize() + Local::storageStickersSize() + Local::storageWebFilesSize()));
p.drawTextLeft(st::boxPadding.left(), top, width(), text); p.drawTextLeft(st::boxPadding.left(), top, width(), text);
@ -108,7 +110,7 @@ void LocalStorageBox::paintEvent(QPaintEvent *e) {
} }
} }
void LocalStorageBox::onClear() { void LocalStorageBox::clearStorage() {
App::wnd()->tempDirDelete(Local::ClearManagerStorage); App::wnd()->tempDirDelete(Local::ClearManagerStorage);
_state = State::Clearing; _state = State::Clearing;
updateControls(); updateControls();

View file

@ -23,25 +23,26 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h" #include "boxes/abstractbox.h"
namespace Ui { namespace Ui {
class RoundButton;
class LinkButton; class LinkButton;
} // namespace Ui } // namespace Ui
class LocalStorageBox : public AbstractBox { class LocalStorageBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
LocalStorageBox(); LocalStorageBox(QWidget*);
private slots: private slots:
void onClear();
void onTempDirCleared(int task); void onTempDirCleared(int task);
void onTempDirClearFailed(int task); void onTempDirClearFailed(int task);
protected: protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
private: private:
void clearStorage();
void updateControls(); void updateControls();
void checkLocalStoredCounts(); void checkLocalStoredCounts();
@ -53,8 +54,7 @@ private:
}; };
State _state = State::Normal; State _state = State::Normal;
ChildWidget<Ui::LinkButton> _clear; object_ptr<Ui::LinkButton> _clear;
ChildWidget<Ui::RoundButton> _close;
int _imagesCount = -1; int _imagesCount = -1;
int _audiosCount = -1; int _audiosCount = -1;

View file

@ -60,22 +60,26 @@ QPoint MembersAddButton::prepareRippleStartPosition() const {
return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
} }
MembersBox::MembersBox(ChannelData *channel, MembersFilter filter) : ItemListBox(st::boxScroll) MembersBox::MembersBox(QWidget*, ChannelData *channel, MembersFilter filter)
, _inner(this, channel, filter) { : _channel(channel)
ItemListBox::init(_inner); , _filter(filter) {
}
setTitleText(lang(_inner->filter() == MembersFilter::Recent ? lng_channel_members : lng_channel_admins)); void MembersBox::prepare() {
if (channel->amCreator() && (channel->membersCount() < (channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilter::Admins)) { setTitle(lang(_filter == MembersFilter::Recent ? lng_channel_members : lng_channel_admins));
_add.create(this, st::contactsAdd);
_add->setClickedCallback([this] { onAdd(); }); _inner = setInnerWidget(object_ptr<Inner>(this, _channel, _filter), st::boxLayerScroll);
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
addButton(lang(lng_close), [this] { closeBox(); });
if (_channel->amCreator() && (_channel->membersCount() < (_channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!_channel->isMegagroup() && !_channel->isPublic()) || _filter == MembersFilter::Admins)) {
addLeftButton(lang((_filter == MembersFilter::Admins) ? lng_channel_add_admin : lng_channel_add_members), [this] { onAdd(); });
} }
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); connect(_inner, SIGNAL(mustScrollTo(int, int)), this, SLOT(onScrollToY(int, int)));
connect(_inner, SIGNAL(mustScrollTo(int, int)), scrollArea(), SLOT(scrollToY(int, int)));
connect(&_loadTimer, SIGNAL(timeout()), _inner, SLOT(load())); _loadTimer.create(this);
connect(_loadTimer, SIGNAL(timeout()), _inner, SLOT(load()));
raiseShadow();
} }
void MembersBox::keyPressEvent(QKeyEvent *e) { void MembersBox::keyPressEvent(QKeyEvent *e) {
@ -84,47 +88,41 @@ void MembersBox::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Up) { } else if (e->key() == Qt::Key_Up) {
_inner->selectSkip(-1); _inner->selectSkip(-1);
} else if (e->key() == Qt::Key_PageDown) { } else if (e->key() == Qt::Key_PageDown) {
_inner->selectSkipPage(scrollArea()->height(), 1); _inner->selectSkipPage(height(), 1);
} else if (e->key() == Qt::Key_PageUp) { } else if (e->key() == Qt::Key_PageUp) {
_inner->selectSkipPage(scrollArea()->height(), -1); _inner->selectSkipPage(height(), -1);
} else { } else {
ItemListBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void MembersBox::resizeEvent(QResizeEvent *e) { void MembersBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e); BoxContent::resizeEvent(e);
_inner->resize(width(), _inner->height()); _inner->resize(width(), _inner->height());
if (_add) {
_add->moveToRight(st::contactsAddPosition.x(), height() - st::contactsAddPosition.y() - _add->height());
}
}
void MembersBox::onScroll() {
_inner->loadProfilePhotos(scrollArea()->scrollTop());
} }
void MembersBox::onAdd() { void MembersBox::onAdd() {
if (_inner->filter() == MembersFilter::Recent && _inner->channel()->membersCount() >= (_inner->channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) { if (_inner->filter() == MembersFilter::Recent && _inner->channel()->membersCount() >= (_inner->channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
Ui::showLayer(new MaxInviteBox(_inner->channel()->inviteLink()), KeepOtherLayers); Ui::show(Box<MaxInviteBox>(_inner->channel()->inviteLink()), KeepOtherLayers);
return; return;
} }
ContactsBox *box = new ContactsBox(_inner->channel(), _inner->filter(), _inner->already()); auto box = Box<ContactsBox>(_inner->channel(), _inner->filter(), _inner->already());
if (_inner->filter() == MembersFilter::Recent) { if (_inner->filter() == MembersFilter::Recent) {
Ui::showLayer(box); Ui::show(std_::move(box));
} else { } else {
_addBox = box; _addBox = Ui::show(std_::move(box), KeepOtherLayers);
connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded())); if (_addBox) {
Ui::showLayer(_addBox, KeepOtherLayers); connect(_addBox, SIGNAL(adminAdded()), this, SLOT(onAdminAdded()));
}
} }
} }
void MembersBox::onAdminAdded() { void MembersBox::onAdminAdded() {
if (!_addBox) return; if (!_addBox) return;
_addBox->onClose(); _addBox->closeBox();
_addBox = 0; _addBox = nullptr;
_loadTimer.start(ReloadChannelMembersTimeout); _loadTimer->start(ReloadChannelMembersTimeout);
} }
MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter filter) : TWidget(parent) MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter filter) : TWidget(parent)
@ -169,8 +167,9 @@ void MembersBox::Inner::paintEvent(QPaintEvent *e) {
_time = unixtime(); _time = unixtime();
p.fillRect(r, st::contactsBg); p.fillRect(r, st::contactsBg);
int32 yFrom = r.y() - st::membersPadding.top(), yTo = r.y() + r.height() - st::membersPadding.top(); auto yFrom = r.y() - st::membersMarginTop;
p.translate(0, st::membersPadding.top()); auto yTo = r.y() + r.height() - st::membersMarginTop;
p.translate(0, st::membersMarginTop);
if (_rows.isEmpty()) { if (_rows.isEmpty()) {
p.setFont(st::noContactsFont); p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor); p.setPen(st::noContactsColor);
@ -229,28 +228,18 @@ void MembersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
if (_kickDown >= 0 && _kickDown == _kickSel && !_kickRequestId) { if (_kickDown >= 0 && _kickDown == _kickSel && !_kickRequestId) {
_kickConfirm = _rows.at(_kickSel); _kickConfirm = _rows.at(_kickSel);
if (_kickBox) _kickBox->deleteLater(); if (_kickBox) _kickBox->deleteLater();
_kickBox = new ConfirmBox((_filter == MembersFilter::Recent ? (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel) : lng_profile_sure_kick_admin)(lt_user, _kickConfirm->firstName)); 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);
connect(_kickBox, SIGNAL(confirmed()), this, SLOT(onKickConfirm())); _kickBox = Ui::show(Box<ConfirmBox>(text, base::lambda_guarded(this, [this] {
connect(_kickBox, SIGNAL(destroyed(QObject*)), this, SLOT(onKickBoxDestroyed(QObject*))); if (_filter == MembersFilter::Recent) {
Ui::showLayer(_kickBox, KeepOtherLayers); _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);
} }
_kickDown = -1; _kickDown = -1;
} }
void MembersBox::Inner::onKickBoxDestroyed(QObject *obj) {
if (_kickBox == obj) {
_kickBox = 0;
}
}
void MembersBox::Inner::onKickConfirm() {
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));
}
}
void MembersBox::Inner::paintDialog(Painter &p, PeerData *peer, MemberData *data, bool sel, bool kickSel, bool kickDown) { void MembersBox::Inner::paintDialog(Painter &p, PeerData *peer, MemberData *data, bool sel, bool kickSel, bool kickDown) {
UserData *user = peer->asUser(); UserData *user = peer->asUser();
@ -317,9 +306,11 @@ void MembersBox::Inner::selectSkipPage(int32 h, int32 dir) {
selectSkip(points * dir); selectSkip(points * dir);
} }
void MembersBox::Inner::loadProfilePhotos(int32 yFrom) { void MembersBox::Inner::loadProfilePhotos() {
if (!parentWidget()) return; if (_visibleTop >= _visibleBottom) return;
int32 yTo = yFrom + parentWidget()->height() * 5;
auto yFrom = _visibleTop;
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
MTP::clearLoaderPriorities(); MTP::clearLoaderPriorities();
if (yTo < 0) return; if (yTo < 0) return;
@ -349,7 +340,7 @@ void MembersBox::Inner::chooseParticipant() {
void MembersBox::Inner::refresh() { void MembersBox::Inner::refresh() {
if (_rows.isEmpty()) { if (_rows.isEmpty()) {
resize(width(), st::membersPadding.top() + st::noContactsHeight + st::membersPadding.bottom()); resize(width(), st::membersMarginTop + st::noContactsHeight + st::membersMarginBottom);
_aboutHeight = 0; _aboutHeight = 0;
} else { } else {
_about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size())); _about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size()));
@ -357,7 +348,7 @@ void MembersBox::Inner::refresh() {
if (_filter != MembersFilter::Recent || (_rows.size() >= _channel->membersCount() && _rows.size() < Global::ChatSizeMax())) { if (_filter != MembersFilter::Recent || (_rows.size() >= _channel->membersCount() && _rows.size() < Global::ChatSizeMax())) {
_aboutHeight = 0; _aboutHeight = 0;
} }
resize(width(), st::membersPadding.top() + _rows.size() * _rowHeight + st::membersPadding.bottom() + _aboutHeight); resize(width(), st::membersMarginTop + _aboutHeight + _rows.size() * _rowHeight + st::membersMarginBottom);
} }
update(); update();
} }
@ -380,6 +371,12 @@ MembersAlreadyIn MembersBox::Inner::already() const {
return result; return result;
} }
void MembersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadProfilePhotos();
}
void MembersBox::Inner::clearSel() { void MembersBox::Inner::clearSel() {
updateSelectedRow(); updateSelectedRow();
_sel = _kickSel = _kickDown = -1; _sel = _kickSel = _kickDown = -1;
@ -426,7 +423,7 @@ void MembersBox::Inner::updateSel() {
if (!_mouseSel) return; if (!_mouseSel) return;
QPoint p(mapFromGlobal(_lastMousePos)); QPoint p(mapFromGlobal(_lastMousePos));
p.setY(p.y() - st::membersPadding.top()); p.setY(p.y() - st::membersMarginTop);
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
int32 newSel = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1; int32 newSel = (in && p.y() >= 0 && p.y() < _rows.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
int32 newKickSel = newSel; int32 newKickSel = newSel;
@ -448,7 +445,7 @@ void MembersBox::Inner::peerUpdated(PeerData *peer) {
void MembersBox::Inner::updateSelectedRow() { void MembersBox::Inner::updateSelectedRow() {
if (_sel >= 0) { if (_sel >= 0) {
update(0, st::membersPadding.top() + _sel * _rowHeight, width(), _rowHeight); update(0, st::membersMarginTop + _sel * _rowHeight, width(), _rowHeight);
} }
} }
@ -457,7 +454,7 @@ void MembersBox::Inner::onPeerNameChanged(PeerData *peer, const PeerData::Names
if (_rows.at(i) == peer) { if (_rows.at(i) == peer) {
if (_datas.at(i)) { if (_datas.at(i)) {
_datas.at(i)->name.setText(st::contactsNameFont, peer->name, _textNameOptions); _datas.at(i)->name.setText(st::contactsNameFont, peer->name, _textNameOptions);
update(0, st::membersPadding.top() + i * _rowHeight, width(), _rowHeight); update(0, st::membersMarginTop + i * _rowHeight, width(), _rowHeight);
} else { } else {
break; break;
} }
@ -566,20 +563,20 @@ void MembersBox::Inner::kickDone(const MTPUpdates &result, mtpRequestId req) {
if (_kickRequestId != req) return; if (_kickRequestId != req) return;
removeKicked(); removeKicked();
if (_kickBox) _kickBox->onClose(); if (_kickBox) _kickBox->closeBox();
} }
void MembersBox::Inner::kickAdminDone(const MTPUpdates &result, mtpRequestId req) { void MembersBox::Inner::kickAdminDone(const MTPUpdates &result, mtpRequestId req) {
if (_kickRequestId != req) return; if (_kickRequestId != req) return;
if (App::main()) App::main()->sentUpdatesReceived(result); if (App::main()) App::main()->sentUpdatesReceived(result);
removeKicked(); removeKicked();
if (_kickBox) _kickBox->onClose(); if (_kickBox) _kickBox->closeBox();
} }
bool MembersBox::Inner::kickFail(const RPCError &error, mtpRequestId req) { bool MembersBox::Inner::kickFail(const RPCError &error, mtpRequestId req) {
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
if (_kickBox) _kickBox->onClose(); if (_kickBox) _kickBox->closeBox();
load(); load();
return true; return true;
} }

View file

@ -49,31 +49,33 @@ private:
}; };
class MembersBox : public ItemListBox { class MembersBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
MembersBox(ChannelData *channel, MembersFilter filter); MembersBox(QWidget*, ChannelData *channel, MembersFilter filter);
public slots: public slots:
void onScroll();
void onAdminAdded(); void onAdminAdded();
protected: protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private: private:
void onAdd(); void onAdd();
ChannelData *_channel = nullptr;
MembersFilter _filter = MembersFilter::Recent;
class Inner; class Inner;
ChildWidget<Inner> _inner; QPointer<Inner> _inner;
ChildWidget<MembersAddButton> _add = { nullptr };
ContactsBox *_addBox = nullptr; QPointer<ContactsBox> _addBox;
SingleTimer _loadTimer; object_ptr<SingleTimer> _loadTimer = { nullptr };
}; };
@ -87,7 +89,6 @@ public:
void selectSkip(int32 dir); void selectSkip(int32 dir);
void selectSkipPage(int32 h, int32 dir); void selectSkipPage(int32 h, int32 dir);
void loadProfilePhotos(int32 yFrom);
void chooseParticipant(); void chooseParticipant();
void refresh(); void refresh();
@ -101,6 +102,7 @@ public:
void clearSel(); void clearSel();
MembersAlreadyIn already() const; MembersAlreadyIn already() const;
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
~Inner(); ~Inner();
@ -114,8 +116,6 @@ public slots:
void updateSel(); void updateSel();
void peerUpdated(PeerData *peer); void peerUpdated(PeerData *peer);
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
void onKickConfirm();
void onKickBoxDestroyed(QObject *obj);
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
@ -133,6 +133,8 @@ private:
bool canKick; bool canKick;
}; };
void loadProfilePhotos();
void updateSelectedRow(); void updateSelectedRow();
MemberData *data(int32 index); MemberData *data(int32 index);
@ -149,6 +151,8 @@ private:
void clear(); void clear();
int _rowHeight; int _rowHeight;
int _visibleTop = 0;
int _visibleBottom = 0;
ChannelData *_channel; ChannelData *_channel;
MembersFilter _filter; MembersFilter _filter;
@ -162,7 +166,7 @@ private:
UserData *_kickConfirm; UserData *_kickConfirm;
mtpRequestId _kickRequestId; mtpRequestId _kickRequestId;
ConfirmBox *_kickBox; QPointer<ConfirmBox> _kickBox;
enum class MemberRole { enum class MemberRole {
None, None,

View file

@ -108,11 +108,15 @@ private:
}; };
NotificationsBox::NotificationsBox() : AbstractBox() NotificationsBox::NotificationsBox(QWidget *parent)
, _chosenCorner(Global::NotificationsCorner()) : _chosenCorner(Global::NotificationsCorner())
, _oldCount(snap(Global::NotificationsCount(), 1, kMaxNotificationsCount)) , _oldCount(snap(Global::NotificationsCount(), 1, kMaxNotificationsCount))
, _countSlider(this) , _countSlider(this) {
, _done(this, lang(lng_about_done), st::defaultBoxButton) { }
void NotificationsBox::prepare() {
addButton(lang(lng_close), [this] { closeBox(); });
_sampleOpacities.reserve(kMaxNotificationsCount); _sampleOpacities.reserve(kMaxNotificationsCount);
for (int i = 0; i != kMaxNotificationsCount; ++i) { for (int i = 0; i != kMaxNotificationsCount; ++i) {
_countSlider->addSection(QString::number(i + 1)); _countSlider->addSection(QString::number(i + 1));
@ -122,15 +126,15 @@ NotificationsBox::NotificationsBox() : AbstractBox()
_countSlider->setSectionActivatedCallback([this] { countChanged(); }); _countSlider->setSectionActivatedCallback([this] { countChanged(); });
setMouseTracking(true); setMouseTracking(true);
_done->setClickedCallback([this] { onClose(); });
prepareNotificationSampleSmall(); prepareNotificationSampleSmall();
prepareNotificationSampleLarge(); prepareNotificationSampleLarge();
setMaxHeight(st::notificationsBoxHeight);
setDimensions(st::boxWideWidth, st::notificationsBoxHeight);
} }
void NotificationsBox::paintEvent(QPaintEvent *e) { void NotificationsBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -203,14 +207,13 @@ QRect NotificationsBox::getScreenRect() const {
} }
void NotificationsBox::resizeEvent(QResizeEvent *e) { void NotificationsBox::resizeEvent(QResizeEvent *e) {
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); BoxContent::resizeEvent(e);
auto screenRect = getScreenRect(); auto screenRect = getScreenRect();
auto sliderTop = screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop + st::notificationsBoxCountTop; auto sliderTop = screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop + st::notificationsBoxCountTop;
auto contentLeft = getContentLeft(); auto contentLeft = getContentLeft();
_countSlider->resizeToWidth(width() - 2 * contentLeft); _countSlider->resizeToWidth(width() - 2 * contentLeft);
_countSlider->move(contentLeft, sliderTop); _countSlider->move(contentLeft, sliderTop);
AbstractBox::resizeEvent(e);
} }
void NotificationsBox::prepareNotificationSampleSmall() { void NotificationsBox::prepareNotificationSampleSmall() {

View file

@ -23,17 +23,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h" #include "boxes/abstractbox.h"
namespace Ui { namespace Ui {
class RoundButton;
class LinkButton; class LinkButton;
class SettingsSlider; class SettingsSlider;
} // namespace Ui } // namespace Ui
class NotificationsBox : public AbstractBox { class NotificationsBox : public BoxContent {
public: public:
NotificationsBox(); NotificationsBox(QWidget*);
~NotificationsBox(); ~NotificationsBox();
protected: protected:
void prepare() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
@ -70,8 +71,7 @@ private:
ScreenCorner _downCorner = ScreenCorner::TopLeft; ScreenCorner _downCorner = ScreenCorner::TopLeft;
int _oldCount; int _oldCount;
ChildWidget<Ui::SettingsSlider> _countSlider; object_ptr<Ui::SettingsSlider> _countSlider;
ChildWidget<Ui::RoundButton> _done;
QVector<SampleWidget*> _cornerSamples[4]; QVector<SampleWidget*> _cornerSamples[4];

View file

@ -29,29 +29,24 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth) PasscodeBox::PasscodeBox(QWidget*, bool turningOff)
, _turningOff(turningOff) : _turningOff(turningOff)
, _about(st::boxWidth - st::boxPadding.left() * 1.5) , _about(st::boxWidth - st::boxPadding.left() * 1.5)
, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton)
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
, _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old)) , _oldPasscode(this, st::defaultInputField, lang(lng_passcode_enter_old))
, _newPasscode(this, st::defaultInputField, lang(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first)) , _newPasscode(this, st::defaultInputField, lang(Global::LocalPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
, _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new)) , _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new))
, _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint)) , _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint))
, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email)) , _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
, _recover(this, lang(lng_signin_recover)) { , _recover(this, lang(lng_signin_recover)) {
init();
} }
PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) : AbstractBox(st::boxWidth) PasscodeBox::PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff)
, _turningOff(turningOff) : _turningOff(turningOff)
, _cloudPwd(true) , _cloudPwd(true)
, _newSalt(newSalt) , _newSalt(newSalt)
, _curSalt(curSalt) , _curSalt(curSalt)
, _hasRecovery(hasRecovery) , _hasRecovery(hasRecovery)
, _about(st::boxWidth - st::boxPadding.left() * 1.5) , _about(st::boxWidth - st::boxPadding.left() * 1.5)
, _saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::defaultBoxButton)
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
, _oldPasscode(this, st::defaultInputField, lang(lng_cloud_password_enter_old)) , _oldPasscode(this, st::defaultInputField, lang(lng_cloud_password_enter_old))
, _newPasscode(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new)) , _newPasscode(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
, _reenterPasscode(this, st::defaultInputField, lang(lng_cloud_password_confirm_new)) , _reenterPasscode(this, st::defaultInputField, lang(lng_cloud_password_confirm_new))
@ -61,12 +56,11 @@ PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, b
textstyleSet(&st::usernameTextStyle); textstyleSet(&st::usernameTextStyle);
if (!hint.isEmpty()) _hintText.setText(st::normalFont, lng_signin_hint(lt_password_hint, hint)); if (!hint.isEmpty()) _hintText.setText(st::normalFont, lng_signin_hint(lt_password_hint, hint));
textstyleRestore(); textstyleRestore();
init();
} }
void PasscodeBox::init() { void PasscodeBox::prepare() {
setBlockTitle(true); addButton(lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
textstyleSet(&st::usernameTextStyle); textstyleSet(&st::usernameTextStyle);
_about.setRichText(st::normalFont, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about)); _about.setRichText(st::normalFont, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about));
@ -74,24 +68,21 @@ void PasscodeBox::init() {
textstyleRestore(); textstyleRestore();
if (_turningOff) { if (_turningOff) {
_oldPasscode->show(); _oldPasscode->show();
setTitleText(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove)); setTitle(lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove));
setMaxHeight(titleHeight() + st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _aboutHeight + st::passcodePadding.bottom());
} else { } else {
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); auto has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
if (has) { if (has) {
_oldPasscode->show(); _oldPasscode->show();
setTitleText(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change)); setTitle(lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change));
setMaxHeight(titleHeight() + st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::contactSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::contactSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWidth, st::passcodePadding.top() + _oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0) + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + st::passcodePadding.bottom());
} else { } else {
_oldPasscode->hide(); _oldPasscode->hide();
setTitleText(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create)); setTitle(lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create));
setMaxHeight(titleHeight() + st::passcodePadding.top() + _newPasscode->height() + st::contactSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::contactSkip : 0) + _aboutHeight + (_cloudPwd ? st::contactSkip + _recoverEmail->height() + st::passcodeSkip : st::passcodePadding.bottom()) + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + _aboutHeight + (_cloudPwd ? st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip : st::passcodePadding.bottom()));
} }
} }
connect(_saveButton, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancelButton, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged())); connect(_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged()));
connect(_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged())); connect(_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
connect(_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged())); connect(_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
@ -113,8 +104,6 @@ void PasscodeBox::init() {
_reenterPasscode->setVisible(!_turningOff); _reenterPasscode->setVisible(!_turningOff);
_passwordHint->setVisible(!_turningOff && _cloudPwd); _passwordHint->setVisible(!_turningOff && _cloudPwd);
_recoverEmail->setVisible(!_turningOff && _cloudPwd && _curSalt.isEmpty()); _recoverEmail->setVisible(!_turningOff && _cloudPwd && _curSalt.isEmpty());
raiseShadow();
} }
void PasscodeBox::onSubmit() { void PasscodeBox::onSubmit() {
@ -153,14 +142,14 @@ void PasscodeBox::onSubmit() {
} }
void PasscodeBox::paintEvent(QPaintEvent *e) { void PasscodeBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
textstyleSet(&st::usernameTextStyle); textstyleSet(&st::usernameTextStyle);
int32 w = st::boxWidth - st::boxPadding.left() * 1.5; int32 w = st::boxWidth - st::boxPadding.left() * 1.5;
int32 abouty = (_passwordHint->isHidden() ? (_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip : _passwordHint->y() + st::contactSkip) + _oldPasscode->height() + st::passcodePadding.bottom(); int32 abouty = (_passwordHint->isHidden() ? (_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip : _passwordHint->y() + st::passcodeLittleSkip) + _oldPasscode->height() + st::passcodePadding.bottom();
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
_about.drawLeft(p, st::boxPadding.left(), abouty, w, width()); _about.drawLeft(p, st::boxPadding.left(), abouty, w, width());
@ -187,30 +176,27 @@ void PasscodeBox::paintEvent(QPaintEvent *e) {
} }
void PasscodeBox::resizeEvent(QResizeEvent *e) { void PasscodeBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode(); bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right(); int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right();
_oldPasscode->resize(w, _oldPasscode->height()); _oldPasscode->resize(w, _oldPasscode->height());
_oldPasscode->moveToLeft(st::boxPadding.left(), titleHeight() + st::passcodePadding.top()); _oldPasscode->moveToLeft(st::boxPadding.left(), st::passcodePadding.top());
_newPasscode->resize(w, _newPasscode->height()); _newPasscode->resize(w, _newPasscode->height());
_newPasscode->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + ((_turningOff || has) ? (_oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0)) : 0)); _newPasscode->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + ((_turningOff || has) ? (_oldPasscode->height() + st::passcodeTextLine + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeTextLine : 0)) : 0));
_reenterPasscode->resize(w, _reenterPasscode->height()); _reenterPasscode->resize(w, _reenterPasscode->height());
_reenterPasscode->moveToLeft(st::boxPadding.left(), _newPasscode->y() + _newPasscode->height() + st::contactSkip); _reenterPasscode->moveToLeft(st::boxPadding.left(), _newPasscode->y() + _newPasscode->height() + st::passcodeLittleSkip);
_passwordHint->resize(w, _passwordHint->height()); _passwordHint->resize(w, _passwordHint->height());
_passwordHint->moveToLeft(st::boxPadding.left(), _reenterPasscode->y() + _reenterPasscode->height() + st::passcodeSkip); _passwordHint->moveToLeft(st::boxPadding.left(), _reenterPasscode->y() + _reenterPasscode->height() + st::passcodeSkip);
_recoverEmail->resize(w, _passwordHint->height()); _recoverEmail->resize(w, _passwordHint->height());
_recoverEmail->moveToLeft(st::boxPadding.left(), _passwordHint->y() + _passwordHint->height() + st::contactSkip + _aboutHeight + st::contactSkip); _recoverEmail->moveToLeft(st::boxPadding.left(), _passwordHint->y() + _passwordHint->height() + st::passcodeLittleSkip + _aboutHeight + st::passcodeLittleSkip);
if (!_recover->isHidden()) { if (!_recover->isHidden()) {
_recover->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + _oldPasscode->height() + (_hintText.isEmpty() ? ((st::passcodeTextLine - _recover->height()) / 2) : st::passcodeTextLine)); _recover->moveToLeft(st::boxPadding.left(), _oldPasscode->y() + _oldPasscode->height() + (_hintText.isEmpty() ? ((st::passcodeTextLine - _recover->height()) / 2) : st::passcodeTextLine));
} }
_saveButton->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton->height());
_cancelButton->moveToRight(st::boxButtonPadding.right() + _saveButton->width() + st::boxButtonPadding.left(), _saveButton->y());
AbstractBox::resizeEvent(e);
} }
void PasscodeBox::doSetInnerFocus() { void PasscodeBox::setInnerFocus() {
if (_skipEmailWarning && !_recoverEmail->isHidden()) { if (_skipEmailWarning && !_recoverEmail->isHidden()) {
_recoverEmail->setFocus(); _recoverEmail->setFocus();
} else if (_oldPasscode->isHidden()) { } else if (_oldPasscode->isHidden()) {
@ -223,15 +209,23 @@ void PasscodeBox::doSetInnerFocus() {
void PasscodeBox::setPasswordDone(const MTPBool &result) { void PasscodeBox::setPasswordDone(const MTPBool &result) {
_setRequest = 0; _setRequest = 0;
emit reloadPassword(); emit reloadPassword();
ConfirmBox *box = new InformBox(lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated))); auto text = lang(_reenterPasscode->isHidden() ? lng_cloud_password_removed : (_oldPasscode->isHidden() ? lng_cloud_password_was_set : lng_cloud_password_updated));
Ui::showLayer(box); Ui::show(Box<InformBox>(text));
}
void PasscodeBox::closeReplacedBy() {
if (isHidden()) {
if (_replacedBy && !_replacedBy->isHidden()) {
_replacedBy->closeBox();
}
}
} }
bool PasscodeBox::setPasswordFail(const RPCError &error) { bool PasscodeBox::setPasswordFail(const RPCError &error) {
if (MTP::isFloodError(error)) { if (MTP::isFloodError(error)) {
if (_oldPasscode->isHidden()) return false; if (_oldPasscode->isHidden()) return false;
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); closeReplacedBy();
_setRequest = 0; _setRequest = 0;
_oldPasscode->selectAll(); _oldPasscode->selectAll();
@ -246,13 +240,13 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) {
} }
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); closeReplacedBy();
_setRequest = 0; _setRequest = 0;
QString err = error.type(); QString err = error.type();
if (err == qstr("PASSWORD_HASH_INVALID")) { if (err == qstr("PASSWORD_HASH_INVALID")) {
if (_oldPasscode->isHidden()) { if (_oldPasscode->isHidden()) {
emit reloadPassword(); emit reloadPassword();
onClose(); closeBox();
} else { } else {
onBadOldPasscode(); onBadOldPasscode();
} }
@ -263,14 +257,14 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) {
update(); update();
} else if (err == qstr("NEW_SALT_INVALID")) { } else if (err == qstr("NEW_SALT_INVALID")) {
emit reloadPassword(); emit reloadPassword();
onClose(); closeBox();
} else if (err == qstr("EMAIL_INVALID")) { } else if (err == qstr("EMAIL_INVALID")) {
_emailError = lang(lng_cloud_password_bad_email); _emailError = lang(lng_cloud_password_bad_email);
_recoverEmail->setFocus(); _recoverEmail->setFocus();
_recoverEmail->showError(); _recoverEmail->showError();
update(); update();
} else if (err == qstr("EMAIL_UNCONFIRMED")) { } else if (err == qstr("EMAIL_UNCONFIRMED")) {
Ui::showLayer(new InformBox(lang(lng_cloud_password_almost))); Ui::show(Box<InformBox>(lang(lng_cloud_password_almost)));
emit reloadPassword(); emit reloadPassword();
} }
return true; return true;
@ -303,7 +297,7 @@ void PasscodeBox::onSave(bool force) {
if (!_turningOff && pwd.isEmpty()) { if (!_turningOff && pwd.isEmpty()) {
_newPasscode->setFocus(); _newPasscode->setFocus();
_newPasscode->showError(); _newPasscode->showError();
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); closeReplacedBy();
return; return;
} }
if (pwd != conf) { if (pwd != conf) {
@ -314,13 +308,13 @@ void PasscodeBox::onSave(bool force) {
_newError = lang(_cloudPwd ? lng_cloud_password_differ : lng_passcode_differ); _newError = lang(_cloudPwd ? lng_cloud_password_differ : lng_passcode_differ);
update(); update();
} }
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); closeReplacedBy();
} else if (!_turningOff && has && old == pwd) { } else if (!_turningOff && has && old == pwd) {
_newPasscode->setFocus(); _newPasscode->setFocus();
_newPasscode->showError(); _newPasscode->showError();
_newError = lang(_cloudPwd ? lng_cloud_password_is_same : lng_passcode_is_same); _newError = lang(_cloudPwd ? lng_cloud_password_is_same : lng_passcode_is_same);
update(); update();
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); closeReplacedBy();
} else if (_cloudPwd) { } else if (_cloudPwd) {
QString hint = _passwordHint->getLastText(), email = _recoverEmail->getLastText().trimmed(); QString hint = _passwordHint->getLastText(), email = _recoverEmail->getLastText().trimmed();
if (_cloudPwd && pwd == hint && !_passwordHint->isHidden() && !_newPasscode->isHidden()) { if (_cloudPwd && pwd == hint && !_passwordHint->isHidden() && !_newPasscode->isHidden()) {
@ -328,15 +322,14 @@ void PasscodeBox::onSave(bool force) {
_newPasscode->showError(); _newPasscode->showError();
_newError = lang(lng_cloud_password_bad); _newError = lang(lng_cloud_password_bad);
update(); update();
if (isHidden() && _replacedBy && !_replacedBy->isHidden()) _replacedBy->onClose(); closeReplacedBy();
return; return;
} }
if (!_recoverEmail->isHidden() && email.isEmpty() && !force) { if (!_recoverEmail->isHidden() && email.isEmpty() && !force) {
_skipEmailWarning = true; _skipEmailWarning = true;
_replacedBy = new ConfirmBox(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton); _replacedBy = Ui::show(Box<ConfirmBox>(lang(lng_cloud_password_about_recover), lang(lng_cloud_password_skip_email), st::attentionBoxButton, base::lambda_guarded(this, [this] {
connect(_replacedBy, SIGNAL(confirmed()), this, SLOT(onForceNoMail())); onSave(true);
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*))); })), KeepOtherLayers);
Ui::showLayer(_replacedBy, KeepOtherLayers);
} else { } else {
QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt); QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt);
QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized); QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized);
@ -362,7 +355,7 @@ void PasscodeBox::onSave(bool force) {
cSetPasscodeBadTries(0); cSetPasscodeBadTries(0);
Local::setPasscode(pwd.toUtf8()); Local::setPasscode(pwd.toUtf8());
App::wnd()->checkAutoLock(); App::wnd()->checkAutoLock();
onClose(); closeBox();
} }
} }
@ -401,16 +394,6 @@ void PasscodeBox::onEmailChanged() {
} }
} }
void PasscodeBox::onForceNoMail() {
onSave(true);
}
void PasscodeBox::onBoxDestroyed(QObject *obj) {
if (obj == _replacedBy) {
_replacedBy = 0;
}
}
void PasscodeBox::onRecoverByEmail() { void PasscodeBox::onRecoverByEmail() {
if (_pattern.isEmpty()) { if (_pattern.isEmpty()) {
_pattern = "-"; _pattern = "-";
@ -427,11 +410,9 @@ void PasscodeBox::onRecoverExpired() {
void PasscodeBox::recover() { void PasscodeBox::recover() {
if (_pattern == "-") return; if (_pattern == "-") return;
_replacedBy = new RecoverBox(_pattern); _replacedBy = Ui::show(Box<RecoverBox>(_pattern), KeepOtherLayers);
connect(_replacedBy, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword())); connect(_replacedBy, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword()));
connect(_replacedBy, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired())); connect(_replacedBy, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired()));
connect(_replacedBy, SIGNAL(destroyed(QObject*)), this, SLOT(onBoxDestroyed(QObject*)));
Ui::showLayer(_replacedBy, KeepOtherLayers);
} }
void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) { void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) {
@ -443,31 +424,29 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
_pattern = QString(); _pattern = QString();
onClose(); closeBox();
return true; return true;
} }
RecoverBox::RecoverBox(const QString &pattern) : AbstractBox(st::boxWidth, lang(lng_signin_recover_title)) RecoverBox::RecoverBox(QWidget*, const QString &pattern)
, _submitRequest(0) : _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
, _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
, _saveButton(this, lang(lng_passcode_submit), st::defaultBoxButton)
, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
, _recoverCode(this, st::defaultInputField, lang(lng_signin_code)) { , _recoverCode(this, st::defaultInputField, lang(lng_signin_code)) {
setBlockTitle(true); }
setMaxHeight(titleHeight() + st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine + st::boxButtonPadding.top() + _saveButton->height() + st::boxButtonPadding.bottom()); void RecoverBox::prepare() {
setTitle(lang(lng_signin_recover_title));
connect(_saveButton, SIGNAL(clicked()), this, SLOT(onSubmit())); addButton(lang(lng_passcode_submit), [this] { onSubmit(); });
connect(_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); addButton(lang(lng_cancel), [this] { closeBox(); });
setDimensions(st::boxWidth, st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine + _recoverCode->height() + st::passcodeTextLine);
connect(_recoverCode, SIGNAL(changed()), this, SLOT(onCodeChanged())); connect(_recoverCode, SIGNAL(changed()), this, SLOT(onCodeChanged()));
connect(_recoverCode, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_recoverCode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
raiseShadow();
} }
void RecoverBox::paintEvent(QPaintEvent *e) { void RecoverBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -483,16 +462,13 @@ void RecoverBox::paintEvent(QPaintEvent *e) {
} }
void RecoverBox::resizeEvent(QResizeEvent *e) { void RecoverBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_recoverCode->resize(st::boxWidth - st::boxPadding.left() - st::boxPadding.right(), _recoverCode->height()); _recoverCode->resize(st::boxWidth - st::boxPadding.left() - st::boxPadding.right(), _recoverCode->height());
_recoverCode->moveToLeft(st::boxPadding.left(), titleHeight() + st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine); _recoverCode->moveToLeft(st::boxPadding.left(), st::passcodePadding.top() + st::passcodePadding.bottom() + st::passcodeTextLine);
_saveButton->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _saveButton->height());
_cancelButton->moveToRight(st::boxButtonPadding.right() + _saveButton->width() + st::boxButtonPadding.left(), _saveButton->y());
AbstractBox::resizeEvent(e);
} }
void RecoverBox::doSetInnerFocus() { void RecoverBox::setInnerFocus() {
_recoverCode->setFocus(); _recoverCode->setFocus();
} }
@ -518,7 +494,7 @@ void RecoverBox::codeSubmitDone(bool recover, const MTPauth_Authorization &resul
_submitRequest = 0; _submitRequest = 0;
emit reloadPassword(); emit reloadPassword();
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed))); Ui::show(Box<InformBox>(lang(lng_cloud_password_removed)));
} }
bool RecoverBox::codeSubmitFail(const RPCError &error) { bool RecoverBox::codeSubmitFail(const RPCError &error) {
@ -536,14 +512,14 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) {
const QString &err = error.type(); const QString &err = error.type();
if (err == qstr("PASSWORD_EMPTY")) { if (err == qstr("PASSWORD_EMPTY")) {
emit reloadPassword(); emit reloadPassword();
Ui::showLayer(new InformBox(lang(lng_cloud_password_removed))); Ui::show(Box<InformBox>(lang(lng_cloud_password_removed)));
return true; return true;
} else if (err == qstr("PASSWORD_RECOVERY_NA")) { } else if (err == qstr("PASSWORD_RECOVERY_NA")) {
onClose(); closeBox();
return true; return true;
} else if (err == qstr("PASSWORD_RECOVERY_EXPIRED")) { } else if (err == qstr("PASSWORD_RECOVERY_EXPIRED")) {
emit recoveryExpired(); emit recoveryExpired();
onClose(); closeBox();
return true; return true;
} else if (err == qstr("CODE_INVALID")) { } else if (err == qstr("CODE_INVALID")) {
_error = lang(lng_signin_wrong_code); _error = lang(lng_signin_wrong_code);

View file

@ -26,15 +26,14 @@ namespace Ui {
class InputField; class InputField;
class PasswordInput; class PasswordInput;
class LinkButton; class LinkButton;
class RoundButton;
} // namespace Ui } // namespace Ui
class PasscodeBox : public AbstractBox, public RPCSender { class PasscodeBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
PasscodeBox(bool turningOff = false); PasscodeBox(QWidget*, bool turningOff);
PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false); PasscodeBox(QWidget*, const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false);
private slots: private slots:
void onSave(bool force = false); void onSave(bool force = false);
@ -42,8 +41,6 @@ private slots:
void onOldChanged(); void onOldChanged();
void onNewChanged(); void onNewChanged();
void onEmailChanged(); void onEmailChanged();
void onForceNoMail();
void onBoxDestroyed(QObject *obj);
void onRecoverByEmail(); void onRecoverByEmail();
void onRecoverExpired(); void onRecoverExpired();
void onSubmit(); void onSubmit();
@ -52,12 +49,14 @@ signals:
void reloadPassword(); void reloadPassword();
protected: protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void init(); void closeReplacedBy();
void setPasswordDone(const MTPBool &result); void setPasswordDone(const MTPBool &result);
bool setPasswordFail(const RPCError &error); bool setPasswordFail(const RPCError &error);
@ -68,7 +67,7 @@ private:
void recover(); void recover();
QString _pattern; QString _pattern;
AbstractBox *_replacedBy = nullptr; QPointer<BoxContent> _replacedBy;
bool _turningOff = false; bool _turningOff = false;
bool _cloudPwd = false; bool _cloudPwd = false;
mtpRequestId _setRequest = 0; mtpRequestId _setRequest = 0;
@ -81,24 +80,22 @@ private:
Text _about, _hintText; Text _about, _hintText;
ChildWidget<Ui::RoundButton> _saveButton; object_ptr<Ui::PasswordInput> _oldPasscode;
ChildWidget<Ui::RoundButton> _cancelButton; object_ptr<Ui::PasswordInput> _newPasscode;
ChildWidget<Ui::PasswordInput> _oldPasscode; object_ptr<Ui::PasswordInput> _reenterPasscode;
ChildWidget<Ui::PasswordInput> _newPasscode; object_ptr<Ui::InputField> _passwordHint;
ChildWidget<Ui::PasswordInput> _reenterPasscode; object_ptr<Ui::InputField> _recoverEmail;
ChildWidget<Ui::InputField> _passwordHint; object_ptr<Ui::LinkButton> _recover;
ChildWidget<Ui::InputField> _recoverEmail;
ChildWidget<Ui::LinkButton> _recover;
QString _oldError, _newError, _emailError; QString _oldError, _newError, _emailError;
}; };
class RecoverBox : public AbstractBox, public RPCSender { class RecoverBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
RecoverBox(const QString &pattern); RecoverBox(QWidget*, const QString &pattern);
public slots: public slots:
void onSubmit(); void onSubmit();
@ -109,22 +106,21 @@ signals:
void recoveryExpired(); void recoveryExpired();
protected: protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void codeSubmitDone(bool recover, const MTPauth_Authorization &result); void codeSubmitDone(bool recover, const MTPauth_Authorization &result);
bool codeSubmitFail(const RPCError &error); bool codeSubmitFail(const RPCError &error);
mtpRequestId _submitRequest; mtpRequestId _submitRequest = 0;
QString _pattern; QString _pattern;
ChildWidget<Ui::RoundButton> _saveButton; object_ptr<Ui::InputField> _recoverCode;
ChildWidget<Ui::RoundButton> _cancelButton;
ChildWidget<Ui::InputField> _recoverCode;
QString _error; QString _error;

View file

@ -29,20 +29,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : AbstractBox() PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer)
, _downState(0) : _img(img)
, _done(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _img(img)
, _peerId(peer) { , _peerId(peer) {
init(img, 0); init(img, nullptr);
} }
PhotoCropBox::PhotoCropBox(const QImage &img, PeerData *peer) : AbstractBox() PhotoCropBox::PhotoCropBox(QWidget*, const QImage &img, PeerData *peer)
, _downState(0) : _img(img)
, _done(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _img(img)
, _peerId(peer->id) { , _peerId(peer->id) {
init(img, peer); init(img, peer);
} }
@ -55,15 +49,17 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) {
} else { } else {
_title = lang(lng_settings_crop_profile); _title = lang(lng_settings_crop_profile);
} }
}
connect(_done, SIGNAL(clicked()), this, SLOT(onSend())); void PhotoCropBox::prepare() {
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); addButton(lang(lng_settings_save), [this] { sendPhoto(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
if (peerToBareInt(_peerId)) { if (peerToBareInt(_peerId)) {
connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&))); connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&)));
} }
int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
_thumb = App::pixmapFromImageInPlace(img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); _thumb = App::pixmapFromImageInPlace(_img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor()); _thumb.setDevicePixelRatio(cRetinaFactor());
_mask = QImage(_thumb.size(), QImage::Format_ARGB32_Premultiplied); _mask = QImage(_thumb.size(), QImage::Format_ARGB32_Premultiplied);
_mask.setDevicePixelRatio(cRetinaFactor()); _mask.setDevicePixelRatio(cRetinaFactor());
@ -83,23 +79,22 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) {
_thumby = st::boxPhotoPadding.top(); _thumby = st::boxPhotoPadding.top();
setMouseTracking(true); setMouseTracking(true);
resizeMaxHeight(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip + st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWideWidth, st::boxPhotoPadding.top() + _thumbh + st::boxPhotoPadding.bottom() + st::boxTextFont->height + st::cropSkip);
} }
void PhotoCropBox::mousePressEvent(QMouseEvent *e) { void PhotoCropBox::mousePressEvent(QMouseEvent *e) {
if (e->button() != Qt::LeftButton) return LayerWidget::mousePressEvent(e); if (e->button() == Qt::LeftButton) {
_downState = mouseState(e->pos());
_downState = mouseState(e->pos()); _fromposx = e->pos().x();
_fromposx = e->pos().x(); _fromposy = e->pos().y();
_fromposy = e->pos().y(); _fromcropx = _cropx;
_fromcropx = _cropx; _fromcropy = _cropy;
_fromcropy = _cropy; _fromcropw = _cropw;
_fromcropw = _cropw; }
return BoxContent::mousePressEvent(e);
return LayerWidget::mousePressEvent(e);
} }
int32 PhotoCropBox::mouseState(QPoint p) { int PhotoCropBox::mouseState(QPoint p) {
p -= QPoint(_thumbx, _thumby); p -= QPoint(_thumbx, _thumby);
int32 delta = st::cropPointSize, mdelta(-delta / 2); int32 delta = st::cropPointSize, mdelta(-delta / 2);
if (QRect(_cropx + mdelta, _cropy + mdelta, delta, delta).contains(p)) { if (QRect(_cropx + mdelta, _cropy + mdelta, delta, delta).contains(p)) {
@ -225,14 +220,14 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
void PhotoCropBox::keyPressEvent(QKeyEvent *e) { void PhotoCropBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onSend(); sendPhoto();
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void PhotoCropBox::paintEvent(QPaintEvent *e) { void PhotoCropBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -262,14 +257,8 @@ void PhotoCropBox::paintEvent(QPaintEvent *e) {
p.fillRect(QRect(_cropx + mdelta, _cropy + _cropw + mdelta, delta, delta), st::photoCropPointFg); p.fillRect(QRect(_cropx + mdelta, _cropy + _cropw + mdelta, delta, delta), st::photoCropPointFg);
} }
void PhotoCropBox::resizeEvent(QResizeEvent *e) { void PhotoCropBox::sendPhoto() {
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); auto from = _img;
_cancel->moveToRight(st::boxButtonPadding.right() + _done->width() + st::boxButtonPadding.left(), _done->y());
AbstractBox::resizeEvent(e);
}
void PhotoCropBox::onSend() {
QImage from(_img);
if (_img.width() < _thumb.width()) { if (_img.width() < _thumb.width()) {
from = _thumb.toImage(); from = _thumb.toImage();
} }
@ -302,7 +291,7 @@ void PhotoCropBox::onSend() {
} }
emit ready(tosend); emit ready(tosend);
onClose(); closeBox();
} }
void PhotoCropBox::onReady(const QImage &tosend) { void PhotoCropBox::onReady(const QImage &tosend) {

View file

@ -22,44 +22,44 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h" #include "boxes/abstractbox.h"
namespace Ui { class PhotoCropBox : public BoxContent {
class RoundButton;
} // namespace Ui
class PhotoCropBox : public AbstractBox {
Q_OBJECT Q_OBJECT
public: public:
PhotoCropBox(const QImage &img, const PeerId &peer); PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer);
PhotoCropBox(const QImage &img, PeerData *peer); PhotoCropBox(QWidget*, const QImage &img, PeerData *peer);
int32 mouseState(QPoint p); int32 mouseState(QPoint p);
public slots: void closeHook() override {
void onSend(); emit closed();
void onReady(const QImage &tosend); }
signals: signals:
void ready(const QImage &tosend); void ready(const QImage &tosend);
void closed();
private slots:
void onReady(const QImage &tosend);
protected: protected:
void prepare() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
private: private:
void init(const QImage &img, PeerData *peer); void init(const QImage &img, PeerData *peer);
void sendPhoto();
QString _title; QString _title;
int32 _downState; int32 _downState = 0;
int32 _thumbx, _thumby, _thumbw, _thumbh; int32 _thumbx, _thumby, _thumbw, _thumbh;
int32 _cropx, _cropy, _cropw; int32 _cropx, _cropy, _cropw;
int32 _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw; int32 _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw;
ChildWidget<Ui::RoundButton> _done;
ChildWidget<Ui::RoundButton> _cancel;
QImage _img; QImage _img;
QPixmap _thumb; QPixmap _thumb;
QImage _mask, _fade; QImage _mask, _fade;

View file

@ -30,18 +30,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "mainwindow.h" #include "mainwindow.h"
ReportBox::ReportBox(PeerData *peer) : AbstractBox(st::boxWidth) ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer)
, _peer(peer)
, _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true, st::defaultBoxCheckbox) , _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true, st::defaultBoxCheckbox)
, _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence), false, st::defaultBoxCheckbox) , _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence), false, st::defaultBoxCheckbox)
, _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography), false, st::defaultBoxCheckbox) , _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography), false, st::defaultBoxCheckbox)
, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox) , _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox) {
, _report(this, lang(lng_report_button), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
setTitleText(lang(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
connect(_report, SIGNAL(clicked()), this, SLOT(onReport())); void ReportBox::prepare() {
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); setTitle(lang(_peer->isUser() ? lng_report_bot_title : (_peer->isMegagroup() ? lng_report_group_title : lng_report_title)));
addButton(lang(lng_report_button), [this] { onReport(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_reasonSpam, SIGNAL(changed()), this, SLOT(onChange())); connect(_reasonSpam, SIGNAL(changed()), this, SLOT(onChange()));
connect(_reasonViolence, SIGNAL(changed()), this, SLOT(onChange())); connect(_reasonViolence, SIGNAL(changed()), this, SLOT(onChange()));
@ -52,18 +52,16 @@ ReportBox::ReportBox(PeerData *peer) : AbstractBox(st::boxWidth)
} }
void ReportBox::resizeEvent(QResizeEvent *e) { void ReportBox::resizeEvent(QResizeEvent *e) {
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); BoxContent::resizeEvent(e);
_reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListPadding.top());
_reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListPadding.top()); _reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top());
_reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListPadding.top()); _reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListSkip);
_reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListSkip);
_reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListSkip);
if (_reasonOtherText) { if (_reasonOtherText) {
_reasonOtherText->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() - st::defaultInputField.textMargins.left(), _reasonOther->bottomNoMargins() + st::newGroupDescriptionPadding.top()); _reasonOtherText->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() - st::defaultInputField.textMargins.left(), _reasonOther->bottomNoMargins() + st::newGroupDescriptionPadding.top());
} }
_report->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _report->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _report->width() + st::boxButtonPadding.left(), _report->y());
AbstractBox::resizeEvent(e);
} }
void ReportBox::onChange() { void ReportBox::onChange() {
@ -87,7 +85,7 @@ void ReportBox::onChange() {
} }
} }
void ReportBox::doSetInnerFocus() { void ReportBox::setInnerFocus() {
if (_reasonOtherText) { if (_reasonOtherText) {
_reasonOtherText->setFocus(); _reasonOtherText->setFocus();
} else { } else {
@ -124,7 +122,7 @@ void ReportBox::onReport() {
void ReportBox::reportDone(const MTPBool &result) { void ReportBox::reportDone(const MTPBool &result) {
_requestId = 0; _requestId = 0;
Ui::showLayer(new InformBox(lang(lng_report_thanks))); Ui::show(Box<InformBox>(lang(lng_report_thanks)));
} }
bool ReportBox::reportFail(const RPCError &error) { bool ReportBox::reportFail(const RPCError &error) {
@ -138,9 +136,9 @@ bool ReportBox::reportFail(const RPCError &error) {
} }
void ReportBox::updateMaxHeight() { void ReportBox::updateMaxHeight() {
int32 h = titleHeight() + 4 * (st::boxOptionListPadding.top() + _reasonSpam->heightNoMargins()) + st::boxButtonPadding.top() + _report->height() + st::boxButtonPadding.bottom(); auto newHeight = st::boxOptionListPadding.top() + 4 * _reasonSpam->heightNoMargins() + 3 * st::boxOptionListSkip + st::boxOptionListPadding.bottom();
if (_reasonOtherText) { if (_reasonOtherText) {
h += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom(); newHeight += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom();
} }
setMaxHeight(h); setDimensions(st::boxWidth, newHeight);
} }

View file

@ -24,15 +24,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class Radiobutton; class Radiobutton;
class RoundButton;
class InputArea; class InputArea;
} // namespace Ui } // namespace Ui
class ReportBox : public AbstractBox, public RPCSender { class ReportBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
ReportBox(PeerData *peer); ReportBox(QWidget*, PeerData *peer);
private slots: private slots:
void onReport(); void onReport();
@ -40,9 +39,10 @@ private slots:
void onDescriptionResized(); void onDescriptionResized();
protected: protected:
void resizeEvent(QResizeEvent *e) override; void prepare() override;
void setInnerFocus() override;
void doSetInnerFocus() override; void resizeEvent(QResizeEvent *e) override;
private: private:
void updateMaxHeight(); void updateMaxHeight();
@ -52,13 +52,11 @@ private:
PeerData *_peer; PeerData *_peer;
ChildWidget<Ui::Radiobutton> _reasonSpam; object_ptr<Ui::Radiobutton> _reasonSpam;
ChildWidget<Ui::Radiobutton> _reasonViolence; object_ptr<Ui::Radiobutton> _reasonViolence;
ChildWidget<Ui::Radiobutton> _reasonPornography; object_ptr<Ui::Radiobutton> _reasonPornography;
ChildWidget<Ui::Radiobutton> _reasonOther; object_ptr<Ui::Radiobutton> _reasonOther;
ChildWidget<Ui::InputArea> _reasonOtherText = { nullptr }; object_ptr<Ui::InputArea> _reasonOtherText = { nullptr };
ChildWidget<Ui::RoundButton> _report, _cancel;
enum Reason { enum Reason {
ReasonSpam, ReasonSpam,

View file

@ -38,14 +38,12 @@ constexpr auto kMinPreviewWidth = 20;
} // namespace } // namespace
SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfirm compressed, bool animated) : AbstractBox(st::boxWideWidth) SendFilesBox::SendFilesBox(QWidget*, const QString &filepath, QImage image, CompressConfirm compressed, bool animated)
, _files(filepath) : _files(filepath)
, _image(image) , _image(image)
, _compressConfirm(compressed) , _compressConfirm(compressed)
, _animated(image.isNull() ? false : animated) , _animated(image.isNull() ? false : animated)
, _caption(this, st::confirmCaptionArea, lang(lng_photo_caption)) , _caption(this, st::confirmCaptionArea, lang(lng_photo_caption)) {
, _send(this, lang(lng_send_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
if (!image.isNull()) { if (!image.isNull()) {
if (!_animated && _compressConfirm == CompressConfirm::None) { if (!_animated && _compressConfirm == CompressConfirm::None) {
auto originalWidth = image.width(); auto originalWidth = image.width();
@ -60,7 +58,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
auto maxW = 0; auto maxW = 0;
auto maxH = 0; auto maxH = 0;
if (_animated) { if (_animated) {
auto limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); auto limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
auto limitH = st::confirmMaxHeight; auto limitH = st::confirmMaxHeight;
maxW = qMax(image.width(), 1); maxW = qMax(image.width(), 1);
maxH = qMax(image.height(), 1); maxH = qMax(image.height(), 1);
@ -82,7 +80,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
if (!originalWidth || !originalHeight) { if (!originalWidth || !originalHeight) {
originalWidth = originalHeight = 1; originalWidth = originalHeight = 1;
} }
_previewWidth = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); _previewWidth = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
if (image.width() < _previewWidth) { if (image.width() < _previewWidth) {
_previewWidth = qMax(image.width(), kMinPreviewWidth); _previewWidth = qMax(image.width(), kMinPreviewWidth);
} }
@ -93,7 +91,7 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
accumulate_max(_previewWidth, kMinPreviewWidth); accumulate_max(_previewWidth, kMinPreviewWidth);
_previewHeight = maxthumbh; _previewHeight = maxthumbh;
} }
_previewLeft = (width() - _previewWidth) / 2; _previewLeft = (st::boxWideWidth - _previewWidth) / 2;
image = std_::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); image = std_::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
image = Images::prepareOpaque(std_::move(image)); image = Images::prepareOpaque(std_::move(image));
@ -117,37 +115,30 @@ SendFilesBox::SendFilesBox(const QString &filepath, QImage image, CompressConfir
_fileIsImage = fileIsImage(filename, mimeTypeForFile(fileinfo).name()); _fileIsImage = fileIsImage(filename, mimeTypeForFile(fileinfo).name());
} }
} }
setup();
} }
SendFilesBox::SendFilesBox(const QStringList &files, CompressConfirm compressed) : AbstractBox(st::boxWideWidth) SendFilesBox::SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed)
, _files(files) : _files(files)
, _compressConfirm(compressed) , _compressConfirm(compressed)
, _caption(this, st::confirmCaptionArea, lang(lng_photos_comment)) , _caption(this, st::confirmCaptionArea, lang(lng_photos_comment)) {
, _send(this, lang(lng_send_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
updateTitleText();
setup();
} }
SendFilesBox::SendFilesBox(const QString &phone, const QString &firstname, const QString &lastname) : AbstractBox(st::boxWideWidth) SendFilesBox::SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname)
, _contactPhone(phone) : _contactPhone(phone)
, _contactFirstName(firstname) , _contactFirstName(firstname)
, _contactLastName(lastname) , _contactLastName(lastname) {
, _send(this, lang(lng_send_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
_nameText.setText(st::semiboldFont, lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName), _textNameOptions); _nameText.setText(st::semiboldFont, lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName), _textNameOptions);
_statusText = _contactPhone; _statusText = _contactPhone;
_statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText)); _statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText));
setup();
} }
void SendFilesBox::setup() { void SendFilesBox::prepare() {
_send->setClickedCallback([this] { onSend(); }); if (_files.size() > 1) {
_cancel->setClickedCallback([this] { onClose(); }); updateTitleText();
}
_send = addButton(lang(lng_send_button), [this] { onSend(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
if (_compressConfirm != CompressConfirm::None) { if (_compressConfirm != CompressConfirm::None) {
auto compressed = (_compressConfirm == CompressConfirm::Auto) ? cCompressPastedImage() : (_compressConfirm == CompressConfirm::Yes); auto compressed = (_compressConfirm == CompressConfirm::Auto) ? cCompressPastedImage() : (_compressConfirm == CompressConfirm::Yes);
@ -163,6 +154,7 @@ void SendFilesBox::setup() {
connect(_caption, SIGNAL(cancelled()), this, SLOT(onClose())); connect(_caption, SIGNAL(cancelled()), this, SLOT(onClose()));
} }
_send->setText(getSendButtonText()); _send->setText(getSendButtonText());
updateButtonsGeometry();
updateBoxSize(); updateBoxSize();
} }
@ -176,8 +168,9 @@ QString SendFilesBox::getSendButtonText() const {
} }
void SendFilesBox::onCompressedChange() { void SendFilesBox::onCompressedChange() {
doSetInnerFocus(); setInnerFocus();
_send->setText(getSendButtonText()); _send->setText(getSendButtonText());
updateButtonsGeometry();
updateControlsGeometry(); updateControlsGeometry();
} }
@ -188,7 +181,7 @@ void SendFilesBox::onCaptionResized() {
} }
void SendFilesBox::updateTitleText() { void SendFilesBox::updateTitleText() {
_titleText = (_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size()); setTitle((_compressConfirm == CompressConfirm::None) ? lng_send_files_selected(lt_count, _files.size()) : lng_send_images_selected(lt_count, _files.size()));
update(); update();
} }
@ -199,7 +192,7 @@ void SendFilesBox::updateBoxSize() {
} else if (!_fileThumb.isNull()) { } else if (!_fileThumb.isNull()) {
newHeight += st::boxPhotoPadding.top() + st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom(); newHeight += st::boxPhotoPadding.top() + st::msgFileThumbPadding.top() + st::msgFileThumbSize + st::msgFileThumbPadding.bottom();
} else if (_files.size() > 1) { } else if (_files.size() > 1) {
newHeight += titleHeight(); newHeight += 0;
} else { } else {
newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
} }
@ -209,20 +202,19 @@ void SendFilesBox::updateBoxSize() {
if (_caption) { if (_caption) {
newHeight += st::boxPhotoCaptionSkip + _caption->height(); newHeight += st::boxPhotoCaptionSkip + _caption->height();
} }
newHeight += st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom(); setDimensions(st::boxWideWidth, newHeight);
setMaxHeight(newHeight);
} }
void SendFilesBox::keyPressEvent(QKeyEvent *e) { void SendFilesBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
onSend((e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier)) && e->modifiers().testFlag(Qt::ShiftModifier)); onSend((e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier)) && e->modifiers().testFlag(Qt::ShiftModifier));
} else { } else {
AbstractBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void SendFilesBox::paintEvent(QPaintEvent *e) { void SendFilesBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -306,14 +298,12 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
} }
void SendFilesBox::resizeEvent(QResizeEvent *e) { void SendFilesBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
updateControlsGeometry(); updateControlsGeometry();
AbstractBox::resizeEvent(e);
} }
void SendFilesBox::updateControlsGeometry() { void SendFilesBox::updateControlsGeometry() {
_send->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _send->height()); auto bottom = height();
_cancel->moveToRight(st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y());
auto bottom = _send->y() - st::boxButtonPadding.top();
if (_caption) { if (_caption) {
_caption->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _caption->height()); _caption->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _caption->height());
_caption->moveToLeft(st::boxPhotoPadding.left(), bottom - _caption->height()); _caption->moveToLeft(st::boxPhotoPadding.left(), bottom - _caption->height());
@ -325,7 +315,7 @@ void SendFilesBox::updateControlsGeometry() {
} }
} }
void SendFilesBox::doSetInnerFocus() { void SendFilesBox::setInnerFocus() {
if (!_caption || _caption->isHidden()) { if (!_caption || _caption->isHidden()) {
setFocus(); setFocus();
} else { } else {
@ -344,33 +334,17 @@ void SendFilesBox::onSend(bool ctrlShiftEnter) {
auto caption = _caption ? prepareText(_caption->getLastText(), true) : QString(); auto caption = _caption ? prepareText(_caption->getLastText(), true) : QString();
_confirmedCallback(_files, compressed, caption, ctrlShiftEnter); _confirmedCallback(_files, compressed, caption, ctrlShiftEnter);
} }
onClose(); closeBox();
} }
void SendFilesBox::closePressed() { void SendFilesBox::closeHook() {
if (!_confirmed && _cancelledCallback) { if (!_confirmed && _cancelledCallback) {
_cancelledCallback(); _cancelledCallback();
} }
} }
EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth) EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg)
, _msgId(msg->fullId()) : _msgId(msg->fullId()) {
, _animated(false)
, _photo(false)
, _doc(false)
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _thumbx(0)
, _thumby(0)
, _thumbw(0)
, _thumbh(0)
, _statusw(0)
, _isImage(false)
, _previewCancelled(false)
, _saveRequestId(0) {
connect(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
QSize dimensions; QSize dimensions;
ImagePtr image; ImagePtr image;
QString caption; QString caption;
@ -437,7 +411,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
} else { } else {
int32 maxW = 0, maxH = 0; int32 maxW = 0, maxH = 0;
if (_animated) { if (_animated) {
int32 limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); int32 limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
int32 limitH = st::confirmMaxHeight; int32 limitH = st::confirmMaxHeight;
maxW = qMax(dimensions.width(), 1); maxW = qMax(dimensions.width(), 1);
maxH = qMax(dimensions.height(), 1); maxH = qMax(dimensions.height(), 1);
@ -462,7 +436,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
if (!tw || !th) { if (!tw || !th) {
tw = th = 1; tw = th = 1;
} }
_thumbw = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(); _thumbw = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
if (_thumb.width() < _thumbw) { if (_thumb.width() < _thumbw) {
_thumbw = (_thumb.width() > 20) ? _thumb.width() : 20; _thumbw = (_thumb.width() > 20) ? _thumb.width() : 20;
} }
@ -475,35 +449,50 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
_thumbw = 10; _thumbw = 10;
} }
} }
_thumbx = (width() - _thumbw) / 2; _thumbx = (st::boxWideWidth - _thumbw) / 2;
_thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); _thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor()); _thumb.setDevicePixelRatio(cRetinaFactor());
} }
if (_animated || _photo || _doc) { if (_animated || _photo || _doc) {
_field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption); _field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
_field->setMaxLength(MaxPhotoCaption); _field->setMaxLength(MaxPhotoCaption);
_field->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both); _field->setCtrlEnterSubmit(Ui::CtrlEnterSubmit::Both);
} else { } else {
auto original = msg->originalText(); auto original = msg->originalText();
QString text = textApplyEntities(original.text, original.entities); auto text = textApplyEntities(original.text, original.entities);
_field.create(this, st::editTextArea, lang(lng_photo_caption), text); _field.create(this, st::editTextArea, lang(lng_photo_caption), text);
// _field->setMaxLength(MaxMessageSize); // entities can make text in input field larger but still valid // _field->setMaxLength(MaxMessageSize); // entities can make text in input field larger but still valid
_field->setCtrlEnterSubmit(cCtrlEnter() ? Ui::CtrlEnterSubmit::CtrlEnter : Ui::CtrlEnterSubmit::Enter); _field->setCtrlEnterSubmit(cCtrlEnter() ? Ui::CtrlEnterSubmit::CtrlEnter : Ui::CtrlEnterSubmit::Enter);
} }
}
bool EditCaptionBox::canEdit(HistoryItem *message) {
if (auto media = message->getMedia()) {
switch (media->type()) {
case MediaTypeGif:
case MediaTypePhoto:
case MediaTypeVideo:
case MediaTypeFile:
case MediaTypeMusicFile:
case MediaTypeVoiceFile: return true;
}
}
return false;
}
void EditCaptionBox::prepare() {
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
updateBoxSize(); updateBoxSize();
connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool))); connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool)));
connect(_field, SIGNAL(cancelled()), this, SLOT(onClose())); connect(_field, SIGNAL(cancelled()), this, SLOT(onClose()));
connect(_field, SIGNAL(resized()), this, SLOT(onCaptionResized())); connect(_field, SIGNAL(resized()), this, SLOT(onCaptionResized()));
QTextCursor c(_field->textCursor()); auto cursor = _field->textCursor();
c.movePosition(QTextCursor::End); cursor.movePosition(QTextCursor::End);
_field->setTextCursor(c); _field->setTextCursor(cursor);
}
bool EditCaptionBox::captionFound() const {
return _animated || _photo || _doc;
} }
void EditCaptionBox::onCaptionResized() { void EditCaptionBox::onCaptionResized() {
@ -513,29 +502,30 @@ void EditCaptionBox::onCaptionResized() {
} }
void EditCaptionBox::updateBoxSize() { void EditCaptionBox::updateBoxSize() {
auto bottomh = st::boxPhotoCaptionSkip + _field->height() + st::normalFont->height + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); auto newHeight = st::boxPhotoPadding.top() + st::boxPhotoCaptionSkip + _field->height() + st::normalFont->height;
if (_photo || _animated) { if (_photo || _animated) {
setMaxHeight(st::boxPhotoPadding.top() + _thumbh + bottomh); newHeight += _thumbh;
} else if (_thumbw) { } else if (_thumbw) {
setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileThumbSize + 0 + bottomh); newHeight += 0 + st::msgFileThumbSize + 0;
} else if (_doc) { } else if (_doc) {
setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileSize + 0 + bottomh); newHeight += 0 + st::msgFileSize + 0;
} else { } else {
setMaxHeight(st::boxPhotoPadding.top() + st::boxTitleFont->height + bottomh); newHeight += st::boxTitleFont->height;
} }
setDimensions(st::boxWideWidth, newHeight);
} }
void EditCaptionBox::paintEvent(QPaintEvent *e) { void EditCaptionBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
if (_photo || _animated) { if (_photo || _animated) {
if (_thumbx > st::boxPhotoPadding.left()) { if (_thumbx > st::boxPhotoPadding.left()) {
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg->b); p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg);
} }
if (_thumbx + _thumbw < width() - st::boxPhotoPadding.right()) { if (_thumbx + _thumbw < width() - st::boxPhotoPadding.right()) {
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg->b); p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg);
} }
p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb); p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb);
if (_animated) { if (_animated) {
@ -613,14 +603,12 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
} }
void EditCaptionBox::resizeEvent(QResizeEvent *e) { void EditCaptionBox::resizeEvent(QResizeEvent *e) {
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); BoxContent::resizeEvent(e);
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
_field->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _field->height()); _field->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _field->height());
_field->moveToLeft(st::boxPhotoPadding.left(), _save->y() - st::boxButtonPadding.top() - st::normalFont->height - _field->height()); _field->moveToLeft(st::boxPhotoPadding.left(), height() - st::normalFont->height - _field->height());
AbstractBox::resizeEvent(e);
} }
void EditCaptionBox::doSetInnerFocus() { void EditCaptionBox::setInnerFocus() {
_field->setFocus(); _field->setFocus();
} }
@ -648,7 +636,7 @@ void EditCaptionBox::onSave(bool ctrlShiftEnter) {
void EditCaptionBox::saveDone(const MTPUpdates &updates) { void EditCaptionBox::saveDone(const MTPUpdates &updates) {
_saveRequestId = 0; _saveRequestId = 0;
onClose(); closeBox();
if (App::main()) { if (App::main()) {
App::main()->sentUpdatesReceived(updates); App::main()->sentUpdatesReceived(updates);
} }
@ -662,7 +650,7 @@ bool EditCaptionBox::saveFail(const RPCError &error) {
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) { if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
_error = lang(lng_edit_error); _error = lang(lng_edit_error);
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) { } else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
onClose(); closeBox();
return true; return true;
} else if (err == qstr("MESSAGE_EMPTY")) { } else if (err == qstr("MESSAGE_EMPTY")) {
_field->setFocus(); _field->setFocus();

View file

@ -29,13 +29,13 @@ class RoundButton;
class InputArea; class InputArea;
} // namespace Ui } // namespace Ui
class SendFilesBox : public AbstractBox { class SendFilesBox : public BoxContent {
Q_OBJECT Q_OBJECT
public: public:
SendFilesBox(const QString &filepath, QImage image, CompressConfirm compressed, bool animated = false); SendFilesBox(QWidget*, const QString &filepath, QImage image, CompressConfirm compressed, bool animated = false);
SendFilesBox(const QStringList &files, CompressConfirm compressed); SendFilesBox(QWidget*, const QStringList &files, CompressConfirm compressed);
SendFilesBox(const QString &phone, const QString &firstname, const QString &lastname); SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname);
void setConfirmedCallback(base::lambda<void(const QStringList &files, bool compressed, const QString &caption, bool ctrlShiftEnter)> &&callback) { void setConfirmedCallback(base::lambda<void(const QStringList &files, bool compressed, const QString &caption, bool ctrlShiftEnter)> &&callback) {
_confirmedCallback = std_::move(callback); _confirmedCallback = std_::move(callback);
@ -44,21 +44,22 @@ public:
_cancelledCallback = std_::move(callback); _cancelledCallback = std_::move(callback);
} }
public slots: void closeHook() override;
void onCompressedChange();
void onSend(bool ctrlShiftEnter = false);
void onCaptionResized();
protected: protected:
void prepare() override;
void setInnerFocus() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void closePressed() override; private slots:
void doSetInnerFocus() override; void onCompressedChange();
void onSend(bool ctrlShiftEnter = false);
void onCaptionResized();
private: private:
void setup();
void updateTitleText(); void updateTitleText();
void updateBoxSize(); void updateBoxSize();
void updateControlsGeometry(); void updateControlsGeometry();
@ -90,32 +91,31 @@ private:
base::lambda<void()> _cancelledCallback; base::lambda<void()> _cancelledCallback;
bool _confirmed = false; bool _confirmed = false;
ChildWidget<Ui::InputArea> _caption = { nullptr }; object_ptr<Ui::InputArea> _caption = { nullptr };
ChildWidget<Ui::Checkbox> _compressed = { nullptr }; object_ptr<Ui::Checkbox> _compressed = { nullptr };
ChildWidget<Ui::RoundButton> _send; QPointer<Ui::RoundButton> _send;
ChildWidget<Ui::RoundButton> _cancel;
}; };
class EditCaptionBox : public AbstractBox, public RPCSender { class EditCaptionBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
EditCaptionBox(HistoryItem *msg); EditCaptionBox(QWidget*, HistoryItem *msg);
static bool canEdit(HistoryItem *message);
bool captionFound() const;
public slots: public slots:
void onCaptionResized(); void onCaptionResized();
void onSave(bool ctrlShiftEnter = false); void onSave(bool ctrlShiftEnter = false);
protected: protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void updateBoxSize(); void updateBoxSize();
@ -123,22 +123,25 @@ private:
bool saveFail(const RPCError &error); bool saveFail(const RPCError &error);
FullMsgId _msgId; FullMsgId _msgId;
bool _animated, _photo, _doc; bool _animated = false;
bool _photo = false;
bool _doc = false;
QPixmap _thumb; QPixmap _thumb;
ChildWidget<Ui::InputArea> _field = { nullptr }; object_ptr<Ui::InputArea> _field = { nullptr };
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
int32 _thumbx, _thumby, _thumbw, _thumbh; int _thumbx = 0;
int _thumby = 0;
int _thumbw = 0;
int _thumbh = 0;
Text _name; Text _name;
QString _status; QString _status;
int32 _statusw; int _statusw = 0;
bool _isImage; bool _isImage = false;
bool _previewCancelled; bool _previewCancelled = false;
mtpRequestId _saveRequestId; mtpRequestId _saveRequestId = 0;
QString _error; QString _error;

View file

@ -31,53 +31,49 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
SessionsBox::SessionsBox() : ScrollableBox(st::sessionsScroll) SessionsBox::SessionsBox(QWidget*)
, _loading(false) : _shortPollTimer(this) {
, _inner(this, &_list, &_current) }
, _shadow(this)
, _done(this, lang(lng_about_done), st::defaultBoxButton) void SessionsBox::prepare() {
, _shortPollRequest(0) { setTitle(lang(lng_sessions_other_header));
setMaxHeight(st::sessionsHeight);
setTitleText(lang(lng_sessions_other_header)); addButton(lang(lng_close), [this] { closeBox(); });
setDimensions(st::boxWideWidth, st::sessionsHeight);
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_inner, SIGNAL(oneTerminated()), this, SLOT(onOneTerminated())); connect(_inner, SIGNAL(oneTerminated()), this, SLOT(onOneTerminated()));
connect(_inner, SIGNAL(allTerminated()), this, SLOT(onAllTerminated())); connect(_inner, SIGNAL(allTerminated()), this, SLOT(onAllTerminated()));
connect(_inner, SIGNAL(terminateAll()), this, SLOT(onTerminateAll())); connect(_inner, SIGNAL(terminateAll()), this, SLOT(onTerminateAll()));
connect(App::wnd(), SIGNAL(checkNewAuthorization()), this, SLOT(onCheckNewAuthorization())); connect(App::wnd(), SIGNAL(checkNewAuthorization()), this, SLOT(onCheckNewAuthorization()));
connect(&_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations())); connect(_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations()));
init(_inner, st::boxButtonPadding.bottom() + _done->height() + st::boxButtonPadding.top(), titleHeight()); _inner = setInnerWidget(object_ptr<Inner>(this, &_list, &_current), st::sessionsScroll);
_inner->resize(width(), st::noContactsHeight); _inner->resize(width(), st::noContactsHeight);
setLoading(true); setLoading(true);
raiseShadow();
MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations)); MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations));
} }
void SessionsBox::setLoading(bool loading) { void SessionsBox::setLoading(bool loading) {
if (_loading != loading) { if (_loading != loading) {
_loading = loading; _loading = loading;
scrollArea()->setVisible(!_loading); setInnerVisible(!_loading);
_shadow->setVisible(!_loading);
} }
} }
void SessionsBox::resizeEvent(QResizeEvent *e) { void SessionsBox::resizeEvent(QResizeEvent *e) {
ScrollableBox::resizeEvent(e); BoxContent::resizeEvent(e);
_shadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _done->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height()); _inner->resize(width(), _inner->height());
} }
void SessionsBox::paintEvent(QPaintEvent *e) { void SessionsBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
p.translate(0, titleHeight());
if (_loading) { if (_loading) {
p.setFont(st::noContactsFont); p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor); p.setPen(st::noContactsColor);
@ -202,7 +198,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
update(); update();
_shortPollTimer.start(SessionsShortPollTimeout); _shortPollTimer->start(SessionsShortPollTimeout);
} }
void SessionsBox::onOneTerminated() { void SessionsBox::onOneTerminated() {
@ -236,9 +232,7 @@ void SessionsBox::onTerminateAll() {
SessionsBox::Inner::Inner(QWidget *parent, SessionsBox::List *list, SessionsBox::Data *current) : TWidget(parent) SessionsBox::Inner::Inner(QWidget *parent, SessionsBox::List *list, SessionsBox::Data *current) : TWidget(parent)
, _list(list) , _list(list)
, _current(current) , _current(current)
, _terminating(0) , _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton) {
, _terminateAll(this, lang(lng_sessions_terminate_all), st::sessionTerminateAllButton)
, _terminateBox(0) {
connect(_terminateAll, SIGNAL(clicked()), this, SLOT(onTerminateAll())); connect(_terminateAll, SIGNAL(clicked()), this, SLOT(onTerminateAll()));
_terminateAll->hide(); _terminateAll->hide();
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
@ -312,49 +306,33 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
void SessionsBox::Inner::onTerminate() { void SessionsBox::Inner::onTerminate() {
for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) { for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) {
if (i.value()->isOver()) { if (i.value()->isOver()) {
_terminating = i.key();
if (_terminateBox) _terminateBox->deleteLater(); if (_terminateBox) _terminateBox->deleteLater();
_terminateBox = new ConfirmBox(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button), st::attentionBoxButton); _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()] {
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateSure())); if (_terminateBox) {
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*))); _terminateBox->closeBox();
Ui::showLayer(_terminateBox, KeepOtherLayers); _terminateBox = nullptr;
}
MTP::send(MTPaccount_ResetAuthorization(MTP_long(terminating)), rpcDone(&Inner::terminateDone, terminating), rpcFail(&Inner::terminateFail, terminating));
TerminateButtons::iterator i = _terminateButtons.find(terminating);
if (i != _terminateButtons.cend()) {
i.value()->clearState();
i.value()->hide();
}
})), KeepOtherLayers);
} }
} }
} }
void SessionsBox::Inner::onTerminateSure() {
if (_terminateBox) {
_terminateBox->onClose();
_terminateBox = 0;
}
MTP::send(MTPaccount_ResetAuthorization(MTP_long(_terminating)), rpcDone(&Inner::terminateDone, _terminating), rpcFail(&Inner::terminateFail, _terminating));
TerminateButtons::iterator i = _terminateButtons.find(_terminating);
if (i != _terminateButtons.cend()) {
i.value()->clearState();
i.value()->hide();
}
}
void SessionsBox::Inner::onTerminateAll() { void SessionsBox::Inner::onTerminateAll() {
if (_terminateBox) _terminateBox->deleteLater(); if (_terminateBox) _terminateBox->deleteLater();
_terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton); _terminateBox = Ui::show(Box<ConfirmBox>(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton, base::lambda_guarded(this, [this] {
connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateAllSure())); if (_terminateBox) {
connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*))); _terminateBox->closeBox();
Ui::showLayer(_terminateBox, KeepOtherLayers); _terminateBox = nullptr;
} }
MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
void SessionsBox::Inner::onTerminateAllSure() { emit terminateAll();
if (_terminateBox) { })), KeepOtherLayers);
_terminateBox->onClose();
_terminateBox = 0;
}
MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&Inner::terminateAllDone), rpcFail(&Inner::terminateAllFail));
emit terminateAll();
}
void SessionsBox::Inner::onNoTerminateBox(QObject *obj) {
if (obj == _terminateBox) _terminateBox = 0;
} }
void SessionsBox::Inner::terminateDone(uint64 hash, const MTPBool &result) { void SessionsBox::Inner::terminateDone(uint64 hash, const MTPBool &result) {

View file

@ -28,26 +28,27 @@ class ConfirmBox;
namespace Ui { namespace Ui {
class IconButton; class IconButton;
class LinkButton; class LinkButton;
class RoundButton;
} // namespace Ui } // namespace Ui
class SessionsBox : public ScrollableBox, public RPCSender { class SessionsBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
SessionsBox(); SessionsBox(QWidget*);
public slots: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private slots:
void onOneTerminated(); void onOneTerminated();
void onAllTerminated(); void onAllTerminated();
void onTerminateAll(); void onTerminateAll();
void onShortPollAuthorizations(); void onShortPollAuthorizations();
void onCheckNewAuthorization(); void onCheckNewAuthorization();
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
private: private:
void setLoading(bool loading); void setLoading(bool loading);
struct Data { struct Data {
@ -61,18 +62,16 @@ private:
void gotAuthorizations(const MTPaccount_Authorizations &result); void gotAuthorizations(const MTPaccount_Authorizations &result);
bool _loading; bool _loading = false;
Data _current; Data _current;
List _list; List _list;
class Inner; class Inner;
ChildWidget<Inner> _inner; QPointer<Inner> _inner;
ChildWidget<ScrollableBoxShadow> _shadow;
ChildWidget<Ui::RoundButton> _done;
SingleTimer _shortPollTimer; object_ptr<SingleTimer> _shortPollTimer;
mtpRequestId _shortPollRequest; mtpRequestId _shortPollRequest = 0;
}; };
@ -96,10 +95,7 @@ signals:
public slots: public slots:
void onTerminate(); void onTerminate();
void onTerminateSure();
void onTerminateAll(); void onTerminateAll();
void onTerminateAllSure();
void onNoTerminateBox(QObject *obj);
private: private:
void terminateDone(uint64 hash, const MTPBool &result); void terminateDone(uint64 hash, const MTPBool &result);
@ -114,8 +110,7 @@ private:
typedef QMap<uint64, Ui::IconButton*> TerminateButtons; typedef QMap<uint64, Ui::IconButton*> TerminateButtons;
TerminateButtons _terminateButtons; TerminateButtons _terminateButtons;
uint64 _terminating; object_ptr<Ui::LinkButton> _terminateAll;
ChildWidget<Ui::LinkButton> _terminateAll; QPointer<ConfirmBox> _terminateBox;
ConfirmBox *_terminateBox;
}; };

View file

@ -39,29 +39,27 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "boxes/contactsbox.h" #include "boxes/contactsbox.h"
ShareBox::ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback) : ItemListBox(st::boxScroll) ShareBox::ShareBox(QWidget*, CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback)
, _copyCallback(std_::move(copyCallback)) : _copyCallback(std_::move(copyCallback))
, _submitCallback(std_::move(submitCallback)) , _submitCallback(std_::move(submitCallback))
, _inner(this, std_::move(filterCallback)) , _filterCallback(std_::move(filterCallback))
, _select(this, st::contactsMultiSelect, lang(lng_participant_filter)) , _select(this, st::contactsMultiSelect, lang(lng_participant_filter))
, _copy(this, lang(lng_share_copy_link), st::defaultBoxButton) , _searchTimer(this) {
, _share(this, lang(lng_share_confirm), st::defaultBoxButton) }
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this) void ShareBox::prepare() {
, _bottomShadow(this) {
_select->resizeToWidth(st::boxWideWidth); _select->resizeToWidth(st::boxWideWidth);
myEnsureResized(_select); myEnsureResized(_select);
setTitleText(lang(lng_share_title));
auto topSkip = getTopScrollSkip(); setTitle(lang(lng_share_title));
auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom();
init(_inner, bottomSkip, topSkip);
_inner = setInnerWidget(object_ptr<Inner>(this, std_::move(_filterCallback)), getTopScrollSkip());
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int))); connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
connect(_copy, SIGNAL(clicked()), this, SLOT(onCopyLink()));
connect(_share, SIGNAL(clicked()), this, SLOT(onSubmit())); createButtons();
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll())); setDimensions(st::boxWideWidth, st::boxMaxListHeight);
_select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); }); _select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
_select->setItemRemovedCallback([this](uint64 itemId) { _select->setItemRemovedCallback([this](uint64 itemId) {
if (auto peer = App::peerLoaded(itemId)) { if (auto peer = App::peerLoaded(itemId)) {
@ -77,16 +75,14 @@ ShareBox::ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback,
onPeerSelectedChanged(peer, checked); onPeerSelectedChanged(peer, checked);
}); });
_searchTimer.setSingleShot(true); _searchTimer->setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
updateButtonsVisibility(); _select->raise();
raiseShadow();
} }
int ShareBox::getTopScrollSkip() const { int ShareBox::getTopScrollSkip() const {
auto result = titleHeight(); auto result = 0;
if (!_select->isHidden()) { if (!_select->isHidden()) {
result += _select->height(); result += _select->height();
} }
@ -94,16 +90,7 @@ int ShareBox::getTopScrollSkip() const {
} }
void ShareBox::updateScrollSkips() { void ShareBox::updateScrollSkips() {
auto oldScrollHeight = scrollArea()->height(); setInnerTopSkip(getTopScrollSkip(), true);
auto topSkip = getTopScrollSkip();
auto bottomSkip = st::boxButtonPadding.top() + _share->height() + st::boxButtonPadding.bottom();
setScrollSkips(bottomSkip, topSkip);
auto scrollHeightDelta = scrollArea()->height() - oldScrollHeight;
if (scrollHeightDelta) {
scrollArea()->scrollToY(scrollArea()->scrollTop() - scrollHeightDelta);
}
_topShadow->setGeometry(0, topSkip, width(), st::lineWidth);
} }
bool ShareBox::onSearchByUsername(bool searchCache) { bool ShareBox::onSearchByUsername(bool searchCache) {
@ -135,7 +122,7 @@ bool ShareBox::onSearchByUsername(bool searchCache) {
void ShareBox::onNeedSearchByUsername() { void ShareBox::onNeedSearchByUsername() {
if (!onSearchByUsername(true)) { if (!onSearchByUsername(true)) {
_searchTimer.start(AutoSearchTimeout); _searchTimer->start(AutoSearchTimeout);
} }
} }
@ -160,7 +147,6 @@ void ShareBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId requ
} }
_peopleRequest = 0; _peopleRequest = 0;
onScroll();
} }
} }
@ -174,22 +160,19 @@ bool ShareBox::peopleFailed(const RPCError &error, mtpRequestId requestId) {
return true; return true;
} }
void ShareBox::doSetInnerFocus() { void ShareBox::setInnerFocus() {
_select->setInnerFocus(); _select->setInnerFocus();
} }
void ShareBox::resizeEvent(QResizeEvent *e) { void ShareBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e); BoxContent::resizeEvent(e);
_select->resizeToWidth(width()); _select->resizeToWidth(width());
_select->moveToLeft(0, titleHeight()); _select->moveToLeft(0, 0);
updateScrollSkips(); updateScrollSkips();
_inner->resizeToWidth(width()); _inner->resizeToWidth(width());
moveButtons();
_topShadow->setGeometry(0, getTopScrollSkip(), width(), st::lineWidth);
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _share->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
} }
void ShareBox::keyPressEvent(QKeyEvent *e) { void ShareBox::keyPressEvent(QKeyEvent *e) {
@ -200,32 +183,37 @@ void ShareBox::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Down) { } else if (e->key() == Qt::Key_Down) {
_inner->activateSkipColumn(1); _inner->activateSkipColumn(1);
} else if (e->key() == Qt::Key_PageUp) { } else if (e->key() == Qt::Key_PageUp) {
_inner->activateSkipPage(scrollArea()->height(), -1); _inner->activateSkipPage(height() - getTopScrollSkip(), -1);
} else if (e->key() == Qt::Key_PageDown) { } else if (e->key() == Qt::Key_PageDown) {
_inner->activateSkipPage(scrollArea()->height(), 1); _inner->activateSkipPage(height() - getTopScrollSkip(), 1);
} else { } else {
ItemListBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} else { } else {
ItemListBox::keyPressEvent(e); BoxContent::keyPressEvent(e);
} }
} }
void ShareBox::moveButtons() { void ShareBox::updateButtons() {
_copy->moveToRight(st::boxButtonPadding.right(), _share->y()); auto hasSelected = _inner->hasSelected();
_share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height()); if (_hasSelected != hasSelected) {
_cancel->moveToRight(st::boxButtonPadding.right() + _share->width() + st::boxButtonPadding.left(), _share->y()); _hasSelected = hasSelected;
createButtons();
}
} }
void ShareBox::updateButtonsVisibility() { void ShareBox::createButtons() {
auto hasSelected = _inner->hasSelected(); clearButtons();
_copy->setVisible(!hasSelected); if (_hasSelected) {
_share->setVisible(hasSelected); addButton(lang(lng_share_confirm), [this] { onSubmit(); });
_cancel->setVisible(hasSelected); } else {
addButton(lang(lng_share_copy_link), [this] { onCopyLink(); });
}
addButton(lang(lng_cancel), [this] { closeBox(); });
} }
void ShareBox::onFilterUpdate(const QString &query) { void ShareBox::onFilterUpdate(const QString &query) {
scrollArea()->scrollToY(0); onScrollToY(0);
_inner->updateFilter(query); _inner->updateFilter(query);
} }
@ -259,33 +247,27 @@ void ShareBox::onCopyLink() {
} }
void ShareBox::onSelectedChanged() { void ShareBox::onSelectedChanged() {
updateButtonsVisibility(); updateButtons();
moveButtons();
update(); update();
} }
void ShareBox::onMustScrollTo(int top, int bottom) { void ShareBox::onMustScrollTo(int top, int bottom) {
auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height(); onScrollToY(top, bottom);
auto from = scrollTop, to = scrollTop; //auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
if (scrollTop > top) { //auto from = scrollTop, to = scrollTop;
to = top; //if (scrollTop > top) {
} else if (scrollBottom < bottom) { // to = top;
to = bottom - (scrollBottom - scrollTop); //} else if (scrollBottom < bottom) {
} // to = bottom - (scrollBottom - scrollTop);
if (from != to) { //}
_scrollAnimation.start([this]() { scrollAnimationCallback(); }, from, to, st::shareScrollDuration, anim::sineInOut); //if (from != to) {
} // _scrollAnimation.start([this]() { scrollAnimationCallback(); }, from, to, st::shareScrollDuration, anim::sineInOut);
//}
} }
void ShareBox::scrollAnimationCallback() { void ShareBox::scrollAnimationCallback() {
auto scrollTop = qRound(_scrollAnimation.current(scrollArea()->scrollTop())); //auto scrollTop = qRound(_scrollAnimation.current(scrollArea()->scrollTop()));
scrollArea()->scrollToY(scrollTop); //scrollArea()->scrollToY(scrollTop);
}
void ShareBox::onScroll() {
auto scroll = scrollArea();
auto scrollTop = scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + scroll->height());
} }
ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback) : TWidget(parent) ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback) : TWidget(parent)
@ -928,7 +910,7 @@ void shareGameScoreFromItem(HistoryItem *item) {
} }
return false; return false;
}; };
Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback), std_::move(filterCallback))); Ui::show(Box<ShareBox>(std_::move(copyCallback), std_::move(submitCallback), std_::move(filterCallback)));
} }
} // namespace } // namespace
@ -938,7 +920,7 @@ void shareGameScoreByHash(const QString &hash) {
auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
if (hashEncrypted.size() <= key128Size || (hashEncrypted.size() % 0x10) != 0) { if (hashEncrypted.size() <= key128Size || (hashEncrypted.size() % 0x10) != 0) {
Ui::showLayer(new InformBox(lang(lng_confirm_phone_link_invalid))); Ui::show(Box<InformBox>(lang(lng_confirm_phone_link_invalid)));
return; return;
} }
@ -958,20 +940,20 @@ void shareGameScoreByHash(const QString &hash) {
// Check next 64 bits of SHA1() of data. // Check next 64 bits of SHA1() of data.
auto skipSha1Part = sizeof(channelAccessHash); auto skipSha1Part = sizeof(channelAccessHash);
if (memcmp(dataSha1 + skipSha1Part, hashEncrypted.constData() + skipSha1Part, key128Size - skipSha1Part) != 0) { if (memcmp(dataSha1 + skipSha1Part, hashEncrypted.constData() + skipSha1Part, key128Size - skipSha1Part) != 0) {
Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return; return;
} }
auto hashDataInts = reinterpret_cast<int32*>(hashData.data()); auto hashDataInts = reinterpret_cast<int32*>(hashData.data());
if (hashDataInts[0] != MTP::authedId()) { if (hashDataInts[0] != MTP::authedId()) {
Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return; return;
} }
// Check first 32 bits of channel access hash. // Check first 32 bits of channel access hash.
auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash); auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash);
if (channelAccessHashInts[0] != hashDataInts[3]) { if (channelAccessHashInts[0] != hashDataInts[3]) {
Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return; return;
} }
@ -979,7 +961,7 @@ void shareGameScoreByHash(const QString &hash) {
auto msgId = hashDataInts[2]; auto msgId = hashDataInts[2];
if (!channelId && channelAccessHash) { if (!channelId && channelAccessHash) {
// If there is no channel id, there should be no channel access_hash. // If there is no channel id, there should be no channel access_hash.
Ui::showLayer(new InformBox(lang(lng_share_wrong_user))); Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
return; return;
} }
@ -991,7 +973,7 @@ void shareGameScoreByHash(const QString &hash) {
if (auto item = App::histItemById(channel, msgId)) { if (auto item = App::histItemById(channel, msgId)) {
shareGameScoreFromItem(item); shareGameScoreFromItem(item);
} else { } else {
Ui::showLayer(new InformBox(lang(lng_edit_deleted))); Ui::show(Box<InformBox>(lang(lng_edit_deleted)));
} }
}); });
}; };

View file

@ -36,24 +36,28 @@ struct PeerUpdate;
namespace Ui { namespace Ui {
class MultiSelect; class MultiSelect;
class RoundButton;
} // namespace Ui } // namespace Ui
QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId); QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
void shareGameScoreByHash(const QString &hash); void shareGameScoreByHash(const QString &hash);
class ShareBox : public ItemListBox, public RPCSender { class ShareBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
using CopyCallback = base::lambda<void()>; using CopyCallback = base::lambda<void()>;
using SubmitCallback = base::lambda<void(const QVector<PeerData*> &)>; using SubmitCallback = base::lambda<void(const QVector<PeerData*> &)>;
using FilterCallback = base::lambda<bool(PeerData*)>; using FilterCallback = base::lambda<bool(PeerData*)>;
ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback); ShareBox(QWidget*, CopyCallback &&copyCallback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
protected:
void prepare() override;
void setInnerFocus() override;
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
private slots: private slots:
void onScroll();
bool onSearchByUsername(bool searchCache = false); bool onSearchByUsername(bool searchCache = false);
void onNeedSearchByUsername(); void onNeedSearchByUsername();
@ -62,19 +66,13 @@ private slots:
void onMustScrollTo(int top, int bottom); void onMustScrollTo(int top, int bottom);
protected:
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void doSetInnerFocus() override;
private: private:
void scrollAnimationCallback(); void scrollAnimationCallback();
void onFilterUpdate(const QString &query); void onFilterUpdate(const QString &query);
void onSelectedChanged(); void onSelectedChanged();
void moveButtons(); void updateButtons();
void updateButtonsVisibility(); void createButtons();
int getTopScrollSkip() const; int getTopScrollSkip() const;
void updateScrollSkips(); void updateScrollSkips();
@ -86,19 +84,16 @@ private:
CopyCallback _copyCallback; CopyCallback _copyCallback;
SubmitCallback _submitCallback; SubmitCallback _submitCallback;
FilterCallback _filterCallback;
object_ptr<Ui::MultiSelect> _select;
class Inner; class Inner;
ChildWidget<Inner> _inner; QPointer<Inner> _inner;
ChildWidget<Ui::MultiSelect> _select;
ChildWidget<Ui::RoundButton> _copy; bool _hasSelected = false;
ChildWidget<Ui::RoundButton> _share;
ChildWidget<Ui::RoundButton> _cancel;
ChildWidget<ScrollableBoxShadow> _topShadow; object_ptr<QTimer> _searchTimer;
ChildWidget<ScrollableBoxShadow> _bottomShadow;
QTimer _searchTimer;
QString _peopleQuery; QString _peopleQuery;
bool _peopleFull = false; bool _peopleFull = false;
mtpRequestId _peopleRequest = 0; mtpRequestId _peopleRequest = 0;

View file

@ -39,8 +39,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace { namespace {
constexpr int kArchivedLimitFirstRequest = 10; constexpr int kArchivedLimitFirstRequest = 1;// 10;
constexpr int kArchivedLimitPerPage = 30; constexpr int kArchivedLimitPerPage = 1;// 30;
} // namespace } // namespace
@ -89,7 +89,6 @@ StickersBox::CounterWidget::CounterWidget(QWidget *parent) : TWidget(parent) {
updateCounter(); updateCounter();
} }
void StickersBox::CounterWidget::setCounter(int counter) { void StickersBox::CounterWidget::setCounter(int counter) {
_text = (counter > 0) ? QString::number(counter) : QString(); _text = (counter > 0) ? QString::number(counter) : QString();
auto dummy = QImage(1, 1, QImage::Format_ARGB32_Premultiplied); auto dummy = QImage(1, 1, QImage::Format_ARGB32_Premultiplied);
@ -116,24 +115,40 @@ void StickersBox::CounterWidget::updateCounter() {
update(); update();
} }
StickersBox::StickersBox(Section section) : ItemListBox(st::boxScroll) template <typename ...Args>
, _topShadow(this, st::shadowColor) StickersBox::Tab::Tab(int index, Args&&... args)
, _tabs(this, st::defaultTabsSlider) : _index(index)
, _widget(std_::forward<Args>(args)...)
, _weak(_widget) {
}
object_ptr<StickersBox::Inner> StickersBox::Tab::takeWidget() {
return std_::move(_widget);
}
void StickersBox::Tab::returnWidget(object_ptr<Inner> widget) {
_widget = std_::move(widget);
t_assert(_widget == _weak);
}
void StickersBox::Tab::saveScrollTop() {
_scrollTop = widget()->getVisibleTop();
}
StickersBox::StickersBox(QWidget*, Section section)
: _tabs(this, st::stickersTabs)
, _unreadBadge(this) , _unreadBadge(this)
, _section(section) , _section(section)
, _installed(0, this, Section::Installed) , _installed(0, this, Section::Installed)
, _featured(1, this, Section::Featured) , _featured(1, this, Section::Featured)
, _archived(2, this, Section::Archived) { , _archived(2, this, Section::Archived) {
setup();
} }
StickersBox::StickersBox(const Stickers::Order &archivedIds) : ItemListBox(st::boxScroll) StickersBox::StickersBox(QWidget*, const Stickers::Order &archivedIds)
, _topShadow(this, st::shadowColor) : _section(Section::ArchivedPart)
, _section(Section::ArchivedPart)
, _archived(0, this, archivedIds) , _archived(0, this, archivedIds)
, _aboutWidth(st::boxWideWidth - 2 * st::stickersReorderPadding.top()) , _aboutWidth(st::boxWideWidth - 2 * st::stickersReorderPadding.top())
, _about(st::boxTextFont, lang(lng_stickers_packs_archived), _defaultOptions, _aboutWidth) { , _about(st::boxTextFont, lang(lng_stickers_packs_archived), _defaultOptions, _aboutWidth) {
setup();
} }
void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) { void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) {
@ -154,7 +169,8 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
archived.clear(); archived.clear();
} }
bool addedSet = false; auto addedSet = false;
auto changedSets = false;
auto &v = stickers.vsets.c_vector().v; auto &v = stickers.vsets.c_vector().v;
for_const (auto &stickerSet, v) { for_const (auto &stickerSet, v) {
const MTPDstickerSet *setData = nullptr; const MTPDstickerSet *setData = nullptr;
@ -177,12 +193,13 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
if (auto set = Stickers::feedSet(*setData)) { if (auto set = Stickers::feedSet(*setData)) {
auto index = archived.indexOf(set->id); auto index = archived.indexOf(set->id);
if (archived.isEmpty() || index != archived.size() - 1) { if (archived.isEmpty() || index != archived.size() - 1) {
changedSets = true;
if (index < archived.size() - 1) { if (index < archived.size() - 1) {
archived.removeAt(index); archived.removeAt(index);
} }
archived.push_back(set->id); archived.push_back(set->id);
} }
if (_archived.widget->appendSet(*set)) { if (_archived.widget()->appendSet(*set)) {
addedSet = true; addedSet = true;
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
App::api()->scheduleStickerSetRequest(set->id, set->access); App::api()->scheduleStickerSetRequest(set->id, set->access);
@ -191,10 +208,12 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
} }
} }
if (addedSet) { if (addedSet) {
_archived.widget->updateSize(); _archived.widget()->updateSize();
_archived.widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
} else { } else {
_allArchivedLoaded = v.isEmpty() || (offsetId != 0); _allArchivedLoaded = v.isEmpty() || (offsetId != 0);
if (changedSets && !_allArchivedLoaded) {
loadMoreArchived();
}
} }
refreshTabs(); refreshTabs();
@ -202,69 +221,63 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
if (_section == Section::Archived && addedSet) { if (_section == Section::Archived && addedSet) {
App::api()->requestStickerSets(); App::api()->requestStickerSets();
} }
checkLoadMoreArchived();
} }
void StickersBox::setup() { void StickersBox::prepare() {
if (_section == Section::Installed) { if (_section == Section::Installed) {
Local::readArchivedStickers(); Local::readArchivedStickers();
} else if (_section == Section::Archived) { } else if (_section == Section::Archived) {
requestArchivedSets(); requestArchivedSets();
} else if (_section == Section::ArchivedPart) { } else if (_section == Section::ArchivedPart) {
setTitleText(lang(lng_stickers_archived)); setTitle(lang(lng_stickers_archived));
} }
if (Global::ArchivedStickerSetsOrder().isEmpty()) { if (Global::ArchivedStickerSetsOrder().isEmpty()) {
preloadArchivedSets(); preloadArchivedSets();
} }
if (_tabs) { if (_tabs) {
setNoContentMargin(true);
_tabs->setSectionActivatedCallback([this] { _tabs->setSectionActivatedCallback([this] {
switchTab(); switchTab();
}); });
refreshTabs(); refreshTabs();
} }
if (_installed.widget && _section != Section::Installed) _installed.widget->hide(); if (_installed.widget() && _section != Section::Installed) _installed.widget()->hide();
if (_featured.widget && _section != Section::Featured) _featured.widget->hide(); if (_featured.widget() && _section != Section::Featured) _featured.widget()->hide();
if (_section != Section::Archived && _section != Section::ArchivedPart) _archived.widget->hide(); if (_section != Section::Archived && _section != Section::ArchivedPart) _archived.widget()->hide();
if (_featured.widget) { if (_featured.widget()) {
_featured.widget->setInstallSetCallback([this](uint64 setId) { installSet(setId); }); _featured.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
} }
_archived.widget->setInstallSetCallback([this](uint64 setId) { installSet(setId); }); _archived.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
_archived.widget()->setLoadMoreCallback([this] { loadMoreArchived(); });
_done.create(this, lang(lng_about_done), st::defaultBoxButton); addButton(lang(lng_about_done), [this] { closeBox(); });
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
auto bottomSkip = st::boxButtonPadding.top() + _done->height() + st::boxButtonPadding.bottom();
if (_section == Section::Installed) { if (_section == Section::Installed) {
_bottomShadow.create(this);
_tab = &_installed; _tab = &_installed;
} else if (_section == Section::ArchivedPart) { } else if (_section == Section::ArchivedPart) {
_aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom(); _aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom();
_titleShadow.create(this);
_tab = &_archived; _tab = &_archived;
} else if (_section == Section::Archived) { } else if (_section == Section::Archived) {
_bottomShadow.create(this);
_tab = &_archived; _tab = &_archived;
} else { // _section == Section::Featured } else { // _section == Section::Featured
_bottomShadow.create(this);
_tab = &_featured; _tab = &_featured;
} }
ItemListBox::init(_tab->widget, bottomSkip, titleHeight() + _aboutHeight); setInnerWidget(_tab->takeWidget(), getTopSkip());
setMaxHeight((_section == Section::ArchivedPart) ? st::sessionsHeight : st::boxMaxListHeight); setDimensions(st::boxWideWidth, (_section == Section::ArchivedPart) ? st::sessionsHeight : st::boxMaxListHeight);
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated())); connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
App::main()->updateStickers(); App::main()->updateStickers();
if (_installed.widget) { if (_installed.widget()) {
connect(_installed.widget, SIGNAL(checkDraggingScroll(int)), this, SLOT(onCheckDraggingScroll(int))); connect(_installed.widget(), SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int)));
connect(_installed.widget, SIGNAL(noDraggingScroll()), this, SLOT(onNoDraggingScroll()));
} }
connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
_scrollTimer.setSingleShot(false);
if (_tabs) {
_tabs->raise();
}
rebuildList(); rebuildList();
raiseShadow();
} }
void StickersBox::refreshTabs() { void StickersBox::refreshTabs() {
@ -288,61 +301,44 @@ void StickersBox::refreshTabs() {
switchTab(); switchTab();
} }
updateTabsGeometry(); updateTabsGeometry();
setBlockTitle(true, (sections.size() < 3), false);
} }
void StickersBox::onScroll() { void StickersBox::loadMoreArchived() {
updateVisibleTopBottom(); if (_section != Section::Archived || _allArchivedLoaded || _archivedRequestId) {
checkLoadMoreArchived(); return;
} }
void StickersBox::updateVisibleTopBottom() { uint64 lastId = 0;
auto visibleTop = scrollArea()->scrollTop(); for (auto setIt = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setIt != e;) {
auto visibleBottom = visibleTop + scrollArea()->height(); --setIt;
_tab->widget->setVisibleTopBottom(visibleTop, visibleBottom); auto it = Global::StickerSets().constFind(*setIt);
} if (it != Global::StickerSets().cend()) {
if (it->flags & MTPDstickerSet::Flag::f_archived) {
void StickersBox::checkLoadMoreArchived() { lastId = it->id;
if (_section != Section::Archived) return; break;
int scrollTop = scrollArea()->scrollTop(), scrollTopMax = scrollArea()->scrollTopMax();
if (scrollTop + PreloadHeightsCount * scrollArea()->height() >= scrollTopMax) {
if (!_archivedRequestId && !_allArchivedLoaded) {
uint64 lastId = 0;
for (auto setId = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setId != e;) {
--setId;
auto it = Global::StickerSets().constFind(*setId);
if (it != Global::StickerSets().cend()) {
if (it->flags & MTPDstickerSet::Flag::f_archived) {
lastId = it->id;
break;
}
}
} }
MTPmessages_GetArchivedStickers::Flags flags = 0;
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
} }
} }
MTPmessages_GetArchivedStickers::Flags flags = 0;
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
} }
void StickersBox::paintEvent(QPaintEvent *e) { void StickersBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
p.translate(0, titleHeight());
if (_aboutHeight > 0) { if (_aboutHeight > 0) {
p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg); p.fillRect(0, st::lineWidth, width(), _aboutHeight - st::lineWidth, st::contactsAboutBg);
p.setPen(st::stickersReorderFg); p.setPen(st::stickersReorderFg);
_about.draw(p, st::stickersReorderPadding.top(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center); _about.draw(p, st::stickersReorderPadding.top(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center);
} }
if (_slideAnimation) { if (_slideAnimation) {
_slideAnimation->paintFrame(p, scrollArea()->x(), scrollArea()->y() - titleHeight(), width(), getms()); _slideAnimation->paintFrame(p, 0, getTopSkip(), width(), getms());
if (!_slideAnimation->animating()) { if (!_slideAnimation->animating()) {
_slideAnimation.reset(); _slideAnimation.reset();
scrollArea()->show(); setInnerVisible(true);
update(); update();
} }
} }
@ -354,9 +350,11 @@ void StickersBox::updateTabsGeometry() {
_tabs->resizeToWidth(_tabIndices.size() * width() / 3); _tabs->resizeToWidth(_tabIndices.size() * width() / 3);
_unreadBadge->setVisible(_tabIndices.contains(Section::Featured)); _unreadBadge->setVisible(_tabIndices.contains(Section::Featured));
setInnerTopSkip(getTopSkip());
auto featuredLeft = width() / 3; auto featuredLeft = width() / 3;
auto featuredRight = 2 * width() / 3; auto featuredRight = 2 * width() / 3;
auto featuredTextWidth = st::defaultTabsSlider.labelFont->width(lang(lng_stickers_featured_tab).toUpper()); auto featuredTextWidth = st::stickersTabs.labelFont->width(lang(lng_stickers_featured_tab).toUpper());
auto featuredTextRight = featuredLeft + (featuredRight - featuredLeft - featuredTextWidth) / 2 + featuredTextWidth; auto featuredTextRight = featuredLeft + (featuredRight - featuredLeft - featuredTextWidth) / 2 + featuredTextWidth;
auto unreadBadgeLeft = featuredTextRight - st::stickersFeaturedBadgeSkip; auto unreadBadgeLeft = featuredTextRight - st::stickersFeaturedBadgeSkip;
auto unreadBadgeTop = st::stickersFeaturedBadgeTop; auto unreadBadgeTop = st::stickersFeaturedBadgeTop;
@ -368,6 +366,10 @@ void StickersBox::updateTabsGeometry() {
_tabs->moveToLeft(0, 0); _tabs->moveToLeft(0, 0);
} }
int StickersBox::getTopSkip() const {
return (_tabs ? (_tabs->height() - st::lineWidth) : 0) + _aboutHeight;
}
void StickersBox::switchTab() { void StickersBox::switchTab() {
if (!_tabs) return; if (!_tabs) return;
@ -386,41 +388,37 @@ void StickersBox::switchTab() {
} }
if (_tab != newTab) { if (_tab != newTab) {
if (_tab == &_installed) { if (_tab == &_installed) {
_localOrder = _tab->widget->getFullOrder(); _localOrder = _tab->widget()->getFullOrder();
_localRemoved = _tab->widget->getRemovedSets(); _localRemoved = _tab->widget()->getRemovedSets();
} }
auto scroll = scrollArea();
auto wasCache = grabContentCache(); auto wasCache = grabContentCache();
auto wasIndex = _tab->index; auto wasIndex = _tab->index();
_tab->scrollTop = scroll->scrollTop(); _tab->saveScrollTop();
auto widget = scroll->takeWidget(); auto widget = takeInnerWidget<Inner>();
widget->setParent(this); widget->setParent(this);
widget->hide(); widget->hide();
_tab->returnWidget(std_::move(widget));
_tab = newTab; _tab = newTab;
_section = newSection; _section = newSection;
scroll->setOwnedWidget(newTab->widget); setInnerWidget(_tab->takeWidget(), getTopSkip());
_tab->widget->show(); _tab->widget()->show();
rebuildList(); rebuildList();
scroll->scrollToY(_tab->scrollTop); onScrollToY(_tab->getScrollTop());
auto nowCache = grabContentCache(); auto nowCache = grabContentCache();
auto nowIndex = _tab->index; auto nowIndex = _tab->index();
_slideAnimation = std_::make_unique<Ui::SlideAnimation>(); _slideAnimation = std_::make_unique<Ui::SlideAnimation>();
_slideAnimation->setSnapshots(std_::move(wasCache), std_::move(nowCache)); _slideAnimation->setSnapshots(std_::move(wasCache), std_::move(nowCache));
auto slideLeft = wasIndex > nowIndex; auto slideLeft = wasIndex > nowIndex;
_slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration); _slideAnimation->start(slideLeft, [this] { update(); }, st::slideDuration);
scrollArea()->hide(); setInnerVisible(false);
update(); update();
} }
} }
QPixmap StickersBox::grabContentCache() { QPixmap StickersBox::grabContentCache() {
_topShadow->hide();
_bottomShadow->hide();
_tabs->hide(); _tabs->hide();
auto result = myGrab(this, scrollArea()->geometry()); auto result = grabInnerCache();
_topShadow->show();
_bottomShadow->show();
_tabs->show(); _tabs->show();
return std_::move(result); return std_::move(result);
} }
@ -435,9 +433,9 @@ void StickersBox::installSet(uint64 setId) {
if (_localRemoved.contains(setId)) { if (_localRemoved.contains(setId)) {
_localRemoved.removeOne(setId); _localRemoved.removeOne(setId);
if (_installed.widget) _installed.widget->setRemovedSets(_localRemoved); if (_installed.widget()) _installed.widget()->setRemovedSets(_localRemoved);
if (_featured.widget) _featured.widget->setRemovedSets(_localRemoved); if (_featured.widget()) _featured.widget()->setRemovedSets(_localRemoved);
_archived.widget->setRemovedSets(_localRemoved); _archived.widget()->setRemovedSets(_localRemoved);
} }
if (!(it->flags & MTPDstickerSet::Flag::f_installed) || (it->flags & MTPDstickerSet::Flag::f_archived)) { if (!(it->flags & MTPDstickerSet::Flag::f_installed) || (it->flags & MTPDstickerSet::Flag::f_archived)) {
MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_boolFalse()), rpcDone(&StickersBox::installDone), rpcFail(&StickersBox::installFail, setId)); MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_boolFalse()), rpcDone(&StickersBox::installDone), rpcFail(&StickersBox::installFail, setId));
@ -449,6 +447,8 @@ void StickersBox::installSet(uint64 setId) {
void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) { void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) {
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); Stickers::applyArchivedResult(result.c_messages_stickerSetInstallResultArchive());
} else {
Stickers::applyArchivedResultFake();
} }
} }
@ -492,31 +492,24 @@ void StickersBox::requestArchivedSets() {
} }
void StickersBox::resizeEvent(QResizeEvent *e) { void StickersBox::resizeEvent(QResizeEvent *e) {
ItemListBox::resizeEvent(e); BoxContent::resizeEvent(e);
if (_tabs) { if (_tabs) {
updateTabsGeometry(); updateTabsGeometry();
_topShadow->setGeometryToLeft(0, _tabs->height() - st::lineWidth, width(), st::lineWidth);
} else {
_topShadow->setGeometryToLeft(0, scrollArea()->y(), width(), st::lineWidth);
} }
if (_installed.widget) _installed.widget->resize(width(), _installed.widget->height()); if (_titleShadow) {
if (_featured.widget) _featured.widget->resize(width(), _featured.widget->height()); _titleShadow->setGeometry(0, 0, width(), st::lineWidth);
_archived.widget->resize(width(), _archived.widget->height());
_tab->widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
updateVisibleTopBottom();
if (_done) {
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
}
if (_bottomShadow) {
_bottomShadow->setGeometry(0, height() - st::boxButtonPadding.bottom() - _done->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
} }
if (_installed.widget()) _installed.widget()->resize(width(), _installed.widget()->height());
if (_featured.widget()) _featured.widget()->resize(width(), _featured.widget()->height());
_archived.widget()->resize(width(), _archived.widget()->height());
} }
void StickersBox::onStickersUpdated() { void StickersBox::onStickersUpdated() {
if (_section == Section::Installed || _section == Section::Featured) { if (_section == Section::Installed || _section == Section::Featured) {
rebuildList(); rebuildList();
} else { } else {
_tab->widget->updateRows(); _tab->widget()->updateRows();
} }
if (Global::ArchivedStickerSetsOrder().isEmpty()) { if (Global::ArchivedStickerSetsOrder().isEmpty()) {
preloadArchivedSets(); preloadArchivedSets();
@ -527,50 +520,25 @@ void StickersBox::onStickersUpdated() {
void StickersBox::rebuildList() { void StickersBox::rebuildList() {
if (_tab == &_installed) { if (_tab == &_installed) {
_localOrder = _tab->widget->getFullOrder(); _localOrder = _tab->widget()->getFullOrder();
_localRemoved = _tab->widget->getRemovedSets(); _localRemoved = _tab->widget()->getRemovedSets();
} }
_tab->widget->rebuild(); _tab->widget()->rebuild();
if (_tab == &_installed) { if (_tab == &_installed) {
_tab->widget->setFullOrder(_localOrder); _tab->widget()->setFullOrder(_localOrder);
} }
_tab->widget->setRemovedSets(_localRemoved); _tab->widget()->setRemovedSets(_localRemoved);
_tab->widget->setVisibleScrollbar((scrollArea()->scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
} }
void StickersBox::onCheckDraggingScroll(int localY) { void StickersBox::closeHook() {
if (localY < scrollArea()->scrollTop()) { if (!_installed.widget()) {
_scrollDelta = localY - scrollArea()->scrollTop();
} else if (localY >= scrollArea()->scrollTop() + scrollArea()->height()) {
_scrollDelta = localY - scrollArea()->scrollTop() - scrollArea()->height() + 1;
} else {
_scrollDelta = 0;
}
if (_scrollDelta) {
_scrollTimer.start(15);
} else {
_scrollTimer.stop();
}
}
void StickersBox::onNoDraggingScroll() {
_scrollTimer.stop();
}
void StickersBox::onScrollTimer() {
int32 d = (_scrollDelta > 0) ? qMin(_scrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_scrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed));
scrollArea()->scrollToY(scrollArea()->scrollTop() + d);
}
void StickersBox::closePressed() {
if (!_installed.widget) {
return; return;
} }
if (_someArchivedLoaded) { if (_someArchivedLoaded) {
Local::writeArchivedStickers(); Local::writeArchivedStickers();
} }
if (auto api = App::api()) { if (auto api = App::api()) {
api->saveStickerSets(_installed.widget->getOrder(), _installed.widget->getRemovedSets()); api->saveStickerSets(_installed.widget()->getOrder(), _installed.widget()->getRemovedSets());
} }
} }
@ -580,12 +548,11 @@ StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidg
, _section(section) , _section(section)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _a_shifting(animation(this, &Inner::step_shifting)) , _a_shifting(animation(this, &Inner::step_shifting))
, _itemsTop(st::membersPadding.top()) , _itemsTop(st::membersMarginTop)
, _addText(lang(lng_stickers_featured_add).toUpper()) , _addText(lang(lng_stickers_featured_add).toUpper())
, _addWidth(st::stickersTrendingAdd.font->width(_addText)) , _addWidth(st::stickersTrendingAdd.font->width(_addText))
, _undoText(lang(lng_stickers_return).toUpper()) , _undoText(lang(lng_stickers_return).toUpper())
, _undoWidth(st::stickersUndoRemove.font->width(_undoText)) , _undoWidth(st::stickersUndoRemove.font->width(_undoText)) {
, _aboveShadow(st::boxShadow) {
setup(); setup();
} }
@ -594,10 +561,9 @@ StickersBox::Inner::Inner(QWidget *parent, const Stickers::Order &archivedIds) :
, _archivedIds(archivedIds) , _archivedIds(archivedIds)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _a_shifting(animation(this, &Inner::step_shifting)) , _a_shifting(animation(this, &Inner::step_shifting))
, _itemsTop(st::membersPadding.top()) , _itemsTop(st::membersMarginTop)
, _addText(lang(lng_stickers_featured_add).toUpper()) , _addText(lang(lng_stickers_featured_add).toUpper())
, _addWidth(st::stickersTrendingAdd.font->width(_addText)) , _addWidth(st::stickersTrendingAdd.font->width(_addText)) {
, _aboveShadow(st::boxShadow) {
setup(); setup();
} }
@ -619,7 +585,7 @@ void StickersBox::Inner::paintEvent(QPaintEvent *e) {
p.fillRect(r, st::boxBg); p.fillRect(r, st::boxBg);
p.setClipRect(r); p.setClipRect(r);
int y = st::membersPadding.top(); auto y = _itemsTop;
if (_rows.isEmpty()) { if (_rows.isEmpty()) {
p.setFont(st::noContactsFont); p.setFont(st::noContactsFont);
p.setPen(st::noContactsColor); p.setPen(st::noContactsColor);
@ -667,21 +633,27 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
if (xadd || yadd) p.translate(xadd, yadd); if (xadd || yadd) p.translate(xadd, yadd);
if (_section == Section::Installed) { if (_section == Section::Installed) {
paintFakeButton(p, index, ms);
if (index == _above) { if (index == _above) {
float64 current = _aboveShadowFadeOpacity.current(); auto current = _aboveShadowFadeOpacity.current();
if (_started >= 0) { if (_started >= 0) {
float64 o = aboveShadowOpacity(); auto reachedOpacity = aboveShadowOpacity();
if (o > current) { if (reachedOpacity > current) {
_aboveShadowFadeOpacity = anim::value(o, o); _aboveShadowFadeOpacity = anim::value(reachedOpacity, reachedOpacity);
current = o; current = reachedOpacity;
} }
} }
auto row = myrtlrect(st::contactsPadding.left() / 2, st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - st::contactsPadding.left() / 2, _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2));
p.setOpacity(current); p.setOpacity(current);
QRect row(myrtlrect(_aboveShadow.getDimensions(st::boxShadowShift).left(), st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - _aboveShadow.getDimensions(st::boxShadowShift).right(), _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2))); Ui::Shadow::paint(p, row, width(), st::boxRoundShadow);
_aboveShadow.paint(p, row, st::boxShadowShift);
p.fillRect(row, st::boxBg);
p.setOpacity(1); p.setOpacity(1);
App::roundRect(p, row, st::boxBg, BoxCorners);
p.setOpacity(1. - current);
paintFakeButton(p, index, ms);
p.setOpacity(1.);
} else {
paintFakeButton(p, index, ms);
} }
} else { } else {
paintFakeButton(p, index, ms); paintFakeButton(p, index, ms);
@ -881,9 +853,18 @@ void StickersBox::Inner::onUpdateSelected() {
_animStartTimes[_dragging] = 0; _animStartTimes[_dragging] = 0;
_a_shifting.step(getms(), true); _a_shifting.step(getms(), true);
emit checkDraggingScroll(local.y()); auto countDraggingScrollDelta = [this, local] {
if (local.y() < _visibleTop) {
return local.y() - _visibleTop;
} else if (local.y() >= _visibleBottom) {
return local.y() + 1 - _visibleBottom;
}
return 0;
};
emit draggingScrollDelta(countDraggingScrollDelta());
} else { } else {
bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersPadding.bottom())).contains(local); bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersMarginBottom)).contains(local);
auto selected = -1; auto selected = -1;
auto actionSel = -1; auto actionSel = -1;
auto inDragArea = false; auto inDragArea = false;
@ -919,7 +900,7 @@ void StickersBox::Inner::onUpdateSelected() {
setCursor(_inDragArea ? style::cur_sizeall : (_selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default); setCursor(_inDragArea ? style::cur_sizeall : (_selected >= 0 || _pressed >= 0) ? style::cur_pointer : style::cur_default);
} }
setActionSel(actionSel); setActionSel(actionSel);
emit noDraggingScroll(); emit draggingScrollDelta(0);
} }
} }
@ -964,7 +945,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
auto it = sets.find(row->id); auto it = sets.find(row->id);
if (it != sets.cend()) { if (it != sets.cend()) {
_selected = -1; _selected = -1;
Ui::showLayer(new StickerSetBox(Stickers::inputSetId(*it)), KeepOtherLayers); Ui::show(Box<StickerSetBox>(Stickers::inputSetId(*it)), KeepOtherLayers);
} }
} }
} }
@ -1018,9 +999,14 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
} }
if (timer) { if (timer) {
if (_dragging >= 0) { if (_dragging >= 0) {
if (updateMin < 0 || updateMin > _dragging) updateMin = _dragging; if (updateMin < 0 || updateMin > _dragging) {
updateMin = _dragging;
}
if (updateMax < _dragging) updateMax = _dragging; if (updateMax < _dragging) updateMax = _dragging;
} }
if (updateMin == 1 && _rows[0]->isRecentSet()) {
updateMin = 0; // Repaint from the very top of the content.
}
if (updateMin >= 0) { if (updateMin >= 0) {
update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3)); update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3));
} }
@ -1060,7 +1046,7 @@ void StickersBox::Inner::setActionSel(int32 actionSel) {
} }
void StickersBox::Inner::rebuild() { void StickersBox::Inner::rebuild() {
_itemsTop = st::membersPadding.top(); _itemsTop = st::membersMarginTop;
int maxNameWidth = countMaxNameWidth(); int maxNameWidth = countMaxNameWidth();
@ -1102,7 +1088,8 @@ void StickersBox::Inner::rebuild() {
} }
void StickersBox::Inner::updateSize() { void StickersBox::Inner::updateSize() {
resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersPadding.bottom()); resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersMarginBottom);
checkLoadMore();
} }
void StickersBox::Inner::updateRows() { void StickersBox::Inner::updateRows() {
@ -1314,11 +1301,23 @@ void StickersBox::Inner::setRemovedSets(const Stickers::Order &removed) {
} }
void StickersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) { void StickersBox::Inner::setVisibleTopBottom(int visibleTop, int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
updateScrollbarWidth();
if (_section == Section::Featured) { if (_section == Section::Featured) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
readVisibleSets(); readVisibleSets();
} }
checkLoadMore();
}
void StickersBox::Inner::checkLoadMore() {
if (_loadMoreCallback) {
auto scrollHeight = (_visibleBottom - _visibleTop);
int scrollTop = _visibleTop, scrollTopMax = height() - scrollHeight;
if (scrollTop + PreloadHeightsCount * scrollHeight >= scrollTopMax) {
_loadMoreCallback();
}
}
} }
void StickersBox::Inner::readVisibleSets() { void StickersBox::Inner::readVisibleSets() {
@ -1339,8 +1338,12 @@ void StickersBox::Inner::readVisibleSets() {
} }
} }
void StickersBox::Inner::setVisibleScrollbar(int32 width) { void StickersBox::Inner::updateScrollbarWidth() {
_scrollbar = width; auto width = (_visibleBottom - _visibleTop < height()) ? (st::boxLayerScroll.width - st::boxLayerScroll.deltax) : 0;
if (_scrollbar != width) {
_scrollbar = width;
update();
}
} }
StickersBox::Inner::~Inner() { StickersBox::Inner::~Inner() {

View file

@ -30,13 +30,12 @@ struct RippleAnimation;
namespace Ui { namespace Ui {
class PlainShadow; class PlainShadow;
class RoundButton;
class RippleAnimation; class RippleAnimation;
class SettingsSlider; class SettingsSlider;
class SlideAnimation; class SlideAnimation;
} // namespace Ui } // namespace Ui
class StickersBox : public ItemListBox, public RPCSender { class StickersBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
@ -46,78 +45,85 @@ public:
Archived, Archived,
ArchivedPart, ArchivedPart,
}; };
StickersBox(Section section = Section::Installed); StickersBox(QWidget*, Section section);
StickersBox(const Stickers::Order &archivedIds); StickersBox(QWidget*, const Stickers::Order &archivedIds);
void closeHook() override;
~StickersBox(); ~StickersBox();
public slots:
void onStickersUpdated();
void onCheckDraggingScroll(int localY);
void onNoDraggingScroll();
void onScrollTimer();
private slots:
void onScroll();
protected: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void closePressed() override; private slots:
void onStickersUpdated();
private: private:
void refreshTabs(); void refreshTabs();
void setup();
void rebuildList(); void rebuildList();
void updateTabsGeometry(); void updateTabsGeometry();
void switchTab(); void switchTab();
void installSet(uint64 setId); void installSet(uint64 setId);
int getTopSkip() const;
QPixmap grabContentCache(); QPixmap grabContentCache();
void installDone(const MTPmessages_StickerSetInstallResult &result); void installDone(const MTPmessages_StickerSetInstallResult &result);
bool installFail(uint64 setId, const RPCError &error); bool installFail(uint64 setId, const RPCError &error);
void updateVisibleTopBottom();
void preloadArchivedSets(); void preloadArchivedSets();
void requestArchivedSets(); void requestArchivedSets();
void checkLoadMoreArchived(); void loadMoreArchived();
void getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result); void getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result);
ChildWidget<Ui::PlainShadow> _topShadow; object_ptr<Ui::SettingsSlider> _tabs = { nullptr };
ChildWidget<Ui::SettingsSlider> _tabs = { nullptr };
QList<Section> _tabIndices; QList<Section> _tabIndices;
class CounterWidget; class CounterWidget;
ChildWidget<CounterWidget> _unreadBadge = { nullptr }; object_ptr<CounterWidget> _unreadBadge = { nullptr };
Section _section; Section _section;
class Inner; class Inner;
struct Tab { class Tab {
Tab() : widget(nullptr) { public:
} Tab() = default;
template <typename ...Args> template <typename ...Args>
Tab(int index, Args&&... args) : index(index), widget(std_::forward<Args>(args)...) { Tab(int index, Args&&... args);
object_ptr<Inner> takeWidget();
void returnWidget(object_ptr<Inner> widget);
Inner *widget() {
return _weak;
}
int index() const {
return _index;
} }
int index = 0; void saveScrollTop();
ChildWidget<Inner> widget = { nullptr }; int getScrollTop() const {
int scrollTop = 0; return _scrollTop;
}
private:
int _index = 0;
object_ptr<Inner> _widget = { nullptr };
QPointer<Inner> _weak;
int _scrollTop = 0;
}; };
Tab _installed; Tab _installed;
Tab _featured; Tab _featured;
Tab _archived; Tab _archived;
Tab *_tab = nullptr; Tab *_tab = nullptr;
ChildWidget<Ui::RoundButton> _done = { nullptr };
ChildWidget<ScrollableBoxShadow> _bottomShadow = { nullptr };
std_::unique_ptr<Ui::SlideAnimation> _slideAnimation; std_::unique_ptr<Ui::SlideAnimation> _slideAnimation;
object_ptr<BoxLayerTitleShadow> _titleShadow = { nullptr };
QTimer _scrollTimer;
int32 _scrollDelta = 0;
int _aboutWidth = 0; int _aboutWidth = 0;
Text _about; Text _about;
@ -159,10 +165,16 @@ public:
void setInstallSetCallback(base::lambda<void(uint64 setId)> &&callback) { void setInstallSetCallback(base::lambda<void(uint64 setId)> &&callback) {
_installSetCallback = std_::move(callback); _installSetCallback = std_::move(callback);
} }
void setLoadMoreCallback(base::lambda<void()> &&callback) {
_loadMoreCallback = std_::move(callback);
}
void setVisibleScrollbar(int32 width);
void setVisibleTopBottom(int visibleTop, int visibleBottom) override; void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
int getVisibleTop() const {
return _visibleTop;
}
~Inner(); ~Inner();
protected: protected:
@ -173,8 +185,7 @@ protected:
void leaveEvent(QEvent *e) override; void leaveEvent(QEvent *e) override;
signals: signals:
void checkDraggingScroll(int localY); void draggingScrollDelta(int delta);
void noDraggingScroll();
public slots: public slots:
void onUpdateSelected(); void onUpdateSelected();
@ -183,6 +194,8 @@ private:
template <typename Check> template <typename Check>
Stickers::Order collectSets(Check check) const; Stickers::Order collectSets(Check check) const;
void checkLoadMore();
void updateScrollbarWidth();
int getRowIndex(uint64 setId) const; int getRowIndex(uint64 setId) const;
void setRowRemoved(int index, bool removed); void setRowRemoved(int index, bool removed);
@ -249,6 +262,7 @@ private:
BasicAnimation _a_shifting; BasicAnimation _a_shifting;
base::lambda<void(uint64 setId)> _installSetCallback; base::lambda<void(uint64 setId)> _installSetCallback;
base::lambda<void()> _loadMoreCallback;
int _visibleTop = 0; int _visibleTop = 0;
int _visibleBottom = 0; int _visibleBottom = 0;
@ -273,8 +287,6 @@ private:
int _dragging = -1; int _dragging = -1;
int _above = -1; int _above = -1;
Ui::RectShadow _aboveShadow;
int _scrollbar = 0; int _scrollbar = 0;
}; };

View file

@ -34,45 +34,33 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st::stickersScroll) StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
, _inner(this, set) : _set(set) {
, _shadow(this) }
, _add(this, lang(lng_stickers_add_pack), st::defaultBoxButton)
, _share(this, lang(lng_stickers_share_pack), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _done(this, lang(lng_about_done), st::defaultBoxButton) {
setTitleText(lang(lng_contacts_loading));
setMaxHeight(st::stickersMaxHeight); void StickerSetBox::prepare() {
setTitle(lang(lng_contacts_loading));
_inner = setInnerWidget(object_ptr<Inner>(this, _set), st::stickersScroll);
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated())); connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
init(_inner, st::boxButtonPadding.bottom() + _cancel->height() + st::boxButtonPadding.top()); setDimensions(st::boxWideWidth, st::stickersMaxHeight);
connect(_add, SIGNAL(clicked()), this, SLOT(onAddStickers())); onUpdateButtons();
connect(_share, SIGNAL(clicked()), this, SLOT(onShareStickers()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_done, SIGNAL(clicked()), this, SLOT(onClose()));
connect(_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons())); connect(_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
connect(_inner, SIGNAL(installed(uint64)), this, SLOT(onInstalled(uint64))); connect(_inner, SIGNAL(installed(uint64)), this, SLOT(onInstalled(uint64)));
onStickersUpdated(); onStickersUpdated();
updateControlsVisibility();
onScroll();
raiseShadow();
} }
void StickerSetBox::onInstalled(uint64 setId) { void StickerSetBox::onInstalled(uint64 setId) {
emit installed(setId); emit installed(setId);
onClose(); closeBox();
} }
void StickerSetBox::onStickersUpdated() { void StickerSetBox::onStickersUpdated() {
updateControlsVisibility(); updateButtons();
} }
void StickerSetBox::onAddStickers() { void StickerSetBox::onAddStickers() {
@ -82,66 +70,35 @@ void StickerSetBox::onAddStickers() {
void StickerSetBox::onShareStickers() { void StickerSetBox::onShareStickers() {
QString url = qsl("https://telegram.me/addstickers/") + _inner->shortName(); QString url = qsl("https://telegram.me/addstickers/") + _inner->shortName();
QApplication::clipboard()->setText(url); QApplication::clipboard()->setText(url);
Ui::showLayer(new InformBox(lang(lng_stickers_copied))); Ui::show(Box<InformBox>(lang(lng_stickers_copied)));
} }
void StickerSetBox::onUpdateButtons() { void StickerSetBox::onUpdateButtons() {
setTitleText(_inner->title()); setTitle(_inner->title());
if (!_cancel->isHidden() || !_done->isHidden()) { updateButtons();
updateControlsVisibility();
}
} }
void StickerSetBox::onScroll() { void StickerSetBox::updateButtons() {
auto scroll = scrollArea(); clearButtons();
auto scrollTop = scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + scroll->height());
}
void StickerSetBox::updateControlsVisibility() {
if (_inner->loaded()) { if (_inner->loaded()) {
_shadow.show();
if (_inner->notInstalled()) { if (_inner->notInstalled()) {
_add->show(); addButton(lang(lng_stickers_add_pack), [this] { onAddStickers(); });
_cancel->show(); addButton(lang(lng_cancel), [this] { closeBox(); });
_share->hide();
_done->hide();
} else if (_inner->official()) { } else if (_inner->official()) {
_add->hide(); addButton(lang(lng_about_done), [this] { closeBox(); });
_share->hide();
_cancel->hide();
_done->show();
} else { } else {
_share->show(); addButton(lang(lng_stickers_share_pack), [this] { onShareStickers(); });
_cancel->show(); addButton(lang(lng_cancel), [this] { closeBox(); });
_add->hide();
_done->hide();
} }
} else { } else {
_shadow.hide(); addButton(lang(lng_cancel), [this] { closeBox(); });
_add->hide();
_share->hide();
_cancel->show();
_done->hide();
} }
resizeEvent(0);
update(); update();
} }
void StickerSetBox::resizeEvent(QResizeEvent *e) { void StickerSetBox::resizeEvent(QResizeEvent *e) {
ScrollableBox::resizeEvent(e); BoxContent::resizeEvent(e);
_inner->resize(width(), _inner->height()); _inner->resize(width(), _inner->height());
_shadow.setGeometry(0, height() - st::boxButtonPadding.bottom() - _cancel->height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
_add->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _add->height());
_share->moveToRight(st::boxButtonPadding.right(), _add->y());
_done->moveToRight(st::boxButtonPadding.right(), _add->y());
if (_add->isHidden() && _share->isHidden()) {
_cancel->moveToRight(st::boxButtonPadding.right(), _add->y());
} else if (_add->isHidden()) {
_cancel->moveToRight(st::boxButtonPadding.right() + _share->width() + st::boxButtonPadding.left(), _add->y());
} else {
_cancel->moveToRight(st::boxButtonPadding.right() + _add->width() + st::boxButtonPadding.left(), _add->y());
}
} }
StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent) StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent)
@ -199,7 +156,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
if (d.vset.type() == mtpc_stickerSet) { if (d.vset.type() == mtpc_stickerSet) {
auto &s = d.vset.c_stickerSet(); auto &s = d.vset.c_stickerSet();
_setTitle = stickerSetTitle(s); _setTitle = stickerSetTitle(s);
_title = st::boxBlockTitleFont->elided(_setTitle, width() - st::boxBlockTitlePosition.x() - st::boxBlockTitleHeight); _title = st::boxTitleFont->elided(_setTitle, width() - st::boxTitlePosition.x() - st::boxTitleHeight);
_setShortName = qs(s.vshort_name); _setShortName = qs(s.vshort_name);
_setId = s.vid.v; _setId = s.vid.v;
_setAccess = s.vaccess_hash.v; _setAccess = s.vaccess_hash.v;
@ -219,7 +176,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
} }
if (_pack.isEmpty()) { if (_pack.isEmpty()) {
Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
} else { } else {
int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0); int32 rows = _pack.size() / StickerPanPerRow + ((_pack.size() % StickerPanPerRow) ? 1 : 0);
resize(st::stickersPadding.left() + StickerPanPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom()); resize(st::stickersPadding.left() + StickerPanPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom());
@ -236,7 +193,7 @@ bool StickerSetBox::Inner::failedSet(const RPCError &error) {
_loaded = true; _loaded = true;
Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
return true; return true;
} }
@ -297,7 +254,7 @@ void StickerSetBox::Inner::installDone(const MTPmessages_StickerSetInstallResult
bool StickerSetBox::Inner::installFail(const RPCError &error) { bool StickerSetBox::Inner::installFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
Ui::showLayer(new InformBox(lang(lng_stickers_not_found))); Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
return true; return true;
} }
@ -467,7 +424,7 @@ QString StickerSetBox::Inner::shortName() const {
void StickerSetBox::Inner::install() { void StickerSetBox::Inner::install() {
if (isMasksSet()) { if (isMasksSet()) {
Ui::showLayer(new InformBox(lang(lng_stickers_masks_pack)), KeepOtherLayers); Ui::show(Box<InformBox>(lang(lng_stickers_masks_pack)), KeepOtherLayers);
return; return;
} }
if (_installRequest) return; if (_installRequest) return;

View file

@ -27,42 +27,38 @@ class ConfirmBox;
namespace Ui { namespace Ui {
class PlainShadow; class PlainShadow;
class RoundButton;
} // namespace Ui } // namespace Ui
class StickerSetBox : public ScrollableBox, public RPCSender { class StickerSetBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
StickerSetBox(const MTPInputStickerSet &set); StickerSetBox(QWidget*, const MTPInputStickerSet &set);
public slots:
void onStickersUpdated();
void onAddStickers();
void onShareStickers();
void onUpdateButtons();
void onScroll();
private slots:
void onInstalled(uint64 id);
signals: signals:
void installed(uint64 id); void installed(uint64 id);
protected: protected:
void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private slots:
void onStickersUpdated();
void onAddStickers();
void onShareStickers();
void onUpdateButtons();
void onInstalled(uint64 id);
private: private:
void updateControlsVisibility(); void updateButtons();
MTPInputStickerSet _set;
class Inner; class Inner;
ChildWidget<Inner> _inner; QPointer<Inner> _inner;
ScrollableBoxShadow _shadow;
ChildWidget<Ui::RoundButton> _add;
ChildWidget<Ui::RoundButton> _share;
ChildWidget<Ui::RoundButton> _cancel;
ChildWidget<Ui::RoundButton> _done;
QString _title; QString _title;
}; };

View file

@ -29,42 +29,42 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
UsernameBox::UsernameBox() : AbstractBox(st::boxWidth, lang(lng_username_title)) UsernameBox::UsernameBox(QWidget*)
, _save(this, lang(lng_settings_save), st::defaultBoxButton) : _username(this, st::defaultInputField, qsl("@username"), App::self()->username, false)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _username(this, st::defaultInputField, qsl("@username"), App::self()->username, false)
, _link(this, QString(), st::boxLinkButton) , _link(this, QString(), st::boxLinkButton)
, _about(st::boxWidth - st::usernamePadding.left()) { , _about(st::boxWidth - st::usernamePadding.left())
setBlockTitle(true); , _checkTimer(this) {
}
void UsernameBox::prepare() {
_goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available); _goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available);
setTitle(lang(lng_username_title));
addButton(lang(lng_settings_save), [this] { onSave(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_username, SIGNAL(changed()), this, SLOT(onChanged()));
connect(_username, SIGNAL(submitted(bool)), this, SLOT(onSave()));
connect(_link, SIGNAL(clicked()), this, SLOT(onLinkClick()));
textstyleSet(&st::usernameTextStyle); textstyleSet(&st::usernameTextStyle);
_about.setRichText(st::boxTextFont, lang(lng_username_about)); _about.setRichText(st::boxTextFont, lang(lng_username_about));
resizeMaxHeight(st::boxWidth, titleHeight() + st::usernamePadding.top() + _username->height() + st::usernameSkip + _about.countHeight(st::boxWidth - st::usernamePadding.left()) + 3 * st::usernameTextStyle.lineHeight + st::usernamePadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); setDimensions(st::boxWidth, st::usernamePadding.top() + _username->height() + st::usernameSkip + _about.countHeight(st::boxWidth - st::usernamePadding.left()) + 3 * st::usernameTextStyle.lineHeight + st::usernamePadding.bottom());
textstyleRestore(); textstyleRestore();
connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); _checkTimer->setSingleShot(true);
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); connect(_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck()));
connect(_username, SIGNAL(changed()), this, SLOT(onChanged()));
connect(_username, SIGNAL(submitted(bool)), this, SLOT(onSave()));
connect(_link, SIGNAL(clicked()), this, SLOT(onLinkClick()));
_checkTimer.setSingleShot(true);
connect(&_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck()));
updateLinkText(); updateLinkText();
raiseShadow();
} }
void UsernameBox::doSetInnerFocus() { void UsernameBox::setInnerFocus() {
_username->setFocus(); _username->setFocus();
} }
void UsernameBox::paintEvent(QPaintEvent *e) { void UsernameBox::paintEvent(QPaintEvent *e) {
AbstractBox::paintEvent(e); BoxContent::paintEvent(e);
Painter p(this); Painter p(this);
@ -99,19 +99,16 @@ void UsernameBox::paintEvent(QPaintEvent *e) {
} }
void UsernameBox::resizeEvent(QResizeEvent *e) { void UsernameBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_username->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _username->height()); _username->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _username->height());
_username->moveToLeft(st::usernamePadding.left(), titleHeight() + st::usernamePadding.top()); _username->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
textstyleSet(&st::usernameTextStyle); textstyleSet(&st::usernameTextStyle);
int32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw); int32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
textstyleRestore(); textstyleRestore();
int32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2); int32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
_link->moveToLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2)); _link->moveToLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2));
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());
AbstractBox::resizeEvent(e);
} }
void UsernameBox::onSave() { void UsernameBox::onSave() {
@ -140,7 +137,7 @@ void UsernameBox::onChanged() {
_copiedTextLink = _errorText = _goodText = QString(); _copiedTextLink = _errorText = _goodText = QString();
update(); update();
} }
_checkTimer.stop(); _checkTimer->stop();
} else { } else {
int32 len = name.size(); int32 len = name.size();
for (int32 i = 0; i < len; ++i) { for (int32 i = 0; i < len; ++i) {
@ -151,7 +148,7 @@ void UsernameBox::onChanged() {
_errorText = lang(lng_username_bad_symbols); _errorText = lang(lng_username_bad_symbols);
update(); update();
} }
_checkTimer.stop(); _checkTimer->stop();
return; return;
} }
} }
@ -161,13 +158,13 @@ void UsernameBox::onChanged() {
_errorText = lang(lng_username_too_short); _errorText = lang(lng_username_too_short);
update(); update();
} }
_checkTimer.stop(); _checkTimer->stop();
} else { } else {
if (!_errorText.isEmpty() || !_goodText.isEmpty() || !_copiedTextLink.isEmpty()) { if (!_errorText.isEmpty() || !_goodText.isEmpty() || !_copiedTextLink.isEmpty()) {
_copiedTextLink = _errorText = _goodText = QString(); _copiedTextLink = _errorText = _goodText = QString();
update(); update();
} }
_checkTimer.start(UsernameCheckTimeout); _checkTimer->start(UsernameCheckTimeout);
} }
} }
} }
@ -180,7 +177,7 @@ void UsernameBox::onLinkClick() {
void UsernameBox::onUpdateDone(const MTPUser &user) { void UsernameBox::onUpdateDone(const MTPUser &user) {
App::feedUsers(MTP_vector<MTPUser>(1, user)); App::feedUsers(MTP_vector<MTPUser>(1, user));
onClose(); closeBox();
} }
bool UsernameBox::onUpdateFail(const RPCError &error) { bool UsernameBox::onUpdateFail(const RPCError &error) {
@ -190,7 +187,7 @@ bool UsernameBox::onUpdateFail(const RPCError &error) {
QString err(error.type()); QString err(error.type());
if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == App::self()->username) { if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == App::self()->username) {
App::self()->setName(textOneLine(App::self()->firstName), textOneLine(App::self()->lastName), textOneLine(App::self()->nameOrPhone), textOneLine(_sentUsername)); App::self()->setName(textOneLine(App::self()->firstName), textOneLine(App::self()->lastName), textOneLine(App::self()->nameOrPhone), textOneLine(_sentUsername));
onClose(); closeBox();
return true; return true;
} else if (err == qstr("USERNAME_INVALID")) { } else if (err == qstr("USERNAME_INVALID")) {
_username->setFocus(); _username->setFocus();

View file

@ -24,17 +24,23 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class UsernameInput; class UsernameInput;
class RoundButton;
class LinkButton; class LinkButton;
} // namespace Ui } // namespace Ui
class UsernameBox : public AbstractBox, public RPCSender { class UsernameBox : public BoxContent, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
UsernameBox(); UsernameBox(QWidget*);
public slots: protected:
void prepare() override;
void setInnerFocus() override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private slots:
void onSave(); void onSave();
void onCheck(); void onCheck();
@ -42,12 +48,6 @@ public slots:
void onLinkClick(); void onLinkClick();
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void doSetInnerFocus() override;
private: private:
void onUpdateDone(const MTPUser &result); void onUpdateDone(const MTPUser &result);
bool onUpdateFail(const RPCError &error); bool onUpdateFail(const RPCError &error);
@ -58,16 +58,14 @@ private:
QString getName() const; QString getName() const;
void updateLinkText(); void updateLinkText();
ChildWidget<Ui::RoundButton> _save; object_ptr<Ui::UsernameInput> _username;
ChildWidget<Ui::RoundButton> _cancel; object_ptr<Ui::LinkButton> _link;
ChildWidget<Ui::UsernameInput> _username;
ChildWidget<Ui::LinkButton> _link;
mtpRequestId _saveRequestId = 0; mtpRequestId _saveRequestId = 0;
mtpRequestId _checkRequestId = 0; mtpRequestId _checkRequestId = 0;
QString _sentUsername, _checkUsername, _errorText, _goodText, _copiedTextLink; QString _sentUsername, _checkUsername, _errorText, _goodText, _copiedTextLink;
Text _about; Text _about;
QTimer _checkTimer; object_ptr<QTimer> _checkTimer;
}; };

View file

@ -104,24 +104,31 @@ TextWithEntities UrlClickHandler::getExpandedLinkTextWithEntities(ExpandLinksMod
} }
void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const { void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const {
auto u = tryConvertUrlToLocal(url()); auto urlText = tryConvertUrlToLocal(url());
if (u.startsWith(qstr("tg://"))) { if (urlText.startsWith(qstr("tg://"))) {
App::openLocalUrl(u); App::openLocalUrl(urlText);
} else { } else {
Ui::showLayer(new ConfirmLinkBox(u)); Ui::show(Box<ConfirmBox>(lang(lng_open_this_link) + qsl("\n\n") + urlText, lang(lng_open_link), [urlText] {
Ui::hideLayer();
UrlClickHandler::doOpen(urlText);
}));
} }
} }
void BotGameUrlClickHandler::onClick(Qt::MouseButton button) const { void BotGameUrlClickHandler::onClick(Qt::MouseButton button) const {
auto u = tryConvertUrlToLocal(url()); auto urlText = tryConvertUrlToLocal(url());
if (u.startsWith(qstr("tg://"))) { if (urlText.startsWith(qstr("tg://"))) {
App::openLocalUrl(u); App::openLocalUrl(urlText);
} else if (!_bot || _bot->isVerified() || Local::isBotTrusted(_bot)) { } else if (!_bot || _bot->isVerified() || Local::isBotTrusted(_bot)) {
doOpen(u); doOpen(urlText);
} else { } else {
Ui::showLayer(new ConfirmBotGameBox(_bot, u)); Ui::show(Box<ConfirmBox>(lng_allow_bot_pass(lt_bot_name, _bot->name), lang(lng_allow_bot), [bot = _bot, urlText] {
Ui::hideLayer();
Local::makeBotTrusted(bot);
UrlClickHandler::doOpen(urlText);
}));
} }
} }

View file

@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "application.h" #include "application.h"
SingleTimer::SingleTimer() { SingleTimer::SingleTimer(QObject *parent) : QTimer(parent) {
QTimer::setSingleShot(true); QTimer::setSingleShot(true);
if (App::app()) { if (App::app()) {
connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust())); connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust()));

View file

@ -26,7 +26,7 @@ class SingleTimer : public QTimer { // single shot timer with check
Q_OBJECT Q_OBJECT
public: public:
SingleTimer(); SingleTimer(QObject *parent = nullptr);
void setSingleShot(bool); // is not available void setSingleShot(bool); // is not available
void start(); // is not available void start(); // is not available

View file

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

View file

@ -50,7 +50,7 @@ dialogsSkip: 8px;
dialogsWidthMin: 260px; dialogsWidthMin: 260px;
dialogsWidthMax: 540px; dialogsWidthMax: 540px;
dialogsTextWidthMin: 150px; dialogsTextWidthMin: 150px;
dialogsScroll: FlatScroll(defaultFlatScroll) { dialogsScroll: ScrollArea(defaultScrollArea) {
topsh: 0px; topsh: 0px;
bottomsh: 0px; bottomsh: 0px;
} }

View file

@ -1887,9 +1887,8 @@ DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent)
, _filter(this, st::dialogsFilter, lang(lng_dlg_filter)) , _filter(this, st::dialogsFilter, lang(lng_dlg_filter))
, _cancelSearch(this, st::dialogsCancelSearch) , _cancelSearch(this, st::dialogsCancelSearch)
, _lockUnlock(this, st::dialogsLock) , _lockUnlock(this, st::dialogsLock)
, _scroll(this, st::dialogsScroll) , _scroll(this, st::dialogsScroll) {
, _inner(this, parent) { _inner = _scroll->setOwnedWidget(object_ptr<DialogsInner>(this, parent));
_scroll->setOwnedWidget(_inner);
connect(_inner, SIGNAL(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(int,int))); connect(_inner, SIGNAL(mustScrollTo(int,int)), _scroll, SLOT(scrollToY(int,int)));
connect(_inner, SIGNAL(dialogMoved(int,int)), this, SLOT(onDialogMoved(int,int))); connect(_inner, SIGNAL(dialogMoved(int,int)), this, SLOT(onDialogMoved(int,int)));
connect(_inner, SIGNAL(searchMessages()), this, SLOT(onNeedSearchMessages())); connect(_inner, SIGNAL(searchMessages()), this, SLOT(onNeedSearchMessages()));

View file

@ -254,8 +254,8 @@ private:
State _state = DefaultState; State _state = DefaultState;
ChildWidget<Ui::LinkButton> _addContactLnk; object_ptr<Ui::LinkButton> _addContactLnk;
ChildWidget<Ui::IconButton> _cancelSearchInPeer; object_ptr<Ui::IconButton> _cancelSearchInPeer;
PeerData *_searchInPeer = nullptr; PeerData *_searchInPeer = nullptr;
PeerData *_searchInMigrated = nullptr; PeerData *_searchInMigrated = nullptr;
@ -382,14 +382,14 @@ private:
mtpRequestId _contactsRequestId = 0; mtpRequestId _contactsRequestId = 0;
bool _pinnedDialogsReceived = false; bool _pinnedDialogsReceived = false;
ChildWidget<Ui::IconButton> _forwardCancel = { nullptr }; object_ptr<Ui::IconButton> _forwardCancel = { nullptr };
ChildWidget<Ui::IconButton> _mainMenuToggle; object_ptr<Ui::IconButton> _mainMenuToggle;
ChildWidget<Ui::FlatInput> _filter; object_ptr<Ui::FlatInput> _filter;
ChildWidget<Ui::CrossButton> _cancelSearch; object_ptr<Ui::CrossButton> _cancelSearch;
ChildWidget<Ui::IconButton> _lockUnlock; object_ptr<Ui::IconButton> _lockUnlock;
ChildWidget<Ui::ScrollArea> _scroll; object_ptr<Ui::ScrollArea> _scroll;
ChildWidget<DialogsInner> _inner; QPointer<DialogsInner> _inner;
ChildWidget<Ui::FlatButton> _updateTelegram = { nullptr }; object_ptr<Ui::FlatButton> _updateTelegram = { nullptr };
Animation _a_show; Animation _a_show;
Window::SlideDirection _showDirection; Window::SlideDirection _showDirection;

View file

@ -99,14 +99,16 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
case ButtonType::RequestLocation: { case ButtonType::RequestLocation: {
hideSingleUseKeyboard(msg); hideSingleUseKeyboard(msg);
Ui::showLayer(new InformBox(lang(lng_bot_share_location_unavailable))); Ui::show(Box<InformBox>(lang(lng_bot_share_location_unavailable)));
} break; } break;
case ButtonType::RequestPhone: { case ButtonType::RequestPhone: {
hideSingleUseKeyboard(msg); hideSingleUseKeyboard(msg);
auto box = new SharePhoneConfirmBox(msg->history()->peer); Ui::show(Box<ConfirmBox>(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm), [peerId = msg->history()->peer->id] {
box->connect(box, SIGNAL(confirmed(PeerData*)), App::main(), SLOT(onSharePhoneWithBot(PeerData*))); if (auto m = App::main()) {
Ui::showLayer(box); m->onShareContact(peerId, App::self());
}
}));
} break; } break;
case ButtonType::SwitchInlineSame: case ButtonType::SwitchInlineSame:
@ -188,6 +190,15 @@ void logOutDelayed() {
} // namespace App } // namespace App
namespace Ui { namespace Ui {
namespace internal {
void showBox(object_ptr<BoxContent> content, ShowLayerOptions options) {
if (auto w = App::wnd()) {
w->ui_showBox(std_::move(content), options);
}
}
} // namespace internal
void showMediaPreview(DocumentData *document) { void showMediaPreview(DocumentData *document) {
if (auto w = App::wnd()) { if (auto w = App::wnd()) {
@ -207,20 +218,16 @@ void hideMediaPreview() {
} }
} }
void showLayer(LayerWidget *box, ShowLayerOptions options) { void hideLayer(bool fast) {
if (auto w = App::wnd()) { if (auto w = App::wnd()) {
w->ui_showLayer(box, options); w->ui_showBox({ nullptr }, CloseOtherLayers | (fast ? ForceFastShowLayer : AnimatedShowLayer));
} else {
delete box;
} }
} }
void hideLayer(bool fast) {
if (auto w = App::wnd()) w->ui_showLayer(0, CloseOtherLayers | (fast ? ForceFastShowLayer : AnimatedShowLayer));
}
void hideSettingsAndLayer(bool fast) { void hideSettingsAndLayer(bool fast) {
if (auto w = App::wnd()) w->ui_hideSettingsAndLayer(fast ? ForceFastShowLayer : AnimatedShowLayer); if (auto w = App::wnd()) {
w->ui_hideSettingsAndLayer(fast ? ForceFastShowLayer : AnimatedShowLayer);
}
} }
bool isLayerShown() { bool isLayerShown() {

View file

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/observer.h" #include "core/observer.h"
class LayerWidget; class LayerWidget;
class BoxContent;
namespace InlineBots { namespace InlineBots {
namespace Layout { namespace Layout {
@ -76,12 +77,23 @@ void logOutDelayed();
} // namespace App } // namespace App
namespace Ui { namespace Ui {
namespace internal {
void showBox(object_ptr<BoxContent> content, ShowLayerOptions options);
} // namespace internal
void showMediaPreview(DocumentData *document); void showMediaPreview(DocumentData *document);
void showMediaPreview(PhotoData *photo); void showMediaPreview(PhotoData *photo);
void hideMediaPreview(); void hideMediaPreview();
void showLayer(LayerWidget *box, ShowLayerOptions options = CloseOtherLayers); template <typename BoxType>
QPointer<BoxType> show(object_ptr<BoxType> content, ShowLayerOptions options = CloseOtherLayers) {
auto result = QPointer<BoxType>(content.data());
internal::showBox(std_::move(content), options);
return result;
}
void hideLayer(bool fast = false); void hideLayer(bool fast = false);
void hideSettingsAndLayer(bool fast = false); void hideSettingsAndLayer(bool fast = false);
bool isLayerShown(); bool isLayerShown();

View file

@ -30,18 +30,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_stickers.h" #include "styles/style_stickers.h"
FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent) FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent)
, _scroll(this, st::mentionScroll) , _scroll(this, st::mentionScroll) {
, _inner(this, &_mrows, &_hrows, &_brows, &_srows) {
connect(_inner, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(mentionChosen(UserData*,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int)));
_inner->setGeometry(rect());
_scroll->setGeometry(rect()); _scroll->setGeometry(rect());
_scroll->setOwnedWidget(_inner); _inner = _scroll->setOwnedWidget(object_ptr<internal::FieldAutocompleteInner>(this, &_mrows, &_hrows, &_brows, &_srows));
_inner->setGeometry(rect());
connect(_inner, SIGNAL(mentionChosen(UserData*, FieldAutocomplete::ChooseMethod)), this, SIGNAL(mentionChosen(UserData*, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(hashtagChosen(QString, FieldAutocomplete::ChooseMethod)), this, SIGNAL(hashtagChosen(QString, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(botCommandChosen(QString, FieldAutocomplete::ChooseMethod)), this, SIGNAL(botCommandChosen(QString, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(stickerChosen(DocumentData*, FieldAutocomplete::ChooseMethod)), this, SIGNAL(stickerChosen(DocumentData*, FieldAutocomplete::ChooseMethod)));
connect(_inner, SIGNAL(mustScrollTo(int, int)), _scroll, SLOT(scrollToY(int, int)));
_scroll->show(); _scroll->show();
_inner->show(); _inner->show();
@ -412,7 +412,7 @@ void FieldAutocomplete::hideAnimated() {
} }
_scroll->hide(); _scroll->hide();
_hiding = true; _hiding = true;
_a_opacity.start([this] { animationCallback(); }, 1., 0., st::defaultDropdownDuration); _a_opacity.start([this] { animationCallback(); }, 1., 0., st::emojiPanDuration);
setAttribute(Qt::WA_OpaquePaintEvent, false); setAttribute(Qt::WA_OpaquePaintEvent, false);
} }
@ -434,7 +434,7 @@ void FieldAutocomplete::showAnimated() {
_scroll->hide(); _scroll->hide();
_hiding = false; _hiding = false;
show(); show();
_a_opacity.start([this] { animationCallback(); }, 0., 1., st::defaultDropdownDuration); _a_opacity.start([this] { animationCallback(); }, 0., 1., st::emojiPanDuration);
setAttribute(Qt::WA_OpaquePaintEvent, false); setAttribute(Qt::WA_OpaquePaintEvent, false);
} }

View file

@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once #pragma once
#include "ui/twidget.h" #include "ui/twidget.h"
#include "ui/effects/rect_shadow.h"
namespace Ui { namespace Ui {
class ScrollArea; class ScrollArea;
@ -109,8 +108,8 @@ private:
void rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const StickerPack &srows, bool resetScroll); void rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const StickerPack &srows, bool resetScroll);
ChildWidget<Ui::ScrollArea> _scroll; object_ptr<Ui::ScrollArea> _scroll;
ChildWidget<internal::FieldAutocompleteInner> _inner; QPointer<internal::FieldAutocompleteInner> _inner;
ChatData *_chat = nullptr; ChatData *_chat = nullptr;
UserData *_user = nullptr; UserData *_user = nullptr;

View file

@ -22,7 +22,7 @@ using "basic.style";
using "dialogs/dialogs.style"; using "dialogs/dialogs.style";
using "ui/widgets/widgets.style"; using "ui/widgets/widgets.style";
historyScroll: FlatScroll(defaultFlatScroll) { historyScroll: ScrollArea(defaultScrollArea) {
barColor: #89a0b47a; barColor: #89a0b47a;
bgColor: #89a0b44c; bgColor: #89a0b44c;
barOverColor: #89a0b4bc; barOverColor: #89a0b4bc;
@ -70,7 +70,7 @@ historyToDownDuration: 150;
membersInnerWidth: 310px; membersInnerWidth: 310px;
membersInnerHeightMax: 360px; membersInnerHeightMax: 360px;
membersInnerDropdown: InnerDropdown(defaultInnerDropdown) { membersInnerDropdown: InnerDropdown(defaultInnerDropdown) {
scroll: FlatScroll(defaultSolidScroll) { scroll: ScrollArea(defaultSolidScroll) {
deltat: 3px; deltat: 3px;
deltab: 3px; deltab: 3px;
round: 1px; round: 1px;
@ -389,7 +389,7 @@ botKbTinyButton: BotKeyboardButton {
botKbScroll: defaultSolidScroll; botKbScroll: defaultSolidScroll;
mentionHeight: 40px; mentionHeight: 40px;
mentionScroll: FlatScroll(defaultFlatScroll) { mentionScroll: ScrollArea(defaultScrollArea) {
topsh: 0px; topsh: 0px;
bottomsh: 0px; bottomsh: 0px;
} }

View file

@ -35,14 +35,23 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "apiwrap.h" #include "apiwrap.h"
#include "mainwidget.h" #include "mainwidget.h"
DragArea::DragArea(QWidget *parent) : TWidget(parent) DragArea::DragArea(QWidget *parent) : TWidget(parent) {
, _hiding(false)
, _in(false)
, _shadow(st::boxShadow) {
setMouseTracking(true); setMouseTracking(true);
setAcceptDrops(true); setAcceptDrops(true);
} }
bool DragArea::overlaps(const QRect &globalRect) {
if (isHidden() || _a_opacity.animating()) {
return false;
}
auto inner = innerRect();
auto testRect = QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size());
return inner.marginsRemoved(QMargins(st::boxRadius, 0, st::boxRadius, 0)).contains(testRect)
|| inner.marginsRemoved(QMargins(0, st::boxRadius, 0, st::boxRadius)).contains(testRect);
}
void DragArea::mouseMoveEvent(QMouseEvent *e) { void DragArea::mouseMoveEvent(QMouseEvent *e) {
if (_hiding) return; if (_hiding) return;
@ -60,7 +69,7 @@ void DragArea::dragMoveEvent(QDragMoveEvent *e) {
void DragArea::setIn(bool in) { void DragArea::setIn(bool in) {
if (_in != in) { if (_in != in) {
_in = in; _in = in;
_a_in.start([this] { update(); }, _in ? 0. : 1., _in ? 1. : 0., st::defaultDropdownDuration); _a_in.start([this] { update(); }, _in ? 0. : 1., _in ? 1. : 0., st::boxDuration);
} }
} }
@ -79,13 +88,15 @@ void DragArea::paintEvent(QPaintEvent *e) {
return; return;
} }
p.setOpacity(opacity); p.setOpacity(opacity);
auto inner = innerRect();
QRect r(st::dragPadding.left(), st::dragPadding.top(), width() - st::dragPadding.left() - st::dragPadding.right(), height() - st::dragPadding.top() - st::dragPadding.bottom()); if (!_cache.isNull()) {
p.drawPixmapLeft(inner.x() - st::boxRoundShadow.extend.left(), inner.y() - st::boxRoundShadow.extend.top(), width(), _cache);
return;
}
// draw shadow Ui::Shadow::paint(p, inner, width(), st::boxRoundShadow);
_shadow.paint(p, r, st::boxShadowShift); App::roundRect(p, inner, st::boxBg, BoxCorners);
p.fillRect(r, st::dragBg);
p.setPen(anim::pen(st::dragColor, st::dragDropColor, _a_in.current(ms, _in ? 1. : 0.))); p.setPen(anim::pen(st::dragColor, st::dragDropColor, _a_in.current(ms, _in ? 1. : 0.)));
@ -128,9 +139,15 @@ void DragArea::hideFast() {
} }
void DragArea::hideStart() { void DragArea::hideStart() {
if (_hiding || isHidden()) {
return;
}
if (_cache.isNull()) {
_cache = myGrab(this, innerRect().marginsAdded(st::boxRoundShadow.extend));
}
_hiding = true; _hiding = true;
setIn(false); setIn(false);
_a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::defaultDropdownDuration); _a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::boxDuration);
} }
void DragArea::hideFinish() { void DragArea::hideFinish() {
@ -140,14 +157,21 @@ void DragArea::hideFinish() {
} }
void DragArea::showStart() { void DragArea::showStart() {
if (!_hiding && !isHidden()) {
return;
}
_hiding = false; _hiding = false;
if (_cache.isNull()) {
_cache = myGrab(this, innerRect().marginsAdded(st::boxRoundShadow.extend));
}
show(); show();
_a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::defaultDropdownDuration); _a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::boxDuration);
} }
void DragArea::opacityAnimationCallback() { void DragArea::opacityAnimationCallback() {
update(); update();
if (!_a_opacity.animating()) { if (!_a_opacity.animating()) {
_cache = QPixmap();
if (_hiding) { if (_hiding) {
hideFinish(); hideFinish();
} }

View file

@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once #pragma once
#include "ui/twidget.h" #include "ui/twidget.h"
#include "ui/effects/rect_shadow.h"
class DragArea : public TWidget { class DragArea : public TWidget {
Q_OBJECT Q_OBJECT
@ -34,15 +33,7 @@ public:
void otherEnter(); void otherEnter();
void otherLeave(); void otherLeave();
bool overlaps(const QRect &globalRect) { bool overlaps(const QRect &globalRect);
if (isHidden() || _a_opacity.animating()) return false;
return QRect(st::dragPadding.left(),
st::dragPadding.top(),
width() - st::dragPadding.left() - st::dragPadding.right(),
height() - st::dragPadding.top() - st::dragPadding.bottom()
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
}
void hideFast(); void hideFast();
@ -67,16 +58,23 @@ public slots:
private: private:
void setIn(bool in); void setIn(bool in);
void opacityAnimationCallback(); void opacityAnimationCallback();
QRect innerRect() const {
return QRect(
st::dragPadding.left(),
st::dragPadding.top(),
width() - st::dragPadding.left() - st::dragPadding.right(),
height() - st::dragPadding.top() - st::dragPadding.bottom()
);
}
bool _hiding = false; bool _hiding = false;
bool _in = false; bool _in = false;
QPixmap _cache;
base::lambda<void(const QMimeData *data)> _droppedCallback; base::lambda<void(const QMimeData *data)> _droppedCallback;
Animation _a_opacity; Animation _a_opacity;
Animation _a_in; Animation _a_in;
Ui::RectShadow _shadow;
QString _text, _subtext; QString _text, _subtext;
}; };

View file

@ -1554,7 +1554,7 @@ void HistoryGif::initDimensions() {
int32 tw = 0, th = 0; int32 tw = 0, th = 0;
if (_gif && _gif->state() == Media::Clip::State::Error) { if (_gif && _gif->state() == Media::Clip::State::Error) {
if (!_gif->autoplay()) { if (!_gif->autoplay()) {
Ui::showLayer(new InformBox(lang(lng_gif_error))); Ui::show(Box<InformBox>(lang(lng_gif_error)));
} }
App::unregGifItem(_gif.get()); App::unregGifItem(_gif.get());
_gif.setBad(); _gif.setBad();
@ -2204,7 +2204,7 @@ ClickHandlerPtr addContactClickHandler(HistoryItem *item) {
auto fname = contact->fname(); auto fname = contact->fname();
auto lname = contact->lname(); auto lname = contact->lname();
auto phone = contact->phone(); auto phone = contact->phone();
Ui::showLayer(new AddContactBox(fname, lname, phone)); Ui::show(Box<AddContactBox>(fname, lname, phone));
} }
} }
} }

View file

@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_service_layout.h" #include "history/history_service_layout.h"
#include "history/history_media_types.h" #include "history/history_media_types.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_widgets.h"
#include "styles/style_history.h" #include "styles/style_history.h"
namespace { namespace {

View file

@ -2677,32 +2677,28 @@ void BotKeyboard::updateSelected() {
HistoryHider::HistoryHider(MainWidget *parent, bool forwardSelected) : TWidget(parent) HistoryHider::HistoryHider(MainWidget *parent, bool forwardSelected) : TWidget(parent)
, _forwardSelected(forwardSelected) , _forwardSelected(forwardSelected)
, _send(this, lang(lng_forward_send), st::defaultBoxButton) , _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _shadow(st::boxShadow) {
init(); init();
} }
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent) HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent)
, _sharedContact(sharedContact) , _sharedContact(sharedContact)
, _send(this, lang(lng_forward_send), st::defaultBoxButton) , _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _shadow(st::boxShadow) {
init(); init();
} }
HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent) HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent)
, _sendPath(true) , _sendPath(true)
, _send(this, lang(lng_forward_send), st::defaultBoxButton) , _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _shadow(st::boxShadow) {
init(); init();
} }
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent) HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent)
, _botAndQuery(botAndQuery) , _botAndQuery(botAndQuery)
, _send(this, lang(lng_forward_send), st::defaultBoxButton) , _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _shadow(st::boxShadow) {
init(); init();
} }
@ -2710,8 +2706,7 @@ HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString
, _shareUrl(url) , _shareUrl(url)
, _shareText(text) , _shareText(text)
, _send(this, lang(lng_forward_send), st::defaultBoxButton) , _send(this, lang(lng_forward_send), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
, _shadow(st::boxShadow) {
init(); init();
} }
@ -2747,15 +2742,16 @@ void HistoryHider::paintEvent(QPaintEvent *e) {
if (_cacheForAnim.isNull() || !_offered) { if (_cacheForAnim.isNull() || !_offered) {
p.setFont(st::forwardFont); p.setFont(st::forwardFont);
if (_offered) { if (_offered) {
_shadow.paint(p, _box, st::boxShadowShift); Ui::Shadow::paint(p, _box, width(), st::boxRoundShadow);
App::roundRect(p, _box, st::boxBg, BoxCorners);
// fill bg
p.fillRect(_box, st::boxBg);
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
_toText.drawElided(p, _box.left() + st::boxPadding.left(), _box.top() + st::boxPadding.top(), _toTextWidth + 2); textstyleSet(&st::boxTextStyle);
_toText.drawLeftElided(p, _box.left() + st::boxPadding.left(), _box.y() + st::boxTopMargin + st::boxPadding.top(), _toTextWidth + 2, width(), 1, style::al_left);
textstyleRestore();
} else { } else {
int32 w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right(), h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom(); auto w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right();
auto h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom();
App::roundRect(p, (width() - w) / 2, (height() - h) / 2, w, h, st::forwardBg, ForwardCorners); App::roundRect(p, (width() - w) / 2, (height() - h) / 2, w, h, st::forwardBg, ForwardCorners);
p.setPen(st::forwardFg); p.setPen(st::forwardFg);
@ -2839,20 +2835,21 @@ MainWidget *HistoryHider::parent() {
} }
void HistoryHider::resizeEvent(QResizeEvent *e) { void HistoryHider::resizeEvent(QResizeEvent *e) {
int32 w = st::boxWidth, h = st::boxPadding.top() + st::boxPadding.bottom(); auto w = st::boxWidth;
auto h = st::boxPadding.top() + st::boxPadding.bottom();
if (_offered) { if (_offered) {
if (!_hiding) { if (!_hiding) {
_send->show(); _send->show();
_cancel->show(); _cancel->show();
} }
h += st::boxTextFont->height + st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom(); h += st::boxTopMargin + qMax(st::boxTextFont->height, st::boxTextStyle.lineHeight) + st::boxButtonPadding.top() + _send->height() + st::boxButtonPadding.bottom();
} else { } else {
h += st::forwardFont->height; h += st::forwardFont->height;
_send->hide(); _send->hide();
_cancel->hide(); _cancel->hide();
} }
_box = QRect((width() - w) / 2, (height() - h) / 2, w, h); _box = QRect((width() - w) / 2, (height() - h) / 2, w, h);
_send->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right(), _box.y() + h - st::boxButtonPadding.bottom() - _send->height()); _send->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right(), _box.y() + _box.height() - st::boxButtonPadding.bottom() - _send->height());
_cancel->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y()); _cancel->moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right() + _send->width() + st::boxButtonPadding.left(), _send->y());
} }
@ -2899,10 +2896,12 @@ bool HistoryHider::offerPeer(PeerId peer) {
return false; return false;
} }
textstyleSet(&st::boxTextStyle);
_toText.setText(st::boxTextFont, phrase, _textNameOptions); _toText.setText(st::boxTextFont, phrase, _textNameOptions);
textstyleRestore();
_toTextWidth = _toText.maxWidth(); _toTextWidth = _toText.maxWidth();
if (_toTextWidth > _box.width() - st::boxPadding.left() - st::boxButtonPadding.right()) { if (_toTextWidth > _box.width() - st::boxPadding.left() - st::boxLayerButtonPadding.right()) {
_toTextWidth = _box.width() - st::boxPadding.left() - st::boxButtonPadding.right(); _toTextWidth = _box.width() - st::boxPadding.left() - st::boxLayerButtonPadding.right();
} }
resizeEvent(nullptr); resizeEvent(nullptr);
@ -3047,7 +3046,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _recordCancelWidth(st::historyRecordFont->width(lang(lng_record_cancel))) , _recordCancelWidth(st::historyRecordFont->width(lang(lng_record_cancel)))
, _a_recording(animation(this, &HistoryWidget::step_recording)) , _a_recording(animation(this, &HistoryWidget::step_recording))
, _kbScroll(this, st::botKbScroll) , _kbScroll(this, st::botKbScroll)
, _keyboard(this)
, _emojiPan(this) , _emojiPan(this)
, _attachDragDocument(this) , _attachDragDocument(this)
, _attachDragPhoto(this) , _attachDragPhoto(this)
@ -3123,7 +3121,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_scroll->hide(); _scroll->hide();
_kbScroll->setOwnedWidget(_keyboard); _keyboard = _kbScroll->setOwnedWidget(object_ptr<BotKeyboard>(this));
_kbScroll->hide(); _kbScroll->hide();
updateScrollColors(); updateScrollColors();
@ -4233,9 +4231,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
_fieldBarCancel->hide(); _fieldBarCancel->hide();
_membersDropdownShowTimer.stop(); _membersDropdownShowTimer.stop();
if (_list) _list->deleteLater(); _scroll->takeWidget<HistoryInner>().destroyDelayed();
_list = nullptr; _list = nullptr;
_scroll->takeWidget();
clearInlineBot(); clearInlineBot();
@ -4299,10 +4296,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
} }
} }
_list = new HistoryInner(this, _scroll, _history);
_list->hide();
_scroll->hide(); _scroll->hide();
_scroll->setWidget(_list); _list = _scroll->setOwnedWidget(object_ptr<HistoryInner>(this, _scroll, _history));
_list->show(); _list->show();
_updateHistoryItems.stop(); _updateHistoryItems.stop();
@ -4790,7 +4785,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId
if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
PeerData *was = _peer; PeerData *was = _peer;
App::main()->showBackFromStack(); App::main()->showBackFromStack();
Ui::showLayer(new InformBox(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); Ui::show(Box<InformBox>(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
return true; return true;
} }
@ -5175,7 +5170,7 @@ void HistoryWidget::saveEditMsg() {
_field->setFocus(); _field->setFocus();
return; return;
} else if (!leftText.isEmpty()) { } else if (!leftText.isEmpty()) {
Ui::showLayer(new InformBox(lang(lng_edit_too_long))); Ui::show(Box<InformBox>(lang(lng_edit_too_long)));
return; return;
} }
@ -5219,14 +5214,14 @@ bool HistoryWidget::saveEditMsgFail(History *history, const RPCError &error, mtp
QString err = error.type(); QString err = error.type();
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) { if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
Ui::showLayer(new InformBox(lang(lng_edit_error))); Ui::show(Box<InformBox>(lang(lng_edit_error)));
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) { } else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
cancelEdit(); cancelEdit();
} else if (err == qstr("MESSAGE_EMPTY")) { } else if (err == qstr("MESSAGE_EMPTY")) {
_field->selectAll(); _field->selectAll();
_field->setFocus(); _field->setFocus();
} else { } else {
Ui::showLayer(new InformBox(lang(lng_edit_error))); Ui::show(Box<InformBox>(lang(lng_edit_error)));
} }
update(); update();
return true; return true;
@ -5347,10 +5342,10 @@ bool HistoryWidget::joinFail(const RPCError &error, mtpRequestId req) {
if (_unblockRequest == req) _unblockRequest = 0; if (_unblockRequest == req) _unblockRequest = 0;
if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) { if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
Ui::showLayer(new InformBox(lang((_peer && _peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); Ui::show(Box<InformBox>(lang((_peer && _peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
return true; return true;
} else if (error.type() == qstr("CHANNELS_TOO_MUCH")) { } else if (error.type() == qstr("CHANNELS_TOO_MUCH")) {
Ui::showLayer(new InformBox(lang(lng_join_channel_error))); Ui::show(Box<InformBox>(lang(lng_join_channel_error)));
} }
return false; return false;
@ -5779,7 +5774,7 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
auto &answerData = answer.c_messages_botCallbackAnswer(); auto &answerData = answer.c_messages_botCallbackAnswer();
if (answerData.has_message()) { if (answerData.has_message()) {
if (answerData.is_alert()) { if (answerData.is_alert()) {
Ui::showLayer(new InformBox(qs(answerData.vmessage))); Ui::show(Box<InformBox>(qs(answerData.vmessage)));
} else if (App::wnd()) { } else if (App::wnd()) {
Ui::Toast::Config toast; Ui::Toast::Config toast;
toast.text = qs(answerData.vmessage); toast.text = qs(answerData.vmessage);
@ -5923,29 +5918,30 @@ DragState HistoryWidget::getDragState(const QMimeData *d) {
void HistoryWidget::updateDragAreas() { void HistoryWidget::updateDragAreas() {
_field->setAcceptDrops(!_attachDrag); _field->setAcceptDrops(!_attachDrag);
updateControlsGeometry();
switch (_attachDrag) { switch (_attachDrag) {
case DragStateNone: case DragStateNone:
_attachDragDocument->otherLeave(); _attachDragDocument->otherLeave();
_attachDragPhoto->otherLeave(); _attachDragPhoto->otherLeave();
break; break;
case DragStateFiles: case DragStateFiles:
_attachDragDocument->otherEnter();
_attachDragDocument->setText(lang(lng_drag_files_here), lang(lng_drag_to_send_files)); _attachDragDocument->setText(lang(lng_drag_files_here), lang(lng_drag_to_send_files));
_attachDragDocument->otherEnter();
_attachDragPhoto->hideFast(); _attachDragPhoto->hideFast();
break; break;
case DragStatePhotoFiles: case DragStatePhotoFiles:
_attachDragDocument->otherEnter();
_attachDragDocument->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_no_compression)); _attachDragDocument->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_no_compression));
_attachDragPhoto->otherEnter();
_attachDragPhoto->setText(lang(lng_drag_photos_here), lang(lng_drag_to_send_quick)); _attachDragPhoto->setText(lang(lng_drag_photos_here), lang(lng_drag_to_send_quick));
_attachDragDocument->otherEnter();
_attachDragPhoto->otherEnter();
break; break;
case DragStateImage: case DragStateImage:
_attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick));
_attachDragDocument->hideFast(); _attachDragDocument->hideFast();
_attachDragPhoto->otherEnter(); _attachDragPhoto->otherEnter();
_attachDragPhoto->setText(lang(lng_drag_images_here), lang(lng_drag_to_send_quick));
break; break;
}; };
resizeEvent(0);
} }
bool HistoryWidget::canSendMessages(PeerData *peer) const { bool HistoryWidget::canSendMessages(PeerData *peer) const {
@ -6157,13 +6153,6 @@ void HistoryWidget::selectMessage() {
if (_list) _list->selectItem(item); if (_list) _list->selectItem(item);
} }
void HistoryWidget::onForwardHere() {
HistoryItem *item = App::contextItem();
if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return;
App::forward(_peer->id, ForwardContextMessage);
}
bool HistoryWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) { bool HistoryWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) {
if (_a_show.animating()) { if (_a_show.animating()) {
auto progress = _a_show.current(1.); auto progress = _a_show.current(1.);
@ -6462,7 +6451,7 @@ void HistoryWidget::updateFieldPlaceholder() {
} }
template <typename SendCallback> template <typename SendCallback>
bool HistoryWidget::showSendFilesBox(SendFilesBox *box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback) { bool HistoryWidget::showSendFilesBox(object_ptr<SendFilesBox> box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback) {
App::wnd()->activateWindow(); App::wnd()->activateWindow();
auto withComment = (addedComment != nullptr); auto withComment = (addedComment != nullptr);
@ -6488,7 +6477,7 @@ bool HistoryWidget::showSendFilesBox(SendFilesBox *box, const QString &insertTex
})); }));
} }
Ui::showLayer(box); Ui::show(std_::move(box));
return true; return true;
} }
@ -6498,11 +6487,11 @@ bool HistoryWidget::validateSendingFiles(const SendingFilesLists &lists, Callbac
App::wnd()->activateWindow(); App::wnd()->activateWindow();
if (!lists.nonLocalUrls.isEmpty()) { if (!lists.nonLocalUrls.isEmpty()) {
Ui::showLayer(new InformBox(lng_send_image_non_local(lt_name, lists.nonLocalUrls.front().toDisplayString()))); Ui::show(Box<InformBox>(lng_send_image_non_local(lt_name, lists.nonLocalUrls.front().toDisplayString())));
} else if (!lists.emptyFiles.isEmpty()) { } else if (!lists.emptyFiles.isEmpty()) {
Ui::showLayer(new InformBox(lng_send_image_empty(lt_name, lists.emptyFiles.front()))); Ui::show(Box<InformBox>(lng_send_image_empty(lt_name, lists.emptyFiles.front())));
} else if (!lists.tooLargeFiles.isEmpty()) { } else if (!lists.tooLargeFiles.isEmpty()) {
Ui::showLayer(new InformBox(lng_send_image_too_large(lt_name, lists.tooLargeFiles.front()))); Ui::show(Box<InformBox>(lng_send_image_too_large(lt_name, lists.tooLargeFiles.front())));
} else if (!lists.filesToSend.isEmpty()) { } else if (!lists.filesToSend.isEmpty()) {
return callback(lists.filesToSend); return callback(lists.filesToSend);
} }
@ -6523,12 +6512,12 @@ bool HistoryWidget::confirmSendingFiles(const SendingFilesLists &lists, Compress
auto insertTextOnCancel = QString(); auto insertTextOnCancel = QString();
auto prepareBox = [this, &files, &lists, compressed, &image] { auto prepareBox = [this, &files, &lists, compressed, &image] {
if (files.size() > 1) { if (files.size() > 1) {
return new SendFilesBox(files, lists.allFilesForCompress ? compressed : CompressConfirm::None); return Box<SendFilesBox>(files, lists.allFilesForCompress ? compressed : CompressConfirm::None);
} }
auto filepath = files.front(); auto filepath = files.front();
auto animated = false; auto animated = false;
image = App::readImage(filepath, nullptr, false, &animated); image = App::readImage(filepath, nullptr, false, &animated);
return new SendFilesBox(filepath, image, imageCompressConfirm(image, compressed, animated), animated); return Box<SendFilesBox>(filepath, image, imageCompressConfirm(image, compressed, animated), animated);
}; };
auto sendCallback = [this, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) { auto sendCallback = [this, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) {
auto type = compressed ? SendMediaType::Photo : SendMediaType::File; auto type = compressed ? SendMediaType::Photo : SendMediaType::File;
@ -6543,12 +6532,12 @@ bool HistoryWidget::confirmSendingFiles(const QImage &image, const QByteArray &c
App::wnd()->activateWindow(); App::wnd()->activateWindow();
auto animated = false; auto animated = false;
auto box = new SendFilesBox(QString(), image, imageCompressConfirm(image, compressed), animated);
auto sendCallback = [this, content, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) { auto sendCallback = [this, content, image](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) {
auto type = compressed ? SendMediaType::Photo : SendMediaType::File; auto type = compressed ? SendMediaType::Photo : SendMediaType::File;
uploadFilesAfterConfirmation(files, image, content, type, caption); uploadFilesAfterConfirmation(files, image, content, type, caption);
}; };
return showSendFilesBox(box, insertTextOnCancel, nullptr, std_::move(sendCallback)); auto box = Box<SendFilesBox>(QString(), image, imageCompressConfirm(image, compressed), animated);
return showSendFilesBox(std_::move(box), insertTextOnCancel, nullptr, std_::move(sendCallback));
} }
bool HistoryWidget::confirmSendingFiles(const QMimeData *data, CompressConfirm compressed, const QString &insertTextOnCancel) { bool HistoryWidget::confirmSendingFiles(const QMimeData *data, CompressConfirm compressed, const QString &insertTextOnCancel) {
@ -6578,12 +6567,12 @@ bool HistoryWidget::confirmSendingFiles(const QMimeData *data, CompressConfirm c
bool HistoryWidget::confirmShareContact(const QString &phone, const QString &fname, const QString &lname, const QString *addedComment) { bool HistoryWidget::confirmShareContact(const QString &phone, const QString &fname, const QString &lname, const QString *addedComment) {
if (!canWriteMessage()) return false; if (!canWriteMessage()) return false;
auto box = new SendFilesBox(phone, fname, lname); auto box = Box<SendFilesBox>(phone, fname, lname);
auto sendCallback = [this, phone, fname, lname](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) { auto sendCallback = [this, phone, fname, lname](const QStringList &files, bool compressed, const QString &caption, MsgId replyTo) {
shareContact(_peer->id, phone, fname, lname, replyTo); shareContact(_peer->id, phone, fname, lname, replyTo);
}; };
auto insertTextOnCancel = QString(); auto insertTextOnCancel = QString();
return showSendFilesBox(box, insertTextOnCancel, addedComment, std_::move(sendCallback)); return showSendFilesBox(std_::move(box), insertTextOnCancel, addedComment, std_::move(sendCallback));
} }
HistoryWidget::SendingFilesLists HistoryWidget::getSendingFilesLists(const QList<QUrl> &files) { HistoryWidget::SendingFilesLists HistoryWidget::getSendingFilesLists(const QList<QUrl> &files) {
@ -6901,18 +6890,15 @@ void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
} }
void HistoryWidget::onReportSpamClicked() { void HistoryWidget::onReportSpamClicked() {
ConfirmBox *box = new ConfirmBox(lang(_peer->isUser() ? lng_report_spam_sure : ((_peer->isChat() || _peer->isMegagroup()) ? lng_report_spam_sure_group : lng_report_spam_sure_channel)), lang(lng_report_spam_ok), st::attentionBoxButton);
connect(box, SIGNAL(confirmed()), this, SLOT(onReportSpamSure()));
Ui::showLayer(box);
_clearPeer = _peer; _clearPeer = _peer;
} auto text = lang(_peer->isUser() ? lng_report_spam_sure : ((_peer->isChat() || _peer->isMegagroup()) ? lng_report_spam_sure_group : lng_report_spam_sure_channel));
Ui::show(Box<ConfirmBox>(text, lang(lng_report_spam_ok), st::attentionBoxButton, base::lambda_guarded(this, [this] {
if (_reportSpamRequest) return;
void HistoryWidget::onReportSpamSure() { Ui::hideLayer();
if (_reportSpamRequest) return; if (_clearPeer->isUser()) MTP::send(MTPcontacts_Block(_clearPeer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _clearPeer), RPCFailHandlerPtr(), 0, 5);
_reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_clearPeer->input), rpcDone(&HistoryWidget::reportSpamDone, _clearPeer), rpcFail(&HistoryWidget::reportSpamFail));
Ui::hideLayer(); })));
if (_clearPeer->isUser()) MTP::send(MTPcontacts_Block(_clearPeer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _clearPeer), RPCFailHandlerPtr(), 0, 5);
_reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_clearPeer->input), rpcDone(&HistoryWidget::reportSpamDone, _clearPeer), rpcFail(&HistoryWidget::reportSpamFail));
} }
void HistoryWidget::reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId req) { void HistoryWidget::reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId req) {
@ -7091,7 +7077,7 @@ void HistoryWidget::updateControlsGeometry() {
updateHistoryDownPosition(); updateHistoryDownPosition();
_emojiPan->setMaxHeight(height() - st::defaultDropdownPadding.top() - st::defaultDropdownPadding.bottom() - _attachEmoji->height()); _emojiPan->setMaxHeight(height() - _attachEmoji->height());
if (_membersDropdown) { if (_membersDropdown) {
_membersDropdown->setMaxHeight(countMembersDropdownHeightMax()); _membersDropdown->setMaxHeight(countMembersDropdownHeightMax());
} }
@ -7855,14 +7841,16 @@ void HistoryWidget::onReplyToMessage() {
onReplyToMessage(); onReplyToMessage();
App::contextItem(to); App::contextItem(to);
} else { } else {
LayerWidget *box = nullptr;
if (to->type() != HistoryItemMsg || to->serviceMsg()) { if (to->type() != HistoryItemMsg || to->serviceMsg()) {
box = new InformBox(lang(lng_reply_cant)); Ui::show(Box<InformBox>(lang(lng_reply_cant)));
} else { } else {
box = new ConfirmBox(lang(lng_reply_cant_forward), lang(lng_selected_forward)); Ui::show(Box<ConfirmBox>(lang(lng_reply_cant_forward), lang(lng_selected_forward), base::lambda_guarded(this, [this] {
connect(box, SIGNAL(confirmed()), this, SLOT(onForwardHere())); auto item = App::contextItem();
if (!item || item->type() != HistoryItemMsg || item->serviceMsg()) return;
App::forward(_peer->id, ForwardContextMessage);
})));
} }
Ui::showLayer(box);
} }
return; return;
} }
@ -7897,15 +7885,12 @@ void HistoryWidget::onReplyToMessage() {
} }
void HistoryWidget::onEditMessage() { void HistoryWidget::onEditMessage() {
HistoryItem *to = App::contextItem(); auto to = App::contextItem();
if (!to) return; if (!to) return;
EditCaptionBox *box = new EditCaptionBox(to); if (EditCaptionBox::canEdit(to)) {
if (box->captionFound()) { Ui::show(Box<EditCaptionBox>(to));
Ui::showLayer(box);
} else { } else {
delete box;
if (!_editMsgId) { if (!_editMsgId) {
if (_replyToId || !_field->isEmpty()) { if (_replyToId || !_field->isEmpty()) {
_history->setLocalDraft(std_::make_unique<Data::Draft>(_field, _replyToId, _previewCancelled)); _history->setLocalDraft(std_::make_unique<Data::Draft>(_field, _replyToId, _previewCancelled));
@ -7954,29 +7939,25 @@ void HistoryWidget::onPinMessage() {
HistoryItem *to = App::contextItem(); HistoryItem *to = App::contextItem();
if (!to || !to->canPin() || !_peer || !_peer->isMegagroup()) return; if (!to || !to->canPin() || !_peer || !_peer->isMegagroup()) return;
Ui::showLayer(new PinMessageBox(_peer->asChannel(), to->id)); Ui::show(Box<PinMessageBox>(_peer->asChannel(), to->id));
} }
void HistoryWidget::onUnpinMessage() { void HistoryWidget::onUnpinMessage() {
if (!_peer || !_peer->isMegagroup()) return; if (!_peer || !_peer->isMegagroup()) return;
ConfirmBox *box = new ConfirmBox(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin)); Ui::show(Box<ConfirmBox>(lang(lng_pinned_unpin_sure), lang(lng_pinned_unpin), base::lambda_guarded(this, [this] {
connect(box, SIGNAL(confirmed()), this, SLOT(onUnpinMessageSure())); if (!_peer || !_peer->isMegagroup()) return;
Ui::showLayer(box);
}
void HistoryWidget::onUnpinMessageSure() { _peer->asChannel()->mgInfo->pinnedMsgId = 0;
if (!_peer || !_peer->isMegagroup()) return; if (pinnedMsgVisibilityUpdated()) {
resizeEvent(0);
update();
}
_peer->asChannel()->mgInfo->pinnedMsgId = 0; Ui::hideLayer();
if (pinnedMsgVisibilityUpdated()) { MTPchannels_UpdatePinnedMessage::Flags flags = 0;
resizeEvent(0); MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _peer->asChannel()->inputChannel, MTP_int(0)), rpcDone(&HistoryWidget::unpinDone));
update(); })));
}
Ui::hideLayer();
MTPchannels_UpdatePinnedMessage::Flags flags = 0;
MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _peer->asChannel()->inputChannel, MTP_int(0)), rpcDone(&HistoryWidget::unpinDone));
} }
void HistoryWidget::unpinDone(const MTPUpdates &updates) { void HistoryWidget::unpinDone(const MTPUpdates &updates) {
@ -8279,9 +8260,13 @@ void HistoryWidget::onCancel() {
auto editTags = textTagsFromEntities(original.entities); auto editTags = textTagsFromEntities(original.entities);
TextWithTags editData = { editText, editTags }; TextWithTags editData = { editText, editTags };
if (_replyEditMsg && editData != _field->getTextWithTags()) { if (_replyEditMsg && editData != _field->getTextWithTags()) {
auto box = new ConfirmBox(lang(lng_cancel_edit_post_sure), lang(lng_cancel_edit_post_yes), st::defaultBoxButton, lang(lng_cancel_edit_post_no)); Ui::show(Box<ConfirmBox>(
connect(box, SIGNAL(confirmed()), this, SLOT(onFieldBarCancel())); lang(lng_cancel_edit_post_sure),
Ui::showLayer(box); lang(lng_cancel_edit_post_yes),
lang(lng_cancel_edit_post_no),
base::lambda_guarded(this, [this] {
onFieldBarCancel();
})));
} else { } else {
onFieldBarCancel(); onFieldBarCancel();
} }
@ -8326,7 +8311,7 @@ void HistoryWidget::peerUpdated(PeerData *data) {
QString restriction = _peer->restrictionReason(); QString restriction = _peer->restrictionReason();
if (!restriction.isEmpty()) { if (!restriction.isEmpty()) {
App::main()->showBackFromStack(); App::main()->showBackFromStack();
Ui::showLayer(new InformBox(restriction)); Ui::show(Box<InformBox>(restriction));
return; return;
} }
bool resize = false; bool resize = false;
@ -8926,7 +8911,3 @@ bool HistoryWidget::touchScroll(const QPoint &delta) {
_scroll->scrollToY(scNew); _scroll->scrollToY(scNew);
return true; return true;
} }
HistoryWidget::~HistoryWidget() {
delete base::take(_list);
}

View file

@ -22,7 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localimageloader.h" #include "localimageloader.h"
#include "ui/filedialog.h" #include "ui/filedialog.h"
#include "ui/effects/rect_shadow.h"
#include "ui/widgets/tooltip.h" #include "ui/widgets/tooltip.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
@ -365,9 +364,9 @@ protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
private: private:
ChildWidget<Ui::FlatButton> _report; object_ptr<Ui::FlatButton> _report;
ChildWidget<Ui::FlatButton> _hide; object_ptr<Ui::FlatButton> _hide;
ChildWidget<Ui::LinkButton> _clear; object_ptr<Ui::LinkButton> _clear;
}; };
@ -506,8 +505,8 @@ private:
QString _shareUrl, _shareText; QString _shareUrl, _shareText;
QString _botAndQuery; QString _botAndQuery;
ChildWidget<Ui::RoundButton> _send; object_ptr<Ui::RoundButton> _send;
ChildWidget<Ui::RoundButton> _cancel; object_ptr<Ui::RoundButton> _cancel;
PeerData *_offered = nullptr; PeerData *_offered = nullptr;
Animation _a_opacity; Animation _a_opacity;
@ -523,8 +522,6 @@ private:
int32 _toTextWidth = 0; int32 _toTextWidth = 0;
QPixmap _cacheForAnim; QPixmap _cacheForAnim;
Ui::RectShadow _shadow;
}; };
EntitiesInText entitiesFromTextTags(const TextWithTags::Tags &tags); EntitiesInText entitiesFromTextTags(const TextWithTags::Tags &tags);
@ -724,8 +721,6 @@ public:
bool cmd_next_chat(); bool cmd_next_chat();
bool cmd_previous_chat(); bool cmd_previous_chat();
~HistoryWidget();
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
@ -746,7 +741,6 @@ public slots:
void onEditMessage(); void onEditMessage();
void onPinMessage(); void onPinMessage();
void onUnpinMessage(); void onUnpinMessage();
void onUnpinMessageSure();
void onPinnedHide(); void onPinnedHide();
void onCopyPostLink(); void onCopyPostLink();
void onFieldBarCancel(); void onFieldBarCancel();
@ -773,7 +767,6 @@ public slots:
void onDocumentFailed(const FullMsgId &msgId); void onDocumentFailed(const FullMsgId &msgId);
void onReportSpamClicked(); void onReportSpamClicked();
void onReportSpamSure();
void onReportSpamHide(); void onReportSpamHide();
void onReportSpamClear(); void onReportSpamClear();
@ -805,8 +798,6 @@ public slots:
void forwardMessage(); void forwardMessage();
void selectMessage(); void selectMessage();
void onForwardHere(); // instead of a reply
void onFieldFocused(); void onFieldFocused();
void onFieldResize(); void onFieldResize();
void onCheckFieldAutocomplete(); void onCheckFieldAutocomplete();
@ -867,7 +858,7 @@ private:
template <typename Callback> template <typename Callback>
bool validateSendingFiles(const SendingFilesLists &lists, Callback callback); bool validateSendingFiles(const SendingFilesLists &lists, Callback callback);
template <typename SendCallback> template <typename SendCallback>
bool showSendFilesBox(SendFilesBox *box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback); bool showSendFilesBox(object_ptr<SendFilesBox> box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback);
CompressConfirm imageCompressConfirm(const QImage &image, CompressConfirm compressed, bool animated = false); CompressConfirm imageCompressConfirm(const QImage &image, CompressConfirm compressed, bool animated = false);
// If an empty filepath is found we upload (possible) "image" with (possible) "content". // If an empty filepath is found we upload (possible) "image" with (possible) "content".
@ -908,7 +899,7 @@ private:
Text _replyEditMsgText; Text _replyEditMsgText;
mutable SingleTimer _updateEditTimeLeftDisplay; mutable SingleTimer _updateEditTimeLeftDisplay;
ChildWidget<Ui::IconButton> _fieldBarCancel; object_ptr<Ui::IconButton> _fieldBarCancel;
void updateReplyEditTexts(bool force = false); void updateReplyEditTexts(bool force = false);
struct PinnedBar { struct PinnedBar {
@ -918,8 +909,8 @@ private:
MsgId msgId = 0; MsgId msgId = 0;
HistoryItem *msg = nullptr; HistoryItem *msg = nullptr;
Text text; Text text;
ChildWidget<Ui::IconButton> cancel; object_ptr<Ui::IconButton> cancel;
ChildWidget<Ui::PlainShadow> shadow; object_ptr<Ui::PlainShadow> shadow;
}; };
std_::unique_ptr<PinnedBar> _pinnedBar; std_::unique_ptr<PinnedBar> _pinnedBar;
void updatePinnedBar(bool force = false); void updatePinnedBar(bool force = false);
@ -1078,8 +1069,8 @@ private:
MsgId _activeAnimMsgId = 0; MsgId _activeAnimMsgId = 0;
ChildWidget<Ui::ScrollArea> _scroll; object_ptr<Ui::ScrollArea> _scroll;
HistoryInner *_list = nullptr; QPointer<HistoryInner> _list;
History *_migrated = nullptr; History *_migrated = nullptr;
History *_history = nullptr; History *_history = nullptr;
bool _histInited = false; // initial updateListSize() called bool _histInited = false; // initial updateListSize() called
@ -1091,9 +1082,9 @@ private:
Animation _historyDownShown; Animation _historyDownShown;
bool _historyDownIsShown = false; bool _historyDownIsShown = false;
ChildWidget<Ui::HistoryDownButton> _historyDown; object_ptr<Ui::HistoryDownButton> _historyDown;
ChildWidget<FieldAutocomplete> _fieldAutocomplete; object_ptr<FieldAutocomplete> _fieldAutocomplete;
UserData *_inlineBot = nullptr; UserData *_inlineBot = nullptr;
QString _inlineBotUsername; QString _inlineBotUsername;
@ -1108,23 +1099,23 @@ private:
bool isMuteUnmute() const; bool isMuteUnmute() const;
bool updateCmdStartShown(); bool updateCmdStartShown();
ChildWidget<ReportSpamPanel> _reportSpamPanel; object_ptr<ReportSpamPanel> _reportSpamPanel;
ChildWidget<Ui::IconButton> _send; object_ptr<Ui::IconButton> _send;
ChildWidget<Ui::FlatButton> _unblock; object_ptr<Ui::FlatButton> _unblock;
ChildWidget<Ui::FlatButton> _botStart; object_ptr<Ui::FlatButton> _botStart;
ChildWidget<Ui::FlatButton> _joinChannel; object_ptr<Ui::FlatButton> _joinChannel;
ChildWidget<Ui::FlatButton> _muteUnmute; object_ptr<Ui::FlatButton> _muteUnmute;
mtpRequestId _unblockRequest = 0; mtpRequestId _unblockRequest = 0;
mtpRequestId _reportSpamRequest = 0; mtpRequestId _reportSpamRequest = 0;
ChildWidget<Ui::IconButton> _attachToggle; object_ptr<Ui::IconButton> _attachToggle;
ChildWidget<Ui::EmojiButton> _attachEmoji; object_ptr<Ui::EmojiButton> _attachEmoji;
ChildWidget<Ui::IconButton> _botKeyboardShow; object_ptr<Ui::IconButton> _botKeyboardShow;
ChildWidget<Ui::IconButton> _botKeyboardHide; object_ptr<Ui::IconButton> _botKeyboardHide;
ChildWidget<Ui::IconButton> _botCommandStart; object_ptr<Ui::IconButton> _botCommandStart;
ChildWidget<SilentToggle> _silent; object_ptr<SilentToggle> _silent;
bool _cmdStartShown = false; bool _cmdStartShown = false;
ChildWidget<MessageField> _field; object_ptr<MessageField> _field;
bool _recording = false; bool _recording = false;
bool _inRecord = false; bool _inRecord = false;
bool _inField = false; bool _inField = false;
@ -1147,15 +1138,15 @@ private:
bool _kbShown = false; bool _kbShown = false;
HistoryItem *_kbReplyTo = nullptr; HistoryItem *_kbReplyTo = nullptr;
ChildWidget<Ui::ScrollArea> _kbScroll; object_ptr<Ui::ScrollArea> _kbScroll;
ChildWidget<BotKeyboard> _keyboard; QPointer<BotKeyboard> _keyboard;
ChildWidget<Ui::InnerDropdown> _membersDropdown = { nullptr }; object_ptr<Ui::InnerDropdown> _membersDropdown = { nullptr };
QTimer _membersDropdownShowTimer; QTimer _membersDropdownShowTimer;
ChildWidget<EmojiPan> _emojiPan; object_ptr<EmojiPan> _emojiPan;
DragState _attachDrag = DragStateNone; DragState _attachDrag = DragStateNone;
ChildWidget<DragArea> _attachDragDocument, _attachDragPhoto; object_ptr<DragArea> _attachDragDocument, _attachDragPhoto;
int32 _selCount; // < 0 - text selected, focus list, not _field int32 _selCount; // < 0 - text selected, focus list, not _field
@ -1186,7 +1177,7 @@ private:
bool _saveDraftText = false; bool _saveDraftText = false;
QTimer _saveDraftTimer, _saveCloudDraftTimer; QTimer _saveDraftTimer, _saveCloudDraftTimer;
ChildWidget<Ui::PlainShadow> _topShadow; object_ptr<Ui::PlainShadow> _topShadow;
bool _inGrab = false; bool _inGrab = false;
}; };

View file

@ -91,20 +91,20 @@ private:
void stopCheck(); void stopCheck();
ChildWidget<Ui::LinkButton> _noTelegramCode; object_ptr<Ui::LinkButton> _noTelegramCode;
mtpRequestId _noTelegramCodeRequestId = 0; mtpRequestId _noTelegramCodeRequestId = 0;
ChildWidget<CodeInput> _code; object_ptr<CodeInput> _code;
QString _sentCode; QString _sentCode;
mtpRequestId _sentRequest = 0; mtpRequestId _sentRequest = 0;
ChildObject<QTimer> _callTimer; object_ptr<QTimer> _callTimer;
Widget::Data::CallStatus _callStatus; Widget::Data::CallStatus _callStatus;
int _callTimeout; int _callTimeout;
mtpRequestId _callRequestId = 0; mtpRequestId _callRequestId = 0;
ChildWidget<Ui::FlatLabel> _callLabel; object_ptr<Ui::FlatLabel> _callLabel;
ChildObject<QTimer> _checkRequest; object_ptr<QTimer> _checkRequest;
}; };

View file

@ -81,7 +81,7 @@ void PhoneWidget::showPhoneError(const QString &text) {
void PhoneWidget::hidePhoneError() { void PhoneWidget::hidePhoneError() {
hideError(); hideError();
if (_signup) { if (_signup) {
_signup->fadeOut(); _signup->hideAnimated();
showDescription(); showDescription();
} }
} }
@ -90,8 +90,8 @@ void PhoneWidget::showSignup() {
showPhoneError(lang(lng_bad_phone_noreg)); showPhoneError(lang(lng_bad_phone_noreg));
if (!_signup) { if (!_signup) {
auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink()); auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink());
auto inner = new Ui::FlatLabel(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription, st::introDescriptionTextStyle); auto inner = object_ptr<Ui::FlatLabel>(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription, st::introDescriptionTextStyle);
_signup.create(this, inner, base::lambda<void()>(), st::introErrorDuration); _signup.create(this, std_::move(inner), st::introErrorDuration);
_signup->entity()->setLink(1, MakeShared<UrlClickHandler>(qsl("https://telegram.org"), false)); _signup->entity()->setLink(1, MakeShared<UrlClickHandler>(qsl("https://telegram.org"), false));
_signup->entity()->setLink(2, MakeShared<LambdaClickHandler>([this] { _signup->entity()->setLink(2, MakeShared<LambdaClickHandler>([this] {
toSignUp(); toSignUp();
@ -99,7 +99,7 @@ void PhoneWidget::showSignup() {
_signup->hideFast(); _signup->hideFast();
updateSignupGeometry(); updateSignupGeometry();
} }
_signup->fadeIn(); _signup->showAnimated();
hideDescription(); hideDescription();
} }

View file

@ -76,16 +76,16 @@ private:
bool _changed = false; bool _changed = false;
ChildWidget<CountryInput> _country; object_ptr<CountryInput> _country;
ChildWidget<Ui::CountryCodeInput> _code; object_ptr<Ui::CountryCodeInput> _code;
ChildWidget<Ui::PhonePartInput> _phone; object_ptr<Ui::PhonePartInput> _phone;
ChildWidget<Ui::WidgetFadeWrap<Ui::FlatLabel>> _signup = { nullptr }; object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _signup = { nullptr };
QString _sentPhone; QString _sentPhone;
mtpRequestId _sentRequest = 0; mtpRequestId _sentRequest = 0;
ChildObject<QTimer> _checkRequest; object_ptr<QTimer> _checkRequest;
}; };

View file

@ -229,19 +229,15 @@ void PwdCheckWidget::onToRecover() {
MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PwdCheckWidget::recoverStarted), rpcFail(&PwdCheckWidget::recoverStartFail)); MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PwdCheckWidget::recoverStarted), rpcFail(&PwdCheckWidget::recoverStartFail));
} }
} else { } else {
ConfirmBox *box = new InformBox(lang(lng_signin_no_email_forgot)); Ui::show(Box<InformBox>(lang(lng_signin_no_email_forgot), [this] { showReset(); }));
Ui::showLayer(box);
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
} }
} }
void PwdCheckWidget::onToPassword() { void PwdCheckWidget::onToPassword() {
ConfirmBox *box = new InformBox(lang(lng_signin_cant_email_forgot)); Ui::show(Box<InformBox>(lang(lng_signin_cant_email_forgot), [this] { showReset(); }));
Ui::showLayer(box);
connect(box, SIGNAL(destroyed(QObject*)), this, SLOT(onToReset()));
} }
void PwdCheckWidget::onToReset() { void PwdCheckWidget::showReset() {
if (_sentRequest) { if (_sentRequest) {
MTP::cancel(base::take(_sentRequest)); MTP::cancel(base::take(_sentRequest));
} }

View file

@ -51,9 +51,10 @@ private slots:
void onToPassword(); void onToPassword();
void onInputChange(); void onInputChange();
void onCheckRequest(); void onCheckRequest();
void onToReset();
private: private:
void showReset();
void pwdSubmitDone(bool recover, const MTPauth_Authorization &result); void pwdSubmitDone(bool recover, const MTPauth_Authorization &result);
bool pwdSubmitFail(const RPCError &error); bool pwdSubmitFail(const RPCError &error);
bool codeSubmitFail(const RPCError &error); bool codeSubmitFail(const RPCError &error);
@ -68,16 +69,16 @@ private:
bool _hasRecovery; bool _hasRecovery;
QString _hint, _emailPattern; QString _hint, _emailPattern;
ChildWidget<Ui::PasswordInput> _pwdField; object_ptr<Ui::PasswordInput> _pwdField;
ChildWidget<Ui::FlatLabel> _pwdHint; object_ptr<Ui::FlatLabel> _pwdHint;
ChildWidget<Ui::InputField> _codeField; object_ptr<Ui::InputField> _codeField;
ChildWidget<Ui::LinkButton> _toRecover; object_ptr<Ui::LinkButton> _toRecover;
ChildWidget<Ui::LinkButton> _toPassword; object_ptr<Ui::LinkButton> _toPassword;
mtpRequestId _sentRequest = 0; mtpRequestId _sentRequest = 0;
QByteArray _pwdSalt; QByteArray _pwdSalt;
ChildObject<QTimer> _checkRequest; object_ptr<QTimer> _checkRequest;
}; };

View file

@ -81,9 +81,8 @@ void SignupWidget::notifyFileQueryUpdated(const FileDialog::QueryUpdate &update)
showError(lang(lng_bad_photo)); showError(lang(lng_bad_photo));
return; return;
} }
auto box = new PhotoCropBox(img, PeerId(0)); auto box = Ui::show(Box<PhotoCropBox>(img, PeerId(0)));
connect(box, SIGNAL(ready(const QImage &)), this, SLOT(onPhotoReady(const QImage &))); connect(box, SIGNAL(ready(const QImage&)), this, SLOT(onPhotoReady(const QImage&)));
Ui::showLayer(box);
} }
void SignupWidget::resizeEvent(QResizeEvent *e) { void SignupWidget::resizeEvent(QResizeEvent *e) {

View file

@ -61,9 +61,9 @@ private:
QImage _photoImage; QImage _photoImage;
ChildWidget<Ui::NewAvatarButton> _photo; object_ptr<Ui::NewAvatarButton> _photo;
ChildWidget<Ui::InputField> _first; object_ptr<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last; object_ptr<Ui::InputField> _last;
QString _firstName, _lastName; QString _firstName, _lastName;
mtpRequestId _sentRequest = 0; mtpRequestId _sentRequest = 0;
@ -71,7 +71,7 @@ private:
bool _invertOrder = false; bool _invertOrder = false;
ChildObject<QTimer> _checkRequest; object_ptr<QTimer> _checkRequest;
}; };

View file

@ -47,8 +47,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Intro { namespace Intro {
Widget::Widget(QWidget *parent) : TWidget(parent) Widget::Widget(QWidget *parent) : TWidget(parent)
, _back(this, new Ui::IconButton(this, st::introBackButton), base::lambda<void()>(), st::introSlideDuration) , _back(this, object_ptr<Ui::IconButton>(this, st::introBackButton), st::introSlideDuration)
, _settings(this, new Ui::RoundButton(this, lang(lng_menu_settings), st::defaultBoxButton), base::lambda<void()>(), st::introCoverDuration) , _settings(this, object_ptr<Ui::RoundButton>(this, lang(lng_menu_settings), st::defaultBoxButton), st::introCoverDuration)
, _next(this, QString(), st::introNextButton) { , _next(this, QString(), st::introNextButton) {
getData()->country = psCurrentCountry(); getData()->country = psCurrentCountry();
@ -65,12 +65,12 @@ Widget::Widget(QWidget *parent) : TWidget(parent)
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[systemLangId].c_str() + qsl(".strings"), langLoaderRequest(lng_switch_to_this)); LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[systemLangId].c_str() + qsl(".strings"), langLoaderRequest(lng_switch_to_this));
QString text = loader.found().value(lng_switch_to_this); QString text = loader.found().value(lng_switch_to_this);
if (!text.isEmpty()) { if (!text.isEmpty()) {
_changeLanguage.create(this, new Ui::LinkButton(this, text), base::lambda<void()>(), st::introCoverDuration); _changeLanguage.create(this, object_ptr<Ui::LinkButton>(this, text), st::introCoverDuration);
_changeLanguage->entity()->setClickedCallback([this, systemLangId] { changeLanguage(systemLangId); }); _changeLanguage->entity()->setClickedCallback([this, systemLangId] { changeLanguage(systemLangId); });
} }
} }
} else { } else {
_changeLanguage.create(this, new Ui::LinkButton(this, langOriginal(lng_switch_to_this)), base::lambda<void()>(), st::introCoverDuration); _changeLanguage.create(this, object_ptr<Ui::LinkButton>(this, langOriginal(lng_switch_to_this)), st::introCoverDuration);
_changeLanguage->entity()->setClickedCallback([this] { changeLanguage(languageDefault); }); _changeLanguage->entity()->setClickedCallback([this] { changeLanguage(languageDefault); });
} }
@ -98,7 +98,7 @@ Widget::Widget(QWidget *parent) : TWidget(parent)
void Widget::onCheckUpdateStatus() { void Widget::onCheckUpdateStatus() {
if (Sandbox::updatingState() == Application::UpdatingReady) { if (Sandbox::updatingState() == Application::UpdatingReady) {
if (_update) return; if (_update) return;
_update.create(this, new Ui::RoundButton(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton), base::lambda<void()>(), st::introCoverDuration); _update.create(this, object_ptr<Ui::RoundButton>(this, lang(lng_menu_update).toUpper(), st::defaultBoxButton), st::introCoverDuration);
if (!_a_show.animating()) _update->show(); if (!_a_show.animating()) _update->show();
_update->entity()->setClickedCallback([] { _update->entity()->setClickedCallback([] {
checkReadyUpdate(); checkReadyUpdate();
@ -152,21 +152,21 @@ void Widget::historyMove(Direction direction) {
delete base::take(wasStep); delete base::take(wasStep);
} }
if (getStep()->hasBack()) { if (getStep()->hasBack()) {
_back->fadeIn(); _back->showAnimated();
} else { } else {
_back->fadeOut(); _back->hideAnimated();
} }
if (getStep()->hasCover()) { if (getStep()->hasCover()) {
_settings->fadeOut(); _settings->hideAnimated();
if (_update) _update->fadeOut(); if (_update) _update->hideAnimated();
if (_changeLanguage) _changeLanguage->fadeIn(); if (_changeLanguage) _changeLanguage->showAnimated();
} else { } else {
_settings->fadeIn(); _settings->showAnimated();
if (_update) _update->fadeIn(); if (_update) _update->showAnimated();
if (_changeLanguage) _changeLanguage->fadeOut(); if (_changeLanguage) _changeLanguage->hideAnimated();
} }
_next->setText(getStep()->nextButtonText()); _next->setText(getStep()->nextButtonText());
if (_resetAccount) _resetAccount->fadeOut(); if (_resetAccount) _resetAccount->hideAnimated();
getStep()->showAnimated(direction); getStep()->showAnimated(direction);
fixOrder(); fixOrder();
} }
@ -206,25 +206,22 @@ void Widget::appendStep(Step *step) {
void Widget::showResetButton() { void Widget::showResetButton() {
if (!_resetAccount) { if (!_resetAccount) {
_resetAccount.create(this, new Ui::RoundButton(this, lang(lng_signin_reset_account), st::introResetButton), base::lambda<void()>(), st::introErrorDuration); auto entity = object_ptr<Ui::RoundButton>(this, lang(lng_signin_reset_account), st::introResetButton);
_resetAccount.create(this, std_::move(entity), st::introErrorDuration);
_resetAccount->hideFast(); _resetAccount->hideFast();
_resetAccount->entity()->setClickedCallback([this] { resetAccount(); }); _resetAccount->entity()->setClickedCallback([this] { resetAccount(); });
updateControlsGeometry(); updateControlsGeometry();
} }
_resetAccount->fadeIn(); _resetAccount->showAnimated();
} }
void Widget::resetAccount() { void Widget::resetAccount() {
if (_resetRequest) return; if (_resetRequest) return;
auto box = new ConfirmBox(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton); Ui::show(Box<ConfirmBox>(lang(lng_signin_sure_reset), lang(lng_signin_reset), st::attentionBoxButton, base::lambda_guarded(this, [this] {
box->setConfirmedCallback([this] { resetAccountSure(); }); if (_resetRequest) return;
Ui::showLayer(box); _resetRequest = MTP::send(MTPaccount_DeleteAccount(MTP_string("Forgot password")), rpcDone(&Widget::resetDone), rpcFail(&Widget::resetFail));
} })));
void Widget::resetAccountSure() {
if (_resetRequest) return;
_resetRequest = MTP::send(MTPaccount_DeleteAccount(MTP_string("Forgot password")), rpcDone(&Widget::resetDone), rpcFail(&Widget::resetFail));
} }
void Widget::resetDone(const MTPBool &result) { void Widget::resetDone(const MTPBool &result) {
@ -251,9 +248,9 @@ bool Widget::resetFail(const RPCError &error) {
} else { } else {
when = lng_signin_reset_in_minutes(lt_count_minutes, minutes); when = lng_signin_reset_in_minutes(lt_count_minutes, minutes);
} }
Ui::showLayer(new InformBox(lng_signin_reset_wait(lt_phone_number, App::formatPhone(getData()->phone), lt_when, when))); Ui::show(Box<InformBox>(lng_signin_reset_wait(lt_phone_number, App::formatPhone(getData()->phone), lt_when, when)));
} else if (type == qstr("2FA_RECENT_CONFIRM")) { } else if (type == qstr("2FA_RECENT_CONFIRM")) {
Ui::showLayer(new InformBox(lang(lng_signin_reset_cancelled))); Ui::show(Box<InformBox>(lang(lng_signin_reset_cancelled)));
} else { } else {
Ui::hideLayer(); Ui::hideLayer();
getStep()->showError(lang(lng_server_error)); getStep()->showError(lang(lng_server_error));
@ -544,11 +541,11 @@ void Widget::Step::fillSentCodeData(const MTPauth_SentCodeType &type) {
} }
void Widget::Step::showDescription() { void Widget::Step::showDescription() {
_description->fadeIn(); _description->showAnimated();
} }
void Widget::Step::hideDescription() { void Widget::Step::hideDescription() {
_description->fadeOut(); _description->hideAnimated();
} }
void Widget::Step::paintContentSnapshot(Painter &p, const QPixmap &snapshot, float64 alpha, float64 howMuchHidden) { void Widget::Step::paintContentSnapshot(Painter &p, const QPixmap &snapshot, float64 alpha, float64 howMuchHidden) {
@ -647,16 +644,16 @@ void Widget::Step::setErrorBelowLink(bool below) {
void Widget::Step::showError(const QString &text) { void Widget::Step::showError(const QString &text) {
_errorText = text; _errorText = text;
if (_errorText.isEmpty()) { if (_errorText.isEmpty()) {
if (_error) _error->fadeOut(); if (_error) _error->hideAnimated();
} else { } else {
if (!_error) { if (!_error) {
auto &st = _errorCentered ? st::introErrorCentered : st::introError; auto &st = _errorCentered ? st::introErrorCentered : st::introError;
_error.create(this, new Ui::FlatLabel(this, st, st::introErrorTextStyle), base::lambda<void()>(), st::introErrorDuration); _error.create(this, object_ptr<Ui::FlatLabel>(this, st, st::introErrorTextStyle), st::introErrorDuration);
_error->hideFast(); _error->hideFast();
} }
_error->entity()->setText(text); _error->entity()->setText(text);
updateLabelsPosition(); updateLabelsPosition();
_error->fadeIn(); _error->showAnimated();
} }
} }
@ -664,7 +661,7 @@ Widget::Step::Step(QWidget *parent, Data *data, bool hasCover) : TWidget(parent)
, _data(data) , _data(data)
, _hasCover(hasCover) , _hasCover(hasCover)
, _title(this, _hasCover ? st::introCoverTitle : st::introTitle, st::defaultTextStyle) , _title(this, _hasCover ? st::introCoverTitle : st::introTitle, st::defaultTextStyle)
, _description(this, new Ui::FlatLabel(this, _hasCover ? st::introCoverDescription : st::introDescription, _hasCover ? st::introCoverDescriptionTextStyle : st::introDescriptionTextStyle), base::lambda<void()>(), st::introErrorDuration) { , _description(this, object_ptr<Ui::FlatLabel>(this, _hasCover ? st::introCoverDescription : st::introDescription, _hasCover ? st::introCoverDescriptionTextStyle : st::introDescriptionTextStyle), st::introErrorDuration) {
hide(); hide();
} }

View file

@ -190,13 +190,13 @@ public:
base::lambda<void(Step *step, Direction direction)> _goCallback; base::lambda<void(Step *step, Direction direction)> _goCallback;
base::lambda<void()> _showResetCallback; base::lambda<void()> _showResetCallback;
ChildWidget<Ui::FlatLabel> _title; object_ptr<Ui::FlatLabel> _title;
ChildWidget<Ui::WidgetFadeWrap<Ui::FlatLabel>> _description; object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _description;
bool _errorCentered = false; bool _errorCentered = false;
bool _errorBelowLink = false; bool _errorBelowLink = false;
QString _errorText; QString _errorText;
ChildWidget<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = { nullptr }; object_ptr<Ui::WidgetFadeWrap<Ui::FlatLabel>> _error = { nullptr };
Animation _a_show; Animation _a_show;
CoverAnimation _coverAnimation; CoverAnimation _coverAnimation;
@ -222,7 +222,6 @@ private:
void showResetButton(); void showResetButton();
void resetAccount(); void resetAccount();
void resetAccountSure();
void resetDone(const MTPBool &result); void resetDone(const MTPBool &result);
bool resetFail(const RPCError &error); bool resetFail(const RPCError &error);
@ -247,13 +246,13 @@ private:
int _nextTopFrom = 0; int _nextTopFrom = 0;
int _controlsTopFrom = 0; int _controlsTopFrom = 0;
ChildWidget<Ui::WidgetFadeWrap<Ui::IconButton>> _back; object_ptr<Ui::WidgetFadeWrap<Ui::IconButton>> _back;
ChildWidget<Ui::WidgetFadeWrap<Ui::RoundButton>> _update = { nullptr }; object_ptr<Ui::WidgetFadeWrap<Ui::RoundButton>> _update = { nullptr };
ChildWidget<Ui::WidgetFadeWrap<Ui::RoundButton>> _settings; object_ptr<Ui::WidgetFadeWrap<Ui::RoundButton>> _settings;
ChildWidget<Ui::RoundButton> _next; object_ptr<Ui::RoundButton> _next;
ChildWidget<Ui::WidgetFadeWrap<Ui::LinkButton>> _changeLanguage = { nullptr }; object_ptr<Ui::WidgetFadeWrap<Ui::LinkButton>> _changeLanguage = { nullptr };
ChildWidget<Ui::WidgetFadeWrap<Ui::RoundButton>> _resetAccount = { nullptr }; object_ptr<Ui::WidgetFadeWrap<Ui::RoundButton>> _resetAccount = { nullptr };
mtpRequestId _resetRequest = 0; mtpRequestId _resetRequest = 0;

Some files were not shown because too many files have changed in this diff Show more