diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index e4c5ebf02..ec4e2b48e 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -98,6 +98,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_intro_next" = "NEXT"; "lng_intro_finish" = "SIGN UP"; +"lng_intro_submit" = "SUBMIT"; "lng_phone_ph" = "Your phone number"; "lng_phone_title" = "Your Phone"; @@ -124,6 +125,19 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_bad_image_for_photo" = "This image can't be sent that way.\nWould you like to send it as a file?"; +"lng_signin_title" = "Cloud password check"; +"lng_signin_desc" = "Please enter your cloud password."; +"lng_signin_recover_desc" = "Please enter code from recovery email."; +"lng_signin_password" = "Your cloud password"; +"lng_signin_code" = "Code from email"; +"lng_signin_recover" = "Recover by email"; +"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_try_password" = "I remember the password"; +"lng_signin_password_removed" = "Your cloud password was removed.\nYou can set new one in Settings."; + "lng_signup_title" = "Information and photo"; "lng_signup_desc" = "Please enter your name and\nupload a photo."; @@ -229,10 +243,12 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_section_advanced" = "Advanced"; -"lng_passcode_turn_on" = "Turn passcode on"; -"lng_passcode_change" = "Change passcode"; -"lng_passcode_create" = "Create passcode"; -"lng_passcode_remove" = "Remove passcode"; +"lng_passcode_remove_button" = "Remove"; + +"lng_passcode_turn_on" = "Turn on local passcode"; +"lng_passcode_change" = "Change local passcode"; +"lng_passcode_create" = "Create local passcode"; +"lng_passcode_remove" = "Remove local passcode"; "lng_passcode_turn_off" = "Turn off"; "lng_passcode_autolock" = "Auto-Lock"; "lng_passcode_autolock_away" = "Auto-Lock if away for:"; @@ -242,14 +258,36 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_passcode_enter_old" = "Enter old passcode"; "lng_passcode_enter_new" = "Enter new passcode"; "lng_passcode_confirm_new" = "Re-enter new passcode"; -"lng_passcode_about" = "When a passcode is set, a lock icon appears in the top menu. Click it to lock the app.\n\nNote: if you forget your 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 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_differ" = "Passcodes are different"; "lng_passcode_wrong" = "Wrong passcode"; "lng_passcode_is_same" = "Passcode was not changed"; -"lng_passcode_enter" = "Enter your Telegram Passcode"; +"lng_passcode_enter" = "Enter your local passcode"; "lng_passcode_submit" = "Submit"; "lng_passcode_logout" = "Log out"; +"lng_cloud_password_waiting" = "Confirmation sent to {email}.."; +"lng_cloud_password_change" = "Change cloud password"; +"lng_cloud_password_create" = "Create cloud password"; +"lng_cloud_password_remove" = "Remove cloud password"; +"lng_cloud_password_set" = "Turn on cloud password"; +"lng_cloud_password_edit" = "Change cloud password"; +"lng_cloud_password_enter_old" = "Enter old password"; +"lng_cloud_password_enter_new" = "Enter new password"; +"lng_cloud_password_confirm_new" = "Re-enter new password"; +"lng_cloud_password_hint" = "Enter new password hint"; +"lng_cloud_password_bad" = "Password and hint should differ."; +"lng_cloud_password_email" = "Enter recover email"; +"lng_cloud_password_bad_email" = "Incorrect email, please try other."; +"lng_cloud_password_about" = "Each new device authorization will require entering cloud password or recover by email."; +"lng_cloud_password_about_recover" = "Warning! Are you sure you don't want to\nenter a recover email address?\n\nIf you forget your cloud password\nyou will loose all your account data."; +"lng_cloud_password_almost" = "A confirmation link was sent\nto the email you provided.\n\nYour cloud password will be enabled\nonly after you follow that link."; +"lng_cloud_password_was_set" = "Your new password is enabled."; +"lng_cloud_password_removed" = "Your cloud password was removed."; +"lng_cloud_password_differ" = "Passwords are different"; +"lng_cloud_password_wrong" = "Wrong cloud password"; +"lng_cloud_password_is_same" = "Cloud password was not changed"; + "lng_connection_type" = "Connection type:"; "lng_connection_auto_connecting" = "Default (connecting..)"; "lng_connection_auto" = "Default ({type} used)"; @@ -264,8 +302,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_connection_user_ph" = "Username"; "lng_connection_password_ph" = "Password"; "lng_connection_save" = "Save"; -"lng_settings_reset" = "Terminate other sessions"; -"lng_settings_reset_sure" = "Are you sure you want to terminate all other sessions?"; +"lng_settings_show_sessions" = "Show all sessions"; +"lng_settings_reset" = "Terminate all other sessions"; +"lng_settings_reset_sure" = "Are you sure you want to terminate\nall other sessions?"; +"lng_settings_reset_one_sure" = "Do you want to terminate this session?"; "lng_settings_reset_button" = "Terminate"; "lng_settings_reset_done" = "Other sessions terminated"; "lng_settings_logout" = "Log Out"; @@ -275,10 +315,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_settings_restart_now" = "Restart"; "lng_settings_restart_later" = "Later"; +"lng_sessions_header" = "Current session"; +"lng_sessions_other_header" = "Other 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_profile_chat_unaccessible" = "Group is unaccessible"; "lng_topbar_info" = "Info"; "lng_profile_settings_section" = "Settings"; -"lng_profile_participants_section" = "Participants"; +"lng_profile_participants_section" = "Members"; "lng_profile_info" = "Contact info"; "lng_profile_group_info" = "Group info"; "lng_profile_add_contact" = "Add Contact"; @@ -320,8 +366,6 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_sure_delete_and_exit" = "Are you sure, you want to delete all message history and leave «{group}»?\n\nThis action cannot be undone."; -"lng_sure_enable_debug" = "Do you want to enable DEBUG mode?\n\nAll network events will be logged."; - "lng_message_empty" = "(empty)"; "lng_action_add_user" = "{from} added {user}"; @@ -487,7 +531,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_mediaview_saved" = "Image was saved to your [c]Downloads[/c] folder"; -"lng_new_authorization" = "{name},\nWe detected a login into your account from a new device on {day}, {date} at {time}\n\nDevice: {device}\nLocation: {location}\n\nIf this wasn't you, you can go to Settings — Terminate other sessions.\n\nThanks,\nThe Telegram Team"; +"lng_new_authorization" = "{name},\nWe detected a login into your account from a new device on {day}, {date} at {time}\n\nDevice: {device}\nLocation: {location}\n\nIf this wasn't you, you can go to Settings — Show all sessions and terminate the new session there.\n\nThanks,\nThe Telegram Team"; "lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}"; "lng_new_version_minor" = "— Bug fixes and other minor improvements"; diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 0d3e4e89e..feded50ff 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -376,6 +376,7 @@ introAlphaShowFunc: transition(easeInCirc); introTextTop: 22px; introTextSize: size(400px, 93px); introCallSkip: 15px; +introPwdTextSize: size(400px, 73px); btnIntroSep: 12px; btnIntroNext: flatButton(btnDefNext, btnDefBig) { @@ -426,9 +427,11 @@ inpIntroCode: flatInput(inpDefGray) { inpIntroName: flatInput(inpIntroPhone) { width: 192px; } +inpIntroPassword: flatInput(inpIntroPhone) { + width: 300px; +} introSelectDelta: 30px; -introSelectMaxHeight: 550px; btnSelectDone: flatButton(btnDefFlat) { color: btnYesColor; overColor: btnYesHover; @@ -489,8 +492,7 @@ countriesAlphaShowFunc: transition(easeInCirc); introErrWidth: 450px; introErrDuration: 200; introErrFunc: transition(linear); -introErrBG: #ffa5a5; -introErrColor: black;//#800000; +introErrColor: black; introErrTop: 15px; introErrHeight: 40px; introErrFont: font(16px); @@ -679,7 +681,7 @@ dlgHistFont: font(fsize); dlgNameColor: #000; dlgNameTop: 2px; dlgSystemColor: #4981af; -dlgTextColor: #888888; +dlgTextColor: #888; dlgDateFont: font(13px); dlgDateColor: #a8a8a8; @@ -1031,18 +1033,22 @@ layerPadding: margins(10px, 10px, 10px, 10px); boxFont: font(16px); boxPadding: margins(18px, 18px, 18px, 18px); -boxBG: white;//rgb(228, 233, 240); +boxVerticalMargin: 10px; + +boxWidth: 364px; +boxMaxListHeight: 600px; + +boxBG: white; boxGrayTitle: #777; -confirmWidth: 364px; +boxTitlePos: point(20px, 15px); +boxTitleFont: font(17px); +boxTitleHeight: 52px; + confirmMaxHeight: 320px; confirmCompressedSkip: 10px; -addContactWidth: 364px; addContactPadding: margins(18px, 24px, 18px, 24px); addContactDelta: 14px; -addContactTitleHeight: 52px; -addContactTitlePos: point(20px, 15px); -addContactTitleFont: font(17px); inpAddContact: flatInput(inpDefGray) { height: 42px; textMrg: margins(10px, 5px, 10px, 5px); @@ -1199,10 +1205,13 @@ profileNameInput: flatInput(setNameInput) { width: 230px; } -newGroupScroll: flatScroll(scrollDef) { - topsh: 0px; +boxScroll: flatScroll(scrollDef) { + topsh: -2px; bottomsh: -2px; } +boxNoTopScroll: flatScroll(boxScroll) { + topsh: 0; +} participantInnerAdd: flatButton(btnDefNext) { width: 145px; @@ -1218,8 +1227,6 @@ participantInnerCancel: flatButton(participantInnerAdd, btnDefBack) { participantCancel: flatButton(participantInnerAdd, btnDefBack) { width: 300px; } -participantWidth: 364px; -participantMaxHeight: 600px; participantFilter: flatInput(inpDefFlat) { width: 364px; height: 52px; @@ -1331,7 +1338,7 @@ aboutCloseButton: flatButton(contactsClose) { downTextTop: 16px; } btnInfoClose: flatButton(aboutCloseButton) { - width: confirmWidth; + width: boxWidth; } emojiTextFont: font(16px); @@ -1728,9 +1735,6 @@ langsCloseButton: flatButton(aboutCloseButton) { backgroundPadding: 10px; backgroundSize: size(108px, 193px); -backgroundScroll: flatScroll(newGroupScroll) { - topsh: -2px; -} passcodeHeaderFont: font(19px); passcodeHeaderHeight: 80px; @@ -1755,3 +1759,23 @@ mentionPadding: margins(8px, 5px, 8px, 5px); mentionTop: 11px; mentionFont: linkFont; mentionPhotoSize: msgPhotoSize; + +sessionsHeight: 440px; +sessionHeight: 50px; +sessionPadding: margins(20px, 7px, 20px, 0); +sessionsCloseButton: flatButton(aboutCloseButton) { + width: boxWidth; +} +sessionNameFont: msgNameFont; +sessionActiveFont: msgDateFont; +sessionActiveColor: #aaa; +sessionInfoFont: msgFont; +sessionInfoColor: dlgTextColor; +sessionTerminateTop: 17px; +sessionTerminateSkip: 10px; +sessionTerminate: iconedButton(notifyClose) { + iconPos: point(3px, 3px); + downIconPos: point(3px, 4px); + width: 16px; + height: 16px; +} diff --git a/Telegram/SourceFiles/_other/updater.cpp b/Telegram/SourceFiles/_other/updater.cpp index 6b5ad904f..c4bcb97e7 100644 --- a/Telegram/SourceFiles/_other/updater.cpp +++ b/Telegram/SourceFiles/_other/updater.cpp @@ -314,7 +314,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParama LPWSTR *args; int argsCount; - bool needupdate = false, autostart = false, debug = false, writeprotected = false, startintray = false; + bool needupdate = false, autostart = false, debug = false, writeprotected = false, startintray = false, testmode = false; args = CommandLineToArgvW(GetCommandLine(), &argsCount); if (args) { for (int i = 1; i < argsCount; ++i) { @@ -327,6 +327,8 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParama openLog(); } else if (equal(args[i], L"-startintray")) { startintray = true; + } else if (equal(args[i], L"-testmode")) { + testmode = true; } else if (equal(args[i], L"-writeprotected") && ++i < argsCount) { writeprotected = true; updateTo = args[i]; @@ -376,6 +378,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParama if (autostart) targs += L" -autostart"; if (debug) targs += L" -debug"; if (startintray) targs += L" -startintray"; + if (testmode) targs += L" -testmode"; bool executed = false; if (writeprotected) { // run un-elevated diff --git a/Telegram/SourceFiles/_other/updater_linux.cpp b/Telegram/SourceFiles/_other/updater_linux.cpp index 03839e797..09ab4c676 100644 --- a/Telegram/SourceFiles/_other/updater_linux.cpp +++ b/Telegram/SourceFiles/_other/updater_linux.cpp @@ -303,7 +303,7 @@ int main(int argc, char *argv[]) { writeLog("Updater started.."); - bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false; + bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false, testmode = false; char *key = 0; for (int i = 1; i < argc; ++i) { @@ -316,6 +316,8 @@ int main(int argc, char *argv[]) { openLog(); } else if (equal(argv[i], "-startintray")) { startintray = true; + } else if (equal(argv[i], "-testmode")) { + testmode = true; } else if (equal(argv[i], "-tosettings")) { tosettings = true; } else if (equal(argv[i], "-key") && ++i < argc) { @@ -379,13 +381,14 @@ int main(int argc, char *argv[]) { char path[MaxLen] = {0}; strcpy(path, (exeDir + "Telegram").c_str()); - char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_startintray[] = "-startintray"; + char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_startintray[] = "-startintray", p_testmode[] = "-testmode"; int argIndex = 0; args[argIndex++] = path; args[argIndex++] = p_noupdate; if (autostart) args[argIndex++] = p_autostart; if (debug) args[argIndex++] = p_debug; if (startintray) args[argIndex++] = p_startintray; + if (testmode) args[argIndex++] = p_testmode; if (tosettings) args[argIndex++] = p_tosettings; if (key) { args[argIndex++] = p_key; diff --git a/Telegram/SourceFiles/_other/updater_osx.m b/Telegram/SourceFiles/_other/updater_osx.m index bed7212f0..62d7cc1f8 100644 --- a/Telegram/SourceFiles/_other/updater_osx.m +++ b/Telegram/SourceFiles/_other/updater_osx.m @@ -78,7 +78,7 @@ int main(int argc, const char * argv[]) { openLog(); pid_t procId = 0; - BOOL update = YES, toSettings = NO, autoStart = NO, startInTray = NO; + BOOL update = YES, toSettings = NO, autoStart = NO, startInTray = NO, testMode = NO; NSString *key = nil; for (int i = 0; i < argc; ++i) { if ([@"-workpath" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) { @@ -101,6 +101,8 @@ int main(int argc, const char * argv[]) { _debug = YES; } else if ([@"-startintray" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) { startInTray = YES; + } else if ([@"-testmode" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) { + testMode = YES; } else if ([@"-key" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) { if (++i < argc) key = [NSString stringWithUTF8String:argv[i]]; } @@ -194,6 +196,7 @@ int main(int argc, const char * argv[]) { if (toSettings) [args addObject:@"-tosettings"]; if (_debug) [args addObject:@"-debug"]; if (startInTray) [args addObject:@"-startintray"]; + if (testMode) [args addObject:@"-testmode"]; if (autoStart) [args addObject:@"-autostart"]; if (key) { [args addObject:@"-key"]; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index c82538c40..e9524f597 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -309,7 +309,7 @@ namespace App { const MTPuser &user(*i); data = 0; bool wasContact = false; - const MTPUserStatus *status = 0; + const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty(); switch (user.type()) { case mtpc_userEmpty: { @@ -323,6 +323,7 @@ namespace App { data->setPhoto(MTP_userProfilePhotoEmpty()); data->access = 0; wasContact = (data->contact > 0); + status = &emptyStatus; data->contact = -1; } break; case mtpc_userDeleted: { @@ -336,6 +337,7 @@ namespace App { data->setPhoto(MTP_userProfilePhotoEmpty()); data->access = 0; wasContact = (data->contact > 0); + status = &emptyStatus; data->contact = -1; } break; case mtpc_userSelf: { @@ -350,7 +352,6 @@ namespace App { data->setPhone(qs(d.vphone)); data->access = 0; wasContact = (data->contact > 0); - data->contact = -1; status = &d.vstatus; if (::self != data) { diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 0293dcc0c..fec3af1d6 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -46,24 +46,16 @@ namespace { } } - class _DebugWaiter : public QObject { + class EventFilterForMac : public QObject { public: - _DebugWaiter(QObject *parent) : QObject(parent), _debugState(0) { + EventFilterForMac(QObject *parent) : QObject(parent) { } bool eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::KeyPress) { QKeyEvent *ev = static_cast(e); - switch (_debugState) { - case 0: if (ev->key() == Qt::Key_F12) _debugState = 1; break; - case 1: if (ev->key() == Qt::Key_F11) _debugState = 2; else if (ev->key() != Qt::Key_F12) _debugState = 0; break; - case 2: if (ev->key() == Qt::Key_F10) _debugState = 3; else if (ev->key() != Qt::Key_F11) _debugState = 0; break; - case 3: if (ev->key() == Qt::Key_F11) _debugState = 4; else if (ev->key() != Qt::Key_F10) _debugState = 0; break; - case 4: if (ev->key() == Qt::Key_F12) offerDebug(); if (ev->key() != Qt::Key_F11) _debugState = 0; break; - } - - if (cPlatform() == dbipMac && ev->key() == Qt::Key_W && (ev->modifiers() & (Qt::MetaModifier | Qt::ControlModifier))) { + if (ev->key() == Qt::Key_W && (ev->modifiers() & (Qt::MetaModifier | Qt::ControlModifier))) { if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) { App::wnd()->minimizeToTray(); return true; @@ -72,15 +64,7 @@ namespace { } return QObject::eventFilter(o, e); } - void offerDebug() { - ConfirmBox *box = new ConfirmBox(lang(lng_sure_enable_debug)); - connect(box, SIGNAL(confirmed()), App::app(), SLOT(onEnableDebugMode())); - App::wnd()->showLayer(box); - } - private: - - int _debugState; }; } @@ -101,7 +85,9 @@ Application::Application(int &argc, char **argv) : PsApplication(argc, argv), } mainApp = this; - installEventFilter(new _DebugWaiter(this)); + if (cPlatform() == dbipMac) { + installEventFilter(new EventFilterForMac(this)); + } QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/OpenSans-Regular.ttf")); QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/OpenSans-Bold.ttf")); @@ -306,9 +292,9 @@ void Application::selfPhotoCleared(const MTPUserProfilePhoto &result) { emit peerPhotoDone(App::self()->id); } -void Application::chatPhotoCleared(PeerId peer, const MTPmessages_StatedMessage &result) { +void Application::chatPhotoCleared(PeerId peer, const MTPUpdates &updates) { if (App::main()) { - App::main()->sentFullDataReceived(0, result); + App::main()->sentUpdatesReceived(updates); } cancelPhotoUpdate(peer); emit peerPhotoDone(peer); @@ -323,9 +309,9 @@ void Application::selfPhotoDone(const MTPphotos_Photo &result) { emit peerPhotoDone(App::self()->id); } -void Application::chatPhotoDone(PeerId peer, const MTPmessages_StatedMessage &result) { +void Application::chatPhotoDone(PeerId peer, const MTPUpdates &updates) { if (App::main()) { - App::main()->sentFullDataReceived(0, result); + App::main()->sentUpdatesReceived(updates); } cancelPhotoUpdate(peer); emit peerPhotoDone(peer); @@ -346,12 +332,6 @@ void Application::peerClearPhoto(PeerId peer) { } } -//void Application::writeUserConfigIn(uint64 ms) { -// if (!writeUserConfigTimer.isActive()) { -// writeUserConfigTimer.start(ms); -// } -//} - void Application::killDownloadSessionsStart(int32 dc) { if (killDownloadSessionTimes.constFind(dc) == killDownloadSessionTimes.cend()) { killDownloadSessionTimes.insert(dc, getms() + MTPAckSendWaiting + MTPKillFileSessionTimeout); @@ -372,10 +352,6 @@ void Application::checkLocalTime() { if (App::main()) App::main()->checkLastUpdate(checkms()); } -//void Application::onWriteUserConfig() { -// Local::writeUserSettings(); -//} - void Application::onAppStateChanged(Qt::ApplicationState state) { checkLocalTime(); if (window) window->updateIsActive((state == Qt::ApplicationActive) ? cOnlineFocusTimeout() : cOfflineBlurTimeout()); @@ -416,8 +392,14 @@ void Application::photoUpdated(MsgId msgId, const MTPInputFile &file) { } } -void Application::onEnableDebugMode() { - if (!cDebug()) { +void Application::onSwitchDebugMode() { + if (cDebug()) { + QFile(cWorkingDir() + qsl("tdata/withdebug")).remove(); + cSetDebug(false); + cSetRestarting(true); + cSetRestartingToSettings(true); + App::quit(); + } else { logsInitDebug(); cSetDebug(true); QFile f(cWorkingDir() + qsl("tdata/withdebug")); @@ -425,8 +407,25 @@ void Application::onEnableDebugMode() { f.write("1"); f.close(); } + App::wnd()->hideLayer(); } - App::wnd()->hideLayer(); +} + +void Application::onSwitchTestMode() { + if (cTestMode()) { + QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove(); + cSetTestMode(false); + } else { + QFile f(cWorkingDir() + qsl("tdata/withtestmode")); + if (f.open(QIODevice::WriteOnly)) { + f.write("1"); + f.close(); + } + cSetTestMode(true); + } + cSetRestarting(true); + cSetRestartingToSettings(true); + App::quit(); } Application::UpdatingState Application::updatingState() { diff --git a/Telegram/SourceFiles/application.h b/Telegram/SourceFiles/application.h index a55d8f76d..78d58834d 100644 --- a/Telegram/SourceFiles/application.h +++ b/Telegram/SourceFiles/application.h @@ -64,9 +64,9 @@ public: void stopUpdate(); void selfPhotoCleared(const MTPUserProfilePhoto &result); - void chatPhotoCleared(PeerId peer, const MTPmessages_StatedMessage &result); + void chatPhotoCleared(PeerId peer, const MTPUpdates &updates); void selfPhotoDone(const MTPphotos_Photo &result); - void chatPhotoDone(PeerId peerId, const MTPmessages_StatedMessage &rersult); + void chatPhotoDone(PeerId peerId, const MTPUpdates &updates); bool peerPhotoFail(PeerId peerId, const RPCError &e); void peerClearPhoto(PeerId peer); @@ -107,8 +107,8 @@ public slots: void photoUpdated(MsgId msgId, const MTPInputFile &file); - void onEnableDebugMode(); -// void onWriteUserConfig(); + void onSwitchDebugMode(); + void onSwitchTestMode(); void killDownloadSessions(); void onAppStateChanged(Qt::ApplicationState state); diff --git a/Telegram/SourceFiles/boxes/aboutbox.cpp b/Telegram/SourceFiles/boxes/aboutbox.cpp index 6d7a399a0..267f414cf 100644 --- a/Telegram/SourceFiles/boxes/aboutbox.cpp +++ b/Telegram/SourceFiles/boxes/aboutbox.cpp @@ -25,11 +25,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org 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) + (DevChannel ? " dev" : ""))) + qsl("[/a]"), st::aboutVersion, st::defaultTextStyle), -_text(this, lang(lng_about_text), st::aboutLabel, st::aboutTextStyle), -_hiding(false), a_opacity(0, 1) { +_text(this, lang(lng_about_text), st::aboutLabel, st::aboutTextStyle) { - _width = st::aboutWidth; - _height = st::aboutHeight; + resizeMaxHeight(st::aboutWidth, st::aboutHeight); _version.move(0, st::aboutVersionTop); _text.move(0, st::aboutTextTop); @@ -37,15 +35,11 @@ _hiding(false), a_opacity(0, 1) { _headerWidth = st::aboutHeaderFont->m.width(qsl("Telegram ")); _subheaderWidth = st::aboutSubheaderFont->m.width(qsl("Desktop")); - _done.move(0, _height - _done.height()); + _done.move(0, height() - _done.height()); connect(&_done, SIGNAL(clicked()), this, SLOT(onClose())); - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void AboutBox::hideAll() { @@ -63,65 +57,21 @@ void AboutBox::showAll() { void AboutBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { onClose(); - } else if (e->key() == Qt::Key_Escape) { - onClose(); + } else { + AbstractBox::keyPressEvent(e); } } -void AboutBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void AboutBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(0, 0, _width, _height, st::boxBG->b); + if (paint(p)) return; - p.drawPixmap(QPoint((_width - st::aboutIcon.pxWidth()) / 2, st::aboutIconTop), App::sprite(), st::aboutIcon); + 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.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")); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } -} - -void AboutBox::animStep(float64 ms) { - if (ms >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - setFocus(); - } - } else { - a_opacity.update(ms, anim::linear); - } - update(); -} - -void AboutBox::onClose() { - emit closed(); -} - -void AboutBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -AboutBox::~AboutBox() { + p.setFont(st::aboutSubheaderFont->f); + p.drawText((width() - (_headerWidth + _subheaderWidth)) / 2 + _headerWidth, st::aboutHeaderTop + st::aboutSubheaderFont->ascent, qsl("Desktop")); } diff --git a/Telegram/SourceFiles/boxes/aboutbox.h b/Telegram/SourceFiles/boxes/aboutbox.h index 8566ffa22..35d3dd210 100644 --- a/Telegram/SourceFiles/boxes/aboutbox.h +++ b/Telegram/SourceFiles/boxes/aboutbox.h @@ -17,37 +17,25 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class AboutBox : public LayeredWidget { +class AboutBox : public AbstractBox { Q_OBJECT public: AboutBox(); - void parentResized(); - void animStep(float64 ms); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); - ~AboutBox(); - -public slots: - - void onClose(); - -private: + +protected: void hideAll(); void showAll(); - int32 _width, _height; +private: + BottomButton _done; FlatLabel _version, _text; int32 _headerWidth, _subheaderWidth; - - bool _hiding; - QPixmap _cache; - - anim::fvalue a_opacity; }; diff --git a/Telegram/SourceFiles/boxes/abstractbox.cpp b/Telegram/SourceFiles/boxes/abstractbox.cpp new file mode 100644 index 000000000..a616475d8 --- /dev/null +++ b/Telegram/SourceFiles/boxes/abstractbox.cpp @@ -0,0 +1,159 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "lang.h" + +#include "localstorage.h" + +#include "abstractbox.h" +#include "mainwidget.h" +#include "window.h" + +AbstractBox::AbstractBox() : _maxHeight(0), _hiding(false), a_opacity(0, 1) { + resize(st::boxWidth, 0); +} + +void AbstractBox::prepare() { + showAll(); + _cache = myGrab(this, rect()); + hideAll(); +} + +void AbstractBox::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Escape) { + onClose(); + } else { + LayeredWidget::keyPressEvent(e); + } +} + +void AbstractBox::parentResized() { + int32 newHeight = countHeight(); + setGeometry((App::wnd()->width() - width()) / 2, (App::wnd()->height() - newHeight) / 2, width(), newHeight); + update(); +} + +bool AbstractBox::paint(QPainter &p) { + bool result = true; + if (_cache.isNull()) { + result = (_hiding && a_opacity.current() < 0.01); + + // fill bg + p.fillRect(rect(), st::boxBG->b); + } else { + p.setOpacity(a_opacity.current()); + p.drawPixmap(0, 0, _cache); + } + return result; +} + +void AbstractBox::paintTitle(QPainter &p, const QString &title, bool withShadow) { + if (withShadow) { + // paint shadow + p.fillRect(0, st::boxTitleHeight, width(), st::scrollDef.topsh, st::scrollDef.shColor->b); + } + + // paint box title + p.setFont(st::boxTitleFont->f); + p.setPen(st::black->p); + p.drawText(st::boxTitlePos.x(), st::boxTitlePos.y() + st::boxTitleFont->ascent, title); +} + +void AbstractBox::paintGrayTitle(QPainter &p, const QString &title) { + // draw box title + p.setFont(st::boxFont->f); + p.setPen(st::boxGrayTitle->p); + p.drawText(QRect(st::boxTitlePos.x(), st::boxTitlePos.y(), width() - 2 * st::boxTitlePos.x(), st::boxFont->height), title, style::al_top); +} + +void AbstractBox::paintEvent(QPaintEvent *e) { + QPainter p(this); + if (paint(p)) return; +} + +void AbstractBox::animStep(float64 ms) { + if (ms >= 1) { + a_opacity.finish(); + _cache = QPixmap(); + if (!_hiding) { + showAll(); + showDone(); + } + } else { + a_opacity.update(ms, anim::linear); + } + update(); +} + +void AbstractBox::setMaxHeight(int32 maxHeight) { + resizeMaxHeight(width(), maxHeight); +} + +void AbstractBox::resizeMaxHeight(int32 newWidth, int32 maxHeight) { + if (width() != newWidth || _maxHeight != maxHeight) { + _maxHeight = maxHeight; + resize(newWidth, countHeight()); + } +} + +int32 AbstractBox::countHeight() const { + return qMin(_maxHeight, App::wnd()->height() - int32(2 * st::boxVerticalMargin)); +} + +void AbstractBox::onClose() { + closePressed(); + emit closed(); +} + +void AbstractBox::startHide() { + _hiding = true; + if (_cache.isNull()) { + _cache = myGrab(this, rect()); + hideAll(); + } + a_opacity.start(0); +} + +ScrollableBox::ScrollableBox(const style::flatScroll &scroll) : AbstractBox(), +_scroll(this, scroll), _innerPtr(0), _topSkip(st::boxTitleHeight), _bottomSkip(0) { +} + +void ScrollableBox::resizeEvent(QResizeEvent *e) { + _scroll.setGeometry(0, _topSkip, width(), height() - _topSkip - _bottomSkip); +} + +void ScrollableBox::init(QWidget *inner, int32 bottomSkip, int32 topSkip) { + _bottomSkip = bottomSkip; + _topSkip = topSkip; + _innerPtr = inner; + _scroll.setWidget(_innerPtr); + _scroll.setFocusPolicy(Qt::NoFocus); + ScrollableBox::resizeEvent(0); +} + +void ScrollableBox::hideAll() { + _scroll.hide(); +} + +void ScrollableBox::showAll() { + _scroll.show(); +} + +ItemListBox::ItemListBox(const style::flatScroll &scroll) : ScrollableBox(scroll) { + setMaxHeight(st::boxMaxListHeight); +} diff --git a/Telegram/SourceFiles/boxes/abstractbox.h b/Telegram/SourceFiles/boxes/abstractbox.h new file mode 100644 index 000000000..46be690b6 --- /dev/null +++ b/Telegram/SourceFiles/boxes/abstractbox.h @@ -0,0 +1,95 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "layerwidget.h" + +class AbstractBox : public LayeredWidget { + Q_OBJECT + +public: + + AbstractBox(); + void parentResized(); + void animStep(float64 ms); + void keyPressEvent(QKeyEvent *e); + void paintEvent(QPaintEvent *e); + void startHide(); + +public slots: + + void onClose(); + +protected: + + void prepare(); + bool paint(QPainter &p); + void paintTitle(QPainter &p, const QString &title, bool withShadow); + void paintGrayTitle(QPainter &p, const QString &title); + void setMaxHeight(int32 maxHeight); + void resizeMaxHeight(int32 newWidth, int32 maxHeight); + + virtual void closePressed() { + } + virtual void hideAll() { + } + virtual void showAll() { + } + virtual void showDone() { + setFocus(); + } + +private: + + int32 _maxHeight; + int32 countHeight() const; + + bool _hiding; + QPixmap _cache; + + anim::fvalue a_opacity; +}; + +class ScrollableBox : public AbstractBox { +public: + + ScrollableBox(const style::flatScroll &scroll); + void resizeEvent(QResizeEvent *e); + +protected: + + void init(QWidget *inner, int32 bottomSkip = 0, int32 topSkip = st::boxTitleHeight); + + virtual void hideAll(); + virtual void showAll(); + + ScrollArea _scroll; + +private: + + QWidget *_innerPtr; + int32 _topSkip, _bottomSkip; + +}; + +class ItemListBox : public ScrollableBox { +public: + + ItemListBox(const style::flatScroll &scroll); + +}; \ No newline at end of file diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index b2b7a0ff4..8b3e84849 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -31,7 +31,7 @@ AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : _firstInput(this, st::inpAddContact, lang(lng_signup_firstname), fname), _lastInput(this, st::inpAddContact, lang(lng_signup_lastname), lname), _phoneInput(this, st::inpAddContact, lang(lng_contact_phone), phone.isEmpty() ? phone : App::formatPhone(phone)), - _contactId(0), _addRequest(0), a_opacity(0, 1), _hiding(false) { + _contactId(0), _addRequest(0) { if (!phone.isEmpty()) { _phoneInput.setDisabled(true); @@ -48,45 +48,32 @@ AddContactBox::AddContactBox(PeerData *peer) : _firstInput(this, st::inpAddContact, lang(peer->chat ? lng_dlg_new_group_name : lng_signup_firstname), peer->chat ? peer->name : peer->asUser()->firstName), _lastInput(this, st::inpAddContact, lang(lng_signup_lastname), peer->chat ? QString() : peer->asUser()->lastName), _phoneInput(this, st::inpAddContact, lang(lng_contact_phone)), - _contactId(0), _addRequest(0), a_opacity(0, 1), _hiding(false) { + _contactId(0), _addRequest(0) { initBox(); } void AddContactBox::initBox() { - _width = st::addContactWidth; if (_peer) { if (_peer->chat) { _boxTitle = lang(lng_edit_group_title); - _height = st::addContactTitleHeight + st::addContactPadding.top() + 1 * _firstInput.height() + st::addContactPadding.bottom() + _addButton.height(); + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 1 * _firstInput.height() + st::addContactPadding.bottom() + _addButton.height()); } else { _boxTitle = lang(_peer == App::self() ? lng_edit_self_title : lng_edit_contact_title); - _height = st::addContactTitleHeight + st::addContactPadding.top() + 2 * _firstInput.height() + 1 * st::addContactDelta + st::addContactPadding.bottom() + _addButton.height(); + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 2 * _firstInput.height() + 1 * st::addContactDelta + st::addContactPadding.bottom() + _addButton.height()); } } else { bool readyToAdd = !_phoneInput.text().isEmpty() && (!_firstInput.text().isEmpty() || !_lastInput.text().isEmpty()); _boxTitle = lang(readyToAdd ? lng_confirm_contact_data : lng_enter_contact_data); - _height = st::addContactTitleHeight + st::addContactPadding.top() + 3 * _firstInput.height() + 2 * st::addContactDelta + st::addContactPadding.bottom() + _addButton.height(); + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 3 * _firstInput.height() + 2 * st::addContactDelta + st::addContactPadding.bottom() + _addButton.height()); } - _firstInput.setGeometry(st::addContactPadding.left(), st::addContactTitleHeight + st::addContactPadding.top(), _width - st::addContactPadding.left() - st::addContactPadding.right(), _firstInput.height()); - _lastInput.setGeometry(st::addContactPadding.left(), _firstInput.y() + _firstInput.height() + st::addContactDelta, _firstInput.width(), _firstInput.height()); - _phoneInput.setGeometry(st::addContactPadding.left(), _lastInput.y() + _lastInput.height() + st::addContactDelta, _lastInput.width(), _lastInput.height()); - - int32 buttonTop = (_peer ? (_peer->chat ? _firstInput : _lastInput) : _phoneInput).y() + _phoneInput.height() + st::addContactPadding.bottom(); - _cancelButton.move(0, buttonTop); - _addButton.move(_width - _addButton.width(), buttonTop); - _retryButton.move(_width - _retryButton.width(), buttonTop); _retryButton.hide(); connect(&_addButton, SIGNAL(clicked()), this, SLOT(onSend())); connect(&_retryButton, SIGNAL(clicked()), this, SLOT(onRetry())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void AddContactBox::hideAll() { @@ -114,6 +101,14 @@ void AddContactBox::showAll() { _cancelButton.show(); } +void AddContactBox::showDone() { + if ((_firstInput.text().isEmpty() && _lastInput.text().isEmpty()) || _phoneInput.isHidden() || !_phoneInput.isEnabled()) { + _firstInput.setFocus(); + } else { + _phoneInput.setFocus(); + } +} + void AddContactBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (_firstInput.hasFocus()) { @@ -154,65 +149,40 @@ void AddContactBox::keyPressEvent(QKeyEvent *e) { onSend(); } } - } else if (e->key() == Qt::Key_Escape) { - onCancel(); + } else { + AbstractBox::keyPressEvent(e); } } -void AddContactBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void AddContactBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); + if (paint(p)) return; - // paint shadows - if (_retryButton.isHidden()) { - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - } - p.fillRect(0, size().height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); - - // paint button sep - p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - - // draw box title / text - p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - if (_retryButton.isHidden()) { - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, _boxTitle); - } else { - int32 h = size().height() - st::boxPadding.top() * 2 - _retryButton.height() - st::boxPadding.bottom(); - p.drawText(QRect(st::boxPadding.left(), st::boxPadding.top(), _width - st::boxPadding.left() - st::boxPadding.right(), h), lng_contact_not_joined(lt_name, _sentName), style::al_topleft); - } - } + if (_retryButton.isHidden()) { + paintTitle(p, _boxTitle, true); } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); + // draw box text + p.setPen(st::black->p); + p.setFont(st::boxTitleFont->f); + int32 h = size().height() - st::boxPadding.top() * 2 - _retryButton.height() - st::boxPadding.bottom(); + p.drawText(QRect(st::boxPadding.left(), st::boxPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), h), lng_contact_not_joined(lt_name, _sentName), style::al_topleft); } + + // paint shadows + p.fillRect(0, size().height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); + + // paint button sep + p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); } -void AddContactBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - if ((_firstInput.text().isEmpty() && _lastInput.text().isEmpty()) || _phoneInput.isHidden() || !_phoneInput.isEnabled()) { - _firstInput.setFocus(); - } else { - _phoneInput.setFocus(); - } - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); +void AddContactBox::resizeEvent(QResizeEvent *e) { + _firstInput.setGeometry(st::addContactPadding.left(), st::boxTitleHeight + st::addContactPadding.top(), width() - st::addContactPadding.left() - st::addContactPadding.right(), _firstInput.height()); + _lastInput.setGeometry(st::addContactPadding.left(), _firstInput.y() + _firstInput.height() + st::addContactDelta, _firstInput.width(), _firstInput.height()); + _phoneInput.setGeometry(st::addContactPadding.left(), _lastInput.y() + _lastInput.height() + st::addContactDelta, _lastInput.width(), _lastInput.height()); + + _cancelButton.move(0, height() - _cancelButton.height()); + _addButton.move(width() - _addButton.width(), height() - _addButton.height()); + _retryButton.move(width() - _retryButton.width(), height() - _retryButton.height()); } void AddContactBox::onSend() { @@ -294,7 +264,7 @@ bool AddContactBox::onSaveFail(const RPCError &error) { } void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { - if (_hiding || !App::main()) return; + if (isHidden() || !App::main()) return; const MTPDcontacts_importedContacts &d(res.c_contacts_importedContacts()); App::feedUsers(d.vusers); @@ -320,17 +290,15 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) { _lastInput.hide(); _phoneInput.hide(); _retryButton.show(); - int32 theight = st::addContactTitleFont->m.boundingRect(0, 0, _width - st::boxPadding.left() - st::boxPadding.right(), 1, Qt::TextWordWrap, lng_contact_not_joined(lt_name, _sentName)).height(); + int32 theight = st::boxTitleFont->m.boundingRect(0, 0, width() - st::boxPadding.left() - st::boxPadding.right(), 1, Qt::TextWordWrap, lng_contact_not_joined(lt_name, _sentName)).height(); int32 h = st::boxPadding.top() * 2 + theight + _retryButton.height() + st::boxPadding.bottom(); - resize(_width, h); - _retryButton.move(_retryButton.x(), h - _retryButton.height()); - _cancelButton.move(_cancelButton.x(), h - _retryButton.height()); + setMaxHeight(h); update(); } } -void AddContactBox::onSaveChatDone(const MTPmessages_StatedMessage &result) { - App::main()->sentFullDataReceived(0, result); +void AddContactBox::onSaveChatDone(const MTPUpdates &updates) { + App::main()->sentUpdatesReceived(updates); emit closed(); } @@ -340,10 +308,6 @@ void AddContactBox::onSaveUserDone(const MTPcontacts_ImportedContacts &res) { emit closed(); } -void AddContactBox::onCancel() { - emit closed(); -} - void AddContactBox::onRetry() { _addRequest = 0; _contactId = 0; @@ -359,18 +323,6 @@ void AddContactBox::onRetry() { _phoneInput.setDisabled(false); _retryButton.hide(); _firstInput.setFocus(); - resize(_width, _height); + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 3 * _firstInput.height() + 2 * st::addContactDelta + st::addContactPadding.bottom() + _addButton.height()); update(); } - -void AddContactBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -AddContactBox::~AddContactBox() { -} diff --git a/Telegram/SourceFiles/boxes/addcontactbox.h b/Telegram/SourceFiles/boxes/addcontactbox.h index 4f0d7f753..630a36cb8 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.h +++ b/Telegram/SourceFiles/boxes/addcontactbox.h @@ -17,39 +17,38 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class AddContactBox : public LayeredWidget, public RPCSender { +class AddContactBox : public AbstractBox, public RPCSender { Q_OBJECT public: AddContactBox(QString fname = QString(), QString lname = QString(), QString phone = QString()); AddContactBox(PeerData *peer); - void parentResized(); - void animStep(float64 dt); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); - ~AddContactBox(); + void resizeEvent(QResizeEvent *e); public slots: void onSend(); void onRetry(); - void onCancel(); -private: +protected: void hideAll(); void showAll(); + void showDone(); + +private: void onImportDone(const MTPcontacts_ImportedContacts &res); void onSaveSelfDone(const MTPUser &user); bool onSaveSelfFail(const RPCError &error); - void onSaveChatDone(const MTPmessages_StatedMessage &result); + void onSaveChatDone(const MTPUpdates &updates); void onSaveUserDone(const MTPcontacts_ImportedContacts &res); bool onSaveFail(const RPCError &e); @@ -58,17 +57,11 @@ private: PeerData *_peer; QString _boxTitle; - int32 _width, _height; FlatButton _addButton, _retryButton, _cancelButton; FlatInput _firstInput, _lastInput, _phoneInput; uint64 _contactId; - QPixmap _cache; - mtpRequestId _addRequest; QString _sentName; - - anim::fvalue a_opacity; - bool _hiding; }; diff --git a/Telegram/SourceFiles/boxes/addparticipantbox.cpp b/Telegram/SourceFiles/boxes/addparticipantbox.cpp deleted file mode 100644 index 38de2fbf3..000000000 --- a/Telegram/SourceFiles/boxes/addparticipantbox.cpp +++ /dev/null @@ -1,1004 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014 John Preston, https://desktop.telegram.org -*/ -#include "stdafx.h" -#include "lang.h" - -#include "addparticipantbox.h" -#include "mainwidget.h" -#include "window.h" - -AddParticipantInner::AddParticipantInner(ChatData *chat) : _chat(chat), -_contacts(&App::main()->contactsList()), -_sel(0), -_filteredSel(-1), -_mouseSel(false), -_selCount(0), -_searching(false), -_byUsernameSel(-1), -_addContactLnk(this, lang(lng_add_contact_button)) { - - connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); - - for (DialogRow *r = _contacts->list.begin; r != _contacts->list.end; r = r->next) { - r->attached = 0; - } - - _filter = qsl("a"); - updateFilter(); - - connect(App::main(), SIGNAL(dialogRowReplaced(DialogRow*,DialogRow*)), this, SLOT(onDialogRowReplaced(DialogRow*,DialogRow*))); - connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*))); - connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*))); - connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*))); -} - -void AddParticipantInner::peerUpdated(PeerData *peer) { - if (!peer || peer == _chat) { - if (_chat->forbidden) { - App::wnd()->hideLayer(); - } else if (!_chat->participants.isEmpty() || _chat->count <= 0) { - for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i ) { - delete i.value(); - } - _contactsData.clear(); - for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) { - row->attached = 0; - } - if (!_filter.isEmpty()) { - for (int32 j = 0, s = _filtered.size(); j < s; ++j) { - _filtered[j]->attached = 0; - } - } - } - } else if (!peer->chat) { - ContactsData::iterator i = _contactsData.find(peer->asUser()); - if (i != _contactsData.cend()) { - for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) { - if (row->attached == i.value()) row->attached = 0; - } - if (!_filter.isEmpty()) { - for (int32 j = 0, s = _filtered.size(); j < s; ++j) { - if (_filtered[j]->attached == i.value()) _filtered[j]->attached = 0; - } - } - delete i.value(); - _contactsData.erase(i); - } - } - - parentWidget()->update(); -} - -void AddParticipantInner::loadProfilePhotos(int32 yFrom) { - int32 yTo = yFrom + (parentWidget() ? parentWidget()->height() : App::wnd()->height()) * 5; - MTP::clearLoaderPriorities(); - - if (yTo < 0) return; - if (yFrom < 0) yFrom = 0; - - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - if (_contacts->list.count) { - _contacts->list.adjustCurrent(yFrom, rh); - for ( - DialogRow *preloadFrom = _contacts->list.current; - preloadFrom != _contacts->list.end && preloadFrom->pos * rh < yTo; - preloadFrom = preloadFrom->next - ) { - preloadFrom->history->peer->photo->load(); - } - } - yFrom -= _contacts->list.count * rh + st::searchedBarHeight; - yTo -= _contacts->list.count * rh + st::searchedBarHeight; - int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsername.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsername.size()) to = _byUsername.size(); - for (; from < to; ++from) { - _byUsername[from]->photo->load(); - } - } - } else if (!_filtered.isEmpty()) { - int32 from = yFrom / rh; - if (from < 0) from = 0; - if (from < _filtered.size()) { - int32 to = (yTo / rh) + 1; - if (to > _filtered.size()) to = _filtered.size(); - - for (; from < to; ++from) { - _filtered[from]->history->peer->photo->load(); - } - } - yFrom -= _filtered.size() * rh + st::searchedBarHeight; - yTo -= _filtered.size() * rh + st::searchedBarHeight; - from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsernameFiltered.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size(); - for (; from < to; ++from) { - _byUsernameFiltered[from]->photo->load(); - } - } - } -} - -AddParticipantInner::ContactData *AddParticipantInner::contactData(DialogRow *row) { - ContactData *data = (ContactData*)row->attached; - if (!data) { - UserData *user = row->history->peer->asUser(); - ContactsData::const_iterator i = _contactsData.constFind(user); - if (i == _contactsData.cend()) { - _contactsData.insert(user, data = new ContactData()); - data->inchat = _chat->participants.contains(user); - data->check = false; - data->name.setText(st::profileListNameFont, user->name, _textNameOptions); - data->online = App::onlineText(user, _time); - } else { - data = i.value(); - } - row->attached = data; - } - return data; -} - -void AddParticipantInner::paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel) { - int32 left = st::profileListPadding.width(); - - if (data->inchat || data->check || _selCount + _chat->count >= cMaxGroupCount()) { - sel = false; - } - - if (sel || data->inchat || data->check) { - p.fillRect(0, 0, width(), 2 * st::profileListPadding.height() + st::profileListPhotoSize, ((data->inchat || data->check) ? st::profileActiveBG : st::profileHoverBG)->b); - } - - p.drawPixmap(left, st::profileListPadding.height(), user->photo->pix(st::profileListPhotoSize)); - - if (data->inchat || data->check) { - p.setPen(st::white->p); - } else { - p.setPen(st::profileListNameColor->p); - } - data->name.drawElided(p, left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListNameTop, width() - st::participantDelta - st::profileListPadding.width() * 2 - st::profileListPhotoSize - st::profileListPadding.width() * 2); - - if (sel || data->check) { - p.drawPixmap(QPoint(width() - st::profileCheckRect.pxWidth() - st::profileCheckDeltaX, st::profileListPadding.height() + (st::profileListPhotoSize - st::profileCheckRect.pxHeight()) / 2 - st::profileCheckDeltaY), App::sprite(), (data->check ? st::profileCheckActiveRect : st::profileCheckRect)); - } - - bool uname = (data->online.at(0) == '@'); - p.setFont(st::profileSubFont->f); - if (uname && !data->inchat && !data->check && !_lastQuery.isEmpty() && user->username.startsWith(_lastQuery, Qt::CaseInsensitive)) { - int32 availw = width() - (left + st::profileListPhotoSize + st::profileListPadding.width() * 2); - QString first = '@' + user->username.mid(0, _lastQuery.size()), second = user->username.mid(_lastQuery.size()); - int32 w = st::profileSubFont->m.width(first); - if (w >= availw || second.isEmpty()) { - p.setPen(st::profileOnlineColor->p); - p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(first, Qt::ElideRight, availw)); - } else { - p.setPen(st::profileOnlineColor->p); - p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, first); - p.setPen(st::profileOfflineColor->p); - p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width() + w, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(second, Qt::ElideRight, availw - w)); - } - } else { - if (data->inchat || data->check) { - p.setPen(st::white->p); - } else { - p.setPen(((uname || App::onlineColorUse(user->onlineTill, _time)) ? st::profileOnlineColor : st::profileOfflineColor)->p); - } - p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online); - } -} - -void AddParticipantInner::paintEvent(QPaintEvent *e) { - QRect r(e->rect()); - QPainter p(this); - - _time = unixtime(); - p.fillRect(r, st::white->b); - - int32 yFrom = r.top(), yTo = r.bottom(); - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - if (_contacts->list.count || !_byUsername.isEmpty()) { - if (_contacts->list.count) { - _contacts->list.adjustCurrent(yFrom, rh); - - DialogRow *drawFrom = _contacts->list.current; - p.translate(0, drawFrom->pos * rh); - while (drawFrom != _contacts->list.end && drawFrom->pos * rh < yTo) { - paintDialog(p, drawFrom->history->peer->asUser(), contactData(drawFrom), (drawFrom == _sel)); - p.translate(0, rh); - drawFrom = drawFrom->next; - } - } - if (!_byUsername.isEmpty()) { - p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); - p.setFont(st::searchedBarFont->f); - p.setPen(st::searchedBarColor->p); - p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center); - p.translate(0, st::searchedBarHeight); - - yFrom -= _contacts->list.count * rh + st::searchedBarHeight; - yTo -= _contacts->list.count * rh + st::searchedBarHeight; - int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsername.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsername.size()) to = _byUsername.size(); - - p.translate(0, from * rh); - for (; from < to; ++from) { - paintDialog(p, _byUsername[from], d_byUsername[from], (_byUsernameSel == from)); - p.translate(0, rh); - } - } - } - } else { - p.setFont(st::noContactsFont->f); - p.setPen(st::noContactsColor->p); - p.drawText(QRect(0, 0, width(), st::noContactsHeight - ((cContactsReceived() && !_searching) ? st::noContactsFont->height : 0)), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_loading), style::al_center); - } - } else { - if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { - p.setFont(st::noContactsFont->f); - p.setPen(st::noContactsColor->p); - p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_loading), style::al_center); - } else { - if (!_filtered.isEmpty()) { - int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _filtered.size()) { - int32 to = (yTo / rh) + 1; - if (to > _filtered.size()) to = _filtered.size(); - - p.translate(0, from * rh); - for (; from < to; ++from) { - paintDialog(p, _filtered[from]->history->peer->asUser(), contactData(_filtered[from]), (_filteredSel == from)); - p.translate(0, rh); - } - } - } - if (!_byUsernameFiltered.isEmpty()) { - p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); - p.setFont(st::searchedBarFont->f); - p.setPen(st::searchedBarColor->p); - p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center); - p.translate(0, st::searchedBarHeight); - - yFrom -= _filtered.size() * rh + st::searchedBarHeight; - yTo -= _filtered.size() * rh + st::searchedBarHeight; - int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsernameFiltered.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size(); - - p.translate(0, from * rh); - for (; from < to; ++from) { - paintDialog(p, _byUsernameFiltered[from], d_byUsernameFiltered[from], (_byUsernameSel == from)); - p.translate(0, rh); - } - } - } - } - } -} - -void AddParticipantInner::enterEvent(QEvent *e) { - setMouseTracking(true); -} - -void AddParticipantInner::leaveEvent(QEvent *e) { - setMouseTracking(false); - if (_sel || _filteredSel >= 0 || _byUsernameSel >= 0) { - _sel = 0; - _filteredSel = _byUsernameSel = -1; - parentWidget()->update(); - } -} - -void AddParticipantInner::mouseMoveEvent(QMouseEvent *e) { - _mouseSel = true; - _lastMousePos = e->globalPos(); - updateSel(); -} - -void AddParticipantInner::mousePressEvent(QMouseEvent *e) { - _mouseSel = true; - _lastMousePos = e->globalPos(); - updateSel(); - if (e->button() == Qt::LeftButton) { - chooseParticipant(); - } -} - -void AddParticipantInner::chooseParticipant() { - _time = unixtime(); - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from; - if (_filter.isEmpty()) { - if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) { - if (d_byUsername[_byUsernameSel]->inchat) return; - changeCheckState(d_byUsername[_byUsernameSel]); - } else { - if (!_sel || contactData(_sel)->inchat) return; - changeCheckState(_sel); - } - } else { - if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) { - if (d_byUsernameFiltered[_byUsernameSel]->inchat) return; - changeCheckState(d_byUsernameFiltered[_byUsernameSel]); - - ContactData *moving = d_byUsernameFiltered[_byUsernameSel]; - int32 i = 0, l = d_byUsername.size(); - for (; i < l; ++i) { - if (d_byUsername[i] == moving) { - break; - } - } - if (i == l) { - d_byUsername.push_back(moving); - _byUsername.push_back(_byUsernameFiltered[_byUsernameSel]); - for (i = 0, l = _byUsernameDatas.size(); i < l;) { - if (_byUsernameDatas[i] == moving) { - _byUsernameDatas.removeAt(i); - --l; - } else { - ++i; - } - } - } - } else { - if (_filteredSel < 0 || _filteredSel >= _filtered.size() || contactData(_filtered[_filteredSel])->inchat) return; - changeCheckState(_filtered[_filteredSel]); - } - emit selectAllQuery(); - } - parentWidget()->update(); -} - -void AddParticipantInner::changeCheckState(DialogRow *row) { - changeCheckState(contactData(row)); -} - -void AddParticipantInner::changeCheckState(ContactData *data) { - if (data->check) { - data->check = false; - --_selCount; - } else if (_selCount + _chat->count < cMaxGroupCount()) { - data->check = true; - ++_selCount; - } -} - -void AddParticipantInner::peopleReceived(const QString &query, const QVector &people) { - _lastQuery = query.toLower().trimmed(); - if (_lastQuery.at(0) == '@') _lastQuery = _lastQuery.mid(1); - int32 already = _byUsernameFiltered.size(); - _byUsernameFiltered.reserve(already + people.size()); - d_byUsernameFiltered.reserve(already + people.size()); - for (QVector::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) { - int32 uid = i->c_contactFound().vuser_id.v, j = 0; - for (; j < already; ++j) { - if (_byUsernameFiltered[j]->id == App::peerFromUser(uid)) break; - } - if (j == already) { - UserData *u = App::user(uid); - ContactData *d = new ContactData(); - _byUsernameDatas.push_back(d); - d->inchat = _chat->participants.contains(u); - d->check = false; - d->name.setText(st::profileListNameFont, u->name, _textNameOptions); - d->online = '@' + u->username; - - _byUsernameFiltered.push_back(u); - d_byUsernameFiltered.push_back(d); - } - } - _searching = false; - refresh(); -} - -void AddParticipantInner::refresh() { - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - if (_contacts->list.count || !_byUsername.isEmpty()) { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - resize(width(), (_contacts->list.count * rh) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * rh))); - } else { - if (cContactsReceived()) { - if (_addContactLnk.isHidden()) _addContactLnk.show(); - } else { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - } - resize(width(), st::noContactsHeight); - } - } else { - if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - resize(width(), st::noContactsHeight); - } else { - resize(width(), (_filtered.size() * rh) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * rh))); - } - } -} - -ChatData *AddParticipantInner::chat() { - return _chat; -} - -QVector AddParticipantInner::selected() { - QVector result; - result.reserve(_contactsData.size()); - for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { - if (i.value()->check) { - result.push_back(i.key()); - } - } - for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { - if (d_byUsername[i]->check) { - result.push_back(_byUsername[i]); - } - } - return result; -} - -void AddParticipantInner::updateSel() { - if (!_mouseSel) return; - - QPoint p(mapFromGlobal(_lastMousePos)); - bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - DialogRow *newSel = (in && (p.y() >= 0) && (p.y() < _contacts->list.count * rh)) ? _contacts->list.rowAtY(p.y(), rh) : 0; - int32 byUsernameSel = (in && p.y() >= _contacts->list.count * rh + st::searchedBarHeight) ? ((p.y() - _contacts->list.count * rh - st::searchedBarHeight) / rh) : -1; - if (byUsernameSel >= _byUsername.size()) byUsernameSel = -1; - if (newSel != _sel || byUsernameSel != _byUsernameSel) { - _sel = newSel; - _byUsernameSel = byUsernameSel; - parentWidget()->update(); - } - } else { - int32 newFilteredSel = (in && p.y() >= 0 && p.y() < _filtered.size() * rh) ? (p.y() / rh) : -1; - int32 byUsernameSel = (in && p.y() >= _filtered.size() * rh + st::searchedBarHeight) ? ((p.y() - _filtered.size() * rh - st::searchedBarHeight) / rh) : -1; - if (byUsernameSel >= _byUsernameFiltered.size()) byUsernameSel = -1; - if (newFilteredSel != _filteredSel || byUsernameSel != _byUsernameSel) { - _filteredSel = newFilteredSel; - _byUsernameSel = byUsernameSel; - parentWidget()->update(); - } - } -} - -void AddParticipantInner::updateFilter(QString filter) { - _lastQuery = filter.toLower().trimmed(); - filter = textSearchKey(filter); - - _time = unixtime(); - QStringList f; - if (!filter.isEmpty()) { - QStringList filterList = filter.split(cWordSplit(), QString::SkipEmptyParts); - int l = filterList.size(); - - f.reserve(l); - for (int i = 0; i < l; ++i) { - QString filterName = filterList[i].trimmed(); - if (filterName.isEmpty()) continue; - f.push_back(filterName); - } - filter = f.join(' '); - } - if (_filter != filter) { - int32 rh = (st::profileListPhotoSize + st::profileListPadding.height() * 2); - _filter = filter; - - _byUsernameFiltered.clear(); - d_byUsernameFiltered.clear(); - for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) { - delete _byUsernameDatas[i]; - } - _byUsernameDatas.clear(); - - if (_filter.isEmpty()) { - _sel = 0; - if (_contacts->list.count) { - _sel = _contacts->list.begin; - while (_sel->next->next &&& contactData(_sel)->inchat) { - _sel = _sel->next; - } - } - if (!_sel && !_byUsername.isEmpty()) { - _byUsernameSel = 0; - while (_byUsernameSel < _byUsername.size() && d_byUsername[_byUsernameSel]->inchat) { - ++_byUsernameSel; - } - if (_byUsernameSel == _byUsername.size()) _byUsernameSel = -1; - } else { - _byUsernameSel = -1; - } - refresh(); - } else { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi; - - _filtered.clear(); - if (!f.isEmpty()) { - DialogsList *dialogsToFilter = 0; - if (_contacts->list.count) { - for (fi = fb; fi != fe; ++fi) { - DialogsIndexed::DialogsIndex::iterator i = _contacts->index.find(fi->at(0)); - if (i == _contacts->index.cend()) { - dialogsToFilter = 0; - break; - } - if (!dialogsToFilter || dialogsToFilter->count > i.value()->count) { - dialogsToFilter = i.value(); - } - } - } - if (dialogsToFilter && dialogsToFilter->count) { - _filtered.reserve(dialogsToFilter->count); - for (DialogRow *i = dialogsToFilter->begin, *e = dialogsToFilter->end; i != e; i = i->next) { - const PeerData::Names &names(i->history->peer->names); - PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni; - for (fi = fb; fi != fe; ++fi) { - QString filterName(*fi); - for (ni = nb; ni != ne; ++ni) { - if (ni->startsWith(*fi)) { - break; - } - } - if (ni == ne) { - break; - } - } - if (fi == fe) { - i->attached = 0; - _filtered.push_back(i); - } - } - } - - _byUsernameFiltered.reserve(_byUsername.size()); - d_byUsernameFiltered.reserve(d_byUsername.size()); - for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { - const PeerData::Names &names(_byUsername[i]->names); - PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni; - for (fi = fb; fi != fe; ++fi) { - QString filterName(*fi); - for (ni = nb; ni != ne; ++ni) { - if (ni->startsWith(*fi)) { - break; - } - } - if (ni == ne) { - break; - } - } - if (fi == fe) { - _byUsernameFiltered.push_back(_byUsername[i]); - d_byUsernameFiltered.push_back(d_byUsername[i]); - } - } - } - _filteredSel = -1; - if (!_filtered.isEmpty()) { - for (_filteredSel = 0; (_filteredSel < _filtered.size()) && contactData(_filtered[_filteredSel])->inchat;) { - ++_filteredSel; - } - if (_filteredSel == _filtered.size()) _filteredSel = -1; - } - _byUsernameSel = -1; - if (_filteredSel < 0 && !_byUsernameFiltered.isEmpty()) { - for (_byUsernameSel = 0; (_byUsernameSel < _byUsernameFiltered.size()) && d_byUsernameFiltered[_byUsernameSel]->inchat;) { - ++_byUsernameSel; - } - if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1; - } - - refresh(); - - _searching = true; - emit searchByUsername(); - } - if (parentWidget()) parentWidget()->update(); - loadProfilePhotos(0); - } -} - -void AddParticipantInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) { - if (!_filter.isEmpty()) { - for (FilteredDialogs::iterator i = _filtered.begin(), e = _filtered.end(); i != e;) { - if (*i == oldRow) { // this row is shown in filtered and maybe is in contacts! - if (newRow) { - *i = newRow; - ++i; - } else { - i = _filtered.erase(i); - } - } else { - ++i; - } - } - if (_filteredSel >= _filtered.size()) { - _filteredSel = -1; - } - } else { - if (_sel == oldRow) { - _sel = newRow; - } - } - _mouseSel = false; - int32 rh = (st::profileListPhotoSize + st::profileListPadding.height() * 2); - int32 newh = (_filter.isEmpty() ? _contacts->list.count : _filtered.size()) * rh; - resize(width(), newh); -} - -AddParticipantInner::~AddParticipantInner() { - for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { - delete *i; - } - for (ByUsernameDatas::const_iterator i = d_byUsername.cbegin(), e = d_byUsername.cend(); i != e; ++i) { - delete *i; - } - for (ByUsernameDatas::const_iterator i = _byUsernameDatas.cbegin(), e = _byUsernameDatas.cend(); i != e; ++i) { - delete *i; - } -} - -void AddParticipantInner::resizeEvent(QResizeEvent *e) { - _addContactLnk.move((width() - _addContactLnk.width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2); -} - -void AddParticipantInner::selectSkip(int32 dir) { - _time = unixtime(); - _mouseSel = false; - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, origDir = dir; - if (_filter.isEmpty()) { - int cur = 0; - if (_sel) { - for (DialogRow *i = _contacts->list.begin; i != _sel; i = i->next) { - ++cur; - } - } else { - cur = (_byUsernameSel >= 0) ? (_contacts->list.count + _byUsernameSel) : -1; - } - cur += dir; - if (cur <= 0) { - _sel = _contacts->list.count ? _contacts->list.begin : 0; - _byUsernameSel = (!_contacts->list.count && !_byUsername.isEmpty()) ? 0 : -1; - } else if (cur >= _contacts->list.count) { - _sel = 0; - _byUsernameSel = cur - _contacts->list.count; - if (_byUsernameSel >= _byUsername.size()) _byUsernameSel = _byUsername.size() - 1; - } else { - for (_sel = _contacts->list.begin; cur; _sel = _sel->next) { - --cur; - } - _byUsernameSel = -1; - } - if (dir > 0) { - while (_sel && _sel->next && contactData(_sel)->inchat) { - _sel = _sel->next; - } - if (!_sel || !_sel->next) { - _sel = 0; - if (!_byUsername.isEmpty()) { - if (_byUsernameSel < 0) _byUsernameSel = 0; - for (; _byUsernameSel < _byUsername.size() && d_byUsername[_byUsernameSel]->inchat;) { - ++_byUsernameSel; - } - if (_byUsernameSel == _byUsername.size()) _byUsernameSel = -1; - } - } - } else { - while (_byUsernameSel >= 0 && d_byUsername[_byUsernameSel]->inchat) { - --_byUsernameSel; - } - if (_byUsernameSel < 0) { - if (_contacts->list.count) { - if (!_sel) _sel = _contacts->list.end->prev; - for (; _sel && contactData(_sel)->inchat;) { - _sel = _sel->prev; - } - } - } - } - if (_sel) { - emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh); - } else if (_byUsernameSel >= 0) { - emit mustScrollTo((_contacts->list.count + _byUsernameSel) * rh + st::searchedBarHeight, (_contacts->list.count + _byUsernameSel + 1) * rh + st::searchedBarHeight); - } - } else { - int cur = (_filteredSel >= 0) ? _filteredSel : ((_byUsernameSel >= 0) ? (_filtered.size() + _byUsernameSel) : -1); - cur += dir; - if (cur <= 0) { - _filteredSel = _filtered.isEmpty() ? -1 : 0; - _byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1; - } else if (cur >= _filtered.size()) { - _filteredSel = -1; - _byUsernameSel = cur - _filtered.size(); - if (_byUsernameSel >= _byUsernameFiltered.size()) _byUsernameSel = _byUsernameFiltered.size() - 1; - } else { - _filteredSel = cur; - _byUsernameSel = -1; - } - if (dir > 0) { - while (_filteredSel >= 0 && _filteredSel < _filtered.size() && contactData(_filtered[_filteredSel])->inchat) { - ++_filteredSel; - } - if (_filteredSel < 0 || _filteredSel >= _filtered.size()) { - _filteredSel = -1; - if (!_byUsernameFiltered.isEmpty()) { - if (_byUsernameSel < 0) _byUsernameSel = 0; - for (; _byUsernameSel < _byUsernameFiltered.size() && d_byUsernameFiltered[_byUsernameSel]->inchat;) { - ++_byUsernameSel; - } - if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1; - } - } - } else { - while (_byUsernameSel >= 0 && d_byUsernameFiltered[_byUsernameSel]->inchat) { - --_byUsernameSel; - } - if (_byUsernameSel < 0) { - if (!_filtered.isEmpty()) { - if (_filteredSel < 0) _filteredSel = _filtered.size() - 1; - for (; _filteredSel >= 0 && contactData(_filtered[_filteredSel])->inchat;) { - --_filteredSel; - } - } - } - } - if (_filteredSel >= 0) { - emit mustScrollTo(_filteredSel * rh, (_filteredSel + 1) * rh); - } else if (_byUsernameSel >= 0) { - int skip = _filtered.size() * rh + st::searchedBarHeight; - emit mustScrollTo(skip + _byUsernameSel * rh, skip + (_byUsernameSel + 1) * rh); - } - } - parentWidget()->update(); -} - -void AddParticipantInner::selectSkipPage(int32 h, int32 dir) { - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - int32 points = h / rh; - if (!points) return; - selectSkip(points * dir); -} - -AddParticipantBox::AddParticipantBox(ChatData *chat) : - _scroll(this, st::newGroupScroll), _inner(chat), - _filter(this, st::contactsFilter, lang(lng_participant_filter)), - _invite(this, lang(lng_participant_invite), st::btnSelectDone), - _cancel(this, lang(lng_cancel), st::btnSelectCancel), - _hiding(false), a_opacity(0, 1) { - - _width = st::participantWidth; - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - if (_height > st::participantMaxHeight) _height = st::participantMaxHeight; - - resize(_width, _height); - - _scroll.setWidget(&_inner); - _scroll.setFocusPolicy(Qt::NoFocus); - - connect(&_invite, SIGNAL(clicked()), this, SLOT(onInvite())); - connect(&_cancel, SIGNAL(clicked()), this, SIGNAL(closed())); - connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(updateSel())); - connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); - connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); - connect(&_filter, SIGNAL(cancelled()), this, SLOT(onClose())); - connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int))); - connect(&_inner, SIGNAL(selectAllQuery()), &_filter, SLOT(selectAll())); - connect(&_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername())); - - _searchTimer.setSingleShot(true); - connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); -} - -bool AddParticipantBox::onSearchByUsername(bool searchCache) { - QString q = _filter.text().trimmed(); - if (q.isEmpty()) { - if (_peopleRequest) { - _peopleRequest = 0; - } - return true; - } - if (q.size() >= MinUsernameLength) { - if (searchCache) { - PeopleCache::const_iterator i = _peopleCache.constFind(q); - if (i != _peopleCache.cend()) { - _peopleQuery = q; - _peopleRequest = 0; - peopleReceived(i.value(), 0); - return true; - } - } else if (_peopleQuery != q) { - _peopleQuery = q; - _peopleFull = false; - _peopleRequest = MTP::send(MTPcontacts_Search(MTP_string(_peopleQuery), MTP_int(SearchPeopleLimit)), rpcDone(&AddParticipantBox::peopleReceived), rpcFail(&AddParticipantBox::peopleFailed)); - _peopleQueries.insert(_peopleRequest, _peopleQuery); - } - } - return false; -} - -void AddParticipantBox::onNeedSearchByUsername() { - if (!onSearchByUsername(true)) { - _searchTimer.start(AutoSearchTimeout); - } -} - -void AddParticipantBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId req) { - QString q = _peopleQuery; - - PeopleQueries::iterator i = _peopleQueries.find(req); - if (i != _peopleQueries.cend()) { - q = i.value(); - _peopleCache[q] = result; - _peopleQueries.erase(i); - } - - if (_peopleRequest == req) { - switch (result.type()) { - case mtpc_contacts_found: { - App::feedUsers(result.c_contacts_found().vusers); - _inner.peopleReceived(q, result.c_contacts_found().vresults.c_vector().v); - } break; - } - - _peopleRequest = 0; - _inner.updateSel(); - onScroll(); - } -} - -bool AddParticipantBox::peopleFailed(const RPCError &error, mtpRequestId req) { - if (_peopleRequest == req) { - _peopleRequest = 0; - _peopleFull = true; - } - return true; -} - -void AddParticipantBox::hideAll() { - _filter.hide(); - _scroll.hide(); - _cancel.hide(); - _invite.hide(); -} - -void AddParticipantBox::showAll() { - _filter.show(); - _scroll.show(); - _cancel.show(); - _invite.show(); -} - -void AddParticipantBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - onClose(); - } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { - _inner.chooseParticipant(); - } else if (e->key() == Qt::Key_Down) { - _inner.selectSkip(1); - } else if (e->key() == Qt::Key_Up) { - _inner.selectSkip(-1); - } else if (e->key() == Qt::Key_PageDown) { - _inner.selectSkipPage(_scroll.height(), 1); - } else if (e->key() == Qt::Key_PageUp) { - _inner.selectSkipPage(_scroll.height(), -1); - } else { - e->ignore(); - } -} - -void AddParticipantBox::parentResized() { - QSize s = parentWidget()->size(); - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - if (_height > st::participantMaxHeight) _height = st::participantMaxHeight; - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - -void AddParticipantBox::paintEvent(QPaintEvent *e) { - QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); - - // paint shadows - p.fillRect(0, st::participantFilter.height, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - p.fillRect(0, size().height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); - - // paint button sep - p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - - // draw box title / text - p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_profile_add_participant)); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } -} - -void AddParticipantBox::resizeEvent(QResizeEvent *e) { - LayeredWidget::resizeEvent(e); - _filter.move(st::newGroupNamePadding.left(), st::contactsAdd.height + st::newGroupNamePadding.top()); - _inner.resize(_width, _inner.height()); - _scroll.resize(_width, _height - st::contactsAdd.height - st::newGroupNamePadding.top() - _filter.height() - st::newGroupNamePadding.bottom() - _cancel.height()); - _scroll.move(0, _filter.y() + _filter.height() + st::newGroupNamePadding.bottom()); - _invite.move(width() - _invite.width(), _height - _invite.height()); - _cancel.move(0, _height - _cancel.height()); -} - -void AddParticipantBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - _filter.setFocus(); - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); -} - -void AddParticipantBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -void AddParticipantBox::onFilterUpdate() { - _scroll.scrollToY(0); - _inner.updateFilter(_filter.text()); -} - -void AddParticipantBox::onClose() { - emit closed(); -} - -void AddParticipantBox::onInvite() { - QVector users(_inner.selected()); - if (users.isEmpty()) { - _filter.setFocus(); - return; - } - - App::main()->addParticipants(_inner.chat(), users); -} - -void AddParticipantBox::onScroll() { - _inner.loadProfilePhotos(_scroll.scrollTop()); -} - -AddParticipantBox::~AddParticipantBox() { - -} diff --git a/Telegram/SourceFiles/boxes/addparticipantbox.h b/Telegram/SourceFiles/boxes/addparticipantbox.h deleted file mode 100644 index 60c666903..000000000 --- a/Telegram/SourceFiles/boxes/addparticipantbox.h +++ /dev/null @@ -1,168 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "layerwidget.h" - -class AddParticipantInner : public QWidget, public RPCSender { - Q_OBJECT - -private: - - struct ContactData; - -public: - - AddParticipantInner(ChatData *chat); - - void paintEvent(QPaintEvent *e); - void enterEvent(QEvent *e); - void leaveEvent(QEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void mousePressEvent(QMouseEvent *e); - void resizeEvent(QResizeEvent *e); - - void paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel); - void updateFilter(QString filter = QString()); - - void selectSkip(int32 dir); - void selectSkipPage(int32 h, int32 dir); - - void loadProfilePhotos(int32 yFrom); - void chooseParticipant(); - void changeCheckState(DialogRow *row); - void changeCheckState(ContactData *data); - - void peopleReceived(const QString &query, const QVector &people); - - void refresh(); - - ChatData *chat(); - QVector selected(); - - ~AddParticipantInner(); - -signals: - - void mustScrollTo(int ymin, int ymax); - void selectAllQuery(); - void searchByUsername(); - -public slots: - - void onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow); - - void updateSel(); - void peerUpdated(PeerData *peer); - -private: - - ChatData *_chat; - - int32 _time; - - DialogsIndexed *_contacts; - DialogRow *_sel; - QString _filter; - typedef QVector FilteredDialogs; - FilteredDialogs _filtered; - int32 _filteredSel; - bool _mouseSel; - - int32 _selCount; - - struct ContactData { - Text name; - QString online; - bool inchat; - bool check; - }; - typedef QMap ContactsData; - ContactsData _contactsData; - - ContactData *contactData(DialogRow *row); - - bool _searching; - QString _lastQuery; - typedef QVector ByUsernameRows; - typedef QVector ByUsernameDatas; - ByUsernameRows _byUsername, _byUsernameFiltered; - ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas - ByUsernameDatas _byUsernameDatas; - int32 _byUsernameSel; - - QPoint _lastMousePos; - LinkButton _addContactLnk; - -}; - -class AddParticipantBox : public LayeredWidget, public RPCSender { - Q_OBJECT - -public: - - AddParticipantBox(ChatData *chat); - void parentResized(); - void animStep(float64 dt); - void keyPressEvent(QKeyEvent *e); - void paintEvent(QPaintEvent *e); - void resizeEvent(QResizeEvent *e); - void startHide(); - ~AddParticipantBox(); - -public slots: - - void onFilterUpdate(); - void onClose(); - void onScroll(); - void onInvite(); - - bool onSearchByUsername(bool searchCache = false); - void onNeedSearchByUsername(); - -private: - - void hideAll(); - void showAll(); - - ScrollArea _scroll; - AddParticipantInner _inner; - int32 _width, _height; - FlatInput _filter; - FlatButton _invite, _cancel; - - bool _hiding; - - QPixmap _cache; - - anim::fvalue a_opacity; - - void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req); - bool peopleFailed(const RPCError &error, mtpRequestId req); - - QTimer _searchTimer; - QString _peopleQuery; - bool _peopleFull; - mtpRequestId _peopleRequest; - - typedef QMap PeopleCache; - PeopleCache _peopleCache; - - typedef QMap PeopleQueries; - PeopleQueries _peopleQueries; -}; diff --git a/Telegram/SourceFiles/boxes/autolockbox.cpp b/Telegram/SourceFiles/boxes/autolockbox.cpp index 1ac0a4a51..6aa3785df 100644 --- a/Telegram/SourceFiles/boxes/autolockbox.cpp +++ b/Telegram/SourceFiles/boxes/autolockbox.cpp @@ -26,17 +26,15 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "window.h" AutoLockBox::AutoLockBox() : -_done(this, lang(lng_about_done), st::langsCloseButton), -_hiding(false), a_opacity(0, 1) { +_done(this, lang(lng_about_done), st::langsCloseButton) { bool haveTestLang = (cLang() == languageTest); int32 opts[] = { 60, 300, 3600, 18000 }, cnt = sizeof(opts) / sizeof(opts[0]); - _width = st::langsWidth; - _height = st::addContactTitleHeight + st::langsPadding.top() + st::langsPadding.bottom() + cnt * (st::langPadding.top() + st::rbDefFlat.height + st::langPadding.bottom()) + _done.height(); + resizeMaxHeight(st::langsWidth, st::boxTitleHeight + st::langsPadding.top() + st::langsPadding.bottom() + cnt * (st::langPadding.top() + st::rbDefFlat.height + st::langPadding.bottom()) + _done.height()); - int32 y = st::addContactTitleHeight + st::langsPadding.top(); + int32 y = st::boxTitleHeight + st::langsPadding.top(); _options.reserve(cnt); for (int32 i = 0; i < cnt; ++i) { int32 v = opts[i]; @@ -46,15 +44,10 @@ _hiding(false), a_opacity(0, 1) { connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange())); } - _done.move(0, _height - _done.height()); - connect(&_done, SIGNAL(clicked()), this, SLOT(onClose())); - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + _done.move(0, height() - _done.height()); + prepare(); } void AutoLockBox::hideAll() { @@ -71,51 +64,11 @@ void AutoLockBox::showAll() { } } -void AutoLockBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - onClose(); - } -} - -void AutoLockBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void AutoLockBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(0, 0, _width, _height, st::boxBG->b); + if (paint(p)) return; - // paint shadows - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - - // draw box title / text - p.setFont(st::addContactTitleFont->f); - p.setPen(st::black->p); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_passcode_autolock)); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } -} - -void AutoLockBox::animStep(float64 ms) { - if (ms >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - setFocus(); - } - } else { - a_opacity.update(ms, anim::linear); - } - update(); + paintTitle(p, lang(lng_passcode_autolock), true); } void AutoLockBox::onChange() { @@ -132,19 +85,6 @@ void AutoLockBox::onChange() { onClose(); } -void AutoLockBox::onClose() { - emit closed(); -} - -void AutoLockBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - AutoLockBox::~AutoLockBox() { for (int32 i = 0, l = _options.size(); i < l; ++i) { delete _options[i]; diff --git a/Telegram/SourceFiles/boxes/autolockbox.h b/Telegram/SourceFiles/boxes/autolockbox.h index 727c20794..bef0d18d1 100644 --- a/Telegram/SourceFiles/boxes/autolockbox.h +++ b/Telegram/SourceFiles/boxes/autolockbox.h @@ -17,37 +17,28 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class AutoLockBox : public LayeredWidget { +class AutoLockBox : public AbstractBox { Q_OBJECT public: AutoLockBox(); - void parentResized(); - void animStep(float64 ms); - void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); ~AutoLockBox(); public slots: void onChange(); - void onClose(); -private: +protected: void hideAll(); void showAll(); +private: + QVector _options; - int32 _width, _height; BottomButton _done; - - bool _hiding; - QPixmap _cache; - - anim::fvalue a_opacity; }; diff --git a/Telegram/SourceFiles/boxes/backgroundbox.cpp b/Telegram/SourceFiles/boxes/backgroundbox.cpp index f92d8db14..368210f86 100644 --- a/Telegram/SourceFiles/boxes/backgroundbox.cpp +++ b/Telegram/SourceFiles/boxes/backgroundbox.cpp @@ -171,100 +171,39 @@ BackgroundInner::~BackgroundInner() { void BackgroundInner::resizeEvent(QResizeEvent *e) { } -BackgroundBox::BackgroundBox() : _scroll(this, st::backgroundScroll), _inner(), -_close(this, lang(lng_contacts_done), st::contactsClose), -_hiding(false), a_opacity(0, 1) { +BackgroundBox::BackgroundBox() : ItemListBox(st::boxScroll), _inner(), +_close(this, lang(lng_contacts_done), st::contactsClose) { - _width = st::participantWidth; - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - - resize(_width, _height); - resizeEvent(0); - - _scroll.setWidget(&_inner); - _scroll.setFocusPolicy(Qt::NoFocus); + init(&_inner, _close.height(), st::boxFont->height + st::newGroupNamePadding.top() + st::newGroupNamePadding.bottom()); connect(&_close, SIGNAL(clicked()), this, SLOT(onClose())); connect(&_inner, SIGNAL(backgroundChosen(int)), this, SLOT(onBackgroundChosen(int))); - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void BackgroundBox::hideAll() { - _scroll.hide(); + ItemListBox::hideAll(); _close.hide(); } void BackgroundBox::showAll() { - _scroll.show(); + ItemListBox::showAll(); _close.show(); _close.raise(); } -void BackgroundBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - onClose(); - } else { - e->ignore(); - } -} - -void BackgroundBox::parentResized() { - QSize s = parentWidget()->size(); - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - if (_height > st::participantMaxHeight) _height = st::participantMaxHeight; - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void BackgroundBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); + if (paint(p)) return; - // draw box title / text - p.setFont(st::boxFont->f); - p.setPen(st::boxGrayTitle->p); - p.drawText(QRect(st::addContactTitlePos.x(), st::addContactTitlePos.y(), _width - 2 * st::addContactTitlePos.x(), st::boxFont->height), lang(lng_backgrounds_header), style::al_top); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } + paintGrayTitle(p, lang(lng_backgrounds_header)); } void BackgroundBox::resizeEvent(QResizeEvent *e) { - LayeredWidget::resizeEvent(e); - _inner.resize(_width, _inner.height()); - _scroll.resize(_width, _height - st::boxFont->height - st::newGroupNamePadding.top() - st::newGroupNamePadding.bottom() - _close.height()); - _scroll.move(0, st::boxFont->height + st::newGroupNamePadding.top() + st::newGroupNamePadding.bottom()); - _close.move(0, _height - _close.height()); -} - -void BackgroundBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); -} - -void BackgroundBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); + ItemListBox::resizeEvent(e); + _inner.resize(width(), _inner.height()); + _close.move(0, height() - _close.height()); } void BackgroundBox::onBackgroundChosen(int index) { @@ -275,11 +214,3 @@ void BackgroundBox::onBackgroundChosen(int index) { } emit closed(); } - -void BackgroundBox::onClose() { - emit closed(); -} - -BackgroundBox::~BackgroundBox() { - -} diff --git a/Telegram/SourceFiles/boxes/backgroundbox.h b/Telegram/SourceFiles/boxes/backgroundbox.h index 441678fe2..c53b8f530 100644 --- a/Telegram/SourceFiles/boxes/backgroundbox.h +++ b/Telegram/SourceFiles/boxes/backgroundbox.h @@ -17,7 +17,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" class BackgroundInner : public QWidget, public RPCSender { Q_OBJECT @@ -48,37 +48,26 @@ private: }; -class BackgroundBox : public LayeredWidget, public RPCSender { +class BackgroundBox : public ItemListBox { Q_OBJECT public: BackgroundBox(); - void parentResized(); - void animStep(float64 dt); - void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); void resizeEvent(QResizeEvent *e); - void startHide(); - ~BackgroundBox(); public slots: void onBackgroundChosen(int index); - void onClose(); -private: +protected: void hideAll(); void showAll(); - ScrollArea _scroll; +private: + BackgroundInner _inner; - int32 _width, _height; BottomButton _close; - bool _hiding; - - QPixmap _cache; - - anim::fvalue a_opacity; }; diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index 030f34e36..36e06a01d 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -33,7 +33,7 @@ ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const QStri _confirm(this, doneText.isEmpty() ? lang(lng_continue) : doneText, st::btnSelectDone), _cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, st::btnSelectCancel), _close(this, QString(), st::btnInfoClose), -_text(100), _hiding(false), a_opacity(0, 1), af_opacity(anim::linear) { +_text(100) { init(text); } @@ -41,40 +41,32 @@ ConfirmBox::ConfirmBox(const QString &text, bool noDone, const QString &cancelTe _confirm(this, QString(), st::btnSelectDone), _cancel(this, QString(), st::btnSelectCancel), _close(this, cancelText.isEmpty() ? lang(lng_close) : cancelText, st::btnInfoClose), -_text(100), _hiding(false), a_opacity(0, 1), af_opacity(anim::linear) { +_text(100) { init(text); } void ConfirmBox::init(const QString &text) { _text.setText(st::boxFont, text, (_infoMsg ? _confirmBoxTextOptions : _textPlainOptions)); - _width = st::confirmWidth; - _textWidth = _width - st::boxPadding.left() - st::boxPadding.right(); + _textWidth = st::boxWidth - st::boxPadding.left() - st::boxPadding.right(); _textHeight = _text.countHeight(_textWidth); - _height = st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + (_infoMsg ? _close.height() : _confirm.height()); + setMaxHeight(st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + (_infoMsg ? _close.height() : _confirm.height())); if (_infoMsg) { _confirm.hide(); _cancel.hide(); - _close.move(0, st::boxPadding.top() + _textHeight + st::boxPadding.bottom()); - connect(&_close, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_close, SIGNAL(clicked()), this, SLOT(onClose())); setMouseTracking(_text.hasLinks()); } else { - _confirm.move(_width - _confirm.width(), st::boxPadding.top() + _textHeight + st::boxPadding.bottom()); - _cancel.move(0, st::boxPadding.top() + _textHeight + st::boxPadding.bottom()); _close.hide(); connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed())); - connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); } - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void ConfirmBox::mouseMoveEvent(QMouseEvent *e) { @@ -122,7 +114,7 @@ void ConfirmBox::updateLink() { void ConfirmBox::updateHover() { QPoint m(mapFromGlobal(_lastMousePos)); bool wasMy = (_myLink == textlnkOver()); - _myLink = _text.link(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, (_text.maxWidth() < _width) ? style::al_center : style::al_left); + _myLink = _text.link(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, (_text.maxWidth() < width()) ? style::al_center : style::al_left); if (_myLink != textlnkOver()) { if (wasMy || _myLink || rect().contains(m)) { textlnkOver(_myLink); @@ -132,6 +124,10 @@ void ConfirmBox::updateHover() { } } +void ConfirmBox::closePressed() { + emit cancelled(); +} + void ConfirmBox::hideAll() { _confirm.hide(); _cancel.hide(); @@ -150,70 +146,34 @@ void ConfirmBox::showAll() { void ConfirmBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { emit confirmed(); - } else if (e->key() == Qt::Key_Escape) { - onCancel(); + } else { + AbstractBox::keyPressEvent(e); } } -void ConfirmBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void ConfirmBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(0, 0, _width, _height, st::boxBG->b); + if (paint(p)) return; - if (!_infoMsg) { - // paint shadows - p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); + if (!_infoMsg) { + // paint shadows + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); - // paint button sep - p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - } + // paint button sep + p.fillRect(st::btnSelectCancel.width, height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); + } - // draw box title / text - p.setFont(st::boxFont->f); - p.setPen(st::black->p); - _text.draw(p, st::boxPadding.left(), st::boxPadding.top(), _textWidth, (_text.maxWidth() < _width) ? style::al_center : style::al_left); - } + // draw box title / text + p.setFont(st::boxFont->f); + p.setPen(st::black->p); + _text.draw(p, st::boxPadding.left(), st::boxPadding.top(), _textWidth, (_text.maxWidth() < width()) ? style::al_center : style::al_left); +} + +void ConfirmBox::resizeEvent(QResizeEvent *e) { + if (_infoMsg) { + _close.move(0, st::boxPadding.top() + _textHeight + st::boxPadding.bottom()); } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); + _confirm.move(width() - _confirm.width(), st::boxPadding.top() + _textHeight + st::boxPadding.bottom()); + _cancel.move(0, st::boxPadding.top() + _textHeight + st::boxPadding.bottom()); } } - -void ConfirmBox::animStep(float64 ms) { - if (ms >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - setFocus(); - } - } else { - a_opacity.update(ms, af_opacity); - } - update(); -} - -void ConfirmBox::onCancel() { - emit cancelled(); - emit closed(); -} - -void ConfirmBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -ConfirmBox::~ConfirmBox() { -} diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index af10e0614..96a2bf288 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -17,35 +17,34 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class ConfirmBox : public LayeredWidget, public RPCSender { +class ConfirmBox : public AbstractBox, public RPCSender { Q_OBJECT public: ConfirmBox(const QString &text, const QString &doneText = QString(), const QString &cancelText = QString()); ConfirmBox(const QString &text, bool noDone, const QString &cancelText = QString()); - void parentResized(); - void animStep(float64 ms); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); + void resizeEvent(QResizeEvent *e); void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); void leaveEvent(QEvent *e); void updateLink(); - void startHide(); - ~ConfirmBox(); signals: void confirmed(); void cancelled(); -public slots: +protected: - void onCancel(); + void closePressed(); + void hideAll(); + void showAll(); private: @@ -53,21 +52,11 @@ private: bool _infoMsg; - void hideAll(); - void showAll(); - - int32 _width, _height; FlatButton _confirm, _cancel; BottomButton _close; Text _text; int32 _textWidth, _textHeight; - bool _hiding; - QPixmap _cache; - - anim::fvalue a_opacity; - anim::transition af_opacity; - void updateHover(); QPoint _lastMousePos; diff --git a/Telegram/SourceFiles/boxes/connectionbox.cpp b/Telegram/SourceFiles/boxes/connectionbox.cpp index d8b8cb487..ca116de2e 100644 --- a/Telegram/SourceFiles/boxes/connectionbox.cpp +++ b/Telegram/SourceFiles/boxes/connectionbox.cpp @@ -33,13 +33,10 @@ ConnectionBox::ConnectionBox() : _passwordInput(this, st::inpConnectionPassword, lang(lng_connection_password_ph), cConnectionProxy().password), _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (cConnectionType() == dbictAuto)), _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (cConnectionType() == dbictHttpProxy)), - _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (cConnectionType() == dbictTcpProxy)), - a_opacity(0, 1), _hiding(false) { - - _width = st::addContactWidth; + _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (cConnectionType() == dbictTcpProxy)) { connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSave())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); connect(&_autoRadio, SIGNAL(changed()), this, SLOT(onChange())); connect(&_httpProxyRadio, SIGNAL(changed()), this, SLOT(onChange())); @@ -47,9 +44,7 @@ ConnectionBox::ConnectionBox() : _passwordInput.setEchoMode(QLineEdit::Password); - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void ConnectionBox::hideAll() { @@ -71,7 +66,48 @@ void ConnectionBox::showAll() { _httpProxyRadio.show(); _tcpProxyRadio.show(); - _autoRadio.move(st::boxPadding.left(), st::addContactTitleHeight + st::connectionSkip); + int32 h = st::boxTitleHeight + st::connectionSkip + _autoRadio.height() + st::connectionSkip + _httpProxyRadio.height() + st::connectionSkip + _tcpProxyRadio.height() + st::connectionSkip; + if (_httpProxyRadio.checked() || _tcpProxyRadio.checked()) { + h += 2 * st::boxPadding.top() + 2 * _hostInput.height(); + _hostInput.show(); + _portInput.show(); + _userInput.show(); + _passwordInput.show(); + } else { + _hostInput.hide(); + _portInput.hide(); + _userInput.hide(); + _passwordInput.hide(); + } + + _saveButton.show(); + _cancelButton.show(); + + setMaxHeight(h + _saveButton.height()); + resizeEvent(0); +} + +void ConnectionBox::showDone() { + if (!_hostInput.isHidden()) { + _hostInput.setFocus(); + } +} + +void ConnectionBox::paintEvent(QPaintEvent *e) { + QPainter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_connection_header), true); + + // paint shadow + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); + + // paint button sep + p.fillRect(st::btnSelectCancel.width, height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); +} + +void ConnectionBox::resizeEvent(QResizeEvent *e) { + _autoRadio.move(st::boxPadding.left(), st::boxTitleHeight + st::connectionSkip); _httpProxyRadio.move(st::boxPadding.left(), _autoRadio.y() + _autoRadio.height() + st::connectionSkip); int32 inputy = 0; @@ -86,85 +122,16 @@ void ConnectionBox::showAll() { } if (inputy) { - _hostInput.show(); - _portInput.show(); - _userInput.show(); - _passwordInput.show(); _hostInput.move(st::boxPadding.left() + st::rbDefFlat.textLeft, inputy); - _portInput.move(_width - st::boxPadding.right() - _portInput.width(), inputy); + _portInput.move(width() - st::boxPadding.right() - _portInput.width(), inputy); _userInput.move(st::boxPadding.left() + st::rbDefFlat.textLeft, _hostInput.y() + _hostInput.height() + st::boxPadding.top()); - _passwordInput.move(_width - st::boxPadding.right() - _passwordInput.width(), _userInput.y()); - } else { - _hostInput.hide(); - _portInput.hide(); - _userInput.hide(); - _passwordInput.hide(); + _passwordInput.move(width() - st::boxPadding.right() - _passwordInput.width(), _userInput.y()); } - _saveButton.show(); - _cancelButton.show(); - int32 buttony = (_tcpProxyRadio.checked() ? (_userInput.y() + _userInput.height()) : (_tcpProxyRadio.y() + _tcpProxyRadio.height())) + st::connectionSkip; - _saveButton.move(_width - _saveButton.width(), buttony); + _saveButton.move(width() - _saveButton.width(), buttony); _cancelButton.move(0, buttony); - - _height = _saveButton.y() + _saveButton.height(); - resize(_width, _height); -} - -void ConnectionBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - } else if (e->key() == Qt::Key_Escape) { - onCancel(); - } -} - -void ConnectionBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - -void ConnectionBox::paintEvent(QPaintEvent *e) { - QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(0, 0, _width, _height, st::boxBG->b); - - // paint shadows - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); - - // paint button sep - p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - - // draw box title / text - p.setFont(st::addContactTitleFont->f); - p.setPen(st::black->p); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_connection_header)); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } -} - -void ConnectionBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - if (!_hostInput.isHidden()) { - _hostInput.setFocus(); - } - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); } void ConnectionBox::onChange() { @@ -210,19 +177,3 @@ void ConnectionBox::onSave() { reinitImageLinkManager(); emit closed(); } - -void ConnectionBox::onCancel() { - emit closed(); -} - -void ConnectionBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -ConnectionBox::~ConnectionBox() { -} diff --git a/Telegram/SourceFiles/boxes/connectionbox.h b/Telegram/SourceFiles/boxes/connectionbox.h index 913510c40..1550ace95 100644 --- a/Telegram/SourceFiles/boxes/connectionbox.h +++ b/Telegram/SourceFiles/boxes/connectionbox.h @@ -17,42 +17,34 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" #include "gui/phoneinput.h" +#include "abstractbox.h" -class ConnectionBox : public LayeredWidget { +class ConnectionBox : public AbstractBox { Q_OBJECT public: ConnectionBox(); - void parentResized(); - void animStep(float64 dt); - void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); - ~ConnectionBox(); + void resizeEvent(QResizeEvent *e); public slots: void onChange(); void onSave(); - void onCancel(); -private: +protected: void hideAll(); void showAll(); + void showDone(); + +private: FlatButton _saveButton, _cancelButton; FlatInput _hostInput; PortInput _portInput; FlatInput _userInput, _passwordInput; FlatRadiobutton _autoRadio, _httpProxyRadio, _tcpProxyRadio; - - int32 _width, _height; - QPixmap _cache; - - anim::fvalue a_opacity; - bool _hiding; }; diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp index 78ca8df7c..b789648ad 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.cpp +++ b/Telegram/SourceFiles/boxes/contactsbox.cpp @@ -23,13 +23,31 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "window.h" -ContactsInner::ContactsInner() : +ContactsInner::ContactsInner(bool creatingChat) : _chat(0), _creatingChat(creatingChat), _contacts(&App::main()->contactsList()), _sel(0), _filteredSel(-1), _mouseSel(false), +_selCount(0), +_searching(false), +_byUsernameSel(-1), _addContactLnk(this, lang(lng_add_contact_button)) { + init(); +} +ContactsInner::ContactsInner(ChatData *chat) : _chat(chat), _creatingChat(false), +_contacts(&App::main()->contactsList()), +_sel(0), +_filteredSel(-1), +_mouseSel(false), +_selCount(0), +_searching(false), +_byUsernameSel(-1), +_addContactLnk(this, lang(lng_add_contact_button)) { + init(); +} + +void ContactsInner::init() { connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); for (DialogRow *r = _contacts->list.begin; r != _contacts->list.end; r = r->next) { @@ -46,7 +64,24 @@ _addContactLnk(this, lang(lng_add_contact_button)) { } void ContactsInner::peerUpdated(PeerData *peer) { - if (!peer->chat) { + if (_chat && (!peer || peer == _chat)) { + if (_chat->forbidden) { + App::wnd()->hideLayer(); + } else if (!_chat->participants.isEmpty() || _chat->count <= 0) { + for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) { + delete i.value(); + } + _contactsData.clear(); + for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) { + row->attached = 0; + } + if (!_filter.isEmpty()) { + for (int32 j = 0, s = _filtered.size(); j < s; ++j) { + _filtered[j]->attached = 0; + } + } + } + } else if (!peer->chat) { ContactsData::iterator i = _contactsData.find(peer->asUser()); if (i != _contactsData.cend()) { for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) { @@ -61,7 +96,7 @@ void ContactsInner::peerUpdated(PeerData *peer) { _contactsData.erase(i); } } - + parentWidget()->update(); } @@ -105,6 +140,8 @@ ContactsInner::ContactData *ContactsInner::contactData(DialogRow *row) { ContactsData::const_iterator i = _contactsData.constFind(user); if (i == _contactsData.cend()) { _contactsData.insert(user, data = new ContactData()); + data->inchat = _chat ? _chat->participants.contains(user) : false; + data->check = false; data->name.setText(st::profileListNameFont, user->name, _textNameOptions); data->online = App::onlineText(user, _time); } else { @@ -115,29 +152,59 @@ ContactsInner::ContactData *ContactsInner::contactData(DialogRow *row) { return data; } -void ContactsInner::paintDialog(QPainter &p, DialogRow *row, bool sel) { +void ContactsInner::paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel) { int32 left = st::profileListPadding.width(); - UserData *user = row->history->peer->asUser(); - ContactData *data = contactData(row); + if (data->inchat || data->check || _selCount + (_chat ? _chat->count : 0) >= cMaxGroupCount()) { + sel = false; + } - if (sel) { - p.fillRect(0, 0, width(), 2 * st::profileListPadding.height() + st::profileListPhotoSize, st::profileHoverBG->b); + if (sel || data->inchat || data->check) { + p.fillRect(0, 0, width(), 2 * st::profileListPadding.height() + st::profileListPhotoSize, ((data->inchat || data->check) ? st::profileActiveBG : st::profileHoverBG)->b); } p.drawPixmap(left, st::profileListPadding.height(), user->photo->pix(st::profileListPhotoSize)); - p.setPen(st::profileListNameColor->p); - data->name.drawElided(p, left + st::profileListPhotoSize + st::participantDelta, st::profileListNameTop, width() - st::profileListPadding.width() - st::profileListPhotoSize - st::profileListPadding.width() - st::participantDelta - st::scrollDef.width - st::contactsImg.pxWidth()); + if (data->inchat || data->check) { + p.setPen(st::white->p); + } else { + p.setPen(st::profileListNameColor->p); + } + int32 iconw = (_chat || _creatingChat) ? st::profileCheckRect.pxWidth() : st::contactsImg.pxWidth(); + data->name.drawElided(p, left + st::profileListPhotoSize + st::participantDelta, st::profileListNameTop, width() - left - st::profileListPhotoSize - st::profileListPadding.width() - st::participantDelta - st::scrollDef.width - iconw); - if (sel) { + if (_chat || _creatingChat) { + if (sel || data->check) { + p.drawPixmap(QPoint(width() - st::profileCheckRect.pxWidth() - st::profileCheckDeltaX, st::profileListPadding.height() + (st::profileListPhotoSize - st::profileCheckRect.pxHeight()) / 2 - st::profileCheckDeltaY), App::sprite(), (data->check ? st::profileCheckActiveRect : st::profileCheckRect)); + } + } else if (sel) { p.drawPixmap(QPoint(width() - st::contactsImg.pxWidth() - st::profileCheckDeltaX, st::profileListPadding.height() + (st::profileListPhotoSize - st::contactsImg.pxHeight()) / 2 - st::profileCheckDeltaY), App::sprite(), st::contactsImg); } - p.setFont(st::profileSubFont->f); - p.setPen((App::onlineColorUse(user->onlineTill, _time) ? st::profileOnlineColor : st::profileOfflineColor)->p); - p.drawText(left + st::profileListPhotoSize + st::participantDelta, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online); + bool uname = (data->online.at(0) == '@'); + p.setFont(st::profileSubFont->f); + if (uname && !data->inchat && !data->check && !_lastQuery.isEmpty() && user->username.startsWith(_lastQuery, Qt::CaseInsensitive)) { + int32 availw = width() - (left + st::profileListPhotoSize + st::profileListPadding.width() * 2); + QString first = '@' + user->username.mid(0, _lastQuery.size()), second = user->username.mid(_lastQuery.size()); + int32 w = st::profileSubFont->m.width(first); + if (w >= availw || second.isEmpty()) { + p.setPen(st::profileOnlineColor->p); + p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(first, Qt::ElideRight, availw)); + } else { + p.setPen(st::profileOnlineColor->p); + p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, first); + p.setPen(st::profileOfflineColor->p); + p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width() + w, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(second, Qt::ElideRight, availw - w)); + } + } else { + if (data->inchat || data->check) { + p.setPen(st::white->p); + } else { + p.setPen(((uname || App::onlineColorUse(user->onlineTill, _time)) ? st::profileOnlineColor : st::profileOfflineColor)->p); + } + p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online); + } } void ContactsInner::paintEvent(QPaintEvent *e) { @@ -147,40 +214,85 @@ void ContactsInner::paintEvent(QPaintEvent *e) { _time = unixtime(); p.fillRect(r, st::white->b); - int32 yFrom = r.top(); + int32 yFrom = r.top(), yTo = r.bottom(); int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; if (_filter.isEmpty()) { - if (_contacts->list.count) { - _contacts->list.adjustCurrent(yFrom, rh); + if (_contacts->list.count || !_byUsername.isEmpty()) { + if (_contacts->list.count) { + _contacts->list.adjustCurrent(yFrom, rh); - DialogRow *drawFrom = _contacts->list.current; - p.translate(0, drawFrom->pos * rh); - while (drawFrom != _contacts->list.end && drawFrom->pos * rh < r.bottom()) { - paintDialog(p, drawFrom, (drawFrom == _sel)); - p.translate(0, rh); - drawFrom = drawFrom->next; + DialogRow *drawFrom = _contacts->list.current; + p.translate(0, drawFrom->pos * rh); + while (drawFrom != _contacts->list.end && drawFrom->pos * rh < yTo) { + paintDialog(p, drawFrom->history->peer->asUser(), contactData(drawFrom), (drawFrom == _sel)); + p.translate(0, rh); + drawFrom = drawFrom->next; + } + } + if (!_byUsername.isEmpty()) { + p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); + p.setFont(st::searchedBarFont->f); + p.setPen(st::searchedBarColor->p); + p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center); + p.translate(0, st::searchedBarHeight); + + yFrom -= _contacts->list.count * rh + st::searchedBarHeight; + yTo -= _contacts->list.count * rh + st::searchedBarHeight; + int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; + if (from < _byUsername.size()) { + int32 to = (yTo / rh) + 1; + if (to > _byUsername.size()) to = _byUsername.size(); + + p.translate(0, from * rh); + for (; from < to; ++from) { + paintDialog(p, _byUsername[from], d_byUsername[from], (_byUsernameSel == from)); + p.translate(0, rh); + } + } } } else { p.setFont(st::noContactsFont->f); p.setPen(st::noContactsColor->p); - p.drawText(QRect(0, 0, width(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_contacts : lng_contacts_loading), style::al_center); + p.drawText(QRect(0, 0, width(), st::noContactsHeight - ((cContactsReceived() && !_searching) ? st::noContactsFont->height : 0)), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_loading), style::al_center); } } else { - if (_filtered.isEmpty()) { + if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { p.setFont(st::noContactsFont->f); p.setPen(st::noContactsColor->p); - p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_not_found), style::al_center); + p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang((cContactsReceived() && !_searching) ? lng_contacts_not_found : lng_contacts_loading), style::al_center); } else { - int32 from = yFrom / rh; - if (from < 0) from = 0; - if (from < _filtered.size()) { - int32 to = (r.bottom() / rh) + 1; - if (to > _filtered.size()) to = _filtered.size(); + if (!_filtered.isEmpty()) { + int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; + if (from < _filtered.size()) { + int32 to = (yTo / rh) + 1; + if (to > _filtered.size()) to = _filtered.size(); - p.translate(0, from * rh); - for (; from < to; ++from) { - paintDialog(p, _filtered[from], (_filteredSel == from)); - p.translate(0, rh); + p.translate(0, from * rh); + for (; from < to; ++from) { + paintDialog(p, _filtered[from]->history->peer->asUser(), contactData(_filtered[from]), (_filteredSel == from)); + p.translate(0, rh); + } + } + } + if (!_byUsernameFiltered.isEmpty()) { + p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); + p.setFont(st::searchedBarFont->f); + p.setPen(st::searchedBarColor->p); + p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center); + p.translate(0, st::searchedBarHeight); + + yFrom -= _filtered.size() * rh + st::searchedBarHeight; + yTo -= _filtered.size() * rh + st::searchedBarHeight; + int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; + if (from < _byUsernameFiltered.size()) { + int32 to = (yTo / rh) + 1; + if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size(); + + p.translate(0, from * rh); + for (; from < to; ++from) { + paintDialog(p, _byUsernameFiltered[from], d_byUsernameFiltered[from], (_byUsernameSel == from)); + p.translate(0, rh); + } } } } @@ -193,7 +305,11 @@ void ContactsInner::enterEvent(QEvent *e) { void ContactsInner::leaveEvent(QEvent *e) { setMouseTracking(false); - updateSel(); + if (_sel || _filteredSel >= 0 || _byUsernameSel >= 0) { + _sel = 0; + _filteredSel = _byUsernameSel = -1; + parentWidget()->update(); + } } void ContactsInner::mouseMoveEvent(QMouseEvent *e) { @@ -212,46 +328,117 @@ void ContactsInner::mousePressEvent(QMouseEvent *e) { } void ContactsInner::chooseParticipant() { - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from; - DialogRow *r = 0; - if (_filter.isEmpty()) { - r = _sel; - } else { - if (_filteredSel < 0 || _filteredSel >= _filtered.size()) return; - r = _filtered[_filteredSel]; - } - if (r) { - App::wnd()->hideSettings(true); - App::main()->showPeer(r->history->peer->id, 0, false, true); - App::wnd()->hideLayer(); - } + if (_chat || _creatingChat) { + _time = unixtime(); + int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from; + if (_filter.isEmpty()) { + if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) { + if (d_byUsername[_byUsernameSel]->inchat) return; + changeCheckState(d_byUsername[_byUsernameSel]); + } else { + if (!_sel || contactData(_sel)->inchat) return; + changeCheckState(_sel); + } + } else { + if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) { + if (d_byUsernameFiltered[_byUsernameSel]->inchat) return; + changeCheckState(d_byUsernameFiltered[_byUsernameSel]); + ContactData *moving = d_byUsernameFiltered[_byUsernameSel]; + int32 i = 0, l = d_byUsername.size(); + for (; i < l; ++i) { + if (d_byUsername[i] == moving) { + break; + } + } + if (i == l) { + d_byUsername.push_back(moving); + _byUsername.push_back(_byUsernameFiltered[_byUsernameSel]); + for (i = 0, l = _byUsernameDatas.size(); i < l;) { + if (_byUsernameDatas[i] == moving) { + _byUsernameDatas.removeAt(i); + --l; + } else { + ++i; + } + } + } + } else { + if (_filteredSel < 0 || _filteredSel >= _filtered.size() || contactData(_filtered[_filteredSel])->inchat) return; + changeCheckState(_filtered[_filteredSel]); + } + emit selectAllQuery(); + } + } else { + int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from; + PeerId peer = 0; + if (_filter.isEmpty()) { + if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) { + peer = _byUsername[_byUsernameSel]->id; + } else { + peer = _sel ? _sel->history->peer->id : 0; + } + } else { + if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) { + peer = _byUsernameFiltered[_byUsernameSel]->id; + } else { + if (_filteredSel < 0 || _filteredSel >= _filtered.size()) return; + peer = _filtered[_filteredSel]->history->peer->id; + } + } + if (peer) { + App::wnd()->hideSettings(true); + App::main()->showPeer(peer, 0, false, true); + App::wnd()->hideLayer(); + } + } parentWidget()->update(); } -void ContactsInner::updateSel() { - if (!_mouseSel) return; +void ContactsInner::changeCheckState(DialogRow *row) { + changeCheckState(contactData(row)); +} - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; +void ContactsInner::changeCheckState(ContactData *data) { + if (data->check) { + data->check = false; + --_selCount; + } else if (_selCount + (_chat ? _chat->count : 0) < cMaxGroupCount()) { + data->check = true; + ++_selCount; + } +} + +void ContactsInner::updateSel() { QPoint p(mapFromGlobal(_lastMousePos)); + bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); + int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; if (_filter.isEmpty()) { - DialogRow *newSel = rect().contains(p) ? _contacts->list.rowAtY(p.y(), rh) : 0; - if (newSel != _sel) { + DialogRow *newSel = (in && (p.y() >= 0) && (p.y() < _contacts->list.count * rh)) ? _contacts->list.rowAtY(p.y(), rh) : 0; + int32 byUsernameSel = (in && p.y() >= _contacts->list.count * rh + st::searchedBarHeight) ? ((p.y() - _contacts->list.count * rh - st::searchedBarHeight) / rh) : -1; + if (byUsernameSel >= _byUsername.size()) byUsernameSel = -1; + if (newSel != _sel || byUsernameSel != _byUsernameSel) { _sel = newSel; + _byUsernameSel = byUsernameSel; parentWidget()->update(); - } + } } else { - int32 newFilteredSel = (p.y() >= 0 && rect().contains(p)) ? (p.y() / rh) : -1; - if (newFilteredSel != _filteredSel) { + int32 newFilteredSel = (in && p.y() >= 0 && p.y() < _filtered.size() * rh) ? (p.y() / rh) : -1; + int32 byUsernameSel = (in && p.y() >= _filtered.size() * rh + st::searchedBarHeight) ? ((p.y() - _filtered.size() * rh - st::searchedBarHeight) / rh) : -1; + if (byUsernameSel >= _byUsernameFiltered.size()) byUsernameSel = -1; + if (newFilteredSel != _filteredSel || byUsernameSel != _byUsernameSel) { _filteredSel = newFilteredSel; + _byUsernameSel = byUsernameSel; parentWidget()->update(); } } } void ContactsInner::updateFilter(QString filter) { + _lastQuery = filter.toLower().trimmed(); filter = textSearchKey(filter); + _time = unixtime(); QStringList f; if (!filter.isEmpty()) { QStringList filterList = filter.split(cWordSplit(), QString::SkipEmptyParts); @@ -268,19 +455,32 @@ void ContactsInner::updateFilter(QString filter) { if (_filter != filter) { int32 rh = (st::profileListPhotoSize + st::profileListPadding.height() * 2); _filter = filter; + + _byUsernameFiltered.clear(); + d_byUsernameFiltered.clear(); + for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) { + delete _byUsernameDatas[i]; + } + _byUsernameDatas.clear(); + if (_filter.isEmpty()) { + _sel = 0; if (_contacts->list.count) { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - resize(width(), _contacts->list.count * rh + st::contactsClose.height); _sel = _contacts->list.begin; - } else { - resize(width(), st::noContactsHeight); - if (cContactsReceived()) { - if (_addContactLnk.isHidden()) _addContactLnk.show(); - } else { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); + while (_sel->next->next && contactData(_sel)->inchat) { + _sel = _sel->next; } } + if (!_sel && !_byUsername.isEmpty()) { + _byUsernameSel = 0; + while (_byUsernameSel < _byUsername.size() && d_byUsername[_byUsernameSel]->inchat) { + ++_byUsernameSel; + } + if (_byUsernameSel == _byUsername.size()) _byUsernameSel = -1; + } else { + _byUsernameSel = -1; + } + refresh(); } else { if (!_addContactLnk.isHidden()) _addContactLnk.hide(); QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi; @@ -322,14 +522,48 @@ void ContactsInner::updateFilter(QString filter) { } } } - } - _filteredSel = _filtered.isEmpty() ? -1 : 0; - if (!_filtered.isEmpty()) { - resize(width(), _filtered.size() * rh + st::contactsClose.height); - } else { - resize(width(), st::noContactsHeight); + _byUsernameFiltered.reserve(_byUsername.size()); + d_byUsernameFiltered.reserve(d_byUsername.size()); + for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { + const PeerData::Names &names(_byUsername[i]->names); + PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni; + for (fi = fb; fi != fe; ++fi) { + QString filterName(*fi); + for (ni = nb; ni != ne; ++ni) { + if (ni->startsWith(*fi)) { + break; + } + } + if (ni == ne) { + break; + } + } + if (fi == fe) { + _byUsernameFiltered.push_back(_byUsername[i]); + d_byUsernameFiltered.push_back(d_byUsername[i]); + } + } } + _filteredSel = -1; + if (!_filtered.isEmpty()) { + for (_filteredSel = 0; (_filteredSel < _filtered.size()) && contactData(_filtered[_filteredSel])->inchat;) { + ++_filteredSel; + } + if (_filteredSel == _filtered.size()) _filteredSel = -1; + } + _byUsernameSel = -1; + if (_filteredSel < 0 && !_byUsernameFiltered.isEmpty()) { + for (_byUsernameSel = 0; (_byUsernameSel < _byUsernameFiltered.size()) && d_byUsernameFiltered[_byUsernameSel]->inchat;) { + ++_byUsernameSel; + } + if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1; + } + + refresh(); + + _searching = true; + emit searchByUsername(); } if (parentWidget()) parentWidget()->update(); loadProfilePhotos(0); @@ -365,6 +599,67 @@ void ContactsInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) { resize(width(), newh); } +void ContactsInner::peopleReceived(const QString &query, const QVector &people) { + _lastQuery = query.toLower().trimmed(); + if (_lastQuery.at(0) == '@') _lastQuery = _lastQuery.mid(1); + int32 already = _byUsernameFiltered.size(); + _byUsernameFiltered.reserve(already + people.size()); + d_byUsernameFiltered.reserve(already + people.size()); + for (QVector::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) { + int32 uid = i->c_contactFound().vuser_id.v, j = 0; + for (; j < already; ++j) { + if (_byUsernameFiltered[j]->id == App::peerFromUser(uid)) break; + } + if (j == already) { + UserData *u = App::user(uid); + ContactData *d = new ContactData(); + _byUsernameDatas.push_back(d); + d->inchat = _chat ? _chat->participants.contains(u) : false; + d->check = false; + d->name.setText(st::profileListNameFont, u->name, _textNameOptions); + d->online = '@' + u->username; + + _byUsernameFiltered.push_back(u); + d_byUsernameFiltered.push_back(d); + } + } + _searching = false; + refresh(); +} + +void ContactsInner::refresh() { + int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; + if (_filter.isEmpty()) { + if (_contacts->list.count || !_byUsername.isEmpty()) { + if (!_addContactLnk.isHidden()) _addContactLnk.hide(); + resize(width(), (_contacts->list.count * rh) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * rh))); + } else { + if (cContactsReceived()) { + if (_addContactLnk.isHidden()) _addContactLnk.show(); + } else { + if (!_addContactLnk.isHidden()) _addContactLnk.hide(); + } + resize(width(), st::noContactsHeight); + } + } else { + if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { + if (!_addContactLnk.isHidden()) _addContactLnk.hide(); + resize(width(), st::noContactsHeight); + } else { + resize(width(), (_filtered.size() * rh) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * rh))); + } + } + update(); +} + +ChatData *ContactsInner::chat() const { + return _chat; +} + +bool ContactsInner::creatingChat() const { + return _creatingChat; +} + ContactsInner::~ContactsInner() { for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) { delete *i; @@ -376,44 +671,115 @@ void ContactsInner::resizeEvent(QResizeEvent *e) { } void ContactsInner::selectSkip(int32 dir) { + _time = unixtime(); _mouseSel = false; int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, origDir = dir; if (_filter.isEmpty()) { + int cur = 0; if (_sel) { - if (dir > 0) { - while (dir && _sel->next->next) { - _sel = _sel->next; - --dir; - } + for (DialogRow *i = _contacts->list.begin; i != _sel; i = i->next) { + ++cur; + } + } else { + cur = (_byUsernameSel >= 0) ? (_contacts->list.count + _byUsernameSel) : -1; + } + cur += dir; + if (cur <= 0) { + _sel = _contacts->list.count ? _contacts->list.begin : 0; + _byUsernameSel = (!_contacts->list.count && !_byUsername.isEmpty()) ? 0 : -1; + } else if (cur >= _contacts->list.count) { + if (_byUsername.isEmpty()) { + _sel = _contacts->list.count ? _contacts->list.end->prev : 0; + _byUsernameSel = -1; } else { - while (dir && _sel->prev) { - _sel = _sel->prev; - ++dir; + _sel = 0; + _byUsernameSel = cur - _contacts->list.count; + if (_byUsernameSel >= _byUsername.size()) _byUsernameSel = _byUsername.size() - 1; + } + } else { + for (_sel = _contacts->list.begin; cur; _sel = _sel->next) { + --cur; + } + _byUsernameSel = -1; + } + if (dir > 0) { + while (_sel && _sel->next && contactData(_sel)->inchat) { + _sel = _sel->next; + } + if (!_sel || !_sel->next) { + _sel = 0; + if (!_byUsername.isEmpty()) { + if (_byUsernameSel < 0) _byUsernameSel = 0; + for (; _byUsernameSel < _byUsername.size() && d_byUsername[_byUsernameSel]->inchat;) { + ++_byUsernameSel; + } + if (_byUsernameSel == _byUsername.size()) _byUsernameSel = -1; + } + } + } else { + while (_byUsernameSel >= 0 && d_byUsername[_byUsernameSel]->inchat) { + --_byUsernameSel; + } + if (_byUsernameSel < 0) { + if (_contacts->list.count) { + if (!_sel) _sel = _contacts->list.end->prev; + for (; _sel && contactData(_sel)->inchat;) { + _sel = _sel->prev; + } } } - } else if (dir > 0 && _contacts->list.count) { - _sel = _contacts->list.begin; } if (_sel) { - emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh + st::contactsClose.height); + emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh); + } else if (_byUsernameSel >= 0) { + emit mustScrollTo((_contacts->list.count + _byUsernameSel) * rh + st::searchedBarHeight, (_contacts->list.count + _byUsernameSel + 1) * rh + st::searchedBarHeight); } } else { + int cur = (_filteredSel >= 0) ? _filteredSel : ((_byUsernameSel >= 0) ? (_filtered.size() + _byUsernameSel) : -1); + cur += dir; + if (cur <= 0) { + _filteredSel = _filtered.isEmpty() ? -1 : 0; + _byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1; + } else if (cur >= _filtered.size()) { + _filteredSel = -1; + _byUsernameSel = cur - _filtered.size(); + if (_byUsernameSel >= _byUsernameFiltered.size()) _byUsernameSel = _byUsernameFiltered.size() - 1; + } else { + _filteredSel = cur; + _byUsernameSel = -1; + } if (dir > 0) { - if (_filteredSel < 0 && dir > 1) { - _filteredSel = 0; + while (_filteredSel >= 0 && _filteredSel < _filtered.size() && contactData(_filtered[_filteredSel])->inchat) { + ++_filteredSel; } - _filteredSel += dir; - if (_filteredSel >= _filtered.size()) { - _filteredSel = _filtered.size() - 1; + if (_filteredSel < 0 || _filteredSel >= _filtered.size()) { + _filteredSel = -1; + if (!_byUsernameFiltered.isEmpty()) { + if (_byUsernameSel < 0) _byUsernameSel = 0; + for (; _byUsernameSel < _byUsernameFiltered.size() && d_byUsernameFiltered[_byUsernameSel]->inchat;) { + ++_byUsernameSel; + } + if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1; + } } - } else if (_filteredSel > 0) { - _filteredSel += dir; - if (_filteredSel < 0) { - _filteredSel = 0; + } else { + while (_byUsernameSel >= 0 && d_byUsernameFiltered[_byUsernameSel]->inchat) { + --_byUsernameSel; + } + if (_byUsernameSel < 0) { + if (!_filtered.isEmpty()) { + if (_filteredSel < 0) _filteredSel = _filtered.size() - 1; + for (; _filteredSel >= 0 && contactData(_filtered[_filteredSel])->inchat;) { + --_filteredSel; + } + } } } if (_filteredSel >= 0) { - emit mustScrollTo(_filteredSel * rh, (_filteredSel + 1) * rh + st::contactsClose.height); + emit mustScrollTo(_filteredSel * rh, (_filteredSel + 1) * rh); + } else if (_byUsernameSel >= 0) { + int skip = _filtered.size() * rh + st::searchedBarHeight; + emit mustScrollTo(skip + _byUsernameSel * rh, skip + (_byUsernameSel + 1) * rh); } } parentWidget()->update(); @@ -426,54 +792,195 @@ void ContactsInner::selectSkipPage(int32 h, int32 dir) { selectSkip(points * dir); } -ContactsBox::ContactsBox() : _scroll(this, st::newGroupScroll), _inner(), - _addContact(this, lang(lng_add_contact_button), st::contactsAdd), - _filter(this, st::contactsFilter, lang(lng_participant_filter)), - _close(this, lang(lng_contacts_done), st::contactsClose), - _hiding(false), a_opacity(0, 1) { +QVector ContactsInner::selected() { + QVector result; + result.reserve(_contactsData.size()); + for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { + if (i.value()->check) { + result.push_back(i.key()); + } + } + for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { + if (d_byUsername[i]->check) { + result.push_back(_byUsername[i]); + } + } + return result; +} - _width = st::participantWidth; - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - if (_height > st::participantMaxHeight) _height = st::participantMaxHeight; +QVector ContactsInner::selectedInputs() { + QVector result; + result.reserve(_contactsData.size()); + for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { + if (i.value()->check) { + result.push_back(i.key()->inputUser); + } + } + for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { + if (d_byUsername[i]->check) { + result.push_back(_byUsername[i]->inputUser); + } + } + return result; +} - resize(_width, _height); +PeerData *ContactsInner::selectedUser() { + for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { + if (i.value()->check) { + return i.key(); + } + } + for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { + if (d_byUsername[i]->check) { + return _byUsername[i]; + } + } + return 0; +} - _scroll.setWidget(&_inner); - _scroll.setFocusPolicy(Qt::NoFocus); +ContactsBox::ContactsBox(bool creatingChat) : ItemListBox(st::boxNoTopScroll), _inner(creatingChat), +_addContact(this, lang(lng_add_contact_button), st::contactsAdd), +_filter(this, st::contactsFilter, lang(lng_participant_filter)), +_next(this, lang(lng_create_group_next), st::btnSelectDone), +_cancel(this, lang(lng_contacts_done), creatingChat ? st::btnSelectCancel : st::contactsClose) { + init(); +} - connect(&_addContact, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); - connect(&_close, SIGNAL(clicked()), this, SLOT(onClose())); +ContactsBox::ContactsBox(ChatData *chat) : ItemListBox(st::boxNoTopScroll), _inner(chat), +_addContact(this, lang(lng_add_contact_button), st::contactsAdd), +_filter(this, st::contactsFilter, lang(lng_participant_filter)), +_next(this, lang(lng_participant_invite), st::btnSelectDone), +_cancel(this, lang(lng_cancel), st::btnSelectCancel) { + init(); +} + +void ContactsBox::init() { + ItemListBox::init(&_inner, _cancel.height(), st::contactsAdd.height + st::newGroupNamePadding.top() + _filter.height() + st::newGroupNamePadding.bottom()); + + if (_inner.chat() || _inner.creatingChat()) { + _addContact.hide(); + } else { + connect(&_addContact, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); + } + if (_inner.chat()) { + connect(&_next, SIGNAL(clicked()), this, SLOT(onInvite())); + } else if (_inner.creatingChat()) { + connect(&_next, SIGNAL(clicked()), this, SLOT(onNext())); + } else { + _next.hide(); + } + connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(updateSel())); connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); connect(&_filter, SIGNAL(cancelled()), this, SLOT(onClose())); - 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(selectAllQuery()), &_filter, SLOT(selectAll())); + connect(&_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername())); - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + _searchTimer.setSingleShot(true); + connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); + + prepare(); +} + +bool ContactsBox::onSearchByUsername(bool searchCache) { + QString q = _filter.text().trimmed(); + if (q.isEmpty()) { + if (_peopleRequest) { + _peopleRequest = 0; + } + return true; + } + if (q.size() >= MinUsernameLength) { + if (searchCache) { + PeopleCache::const_iterator i = _peopleCache.constFind(q); + if (i != _peopleCache.cend()) { + _peopleQuery = q; + _peopleRequest = 0; + peopleReceived(i.value(), 0); + return true; + } + } else if (_peopleQuery != q) { + _peopleQuery = q; + _peopleFull = false; + _peopleRequest = MTP::send(MTPcontacts_Search(MTP_string(_peopleQuery), MTP_int(SearchPeopleLimit)), rpcDone(&ContactsBox::peopleReceived), rpcFail(&ContactsBox::peopleFailed)); + _peopleQueries.insert(_peopleRequest, _peopleQuery); + } + } + return false; +} + +void ContactsBox::onNeedSearchByUsername() { + if (!onSearchByUsername(true)) { + _searchTimer.start(AutoSearchTimeout); + } +} + +void ContactsBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId req) { + QString q = _peopleQuery; + + PeopleQueries::iterator i = _peopleQueries.find(req); + if (i != _peopleQueries.cend()) { + q = i.value(); + _peopleCache[q] = result; + _peopleQueries.erase(i); + } + + if (_peopleRequest == req) { + switch (result.type()) { + case mtpc_contacts_found: { + App::feedUsers(result.c_contacts_found().vusers); + _inner.peopleReceived(q, result.c_contacts_found().vresults.c_vector().v); + } break; + } + + _peopleRequest = 0; + _inner.updateSel(); + onScroll(); + } +} + +bool ContactsBox::peopleFailed(const RPCError &error, mtpRequestId req) { + if (_peopleRequest == req) { + _peopleRequest = 0; + _peopleFull = true; + } + return true; } void ContactsBox::hideAll() { + ItemListBox::hideAll(); _addContact.hide(); _filter.hide(); - _scroll.hide(); - _close.hide(); + _next.hide(); + _cancel.hide(); } void ContactsBox::showAll() { + ItemListBox::showAll(); _addContact.show(); _filter.show(); - _scroll.show(); - _close.show(); + if (_inner.chat() || _inner.creatingChat()) { + _next.show(); + _addContact.hide(); + } else { + _next.hide(); + _addContact.show(); + } + _cancel.show(); +} + +void ContactsBox::showDone() { + _filter.setFocus(); } void ContactsBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - onClose(); - } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { + if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { if (_filter.hasFocus()) { _inner.chooseParticipant(); + } else { + ItemListBox::keyPressEvent(e); } } else if (_filter.hasFocus()) { if (e->key() == Qt::Key_Down) { @@ -485,73 +992,34 @@ void ContactsBox::keyPressEvent(QKeyEvent *e) { } else if (e->key() == Qt::Key_PageUp) { _inner.selectSkipPage(_scroll.height(), -1); } else { - e->ignore(); + ItemListBox::keyPressEvent(e); } } else { - e->ignore(); + ItemListBox::keyPressEvent(e); } } -void ContactsBox::parentResized() { - QSize s = parentWidget()->size(); - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - if (_height > st::participantMaxHeight) _height = st::participantMaxHeight; - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void ContactsBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); + if (paint(p)) return; - // paint shadows - p.fillRect(0, _addContact.height(), _width, st::scrollDef.topsh, st::scrollDef.shColor->b); + if (_inner.chat() || _inner.creatingChat()) { + paintTitle(p, lang(_inner.chat() ? lng_profile_add_participant : lng_create_new_group), true); - // draw box title / text - p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_contacts_header)); - } + // paint button sep + p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); + paintTitle(p, lang(lng_contacts_header), true); } } void ContactsBox::resizeEvent(QResizeEvent *e) { - LayeredWidget::resizeEvent(e); - _addContact.move(_width - _addContact.width(), 0); + ItemListBox::resizeEvent(e); + _addContact.move(width() - _addContact.width(), 0); _filter.move(st::newGroupNamePadding.left(), _addContact.height() + st::newGroupNamePadding.top()); - _inner.resize(_width, _inner.height()); - _scroll.resize(_width, _height - _addContact.height() - st::newGroupNamePadding.top() - _filter.height() - st::newGroupNamePadding.bottom()); - _scroll.move(0, _filter.y() + _filter.height() + st::newGroupNamePadding.bottom()); - _close.move(0, _height - _close.height()); -} - -void ContactsBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - _filter.setFocus(); - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); -} - -void ContactsBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); + _inner.resize(width(), _inner.height()); + _next.move(width() - _next.width(), height() - _next.height()); + _cancel.move(0, height() - _cancel.height()); } void ContactsBox::onFilterUpdate() { @@ -563,14 +1031,144 @@ void ContactsBox::onAdd() { App::wnd()->replaceLayer(new AddContactBox()); } -void ContactsBox::onClose() { - emit closed(); +void ContactsBox::onInvite() { + QVector users(_inner.selected()); + if (users.isEmpty()) { + _filter.setFocus(); + return; + } + + App::main()->addParticipants(_inner.chat(), users); +} + +void ContactsBox::onNext() { + MTPVector users(MTP_vector(_inner.selectedInputs())); + const QVector &v(users.c_vector().v); + if (v.isEmpty()) { + _filter.setFocus(); + _filter.notaBene(); + } else if (v.size() == 1) { + App::main()->showPeer(_inner.selectedUser()->id); + } else { + App::wnd()->replaceLayer(new CreateGroupBox(users)); + } } void ContactsBox::onScroll() { _inner.loadProfilePhotos(_scroll.scrollTop()); } -ContactsBox::~ContactsBox() { +CreateGroupBox::CreateGroupBox(const MTPVector &users) : AbstractBox(), _users(users), +_createRequestId(0), +_name(this, st::newGroupName, lang(lng_dlg_new_group_name)), +_create(this, lang(lng_dlg_create_group), st::btnSelectDone), +_cancel(this, lang(lng_cancel), st::btnSelectCancel) { + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + _name.height() + st::addContactPadding.bottom() + _create.height()); + + connect(&_create, SIGNAL(clicked()), this, SLOT(onCreate())); + connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + + prepare(); +} + +void CreateGroupBox::hideAll() { + _name.hide(); + _cancel.hide(); + _create.hide(); +} + +void CreateGroupBox::showAll() { + _name.show(); + _cancel.show(); + _create.show(); +} + +void CreateGroupBox::showDone() { + _name.setFocus(); +} + +void CreateGroupBox::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { + if (_name.hasFocus()) { + if (_name.text().trimmed().isEmpty()) { + _name.setFocus(); + _name.notaBene(); + } else { + onCreate(); + } + } + } else { + AbstractBox::keyPressEvent(e); + } +} + +void CreateGroupBox::paintEvent(QPaintEvent *e) { + QPainter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_create_group_title), true); + + // paint shadow + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); + + // paint button sep + p.fillRect(st::btnSelectCancel.width, height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); +} + +void CreateGroupBox::resizeEvent(QResizeEvent *e) { + _name.setGeometry(st::addContactPadding.left(), st::boxTitleHeight + st::addContactPadding.top(), width() - st::addContactPadding.left() - st::addContactPadding.right(), _name.height()); + + int32 buttonTop = _name.y() + _name.height() + st::addContactPadding.bottom(); + _cancel.move(0, buttonTop); + _create.move(width() - _create.width(), buttonTop); +} + +void CreateGroupBox::onCreate() { + if (_createRequestId) return; + + QString name = _name.text(); + if (name.isEmpty()) { + _name.setFocus(); + _name.notaBene(); + return; + } + + _create.setDisabled(true); + _name.setDisabled(true); + _createRequestId = MTP::send(MTPmessages_CreateChat(_users, MTP_string(_name.text())), rpcDone(&CreateGroupBox::created), rpcFail(&CreateGroupBox::failed)); +} + +void CreateGroupBox::created(const MTPUpdates &updates) { + App::main()->sentUpdatesReceived(updates); + + App::wnd()->hideLayer(); + const QVector *v = 0; + switch (updates.type()) { + case mtpc_updates: v = &updates.c_updates().vchats.c_vector().v; break; + case mtpc_updatesCombined: v = &updates.c_updatesCombined().vchats.c_vector().v; break; + case mtpc_updateShort: { + } break; + case mtpc_updateShortMessage: { + } break; + case mtpc_updateShortChatMessage: { + } break; + case mtpc_updatesTooLong: { + } break; + } + if (v && !v->isEmpty() && v->front().type() == mtpc_chat) { + App::main()->showPeer(App::peerFromChat(v->front().c_chat().vid.v)); + } +} + +bool CreateGroupBox::failed(const RPCError &e) { + _createRequestId = 0; + if (e.type() == "NO_CHAT_TITLE") { + _name.setFocus(); + return true; + } else if (e.type() == "USERS_TOO_FEW") { + emit closed(); + return true; + } + return false; } diff --git a/Telegram/SourceFiles/boxes/contactsbox.h b/Telegram/SourceFiles/boxes/contactsbox.h index 77515bcdf..a6b1612fa 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.h +++ b/Telegram/SourceFiles/boxes/contactsbox.h @@ -17,14 +17,20 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" class ContactsInner : public QWidget, public RPCSender { Q_OBJECT +private: + + struct ContactData; + public: - ContactsInner(); + ContactsInner(bool creatingChat); + ContactsInner(ChatData *chat); + void init(); void paintEvent(QPaintEvent *e); void enterEvent(QEvent *e); @@ -33,19 +39,35 @@ public: void mousePressEvent(QMouseEvent *e); void resizeEvent(QResizeEvent *e); - void paintDialog(QPainter &p, DialogRow *row, bool sel); + void paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel); void updateFilter(QString filter = QString()); void selectSkip(int32 dir); void selectSkipPage(int32 h, int32 dir); + QVector selected(); + QVector selectedInputs(); + PeerData *selectedUser(); + void loadProfilePhotos(int32 yFrom); + void chooseParticipant(); + void changeCheckState(DialogRow *row); + void changeCheckState(ContactData *data); + + void peopleReceived(const QString &query, const QVector &people); + + void refresh(); + + ChatData *chat() const; + bool creatingChat() const; ~ContactsInner(); signals: void mustScrollTo(int ymin, int ymax); + void selectAllQuery(); + void searchByUsername(); public slots: @@ -54,10 +76,11 @@ public slots: void updateSel(); void peerUpdated(PeerData *peer); - void chooseParticipant(); - private: + ChatData *_chat; + bool _creatingChat; + int32 _time; DialogsIndexed *_contacts; @@ -68,58 +91,116 @@ private: int32 _filteredSel; bool _mouseSel; - typedef struct { + int32 _selCount; + + struct ContactData { Text name; QString online; - } ContactData; + bool inchat; + bool check; + }; typedef QMap ContactsData; ContactsData _contactsData; ContactData *contactData(DialogRow *row); + bool _searching; + QString _lastQuery; + typedef QVector ByUsernameRows; + typedef QVector ByUsernameDatas; + ByUsernameRows _byUsername, _byUsernameFiltered; + ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas + ByUsernameDatas _byUsernameDatas; + int32 _byUsernameSel; + QPoint _lastMousePos; LinkButton _addContactLnk; }; -class ContactsBox : public LayeredWidget, public RPCSender { +class ContactsBox : public ItemListBox, public RPCSender { Q_OBJECT public: - ContactsBox(); - void parentResized(); - void animStep(float64 dt); + ContactsBox(bool creatingChat = false); + ContactsBox(ChatData *chat); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); void resizeEvent(QResizeEvent *e); - void startHide(); - ~ContactsBox(); public slots: void onFilterUpdate(); - void onClose(); void onScroll(); - void onAdd(); -private: + void onAdd(); + void onInvite(); + void onNext(); + + bool onSearchByUsername(bool searchCache = false); + void onNeedSearchByUsername(); + +protected: void hideAll(); void showAll(); + void showDone(); - void created(const MTPmessages_StatedMessage &result); - bool failed(const RPCError &e); +private: + + void init(); - ScrollArea _scroll; ContactsInner _inner; FlatButton _addContact; - int32 _width, _height; FlatInput _filter; - BottomButton _close; - bool _hiding; - QPixmap _cache; + FlatButton _next, _cancel; - anim::fvalue a_opacity; + void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req); + bool peopleFailed(const RPCError &error, mtpRequestId req); + + QTimer _searchTimer; + QString _peopleQuery; + bool _peopleFull; + mtpRequestId _peopleRequest; + + typedef QMap PeopleCache; + PeopleCache _peopleCache; + + typedef QMap PeopleQueries; + PeopleQueries _peopleQueries; +}; + +class CreateGroupBox : public AbstractBox, public RPCSender { + Q_OBJECT + +public: + + CreateGroupBox(const MTPVector &users); + void keyPressEvent(QKeyEvent *e); + void paintEvent(QPaintEvent *e); + void resizeEvent(QResizeEvent *e); + +public slots: + + void onCreate(); + +protected: + + void hideAll(); + void showAll(); + void showDone(); + +private: + + void created(const MTPUpdates &updates); + bool failed(const RPCError &e); + + MTPVector _users; + + int32 _createRequestId; + + FlatInput _name; + FlatButton _create, _cancel; }; diff --git a/Telegram/SourceFiles/boxes/downloadpathbox.cpp b/Telegram/SourceFiles/boxes/downloadpathbox.cpp index 5981baf2e..9bfd73734 100644 --- a/Telegram/SourceFiles/boxes/downloadpathbox.cpp +++ b/Telegram/SourceFiles/boxes/downloadpathbox.cpp @@ -30,13 +30,10 @@ DownloadPathBox::DownloadPathBox() : _dirRadio(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), !_path.isEmpty() && _path != qsl("tmp")), _dirInput(this, st::inpDownloadDir, QString(), (_path.isEmpty() || _path == qsl("tmp")) ? QString() : QDir::toNativeSeparators(_path)), _saveButton(this, lang(lng_connection_save), st::btnSelectDone), - _cancelButton(this, lang(lng_cancel), st::btnSelectCancel), - a_opacity(0, 1), _hiding(false) { - - _width = st::addContactWidth; + _cancelButton(this, lang(lng_cancel), st::btnSelectCancel) { connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSave())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); connect(&_defaultRadio, SIGNAL(changed()), this, SLOT(onChange())); connect(&_tempRadio, SIGNAL(changed()), this, SLOT(onChange())); @@ -45,9 +42,7 @@ DownloadPathBox::DownloadPathBox() : connect(&_dirInput, SIGNAL(focused()), this, SLOT(onEditPath())); _dirInput.setCursorPosition(0); - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void DownloadPathBox::hideAll() { @@ -75,71 +70,38 @@ void DownloadPathBox::showAll() { _saveButton.show(); _cancelButton.show(); - _defaultRadio.move(st::boxPadding.left(), st::addContactTitleHeight + st::downloadSkip); + int32 h = st::boxTitleHeight + st::downloadSkip + _defaultRadio.height() + st::downloadSkip + _tempRadio.height() + st::downloadSkip + _dirRadio.height(); + if (_dirRadio.checked()) h += st::boxPadding.top() + _dirInput.height(); + h += st::downloadSkip + _saveButton.height(); + + setMaxHeight(h); +} + +void DownloadPathBox::paintEvent(QPaintEvent *e) { + QPainter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_download_path_header), true); + + // paint shadows + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); + + // paint button sep + p.fillRect(st::btnSelectCancel.width, height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); +} + +void DownloadPathBox::resizeEvent(QResizeEvent *e) { + _defaultRadio.move(st::boxPadding.left(), st::boxTitleHeight + st::downloadSkip); _tempRadio.move(st::boxPadding.left(), _defaultRadio.y() + _defaultRadio.height() + st::downloadSkip); _dirRadio.move(st::boxPadding.left(), _tempRadio.y() + _tempRadio.height() + st::downloadSkip); int32 inputy = _dirRadio.y() + _dirRadio.height() + st::boxPadding.top(); _dirInput.move(st::boxPadding.left() + st::rbDefFlat.textLeft, inputy); - + int32 buttony = (_dirRadio.checked() ? (_dirInput.y() + _dirInput.height()) : (_dirRadio.y() + _dirRadio.height())) + st::downloadSkip; - _saveButton.move(_width - _saveButton.width(), buttony); + _saveButton.move(width() - _saveButton.width(), buttony); _cancelButton.move(0, buttony); - - _height = _saveButton.y() + _saveButton.height(); - resize(_width, _height); -} - -void DownloadPathBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - } else if (e->key() == Qt::Key_Escape) { - onCancel(); - } -} - -void DownloadPathBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - -void DownloadPathBox::paintEvent(QPaintEvent *e) { - QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(0, 0, _width, _height, st::boxBG->b); - - // paint shadows - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); - - // paint button sep - p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - - // draw box title / text - p.setFont(st::addContactTitleFont->f); - p.setPen(st::black->p); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_download_path_header)); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } -} - -void DownloadPathBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); } void DownloadPathBox::onChange() { @@ -186,19 +148,3 @@ void DownloadPathBox::onSave() { Local::writeUserSettings(); emit closed(); } - -void DownloadPathBox::onCancel() { - emit closed(); -} - -void DownloadPathBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -DownloadPathBox::~DownloadPathBox() { -} diff --git a/Telegram/SourceFiles/boxes/downloadpathbox.h b/Telegram/SourceFiles/boxes/downloadpathbox.h index e6fd6caac..7219612ef 100644 --- a/Telegram/SourceFiles/boxes/downloadpathbox.h +++ b/Telegram/SourceFiles/boxes/downloadpathbox.h @@ -17,43 +17,33 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" -#include "gui/phoneinput.h" +#include "abstractbox.h" -class DownloadPathBox : public LayeredWidget { +class DownloadPathBox : public AbstractBox { Q_OBJECT public: DownloadPathBox(); - void parentResized(); - void animStep(float64 dt); - void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); - ~DownloadPathBox(); + void resizeEvent(QResizeEvent *e); public slots: void onChange(); void onEditPath(); void onSave(); - void onCancel(); -private: +protected: void hideAll(); void showAll(); +private: + QString _path; FlatRadiobutton _defaultRadio, _tempRadio, _dirRadio; FlatInput _dirInput; FlatButton _saveButton, _cancelButton; - - int32 _width, _height; - QPixmap _cache; - - anim::fvalue a_opacity; - bool _hiding; }; diff --git a/Telegram/SourceFiles/boxes/emojibox.cpp b/Telegram/SourceFiles/boxes/emojibox.cpp index 04fa6ff03..85b8b574d 100644 --- a/Telegram/SourceFiles/boxes/emojibox.cpp +++ b/Telegram/SourceFiles/boxes/emojibox.cpp @@ -68,31 +68,16 @@ namespace { const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace), replacesInRow = 7; } -EmojiBox::EmojiBox() : _done(this, lang(lng_about_done), st::aboutCloseButton), - _hiding(false), a_opacity(0, 1) { - +EmojiBox::EmojiBox() : _done(this, lang(lng_about_done), st::aboutCloseButton) { fillBlocks(); _blockHeight = st::emojiReplaceInnerHeight; - _width = _blocks[0].size() * st::emojiReplaceWidth + (st::emojiReplaceWidth - st::emojiSize); - - _height = st::boxPadding.top() + st::boxFont->height; - _height += _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight); - _height += _done.height(); - - _done.setWidth(_width); - _header.setText(st::boxFont, lang(lng_settings_emoji_list)); - - _done.move(0, _height - _done.height()); + resizeMaxHeight(_blocks[0].size() * st::emojiReplaceWidth + (st::emojiReplaceWidth - st::emojiSize), st::boxPadding.top() + st::boxFont->height + _blocks.size() * st::emojiReplaceHeight + (st::emojiReplaceHeight - _blockHeight) + _done.height()); connect(&_done, SIGNAL(clicked()), this, SLOT(onClose())); - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void EmojiBox::fillBlocks() { @@ -122,77 +107,35 @@ void EmojiBox::showAll() { void EmojiBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { onClose(); - } else if (e->key() == Qt::Key_Escape) { - onClose(); + } else { + AbstractBox::keyPressEvent(e); } } -void EmojiBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void EmojiBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(0, 0, _width, _height, st::boxBG->b); + if (paint(p)) return; - p.setFont(st::boxFont->f); - p.setPen(st::boxGrayTitle->p); - _header.draw(p, 0, st::boxPadding.top(), _width, Qt::AlignCenter); + paintGrayTitle(p, lang(lng_settings_emoji_list)); - p.setFont(st::emojiTextFont->f); - p.setPen(st::black->p); - int32 top = st::boxPadding.top() + st::boxFont->height + (st::emojiReplaceHeight - _blockHeight) / 2; - for (Blocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) { - int32 rowSize = i->size(), left = (_width - rowSize * st::emojiReplaceWidth) / 2; - for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) { - if (j->emoji) { - QPoint pos(left + (st::emojiReplaceWidth - st::emojiSize) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2); - p.drawPixmap(pos, App::emojis(), QRect(j->emoji->x, j->emoji->y, st::emojiImgSize, st::emojiImgSize)); - } - QRect trect(left, top + (st::emojiReplaceHeight + _blockHeight) / 2 - st::emojiTextFont->height, st::emojiReplaceWidth, st::emojiTextFont->height); - p.drawText(trect, j->text, QTextOption(Qt::AlignHCenter | Qt::AlignTop)); - left += st::emojiReplaceWidth; - } - top += st::emojiReplaceHeight; + p.setFont(st::emojiTextFont->f); + p.setPen(st::black->p); + int32 top = st::boxPadding.top() + st::boxFont->height + (st::emojiReplaceHeight - _blockHeight) / 2; + for (Blocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) { + int32 rowSize = i->size(), left = (width() - rowSize * st::emojiReplaceWidth) / 2; + for (BlockRow::const_iterator j = i->cbegin(), en = i->cend(); j != en; ++j) { + if (j->emoji) { + QPoint pos(left + (st::emojiReplaceWidth - st::emojiSize) / 2, top + (st::emojiReplaceHeight - _blockHeight) / 2); + p.drawPixmap(pos, App::emojis(), QRect(j->emoji->x, j->emoji->y, st::emojiImgSize, st::emojiImgSize)); } + QRect trect(left, top + (st::emojiReplaceHeight + _blockHeight) / 2 - st::emojiTextFont->height, st::emojiReplaceWidth, st::emojiTextFont->height); + p.drawText(trect, j->text, QTextOption(Qt::AlignHCenter | Qt::AlignTop)); + left += st::emojiReplaceWidth; } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); + top += st::emojiReplaceHeight; } } -void EmojiBox::animStep(float64 ms) { - if (ms >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - setFocus(); - } - } else { - a_opacity.update(ms, anim::linear); - } - update(); -} - -void EmojiBox::onClose() { - emit closed(); -} - -void EmojiBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -EmojiBox::~EmojiBox() { +void EmojiBox::resizeEvent(QResizeEvent *e) { + _done.setGeometry(0, height() - _done.height(), width(), _done.height()); } diff --git a/Telegram/SourceFiles/boxes/emojibox.h b/Telegram/SourceFiles/boxes/emojibox.h index 7915c548e..f3c4f90b0 100644 --- a/Telegram/SourceFiles/boxes/emojibox.h +++ b/Telegram/SourceFiles/boxes/emojibox.h @@ -17,37 +17,29 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class EmojiBox : public LayeredWidget { +class EmojiBox : public AbstractBox { Q_OBJECT public: EmojiBox(); - void parentResized(); - void animStep(float64 ms); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); - ~EmojiBox(); + void resizeEvent(QResizeEvent *e); -public slots: - - void onClose(); - -private: +protected: void hideAll(); void showAll(); +private: + void fillBlocks(); - int32 _width, _height; BottomButton _done; - Text _header; - int32 _blockHeight; struct Block { Block(const EmojiData *emoji = 0, const QString &text = QString()) : emoji(emoji), text(text) { @@ -58,9 +50,4 @@ private: typedef QVector BlockRow; typedef QVector Blocks; Blocks _blocks; - - bool _hiding; - QPixmap _cache; - - anim::fvalue a_opacity; }; diff --git a/Telegram/SourceFiles/boxes/languagebox.cpp b/Telegram/SourceFiles/boxes/languagebox.cpp index 25a973fb2..44be0e895 100644 --- a/Telegram/SourceFiles/boxes/languagebox.cpp +++ b/Telegram/SourceFiles/boxes/languagebox.cpp @@ -28,15 +28,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "langloaderplain.h" LanguageBox::LanguageBox() : -_done(this, lang(lng_about_done), st::langsCloseButton), -_hiding(false), a_opacity(0, 1) { +_done(this, lang(lng_about_done), st::langsCloseButton) { bool haveTestLang = (cLang() == languageTest); - _width = st::langsWidth; - _height = st::addContactTitleHeight + st::langsPadding.top() + st::langsPadding.bottom() + (languageCount + (haveTestLang ? 1 : 0)) * (st::langPadding.top() + st::rbDefFlat.height + st::langPadding.bottom()) + _done.height(); - - int32 y = st::addContactTitleHeight + st::langsPadding.top(); + int32 y = st::boxTitleHeight + st::langsPadding.top(); _langs.reserve(languageCount + (haveTestLang ? 1 : 0)); if (haveTestLang) { _langs.push_back(new FlatRadiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langButton)); @@ -58,15 +54,11 @@ _hiding(false), a_opacity(0, 1) { connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange())); } - _done.move(0, _height - _done.height()); + resizeMaxHeight(st::langsWidth, st::boxTitleHeight + st::langsPadding.top() + st::langsPadding.bottom() + (languageCount + (haveTestLang ? 1 : 0)) * (st::langPadding.top() + st::rbDefFlat.height + st::langPadding.bottom()) + _done.height()); connect(&_done, SIGNAL(clicked()), this, SLOT(onClose())); - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void LanguageBox::hideAll() { @@ -83,12 +75,6 @@ void LanguageBox::showAll() { } } -void LanguageBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - onClose(); - } -} - void LanguageBox::mousePressEvent(QMouseEvent *e) { if ((e->modifiers() & Qt::CTRL) && (e->modifiers() & Qt::ALT) && (e->modifiers() & Qt::SHIFT)) { for (int32 i = 1; i < languageCount; ++i) { @@ -107,45 +93,15 @@ void LanguageBox::mousePressEvent(QMouseEvent *e) { } } -void LanguageBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void LanguageBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(0, 0, _width, _height, st::boxBG->b); + if (paint(p)) return; - // paint shadows - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - - // draw box title / text - p.setFont(st::addContactTitleFont->f); - p.setPen(st::black->p); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_languages)); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } + paintTitle(p, lang(lng_languages), true); } -void LanguageBox::animStep(float64 ms) { - if (ms >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - setFocus(); - } - } else { - a_opacity.update(ms, anim::linear); - } - update(); +void LanguageBox::resizeEvent(QResizeEvent *e) { + _done.move(0, height() - _done.height()); } void LanguageBox::onChange() { @@ -193,19 +149,6 @@ void LanguageBox::onSave() { } } -void LanguageBox::onClose() { - emit closed(); -} - -void LanguageBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - LanguageBox::~LanguageBox() { for (int32 i = 0, l = _langs.size(); i < l; ++i) { delete _langs[i]; diff --git a/Telegram/SourceFiles/boxes/languagebox.h b/Telegram/SourceFiles/boxes/languagebox.h index 12ce5c7d1..c5cb8e5da 100644 --- a/Telegram/SourceFiles/boxes/languagebox.h +++ b/Telegram/SourceFiles/boxes/languagebox.h @@ -17,20 +17,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class LanguageBox : public LayeredWidget { +class LanguageBox : public AbstractBox { Q_OBJECT public: LanguageBox(); - void parentResized(); - void animStep(float64 ms); - void keyPressEvent(QKeyEvent *e); void mousePressEvent(QMouseEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); + void resizeEvent(QResizeEvent *e); ~LanguageBox(); public slots: @@ -38,19 +35,14 @@ public slots: void onChange(); void onRestore(); void onSave(); - void onClose(); -private: +protected: void hideAll(); void showAll(); +private: + QVector _langs; - int32 _width, _height; BottomButton _done; - - bool _hiding; - QPixmap _cache; - - anim::fvalue a_opacity; }; diff --git a/Telegram/SourceFiles/boxes/newgroupbox.cpp b/Telegram/SourceFiles/boxes/newgroupbox.cpp deleted file mode 100644 index 2b89c418b..000000000 --- a/Telegram/SourceFiles/boxes/newgroupbox.cpp +++ /dev/null @@ -1,1095 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014 John Preston, https://desktop.telegram.org -*/ -#include "stdafx.h" -#include "lang.h" - -#include "newgroupbox.h" -#include "mainwidget.h" -#include "window.h" - -#include "confirmbox.h" - -NewGroupInner::NewGroupInner() : -_contacts(&App::main()->contactsList()), -_sel(0), -_filteredSel(-1), -_mouseSel(false), -_selCount(0), -_searching(false), -_byUsernameSel(-1), -_addContactLnk(this, lang(lng_add_contact_button)) { - - connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); - - for (DialogRow *r = _contacts->list.begin; r != _contacts->list.end; r = r->next) { - r->attached = 0; - } - - _filter = qsl("a"); - updateFilter(); - - for (DialogRow *r = _contacts->list.begin; r != _contacts->list.end; r = r->next) { - r->attached = 0; - } - - connect(App::main(), SIGNAL(dialogRowReplaced(DialogRow *, DialogRow *)), this, SLOT(onDialogRowReplaced(DialogRow *, DialogRow *))); - connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData *))); - connect(App::main(), SIGNAL(peerNameChanged(PeerData *, const PeerData::Names &, const PeerData::NameFirstChars &)), this, SLOT(peerUpdated(PeerData *))); - connect(App::main(), SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(peerUpdated(PeerData *))); -} - -void NewGroupInner::peerUpdated(PeerData *peer) { - if (!peer->chat) { - ContactsData::iterator i = _contactsData.find(peer->asUser()); - if (i != _contactsData.cend()) { - for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) { - if (row->attached == i.value()) row->attached = 0; - } - if (!_filter.isEmpty()) { - for (int32 j = 0, s = _filtered.size(); j < s; ++j) { - if (_filtered[j]->attached == i.value()) _filtered[j]->attached = 0; - } - } - delete i.value(); - _contactsData.erase(i); - } - } - - parentWidget()->update(); -} - -void NewGroupInner::loadProfilePhotos(int32 yFrom) { - int32 yTo = yFrom + (parentWidget() ? parentWidget()->height() : App::wnd()->height()) * 5; - MTP::clearLoaderPriorities(); - - if (yTo < 0) return; - if (yFrom < 0) yFrom = 0; - - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - if (_contacts->list.count) { - _contacts->list.adjustCurrent(yFrom, rh); - for ( - DialogRow *preloadFrom = _contacts->list.current; - preloadFrom != _contacts->list.end && preloadFrom->pos * rh < yTo; - preloadFrom = preloadFrom->next - ) { - preloadFrom->history->peer->photo->load(); - } - } - yFrom -= _contacts->list.count * rh + st::searchedBarHeight; - yTo -= _contacts->list.count * rh + st::searchedBarHeight; - int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsername.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsername.size()) to = _byUsername.size(); - for (; from < to; ++from) { - _byUsername[from]->photo->load(); - } - } - } else if (!_filtered.isEmpty()) { - int32 from = yFrom / rh; - if (from < 0) from = 0; - if (from < _filtered.size()) { - int32 to = (yTo / rh) + 1; - if (to > _filtered.size()) to = _filtered.size(); - - for (; from < to; ++from) { - _filtered[from]->history->peer->photo->load(); - } - } - yFrom -= _filtered.size() * rh + st::searchedBarHeight; - yTo -= _filtered.size() * rh + st::searchedBarHeight; - from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsernameFiltered.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size(); - for (; from < to; ++from) { - _byUsernameFiltered[from]->photo->load(); - } - } - } -} - -NewGroupInner::ContactData *NewGroupInner::contactData(DialogRow *row) { - ContactData *data = (ContactData*)row->attached; - if (!data) { - UserData *user = row->history->peer->asUser(); - ContactsData::const_iterator i = _contactsData.constFind(user); - if (i == _contactsData.cend()) { - _contactsData.insert(user, data = new ContactData()); - data->check = false; - data->name.setText(st::profileListNameFont, user->name, _textNameOptions); - data->online = App::onlineText(user, _time); - } else { - data = i.value(); - } - row->attached = data; - } - return data; -} - -void NewGroupInner::paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel) { - int32 left = st::profileListPadding.width(); - - if (_selCount >= cMaxGroupCount() && !data->check) { - sel = false; - } - - if (sel || data->check) { - p.fillRect(0, 0, width(), 2 * st::profileListPadding.height() + st::profileListPhotoSize, (data->check ? st::profileActiveBG : st::profileHoverBG)->b); - } - - p.drawPixmap(left, st::profileListPadding.height(), user->photo->pix(st::profileListPhotoSize)); - - if (data->check) { - p.setPen(st::white->p); - } else { - p.setPen(st::profileListNameColor->p); - } - data->name.drawElided(p, left + st::profileListPhotoSize + st::participantDelta, st::profileListNameTop, width() - st::profileListPadding.width() - st::profileListPhotoSize - st::profileListPadding.width() - st::participantDelta - st::scrollDef.width - st::profileCheckRect.pxWidth()); - - if (sel || data->check) { - p.drawPixmap(QPoint(width() - st::profileCheckRect.pxWidth() - st::profileCheckDeltaX, st::profileListPadding.height() + (st::profileListPhotoSize - st::profileCheckRect.pxHeight()) / 2 - st::profileCheckDeltaY), App::sprite(), (data->check ? st::profileCheckActiveRect : st::profileCheckRect)); - } - - bool uname = (data->online.at(0) == '@'); - p.setFont(st::profileSubFont->f); - if (uname && !data->check && !_lastQuery.isEmpty() && user->username.startsWith(_lastQuery, Qt::CaseInsensitive)) { - int32 availw = width() - (left + st::profileListPhotoSize + st::profileListPadding.width() * 2); - QString first = '@' + user->username.mid(0, _lastQuery.size()), second = user->username.mid(_lastQuery.size()); - int32 w = st::profileSubFont->m.width(first); - if (w >= availw || second.isEmpty()) { - p.setPen(st::profileOnlineColor->p); - p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(first, Qt::ElideRight, availw)); - } else { - p.setPen(st::profileOnlineColor->p); - p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, first); - p.setPen(st::profileOfflineColor->p); - p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width() + w, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(second, Qt::ElideRight, availw - w)); - } - } else { - if (data->check) { - p.setPen(st::white->p); - } else { - p.setPen(((uname || App::onlineColorUse(user->onlineTill, _time)) ? st::profileOnlineColor : st::profileOfflineColor)->p); - } - p.drawText(left + st::profileListPhotoSize + st::participantDelta, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online); - } -} - -void NewGroupInner::paintEvent(QPaintEvent *e) { - QRect r(e->rect()); - QPainter p(this); - - _time = unixtime(); - p.fillRect(r, st::white->b); - - int32 yFrom = r.top(), yTo = r.bottom(); - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - if (_contacts->list.count || !_byUsername.isEmpty()) { - if (_contacts->list.count) { - _contacts->list.adjustCurrent(yFrom, rh); - - DialogRow *drawFrom = _contacts->list.current; - p.translate(0, drawFrom->pos * rh); - while (drawFrom != _contacts->list.end && drawFrom->pos * rh < r.bottom()) { - paintDialog(p, drawFrom->history->peer->asUser(), contactData(drawFrom), (drawFrom == _sel)); - p.translate(0, rh); - drawFrom = drawFrom->next; - } - } - if (!_byUsername.isEmpty()) { - p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); - p.setFont(st::searchedBarFont->f); - p.setPen(st::searchedBarColor->p); - p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center); - p.translate(0, st::searchedBarHeight); - - yFrom -= _contacts->list.count * rh + st::searchedBarHeight; - yTo -= _contacts->list.count * rh + st::searchedBarHeight; - int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsername.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsername.size()) to = _byUsername.size(); - - p.translate(0, from * rh); - for (; from < to; ++from) { - paintDialog(p, _byUsername[from], d_byUsername[from], (_byUsernameSel == from)); - p.translate(0, rh); - } - } - } - } else { - p.setFont(st::noContactsFont->f); - p.setPen(st::noContactsColor->p); - p.drawText(QRect(0, 0, width(), st::noContactsHeight - ((cContactsReceived() && !_searching) ? st::noContactsFont->height : 0)), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_loading), style::al_center); - } - } else { - if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { - p.setFont(st::noContactsFont->f); - p.setPen(st::noContactsColor->p); - p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_not_found), style::al_center); - } else { - if (!_filtered.isEmpty()) { - int32 from = yFrom / rh; - if (from < 0) from = 0; - if (from < _filtered.size()) { - int32 to = (r.bottom() / rh) + 1; - if (to > _filtered.size()) to = _filtered.size(); - - p.translate(0, from * rh); - for (; from < to; ++from) { - paintDialog(p, _filtered[from]->history->peer->asUser(), contactData(_filtered[from]), (_filteredSel == from)); - p.translate(0, rh); - } - } - } - if (!_byUsernameFiltered.isEmpty()) { - p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); - p.setFont(st::searchedBarFont->f); - p.setPen(st::searchedBarColor->p); - p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center); - p.translate(0, st::searchedBarHeight); - - yFrom -= _filtered.size() * rh + st::searchedBarHeight; - yTo -= _filtered.size() * rh + st::searchedBarHeight; - int32 from = (yFrom >= 0) ? (yFrom / rh) : 0; - if (from < _byUsernameFiltered.size()) { - int32 to = (yTo / rh) + 1; - if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size(); - - p.translate(0, from * rh); - for (; from < to; ++from) { - paintDialog(p, _byUsernameFiltered[from], d_byUsernameFiltered[from], (_byUsernameSel == from)); - p.translate(0, rh); - } - } - } - } - } -} - -void NewGroupInner::enterEvent(QEvent *e) { - setMouseTracking(true); -} - -void NewGroupInner::leaveEvent(QEvent *e) { - setMouseTracking(false); - if (_sel || _filteredSel >= 0 || _byUsernameSel >= 0) { - _sel = 0; - _filteredSel = _byUsernameSel = -1; - parentWidget()->update(); - } -} - -void NewGroupInner::mouseMoveEvent(QMouseEvent *e) { - _mouseSel = true; - _lastMousePos = e->globalPos(); - updateSel(); -} - -void NewGroupInner::mousePressEvent(QMouseEvent *e) { - _mouseSel = true; - _lastMousePos = e->globalPos(); - updateSel(); - if (e->button() == Qt::LeftButton) { - chooseParticipant(); - } -} - -void NewGroupInner::changeCheckState(DialogRow *row) { - changeCheckState(contactData(row)); -} - -void NewGroupInner::changeCheckState(ContactData *data) { - if (data->check) { - data->check = false; - --_selCount; - } else if (_selCount < cMaxGroupCount()) { - data->check = true; - ++_selCount; - } -} - -void NewGroupInner::chooseParticipant() { - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from; - if (_filter.isEmpty()) { - if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) { - changeCheckState(d_byUsername[_byUsernameSel]); - } else { - if (!_sel) return; - changeCheckState(_sel); - } - } else { - if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) { - changeCheckState(d_byUsernameFiltered[_byUsernameSel]); - - ContactData *moving = d_byUsernameFiltered[_byUsernameSel]; - int32 i = 0, l = d_byUsername.size(); - for (; i < l; ++i) { - if (d_byUsername[i] == moving) { - break; - } - } - if (i == l) { - d_byUsername.push_back(moving); - _byUsername.push_back(_byUsernameFiltered[_byUsernameSel]); - for (i = 0, l = _byUsernameDatas.size(); i < l;) { - if (_byUsernameDatas[i] == moving) { - _byUsernameDatas.removeAt(i); - --l; - } else { - ++i; - } - } - } - } else { - if (_filteredSel < 0 || _filteredSel >= _filtered.size()) return; - changeCheckState(_filtered[_filteredSel]); - } - emit selectAllQuery(); - } - - parentWidget()->update(); -} - -void NewGroupInner::peopleReceived(const QString &query, const QVector &people) { - _lastQuery = query.toLower().trimmed(); - if (_lastQuery.at(0) == '@') _lastQuery = _lastQuery.mid(1); - int32 already = _byUsernameFiltered.size(); - _byUsernameFiltered.reserve(already + people.size()); - d_byUsernameFiltered.reserve(already + people.size()); - for (QVector::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) { - int32 uid = i->c_contactFound().vuser_id.v, j = 0; - for (; j < already; ++j) { - if (_byUsernameFiltered[j]->id == App::peerFromUser(uid)) break; - } - if (j == already) { - UserData *u = App::user(uid); - ContactData *d = new ContactData(); - _byUsernameDatas.push_back(d); - d->check = false; - d->name.setText(st::profileListNameFont, u->name, _textNameOptions); - d->online = '@' + u->username; - - _byUsernameFiltered.push_back(u); - d_byUsernameFiltered.push_back(d); - } - } - _searching = false; - refresh(); -} - -void NewGroupInner::refresh() { - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - if (_contacts->list.count || !_byUsername.isEmpty()) { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - resize(width(), (_contacts->list.count * rh) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * rh))); - } else { - if (cContactsReceived()) { - if (_addContactLnk.isHidden()) _addContactLnk.show(); - } else { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - } - resize(width(), st::noContactsHeight); - } - } else { - if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - resize(width(), st::noContactsHeight); - } else { - resize(width(), (_filtered.size() * rh) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * rh))); - } - } -} - -void NewGroupInner::updateSel() { - if (!_mouseSel) return; - - QPoint p(mapFromGlobal(_lastMousePos)); - bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos)); - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - if (_filter.isEmpty()) { - DialogRow *newSel = (in && (p.y() >= 0) && (p.y() < _contacts->list.count * rh)) ? _contacts->list.rowAtY(p.y(), rh) : 0; - int32 byUsernameSel = (in && p.y() >= _contacts->list.count * rh + st::searchedBarHeight) ? ((p.y() - _contacts->list.count * rh - st::searchedBarHeight) / rh) : -1; - if (byUsernameSel >= _byUsername.size()) byUsernameSel = -1; - if (newSel != _sel || byUsernameSel != _byUsernameSel) { - _sel = newSel; - _byUsernameSel = byUsernameSel; - parentWidget()->update(); - } - } else { - int32 newFilteredSel = (in && p.y() >= 0 && p.y() < _filtered.size() * rh) ? (p.y() / rh) : -1; - int32 byUsernameSel = (in && p.y() >= _filtered.size() * rh + st::searchedBarHeight) ? ((p.y() - _filtered.size() * rh - st::searchedBarHeight) / rh) : -1; - if (byUsernameSel >= _byUsernameFiltered.size()) byUsernameSel = -1; - if (newFilteredSel != _filteredSel || byUsernameSel != _byUsernameSel) { - _filteredSel = newFilteredSel; - _byUsernameSel = byUsernameSel; - parentWidget()->update(); - } - } -} - -void NewGroupInner::updateFilter(QString filter) { - _lastQuery = filter.toLower().trimmed(); - filter = textSearchKey(filter); - - QStringList f; - if (!filter.isEmpty()) { - QStringList filterList = filter.split(cWordSplit(), QString::SkipEmptyParts); - int l = filterList.size(); - - f.reserve(l); - for (int i = 0; i < l; ++i) { - QString filterName = filterList[i].trimmed(); - if (filterName.isEmpty()) continue; - f.push_back(filterName); - } - filter = f.join(' '); - } - if (_filter != filter) { - int32 rh = (st::profileListPhotoSize + st::profileListPadding.height() * 2); - _filter = filter; - - _byUsernameFiltered.clear(); - d_byUsernameFiltered.clear(); - for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) { - delete _byUsernameDatas[i]; - } - _byUsernameDatas.clear(); - - if (_filter.isEmpty()) { - _sel = 0; - if (_contacts->list.count) { - _sel = _contacts->list.begin; - } - if (!_sel && !_byUsername.isEmpty()) { - _byUsernameSel = 0; - } - refresh(); - } else { - if (!_addContactLnk.isHidden()) _addContactLnk.hide(); - QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi; - - _filtered.clear(); - if (!f.isEmpty()) { - DialogsList *dialogsToFilter = 0; - if (_contacts->list.count) { - for (fi = fb; fi != fe; ++fi) { - DialogsIndexed::DialogsIndex::iterator i = _contacts->index.find(fi->at(0)); - if (i == _contacts->index.cend()) { - dialogsToFilter = 0; - break; - } - if (!dialogsToFilter || dialogsToFilter->count > i.value()->count) { - dialogsToFilter = i.value(); - } - } - } - if (dialogsToFilter && dialogsToFilter->count) { - _filtered.reserve(dialogsToFilter->count); - for (DialogRow *i = dialogsToFilter->begin, *e = dialogsToFilter->end; i != e; i = i->next) { - const PeerData::Names &names(i->history->peer->names); - PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni; - for (fi = fb; fi != fe; ++fi) { - QString filterName(*fi); - for (ni = nb; ni != ne; ++ni) { - if (ni->startsWith(*fi)) { - break; - } - } - if (ni == ne) { - break; - } - } - if (fi == fe) { - i->attached = 0; - _filtered.push_back(i); - } - } - } - - _byUsernameFiltered.reserve(_byUsername.size()); - d_byUsernameFiltered.reserve(d_byUsername.size()); - for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { - const PeerData::Names &names(_byUsername[i]->names); - PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni; - for (fi = fb; fi != fe; ++fi) { - QString filterName(*fi); - for (ni = nb; ni != ne; ++ni) { - if (ni->startsWith(*fi)) { - break; - } - } - if (ni == ne) { - break; - } - } - if (fi == fe) { - _byUsernameFiltered.push_back(_byUsername[i]); - d_byUsernameFiltered.push_back(d_byUsername[i]); - } - } - } - _filteredSel = _filtered.isEmpty() ? -1 : 0; - _byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1; - - refresh(); - - _searching = true; - emit searchByUsername(); - } - if (parentWidget()) parentWidget()->update(); - loadProfilePhotos(0); - } -} - -void NewGroupInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) { - if (!_filter.isEmpty()) { - for (FilteredDialogs::iterator i = _filtered.begin(), e = _filtered.end(); i != e;) { - if (*i == oldRow) { // this row is shown in filtered and maybe is in contacts! - if (newRow) { - *i = newRow; - ++i; - } else { - i = _filtered.erase(i); - } - } else { - ++i; - } - } - if (_filteredSel >= _filtered.size()) { - _filteredSel = -1; - } - } else { - if (_sel == oldRow) { - _sel = newRow; - } - } - _mouseSel = false; - int32 rh = (st::profileListPhotoSize + st::profileListPadding.height() * 2); - int32 newh = (_filter.isEmpty() ? _contacts->list.count : _filtered.size()) * rh; - resize(width(), newh); -} - -NewGroupInner::~NewGroupInner() { - for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { - delete *i; - } - for (ByUsernameDatas::const_iterator i = d_byUsername.cbegin(), e = d_byUsername.cend(); i != e; ++i) { - delete *i; - } - for (ByUsernameDatas::const_iterator i = _byUsernameDatas.cbegin(), e = _byUsernameDatas.cend(); i != e; ++i) { - delete *i; - } -} - -void NewGroupInner::resizeEvent(QResizeEvent *e) { - _addContactLnk.move((width() - _addContactLnk.width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2); -} - -void NewGroupInner::selectSkip(int32 dir) { - _mouseSel = false; - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, origDir = dir; - if (_filter.isEmpty()) { - int cur = 0; - if (_sel) { - for (DialogRow *i = _contacts->list.begin; i != _sel; i = i->next) { - ++cur; - } - } else { - cur = (_byUsernameSel >= 0) ? (_contacts->list.count + _byUsernameSel) : -1; - } - cur += dir; - if (cur <= 0) { - _sel = _contacts->list.count ? _contacts->list.begin : 0; - _byUsernameSel = (!_contacts->list.count && !_byUsername.isEmpty()) ? 0 : -1; - } else if (cur >= _contacts->list.count) { - _sel = 0; - _byUsernameSel = cur - _contacts->list.count; - if (_byUsernameSel >= _byUsername.size()) _byUsernameSel = _byUsername.size() - 1; - } else { - for (_sel = _contacts->list.begin; cur; _sel = _sel->next) { - --cur; - } - _byUsernameSel = -1; - } - if (_sel) { - emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh); - } else if (_byUsernameSel >= 0) { - emit mustScrollTo((_contacts->list.count + _byUsernameSel) * rh + st::searchedBarHeight, (_contacts->list.count + _byUsernameSel + 1) * rh + st::searchedBarHeight); - } - } else { - int cur = (_filteredSel >= 0) ? _filteredSel : ((_byUsernameSel >= 0) ? (_filtered.size() + _byUsernameSel) : -1); - cur += dir; - if (cur <= 0) { - _filteredSel = _filtered.isEmpty() ? -1 : 0; - _byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1; - } else if (cur >= _filtered.size()) { - _filteredSel = -1; - _byUsernameSel = cur - _filtered.size(); - if (_byUsernameSel >= _byUsernameFiltered.size()) _byUsernameSel = _byUsernameFiltered.size() - 1; - } else { - _filteredSel = cur; - _byUsernameSel = -1; - } - if (_filteredSel >= 0) { - emit mustScrollTo(_filteredSel * rh, (_filteredSel + 1) * rh); - } else if (_byUsernameSel >= 0) { - int skip = _filtered.size() * rh + st::searchedBarHeight; - emit mustScrollTo(skip + _byUsernameSel * rh, skip + (_byUsernameSel + 1) * rh); - } - } - parentWidget()->update(); -} - -void NewGroupInner::selectSkipPage(int32 h, int32 dir) { - int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2; - int32 points = h / rh; - if (!points) return; - selectSkip(points * dir); -} - -QVector NewGroupInner::selectedInputs() { - QVector result; - result.reserve(_contactsData.size()); - for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { - if (i.value()->check) { - result.push_back(i.key()->inputUser); - } - } - for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { - if (d_byUsername[i]->check) { - result.push_back(_byUsername[i]->inputUser); - } - } - return result; -} - -PeerData *NewGroupInner::selectedUser() { - for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) { - if (i.value()->check) { - return i.key(); - } - } - for (int32 i = 0, l = _byUsername.size(); i < l; ++i) { - if (d_byUsername[i]->check) { - return _byUsername[i]; - } - } - return 0; -} - -NewGroupBox::NewGroupBox() : _scroll(this, st::newGroupScroll), _inner(), - _filter(this, st::contactsFilter, lang(lng_participant_filter)), - _next(this, lang(lng_create_group_next), st::btnSelectDone), - _cancel(this, lang(lng_cancel), st::btnSelectCancel), - _hiding(false), a_opacity(0, 1) { - - _width = st::participantWidth; - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - if (_height > st::participantMaxHeight) _height = st::participantMaxHeight; - - resize(_width, _height); - - _scroll.setWidget(&_inner); - _scroll.setFocusPolicy(Qt::NoFocus); - - connect(&_next, SIGNAL(clicked()), this, SLOT(onNext())); - connect(&_cancel, SIGNAL(clicked()), this, SIGNAL(closed())); - connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(updateSel())); - connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); - connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); - connect(&_filter, SIGNAL(cancelled()), this, SLOT(onClose())); - connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int))); - connect(&_inner, SIGNAL(selectAllQuery()), &_filter, SLOT(selectAll())); - connect(&_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername())); - - _searchTimer.setSingleShot(true); - connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername())); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); -} - -bool NewGroupBox::onSearchByUsername(bool searchCache) { - QString q = _filter.text().trimmed(); - if (q.isEmpty()) { - if (_peopleRequest) { - _peopleRequest = 0; - } - return true; - } - if (q.size() >= MinUsernameLength) { - if (searchCache) { - PeopleCache::const_iterator i = _peopleCache.constFind(q); - if (i != _peopleCache.cend()) { - _peopleQuery = q; - _peopleRequest = 0; - peopleReceived(i.value(), 0); - return true; - } - } else if (_peopleQuery != q) { - _peopleQuery = q; - _peopleFull = false; - _peopleRequest = MTP::send(MTPcontacts_Search(MTP_string(_peopleQuery), MTP_int(SearchPeopleLimit)), rpcDone(&NewGroupBox::peopleReceived), rpcFail(&NewGroupBox::peopleFailed)); - _peopleQueries.insert(_peopleRequest, _peopleQuery); - } - } - return false; -} - -void NewGroupBox::onNeedSearchByUsername() { - if (!onSearchByUsername(true)) { - _searchTimer.start(AutoSearchTimeout); - } -} - -void NewGroupBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId req) { - QString q = _peopleQuery; - - PeopleQueries::iterator i = _peopleQueries.find(req); - if (i != _peopleQueries.cend()) { - q = i.value(); - _peopleCache[q] = result; - _peopleQueries.erase(i); - } - - if (_peopleRequest == req) { - switch (result.type()) { - case mtpc_contacts_found: { - App::feedUsers(result.c_contacts_found().vusers); - _inner.peopleReceived(q, result.c_contacts_found().vresults.c_vector().v); - } break; - } - - _peopleRequest = 0; - _inner.updateSel(); - onScroll(); - } -} - -bool NewGroupBox::peopleFailed(const RPCError &error, mtpRequestId req) { - if (_peopleRequest == req) { - _peopleRequest = 0; - _peopleFull = true; - } - return true; -} - -void NewGroupBox::hideAll() { - _filter.hide(); - _scroll.hide(); - _next.hide(); - _cancel.hide(); -} - -void NewGroupBox::showAll() { - _filter.show(); - _scroll.show(); - _next.show(); - _cancel.show(); -} - -void NewGroupBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - onClose(); - } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { - _inner.chooseParticipant(); - } else if (_filter.hasFocus()) { - if (e->key() == Qt::Key_Down) { - _inner.selectSkip(1); - } else if (e->key() == Qt::Key_Up) { - _inner.selectSkip(-1); - } else if (e->key() == Qt::Key_PageDown) { - _inner.selectSkipPage(_scroll.height(), 1); - } else if (e->key() == Qt::Key_PageUp) { - _inner.selectSkipPage(_scroll.height(), -1); - } else { - e->ignore(); - } - } else { - e->ignore(); - } -} - -void NewGroupBox::parentResized() { - QSize s = parentWidget()->size(); - _height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom(); - if (_height > st::participantMaxHeight) _height = st::participantMaxHeight; - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - -void NewGroupBox::paintEvent(QPaintEvent *e) { - QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); - - // paint shadows - p.fillRect(0, st::participantFilter.height, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - p.fillRect(0, size().height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); - - // paint button sep - p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - - // draw box title / text - p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_create_new_group)); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } -} - -void NewGroupBox::resizeEvent(QResizeEvent *e) { - LayeredWidget::resizeEvent(e); - _filter.move(st::newGroupNamePadding.left(), st::contactsAdd.height + st::newGroupNamePadding.top()); - _inner.resize(_width, _inner.height()); - _scroll.resize(_width, _height - st::contactsAdd.height - st::newGroupNamePadding.top() - _filter.height() - st::newGroupNamePadding.bottom() - _cancel.height()); - _scroll.move(0, _filter.y() + _filter.height() + st::newGroupNamePadding.bottom()); - _next.move(width() - _next.width(), _height - _next.height()); - _cancel.move(0, _height - _cancel.height()); -} - -void NewGroupBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - _filter.setFocus(); - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); -} - -void NewGroupBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -void NewGroupBox::onFilterUpdate() { - _scroll.scrollToY(0); - _inner.updateFilter(_filter.text()); -} - -void NewGroupBox::onClose() { - emit closed(); -} - -void NewGroupBox::onNext() { - MTPVector users(MTP_vector(_inner.selectedInputs())); - const QVector &v(users.c_vector().v); - if (v.isEmpty()) { - _filter.setFocus(); - _filter.notaBene(); - } else if (v.size() == 1) { - App::main()->showPeer(_inner.selectedUser()->id); - } else { - App::wnd()->replaceLayer(new CreateGroupBox(users)); - } -} - -void NewGroupBox::onScroll() { - _inner.loadProfilePhotos(_scroll.scrollTop()); -} - -NewGroupBox::~NewGroupBox() { -} - -CreateGroupBox::CreateGroupBox(const MTPVector &users) : _users(users), - _createRequestId(0), - _name(this, st::newGroupName, lang(lng_dlg_new_group_name)), - _create(this, lang(lng_dlg_create_group), st::btnSelectDone), - _cancel(this, lang(lng_cancel), st::btnSelectCancel), - _hiding(false), a_opacity(0, 1) { - _width = st::addContactWidth; - - _height = st::addContactTitleHeight + st::addContactPadding.top() + _name.height() + st::addContactPadding.bottom() + _create.height(); - - _name.setGeometry(st::addContactPadding.left(), st::addContactTitleHeight + st::addContactPadding.top(), _width - st::addContactPadding.left() - st::addContactPadding.right(), _name.height()); - - int32 buttonTop = _name.y() + _name.height() + st::addContactPadding.bottom(); - _cancel.move(0, buttonTop); - _create.move(_width - _create.width(), buttonTop); - - connect(&_create, SIGNAL(clicked()), this, SLOT(onCreate())); - connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel())); - - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); -} - -void CreateGroupBox::hideAll() { - _name.hide(); - _cancel.hide(); - _create.hide(); -} - -void CreateGroupBox::showAll() { - _name.show(); - _cancel.show(); - _create.show(); -} - -void CreateGroupBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - if (_name.hasFocus()) { - if (_name.text().trimmed().isEmpty()) { - _name.setFocus(); - _name.notaBene(); - } else { - onCreate(); - } - } - } else if (e->key() == Qt::Key_Escape) { - onCancel(); - } -} - -void CreateGroupBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - -void CreateGroupBox::paintEvent(QPaintEvent *e) { - QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); - - // paint shadows - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); - - // paint button sep - p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - - // draw box title / text - p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_create_group_title)); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); - } -} - -void CreateGroupBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - _name.setFocus(); - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); -} - -void CreateGroupBox::onCreate() { - if (_createRequestId) return; - - QString name = _name.text(); - if (name.isEmpty()) { - _name.setFocus(); - _name.notaBene(); - return; - } - - _create.setDisabled(true); - _name.setDisabled(true); - _createRequestId = MTP::send(MTPmessages_CreateChat(_users, MTP_string(_name.text())), rpcDone(&CreateGroupBox::created), rpcFail(&CreateGroupBox::failed)); -} - -void CreateGroupBox::created(const MTPmessages_StatedMessage &result) { - App::main()->sentFullDataReceived(0, result); - const QVector *d = 0; - switch (result.type()) { - case mtpc_messages_statedMessage: { - d = &result.c_messages_statedMessage().vchats.c_vector().v; - } break; - - case mtpc_messages_statedMessageLink: { - d = &result.c_messages_statedMessageLink().vchats.c_vector().v; - } break; - } - App::wnd()->hideLayer(); - PeerId peerId = 0; - if (d && !d->isEmpty()) { - switch (d->first().type()) { - case mtpc_chat: peerId = App::peerFromChat(d->first().c_chat().vid); break; - case mtpc_chatForbidden: peerId = App::peerFromChat(d->first().c_chatForbidden().vid); break; - case mtpc_chatEmpty: peerId = App::peerFromChat(d->first().c_chatEmpty().vid); break; - } - } - if (peerId) { - App::main()->showPeer(peerId); - } -} - -bool CreateGroupBox::failed(const RPCError &e) { - _createRequestId = 0; - if (e.type() == "NO_CHAT_TITLE") { - _name.setFocus(); - return true; - } else if (e.type() == "USERS_TOO_FEW") { - emit closed(); - return true; - } - return false; -} - -void CreateGroupBox::onCancel() { - emit closed(); -} - -void CreateGroupBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -CreateGroupBox::~CreateGroupBox() { -} diff --git a/Telegram/SourceFiles/boxes/newgroupbox.h b/Telegram/SourceFiles/boxes/newgroupbox.h deleted file mode 100644 index 4313a147e..000000000 --- a/Telegram/SourceFiles/boxes/newgroupbox.h +++ /dev/null @@ -1,206 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "layerwidget.h" - -class NewGroupInner : public QWidget { - Q_OBJECT - -private: - - struct ContactData; - -public: - - NewGroupInner(); - - void paintEvent(QPaintEvent *e); - void enterEvent(QEvent *e); - void leaveEvent(QEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void mousePressEvent(QMouseEvent *e); - void resizeEvent(QResizeEvent *e); - - void paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel); - void updateFilter(QString filter = QString()); - - void selectSkip(int32 dir); - void selectSkipPage(int32 h, int32 dir); - - QVector selectedInputs(); - PeerData *selectedUser(); - - void loadProfilePhotos(int32 yFrom); - - void changeCheckState(DialogRow *row); - void changeCheckState(ContactData *data); - - void peopleReceived(const QString &query, const QVector &people); - - void refresh(); - - ~NewGroupInner(); - -signals: - - void mustScrollTo(int ymin, int ymax); - void selectAllQuery(); - void searchByUsername(); - -public slots: - - void onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow); - - void updateSel(); - void peerUpdated(PeerData *peer); - - void chooseParticipant(); - -private: - - int32 _time; - - DialogsIndexed *_contacts; - DialogRow *_sel; - QString _filter; - typedef QVector FilteredDialogs; - FilteredDialogs _filtered; - int32 _filteredSel; - bool _mouseSel; - - struct ContactData { - Text name; - QString online; - bool check; - }; - typedef QMap ContactsData; - ContactsData _contactsData; - int32 _selCount; - - ContactData *contactData(DialogRow *row); - - bool _searching; - QString _lastQuery; - typedef QVector ByUsernameRows; - typedef QVector ByUsernameDatas; - ByUsernameRows _byUsername, _byUsernameFiltered; - ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas - ByUsernameDatas _byUsernameDatas; - int32 _byUsernameSel; - - QPoint _lastMousePos; - LinkButton _addContactLnk; - -}; - -class NewGroupBox : public LayeredWidget, public RPCSender { - Q_OBJECT - -public: - - NewGroupBox(); - void parentResized(); - void animStep(float64 dt); - void keyPressEvent(QKeyEvent *e); - void paintEvent(QPaintEvent *e); - void resizeEvent(QResizeEvent *e); - void startHide(); - ~NewGroupBox(); - -public slots: - - void onFilterUpdate(); - void onClose(); - void onNext(); - void onScroll(); - - bool onSearchByUsername(bool searchCache = false); - void onNeedSearchByUsername(); - -private: - - void hideAll(); - void showAll(); - - ScrollArea _scroll; - NewGroupInner _inner; - int32 _width, _height; - FlatInput _filter; - FlatButton _next, _cancel; - bool _hiding; - - QPixmap _cache; - - anim::fvalue a_opacity; - - void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req); - bool peopleFailed(const RPCError &error, mtpRequestId req); - - QTimer _searchTimer; - QString _peopleQuery; - bool _peopleFull; - mtpRequestId _peopleRequest; - - typedef QMap PeopleCache; - PeopleCache _peopleCache; - - typedef QMap PeopleQueries; - PeopleQueries _peopleQueries; -}; - -class CreateGroupBox : public LayeredWidget, public RPCSender { - Q_OBJECT - -public: - - CreateGroupBox(const MTPVector &users); - void parentResized(); - void animStep(float64 dt); - void keyPressEvent(QKeyEvent *e); - void paintEvent(QPaintEvent *e); - void startHide(); - ~CreateGroupBox(); - -public slots: - - void onCreate(); - void onCancel(); - -private: - - void hideAll(); - void showAll(); - - void created(const MTPmessages_StatedMessage &result); - bool failed(const RPCError &e); - - MTPVector _users; - - int32 _createRequestId; - - int32 _width, _height; - FlatInput _name; - FlatButton _create, _cancel; - - bool _hiding; - - QPixmap _cache; - - anim::fvalue a_opacity; -}; diff --git a/Telegram/SourceFiles/boxes/passcodebox.cpp b/Telegram/SourceFiles/boxes/passcodebox.cpp index c6e6de55c..f0d019f7e 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.cpp +++ b/Telegram/SourceFiles/boxes/passcodebox.cpp @@ -19,93 +19,131 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "lang.h" #include "passcodebox.h" +#include "confirmbox.h" #include "window.h" #include "localstorage.h" -PasscodeBox::PasscodeBox(bool turningOff) : _turningOff(turningOff), -_about(st::addContactWidth - st::addContactPadding.left() - st::addContactPadding.right()), -_saveButton(this, lang(lng_settings_save), st::btnSelectDone), +PasscodeBox::PasscodeBox(bool turningOff) : _turningOff(turningOff), _cloudPwd(false), +_setRequest(0), _hasRecovery(false), _aboutHeight(0), +_about(st::boxWidth - st::addContactPadding.left() - st::addContactPadding.right()), +_saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::btnSelectDone), _cancelButton(this, lang(lng_cancel), st::btnSelectCancel), _oldPasscode(this, st::inpAddContact, lang(lng_passcode_enter_old)), _newPasscode(this, st::inpAddContact, lang(lng_passcode_enter_new)), _reenterPasscode(this, st::inpAddContact, lang(lng_passcode_confirm_new)), -a_opacity(0, 1), _hiding(false) { +_passwordHint(this, st::inpAddContact, lang(lng_cloud_password_hint)), +_recoverEmail(this, st::inpAddContact, lang(lng_cloud_password_email)), +_recover(this, lang(lng_signin_recover)) { + init(); + prepare(); +} - _width = st::addContactWidth; - _about.setRichText(st::usernameFont, lang(lng_passcode_about)); - int32 aboutHeight = _about.countHeight(_width - st::addContactPadding.left() - st::addContactPadding.right()); +PasscodeBox::PasscodeBox(const QByteArray &newSalt, const QByteArray &curSalt, bool hasRecovery, const QString &hint, bool turningOff) : _turningOff(turningOff), _cloudPwd(true), +_setRequest(0), _newSalt(newSalt), _curSalt(curSalt), _hasRecovery(hasRecovery), _hint(hint), _aboutHeight(0), +_about(st::boxWidth - st::addContactPadding.left() - st::addContactPadding.right()), +_saveButton(this, lang(_turningOff ? lng_passcode_remove_button : lng_settings_save), st::btnSelectDone), +_cancelButton(this, lang(lng_cancel), st::btnSelectCancel), +_oldPasscode(this, st::inpAddContact, lang(lng_cloud_password_enter_old)), +_newPasscode(this, st::inpAddContact, lang(lng_cloud_password_enter_new)), +_reenterPasscode(this, st::inpAddContact, lang(lng_cloud_password_confirm_new)), +_passwordHint(this, st::inpAddContact, lang(lng_cloud_password_hint)), +_recoverEmail(this, st::inpAddContact, lang(lng_cloud_password_email)), +_recover(this, lang(lng_signin_recover)) { + init(); + prepare(); +} + +void PasscodeBox::init() { + _about.setRichText(st::usernameFont, lang(_cloudPwd ? lng_cloud_password_about : lng_passcode_about)); + if (!_hint.isEmpty()) _hintText.setText(st::usernameFont, lng_signin_hint(lt_password_hint, _hint)); + _aboutHeight = _about.countHeight(st::boxWidth - st::addContactPadding.left() - st::addContactPadding.right()); _oldPasscode.setEchoMode(QLineEdit::Password); _newPasscode.setEchoMode(QLineEdit::Password); _reenterPasscode.setEchoMode(QLineEdit::Password); - if (turningOff) { + if (_turningOff) { _oldPasscode.show(); - _boxTitle = lang(lng_passcode_remove); - _height = st::addContactTitleHeight + st::addContactPadding.top() + 1 * _oldPasscode.height() + st::usernameSkip + aboutHeight + st::addContactPadding.bottom() + _saveButton.height(); + _boxTitle = lang(_cloudPwd ? lng_cloud_password_remove : lng_passcode_remove); + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 1 * _oldPasscode.height() + st::usernameSkip + _aboutHeight + (_hasRecovery ? ((st::usernameSkip + _recover.height()) / 2) : 0) + st::addContactPadding.bottom() + _saveButton.height()); } else { - if (cHasPasscode()) { + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + if (has) { _oldPasscode.show(); - _boxTitle = lang(lng_passcode_change); - _height = st::addContactTitleHeight + st::addContactPadding.top() + 3 * _oldPasscode.height() + st::usernameSkip * 2 + 1 * st::addContactDelta + aboutHeight + st::addContactPadding.bottom() + _saveButton.height(); + _boxTitle = lang(_cloudPwd ? lng_cloud_password_change : lng_passcode_change); + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 3 * _oldPasscode.height() + st::usernameSkip * 2 + 1 * st::addContactDelta + (_cloudPwd ? _passwordHint.height() + st::addContactDelta : 0) + _aboutHeight + (_hasRecovery ? ((st::usernameSkip + _recover.height()) / 2) : 0) + st::addContactPadding.bottom() + _saveButton.height()); } else { _oldPasscode.hide(); - _boxTitle = lang(lng_passcode_create); - _height = st::addContactTitleHeight + st::addContactPadding.top() + 2 * _oldPasscode.height() + st::usernameSkip + 1 * st::addContactDelta + aboutHeight + st::addContactPadding.bottom() + _saveButton.height(); + _boxTitle = lang(_cloudPwd ? lng_cloud_password_create : lng_passcode_create); + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + 2 * _oldPasscode.height() + st::usernameSkip + 1 * st::addContactDelta + (_cloudPwd ? _passwordHint.height() + st::addContactDelta : 0) + _aboutHeight + (_cloudPwd ? st::addContactDelta + _recoverEmail.height() + st::usernameSkip : st::addContactPadding.bottom()) + _saveButton.height()); } } - _oldPasscode.setGeometry(st::addContactPadding.left(), st::addContactTitleHeight + st::addContactPadding.top(), _width - st::addContactPadding.left() - st::addContactPadding.right(), _oldPasscode.height()); - _newPasscode.setGeometry(st::addContactPadding.left(), _oldPasscode.y() + ((turningOff || cHasPasscode()) ? (_oldPasscode.height() + st::usernameSkip) : 0), _oldPasscode.width(), _oldPasscode.height()); - _reenterPasscode.setGeometry(st::addContactPadding.left(), _newPasscode.y() + _newPasscode.height() + st::addContactDelta, _newPasscode.width(), _newPasscode.height()); - - int32 buttonTop = _height - _cancelButton.height(); - _cancelButton.move(0, buttonTop); - _saveButton.move(_width - _saveButton.width(), buttonTop); - connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSave())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); - + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); + _badOldTimer.setSingleShot(true); connect(&_badOldTimer, SIGNAL(timeout()), this, SLOT(onBadOldPasscode())); connect(&_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged())); connect(&_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged())); connect(&_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged())); - - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + connect(&_recoverEmail, SIGNAL(changed()), this, SLOT(onEmailChanged())); } void PasscodeBox::hideAll() { _oldPasscode.hide(); _newPasscode.hide(); _reenterPasscode.hide(); + _passwordHint.hide(); + _recoverEmail.hide(); + _recover.hide(); _saveButton.hide(); _cancelButton.hide(); } void PasscodeBox::showAll() { + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); if (_turningOff) { _oldPasscode.show(); + if (_cloudPwd && _hasRecovery) { + _recover.show(); + } else { + _recover.hide(); + } + _passwordHint.hide(); _newPasscode.hide(); _reenterPasscode.hide(); } else { - if (cHasPasscode()) { + if (has) { _oldPasscode.show(); + if (_cloudPwd && _hasRecovery) { + _recover.show(); + } else { + _recover.hide(); + } } else { _oldPasscode.hide(); + _recover.hide(); } _newPasscode.show(); _reenterPasscode.show(); + if (_cloudPwd) { + _passwordHint.show(); + } else { + _passwordHint.hide(); + } + if (_cloudPwd && _curSalt.isEmpty()) { + _recoverEmail.show(); + } else { + _recoverEmail.hide(); + } } _saveButton.show(); _cancelButton.show(); } void PasscodeBox::keyPressEvent(QKeyEvent *e) { + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { if (_oldPasscode.hasFocus()) { if (_turningOff) { @@ -116,7 +154,7 @@ void PasscodeBox::keyPressEvent(QKeyEvent *e) { } else if (_newPasscode.hasFocus()) { _reenterPasscode.setFocus(); } else if (_reenterPasscode.hasFocus()) { - if (cHasPasscode() && _oldPasscode.text().isEmpty()) { + if (has && _oldPasscode.text().isEmpty()) { _oldPasscode.setFocus(); _oldPasscode.notaBene(); } else if (_newPasscode.text().isEmpty()) { @@ -124,80 +162,137 @@ void PasscodeBox::keyPressEvent(QKeyEvent *e) { _newPasscode.notaBene(); } else if (_reenterPasscode.text().isEmpty()) { _reenterPasscode.notaBene(); + } else if (!_passwordHint.isHidden()) { + _passwordHint.setFocus(); } else { onSave(); } + } else if (_passwordHint.hasFocus()) { + if (_recoverEmail.isHidden()) { + onSave(); + } else { + _recoverEmail.setFocus(); + } + } else if (_recoverEmail.hasFocus()) { + onSave(); } - } else if (e->key() == Qt::Key_Escape) { - onCancel(); + } else { + AbstractBox::keyPressEvent(e); } } -void PasscodeBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void PasscodeBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); + if (paint(p)) return; - // paint shadows - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - p.fillRect(0, size().height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); + paintTitle(p, _boxTitle, true); - p.setPen(st::usernameColor->p); - _about.draw(p, st::addContactPadding.left(), (_turningOff ? _oldPasscode : _reenterPasscode).y() + _oldPasscode.height() + st::usernameSkip, _width - st::addContactPadding.left() - st::addContactPadding.right()); + // paint shadow + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); - if (!_oldError.isEmpty()) { - p.setPen(st::setErrColor->p); - p.drawText(QRect(0, _oldPasscode.y() + _oldPasscode.height(), _width, st::usernameSkip), _oldError, style::al_center); - } + int32 w = width() - st::addContactPadding.left() - st::addContactPadding.right(); + int32 abouty = (_passwordHint.isHidden() ? (_reenterPasscode.isHidden() ? _oldPasscode : _reenterPasscode).y() + st::usernameSkip : _passwordHint.y() + st::addContactDelta) + _oldPasscode.height(); + p.setPen(st::usernameColor->p); + _about.draw(p, st::addContactPadding.left(), abouty, w); - if (!_newError.isEmpty()) { - p.setPen(st::setErrColor->p); - p.drawText(QRect(0, _reenterPasscode.y() + _reenterPasscode.height(), _width, st::usernameSkip), _newError, style::al_center); - } + if (!_hint.isEmpty() && _oldError.isEmpty()) { + p.setPen(st::black->p); + _hintText.drawElided(p, st::addContactPadding.left(), _oldPasscode.y() + _oldPasscode.height() + ((st::usernameSkip - st::usernameFont->height) / 2), w, 1, style::al_top); + } - // paint button sep - p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); + if (!_oldError.isEmpty()) { + p.setPen(st::setErrColor->p); + p.drawText(QRect(0, _oldPasscode.y() + _oldPasscode.height(), width(), st::usernameSkip), _oldError, style::al_center); + } - // draw box title / text - p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, _boxTitle); + if (!_newError.isEmpty()) { + p.setPen(st::setErrColor->p); + p.drawText(QRect(0, _reenterPasscode.y() + _reenterPasscode.height(), width(), st::usernameSkip), _newError, style::al_center); + } + + if (!_emailError.isEmpty()) { + p.setPen(st::setErrColor->p); + p.drawText(QRect(0, _recoverEmail.y() + _recoverEmail.height(), width(), st::usernameSkip), _emailError, style::al_center); + } + + // paint button sep + p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); +} + +void PasscodeBox::resizeEvent(QResizeEvent *e) { + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + _oldPasscode.setGeometry(st::addContactPadding.left(), st::boxTitleHeight + st::addContactPadding.top(), width() - st::addContactPadding.left() - st::addContactPadding.right(), _oldPasscode.height()); + _newPasscode.setGeometry(st::addContactPadding.left(), _oldPasscode.y() + ((_turningOff || has) ? (_oldPasscode.height() + st::usernameSkip) : 0), _oldPasscode.width(), _oldPasscode.height()); + _reenterPasscode.setGeometry(st::addContactPadding.left(), _newPasscode.y() + _newPasscode.height() + st::addContactDelta, _newPasscode.width(), _newPasscode.height()); + _passwordHint.setGeometry(st::addContactPadding.left(), _reenterPasscode.y() + _reenterPasscode.height() + st::usernameSkip, _reenterPasscode.width(), _reenterPasscode.height()); + + _recoverEmail.setGeometry(st::addContactPadding.left(), _passwordHint.y() + _passwordHint.height() + st::addContactDelta + _aboutHeight + st::addContactDelta, _passwordHint.width(), _passwordHint.height()); + + 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::addContactDelta + _aboutHeight + ((st::usernameSkip - _recover.height()) / 2)); } + } + + int32 buttonTop = height() - _cancelButton.height(); + _cancelButton.move(0, buttonTop); + _saveButton.move(width() - _saveButton.width(), buttonTop); +} + +void PasscodeBox::showDone() { + if (_oldPasscode.isHidden()) { + _newPasscode.setFocus(); } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); + _oldPasscode.setFocus(); } } -void PasscodeBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - if (_oldPasscode.isHidden()) { - _newPasscode.setFocus(); - } else { - _oldPasscode.setFocus(); - } - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); +void PasscodeBox::setPasswordDone(const MTPBool &result) { + _setRequest = 0; + emit reloadPassword(); + ConfirmBox *box = new ConfirmBox(lang(_reenterPasscode.isHidden() ? lng_cloud_password_removed : lng_cloud_password_was_set), true, lang(lng_about_done)); + App::wnd()->showLayer(box, true); } -void PasscodeBox::onSave() { +bool PasscodeBox::setPasswordFail(const RPCError &error) { + _setRequest = 0; + QString err = error.type(); + if (err == "PASSWORD_HASH_INVALID") { + if (_oldPasscode.isHidden()) { + emit reloadPassword(); + onClose(); + } else { + onBadOldPasscode(); + } + } else if (err == "NEW_PASSWORD_BAD") { + _newPasscode.setFocus(); + _newPasscode.notaBene(); + _newError = lang(lng_cloud_password_bad); + update(); + } else if (err == "NEW_SALT_INVALID") { + emit reloadPassword(); + onClose(); + } else if (err == "EMAIL_INVALID") { + _emailError = lang(lng_cloud_password_bad_email); + _recoverEmail.setFocus(); + _recoverEmail.notaBene(); + update(); + } else if (err == "EMAIL_UNCONFIRMED") { + ConfirmBox *box = new ConfirmBox(lang(lng_cloud_password_almost), true, lang(lng_about_done)); + App::wnd()->showLayer(box, true); + emit reloadPassword(); + } + return true; +} + +void PasscodeBox::onSave(bool force) { + if (_setRequest) return; + QString old = _oldPasscode.text(), pwd = _newPasscode.text(), conf = _reenterPasscode.text(); - if (_turningOff || cHasPasscode()) { + bool has = _cloudPwd ? (!_curSalt.isEmpty()) : cHasPasscode(); + if (!_cloudPwd && (_turningOff || has)) { if (Local::checkPasscode(old.toUtf8())) { if (_turningOff) pwd = conf = QString(); } else { @@ -220,14 +315,42 @@ void PasscodeBox::onSave() { _reenterPasscode.setFocus(); _reenterPasscode.notaBene(); if (!conf.isEmpty()) { - _newError = lang(lng_passcode_differ); + _newError = lang(_cloudPwd ? lng_cloud_password_differ : lng_passcode_differ); update(); } - } else if (!_turningOff && cHasPasscode() && old == pwd) { + } else if (!_turningOff && has && old == pwd) { _newPasscode.setFocus(); _newPasscode.notaBene(); - _newError = lang(lng_passcode_is_same); + _newError = lang(_cloudPwd ? lng_cloud_password_differ : lng_passcode_is_same); update(); + } else if (_cloudPwd) { + QString hint = _passwordHint.text(), email = _recoverEmail.text().trimmed(); + if (!_recoverEmail.isHidden() && email.isEmpty() && !force) { + ConfirmBox *box = new ConfirmBox(lang(lng_cloud_password_about_recover)); + connect(box, SIGNAL(confirmed()), this, SLOT(onForceNoMail())); + connect(box, SIGNAL(confirmed()), box, SLOT(onClose())); + App::wnd()->replaceLayer(box); + } else { + QByteArray newPasswordData = pwd.isEmpty() ? QByteArray() : (_newSalt + pwd.toUtf8() + _newSalt); + QByteArray newPasswordHash = pwd.isEmpty() ? QByteArray() : QByteArray(32, Qt::Uninitialized); + if (pwd.isEmpty()) { + hint = QString(); + email = QString(); + } else { + hashSha256(newPasswordData.constData(), newPasswordData.size(), newPasswordHash.data()); + } + QByteArray oldPasswordData = _oldPasscode.isHidden() ? QByteArray() : (_curSalt + old.toUtf8() + _curSalt); + QByteArray oldPasswordHash = _oldPasscode.isHidden() ? QByteArray() : QByteArray(32, Qt::Uninitialized); + if (!_oldPasscode.isHidden()) { + hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data()); + } + int32 flags = MTPDaccount_passwordInputSettings::flag_new_salt | MTPDaccount_passwordInputSettings::flag_new_password_hash | MTPDaccount_passwordInputSettings::flag_hint; + if (_oldPasscode.isHidden() || _newPasscode.isHidden()) { + flags |= MTPDaccount_passwordInputSettings::flag_email; + } + MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_int(flags), MTP_string(_newSalt), MTP_string(newPasswordHash), MTP_string(hint), MTP_string(email))); + _setRequest = MTP::send(MTPaccount_UpdatePasswordSettings(MTP_string(oldPasswordHash), settings), rpcDone(&PasscodeBox::setPasswordDone), rpcFail(&PasscodeBox::setPasswordFail)); + } } else { Local::setPasscode(pwd.toUtf8()); App::wnd()->checkAutoLock(); @@ -244,7 +367,7 @@ void PasscodeBox::onBadOldPasscode() { _oldPasscode.selectAll(); _oldPasscode.setFocus(); _oldPasscode.notaBene(); - _oldError = lang(lng_passcode_wrong); + _oldError = lang(_cloudPwd ? lng_cloud_password_wrong : lng_passcode_wrong); update(); } @@ -262,18 +385,182 @@ void PasscodeBox::onNewChanged() { } } -void PasscodeBox::onCancel() { - emit closed(); -} - -void PasscodeBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); +void PasscodeBox::onEmailChanged() { + if (!_emailError.isEmpty()) { + _emailError = QString(); + update(); } - a_opacity.start(0); } -PasscodeBox::~PasscodeBox() { +void PasscodeBox::onForceNoMail() { + onSave(true); +} + +void PasscodeBox::onRecoverByEmail() { + if (_pattern.isEmpty()) { + _pattern = "-"; + MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&PasscodeBox::recoverStarted), rpcFail(&PasscodeBox::recoverStartFail)); + } else { + recover(); + } +} + +void PasscodeBox::onRecoverExpired() { + _pattern = QString(); +} + +void PasscodeBox::recover() { + if (_pattern == "-") return; + + RecoverBox *box = new RecoverBox(_pattern); + connect(box, SIGNAL(reloadPassword()), this, SIGNAL(reloadPassword())); + connect(box, SIGNAL(recoveryExpired()), this, SLOT(onRecoverExpired())); + App::wnd()->replaceLayer(box); +} + +void PasscodeBox::recoverStarted(const MTPauth_PasswordRecovery &result) { + _pattern = qs(result.c_auth_passwordRecovery().vemail_pattern); + recover(); +} + +bool PasscodeBox::recoverStartFail(const RPCError &error) { + _pattern = QString(); + onClose(); + return true; +} + +RecoverBox::RecoverBox(const QString &pattern) : _pattern(lng_signin_recover_hint(lt_recover_email, pattern)), +_submitRequest(0), +_saveButton(this, lang(lng_passcode_submit), st::btnSelectDone), +_cancelButton(this, lang(lng_cancel), st::btnSelectCancel), +_recoverCode(this, st::inpAddContact, lang(lng_signin_code)) { + setMaxHeight(st::boxTitleHeight + st::addContactPadding.top() + st::usernameSkip + _recoverCode.height() + st::usernameSkip + st::addContactPadding.bottom() + _saveButton.height()); + + connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSubmit())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); + + connect(&_recoverCode, SIGNAL(changed()), this, SLOT(onCodeChanged())); + + prepare(); +} + +void RecoverBox::hideAll() { + _recoverCode.hide(); + _saveButton.hide(); + _cancelButton.hide(); +} + +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.text().isEmpty()) { + _recoverCode.setFocus(); + _recoverCode.notaBene(); + } else { + onSubmit(); + } + } else { + AbstractBox::keyPressEvent(e); + } +} + +void RecoverBox::paintEvent(QPaintEvent *e) { + QPainter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_signin_recover), true); + + // paint shadow + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); + + int32 w = width() - st::addContactPadding.left() - st::addContactPadding.right(); + p.drawText(QRect(st::addContactPadding.left(), _recoverCode.y() - st::usernameSkip, w, st::usernameSkip), st::usernameFont->m.elidedText(_pattern, Qt::ElideRight, w), style::al_center); + + if (!_error.isEmpty()) { + p.setPen(st::setErrColor->p); + p.drawText(QRect(0, _recoverCode.y() + _recoverCode.height(), width(), st::usernameSkip), _error, style::al_center); + } + + // paint button sep + p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); +} + +void RecoverBox::resizeEvent(QResizeEvent *e) { + _recoverCode.setGeometry(st::addContactPadding.left(), st::boxTitleHeight + st::addContactPadding.top() + st::usernameSkip, width() - st::addContactPadding.left() - st::addContactPadding.right(), _recoverCode.height()); + + int32 buttonTop = height() - _cancelButton.height(); + _cancelButton.move(0, buttonTop); + _saveButton.move(width() - _saveButton.width(), buttonTop); +} + +void RecoverBox::showDone() { + _recoverCode.setFocus(); +} + +void RecoverBox::onSubmit() { + if (_submitRequest) return; + + QString code = _recoverCode.text().trimmed(); + if (code.isEmpty()) { + _recoverCode.notaBene(); + return; + } + + _submitRequest = MTP::send(MTPauth_RecoverPassword(MTP_string(code)), rpcDone(&RecoverBox::codeSubmitDone, true), rpcFail(&RecoverBox::codeSubmitFail)); +} + +void RecoverBox::onCodeChanged() { + _error = QString(); + update(); +} + +void RecoverBox::codeSubmitDone(bool recover, const MTPauth_Authorization &result) { + _submitRequest = 0; + + emit reloadPassword(); + ConfirmBox *box = new ConfirmBox(lang(lng_cloud_password_removed), true, lang(lng_about_done)); + App::wnd()->showLayer(box, true); +} + +bool RecoverBox::codeSubmitFail(const RPCError &error) { + _submitRequest = 0; + + const QString &err = error.type(); + if (err == "PASSWORD_EMPTY") { + emit reloadPassword(); + ConfirmBox *box = new ConfirmBox(lang(lng_cloud_password_removed), true, lang(lng_about_done)); + App::wnd()->showLayer(box, true); + return true; + } else if (err == "PASSWORD_RECOVERY_NA") { + onClose(); + return true; + } else if (err == "PASSWORD_RECOVERY_EXPIRED") { + emit recoveryExpired(); + onClose(); + return true; + } else if (err == "CODE_INVALID") { + _error = lang(lng_signin_wrong_code); + update(); + _recoverCode.notaBene(); + return true; + } + if (QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err).hasMatch()) { + _error = lang(lng_flood_error); + update(); + _recoverCode.notaBene(); + return true; + } + if (cDebug()) { // internal server error + _error = err + ": " + error.description(); + } else { + _error = lang(lng_server_error); + } + update(); + _recoverCode.setFocus(); + return false; } diff --git a/Telegram/SourceFiles/boxes/passcodebox.h b/Telegram/SourceFiles/boxes/passcodebox.h index 7e1d33b3f..f797c490f 100644 --- a/Telegram/SourceFiles/boxes/passcodebox.h +++ b/Telegram/SourceFiles/boxes/passcodebox.h @@ -17,48 +17,109 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class PasscodeBox : public LayeredWidget { +class PasscodeBox : public AbstractBox, public RPCSender { Q_OBJECT public: PasscodeBox(bool turningOff = false); - void parentResized(); - void animStep(float64 dt); + 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 startHide(); - ~PasscodeBox(); + void resizeEvent(QResizeEvent *e); public slots: - void onSave(); + void onSave(bool force = false); void onBadOldPasscode(); void onOldChanged(); void onNewChanged(); - void onCancel(); + void onEmailChanged(); + void onForceNoMail(); + void onRecoverByEmail(); + void onRecoverExpired(); -private: +signals: + + void reloadPassword(); + +protected: void hideAll(); void showAll(); + void showDone(); - bool _turningOff; +private: + + void setPasswordDone(const MTPBool &result); + bool setPasswordFail(const RPCError &error); + + void recoverStarted(const MTPauth_PasswordRecovery &result); + bool recoverStartFail(const RPCError &error); + + void recover(); + QString _pattern; + + bool _turningOff, _cloudPwd; + mtpRequestId _setRequest; + + QByteArray _newSalt, _curSalt; + bool _hasRecovery; + QString _hint; + + int32 _aboutHeight; QString _boxTitle; - Text _about; + Text _about, _hintText; - int32 _width, _height; FlatButton _saveButton, _cancelButton; - FlatInput _oldPasscode, _newPasscode, _reenterPasscode; - - QPixmap _cache; - - anim::fvalue a_opacity; - bool _hiding; + FlatInput _oldPasscode, _newPasscode, _reenterPasscode, _passwordHint, _recoverEmail; + LinkButton _recover; QTimer _badOldTimer; - QString _oldError, _newError; + QString _oldError, _newError, _emailError; +}; + +class RecoverBox : public AbstractBox, public RPCSender { + Q_OBJECT + +public: + + RecoverBox(const QString &pattern); + void keyPressEvent(QKeyEvent *e); + void paintEvent(QPaintEvent *e); + void resizeEvent(QResizeEvent *e); + +public slots: + + void onSubmit(); + void onCodeChanged(); + +signals: + + void reloadPassword(); + void recoveryExpired(); + +protected: + + void hideAll(); + void showAll(); + void showDone(); + +private: + + void codeSubmitDone(bool recover, const MTPauth_Authorization &result); + bool codeSubmitFail(const RPCError &error); + + mtpRequestId _submitRequest; + + QString _pattern; + + FlatButton _saveButton, _cancelButton; + FlatInput _recoverCode; + + QString _error; }; diff --git a/Telegram/SourceFiles/boxes/photocropbox.cpp b/Telegram/SourceFiles/boxes/photocropbox.cpp index 9d30e1ba4..ea0db6d56 100644 --- a/Telegram/SourceFiles/boxes/photocropbox.cpp +++ b/Telegram/SourceFiles/boxes/photocropbox.cpp @@ -27,10 +27,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : _downState(0), _sendButton(this, lang(lng_settings_save), st::btnSelectDone), _cancelButton(this, lang(lng_cancel), st::btnSelectCancel), - _img(img), _peerId(peer), a_opacity(0, 1) { + _img(img), _peerId(peer) { connect(&_sendButton, SIGNAL(clicked()), this, SLOT(onSend())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); if (_peerId) { connect(this, SIGNAL(ready(const QImage &)), this, SLOT(onReady(const QImage &))); } @@ -46,13 +46,12 @@ PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : _downState(0 } _cropx = (_thumbw - _cropw) / 2; _cropy = (_thumbh - _cropw) / 2; - _width = st::cropBoxWidth; - _height = _thumbh + st::boxPadding.top() + st::boxFont->height + st::boxPadding.top() + st::boxPadding.bottom() + _sendButton.height(); - _thumbx = (_width - _thumbw) / 2; + + _thumbx = (st::cropBoxWidth - _thumbw) / 2; _thumby = st::boxPadding.top() * 2 + st::boxFont->height; setMouseTracking(true); - resize(_width, _height); + resizeMaxHeight(st::cropBoxWidth, _thumbh + st::boxPadding.top() + st::boxFont->height + st::boxPadding.top() + st::boxPadding.bottom() + _sendButton.height()); } void PhotoCropBox::mousePressEvent(QMouseEvent *e) { @@ -195,39 +194,26 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) { void PhotoCropBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { onSend(); - } else if (e->key() == Qt::Key_Escape) { - onCancel(); + } else { + AbstractBox::keyPressEvent(e); } } -void PhotoCropBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - _sendButton.move(_width - _sendButton.width(), _height - _sendButton.height()); - _cancelButton.move(0, _height - _cancelButton.height()); - update(); -} - void PhotoCropBox::paintEvent(QPaintEvent *e) { QPainter p(this); - p.setOpacity(a_opacity.current()); + if (paint(p)) return; - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); - - // paint shadows - p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); + // paint shadow + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); // paint button sep - p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); + p.fillRect(st::btnSelectCancel.width, height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - p.setFont(st::boxFont->f); - p.setPen(st::boxGrayTitle->p); - p.drawText(QRect(st::boxPadding.left(), st::boxPadding.top(), _width - st::boxPadding.left() - st::boxPadding.right(), st::boxFont->height), lang(lng_settings_crop_profile), style::al_center); + paintGrayTitle(p, lang(lng_settings_crop_profile)); p.translate(_thumbx, _thumby); p.drawPixmap(0, 0, _thumb); - p.setOpacity(a_opacity.current() * 0.5); + p.setOpacity(0.5); if (_cropy > 0) { p.fillRect(QRect(0, 0, _cropx + _cropw, _cropy), st::black->b); } @@ -248,15 +234,9 @@ void PhotoCropBox::paintEvent(QPaintEvent *e) { p.fillRect(QRect(_cropx + mdelta, _cropy + _cropw + mdelta, delta, delta), st::white->b); } -void PhotoCropBox::animStep(float64 ms) { - if (ms >= 1) { - a_opacity.finish(); - } else { - a_opacity.update(ms, anim::linear); - } - _sendButton.setOpacity(a_opacity.current()); - _cancelButton.setOpacity(a_opacity.current()); - update(); +void PhotoCropBox::resizeEvent(QResizeEvent *e) { + _sendButton.move(width() - _sendButton.width(), height() - _sendButton.height()); + _cancelButton.move(0, height() - _cancelButton.height()); } void PhotoCropBox::onSend() { @@ -296,14 +276,12 @@ void PhotoCropBox::onReady(const QImage &tosend) { emit closed(); } -void PhotoCropBox::onCancel() { - emit closed(); +void PhotoCropBox::hideAll() { + _sendButton.hide(); + _cancelButton.hide(); } -void PhotoCropBox::startHide() { - _hiding = true; - a_opacity.start(0); -} - -PhotoCropBox::~PhotoCropBox() { +void PhotoCropBox::showAll() { + _sendButton.show(); + _cancelButton.show(); } diff --git a/Telegram/SourceFiles/boxes/photocropbox.h b/Telegram/SourceFiles/boxes/photocropbox.h index 29c235c5c..4afda343c 100644 --- a/Telegram/SourceFiles/boxes/photocropbox.h +++ b/Telegram/SourceFiles/boxes/photocropbox.h @@ -17,39 +17,41 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" -class PhotoCropBox : public LayeredWidget { +class PhotoCropBox : public AbstractBox { Q_OBJECT public: PhotoCropBox(const QImage &img, const PeerId &peer); - void parentResized(); - void animStep(float64 ms); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); + void resizeEvent(QResizeEvent *e); + void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); int32 mouseState(QPoint p); - ~PhotoCropBox(); public slots: void onSend(); - void onCancel(); void onReady(const QImage &tosend); signals: void ready(const QImage &tosend); +protected: + + void hideAll(); + void showAll(); + private: int32 _downState; - int32 _width, _height, _thumbx, _thumby, _thumbw, _thumbh; + int32 _thumbx, _thumby, _thumbw, _thumbh; int32 _cropx, _cropy, _cropw; int32 _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw; FlatButton _sendButton, _cancelButton; @@ -57,8 +59,4 @@ private: QPixmap _thumb; PeerId _peerId; - anim::fvalue a_opacity; - - bool _hiding; - }; diff --git a/Telegram/SourceFiles/boxes/photosendbox.cpp b/Telegram/SourceFiles/boxes/photosendbox.cpp index b56a152e4..bf9ce79db 100644 --- a/Telegram/SourceFiles/boxes/photosendbox.cpp +++ b/Telegram/SourceFiles/boxes/photosendbox.cpp @@ -29,12 +29,10 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(new ReadyLocalMedi _compressed(this, lang(lng_send_image_compressed), cCompressPastedImage()), _sendButton(this, lang(lng_send_button), st::btnSelectDone), _cancelButton(this, lang(lng_cancel), st::btnSelectCancel), - _replyTo(img.replyTo), - a_opacity(0, 1) { + _replyTo(img.replyTo) { connect(&_sendButton, SIGNAL(clicked()), this, SLOT(onSend())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); - _width = st::confirmWidth; if (_img->type == ToPreparePhoto) { int32 maxW = 0, maxH = 0; for (PreparedPhotoThumbs::const_iterator i = _img->photoThumbs.cbegin(), e = _img->photoThumbs.cend(); i != e; ++i) { @@ -48,7 +46,7 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(new ReadyLocalMedi if (!tw || !th) { tw = th = 1; } - _thumbw = _width - st::boxPadding.left() - st::boxPadding.right(); + _thumbw = width() - st::boxPadding.left() - st::boxPadding.right(); if (_thumb.width() < _thumbw) { _thumbw = (_thumb.width() > 20) ? _thumb.width() : 20; } @@ -61,7 +59,7 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(new ReadyLocalMedi _thumbw = 10; } } - _height = _thumbh + st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::boxPadding.bottom() + _compressed.height() + _sendButton.height(); + resizeMaxHeight(st::boxWidth, _thumbh + st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::boxPadding.bottom() + _compressed.height() + _sendButton.height()); _thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw, _thumbh, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly); } else { @@ -85,15 +83,14 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(new ReadyLocalMedi _thumb = QPixmap::fromImage(_thumb.toImage().scaledToWidth(_thumbw * cIntRetinaFactor(), Qt::SmoothTransformation), Qt::ColorOnly); _thumb.setDevicePixelRatio(cRetinaFactor()); } - _height = st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom() + st::boxPadding.bottom() + _sendButton.height(); + resizeMaxHeight(st::boxWidth, st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom() + st::boxPadding.bottom() + _sendButton.height()); _name = _img->filename; _namew = st::mediaFont->m.width(_name); _size = formatSizeText(_img->filesize); _textw = qMax(_namew, st::mediaFont->m.width(_size)); } - - resize(_width, _height); + prepare(); } PhotoSendBox::PhotoSendBox(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo) : _img(0), @@ -101,70 +98,54 @@ _thumbx(0), _thumby(0), _thumbw(0), _thumbh(0), _namew(0), _textw(0), _compressed(this, lang(lng_send_image_compressed), true), _sendButton(this, lang(lng_send_button), st::btnSelectDone), _cancelButton(this, lang(lng_cancel), st::btnSelectCancel), -_phone(phone), _fname(fname), _lname(lname), _replyTo(replyTo), -a_opacity(0, 1) { +_phone(phone), _fname(fname), _lname(lname), _replyTo(replyTo) { connect(&_sendButton, SIGNAL(clicked()), this, SLOT(onSend())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); - _width = st::confirmWidth; _compressed.hide(); - _height = st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom() + st::boxPadding.bottom() + _sendButton.height(); _name = _fname + QChar(' ') + _lname; _namew = st::mediaFont->m.width(_name); _size = _phone; _textw = qMax(_namew, st::mediaFont->m.width(_size)); - resize(_width, _height); + resizeMaxHeight(st::boxWidth, st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom() + st::boxPadding.bottom() + _sendButton.height()); + prepare(); } void PhotoSendBox::keyPressEvent(QKeyEvent *e) { 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)); - } else if (e->key() == Qt::Key_Escape) { - onCancel(); + } else { + AbstractBox::keyPressEvent(e); } } -void PhotoSendBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - _sendButton.move(_width - _sendButton.width(), _height - _sendButton.height()); - _cancelButton.move(0, _height - _cancelButton.height()); - _compressed.move((width() - _compressed.width()) / 2, _height - _cancelButton.height() - _compressed.height() - st::confirmCompressedSkip); - update(); -} - void PhotoSendBox::paintEvent(QPaintEvent *e) { QPainter p(this); - p.setOpacity(a_opacity.current()); - - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); + if (paint(p)) return; - // paint shadows - p.fillRect(0, _height - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); + // paint shadow + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); // paint button sep - p.fillRect(st::btnSelectCancel.width, _height - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); + p.fillRect(st::btnSelectCancel.width, height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b); - p.setFont(st::boxFont->f); - p.setPen(st::boxGrayTitle->p); if (_img && _img->type == ToPreparePhoto) { - p.drawText(QRect(st::boxPadding.left(), st::boxPadding.top(), _width - st::boxPadding.left() - st::boxPadding.right(), st::boxFont->height), lang(lng_really_send_image), style::al_center); - p.drawPixmap((_width - _thumbw) / 2, st::boxPadding.top() * 2 + st::boxFont->height, _thumb); + paintGrayTitle(p, lang(lng_really_send_image)); + p.drawPixmap((width() - _thumbw) / 2, st::boxPadding.top() * 2 + st::boxFont->height, _thumb); } else { - p.drawText(QRect(st::boxPadding.left(), st::boxPadding.top(), _width - st::boxPadding.left() - st::boxPadding.right(), st::boxFont->height), lang(_img ? lng_really_send_file : lng_really_share_contact), style::al_center); + paintGrayTitle(p, lang(_img ? lng_really_send_file : lng_really_share_contact)); - int32 w = _width - st::boxPadding.left() - st::boxPadding.right(), h = st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom(); + int32 w = width() - st::boxPadding.left() - st::boxPadding.right(), h = st::mediaPadding.top() + st::mediaThumbSize + st::mediaPadding.bottom(); int32 tleft = st::mediaPadding.left() + st::mediaThumbSize + st::mediaPadding.right(); int32 twidth = w - tleft - st::mediaPadding.right(); if (twidth > _textw) { w -= (twidth - _textw); twidth = _textw; } - int32 x = (_width - w) / 2, y = st::boxPadding.top() * 2 + st::boxFont->height; + int32 x = (width() - w) / 2, y = st::boxPadding.top() * 2 + st::boxFont->height; p.fillRect(QRect(x, y, w, h), st::msgOutBG->b); p.fillRect(x, y + h, w, st::msgShadow, st::msgOutShadow->b); @@ -190,16 +171,26 @@ void PhotoSendBox::paintEvent(QPaintEvent *e) { } } -void PhotoSendBox::animStep(float64 ms) { - if (ms >= 1) { - a_opacity.finish(); - } else { - a_opacity.update(ms, anim::linear); - } - _sendButton.setOpacity(a_opacity.current()); - _cancelButton.setOpacity(a_opacity.current()); - _compressed.setOpacity(a_opacity.current()); - update(); +void PhotoSendBox::resizeEvent(QResizeEvent *e) { + _sendButton.move(width() - _sendButton.width(), height() - _sendButton.height()); + _cancelButton.move(0, height() - _cancelButton.height()); + _compressed.move((width() - _compressed.width()) / 2, height() - _cancelButton.height() - _compressed.height() - st::confirmCompressedSkip); +} + +void PhotoSendBox::closePressed() { + if (App::main()) App::main()->cancelSendImage(); +} + +void PhotoSendBox::hideAll() { + _sendButton.hide(); + _cancelButton.hide(); + _compressed.hide(); +} + +void PhotoSendBox::showAll() { + _sendButton.show(); + _cancelButton.show(); + _compressed.show(); } void PhotoSendBox::onSend(bool ctrlShiftEnter) { @@ -222,17 +213,7 @@ void PhotoSendBox::onSend(bool ctrlShiftEnter) { emit closed(); } -void PhotoSendBox::onCancel() { - if (App::main()) App::main()->cancelSendImage(); - emit closed(); -} - -void PhotoSendBox::startHide() { - _hiding = true; - a_opacity.start(0); -} - PhotoSendBox::~PhotoSendBox() { delete _img; - if (App::main()) App::main()->cancelSendImage(); + closePressed(); } diff --git a/Telegram/SourceFiles/boxes/photosendbox.h b/Telegram/SourceFiles/boxes/photosendbox.h index 7d6594eea..232e2bebc 100644 --- a/Telegram/SourceFiles/boxes/photosendbox.h +++ b/Telegram/SourceFiles/boxes/photosendbox.h @@ -17,32 +17,35 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" #include "localimageloader.h" -class PhotoSendBox : public LayeredWidget { +class PhotoSendBox : public AbstractBox { Q_OBJECT public: PhotoSendBox(const ReadyLocalMedia &img); PhotoSendBox(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo); - void parentResized(); - void animStep(float64 ms); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); + void resizeEvent(QResizeEvent *e); ~PhotoSendBox(); public slots: void onSend(bool ctrlShiftEnter = false); - void onCancel(); + +protected: + + void closePressed(); + void hideAll(); + void showAll(); private: ReadyLocalMedia *_img; - int32 _width, _height, _thumbx, _thumby, _thumbw, _thumbh; + int32 _thumbx, _thumby, _thumbw, _thumbh; QString _name, _size; int32 _namew, _textw; FlatCheckbox _compressed; @@ -52,8 +55,5 @@ private: QString _phone, _fname, _lname; MsgId _replyTo; - anim::fvalue a_opacity; - - bool _hiding; }; diff --git a/Telegram/SourceFiles/boxes/sessionsbox.cpp b/Telegram/SourceFiles/boxes/sessionsbox.cpp new file mode 100644 index 000000000..0d10b5b69 --- /dev/null +++ b/Telegram/SourceFiles/boxes/sessionsbox.cpp @@ -0,0 +1,390 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "lang.h" + +#include "localstorage.h" + +#include "sessionsbox.h" +#include "mainwidget.h" +#include "window.h" + +#include "countries.h" +#include "confirmbox.h" + +SessionsInner::SessionsInner(SessionsList *list) : _list(list), _terminating(0), _terminateBox(0) { +} + +void SessionsInner::paintEvent(QPaintEvent *e) { + QRect r(e->rect()); + Painter p(this); + + p.fillRect(r, st::white->b); + p.setFont(st::linkFont->f); + int32 x = st::sessionPadding.left(), xact = st::sessionTerminateSkip + st::sessionTerminate.width + st::sessionTerminateSkip; + int32 w = width() - 2 * x, availw = width() - 2 * xact; + int32 from = (r.top() >= 0) ? qFloor(r.top() / st::sessionHeight) : 0, count = _list->size(); + if (from < count) { + int32 to = (r.bottom() >= 0 ? qFloor(r.bottom() / st::sessionHeight) : 0) + 1; + if (to > count) to = count; + p.translate(0, from * st::sessionHeight); + for (int32 i = from; i < to; ++i) { + const SessionData &auth(_list->at(i)); + + p.setFont(st::sessionNameFont->f); + p.setPen(st::black->p); + p.drawTextLeft(x, st::sessionPadding.top(), w, auth.name, auth.nameWidth); + + p.setFont(st::sessionActiveFont->f); + p.setPen(st::sessionActiveColor->p); + p.drawTextRight(xact, st::sessionPadding.top(), availw, auth.active, auth.activeWidth); + + p.setFont(st::sessionInfoFont->f); + p.setPen(st::sessionInfoColor->p); + p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height, w, auth.info, auth.infoWidth); + + p.translate(0, st::sessionHeight); + } + } +} + +void SessionsInner::onTerminate() { + for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) { + if (i.value()->getState() & Button::StateOver) { + _terminating = i.key(); + + if (_terminateBox) _terminateBox->deleteLater(); + _terminateBox = new ConfirmBox(lang(lng_settings_reset_one_sure), lang(lng_settings_reset_button)); + connect(_terminateBox, SIGNAL(confirmed()), this, SLOT(onTerminateSure())); + connect(_terminateBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoTerminateBox(QObject*))); + App::wnd()->replaceLayer(_terminateBox); + } + } +} + +void SessionsInner::onTerminateSure() { + if (_terminateBox) { + _terminateBox->onClose(); + _terminateBox = 0; + } + MTP::send(MTPaccount_ResetAuthorization(MTP_long(_terminating)), rpcDone(&SessionsInner::terminateDone, _terminating), rpcFail(&SessionsInner::terminateFail, _terminating)); + TerminateButtons::iterator i = _terminateButtons.find(_terminating); + if (i != _terminateButtons.cend()) { + i.value()->clearState(); + i.value()->hide(); + } +} + +void SessionsInner::onNoTerminateBox(QObject *obj) { + if (obj == _terminateBox) _terminateBox = 0; +} + +void SessionsInner::terminateDone(uint64 hash, const MTPBool &result) { + for (int32 i = 0, l = _list->size(); i < l; ++i) { + if (_list->at(i).hash == hash) { + _list->removeAt(i); + break; + } + } + listUpdated(); + emit oneTerminated(); +} + +bool SessionsInner::terminateFail(uint64 hash, const RPCError &error) { + TerminateButtons::iterator i = _terminateButtons.find(hash); + if (i != _terminateButtons.end()) { + i.value()->show(); + return true; + } + return false; +} + +void SessionsInner::resizeEvent(QResizeEvent *e) { + +} + +void SessionsInner::listUpdated() { + for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) { + i.value()->move(0, -1); + } + for (int32 i = 0, l = _list->size(); i < l; ++i) { + TerminateButtons::iterator j = _terminateButtons.find(_list->at(i).hash); + if (j == _terminateButtons.cend()) { + 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() - 2 * st::sessionTerminateSkip); + } + for (TerminateButtons::iterator i = _terminateButtons.begin(); i != _terminateButtons.cend();) { + if (i.value()->y() >= 0) { + ++i; + } else { + delete i.value(); + i = _terminateButtons.erase(i); + } + } + resize(width(), _list->isEmpty() ? st::noContactsHeight : (_list->size() * st::sessionHeight)); + if (parentWidget()) parentWidget()->update(); +} + +SessionsInner::~SessionsInner() { + for (int32 i = 0, l = _terminateButtons.size(); i < l; ++i) { + delete _terminateButtons[i]; + } +} + +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) { + 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(App::wnd(), SIGNAL(newAuthorization()), this, SLOT(onNewAuthorization())); + connect(&_shortPollTimer, SIGNAL(timeout()), this, SLOT(onShortPollAuthorizations())); + + init(&_inner, _done.height(), st::boxTitleHeight + st::sessionHeight + 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::boxTitlePos.y() + st::boxTitleFont->ascent - st::linkFont->ascent, width() - 2 * st::sessionPadding.left()); +} + +void SessionsBox::hideAll() { + _done.hide(); + _terminateAll.hide(); + ScrollableBox::hideAll(); +} + +void SessionsBox::showAll() { + _done.show(); + if (_list.isEmpty()) { + _terminateAll.hide(); + _scroll.hide(); + } else { + _terminateAll.show(); + if (_loading) { + _scroll.hide(); + } else { + _scroll.show(); + } + } +} + +void SessionsBox::paintEvent(QPaintEvent *e) { + Painter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_sessions_header), true); + 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() - x - st::sessionPadding.right(); + + 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::sessionInfoColor->p); + p.drawTextLeft(x, st::sessionPadding.top() + st::sessionNameFont->height, w, _current.info, _current.infoWidth); + + p.translate(0, st::sessionHeight); + if (_list.isEmpty()) { + paintTitle(p, lang(lng_sessions_no_other), true); + + p.setFont(st::sessionInfoFont->f); + p.setPen(st::sessionInfoColor->p); + p.drawText(QRect(st::sessionPadding.left(), st::boxTitleHeight + st::boxTitlePos.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), false); + } + } +} + +void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) { + _loading = false; + _shortPollRequest = 0; + + int32 availCurrent = st::boxWidth - st::sessionPadding.left() - st::sessionTerminateSkip; + int32 availOther = availCurrent - st::sessionTerminate.width - st::sessionTerminateSkip; + + _list.clear(); + const QVector &v(result.c_account_authorizations().vauthorizations.c_vector().v); + int32 l = v.size(); + if (l > 1) _list.reserve(l - 1); + + const CountriesByISO2 &countries(countriesByISO2()); + + for (int32 i = 0; i < l; ++i) { + const MTPDauthorization &d(v.at(i).c_authorization()); + SessionData data; + data.hash = d.vhash.v; + + QString appName, systemVer = qs(d.vsystem_version); + if (d.vapi_id.v == 2040 || d.vapi_id.v == 17349) { + appName = (d.vapi_id.v == 2040) ? qsl("Telegram Desktop") : qsl("Telegram Desktop (GitHub)"); + if (systemVer == QLatin1String("windows")) { + systemVer = qsl("Windows"); + } else if (systemVer == QLatin1String("os x")) { + systemVer = qsl("Mac OS X"); + } else if (systemVer == QLatin1String("linux")) { + systemVer = qsl("Linux"); + } + } else { + appName = qs(d.vapp_name); + } + data.name = appName; + data.nameWidth = st::sessionNameFont->m.width(data.name); + + QString country = qs(d.vcountry); + CountriesByISO2::const_iterator j = countries.constFind(country); + if (j != countries.cend()) country = QString::fromUtf8(j.value()->name); + + data.info = country + QLatin1String(" (") + qs(d.vip) + QLatin1String("), ") + systemVer; + if (!data.hash || (d.vflags.v & 1)) { + data.active = QString(); + data.activeWidth = 0; + if (data.nameWidth > availCurrent) { + data.name = st::sessionNameFont->m.elidedText(data.name, Qt::ElideRight, availCurrent); + data.nameWidth = st::sessionNameFont->m.width(data.name); + } + data.infoWidth = st::sessionInfoFont->m.width(data.info); + if (data.infoWidth > availCurrent) { + data.info = st::sessionInfoFont->m.elidedText(data.info, Qt::ElideRight, availCurrent); + data.infoWidth = st::sessionInfoFont->m.width(data.info); + } + _current = data; + } else { + data.active = date(d.vdate_active.v ? d.vdate_active : d.vdate_created).toString(qsl("hh:mm")); + data.activeWidth = st::sessionActiveFont->m.width(data.active); + int32 availForName = availOther - st::sessionPadding.right() - data.activeWidth; + if (data.nameWidth > availForName) { + data.name = st::sessionNameFont->m.elidedText(data.name, Qt::ElideRight, availForName); + data.nameWidth = st::sessionNameFont->m.width(data.name); + } + data.infoWidth = st::sessionInfoFont->m.width(data.info); + if (data.infoWidth > availOther) { + data.info = st::sessionInfoFont->m.elidedText(data.info, Qt::ElideRight, availOther); + data.infoWidth = st::sessionInfoFont->m.width(data.info); + } + + _list.push_back(data); + for (int32 i = _list.size(); i > 1;) { + --i; + if (_list.at(i).active > _list.at(i - 1).active) { + qSwap(_list[i], _list[i - 1]); + } + } + } + } + _inner.listUpdated(); + if (!_done.isHidden()) { + showAll(); + update(); + } + + _shortPollTimer.start(SessionsShortPollTimeout); +} + +void SessionsBox::onTerminateAll() { + if (_terminateBox) _terminateBox->deleteLater(); + _terminateBox = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button)); + 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()) { + showAll(); + update(); + } + } +} + +void SessionsBox::onShortPollAuthorizations() { + if (!_shortPollRequest) { + _shortPollRequest = MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations)); + if (!_done.isHidden()) { + showAll(); + update(); + } + } +} + +void SessionsBox::onNewAuthorization() { + onShortPollAuthorizations(); +// _shortPollTimer.start(1000); +} + +void SessionsBox::terminateAllDone(const MTPBool &result) { + MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations)); + if (_shortPollRequest) { + MTP::cancel(_shortPollRequest); + _shortPollRequest = 0; + } +} + +bool SessionsBox::terminateAllFail(const RPCError &error) { + MTP::send(MTPaccount_GetAuthorizations(), rpcDone(&SessionsBox::gotAuthorizations)); + if (_shortPollRequest) { + MTP::cancel(_shortPollRequest); + _shortPollRequest = 0; + } + return true; +} diff --git a/Telegram/SourceFiles/boxes/sessionsbox.h b/Telegram/SourceFiles/boxes/sessionsbox.h new file mode 100644 index 000000000..fe47a9d9f --- /dev/null +++ b/Telegram/SourceFiles/boxes/sessionsbox.h @@ -0,0 +1,114 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "abstractbox.h" + +class ConfirmBox; + +struct SessionData { + uint64 hash; + + int32 nameWidth, activeWidth, infoWidth; + QString name, active, info; +}; +typedef QList SessionsList; + +class SessionsInner : public QWidget, public RPCSender { + Q_OBJECT + +public: + + SessionsInner(SessionsList *list); + + void paintEvent(QPaintEvent *e); + void resizeEvent(QResizeEvent *e); + + void listUpdated(); + + ~SessionsInner(); + +signals: + + void oneTerminated(); + +public slots: + + void onTerminate(); + void onTerminateSure(); + void onNoTerminateBox(QObject *obj); + +private: + + void terminateDone(uint64 hash, const MTPBool &result); + bool terminateFail(uint64 hash, const RPCError &error); + + SessionsList *_list; + + typedef QMap TerminateButtons; + TerminateButtons _terminateButtons; + + uint64 _terminating; + ConfirmBox *_terminateBox; + +}; + +class SessionsBox : public ScrollableBox, public RPCSender { + Q_OBJECT + +public: + + SessionsBox(); + void resizeEvent(QResizeEvent *e); + void paintEvent(QPaintEvent *e); + +public slots: + + void onTerminateAll(); + void onTerminateAllSure(); + void onNoTerminateBox(QObject *obj); + void onOneTerminated(); + void onShortPollAuthorizations(); + void onNewAuthorization(); + +protected: + + void hideAll(); + void showAll(); + +private: + + void gotAuthorizations(const MTPaccount_Authorizations &result); + void terminateAllDone(const MTPBool &res); + bool terminateAllFail(const RPCError &error); + + bool _loading; + + SessionData _current; + SessionsList _list; + + SessionsInner _inner; + FlatButton _done; + + LinkButton _terminateAll; + ConfirmBox *_terminateBox; + + SingleTimer _shortPollTimer; + mtpRequestId _shortPollRequest; + +}; diff --git a/Telegram/SourceFiles/boxes/usernamebox.cpp b/Telegram/SourceFiles/boxes/usernamebox.cpp index baf1a9978..8712897b0 100644 --- a/Telegram/SourceFiles/boxes/usernamebox.cpp +++ b/Telegram/SourceFiles/boxes/usernamebox.cpp @@ -55,34 +55,23 @@ UsernameBox::UsernameBox() : _saveButton(this, lang(lng_settings_save), st::usernameDone), _cancelButton(this, lang(lng_cancel), st::usernameCancel), _usernameInput(this, st::inpAddContact, qsl("@username"), App::self()->username), -_saveRequest(0), _checkRequest(0), _about(st::usernameWidth - 2 * st::addContactTitlePos.x()), -a_opacity(0, 1), _hiding(false) { +_saveRequest(0), _checkRequest(0), _about(st::usernameWidth - 2 * st::boxTitlePos.x()) { _about.setRichText(st::usernameFont, lang(lng_username_about)); _goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available); initBox(); } void UsernameBox::initBox() { - _width = st::usernameWidth; - _height = st::addContactTitleHeight + st::addContactPadding.top() + _usernameInput.height() + st::addContactPadding.bottom() + _about.countHeight(st::usernameWidth - 2 * st::addContactTitlePos.x()) + st::usernameSkip + _saveButton.height(); - _usernameInput.setGeometry(st::addContactPadding.left(), st::addContactTitleHeight + st::addContactPadding.top(), _width - st::addContactPadding.left() - st::addContactPadding.right(), _usernameInput.height()); - - int32 buttonTop = _height - _cancelButton.height(); - _cancelButton.move(0, buttonTop); - _saveButton.move(_width - _saveButton.width(), buttonTop); + resizeMaxHeight(st::usernameWidth, st::boxTitleHeight + st::addContactPadding.top() + _usernameInput.height() + st::addContactPadding.bottom() + _about.countHeight(st::usernameWidth - 2 * st::boxTitlePos.x()) + st::usernameSkip + _saveButton.height()); connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSave())); - connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onClose())); connect(&_usernameInput, SIGNAL(changed()), this, SLOT(onChanged())); _checkTimer.setSingleShot(true); connect(&_checkTimer, SIGNAL(timeout()), this, SLOT(onCheck())); - resize(_width, _height); - - showAll(); - _cache = myGrab(this, rect()); - hideAll(); + prepare(); } void UsernameBox::hideAll() { @@ -97,71 +86,51 @@ void UsernameBox::showAll() { _cancelButton.show(); } +void UsernameBox::showDone() { + _usernameInput.setFocus(); +} + void UsernameBox::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { onSave(); - } else if (e->key() == Qt::Key_Escape) { - onCancel(); + } else { + AbstractBox::keyPressEvent(e); } } -void UsernameBox::parentResized() { - QSize s = parentWidget()->size(); - setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height); - update(); -} - void UsernameBox::paintEvent(QPaintEvent *e) { QPainter p(this); - if (_cache.isNull()) { - if (!_hiding || a_opacity.current() > 0.01) { - // fill bg - p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b); + if (paint(p)) return; - // paint shadows - p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b); - p.fillRect(0, size().height() - st::usernameCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b); + paintTitle(p, lang(lng_username_title), true); - // paint button sep - p.fillRect(st::usernameCancel.width, size().height() - st::usernameCancel.height, st::lineWidth, st::usernameCancel.height, st::btnSelectSep->b); + // paint shadow + p.fillRect(0, height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, width(), st::scrollDef.bottomsh, st::scrollDef.shColor->b); - // draw box title / text - p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_username_title)); + // paint button sep + p.fillRect(st::usernameCancel.width, size().height() - st::usernameCancel.height, st::lineWidth, st::usernameCancel.height, st::btnSelectSep->b); - if (!_errorText.isEmpty()) { - p.setPen(st::setErrColor->p); - p.setFont(st::setErrFont->f); - int32 w = st::setErrFont->m.width(_errorText); - p.drawText((_width - w) / 2, _usernameInput.y() + _usernameInput.height() + ((st::usernameSkip - st::setErrFont->height) / 2) + st::setErrFont->ascent, _errorText); - } else if (!_goodText.isEmpty()) { - p.setPen(st::setGoodColor->p); - p.setFont(st::setErrFont->f); - int32 w = st::setErrFont->m.width(_goodText); - p.drawText((_width - w) / 2, _usernameInput.y() + _usernameInput.height() + ((st::usernameSkip - st::setErrFont->height) / 2) + st::setErrFont->ascent, _goodText); - } - p.setPen(st::usernameColor->p); - _about.draw(p, st::addContactTitlePos.x(), _usernameInput.y() + _usernameInput.height() + st::usernameSkip, width() - 2 * st::addContactTitlePos.x()); - } - } else { - p.setOpacity(a_opacity.current()); - p.drawPixmap(0, 0, _cache); + if (!_errorText.isEmpty()) { + p.setPen(st::setErrColor->p); + p.setFont(st::setErrFont->f); + int32 w = st::setErrFont->m.width(_errorText); + p.drawText((width() - w) / 2, _usernameInput.y() + _usernameInput.height() + ((st::usernameSkip - st::setErrFont->height) / 2) + st::setErrFont->ascent, _errorText); + } else if (!_goodText.isEmpty()) { + p.setPen(st::setGoodColor->p); + p.setFont(st::setErrFont->f); + int32 w = st::setErrFont->m.width(_goodText); + p.drawText((width() - w) / 2, _usernameInput.y() + _usernameInput.height() + ((st::usernameSkip - st::setErrFont->height) / 2) + st::setErrFont->ascent, _goodText); } + p.setPen(st::usernameColor->p); + _about.draw(p, st::boxTitlePos.x(), _usernameInput.y() + _usernameInput.height() + st::usernameSkip, width() - 2 * st::boxTitlePos.x()); } -void UsernameBox::animStep(float64 dt) { - if (dt >= 1) { - a_opacity.finish(); - _cache = QPixmap(); - if (!_hiding) { - showAll(); - _usernameInput.setFocus(); - } - } else { - a_opacity.update(dt, anim::linear); - } - update(); +void UsernameBox::resizeEvent(QResizeEvent *e) { + _usernameInput.setGeometry(st::addContactPadding.left(), st::boxTitleHeight + st::addContactPadding.top(), width() - st::addContactPadding.left() - st::addContactPadding.right(), _usernameInput.height()); + + int32 buttonTop = height() - _cancelButton.height(); + _cancelButton.move(0, buttonTop); + _saveButton.move(width() - _saveButton.width(), buttonTop); } void UsernameBox::onSave() { @@ -277,19 +246,3 @@ bool UsernameBox::onCheckFail(const RPCError &error) { QString UsernameBox::getName() const { return _usernameInput.text().replace('@', QString()).trimmed(); } - -void UsernameBox::onCancel() { - emit closed(); -} - -void UsernameBox::startHide() { - _hiding = true; - if (_cache.isNull()) { - _cache = myGrab(this, rect()); - hideAll(); - } - a_opacity.start(0); -} - -UsernameBox::~UsernameBox() { -} diff --git a/Telegram/SourceFiles/boxes/usernamebox.h b/Telegram/SourceFiles/boxes/usernamebox.h index f3b4eb428..73ea1a88e 100644 --- a/Telegram/SourceFiles/boxes/usernamebox.h +++ b/Telegram/SourceFiles/boxes/usernamebox.h @@ -17,7 +17,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -#include "layerwidget.h" +#include "abstractbox.h" class UsernameInput : public FlatInput { public: @@ -30,31 +30,30 @@ protected: }; -class UsernameBox : public LayeredWidget, public RPCSender { +class UsernameBox : public AbstractBox, public RPCSender { Q_OBJECT public: UsernameBox(); - void parentResized(); - void animStep(float64 dt); void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); - void startHide(); - ~UsernameBox(); + void resizeEvent(QResizeEvent *e); public slots: void onSave(); - void onCancel(); void onCheck(); void onChanged(); -private: +protected: void hideAll(); void showAll(); + void showDone(); + +private: void onUpdateDone(const MTPUser &result); bool onUpdateFail(const RPCError &error); @@ -65,18 +64,12 @@ private: QString getName() const; void initBox(); - int32 _width, _height; FlatButton _saveButton, _cancelButton; UsernameInput _usernameInput; - QPixmap _cache; - mtpRequestId _saveRequest, _checkRequest; QString _sentUsername, _checkUsername, _errorText, _goodText; Text _about; QTimer _checkTimer; - - anim::fvalue a_opacity; - bool _hiding; }; diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index e17df605f..b4de74b30 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -118,7 +118,7 @@ enum { SaveDraftTimeout = 1000, // save draft after 1 secs of not changing text SaveDraftAnywayTimeout = 5000, // or save anyway each 5 secs - HiddenIsOnlineAfterMessage = 30, // user with hidden last seen stays online for such amount of seconds in the interface + HiddenIsOnlineAfterMessage = 30, // user with hidden last seen stays online for such amount of seconds in the interface ServiceUserId = 777000, @@ -129,6 +129,7 @@ enum { UpdateDelayRandPart = 8 * 3600, // 8 hour max - min time between update check requests WrongPasscodeTimeout = 1500, + SessionsShortPollTimeout = 60000, }; inline bool isServiceUser(uint64 id) { @@ -238,7 +239,7 @@ static const char *ApiLang = "en"; extern QString gKeyFile; inline const QString &cDataFile() { if (!gKeyFile.isEmpty()) return gKeyFile; - static const QString res(cTestMode() ? qsl("data_test") : qsl("data")); + static const QString res(qsl("data")); return res; } @@ -285,7 +286,7 @@ enum { UpdateChunk = 100 * 1024, // 100kb parts when downloading the update IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle - ForwardOnAdd = 120, // how many messages from chat history server should forward to user, that was added to this chat + ForwardOnAdd = 100, // how many messages from chat history server should forward to user, that was added to this chat }; inline const QRegularExpression &cWordSplit() { diff --git a/Telegram/SourceFiles/countries.h b/Telegram/SourceFiles/countries.h index 406d16fb0..2df097ee1 100644 --- a/Telegram/SourceFiles/countries.h +++ b/Telegram/SourceFiles/countries.h @@ -15,6 +15,15 @@ GNU General Public License for more details. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014 John Preston, https://desktop.telegram.org */ + +#pragma once + +struct CountryInfo { + CountryInfo(const char *_name, const char *_iso2, const char *_code) : name(_name), iso2(_iso2), code(_code) { + } + const char *name, *iso2, *code; +}; + static const CountryInfo countries[] = { CountryInfo("Afghanistan", "AF", "93"), CountryInfo("Albania", "AL", "355"), @@ -248,3 +257,9 @@ static const CountryInfo countries[] = { CountryInfo("Zambia", "ZM", "260"), CountryInfo("Zimbabwe", "ZW", "263"), }; + +typedef QHash CountriesByCode; +typedef QHash CountriesByISO2; + +const CountriesByCode &countriesByCode(); +const CountriesByISO2 &countriesByISO2(); diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 2fb1c38b5..ca3df09dc 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -23,7 +23,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "dialogswidget.h" #include "mainwidget.h" #include "boxes/addcontactbox.h" -#include "boxes/newgroupbox.h" +#include "boxes/contactsbox.h" #include "localstorage.h" @@ -718,7 +718,11 @@ void DialogsListWidget::peopleReceived(const QString &query, const QVector &contacts) { cSetContactsReceived(true); for (QVector::const_iterator i = contacts.cbegin(), e = contacts.cend(); i != e; ++i) { - addNewContact(i->c_contact().vuser_id.v); + int32 uid = i->c_contact().vuser_id.v; + addNewContact(uid); + if (uid == MTP::authedId() && App::self()) { + App::self()->contact = 1; + } } if (!sel && contactsNoDialogs.list.count) { sel = contactsNoDialogs.list.begin; @@ -1877,7 +1881,7 @@ void DialogsWidget::onAddContact() { } void DialogsWidget::onNewGroup() { - App::wnd()->showLayer(new NewGroupBox()); + App::wnd()->showLayer(new ContactsBox(true)); } bool DialogsWidget::onCancelSearch() { diff --git a/Telegram/SourceFiles/gui/countryinput.cpp b/Telegram/SourceFiles/gui/countryinput.cpp index a2b7f450b..e5c3da0f6 100644 --- a/Telegram/SourceFiles/gui/countryinput.cpp +++ b/Telegram/SourceFiles/gui/countryinput.cpp @@ -23,26 +23,18 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "gui/countryinput.h" #include "gui/scrollarea.h" -namespace { - - struct CountryInfo { - CountryInfo(const char *_name, const char *_iso2, const char *_code) : name(_name), iso2(_iso2), code(_code) { - } - const char *name, *iso2, *code; - }; - #include "countries.h" - typedef QHash CountriesByCode; - typedef QHash CountriesByISO2; +namespace { + typedef QList CountriesFiltered; typedef QVector CountriesIds; typedef QHash CountriesByLetter; typedef QVector CountryNames; typedef QVector CountriesNames; - CountriesByCode countriesByCode; - CountriesByISO2 countriesByISO2; + CountriesByCode _countriesByCode; + CountriesByISO2 _countriesByISO2; CountriesFiltered countriesFiltered, countriesAll, *countriesNow = &countriesAll; CountriesByLetter countriesByLetter; CountriesNames countriesNames; @@ -51,19 +43,19 @@ namespace { int countriesCount = sizeof(countries) / sizeof(countries[0]); void initCountries() { - if (countriesByCode.size()) return; + if (!_countriesByCode.isEmpty()) return; - countriesByCode.reserve(countriesCount); - countriesByISO2.reserve(countriesCount); + _countriesByCode.reserve(countriesCount); + _countriesByISO2.reserve(countriesCount); for (int i = 0; i < countriesCount; ++i) { const CountryInfo *info(countries + i); - countriesByCode.insert(info->code, info); - CountriesByISO2::const_iterator already = countriesByISO2.constFind(info->iso2); - if (already != countriesByISO2.cend()) { + _countriesByCode.insert(info->code, info); + CountriesByISO2::const_iterator already = _countriesByISO2.constFind(info->iso2); + if (already != _countriesByISO2.cend()) { QString badISO = info->iso2; (void)badISO; } - countriesByISO2.insert(info->iso2, info); + _countriesByISO2.insert(info->iso2, info); } countriesAll.reserve(countriesCount); countriesFiltered.reserve(countriesCount); @@ -71,10 +63,20 @@ namespace { } } +const CountriesByCode &countriesByCode() { + initCountries(); + return _countriesByCode; +} + +const CountriesByISO2 &countriesByISO2() { + initCountries(); + return _countriesByISO2; +} + QString findValidCode(QString fullCode) { while (fullCode.length()) { - CountriesByCode::const_iterator i = countriesByCode.constFind(fullCode); - if (i != countriesByCode.cend()) { + CountriesByCode::const_iterator i = _countriesByCode.constFind(fullCode); + if (i != _countriesByCode.cend()) { return (*i)->code; } fullCode = fullCode.mid(0, fullCode.length() - 1); @@ -159,8 +161,8 @@ void CountryInput::onChooseCode(const QString &code) { emit selectClosed(); } if (code.length()) { - CountriesByCode::const_iterator i = countriesByCode.constFind(code); - if (i != countriesByCode.cend()) { + CountriesByCode::const_iterator i = _countriesByCode.constFind(code); + if (i != _countriesByCode.cend()) { const CountryInfo *info = *i; lastValidISO = info->iso2; setText(QString::fromUtf8(info->name)); @@ -174,8 +176,8 @@ void CountryInput::onChooseCode(const QString &code) { } bool CountryInput::onChooseCountry(const QString &iso) { - CountriesByISO2::const_iterator i = countriesByISO2.constFind(iso); - const CountryInfo *info = (i == countriesByISO2.cend()) ? 0 : (*i); + CountriesByISO2::const_iterator i = _countriesByISO2.constFind(iso); + const CountryInfo *info = (i == _countriesByISO2.cend()) ? 0 : (*i); if (info) { lastValidISO = info->iso2; @@ -206,12 +208,12 @@ CountryInput::~CountryInput() { CountryList::CountryList(QWidget *parent, const style::countryList &st) : QWidget(parent), _sel(0), _st(st), _mouseSel(false) { - CountriesByISO2::const_iterator l = countriesByISO2.constFind(lastValidISO); + CountriesByISO2::const_iterator l = _countriesByISO2.constFind(lastValidISO); bool seenLastValid = false; int already = countriesAll.size(); countriesByLetter.clear(); - const CountryInfo *lastValid = (l == countriesByISO2.cend()) ? 0 : (*l); + const CountryInfo *lastValid = (l == _countriesByISO2.cend()) ? 0 : (*l); for (int i = 0; i < countriesCount; ++i) { const CountryInfo *ins = lastValid ? (i ? (countries + i - (seenLastValid ? 0 : 1)) : lastValid) : (countries + i); if (lastValid && i && ins == lastValid) { @@ -496,8 +498,8 @@ void CountrySelect::paintEvent(QPaintEvent *e) { // draw box title / text p.setPen(st::black->p); - p.setFont(st::addContactTitleFont->f); - p.drawText(_innerLeft + st::addContactTitlePos.x(), _innerTop + st::addContactTitlePos.y() + st::addContactTitleFont->ascent, lang(lng_country_select)); + p.setFont(st::boxTitleFont->f); + p.drawText(_innerLeft + st::boxTitlePos.x(), _innerTop + st::boxTitlePos.y() + st::boxTitleFont->ascent, lang(lng_country_select)); } } } @@ -542,8 +544,8 @@ void CountrySelect::resizeEvent(QResizeEvent *e) { if (height() != e->oldSize().height()) { _innerTop = st::introSelectDelta; _innerHeight = height() - _innerTop - st::introSelectDelta; - if (_innerHeight > st::introSelectMaxHeight) { - _innerHeight = st::introSelectMaxHeight; + if (_innerHeight > st::boxMaxListHeight) { + _innerHeight = st::boxMaxListHeight; _innerTop = (height() - _innerHeight) / 2; } } diff --git a/Telegram/SourceFiles/gui/scrollarea.cpp b/Telegram/SourceFiles/gui/scrollarea.cpp index 1125f4b98..1b9e9f027 100644 --- a/Telegram/SourceFiles/gui/scrollarea.cpp +++ b/Telegram/SourceFiles/gui/scrollarea.cpp @@ -57,7 +57,7 @@ void ScrollBar::recountSize() { setGeometry(_vertical ? QRect(_area->width() - _st->width, 0, _st->width, _area->height()) : QRect(0, _area->height() - _st->width, _area->width(), _st->width)); } -void ScrollBar::updateBar() { +void ScrollBar::updateBar(bool force) { QRect newBar; if (_connected->maximum() != _scrollMax) { int32 oldMax = _scrollMax, newMax = _connected->maximum(); @@ -68,8 +68,9 @@ void ScrollBar::updateBar() { int sh = _area->scrollHeight(), rh = height() - 2 * _st->deltay, h = sh ? int32((rh * int64(_area->height())) / sh) : 0; if (h >= rh || !_area->scrollTopMax() || rh < _st->minHeight) { if (!isHidden()) hide(); - if (_topSh) emit topShadowVisibility(_topSh = (_st->topsh < 0)); - if (_bottomSh) emit bottomShadowVisibility(_bottomSh = (_st->bottomsh < 0)); + bool newTopSh = (_st->topsh < 0), newBottomSh = (_st->bottomsh < 0); + if (newTopSh != _topSh || force) emit topShadowVisibility(_topSh = newTopSh); + if (newBottomSh != _bottomSh || force) emit bottomShadowVisibility(_bottomSh = newBottomSh); return; } @@ -97,8 +98,8 @@ void ScrollBar::updateBar() { } if (_vertical) { bool newTopSh = (_st->topsh < 0) || (_area->scrollTop() > _st->topsh), newBottomSh = (_st->bottomsh < 0) || (_area->scrollTop() < _area->scrollTopMax() - _st->bottomsh); - if (newTopSh != _topSh) emit topShadowVisibility(_topSh = newTopSh); - if (newBottomSh != _bottomSh) emit bottomShadowVisibility(_bottomSh = newBottomSh); + if (newTopSh != _topSh || force) emit topShadowVisibility(_topSh = newTopSh); + if (newBottomSh != _bottomSh || force) emit bottomShadowVisibility(_bottomSh = newBottomSh); } if (isHidden()) show(); } @@ -252,15 +253,16 @@ void ScrollBar::resizeEvent(QResizeEvent *e) { } ScrollArea::ScrollArea(QWidget *parent, const style::flatScroll &st, bool handleTouch) : QScrollArea(parent), - _st(st), - hor(this, false, &_st), vert(this, true, &_st), topSh(this, &_st), bottomSh(this, &_st), - _touchEnabled(handleTouch), _touchScroll(false), _touchPress(false), _touchRightButton(false), - _touchScrollState(TouchScrollManual), _touchPrevPosValid(false), _touchWaitingAcceleration(false), - _touchSpeedTime(0), _touchAccelerationTime(0), _touchTime(0), _widgetAcceptsTouch(false) { +_st(st), +hor(this, false, &_st), vert(this, true, &_st), topSh(this, &_st), bottomSh(this, &_st), +_touchEnabled(handleTouch), _touchScroll(false), _touchPress(false), _touchRightButton(false), +_touchScrollState(TouchScrollManual), _touchPrevPosValid(false), _touchWaitingAcceleration(false), +_touchSpeedTime(0), _touchAccelerationTime(0), _touchTime(0), _widgetAcceptsTouch(false) { connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SIGNAL(scrolled())); connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SIGNAL(scrolled())); connect(&vert, SIGNAL(topShadowVisibility(bool)), &topSh, SLOT(changeVisibility(bool))); connect(&vert, SIGNAL(bottomShadowVisibility(bool)), &bottomSh, SLOT(changeVisibility(bool))); + vert.updateBar(true); if (_st.hiding) { connect(this, SIGNAL(scrolled()), this, SLOT(onScrolled())); } diff --git a/Telegram/SourceFiles/gui/scrollarea.h b/Telegram/SourceFiles/gui/scrollarea.h index fcd7fd4bf..6e3580511 100644 --- a/Telegram/SourceFiles/gui/scrollarea.h +++ b/Telegram/SourceFiles/gui/scrollarea.h @@ -70,7 +70,7 @@ public: public slots: - void updateBar(); + void updateBar(bool force = false); void onHideTimer(); signals: diff --git a/Telegram/SourceFiles/gui/twidget.cpp b/Telegram/SourceFiles/gui/twidget.cpp index e845662b0..7690b3c1e 100644 --- a/Telegram/SourceFiles/gui/twidget.cpp +++ b/Telegram/SourceFiles/gui/twidget.cpp @@ -20,18 +20,34 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "application.h" namespace { - void _sendResizeEvents(QWidget *target) { - QResizeEvent e(target->size(), QSize()); - QApplication::sendEvent(target, &e); - - const QObjectList children = target->children(); - for (int i = 0; i < children.size(); ++i) { - QWidget *child = static_cast(children.at(i)); - if (child->isWidgetType() && !child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent)) { - _sendResizeEvents(child); - } - } - } + Qt::LayoutDirection _dir = Qt::LeftToRight; + bool _rtl = false; + + void _sendResizeEvents(QWidget *target) { + QResizeEvent e(target->size(), QSize()); + QApplication::sendEvent(target, &e); + + const QObjectList children = target->children(); + for (int i = 0; i < children.size(); ++i) { + QWidget *child = static_cast(children.at(i)); + if (child->isWidgetType() && !child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent)) { + _sendResizeEvents(child); + } + } + } +} + +void rtl(bool is) { + _rtl = is; + _dir = _rtl ? Qt::RightToLeft : Qt::LeftToRight; +} + +bool rtl() { + return _rtl; +} + +Qt::LayoutDirection langDir() { // current lang dependent + return _dir; } QPixmap myGrab(QWidget *target, const QRect &rect) { diff --git a/Telegram/SourceFiles/gui/twidget.h b/Telegram/SourceFiles/gui/twidget.h index d71c5a03a..74bf7fac1 100644 --- a/Telegram/SourceFiles/gui/twidget.h +++ b/Telegram/SourceFiles/gui/twidget.h @@ -17,12 +17,47 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org */ #pragma once -class TWidget : public QWidget { +void rtl(bool is); +bool rtl(); +Qt::LayoutDirection langDir(); + +class Widget : public QWidget { +public: + + Widget(QWidget *parent = 0) : QWidget(parent) { + } + void moveToLeft(int x, int y, int w) { + move(rtl() ? (x + w - width()) : x, y); + } + void moveToRight(int x, int y, int w) { + move(rtl() ? x : (x + w - width()), y); + } + +}; + +class Painter : public QPainter { +public: + explicit Painter(QPaintDevice *device) : QPainter(device) { + } + + void drawTextLeft(int x, int y, int w, const QString &text, int textWidth = -1) { + QFontMetrics m(fontMetrics()); + if (rtl() && textWidth < 0) textWidth = m.width(text); + drawText(x + (rtl() ? (w - textWidth) : 0), y + m.ascent(), text); + } + void drawTextRight(int x, int y, int w, const QString &text, int textWidth = -1) { + QFontMetrics m(fontMetrics()); + if (!rtl() && textWidth < 0) textWidth = m.width(text); + drawText(x + (rtl() ? 0 : (w - textWidth)), y + m.ascent(), text); + } +}; + +class TWidget : public Widget { Q_OBJECT public: - TWidget(QWidget *parent = 0) : QWidget(parent) { + TWidget(QWidget *parent = 0) : Widget(parent) { } TWidget *tparent() { return qobject_cast(parentWidget()); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index f4d5ff9d0..93094a715 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2584,7 +2584,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const int32 flags = (p->input.type() == mtpc_inputPeerSelf) ? 0 : (MTPDmessage_flag_unread | MTPDmessage_flag_out); // unread, out if (replyTo) flags |= MTPDmessage::flag_reply_to_msg_id; h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(_replyToId), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)))); - h->sendRequestId = MTP::send(MTPmessages_SendMedia(p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentFullDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + h->sendRequestId = MTP::send(MTPmessages_SendMedia(p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); App::historyRegRandom(randomId, newId); if (hist && histPeer && peer == histPeer->id) { @@ -3193,7 +3193,7 @@ void HistoryWidget::onPhotoUploaded(MsgId newId, const MTPInputFile &file) { App::historyRegRandom(randomId, newId); History *hist = item->history(); MsgId replyTo = item->toHistoryReply() ? item->toHistoryReply()->replyToId() : 0; - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedPhoto(file), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentFullDataReceived, randomId), App::main()->rpcFail(&MainWidget::sendPhotoFailed, randomId), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedPhoto(file), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendPhotoFailed, randomId), 0, 0, hist->sendRequestId); } } @@ -3229,7 +3229,7 @@ void HistoryWidget::onDocumentUploaded(MsgId newId, const MTPInputFile &file) { App::historyRegRandom(randomId, newId); History *hist = item->history(); MsgId replyTo = item->toHistoryReply() ? item->toHistoryReply()->replyToId() : 0; - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedDocument(file, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentFullDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedDocument(file, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } } } @@ -3251,7 +3251,7 @@ void HistoryWidget::onThumbDocumentUploaded(MsgId newId, const MTPInputFile &fil App::historyRegRandom(randomId, newId); History *hist = item->history(); MsgId replyTo = item->toHistoryReply() ? item->toHistoryReply()->replyToId() : 0; - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedThumbDocument(file, thumb, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentFullDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(item->history()->peer->input, MTP_int(replyTo), MTP_inputMediaUploadedThumbDocument(file, thumb, MTP_string(document->mime), _composeDocumentAttributes(document)), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } } } @@ -3525,7 +3525,7 @@ void HistoryWidget::onStickerSend(DocumentData *sticker) { if (_replyToId) flags |= MTPDmessage::flag_reply_to_msg_id; hist->addToBackDocument(newId, flags, _replyToId, date(MTP_int(unixtime())), MTP::authedId(), sticker); - hist->sendRequestId = MTP::send(MTPmessages_SendMedia(histPeer->input, MTP_int(_replyToId), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentFullDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_SendMedia(histPeer->input, MTP_int(_replyToId), MTP_inputMediaDocument(MTP_inputDocument(MTP_long(sticker->id), MTP_long(sticker->access))), MTP_long(randomId)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); App::main()->finishForwarding(hist); cancelReply(); diff --git a/Telegram/SourceFiles/intro/intro.cpp b/Telegram/SourceFiles/intro/intro.cpp index b4bb82b1d..67ec44e3f 100644 --- a/Telegram/SourceFiles/intro/intro.cpp +++ b/Telegram/SourceFiles/intro/intro.cpp @@ -26,6 +26,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "intro/introphone.h" #include "intro/introcode.h" #include "intro/introsignup.h" +#include "intro/intropwdcheck.h" #include "mainwidget.h" #include "window.h" #include "application.h" @@ -55,10 +56,13 @@ steps(new IntroSteps(this)), phone(0), code(0), signup(0), +pwdcheck(0), current(0), moving(0), visibilityChanging(0), _callTimeout(60), +_registered(false), +_hasRecovery(false), _back(this, st::setClose), _backFrom(0), _backTo(0) { setGeometry(QRect(0, st::titleHeight, wnd->width(), wnd->height() - st::titleHeight)); @@ -80,6 +84,8 @@ _backFrom(0), _backTo(0) { show(); setFocus(); + cSetPasswordRecovered(false); + _back.move(st::setClosePos.x(), st::setClosePos.y()); } @@ -117,7 +123,13 @@ bool IntroWidget::createNext() { switch (current) { case 0: stages[current + 1] = phone = new IntroPhone(this); break; case 1: stages[current + 1] = code = new IntroCode(this); break; - case 2: stages[current + 1] = signup = new IntroSignup(this); break; + case 2: + if (_pwdSalt.isEmpty()) { + stages[current + 1] = signup = new IntroSignup(this); + } else { + stages[current + 1] = pwdcheck = new IntroPwdCheck(this); + } + break; } } _back.raise(); @@ -154,7 +166,7 @@ void IntroWidget::onDoneStateChanged(int oldState, ButtonStateChangeSource sourc } else { makeHideCache(); } - } else if (source == ButtonByHover) { + } else if (source == ButtonByHover && current != 2) { if (!createNext()) return; if (!cacheForShow) makeShowCache(current + 1); } @@ -299,6 +311,23 @@ void IntroWidget::setCode(const QString &code) { _code = code; } +void IntroWidget::setPwdSalt(const QByteArray &salt) { + _pwdSalt = salt; + delete signup; + delete pwdcheck; + stages[3] = 0; + signup = 0; + pwdcheck = 0; +} + +void IntroWidget::setHasRecovery(bool has) { + _hasRecovery = has; +} + +void IntroWidget::setPwdHint(const QString &hint) { + _pwdHint = hint; +} + void IntroWidget::setCallTimeout(int32 callTimeout) { _callTimeout = callTimeout; } @@ -319,12 +348,25 @@ int32 IntroWidget::getCallTimeout() const { return _callTimeout; } +const QByteArray &IntroWidget::getPwdSalt() const { + return _pwdSalt; +} + +bool IntroWidget::getHasRecovery() const { + return _hasRecovery; +} + +const QString &IntroWidget::getPwdHint() const { + return _pwdHint; +} + void IntroWidget::resizeEvent(QResizeEvent *e) { QRect r(innerRect()); if (steps) steps->setGeometry(r); if (phone) phone->setGeometry(r); if (code) code->setGeometry(r); if (signup) signup->setGeometry(r); + if (pwdcheck) pwdcheck->setGeometry(r); } void IntroWidget::mousePressEvent(QMouseEvent *e) { @@ -355,6 +397,7 @@ void IntroWidget::rpcInvalidate() { if (phone) phone->rpcInvalidate(); if (code) code->rpcInvalidate(); if (signup) signup->rpcInvalidate(); + if (pwdcheck) pwdcheck->rpcInvalidate(); } IntroWidget::~IntroWidget() { @@ -362,5 +405,6 @@ IntroWidget::~IntroWidget() { delete phone; delete code; delete signup; + delete pwdcheck; if (App::wnd()) App::wnd()->noIntro(this); } diff --git a/Telegram/SourceFiles/intro/intro.h b/Telegram/SourceFiles/intro/intro.h index 87371a9a0..466c92563 100644 --- a/Telegram/SourceFiles/intro/intro.h +++ b/Telegram/SourceFiles/intro/intro.h @@ -22,6 +22,7 @@ class IntroSteps; class IntroPhone; class IntroCode; class IntroSignup; +class IntroPwdCheck; class IntroStage; class Text; @@ -48,11 +49,17 @@ public: void setPhone(const QString &phone, const QString &phone_hash, bool registered); void setCode(const QString &code); void setCallTimeout(int32 callTimeout); + void setPwdSalt(const QByteArray &salt); + void setHasRecovery(bool hasRecovery); + void setPwdHint(const QString &hint); const QString &getPhone() const; const QString &getPhoneHash() const; const QString &getCode() const; int32 getCallTimeout() const; + const QByteArray &getPwdSalt() const; + bool getHasRecovery() const; + const QString &getPwdHint() const; void finish(const MTPUser &user, const QImage &photo = QImage()); @@ -96,6 +103,7 @@ private: IntroPhone *phone; IntroCode *code; IntroSignup *signup; + IntroPwdCheck *pwdcheck; IntroStage *stages[4]; int current, moving, visibilityChanging; @@ -105,6 +113,10 @@ private: QString _code; + QByteArray _pwdSalt; + bool _hasRecovery; + QString _pwdHint; + QString _firstname, _lastname; IconedButton _back; diff --git a/Telegram/SourceFiles/intro/introcode.cpp b/Telegram/SourceFiles/intro/introcode.cpp index 4fa6b9292..9895aba91 100644 --- a/Telegram/SourceFiles/intro/introcode.cpp +++ b/Telegram/SourceFiles/intro/introcode.cpp @@ -216,6 +216,12 @@ bool IntroCode::codeSubmitFail(const RPCError &error) { intro()->setCode(sentCode); intro()->onIntroNext(); return true; + } else if (err == "SESSION_PASSWORD_NEEDED") { + intro()->setCode(sentCode); + code.setDisabled(false); + checkRequest.start(1000); + sentRequest = MTP::send(MTPaccount_GetPassword(), rpcDone(&IntroCode::gotPassword), rpcFail(&IntroCode::codeSubmitFail)); + return true; } if (QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err).hasMatch()) { showError(lang(lng_flood_error)); @@ -251,6 +257,24 @@ void IntroCode::callDone(const MTPBool &v) { } } +void IntroCode::gotPassword(const MTPaccount_Password &result) { + stopCheck(); + code.setDisabled(false); + switch (result.type()) { + case mtpc_account_noPassword: // should not happen + code.setFocus(); + break; + + case mtpc_account_password: { + const MTPDaccount_password &d(result.c_account_password()); + intro()->setPwdSalt(qba(d.vcurrent_salt)); + intro()->setHasRecovery(d.vhas_recovery.v); + intro()->setPwdHint(qs(d.vhint)); + intro()->onIntroNext(); + } break; + } +} + void IntroCode::onSubmitCode(bool force) { if (!force && (code.text() == sentCode || !code.isEnabled())) return; @@ -262,6 +286,9 @@ void IntroCode::onSubmitCode(bool force) { checkRequest.start(1000); sentCode = code.text(); + intro()->setPwdSalt(QByteArray()); + intro()->setHasRecovery(false); + intro()->setPwdHint(QString()); sentRequest = MTP::send(MTPauth_SignIn(MTP_string(intro()->getPhone()), MTP_string(intro()->getPhoneHash()), MTP_string(sentCode)), rpcDone(&IntroCode::codeSubmitDone), rpcFail(&IntroCode::codeSubmitFail)); } diff --git a/Telegram/SourceFiles/intro/introcode.h b/Telegram/SourceFiles/intro/introcode.h index bbefa46d0..67c70b6f8 100644 --- a/Telegram/SourceFiles/intro/introcode.h +++ b/Telegram/SourceFiles/intro/introcode.h @@ -74,6 +74,8 @@ private: void showError(const QString &err); void callDone(const MTPBool &v); + void gotPassword(const MTPaccount_Password &result); + void stopCheck(); QString error; diff --git a/Telegram/SourceFiles/intro/intropwdcheck.cpp b/Telegram/SourceFiles/intro/intropwdcheck.cpp new file mode 100644 index 000000000..105fd7c62 --- /dev/null +++ b/Telegram/SourceFiles/intro/intropwdcheck.cpp @@ -0,0 +1,319 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "lang.h" +#include "style.h" + +#include "gui/filedialog.h" +#include "boxes/confirmbox.h" + +#include "application.h" + +#include "intro/intropwdcheck.h" +#include "intro/intro.h" + +IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStage(parent), +errorAlpha(0), +_next(this, lang(lng_intro_submit), st::btnIntroNext), +_salt(parent->getPwdSalt()), +_hasRecovery(parent->getHasRecovery()), +_hint(parent->getPwdHint()), +_pwdField(this, st::inpIntroPassword, lang(lng_signin_password)), +_codeField(this, st::inpIntroPassword, lang(lng_signin_code)), +_toRecover(this, lang(lng_signin_recover)), +_toPassword(this, lang(lng_signin_try_password)) { + setVisible(false); + setGeometry(parent->innerRect()); + + connect(&_next, SIGNAL(clicked()), this, SLOT(onSubmitPwd())); + connect(&checkRequest, SIGNAL(timeout()), this, SLOT(onCheckRequest())); + connect(&_toRecover, SIGNAL(clicked()), this, SLOT(onToRecover())); + connect(&_toPassword, SIGNAL(clicked()), this, SLOT(onToPassword())); + connect(&_pwdField, SIGNAL(changed()), this, SLOT(onInputChange())); + connect(&_codeField, SIGNAL(changed()), this, SLOT(onInputChange())); + + _pwdField.setEchoMode(QLineEdit::Password); + + if (!_hint.isEmpty()) { + _hintText.setText(st::introFont, lng_signin_hint(lt_password_hint, _hint)); + } + _codeField.hide(); + _toPassword.hide(); + _toRecover.setVisible(_hasRecovery); + + setMouseTracking(true); +} + +void IntroPwdCheck::paintEvent(QPaintEvent *e) { + bool trivial = (rect() == e->rect()); + + QPainter p(this); + if (!trivial) { + p.setClipRect(e->rect()); + } + if (trivial || e->rect().intersects(textRect)) { + p.setFont(st::introHeaderFont->f); + p.drawText(textRect, lang(lng_signin_title), style::al_top); + p.setFont(st::introFont->f); + p.drawText(textRect, lang(_pwdField.isHidden() ? lng_signin_recover_desc : lng_signin_desc), style::al_bottom); + } + if (_pwdField.isHidden()) { + if (!_emailPattern.isEmpty()) { + p.drawText(QRect(textRect.x(), _pwdField.y() + _pwdField.height() + st::introFinishSkip, textRect.width(), st::introFont->height), _emailPattern, style::al_top); + } + } else if (!_hint.isEmpty()) { + _hintText.drawElided(p, _pwdField.x(), _pwdField.y() + _pwdField.height() + st::introFinishSkip, _pwdField.width(), 1, style::al_top); + } + if (animating() || error.length()) { + p.setOpacity(errorAlpha.current()); + + QRect errRect((width() - st::introErrWidth) / 2, (_pwdField.y() + _pwdField.height() + st::introFinishSkip + st::introFont->height + _next.y() - st::introErrHeight) / 2, st::introErrWidth, st::introErrHeight); + p.setFont(st::introErrFont->f); + p.setPen(st::introErrColor->p); + p.drawText(errRect, error, QTextOption(style::al_center)); + + p.setOpacity(1); + } +} + +void IntroPwdCheck::resizeEvent(QResizeEvent *e) { + if (e->oldSize().width() != width()) { + _next.move((width() - _next.width()) / 2, st::introBtnTop); + _pwdField.move((width() - _pwdField.width()) / 2, st::introTextTop + st::introTextSize.height() + st::introCountry.top); + _codeField.move((width() - _codeField.width()) / 2, st::introTextTop + st::introTextSize.height() + st::introCountry.top); + _toRecover.move(_next.x() + (_pwdField.width() - _toRecover.width()) / 2, _next.y() + _next.height() + st::introFinishSkip); + _toPassword.move(_next.x() + (_pwdField.width() - _toPassword.width()) / 2, _next.y() + _next.height() + st::introFinishSkip); + } + textRect = QRect((width() - st::introTextSize.width()) / 2, st::introTextTop, st::introTextSize.width(), st::introTextSize.height()); +} + +void IntroPwdCheck::showError(const QString &err) { + if (!animating() && err == error) return; + + if (err.length()) { + error = err; + errorAlpha.start(1); + } else { + errorAlpha.start(0); + } + anim::start(this); +} + +bool IntroPwdCheck::animStep(float64 ms) { + float64 dt = ms / st::introErrDuration; + + bool res = true; + if (dt >= 1) { + res = false; + errorAlpha.finish(); + if (!errorAlpha.current()) { + error = ""; + } + } else { + errorAlpha.update(dt, st::introErrFunc); + } + update(); + return res; +} + +void IntroPwdCheck::activate() { + show(); + if (_pwdField.isHidden()) { + _codeField.setFocus(); + } else { + _pwdField.setFocus(); + } +} + +void IntroPwdCheck::deactivate() { + hide(); +} + +void IntroPwdCheck::stopCheck() { + checkRequest.stop(); +} + +void IntroPwdCheck::onCheckRequest() { + int32 status = MTP::state(sentRequest); + if (status < 0) { + int32 leftms = -status; + if (leftms >= 1000) { + MTP::cancel(sentRequest); + sentRequest = 0; + if (!_pwdField.isEnabled()) { + _pwdField.setDisabled(false); + _codeField.setDisabled(false); + activate(); + } + } + } + if (!sentRequest && status == MTP::RequestSent) { + stopCheck(); + } +} + +void IntroPwdCheck::pwdSubmitDone(bool recover, const MTPauth_Authorization &result) { + stopCheck(); + if (recover) { + cSetPasswordRecovered(true); + } + _pwdField.setDisabled(false); + _codeField.setDisabled(false); + const MTPDauth_authorization &d(result.c_auth_authorization()); + if (d.vuser.type() != mtpc_userSelf) { // wtf? + showError(lang(lng_server_error)); + return; + } + intro()->finish(d.vuser); +} + +bool IntroPwdCheck::pwdSubmitFail(const RPCError &error) { + stopCheck(); + _pwdField.setDisabled(false); + _codeField.setDisabled(false); + const QString &err = error.type(); + if (err == "PASSWORD_HASH_INVALID") { + showError(lang(lng_signin_bad_password)); + _pwdField.notaBene(); + return true; + } else if (err == "PASSWORD_EMPTY") { + intro()->onIntroBack(); + } + if (QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err).hasMatch()) { + showError(lang(lng_flood_error)); + _pwdField.setFocus(); + return true; + } + if (cDebug()) { // internal server error + showError(err + ": " + error.description()); + } else { + showError(lang(lng_server_error)); + } + _pwdField.setFocus(); + return false; +} + +bool IntroPwdCheck::codeSubmitFail(const RPCError &error) { + stopCheck(); + _pwdField.setDisabled(false); + _codeField.setDisabled(false); + const QString &err = error.type(); + if (err == "PASSWORD_EMPTY") { + intro()->onIntroBack(); + return true; + } else if (err == "PASSWORD_RECOVERY_NA") { + recoverStartFail(error); + return true; + } else if (err == "PASSWORD_RECOVERY_EXPIRED") { + _emailPattern = QString(); + onToPassword(); + return true; + } else if (err == "CODE_INVALID") { + showError(lang(lng_signin_wrong_code)); + _pwdField.notaBene(); + return true; + } + if (QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err).hasMatch()) { + showError(lang(lng_flood_error)); + _codeField.notaBene(); + return true; + } + if (cDebug()) { // internal server error + showError(err + ": " + error.description()); + } else { + showError(lang(lng_server_error)); + } + _codeField.setFocus(); + return false; +} + +void IntroPwdCheck::recoverStarted(const MTPauth_PasswordRecovery &result) { + _emailPattern = lng_signin_recover_hint(lt_recover_email, qs(result.c_auth_passwordRecovery().vemail_pattern)); + update(); +} + +bool IntroPwdCheck::recoverStartFail(const RPCError &error) { + stopCheck(); + _pwdField.setDisabled(false); + _codeField.setDisabled(false); + _pwdField.show(); + _codeField.hide(); + _pwdField.setFocus(); + update(); + showError(""); + return true; +} + +void IntroPwdCheck::onToRecover() { + showError(""); + _toRecover.hide(); + _toPassword.show(); + _pwdField.hide(); + _pwdField.setText(QString()); + _codeField.show(); + _codeField.setFocus(); + if (_emailPattern.isEmpty()) { + MTP::send(MTPauth_RequestPasswordRecovery(), rpcDone(&IntroPwdCheck::recoverStarted), rpcFail(&IntroPwdCheck::recoverStartFail)); + } + update(); +} + +void IntroPwdCheck::onToPassword() { + _toRecover.show(); + _toPassword.hide(); + _pwdField.show(); + _codeField.hide(); + _codeField.setText(QString()); + _pwdField.setFocus(); + update(); +} + +void IntroPwdCheck::onInputChange() { + showError(""); +} + +void IntroPwdCheck::onSubmitPwd(bool force) { + if (_pwdField.isHidden()) { + if (!force && !_codeField.isEnabled()) return; + QString code = _codeField.text().trimmed(); + if (code.isEmpty()) { + _codeField.notaBene(); + return; + } + + sentRequest = MTP::send(MTPauth_RecoverPassword(MTP_string(code)), rpcDone(&IntroPwdCheck::pwdSubmitDone, true), rpcFail(&IntroPwdCheck::codeSubmitFail)); + } else { + if (!force && !_pwdField.isEnabled()) return; + + _pwdField.setDisabled(true); + setFocus(); + + showError(""); + + QByteArray pwdData = _salt + _pwdField.text().toUtf8() + _salt, pwdHash(32, Qt::Uninitialized); + hashSha256(pwdData.constData(), pwdData.size(), pwdHash.data()); + sentRequest = MTP::send(MTPauth_CheckPassword(MTP_string(pwdHash)), rpcDone(&IntroPwdCheck::pwdSubmitDone, false), rpcFail(&IntroPwdCheck::pwdSubmitFail)); + } +} + +void IntroPwdCheck::onNext() { + onSubmitPwd(); +} + +void IntroPwdCheck::onBack() { +} diff --git a/Telegram/SourceFiles/intro/intropwdcheck.h b/Telegram/SourceFiles/intro/intropwdcheck.h new file mode 100644 index 000000000..b10467116 --- /dev/null +++ b/Telegram/SourceFiles/intro/intropwdcheck.h @@ -0,0 +1,82 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include +#include "gui/flatbutton.h" +#include "gui/flatinput.h" +#include "intro.h" + +class IntroPwdCheck : public IntroStage, public Animated, public RPCSender { + Q_OBJECT + +public: + + IntroPwdCheck(IntroWidget *parent); + + void paintEvent(QPaintEvent *e); + void resizeEvent(QResizeEvent *e); + + bool animStep(float64 ms); + + void activate(); + void deactivate(); + void onNext(); + void onBack(); + + void pwdSubmitDone(bool recover, const MTPauth_Authorization &result); + bool pwdSubmitFail(const RPCError &error); + bool codeSubmitFail(const RPCError &error); + bool recoverStartFail(const RPCError &error); + + void recoverStarted(const MTPauth_PasswordRecovery &result); + +public slots: + + void onSubmitPwd(bool force = false); + void onToRecover(); + void onToPassword(); + void onInputChange(); + void onCheckRequest(); + +private: + + void showError(const QString &err); + void stopCheck(); + + QString error; + anim::fvalue errorAlpha; + + FlatButton _next; + + QRect textRect; + + QByteArray _salt; + bool _hasRecovery; + QString _hint, _emailPattern; + + FlatInput _pwdField, _codeField; + LinkButton _toRecover, _toPassword; + mtpRequestId sentRequest; + + Text _hintText; + + QByteArray _pwdSalt; + + QTimer checkRequest; +}; diff --git a/Telegram/SourceFiles/intro/introsignup.cpp b/Telegram/SourceFiles/intro/introsignup.cpp index 1a84fa9dd..fa96cb36d 100644 --- a/Telegram/SourceFiles/intro/introsignup.cpp +++ b/Telegram/SourceFiles/intro/introsignup.cpp @@ -103,7 +103,6 @@ void IntroSignup::paintEvent(QPaintEvent *e) { p.setOpacity(errorAlpha.current()); QRect errRect((width() - st::introErrWidth) / 2, (last.y() + last.height() + next.y() - st::introErrHeight) / 2, st::introErrWidth, st::introErrHeight); - p.fillRect(errRect, st::introErrBG->b); p.setFont(st::introErrFont->f); p.setPen(st::introErrColor->p); p.drawText(errRect, error, QTextOption(style::al_center)); diff --git a/Telegram/SourceFiles/lang.cpp b/Telegram/SourceFiles/lang.cpp index 38a90b07f..6ee239eb0 100644 --- a/Telegram/SourceFiles/lang.cpp +++ b/Telegram/SourceFiles/lang.cpp @@ -19,10 +19,6 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "lang.h" -Qt::LayoutDirection langDir() { // current lang dependent - return Qt::LeftToRight; -} - LangString langCounted(ushort key0, ushort tag, float64 value) { // current lang dependent int v = qFloor(value); QString sv; diff --git a/Telegram/SourceFiles/lang.h b/Telegram/SourceFiles/lang.h index 99eb0964f..7cb0fea1d 100644 --- a/Telegram/SourceFiles/lang.h +++ b/Telegram/SourceFiles/lang.h @@ -92,8 +92,6 @@ inline LangString langDayOfWeekFull(const QDate &date) { return (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1_full + day - 1)) : qsl("DAY_ERR"); } -Qt::LayoutDirection langDir(); - class LangLoader { public: const QString &errors() const; diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp index 647a5ff4b..d382a83b6 100644 --- a/Telegram/SourceFiles/localstorage.cpp +++ b/Telegram/SourceFiles/localstorage.cpp @@ -1031,7 +1031,7 @@ namespace { bool _readOldUserSettings(bool remove = true) { bool result = false; - QFile file(cWorkingDir() + cDataFile() + qsl("_config")); + QFile file(cWorkingDir() + cDataFile() + (cTestMode() ? qsl("_test") : QString()) + qsl("_config")); if (file.open(QIODevice::ReadOnly)) { LOG(("App Info: reading old user config..")); qint32 version = 0; @@ -1111,7 +1111,7 @@ namespace { bool _readOldMtpData(bool remove = true) { bool result = false; - QFile file(cWorkingDir() + cDataFile()); + QFile file(cWorkingDir() + cDataFile() + (cTestMode() ? qsl("_test") : QString())); if (file.open(QIODevice::ReadOnly)) { LOG(("App Info: reading old keys..")); qint32 version = 0; @@ -1235,7 +1235,7 @@ namespace { Local::ReadMapState _readMap(const QByteArray &pass) { uint64 ms = getms(); - QByteArray dataNameUtf8 = cDataFile().toUtf8(); + QByteArray dataNameUtf8 = (cDataFile() + (cTestMode() ? qsl(":/test/") : QString())).toUtf8(); FileKey dataNameHash[2]; hashMd5(dataNameUtf8.constData(), dataNameUtf8.size(), dataNameHash); _dataNameKey = dataNameHash[0]; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index f7f97dc68..a2acceb3f 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -490,7 +490,7 @@ void MainWidget::finishForwarding(History *hist) { MsgId newId = clientMsgId(); hist->addToBackForwarded(newId, static_cast(_toForward.cbegin().value())); App::historyRegRandom(randomId, newId); - hist->sendRequestId = MTP::send(MTPmessages_ForwardMessage(hist->peer->input, MTP_int(_toForward.cbegin().key()), MTP_long(randomId)), rpcDone(&MainWidget::sentFullDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_ForwardMessage(hist->peer->input, MTP_int(_toForward.cbegin().key()), MTP_long(randomId)), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } else { QVector ids; QVector randomIds; @@ -504,7 +504,7 @@ void MainWidget::finishForwarding(History *hist) { ids.push_back(MTP_int(i.key())); randomIds.push_back(MTP_long(randomId)); } - hist->sendRequestId = MTP::send(MTPmessages_ForwardMessages(hist->peer->input, MTP_vector(ids), MTP_vector(randomIds)), rpcDone(&MainWidget::forwardDone, hist->peer->id), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); + hist->sendRequestId = MTP::send(MTPmessages_ForwardMessages(hist->peer->input, MTP_vector(ids), MTP_vector(randomIds)), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId); } if (history.peer() == hist->peer) history.peerMessagesUpdated(); cancelForwarding(); @@ -649,8 +649,8 @@ bool MainWidget::leaveChatFailed(PeerData *peer, const RPCError &e) { return false; } -void MainWidget::deleteHistory(PeerData *peer, const MTPmessages_StatedMessage &result) { - sentFullDataReceived(0, result); +void MainWidget::deleteHistory(PeerData *peer, const MTPUpdates &updates) { + sentUpdatesReceived(updates); if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) { showPeer(0, 0, false, true); } @@ -707,16 +707,12 @@ void MainWidget::removeContact(UserData *user) { void MainWidget::addParticipants(ChatData *chat, const QVector &users) { for (QVector::const_iterator i = users.cbegin(), e = users.cend(); i != e; ++i) { - MTP::send(MTPmessages_AddChatUser(MTP_int(chat->id & 0xFFFFFFFF), (*i)->inputUser, MTP_int(ForwardOnAdd)), rpcDone(&MainWidget::addParticipantDone, chat), rpcFail(&MainWidget::addParticipantFail, chat), 0, 5); + MTP::send(MTPmessages_AddChatUser(MTP_int(chat->id & 0xFFFFFFFF), (*i)->inputUser, MTP_int(ForwardOnAdd)), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::addParticipantFail, chat), 0, 5); } App::wnd()->hideLayer(); showPeer(chat->id, 0, false); } -void MainWidget::addParticipantDone(ChatData *chat, const MTPmessages_StatedMessage &result) { - sentFullDataReceived(0, result); -} - bool MainWidget::addParticipantFail(ChatData *chat, const RPCError &e) { ConfirmBox *box = new ConfirmBox(lang(lng_failed_add_participant), true); App::wnd()->showLayer(box); @@ -726,15 +722,11 @@ bool MainWidget::addParticipantFail(ChatData *chat, const RPCError &e) { } void MainWidget::kickParticipant(ChatData *chat, UserData *user) { - MTP::send(MTPmessages_DeleteChatUser(MTP_int(chat->id & 0xFFFFFFFF), user->inputUser), rpcDone(&MainWidget::kickParticipantDone, chat), rpcFail(&MainWidget::kickParticipantFail, chat)); + MTP::send(MTPmessages_DeleteChatUser(MTP_int(chat->id & 0xFFFFFFFF), user->inputUser), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::kickParticipantFail, chat)); App::wnd()->hideLayer(); showPeer(chat->id, 0, false); } -void MainWidget::kickParticipantDone(ChatData *chat, const MTPmessages_StatedMessage &result) { - sentFullDataReceived(0, result); -} - bool MainWidget::kickParticipantFail(ChatData *chat, const RPCError &e) { e.type(); return false; @@ -1886,115 +1878,8 @@ void MainWidget::sentDataReceived(uint64 randomId, const MTPmessages_SentMessage }; } -void MainWidget::sentFullDataReceived(uint64 randomId, const MTPmessages_StatedMessage &result) { - const MTPMessage *msg = 0; - MsgId msgId = 0; - if (randomId) { - switch (result.type()) { - case mtpc_messages_statedMessage: msg = &result.c_messages_statedMessage().vmessage; break; - case mtpc_messages_statedMessageLink: msg = &result.c_messages_statedMessageLink().vmessage; break; - } - if (msg) { - switch (msg->type()) { - case mtpc_message: msgId = msg->c_message().vid.v; break; - case mtpc_messageEmpty: msgId = msg->c_messageEmpty().vid.v; break; - case mtpc_messageService: msgId = msg->c_messageService().vid.v; break; - } - if (msgId) { - feedUpdate(MTP_updateMessageID(MTP_int(msgId), MTP_long(randomId))); // ignore real date - } - } - } - - switch (result.type()) { - case mtpc_messages_statedMessage: { - const MTPDmessages_statedMessage &d(result.c_messages_statedMessage()); - - App::feedChats(d.vchats); - App::feedUsers(d.vusers); - if (msg && msgId) { - App::feedMessageMedia(msgId, *msg); - } - if (updInited) { - if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { - _byPtsStatedMessage.insert(ptsKey(SkippedStatedMessage), result); - return; - } - } - if (!randomId) { - ++updSkipPtsUpdateLevel; - feedUpdate(MTP_updateNewMessage(d.vmessage, d.vpts, d.vpts_count)); - --updSkipPtsUpdateLevel; - } - } break; - - case mtpc_messages_statedMessageLink: { - const MTPDmessages_statedMessageLink &d(result.c_messages_statedMessageLink()); - - App::feedChats(d.vchats); - App::feedUsers(d.vusers); - if (msg && msgId) { - App::feedMessageMedia(msgId, *msg); - } - if (updInited) { - if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { - _byPtsStatedMessage.insert(ptsKey(SkippedStatedMessage), result); - return; - } - } - if (!randomId) { - ++updSkipPtsUpdateLevel; - feedUpdate(MTP_updateNewMessage(d.vmessage, d.vpts, d.vpts_count)); - --updSkipPtsUpdateLevel; - } - App::feedUserLinks(d.vlinks); - } break; - }; -} - -void MainWidget::sentFullDatasReceived(const MTPmessages_StatedMessages &result) { - switch (result.type()) { - case mtpc_messages_statedMessages: { - const MTPDmessages_statedMessages &d(result.c_messages_statedMessages()); - if (updInited) { - if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { - _byPtsStatedMessages.insert(ptsKey(SkippedStatedMessages), result); - return; - } - } - - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - App::feedMsgs(d.vmessages, 1); - history.peerMessagesUpdated(); - } break; - - case mtpc_messages_statedMessagesLinks: { - const MTPDmessages_statedMessagesLinks &d(result.c_messages_statedMessagesLinks()); - - if (updInited) { - if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { - _byPtsStatedMessages.insert(ptsKey(SkippedStatedMessages), result); - return; - } - } - - App::feedUsers(d.vusers); - App::feedChats(d.vchats); - App::feedMsgs(d.vmessages, 1); - history.peerMessagesUpdated(); - - App::feedUserLinks(d.vlinks); - } break; - }; -} - -void MainWidget::forwardDone(PeerId peer, const MTPmessages_StatedMessages &result) { - sentFullDatasReceived(result); - if (hider) hider->forwardDone(); - clearSelectedItems(); - showPeer(peer, 0, false, true); - history.onClearSelected(); +void MainWidget::sentUpdatesReceived(const MTPUpdates &result) { + handleUpdates(result); } void MainWidget::msgUpdated(PeerId peer, const HistoryItem *msg) { @@ -2090,6 +1975,10 @@ void MainWidget::hideAll() { } void MainWidget::showAll() { + if (cPasswordRecovered()) { + cSetPasswordRecovered(false); + App::wnd()->showLayer(new ConfirmBox(lang(lng_signin_password_removed), true, lang(lng_continue))); + } if (cWideMode()) { if (hider) { hider->show(); @@ -2363,8 +2252,6 @@ void MainWidget::applySkippedPtsUpdates() { case SkippedUpdate: feedUpdate(_byPtsUpdate.value(i.key())); break; case SkippedUpdates: handleUpdates(_byPtsUpdates.value(i.key())); break; case SkippedSentMessage: sentDataReceived(0, _byPtsSentMessage.value(i.key())); break; - case SkippedStatedMessage: sentFullDataReceived(0, _byPtsStatedMessage.value(i.key())); break; - case SkippedStatedMessages: sentFullDatasReceived(_byPtsStatedMessages.value(i.key())); break; } } --updSkipPtsUpdateLevel; @@ -2376,8 +2263,6 @@ void MainWidget::clearSkippedPtsUpdates() { _byPtsUpdate.clear(); _byPtsUpdates.clear(); _byPtsSentMessage.clear(); - _byPtsStatedMessage.clear(); - _byPtsStatedMessages.clear(); updSkipPtsUpdateLevel = 0; } @@ -2965,6 +2850,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { if (history.peer() && history.peer()->id == peer) history.update(); } break; + case mtpc_updateWebPage: { + const MTPDupdateWebPage &d(update.c_updateWebPage()); + // + } break; + case mtpc_updateDeleteMessages: { const MTPDupdateDeleteMessages &d(update.c_updateDeleteMessages()); if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { @@ -3140,12 +3030,14 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateNewAuthorization: { const MTPDupdateNewAuthorization &d(update.c_updateNewAuthorization()); QDateTime datetime = date(d.vdate); - + QString name = App::self()->firstName; QString day = langDayOfWeekFull(datetime.date()), date = langDayOfMonth(datetime.date()), time = datetime.time().toString(cTimeFormat()); QString device = qs(d.vdevice), location = qs(d.vlocation); LangString text = lng_new_authorization(lt_name, App::self()->firstName, lt_day, day, lt_date, date, lt_time, time, lt_device, device, lt_location, location); App::wnd()->serviceNotification(text); + + emit App::wnd()->newAuthorization(); } break; case mtpc_updateServiceNotification: { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index bfc8c3ed1..57dfcd6d1 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -206,9 +206,7 @@ public: void windowShown(); void sentDataReceived(uint64 randomId, const MTPmessages_SentMessage &data); - void sentFullDataReceived(uint64 randomId, const MTPmessages_StatedMessage &result); // randomId = 0 - new message, <> 0 - already added new message - void sentFullDatasReceived(const MTPmessages_StatedMessages &result); - void forwardDone(PeerId peer, const MTPmessages_StatedMessages &result); + void sentUpdatesReceived(const MTPUpdates &updates); void msgUpdated(PeerId peer, const HistoryItem *msg); void historyToDown(History *hist); void dialogsToUp(); @@ -259,7 +257,7 @@ public: void dialogsActivate(); bool leaveChatFailed(PeerData *peer, const RPCError &e); - void deleteHistory(PeerData *peer, const MTPmessages_StatedMessage &result); + void deleteHistory(PeerData *peer, const MTPUpdates &updates); void deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result); void deleteMessages(const QVector &ids); void deletedContact(UserData *user, const MTPcontacts_Link &result); @@ -268,11 +266,9 @@ public: void removeContact(UserData *user); void addParticipants(ChatData *chat, const QVector &users); - void addParticipantDone(ChatData *chat, const MTPmessages_StatedMessage &result); bool addParticipantFail(ChatData *chat, const RPCError &e); void kickParticipant(ChatData *chat, UserData *user); - void kickParticipantDone(ChatData *chat, const MTPmessages_StatedMessage &result); bool kickParticipantFail(ChatData *chat, const RPCError &e); void checkPeerHistory(PeerData *peer); @@ -487,8 +483,6 @@ private: QMap _byPtsUpdate; QMap _byPtsUpdates; QMap _byPtsSentMessage; - QMap _byPtsStatedMessage; - QMap _byPtsStatedMessages; SingleTimer _byPtsTimer; QMap _bySeqUpdates; diff --git a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h index a4302ba16..26422f231 100644 --- a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h +++ b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h @@ -317,8 +317,6 @@ enum { mtpc_boolTrue = 0x997275b5, mtpc_boolFalse = 0xbc799737, mtpc_vector = 0x1cb5c415, - mtpc_error = 0xc4b9f9bb, - mtpc_null = 0x56730bcc, // layers mtpc_invokeWithLayer1 = 0x53835315, @@ -368,7 +366,7 @@ static const mtpTypeId mtpLayers[] = { mtpc_invokeWithLayer17, mtpc_invokeWithLayer18, }, mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]); -static const mtpPrime mtpCurrentLayer = 25; +static const mtpPrime mtpCurrentLayer = 27; template class MTPBoxed : public bareT { @@ -944,89 +942,6 @@ inline bool operator!=(const MTPvector &a, const MTPvector &b) { return a.c_vector().v != b.c_vector().v; } -class MTPDerror : public mtpDataImpl { -public: - MTPint vcode; - MTPstring vtext; - - MTPDerror() { - } - MTPDerror(MTPint code, MTPString text) : vcode(code), vtext(text) { - } -}; -class MTPerror : private mtpDataOwner { -public: - MTPerror() : mtpDataOwner(0) { - } - MTPerror(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_error) : mtpDataOwner(0) { - read(from, end, cons); - } - - MTPDerror &_error() { - if (!data) throw mtpErrorUninitialized(); - split(); - return *(MTPDerror*)data; - } - const MTPDerror &c_error() const { - if (!data) throw mtpErrorUninitialized(); - return *(const MTPDerror*)data; - } - - uint32 innerLength() const { - return c_error().vcode.innerLength() + c_error().vtext.innerLength(); - } - mtpTypeId type() const { - return mtpc_error; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_error) { - if (cons != mtpc_error) throw mtpErrorUnexpected(cons, "MTPerror"); - - if (!data) setData(new MTPDerror()); - MTPDerror &v(_error()); - v.vcode.read(from, end); - v.vtext.read(from, end); - } - void write(mtpBuffer &to) const { - c_error().vcode.write(to); - c_error().vtext.write(to); - } - -private: - explicit MTPerror(MTPDerror *_data) : mtpDataOwner(_data) { - } - - friend MTPerror MTP_error(MTPint code, MTPstring text); -}; -inline MTPerror MTP_error(MTPint code, MTPstring text) { - return MTPerror(new MTPDerror(code, text)); -} -typedef MTPBoxed MTPError; - -class MTPnull { -public: - MTPnull() { - } - MTPnull(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_null) { - read(from, end, cons); - } - - uint32 innerLength() const { - return 0; - } - mtpTypeId type() const { - return mtpc_null; - } - void read(const mtpPrime *& /*from*/, const mtpPrime * /*end*/, mtpTypeId cons = mtpc_null) { - if (cons != mtpc_null) throw mtpErrorUnexpected(cons, "MTPnull"); - } - void write(mtpBuffer & /*to*/) const { - } -}; -inline MTPnull MTP_null() { - return MTPnull(); -} -typedef MTPBoxed MTPNull; - // Human-readable text serialization #if (defined _DEBUG || defined _WITH_DEBUG) diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp index fc289d628..22bcb093b 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp +++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp @@ -461,6 +461,24 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_error: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ error"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" code: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_null: + to.add("{ null }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); + break; + case mtpc_inputPeerEmpty: to.add("{ inputPeerEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; @@ -1516,6 +1534,19 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_messageMediaWebPage: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messageMediaWebPage"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" webpage: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_messageActionEmpty: to.add("{ messageActionEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; @@ -2216,78 +2247,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("{ messages_messageEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - case mtpc_messages_statedMessages: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_statedMessages"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" messages: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" users: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_messages_statedMessagesLinks: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_statedMessagesLinks"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" messages: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" users: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" links: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" seq: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_messages_statedMessage: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_statedMessage"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" message: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" users: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_messages_statedMessageLink: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_statedMessageLink"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" message: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" chats: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" users: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" links: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 6: to.add(" seq: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - case mtpc_messages_sentMessage: if (stage) { to.add(",\n").addSpaces(lev); @@ -2298,8 +2257,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP switch (stage) { case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -2314,10 +2274,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP switch (stage) { case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 1: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 4: to.add(" links: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 5: to.add(" seq: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" links: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 6: to.add(" seq: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -2802,6 +2763,19 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_updateWebPage: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ updateWebPage"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" webpage: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_updates_state: if (stage) { to.add(",\n").addSpaces(lev); @@ -3056,14 +3030,15 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP case 4: to.add(" dc_options: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 5: to.add(" chat_size_max: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; case 6: to.add(" broadcast_size_max: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 7: to.add(" online_update_period_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 8: to.add(" offline_blur_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 9: to.add(" offline_idle_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 10: to.add(" online_cloud_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 11: to.add(" notify_cloud_delay_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 12: to.add(" notify_default_delay_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 13: to.add(" chat_big_size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 14: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 7: to.add(" forwarded_count_max: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 8: to.add(" online_update_period_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 9: to.add(" offline_blur_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 10: to.add(" offline_idle_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 11: to.add(" online_cloud_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 12: to.add(" notify_cloud_delay_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 13: to.add(" notify_default_delay_ms: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 14: to.add(" chat_big_size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 15: to.add(" disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -3836,34 +3811,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_account_noPassword: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ account_noPassword"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" new_salt: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - - case mtpc_account_password: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ account_password"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" current_salt: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" new_salt: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" hint: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - case mtpc_documentAttributeImageSize: if (stage) { to.add(",\n").addSpaces(lev); @@ -4031,6 +3978,162 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP to.add("{ contactLinkContact }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + case mtpc_webPageEmpty: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ webPageEmpty"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_webPagePending: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ webPagePending"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_webPage: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ webPage"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" display_url: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" title: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" description: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" photo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_authorization: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ authorization"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" flags: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" device_model: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" platform: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" system_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 5: to.add(" api_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 6: to.add(" app_name: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 7: to.add(" app_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 8: to.add(" date_created: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 9: to.add(" date_active: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 10: to.add(" ip: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 11: to.add(" country: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 12: to.add(" region: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_account_authorizations: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_authorizations"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" authorizations: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_account_noPassword: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_noPassword"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" new_salt: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" email_unconfirmed_pattern: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_account_password: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_password"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" current_salt: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" new_salt: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" hint: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" has_recovery: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" email_unconfirmed_pattern: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_account_passwordSettings: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_passwordSettings"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" email: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_account_passwordInputSettings: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_passwordInputSettings"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" new_salt: "); ++stages.back(); if (flag & MTPDaccount_passwordInputSettings::flag_new_salt) { types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 2: to.add(" new_password_hash: "); ++stages.back(); if (flag & MTPDaccount_passwordInputSettings::flag_new_password_hash) { types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 3: to.add(" hint: "); ++stages.back(); if (flag & MTPDaccount_passwordInputSettings::flag_hint) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; + case 4: to.add(" email: "); ++stages.back(); if (flag & MTPDaccount_passwordInputSettings::flag_email) { types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_auth_passwordRecovery: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_passwordRecovery"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" email_pattern: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_req_pq: if (stage) { to.add(",\n").addSpaces(lev); @@ -4481,22 +4584,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_account_setPassword: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ account_setPassword"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" current_password_hash: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" new_salt: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" new_password_hash: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 3: to.add(" hint: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - case mtpc_account_updateDeviceLocked: if (stage) { to.add(",\n").addSpaces(lev); @@ -4510,6 +4597,33 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_account_resetAuthorization: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_resetAuthorization"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_account_updatePasswordSettings: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_updatePasswordSettings"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" current_password_hash: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" new_settings: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_invokeAfterMsg: if (stage) { to.add(",\n").addSpaces(lev); @@ -4659,6 +4773,19 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_auth_recoverPassword: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ auth_recoverPassword"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" code: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_auth_exportAuthorization: if (stage) { to.add(",\n").addSpaces(lev); @@ -5022,6 +5149,21 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_messages_forwardMessages: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ messages_forwardMessages"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_int); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" random_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + case mtpc_messages_editChatTitle: if (stage) { to.add(",\n").addSpaces(lev); @@ -5108,21 +5250,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_messages_forwardMessages: - if (stage) { - to.add(",\n").addSpaces(lev); - } else { - to.add("{ messages_forwardMessages"); - to.add("\n").addSpaces(lev); - } - switch (stage) { - case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_int); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" random_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break; - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; - } - break; - case mtpc_messages_sendBroadcast: if (stage) { to.add(",\n").addSpaces(lev); @@ -5132,8 +5259,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } switch (stage) { case 0: to.add(" contacts: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 1: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; - case 2: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" random_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break; + case 2: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 3: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } break; @@ -5625,10 +5753,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; - case mtpc_account_getPassword: - to.add("{ account_getPassword }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); - break; - case mtpc_messages_getStickers: if (stage) { to.add(",\n").addSpaces(lev); @@ -5656,6 +5780,31 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP } break; + case mtpc_account_getAuthorizations: + to.add("{ account_getAuthorizations }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); + break; + + case mtpc_account_getPassword: + to.add("{ account_getPassword }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); + break; + + case mtpc_account_getPasswordSettings: + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ account_getPasswordSettings"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" current_password_hash: "); ++stages.back(); types.push_back(mtpc_bytes); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } + break; + + case mtpc_auth_requestPasswordRecovery: + to.add("{ auth_requestPasswordRecovery }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); + break; + case mtpc_rpc_result: if (stage) { to.add(",\n").addSpaces(lev); diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h index 7abcc1c2e..3f3fffed8 100644 --- a/Telegram/SourceFiles/mtproto/mtpScheme.h +++ b/Telegram/SourceFiles/mtproto/mtpScheme.h @@ -63,6 +63,8 @@ enum { mtpc_ping_delay_disconnect = 0xf3427b8c, mtpc_destroy_session = 0xe7512126, mtpc_register_saveDeveloperInfo = 0x9a5f6e95, + mtpc_error = 0xc4b9f9bb, + mtpc_null = 0x56730bcc, mtpc_inputPeerEmpty = 0x7f3b18ea, mtpc_inputPeerSelf = 0x7da07ec9, mtpc_inputPeerContact = 0x1023dbe8, @@ -191,9 +193,7 @@ enum { mtpc_messages_messages = 0x8c718e87, mtpc_messages_messagesSlice = 0xb446ae3, mtpc_messages_messageEmpty = 0x3f4e0648, - mtpc_messages_statedMessages = 0x7d84b48, - mtpc_messages_statedMessage = 0x96240c6a, - mtpc_messages_sentMessage = 0x900eac40, + mtpc_messages_sentMessage = 0x4c3d47f3, mtpc_messages_chats = 0x64ff9fd5, mtpc_messages_chatFull = 0xe5d7d19c, mtpc_messages_affectedHistory = 0xb45c69d1, @@ -232,14 +232,12 @@ enum { mtpc_photos_photo = 0x20212ca8, mtpc_upload_file = 0x96a18d5, mtpc_dcOption = 0x2ec2a43c, - mtpc_config = 0x3e6f732a, + mtpc_config = 0x68bac247, mtpc_nearestDc = 0x8e1a1775, mtpc_help_appUpdate = 0x8987f311, mtpc_help_noAppUpdate = 0xc45a6536, mtpc_help_inviteText = 0x18cb9f78, - mtpc_messages_statedMessagesLinks = 0x51be5d19, - mtpc_messages_statedMessageLink = 0x948a288, - mtpc_messages_sentMessageLink = 0xe923400d, + mtpc_messages_sentMessageLink = 0x35a1a663, mtpc_inputGeoChat = 0x74d456fa, mtpc_inputNotifyGeoChatPeer = 0x4d8ddec8, mtpc_geoChat = 0x75eaea5a, @@ -341,8 +339,6 @@ enum { mtpc_accountDaysTTL = 0xb8d0afdf, mtpc_account_sentChangePhoneCode = 0xa4f58c4c, mtpc_updateUserPhone = 0x12b9417b, - mtpc_account_noPassword = 0x5770e7a9, - mtpc_account_password = 0x739e5f72, mtpc_documentAttributeImageSize = 0x6c37c15c, mtpc_documentAttributeAnimated = 0x11b58939, mtpc_documentAttributeSticker = 0x994c9882, @@ -362,6 +358,18 @@ enum { mtpc_contactLinkNone = 0xfeedd3ad, mtpc_contactLinkHasPhone = 0x268f3f59, mtpc_contactLinkContact = 0xd502c2d0, + mtpc_updateWebPage = 0x2cc36971, + mtpc_webPageEmpty = 0xeb1477e8, + mtpc_webPagePending = 0xc586da1c, + mtpc_webPage = 0x39c1cef9, + mtpc_messageMediaWebPage = 0xa32dd600, + mtpc_authorization = 0x7bf2e6f6, + mtpc_account_authorizations = 0x1250abde, + mtpc_account_noPassword = 0x96dabc18, + mtpc_account_password = 0x7c18141c, + mtpc_account_passwordSettings = 0xb7b72ab3, + mtpc_account_passwordInputSettings = 0xbcfc532c, + mtpc_auth_passwordRecovery = 0x137948a5, mtpc_invokeAfterMsg = 0xcb9f372d, mtpc_invokeAfterMsgs = 0x3dc4b4f0, mtpc_auth_checkPhone = 0x6fe51dfb, @@ -406,15 +414,15 @@ enum { mtpc_messages_receivedMessages = 0x28abcb68, mtpc_messages_setTyping = 0xa3825e50, mtpc_messages_sendMessage = 0x1ca852a1, - mtpc_messages_sendMedia = 0xfcee7fc0, - mtpc_messages_forwardMessages = 0xded42045, + mtpc_messages_sendMedia = 0x33f6d58c, + mtpc_messages_forwardMessages = 0x55e1728d, mtpc_messages_getChats = 0x3c6aa187, mtpc_messages_getFullChat = 0x3b831c66, - mtpc_messages_editChatTitle = 0xb4bc68b5, - mtpc_messages_editChatPhoto = 0xd881821d, - mtpc_messages_addChatUser = 0x2ee9ee9e, - mtpc_messages_deleteChatUser = 0xc3c5cd23, - mtpc_messages_createChat = 0x419d9aee, + mtpc_messages_editChatTitle = 0xdc452855, + mtpc_messages_editChatPhoto = 0xca4c79d8, + mtpc_messages_addChatUser = 0xf9a0aa09, + mtpc_messages_deleteChatUser = 0xe0611f16, + mtpc_messages_createChat = 0x9cb126e, mtpc_updates_getState = 0xedd4882a, mtpc_updates_getDifference = 0xa041495, mtpc_photos_updateProfilePhoto = 0xeef579a0, @@ -428,8 +436,8 @@ enum { mtpc_help_saveAppLog = 0x6f02f748, mtpc_help_getInviteText = 0xa4a95186, mtpc_photos_getUserPhotos = 0xb7ee553c, - mtpc_messages_forwardMessage = 0x3f3f4f2, - mtpc_messages_sendBroadcast = 0x41bb0972, + mtpc_messages_forwardMessage = 0x33963bf9, + mtpc_messages_sendBroadcast = 0xbf73f4da, mtpc_geochats_getLocated = 0x7f192d8f, mtpc_geochats_getRecents = 0xe1427e6f, mtpc_geochats_checkin = 0x55b3e8fb, @@ -469,12 +477,17 @@ enum { mtpc_contacts_resolveUsername = 0xbf0131c, mtpc_account_sendChangePhoneCode = 0xa407a8f4, mtpc_account_changePhone = 0x70c32edb, - mtpc_account_getPassword = 0x548a30f5, - mtpc_account_setPassword = 0xdd2a4d8f, - mtpc_auth_checkPassword = 0xa63011e, mtpc_messages_getStickers = 0xae22e045, mtpc_messages_getAllStickers = 0xaa3bc868, - mtpc_account_updateDeviceLocked = 0x38df3532 + mtpc_account_updateDeviceLocked = 0x38df3532, + mtpc_account_getAuthorizations = 0xe320c158, + mtpc_account_resetAuthorization = 0xdf77f3bc, + mtpc_account_getPassword = 0x548a30f5, + mtpc_account_getPasswordSettings = 0xbc8d11bb, + mtpc_account_updatePasswordSettings = 0xfa7c4b86, + mtpc_auth_checkPassword = 0xa63011e, + mtpc_auth_requestPasswordRecovery = 0xd897bc66, + mtpc_auth_recoverPassword = 0x4ea56e92 }; // Type forward declarations @@ -547,6 +560,11 @@ class MTPDnew_session_created; class MTPhttpWait; class MTPDhttp_wait; +class MTPerror; +class MTPDerror; + +class MTPnull; + class MTPinputPeer; class MTPDinputPeerContact; class MTPDinputPeerForeign; @@ -659,6 +677,7 @@ class MTPDmessageMediaGeo; class MTPDmessageMediaContact; class MTPDmessageMediaDocument; class MTPDmessageMediaAudio; +class MTPDmessageMediaWebPage; class MTPmessageAction; class MTPDmessageActionChatCreate; @@ -765,14 +784,6 @@ class MTPDmessages_messagesSlice; class MTPmessages_message; -class MTPmessages_statedMessages; -class MTPDmessages_statedMessages; -class MTPDmessages_statedMessagesLinks; - -class MTPmessages_statedMessage; -class MTPDmessages_statedMessage; -class MTPDmessages_statedMessageLink; - class MTPmessages_sentMessage; class MTPDmessages_sentMessage; class MTPDmessages_sentMessageLink; @@ -817,6 +828,7 @@ class MTPDupdatePrivacy; class MTPDupdateUserPhone; class MTPDupdateReadHistoryInbox; class MTPDupdateReadHistoryOutbox; +class MTPDupdateWebPage; class MTPupdates_state; class MTPDupdates_state; @@ -955,10 +967,6 @@ class MTPDaccountDaysTTL; class MTPaccount_sentChangePhoneCode; class MTPDaccount_sentChangePhoneCode; -class MTPaccount_password; -class MTPDaccount_noPassword; -class MTPDaccount_password; - class MTPdocumentAttribute; class MTPDdocumentAttributeImageSize; class MTPDdocumentAttributeSticker; @@ -983,6 +991,30 @@ class MTPDmessages_affectedMessages; class MTPcontactLink; +class MTPwebPage; +class MTPDwebPageEmpty; +class MTPDwebPagePending; +class MTPDwebPage; + +class MTPauthorization; +class MTPDauthorization; + +class MTPaccount_authorizations; +class MTPDaccount_authorizations; + +class MTPaccount_password; +class MTPDaccount_noPassword; +class MTPDaccount_password; + +class MTPaccount_passwordSettings; +class MTPDaccount_passwordSettings; + +class MTPaccount_passwordInputSettings; +class MTPDaccount_passwordInputSettings; + +class MTPauth_passwordRecovery; +class MTPDauth_passwordRecovery; + // Boxed types definitions typedef MTPBoxed MTPResPQ; @@ -1006,6 +1038,8 @@ typedef MTPBoxed MTPPong; typedef MTPBoxed MTPDestroySessionRes; typedef MTPBoxed MTPNewSession; typedef MTPBoxed MTPHttpWait; +typedef MTPBoxed MTPError; +typedef MTPBoxed MTPNull; typedef MTPBoxed MTPInputPeer; typedef MTPBoxed MTPInputUser; typedef MTPBoxed MTPInputContact; @@ -1062,8 +1096,6 @@ typedef MTPBoxed MTPcontacts_Suggested; typedef MTPBoxed MTPmessages_Dialogs; typedef MTPBoxed MTPmessages_Messages; typedef MTPBoxed MTPmessages_Message; -typedef MTPBoxed MTPmessages_StatedMessages; -typedef MTPBoxed MTPmessages_StatedMessage; typedef MTPBoxed MTPmessages_SentMessage; typedef MTPBoxed MTPmessages_Chats; typedef MTPBoxed MTPmessages_ChatFull; @@ -1109,7 +1141,6 @@ typedef MTPBoxed MTPPrivacyRule; typedef MTPBoxed MTPaccount_PrivacyRules; typedef MTPBoxed MTPAccountDaysTTL; typedef MTPBoxed MTPaccount_SentChangePhoneCode; -typedef MTPBoxed MTPaccount_Password; typedef MTPBoxed MTPDocumentAttribute; typedef MTPBoxed MTPmessages_Stickers; typedef MTPBoxed MTPStickerPack; @@ -1117,6 +1148,13 @@ typedef MTPBoxed MTPmessages_AllStickers; typedef MTPBoxed MTPDisabledFeature; typedef MTPBoxed MTPmessages_AffectedMessages; typedef MTPBoxed MTPContactLink; +typedef MTPBoxed MTPWebPage; +typedef MTPBoxed MTPAuthorization; +typedef MTPBoxed MTPaccount_Authorizations; +typedef MTPBoxed MTPaccount_Password; +typedef MTPBoxed MTPaccount_PasswordSettings; +typedef MTPBoxed MTPaccount_PasswordInputSettings; +typedef MTPBoxed MTPauth_PasswordRecovery; // Type classes definitions @@ -1893,6 +1931,58 @@ private: }; typedef MTPBoxed MTPHttpWait; +class MTPerror : private mtpDataOwner { +public: + MTPerror(); + MTPerror(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_error) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDerror &_error() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDerror*)data; + } + const MTPDerror &c_error() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDerror*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_error); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPerror(MTPDerror *_data); + + friend MTPerror MTP_error(MTPint _code, const MTPstring &_text); +}; +typedef MTPBoxed MTPError; + +class MTPnull { +public: + MTPnull() { + } + MTPnull(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_null) { + read(from, end, cons); + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_null); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + + friend MTPnull MTP_null(); +}; +typedef MTPBoxed MTPNull; + class MTPinputPeer : private mtpDataOwner { public: MTPinputPeer() : mtpDataOwner(0), _type(0) { @@ -3325,6 +3415,18 @@ public: return *(const MTPDmessageMediaAudio*)data; } + MTPDmessageMediaWebPage &_messageMediaWebPage() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messageMediaWebPage) throw mtpErrorWrongTypeId(_type, mtpc_messageMediaWebPage); + split(); + return *(MTPDmessageMediaWebPage*)data; + } + const MTPDmessageMediaWebPage &c_messageMediaWebPage() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_messageMediaWebPage) throw mtpErrorWrongTypeId(_type, mtpc_messageMediaWebPage); + return *(const MTPDmessageMediaWebPage*)data; + } + uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -3340,6 +3442,7 @@ private: explicit MTPmessageMedia(MTPDmessageMediaContact *_data); explicit MTPmessageMedia(MTPDmessageMediaDocument *_data); explicit MTPmessageMedia(MTPDmessageMediaAudio *_data); + explicit MTPmessageMedia(MTPDmessageMediaWebPage *_data); friend MTPmessageMedia MTP_messageMediaEmpty(); friend MTPmessageMedia MTP_messageMediaPhoto(const MTPPhoto &_photo); @@ -3349,6 +3452,7 @@ private: friend MTPmessageMedia MTP_messageMediaUnsupported(); friend MTPmessageMedia MTP_messageMediaDocument(const MTPDocument &_document); friend MTPmessageMedia MTP_messageMediaAudio(const MTPAudio &_audio); + friend MTPmessageMedia MTP_messageMediaWebPage(const MTPWebPage &_webpage); mtpTypeId _type; }; @@ -4590,108 +4694,6 @@ private: }; typedef MTPBoxed MTPmessages_Message; -class MTPmessages_statedMessages : private mtpDataOwner { -public: - MTPmessages_statedMessages() : mtpDataOwner(0), _type(0) { - } - MTPmessages_statedMessages(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { - read(from, end, cons); - } - - MTPDmessages_statedMessages &_messages_statedMessages() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessages) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessages); - split(); - return *(MTPDmessages_statedMessages*)data; - } - const MTPDmessages_statedMessages &c_messages_statedMessages() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessages) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessages); - return *(const MTPDmessages_statedMessages*)data; - } - - MTPDmessages_statedMessagesLinks &_messages_statedMessagesLinks() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessagesLinks) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessagesLinks); - split(); - return *(MTPDmessages_statedMessagesLinks*)data; - } - const MTPDmessages_statedMessagesLinks &c_messages_statedMessagesLinks() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessagesLinks) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessagesLinks); - return *(const MTPDmessages_statedMessagesLinks*)data; - } - - uint32 innerLength() const; - mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); - void write(mtpBuffer &to) const; - - typedef void ResponseType; - -private: - explicit MTPmessages_statedMessages(mtpTypeId type); - explicit MTPmessages_statedMessages(MTPDmessages_statedMessages *_data); - explicit MTPmessages_statedMessages(MTPDmessages_statedMessagesLinks *_data); - - friend MTPmessages_statedMessages MTP_messages_statedMessages(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count); - friend MTPmessages_statedMessages MTP_messages_statedMessagesLinks(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq); - - mtpTypeId _type; -}; -typedef MTPBoxed MTPmessages_StatedMessages; - -class MTPmessages_statedMessage : private mtpDataOwner { -public: - MTPmessages_statedMessage() : mtpDataOwner(0), _type(0) { - } - MTPmessages_statedMessage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { - read(from, end, cons); - } - - MTPDmessages_statedMessage &_messages_statedMessage() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessage) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessage); - split(); - return *(MTPDmessages_statedMessage*)data; - } - const MTPDmessages_statedMessage &c_messages_statedMessage() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessage) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessage); - return *(const MTPDmessages_statedMessage*)data; - } - - MTPDmessages_statedMessageLink &_messages_statedMessageLink() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessageLink) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessageLink); - split(); - return *(MTPDmessages_statedMessageLink*)data; - } - const MTPDmessages_statedMessageLink &c_messages_statedMessageLink() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_messages_statedMessageLink) throw mtpErrorWrongTypeId(_type, mtpc_messages_statedMessageLink); - return *(const MTPDmessages_statedMessageLink*)data; - } - - uint32 innerLength() const; - mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); - void write(mtpBuffer &to) const; - - typedef void ResponseType; - -private: - explicit MTPmessages_statedMessage(mtpTypeId type); - explicit MTPmessages_statedMessage(MTPDmessages_statedMessage *_data); - explicit MTPmessages_statedMessage(MTPDmessages_statedMessageLink *_data); - - friend MTPmessages_statedMessage MTP_messages_statedMessage(const MTPMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count); - friend MTPmessages_statedMessage MTP_messages_statedMessageLink(const MTPMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq); - - mtpTypeId _type; -}; -typedef MTPBoxed MTPmessages_StatedMessage; - class MTPmessages_sentMessage : private mtpDataOwner { public: MTPmessages_sentMessage() : mtpDataOwner(0), _type(0) { @@ -4736,8 +4738,8 @@ private: explicit MTPmessages_sentMessage(MTPDmessages_sentMessage *_data); explicit MTPmessages_sentMessage(MTPDmessages_sentMessageLink *_data); - friend MTPmessages_sentMessage MTP_messages_sentMessage(MTPint _id, MTPint _date, MTPint _pts, MTPint _pts_count); - friend MTPmessages_sentMessage MTP_messages_sentMessageLink(MTPint _id, MTPint _date, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq); + friend MTPmessages_sentMessage MTP_messages_sentMessage(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count); + friend MTPmessages_sentMessage MTP_messages_sentMessageLink(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq); mtpTypeId _type; }; @@ -5210,6 +5212,18 @@ public: return *(const MTPDupdateReadHistoryOutbox*)data; } + MTPDupdateWebPage &_updateWebPage() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateWebPage) throw mtpErrorWrongTypeId(_type, mtpc_updateWebPage); + split(); + return *(MTPDupdateWebPage*)data; + } + const MTPDupdateWebPage &c_updateWebPage() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_updateWebPage) throw mtpErrorWrongTypeId(_type, mtpc_updateWebPage); + return *(const MTPDupdateWebPage*)data; + } + uint32 innerLength() const; mtpTypeId type() const; void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); @@ -5247,6 +5261,7 @@ private: explicit MTPupdate(MTPDupdateUserPhone *_data); explicit MTPupdate(MTPDupdateReadHistoryInbox *_data); explicit MTPupdate(MTPDupdateReadHistoryOutbox *_data); + explicit MTPupdate(MTPDupdateWebPage *_data); friend MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count); friend MTPupdate MTP_updateMessageID(MTPint _id, const MTPlong &_random_id); @@ -5276,6 +5291,7 @@ private: friend MTPupdate MTP_updateUserPhone(MTPint _user_id, const MTPstring &_phone); friend MTPupdate MTP_updateReadHistoryInbox(const MTPPeer &_peer, MTPint _max_id, MTPint _pts, MTPint _pts_count); friend MTPupdate MTP_updateReadHistoryOutbox(const MTPPeer &_peer, MTPint _max_id, MTPint _pts, MTPint _pts_count); + friend MTPupdate MTP_updateWebPage(const MTPWebPage &_webpage); mtpTypeId _type; }; @@ -5642,7 +5658,7 @@ public: private: explicit MTPconfig(MTPDconfig *_data); - friend MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _broadcast_size_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, const MTPVector &_disabled_features); + friend MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _broadcast_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, const MTPVector &_disabled_features); }; typedef MTPBoxed MTPConfig; @@ -6925,57 +6941,6 @@ private: }; typedef MTPBoxed MTPaccount_SentChangePhoneCode; -class MTPaccount_password : private mtpDataOwner { -public: - MTPaccount_password() : mtpDataOwner(0), _type(0) { - } - MTPaccount_password(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { - read(from, end, cons); - } - - MTPDaccount_noPassword &_account_noPassword() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_account_noPassword) throw mtpErrorWrongTypeId(_type, mtpc_account_noPassword); - split(); - return *(MTPDaccount_noPassword*)data; - } - const MTPDaccount_noPassword &c_account_noPassword() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_account_noPassword) throw mtpErrorWrongTypeId(_type, mtpc_account_noPassword); - return *(const MTPDaccount_noPassword*)data; - } - - MTPDaccount_password &_account_password() { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_account_password) throw mtpErrorWrongTypeId(_type, mtpc_account_password); - split(); - return *(MTPDaccount_password*)data; - } - const MTPDaccount_password &c_account_password() const { - if (!data) throw mtpErrorUninitialized(); - if (_type != mtpc_account_password) throw mtpErrorWrongTypeId(_type, mtpc_account_password); - return *(const MTPDaccount_password*)data; - } - - uint32 innerLength() const; - mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); - void write(mtpBuffer &to) const; - - typedef void ResponseType; - -private: - explicit MTPaccount_password(mtpTypeId type); - explicit MTPaccount_password(MTPDaccount_noPassword *_data); - explicit MTPaccount_password(MTPDaccount_password *_data); - - friend MTPaccount_password MTP_account_noPassword(const MTPbytes &_new_salt); - friend MTPaccount_password MTP_account_password(const MTPbytes &_current_salt, const MTPbytes &_new_salt, const MTPstring &_hint); - - mtpTypeId _type; -}; -typedef MTPBoxed MTPaccount_Password; - class MTPdocumentAttribute : private mtpDataOwner { public: MTPdocumentAttribute() : mtpDataOwner(0), _type(0) { @@ -7266,6 +7231,277 @@ private: }; typedef MTPBoxed MTPContactLink; +class MTPwebPage : private mtpDataOwner { +public: + MTPwebPage() : mtpDataOwner(0), _type(0) { + } + MTPwebPage(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDwebPageEmpty &_webPageEmpty() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_webPageEmpty) throw mtpErrorWrongTypeId(_type, mtpc_webPageEmpty); + split(); + return *(MTPDwebPageEmpty*)data; + } + const MTPDwebPageEmpty &c_webPageEmpty() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_webPageEmpty) throw mtpErrorWrongTypeId(_type, mtpc_webPageEmpty); + return *(const MTPDwebPageEmpty*)data; + } + + MTPDwebPagePending &_webPagePending() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_webPagePending) throw mtpErrorWrongTypeId(_type, mtpc_webPagePending); + split(); + return *(MTPDwebPagePending*)data; + } + const MTPDwebPagePending &c_webPagePending() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_webPagePending) throw mtpErrorWrongTypeId(_type, mtpc_webPagePending); + return *(const MTPDwebPagePending*)data; + } + + MTPDwebPage &_webPage() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_webPage) throw mtpErrorWrongTypeId(_type, mtpc_webPage); + split(); + return *(MTPDwebPage*)data; + } + const MTPDwebPage &c_webPage() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_webPage) throw mtpErrorWrongTypeId(_type, mtpc_webPage); + return *(const MTPDwebPage*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPwebPage(mtpTypeId type); + explicit MTPwebPage(MTPDwebPageEmpty *_data); + explicit MTPwebPage(MTPDwebPagePending *_data); + explicit MTPwebPage(MTPDwebPage *_data); + + friend MTPwebPage MTP_webPageEmpty(const MTPlong &_id); + friend MTPwebPage MTP_webPagePending(const MTPlong &_id, MTPint _date); + friend MTPwebPage MTP_webPage(const MTPlong &_id, const MTPstring &_display_url, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo); + + mtpTypeId _type; +}; +typedef MTPBoxed MTPWebPage; + +class MTPauthorization : private mtpDataOwner { +public: + MTPauthorization(); + MTPauthorization(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_authorization) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDauthorization &_authorization() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDauthorization*)data; + } + const MTPDauthorization &c_authorization() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDauthorization*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_authorization); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPauthorization(MTPDauthorization *_data); + + friend MTPauthorization MTP_authorization(const MTPlong &_hash, MTPint _flags, const MTPstring &_device_model, const MTPstring &_platform, const MTPstring &_system_version, MTPint _api_id, const MTPstring &_app_name, const MTPstring &_app_version, MTPint _date_created, MTPint _date_active, const MTPstring &_ip, const MTPstring &_country, const MTPstring &_region); +}; +typedef MTPBoxed MTPAuthorization; + +class MTPaccount_authorizations : private mtpDataOwner { +public: + MTPaccount_authorizations(); + MTPaccount_authorizations(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_authorizations) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDaccount_authorizations &_account_authorizations() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDaccount_authorizations*)data; + } + const MTPDaccount_authorizations &c_account_authorizations() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDaccount_authorizations*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_authorizations); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPaccount_authorizations(MTPDaccount_authorizations *_data); + + friend MTPaccount_authorizations MTP_account_authorizations(const MTPVector &_authorizations); +}; +typedef MTPBoxed MTPaccount_Authorizations; + +class MTPaccount_password : private mtpDataOwner { +public: + MTPaccount_password() : mtpDataOwner(0), _type(0) { + } + MTPaccount_password(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { + read(from, end, cons); + } + + MTPDaccount_noPassword &_account_noPassword() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_account_noPassword) throw mtpErrorWrongTypeId(_type, mtpc_account_noPassword); + split(); + return *(MTPDaccount_noPassword*)data; + } + const MTPDaccount_noPassword &c_account_noPassword() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_account_noPassword) throw mtpErrorWrongTypeId(_type, mtpc_account_noPassword); + return *(const MTPDaccount_noPassword*)data; + } + + MTPDaccount_password &_account_password() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_account_password) throw mtpErrorWrongTypeId(_type, mtpc_account_password); + split(); + return *(MTPDaccount_password*)data; + } + const MTPDaccount_password &c_account_password() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_account_password) throw mtpErrorWrongTypeId(_type, mtpc_account_password); + return *(const MTPDaccount_password*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPaccount_password(mtpTypeId type); + explicit MTPaccount_password(MTPDaccount_noPassword *_data); + explicit MTPaccount_password(MTPDaccount_password *_data); + + friend MTPaccount_password MTP_account_noPassword(const MTPbytes &_new_salt, const MTPstring &_email_unconfirmed_pattern); + friend MTPaccount_password MTP_account_password(const MTPbytes &_current_salt, const MTPbytes &_new_salt, const MTPstring &_hint, MTPBool _has_recovery, const MTPstring &_email_unconfirmed_pattern); + + mtpTypeId _type; +}; +typedef MTPBoxed MTPaccount_Password; + +class MTPaccount_passwordSettings : private mtpDataOwner { +public: + MTPaccount_passwordSettings(); + MTPaccount_passwordSettings(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_passwordSettings) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDaccount_passwordSettings &_account_passwordSettings() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDaccount_passwordSettings*)data; + } + const MTPDaccount_passwordSettings &c_account_passwordSettings() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDaccount_passwordSettings*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_passwordSettings); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPaccount_passwordSettings(MTPDaccount_passwordSettings *_data); + + friend MTPaccount_passwordSettings MTP_account_passwordSettings(const MTPstring &_email); +}; +typedef MTPBoxed MTPaccount_PasswordSettings; + +class MTPaccount_passwordInputSettings : private mtpDataOwner { +public: + MTPaccount_passwordInputSettings(); + MTPaccount_passwordInputSettings(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_passwordInputSettings) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDaccount_passwordInputSettings &_account_passwordInputSettings() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDaccount_passwordInputSettings*)data; + } + const MTPDaccount_passwordInputSettings &c_account_passwordInputSettings() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDaccount_passwordInputSettings*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_passwordInputSettings); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPaccount_passwordInputSettings(MTPDaccount_passwordInputSettings *_data); + + friend MTPaccount_passwordInputSettings MTP_account_passwordInputSettings(MTPint _flags, const MTPbytes &_new_salt, const MTPbytes &_new_password_hash, const MTPstring &_hint, const MTPstring &_email); +}; +typedef MTPBoxed MTPaccount_PasswordInputSettings; + +class MTPauth_passwordRecovery : private mtpDataOwner { +public: + MTPauth_passwordRecovery(); + MTPauth_passwordRecovery(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_passwordRecovery) : mtpDataOwner(0) { + read(from, end, cons); + } + + MTPDauth_passwordRecovery &_auth_passwordRecovery() { + if (!data) throw mtpErrorUninitialized(); + split(); + return *(MTPDauth_passwordRecovery*)data; + } + const MTPDauth_passwordRecovery &c_auth_passwordRecovery() const { + if (!data) throw mtpErrorUninitialized(); + return *(const MTPDauth_passwordRecovery*)data; + } + + uint32 innerLength() const; + mtpTypeId type() const; + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_passwordRecovery); + void write(mtpBuffer &to) const; + + typedef void ResponseType; + +private: + explicit MTPauth_passwordRecovery(MTPDauth_passwordRecovery *_data); + + friend MTPauth_passwordRecovery MTP_auth_passwordRecovery(const MTPstring &_email_pattern); +}; +typedef MTPBoxed MTPauth_PasswordRecovery; + // Type constructors with data class MTPDresPQ : public mtpDataImpl { @@ -7588,6 +7824,17 @@ public: MTPint vmax_wait; }; +class MTPDerror : public mtpDataImpl { +public: + MTPDerror() { + } + MTPDerror(MTPint _code, const MTPstring &_text) : vcode(_code), vtext(_text) { + } + + MTPint vcode; + MTPstring vtext; +}; + class MTPDinputPeerContact : public mtpDataImpl { public: MTPDinputPeerContact() { @@ -8264,14 +8511,14 @@ public: MTPMessageMedia vmedia; enum { - flag_fwd_from_id = (1 << 2), - flag_fwd_date = (1 << 2), flag_reply_to_msg_id = (1 << 3), + flag_fwd_date = (1 << 2), + flag_fwd_from_id = (1 << 2), }; - bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } - bool has_fwd_date() const { return vflags.v & flag_fwd_date; } bool has_reply_to_msg_id() const { return vflags.v & flag_reply_to_msg_id; } + bool has_fwd_date() const { return vflags.v & flag_fwd_date; } + bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } }; class MTPDmessageService : public mtpDataImpl { @@ -8352,6 +8599,16 @@ public: MTPAudio vaudio; }; +class MTPDmessageMediaWebPage : public mtpDataImpl { +public: + MTPDmessageMediaWebPage() { + } + MTPDmessageMediaWebPage(const MTPWebPage &_webpage) : vwebpage(_webpage) { + } + + MTPWebPage vwebpage; +}; + class MTPDmessageActionChatCreate : public mtpDataImpl { public: MTPDmessageActionChatCreate() { @@ -8867,75 +9124,16 @@ public: MTPVector vusers; }; -class MTPDmessages_statedMessages : public mtpDataImpl { -public: - MTPDmessages_statedMessages() { - } - MTPDmessages_statedMessages(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count) : vmessages(_messages), vchats(_chats), vusers(_users), vpts(_pts), vpts_count(_pts_count) { - } - - MTPVector vmessages; - MTPVector vchats; - MTPVector vusers; - MTPint vpts; - MTPint vpts_count; -}; - -class MTPDmessages_statedMessagesLinks : public mtpDataImpl { -public: - MTPDmessages_statedMessagesLinks() { - } - MTPDmessages_statedMessagesLinks(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) : vmessages(_messages), vchats(_chats), vusers(_users), vpts(_pts), vpts_count(_pts_count), vlinks(_links), vseq(_seq) { - } - - MTPVector vmessages; - MTPVector vchats; - MTPVector vusers; - MTPint vpts; - MTPint vpts_count; - MTPVector vlinks; - MTPint vseq; -}; - -class MTPDmessages_statedMessage : public mtpDataImpl { -public: - MTPDmessages_statedMessage() { - } - MTPDmessages_statedMessage(const MTPMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count) : vmessage(_message), vchats(_chats), vusers(_users), vpts(_pts), vpts_count(_pts_count) { - } - - MTPMessage vmessage; - MTPVector vchats; - MTPVector vusers; - MTPint vpts; - MTPint vpts_count; -}; - -class MTPDmessages_statedMessageLink : public mtpDataImpl { -public: - MTPDmessages_statedMessageLink() { - } - MTPDmessages_statedMessageLink(const MTPMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) : vmessage(_message), vchats(_chats), vusers(_users), vpts(_pts), vpts_count(_pts_count), vlinks(_links), vseq(_seq) { - } - - MTPMessage vmessage; - MTPVector vchats; - MTPVector vusers; - MTPint vpts; - MTPint vpts_count; - MTPVector vlinks; - MTPint vseq; -}; - class MTPDmessages_sentMessage : public mtpDataImpl { public: MTPDmessages_sentMessage() { } - MTPDmessages_sentMessage(MTPint _id, MTPint _date, MTPint _pts, MTPint _pts_count) : vid(_id), vdate(_date), vpts(_pts), vpts_count(_pts_count) { + MTPDmessages_sentMessage(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count) : vid(_id), vdate(_date), vmedia(_media), vpts(_pts), vpts_count(_pts_count) { } MTPint vid; MTPint vdate; + MTPMessageMedia vmedia; MTPint vpts; MTPint vpts_count; }; @@ -8944,11 +9142,12 @@ class MTPDmessages_sentMessageLink : public mtpDataImpl &_links, MTPint _seq) : vid(_id), vdate(_date), vpts(_pts), vpts_count(_pts_count), vlinks(_links), vseq(_seq) { + MTPDmessages_sentMessageLink(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) : vid(_id), vdate(_date), vmedia(_media), vpts(_pts), vpts_count(_pts_count), vlinks(_links), vseq(_seq) { } MTPint vid; MTPint vdate; + MTPMessageMedia vmedia; MTPint vpts; MTPint vpts_count; MTPVector vlinks; @@ -9314,6 +9513,16 @@ public: MTPint vpts_count; }; +class MTPDupdateWebPage : public mtpDataImpl { +public: + MTPDupdateWebPage() { + } + MTPDupdateWebPage(const MTPWebPage &_webpage) : vwebpage(_webpage) { + } + + MTPWebPage vwebpage; +}; + class MTPDupdates_state : public mtpDataImpl { public: MTPDupdates_state() { @@ -9388,14 +9597,14 @@ public: MTPint vreply_to_msg_id; enum { - flag_fwd_from_id = (1 << 2), - flag_fwd_date = (1 << 2), flag_reply_to_msg_id = (1 << 3), + flag_fwd_date = (1 << 2), + flag_fwd_from_id = (1 << 2), }; - bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } - bool has_fwd_date() const { return vflags.v & flag_fwd_date; } bool has_reply_to_msg_id() const { return vflags.v & flag_reply_to_msg_id; } + bool has_fwd_date() const { return vflags.v & flag_fwd_date; } + bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } }; class MTPDupdateShortChatMessage : public mtpDataImpl { @@ -9418,14 +9627,14 @@ public: MTPint vreply_to_msg_id; enum { - flag_fwd_from_id = (1 << 2), - flag_fwd_date = (1 << 2), flag_reply_to_msg_id = (1 << 3), + flag_fwd_date = (1 << 2), + flag_fwd_from_id = (1 << 2), }; - bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } - bool has_fwd_date() const { return vflags.v & flag_fwd_date; } bool has_reply_to_msg_id() const { return vflags.v & flag_reply_to_msg_id; } + bool has_fwd_date() const { return vflags.v & flag_fwd_date; } + bool has_fwd_from_id() const { return vflags.v & flag_fwd_from_id; } }; class MTPDupdateShort : public mtpDataImpl { @@ -9531,7 +9740,7 @@ class MTPDconfig : public mtpDataImpl { public: MTPDconfig() { } - MTPDconfig(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _broadcast_size_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, const MTPVector &_disabled_features) : vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vbroadcast_size_max(_broadcast_size_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vdisabled_features(_disabled_features) { + MTPDconfig(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _broadcast_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, const MTPVector &_disabled_features) : vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vbroadcast_size_max(_broadcast_size_max), vforwarded_count_max(_forwarded_count_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vdisabled_features(_disabled_features) { } MTPint vdate; @@ -9541,6 +9750,7 @@ public: MTPVector vdc_options; MTPint vchat_size_max; MTPint vbroadcast_size_max; + MTPint vforwarded_count_max; MTPint vonline_update_period_ms; MTPint voffline_blur_timeout_ms; MTPint voffline_idle_timeout_ms; @@ -10075,28 +10285,6 @@ public: MTPint vsend_call_timeout; }; -class MTPDaccount_noPassword : public mtpDataImpl { -public: - MTPDaccount_noPassword() { - } - MTPDaccount_noPassword(const MTPbytes &_new_salt) : vnew_salt(_new_salt) { - } - - MTPbytes vnew_salt; -}; - -class MTPDaccount_password : public mtpDataImpl { -public: - MTPDaccount_password() { - } - MTPDaccount_password(const MTPbytes &_current_salt, const MTPbytes &_new_salt, const MTPstring &_hint) : vcurrent_salt(_current_salt), vnew_salt(_new_salt), vhint(_hint) { - } - - MTPbytes vcurrent_salt; - MTPbytes vnew_salt; - MTPstring vhint; -}; - class MTPDdocumentAttributeImageSize : public mtpDataImpl { public: MTPDdocumentAttributeImageSize() { @@ -10206,6 +10394,144 @@ public: MTPint vpts_count; }; +class MTPDwebPageEmpty : public mtpDataImpl { +public: + MTPDwebPageEmpty() { + } + MTPDwebPageEmpty(const MTPlong &_id) : vid(_id) { + } + + MTPlong vid; +}; + +class MTPDwebPagePending : public mtpDataImpl { +public: + MTPDwebPagePending() { + } + MTPDwebPagePending(const MTPlong &_id, MTPint _date) : vid(_id), vdate(_date) { + } + + MTPlong vid; + MTPint vdate; +}; + +class MTPDwebPage : public mtpDataImpl { +public: + MTPDwebPage() { + } + MTPDwebPage(const MTPlong &_id, const MTPstring &_display_url, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo) : vid(_id), vdisplay_url(_display_url), vtitle(_title), vdescription(_description), vphoto(_photo) { + } + + MTPlong vid; + MTPstring vdisplay_url; + MTPstring vtitle; + MTPstring vdescription; + MTPPhoto vphoto; +}; + +class MTPDauthorization : public mtpDataImpl { +public: + MTPDauthorization() { + } + MTPDauthorization(const MTPlong &_hash, MTPint _flags, const MTPstring &_device_model, const MTPstring &_platform, const MTPstring &_system_version, MTPint _api_id, const MTPstring &_app_name, const MTPstring &_app_version, MTPint _date_created, MTPint _date_active, const MTPstring &_ip, const MTPstring &_country, const MTPstring &_region) : vhash(_hash), vflags(_flags), vdevice_model(_device_model), vplatform(_platform), vsystem_version(_system_version), vapi_id(_api_id), vapp_name(_app_name), vapp_version(_app_version), vdate_created(_date_created), vdate_active(_date_active), vip(_ip), vcountry(_country), vregion(_region) { + } + + MTPlong vhash; + MTPint vflags; + MTPstring vdevice_model; + MTPstring vplatform; + MTPstring vsystem_version; + MTPint vapi_id; + MTPstring vapp_name; + MTPstring vapp_version; + MTPint vdate_created; + MTPint vdate_active; + MTPstring vip; + MTPstring vcountry; + MTPstring vregion; +}; + +class MTPDaccount_authorizations : public mtpDataImpl { +public: + MTPDaccount_authorizations() { + } + MTPDaccount_authorizations(const MTPVector &_authorizations) : vauthorizations(_authorizations) { + } + + MTPVector vauthorizations; +}; + +class MTPDaccount_noPassword : public mtpDataImpl { +public: + MTPDaccount_noPassword() { + } + MTPDaccount_noPassword(const MTPbytes &_new_salt, const MTPstring &_email_unconfirmed_pattern) : vnew_salt(_new_salt), vemail_unconfirmed_pattern(_email_unconfirmed_pattern) { + } + + MTPbytes vnew_salt; + MTPstring vemail_unconfirmed_pattern; +}; + +class MTPDaccount_password : public mtpDataImpl { +public: + MTPDaccount_password() { + } + MTPDaccount_password(const MTPbytes &_current_salt, const MTPbytes &_new_salt, const MTPstring &_hint, MTPBool _has_recovery, const MTPstring &_email_unconfirmed_pattern) : vcurrent_salt(_current_salt), vnew_salt(_new_salt), vhint(_hint), vhas_recovery(_has_recovery), vemail_unconfirmed_pattern(_email_unconfirmed_pattern) { + } + + MTPbytes vcurrent_salt; + MTPbytes vnew_salt; + MTPstring vhint; + MTPBool vhas_recovery; + MTPstring vemail_unconfirmed_pattern; +}; + +class MTPDaccount_passwordSettings : public mtpDataImpl { +public: + MTPDaccount_passwordSettings() { + } + MTPDaccount_passwordSettings(const MTPstring &_email) : vemail(_email) { + } + + MTPstring vemail; +}; + +class MTPDaccount_passwordInputSettings : public mtpDataImpl { +public: + MTPDaccount_passwordInputSettings() { + } + MTPDaccount_passwordInputSettings(MTPint _flags, const MTPbytes &_new_salt, const MTPbytes &_new_password_hash, const MTPstring &_hint, const MTPstring &_email) : vflags(_flags), vnew_salt(_new_salt), vnew_password_hash(_new_password_hash), vhint(_hint), vemail(_email) { + } + + MTPint vflags; + MTPbytes vnew_salt; + MTPbytes vnew_password_hash; + MTPstring vhint; + MTPstring vemail; + + enum { + flag_new_salt = (1 << 0), + flag_new_password_hash = (1 << 0), + flag_email = (1 << 1), + flag_hint = (1 << 0), + }; + + bool has_new_salt() const { return vflags.v & flag_new_salt; } + bool has_new_password_hash() const { return vflags.v & flag_new_password_hash; } + bool has_email() const { return vflags.v & flag_email; } + bool has_hint() const { return vflags.v & flag_hint; } +}; + +class MTPDauth_passwordRecovery : public mtpDataImpl { +public: + MTPDauth_passwordRecovery() { + } + MTPDauth_passwordRecovery(const MTPstring &_email_pattern) : vemail_pattern(_email_pattern) { + } + + MTPstring vemail_pattern; +}; + // RPC methods class MTPreq_pq { // RPC method 'req_pq' @@ -12441,7 +12767,7 @@ public: vrandom_id.write(to); } - typedef MTPmessages_StatedMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_SendMedia : public MTPBoxed { public: @@ -12486,7 +12812,7 @@ public: vrandom_id.write(to); } - typedef MTPmessages_StatedMessages ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_ForwardMessages : public MTPBoxed { public: @@ -12606,7 +12932,7 @@ public: vtitle.write(to); } - typedef MTPmessages_StatedMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_EditChatTitle : public MTPBoxed { public: @@ -12648,7 +12974,7 @@ public: vphoto.write(to); } - typedef MTPmessages_StatedMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_EditChatPhoto : public MTPBoxed { public: @@ -12693,7 +13019,7 @@ public: vfwd_limit.write(to); } - typedef MTPmessages_StatedMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_AddChatUser : public MTPBoxed { public: @@ -12735,7 +13061,7 @@ public: vuser_id.write(to); } - typedef MTPmessages_StatedMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_DeleteChatUser : public MTPBoxed { public: @@ -12777,7 +13103,7 @@ public: vtitle.write(to); } - typedef MTPmessages_StatedMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_CreateChat : public MTPBoxed { public: @@ -13353,7 +13679,7 @@ public: vrandom_id.write(to); } - typedef MTPmessages_StatedMessage ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_ForwardMessage : public MTPBoxed { public: @@ -13370,6 +13696,7 @@ public: class MTPmessages_sendBroadcast { // RPC method 'messages.sendBroadcast' public: MTPVector vcontacts; + MTPVector vrandom_id; MTPstring vmessage; MTPInputMedia vmedia; @@ -13378,27 +13705,29 @@ public: MTPmessages_sendBroadcast(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_sendBroadcast) { read(from, end, cons); } - MTPmessages_sendBroadcast(const MTPVector &_contacts, const MTPstring &_message, const MTPInputMedia &_media) : vcontacts(_contacts), vmessage(_message), vmedia(_media) { + MTPmessages_sendBroadcast(const MTPVector &_contacts, const MTPVector &_random_id, const MTPstring &_message, const MTPInputMedia &_media) : vcontacts(_contacts), vrandom_id(_random_id), vmessage(_message), vmedia(_media) { } uint32 innerLength() const { - return vcontacts.innerLength() + vmessage.innerLength() + vmedia.innerLength(); + return vcontacts.innerLength() + vrandom_id.innerLength() + vmessage.innerLength() + vmedia.innerLength(); } mtpTypeId type() const { return mtpc_messages_sendBroadcast; } void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_sendBroadcast) { vcontacts.read(from, end); + vrandom_id.read(from, end); vmessage.read(from, end); vmedia.read(from, end); } void write(mtpBuffer &to) const { vcontacts.write(to); + vrandom_id.write(to); vmessage.write(to); vmedia.write(to); } - typedef MTPmessages_StatedMessages ResponseType; + typedef MTPUpdates ResponseType; }; class MTPmessages_SendBroadcast : public MTPBoxed { public: @@ -13408,7 +13737,7 @@ public: } MTPmessages_SendBroadcast(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { } - MTPmessages_SendBroadcast(const MTPVector &_contacts, const MTPstring &_message, const MTPInputMedia &_media) : MTPBoxed(MTPmessages_sendBroadcast(_contacts, _message, _media)) { + MTPmessages_SendBroadcast(const MTPVector &_contacts, const MTPVector &_random_id, const MTPstring &_message, const MTPInputMedia &_media) : MTPBoxed(MTPmessages_sendBroadcast(_contacts, _random_id, _message, _media)) { } }; @@ -15073,124 +15402,6 @@ public: } }; -class MTPaccount_getPassword { // RPC method 'account.getPassword' -public: - MTPaccount_getPassword() { - } - MTPaccount_getPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getPassword) { - read(from, end, cons); - } - - uint32 innerLength() const { - return 0; - } - mtpTypeId type() const { - return mtpc_account_getPassword; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getPassword) { - } - void write(mtpBuffer &to) const { - } - - typedef MTPaccount_Password ResponseType; -}; -class MTPaccount_GetPassword : public MTPBoxed { -public: - MTPaccount_GetPassword() { - } - MTPaccount_GetPassword(const MTPaccount_getPassword &v) : MTPBoxed(v) { - } - MTPaccount_GetPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } -}; - -class MTPaccount_setPassword { // RPC method 'account.setPassword' -public: - MTPbytes vcurrent_password_hash; - MTPbytes vnew_salt; - MTPbytes vnew_password_hash; - MTPstring vhint; - - MTPaccount_setPassword() { - } - MTPaccount_setPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_setPassword) { - read(from, end, cons); - } - MTPaccount_setPassword(const MTPbytes &_current_password_hash, const MTPbytes &_new_salt, const MTPbytes &_new_password_hash, const MTPstring &_hint) : vcurrent_password_hash(_current_password_hash), vnew_salt(_new_salt), vnew_password_hash(_new_password_hash), vhint(_hint) { - } - - uint32 innerLength() const { - return vcurrent_password_hash.innerLength() + vnew_salt.innerLength() + vnew_password_hash.innerLength() + vhint.innerLength(); - } - mtpTypeId type() const { - return mtpc_account_setPassword; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_setPassword) { - vcurrent_password_hash.read(from, end); - vnew_salt.read(from, end); - vnew_password_hash.read(from, end); - vhint.read(from, end); - } - void write(mtpBuffer &to) const { - vcurrent_password_hash.write(to); - vnew_salt.write(to); - vnew_password_hash.write(to); - vhint.write(to); - } - - typedef MTPBool ResponseType; -}; -class MTPaccount_SetPassword : public MTPBoxed { -public: - MTPaccount_SetPassword() { - } - MTPaccount_SetPassword(const MTPaccount_setPassword &v) : MTPBoxed(v) { - } - MTPaccount_SetPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPaccount_SetPassword(const MTPbytes &_current_password_hash, const MTPbytes &_new_salt, const MTPbytes &_new_password_hash, const MTPstring &_hint) : MTPBoxed(MTPaccount_setPassword(_current_password_hash, _new_salt, _new_password_hash, _hint)) { - } -}; - -class MTPauth_checkPassword { // RPC method 'auth.checkPassword' -public: - MTPbytes vpassword_hash; - - MTPauth_checkPassword() { - } - MTPauth_checkPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_checkPassword) { - read(from, end, cons); - } - MTPauth_checkPassword(const MTPbytes &_password_hash) : vpassword_hash(_password_hash) { - } - - uint32 innerLength() const { - return vpassword_hash.innerLength(); - } - mtpTypeId type() const { - return mtpc_auth_checkPassword; - } - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_checkPassword) { - vpassword_hash.read(from, end); - } - void write(mtpBuffer &to) const { - vpassword_hash.write(to); - } - - typedef MTPauth_Authorization ResponseType; -}; -class MTPauth_CheckPassword : public MTPBoxed { -public: - MTPauth_CheckPassword() { - } - MTPauth_CheckPassword(const MTPauth_checkPassword &v) : MTPBoxed(v) { - } - MTPauth_CheckPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { - } - MTPauth_CheckPassword(const MTPbytes &_password_hash) : MTPBoxed(MTPauth_checkPassword(_password_hash)) { - } -}; - class MTPmessages_getStickers { // RPC method 'messages.getStickers' public: MTPstring vemoticon; @@ -15311,6 +15522,297 @@ public: } }; +class MTPaccount_getAuthorizations { // RPC method 'account.getAuthorizations' +public: + MTPaccount_getAuthorizations() { + } + MTPaccount_getAuthorizations(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getAuthorizations) { + read(from, end, cons); + } + + uint32 innerLength() const { + return 0; + } + mtpTypeId type() const { + return mtpc_account_getAuthorizations; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getAuthorizations) { + } + void write(mtpBuffer &to) const { + } + + typedef MTPaccount_Authorizations ResponseType; +}; +class MTPaccount_GetAuthorizations : public MTPBoxed { +public: + MTPaccount_GetAuthorizations() { + } + MTPaccount_GetAuthorizations(const MTPaccount_getAuthorizations &v) : MTPBoxed(v) { + } + MTPaccount_GetAuthorizations(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } +}; + +class MTPaccount_resetAuthorization { // RPC method 'account.resetAuthorization' +public: + MTPlong vhash; + + MTPaccount_resetAuthorization() { + } + MTPaccount_resetAuthorization(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_resetAuthorization) { + read(from, end, cons); + } + MTPaccount_resetAuthorization(const MTPlong &_hash) : vhash(_hash) { + } + + uint32 innerLength() const { + return vhash.innerLength(); + } + mtpTypeId type() const { + return mtpc_account_resetAuthorization; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_resetAuthorization) { + vhash.read(from, end); + } + void write(mtpBuffer &to) const { + vhash.write(to); + } + + typedef MTPBool ResponseType; +}; +class MTPaccount_ResetAuthorization : public MTPBoxed { +public: + MTPaccount_ResetAuthorization() { + } + MTPaccount_ResetAuthorization(const MTPaccount_resetAuthorization &v) : MTPBoxed(v) { + } + MTPaccount_ResetAuthorization(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPaccount_ResetAuthorization(const MTPlong &_hash) : MTPBoxed(MTPaccount_resetAuthorization(_hash)) { + } +}; + +class MTPaccount_getPassword { // RPC method 'account.getPassword' +public: + MTPaccount_getPassword() { + } + MTPaccount_getPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getPassword) { + read(from, end, cons); + } + + uint32 innerLength() const { + return 0; + } + mtpTypeId type() const { + return mtpc_account_getPassword; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getPassword) { + } + void write(mtpBuffer &to) const { + } + + typedef MTPaccount_Password ResponseType; +}; +class MTPaccount_GetPassword : public MTPBoxed { +public: + MTPaccount_GetPassword() { + } + MTPaccount_GetPassword(const MTPaccount_getPassword &v) : MTPBoxed(v) { + } + MTPaccount_GetPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } +}; + +class MTPaccount_getPasswordSettings { // RPC method 'account.getPasswordSettings' +public: + MTPbytes vcurrent_password_hash; + + MTPaccount_getPasswordSettings() { + } + MTPaccount_getPasswordSettings(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getPasswordSettings) { + read(from, end, cons); + } + MTPaccount_getPasswordSettings(const MTPbytes &_current_password_hash) : vcurrent_password_hash(_current_password_hash) { + } + + uint32 innerLength() const { + return vcurrent_password_hash.innerLength(); + } + mtpTypeId type() const { + return mtpc_account_getPasswordSettings; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_getPasswordSettings) { + vcurrent_password_hash.read(from, end); + } + void write(mtpBuffer &to) const { + vcurrent_password_hash.write(to); + } + + typedef MTPaccount_PasswordSettings ResponseType; +}; +class MTPaccount_GetPasswordSettings : public MTPBoxed { +public: + MTPaccount_GetPasswordSettings() { + } + MTPaccount_GetPasswordSettings(const MTPaccount_getPasswordSettings &v) : MTPBoxed(v) { + } + MTPaccount_GetPasswordSettings(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPaccount_GetPasswordSettings(const MTPbytes &_current_password_hash) : MTPBoxed(MTPaccount_getPasswordSettings(_current_password_hash)) { + } +}; + +class MTPaccount_updatePasswordSettings { // RPC method 'account.updatePasswordSettings' +public: + MTPbytes vcurrent_password_hash; + MTPaccount_PasswordInputSettings vnew_settings; + + MTPaccount_updatePasswordSettings() { + } + MTPaccount_updatePasswordSettings(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_updatePasswordSettings) { + read(from, end, cons); + } + MTPaccount_updatePasswordSettings(const MTPbytes &_current_password_hash, const MTPaccount_PasswordInputSettings &_new_settings) : vcurrent_password_hash(_current_password_hash), vnew_settings(_new_settings) { + } + + uint32 innerLength() const { + return vcurrent_password_hash.innerLength() + vnew_settings.innerLength(); + } + mtpTypeId type() const { + return mtpc_account_updatePasswordSettings; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_updatePasswordSettings) { + vcurrent_password_hash.read(from, end); + vnew_settings.read(from, end); + } + void write(mtpBuffer &to) const { + vcurrent_password_hash.write(to); + vnew_settings.write(to); + } + + typedef MTPBool ResponseType; +}; +class MTPaccount_UpdatePasswordSettings : public MTPBoxed { +public: + MTPaccount_UpdatePasswordSettings() { + } + MTPaccount_UpdatePasswordSettings(const MTPaccount_updatePasswordSettings &v) : MTPBoxed(v) { + } + MTPaccount_UpdatePasswordSettings(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPaccount_UpdatePasswordSettings(const MTPbytes &_current_password_hash, const MTPaccount_PasswordInputSettings &_new_settings) : MTPBoxed(MTPaccount_updatePasswordSettings(_current_password_hash, _new_settings)) { + } +}; + +class MTPauth_checkPassword { // RPC method 'auth.checkPassword' +public: + MTPbytes vpassword_hash; + + MTPauth_checkPassword() { + } + MTPauth_checkPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_checkPassword) { + read(from, end, cons); + } + MTPauth_checkPassword(const MTPbytes &_password_hash) : vpassword_hash(_password_hash) { + } + + uint32 innerLength() const { + return vpassword_hash.innerLength(); + } + mtpTypeId type() const { + return mtpc_auth_checkPassword; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_checkPassword) { + vpassword_hash.read(from, end); + } + void write(mtpBuffer &to) const { + vpassword_hash.write(to); + } + + typedef MTPauth_Authorization ResponseType; +}; +class MTPauth_CheckPassword : public MTPBoxed { +public: + MTPauth_CheckPassword() { + } + MTPauth_CheckPassword(const MTPauth_checkPassword &v) : MTPBoxed(v) { + } + MTPauth_CheckPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPauth_CheckPassword(const MTPbytes &_password_hash) : MTPBoxed(MTPauth_checkPassword(_password_hash)) { + } +}; + +class MTPauth_requestPasswordRecovery { // RPC method 'auth.requestPasswordRecovery' +public: + MTPauth_requestPasswordRecovery() { + } + MTPauth_requestPasswordRecovery(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_requestPasswordRecovery) { + read(from, end, cons); + } + + uint32 innerLength() const { + return 0; + } + mtpTypeId type() const { + return mtpc_auth_requestPasswordRecovery; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_requestPasswordRecovery) { + } + void write(mtpBuffer &to) const { + } + + typedef MTPauth_PasswordRecovery ResponseType; +}; +class MTPauth_RequestPasswordRecovery : public MTPBoxed { +public: + MTPauth_RequestPasswordRecovery() { + } + MTPauth_RequestPasswordRecovery(const MTPauth_requestPasswordRecovery &v) : MTPBoxed(v) { + } + MTPauth_RequestPasswordRecovery(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } +}; + +class MTPauth_recoverPassword { // RPC method 'auth.recoverPassword' +public: + MTPstring vcode; + + MTPauth_recoverPassword() { + } + MTPauth_recoverPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_recoverPassword) { + read(from, end, cons); + } + MTPauth_recoverPassword(const MTPstring &_code) : vcode(_code) { + } + + uint32 innerLength() const { + return vcode.innerLength(); + } + mtpTypeId type() const { + return mtpc_auth_recoverPassword; + } + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_auth_recoverPassword) { + vcode.read(from, end); + } + void write(mtpBuffer &to) const { + vcode.write(to); + } + + typedef MTPauth_Authorization ResponseType; +}; +class MTPauth_RecoverPassword : public MTPBoxed { +public: + MTPauth_RecoverPassword() { + } + MTPauth_RecoverPassword(const MTPauth_recoverPassword &v) : MTPBoxed(v) { + } + MTPauth_RecoverPassword(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed(from, end, cons) { + } + MTPauth_RecoverPassword(const MTPstring &_code) : MTPBoxed(MTPauth_recoverPassword(_code)) { + } +}; + // Inline methods definition inline MTPresPQ::MTPresPQ() : mtpDataOwner(new MTPDresPQ()) { @@ -16206,6 +16708,49 @@ inline MTPhttpWait MTP_http_wait(MTPint _max_delay, MTPint _wait_after, MTPint _ return MTPhttpWait(new MTPDhttp_wait(_max_delay, _wait_after, _max_wait)); } +inline MTPerror::MTPerror() : mtpDataOwner(new MTPDerror()) { +} + +inline uint32 MTPerror::innerLength() const { + const MTPDerror &v(c_error()); + return v.vcode.innerLength() + v.vtext.innerLength(); +} +inline mtpTypeId MTPerror::type() const { + return mtpc_error; +} +inline void MTPerror::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_error) throw mtpErrorUnexpected(cons, "MTPerror"); + + if (!data) setData(new MTPDerror()); + MTPDerror &v(_error()); + v.vcode.read(from, end); + v.vtext.read(from, end); +} +inline void MTPerror::write(mtpBuffer &to) const { + const MTPDerror &v(c_error()); + v.vcode.write(to); + v.vtext.write(to); +} +inline MTPerror::MTPerror(MTPDerror *_data) : mtpDataOwner(_data) { +} +inline MTPerror MTP_error(MTPint _code, const MTPstring &_text) { + return MTPerror(new MTPDerror(_code, _text)); +} + +inline uint32 MTPnull::innerLength() const { + return 0; +} +inline mtpTypeId MTPnull::type() const { + return mtpc_null; +} +inline void MTPnull::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { +} +inline void MTPnull::write(mtpBuffer &to) const { +} +inline MTPnull MTP_null() { + return MTPnull(); +} + inline uint32 MTPinputPeer::innerLength() const { switch (_type) { case mtpc_inputPeerContact: { @@ -18216,6 +18761,10 @@ inline uint32 MTPmessageMedia::innerLength() const { const MTPDmessageMediaAudio &v(c_messageMediaAudio()); return v.vaudio.innerLength(); } + case mtpc_messageMediaWebPage: { + const MTPDmessageMediaWebPage &v(c_messageMediaWebPage()); + return v.vwebpage.innerLength(); + } } return 0; } @@ -18261,6 +18810,11 @@ inline void MTPmessageMedia::read(const mtpPrime *&from, const mtpPrime *end, mt MTPDmessageMediaAudio &v(_messageMediaAudio()); v.vaudio.read(from, end); } break; + case mtpc_messageMediaWebPage: _type = cons; { + if (!data) setData(new MTPDmessageMediaWebPage()); + MTPDmessageMediaWebPage &v(_messageMediaWebPage()); + v.vwebpage.read(from, end); + } break; default: throw mtpErrorUnexpected(cons, "MTPmessageMedia"); } } @@ -18293,6 +18847,10 @@ inline void MTPmessageMedia::write(mtpBuffer &to) const { const MTPDmessageMediaAudio &v(c_messageMediaAudio()); v.vaudio.write(to); } break; + case mtpc_messageMediaWebPage: { + const MTPDmessageMediaWebPage &v(c_messageMediaWebPage()); + v.vwebpage.write(to); + } break; } } inline MTPmessageMedia::MTPmessageMedia(mtpTypeId type) : mtpDataOwner(0), _type(type) { @@ -18305,6 +18863,7 @@ inline MTPmessageMedia::MTPmessageMedia(mtpTypeId type) : mtpDataOwner(0), _type case mtpc_messageMediaUnsupported: break; case mtpc_messageMediaDocument: setData(new MTPDmessageMediaDocument()); break; case mtpc_messageMediaAudio: setData(new MTPDmessageMediaAudio()); break; + case mtpc_messageMediaWebPage: setData(new MTPDmessageMediaWebPage()); break; default: throw mtpErrorBadTypeId(type, "MTPmessageMedia"); } } @@ -18320,6 +18879,8 @@ inline MTPmessageMedia::MTPmessageMedia(MTPDmessageMediaDocument *_data) : mtpDa } inline MTPmessageMedia::MTPmessageMedia(MTPDmessageMediaAudio *_data) : mtpDataOwner(_data), _type(mtpc_messageMediaAudio) { } +inline MTPmessageMedia::MTPmessageMedia(MTPDmessageMediaWebPage *_data) : mtpDataOwner(_data), _type(mtpc_messageMediaWebPage) { +} inline MTPmessageMedia MTP_messageMediaEmpty() { return MTPmessageMedia(mtpc_messageMediaEmpty); } @@ -18344,6 +18905,9 @@ inline MTPmessageMedia MTP_messageMediaDocument(const MTPDocument &_document) { inline MTPmessageMedia MTP_messageMediaAudio(const MTPAudio &_audio) { return MTPmessageMedia(new MTPDmessageMediaAudio(_audio)); } +inline MTPmessageMedia MTP_messageMediaWebPage(const MTPWebPage &_webpage) { + return MTPmessageMedia(new MTPDmessageMediaWebPage(_webpage)); +} inline uint32 MTPmessageAction::innerLength() const { switch (_type) { @@ -19900,181 +20464,15 @@ inline MTPmessages_message MTP_messages_messageEmpty() { return MTPmessages_message(); } -inline uint32 MTPmessages_statedMessages::innerLength() const { - switch (_type) { - case mtpc_messages_statedMessages: { - const MTPDmessages_statedMessages &v(c_messages_statedMessages()); - return v.vmessages.innerLength() + v.vchats.innerLength() + v.vusers.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength(); - } - case mtpc_messages_statedMessagesLinks: { - const MTPDmessages_statedMessagesLinks &v(c_messages_statedMessagesLinks()); - return v.vmessages.innerLength() + v.vchats.innerLength() + v.vusers.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength() + v.vlinks.innerLength() + v.vseq.innerLength(); - } - } - return 0; -} -inline mtpTypeId MTPmessages_statedMessages::type() const { - if (!_type) throw mtpErrorUninitialized(); - return _type; -} -inline void MTPmessages_statedMessages::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != _type) setData(0); - switch (cons) { - case mtpc_messages_statedMessages: _type = cons; { - if (!data) setData(new MTPDmessages_statedMessages()); - MTPDmessages_statedMessages &v(_messages_statedMessages()); - v.vmessages.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); - v.vpts.read(from, end); - v.vpts_count.read(from, end); - } break; - case mtpc_messages_statedMessagesLinks: _type = cons; { - if (!data) setData(new MTPDmessages_statedMessagesLinks()); - MTPDmessages_statedMessagesLinks &v(_messages_statedMessagesLinks()); - v.vmessages.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); - v.vpts.read(from, end); - v.vpts_count.read(from, end); - v.vlinks.read(from, end); - v.vseq.read(from, end); - } break; - default: throw mtpErrorUnexpected(cons, "MTPmessages_statedMessages"); - } -} -inline void MTPmessages_statedMessages::write(mtpBuffer &to) const { - switch (_type) { - case mtpc_messages_statedMessages: { - const MTPDmessages_statedMessages &v(c_messages_statedMessages()); - v.vmessages.write(to); - v.vchats.write(to); - v.vusers.write(to); - v.vpts.write(to); - v.vpts_count.write(to); - } break; - case mtpc_messages_statedMessagesLinks: { - const MTPDmessages_statedMessagesLinks &v(c_messages_statedMessagesLinks()); - v.vmessages.write(to); - v.vchats.write(to); - v.vusers.write(to); - v.vpts.write(to); - v.vpts_count.write(to); - v.vlinks.write(to); - v.vseq.write(to); - } break; - } -} -inline MTPmessages_statedMessages::MTPmessages_statedMessages(mtpTypeId type) : mtpDataOwner(0), _type(type) { - switch (type) { - case mtpc_messages_statedMessages: setData(new MTPDmessages_statedMessages()); break; - case mtpc_messages_statedMessagesLinks: setData(new MTPDmessages_statedMessagesLinks()); break; - default: throw mtpErrorBadTypeId(type, "MTPmessages_statedMessages"); - } -} -inline MTPmessages_statedMessages::MTPmessages_statedMessages(MTPDmessages_statedMessages *_data) : mtpDataOwner(_data), _type(mtpc_messages_statedMessages) { -} -inline MTPmessages_statedMessages::MTPmessages_statedMessages(MTPDmessages_statedMessagesLinks *_data) : mtpDataOwner(_data), _type(mtpc_messages_statedMessagesLinks) { -} -inline MTPmessages_statedMessages MTP_messages_statedMessages(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count) { - return MTPmessages_statedMessages(new MTPDmessages_statedMessages(_messages, _chats, _users, _pts, _pts_count)); -} -inline MTPmessages_statedMessages MTP_messages_statedMessagesLinks(const MTPVector &_messages, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) { - return MTPmessages_statedMessages(new MTPDmessages_statedMessagesLinks(_messages, _chats, _users, _pts, _pts_count, _links, _seq)); -} - -inline uint32 MTPmessages_statedMessage::innerLength() const { - switch (_type) { - case mtpc_messages_statedMessage: { - const MTPDmessages_statedMessage &v(c_messages_statedMessage()); - return v.vmessage.innerLength() + v.vchats.innerLength() + v.vusers.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength(); - } - case mtpc_messages_statedMessageLink: { - const MTPDmessages_statedMessageLink &v(c_messages_statedMessageLink()); - return v.vmessage.innerLength() + v.vchats.innerLength() + v.vusers.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength() + v.vlinks.innerLength() + v.vseq.innerLength(); - } - } - return 0; -} -inline mtpTypeId MTPmessages_statedMessage::type() const { - if (!_type) throw mtpErrorUninitialized(); - return _type; -} -inline void MTPmessages_statedMessage::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != _type) setData(0); - switch (cons) { - case mtpc_messages_statedMessage: _type = cons; { - if (!data) setData(new MTPDmessages_statedMessage()); - MTPDmessages_statedMessage &v(_messages_statedMessage()); - v.vmessage.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); - v.vpts.read(from, end); - v.vpts_count.read(from, end); - } break; - case mtpc_messages_statedMessageLink: _type = cons; { - if (!data) setData(new MTPDmessages_statedMessageLink()); - MTPDmessages_statedMessageLink &v(_messages_statedMessageLink()); - v.vmessage.read(from, end); - v.vchats.read(from, end); - v.vusers.read(from, end); - v.vpts.read(from, end); - v.vpts_count.read(from, end); - v.vlinks.read(from, end); - v.vseq.read(from, end); - } break; - default: throw mtpErrorUnexpected(cons, "MTPmessages_statedMessage"); - } -} -inline void MTPmessages_statedMessage::write(mtpBuffer &to) const { - switch (_type) { - case mtpc_messages_statedMessage: { - const MTPDmessages_statedMessage &v(c_messages_statedMessage()); - v.vmessage.write(to); - v.vchats.write(to); - v.vusers.write(to); - v.vpts.write(to); - v.vpts_count.write(to); - } break; - case mtpc_messages_statedMessageLink: { - const MTPDmessages_statedMessageLink &v(c_messages_statedMessageLink()); - v.vmessage.write(to); - v.vchats.write(to); - v.vusers.write(to); - v.vpts.write(to); - v.vpts_count.write(to); - v.vlinks.write(to); - v.vseq.write(to); - } break; - } -} -inline MTPmessages_statedMessage::MTPmessages_statedMessage(mtpTypeId type) : mtpDataOwner(0), _type(type) { - switch (type) { - case mtpc_messages_statedMessage: setData(new MTPDmessages_statedMessage()); break; - case mtpc_messages_statedMessageLink: setData(new MTPDmessages_statedMessageLink()); break; - default: throw mtpErrorBadTypeId(type, "MTPmessages_statedMessage"); - } -} -inline MTPmessages_statedMessage::MTPmessages_statedMessage(MTPDmessages_statedMessage *_data) : mtpDataOwner(_data), _type(mtpc_messages_statedMessage) { -} -inline MTPmessages_statedMessage::MTPmessages_statedMessage(MTPDmessages_statedMessageLink *_data) : mtpDataOwner(_data), _type(mtpc_messages_statedMessageLink) { -} -inline MTPmessages_statedMessage MTP_messages_statedMessage(const MTPMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count) { - return MTPmessages_statedMessage(new MTPDmessages_statedMessage(_message, _chats, _users, _pts, _pts_count)); -} -inline MTPmessages_statedMessage MTP_messages_statedMessageLink(const MTPMessage &_message, const MTPVector &_chats, const MTPVector &_users, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) { - return MTPmessages_statedMessage(new MTPDmessages_statedMessageLink(_message, _chats, _users, _pts, _pts_count, _links, _seq)); -} - inline uint32 MTPmessages_sentMessage::innerLength() const { switch (_type) { case mtpc_messages_sentMessage: { const MTPDmessages_sentMessage &v(c_messages_sentMessage()); - return v.vid.innerLength() + v.vdate.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength(); + return v.vid.innerLength() + v.vdate.innerLength() + v.vmedia.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength(); } case mtpc_messages_sentMessageLink: { const MTPDmessages_sentMessageLink &v(c_messages_sentMessageLink()); - return v.vid.innerLength() + v.vdate.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength() + v.vlinks.innerLength() + v.vseq.innerLength(); + return v.vid.innerLength() + v.vdate.innerLength() + v.vmedia.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength() + v.vlinks.innerLength() + v.vseq.innerLength(); } } return 0; @@ -20091,6 +20489,7 @@ inline void MTPmessages_sentMessage::read(const mtpPrime *&from, const mtpPrime MTPDmessages_sentMessage &v(_messages_sentMessage()); v.vid.read(from, end); v.vdate.read(from, end); + v.vmedia.read(from, end); v.vpts.read(from, end); v.vpts_count.read(from, end); } break; @@ -20099,6 +20498,7 @@ inline void MTPmessages_sentMessage::read(const mtpPrime *&from, const mtpPrime MTPDmessages_sentMessageLink &v(_messages_sentMessageLink()); v.vid.read(from, end); v.vdate.read(from, end); + v.vmedia.read(from, end); v.vpts.read(from, end); v.vpts_count.read(from, end); v.vlinks.read(from, end); @@ -20113,6 +20513,7 @@ inline void MTPmessages_sentMessage::write(mtpBuffer &to) const { const MTPDmessages_sentMessage &v(c_messages_sentMessage()); v.vid.write(to); v.vdate.write(to); + v.vmedia.write(to); v.vpts.write(to); v.vpts_count.write(to); } break; @@ -20120,6 +20521,7 @@ inline void MTPmessages_sentMessage::write(mtpBuffer &to) const { const MTPDmessages_sentMessageLink &v(c_messages_sentMessageLink()); v.vid.write(to); v.vdate.write(to); + v.vmedia.write(to); v.vpts.write(to); v.vpts_count.write(to); v.vlinks.write(to); @@ -20138,11 +20540,11 @@ inline MTPmessages_sentMessage::MTPmessages_sentMessage(MTPDmessages_sentMessage } inline MTPmessages_sentMessage::MTPmessages_sentMessage(MTPDmessages_sentMessageLink *_data) : mtpDataOwner(_data), _type(mtpc_messages_sentMessageLink) { } -inline MTPmessages_sentMessage MTP_messages_sentMessage(MTPint _id, MTPint _date, MTPint _pts, MTPint _pts_count) { - return MTPmessages_sentMessage(new MTPDmessages_sentMessage(_id, _date, _pts, _pts_count)); +inline MTPmessages_sentMessage MTP_messages_sentMessage(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count) { + return MTPmessages_sentMessage(new MTPDmessages_sentMessage(_id, _date, _media, _pts, _pts_count)); } -inline MTPmessages_sentMessage MTP_messages_sentMessageLink(MTPint _id, MTPint _date, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) { - return MTPmessages_sentMessage(new MTPDmessages_sentMessageLink(_id, _date, _pts, _pts_count, _links, _seq)); +inline MTPmessages_sentMessage MTP_messages_sentMessageLink(MTPint _id, MTPint _date, const MTPMessageMedia &_media, MTPint _pts, MTPint _pts_count, const MTPVector &_links, MTPint _seq) { + return MTPmessages_sentMessage(new MTPDmessages_sentMessageLink(_id, _date, _media, _pts, _pts_count, _links, _seq)); } inline MTPmessages_chats::MTPmessages_chats() : mtpDataOwner(new MTPDmessages_chats()) { @@ -20405,6 +20807,10 @@ inline uint32 MTPupdate::innerLength() const { const MTPDupdateReadHistoryOutbox &v(c_updateReadHistoryOutbox()); return v.vpeer.innerLength() + v.vmax_id.innerLength() + v.vpts.innerLength() + v.vpts_count.innerLength(); } + case mtpc_updateWebPage: { + const MTPDupdateWebPage &v(c_updateWebPage()); + return v.vwebpage.innerLength(); + } } return 0; } @@ -20600,6 +21006,11 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI v.vpts.read(from, end); v.vpts_count.read(from, end); } break; + case mtpc_updateWebPage: _type = cons; { + if (!data) setData(new MTPDupdateWebPage()); + MTPDupdateWebPage &v(_updateWebPage()); + v.vwebpage.read(from, end); + } break; default: throw mtpErrorUnexpected(cons, "MTPupdate"); } } @@ -20762,6 +21173,10 @@ inline void MTPupdate::write(mtpBuffer &to) const { v.vpts.write(to); v.vpts_count.write(to); } break; + case mtpc_updateWebPage: { + const MTPDupdateWebPage &v(c_updateWebPage()); + v.vwebpage.write(to); + } break; } } inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { @@ -20794,6 +21209,7 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) { case mtpc_updateUserPhone: setData(new MTPDupdateUserPhone()); break; case mtpc_updateReadHistoryInbox: setData(new MTPDupdateReadHistoryInbox()); break; case mtpc_updateReadHistoryOutbox: setData(new MTPDupdateReadHistoryOutbox()); break; + case mtpc_updateWebPage: setData(new MTPDupdateWebPage()); break; default: throw mtpErrorBadTypeId(type, "MTPupdate"); } } @@ -20853,6 +21269,8 @@ inline MTPupdate::MTPupdate(MTPDupdateReadHistoryInbox *_data) : mtpDataOwner(_d } inline MTPupdate::MTPupdate(MTPDupdateReadHistoryOutbox *_data) : mtpDataOwner(_data), _type(mtpc_updateReadHistoryOutbox) { } +inline MTPupdate::MTPupdate(MTPDupdateWebPage *_data) : mtpDataOwner(_data), _type(mtpc_updateWebPage) { +} inline MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count) { return MTPupdate(new MTPDupdateNewMessage(_message, _pts, _pts_count)); } @@ -20937,6 +21355,9 @@ inline MTPupdate MTP_updateReadHistoryInbox(const MTPPeer &_peer, MTPint _max_id inline MTPupdate MTP_updateReadHistoryOutbox(const MTPPeer &_peer, MTPint _max_id, MTPint _pts, MTPint _pts_count) { return MTPupdate(new MTPDupdateReadHistoryOutbox(_peer, _max_id, _pts, _pts_count)); } +inline MTPupdate MTP_updateWebPage(const MTPWebPage &_webpage) { + return MTPupdate(new MTPDupdateWebPage(_webpage)); +} inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) { } @@ -21427,7 +21848,7 @@ inline MTPconfig::MTPconfig() : mtpDataOwner(new MTPDconfig()) { inline uint32 MTPconfig::innerLength() const { const MTPDconfig &v(c_config()); - return v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vbroadcast_size_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vdisabled_features.innerLength(); + return v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vbroadcast_size_max.innerLength() + v.vforwarded_count_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vdisabled_features.innerLength(); } inline mtpTypeId MTPconfig::type() const { return mtpc_config; @@ -21444,6 +21865,7 @@ inline void MTPconfig::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI v.vdc_options.read(from, end); v.vchat_size_max.read(from, end); v.vbroadcast_size_max.read(from, end); + v.vforwarded_count_max.read(from, end); v.vonline_update_period_ms.read(from, end); v.voffline_blur_timeout_ms.read(from, end); v.voffline_idle_timeout_ms.read(from, end); @@ -21462,6 +21884,7 @@ inline void MTPconfig::write(mtpBuffer &to) const { v.vdc_options.write(to); v.vchat_size_max.write(to); v.vbroadcast_size_max.write(to); + v.vforwarded_count_max.write(to); v.vonline_update_period_ms.write(to); v.voffline_blur_timeout_ms.write(to); v.voffline_idle_timeout_ms.write(to); @@ -21473,8 +21896,8 @@ inline void MTPconfig::write(mtpBuffer &to) const { } inline MTPconfig::MTPconfig(MTPDconfig *_data) : mtpDataOwner(_data) { } -inline MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _broadcast_size_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, const MTPVector &_disabled_features) { - return MTPconfig(new MTPDconfig(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _broadcast_size_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _disabled_features)); +inline MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector &_dc_options, MTPint _chat_size_max, MTPint _broadcast_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, const MTPVector &_disabled_features) { + return MTPconfig(new MTPDconfig(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _broadcast_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _disabled_features)); } inline MTPnearestDc::MTPnearestDc() : mtpDataOwner(new MTPDnearestDc()) { @@ -23157,73 +23580,6 @@ inline MTPaccount_sentChangePhoneCode MTP_account_sentChangePhoneCode(const MTPs return MTPaccount_sentChangePhoneCode(new MTPDaccount_sentChangePhoneCode(_phone_code_hash, _send_call_timeout)); } -inline uint32 MTPaccount_password::innerLength() const { - switch (_type) { - case mtpc_account_noPassword: { - const MTPDaccount_noPassword &v(c_account_noPassword()); - return v.vnew_salt.innerLength(); - } - case mtpc_account_password: { - const MTPDaccount_password &v(c_account_password()); - return v.vcurrent_salt.innerLength() + v.vnew_salt.innerLength() + v.vhint.innerLength(); - } - } - return 0; -} -inline mtpTypeId MTPaccount_password::type() const { - if (!_type) throw mtpErrorUninitialized(); - return _type; -} -inline void MTPaccount_password::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != _type) setData(0); - switch (cons) { - case mtpc_account_noPassword: _type = cons; { - if (!data) setData(new MTPDaccount_noPassword()); - MTPDaccount_noPassword &v(_account_noPassword()); - v.vnew_salt.read(from, end); - } break; - case mtpc_account_password: _type = cons; { - if (!data) setData(new MTPDaccount_password()); - MTPDaccount_password &v(_account_password()); - v.vcurrent_salt.read(from, end); - v.vnew_salt.read(from, end); - v.vhint.read(from, end); - } break; - default: throw mtpErrorUnexpected(cons, "MTPaccount_password"); - } -} -inline void MTPaccount_password::write(mtpBuffer &to) const { - switch (_type) { - case mtpc_account_noPassword: { - const MTPDaccount_noPassword &v(c_account_noPassword()); - v.vnew_salt.write(to); - } break; - case mtpc_account_password: { - const MTPDaccount_password &v(c_account_password()); - v.vcurrent_salt.write(to); - v.vnew_salt.write(to); - v.vhint.write(to); - } break; - } -} -inline MTPaccount_password::MTPaccount_password(mtpTypeId type) : mtpDataOwner(0), _type(type) { - switch (type) { - case mtpc_account_noPassword: setData(new MTPDaccount_noPassword()); break; - case mtpc_account_password: setData(new MTPDaccount_password()); break; - default: throw mtpErrorBadTypeId(type, "MTPaccount_password"); - } -} -inline MTPaccount_password::MTPaccount_password(MTPDaccount_noPassword *_data) : mtpDataOwner(_data), _type(mtpc_account_noPassword) { -} -inline MTPaccount_password::MTPaccount_password(MTPDaccount_password *_data) : mtpDataOwner(_data), _type(mtpc_account_password) { -} -inline MTPaccount_password MTP_account_noPassword(const MTPbytes &_new_salt) { - return MTPaccount_password(new MTPDaccount_noPassword(_new_salt)); -} -inline MTPaccount_password MTP_account_password(const MTPbytes &_current_salt, const MTPbytes &_new_salt, const MTPstring &_hint) { - return MTPaccount_password(new MTPDaccount_password(_current_salt, _new_salt, _hint)); -} - inline uint32 MTPdocumentAttribute::innerLength() const { switch (_type) { case mtpc_documentAttributeImageSize: { @@ -23588,6 +23944,338 @@ inline MTPcontactLink MTP_contactLinkContact() { return MTPcontactLink(mtpc_contactLinkContact); } +inline uint32 MTPwebPage::innerLength() const { + switch (_type) { + case mtpc_webPageEmpty: { + const MTPDwebPageEmpty &v(c_webPageEmpty()); + return v.vid.innerLength(); + } + case mtpc_webPagePending: { + const MTPDwebPagePending &v(c_webPagePending()); + return v.vid.innerLength() + v.vdate.innerLength(); + } + case mtpc_webPage: { + const MTPDwebPage &v(c_webPage()); + return v.vid.innerLength() + v.vdisplay_url.innerLength() + v.vtitle.innerLength() + v.vdescription.innerLength() + v.vphoto.innerLength(); + } + } + return 0; +} +inline mtpTypeId MTPwebPage::type() const { + if (!_type) throw mtpErrorUninitialized(); + return _type; +} +inline void MTPwebPage::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != _type) setData(0); + switch (cons) { + case mtpc_webPageEmpty: _type = cons; { + if (!data) setData(new MTPDwebPageEmpty()); + MTPDwebPageEmpty &v(_webPageEmpty()); + v.vid.read(from, end); + } break; + case mtpc_webPagePending: _type = cons; { + if (!data) setData(new MTPDwebPagePending()); + MTPDwebPagePending &v(_webPagePending()); + v.vid.read(from, end); + v.vdate.read(from, end); + } break; + case mtpc_webPage: _type = cons; { + if (!data) setData(new MTPDwebPage()); + MTPDwebPage &v(_webPage()); + v.vid.read(from, end); + v.vdisplay_url.read(from, end); + v.vtitle.read(from, end); + v.vdescription.read(from, end); + v.vphoto.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPwebPage"); + } +} +inline void MTPwebPage::write(mtpBuffer &to) const { + switch (_type) { + case mtpc_webPageEmpty: { + const MTPDwebPageEmpty &v(c_webPageEmpty()); + v.vid.write(to); + } break; + case mtpc_webPagePending: { + const MTPDwebPagePending &v(c_webPagePending()); + v.vid.write(to); + v.vdate.write(to); + } break; + case mtpc_webPage: { + const MTPDwebPage &v(c_webPage()); + v.vid.write(to); + v.vdisplay_url.write(to); + v.vtitle.write(to); + v.vdescription.write(to); + v.vphoto.write(to); + } break; + } +} +inline MTPwebPage::MTPwebPage(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_webPageEmpty: setData(new MTPDwebPageEmpty()); break; + case mtpc_webPagePending: setData(new MTPDwebPagePending()); break; + case mtpc_webPage: setData(new MTPDwebPage()); break; + default: throw mtpErrorBadTypeId(type, "MTPwebPage"); + } +} +inline MTPwebPage::MTPwebPage(MTPDwebPageEmpty *_data) : mtpDataOwner(_data), _type(mtpc_webPageEmpty) { +} +inline MTPwebPage::MTPwebPage(MTPDwebPagePending *_data) : mtpDataOwner(_data), _type(mtpc_webPagePending) { +} +inline MTPwebPage::MTPwebPage(MTPDwebPage *_data) : mtpDataOwner(_data), _type(mtpc_webPage) { +} +inline MTPwebPage MTP_webPageEmpty(const MTPlong &_id) { + return MTPwebPage(new MTPDwebPageEmpty(_id)); +} +inline MTPwebPage MTP_webPagePending(const MTPlong &_id, MTPint _date) { + return MTPwebPage(new MTPDwebPagePending(_id, _date)); +} +inline MTPwebPage MTP_webPage(const MTPlong &_id, const MTPstring &_display_url, const MTPstring &_title, const MTPstring &_description, const MTPPhoto &_photo) { + return MTPwebPage(new MTPDwebPage(_id, _display_url, _title, _description, _photo)); +} + +inline MTPauthorization::MTPauthorization() : mtpDataOwner(new MTPDauthorization()) { +} + +inline uint32 MTPauthorization::innerLength() const { + const MTPDauthorization &v(c_authorization()); + return v.vhash.innerLength() + v.vflags.innerLength() + v.vdevice_model.innerLength() + v.vplatform.innerLength() + v.vsystem_version.innerLength() + v.vapi_id.innerLength() + v.vapp_name.innerLength() + v.vapp_version.innerLength() + v.vdate_created.innerLength() + v.vdate_active.innerLength() + v.vip.innerLength() + v.vcountry.innerLength() + v.vregion.innerLength(); +} +inline mtpTypeId MTPauthorization::type() const { + return mtpc_authorization; +} +inline void MTPauthorization::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_authorization) throw mtpErrorUnexpected(cons, "MTPauthorization"); + + if (!data) setData(new MTPDauthorization()); + MTPDauthorization &v(_authorization()); + v.vhash.read(from, end); + v.vflags.read(from, end); + v.vdevice_model.read(from, end); + v.vplatform.read(from, end); + v.vsystem_version.read(from, end); + v.vapi_id.read(from, end); + v.vapp_name.read(from, end); + v.vapp_version.read(from, end); + v.vdate_created.read(from, end); + v.vdate_active.read(from, end); + v.vip.read(from, end); + v.vcountry.read(from, end); + v.vregion.read(from, end); +} +inline void MTPauthorization::write(mtpBuffer &to) const { + const MTPDauthorization &v(c_authorization()); + v.vhash.write(to); + v.vflags.write(to); + v.vdevice_model.write(to); + v.vplatform.write(to); + v.vsystem_version.write(to); + v.vapi_id.write(to); + v.vapp_name.write(to); + v.vapp_version.write(to); + v.vdate_created.write(to); + v.vdate_active.write(to); + v.vip.write(to); + v.vcountry.write(to); + v.vregion.write(to); +} +inline MTPauthorization::MTPauthorization(MTPDauthorization *_data) : mtpDataOwner(_data) { +} +inline MTPauthorization MTP_authorization(const MTPlong &_hash, MTPint _flags, const MTPstring &_device_model, const MTPstring &_platform, const MTPstring &_system_version, MTPint _api_id, const MTPstring &_app_name, const MTPstring &_app_version, MTPint _date_created, MTPint _date_active, const MTPstring &_ip, const MTPstring &_country, const MTPstring &_region) { + return MTPauthorization(new MTPDauthorization(_hash, _flags, _device_model, _platform, _system_version, _api_id, _app_name, _app_version, _date_created, _date_active, _ip, _country, _region)); +} + +inline MTPaccount_authorizations::MTPaccount_authorizations() : mtpDataOwner(new MTPDaccount_authorizations()) { +} + +inline uint32 MTPaccount_authorizations::innerLength() const { + const MTPDaccount_authorizations &v(c_account_authorizations()); + return v.vauthorizations.innerLength(); +} +inline mtpTypeId MTPaccount_authorizations::type() const { + return mtpc_account_authorizations; +} +inline void MTPaccount_authorizations::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_account_authorizations) throw mtpErrorUnexpected(cons, "MTPaccount_authorizations"); + + if (!data) setData(new MTPDaccount_authorizations()); + MTPDaccount_authorizations &v(_account_authorizations()); + v.vauthorizations.read(from, end); +} +inline void MTPaccount_authorizations::write(mtpBuffer &to) const { + const MTPDaccount_authorizations &v(c_account_authorizations()); + v.vauthorizations.write(to); +} +inline MTPaccount_authorizations::MTPaccount_authorizations(MTPDaccount_authorizations *_data) : mtpDataOwner(_data) { +} +inline MTPaccount_authorizations MTP_account_authorizations(const MTPVector &_authorizations) { + return MTPaccount_authorizations(new MTPDaccount_authorizations(_authorizations)); +} + +inline uint32 MTPaccount_password::innerLength() const { + switch (_type) { + case mtpc_account_noPassword: { + const MTPDaccount_noPassword &v(c_account_noPassword()); + return v.vnew_salt.innerLength() + v.vemail_unconfirmed_pattern.innerLength(); + } + case mtpc_account_password: { + const MTPDaccount_password &v(c_account_password()); + return v.vcurrent_salt.innerLength() + v.vnew_salt.innerLength() + v.vhint.innerLength() + v.vhas_recovery.innerLength() + v.vemail_unconfirmed_pattern.innerLength(); + } + } + return 0; +} +inline mtpTypeId MTPaccount_password::type() const { + if (!_type) throw mtpErrorUninitialized(); + return _type; +} +inline void MTPaccount_password::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != _type) setData(0); + switch (cons) { + case mtpc_account_noPassword: _type = cons; { + if (!data) setData(new MTPDaccount_noPassword()); + MTPDaccount_noPassword &v(_account_noPassword()); + v.vnew_salt.read(from, end); + v.vemail_unconfirmed_pattern.read(from, end); + } break; + case mtpc_account_password: _type = cons; { + if (!data) setData(new MTPDaccount_password()); + MTPDaccount_password &v(_account_password()); + v.vcurrent_salt.read(from, end); + v.vnew_salt.read(from, end); + v.vhint.read(from, end); + v.vhas_recovery.read(from, end); + v.vemail_unconfirmed_pattern.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPaccount_password"); + } +} +inline void MTPaccount_password::write(mtpBuffer &to) const { + switch (_type) { + case mtpc_account_noPassword: { + const MTPDaccount_noPassword &v(c_account_noPassword()); + v.vnew_salt.write(to); + v.vemail_unconfirmed_pattern.write(to); + } break; + case mtpc_account_password: { + const MTPDaccount_password &v(c_account_password()); + v.vcurrent_salt.write(to); + v.vnew_salt.write(to); + v.vhint.write(to); + v.vhas_recovery.write(to); + v.vemail_unconfirmed_pattern.write(to); + } break; + } +} +inline MTPaccount_password::MTPaccount_password(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_account_noPassword: setData(new MTPDaccount_noPassword()); break; + case mtpc_account_password: setData(new MTPDaccount_password()); break; + default: throw mtpErrorBadTypeId(type, "MTPaccount_password"); + } +} +inline MTPaccount_password::MTPaccount_password(MTPDaccount_noPassword *_data) : mtpDataOwner(_data), _type(mtpc_account_noPassword) { +} +inline MTPaccount_password::MTPaccount_password(MTPDaccount_password *_data) : mtpDataOwner(_data), _type(mtpc_account_password) { +} +inline MTPaccount_password MTP_account_noPassword(const MTPbytes &_new_salt, const MTPstring &_email_unconfirmed_pattern) { + return MTPaccount_password(new MTPDaccount_noPassword(_new_salt, _email_unconfirmed_pattern)); +} +inline MTPaccount_password MTP_account_password(const MTPbytes &_current_salt, const MTPbytes &_new_salt, const MTPstring &_hint, MTPBool _has_recovery, const MTPstring &_email_unconfirmed_pattern) { + return MTPaccount_password(new MTPDaccount_password(_current_salt, _new_salt, _hint, _has_recovery, _email_unconfirmed_pattern)); +} + +inline MTPaccount_passwordSettings::MTPaccount_passwordSettings() : mtpDataOwner(new MTPDaccount_passwordSettings()) { +} + +inline uint32 MTPaccount_passwordSettings::innerLength() const { + const MTPDaccount_passwordSettings &v(c_account_passwordSettings()); + return v.vemail.innerLength(); +} +inline mtpTypeId MTPaccount_passwordSettings::type() const { + return mtpc_account_passwordSettings; +} +inline void MTPaccount_passwordSettings::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_account_passwordSettings) throw mtpErrorUnexpected(cons, "MTPaccount_passwordSettings"); + + if (!data) setData(new MTPDaccount_passwordSettings()); + MTPDaccount_passwordSettings &v(_account_passwordSettings()); + v.vemail.read(from, end); +} +inline void MTPaccount_passwordSettings::write(mtpBuffer &to) const { + const MTPDaccount_passwordSettings &v(c_account_passwordSettings()); + v.vemail.write(to); +} +inline MTPaccount_passwordSettings::MTPaccount_passwordSettings(MTPDaccount_passwordSettings *_data) : mtpDataOwner(_data) { +} +inline MTPaccount_passwordSettings MTP_account_passwordSettings(const MTPstring &_email) { + return MTPaccount_passwordSettings(new MTPDaccount_passwordSettings(_email)); +} + +inline MTPaccount_passwordInputSettings::MTPaccount_passwordInputSettings() : mtpDataOwner(new MTPDaccount_passwordInputSettings()) { +} + +inline uint32 MTPaccount_passwordInputSettings::innerLength() const { + const MTPDaccount_passwordInputSettings &v(c_account_passwordInputSettings()); + return v.vflags.innerLength() + (v.has_new_salt() ? v.vnew_salt.innerLength() : 0) + (v.has_new_password_hash() ? v.vnew_password_hash.innerLength() : 0) + (v.has_hint() ? v.vhint.innerLength() : 0) + (v.has_email() ? v.vemail.innerLength() : 0); +} +inline mtpTypeId MTPaccount_passwordInputSettings::type() const { + return mtpc_account_passwordInputSettings; +} +inline void MTPaccount_passwordInputSettings::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_account_passwordInputSettings) throw mtpErrorUnexpected(cons, "MTPaccount_passwordInputSettings"); + + if (!data) setData(new MTPDaccount_passwordInputSettings()); + MTPDaccount_passwordInputSettings &v(_account_passwordInputSettings()); + v.vflags.read(from, end); + if (v.has_new_salt()) { v.vnew_salt.read(from, end); } else { v.vnew_salt = MTPbytes(); } + if (v.has_new_password_hash()) { v.vnew_password_hash.read(from, end); } else { v.vnew_password_hash = MTPbytes(); } + if (v.has_hint()) { v.vhint.read(from, end); } else { v.vhint = MTPstring(); } + if (v.has_email()) { v.vemail.read(from, end); } else { v.vemail = MTPstring(); } +} +inline void MTPaccount_passwordInputSettings::write(mtpBuffer &to) const { + const MTPDaccount_passwordInputSettings &v(c_account_passwordInputSettings()); + v.vflags.write(to); + if (v.has_new_salt()) v.vnew_salt.write(to); + if (v.has_new_password_hash()) v.vnew_password_hash.write(to); + if (v.has_hint()) v.vhint.write(to); + if (v.has_email()) v.vemail.write(to); +} +inline MTPaccount_passwordInputSettings::MTPaccount_passwordInputSettings(MTPDaccount_passwordInputSettings *_data) : mtpDataOwner(_data) { +} +inline MTPaccount_passwordInputSettings MTP_account_passwordInputSettings(MTPint _flags, const MTPbytes &_new_salt, const MTPbytes &_new_password_hash, const MTPstring &_hint, const MTPstring &_email) { + return MTPaccount_passwordInputSettings(new MTPDaccount_passwordInputSettings(_flags, _new_salt, _new_password_hash, _hint, _email)); +} + +inline MTPauth_passwordRecovery::MTPauth_passwordRecovery() : mtpDataOwner(new MTPDauth_passwordRecovery()) { +} + +inline uint32 MTPauth_passwordRecovery::innerLength() const { + const MTPDauth_passwordRecovery &v(c_auth_passwordRecovery()); + return v.vemail_pattern.innerLength(); +} +inline mtpTypeId MTPauth_passwordRecovery::type() const { + return mtpc_auth_passwordRecovery; +} +inline void MTPauth_passwordRecovery::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { + if (cons != mtpc_auth_passwordRecovery) throw mtpErrorUnexpected(cons, "MTPauth_passwordRecovery"); + + if (!data) setData(new MTPDauth_passwordRecovery()); + MTPDauth_passwordRecovery &v(_auth_passwordRecovery()); + v.vemail_pattern.read(from, end); +} +inline void MTPauth_passwordRecovery::write(mtpBuffer &to) const { + const MTPDauth_passwordRecovery &v(c_auth_passwordRecovery()); + v.vemail_pattern.write(to); +} +inline MTPauth_passwordRecovery::MTPauth_passwordRecovery(MTPDauth_passwordRecovery *_data) : mtpDataOwner(_data) { +} +inline MTPauth_passwordRecovery MTP_auth_passwordRecovery(const MTPstring &_email_pattern) { + return MTPauth_passwordRecovery(new MTPDauth_passwordRecovery(_email_pattern)); +} + // Human-readable text serialization #if (defined _DEBUG || defined _WITH_DEBUG) diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index d05eefcec..0fd51e9ce 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -126,6 +126,10 @@ register.saveDeveloperInfo#9a5f6e95 name:string email:string phone_number:string ---types--- +error#c4b9f9bb code:int text:string = Error; + +null#56730bcc = Null; + inputPeerEmpty#7f3b18ea = InputPeer; inputPeerSelf#7da07ec9 = InputPeer; inputPeerContact#1023dbe8 user_id:int = InputPeer; @@ -310,11 +314,7 @@ messages.messagesSlice#b446ae3 count:int messages:Vector chats:Vector chats:Vector users:Vector pts:int pts_count:int = messages.StatedMessages; - -messages.statedMessage#96240c6a message:Message chats:Vector users:Vector pts:int pts_count:int = messages.StatedMessage; - -messages.sentMessage#900eac40 id:int date:int pts:int pts_count:int = messages.SentMessage; +messages.sentMessage#4c3d47f3 id:int date:int media:MessageMedia pts:int pts_count:int = messages.SentMessage; messages.chats#64ff9fd5 chats:Vector = messages.Chats; @@ -366,7 +366,7 @@ upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File; dcOption#2ec2a43c id:int hostname:string ip_address:string port:int = DcOption; -config#3e6f732a date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int broadcast_size_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int disabled_features:Vector = Config; +config#68bac247 date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int broadcast_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int disabled_features:Vector = Config; nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc; @@ -375,11 +375,7 @@ help.noAppUpdate#c45a6536 = help.AppUpdate; help.inviteText#18cb9f78 message:string = help.InviteText; -messages.statedMessagesLinks#51be5d19 messages:Vector chats:Vector users:Vector pts:int pts_count:int links:Vector seq:int = messages.StatedMessages; - -messages.statedMessageLink#948a288 message:Message chats:Vector users:Vector pts:int pts_count:int links:Vector seq:int = messages.StatedMessage; - -messages.sentMessageLink#e923400d id:int date:int pts:int pts_count:int links:Vector seq:int = messages.SentMessage; +messages.sentMessageLink#35a1a663 id:int date:int media:MessageMedia pts:int pts_count:int links:Vector seq:int = messages.SentMessage; inputGeoChat#74d456fa chat_id:int access_hash:long = InputGeoChat; @@ -529,9 +525,6 @@ account.sentChangePhoneCode#a4f58c4c phone_code_hash:string send_call_timeout:in updateUserPhone#12b9417b user_id:int phone:string = Update; -account.noPassword#5770e7a9 new_salt:bytes = account.Password; -account.password#739e5f72 current_salt:bytes new_salt:bytes hint:string = account.Password; - documentAttributeImageSize#6c37c15c w:int h:int = DocumentAttribute; documentAttributeAnimated#11b58939 = DocumentAttribute; documentAttributeSticker#994c9882 alt:string = DocumentAttribute; @@ -559,6 +552,27 @@ contactLinkNone#feedd3ad = ContactLink; contactLinkHasPhone#268f3f59 = ContactLink; contactLinkContact#d502c2d0 = ContactLink; +updateWebPage#2cc36971 webpage:WebPage = Update; + +webPageEmpty#eb1477e8 id:long = WebPage; +webPagePending#c586da1c id:long date:int = WebPage; +webPage#39c1cef9 id:long display_url:string title:string description:string photo:Photo = WebPage; + +messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia; + +authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization; + +account.authorizations#1250abde authorizations:Vector = account.Authorizations; + +account.noPassword#96dabc18 new_salt:bytes email_unconfirmed_pattern:string = account.Password; +account.password#7c18141c current_salt:bytes new_salt:bytes hint:string has_recovery:Bool email_unconfirmed_pattern:string = account.Password; + +account.passwordSettings#b7b72ab3 email:string = account.PasswordSettings; + +account.passwordInputSettings#bcfc532c flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string = account.PasswordInputSettings; + +auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -611,15 +625,15 @@ messages.deleteMessages#a5f18925 id:Vector = messages.AffectedMessages; messages.receivedMessages#28abcb68 max_id:int = Vector; messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool; messages.sendMessage#1ca852a1 peer:InputPeer reply_to_msg_id:int message:string random_id:long = messages.SentMessage; -messages.sendMedia#fcee7fc0 peer:InputPeer reply_to_msg_id:int media:InputMedia random_id:long = messages.StatedMessage; -messages.forwardMessages#ded42045 peer:InputPeer id:Vector random_id:Vector = messages.StatedMessages; +messages.sendMedia#33f6d58c peer:InputPeer reply_to_msg_id:int media:InputMedia random_id:long = Updates; +messages.forwardMessages#55e1728d peer:InputPeer id:Vector random_id:Vector = Updates; messages.getChats#3c6aa187 id:Vector = messages.Chats; messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull; -messages.editChatTitle#b4bc68b5 chat_id:int title:string = messages.StatedMessage; -messages.editChatPhoto#d881821d chat_id:int photo:InputChatPhoto = messages.StatedMessage; -messages.addChatUser#2ee9ee9e chat_id:int user_id:InputUser fwd_limit:int = messages.StatedMessage; -messages.deleteChatUser#c3c5cd23 chat_id:int user_id:InputUser = messages.StatedMessage; -messages.createChat#419d9aee users:Vector title:string = messages.StatedMessage; +messages.editChatTitle#dc452855 chat_id:int title:string = Updates; +messages.editChatPhoto#ca4c79d8 chat_id:int photo:InputChatPhoto = Updates; +messages.addChatUser#f9a0aa09 chat_id:int user_id:InputUser fwd_limit:int = Updates; +messages.deleteChatUser#e0611f16 chat_id:int user_id:InputUser = Updates; +messages.createChat#9cb126e users:Vector title:string = Updates; updates.getState#edd4882a = updates.State; updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference; @@ -639,8 +653,8 @@ help.getInviteText#a4a95186 lang_code:string = help.InviteText; photos.getUserPhotos#b7ee553c user_id:InputUser offset:int max_id:int limit:int = photos.Photos; -messages.forwardMessage#3f3f4f2 peer:InputPeer id:int random_id:long = messages.StatedMessage; -messages.sendBroadcast#41bb0972 contacts:Vector message:string media:InputMedia = messages.StatedMessages; +messages.forwardMessage#33963bf9 peer:InputPeer id:int random_id:long = Updates; +messages.sendBroadcast#bf73f4da contacts:Vector random_id:Vector message:string media:InputMedia = Updates; geochats.getLocated#7f192d8f geo_point:InputGeoPoint radius:int limit:int = geochats.Located; geochats.getRecents#e1427e6f offset:int limit:int = geochats.Messages; @@ -693,12 +707,17 @@ contacts.resolveUsername#bf0131c username:string = User; account.sendChangePhoneCode#a407a8f4 phone_number:string = account.SentChangePhoneCode; account.changePhone#70c32edb phone_number:string phone_code_hash:string phone_code:string = User; -account.getPassword#548a30f5 = account.Password; -account.setPassword#dd2a4d8f current_password_hash:bytes new_salt:bytes new_password_hash:bytes hint:string = Bool; - -auth.checkPassword#a63011e password_hash:bytes = auth.Authorization; messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers; messages.getAllStickers#aa3bc868 hash:string = messages.AllStickers; -account.updateDeviceLocked#38df3532 period:int = Bool; \ No newline at end of file +account.updateDeviceLocked#38df3532 period:int = Bool; +account.getAuthorizations#e320c158 = account.Authorizations; +account.resetAuthorization#df77f3bc hash:long = Bool; +account.getPassword#548a30f5 = account.Password; +account.getPasswordSettings#bc8d11bb current_password_hash:bytes = account.PasswordSettings; +account.updatePasswordSettings#fa7c4b86 current_password_hash:bytes new_settings:account.PasswordInputSettings = Bool; + +auth.checkPassword#a63011e password_hash:bytes = auth.Authorization; +auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery; +auth.recoverPassword#4ea56e92 code:string = auth.Authorization; \ No newline at end of file diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 73da06f58..12985f481 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -25,7 +25,6 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "boxes/confirmbox.h" #include "boxes/photocropbox.h" #include "application.h" -#include "boxes/addparticipantbox.h" #include "gui/filedialog.h" // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index 6ef0ed612..4c1789428 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -25,7 +25,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "boxes/confirmbox.h" #include "boxes/photocropbox.h" #include "application.h" -#include "boxes/addparticipantbox.h" +#include "boxes/contactsbox.h" #include "gui/filedialog.h" ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const PeerData *peer) : TWidget(0), @@ -197,8 +197,7 @@ void ProfileInner::onClearHistorySure() { } void ProfileInner::onAddParticipant() { - AddParticipantBox *box = new AddParticipantBox(_peerChat); - App::wnd()->showLayer(box); + App::wnd()->showLayer(new ContactsBox(_peerChat)); } void ProfileInner::onUpdatePhotoCancel() { diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index 20c8b70c7..9ce13311e 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -1721,7 +1721,7 @@ bool _execUpdater(bool update = true) { QByteArray data(QFile::encodeName(cExeDir() + "Updater")); memcpy(path, data.constData(), data.size()); - char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_path[] = "-workpath", p_startintray[] = "-startintray"; + char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_path[] = "-workpath", p_startintray[] = "-startintray", p_testmode[] = "-testmode"; char p_datafile[MaxLen] = {0}, p_pathbuf[MaxLen] = {0}; int argIndex = 0; args[argIndex++] = path; @@ -1732,7 +1732,8 @@ bool _execUpdater(bool update = true) { if (cFromAutoStart()) args[argIndex++] = p_autostart; if (cDebug()) args[argIndex++] = p_debug; if (cStartInTray()) args[argIndex++] = p_startintray; - if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) { + if (cTestMode()) args[argIndex++] = p_testmode; + if (cDataFile() != qsl("data")) { QByteArray dataf = QFile::encodeName(cDataFile()); if (dataf.size() < MaxLen) { memcpy(p_datafile, dataf.constData(), dataf.size()); diff --git a/Telegram/SourceFiles/pspecific_mac_p.mm b/Telegram/SourceFiles/pspecific_mac_p.mm index fb8f6c39b..fe5c91c15 100644 --- a/Telegram/SourceFiles/pspecific_mac_p.mm +++ b/Telegram/SourceFiles/pspecific_mac_p.mm @@ -915,7 +915,8 @@ BOOL _execUpdater(BOOL update = YES) { if (cFromAutoStart()) [args addObject:@"-autostart"]; if (cDebug()) [args addObject:@"-debug"]; if (cStartInTray()) [args addObject:@"-startintray"]; - if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) { + if (cTestMode()) [args addObject:@"-testmode"]; + if (cDataFile() != qsl("data")) { [args addObject:@"-key"]; [args addObject:QNSString(cDataFile()).s()]; } diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index 287b9987b..1ec5d4231 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -1729,8 +1729,9 @@ void PsUpdateDownloader::unpackUpdate() { fVersion.close(); } - if (!tempDir.rename(tempDir.absolutePath(), readyDir.absolutePath())) { - LOG(("Update Error: cant rename temp dir '%1' to ready dir '%2'").arg(tempDir.absolutePath()).arg(readyDir.absolutePath())); + QFile tempDirFile(tempDir.absolutePath()); + if (!tempDirFile.rename(readyDir.absolutePath())) { + LOG(("Update Error: cant rename temp dir '%1' to ready dir '%2', error %3: %4").arg(tempDir.absolutePath()).arg(readyDir.absolutePath()).arg(tempDirFile.error()).arg(tempDirFile.errorString())); return fatalFail(); } deleteDir(tempDirPath); @@ -2476,7 +2477,8 @@ void psExecTelegram() { if (cFromAutoStart()) targs += qsl(" -autostart"); if (cDebug()) targs += qsl(" -debug"); if (cStartInTray()) targs += qsl(" -startintray"); - if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) targs += qsl(" -key \"") + cDataFile() + '"'; + if (cTestMode()) targs += qsl(" -testmode"); + if (cDataFile() != qsl("data")) targs += qsl(" -key \"") + cDataFile() + '"'; QString telegram(QDir::toNativeSeparators(cExeDir() + QString::fromWCharArray(AppFile) + qsl(".exe"))), wdir(QDir::toNativeSeparators(cWorkingDir())); diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index d399a799c..a1015086a 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -94,6 +94,8 @@ RecentStickerPack gRecentStickers; RecentHashtagPack gRecentWriteHashtags, gRecentSearchHashtags; +bool gPasswordRecovered = false; + int32 gLang = -2; // auto QString gLangFile; diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index 6f58db58b..fa0be104a 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -181,6 +181,8 @@ typedef QList > RecentHashtagPack; DeclareSetting(RecentHashtagPack, RecentWriteHashtags); DeclareSetting(RecentHashtagPack, RecentSearchHashtags); +DeclareSetting(bool, PasswordRecovered); + inline void incrementRecentHashtag(RecentHashtagPack &recent, const QString &tag) { RecentHashtagPack::iterator i = recent.begin(), e = recent.end(); for (; i != e; ++i) { diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp index d753602f6..a6c0629c6 100644 --- a/Telegram/SourceFiles/settingswidget.cpp +++ b/Telegram/SourceFiles/settingswidget.cpp @@ -33,6 +33,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include "boxes/languagebox.h" #include "boxes/passcodebox.h" #include "boxes/autolockbox.h" +#include "boxes/sessionsbox.h" #include "langloaderplain.h" #include "gui/filedialog.h" @@ -176,21 +177,26 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), _autoLock(this, (cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600)), _autoLockText(lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive) + ' '), _autoLockWidth(st::linkFont->m.width(_autoLockText)), + _passwordEdit(this, lang(lng_cloud_password_set)), + _passwordTurnOff(this, lang(lng_passcode_turn_off)), + _hasPasswordRecovery(false), _connectionType(this, lng_connection_auto(lt_type, QString())), _connectionTypeText(lang(lng_connection_type) + ' '), _connectionTypeWidth(st::linkFont->m.width(_connectionTypeText)), - _resetSessions(this, lang(lng_settings_reset)), - _logOut(this, lang(lng_settings_logout), st::btnLogout), - _resetDone(false) + _showSessions(this, lang(lng_settings_show_sessions)), + _logOut(this, lang(lng_settings_logout), st::btnLogout) { if (self()) { _nameText.setText(st::setNameFont, _nameCache, _textNameOptions); PhotoData *selfPhoto = self()->photoId ? App::photo(self()->photoId) : 0; if (selfPhoto && selfPhoto->date) _photoLink = TextLinkPtr(new PhotoLink(selfPhoto, self())); - MTP::send(MTPusers_GetFullUser(self()->inputUser), rpcDone(&SettingsInner::gotFullSelf)); + MTP::send(MTPusers_GetFullUser(self()->inputUser), rpcDone(&SettingsInner::gotFullSelf), RPCFailHandlerPtr(), 0, 10); + onReloadPassword(); connect(App::main(), SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(peerUpdated(PeerData *))); connect(App::main(), SIGNAL(peerNameChanged(PeerData *, const PeerData::Names &, const PeerData::NameFirstChars &)), this, SLOT(peerUpdated(PeerData *))); + + connect(App::app(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(onReloadPassword(Qt::ApplicationState))); } // profile @@ -276,8 +282,10 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent), connect(&_passcodeEdit, SIGNAL(clicked()), this, SLOT(onPasscode())); connect(&_passcodeTurnOff, SIGNAL(clicked()), this, SLOT(onPasscodeOff())); connect(&_autoLock, SIGNAL(clicked()), this, SLOT(onAutoLock())); + connect(&_passwordEdit, SIGNAL(clicked()), this, SLOT(onPassword())); + connect(&_passwordTurnOff, SIGNAL(clicked()), this, SLOT(onPasswordOff())); connect(&_connectionType, SIGNAL(clicked()), this, SLOT(onConnectionType())); - connect(&_resetSessions, SIGNAL(clicked()), this, SLOT(onResetSessions())); + connect(&_showSessions, SIGNAL(clicked()), this, SLOT(onShowSessions())); connect(&_logOut, SIGNAL(clicked()), App::wnd(), SLOT(onLogout())); if (App::main()) { @@ -598,13 +606,11 @@ void SettingsInner::paintEvent(QPaintEvent *e) { p.drawText(_left, top + st::linkFont->ascent, _autoLockText); top += _autoLock.height() + st::setLittleSkip; } + if (!_waitingConfirm.isEmpty()) p.drawText(_left, top + st::linkFont->ascent, _waitingConfirm); + top += _passwordEdit.height() + st::setLittleSkip; } p.drawText(_left, _connectionType.y() + st::linkFont->ascent, _connectionTypeText); - - if (self() && _resetDone) { - p.drawText(_resetSessions.x(), _resetSessions.y() + st::linkFont->ascent, lang(lng_settings_reset_done)); - } } void SettingsInner::resizeEvent(QResizeEvent *e) { @@ -704,11 +710,13 @@ void SettingsInner::resizeEvent(QResizeEvent *e) { if (cHasPasscode()) { _autoLock.move(_left + _autoLockWidth, top); top += _autoLock.height() + st::setLittleSkip; } + _passwordEdit.move(_left, top); + _passwordTurnOff.move(_left + st::setWidth - _passwordTurnOff.width(), top); top += _passwordTurnOff.height() + st::setLittleSkip; } _connectionType.move(_left + _connectionTypeWidth, top); top += _connectionType.height() + st::setLittleSkip; if (self()) { - _resetSessions.move(_left, top); top += _resetSessions.height() + st::setSectionSkip; + _showSessions.move(_left, top); top += _showSessions.height() + st::setSectionSkip; _logOut.move(_left, top); } } @@ -717,6 +725,30 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { App::wnd()->showSettings(); } + _secretText += e->text().toLower(); + int32 size = _secretText.size(), from = 0; + while (size > from) { + QStringRef str(_secretText.midRef(from)); + if (str == QLatin1String("debugmode")) { + QString text = cDebug() ? qsl("Do you want to disable DEBUG logs?") : qsl("Do you want to enable DEBUG logs?\n\nAll network events will be logged."); + ConfirmBox *box = new ConfirmBox(text); + connect(box, SIGNAL(confirmed()), App::app(), SLOT(onSwitchDebugMode())); + App::wnd()->showLayer(box); + from = size; + break; + } else if (str == QLatin1String("testmode")) { + QString text = cTestMode() ? qsl("Do you want to disable TEST mode?") : qsl("Do you want to enable TEST mode?\n\nYou will be switched to test cloud."); + ConfirmBox *box = new ConfirmBox(text); + connect(box, SIGNAL(confirmed()), App::app(), SLOT(onSwitchTestMode())); + App::wnd()->showLayer(box); + from = size; + break; + } else if (qsl("debugmode").startsWith(str) || qsl("testmode").startsWith(str)) { + break; + } + ++from; + } + _secretText = (size > from) ? _secretText.mid(from) : QString(); } void SettingsInner::mouseMoveEvent(QMouseEvent *e) { @@ -804,6 +836,7 @@ void SettingsInner::passcodeChanged() { resizeEvent(0); _passcodeEdit.setText(lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on)); _autoLock.setText((cAutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, cAutoLock() / 60) : lng_passcode_autolock_hours(lt_count, cAutoLock() / 3600)); +// _passwordEdit.setText() showAll(); } @@ -823,6 +856,48 @@ void SettingsInner::gotFullSelf(const MTPUserFull &selfFull) { } } +void SettingsInner::gotPassword(const MTPaccount_Password &result) { + _waitingConfirm = QString(); + + switch (result.type()) { + case mtpc_account_noPassword: { + const MTPDaccount_noPassword &d(result.c_account_noPassword()); + _curPasswordSalt = QByteArray(); + _hasPasswordRecovery = false; + _curPasswordHint = QString(); + _newPasswordSalt = qba(d.vnew_salt); + QString pattern = qs(d.vemail_unconfirmed_pattern); + if (!pattern.isEmpty()) _waitingConfirm = lng_cloud_password_waiting(lt_email, pattern); + } break; + + case mtpc_account_password: { + const MTPDaccount_password &d(result.c_account_password()); + _curPasswordSalt = qba(d.vcurrent_salt); + _hasPasswordRecovery = d.vhas_recovery.v; + _curPasswordHint = qs(d.vhint); + _newPasswordSalt = qba(d.vnew_salt); + QString pattern = qs(d.vemail_unconfirmed_pattern); + if (!pattern.isEmpty()) _waitingConfirm = lng_cloud_password_waiting(lt_email, pattern); + } break; + } + _waitingConfirm = st::linkFont->m.elidedText(_waitingConfirm, Qt::ElideRight, st::setWidth - _passwordTurnOff.width()); + _passwordEdit.setText(lang(_curPasswordSalt.isEmpty() ? lng_cloud_password_set : lng_cloud_password_edit)); + showAll(); + update(); + + _newPasswordSalt.resize(_newPasswordSalt.size() + 8); + memset_rand(_newPasswordSalt.data() + _newPasswordSalt.size() - 8, 8); +} + +void SettingsInner::offPasswordDone(const MTPBool &result) { + onReloadPassword(); +} + +bool SettingsInner::offPasswordFail(const RPCError &error) { + onReloadPassword(); + return true; +} + void SettingsInner::usernameChanged() { _chooseUsername.setText((self() && !self()->username.isEmpty()) ? ('@' + self()->username) : lang(lng_settings_choose_username)); showAll(); @@ -958,17 +1033,25 @@ void SettingsInner::showAll() { _autoLock.hide(); _passcodeTurnOff.hide(); } - if (_resetDone) { - _resetSessions.hide(); + if (_waitingConfirm.isEmpty()) { + _passwordEdit.show(); } else { - _resetSessions.show(); + _passwordEdit.hide(); } + if (_curPasswordSalt.isEmpty() && _waitingConfirm.isEmpty()) { + _passwordTurnOff.hide(); + } else { + _passwordTurnOff.show(); + } + _showSessions.show(); _logOut.show(); } else { _passcodeEdit.hide(); _autoLock.hide(); _passcodeTurnOff.hide(); - _resetSessions.hide(); + _passwordEdit.hide(); + _passwordTurnOff.hide(); + _showSessions.hide(); _logOut.hide(); } } @@ -1017,25 +1100,11 @@ void SettingsInner::onUpdatePhoto() { App::wnd()->showLayer(box); } -void SettingsInner::onResetSessions() { - ConfirmBox *box = new ConfirmBox(lang(lng_settings_reset_sure), lang(lng_settings_reset_button)); - connect(box, SIGNAL(confirmed()), this, SLOT(onResetSessionsSure())); +void SettingsInner::onShowSessions() { + SessionsBox *box = new SessionsBox(); App::wnd()->showLayer(box); } -void SettingsInner::onResetSessionsSure() { - App::wnd()->layerHidden(); - MTP::send(MTPauth_ResetAuthorizations(), rpcDone(&SettingsInner::doneResetSessions)); -} - -void SettingsInner::doneResetSessions(const MTPBool &res) { - if (res.v) { - _resetDone = true; - showAll(); - update(); - } -} - void SettingsInner::onChangeLanguage() { if ((_changeLanguage.clickModifiers() & Qt::ShiftModifier) && (_changeLanguage.clickModifiers() & Qt::AltModifier)) { QString file; @@ -1123,6 +1192,33 @@ void SettingsInner::onPasscodeOff() { App::wnd()->showLayer(box); } +void SettingsInner::onPassword() { + PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint); + connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword())); + App::wnd()->showLayer(box); +} + +void SettingsInner::onPasswordOff() { + if (_curPasswordSalt.isEmpty()) { + _passwordTurnOff.hide(); + +// int32 flags = MTPDaccount_passwordInputSettings::flag_new_salt | MTPDaccount_passwordInputSettings::flag_new_password_hash | MTPDaccount_passwordInputSettings::flag_hint | MTPDaccount_passwordInputSettings::flag_email; + int32 flags = MTPDaccount_passwordInputSettings::flag_email; + MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_int(flags), MTP_string(QByteArray()), MTP_string(QByteArray()), MTP_string(QString()), MTP_string(QString()))); + MTP::send(MTPaccount_UpdatePasswordSettings(MTP_string(QByteArray()), settings), rpcDone(&SettingsInner::offPasswordDone), rpcFail(&SettingsInner::offPasswordFail)); + } else { + PasscodeBox *box = new PasscodeBox(_newPasswordSalt, _curPasswordSalt, _hasPasswordRecovery, _curPasswordHint, true); + connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword())); + App::wnd()->showLayer(box); + } +} + +void SettingsInner::onReloadPassword(Qt::ApplicationState state) { + if (state == Qt::ApplicationActive) { + MTP::send(MTPaccount_GetPassword(), rpcDone(&SettingsInner::gotPassword)); + } +} + void SettingsInner::onAutoLock() { AutoLockBox *box = new AutoLockBox(); connect(box, SIGNAL(closed()), this, SLOT(passcodeChanged())); diff --git a/Telegram/SourceFiles/settingswidget.h b/Telegram/SourceFiles/settingswidget.h index 851cde1c0..1de46a36c 100644 --- a/Telegram/SourceFiles/settingswidget.h +++ b/Telegram/SourceFiles/settingswidget.h @@ -102,6 +102,9 @@ public slots: void onPasscode(); void onPasscodeOff(); void onAutoLock(); + void onPassword(); + void onPasswordOff(); + void onReloadPassword(Qt::ApplicationState state = Qt::ApplicationActive); void onConnectionType(); @@ -148,8 +151,7 @@ public slots: void onUpdateReady(); void onUpdateFailed(); - void onResetSessions(); - void onResetSessionsSure(); + void onShowSessions(); void onPhotoUpdateDone(PeerId peer); void onPhotoUpdateFail(PeerId peer); @@ -162,12 +164,11 @@ public slots: private: - void doneResetSessions(const MTPBool &res); void saveError(const QString &str = QString()); void setScale(DBIScale newScale); - QString _testlang; + QString _testlang, _secretText; UserData *_self; UserData *self() const { @@ -251,17 +252,26 @@ private: LinkButton _passcodeEdit, _passcodeTurnOff, _autoLock; QString _autoLockText; int32 _autoLockWidth; + LinkButton _passwordEdit, _passwordTurnOff; + QString _waitingConfirm; + QByteArray _curPasswordSalt; + bool _hasPasswordRecovery; + QString _curPasswordHint; + QByteArray _newPasswordSalt; LinkButton _connectionType; QString _connectionTypeText; int32 _connectionTypeWidth; - LinkButton _resetSessions; + LinkButton _showSessions; FlatButton _logOut; - bool _resetDone; + void gotPassword(const MTPaccount_Password &result); + void offPasswordDone(const MTPBool &result); + bool offPasswordFail(const RPCError &error); void setUpdatingState(UpdatingState state, bool force = false); void setDownloadProgress(qint64 ready, qint64 total); + }; class SettingsWidget : public QWidget, public Animated { diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index 1409cee02..ed30365cd 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -26,6 +26,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org #include #include #include +#include +#include #include #include diff --git a/Telegram/SourceFiles/types.cpp b/Telegram/SourceFiles/types.cpp index a6f69e150..f097dd627 100644 --- a/Telegram/SourceFiles/types.cpp +++ b/Telegram/SourceFiles/types.cpp @@ -189,8 +189,8 @@ namespace { char buf[16]; memcpy(buf, &_msStart, 8); memcpy(buf + 8, &_msFreq, 8); - uchar sha1Buffer[20]; - RAND_seed(hashSha1(buf, 16, sha1Buffer), 20); + uchar sha256Buffer[32]; + RAND_seed(hashSha256(buf, 16, sha256Buffer), 32); if (!RAND_status()) { LOG(("MTP Error: Could not init OpenSSL rand, RAND_status() is 0..")); } @@ -344,83 +344,12 @@ int32 hashCrc32(const void *data, uint32 len) { return crc ^ 0xffffffff; } -// sha1 hash, taken somewhere from the internet - -namespace{ - inline uint32 sha1Shift(uint32 v, uint32 shift) { - return ((v << shift) | (v >> (32 - shift))); - } - void sha1PartHash(uint32 *sha, uint32 *temp) - { - uint32 a = sha[0], b = sha[1], c = sha[2], d = sha[3], e = sha[4], round = 0; - - #define _shiftswap(f, v) { \ - uint32 t = sha1Shift(a, 5) + (f) + e + v + temp[round]; \ - e = d; \ - d = c; \ - c = sha1Shift(b, 30); \ - b = a; \ - a = t; \ - ++round; \ - } - #define _shiftshiftswap(f, v) { \ - temp[round] = sha1Shift((temp[round - 3] ^ temp[round - 8] ^ temp[round - 14] ^ temp[round - 16]), 1); \ - _shiftswap(f, v) \ - } - - while (round < 16) _shiftswap((b & c) | (~b & d), 0x5a827999) - while (round < 20) _shiftshiftswap((b & c) | (~b & d), 0x5a827999) - while (round < 40) _shiftshiftswap(b ^ c ^ d, 0x6ed9eba1) - while (round < 60) _shiftshiftswap((b & c) | (b & d) | (c & d), 0x8f1bbcdc) - while (round < 80) _shiftshiftswap(b ^ c ^ d, 0xca62c1d6) - - #undef _shiftshiftswap - #undef _shiftswap - - sha[0] += a; - sha[1] += b; - sha[2] += c; - sha[3] += d; - sha[4] += e; - } +int32 *hashSha1(const void *data, uint32 len, void *dest) { + return (int32*)SHA1((const uchar*)data, (size_t)len, (uchar*)dest); } -int32 *hashSha1(const void *data, uint32 len, void *dest) { - const uchar *buf = (const uchar *)data; - - uint32 temp[80], block = 0, end; - uint32 sha[5] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}; - for (end = block + 64; block + 64 <= len; end = block + 64) { - for (uint32 i = 0; block < end; block += 4) { - temp[i++] = (uint32) buf[block + 3] - | (((uint32) buf[block + 2]) << 8) - | (((uint32) buf[block + 1]) << 16) - | (((uint32) buf[block]) << 24); - } - sha1PartHash(sha, temp); - } - - end = len - block; - memset(temp, 0, sizeof(uint32) * 16); - uint32 last = 0; - for (; last < end; ++last) { - temp[last >> 2] |= (uint32)buf[last + block] << ((3 - (last & 0x03)) << 3); - } - temp[last >> 2] |= 0x80 << ((3 - (last & 3)) << 3); - if (end >= 56) { - sha1PartHash(sha, temp); - memset(temp, 0, sizeof(uint32) * 16); - } - temp[15] = len << 3; - sha1PartHash(sha, temp); - - uchar *sha1To = (uchar*)dest; - - for (int32 i = 19; i >= 0; --i) { - sha1To[i] = (sha[i >> 2] >> (((3 - i) & 0x03) << 3)) & 0xFF; - } - - return (int32*)sha1To; +int32 *hashSha256(const void *data, uint32 len, void *dest) { + return (int32*)SHA256((const uchar*)data, (size_t)len, (uchar*)dest); } // md5 hash, taken somewhere from the internet diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 44ad248b2..f246d1a20 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -156,6 +156,7 @@ private: int32 hashCrc32(const void *data, uint32 len); int32 *hashSha1(const void *data, uint32 len, void *dest); // dest - ptr to 20 bytes, returns (int32*)dest +int32 *hashSha256(const void *data, uint32 len, void *dest); // dest - ptr to 32 bytes, returns (int32*)dest int32 *hashMd5(const void *data, uint32 len, void *dest); // dest = ptr to 16 bytes, returns (int32*)dest char *hashMd5Hex(const int32 *hashmd5, void *dest); // dest = ptr to 32 bytes, returns (char*)dest inline char *hashMd5Hex(const void *data, uint32 len, void *dest) { // dest = ptr to 32 bytes, returns (char*)dest diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h index 72459c8fe..668a433fb 100644 --- a/Telegram/SourceFiles/window.h +++ b/Telegram/SourceFiles/window.h @@ -273,6 +273,7 @@ signals: void resized(const QSize &size); void tempDirCleared(int task); void tempDirClearFailed(int task); + void newAuthorization(); private: diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 37449a285..c333ada45 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -150,11 +150,11 @@ true true - + true true - + true true @@ -270,6 +270,10 @@ true true + + true + true + true true @@ -318,10 +322,6 @@ true true - - true - true - true true @@ -368,6 +368,10 @@ true true + + true + true + true true @@ -404,11 +408,11 @@ true true - + true true - + true true @@ -524,6 +528,10 @@ true true + + true + true + true true @@ -572,10 +580,6 @@ true true - - true - true - true true @@ -622,6 +626,10 @@ true true + + true + true + true true @@ -667,11 +675,11 @@ true true - + true true - + true true @@ -787,6 +795,10 @@ true true + + true + true + true true @@ -835,10 +847,6 @@ true true - - true - true - true true @@ -885,6 +893,10 @@ true true + + true + true + true true @@ -923,8 +935,8 @@ + - @@ -933,10 +945,10 @@ - + @@ -966,6 +978,7 @@ + @@ -1114,20 +1127,6 @@ $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) - - Moc%27ing addparticipantbox.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/boxes/addparticipantbox.h" - Moc%27ing addparticipantbox.h... - Moc%27ing addparticipantbox.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/boxes/addparticipantbox.h" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/boxes/addparticipantbox.h" - $(QTDIR)\bin\moc.exe;%(FullPath) - $(QTDIR)\bin\moc.exe;%(FullPath) - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing confirmbox.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp @@ -1170,20 +1169,6 @@ $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) - - Moc%27ing newgroupbox.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/boxes/newgroupbox.h" - Moc%27ing newgroupbox.h... - Moc%27ing newgroupbox.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/boxes/newgroupbox.h" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/boxes/newgroupbox.h" - $(QTDIR)\bin\moc.exe;%(FullPath) - $(QTDIR)\bin\moc.exe;%(FullPath) - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing photocropbox.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp @@ -1324,6 +1309,34 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/passcodebox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing sessionsbox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/sessionsbox.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing sessionsbox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/sessionsbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing sessionsbox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/sessionsbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing abstractbox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/abstractbox.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing abstractbox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/abstractbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing abstractbox.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/abstractbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + Moc%27ing animation.h... @@ -1673,6 +1686,20 @@ $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing intropwdcheck.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/intro/intropwdcheck.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing intropwdcheck.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/intro/intropwdcheck.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing intropwdcheck.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/intro/intropwdcheck.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" + Moc%27ing layerwidget.h... diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters index 1e69ee80f..842801a95 100644 --- a/Telegram/Telegram.vcxproj.filters +++ b/Telegram/Telegram.vcxproj.filters @@ -168,9 +168,6 @@ boxes - - boxes - boxes @@ -180,9 +177,6 @@ boxes - - boxes - boxes @@ -330,15 +324,6 @@ Generated Files\Release - - Generated Files\Deploy - - - Generated Files\Debug - - - Generated Files\Release - Generated Files\Deploy @@ -618,15 +603,6 @@ Generated Files\Release - - Generated Files\Deploy - - - Generated Files\Debug - - - Generated Files\Release - Generated Files\Deploy @@ -858,6 +834,42 @@ Generated Files\Release + + Generated Files\Deploy + + + Generated Files\Debug + + + Generated Files\Release + + + boxes + + + boxes + + + Generated Files\Deploy + + + Generated Files\Debug + + + Generated Files\Release + + + intro + + + Generated Files\Deploy + + + Generated Files\Debug + + + Generated Files\Release + @@ -1038,9 +1050,6 @@ boxes - - boxes - boxes @@ -1050,9 +1059,6 @@ boxes - - boxes - boxes @@ -1139,6 +1145,15 @@ Source Files + + boxes + + + boxes + + + intro + diff --git a/Telegram/Updater.vcxproj b/Telegram/Updater.vcxproj index 0afe10630..7babc5574 100644 --- a/Telegram/Updater.vcxproj +++ b/Telegram/Updater.vcxproj @@ -126,6 +126,11 @@ + + true + true + true + @@ -134,6 +139,13 @@ + + + true + true + true + + diff --git a/Telegram/Updater.vcxproj.filters b/Telegram/Updater.vcxproj.filters index f35e8301b..f5945efd7 100644 --- a/Telegram/Updater.vcxproj.filters +++ b/Telegram/Updater.vcxproj.filters @@ -17,5 +17,9 @@ + + + + \ No newline at end of file