2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-09-01 15:05:56 +00:00

initial commit for 0.4.18 version of Telegram Desktop

This commit is contained in:
John Preston
2014-05-30 12:53:19 +04:00
parent 6d9ac2c475
commit 4221fe666f
1933 changed files with 137552 additions and 3 deletions

View File

@@ -0,0 +1,297 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#include "stdafx.h"
#include "lang.h"
#include "style.h"
#include "intro/intro.h"
#include "intro/introsteps.h"
#include "intro/introphone.h"
#include "intro/introcode.h"
#include "intro/introsignup.h"
#include "mainwidget.h"
#include "window.h"
#include "application.h"
#include "gui/text.h"
namespace {
IntroWidget *signalEmitOn = 0;
QString countryForReg;
void gotNearestDC(const MTPNearestDc &result) {
const MTPDnearestDc &nearest(result.c_nearestDc());
DEBUG_LOG(("Got nearest dc, country: %1, nearest: %2, this: %3").arg(nearest.vcountry.c_string().v.c_str()).arg(nearest.vnearest_dc.v).arg(nearest.vthis_dc.v));
MTP::setdc(result.c_nearestDc().vnearest_dc.v, true);
if (countryForReg != nearest.vcountry.c_string().v.c_str()) {
countryForReg = nearest.vcountry.c_string().v.c_str();
emit signalEmitOn->countryChanged();
}
if (App::app()) App::app()->startUpdateCheck();
}
}
IntroWidget::IntroWidget(Window *window) : QWidget(window),
wnd(window), cacheForHideInd(0), cacheForShowInd(0), _callTimeout(60),
steps(new IntroSteps(this)), phone(0), code(0), signup(0), current(0), moving(0), visibilityChanging(0) {
setGeometry(QRect(0, st::titleHeight, wnd->width(), wnd->height() - st::titleHeight));
countryForReg = psCurrentCountry();
MTP::send(MTPhelp_GetNearestDc(), rpcDone(gotNearestDC));
signalEmitOn = this;
stages[0] = steps;
memset(stages + 1, 0, sizeof(QWidget*) * 3);
connect(window, SIGNAL(resized(const QSize &)), this, SLOT(onParentResize(const QSize &)));
show();
setFocus();
}
void IntroWidget::onParentResize(const QSize &newSize) {
resize(newSize);
}
void IntroWidget::onIntroBack() {
if (!current) return;
moving = -1;
prepareMove();
}
void IntroWidget::onIntroNext() {
if (!createNext()) return;
moving = 1;
prepareMove();
}
bool IntroWidget::createNext() {
if (current == sizeof(stages) / sizeof(stages[0]) - 1) return false;
if (!stages[current + 1]) {
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;
}
}
return true;
}
void IntroWidget::prepareMove() {
if (cacheForHide.isNull() || cacheForHideInd != current) makeHideCache();
if (cacheForShow.isNull() || cacheForShowInd != current + moving) makeShowCache();
xCoordHide = anim::ivalue(0, -moving * st::introSlideShift);
cAlphaHide = anim::fvalue(1, 0);
xCoordShow = anim::ivalue(moving * st::introSlideShift, 0);
cAlphaShow = anim::fvalue(0, 1);
anim::start(this);
stages[current]->deactivate();
stages[current + moving]->hide();
}
void IntroWidget::onDoneStateChanged(int oldState, ButtonStateChangeSource source) {
if (animating()) return;
if (source == ButtonByPress) {
if (oldState & Button::StateDown) {
cacheForHide = QPixmap();
} else {
makeHideCache();
}
} else if (source == ButtonByHover) {
if (!createNext()) return;
if (!cacheForShow) makeShowCache(current + 1);
}
}
void IntroWidget::makeHideCache(int stage) {
if (stage < 0) stage = current;
int w = st::introSize.width(), h = st::introSize.height();
cacheForHide = stages[stage]->grab(QRect(st::introSlideShift, 0, w, h));
cacheForHideInd = stage;
}
void IntroWidget::makeShowCache(int stage) {
if (stage < 0) stage = current + moving;
int w = st::introSize.width(), h = st::introSize.height();
cacheForShow = stages[stage]->grab(QRect(st::introSlideShift, 0, w, h));
cacheForShowInd = stage;
}
void IntroWidget::animShow(const QPixmap &bgAnimCache, bool back) {
_bgAnimCache = bgAnimCache;
anim::stop(this);
stages[current]->show();
_animCache = grab(rect());
visibilityChanging = 1;
a_coord = back ? anim::ivalue(-st::introSlideShift, 0) : anim::ivalue(st::introSlideShift, 0);
a_alpha = anim::fvalue(0, 1);
a_bgCoord = back ? anim::ivalue(0, st::introSlideShift) : anim::ivalue(0, -st::introSlideShift);
a_bgAlpha = anim::fvalue(1, 0);
stages[current]->deactivate();
stages[current]->hide();
anim::start(this);
show();
}
bool IntroWidget::animStep(float64 ms) {
float64 fullDuration = st::introSlideDelta + st::introSlideDuration, dt = ms / fullDuration;
float64 dt1 = (ms > st::introSlideDuration) ? 1 : (ms / st::introSlideDuration), dt2 = (ms > st::introSlideDelta) ? (ms - st::introSlideDelta) / (st::introSlideDuration) : 0;
bool res = true;
if (visibilityChanging) {
if (dt2 >= 1) {
res = false;
a_bgCoord.finish();
a_bgAlpha.finish();
a_coord.finish();
a_alpha.finish();
_animCache = _bgAnimCache = QPixmap();
visibilityChanging = 0;
setFocus();
stages[current]->show();
stages[current]->activate();
} else {
a_bgCoord.update(dt1, st::introHideFunc);
a_bgAlpha.update(dt1, st::introAlphaHideFunc);
a_coord.update(dt2, st::introShowFunc);
a_alpha.update(dt2, st::introAlphaShowFunc);
}
} else if (dt >= 1) {
res = false;
xCoordShow.finish();
cAlphaShow.finish();
cacheForHide = cacheForShow = QPixmap();
current += moving;
moving = 0;
setFocus();
stages[current]->activate();
} else {
xCoordShow.update(dt2, st::introShowFunc);
cAlphaShow.update(dt2, st::introAlphaShowFunc);
xCoordHide.update(dt1, st::introHideFunc);
cAlphaHide.update(dt1, st::introAlphaHideFunc);
}
update();
return res;
}
void IntroWidget::paintEvent(QPaintEvent *e) {
bool trivial = (rect() == e->rect());
setMouseTracking(true);
QPainter p(this);
if (!trivial) {
p.setClipRect(e->rect());
}
if (animating()) {
if (visibilityChanging) {
p.setOpacity(a_bgAlpha.current());
p.drawPixmap(a_bgCoord.current(), 0, _bgAnimCache);
p.setOpacity(a_alpha.current());
p.drawPixmap(a_coord.current(), 0, _animCache);
} else {
p.setOpacity(cAlphaHide.current());
p.drawPixmap(stages[current]->x() + st::introSlideShift + xCoordHide.current(), stages[current]->y(), cacheForHide.width(), cacheForHide.height(), cacheForHide);
p.setOpacity(cAlphaShow.current());
p.drawPixmap(stages[current + moving]->x() + st::introSlideShift + xCoordShow.current(), stages[current + moving]->y(), cacheForShow.width(), cacheForShow.height(), cacheForShow);
}
}
}
QRect IntroWidget::innerRect() const {
int innerWidth = st::introSize.width() + 2 * st::introSlideShift, innerHeight = st::introSize.height();
return QRect((width() - innerWidth) / 2, (height() - innerHeight) / 2, innerWidth, (height() + innerHeight) / 2);
}
QString IntroWidget::currentCountry() const {
return countryForReg;
}
void IntroWidget::setPhone(const QString &phone, const QString &phone_hash, bool registered) {
_phone = phone;
_phone_hash = phone_hash;
_registered = registered;
}
void IntroWidget::setCode(const QString &code) {
_code = code;
}
void IntroWidget::setCallTimeout(int32 callTimeout) {
_callTimeout = callTimeout;
}
const QString &IntroWidget::getPhone() const {
return _phone;
}
const QString &IntroWidget::getPhoneHash() const {
return _phone_hash;
}
const QString &IntroWidget::getCode() const {
return _code;
}
int32 IntroWidget::getCallTimeout() const {
return _callTimeout;
}
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);
}
void IntroWidget::mousePressEvent(QMouseEvent *e) {
}
void IntroWidget::finish(const MTPUser &user, const QImage &photo) {
wnd->setupMain(true);
wnd->startMain(user);
if (!photo.isNull()) {
App::app()->uploadProfilePhoto(photo, MTP::authedId());
}
}
void IntroWidget::keyPressEvent(QKeyEvent *e) {
if (animating()) return;
if (e->key() == Qt::Key_Escape) {
stages[current]->onBack();
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return || e->key() == Qt::Key_Space) {
stages[current]->onNext();
}
}
IntroWidget::~IntroWidget() {
delete steps;
delete phone;
delete code;
delete signup;
if (App::wnd()) App::wnd()->noIntro(this);
}

View File

@@ -0,0 +1,124 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#pragma once
#include <QtWidgets/QWidget>
#include "gui/flatbutton.h"
class Window;
class IntroSteps;
class IntroPhone;
class IntroCode;
class IntroSignup;
class IntroStage;
class Text;
class IntroWidget : public QWidget, public Animated {
Q_OBJECT
public:
IntroWidget(Window *window);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
void mousePressEvent(QMouseEvent *e);
void keyPressEvent(QKeyEvent *e);
void animShow(const QPixmap &bgAnimCache, bool back = false);
bool animStep(float64 ms);
QRect innerRect() const;
QString currentCountry() const;
void setPhone(const QString &phone, const QString &phone_hash, bool registered);
void setCode(const QString &code);
void setCallTimeout(int32 callTimeout);
const QString &getPhone() const;
const QString &getPhoneHash() const;
const QString &getCode() const;
int32 getCallTimeout() const;
void finish(const MTPUser &user, const QImage &photo = QImage());
~IntroWidget();
public slots:
void onIntroNext();
void onIntroBack();
void onDoneStateChanged(int oldState, ButtonStateChangeSource source);
void onParentResize(const QSize &newSize);
signals:
void countryChanged();
private:
void makeHideCache(int stage = -1);
void makeShowCache(int stage = -1);
void prepareMove();
bool createNext();
QPixmap cacheForHide, cacheForShow;
int cacheForHideInd, cacheForShowInd;
anim::ivalue xCoordHide, xCoordShow;
anim::fvalue cAlphaHide, cAlphaShow;
QPixmap _animCache, _bgAnimCache;
anim::ivalue a_coord, a_bgCoord;
anim::fvalue a_alpha, a_bgAlpha;
Window *wnd;
IntroSteps *steps;
IntroPhone *phone;
IntroCode *code;
IntroSignup *signup;
IntroStage *stages[4];
int current, moving, visibilityChanging;
QString _phone, _phone_hash;
int32 _callTimeout;
bool _registered;
QString _code;
QString _firstname, _lastname;
};
class IntroStage : public QWidget {
public:
IntroStage(IntroWidget *parent) : QWidget(parent) {
}
virtual void activate() = 0; // show and activate
virtual void deactivate() = 0; // deactivate and hide
virtual void onNext() = 0;
virtual void onBack() = 0;
protected:
IntroWidget *intro() {
return qobject_cast<IntroWidget*>(parent());
}
};

View File

@@ -0,0 +1,279 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#include "stdafx.h"
#include "lang.h"
#include "style.h"
#include "application.h"
#include "intro/introcode.h"
#include "intro/intro.h"
CodeInput::CodeInput(QWidget *parent, const style::flatInput &st, const QString &ph) : FlatInput(parent, st, ph) {
}
void CodeInput::correctValue(QKeyEvent *e, const QString &was) {
QString oldText(text()), newText;
int oldPos(cursorPosition()), newPos(-1), oldLen(oldText.length()), digitCount = 0;
for (int i = 0; i < oldLen; ++i) {
if (oldText[i].isDigit()) {
++digitCount;
}
}
if (digitCount > 5) digitCount = 5;
bool strict = (digitCount == 5);
newText.reserve(oldLen);
for (int i = 0; i < oldLen; ++i) {
QChar ch(oldText[i]);
if (ch.isDigit()) {
if (!digitCount--) {
break;
}
newText += ch;
if (strict && !digitCount) {
break;
}
}
if (i == oldPos) {
newPos = newText.length();
}
}
if (newPos < 0) {
newPos = newText.length();
}
if (newText != oldText) {
setText(newText);
if (newPos != oldPos) {
setCursorPosition(newPos);
}
}
if (strict) emit codeEntered();
}
IntroCode::IntroCode(IntroWidget *parent) : IntroStage(parent),
next(this, lang(lng_intro_next), st::btnIntroNext),
back(this, lang(lng_intro_back), st::btnIntroBack),
code(this, st::inpIntroCode, lang(lng_code_ph)), errorAlpha(0), waitTillCall(intro()->getCallTimeout()) {
setVisible(false);
setGeometry(parent->innerRect());
connect(&next, SIGNAL(stateChanged(int, ButtonStateChangeSource)), parent, SLOT(onDoneStateChanged(int, ButtonStateChangeSource)));
connect(&next, SIGNAL(clicked()), this, SLOT(onSubmitCode()));
connect(&back, SIGNAL(clicked()), parent, SLOT(onIntroBack()));
connect(&code, SIGNAL(changed()), this, SLOT(onInputChange()));
connect(&callTimer, SIGNAL(timeout()), this, SLOT(onSendCall()));
connect(&checkRequest, SIGNAL(timeout()), this, SLOT(onCheckRequest()));
}
void IntroCode::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, intro()->getPhone(), style::al_topleft);
p.setFont(st::introFont->f);
p.drawText(textRect, lang(lng_code_desc), style::al_bottomleft);
}
QString callText = lang(lng_code_calling);
if (waitTillCall >= 3600) {
callText = lang(lng_code_call).arg(QString("%1:%2").arg(waitTillCall / 3600).arg((waitTillCall / 60) % 60, 2, 10, QChar('0'))).arg(waitTillCall % 60, 2, 10, QChar('0'));
} else if (waitTillCall > 0) {
callText = lang(lng_code_call).arg(waitTillCall / 60).arg(waitTillCall % 60, 2, 10, QChar('0'));
} else if (waitTillCall < 0) {
callText = lang(lng_code_called);
}
p.drawText(QRect(textRect.left(), code.y() + code.height() + st::introSkip, st::introTextSize.width(), st::introErrHeight), callText, style::al_left);
if (animating() || error.length()) {
p.setOpacity(errorAlpha.current());
p.setFont(st::introErrFont->f);
p.setPen(st::introErrColor->p);
p.drawText(textRect.left(), next.y() + next.height() + st::introErrTop + st::introErrFont->ascent, error);
}
}
void IntroCode::resizeEvent(QResizeEvent *e) {
int sumBack = st::btnIntroNext.width + st::btnIntroBack.width + st::btnIntroSep;
if (e->oldSize().width() != width()) {
int sumNext = st::btnIntroNext.width - st::btnIntroBack.width - st::btnIntroSep;
back.move((width() - sumBack) / 2, st::introBtnTop);
next.move((width() - sumNext) / 2, st::introBtnTop);
code.move((width() - sumBack) / 2, st::introTextSize.height() + 24);
}
textRect = QRect((width() - sumBack) / 2, 0, st::introTextSize.width(), st::introTextSize.height());
}
void IntroCode::showError(const QString &err) {
if (!err.isEmpty()) code.notaBene();
if (!animating() && err == error) return;
if (err.length()) {
error = err;
errorAlpha.start(1);
} else {
errorAlpha.start(0);
}
anim::start(this);
}
bool IntroCode::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 IntroCode::activate() {
waitTillCall = intro()->getCallTimeout();
callTimer.start(1000);
error = "";
errorAlpha = anim::fvalue(0);
show();
code.setDisabled(false);
code.setFocus();
}
void IntroCode::deactivate() {
callTimer.stop();
hide();
code.clearFocus();
}
void IntroCode::stopCheck() {
checkRequest.stop();
}
void IntroCode::onCheckRequest() {
int32 status = MTP::state(sentRequest);
if (status < 0) {
int32 leftms = -status;
if (leftms >= 1000) {
if (sentRequest) {
MTP::cancel(sentRequest);
sentCode = "";
}
sentRequest = 0;
if (!code.isEnabled()) {
code.setDisabled(false);
code.setFocus();
}
}
}
if (!sentRequest && status == MTP::RequestSent) {
stopCheck();
}
}
void IntroCode::codeSubmitDone(const MTPauth_Authorization &result) {
stopCheck();
code.setDisabled(false);
const MTPDauth_authorization &d(result.c_auth_authorization());
if (d.vuser.type() != mtpc_userSelf) { // wtf?
showError(lang(lng_server_error));
return;
}
cSetLoggedPhoneNumber(intro()->getPhone());
intro()->finish(d.vuser);
}
bool IntroCode::codeSubmitFail(const RPCError &error) {
stopCheck();
code.setDisabled(false);
const QString &err = error.type();
if (err == "PHONE_NUMBER_INVALID" || err == "PHONE_CODE_EXPIRED") { // show error
onBack();
return true;
} else if (err == "PHONE_CODE_EMPTY" || err == "PHONE_CODE_INVALID") {
showError(lang(lng_bad_code));
code.setFocus();
return true;
} else if (err == "PHONE_NUMBER_UNOCCUPIED") { // success, need to signUp
intro()->setCode(sentCode);
intro()->onIntroNext();
return true;
}
if (QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err).hasMatch()) {
showError(lang(lng_flood_error));
code.setFocus();
return true;
}
if (cDebug()) { // internal server error
showError(err + ": " + error.description());
} else {
showError(lang(lng_server_error));
}
code.setFocus();
return false;
}
void IntroCode::onInputChange() {
showError("");
if (code.text().length() == 5) onSubmitCode();
}
void IntroCode::onSendCall() {
if (!--waitTillCall) {
callTimer.stop();
MTP::send(MTPauth_SendCall(MTP_string(intro()->getPhone()), MTP_string(intro()->getPhoneHash())), rpcDone(&IntroCode::callDone));
}
update();
}
void IntroCode::callDone(const MTPBool &v) {
if (!waitTillCall) {
waitTillCall = -1;
update();
}
}
void IntroCode::onSubmitCode(bool force) {
if (!force && (code.text() == sentCode || !code.isEnabled())) return;
code.setDisabled(true);
setFocus();
showError("");
checkRequest.start(1000);
sentCode = code.text();
sentRequest = MTP::send(MTPauth_SignIn(MTP_string(intro()->getPhone()), MTP_string(intro()->getPhoneHash()), MTP_string(sentCode)), rpcDone(&IntroCode::codeSubmitDone), rpcFail(&IntroCode::codeSubmitFail));
}
void IntroCode::onNext() {
onSubmitCode();
}
void IntroCode::onBack() {
intro()->onIntroBack();
}

View File

@@ -0,0 +1,89 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#pragma once
#include <QtWidgets/QWidget>
#include "gui/flatbutton.h"
#include "gui/flatinput.h"
#include "intro.h"
class CodeInput : public FlatInput {
Q_OBJECT
public:
CodeInput(QWidget *parent, const style::flatInput &st, const QString &ph);
signals:
void codeEntered();
protected:
void correctValue(QKeyEvent *e, const QString &was);
};
class IntroCode : public IntroStage, public Animated, public RPCSender {
Q_OBJECT
public:
IntroCode(IntroWidget *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
bool animStep(float64 ms);
void activate();
void deactivate();
void onNext();
void onBack();
void codeSubmitDone(const MTPauth_Authorization &result);
bool codeSubmitFail(const RPCError &error);
public slots:
void onSubmitCode(bool force = false);
void onInputChange();
void onSendCall();
void onCheckRequest();
private:
void showError(const QString &err);
void callDone(const MTPBool &v);
void stopCheck();
QString error;
anim::fvalue errorAlpha;
FlatButton next, back;
QRect textRect;
CodeInput code;
QString sentCode;
mtpRequestId sentRequest;
QTimer callTimer;
int32 waitTillCall;
QTimer checkRequest;
};

View File

@@ -0,0 +1,300 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#include "stdafx.h"
#include "lang.h"
#include "style.h"
#include "application.h"
#include "intro/introphone.h"
#include "intro/intro.h"
namespace {
class SignUpLink : public ITextLink {
public:
SignUpLink(IntroPhone *widget) : _widget(widget) {
}
void onClick(Qt::MouseButton) const {
_widget->toSignUp();
}
private:
IntroPhone *_widget;
};
}
IntroPhone::IntroPhone(IntroWidget *parent) : IntroStage(parent), changed(false),
next(this, lang(lng_intro_next), st::btnIntroStart),
country(this, st::introCountry), errorAlpha(0), _signup(this, lang(lng_phone_notreg).replace(qsl("{signup}"), textcmdStartLink(1)).replace(qsl("{/signup}"), textcmdStopLink()), st::introErrLabel), _showSignup(false),
phone(this, st::inpIntroPhone, lang(lng_phone_ph)), code(this, st::inpIntroCountryCode) {
setVisible(false);
setGeometry(parent->innerRect());
connect(&next, SIGNAL(stateChanged(int, ButtonStateChangeSource)), parent, SLOT(onDoneStateChanged(int, ButtonStateChangeSource)));
connect(&next, SIGNAL(clicked()), this, SLOT(onSubmitPhone()));
connect(&phone, SIGNAL(voidBackspace(QKeyEvent*)), &code, SLOT(startErasing(QKeyEvent*)));
connect(&country, SIGNAL(codeChanged(const QString &)), &code, SLOT(codeSelected(const QString &)));
connect(&code, SIGNAL(codeChanged(const QString &)), &country, SLOT(onChooseCode(const QString &)));
connect(&code, SIGNAL(addedToNumber(const QString &)), &phone, SLOT(addedToNumber(const QString &)));
connect(&country, SIGNAL(selectClosed()), this, SLOT(onSelectClose()));
connect(&phone, SIGNAL(changed()), this, SLOT(onInputChange()));
connect(&code, SIGNAL(changed()), this, SLOT(onInputChange()));
connect(intro(), SIGNAL(countryChanged()), this, SLOT(countryChanged()));
connect(&checkRequest, SIGNAL(timeout()), this, SLOT(onCheckRequest()));
_signup.setLink(1, TextLinkPtr(new SignUpLink(this)));
_signup.hide();
_signupCache = _signup.grab(_signup.rect());
if (!country.onChooseCountry(intro()->currentCountry())) {
country.onChooseCountry(qsl("US"));
}
changed = false;
}
void IntroPhone::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_phone_title), style::al_topleft);
p.setFont(st::introFont->f);
p.drawText(textRect, lang(lng_phone_desc), style::al_bottomleft);
}
if (animating() || error.length()) {
p.setOpacity(errorAlpha.current());
p.setFont(st::introErrFont->f);
p.setPen(st::introErrColor->p);
p.drawText(textRect.x(), next.y() + next.height() + st::introErrTop + st::introErrFont->ascent, error);
if (_signup.isHidden() && _showSignup) {
p.drawPixmap(_signup.x(), _signup.y(), _signupCache);
}
}
}
void IntroPhone::resizeEvent(QResizeEvent *e) {
if (e->oldSize().width() != width()) {
next.move((width() - next.width()) / 2, st::introBtnTop);
country.move((width() - country.width()) / 2, st::introTextSize.height() + st::introCountry.top);
int phoneTop = country.y() + country.height() + st::introPhoneTop;
phone.move((width() + country.width()) / 2 - st::inpIntroPhone.width, phoneTop);
code.move((width() - country.width()) / 2, phoneTop);
}
_signup.move((width() - next.width()) / 2, next.y() + next.height() + st::introErrTop * 2 + st::introErrFont->height);
textRect = QRect((width() - next.width()) / 2, 0, st::introTextSize.width(), st::introTextSize.height());
}
void IntroPhone::showError(const QString &err, bool signUp) {
if (!err.isEmpty()) {
phone.notaBene();
_showSignup = signUp;
}
if (!animating() && err == error) return;
if (err.length()) {
error = err;
errorAlpha.start(1);
} else {
errorAlpha.start(0);
}
_signup.hide();
anim::start(this);
}
bool IntroPhone::animStep(float64 ms) {
float64 dt = ms / st::introErrDuration;
bool res = true;
if (dt >= 1) {
res = false;
errorAlpha.finish();
if (!errorAlpha.current()) {
error = "";
_signup.hide();
} else if (!error.isEmpty() && _showSignup) {
_signup.show();
}
} else {
errorAlpha.update(dt, st::introErrFunc);
}
update();
return res;
}
void IntroPhone::countryChanged() {
if (!changed) {
selectCountry(intro()->currentCountry());
}
}
void IntroPhone::onSelectClose() {
phone.setFocus();
}
void IntroPhone::onInputChange() {
changed = true;
showError("");
}
void IntroPhone::disableAll() {
next.setDisabled(true);
phone.setDisabled(true);
country.setDisabled(true);
code.setDisabled(true);
setFocus();
}
void IntroPhone::enableAll(bool failed) {
next.setDisabled(false);
phone.setDisabled(false);
country.setDisabled(false);
code.setDisabled(false);
if (failed) phone.setFocus();
}
void IntroPhone::onSubmitPhone(bool force) {
if (!force && !next.isEnabled()) return;
if (!App::isValidPhone(fullNumber())) {
showError(lang(lng_bad_phone));
phone.setFocus();
return;
}
disableAll();
showError("");
checkRequest.start(1000);
sentPhone = fullNumber();
sentRequest = MTP::send(MTPauth_CheckPhone(MTP_string(sentPhone)), rpcDone(&IntroPhone::phoneCheckDone), rpcFail(&IntroPhone::phoneSubmitFail));
}
void IntroPhone::stopCheck() {
checkRequest.stop();
}
void IntroPhone::onCheckRequest() {
int32 status = MTP::state(sentRequest);
if (status < 0) {
int32 leftms = -status;
if (leftms >= 1000) {
MTP::cancel(sentRequest);
sentRequest = 0;
if (!phone.isEnabled()) enableAll(true);
}
}
if (!sentRequest && status == MTP::RequestSent) {
stopCheck();
}
}
void IntroPhone::phoneCheckDone(const MTPauth_CheckedPhone &result) {
stopCheck();
const MTPDauth_checkedPhone &d(result.c_auth_checkedPhone());
if (d.vphone_registered.v) {
disableAll();
showError("");
checkRequest.start(1000);
sentRequest = MTP::send(MTPauth_SendCode(MTP_string(sentPhone), MTP_int(0), MTP_int(ApiId), MTP_string(ApiHash), MTP_string(Application::lang())), rpcDone(&IntroPhone::phoneSubmitDone), rpcFail(&IntroPhone::phoneSubmitFail));
} else {
showError(lang(lng_bad_phone_noreg), true);
enableAll(true);
}
}
void IntroPhone::phoneSubmitDone(const MTPauth_SentCode &result) {
stopCheck();
enableAll(false);
const MTPDauth_sentCode &d(result.c_auth_sentCode());
intro()->setPhone(sentPhone, d.vphone_code_hash.c_string().v.c_str(), d.vphone_registered.v);
intro()->setCallTimeout(result.c_auth_sentCode().vsend_call_timeout.v);
intro()->onIntroNext();
}
void IntroPhone::toSignUp() {
disableAll();
showError("");
checkRequest.start(1000);
sentRequest = MTP::send(MTPauth_SendCode(MTP_string(sentPhone), MTP_int(0), MTP_int(ApiId), MTP_string(ApiHash), MTP_string(Application::lang())), rpcDone(&IntroPhone::phoneSubmitDone), rpcFail(&IntroPhone::phoneSubmitFail));
}
bool IntroPhone::phoneSubmitFail(const RPCError &error) {
stopCheck();
const QString &err = error.type();
if (err == "PHONE_NUMBER_INVALID") { // show error
showError(lang(lng_bad_phone));
enableAll(true);
return true;
}
if (QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err).hasMatch()) {
showError(lang(lng_flood_error));
enableAll(true);
return true;
}
if (cDebug()) { // internal server error
showError(err + ": " + error.description());
} else {
showError(lang(lng_server_error));
}
enableAll(true);
return false;
}
QString IntroPhone::fullNumber() const {
return code.text() + phone.text();
}
void IntroPhone::selectCountry(const QString &c) {
country.onChooseCountry(c);
}
void IntroPhone::activate() {
error = "";
errorAlpha = anim::fvalue(0);
show();
enableAll(true);
}
void IntroPhone::deactivate() {
checkRequest.stop();
hide();
phone.clearFocus();
}
void IntroPhone::onNext() {
onSubmitPhone();
}
void IntroPhone::onBack() {
}

View File

@@ -0,0 +1,89 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#pragma once
#include <QtWidgets/QWidget>
#include "gui/flatbutton.h"
#include "gui/phoneinput.h"
#include "gui/countrycodeinput.h"
#include "gui/countryinput.h"
#include "intro.h"
class IntroPhone : public IntroStage, public Animated, public RPCSender {
Q_OBJECT
public:
IntroPhone(IntroWidget *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
bool animStep(float64 ms);
void selectCountry(const QString &country);
void activate();
void deactivate();
void onNext();
void onBack();
void phoneCheckDone(const MTPauth_CheckedPhone &result);
void phoneSubmitDone(const MTPauth_SentCode &result);
bool phoneSubmitFail(const RPCError &error);
void toSignUp();
public slots:
void countryChanged();
void onSelectClose();
void onInputChange();
void onSubmitPhone(bool force = false);
void onCheckRequest();
private:
QString fullNumber() const;
void disableAll();
void enableAll(bool failed);
void stopCheck();
void showError(const QString &err, bool signUp = false);
QString error;
anim::fvalue errorAlpha;
bool changed;
FlatButton next;
QRect textRect;
CountryInput country;
PhoneInput phone;
CountryCodeInput code;
FlatLabel _signup;
QPixmap _signupCache;
bool _showSignup;
QString sentPhone;
mtpRequestId sentRequest;
QTimer checkRequest;
};

View File

@@ -0,0 +1,283 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#include "stdafx.h"
#include "lang.h"
#include "style.h"
#include "gui/filedialog.h"
#include "boxes/photocropbox.h"
#include "application.h"
#include "intro/introsignup.h"
#include "intro/intro.h"
IntroSignup::IntroSignup(IntroWidget *parent) : IntroStage(parent),
next(this, lang(lng_intro_finish), st::btnIntroFinish), errorAlpha(0), a_photo(0),
first(this, st::inpIntroName, lang(lng_signup_firstname)),
last(this, st::inpIntroName, lang(lng_signup_lastname)) {
setVisible(false);
setGeometry(parent->innerRect());
connect(&next, SIGNAL(clicked()), this, SLOT(onSubmitName()));
connect(&checkRequest, SIGNAL(timeout()), this, SLOT(onCheckRequest()));
setMouseTracking(true);
}
void IntroSignup::mouseMoveEvent(QMouseEvent *e) {
bool photoOver = QRect(_phLeft, _phTop, st::setPhotoSize, st::setPhotoSize).contains(e->pos());
if (photoOver != _photoOver) {
_photoOver = photoOver;
if (_photoSmall.isNull()) {
a_photo.start(_photoOver ? 1 : 0);
errorAlpha.restart();
anim::start(this);
}
}
setCursor(_photoOver ? style::cur_pointer : style::cur_default);
}
void IntroSignup::mousePressEvent(QMouseEvent *e) {
mouseMoveEvent(e);
if (QRect(_phLeft, _phTop, st::setPhotoSize, st::setPhotoSize).contains(e->pos())) {
QStringList imgExtensions(cImgExtensions());
QString filter(qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;All files (*.*)"));
QImage img;
QString file;
QByteArray remoteContent;
if (filedialogGetOpenFile(file, remoteContent, lang(lng_choose_images), filter)) {
if (!remoteContent.isEmpty()) {
img = App::readImage(remoteContent);
} else {
if (!file.isEmpty()) {
img = App::readImage(file);
}
}
} else {
return;
}
if (img.isNull() || img.width() > 10 * img.height() || img.height() > 10 * img.width()) {
showError(lang(lng_bad_photo));
return;
}
PhotoCropBox *box = new PhotoCropBox(img, 0);
connect(box, SIGNAL(ready(const QImage &)), this, SLOT(onPhotoReady(const QImage &)));
App::wnd()->showLayer(box);
}
}
void IntroSignup::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::introTitleFont->f);
p.drawText(textRect, lang(lng_signup_title), QTextOption(Qt::AlignHCenter | Qt::AlignTop));
}
if (animating() || error.length()) {
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));
p.setOpacity(1);
}
if (_photoSmall.isNull()) {
if (a_photo.current() < 1) {
p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), st::setPhotoImg);
}
if (a_photo.current() > 0) {
p.setOpacity(a_photo.current());
p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), st::setOverPhotoImg);
p.setOpacity(1);
}
} else {
p.drawPixmap(_phLeft, _phTop, _photoSmall);
}
}
void IntroSignup::resizeEvent(QResizeEvent *e) {
textRect = QRect((width() - st::introTextSize.width()) / 2, 0, st::introTextSize.width(), st::introTextSize.height());
_phLeft = (width() - st::setPhotoImg.width()) / 2;
_phTop = st::introHeaderFont->height + st::introFinishSkip;
if (e->oldSize().width() != width()) {
int sumNext = st::btnIntroNext.width - st::btnIntroBack.width - st::btnIntroSep;
next.move((width() - sumNext) / 2, st::introSize.height() - st::btnIntroNext.height);
}
if (e->oldSize().width() != width()) {
next.move((width() - next.width()) / 2, st::introSize.height() - st::btnIntroNext.height);
first.move((width() - first.width()) / 2, _phTop + st::setPhotoImg.height() + st::introFinishSkip);
last.move((width() - last.width()) / 2, first.y() + first.height() + st::introFinishSkip);
}
}
void IntroSignup::showError(const QString &err) {
if (!animating() && err == error) return;
if (err.length()) {
error = err;
errorAlpha.start(1);
} else {
errorAlpha.start(0);
}
a_photo.restart();
anim::start(this);
}
bool IntroSignup::animStep(float64 ms) {
float64 dt = ms / st::introErrDuration;
bool res = true;
if (dt >= 1) {
res = false;
errorAlpha.finish();
if (!errorAlpha.current()) {
error = "";
}
a_photo.finish();
} else {
errorAlpha.update(dt, st::introErrFunc);
a_photo.update(dt, anim::linear);
}
update();
return res;
}
void IntroSignup::activate() {
show();
first.setFocus();
}
void IntroSignup::deactivate() {
hide();
}
void IntroSignup::stopCheck() {
checkRequest.stop();
}
void IntroSignup::onCheckRequest() {
int32 status = MTP::state(sentRequest);
if (status < 0) {
int32 leftms = -status;
if (leftms >= 1000) {
MTP::cancel(sentRequest);
sentRequest = 0;
if (!first.isEnabled()) {
first.setDisabled(false);
last.setDisabled(false);
last.setFocus();
}
}
}
if (!sentRequest && status == MTP::RequestSent) {
stopCheck();
}
}
void IntroSignup::onPhotoReady(const QImage &img) {
_photoBig = img;
_photoSmall = QPixmap::fromImage(img.scaled(st::setPhotoSize, st::setPhotoSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
App::wnd()->hideLayer();
}
void IntroSignup::nameSubmitDone(const MTPauth_Authorization &result) {
stopCheck();
first.setDisabled(false);
last.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, _photoBig);
}
bool IntroSignup::nameSubmitFail(const RPCError &error) {
stopCheck();
first.setDisabled(false);
last.setDisabled(false);
const QString &err = error.type();
if (err == "PHONE_NUMBER_INVALID" || err == "PHONE_CODE_EXPIRED" || err == "PHONE_CODE_EMPTY" || err == "PHONE_CODE_INVALID" || err == "PHONE_NUMBER_OCCUPIED") {
intro()->onIntroBack();
return true;
} else if (err == "FIRSTNAME_INVALID") {
showError(lang(lng_bad_name));
first.setFocus();
return true;
} else if (err == "LASTNAME_INVALID") {
showError(lang(lng_bad_name));
last.setFocus();
return true;
}
if (QRegularExpression("^FLOOD_WAIT_(\\d+)$").match(err).hasMatch()) {
showError(lang(lng_flood_error));
last.setFocus();
return true;
}
if (cDebug()) { // internal server error
showError(err + ": " + error.description());
} else {
showError(lang(lng_server_error));
}
first.setFocus();
return false;
}
void IntroSignup::onInputChange() {
showError("");
}
void IntroSignup::onSubmitName(bool force) {
if ((first.hasFocus() || first.text().trimmed().length()) && !last.text().trimmed().length()) {
last.setFocus();
return;
} else if (!first.text().trimmed().length()) {
first.setFocus();
return;
}
if (!force && !first.isEnabled()) return;
first.setDisabled(true);
last.setDisabled(true);
setFocus();
showError("");
firstName = first.text().trimmed();
lastName = last.text().trimmed();
sentRequest = MTP::send(MTPauth_SignUp(MTP_string(intro()->getPhone()), MTP_string(intro()->getPhoneHash()), MTP_string(intro()->getCode()), MTP_string(firstName), MTP_string(lastName)), rpcDone(&IntroSignup::nameSubmitDone), rpcFail(&IntroSignup::nameSubmitFail));
}
void IntroSignup::onNext() {
onSubmitName();
}
void IntroSignup::onBack() {
}

View File

@@ -0,0 +1,76 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#pragma once
#include <QtWidgets/QWidget>
#include "gui/flatbutton.h"
#include "gui/flatinput.h"
#include "intro.h"
class IntroSignup : public IntroStage, public Animated, public RPCSender {
Q_OBJECT
public:
IntroSignup(IntroWidget *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
bool animStep(float64 ms);
void activate();
void deactivate();
void onNext();
void onBack();
void nameSubmitDone(const MTPauth_Authorization &result);
bool nameSubmitFail(const RPCError &error);
public slots:
void onSubmitName(bool force = false);
void onInputChange();
void onCheckRequest();
void onPhotoReady(const QImage &img);
private:
void showError(const QString &err);
void stopCheck();
QString error;
anim::fvalue errorAlpha, a_photo;
FlatButton next;
QRect textRect;
bool _photoOver;
QImage _photoBig;
QPixmap _photoSmall;
int32 _phLeft, _phTop;
FlatInput first, last;
QString firstName, lastName;
mtpRequestId sentRequest;
QTimer checkRequest;
};

View File

@@ -0,0 +1,80 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#include "stdafx.h"
#include "lang.h"
#include "style.h"
#include "application.h"
#include "intro/introsteps.h"
#include "intro/intro.h"
IntroSteps::IntroSteps(IntroWidget *parent) : IntroStage(parent),
_intro1(this, lang(lng_intro1), st::introLabel),
_intro2(this, lang(lng_intro2), st::introLabel),
_next(this, lang(lng_start_msgs), st::btnIntroStart) {
_headerWidth = st::introHeaderFont->m.width(lang(lng_maintitle));
setGeometry(parent->innerRect());
connect(&_next, SIGNAL(stateChanged(int, ButtonStateChangeSource)), parent, SLOT(onDoneStateChanged(int, ButtonStateChangeSource)));
connect(&_next, SIGNAL(clicked()), parent, SLOT(onIntroNext()));
setMouseTracking(true);
}
void IntroSteps::paintEvent(QPaintEvent *e) {
bool trivial = (rect() == e->rect());
QPainter p(this);
if (!trivial) {
p.setClipRect(e->rect());
}
int32 hy = _intro1.y() - st::introHeaderFont->height - st::introHeaderSkip + st::introHeaderFont->ascent;
p.setFont(st::introHeaderFont->f);
p.drawText(_next.x(), hy, lang(lng_maintitle));
p.setPen(st::introColor->p);
p.setFont(st::introVersionFont->f);
p.setPen(st::introVersionColor->p);
p.drawText(_next.x() + _headerWidth + st::introVersionSkip, hy, qsl("alpha ") + QString::fromWCharArray(AppVersionStr));
}
void IntroSteps::resizeEvent(QResizeEvent *e) {
if (e->oldSize().width() != width()) {
_next.move((width() - st::btnIntroStart.width) / 2, st::introBtnTop);
_intro2.move(_next.x(), _next.y() - _intro2.height() - st::intro2Skip);
_intro1.move(_next.x(), _intro2.y() - _intro1.height() - st::intro1Skip);
}
}
void IntroSteps::activate() {
show();
}
void IntroSteps::deactivate() {
hide();
}
void IntroSteps::onNext() {
intro()->onIntroNext();
}
void IntroSteps::onBack() {
}

View File

@@ -0,0 +1,43 @@
/*
This file is part of Telegram Desktop,
an unofficial desktop 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://tdesktop.com
*/
#pragma once
#include <QtWidgets/QWidget>
#include "gui/flatbutton.h"
#include "intro.h"
class IntroSteps : public IntroStage {
public:
IntroSteps(IntroWidget *parent);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
void activate();
void deactivate();
void onNext();
void onBack();
private:
FlatLabel _intro1, _intro2;
FlatButton _next;
int32 _headerWidth;
};