diff --git a/Telegram/Resources/lang.txt b/Telegram/Resources/lang.txt index ab9c893310..62d0187bc7 100644 --- a/Telegram/Resources/lang.txt +++ b/Telegram/Resources/lang.txt @@ -22,6 +22,7 @@ lng_maintitle: "Telegram D"; lng_menu_contacts: "Contacts"; lng_menu_settings: "Settings"; lng_menu_about: "About"; +lng_menu_update: "Update"; lng_open_from_tray: "Open Telegram"; lng_minimize_to_tray: "Minimize to tray"; diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index b79c55f996..92dabf00f3 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -86,6 +86,7 @@ sysUpd: sysButton { overColor: white; duration: 150; } +updateBlinkDuration: 500; sysMin: sysButton(sysUpd) { img: sprite(207px, 1px, 19px, 19px); } @@ -1624,6 +1625,7 @@ mediaviewLoaderSkip: 9px; minPhotoWidth: 90px; minPhotoHeight: 90px; +maxMediaSize: 400px; usernameFont: font(14px); usernameColor: #777; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 1fe000a8c6..b5032836ce 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -165,6 +165,31 @@ namespace App { return (peer_id & 0x100000000L) ? int32(peer_id & 0xFFFFFFFFL) : 0; } + int32 onlineForSort(int32 online, int32 now) { + if (online <= 0) { + switch (online) { + case -2: { + QDate yesterday(date(now).date()); + yesterday.addDays(-1); + return int32(QDateTime(yesterday).toTime_t()); + } break; + + case -3: { + QDate weekago(date(now).date()); + weekago.addDays(-7); + return int32(QDateTime(weekago).toTime_t()); + } break; + + case -4: { + QDate monthago(date(now).date()); + monthago.addDays(-30); + return int32(QDateTime(monthago).toTime_t()); + } break; + } + } + return online; + } + int32 onlineWillChangeIn(int32 online, int32 now) { if (online <= 0) return 86400; if (online > now) { diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 3935059921..587656aee5 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -63,6 +63,7 @@ namespace App { int32 userFromPeer(const PeerId &peer_id); int32 chatFromPeer(const PeerId &peer_id); + int32 onlineForSort(int32 online, int32 now); int32 onlineWillChangeIn(int32 onlineOnServer, int32 nowOnServer); QString onlineText(int32 onlineOnServer, int32 nowOnServer, bool precise = false); diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 03cb6ba2a8..464710498b 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -37,6 +37,7 @@ enum { MTPAckSendWaiting = 10000, // how much time to wait for some more requests, when sending msg acks MTPResendThreshold = 1, // how much ints should message contain for us not to resend, but to check it's state MTPContainerLives = 600, // container lives 10 minutes in haveSent map + MTPMinReceiveDelay = 4000, // 4 seconds MTPMaxReceiveDelay = 64000, // 64 seconds MTPConnectionOldTimeout = 192000, // 192 seconds MTPTcpConnectionWaitTimeout = 3000, // 3 seconds waiting for tcp, until we accept http @@ -50,7 +51,6 @@ enum { MTPDebugBufferSize = 1024 * 1024, // 1 mb start size - MinReceiveDelay = 1000, // 1 seconds MaxSelectedItems = 100, MaxPhoneTailLength = 18, // rest of the phone number, without country code (seen 12 at least) diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 48a3bdf899..20385ec7cd 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -2059,15 +2059,15 @@ HistoryItem *regItem(HistoryItem *item, bool returnExisting) { return item; } -HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, int32 width) : data(App::feedPhoto(photo)) -, openl(new PhotoLink(data)) -, w(width) { +HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, int32 width) : HistoryMedia(width) +, data(App::feedPhoto(photo)) +, openl(new PhotoLink(data)) { init(); } -HistoryPhoto::HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width) : data(App::feedPhoto(photo)) -, openl(new PhotoLink(data, chat)) -, w(width) { +HistoryPhoto::HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width) : HistoryMedia(width) +, data(App::feedPhoto(photo)) +, openl(new PhotoLink(data, chat)) { init(); } @@ -2080,29 +2080,31 @@ void HistoryPhoto::initDimensions(const HistoryItem *parent) { if (!tw || !th) { tw = th = 1; } - int32 thumbw = qMax(tw, int32(st::minPhotoWidth)), maxthumbh = thumbw; - int32 thumbh = qRound(th * float64(thumbw) / tw); - if (thumbh > maxthumbh) { - thumbw = qRound(thumbw * float64(maxthumbh) / thumbh); - thumbh = maxthumbh; - if (thumbw < st::minPhotoWidth) { - thumbw = st::minPhotoWidth; - } - } - if (thumbh < st::minPhotoHeight) { - thumbh = st::minPhotoHeight; - } + int32 thumbw = tw; + int32 thumbh = th; if (!w) { w = thumbw; + } else { + thumbh = w; // square chat photo updates } _maxw = w; _height = _minh = thumbh; + if (_maxw < st::minPhotoWidth) { + _maxw = st::minPhotoWidth; + } + if (_height < st::minPhotoHeight) { + _height = st::minPhotoHeight; + } } int32 HistoryPhoto::resize(int32 width, bool dontRecountText, const HistoryItem *parent) { - w = width; + w = qMin(width, _maxw); int32 tw = convertScale(data->full->width()), th = convertScale(data->full->height()); + if (tw > st::maxMediaSize) { + th = (st::maxMediaSize * th) / tw; + tw = st::maxMediaSize; + } _height = th; if (tw > w) { _height = (w * _height / tw); @@ -2254,11 +2256,11 @@ QString formatDurationAndSizeText(qint64 duration, qint64 size) { int32 _downloadWidth = 0, _openWithWidth = 0, _cancelWidth = 0, _buttonWidth = 0; -HistoryVideo::HistoryVideo(const MTPDvideo &video, int32 width) : data(App::feedVideo(video)) +HistoryVideo::HistoryVideo(const MTPDvideo &video, int32 width) : HistoryMedia(width) +, data(App::feedVideo(video)) , _openl(new VideoOpenLink(data)) , _savel(new VideoSaveLink(data)) , _cancell(new VideoCancelLink(data)) -, w(width) , _dldDone(0) , _uplDone(0) { @@ -2304,11 +2306,6 @@ void HistoryVideo::unregItem(HistoryItem *item) { App::unregVideoItem(data, item); } -int32 HistoryVideo::resize(int32 width, bool dontRecountText, const HistoryItem *parent) { - w = width; - return _height; -} - const QString HistoryVideo::inDialogsText() const { return lang(lng_in_dlg_video); } @@ -2451,11 +2448,11 @@ void HistoryVideo::draw(QPainter &p, const HistoryItem *parent, bool selected, i } } -HistoryAudio::HistoryAudio(const MTPDaudio &audio, int32 width) : data(App::feedAudio(audio)) +HistoryAudio::HistoryAudio(const MTPDaudio &audio, int32 width) : HistoryMedia(width) +, data(App::feedAudio(audio)) , _openl(new AudioOpenLink(data)) , _savel(new AudioSaveLink(data)) , _cancell(new AudioCancelLink(data)) -, w(width) , _dldDone(0) , _uplDone(0) { @@ -2606,11 +2603,6 @@ void HistoryAudio::unregItem(HistoryItem *item) { App::unregAudioItem(data, item); } -int32 HistoryAudio::resize(int32 width, bool dontRecountText, const HistoryItem *parent) { - w = width; - return _height; -} - const QString HistoryAudio::inDialogsText() const { return lang(lng_in_dlg_audio); } @@ -2650,11 +2642,11 @@ HistoryMedia *HistoryAudio::clone() const { return new HistoryAudio(*this); } -HistoryDocument::HistoryDocument(const MTPDdocument &document, int32 width) : data(App::feedDocument(document)) +HistoryDocument::HistoryDocument(const MTPDdocument &document, int32 width) : HistoryMedia(width) +, data(App::feedDocument(document)) , _openl(new DocumentOpenLink(data)) , _savel(new DocumentSaveLink(data)) , _cancell(new DocumentCancelLink(data)) -, w(width) , _name(data->name) , _dldDone(0) , _uplDone(0) @@ -2848,8 +2840,11 @@ void HistoryDocument::updateFrom(const MTPMessageMedia &media) { } int32 HistoryDocument::resize(int32 width, bool dontRecountText, const HistoryItem *parent) { - w = width; + w = qMin(width, _maxw); if (parent == animated.msg) { + if (w > st::maxMediaSize) { + w = st::maxMediaSize; + } _height = animated.h; if (animated.w > w) { _height = (w * _height / animated.w); @@ -2921,8 +2916,8 @@ HistoryMedia *HistoryDocument::clone() const { return new HistoryDocument(*this); } -HistoryContact::HistoryContact(int32 userId, const QString &first, const QString &last, const QString &phone) : userId(userId) -, w(0) +HistoryContact::HistoryContact(int32 userId, const QString &first, const QString &last, const QString &phone) : HistoryMedia(0) +, userId(userId) , phone(App::formatPhone(phone)) , contact(App::userLoaded(userId)) { @@ -2955,7 +2950,7 @@ void HistoryContact::initDimensions(const HistoryItem *parent) { } int32 HistoryContact::resize(int32 width, bool dontRecountText, const HistoryItem *parent) { - w = width; + w = qMin(width, _maxw); return _height; } @@ -3372,7 +3367,7 @@ void ImageLinkData::load() { manager.getData(this); } -HistoryImageLink::HistoryImageLink(const QString &url, int32 width) : w(width) { +HistoryImageLink::HistoryImageLink(const QString &url, int32 width) : HistoryMedia(width) { if (url.startsWith(qsl("location:"))) { data = App::imageLink(url, GoogleMapsLink, qsl("https://maps.google.com/maps?q=") + url.mid(9) + qsl("&ll=") + url.mid(9) + qsl("&z=17")); } else { @@ -3384,6 +3379,7 @@ HistoryImageLink::HistoryImageLink(const QString &url, int32 width) : w(width) { m = reInstagram.match(url); if (m.hasMatch()) { data = App::imageLink(qsl("instagram:") + m.captured(3), InstagramLink, url); + data->title = qsl("instagram.com/p/") + m.captured(3); } else { data = 0; } @@ -3460,7 +3456,7 @@ void HistoryImageLink::draw(QPainter &p, const HistoryItem *parent, bool selecte if (data) { switch (data->type) { case YouTubeLink: p.drawPixmap(QPoint((width - st::youtubeIcon.pxWidth()) / 2, (_height - st::youtubeIcon.pxHeight()) / 2), App::sprite(), st::youtubeIcon); break; - case InstagramLink: p.drawPixmap(QPoint((width - st::instagramIcon.pxWidth()) / 2, (_height - st::instagramIcon.pxHeight()) / 2), App::sprite(), st::instagramIcon); break; +// case InstagramLink: p.drawPixmap(QPoint((width - st::instagramIcon.pxWidth()) / 2, (_height - st::instagramIcon.pxHeight()) / 2), App::sprite(), st::instagramIcon); break; } if (!data->title.isEmpty() || !data->duration.isEmpty()) { p.fillRect(0, 0, width, st::msgDateFont->height + 2 * st::msgDateImgPadding.y(), st::msgDateImgBg->b); @@ -3515,9 +3511,13 @@ void HistoryImageLink::draw(QPainter &p, const HistoryItem *parent, bool selecte } int32 HistoryImageLink::resize(int32 width, bool dontRecountText, const HistoryItem *parent) { - w = width; + w = qMin(width, _maxw); int32 tw = convertScale(fullWidth()), th = convertScale(fullHeight()); + if (tw > st::maxMediaSize) { + th = (st::maxMediaSize * th) / tw; + tw = st::maxMediaSize; + } _height = th; if (tw > w) { _height = (w * _height / tw); @@ -3736,7 +3736,10 @@ void HistoryMessage::draw(QPainter &p, uint32 selection) const { _fromVersion = _from->nameVersion; } int32 left = _out ? st::msgMargin.right() : st::msgMargin.left(), width = _history->width - st::msgMargin.left() - st::msgMargin.right(), mwidth = st::msgMaxWidth; - if (_media && _media->maxWidth() > mwidth) mwidth = _media->maxWidth(); + if (_media) { + if (_media->maxWidth() > mwidth) mwidth = _media->maxWidth(); + if (_media->currentWidth() < mwidth) mwidth = _media->currentWidth(); + } if (width > mwidth) { if (_out) left += width - mwidth; width = mwidth; diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 086d8d75a3..0675e8c61e 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -1218,12 +1218,19 @@ HistoryItem *regItem(HistoryItem *item, bool returnExisting = false); class HistoryMedia : public HistoryElem { public: + HistoryMedia(int32 width = 0) : w(width) { + } + virtual HistoryMediaType type() const = 0; virtual const QString inDialogsText() const = 0; virtual bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0; virtual int32 countHeight(const HistoryItem *parent, int32 width = -1) const { return height(); } + virtual int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0) { + w = qMin(width, _maxw); + return _height; + } virtual TextLinkPtr getLink(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0; virtual void draw(QPainter &p, const HistoryItem *parent, bool selected, int32 width = -1) const = 0; virtual bool uploading() const { @@ -1244,6 +1251,14 @@ public: return false; } + int32 currentWidth() const { + return w; + } + +protected: + + int32 w; + }; class HistoryPhoto : public HistoryMedia { @@ -1281,7 +1296,7 @@ public: private: PhotoData *data; TextLinkPtr openl; - int32 w; + }; QString formatSizeText(qint64 size); @@ -1293,7 +1308,6 @@ public: void initDimensions(const HistoryItem *parent); void draw(QPainter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; - int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0); HistoryMediaType type() const { return MediaTypeVideo; } @@ -1311,8 +1325,7 @@ public: private: VideoData *data; TextLinkPtr _openl, _savel, _cancell; - int32 w; - + QString _size; int32 _thumbw, _thumbx, _thumby; @@ -1327,7 +1340,6 @@ public: void initDimensions(const HistoryItem *parent); void draw(QPainter &p, const HistoryItem *parent, bool selected, int32 width = -1) const; - int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0); HistoryMediaType type() const { return MediaTypeAudio; } @@ -1345,7 +1357,6 @@ public: private: AudioData *data; TextLinkPtr _openl, _savel, _cancell; - int32 w; QString _size; @@ -1386,7 +1397,6 @@ private: DocumentData *data; TextLinkPtr _openl, _savel, _cancell; - int32 w; int32 _namew; QString _name, _size; @@ -1494,7 +1504,7 @@ public: private: ImageLinkData *data; - int32 w; + }; class HistoryMessage : public HistoryItem { diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.cpp b/Telegram/SourceFiles/mtproto/mtpConnection.cpp index 6652f97548..81b57745c4 100644 --- a/Telegram/SourceFiles/mtproto/mtpConnection.cpp +++ b/Telegram/SourceFiles/mtproto/mtpConnection.cpp @@ -309,8 +309,8 @@ void MTProtoConnection::restart() { } void MTProtoConnection::stop() { - data->stop(); - thread->quit(); + if (data) data->stop(); + if (thread) thread->quit(); } void MTProtoConnection::stopped() { @@ -604,7 +604,7 @@ void MTPabstractTcpConnection::socketRead() { } MTPautoConnection::MTPautoConnection(QThread *thread) : status(WaitingBoth), -tcpNonce(MTP::nonce()), httpNonce(MTP::nonce()), _tcpTimeout(1) { +tcpNonce(MTP::nonce()), httpNonce(MTP::nonce()), _tcpTimeout(MTPMinReceiveDelay) { moveToThread(thread); manager.moveToThread(thread); @@ -642,7 +642,7 @@ void MTPautoConnection::onSocketConnected() { DEBUG_LOG(("Connection Info: sending fake req_pq through tcp transport")); if (_tcpTimeout < 0) _tcpTimeout = -_tcpTimeout; - tcpTimeoutTimer.start(_tcpTimeout * 1000); + tcpTimeoutTimer.start(_tcpTimeout); tcpSend(buffer); } else if (status == WaitingHttp || status == UsingHttp) { @@ -652,7 +652,7 @@ void MTPautoConnection::onSocketConnected() { void MTPautoConnection::onTcpTimeoutTimer() { if (status == HttpReady || status == WaitingBoth || status == WaitingTcp) { - if (_tcpTimeout < 64) _tcpTimeout *= 2; + if (_tcpTimeout < MTPMaxReceiveDelay) _tcpTimeout *= 2; _tcpTimeout = -_tcpTimeout; QAbstractSocket::SocketState state = sock.state(); @@ -1083,7 +1083,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne , conn(0) , retryTimeout(1) , oldConnection(true) - , receiveDelay(MinReceiveDelay) + , receiveDelay(MTPMinReceiveDelay) , firstSentAt(-1) , pingId(0) , toSendPingId(0) @@ -1774,14 +1774,14 @@ void MTProtoConnectionPrivate::onReceivedSome() { int32 ms = getms(true) - firstSentAt; DEBUG_LOG(("MTP Info: response in %1ms, receiveDelay: %2ms").arg(ms).arg(receiveDelay)); - if (ms > 0 && ms * 2 < int32(receiveDelay)) receiveDelay = qMax(ms * 2, int32(MinReceiveDelay)); + if (ms > 0 && ms * 2 < int32(receiveDelay)) receiveDelay = qMax(ms * 2, int32(MTPMinReceiveDelay)); firstSentAt = -1; } } void MTProtoConnectionPrivate::onOldConnection() { oldConnection = true; - receiveDelay = MinReceiveDelay; + receiveDelay = MTPMinReceiveDelay; DEBUG_LOG(("This connection marked as old! delay now %1ms").arg(receiveDelay)); } diff --git a/Telegram/SourceFiles/mtproto/mtpSession.cpp b/Telegram/SourceFiles/mtproto/mtpSession.cpp index d4fac36f92..972ec83d0a 100644 --- a/Telegram/SourceFiles/mtproto/mtpSession.cpp +++ b/Telegram/SourceFiles/mtproto/mtpSession.cpp @@ -129,7 +129,7 @@ void MTProtoSession::restart() { } void MTProtoSession::stop() { - while (connections.size()) { + while (!connections.isEmpty()) { connections.back()->stop(); connections.pop_back(); } diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index 7befcb821f..8e781e2570 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -340,13 +340,13 @@ void ProfileInner::reorderParticipants() { UserData *self = App::self(); for (ChatData::Participants::const_iterator i = _peerChat->participants.cbegin(), e = _peerChat->participants.cend(); i != e; ++i) { UserData *user = i.key(); - int32 until = user->onlineTill; + int32 until = App::onlineForSort(user->onlineTill, t); Participants::iterator before = _participants.begin(); if (user != self) { if (before != _participants.end() && (*before) == self) { ++before; } - while (before != _participants.end() && (*before)->onlineTill >= until) { + while (before != _participants.end() && App::onlineForSort((*before)->onlineTill, t) >= until) { ++before; } } diff --git a/Telegram/SourceFiles/sysbuttons.cpp b/Telegram/SourceFiles/sysbuttons.cpp index 0e3e5b0b13..8b0de6501d 100644 --- a/Telegram/SourceFiles/sysbuttons.cpp +++ b/Telegram/SourceFiles/sysbuttons.cpp @@ -23,13 +23,19 @@ Copyright (c) 2014 John Preston, https://tdesktop.com #include "window.h" #include "application.h" -SysBtn::SysBtn(QWidget *parent, const style::sysButton &st) : Button(parent), - _st(st), a_color(_st.color->c) { - resize(_st.size); +SysBtn::SysBtn(QWidget *parent, const style::sysButton &st, const QString &text) : Button(parent), +_st(st), a_color(_st.color->c), _text(text), _overLevel(0) { + int32 w = _st.size.width() + (_text.isEmpty() ? 0 : ((_st.size.width() - _st.img.pxWidth()) / 2 + st::titleTextButton.font->m.width(_text))); + resize(w, _st.size.height()); setCursor(style::cur_default); connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource))); } +void SysBtn::setOverLevel(float64 level) { + _overLevel = level; + update(); +} + void SysBtn::onStateChange(int oldState, ButtonStateChangeSource source) { a_color.start((_state & StateOver ? _st.overColor : _st.color)->c); @@ -45,9 +51,25 @@ void SysBtn::onStateChange(int oldState, ButtonStateChangeSource source) { void SysBtn::paintEvent(QPaintEvent *e) { QPainter p(this); - int x = (width() - _st.img.pxWidth()) / 2, y = (height() - _st.img.pxHeight()) / 2; - p.fillRect(x, y, _st.img.pxWidth(), _st.img.pxHeight(), a_color.current()); + int x = width() - ((_st.size.width() + _st.img.pxWidth()) / 2), y = (height() - _st.img.pxHeight()) / 2; + QColor c = a_color.current(); + if (_overLevel > 0) { + if (_overLevel >= 1) { + c = _st.overColor->c; + } else { + c.setRedF(c.redF() * (1 - _overLevel) + _st.overColor->c.redF() * _overLevel); + c.setGreenF(c.greenF() * (1 - _overLevel) + _st.overColor->c.greenF() * _overLevel); + c.setBlueF(c.blueF() * (1 - _overLevel) + _st.overColor->c.blueF() * _overLevel); + } + } + p.fillRect(x, y, _st.img.pxWidth(), _st.img.pxHeight(), c); p.drawPixmap(QPoint(x, y), App::sprite(), _st.img); + + if (!_text.isEmpty()) { + p.setFont(st::titleTextButton.font->f); + p.setPen(c); + p.drawText((_st.size.width() - _st.img.pxWidth()) / 2, st::titleTextButton.textTop + st::titleTextButton.font->ascent, _text); + } } HitTestType SysBtn::hitTest(const QPoint &p) const { @@ -103,7 +125,7 @@ void CloseBtn::onClick() { wnd->close(); } -UpdateBtn::UpdateBtn(QWidget *parent, Window *window) : SysBtn(parent, st::sysUpd), wnd(window) { +UpdateBtn::UpdateBtn(QWidget *parent, Window *window, const QString &text) : SysBtn(parent, st::sysUpd, text), wnd(window) { connect(this, SIGNAL(clicked()), this, SLOT(onClick())); } diff --git a/Telegram/SourceFiles/sysbuttons.h b/Telegram/SourceFiles/sysbuttons.h index 8d08a85ded..9821882a7c 100644 --- a/Telegram/SourceFiles/sysbuttons.h +++ b/Telegram/SourceFiles/sysbuttons.h @@ -28,12 +28,14 @@ class SysBtn : public Button, public Animated { public: - SysBtn(QWidget *parent, const style::sysButton &st); + SysBtn(QWidget *parent, const style::sysButton &st, const QString &text = QString()); void paintEvent(QPaintEvent *e); HitTestType hitTest(const QPoint &p) const; + void setOverLevel(float64 level); + bool animStep(float64 ms); public slots: @@ -44,6 +46,8 @@ protected: style::sysButton _st; anim::cvalue a_color; + float64 _overLevel; + QString _text; }; @@ -116,7 +120,7 @@ class UpdateBtn : public SysBtn { public: - UpdateBtn(QWidget *parent, Window *window); + UpdateBtn(QWidget *parent, Window *window, const QString &text = QString()); public slots: diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index 0683cf433c..57dae478f8 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -54,7 +54,7 @@ TitleWidget::TitleWidget(Window *window) , _settings(this, lang(lng_menu_settings), st::titleTextButton) , _contacts(this, lang(lng_menu_contacts), st::titleTextButton) , _about(this, lang(lng_menu_about), st::titleTextButton) - , _update(this, window) + , _update(this, window, lang(lng_menu_update)) , _minimize(this, window) , _maximize(this, window) , _restore(this, window) @@ -65,10 +65,9 @@ TitleWidget::TitleWidget(Window *window) setGeometry(0, 0, wnd->width(), st::titleHeight); stateChanged(); + _update.hide(); if (App::app()->updatingState() == Application::UpdatingReady) { - _update.show(); - } else { - _update.hide(); + showUpdateBtn(); } connect(&_settings, SIGNAL(clicked()), window, SLOT(showSettings())); @@ -92,6 +91,13 @@ void TitleWidget::paintEvent(QPaintEvent *e) { p.drawPixmap(st::titleIconPos, App::sprite(), st::titleIconRect); } +bool TitleWidget::animStep(float64 ms) { + float64 phase = sin(M_PI_2 * (ms / st::updateBlinkDuration)); + if (phase < 0) phase = -phase; + _update.setOverLevel(phase); + return true; +} + void TitleWidget::setHideLevel(float64 level) { if (level != hideLevel) { hideLevel = level; @@ -126,7 +132,13 @@ TitleWidget::~TitleWidget() { void TitleWidget::resizeEvent(QResizeEvent *e) { QPoint p(width() - ((cPlatform() == dbipWindows && lastMaximized) ? 0 : st::sysBtnDelta), 0); - + + if (!_update.isHidden()) { + p.setX(p.x() - _update.width()); + _update.move(p); + p.setX(p.x() + _update.width()); + } + if (cPlatform() == dbipWindows) { p.setX(p.x() - _close.width()); _close.move(p); @@ -138,11 +150,6 @@ void TitleWidget::resizeEvent(QResizeEvent *e) { _minimize.move(p); } - if (!_update.isHidden()) { - p.setX(p.x() - _update.width()); - _update.move(p); - } - _settings.move(st::titleMenuOffset, 0); if (MTP::authedId()) { _contacts.show(); @@ -182,19 +189,30 @@ void TitleWidget::stateChanged(Qt::WindowState state) { void TitleWidget::showUpdateBtn() { if (App::app()->updatingState() == Application::UpdatingReady || cEvalScale(cConfigScale()) != cEvalScale(cRealScale())) { _update.show(); + _minimize.hide(); + _restore.hide(); + _maximize.hide(); + _close.hide(); + anim::start(this); } else { _update.hide(); + if (cPlatform() == dbipWindows) { + _minimize.show(); + maximizedChanged(wnd->windowState().testFlag(Qt::WindowMaximized), true); + _close.show(); + } + anim::stop(this); } resizeEvent(0); update(); } -void TitleWidget::maximizedChanged(bool maximized) { - if (lastMaximized == maximized) return; +void TitleWidget::maximizedChanged(bool maximized, bool force) { + if (lastMaximized == maximized && !force) return; lastMaximized = maximized; - if (cPlatform() != dbipWindows) return; + if (cPlatform() != dbipWindows || !_update.isHidden()) return; if (maximized) { _maximize.clearState(); } else { diff --git a/Telegram/SourceFiles/title.h b/Telegram/SourceFiles/title.h index 7ce806fbfe..202e514a71 100644 --- a/Telegram/SourceFiles/title.h +++ b/Telegram/SourceFiles/title.h @@ -36,7 +36,7 @@ private: }; -class TitleWidget : public QWidget { +class TitleWidget : public QWidget, public Animated { Q_OBJECT public: @@ -48,12 +48,14 @@ public: void mousePressEvent(QMouseEvent *e); void mouseDoubleClickEvent(QMouseEvent *e); - void maximizedChanged(bool maximized); + void maximizedChanged(bool maximized, bool force = false); HitTestType hitTest(const QPoint &p); void setHideLevel(float64 level); + bool animStep(float64 ms); + ~TitleWidget(); public slots: @@ -76,6 +78,8 @@ private: float64 hideLevel; TitleHider *hider; + float64 _lastUpdateMs; + FlatButton _settings, _contacts, _about; UpdateBtn _update;