From fe9a1bc947468de3cdce12519c0ca8d65a19fbb4 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Mon, 12 Oct 2015 23:02:10 +0200
Subject: [PATCH] boxes redesign finished

---
 Telegram/Resources/lang.strings              |  33 +--
 Telegram/Resources/style.txt                 |  86 +++----
 Telegram/SourceFiles/apiwrap.cpp             |   1 +
 Telegram/SourceFiles/boxes/aboutbox.cpp      |  70 +++--
 Telegram/SourceFiles/boxes/aboutbox.h        |  13 +-
 Telegram/SourceFiles/boxes/abstractbox.cpp   |   4 +-
 Telegram/SourceFiles/boxes/addcontactbox.cpp |   8 +-
 Telegram/SourceFiles/boxes/confirmbox.cpp    |   2 +-
 Telegram/SourceFiles/boxes/contactsbox.cpp   |   4 +-
 Telegram/SourceFiles/boxes/passcodebox.cpp   | 254 +++++++++++--------
 Telegram/SourceFiles/boxes/passcodebox.h     |   4 +-
 Telegram/SourceFiles/boxes/sessionsbox.cpp   | 205 ++++++++-------
 Telegram/SourceFiles/boxes/sessionsbox.h     |  26 +-
 Telegram/SourceFiles/boxes/stickersetbox.cpp |  22 +-
 Telegram/SourceFiles/boxes/stickersetbox.h   |   2 +-
 Telegram/SourceFiles/boxes/usernamebox.cpp   |   2 +-
 Telegram/SourceFiles/gui/flatbutton.cpp      |  12 -
 Telegram/SourceFiles/gui/flatbutton.h        |   8 -
 Telegram/SourceFiles/gui/scrollarea.cpp      |   2 +-
 Telegram/SourceFiles/gui/twidget.cpp         |   9 +-
 Telegram/SourceFiles/historywidget.cpp       |   9 +-
 Telegram/SourceFiles/mainwidget.cpp          |   4 +-
 Telegram/SourceFiles/overviewwidget.cpp      |  16 +-
 Telegram/SourceFiles/passcodewidget.cpp      |   4 +-
 Telegram/SourceFiles/profilewidget.cpp       |  15 +-
 Telegram/SourceFiles/settingswidget.cpp      |  12 +-
 Telegram/SourceFiles/structs.h               |   7 +-
 27 files changed, 445 insertions(+), 389 deletions(-)

diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings
index 0b8de3353..b454398c0 100644
--- a/Telegram/Resources/lang.strings
+++ b/Telegram/Resources/lang.strings
@@ -138,7 +138,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 
 "lng_bad_phone" = "Invalid phone number. Please try again.";
 "lng_bad_phone_noreg" = "Phone number not registered.";
-"lng_bad_code" = "You have entered an invalid code. Please try again.";
+"lng_bad_code" = "You have entered an invalid code.";
 "lng_bad_name" = "Please enter your first and last name.";
 "lng_bad_photo" = "Bad image selected.";
 
@@ -150,16 +150,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 "lng_signin_password" = "Your cloud password";
 "lng_signin_code" = "Code from e-mail";
 "lng_signin_recover" = "Forgot password?";
+"lng_signin_recover_title" = "Password reset";
 "lng_signin_hint" = "Hint: {password_hint}";
 "lng_signin_recover_hint" = "Code was sent to {recover_email}";
 "lng_signin_bad_password" = "You have entered a wrong password.";
-"lng_signin_wrong_code" = "You have entered an invalid code. Please try again.";
+"lng_signin_wrong_code" = "You have entered an invalid code.";
 "lng_signin_try_password" = "Having trouble accessing your e-mail?";
 "lng_signin_password_removed" = "Your cloud password was disabled.\nYou can set a new one in Settings.";
 "lng_signin_no_email_forgot" = "Since you haven't provided a recovery\ne-mail when setting up your password, your remaining options are either to remember your password or to reset your account.";
 "lng_signin_cant_email_forgot" = "If you can't restore access to the e-mail, your remaining options are either to remember your password or to reset your account.";
 "lng_signin_reset_account" = "Reset your account";
-"lng_signin_sure_reset" = "Warning!\n\nYou will lose all your chats and messages,\nalong with any media and files you shared!\n\nDo you want to reset your account?";
+"lng_signin_sure_reset" = "Warning!\n\nYou will lose all your chats and messages, along with any media and files you shared!\n\nDo you want to reset your account?";
 "lng_signin_reset" = "Reset";
 
 "lng_signup_title" = "Information and photo";
@@ -280,7 +281,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 
 "lng_passcode_turn_on" = "Turn on local passcode";
 "lng_passcode_change" = "Change local passcode";
-"lng_passcode_create" = "Create local passcode";
+"lng_passcode_create" = "Local passcode";
 "lng_passcode_remove" = "Remove local passcode";
 "lng_passcode_turn_off" = "Turn off";
 "lng_passcode_autolock" = "Auto-Lock";
@@ -288,11 +289,11 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 "lng_passcode_autolock_inactive" = "Auto-Lock if inactive for:";
 "lng_passcode_autolock_minutes" = "{count:_not_used_|# minute|# minutes}";
 "lng_passcode_autolock_hours" = "{count:_not_used_|# hour|# hours}";
-"lng_passcode_enter_old" = "Enter old passcode";
+"lng_passcode_enter_old" = "Enter current passcode";
 "lng_passcode_enter_first" = "Enter a passcode";
 "lng_passcode_enter_new" = "Enter new passcode";
 "lng_passcode_confirm_new" = "Re-enter new passcode";
-"lng_passcode_about" = "When a local passcode is set, a lock icon appears in the top menu. Click it to lock the app.\n\nNote: if you forget your local passcode, you'll need to relogin in Telegram Desktop.";
+"lng_passcode_about" = "When a local passcode is set, a lock icon appears in the top right corner of the window. Click it to lock the app.\n\nNote: if you forget your local passcode, you'll need to relogin in Telegram Desktop.";
 "lng_passcode_differ" = "Passcodes are different";
 "lng_passcode_wrong" = "Wrong passcode";
 "lng_passcode_is_same" = "Passcode was not changed";
@@ -302,22 +303,23 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 
 "lng_cloud_password_waiting" = "Confirmation link sent to {email}..";
 "lng_cloud_password_change" = "Change cloud password";
-"lng_cloud_password_create" = "Create cloud password";
+"lng_cloud_password_create" = "Cloud password";
 "lng_cloud_password_remove" = "Remove cloud password";
 "lng_cloud_password_set" = "Enable two-step verification";
 "lng_cloud_password_edit" = "Change cloud password";
-"lng_cloud_password_enter_old" = "Enter old password";
+"lng_cloud_password_enter_old" = "Enter current password";
 "lng_cloud_password_enter_first" = "Enter a password";
 "lng_cloud_password_enter_new" = "Enter new password";
 "lng_cloud_password_confirm_new" = "Re-enter new password";
 "lng_cloud_password_hint" = "Enter password hint";
+"lng_cloud_password_change_hint" = "Enter new password hint";
 "lng_cloud_password_bad" = "Password and hint cannot be the same.";
 "lng_cloud_password_email" = "Enter recovery e-mail";
 "lng_cloud_password_bad_email" = "Incorrect e-mail, please try other.";
-"lng_cloud_password_about" = "This password will be required when you log in on a new device in addition to the pin code.";
+"lng_cloud_password_about" = "This password will be asked when you log in on a new device in addition to the pin code.";
 "lng_cloud_password_about_recover" = "Warning! Are you sure you don't want to\nadd a password recovery e-mail?\n\nIf you forget your password, you will\nlose access to your Telegram account.";
 "lng_cloud_password_skip_email" = "Skip e-mail";
-"lng_cloud_password_almost" = "A confirmation link was sent to the e-mail you provided. Two-step verification will be enabled as soon as you follow that link.";
+"lng_cloud_password_almost" = "A confirmation link was sent to the\ne-mail you provided. Two-step verification will be enabled as soon as you follow that link.";
 "lng_cloud_password_was_set" = "Two-step verification enabled.";
 "lng_cloud_password_updated" = "Your cloud password was updated.";
 "lng_cloud_password_removed" = "Two-step verification was disabled.";
@@ -361,8 +363,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 "lng_sessions_header" = "Current session";
 "lng_sessions_other_header" = "Active sessions";
 "lng_sessions_no_other" = "No other sessions";
-"lng_sessions_other_desc" = "You can log in to Telegram from other\nmobile, tablet and desktop devices, using\nthe same phone number. All your data\nwill be instantly synchronized.";
-"lng_sessions_terminate_all" = "Terminate all";
+"lng_sessions_other_desc" = "You can log in to Telegram from other mobile, tablet and desktop devices, using the same phone number. All your data will be instantly synchronized.";
+"lng_sessions_terminate_all" = "Terminate all other sessions";
 
 "lng_preview_loading" = "Getting Link Info..";
 
@@ -693,7 +695,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 "lng_contacts_header" = "Contacts";
 "lng_contact_not_joined" = "Unfortunately {name} did not join Telegram yet, but you can send your friend an invitation.\n\nWe will notify you about any of your contacts who is joining Telegram.";
 "lng_try_other_contact" = "Try other";
-"lng_contacts_done" = "Close";
 "lng_create_group_link" = "Link";
 "lng_create_group_invite_link" = "Invite link";
 "lng_create_group_photo" = "Set Photo";
@@ -717,8 +718,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 "lng_box_delete" = "Delete";
 "lng_box_leave" = "Leave";
 
-"lng_about_version" = "Version {version}";
-"lng_about_text" = "Official free messaging app based on [a href=\"https://core.telegram.org/mtproto\"]MTProto[/a] and\n[a href=\"https://core.telegram.org/api\"]Telegram API[/a] for speed and security\n\nThis software is licensed under [a href=\"https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\"]GNU GPL[/a] version 3,\nsource code is available on [a href=\"https://github.com/telegramdesktop/tdesktop\"]GitHub[/a].";
+"lng_about_version" = "version {version}";
+"lng_about_text_1" = "Official free messaging app based on [a href=\"https://core.telegram.org/api\"]Telegram API[/a]\nfor speed and security";
+"lng_about_text_2" = "This software is licensed under [a href=\"https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\"]GNU GPL[/a] version 3.\nSource code is available on [a href=\"https://github.com/telegramdesktop/tdesktop\"]GitHub[/a].";
+"lng_about_text_3" = "Visit {faq_open}Telegram FAQ{faq_close} for more info.";
 "lng_about_done" = "Done";
 
 "lng_search_found_results" = "{count:No messages found|Found # message|Found # messages}";
diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index c0f4862b2..dcdbc631f 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -115,6 +115,11 @@ defaultBoxLinkButton: linkButton {
 	font: boxTextFont;
 	overFont: font(boxFontSize underline);
 }
+redBoxLinkButton: linkButton(defaultBoxLinkButton) {
+	color: #d15948;
+	overColor: #d15948;
+	downColor: #db6352;
+}
 
 defaultInputArea: InputArea {
 	textFg: black;
@@ -142,7 +147,7 @@ defaultInputArea: InputArea {
 }
 defaultInputField: InputField {
 	textFg: black;
-	textMargins: margins(5px, 5px, 5px, 5px);
+	textMargins: margins(0px, 6px, 0px, 4px);
 	textAlign: align(topleft);
 
 	placeholderFg: #999;
@@ -254,6 +259,8 @@ boxSearchField: InputField(defaultInputField) {
 
 	iconSprite: sprite(227px, 21px, 24px, 24px);
 	iconPosition: point(15px, 14px);
+
+	font: normalFont;
 }
 boxSearchCancel: iconedButton {
 	color: white;
@@ -1576,9 +1583,6 @@ newGroupPadding: margins(4px, 6px, 4px, 3px);
 newGroupSkip: 17px;
 newGroupInfoPadding: margins(0px, -4px, 0px, 1px);
 
-newGroupLink: InputField(defaultInputField) {
-	textMargins: margins(0px, 6px, 0px, 0px);
-}
 newGroupLinkPadding: margins(4px, 27px, 4px, 12px);
 newGroupLinkTop: 3px;
 newGroupLinkFont: font(16px);
@@ -1590,9 +1594,6 @@ newGroupPhotoIcon: sprite(74px, 104px, 30px, 27px);
 newGroupPhotoIconPosition: point(23px, 25px);
 
 newGroupNamePosition: point(27px, 20px);
-newGroupName: InputField(defaultInputField) {
-	textMargins: margins(1px, 6px, 1px, 0px);
-}
 
 newGroupDescriptionPadding: margins(0px, 23px, 0px, 14px);
 newGroupDescription: InputArea(defaultInputArea) {
@@ -1627,49 +1628,22 @@ contactsAdd: flatButton(topBarButton) {
 }
 
 aboutIcon: sprite(0px, 0px, 104px, 104px);
-aboutIconTop: 28px;
-aboutWidth: 448px;
-aboutHeight: 441px;
-aboutHeaderFont: font(24px semibold);
-aboutSubheaderFont: font(24px);
-aboutHeaderTop: 139px;
-aboutVersion: flatLabel(labelDefFlat) {
-	font: font(16px);
-	width: aboutWidth;
-	align: align(center);
+aboutWidth: 390px;
+aboutVersionTop: -3px;
+aboutVersionLink: linkButton(btnDefLink) {
+	color: #999;
+	overColor: #999;
+	downColor: #999;
 }
-aboutVersionTop: 178px;
-aboutTextFont: font(15px);
-aboutTextTop: 221px;
+aboutTextTop: 34px;
+aboutSkip: 14px;
 aboutLabel: flatLabel(labelDefFlat) {
-	font: aboutTextFont;
-	width: aboutWidth;
-	align: align(center);
+	font: normalFont;
+	width: 330px;
+	align: align(topleft);
 }
 aboutTextStyle: textStyle(defaultTextStyle) {
-	lineHeight: 24px;
-}
-aboutCloseButton: flatButton {
-	color: btnYesColor;
-	overColor: btnYesHover;
-	downColor: btnYesHover;
-
-	bgColor: white;
-	overBgColor: white;
-	downBgColor: white;
-
-	width: aboutWidth;
-	height: 52px;
-
-	textTop: 15px;
-	overTextTop: 15px;
-	downTextTop: 16px;
-
-	font: font(16px);
-	overFont: font(16px);
-}
-btnInfoClose: flatButton(aboutCloseButton) {
-	width: boxWideWidth;
+	lineHeight: 22px;
 }
 
 emojiTextFont: font(15px);
@@ -2116,9 +2090,6 @@ usernameSkip: 49px;
 usernameTextStyle: textStyle(defaultTextStyle) {
 	lineHeight: 20px;
 }
-usernameField: InputField(defaultInputField) {
-	textMargins: margins(0px, 6px, 0px, 4px);
-}
 usernameDefaultFg: #777;
 
 youtubeIcon: sprite(336px, 221px, 60px, 60px);
@@ -2144,7 +2115,6 @@ backgroundScroll: flatScroll(boxScroll) {
 
 passcodeHeaderFont: font(19px);
 passcodeHeaderHeight: 80px;
-passcodeSkip: 40px;
 passcodeInput: flatInput(inpIntroPhone) {
 }
 passcodeSubmit: flatButton(btnIntroNext) {
@@ -2155,6 +2125,9 @@ passcodeSubmit: flatButton(btnIntroNext) {
 	font: font(19px);
 	overFont: font(19px);
 }
+passcodeSubmitSkip: 40px;
+passcodePadding: margins(0px, 22px, 0px, 3px);
+passcodeSkip: 31px;
 
 mentionHeight: 40px;
 mentionScroll: flatScroll(scrollDef) {
@@ -2171,19 +2144,22 @@ mentionFgOver: #707070;
 mentionFgActive: #0080c0;
 mentionFgOverActive: #0077b3;
 
+sessionsScroll: flatScroll(boxScroll) {
+	deltax: 5px;
+	width: 14px;
+}
 sessionsHeight: 440px;
 sessionHeight: 70px;
-sessionPadding: margins(20px, 10px, 20px, 0);
-sessionsCloseButton: flatButton(aboutCloseButton) {
-	width: boxWideWidth;
-}
+sessionCurrentPadding: margins(0px, 7px, 0px, 4px);
+sessionCurrentHeight: 118px;
+sessionPadding: margins(21px, 10px, 21px, 0);
 sessionNameFont: msgNameFont;
 sessionActiveFont: msgDateFont;
 sessionActiveColor: #aaa;
 sessionInfoFont: msgFont;
 sessionInfoColor: dlgTextColor;
 sessionTerminateTop: 30px;
-sessionTerminateSkip: 10px;
+sessionTerminateSkip: 18px;
 sessionTerminate: iconedButton(notifyClose) {
 	iconPos: point(3px, 3px);
 	downIconPos: point(3px, 4px);
diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 4f30a9fdd..54a54beae 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -271,6 +271,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result) {
 		const MTPDchannelFull &f(d.vfull_chat.c_channelFull());
 		PhotoData *photo = App::feedPhoto(f.vchat_photo);
 		ChannelData *channel = peer->asChannel();
+		channel->flagsFull = f.vflags.v;
 		if (photo) {
 			channel->photoId = photo->id;
 			photo->peer = channel;
diff --git a/Telegram/SourceFiles/boxes/aboutbox.cpp b/Telegram/SourceFiles/boxes/aboutbox.cpp
index 71bc8e304..11cf21899 100644
--- a/Telegram/SourceFiles/boxes/aboutbox.cpp
+++ b/Telegram/SourceFiles/boxes/aboutbox.cpp
@@ -25,36 +25,48 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 #include "mainwidget.h"
 #include "window.h"
 
-AboutBox::AboutBox() :
-_done(this, lang(lng_about_done), st::aboutCloseButton),
-_version(this, qsl("[a href=\"https://desktop.telegram.org/#changelog\"]") + textClean(lng_about_version(lt_version, QString::fromWCharArray(AppVersionStr) + (cDevVersion() ? " dev" : ""))) + qsl("[/a]"), st::aboutVersion, st::defaultTextStyle),
-_text(this, lang(lng_about_text), st::aboutLabel, st::aboutTextStyle) {
-	
-	resizeMaxHeight(st::aboutWidth, st::aboutHeight);
+AboutBox::AboutBox() : AbstractBox(st::aboutWidth)
+, _version(this, lng_about_version(lt_version, QString::fromWCharArray(AppVersionStr) + (cDevVersion() ? " dev" : "")), st::aboutVersionLink)
+, _text1(this, lang(lng_about_text_1), st::aboutLabel, st::aboutTextStyle)
+, _text2(this, lang(lng_about_text_2), st::aboutLabel, st::aboutTextStyle)
+, _text3(this, QString(), st::aboutLabel, st::aboutTextStyle)
+, _done(this, lang(lng_close), st::defaultBoxButton) {
+	_text3.setRichText(lng_about_text_3(lt_faq_open, qsl("[a href=\"%1\"]").arg(telegramFaqLink()), lt_faq_close, qsl("[/a]")));
 
-	_version.move(0, st::aboutVersionTop);
-	_text.move(0, st::aboutTextTop);
-
-	_headerWidth = st::aboutHeaderFont->width(qsl("Telegram "));
-	_subheaderWidth = st::aboutSubheaderFont->width(qsl("Desktop"));
-
-	_done.move(0, height() - _done.height());
+	setMaxHeight(st::boxTitleHeight + st::aboutTextTop + _text1.height() + st::aboutSkip + _text2.height() + st::aboutSkip + _text3.height() + st::boxButtonPadding.top() + _done.height() + st::boxButtonPadding.bottom());
 
+	connect(&_version, SIGNAL(clicked()), this, SLOT(onVersion()));
 	connect(&_done, SIGNAL(clicked()), this, SLOT(onClose()));
 
 	prepare();
 }
 
 void AboutBox::hideAll() {
-	_done.hide();
 	_version.hide();
-	_text.hide();
+	_text1.hide();
+	_text2.hide();
+	_text3.hide();
+	_done.hide();
 }
 
 void AboutBox::showAll() {
-	_done.show();
 	_version.show();
-	_text.show();
+	_text1.show();
+	_text2.show();
+	_text3.show();
+	_done.show();
+}
+
+void AboutBox::resizeEvent(QResizeEvent *e) {
+	_version.moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::aboutVersionTop);
+	_text1.moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::aboutTextTop);
+	_text2.moveToLeft(st::boxPadding.left(), _text1.y() + _text1.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());
+}
+
+void AboutBox::onVersion() {
+	QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog"));
 }
 
 void AboutBox::keyPressEvent(QKeyEvent *e) {
@@ -66,15 +78,21 @@ void AboutBox::keyPressEvent(QKeyEvent *e) {
 }
 
 void AboutBox::paintEvent(QPaintEvent *e) {
-	QPainter p(this);
+	Painter p(this);
 	if (paint(p)) return;
 
-	p.drawPixmap(QPoint((width() - st::aboutIcon.pxWidth()) / 2, st::aboutIconTop), App::sprite(), st::aboutIcon);
-
-	p.setPen(st::black->p);
-	p.setFont(st::aboutHeaderFont->f);
-	p.drawText((width() - (_headerWidth + _subheaderWidth)) / 2, st::aboutHeaderTop + st::aboutHeaderFont->ascent, qsl("Telegram"));
-
-	p.setFont(st::aboutSubheaderFont->f);
-	p.drawText((width() - (_headerWidth + _subheaderWidth)) / 2 + _headerWidth, st::aboutHeaderTop + st::aboutSubheaderFont->ascent, qsl("Desktop"));
+	paintTitle(p, qsl("Telegram Desktop"));
 }
+
+QString telegramFaqLink() {
+	QString result = qsl("https://telegram.org/faq");
+	if (cLang() > languageDefault && cLang() < languageCount) {
+		const char *code = LanguageCodes[cLang()];
+		if (qstr("de") == code || qstr("es") == code || qstr("it") == code || qstr("ko") == code) {
+			result += qsl("/") + code;
+		} else if (qstr("pt_BR") == code) {
+			result += qsl("/br");
+		}
+	}
+	return result;
+}
\ No newline at end of file
diff --git a/Telegram/SourceFiles/boxes/aboutbox.h b/Telegram/SourceFiles/boxes/aboutbox.h
index 36ab71280..533ab0323 100644
--- a/Telegram/SourceFiles/boxes/aboutbox.h
+++ b/Telegram/SourceFiles/boxes/aboutbox.h
@@ -28,9 +28,14 @@ class AboutBox : public AbstractBox {
 public:
 
 	AboutBox();
+	void resizeEvent(QResizeEvent *e);
 	void keyPressEvent(QKeyEvent *e);
 	void paintEvent(QPaintEvent *e);
 	
+public slots:
+
+	void onVersion();
+
 protected:
 
 	void hideAll();
@@ -38,7 +43,9 @@ protected:
 
 private:
 
-	BottomButton _done;
-	FlatLabel _version, _text;
-	int32 _headerWidth, _subheaderWidth;
+	LinkButton _version;
+	FlatLabel _text1, _text2, _text3;
+	BoxButton _done;
 };
+
+QString telegramFaqLink();
diff --git a/Telegram/SourceFiles/boxes/abstractbox.cpp b/Telegram/SourceFiles/boxes/abstractbox.cpp
index d7b8acf07..d2d8bdae0 100644
--- a/Telegram/SourceFiles/boxes/abstractbox.cpp
+++ b/Telegram/SourceFiles/boxes/abstractbox.cpp
@@ -179,7 +179,9 @@ void AbstractBox::resizeMaxHeight(int32 newWidth, int32 maxHeight) {
 		QRect g(geometry());
 		_maxHeight = maxHeight;
 		resize(newWidth, countHeight());
-		if (parentWidget()) parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.pxWidth(), st::boxShadow.pxHeight(), st::boxShadow.pxWidth(), st::boxShadow.pxHeight())));
+		if (parentWidget()) {
+			parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.pxWidth(), st::boxShadow.pxHeight(), st::boxShadow.pxWidth(), st::boxShadow.pxHeight())));
+		}
 	}
 }
 
diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp
index fc6a4f6a6..778fb7f60 100644
--- a/Telegram/SourceFiles/boxes/addcontactbox.cpp
+++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp
@@ -342,7 +342,7 @@ _creating(creating),
 a_photoOver(0, 0),
 _a_photoOver(animFunc(this, &GroupInfoBox::animStep_photoOver)),
 _photoOver(false),
-_title(this, st::newGroupName, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)),
+_title(this, st::defaultInputField, lang(_creating == CreatingGroupChannel ? lng_dlg_new_channel_name : lng_dlg_new_group_name)),
 _description(this, st::newGroupDescription, lang(lng_create_group_description)),
 _next(this, lang(_creating == CreatingGroupChannel ? lng_create_group_create : lng_create_group_next), st::defaultBoxButton),
 _cancel(this, lang(fromTypeChoose ? lng_create_group_back : lng_cancel), st::cancelBoxButton),
@@ -613,7 +613,7 @@ _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right()
 _aboutPublic(st::normalFont, lang(lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth),
 _aboutPrivate(st::normalFont, lang(lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth),
 _aboutComments(st::normalFont, lang(lng_create_channel_comments_about), _defaultOptions, _aboutPublicWidth),
-_link(this, st::newGroupLink, QString(), channel->username, true),
+_link(this, st::defaultInputField, 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),
@@ -700,7 +700,7 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
 
 	p.setPen(st::black);
 	p.setFont(st::newGroupLinkFont);
-	p.drawTextLeft(st::boxPadding.left() + st::newGroupPadding.left() + st::newGroupLink.textMargins.left(), _link.y() - st::newGroupLinkPadding.top() + st::newGroupLinkTop, width(), lang(_link.isHidden() ? lng_create_group_invite_link : lng_create_group_link));
+	p.drawTextLeft(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultInputField.textMargins.left(), _link.y() - st::newGroupLinkPadding.top() + st::newGroupLinkTop, width(), lang(_link.isHidden() ? lng_create_group_invite_link : lng_create_group_link));
 
 	if (_link.isHidden()) {
 		QTextOption option(style::al_left);
@@ -1155,7 +1155,7 @@ EditChannelBox::EditChannelBox(ChannelData *channel) :
 _channel(channel),
 _save(this, lang(lng_settings_save), st::defaultBoxButton),
 _cancel(this, lang(lng_cancel), st::cancelBoxButton),
-_title(this, st::newGroupName, 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),
 _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::defaultBoxLinkButton),
 _saveTitleRequestId(0), _saveDescriptionRequestId(0) {
diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp
index 8370cbe4f..637f56278 100644
--- a/Telegram/SourceFiles/boxes/confirmbox.cpp
+++ b/Telegram/SourceFiles/boxes/confirmbox.cpp
@@ -263,7 +263,7 @@ void MaxInviteBox::paintEvent(QPaintEvent *e) {
 
 	QTextOption option(style::al_left);
 	option.setWrapMode(QTextOption::WrapAnywhere);
-	p.setFont(_linkOver ? st::newGroupLink.font->underline() : st::newGroupLink.font);
+	p.setFont(_linkOver ? st::defaultInputField.font->underline() : st::defaultInputField.font);
 	p.setPen(st::btnDefLink.color);
 	p.drawText(_invitationLink, _link, option);
 	if (!_goodTextLink.isEmpty() && a_goodOpacity.current() > 0) {
diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp
index 6ce3098cd..5cecfbc61 100644
--- a/Telegram/SourceFiles/boxes/contactsbox.cpp
+++ b/Telegram/SourceFiles/boxes/contactsbox.cpp
@@ -1133,7 +1133,7 @@ ContactsBox::ContactsBox() : ItemListBox(st::contactsScroll)
 , _filter(this, st::boxSearchField, lang(lng_participant_filter))
 , _filterCancel(this, st::boxSearchCancel)
 , _next(this, lang(lng_create_group_next), st::defaultBoxButton)
-, _cancel(this, lang(lng_contacts_done), st::cancelBoxButton)
+, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
 , _topShadow(this)
 , _bottomShadow(0)
 , _creationRequestId(0) {
@@ -1171,7 +1171,7 @@ ContactsBox::ContactsBox(ChannelData *channel, MembersFilter filter, const Membe
 , _filter(this, st::boxSearchField, lang(lng_participant_filter))
 , _filterCancel(this, st::boxSearchCancel)
 , _next(this, lang(lng_participant_invite), st::defaultBoxButton)
-, _cancel(this, lang(filter == MembersFilterAdmins ? lng_contacts_done : lng_cancel), st::cancelBoxButton)
+, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
 , _topShadow(this)
 , _bottomShadow(0)
 , _creationRequestId(0) {
diff --git a/Telegram/SourceFiles/boxes/passcodebox.cpp b/Telegram/SourceFiles/boxes/passcodebox.cpp
index ca01abfb3..15cd44468 100644
--- a/Telegram/SourceFiles/boxes/passcodebox.cpp
+++ b/Telegram/SourceFiles/boxes/passcodebox.cpp
@@ -27,57 +27,74 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 
 #include "localstorage.h"
 
-PasscodeBox::PasscodeBox(bool turningOff) : _replacedBy(0), _turningOff(turningOff), _cloudPwd(false),
-_setRequest(0), _hasRecovery(false), _skipEmailWarning(false), _aboutHeight(0),
-_about(st::boxWideWidth - st::boxPadding.left() - st::boxPadding.right()),
-_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)),
-_newPasscode(this, st::defaultInputField, lang(cHasPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first)),
-_reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new)),
-_passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint)),
-_recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email)),
-_recover(this, lang(lng_signin_recover)) {
+PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth)
+, _replacedBy(0)
+, _turningOff(turningOff)
+, _cloudPwd(false)
+, _setRequest(0)
+, _hasRecovery(false)
+, _skipEmailWarning(false)
+, _aboutHeight(0)
+, _about(st::boxWidth - st::boxPadding.left() - st::boxPadding.right())
+, _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))
+, _newPasscode(this, st::defaultInputField, lang(cHasPasscode() ? lng_passcode_enter_new : lng_passcode_enter_first))
+, _reenterPasscode(this, st::defaultInputField, lang(lng_passcode_confirm_new))
+, _passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint))
+, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
+, _recover(this, lang(lng_signin_recover)) {
 	init();
 	prepare();
 }
 
-PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) : _replacedBy(0), _turningOff(turningOff), _cloudPwd(true),
-_setRequest(0), _newSalt(newSalt), _curSalt(curSalt), _hasRecovery(hasRecovery), _skipEmailWarning(false), _hint(hint), _aboutHeight(0),
-_about(st::boxWideWidth - st::boxPadding.left() - st::boxPadding.right()),
-_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)),
-_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)),
-_passwordHint(this, st::defaultInputField, lang(lng_cloud_password_hint)),
-_recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email)),
-_recover(this, lang(lng_signin_recover)) {
+PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) : AbstractBox(st::boxWidth)
+, _replacedBy(0)
+, _turningOff(turningOff)
+, _cloudPwd(true)
+, _setRequest(0)
+, _newSalt(newSalt)
+, _curSalt(curSalt)
+, _hasRecovery(hasRecovery)
+, _skipEmailWarning(false)
+, _aboutHeight(0)
+, _about(st::boxWidth - st::boxPadding.left() - st::boxPadding.right())
+, _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))
+, _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))
+, _passwordHint(this, st::defaultInputField, lang(curSalt.isEmpty() ? lng_cloud_password_hint : lng_cloud_password_change_hint))
+, _recoverEmail(this, st::defaultInputField, lang(lng_cloud_password_email))
+, _recover(this, lang(lng_signin_recover)) {
+	textstyleSet(&st::usernameTextStyle);
+	if (!hint.isEmpty()) _hintText.setText(st::normalFont, lng_signin_hint(lt_password_hint, hint));
+	textstyleRestore();
 	init();
 	prepare();
 }
 
 void PasscodeBox::init() {
+	setBlueTitle(true);
+
+	textstyleSet(&st::usernameTextStyle);
 	_about.setRichText(st::normalFont, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about));
-	if (!_hint.isEmpty()) _hintText.setText(st::normalFont, lng_signin_hint(lt_password_hint, _hint));
-	_aboutHeight = _about.countHeight(st::boxWideWidth - st::boxPadding.left() - st::boxPadding.right());
-	_oldPasscode.setEchoMode(QLineEdit::Password);
-	_newPasscode.setEchoMode(QLineEdit::Password);
-	_reenterPasscode.setEchoMode(QLineEdit::Password);
+	_aboutHeight = _about.countHeight(st::boxWidth - st::boxPadding.left() - st::boxPadding.right());
+	textstyleRestore();
 	if (_turningOff) {
 		_oldPasscode.show();
 		_boxTitle = lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove);
-		setMaxHeight(st::boxTitleHeight + st::contactPadding.top() + 1 * _oldPasscode.height() + st::usernameSkip + _aboutHeight + (_hasRecovery ? ((st::usernameSkip + _recover.height()) / 2) : 0) + st::contactPadding.bottom() + _saveButton.height());
+		setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + _oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 0) + _aboutHeight + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom());
 	} else {
 		bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
 		if (has) {
 			_oldPasscode.show();
 			_boxTitle = lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change);
-			setMaxHeight(st::boxTitleHeight + st::contactPadding.top() + 3 * _oldPasscode.height() + st::usernameSkip * 2 + 1 * st::contactSkip + (_cloudPwd ? _passwordHint.height() + st::contactSkip : 0) + _aboutHeight + (_hasRecovery ? ((st::usernameSkip + _recover.height()) / 2) : 0) + st::contactPadding.bottom() + _saveButton.height());
+			setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + _oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 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());
 		} else {
 			_oldPasscode.hide();
 			_boxTitle = lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create);
-			setMaxHeight(st::boxTitleHeight + st::contactPadding.top() + 2 * _oldPasscode.height() + st::usernameSkip + 1 * st::contactSkip + (_cloudPwd ? _passwordHint.height() + st::contactSkip : 0) + _aboutHeight + (_cloudPwd ? st::contactSkip + _recoverEmail.height() + st::usernameSkip : st::contactPadding.bottom()) + _saveButton.height());
+			setMaxHeight(st::boxTitleHeight + 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());
 		}
 	}
 
@@ -87,8 +104,15 @@ void PasscodeBox::init() {
 	connect(&_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged()));
 	connect(&_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
 	connect(&_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
+	connect(&_passwordHint, SIGNAL(changed()), this, SLOT(onNewChanged()));
 	connect(&_recoverEmail, SIGNAL(changed()), this, SLOT(onEmailChanged()));
 
+	connect(&_oldPasscode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
+	connect(&_newPasscode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
+	connect(&_reenterPasscode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
+	connect(&_passwordHint, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
+	connect(&_recoverEmail, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
+
 	connect(&_recover, SIGNAL(clicked()), this, SLOT(onRecoverByEmail()));
 }
 
@@ -101,6 +125,7 @@ void PasscodeBox::hideAll() {
 	_recover.hide();
 	_saveButton.hide();
 	_cancelButton.hide();
+	AbstractBox::hideAll();
 }
 
 void PasscodeBox::showAll() {
@@ -142,44 +167,41 @@ void PasscodeBox::showAll() {
 	}
 	_saveButton.show();
 	_cancelButton.show();
+	AbstractBox::showAll();
 }
 
-void PasscodeBox::keyPressEvent(QKeyEvent *e) {
+void PasscodeBox::onSubmit() {
 	bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
-	if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
-		if (_oldPasscode.hasFocus()) {
-			if (_turningOff) {
-				onSave();
-			} else {
-				_newPasscode.setFocus();
-			}
-		} else if (_newPasscode.hasFocus()) {
-			_reenterPasscode.setFocus();
-		} else if (_reenterPasscode.hasFocus()) {
-			if (has && _oldPasscode.text().isEmpty()) {
-				_oldPasscode.setFocus();
-				_oldPasscode.showError();
-			} else if (_newPasscode.text().isEmpty()) {
-				_newPasscode.setFocus();
-				_newPasscode.showError();
-			} else if (_reenterPasscode.text().isEmpty()) {
-				_reenterPasscode.showError();
-			} else if (!_passwordHint.isHidden()) {
-				_passwordHint.setFocus();
-			} else {
-				onSave();
-			}
-		} else if (_passwordHint.hasFocus()) {
-			if (_recoverEmail.isHidden()) {
-				onSave();
-			} else {
-				_recoverEmail.setFocus();
-			}
-		} else if (_recoverEmail.hasFocus()) {
+	if (_oldPasscode.hasFocus()) {
+		if (_turningOff) {
+			onSave();
+		} else {
+			_newPasscode.setFocus();
+		}
+	} else if (_newPasscode.hasFocus()) {
+		_reenterPasscode.setFocus();
+	} else if (_reenterPasscode.hasFocus()) {
+		if (has && _oldPasscode.text().isEmpty()) {
+			_oldPasscode.setFocus();
+			_oldPasscode.showError();
+		} else if (_newPasscode.text().isEmpty()) {
+			_newPasscode.setFocus();
+			_newPasscode.showError();
+		} else if (_reenterPasscode.text().isEmpty()) {
+			_reenterPasscode.showError();
+		} else if (!_passwordHint.isHidden()) {
+			_passwordHint.setFocus();
+		} else {
 			onSave();
 		}
-	} else {
-		AbstractBox::keyPressEvent(e);
+	} else if (_passwordHint.hasFocus()) {
+		if (_recoverEmail.isHidden()) {
+			onSave();
+		} else {
+			_recoverEmail.setFocus();
+		}
+	} else if (_recoverEmail.hasFocus()) {
+		onSave();
 	}
 }
 
@@ -189,52 +211,58 @@ void PasscodeBox::paintEvent(QPaintEvent *e) {
 
 	paintTitle(p, _boxTitle);
 
+	textstyleSet(&st::usernameTextStyle);
+
 	int32 w = width() - st::boxPadding.left() - st::boxPadding.right();
-	int32 abouty = (_passwordHint.isHidden() ? (_reenterPasscode.isHidden() ? _oldPasscode : _reenterPasscode).y() + st::usernameSkip : _passwordHint.y() + st::contactSkip) + _oldPasscode.height();
+	int32 abouty = (_passwordHint.isHidden() ? (_reenterPasscode.isHidden() ? (_oldPasscode.y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeSkip : 0)) : _reenterPasscode.y()) + st::passcodeSkip : _passwordHint.y() + st::contactSkip) + _oldPasscode.height();
 	p.setPen(st::black);
 	_about.draw(p, st::boxPadding.left(), abouty, w);
 
-	if (!_hint.isEmpty() && _oldError.isEmpty()) {
+	if (!_hintText.isEmpty() && _oldError.isEmpty()) {
 		p.setPen(st::black->p);
-		_hintText.drawElided(p, st::boxPadding.left(), _oldPasscode.y() + _oldPasscode.height() + ((st::usernameSkip - st::normalFont->height) / 2), w, 1, style::al_top);
+		_hintText.drawElided(p, st::boxPadding.left(), _oldPasscode.y() + _oldPasscode.height() + ((st::passcodeSkip - st::normalFont->height) / 2), w, 1, style::al_topleft);
 	}
 
 	if (!_oldError.isEmpty()) {
 		p.setPen(st::setErrColor->p);
-		p.drawText(QRect(0, _oldPasscode.y() + _oldPasscode.height(), width(), st::usernameSkip), _oldError, style::al_center);
+		p.drawText(QRect(st::boxPadding.left(), _oldPasscode.y() + _oldPasscode.height(), width() - st::boxPadding.left() - st::boxPadding.right(), st::passcodeSkip), _oldError, style::al_left);
 	}
 
 	if (!_newError.isEmpty()) {
 		p.setPen(st::setErrColor->p);
-		p.drawText(QRect(0, _reenterPasscode.y() + _reenterPasscode.height(), width(), st::usernameSkip), _newError, style::al_center);
+		p.drawText(QRect(st::boxPadding.left(), _reenterPasscode.y() + _reenterPasscode.height(), width() - st::boxPadding.left() - st::boxPadding.right(), st::passcodeSkip), _newError, style::al_left);
 	}
 
 	if (!_emailError.isEmpty()) {
 		p.setPen(st::setErrColor->p);
-		p.drawText(QRect(0, _recoverEmail.y() + _recoverEmail.height(), width(), st::usernameSkip), _emailError, style::al_center);
+		p.drawText(QRect(st::boxPadding.left(), _recoverEmail.y() + _recoverEmail.height(), width() - st::boxPadding.left() - st::boxPadding.right(), st::passcodeSkip), _emailError, style::al_left);
 	}
+
+	textstyleRestore();
 }
 
 void PasscodeBox::resizeEvent(QResizeEvent *e) {
 	bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode();
-	_oldPasscode.setGeometry(st::boxPadding.left(), st::boxTitleHeight + st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), _oldPasscode.height());
-	_newPasscode.setGeometry(st::boxPadding.left(), _oldPasscode.y() + ((_turningOff || has) ? (_oldPasscode.height() + st::usernameSkip) : 0), _oldPasscode.width(), _oldPasscode.height());
-	_reenterPasscode.setGeometry(st::boxPadding.left(), _newPasscode.y() + _newPasscode.height() + st::contactSkip, _newPasscode.width(), _newPasscode.height());
-	_passwordHint.setGeometry(st::boxPadding.left(), _reenterPasscode.y() + _reenterPasscode.height() + st::usernameSkip, _reenterPasscode.width(), _reenterPasscode.height());
-
-	_recoverEmail.setGeometry(st::boxPadding.left(), _passwordHint.y() + _passwordHint.height() + st::contactSkip + _aboutHeight + st::contactSkip, _passwordHint.width(), _passwordHint.height());
+	int32 w = width() - st::boxPadding.left() - st::boxPadding.right();
+	_oldPasscode.resize(w, _oldPasscode.height());
+	_oldPasscode.moveToLeft(st::boxPadding.left(), st::boxTitleHeight + st::passcodePadding.top());
+	_newPasscode.resize(w, _newPasscode.height());
+	_newPasscode.moveToLeft(st::boxPadding.left(), _oldPasscode.y() + ((_turningOff || has) ? (_oldPasscode.height() + st::passcodeSkip + ((_hasRecovery && !_hintText.isEmpty()) ? st::passcodeSkip : 0)) : 0));
+	_reenterPasscode.resize(w, _reenterPasscode.height());
+	_reenterPasscode.moveToLeft(st::boxPadding.left(), _newPasscode.y() + _newPasscode.height() + st::contactSkip);
+	_passwordHint.resize(w, _passwordHint.height());
+	_passwordHint.moveToLeft(st::boxPadding.left(), _reenterPasscode.y() + _reenterPasscode.height() + st::passcodeSkip);
+	_recoverEmail.resize(w, _passwordHint.height());
+	_recoverEmail.moveToLeft(st::boxPadding.left(), _passwordHint.y() + _passwordHint.height() + st::contactSkip + _aboutHeight + st::contactSkip);
 
 	if (!_recover.isHidden()) {
-		if (_turningOff) {
-			_recover.move((width() - _recover.width()) / 2, _oldPasscode.y() + _oldPasscode.height() + st::usernameSkip + _aboutHeight + ((st::usernameSkip - _recover.height()) / 2));
-		} else {
-			_recover.move((width() - _recover.width()) / 2, _passwordHint.y() + _passwordHint.height() + st::contactSkip + _aboutHeight + ((st::usernameSkip - _recover.height()) / 2));
-		}
+		_recover.moveToLeft(st::boxPadding.left(), _oldPasscode.y() + _oldPasscode.height() + (_hintText.isEmpty() ? ((st::passcodeSkip - _recover.height()) / 2) : st::passcodeSkip));
 	}
 
-	int32 buttonTop = height() - _cancelButton.height();
-	_cancelButton.move(0, buttonTop);
-	_saveButton.move(width() - _saveButton.width(), buttonTop);
+	_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::showDone() {
@@ -289,6 +317,10 @@ bool PasscodeBox::setPasswordFail(const RPCError &error) {
 		_oldPasscode.setFocus();
 		_oldPasscode.showError();
 		_oldError = lang(lng_flood_error);
+		if (_hasRecovery && _hintText.isEmpty()) {
+			_recover.hide();
+		}
+		update();
 	}
 	return true;
 }
@@ -388,12 +420,18 @@ void PasscodeBox::onBadOldPasscode() {
 	_oldPasscode.setFocus();
 	_oldPasscode.showError();
 	_oldError = lang(_cloudPwd ? lng_cloud_password_wrong : lng_passcode_wrong);
+	if (_hasRecovery && _hintText.isEmpty()) {
+		_recover.hide();
+	}
 	update();
 }
 
 void PasscodeBox::onOldChanged() {
 	if (!_oldError.isEmpty()) {
 		_oldError = QString();
+		if (_hasRecovery && _hintText.isEmpty()) {
+			_recover.show();
+		}
 		update();
 	}
 }
@@ -458,17 +496,21 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) {
 	return true;
 }
 
-RecoverBox::RecoverBox(const QString &pattern) :
-_submitRequest(0), _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWideWidth - st::boxPadding.left() - st::boxPadding.right())),
-_saveButton(this, lang(lng_passcode_submit), st::defaultBoxButton),
-_cancelButton(this, lang(lng_cancel), st::cancelBoxButton),
-_recoverCode(this, st::defaultInputField, lang(lng_signin_code)) {
-	setMaxHeight(st::boxTitleHeight + st::contactPadding.top() + st::usernameSkip + _recoverCode.height() + st::usernameSkip + st::contactPadding.bottom() + _saveButton.height());
+RecoverBox::RecoverBox(const QString &pattern) : AbstractBox(st::boxWidth)
+, _submitRequest(0)
+, _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() - st::boxPadding.right()))
+, _saveButton(this, lang(lng_passcode_submit), st::defaultBoxButton)
+, _cancelButton(this, lang(lng_cancel), st::cancelBoxButton)
+, _recoverCode(this, st::defaultInputField, lang(lng_signin_code)) {
+	setBlueTitle(true);
+
+	setMaxHeight(st::boxTitleHeight + st::passcodePadding.top() + st::passcodeSkip + _recoverCode.height() + st::passcodeSkip + st::passcodePadding.bottom() + st::boxButtonPadding.top() + _saveButton.height() + st::boxButtonPadding.bottom());
 
 	connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSubmit()));
 	connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose()));
 
 	connect(&_recoverCode, SIGNAL(changed()), this, SLOT(onCodeChanged()));
+	connect(&_recoverCode, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
 
 	prepare();
 }
@@ -477,49 +519,40 @@ void RecoverBox::hideAll() {
 	_recoverCode.hide();
 	_saveButton.hide();
 	_cancelButton.hide();
+	AbstractBox::hideAll();
 }
 
 void RecoverBox::showAll() {
 	_recoverCode.show();
 	_saveButton.show();
 	_cancelButton.show();
-}
-
-void RecoverBox::keyPressEvent(QKeyEvent *e) {
-	if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
-		if (_recoverCode.getLastText().isEmpty()) {
-			_recoverCode.setFocus();
-			_recoverCode.showError();
-		} else {
-			onSubmit();
-		}
-	} else {
-		AbstractBox::keyPressEvent(e);
-	}
+	AbstractBox::showAll();
 }
 
 void RecoverBox::paintEvent(QPaintEvent *e) {
 	Painter p(this);
 	if (paint(p)) return;
 
-	paintTitle(p, lang(lng_signin_recover));
+	paintTitle(p, lang(lng_signin_recover_title));
 
-	p.setFont(st::normalFont->f);
+	p.setFont(st::normalFont);
+	p.setPen(st::black);
 	int32 w = width() - st::boxPadding.left() - st::boxPadding.right();
-	p.drawText(QRect(st::boxPadding.left(), _recoverCode.y() - st::usernameSkip - st::contactPadding.top(), w, st::contactPadding.top() + st::usernameSkip), _pattern, style::al_center);
+	p.drawText(QRect(st::boxPadding.left(), _recoverCode.y() - st::passcodeSkip - st::passcodePadding.top(), w, st::passcodePadding.top() + st::passcodeSkip), _pattern, style::al_left);
 
 	if (!_error.isEmpty()) {
 		p.setPen(st::setErrColor->p);
-		p.drawText(QRect(0, _recoverCode.y() + _recoverCode.height(), width(), st::usernameSkip), _error, style::al_center);
+		p.drawText(QRect(st::boxPadding.left(), _recoverCode.y() + _recoverCode.height(), w, st::passcodeSkip), _error, style::al_left);
 	}
 }
 
 void RecoverBox::resizeEvent(QResizeEvent *e) {
-	_recoverCode.setGeometry(st::boxPadding.left(), st::boxTitleHeight + st::contactPadding.top() + st::usernameSkip, width() - st::boxPadding.left() - st::boxPadding.right(), _recoverCode.height());
+	_recoverCode.setGeometry(st::boxPadding.left(), st::boxTitleHeight + st::passcodePadding.top() + st::passcodeSkip, width() - st::boxPadding.left() - st::boxPadding.right(), _recoverCode.height());
 
-	int32 buttonTop = height() - _cancelButton.height();
-	_cancelButton.move(0, buttonTop);
-	_saveButton.move(width() - _saveButton.width(), buttonTop);
+	_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::showDone() {
@@ -531,6 +564,7 @@ void RecoverBox::onSubmit() {
 
 	QString code = _recoverCode.getLastText().trimmed();
 	if (code.isEmpty()) {
+		_recoverCode.setFocus();
 		_recoverCode.showError();
 		return;
 	}
diff --git a/Telegram/SourceFiles/boxes/passcodebox.h b/Telegram/SourceFiles/boxes/passcodebox.h
index 2ac2c74bf..f280af9a0 100644
--- a/Telegram/SourceFiles/boxes/passcodebox.h
+++ b/Telegram/SourceFiles/boxes/passcodebox.h
@@ -30,7 +30,6 @@ public:
 	PasscodeBox(bool turningOff = false);
 	PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff = false);
 	void init();
-	void keyPressEvent(QKeyEvent *e);
 	void paintEvent(QPaintEvent *e);
 	void resizeEvent(QResizeEvent *e);
 
@@ -45,6 +44,7 @@ public slots:
 	void onBoxDestroyed(QObject *obj);
 	void onRecoverByEmail();
 	void onRecoverExpired();
+	void onSubmit();
 
 signals:
 
@@ -73,7 +73,6 @@ private:
 
 	QByteArray _newSalt, _curSalt;
 	bool _hasRecovery, _skipEmailWarning;
-	QString _hint;
 
 	int32 _aboutHeight;
 
@@ -94,7 +93,6 @@ class RecoverBox : public AbstractBox, public RPCSender {
 public:
 
 	RecoverBox(const QString &pattern);
-	void keyPressEvent(QKeyEvent *e);
 	void paintEvent(QPaintEvent *e);
 	void resizeEvent(QResizeEvent *e);
 
diff --git a/Telegram/SourceFiles/boxes/sessionsbox.cpp b/Telegram/SourceFiles/boxes/sessionsbox.cpp
index a76d13b3f..8d58681ff 100644
--- a/Telegram/SourceFiles/boxes/sessionsbox.cpp
+++ b/Telegram/SourceFiles/boxes/sessionsbox.cpp
@@ -30,7 +30,15 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 #include "countries.h"
 #include "confirmbox.h"
 
-SessionsInner::SessionsInner(SessionsList *list) : _list(list), _terminating(0), _terminateBox(0) {
+SessionsInner::SessionsInner(SessionsList *list, SessionData *current) : TWidget()
+, _list(list)
+, _current(current)
+, _terminating(0)
+, _terminateAll(this, lang(lng_sessions_terminate_all), st::redBoxLinkButton)
+, _terminateBox(0) {
+	connect(&_terminateAll, SIGNAL(clicked()), this, SLOT(onTerminateAll()));
+	_terminateAll.hide();
+	setAttribute(Qt::WA_OpaquePaintEvent);
 }
 
 void SessionsInner::paintEvent(QPaintEvent *e) {
@@ -38,12 +46,44 @@ void SessionsInner::paintEvent(QPaintEvent *e) {
 	Painter p(this);
 
 	p.fillRect(r, st::white->b);
-	p.setFont(st::linkFont->f);
 	int32 x = st::sessionPadding.left(), xact = st::sessionTerminateSkip + st::sessionTerminate.iconPos.x();// st::sessionTerminateSkip + st::sessionTerminate.width + st::sessionTerminateSkip;
 	int32 w = width();
+
+	if (_current->active.isEmpty() && _list->isEmpty()) {
+		p.setFont(st::noContactsFont->f);
+		p.setPen(st::noContactsColor->p);
+		p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
+		return;
+	}
+
+	if (r.y() <= st::sessionCurrentHeight) {
+		p.translate(0, st::sessionCurrentPadding.top());
+		p.setFont(st::sessionNameFont->f);
+		p.setPen(st::black->p);
+		p.drawTextLeft(x, st::sessionPadding.top(), w, _current->name, _current->nameWidth);
+
+		p.setFont(st::sessionActiveFont->f);
+		p.setPen(st::sessionActiveColor->p);
+		p.drawTextRight(x, st::sessionPadding.top(), w, _current->active, _current->activeWidth);
+
+		p.setFont(st::sessionInfoFont->f);
+		p.setPen(st::black->p);
+		p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height, w, _current->info, _current->infoWidth);
+		p.setPen(st::sessionInfoColor->p);
+		p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height + st::sessionInfoFont->height, w, _current->ip, _current->ipWidth);
+	}
+	p.translate(0, st::sessionCurrentHeight - st::sessionCurrentPadding.top());
+	if (_list->isEmpty()) {
+		p.setFont(st::sessionInfoFont->f);
+		p.setPen(st::sessionInfoColor->p);
+		p.drawText(QRect(st::sessionPadding.left(), 0, width() - st::sessionPadding.left() - st::sessionPadding.right(), st::noContactsHeight), lang(lng_sessions_other_desc), style::al_topleft);
+		return;
+	}
+
+	p.setFont(st::linkFont->f);
 	int32 count = _list->size();
-	int32 from = floorclamp(r.y(), st::sessionHeight, 0, count);
-	int32 to = ceilclamp(r.y() + r.height(), st::sessionHeight, 0, count);
+	int32 from = floorclamp(r.y() - st::sessionCurrentHeight, st::sessionHeight, 0, count);
+	int32 to = ceilclamp(r.y() + r.height() - st::sessionCurrentHeight, st::sessionHeight, 0, count);
 	p.translate(0, from * st::sessionHeight);
 	for (int32 i = from; i < to; ++i) {
 		const SessionData &auth(_list->at(i));
@@ -93,6 +133,23 @@ void SessionsInner::onTerminateSure() {
 	}
 }
 
+void SessionsInner::onTerminateAll() {
+	if (_terminateBox) _terminateBox->deleteLater();
+	_terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
+	connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateAllSure()));
+	connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
+	App::wnd()->replaceLayer(_terminateBox);
+}
+
+void SessionsInner::onTerminateAllSure() {
+	if (_terminateBox) {
+		_terminateBox->onClose();
+		_terminateBox = 0;
+	}
+	MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&SessionsInner::terminateAllDone), rpcFail(&SessionsInner::terminateAllFail));
+	emit terminateAll();
+}
+
 void SessionsInner::onNoTerminateBox(QObject *obj) {
 	if (obj == _terminateBox) _terminateBox = 0;
 }
@@ -119,11 +176,26 @@ bool SessionsInner::terminateFail(uint64 hash, const RPCError &error) {
 	return false;
 }
 
-void SessionsInner::resizeEvent(QResizeEvent *e) {
+void SessionsInner::terminateAllDone(const MTPBool &result) {
+	emit allTerminated();
+}
 
+bool SessionsInner::terminateAllFail(const RPCError &error) {
+	if (mtpIsFlood(error)) return false;
+	emit allTerminated();
+	return true;
+}
+
+void SessionsInner::resizeEvent(QResizeEvent *e) {
+	_terminateAll.moveToLeft(st::sessionPadding.left(), st::sessionCurrentPadding.top() + st::sessionHeight + st::sessionCurrentPadding.bottom());
 }
 
 void SessionsInner::listUpdated() {
+	if (_list->isEmpty()) {
+		_terminateAll.hide();
+	} else {
+		_terminateAll.show();
+	}
 	for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) {
 		i.value()->move(0, -1);
 	}
@@ -133,7 +205,8 @@ void SessionsInner::listUpdated() {
 			j = _terminateButtons.insert(_list->at(i).hash, new IconedButton(this, st::sessionTerminate));
 			connect(j.value(), SIGNAL(clicked()), this, SLOT(onTerminate()));
 		}
-		j.value()->moveToRight(st::sessionTerminateSkip, i * st::sessionHeight + st::sessionTerminateTop, width());
+		j.value()->moveToRight(st::sessionTerminateSkip, st::sessionCurrentHeight + i * st::sessionHeight + st::sessionTerminateTop, width());
+		j.value()->show();
 	}
 	for (TerminateButtons::iterator i = _terminateButtons.begin(); i != _terminateButtons.cend();) {
 		if (i.value()->y() >= 0) {
@@ -143,8 +216,8 @@ void SessionsInner::listUpdated() {
 			i = _terminateButtons.erase(i);
 		}
 	}
-	resize(width(), _list->isEmpty() ? st::noContactsHeight : (_list->size() * st::sessionHeight));
-	if (parentWidget()) parentWidget()->update();
+	resize(width(), _list->isEmpty() ? (st::sessionCurrentHeight + st::noContactsHeight) : (st::sessionCurrentHeight + _list->size() * st::sessionHeight));
+	update();
 }
 
 SessionsInner::~SessionsInner() {
@@ -153,94 +226,63 @@ SessionsInner::~SessionsInner() {
 	}
 }
 
-SessionsBox::SessionsBox() : ScrollableBox(st::boxScroll), _loading(true), _inner(&_list),
-_done(this, lang(lng_about_done), st::sessionsCloseButton),
-_terminateAll(this, lang(lng_sessions_terminate_all)), _terminateBox(0), _shortPollRequest(0) {
+SessionsBox::SessionsBox() : ScrollableBox(st::sessionsScroll)
+, _loading(true)
+, _inner(&_list, &_current)
+, _shadow(this)
+, _done(this, lang(lng_about_done), st::defaultBoxButton)
+, _shortPollRequest(0) {
 	setMaxHeight(st::sessionsHeight);
 
 	connect(&_done, SIGNAL(clicked()), this, SLOT(onClose()));
-	connect(&_terminateAll, SIGNAL(clicked()), this, SLOT(onTerminateAll()));
 	connect(&_inner, SIGNAL(oneTerminated()), this, SLOT(onOneTerminated()));
+	connect(&_inner, SIGNAL(allTerminated()), this, SLOT(onAllTerminated()));
+	connect(&_inner, SIGNAL(terminateAll()), this, SLOT(onTerminateAll()));
 	connect(App::wnd(), SIGNAL(newAuthorization()), this, SLOT(onNewAuthorization()));
 	connect(&_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations()));
 
-	init(&_inner, _done.height(), st::boxTitleHeight + st::sessionHeight + st::boxTitleHeight);
+	init(&_inner, st::boxButtonPadding.bottom() + _done.height() + st::boxButtonPadding.top(), st::boxTitleHeight);
 	_inner.resize(width(), st::noContactsHeight);
 
 	prepare();
 
-	_scroll.hide();
 	MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations));
 }
 
 void SessionsBox::resizeEvent(QResizeEvent *e) {
 	ScrollableBox::resizeEvent(e);
-	_done.move(0, height() - _done.height());
-	_terminateAll.moveToRight(st::sessionPadding.left(), st::boxTitleHeight + st::sessionHeight + st::boxTitlePosition.y() + st::boxTitleFont->ascent - st::linkFont->ascent);
+	_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());
 }
 
 void SessionsBox::hideAll() {
 	_done.hide();
-	_terminateAll.hide();
 	ScrollableBox::hideAll();
 }
 
 void SessionsBox::showAll() {
 	_done.show();
-	if (_list.isEmpty()) {
-		_terminateAll.hide();
+	if (_loading) {
 		_scroll.hide();
+		_shadow.hide();
 	} else {
-		_terminateAll.show();
-		if (_loading) {
-			_scroll.hide();
-		} else {
-			_scroll.show();
-		}
+		_scroll.show();
+		_shadow.show();
 	}
+	ScrollableBox::showAll();
 }
 
 void SessionsBox::paintEvent(QPaintEvent *e) {
 	Painter p(this);
 	if (paint(p)) return;
 
-	paintTitle(p, lang(lng_sessions_header));
+	paintTitle(p, lang(lng_sessions_other_header));
 	p.translate(0, st::boxTitleHeight);
 
 	if (_loading) {
 		p.setFont(st::noContactsFont->f);
 		p.setPen(st::noContactsColor->p);
 		p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
-	} else {
-		int32 x = st::sessionPadding.left();
-		int32 w = width();
-
-		p.setFont(st::sessionNameFont->f);
-		p.setPen(st::black->p);
-		p.drawTextLeft(x, st::sessionPadding.top(), w, _current.name, _current.nameWidth);
-
-		p.setFont(st::sessionActiveFont->f);
-		p.setPen(st::sessionActiveColor->p);
-		p.drawTextRight(x, st::sessionPadding.top(), w, _current.active, _current.activeWidth);
-
-		p.setFont(st::sessionInfoFont->f);
-		p.setPen(st::black->p);
-		p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height, w, _current.info, _current.infoWidth);
-		p.setPen(st::sessionInfoColor->p);
-		p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height + st::sessionInfoFont->height, w, _current.ip, _current.ipWidth);
-		p.translate(0, st::sessionHeight);
-		if (_list.isEmpty()) {
-			paintTitle(p, lang(lng_sessions_no_other));
-
-			p.setFont(st::sessionInfoFont->f);
-			p.setPen(st::sessionInfoColor->p);
-			p.drawText(QRect(st::sessionPadding.left(), st::boxTitleHeight + st::boxTitlePosition.y(), width() - st::sessionPadding.left() - st::sessionPadding.right(), _scroll.height()), lang(lng_sessions_other_desc), style::al_topleft);
-
-			// paint shadow
-			p.fillRect(0, height() - st::sessionsCloseButton.height - st::scrollDef.bottomsh - st::sessionHeight - st::boxTitleHeight, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b);
-		} else {
-			paintTitle(p, lang(lng_sessions_other_header));
-		}
 	}
 }
 
@@ -297,10 +339,11 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
 		data.info = qs(d.vdevice_model) + qstr(", ") + (platform.isEmpty() ? QString() : platform + ' ') + qs(d.vsystem_version);
 		data.ip = qs(d.vip) + (country.isEmpty() ? QString() : QString::fromUtf8(" \xe2\x80\x93 ") + country);
 		if (!data.hash || (d.vflags.v & 1)) {
-			data.active = QString();
-			data.activeWidth = 0;
-			if (data.nameWidth > availCurrent) {
-				data.name = st::sessionNameFont->elided(data.name, availCurrent);
+			data.active = lang(lng_sessions_header);
+			data.activeWidth = st::sessionActiveFont->width(lang(lng_sessions_header));
+			int32 availForName = availCurrent - st::sessionPadding.right() - data.activeWidth;
+			if (data.nameWidth > availForName) {
+				data.name = st::sessionNameFont->elided(data.name, availForName);
 				data.nameWidth = st::sessionNameFont->width(data.name);
 			}
 			data.infoWidth = st::sessionInfoFont->width(data.info);
@@ -360,31 +403,6 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
 	_shortPollTimer.start(SessionsShortPollTimeout);
 }
 
-void SessionsBox::onTerminateAll() {
-	if (_terminateBox) _terminateBox->deleteLater();
-	_terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button), st::attentionBoxButton);
-	connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateAllSure()));
-	connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*)));
-	App::wnd()->replaceLayer(_terminateBox);
-}
-
-void SessionsBox::onTerminateAllSure() {
-	if (_terminateBox) {
-		_terminateBox->onClose();
-		_terminateBox = 0;
-	}
-	MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&SessionsBox::terminateAllDone), rpcFail(&SessionsBox::terminateAllFail));
-	_loading = true;
-	if (!_done.isHidden()) {
-		showAll();
-		update();
-	}
-}
-
-void SessionsBox::onNoTerminateBox(QObject *obj) {
-	if (obj == _terminateBox) _terminateBox = 0;
-}
-
 void SessionsBox::onOneTerminated() {
 	if (_list.isEmpty()) {
 		if (!_done.isHidden()) {
@@ -409,7 +427,7 @@ void SessionsBox::onNewAuthorization() {
 //	_shortPollTimer.start(1000);
 }
 
-void SessionsBox::terminateAllDone(const MTPBool &result) {
+void SessionsBox::onAllTerminated() {
 	MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations));
 	if (_shortPollRequest) {
 		MTP::cancel(_shortPollRequest);
@@ -417,13 +435,10 @@ void SessionsBox::terminateAllDone(const MTPBool &result) {
 	}
 }
 
-bool SessionsBox::terminateAllFail(const RPCError &error) {
-	if (mtpIsFlood(error)) return false;
-
-	MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations));
-	if (_shortPollRequest) {
-		MTP::cancel(_shortPollRequest);
-		_shortPollRequest = 0;
+void SessionsBox::onTerminateAll() {
+	_loading = true;
+	if (!_done.isHidden()) {
+		showAll();
+		update();
 	}
-	return true;
-}
+}
\ No newline at end of file
diff --git a/Telegram/SourceFiles/boxes/sessionsbox.h b/Telegram/SourceFiles/boxes/sessionsbox.h
index e49ec799f..3c84bc65d 100644
--- a/Telegram/SourceFiles/boxes/sessionsbox.h
+++ b/Telegram/SourceFiles/boxes/sessionsbox.h
@@ -33,12 +33,12 @@ struct SessionData {
 };
 typedef QList<SessionData> SessionsList;
 
-class SessionsInner : public QWidget, public RPCSender {
+class SessionsInner : public TWidget, public RPCSender {
 	Q_OBJECT
 
 public:
 
-	SessionsInner(SessionsList *list);
+	SessionsInner(SessionsList *list, SessionData *current);
 
 	void paintEvent(QPaintEvent *e);
 	void resizeEvent(QResizeEvent *e);
@@ -50,11 +50,15 @@ public:
 signals:
 
 	void oneTerminated();
+	void allTerminated();
+	void terminateAll();
 
 public slots:
 
 	void onTerminate();
 	void onTerminateSure();
+	void onTerminateAll();
+	void onTerminateAllSure();
 	void onNoTerminateBox(QObject *obj);
 
 private:
@@ -62,12 +66,17 @@ private:
 	void terminateDone(uint64 hash, const MTPBool &result);
 	bool terminateFail(uint64 hash, const RPCError &error);
 
+	void terminateAllDone(const MTPBool &res);
+	bool terminateAllFail(const RPCError &error);
+
 	SessionsList *_list;
+	SessionData *_current;
 
 	typedef QMap<uint64, IconedButton*> TerminateButtons;
 	TerminateButtons _terminateButtons;
 
 	uint64 _terminating;
+	LinkButton _terminateAll;
 	ConfirmBox *_terminateBox;
 
 };
@@ -83,10 +92,9 @@ public:
 
 public slots:
 
-	void onTerminateAll();
-	void onTerminateAllSure();
-	void onNoTerminateBox(QObject *obj);
 	void onOneTerminated();
+	void onAllTerminated();
+	void onTerminateAll();
 	void onShortPollAuthorizations();
 	void onNewAuthorization();
 
@@ -98,8 +106,6 @@ protected:
 private:
 
 	void gotAuthorizations(const MTPaccount_Authorizations &result);
-	void terminateAllDone(const MTPBool &res);
-	bool terminateAllFail(const RPCError &error);
 
 	bool _loading;
 
@@ -107,10 +113,8 @@ private:
 	SessionsList _list;
 
 	SessionsInner _inner;
-	FlatButton _done;
-
-	LinkButton _terminateAll;
-	ConfirmBox *_terminateBox;
+	ScrollableBoxShadow _shadow;
+	BoxButton _done;
 
 	SingleTimer _shortPollTimer;
 	mtpRequestId _shortPollRequest;
diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp
index 8a0119691..a02680523 100644
--- a/Telegram/SourceFiles/boxes/stickersetbox.cpp
+++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp
@@ -223,7 +223,8 @@ StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st::
 , _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) {
+, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
+, _done(this, lang(lng_about_done), st::defaultBoxButton) {
 	setMaxHeight(st::stickersMaxHeight);
 	connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
 
@@ -232,6 +233,7 @@ StickerSetBox::StickerSetBox(const MTPInputStickerSet &set) : ScrollableBox(st::
 	connect(&_add, SIGNAL(clicked()), this, SLOT(onAddStickers()));
 	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(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
@@ -260,7 +262,7 @@ void StickerSetBox::onShareStickers() {
 }
 
 void StickerSetBox::onUpdateButtons() {
-	if (!_cancel.isHidden()) {
+	if (!_cancel.isHidden() || !_done.isHidden()) {
 		showAll();
 	}
 }
@@ -275,29 +277,36 @@ void StickerSetBox::hideAll() {
 	_cancel.hide();
 	_add.hide();
 	_share.hide();
+	_done.hide();
 }
 
 void StickerSetBox::showAll() {
 	ScrollableBox::showAll();
-	_shadow.show();
-	_cancel.show();
 	int32 cnt = _inner.notInstalled();
 	if (_inner.loaded()) {
+		_shadow.show();
 		if (_inner.official()) {
 			_add.hide();
 			_share.hide();
+			_cancel.hide();
+			_done.show();
 		} else if (_inner.notInstalled()) {
 			_add.show();
-			_add.raise();
+			_cancel.show();
 			_share.hide();
+			_done.hide();
 		} else {
 			_share.show();
-			_share.raise();
+			_cancel.show();
 			_add.hide();
+			_done.hide();
 		}
 	} else {
+		_shadow.hide();
 		_add.hide();
 		_share.hide();
+		_cancel.show();
+		_done.hide();
 	}
 	resizeEvent(0);
 	update();
@@ -316,6 +325,7 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) {
 	_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()) {
diff --git a/Telegram/SourceFiles/boxes/stickersetbox.h b/Telegram/SourceFiles/boxes/stickersetbox.h
index 7789e6d33..c57e32bfd 100644
--- a/Telegram/SourceFiles/boxes/stickersetbox.h
+++ b/Telegram/SourceFiles/boxes/stickersetbox.h
@@ -103,6 +103,6 @@ private:
 
 	StickerSetInner _inner;
 	ScrollableBoxShadow _shadow;
-	BoxButton _add, _share, _cancel;
+	BoxButton _add, _share, _cancel, _done;
 	QString _title;
 };
diff --git a/Telegram/SourceFiles/boxes/usernamebox.cpp b/Telegram/SourceFiles/boxes/usernamebox.cpp
index 635ff21b7..d8c0a69f2 100644
--- a/Telegram/SourceFiles/boxes/usernamebox.cpp
+++ b/Telegram/SourceFiles/boxes/usernamebox.cpp
@@ -29,7 +29,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 UsernameBox::UsernameBox() : AbstractBox(st::boxWidth),
 _save(this, lang(lng_settings_save), st::defaultBoxButton),
 _cancel(this, lang(lng_cancel), st::cancelBoxButton),
-_username(this, st::usernameField, qsl("@username"), App::self()->username, false),
+_username(this, st::defaultInputField, qsl("@username"), App::self()->username, false),
 _link(this, QString(), st::defaultBoxLinkButton),
 _saveRequestId(0), _checkRequestId(0),
 _about(st::boxWidth - st::usernamePadding.left()) {
diff --git a/Telegram/SourceFiles/gui/flatbutton.cpp b/Telegram/SourceFiles/gui/flatbutton.cpp
index 75db4c86b..e881a5af1 100644
--- a/Telegram/SourceFiles/gui/flatbutton.cpp
+++ b/Telegram/SourceFiles/gui/flatbutton.cpp
@@ -138,18 +138,6 @@ void FlatButton::paintEvent(QPaintEvent *e) {
 	p.drawText(r, _text, style::al_top);
 }
 
-BottomButton::BottomButton(QWidget *w, const QString &t, const style::flatButton &s) : FlatButton(w, t, s) {
-	resize(width(), height() + 1);
-}
-
-void BottomButton::paintEvent(QPaintEvent *e) {
-	QPainter p(this);
-
-	p.fillRect(0, 0, width(), st::lineWidth, st::scrollDef.shColor->b);
-
-	FlatButton::paintEvent(e);
-}
-
 LinkButton::LinkButton(QWidget *parent, const QString &text, const style::linkButton &st) : Button(parent), _text(text), _st(st) {
 	connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource)));
 	resize(_st.font->width(_text), _st.font->height);
diff --git a/Telegram/SourceFiles/gui/flatbutton.h b/Telegram/SourceFiles/gui/flatbutton.h
index 3a90686a5..c6f0dc54b 100644
--- a/Telegram/SourceFiles/gui/flatbutton.h
+++ b/Telegram/SourceFiles/gui/flatbutton.h
@@ -66,14 +66,6 @@ private:
 	float64 _opacity;
 };
 
-class BottomButton : public FlatButton {
-public:
-
-	BottomButton(QWidget *parent, const QString &text, const style::flatButton &st);
-	void paintEvent(QPaintEvent *e);
-
-};
-
 class LinkButton : public Button {
 	Q_OBJECT
 
diff --git a/Telegram/SourceFiles/gui/scrollarea.cpp b/Telegram/SourceFiles/gui/scrollarea.cpp
index 8523c0491..0f76852b6 100644
--- a/Telegram/SourceFiles/gui/scrollarea.cpp
+++ b/Telegram/SourceFiles/gui/scrollarea.cpp
@@ -155,7 +155,7 @@ bool ScrollBar::animStep(float64 ms) {
 		a_bg.update(dt, anim::linear);
 		a_bar.update(dt, anim::linear);
 	}
-	update();// parentWidget()->update(geometry());
+	update();
 	return res;
 }
 
diff --git a/Telegram/SourceFiles/gui/twidget.cpp b/Telegram/SourceFiles/gui/twidget.cpp
index 5c69e7d1a..d58b3f813 100644
--- a/Telegram/SourceFiles/gui/twidget.cpp
+++ b/Telegram/SourceFiles/gui/twidget.cpp
@@ -44,14 +44,11 @@ void myEnsureResized(QWidget *target) {
 }
 
 QPixmap myGrab(QWidget *target, const QRect &rect) {
-    if (!cRetina()) return target->grab(rect);
-    
-	myEnsureResized(target);
-    
+	myEnsureResized(target);    
     qreal dpr = App::app()->devicePixelRatio();
     QPixmap result(rect.size() * dpr);
     result.setDevicePixelRatio(dpr);
     result.fill(Qt::transparent);
-    target->render(&result, QPoint(), QRegion(rect), QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
-    return result;
+    target->render(&result, QPoint(), QRegion(rect), QWidget::DrawChildren | QWidget::IgnoreMask);
+	return result;
 }
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index db24f7f37..9f2603b0e 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -1650,6 +1650,7 @@ bool MessageField::hasSendText() const {
 }
 
 void MessageField::onEmojiInsert(EmojiPtr emoji) {
+	if (isHidden()) return;
 	insertEmoji(emoji, textCursor());
 }
 
@@ -2633,7 +2634,9 @@ void HistoryWidget::activate() {
 }
 
 void HistoryWidget::setInnerFocus() {
-	if (_list) {
+	if (_scroll.isHidden()) {
+		setFocus();
+	} else if (_list) {
 		if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked() || !_canSendMessages) {
 			_list->setFocus();
 		} else {
@@ -3035,7 +3038,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
 		doneShow();
 	}
 
-	if (App::wnd()) App::wnd()->setInnerFocus();
+	if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus()));
 
 	App::main()->dlgUpdated(wasHistory, wasMsgId);
 	emit historyShown(_history, _showAtMsgId);
@@ -5616,7 +5619,7 @@ void HistoryWidget::onFieldTabbed() {
 }
 
 void HistoryWidget::onStickerSend(DocumentData *sticker) {
-	if (!_history || !sticker) return;
+	if (!_history || !sticker || !canSendMessages(_peer)) return;
 
 	App::main()->readServerHistory(_history, false);
 	fastShowAtEnd(_history);
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 19fa8fb8b..1cfd27d5b 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -2204,8 +2204,10 @@ void MainWidget::setInnerFocus() {
 		} else {
 			dialogsActivate();
 		}
+	} else if (overview) {
+		overview->activate();
 	} else if (profile) {
-		profile->setFocus();
+		profile->activate();
 	} else {
 		history.setInnerFocus();
 	}
diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp
index 77f95b134..d4b7aa18a 100644
--- a/Telegram/SourceFiles/overviewwidget.cpp
+++ b/Telegram/SourceFiles/overviewwidget.cpp
@@ -761,7 +761,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
 			}
 		} else {
 			_selected.clear();
-			parentWidget()->update();
+			update();
 		}
 	} else if (_dragAction == Selecting) {
 		if (_dragSelFrom && _dragSelTo) {
@@ -1669,7 +1669,7 @@ void OverviewInner::updateDragSelection(MsgId dragSelFrom, int32 dragSelFromInde
 			qSwap(_dragSelFromIndex, _dragSelToIndex);
 		}
 		_dragSelecting = dragSelecting;
-		parentWidget()->update();
+		update();
 	}
 }
 
@@ -2045,7 +2045,7 @@ void OverviewInner::onNeedSearchMessages() {
 	if (!onSearchMessages(true)) {
 		_searchTimer.start(AutoSearchTimeout);
 		if (_inSearch && _searchFull && _searchResults.isEmpty()) {
-			parentWidget()->update();
+			update();
 		}
 	}
 }
@@ -2415,7 +2415,7 @@ void OverviewInner::itemRemoved(HistoryItem *item) {
 	}
 	updateDragSelection(_dragSelFrom, _dragSelFromIndex, _dragSelTo, _dragSelToIndex, _dragSelecting);
 
-	parentWidget()->update();
+	update();
 }
 
 void OverviewInner::itemResized(HistoryItem *item, bool scrollToIt) {
@@ -2447,7 +2447,7 @@ void OverviewInner::itemResized(HistoryItem *item, bool scrollToIt) {
 							_scroll->scrollToY(_addToY + _height - _items[i].y);
 						}
 					}
-					parentWidget()->update();
+					update();
 				}
 				break;
 			}
@@ -2881,7 +2881,11 @@ OverviewWidget::~OverviewWidget() {
 }
 
 void OverviewWidget::activate() {
-	_inner.activate();
+	if (_scroll.isHidden()) {
+		setFocus();
+	} else {
+		_inner.activate();
+	}
 }
 
 QPoint OverviewWidget::clampMousePosition(QPoint point) {
diff --git a/Telegram/SourceFiles/passcodewidget.cpp b/Telegram/SourceFiles/passcodewidget.cpp
index 5532274a3..b92ae82b1 100644
--- a/Telegram/SourceFiles/passcodewidget.cpp
+++ b/Telegram/SourceFiles/passcodewidget.cpp
@@ -188,14 +188,14 @@ void PasscodeWidget::paintEvent(QPaintEvent *e) {
 		if (!_error.isEmpty()) {
 			p.setFont(st::boxTextFont->f);
 			p.setPen(st::setErrColor->p);
-			p.drawText(QRect(0, _passcode.y() + _passcode.height(), width(), st::usernameSkip), _error, style::al_center);
+			p.drawText(QRect(0, _passcode.y() + _passcode.height(), width(), st::passcodeSubmitSkip), _error, style::al_center);
 		}
 	}
 }
 
 void PasscodeWidget::resizeEvent(QResizeEvent *e) {
 	_passcode.move((width() - _passcode.width()) / 2, (height() / 3));
-	_submit.move(_passcode.x(), _passcode.y() + _passcode.height() + st::passcodeSkip);
+	_submit.move(_passcode.x(), _passcode.y() + _passcode.height() + st::passcodeSubmitSkip);
 	_logout.move(_passcode.x() + (_passcode.width() - _logout.width()) / 2, _submit.y() + _submit.height() + st::linkFont->ascent);
 }
 
diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp
index 42c40b773..16107c508 100644
--- a/Telegram/SourceFiles/profilewidget.cpp
+++ b/Telegram/SourceFiles/profilewidget.cpp
@@ -697,7 +697,7 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
 	} else if (_peerChannel && (_peerChannel->isPublic() || _amCreator)) {
 		addbyname = st::profileStatusTop + st::linkFont->ascent - (st::profileNameTop + st::profileNameFont->ascent);
 	}
-	if (!_peerChannel || (!_amCreator && !_peerChannel->amEditor() && !_peerChannel->amModerator())) {
+	if (!_peerChannel || !_peerChannel->canViewParticipants()) {
 		p.setPen((_peerUser && App::onlineColorUse(_peerUser, l_time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
 		p.drawText(_left + st::profilePhotoSize + st::profileStatusLeft, top + addbyname + st::profileStatusTop + st::linkFont->ascent, _onlineText);
 	}
@@ -1461,12 +1461,15 @@ void ProfileInner::showAll() {
 			_username.hide();
 		}
 		if (_amCreator || _peerChannel->amEditor() || _peerChannel->amModerator()) {
-			_members.show();
 			_admins.show();
 		} else {
-			_members.hide();
 			_admins.hide();
 		}
+		if (_peerChannel->canViewParticipants()) {
+			_members.show();
+		} else {
+			_members.hide();
+		}
 	}
 	_enableNotifications.show();
 	updateNotifySettings();
@@ -1696,5 +1699,9 @@ ProfileWidget::~ProfileWidget() {
 }
 
 void ProfileWidget::activate() {
-	_inner.setFocus();
+	if (_scroll.isHidden()) {
+		setFocus();
+	} else {
+		_inner.setFocus();
+	}
 }
diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp
index 9679783e6..0106d151b 100644
--- a/Telegram/SourceFiles/settingswidget.cpp
+++ b/Telegram/SourceFiles/settingswidget.cpp
@@ -22,6 +22,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 #include "style.h"
 #include "lang.h"
 
+#include "boxes/aboutbox.h"
 #include "settingswidget.h"
 #include "mainwidget.h"
 #include "application.h"
@@ -1192,16 +1193,7 @@ void SettingsInner::onAskQuestionSure() {
 }
 
 void SettingsInner::onTelegramFAQ() {
-	QString url = qsl("https://telegram.org/faq");
-	if (cLang() > languageDefault && cLang() < languageCount) {
-		const char *code = LanguageCodes[cLang()];
-		if (qstr("de") == code || qstr("es") == code || qstr("it") == code || qstr("ko") == code) {
-			url += qsl("/") + code;
-		} else if (qstr("pt_BR") == code) {
-			url += qsl("/br");
-		}
-	}
-	QDesktopServices::openUrl(url);
+	QDesktopServices::openUrl(telegramFaqLink());
 }
 
 void SettingsInner::chooseCustomLang() {
diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h
index cda4ac21c..2014ebd39 100644
--- a/Telegram/SourceFiles/structs.h
+++ b/Telegram/SourceFiles/structs.h
@@ -454,7 +454,7 @@ private:
 class ChannelData : public PeerData {
 public:
 
-	ChannelData(const PeerId &id) : PeerData(id), access(0), inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))), count(1), adminsCount(1), date(0), version(0), isForbidden(true), botStatus(-1), inviter(0), _lastFullUpdate(0) {
+	ChannelData(const PeerId &id) : PeerData(id), access(0), inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))), count(1), adminsCount(1), date(0), version(0), flags(0), flagsFull(0), isForbidden(true), botStatus(-1), inviter(0), _lastFullUpdate(0) {
 		setName(QString(), QString());
 	}
 	void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId);
@@ -472,7 +472,7 @@ public:
 	int32 count, adminsCount;
 	int32 date;
 	int32 version;
-	int32 flags;
+	int32 flags, flagsFull;
 	bool isBroadcast() const {
 		return flags & MTPDchannel_flag_is_broadcast;
 	}
@@ -500,6 +500,9 @@ public:
 	bool canPublish() const {
 		return amCreator() || amEditor();
 	}
+	bool canViewParticipants() const {
+		return flagsFull & MTPDchannelFull_flag_can_view_participants;
+	}
 	bool isForbidden;
 	bool isVerified() const {
 		return flags & MTPDchannel_flag_is_verified;