mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 23:27:09 +02:00
Some more ripple animations. Now only anim::value (float64).
Also each FloatAnimation now stops MTP responses. Also slide animations done by FloatAnimation. Closed beta 10019012.
This commit is contained in:
parent
a248cef15d
commit
06ed7b8eaf
109 changed files with 2129 additions and 1796 deletions
|
@ -475,17 +475,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
"lng_profile_shared_media" = "Shared media";
|
||||
"lng_profile_no_media" = "No media in this conversation.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# photo|# photos}";
|
||||
"lng_profile_photos_header" = "Photos overview";
|
||||
"lng_profile_photos_header" = "Photos";
|
||||
"lng_profile_videos" = "{count:_not_used_|# video|# videos}";
|
||||
"lng_profile_videos_header" = "Videos overview";
|
||||
"lng_profile_videos_header" = "Videos";
|
||||
"lng_profile_songs" = "{count:_not_used_|# audio file|# audio files}";
|
||||
"lng_profile_songs_header" = "Audio files overview";
|
||||
"lng_profile_songs_header" = "Audio files";
|
||||
"lng_profile_files" = "{count:_not_used_|# file|# files}";
|
||||
"lng_profile_files_header" = "Files overview";
|
||||
"lng_profile_files_header" = "Files";
|
||||
"lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages}";
|
||||
"lng_profile_audios_header" = "Voice messages overview";
|
||||
"lng_profile_audios_header" = "Voice messages";
|
||||
"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links}";
|
||||
"lng_profile_shared_links_header" = "Shared links overview";
|
||||
"lng_profile_shared_links_header" = "Shared links";
|
||||
"lng_profile_copy_phone" = "Copy Phone Number";
|
||||
"lng_profile_copy_fullname" = "Copy Name";
|
||||
"lng_profile_drop_area_title" = "Drop your image here";
|
||||
|
|
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,10,19,11
|
||||
PRODUCTVERSION 0,10,19,11
|
||||
FILEVERSION 0,10,19,12
|
||||
PRODUCTVERSION 0,10,19,12
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -51,10 +51,10 @@ BEGIN
|
|||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileVersion", "0.10.19.11"
|
||||
VALUE "FileVersion", "0.10.19.12"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "0.10.19.11"
|
||||
VALUE "ProductVersion", "0.10.19.12"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,10,19,11
|
||||
PRODUCTVERSION 0,10,19,11
|
||||
FILEVERSION 0,10,19,12
|
||||
PRODUCTVERSION 0,10,19,12
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -43,10 +43,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileDescription", "Telegram Updater"
|
||||
VALUE "FileVersion", "0.10.19.11"
|
||||
VALUE "FileVersion", "0.10.19.12"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "0.10.19.11"
|
||||
VALUE "ProductVersion", "0.10.19.12"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -1246,7 +1246,7 @@ namespace {
|
|||
if (auto history = App::historyLoaded(peer)) {
|
||||
history->outboxRead(upTo);
|
||||
if (history->lastMsg && history->lastMsg->out() && history->lastMsg->id <= upTo) {
|
||||
if (App::main()) App::main()->dlgUpdated(history, history->lastMsg->id);
|
||||
if (App::main()) App::main()->dlgUpdated(history->peer, history->lastMsg->id);
|
||||
}
|
||||
history->updateChatListEntry();
|
||||
|
||||
|
|
|
@ -711,8 +711,6 @@ AppClass::AppClass() : QObject() {
|
|||
|
||||
cChangeTimeFormat(QLocale::system().timeFormat(QLocale::ShortFormat));
|
||||
|
||||
connect(&_mtpUnpauseTimer, SIGNAL(timeout()), this, SLOT(doMtpUnpause()));
|
||||
|
||||
connect(&killDownloadSessionsTimer, SIGNAL(timeout()), this, SLOT(killDownloadSessions()));
|
||||
|
||||
DEBUG_LOG(("Application Info: starting app..."));
|
||||
|
@ -832,19 +830,6 @@ void AppClass::cancelPhotoUpdate(const PeerId &peer) {
|
|||
}
|
||||
}
|
||||
|
||||
void AppClass::mtpPause() {
|
||||
MTP::pause();
|
||||
_mtpUnpauseTimer.start(st::slideDuration * 2);
|
||||
}
|
||||
|
||||
void AppClass::mtpUnpause() {
|
||||
_mtpUnpauseTimer.start(1);
|
||||
}
|
||||
|
||||
void AppClass::doMtpUnpause() {
|
||||
MTP::unpause();
|
||||
}
|
||||
|
||||
void AppClass::selfPhotoCleared(const MTPUserProfilePhoto &result) {
|
||||
if (!App::self()) return;
|
||||
App::self()->setPhoto(result);
|
||||
|
|
|
@ -159,9 +159,6 @@ public:
|
|||
bool isPhotoUpdating(const PeerId &peer);
|
||||
void cancelPhotoUpdate(const PeerId &peer);
|
||||
|
||||
void mtpPause();
|
||||
void mtpUnpause();
|
||||
|
||||
void selfPhotoCleared(const MTPUserProfilePhoto &result);
|
||||
void chatPhotoCleared(PeerId peer, const MTPUpdates &updates);
|
||||
void selfPhotoDone(const MTPphotos_Photo &result);
|
||||
|
@ -185,9 +182,6 @@ signals:
|
|||
void adjustSingleTimers();
|
||||
|
||||
public slots:
|
||||
|
||||
void doMtpUnpause();
|
||||
|
||||
void photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file);
|
||||
|
||||
void onSwitchDebugMode();
|
||||
|
@ -217,6 +211,4 @@ private:
|
|||
FileUploader *_uploader = nullptr;
|
||||
Translator *_translator = nullptr;
|
||||
|
||||
SingleTimer _mtpUnpauseTimer;
|
||||
|
||||
};
|
||||
|
|
|
@ -557,7 +557,7 @@ void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
|
|||
if (_linkOver) {
|
||||
Application::clipboard()->setText(_channel->inviteLink());
|
||||
_goodTextLink = lang(lng_create_channel_link_copied);
|
||||
a_goodOpacity = anim::fvalue(1, 0);
|
||||
a_goodOpacity = anim::value(1, 0);
|
||||
_a_goodFade.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ private:
|
|||
QString _sentUsername, _checkUsername, _errorText, _goodText;
|
||||
|
||||
QString _goodTextLink;
|
||||
anim::fvalue a_goodOpacity;
|
||||
anim::value a_goodOpacity;
|
||||
Animation _a_goodFade;
|
||||
|
||||
QTimer _checkTimer;
|
||||
|
|
|
@ -332,6 +332,7 @@ contactsPhotoCheckbox: RoundImageCheckbox {
|
|||
}
|
||||
contactsPhotoDisabledCheckFg: #bbbbbb;
|
||||
contactsNameCheckedFg: #2b88b8;
|
||||
contactsRipple: defaultRippleAnimation;
|
||||
|
||||
localStorageBoxSkip: 10px;
|
||||
|
||||
|
@ -381,15 +382,21 @@ sessionWhenFont: msgDateFont;
|
|||
sessionWhenFg: #aaaaaa;
|
||||
sessionInfoFont: msgFont;
|
||||
sessionInfoFg: #888888;
|
||||
sessionTerminateTop: 30px;
|
||||
sessionTerminateSkip: 18px;
|
||||
sessionTerminateTop: 28px;
|
||||
sessionTerminateSkip: 22px;
|
||||
sessionTerminate: IconButton {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
icon: simpleCloseIcon;
|
||||
iconOver: simpleCloseIconOver;
|
||||
iconPosition: point(3px, 3px);
|
||||
iconPosition: point(5px, 5px);
|
||||
|
||||
rippleAreaPosition: point(0px, 0px);
|
||||
rippleAreaSize: 20px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
}
|
||||
sessionTerminateAllButton: LinkButton(boxLinkButton) {
|
||||
color: #d15948;
|
||||
|
|
|
@ -226,7 +226,7 @@ void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
|
|||
if (_linkOver) {
|
||||
Application::clipboard()->setText(_link);
|
||||
_goodTextLink = lang(lng_create_channel_link_copied);
|
||||
a_goodOpacity = anim::fvalue(1, 0);
|
||||
a_goodOpacity = anim::value(1, 0);
|
||||
_a_good.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ private:
|
|||
QPoint _lastMousePos;
|
||||
|
||||
QString _goodTextLink;
|
||||
anim::fvalue a_goodOpacity;
|
||||
anim::value a_goodOpacity;
|
||||
Animation _a_good;
|
||||
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "ui/widgets/multi_select.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/effects/widget_slide_wrap.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "boxes/photocropbox.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "observer_peer.h"
|
||||
|
@ -546,10 +547,14 @@ bool ContactsBox::creationFail(const RPCError &error) {
|
|||
return false;
|
||||
}
|
||||
|
||||
ContactsBox::Inner::ContactData::ContactData() = default;
|
||||
|
||||
ContactsBox::Inner::ContactData::ContactData(PeerData *peer, const base::lambda_copy<void()> &updateCallback)
|
||||
: checkbox(std_::make_unique<Ui::RoundImageCheckbox>(st::contactsPhotoCheckbox, updateCallback, PaintUserpicCallback(peer))) {
|
||||
}
|
||||
|
||||
ContactsBox::Inner::ContactData::~ContactData() = default;
|
||||
|
||||
ContactsBox::Inner::Inner(QWidget *parent, CreatingGroupType creating) : TWidget(parent)
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _creating(creating)
|
||||
|
@ -924,16 +929,16 @@ ContactsBox::Inner::ContactData *ContactsBox::Inner::contactData(Dialogs::Row *r
|
|||
return data;
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, ContactData *data, bool sel) {
|
||||
UserData *user = peer->asUser();
|
||||
void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, ContactData *data, bool selected) {
|
||||
auto user = peer->asUser();
|
||||
|
||||
if (_chat && _membersFilter == MembersFilter::Admins) {
|
||||
if (_allAdmins->checked() || peer->id == peerFromUser(_chat->creator) || _saving) {
|
||||
sel = false;
|
||||
selected = false;
|
||||
}
|
||||
} else {
|
||||
if (data->disabledChecked || selectedCount() >= Global::MegagroupSizeMax()) {
|
||||
sel = false;
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -945,7 +950,13 @@ void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, Cont
|
|||
}
|
||||
|
||||
auto checkedRatio = 0.;
|
||||
p.fillRect(0, 0, width(), _rowHeight, sel ? st::contactsBgOver : st::contactsBg);
|
||||
p.fillRect(0, 0, width(), _rowHeight, selected ? st::contactsBgOver : st::contactsBg);
|
||||
if (data->ripple) {
|
||||
data->ripple->paint(p, 0, 0, width(), ms);
|
||||
if (data->ripple->empty()) {
|
||||
data->ripple.reset();
|
||||
}
|
||||
}
|
||||
if (paintDisabledCheck) {
|
||||
paintDisabledCheckUserpic(p, peer, st::contactsPadding.left(), st::contactsPadding.top(), width());
|
||||
} else if (usingMultiSelect()) {
|
||||
|
@ -979,14 +990,14 @@ void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, Cont
|
|||
int32 secondw = st::contactsStatusFont->width(second);
|
||||
p.setPen(st::contactsStatusFgOnline);
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width() - secondw, first);
|
||||
p.setPen(sel ? st::contactsStatusFgOver : st::contactsStatusFg);
|
||||
p.setPen(selected ? st::contactsStatusFgOver : st::contactsStatusFg);
|
||||
p.drawTextLeft(namex + w, st::contactsPadding.top() + st::contactsStatusTop, width() + w, second);
|
||||
}
|
||||
} else {
|
||||
if ((user && (uname || data->statusHasOnlineColor)) || (peer->isChannel() && uname)) {
|
||||
p.setPen(st::contactsStatusFgOnline);
|
||||
} else {
|
||||
p.setPen(sel ? st::contactsStatusFgOver : st::contactsStatusFg);
|
||||
p.setPen(selected ? st::contactsStatusFgOver : st::contactsStatusFg);
|
||||
}
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), data->statusText);
|
||||
}
|
||||
|
@ -1064,7 +1075,8 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
if ((*i)->pos() * _rowHeight >= yTo) {
|
||||
break;
|
||||
}
|
||||
paintDialog(p, ms, (*i)->history()->peer, contactData(*i), (*i == _sel));
|
||||
auto selected = _pressed ? (*i == _pressed) : (*i == _selected);
|
||||
paintDialog(p, ms, (*i)->history()->peer, contactData(*i), selected);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
yFrom -= _contacts->size() * _rowHeight;
|
||||
|
@ -1080,11 +1092,12 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
yTo -= st::searchedBarHeight;
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
|
||||
int32 from = floorclamp(yFrom, _rowHeight, 0, _byUsername.size());
|
||||
int32 to = ceilclamp(yTo, _rowHeight, 0, _byUsername.size());
|
||||
auto from = floorclamp(yFrom, _rowHeight, 0, _byUsername.size());
|
||||
auto to = ceilclamp(yTo, _rowHeight, 0, _byUsername.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, ms, _byUsername[from], d_byUsername[from], (_byUsernameSel == from));
|
||||
auto selected = (_searchedPressed >= 0) ? (_searchedPressed == from) : (_searchedSelected == from);
|
||||
paintDialog(p, ms, _byUsername[from], d_byUsername[from], selected);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
}
|
||||
|
@ -1130,7 +1143,8 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
int32 to = ceilclamp(yTo, _rowHeight, 0, _filtered.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, ms, _filtered[from]->history()->peer, contactData(_filtered[from]), (_filteredSel == from));
|
||||
auto selected = (_filteredPressed >= 0) ? (_filteredPressed == from) : (_filteredSelected == from);
|
||||
paintDialog(p, ms, _filtered[from]->history()->peer, contactData(_filtered[from]), selected);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
}
|
||||
|
@ -1147,7 +1161,8 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
int32 to = ceilclamp(yTo, _rowHeight, 0, _byUsernameFiltered.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, ms, _byUsernameFiltered[from], d_byUsernameFiltered[from], (_byUsernameSel == from));
|
||||
auto selected = (_searchedPressed >= 0) ? (_searchedPressed == from) : (_searchedSelected == from);
|
||||
paintDialog(p, ms, _byUsernameFiltered[from], d_byUsernameFiltered[from], selected);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
}
|
||||
|
@ -1161,16 +1176,16 @@ void ContactsBox::Inner::enterEvent(QEvent *e) {
|
|||
|
||||
int ContactsBox::Inner::getSelectedRowTop() const {
|
||||
if (_filter.isEmpty()) {
|
||||
if (_sel) {
|
||||
return _aboutHeight + (_sel->pos() * _rowHeight);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_byUsernameSel * _rowHeight);
|
||||
if (_selected) {
|
||||
return _aboutHeight + (_selected->pos() * _rowHeight);
|
||||
} else if (_searchedSelected >= 0) {
|
||||
return _aboutHeight + (_contacts->size() * _rowHeight) + st::searchedBarHeight + (_searchedSelected * _rowHeight);
|
||||
}
|
||||
} else {
|
||||
if (_filteredSel >= 0) {
|
||||
return (_filteredSel * _rowHeight);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
return (_filtered.size() * _rowHeight + st::searchedBarHeight + _byUsernameSel * _rowHeight);
|
||||
if (_filteredSelected >= 0) {
|
||||
return (_filteredSelected * _rowHeight);
|
||||
} else if (_searchedSelected >= 0) {
|
||||
return (_filtered.size() * _rowHeight + st::searchedBarHeight + _searchedSelected * _rowHeight);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
@ -1222,53 +1237,130 @@ void ContactsBox::Inner::updateRowWithPeer(PeerData *peer) {
|
|||
}
|
||||
|
||||
void ContactsBox::Inner::leaveEvent(QEvent *e) {
|
||||
_mouseSel = false;
|
||||
_mouseSelection = false;
|
||||
setMouseTracking(false);
|
||||
if (_sel || _filteredSel >= 0 || _byUsernameSel >= 0) {
|
||||
if (_selected || _filteredSelected >= 0 || _searchedSelected >= 0) {
|
||||
updateSelectedRow();
|
||||
_sel = 0;
|
||||
_filteredSel = _byUsernameSel = -1;
|
||||
_selected = nullptr;
|
||||
_filteredSelected = _searchedSelected = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
_mouseSel = true;
|
||||
_mouseSelection = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||
_mouseSel = true;
|
||||
_mouseSelection = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSelection();
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
chooseParticipant();
|
||||
|
||||
setPressed(_selected);
|
||||
setFilteredPressed(_filteredSelected);
|
||||
setSearchedPressed(_searchedSelected);
|
||||
if (_pressed) {
|
||||
addRipple(contactData(_selected));
|
||||
} else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) {
|
||||
addRipple(contactData(_filtered[_filteredSelected]));
|
||||
} else if (_searchedSelected >= 0) {
|
||||
if (_filter.isEmpty() && _searchedSelected < d_byUsername.size()) {
|
||||
addRipple(d_byUsername[_searchedSelected]);
|
||||
} else if (!_filter.isEmpty() && _searchedSelected < d_byUsernameFiltered.size()) {
|
||||
addRipple(d_byUsernameFiltered[_searchedSelected]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
auto pressed = _pressed;
|
||||
setPressed(nullptr);
|
||||
auto filteredPressed = _filteredPressed;
|
||||
setFilteredPressed(-1);
|
||||
auto searchedPressed = _searchedPressed;
|
||||
setSearchedPressed(-1);
|
||||
updateSelectedRow();
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
if (pressed && pressed == _selected) {
|
||||
chooseParticipant();
|
||||
} else if (filteredPressed >= 0 && filteredPressed == _filteredSelected) {
|
||||
chooseParticipant();
|
||||
} else if (searchedPressed >= 0 && searchedPressed == _searchedSelected) {
|
||||
chooseParticipant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::addRipple(ContactData *data) {
|
||||
auto rowTop = getSelectedRowTop();
|
||||
if (!data->ripple) {
|
||||
auto mask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight));
|
||||
data->ripple = std_::make_unique<Ui::RippleAnimation>(st::contactsRipple, std_::move(mask), [this, data] {
|
||||
updateRowWithTop(data->rippleRowTop);
|
||||
});
|
||||
}
|
||||
data->rippleRowTop = rowTop;
|
||||
data->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(0, rowTop));
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::stopLastRipple(ContactData *data) {
|
||||
if (data->ripple) {
|
||||
data->ripple->lastStop();
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::setPressed(Dialogs::Row *pressed) {
|
||||
if (_pressed != pressed) {
|
||||
if (_pressed) {
|
||||
stopLastRipple(contactData(_pressed));
|
||||
}
|
||||
_pressed = pressed;
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::setFilteredPressed(int pressed) {
|
||||
if (_filteredPressed >= 0 && _filteredPressed < _filtered.size()) {
|
||||
stopLastRipple(contactData(_filtered[_filteredPressed]));
|
||||
}
|
||||
_filteredPressed = pressed;
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::setSearchedPressed(int pressed) {
|
||||
if (_searchedPressed >= 0) {
|
||||
if (_searchedPressed < d_byUsername.size()) {
|
||||
stopLastRipple(d_byUsername[_searchedPressed]);
|
||||
}
|
||||
if (_searchedPressed < d_byUsernameFiltered.size()) {
|
||||
stopLastRipple(d_byUsernameFiltered[_searchedPressed]);
|
||||
}
|
||||
}
|
||||
_searchedPressed = pressed;
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::chooseParticipant() {
|
||||
if (_saving) return;
|
||||
bool addingAdmin = (_channel && _membersFilter == MembersFilter::Admins);
|
||||
if (!addingAdmin && usingMultiSelect()) {
|
||||
_time = unixtime();
|
||||
if (_filter.isEmpty()) {
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) {
|
||||
auto data = d_byUsername[_byUsernameSel];
|
||||
auto peer = _byUsername[_byUsernameSel];
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsername.size()) {
|
||||
auto data = d_byUsername[_searchedSelected];
|
||||
auto peer = _byUsername[_searchedSelected];
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
changeCheckState(data, peer);
|
||||
} else if (_sel) {
|
||||
auto data = contactData(_sel);
|
||||
auto peer = _sel->history()->peer;
|
||||
} else if (_selected) {
|
||||
auto data = contactData(_selected);
|
||||
auto peer = _selected->history()->peer;
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
changeCheckState(_sel);
|
||||
changeCheckState(_selected);
|
||||
}
|
||||
} else {
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) {
|
||||
auto data = d_byUsernameFiltered[_byUsernameSel];
|
||||
auto peer = _byUsernameFiltered[_byUsernameSel];
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsernameFiltered.size()) {
|
||||
auto data = d_byUsernameFiltered[_searchedSelected];
|
||||
auto peer = _byUsernameFiltered[_searchedSelected];
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
int i = 0, l = d_byUsername.size();
|
||||
|
@ -1291,9 +1383,9 @@ void ContactsBox::Inner::chooseParticipant() {
|
|||
}
|
||||
|
||||
changeCheckState(data, peer);
|
||||
} else if (_filteredSel >= 0 && _filteredSel < _filtered.size()) {
|
||||
auto data = contactData(_filtered[_filteredSel]);
|
||||
auto peer = _filtered[_filteredSel]->history()->peer;
|
||||
} else if (_filteredSelected >= 0 && _filteredSelected < _filtered.size()) {
|
||||
auto data = contactData(_filtered[_filteredSelected]);
|
||||
auto peer = _filtered[_filteredSelected]->history()->peer;
|
||||
if (data->disabledChecked) return;
|
||||
|
||||
changeCheckState(data, peer);
|
||||
|
@ -1302,17 +1394,17 @@ void ContactsBox::Inner::chooseParticipant() {
|
|||
} else {
|
||||
PeerData *peer = 0;
|
||||
if (_filter.isEmpty()) {
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) {
|
||||
peer = _byUsername[_byUsernameSel];
|
||||
} else if (_sel) {
|
||||
peer = _sel->history()->peer;
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsername.size()) {
|
||||
peer = _byUsername[_searchedSelected];
|
||||
} else if (_selected) {
|
||||
peer = _selected->history()->peer;
|
||||
}
|
||||
} else {
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) {
|
||||
peer = _byUsernameFiltered[_byUsernameSel];
|
||||
if (_searchedSelected >= 0 && _searchedSelected < _byUsernameFiltered.size()) {
|
||||
peer = _byUsernameFiltered[_searchedSelected];
|
||||
} else {
|
||||
if (_filteredSel < 0 || _filteredSel >= _filtered.size()) return;
|
||||
peer = _filtered[_filteredSel]->history()->peer;
|
||||
if (_filteredSelected < 0 || _filteredSelected >= _filtered.size()) return;
|
||||
peer = _filtered[_filteredSelected]->history()->peer;
|
||||
}
|
||||
}
|
||||
if (peer) {
|
||||
|
@ -1408,31 +1500,35 @@ int32 ContactsBox::Inner::selectedCount() const {
|
|||
}
|
||||
|
||||
void ContactsBox::Inner::updateSelection() {
|
||||
if (!_mouseSel) return;
|
||||
if (!_mouseSelection) return;
|
||||
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
auto p = mapFromGlobal(_lastMousePos);
|
||||
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
|
||||
if (_filter.isEmpty()) {
|
||||
_filteredSelected = -1;
|
||||
setFilteredPressed(-1);
|
||||
if (_aboutHeight) {
|
||||
p.setY(p.y() - _aboutHeight);
|
||||
}
|
||||
Dialogs::Row *newSel = (in && (p.y() >= 0) && (p.y() < _contacts->size() * _rowHeight)) ? _contacts->rowAtY(p.y(), _rowHeight) : nullptr;
|
||||
int32 byUsernameSel = (in && p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
|
||||
if (byUsernameSel >= _byUsername.size()) byUsernameSel = -1;
|
||||
if (newSel != _sel || byUsernameSel != _byUsernameSel) {
|
||||
auto selected = (in && (p.y() >= 0) && (p.y() < _contacts->size() * _rowHeight)) ? _contacts->rowAtY(p.y(), _rowHeight) : nullptr;
|
||||
auto searchedSelected = (in && p.y() >= _contacts->size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _contacts->size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
|
||||
if (searchedSelected >= _byUsername.size()) searchedSelected = -1;
|
||||
if (_selected != selected || _searchedSelected != searchedSelected) {
|
||||
updateSelectedRow();
|
||||
_sel = newSel;
|
||||
_byUsernameSel = byUsernameSel;
|
||||
_selected = selected;
|
||||
_searchedSelected = searchedSelected;
|
||||
updateSelectedRow();
|
||||
}
|
||||
} else {
|
||||
int32 newFilteredSel = (in && p.y() >= 0 && p.y() < _filtered.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
|
||||
int32 byUsernameSel = (in && p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
|
||||
if (byUsernameSel >= _byUsernameFiltered.size()) byUsernameSel = -1;
|
||||
if (newFilteredSel != _filteredSel || byUsernameSel != _byUsernameSel) {
|
||||
_selected = nullptr;
|
||||
setPressed(nullptr);
|
||||
auto filteredSelected = (in && p.y() >= 0 && p.y() < _filtered.size() * _rowHeight) ? (p.y() / _rowHeight) : -1;
|
||||
auto searchedSelected = (in && p.y() >= _filtered.size() * _rowHeight + st::searchedBarHeight) ? ((p.y() - _filtered.size() * _rowHeight - st::searchedBarHeight) / _rowHeight) : -1;
|
||||
if (searchedSelected >= _byUsernameFiltered.size()) searchedSelected = -1;
|
||||
if (_filteredSelected != filteredSelected || _searchedSelected != searchedSelected) {
|
||||
updateSelectedRow();
|
||||
_filteredSel = newFilteredSel;
|
||||
_byUsernameSel = byUsernameSel;
|
||||
_filteredSelected = filteredSelected;
|
||||
_searchedSelected = searchedSelected;
|
||||
updateSelectedRow();
|
||||
}
|
||||
}
|
||||
|
@ -1461,13 +1557,15 @@ void ContactsBox::Inner::updateFilter(QString filter) {
|
|||
|
||||
_byUsernameFiltered.clear();
|
||||
d_byUsernameFiltered.clear();
|
||||
for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) {
|
||||
delete _byUsernameDatas[i];
|
||||
}
|
||||
_byUsernameDatas.clear();
|
||||
clearSearchedContactDatas();
|
||||
|
||||
_selected = nullptr;
|
||||
setPressed(nullptr);
|
||||
_filteredSelected = -1;
|
||||
setFilteredPressed(-1);
|
||||
_searchedSelected = -1;
|
||||
setSearchedPressed(-1);
|
||||
if (_filter.isEmpty()) {
|
||||
_sel = 0;
|
||||
refresh();
|
||||
} else {
|
||||
if (!_addContactLnk->isHidden()) _addContactLnk->hide();
|
||||
|
@ -1534,21 +1632,19 @@ void ContactsBox::Inner::updateFilter(QString filter) {
|
|||
}
|
||||
}
|
||||
}
|
||||
_filteredSel = -1;
|
||||
if (!_filtered.isEmpty()) {
|
||||
for (_filteredSel = 0; (_filteredSel < _filtered.size()) && contactData(_filtered[_filteredSel])->disabledChecked;) {
|
||||
++_filteredSel;
|
||||
for (_filteredSelected = 0; (_filteredSelected < _filtered.size()) && contactData(_filtered[_filteredSelected])->disabledChecked;) {
|
||||
++_filteredSelected;
|
||||
}
|
||||
if (_filteredSel == _filtered.size()) _filteredSel = -1;
|
||||
if (_filteredSelected == _filtered.size()) _filteredSelected = -1;
|
||||
}
|
||||
_byUsernameSel = -1;
|
||||
if (_filteredSel < 0 && !_byUsernameFiltered.isEmpty()) {
|
||||
for (_byUsernameSel = 0; (_byUsernameSel < _byUsernameFiltered.size()) && d_byUsernameFiltered[_byUsernameSel]->disabledChecked;) {
|
||||
++_byUsernameSel;
|
||||
if (_filteredSelected < 0 && !_byUsernameFiltered.isEmpty()) {
|
||||
for (_searchedSelected = 0; (_searchedSelected < _byUsernameFiltered.size()) && d_byUsernameFiltered[_searchedSelected]->disabledChecked;) {
|
||||
++_searchedSelected;
|
||||
}
|
||||
if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1;
|
||||
if (_searchedSelected == _byUsernameFiltered.size()) _searchedSelected = -1;
|
||||
}
|
||||
_mouseSel = false;
|
||||
_mouseSelection = false;
|
||||
refresh();
|
||||
|
||||
if ((!bot() || sharingBotGame()) && (!_chat || _membersFilter != MembersFilter::Admins)) {
|
||||
|
@ -1561,9 +1657,15 @@ void ContactsBox::Inner::updateFilter(QString filter) {
|
|||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::clearSearchedContactDatas() {
|
||||
for (auto data : base::take(_byUsernameDatas)) {
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRow) {
|
||||
if (!_filter.isEmpty()) {
|
||||
for (FilteredDialogs::iterator i = _filtered.begin(), e = _filtered.end(); i != e;) {
|
||||
for (auto 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;
|
||||
|
@ -1575,18 +1677,21 @@ void ContactsBox::Inner::onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row
|
|||
++i;
|
||||
}
|
||||
}
|
||||
if (_filteredSel >= _filtered.size()) {
|
||||
_filteredSel = -1;
|
||||
if (_filteredSelected >= _filtered.size()) {
|
||||
_filteredSelected = -1;
|
||||
}
|
||||
if (_filteredPressed >= _filtered.size()) {
|
||||
_filteredPressed = -1;
|
||||
}
|
||||
} else {
|
||||
if (_sel == oldRow) {
|
||||
_sel = newRow;
|
||||
if (_selected == oldRow) {
|
||||
_selected = newRow;
|
||||
}
|
||||
if (_pressed == oldRow) {
|
||||
setPressed(newRow);
|
||||
}
|
||||
}
|
||||
_mouseSel = false;
|
||||
int cnt = (_filter.isEmpty() ? _contacts->size() : _filtered.size());
|
||||
int newh = cnt ? (cnt * _rowHeight) : st::noContactsHeight;
|
||||
resize(width(), newh);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void ContactsBox::Inner::peopleReceived(const QString &query, const QVector<MTPPeer> &people) {
|
||||
|
@ -1707,6 +1812,10 @@ ContactsBox::Inner::~Inner() {
|
|||
for (auto contactData : base::take(_contactsData)) {
|
||||
delete contactData;
|
||||
}
|
||||
clearSearchedContactDatas();
|
||||
for (auto data : base::take(d_byUsername)) {
|
||||
delete data;
|
||||
}
|
||||
if (_bot) {
|
||||
if (auto &info = _bot->botInfo) {
|
||||
info->startGroupToken = QString();
|
||||
|
@ -1722,127 +1831,127 @@ void ContactsBox::Inner::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
void ContactsBox::Inner::selectSkip(int32 dir) {
|
||||
_time = unixtime();
|
||||
_mouseSel = false;
|
||||
_mouseSelection = false;
|
||||
if (_filter.isEmpty()) {
|
||||
int cur = 0;
|
||||
if (_sel) {
|
||||
for (auto i = _contacts->cbegin(); *i != _sel; ++i) {
|
||||
if (_selected) {
|
||||
for (auto i = _contacts->cbegin(); *i != _selected; ++i) {
|
||||
++cur;
|
||||
}
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
cur = (_contacts->size() + _byUsernameSel);
|
||||
} else if (_searchedSelected >= 0) {
|
||||
cur = (_contacts->size() + _searchedSelected);
|
||||
} else {
|
||||
cur = -1;
|
||||
}
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_sel = (!_contacts->isEmpty()) ? *_contacts->cbegin() : nullptr;
|
||||
_byUsernameSel = (_contacts->isEmpty() && !_byUsername.isEmpty()) ? 0 : -1;
|
||||
_selected = (!_contacts->isEmpty()) ? *_contacts->cbegin() : nullptr;
|
||||
_searchedSelected = (_contacts->isEmpty() && !_byUsername.isEmpty()) ? 0 : -1;
|
||||
} else if (cur >= _contacts->size()) {
|
||||
if (_byUsername.isEmpty()) {
|
||||
_sel = _contacts->isEmpty() ? nullptr : *(_contacts->cend() - 1);
|
||||
_byUsernameSel = -1;
|
||||
_selected = _contacts->isEmpty() ? nullptr : *(_contacts->cend() - 1);
|
||||
_searchedSelected = -1;
|
||||
} else {
|
||||
_sel = nullptr;
|
||||
_byUsernameSel = cur - _contacts->size();
|
||||
if (_byUsernameSel >= _byUsername.size()) _byUsernameSel = _byUsername.size() - 1;
|
||||
_selected = nullptr;
|
||||
_searchedSelected = cur - _contacts->size();
|
||||
if (_searchedSelected >= _byUsername.size()) _searchedSelected = _byUsername.size() - 1;
|
||||
}
|
||||
} else {
|
||||
for (auto i = _contacts->cbegin(); ; ++i) {
|
||||
_sel = *i;
|
||||
_selected = *i;
|
||||
if (!cur) {
|
||||
break;
|
||||
} else {
|
||||
--cur;
|
||||
}
|
||||
}
|
||||
_byUsernameSel = -1;
|
||||
_searchedSelected = -1;
|
||||
}
|
||||
if (dir > 0) {
|
||||
for (auto i = _contacts->cfind(_sel), end = _contacts->cend(); i != end && contactData(*i)->disabledChecked; ++i) {
|
||||
_sel = *i;
|
||||
for (auto i = _contacts->cfind(_selected), end = _contacts->cend(); i != end && contactData(*i)->disabledChecked; ++i) {
|
||||
_selected = *i;
|
||||
}
|
||||
if (_sel && contactData(_sel)->disabledChecked) {
|
||||
_sel = nullptr;
|
||||
if (_selected && contactData(_selected)->disabledChecked) {
|
||||
_selected = nullptr;
|
||||
}
|
||||
if (!_sel) {
|
||||
if (!_selected) {
|
||||
if (!_byUsername.isEmpty()) {
|
||||
if (_byUsernameSel < 0) _byUsernameSel = 0;
|
||||
for (; _byUsernameSel < _byUsername.size() && d_byUsername[_byUsernameSel]->disabledChecked;) {
|
||||
++_byUsernameSel;
|
||||
if (_searchedSelected < 0) _searchedSelected = 0;
|
||||
for (; _searchedSelected < _byUsername.size() && d_byUsername[_searchedSelected]->disabledChecked;) {
|
||||
++_searchedSelected;
|
||||
}
|
||||
if (_byUsernameSel == _byUsername.size()) _byUsernameSel = -1;
|
||||
if (_searchedSelected == _byUsername.size()) _searchedSelected = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (_byUsernameSel >= 0 && d_byUsername[_byUsernameSel]->disabledChecked) {
|
||||
--_byUsernameSel;
|
||||
while (_searchedSelected >= 0 && d_byUsername[_searchedSelected]->disabledChecked) {
|
||||
--_searchedSelected;
|
||||
}
|
||||
if (_byUsernameSel < 0) {
|
||||
if (_searchedSelected < 0) {
|
||||
if (!_contacts->isEmpty()) {
|
||||
if (!_sel) _sel = *(_contacts->cend() - 1);
|
||||
if (_sel) {
|
||||
for (auto i = _contacts->cfind(_sel), b = _contacts->cbegin(); i != b && contactData(*i)->disabledChecked; --i) {
|
||||
_sel = *i;
|
||||
if (!_selected) _selected = *(_contacts->cend() - 1);
|
||||
if (_selected) {
|
||||
for (auto i = _contacts->cfind(_selected), b = _contacts->cbegin(); i != b && contactData(*i)->disabledChecked; --i) {
|
||||
_selected = *i;
|
||||
}
|
||||
if (contactData(_sel)->disabledChecked) {
|
||||
_sel = nullptr;
|
||||
if (contactData(_selected)->disabledChecked) {
|
||||
_selected = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_sel) {
|
||||
emit mustScrollTo(_aboutHeight + _sel->pos() * _rowHeight, _aboutHeight + (_sel->pos() + 1) * _rowHeight);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
emit mustScrollTo(_aboutHeight + (_contacts->size() + _byUsernameSel) * _rowHeight + st::searchedBarHeight, _aboutHeight + (_contacts->size() + _byUsernameSel + 1) * _rowHeight + st::searchedBarHeight);
|
||||
if (_selected) {
|
||||
emit mustScrollTo(_aboutHeight + _selected->pos() * _rowHeight, _aboutHeight + (_selected->pos() + 1) * _rowHeight);
|
||||
} else if (_searchedSelected >= 0) {
|
||||
emit mustScrollTo(_aboutHeight + (_contacts->size() + _searchedSelected) * _rowHeight + st::searchedBarHeight, _aboutHeight + (_contacts->size() + _searchedSelected + 1) * _rowHeight + st::searchedBarHeight);
|
||||
}
|
||||
} else {
|
||||
int cur = (_filteredSel >= 0) ? _filteredSel : ((_byUsernameSel >= 0) ? (_filtered.size() + _byUsernameSel) : -1);
|
||||
int cur = (_filteredSelected >= 0) ? _filteredSelected : ((_searchedSelected >= 0) ? (_filtered.size() + _searchedSelected) : -1);
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_filteredSel = _filtered.isEmpty() ? -1 : 0;
|
||||
_byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1;
|
||||
_filteredSelected = _filtered.isEmpty() ? -1 : 0;
|
||||
_searchedSelected = (_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;
|
||||
_filteredSelected = -1;
|
||||
_searchedSelected = cur - _filtered.size();
|
||||
if (_searchedSelected >= _byUsernameFiltered.size()) _searchedSelected = _byUsernameFiltered.size() - 1;
|
||||
} else {
|
||||
_filteredSel = cur;
|
||||
_byUsernameSel = -1;
|
||||
_filteredSelected = cur;
|
||||
_searchedSelected = -1;
|
||||
}
|
||||
if (dir > 0) {
|
||||
while (_filteredSel >= 0 && _filteredSel < _filtered.size() && contactData(_filtered[_filteredSel])->disabledChecked) {
|
||||
++_filteredSel;
|
||||
while (_filteredSelected >= 0 && _filteredSelected < _filtered.size() && contactData(_filtered[_filteredSelected])->disabledChecked) {
|
||||
++_filteredSelected;
|
||||
}
|
||||
if (_filteredSel < 0 || _filteredSel >= _filtered.size()) {
|
||||
_filteredSel = -1;
|
||||
if (_filteredSelected < 0 || _filteredSelected >= _filtered.size()) {
|
||||
_filteredSelected = -1;
|
||||
if (!_byUsernameFiltered.isEmpty()) {
|
||||
if (_byUsernameSel < 0) _byUsernameSel = 0;
|
||||
for (; _byUsernameSel < _byUsernameFiltered.size() && d_byUsernameFiltered[_byUsernameSel]->disabledChecked;) {
|
||||
++_byUsernameSel;
|
||||
if (_searchedSelected < 0) _searchedSelected = 0;
|
||||
for (; _searchedSelected < _byUsernameFiltered.size() && d_byUsernameFiltered[_searchedSelected]->disabledChecked;) {
|
||||
++_searchedSelected;
|
||||
}
|
||||
if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1;
|
||||
if (_searchedSelected == _byUsernameFiltered.size()) _searchedSelected = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (_byUsernameSel >= 0 && d_byUsernameFiltered[_byUsernameSel]->disabledChecked) {
|
||||
--_byUsernameSel;
|
||||
while (_searchedSelected >= 0 && d_byUsernameFiltered[_searchedSelected]->disabledChecked) {
|
||||
--_searchedSelected;
|
||||
}
|
||||
if (_byUsernameSel < 0) {
|
||||
if (_searchedSelected < 0) {
|
||||
if (!_filtered.isEmpty()) {
|
||||
if (_filteredSel < 0) _filteredSel = _filtered.size() - 1;
|
||||
for (; _filteredSel >= 0 && contactData(_filtered[_filteredSel])->disabledChecked;) {
|
||||
--_filteredSel;
|
||||
if (_filteredSelected < 0) _filteredSelected = _filtered.size() - 1;
|
||||
for (; _filteredSelected >= 0 && contactData(_filtered[_filteredSelected])->disabledChecked;) {
|
||||
--_filteredSelected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_filteredSel >= 0) {
|
||||
emit mustScrollTo(_filteredSel * _rowHeight, (_filteredSel + 1) * _rowHeight);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
if (_filteredSelected >= 0) {
|
||||
emit mustScrollTo(_filteredSelected * _rowHeight, (_filteredSelected + 1) * _rowHeight);
|
||||
} else if (_searchedSelected >= 0) {
|
||||
int skip = _filtered.size() * _rowHeight + st::searchedBarHeight;
|
||||
emit mustScrollTo(skip + _byUsernameSel * _rowHeight, skip + (_byUsernameSel + 1) * _rowHeight);
|
||||
emit mustScrollTo(skip + _searchedSelected * _rowHeight, skip + (_searchedSelected + 1) * _rowHeight);
|
||||
}
|
||||
}
|
||||
update();
|
||||
|
|
|
@ -31,6 +31,7 @@ class IndexedList;
|
|||
} // namespace Dialogs
|
||||
|
||||
namespace Ui {
|
||||
class RippleAnimation;
|
||||
class RoundButton;
|
||||
class LinkButton;
|
||||
class Checkbox;
|
||||
|
@ -208,19 +209,29 @@ protected:
|
|||
void leaveEvent(QEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
struct ContactData {
|
||||
ContactData() = default;
|
||||
ContactData();
|
||||
ContactData(PeerData *peer, const base::lambda_copy<void()> &updateCallback);
|
||||
~ContactData();
|
||||
|
||||
std_::unique_ptr<Ui::RoundImageCheckbox> checkbox;
|
||||
std_::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
int rippleRowTop = 0;
|
||||
Text name;
|
||||
QString statusText;
|
||||
bool statusHasOnlineColor = false;
|
||||
bool disabledChecked = false;
|
||||
};
|
||||
void addRipple(ContactData *data);
|
||||
void stopLastRipple(ContactData *data);
|
||||
void setPressed(Dialogs::Row *pressed);
|
||||
void setFilteredPressed(int pressed);
|
||||
void setSearchedPressed(int pressed);
|
||||
void clearSearchedContactDatas();
|
||||
|
||||
void init();
|
||||
void initList();
|
||||
|
@ -277,12 +288,14 @@ private:
|
|||
|
||||
std_::unique_ptr<Dialogs::IndexedList> _customList;
|
||||
Dialogs::IndexedList *_contacts = nullptr;
|
||||
Dialogs::Row *_sel = nullptr;
|
||||
Dialogs::Row *_selected = nullptr;
|
||||
Dialogs::Row *_pressed = nullptr;
|
||||
QString _filter;
|
||||
using FilteredDialogs = QVector<Dialogs::Row*>;
|
||||
FilteredDialogs _filtered;
|
||||
int _filteredSel = -1;
|
||||
bool _mouseSel = false;
|
||||
int _filteredSelected = -1;
|
||||
int _filteredPressed = -1;
|
||||
bool _mouseSelection = false;
|
||||
|
||||
using ContactsData = QMap<PeerData*, ContactData*>;
|
||||
ContactsData _contactsData;
|
||||
|
@ -298,7 +311,8 @@ private:
|
|||
ByUsernameRows _byUsername, _byUsernameFiltered;
|
||||
ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas
|
||||
ByUsernameDatas _byUsernameDatas;
|
||||
int _byUsernameSel = -1;
|
||||
int _searchedSelected = -1;
|
||||
int _searchedPressed = -1;
|
||||
|
||||
QPoint _lastMousePos;
|
||||
ChildWidget<Ui::LinkButton> _addContactLnk;
|
||||
|
|
|
@ -44,8 +44,8 @@ void MembersAddButton::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
auto ms = getms();
|
||||
auto over = (_state & StateOver);
|
||||
auto down = (_state & StateDown);
|
||||
auto over = isOver();
|
||||
auto down = isDown();
|
||||
|
||||
((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
|
|
|
@ -311,7 +311,7 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
|
||||
void SessionsBox::Inner::onTerminate() {
|
||||
for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) {
|
||||
if (i.value()->getState() & Ui::AbstractButton::StateOver) {
|
||||
if (i.value()->isOver()) {
|
||||
_terminating = i.key();
|
||||
|
||||
if (_terminateBox) _terminateBox->deleteLater();
|
||||
|
|
|
@ -274,7 +274,7 @@ void ShareBox::onMustScrollTo(int top, int bottom) {
|
|||
}
|
||||
if (from != to) {
|
||||
_scrollAnimation.start([this]() {
|
||||
scrollArea()->scrollToY(_scrollAnimation.current(scrollArea()->scrollTop()));
|
||||
scrollArea()->scrollToY(qRound(_scrollAnimation.current(scrollArea()->scrollTop())));
|
||||
}, from, to, st::shareScrollDuration, anim::sineInOut);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ private:
|
|||
using PeopleQueries = QMap<mtpRequestId, QString>;
|
||||
PeopleQueries _peopleQueries;
|
||||
|
||||
IntAnimation _scrollAnimation;
|
||||
FloatAnimation _scrollAnimation;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -663,7 +663,7 @@ QRect StickersBox::Inner::relativeButtonRect(bool removeButton) const {
|
|||
void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
||||
auto s = _rows.at(index);
|
||||
|
||||
auto xadd = 0, yadd = s->yadd.current();
|
||||
auto xadd = 0, yadd = qRound(s->yadd.current());
|
||||
if (xadd || yadd) p.translate(xadd, yadd);
|
||||
|
||||
if (_section == Section::Installed) {
|
||||
|
@ -673,7 +673,7 @@ void StickersBox::Inner::paintRow(Painter &p, int index, TimeMs ms) {
|
|||
if (_started >= 0) {
|
||||
float64 o = aboveShadowOpacity();
|
||||
if (o > current) {
|
||||
_aboveShadowFadeOpacity = anim::fvalue(o, o);
|
||||
_aboveShadowFadeOpacity = anim::value(o, o);
|
||||
current = o;
|
||||
}
|
||||
}
|
||||
|
@ -858,14 +858,14 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
shift = -floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging - firstSetIndex);
|
||||
for (int32 from = _dragging, to = _dragging + shift; from > to; --from) {
|
||||
qSwap(_rows[from], _rows[from - 1]);
|
||||
_rows.at(from)->yadd = anim::ivalue(_rows.at(from)->yadd.current() - _rowHeight, 0);
|
||||
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() - _rowHeight, 0);
|
||||
_animStartTimes[from] = ms;
|
||||
}
|
||||
} else if (_dragStart.y() < local.y() && _dragging + 1 < _rows.size()) {
|
||||
shift = floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1);
|
||||
for (int32 from = _dragging, to = _dragging + shift; from < to; ++from) {
|
||||
qSwap(_rows[from], _rows[from + 1]);
|
||||
_rows.at(from)->yadd = anim::ivalue(_rows.at(from)->yadd.current() + _rowHeight, 0);
|
||||
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() + _rowHeight, 0);
|
||||
_animStartTimes[from] = ms;
|
||||
}
|
||||
}
|
||||
|
@ -877,7 +877,7 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
_a_shifting.start();
|
||||
}
|
||||
}
|
||||
_rows.at(_dragging)->yadd = anim::ivalue(local.y() - _dragStart.y(), local.y() - _dragStart.y());
|
||||
_rows[_dragging]->yadd = anim::value(local.y() - _dragStart.y(), local.y() - _dragStart.y());
|
||||
_animStartTimes[_dragging] = 0;
|
||||
_a_shifting.step(getms(), true);
|
||||
|
||||
|
@ -926,8 +926,8 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
float64 StickersBox::Inner::aboveShadowOpacity() const {
|
||||
if (_above < 0) return 0;
|
||||
|
||||
int32 dx = 0;
|
||||
int32 dy = qAbs(_above * _rowHeight + _rows.at(_above)->yadd.current() - _started * _rowHeight);
|
||||
auto dx = 0;
|
||||
auto dy = qAbs(_above * _rowHeight + qRound(_rows[_above]->yadd.current()) - _started * _rowHeight);
|
||||
return qMin((dx + dy) * 2. / _rowHeight, 1.);
|
||||
}
|
||||
|
||||
|
@ -948,9 +948,9 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
}
|
||||
} else if (_dragging >= 0) {
|
||||
QPoint local(mapFromGlobal(_mouse));
|
||||
_rows[_dragging]->yadd.start(0);
|
||||
_rows[_dragging]->yadd.start(0.);
|
||||
_aboveShadowFadeStart = _animStartTimes[_dragging] = getms();
|
||||
_aboveShadowFadeOpacity = anim::fvalue(aboveShadowOpacity(), 0);
|
||||
_aboveShadowFadeOpacity = anim::value(aboveShadowOpacity(), 0);
|
||||
if (!_a_shifting.animating()) {
|
||||
_a_shifting.start();
|
||||
}
|
||||
|
@ -994,10 +994,10 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
|
|||
if (updateMin < 0) updateMin = i;
|
||||
updateMax = i;
|
||||
if (start + st::stickersRowDuration > ms && ms >= start) {
|
||||
_rows.at(i)->yadd.update(float64(ms - start) / st::stickersRowDuration, anim::sineInOut);
|
||||
_rows[i]->yadd.update(float64(ms - start) / st::stickersRowDuration, anim::sineInOut);
|
||||
animating = true;
|
||||
} else {
|
||||
_rows.at(i)->yadd.finish();
|
||||
_rows[i]->yadd.finish();
|
||||
_animStartTimes[i] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1035,7 +1035,7 @@ void StickersBox::Inner::clear() {
|
|||
_rows.clear();
|
||||
_animStartTimes.clear();
|
||||
_aboveShadowFadeStart = 0;
|
||||
_aboveShadowFadeOpacity = anim::fvalue(0, 0);
|
||||
_aboveShadowFadeOpacity = anim::value();
|
||||
_a_shifting.stop();
|
||||
_above = _dragging = _started = -1;
|
||||
_selected = -1;
|
||||
|
|
|
@ -229,7 +229,7 @@ private:
|
|||
int titleWidth;
|
||||
bool installed, official, unread, archived, removed;
|
||||
int32 pixw, pixh;
|
||||
anim::ivalue yadd;
|
||||
anim::value yadd;
|
||||
QSharedPointer<Ui::RippleAnimation> ripple;
|
||||
};
|
||||
using Rows = QList<Row*>;
|
||||
|
@ -245,7 +245,7 @@ private:
|
|||
Rows _rows;
|
||||
QList<TimeMs> _animStartTimes;
|
||||
TimeMs _aboveShadowFadeStart = 0;
|
||||
anim::fvalue _aboveShadowFadeOpacity = { 0., 0. };
|
||||
anim::value _aboveShadowFadeOpacity;
|
||||
Animation _a_shifting;
|
||||
|
||||
base::lambda<void(uint64 setId)> _installSetCallback;
|
||||
|
|
|
@ -200,6 +200,7 @@ public:
|
|||
}
|
||||
~unique_ptr() noexcept {
|
||||
if (_p) {
|
||||
static_assert(sizeof(T) > 0, "can't delete an incomplete type");
|
||||
delete _p;
|
||||
_p = nullptr;
|
||||
}
|
||||
|
@ -228,6 +229,7 @@ public:
|
|||
auto old = _p;
|
||||
_p = p;
|
||||
if (old) {
|
||||
static_assert(sizeof(T) > 0, "can't delete an incomplete type");
|
||||
delete old;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "core/utils.h"
|
||||
|
||||
#define BETA_VERSION_MACRO (10019011ULL)
|
||||
#define BETA_VERSION_MACRO (10019012ULL)
|
||||
|
||||
constexpr int AppVersion = 10020;
|
||||
constexpr str_const AppVersionStr = "0.10.20";
|
||||
|
|
|
@ -27,6 +27,10 @@ dialogsUnreadFont: font(12px bold);
|
|||
dialogsUnreadHeight: 19px;
|
||||
dialogsUnreadPadding: 5px;
|
||||
|
||||
dialogsRipple: defaultRippleAnimation;
|
||||
dialogsRippleBg: windowBgRipple;
|
||||
dialogsRippleBgActive: activeButtonBgRipple;
|
||||
|
||||
dialogsTextFont: font(fsize);
|
||||
dialogsDateFont: font(13px);
|
||||
dialogsDateSkip: 5px;
|
||||
|
|
|
@ -59,20 +59,21 @@ void paintRowDate(Painter &p, const QDateTime &date, QRect &rectForName, bool ac
|
|||
}
|
||||
|
||||
template <typename PaintItemCallback>
|
||||
void paintRow(Painter &p, History *history, HistoryItem *item, Data::Draft *draft, QDateTime date, int w, bool active, bool selected, bool onlyBackground, TimeMs ms, PaintItemCallback paintItemCallback) {
|
||||
QRect fullRect(0, 0, w, st::dialogsRowHeight);
|
||||
void paintRow(Painter &p, const RippleRow *row, History *history, HistoryItem *item, Data::Draft *draft, QDateTime date, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms, PaintItemCallback paintItemCallback) {
|
||||
QRect fullRect(0, 0, fullWidth, st::dialogsRowHeight);
|
||||
p.fillRect(fullRect, active ? st::dialogsBgActive : (selected ? st::dialogsBgOver : st::dialogsBg));
|
||||
row->paintRipple(p, 0, 0, fullWidth, ms, &(active ? st::dialogsRippleBgActive : st::dialogsRippleBg)->c);
|
||||
if (onlyBackground) return;
|
||||
|
||||
PeerData *userpicPeer = (history->peer->migrateTo() ? history->peer->migrateTo() : history->peer);
|
||||
userpicPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), w);
|
||||
auto userpicPeer = (history->peer->migrateTo() ? history->peer->migrateTo() : history->peer);
|
||||
userpicPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), fullWidth);
|
||||
|
||||
int32 nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
|
||||
int32 namewidth = w - nameleft - st::dialogsPadding.x();
|
||||
auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
|
||||
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x();
|
||||
QRect rectForName(nameleft, st::dialogsPadding.y() + st::dialogsNameTop, namewidth, st::msgNameFont->height);
|
||||
|
||||
if (auto chatTypeIcon = ChatTypeIcon(history->peer, active, selected)) {
|
||||
chatTypeIcon->paint(p, rectForName.topLeft(), w);
|
||||
chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth);
|
||||
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
|
||||
}
|
||||
|
||||
|
@ -82,7 +83,7 @@ void paintRow(Painter &p, History *history, HistoryItem *item, Data::Draft *draf
|
|||
|
||||
p.setFont(st::dialogsTextFont);
|
||||
auto &color = active ? st::dialogsTextFgServiceActive : (selected ? st::dialogsTextFgServiceOver : st::dialogsTextFgService);
|
||||
if (!history->paintSendAction(p, nameleft, texttop, namewidth, w, color, ms)) {
|
||||
if (!history->paintSendAction(p, nameleft, texttop, namewidth, fullWidth, color, ms)) {
|
||||
if (history->cloudDraftTextCache.isEmpty()) {
|
||||
auto draftWrapped = textcmdLink(1, lng_dialogs_text_from_wrapped(lt_from, lang(lng_from_draft)));
|
||||
auto draftText = lng_dialogs_text_with_from(lt_from_part, draftWrapped, lt_message, textClean(draft->textWithTags.text));
|
||||
|
@ -96,7 +97,7 @@ void paintRow(Painter &p, History *history, HistoryItem *item, Data::Draft *draf
|
|||
} else if (!item) {
|
||||
auto &color = active ? st::dialogsTextFgServiceActive : (selected ? st::dialogsTextFgServiceOver : st::dialogsTextFgService);
|
||||
p.setFont(st::dialogsTextFont);
|
||||
if (!history->paintSendAction(p, nameleft, texttop, namewidth, w, color, ms)) {
|
||||
if (!history->paintSendAction(p, nameleft, texttop, namewidth, fullWidth, color, ms)) {
|
||||
p.setPen(color);
|
||||
p.drawText(nameleft, texttop + st::msgNameFont->ascent, lang(lng_empty_history));
|
||||
}
|
||||
|
@ -123,13 +124,13 @@ void paintRow(Painter &p, History *history, HistoryItem *item, Data::Draft *draf
|
|||
})();
|
||||
if (sendStateIcon) {
|
||||
rectForName.setWidth(rectForName.width() - st::dialogsSendStateSkip);
|
||||
sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), w);
|
||||
sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), fullWidth);
|
||||
}
|
||||
|
||||
if (history->peer->isUser() && history->peer->isVerified()) {
|
||||
auto icon = &(active ? st::dialogsVerifiedIconActive : (selected ? st::dialogsVerifiedIconOver : st::dialogsVerifiedIcon));
|
||||
rectForName.setWidth(rectForName.width() - icon->width());
|
||||
icon->paint(p, rectForName.topLeft() + QPoint(qMin(history->peer->dialogName().maxWidth(), rectForName.width()), 0), w);
|
||||
icon->paint(p, rectForName.topLeft() + QPoint(qMin(history->peer->dialogName().maxWidth(), rectForName.width()), 0), fullWidth);
|
||||
}
|
||||
|
||||
p.setPen(active ? st::dialogsNameFgActive : (selected ? st::dialogsNameFgOver : st::dialogsNameFg));
|
||||
|
@ -241,7 +242,7 @@ void paintUnreadCount(Painter &p, const QString &text, int x, int y, const Unrea
|
|||
p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + textTop + st.font->ascent, text);
|
||||
}
|
||||
|
||||
void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground, TimeMs ms) {
|
||||
void RowPainter::paint(Painter &p, const Row *row, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms) {
|
||||
auto history = row->history();
|
||||
auto item = history->lastMsg;
|
||||
auto cloudDraft = history->cloudDraft();
|
||||
|
@ -267,15 +268,15 @@ void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool sele
|
|||
if (item && cloudDraft && unreadCount > 0) {
|
||||
cloudDraft = nullptr; // Draw item, if draft is older.
|
||||
}
|
||||
paintRow(p, history, item, cloudDraft, displayDate(), w, active, selected, onlyBackground, ms, [&p, w, active, selected, ms, history, unreadCount](int nameleft, int namewidth, HistoryItem *item) {
|
||||
paintRow(p, row, history, item, cloudDraft, displayDate(), fullWidth, active, selected, onlyBackground, ms, [&p, fullWidth, active, selected, ms, history, unreadCount](int nameleft, int namewidth, HistoryItem *item) {
|
||||
int availableWidth = namewidth;
|
||||
int texttop = st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip;
|
||||
if (unreadCount) {
|
||||
auto counter = QString::number(unreadCount);
|
||||
auto mutedCounter = history->mute();
|
||||
int unreadRight = w - st::dialogsPadding.x();
|
||||
int unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
|
||||
int unreadWidth = 0;
|
||||
auto unreadRight = fullWidth - st::dialogsPadding.x();
|
||||
auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
|
||||
auto unreadWidth = 0;
|
||||
|
||||
UnreadBadgeStyle st;
|
||||
st.active = active;
|
||||
|
@ -284,16 +285,16 @@ void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool sele
|
|||
availableWidth -= unreadWidth + st.padding;
|
||||
}
|
||||
auto &color = active ? st::dialogsTextFgServiceActive : (selected ? st::dialogsTextFgServiceOver : st::dialogsTextFgService);
|
||||
if (!history->paintSendAction(p, nameleft, texttop, availableWidth, w, color, ms)) {
|
||||
if (!history->paintSendAction(p, nameleft, texttop, availableWidth, fullWidth, color, ms)) {
|
||||
item->drawInDialog(p, QRect(nameleft, texttop, availableWidth, st::dialogsTextFont->height), active, selected, history->textCachedFor, history->lastItemTextCache);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void RowPainter::paint(Painter &p, const FakeRow *row, int w, bool active, bool selected, bool onlyBackground, TimeMs ms) {
|
||||
void RowPainter::paint(Painter &p, const FakeRow *row, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms) {
|
||||
auto item = row->item();
|
||||
auto history = item->history();
|
||||
paintRow(p, history, item, nullptr, item->date, w, active, selected, onlyBackground, ms, [&p, row, active, selected](int nameleft, int namewidth, HistoryItem *item) {
|
||||
paintRow(p, row, history, item, nullptr, item->date, fullWidth, active, selected, onlyBackground, ms, [&p, row, active, selected](int nameleft, int namewidth, HistoryItem *item) {
|
||||
int lastWidth = namewidth, texttop = st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip;
|
||||
item->drawInDialog(p, QRect(nameleft, texttop, lastWidth, st::dialogsTextFont->height), active, selected, row->_cacheFor, row->_cache);
|
||||
});
|
||||
|
@ -306,8 +307,8 @@ QRect RowPainter::sendActionAnimationRect(int animationWidth, int animationHeigh
|
|||
return QRect(nameleft, texttop, textUpdated ? namewidth : animationWidth, animationHeight);
|
||||
}
|
||||
|
||||
void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool onlyBackground) {
|
||||
p.fillRect(0, 0, w, st::dialogsImportantBarHeight, selected ? st::dialogsBgOver : st::dialogsBg);
|
||||
void paintImportantSwitch(Painter &p, Mode current, int fullWidth, bool selected, bool onlyBackground) {
|
||||
p.fillRect(0, 0, fullWidth, st::dialogsImportantBarHeight, selected ? st::dialogsBgOver : st::dialogsBg);
|
||||
if (onlyBackground) {
|
||||
return;
|
||||
}
|
||||
|
@ -323,7 +324,7 @@ void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool o
|
|||
|
||||
if (mutedHidden) {
|
||||
if (int32 unread = App::histories().unreadMutedCount()) {
|
||||
int unreadRight = w - st::dialogsPadding.x();
|
||||
int unreadRight = fullWidth - st::dialogsPadding.x();
|
||||
UnreadBadgeStyle st;
|
||||
st.muted = true;
|
||||
paintUnreadCount(p, QString::number(unread), unreadRight, unreadTop, st, nullptr);
|
||||
|
|
|
@ -31,13 +31,13 @@ const style::icon *ChatTypeIcon(PeerData *peer, bool active, bool selected);
|
|||
|
||||
class RowPainter {
|
||||
public:
|
||||
static void paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground, TimeMs ms);
|
||||
static void paint(Painter &p, const FakeRow *row, int w, bool active, bool selected, bool onlyBackground, TimeMs ms);
|
||||
static void paint(Painter &p, const Row *row, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms);
|
||||
static void paint(Painter &p, const FakeRow *row, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms);
|
||||
static QRect sendActionAnimationRect(int animationWidth, int animationHeight, int fullWidth, bool textUpdated);
|
||||
|
||||
};
|
||||
|
||||
void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool onlyBackground);
|
||||
void paintImportantSwitch(Painter &p, Mode current, int fullWidth, bool selected, bool onlyBackground);
|
||||
|
||||
enum UnreadBadgeSize {
|
||||
UnreadBadgeInDialogs = 0,
|
||||
|
|
|
@ -201,7 +201,7 @@ bool List::del(PeerId peerId, Row *replacedBy) {
|
|||
auto i = _rowByPeer.find(peerId);
|
||||
if (i == _rowByPeer.cend()) return false;
|
||||
|
||||
Row *row = i.value();
|
||||
auto row = i.value();
|
||||
if (App::main()) {
|
||||
emit App::main()->dialogRowReplaced(row, replacedBy);
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ bool List::del(PeerId peerId, Row *replacedBy) {
|
|||
if (row == _current) {
|
||||
_current = row->_next;
|
||||
}
|
||||
for (Row *change = row->_next; change != _end; change = change->_next) {
|
||||
for (auto change = row->_next; change != _end; change = change->_next) {
|
||||
--change->_pos;
|
||||
}
|
||||
--_end->_pos;
|
||||
|
|
|
@ -22,9 +22,37 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "dialogs/dialogs_row.h"
|
||||
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "mainwidget.h"
|
||||
|
||||
namespace Dialogs {
|
||||
|
||||
RippleRow::RippleRow() = default;
|
||||
RippleRow::~RippleRow() = default;
|
||||
|
||||
void RippleRow::addRipple(QPoint origin, QSize size, base::lambda_copy<void()> &&updateCallback) {
|
||||
if (!_ripple) {
|
||||
auto mask = Ui::RippleAnimation::rectMask(size);
|
||||
_ripple = std_::make_unique<Ui::RippleAnimation>(st::dialogsRipple, std_::move(mask), std_::move(updateCallback));
|
||||
}
|
||||
_ripple->add(origin);
|
||||
}
|
||||
|
||||
void RippleRow::stopLastRipple() {
|
||||
if (_ripple) {
|
||||
_ripple->lastStop();
|
||||
}
|
||||
}
|
||||
|
||||
void RippleRow::paintRipple(Painter &p, int x, int y, int outerWidth, TimeMs ms, const QColor *colorOverride) const {
|
||||
if (_ripple) {
|
||||
_ripple->paint(p, x, y, outerWidth, ms, colorOverride);
|
||||
if (_ripple->empty()) {
|
||||
_ripple.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FakeRow::FakeRow(HistoryItem *item) : _item(item), _cache(st::dialogsTextWidthMin) {
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,32 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
class History;
|
||||
class HistoryItem;
|
||||
|
||||
namespace Ui {
|
||||
class RippleAnimation;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Dialogs {
|
||||
namespace Layout {
|
||||
class RowPainter;
|
||||
} // namespace Layout
|
||||
|
||||
class RippleRow {
|
||||
public:
|
||||
RippleRow();
|
||||
~RippleRow();
|
||||
|
||||
void addRipple(QPoint origin, QSize size, base::lambda_copy<void()> &&updateCallback);
|
||||
void stopLastRipple();
|
||||
|
||||
void paintRipple(Painter &p, int x, int y, int outerWidth, TimeMs ms, const QColor *colorOverride = nullptr) const;
|
||||
|
||||
private:
|
||||
mutable std_::unique_ptr<Ui::RippleAnimation> _ripple;
|
||||
|
||||
};
|
||||
|
||||
class List;
|
||||
class Row {
|
||||
class Row : public RippleRow {
|
||||
public:
|
||||
Row(History *history, Row *prev, Row *next, int pos)
|
||||
: _history(history)
|
||||
|
@ -57,7 +76,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class FakeRow {
|
||||
class FakeRow : public RippleRow {
|
||||
public:
|
||||
FakeRow(HistoryItem *item);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -57,25 +57,24 @@ public:
|
|||
void dialogsReceived(const QVector<MTPDialog> &dialogs);
|
||||
void addSavedPeersAfter(const QDateTime &date);
|
||||
void addAllSavedPeers();
|
||||
bool searchReceived(const QVector<MTPMessage> &messages, DialogsSearchRequestType type, int32 fullCount);
|
||||
void peopleReceived(const QString &query, const QVector<MTPPeer> &people);
|
||||
bool searchReceived(const QVector<MTPMessage> &result, DialogsSearchRequestType type, int32 fullCount);
|
||||
void peerSearchReceived(const QString &query, const QVector<MTPPeer> &result);
|
||||
void showMore(int32 pixels);
|
||||
|
||||
void activate();
|
||||
|
||||
void contactsReceived(const QVector<MTPContact> &contacts);
|
||||
void contactsReceived(const QVector<MTPContact> &result);
|
||||
|
||||
void selectSkip(int32 direction);
|
||||
void selectSkipPage(int32 pixels, int32 direction);
|
||||
|
||||
void createDialog(History *history);
|
||||
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
|
||||
void dlgUpdated(History *row, MsgId msgId);
|
||||
void dlgUpdated(PeerData *peer, MsgId msgId);
|
||||
void removeDialog(History *history);
|
||||
|
||||
void dragLeft();
|
||||
|
||||
void loadPeerPhotos(int32 yFrom);
|
||||
void clearFilter();
|
||||
void refresh(bool toTop = false);
|
||||
|
||||
|
@ -88,21 +87,14 @@ public:
|
|||
void peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const;
|
||||
void scrollToPeer(const PeerId &peer, MsgId msgId);
|
||||
|
||||
typedef QVector<Dialogs::Row*> FilteredDialogs;
|
||||
typedef QVector<PeerData*> PeopleResults;
|
||||
typedef QVector<Dialogs::FakeRow*> SearchResults;
|
||||
|
||||
Dialogs::IndexedList *contactsList();
|
||||
Dialogs::IndexedList *dialogsList();
|
||||
FilteredDialogs &filteredList();
|
||||
PeopleResults &peopleList();
|
||||
SearchResults &searchList();
|
||||
int32 lastSearchDate() const;
|
||||
PeerData *lastSearchPeer() const;
|
||||
MsgId lastSearchId() const;
|
||||
MsgId lastSearchMigratedId() const;
|
||||
|
||||
void setMouseSel(bool msel, bool toTop = false);
|
||||
void setMouseSelection(bool mouseSelection, bool toTop = false);
|
||||
|
||||
enum State {
|
||||
DefaultState = 0,
|
||||
|
@ -120,7 +112,10 @@ public:
|
|||
|
||||
PeerData *updateFromParentDrag(QPoint globalPos);
|
||||
|
||||
void updateNotifySettings(PeerData *peer);
|
||||
void setLoadMoreCallback(base::lambda<void()> &&callback) {
|
||||
_loadMoreCallback = std_::move(callback);
|
||||
}
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
|
||||
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||
void notify_historyMuteUpdated(History *history);
|
||||
|
@ -128,7 +123,6 @@ public:
|
|||
~DialogsInner();
|
||||
|
||||
public slots:
|
||||
void onUpdateSelected(bool force = false);
|
||||
void onParentGeometryChanged();
|
||||
void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
|
||||
void onPeerPhotoChanged(PeerData *peer);
|
||||
|
@ -149,67 +143,109 @@ protected:
|
|||
void paintRegion(Painter &p, const QRegion ®ion, bool paintingOther) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void enterEvent(QEvent *e) override;
|
||||
void leaveEvent(QEvent *e) override;
|
||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||
|
||||
private:
|
||||
struct ImportantSwitch;
|
||||
using DialogsList = std_::unique_ptr<Dialogs::IndexedList>;
|
||||
using FilteredDialogs = QVector<Dialogs::Row*>;
|
||||
using SearchResults = std_::vector_of_moveable<std_::unique_ptr<Dialogs::FakeRow>>;
|
||||
struct HashtagResult;
|
||||
using HashtagResults = std_::vector_of_moveable<std_::unique_ptr<HashtagResult>>;
|
||||
struct PeerSearchResult;
|
||||
using PeerSearchResults = std_::vector_of_moveable<std_::unique_ptr<PeerSearchResult>>;
|
||||
|
||||
void mousePressReleased(Qt::MouseButton button);
|
||||
void clearIrrelevantState();
|
||||
void updateSelected() {
|
||||
updateSelected(mapFromGlobal(QCursor::pos()));
|
||||
}
|
||||
void updateSelected(QPoint localPos);
|
||||
void loadPeerPhotos(int visibleTop);
|
||||
void setImportantSwitchPressed(bool pressed);
|
||||
void setPressed(Dialogs::Row *pressed);
|
||||
void setHashtagPressed(int pressed);
|
||||
void setFilteredPressed(int pressed);
|
||||
void setPeerSearchPressed(int pressed);
|
||||
void setSearchedPressed(int pressed);
|
||||
bool isPressed() const {
|
||||
return _importantSwitchPressed || _pressed || (_hashtagPressed >= 0) || (_filteredPressed >= 0) || (_peerSearchPressed >= 0) || (_searchedPressed >= 0);
|
||||
}
|
||||
bool isSelected() const {
|
||||
return _importantSwitchSelected || _selected || (_hashtagSelected >= 0) || (_filteredSelected>= 0) || (_peerSearchSelected >= 0) || (_searchedSelected >= 0);
|
||||
}
|
||||
|
||||
void itemRemoved(HistoryItem *item);
|
||||
enum class UpdateRowSection {
|
||||
Default = 0x01,
|
||||
Filtered = 0x02,
|
||||
GlobalSearch = 0x04,
|
||||
PeerSearch = 0x04,
|
||||
MessageSearch = 0x08,
|
||||
All = 0x0F,
|
||||
};
|
||||
Q_DECLARE_FLAGS(UpdateRowSections, UpdateRowSection);
|
||||
Q_DECLARE_FRIEND_OPERATORS_FOR_FLAGS(UpdateRowSections);
|
||||
void updateDialogRow(History *history, MsgId msgId, QRect updateRect, UpdateRowSections sections = UpdateRowSection::All);
|
||||
void updateDialogRow(PeerData *peer, MsgId msgId, QRect updateRect, UpdateRowSections sections = UpdateRowSection::All);
|
||||
|
||||
int dialogsOffset() const;
|
||||
int filteredOffset() const;
|
||||
int peopleOffset() const;
|
||||
int peerSearchOffset() const;
|
||||
int searchedOffset() const;
|
||||
|
||||
void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool active, bool selected, bool onlyBackground) const;
|
||||
void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const;
|
||||
void paintDialog(QPainter &p, Dialogs::Row *dialog);
|
||||
void paintPeerSearchResult(Painter &p, const PeerSearchResult *result, int32 w, bool active, bool selected, bool onlyBackground, TimeMs ms) const;
|
||||
void paintSearchInPeer(Painter &p, int32 w, bool onlyBackground) const;
|
||||
|
||||
void clearSelection();
|
||||
void clearSearchResults(bool clearPeople = true);
|
||||
void clearSearchResults(bool clearPeerSearchResults = true);
|
||||
void updateSelectedRow(PeerData *peer = 0);
|
||||
|
||||
Dialogs::IndexedList *shownDialogs() const {
|
||||
return (Global::DialogsMode() == Dialogs::Mode::Important) ? importantDialogs.get() : dialogs.get();
|
||||
return (Global::DialogsMode() == Dialogs::Mode::Important) ? _dialogsImportant.get() : _dialogs.get();
|
||||
}
|
||||
|
||||
using DialogsList = std_::unique_ptr<Dialogs::IndexedList>;
|
||||
DialogsList dialogs;
|
||||
DialogsList importantDialogs;
|
||||
DialogsList _dialogs;
|
||||
DialogsList _dialogsImportant;
|
||||
|
||||
DialogsList contactsNoDialogs;
|
||||
DialogsList contacts;
|
||||
DialogsList _contactsNoDialogs;
|
||||
DialogsList _contacts;
|
||||
|
||||
bool _importantSwitchSel = false;
|
||||
Dialogs::Row *_sel = nullptr;
|
||||
bool _selByMouse = false;
|
||||
bool _mouseSelection = false;
|
||||
Qt::MouseButton _pressButton = Qt::LeftButton;
|
||||
|
||||
std_::unique_ptr<ImportantSwitch> _importantSwitch;
|
||||
bool _importantSwitchSelected = false;
|
||||
bool _importantSwitchPressed = false;
|
||||
Dialogs::Row *_selected = nullptr;
|
||||
Dialogs::Row *_pressed = nullptr;
|
||||
|
||||
int _visibleAreaHeight = 0;
|
||||
QString _filter, _hashtagFilter;
|
||||
|
||||
QStringList _hashtagResults;
|
||||
int _hashtagSel = -1;
|
||||
HashtagResults _hashtagResults;
|
||||
int _hashtagSelected = -1;
|
||||
int _hashtagPressed = -1;
|
||||
bool _hashtagDeleteSelected = false;
|
||||
bool _hashtagDeletePressed = false;
|
||||
|
||||
FilteredDialogs _filterResults;
|
||||
int _filteredSel = -1;
|
||||
int _filteredSelected = -1;
|
||||
int _filteredPressed = -1;
|
||||
|
||||
QString _peerSearchQuery;
|
||||
PeerSearchResults _peerSearchResults;
|
||||
int _peerSearchSelected = -1;
|
||||
int _peerSearchPressed = -1;
|
||||
|
||||
SearchResults _searchResults;
|
||||
int _searchedCount = 0;
|
||||
int _searchedMigratedCount = 0;
|
||||
int _searchedSel = -1;
|
||||
|
||||
QString _peopleQuery;
|
||||
PeopleResults _peopleResults;
|
||||
int _peopleSel = -1;
|
||||
int _searchedSelected = -1;
|
||||
int _searchedPressed = -1;
|
||||
|
||||
int _lastSearchDate = 0;
|
||||
PeerData *_lastSearchPeer = nullptr;
|
||||
|
@ -218,21 +254,17 @@ private:
|
|||
|
||||
State _state = DefaultState;
|
||||
|
||||
QPoint lastMousePos;
|
||||
|
||||
void paintDialog(QPainter &p, Dialogs::Row *dialog);
|
||||
|
||||
ChildWidget<Ui::LinkButton> _addContactLnk;
|
||||
ChildWidget<Ui::IconButton> _cancelSearchInPeer;
|
||||
|
||||
bool _overDelete = false;
|
||||
|
||||
PeerData *_searchInPeer = nullptr;
|
||||
PeerData *_searchInMigrated = nullptr;
|
||||
PeerData *_menuPeer = nullptr;
|
||||
|
||||
Ui::PopupMenu *_menu = nullptr;
|
||||
|
||||
base::lambda<void()> _loadMoreCallback;
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(DialogsInner::UpdateRowSections);
|
||||
|
@ -243,27 +275,14 @@ class DialogsWidget : public TWidget, public RPCSender, private base::Subscriber
|
|||
public:
|
||||
DialogsWidget(QWidget *parent);
|
||||
|
||||
void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req);
|
||||
void contactsReceived(const MTPcontacts_Contacts &contacts);
|
||||
void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *e) override;
|
||||
void dragMoveEvent(QDragMoveEvent *e) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
||||
void dropEvent(QDropEvent *e) override;
|
||||
void updateDragInScroll(bool inScroll);
|
||||
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void searchInPeer(PeerData *peer);
|
||||
|
||||
void loadDialogs();
|
||||
void createDialog(History *history);
|
||||
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
|
||||
void dlgUpdated(History *row, MsgId msgId);
|
||||
void dlgUpdated(PeerData *peer, MsgId msgId);
|
||||
|
||||
void dialogsToUp();
|
||||
|
||||
|
@ -272,7 +291,6 @@ public:
|
|||
}
|
||||
void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms);
|
||||
void showFast();
|
||||
void step_show(float64 ms, bool timer);
|
||||
|
||||
void destroyData();
|
||||
|
||||
|
@ -321,7 +339,22 @@ private slots:
|
|||
void onCheckUpdateStatus();
|
||||
#endif // TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent *e) override;
|
||||
void dragMoveEvent(QDragMoveEvent *e) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
||||
void dropEvent(QDropEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
void animationCallback();
|
||||
void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req);
|
||||
void contactsReceived(const MTPcontacts_Contacts &result);
|
||||
void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
void peerSearchReceived(const MTPcontacts_Found &result, mtpRequestId req);
|
||||
|
||||
void setSearchInPeer(PeerData *peer);
|
||||
void showMainMenu();
|
||||
void updateLockUnlockVisibility();
|
||||
|
@ -354,31 +387,34 @@ private:
|
|||
ChildWidget<DialogsInner> _inner;
|
||||
ChildWidget<Ui::FlatButton> _updateTelegram = { nullptr };
|
||||
|
||||
Animation _a_show;
|
||||
FloatAnimation _a_show;
|
||||
Window::SlideDirection _showDirection;
|
||||
QPixmap _cacheUnder, _cacheOver;
|
||||
anim::ivalue a_coordUnder, a_coordOver;
|
||||
anim::fvalue a_progress;
|
||||
|
||||
PeerData *_searchInPeer = nullptr;
|
||||
PeerData *_searchInMigrated = nullptr;
|
||||
|
||||
QTimer _searchTimer;
|
||||
QString _searchQuery, _peopleQuery;
|
||||
|
||||
QString _peerSearchQuery;
|
||||
bool _peerSearchFull = false;
|
||||
mtpRequestId _peerSearchRequest = 0;
|
||||
|
||||
QString _searchQuery;
|
||||
bool _searchFull = false;
|
||||
bool _searchFullMigrated = false;
|
||||
bool _peopleFull = false;
|
||||
mtpRequestId _searchRequest, _peopleRequest;
|
||||
mtpRequestId _searchRequest = 0;
|
||||
|
||||
typedef QMap<QString, MTPmessages_Messages> SearchCache;
|
||||
using SearchCache = QMap<QString, MTPmessages_Messages>;
|
||||
SearchCache _searchCache;
|
||||
|
||||
typedef QMap<mtpRequestId, QString> SearchQueries;
|
||||
using SearchQueries = QMap<mtpRequestId, QString>;
|
||||
SearchQueries _searchQueries;
|
||||
|
||||
typedef QMap<QString, MTPcontacts_Found> PeopleCache;
|
||||
PeopleCache _peopleCache;
|
||||
using PeerSearchCache = QMap<QString, MTPcontacts_Found>;
|
||||
PeerSearchCache _peerSearchCache;
|
||||
|
||||
typedef QMap<mtpRequestId, QString> PeopleQueries;
|
||||
PeopleQueries _peopleQueries;
|
||||
using PeerSearchQueries = QMap<mtpRequestId, QString>;
|
||||
PeerSearchQueries _peerSearchQueries;
|
||||
|
||||
};
|
||||
|
|
|
@ -395,7 +395,7 @@ void FieldAutocomplete::hideFast() {
|
|||
if (_a_appearance.animating()) {
|
||||
_a_appearance.stop();
|
||||
}
|
||||
a_opacity = anim::fvalue(0, 0);
|
||||
a_opacity = anim::value();
|
||||
hideFinish();
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ private:
|
|||
int32 _width, _height;
|
||||
bool _hiding = false;
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
anim::value a_opacity;
|
||||
Animation _a_appearance;
|
||||
|
||||
friend class internal::FieldAutocompleteInner;
|
||||
|
|
|
@ -240,8 +240,6 @@ historyAttachEmoji: IconButton(historyAttach) {
|
|||
icon: icon {{ "send_control_emoji", historyComposeIconFg }};
|
||||
iconOver: icon {{ "send_control_emoji", historyComposeIconFgOver }};
|
||||
iconPosition: point(15px, 15px);
|
||||
|
||||
ripple: emptyRippleAnimation;
|
||||
}
|
||||
historyEmojiCircle: size(20px, 20px);
|
||||
historyEmojiCirclePeriod: 1500;
|
||||
|
@ -251,16 +249,16 @@ historyEmojiCircleLine: 2px;
|
|||
historyEmojiCircleFg: historyComposeIconFg;
|
||||
historyEmojiCircleFgOver: historyComposeIconFgOver;
|
||||
historyEmojiCirclePart: 3.5;
|
||||
historyBotKeyboardShow: IconButton(historySend) {
|
||||
historyBotKeyboardShow: IconButton(historyAttach) {
|
||||
icon: icon {{ "send_control_bot_keyboard", historyComposeIconFg }};
|
||||
iconOver: icon {{ "send_control_bot_keyboard", historyComposeIconFgOver }};
|
||||
}
|
||||
historyBotKeyboardHide: IconButton(historySend) {
|
||||
historyBotKeyboardHide: IconButton(historyAttach) {
|
||||
icon: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFg }};
|
||||
iconOver: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFgOver }};
|
||||
iconPosition: point(11px, 16px);
|
||||
}
|
||||
historyBotCommandStart: IconButton(historySend) {
|
||||
historyBotCommandStart: IconButton(historyAttach) {
|
||||
icon: icon {{ "send_control_bot_command", historyComposeIconFg }};
|
||||
iconOver: icon {{ "send_control_bot_command", historyComposeIconFgOver }};
|
||||
}
|
||||
|
@ -270,6 +268,7 @@ historyRecordVoiceFgActive: windowBgActive;
|
|||
historyRecordVoice: icon {{ "send_control_record", historyRecordVoiceFg }};
|
||||
historyRecordVoiceOver: icon {{ "send_control_record", historyRecordVoiceFgOver }};
|
||||
historyRecordVoiceActive: icon {{ "send_control_record", historyRecordVoiceFgActive }};
|
||||
historyRecordVoiceRippleBgActive: lightButtonBgOver;
|
||||
historyRecordSignalColor: #f17077;
|
||||
historyRecordSignalMin: 5px;
|
||||
historyRecordSignalMax: 12px;
|
||||
|
|
|
@ -133,14 +133,14 @@ void DragArea::hideFast() {
|
|||
if (_a_appearance.animating()) {
|
||||
_a_appearance.stop();
|
||||
}
|
||||
a_opacity = anim::fvalue(0, 0);
|
||||
a_opacity = anim::value();
|
||||
hide();
|
||||
}
|
||||
|
||||
void DragArea::hideStart() {
|
||||
_hiding = true;
|
||||
_in = false;
|
||||
a_opacity.start(0);
|
||||
a_opacity.start(0.);
|
||||
a_colorDrop.start(_in ? 1. : 0.);
|
||||
_a_appearance.start();
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ void DragArea::hideStart() {
|
|||
void DragArea::hideFinish() {
|
||||
hide();
|
||||
_in = false;
|
||||
a_colorDrop = anim::fvalue(0.);
|
||||
a_colorDrop = anim::value();
|
||||
}
|
||||
|
||||
void DragArea::showStart() {
|
||||
|
|
|
@ -70,8 +70,8 @@ private:
|
|||
bool _hiding, _in;
|
||||
base::lambda<void(const QMimeData *data)> _droppedCallback;
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
anim::fvalue a_colorDrop;
|
||||
anim::value a_opacity;
|
||||
anim::value a_colorDrop;
|
||||
Animation _a_appearance;
|
||||
|
||||
Ui::RectShadow _shadow;
|
||||
|
|
|
@ -584,7 +584,7 @@ void HistoryItem::finishCreate() {
|
|||
void HistoryItem::finishEdition(int oldKeyboardTop) {
|
||||
setPendingInitDimensions();
|
||||
if (App::main()) {
|
||||
App::main()->dlgUpdated(history(), id);
|
||||
App::main()->dlgUpdated(history()->peer, id);
|
||||
}
|
||||
|
||||
// invalidate cache for drawInDialog
|
||||
|
|
|
@ -1456,7 +1456,7 @@ bool HistoryDocument::updateStatusText() const {
|
|||
if (voice->_playback->_position < playbackState.position) {
|
||||
voice->_playback->a_progress.start(prg);
|
||||
} else {
|
||||
voice->_playback->a_progress = anim::fvalue(0., prg);
|
||||
voice->_playback->a_progress = anim::value(0., prg);
|
||||
}
|
||||
voice->_playback->_position = playbackState.position;
|
||||
voice->_playback->_a_progress.start();
|
||||
|
|
|
@ -99,7 +99,7 @@ protected:
|
|||
, _a_thumbOver(std_::move(thumbOverCallbacks))
|
||||
, radial(std_::move(radialCallbacks)) {
|
||||
}
|
||||
anim::fvalue a_thumbOver;
|
||||
anim::value a_thumbOver;
|
||||
Animation _a_thumbOver;
|
||||
|
||||
Ui::RadialAnimation radial;
|
||||
|
@ -306,7 +306,7 @@ struct HistoryDocumentVoicePlayback {
|
|||
HistoryDocumentVoicePlayback(const HistoryDocument *that);
|
||||
|
||||
int32 _position;
|
||||
anim::fvalue a_progress;
|
||||
anim::value a_progress;
|
||||
Animation _a_progress;
|
||||
};
|
||||
struct HistoryDocumentVoice : public RuntimeComponent<HistoryDocumentVoice> {
|
||||
|
|
|
@ -2329,7 +2329,7 @@ bool HistoryService::updateDependentText() {
|
|||
history()->textCachedFor = 0;
|
||||
}
|
||||
if (App::main()) {
|
||||
App::main()->dlgUpdated(history(), id);
|
||||
App::main()->dlgUpdated(history()->peer, id);
|
||||
}
|
||||
App::historyUpdateDependent(this);
|
||||
return result;
|
||||
|
|
|
@ -34,6 +34,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/inner_dropdown.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "inline_bots/inline_bot_result.h"
|
||||
#include "data/data_drafts.h"
|
||||
#include "history/history_service_layout.h"
|
||||
|
@ -2971,7 +2972,7 @@ void SilentToggle::mouseMoveEvent(QMouseEvent *e) {
|
|||
void SilentToggle::setChecked(bool checked) {
|
||||
if (_checked != checked) {
|
||||
_checked = checked;
|
||||
setIcon(_checked ? &st::historySilentToggleOn : nullptr, _checked ? &st::historySilentToggleOnOver : nullptr);
|
||||
setIconOverride(_checked ? &st::historySilentToggleOn : nullptr, _checked ? &st::historySilentToggleOnOver : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3051,9 +3052,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
, _botCommandStart(this, st::historyBotCommandStart)
|
||||
, _silent(this)
|
||||
, _field(this, st::historyComposeField, lang(lng_message_ph))
|
||||
, _a_record(animation(this, &HistoryWidget::step_record))
|
||||
, _a_recording(animation(this, &HistoryWidget::step_recording))
|
||||
, a_recordCancelActive(0, 0)
|
||||
, _recordCancelWidth(st::historyRecordFont->width(lang(lng_record_cancel)))
|
||||
, _kbScroll(this, st::botKbScroll)
|
||||
, _keyboard(this)
|
||||
|
@ -3061,7 +3060,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
, _attachDragDocument(this)
|
||||
, _attachDragPhoto(this)
|
||||
, _fileLoader(this, FileLoaderQueueStopTimeout)
|
||||
, _a_show(animation(this, &HistoryWidget::step_show))
|
||||
, _topShadow(this, st::shadowColor) {
|
||||
setAcceptDrops(true);
|
||||
|
||||
|
@ -3318,10 +3316,8 @@ void HistoryWidget::onTextChange() {
|
|||
_send->show();
|
||||
}
|
||||
updateMouseTracking();
|
||||
_a_record.stop();
|
||||
_a_recordActive.finish();
|
||||
_inRecord = _inField = false;
|
||||
a_recordDown = anim::fvalue(0, 0);
|
||||
a_recordCancelActive = anim::fvalue(0, 0);
|
||||
}
|
||||
}
|
||||
if (updateCmdStartShown()) {
|
||||
|
@ -4197,7 +4193,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
|
||||
historyLoaded();
|
||||
}
|
||||
App::main()->dlgUpdated(wasHistory, wasMsgId);
|
||||
App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId);
|
||||
emit historyShown(_history, _showAtMsgId);
|
||||
|
||||
App::main()->topBar()->update();
|
||||
|
@ -4358,7 +4354,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
|
||||
if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus()));
|
||||
|
||||
App::main()->dlgUpdated(wasHistory, wasMsgId);
|
||||
App::main()->dlgUpdated(wasHistory ? wasHistory->peer : nullptr, wasMsgId);
|
||||
emit historyShown(_history, _showAtMsgId);
|
||||
|
||||
App::main()->historyPeerChanged().notify(_peer, true);
|
||||
|
@ -4650,7 +4646,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
} else {
|
||||
_send->show();
|
||||
}
|
||||
_a_record.stop();
|
||||
_a_recordActive.finish();
|
||||
_inRecord = _inField = false;
|
||||
}
|
||||
if (_recording) {
|
||||
|
@ -5441,9 +5437,9 @@ PeerData *HistoryWidget::peer() const {
|
|||
|
||||
void HistoryWidget::setMsgId(MsgId showAtMsgId) { // sometimes _showAtMsgId is set directly
|
||||
if (_showAtMsgId != showAtMsgId) {
|
||||
MsgId wasMsgId = _showAtMsgId;
|
||||
auto wasMsgId = _showAtMsgId;
|
||||
_showAtMsgId = showAtMsgId;
|
||||
App::main()->dlgUpdated(_history, wasMsgId);
|
||||
App::main()->dlgUpdated(_history ? _history->peer : nullptr, wasMsgId);
|
||||
emit historyShown(_history, _showAtMsgId);
|
||||
}
|
||||
}
|
||||
|
@ -5453,7 +5449,9 @@ MsgId HistoryWidget::msgId() const {
|
|||
}
|
||||
|
||||
void HistoryWidget::showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms) {
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
_showDirection = direction;
|
||||
|
||||
_a_show.finish();
|
||||
|
||||
_cacheUnder = params.oldContentCache;
|
||||
show();
|
||||
|
@ -5487,47 +5485,26 @@ void HistoryWidget::showAnimated(Window::SlideDirection direction, const Window:
|
|||
_pinnedBar->cancel->hide();
|
||||
}
|
||||
|
||||
int delta = st::slideShift;
|
||||
if (direction == Window::SlideDirection::FromLeft) {
|
||||
a_progress = anim::fvalue(1, 0);
|
||||
if (_showDirection == Window::SlideDirection::FromLeft) {
|
||||
std::swap(_cacheUnder, _cacheOver);
|
||||
a_coordUnder = anim::ivalue(-delta, 0);
|
||||
a_coordOver = anim::ivalue(0, width());
|
||||
} else {
|
||||
a_progress = anim::fvalue(0, 1);
|
||||
a_coordUnder = anim::ivalue(0, -delta);
|
||||
a_coordOver = anim::ivalue(width(), 0);
|
||||
}
|
||||
_a_show.start();
|
||||
_a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition());
|
||||
|
||||
App::main()->topBar()->update();
|
||||
|
||||
activate();
|
||||
}
|
||||
|
||||
void HistoryWidget::step_show(float64 ms, bool timer) {
|
||||
float64 dt = ms / st::slideDuration;
|
||||
if (dt >= 1) {
|
||||
_a_show.stop();
|
||||
void HistoryWidget::animationCallback() {
|
||||
update();
|
||||
App::main()->topBar()->update();
|
||||
if (!_a_show.animating()) {
|
||||
_topShadow->setVisible(_peer ? true : false);
|
||||
_historyToEnd->finishAnimation();
|
||||
|
||||
a_coordUnder.finish();
|
||||
a_coordOver.finish();
|
||||
a_progress.finish();
|
||||
_cacheUnder = _cacheOver = QPixmap();
|
||||
App::main()->topBar()->stopAnim();
|
||||
doneShow();
|
||||
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
} else {
|
||||
a_coordUnder.update(dt, Window::SlideAnimation::transition());
|
||||
a_coordOver.update(dt, Window::SlideAnimation::transition());
|
||||
a_progress.update(dt, Window::SlideAnimation::transition());
|
||||
}
|
||||
if (timer) {
|
||||
update();
|
||||
App::main()->topBar()->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5547,29 +5524,21 @@ void HistoryWidget::doneShow() {
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::animStop() {
|
||||
void HistoryWidget::finishAnimation() {
|
||||
if (!_a_show.animating()) return;
|
||||
_a_show.stop();
|
||||
_a_show.finish();
|
||||
_topShadow->setVisible(_peer ? true : false);
|
||||
_historyToEnd->finishAnimation();
|
||||
}
|
||||
|
||||
void HistoryWidget::step_record(float64 ms, bool timer) {
|
||||
float64 dt = ms / st::historyComposeButton.duration;
|
||||
if (dt >= 1 || !_send->isHidden() || (_inlineBotCancel && !_inlineBotCancel->isHidden()) || isBotStart() || isBlocked()) {
|
||||
_a_record.stop();
|
||||
a_recordDown.finish();
|
||||
a_recordCancelActive.finish();
|
||||
void HistoryWidget::recordActiveCallback() {
|
||||
if (_recording) {
|
||||
updateField();
|
||||
} else {
|
||||
a_recordDown.update(dt, anim::linear);
|
||||
a_recordCancelActive.update(dt, anim::linear);
|
||||
update(_send->geometry());
|
||||
}
|
||||
if (timer) {
|
||||
if (_recording) {
|
||||
updateField();
|
||||
} else {
|
||||
update(_send->geometry());
|
||||
}
|
||||
if (!_send->isHidden() || (_inlineBotCancel && !_inlineBotCancel->isHidden()) || isBotStart() || isBlocked()) {
|
||||
_a_recordActive.finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5665,9 +5634,7 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
|
|||
}
|
||||
if (inField != _inField && _recording) {
|
||||
_inField = inField;
|
||||
a_recordDown.start(_inField ? 1 : 0);
|
||||
a_recordCancelActive.start(_inField ? 0. : 1.);
|
||||
_a_record.start();
|
||||
_a_recordActive.start([this] { recordActiveCallback(); }, _inField ? 0. : 1., _inField ? 1. : 0., st::historyComposeButton.duration);
|
||||
}
|
||||
_inReplyEdit = inReplyEdit;
|
||||
_inPinnedMsg = inPinnedMsg;
|
||||
|
@ -5698,7 +5665,7 @@ void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) {
|
|||
void HistoryWidget::stopRecording(bool send) {
|
||||
emit audioCapture()->stop(send);
|
||||
|
||||
a_recordingLevel = anim::ivalue(0, 0);
|
||||
a_recordingLevel = anim::value();
|
||||
_a_recording.stop();
|
||||
|
||||
_recording = false;
|
||||
|
@ -5712,9 +5679,13 @@ void HistoryWidget::stopRecording(bool send) {
|
|||
|
||||
updateField();
|
||||
|
||||
a_recordDown.start(0);
|
||||
a_recordCancelActive = anim::fvalue(0., 0.);
|
||||
_a_record.start();
|
||||
if (_inField) {
|
||||
_a_recordActive.start([this] { recordActiveCallback(); }, 1., 0., st::historyComposeButton.duration);
|
||||
}
|
||||
|
||||
if (_recordRipple) {
|
||||
_recordRipple->lastStop();
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) { // replyTo != 0 from ReplyKeyboardMarkup, == 0 from cmd links
|
||||
|
@ -6202,16 +6173,21 @@ void HistoryWidget::onForwardHere() {
|
|||
|
||||
bool HistoryWidget::paintTopBar(Painter &p, int decreaseWidth, TimeMs ms) {
|
||||
if (_a_show.animating()) {
|
||||
int retina = cIntRetinaFactor();
|
||||
if (a_coordOver.current() > 0) {
|
||||
p.drawPixmap(QRect(0, 0, a_coordOver.current(), st::topBarHeight), _cacheUnder, QRect(-a_coordUnder.current() * retina, 0, a_coordOver.current() * retina, st::topBarHeight * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
p.fillRect(0, 0, a_coordOver.current(), st::topBarHeight, st::slideFadeOutBg);
|
||||
auto progress = _a_show.current(1.);
|
||||
auto retina = cIntRetinaFactor();
|
||||
auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft);
|
||||
auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
|
||||
auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
|
||||
auto shadow = fromLeft ? (1. - progress) : progress;
|
||||
if (coordOver > 0) {
|
||||
p.drawPixmap(QRect(0, 0, coordOver, st::topBarHeight), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, st::topBarHeight * retina));
|
||||
p.setOpacity(shadow);
|
||||
p.fillRect(0, 0, coordOver, st::topBarHeight, st::slideFadeOutBg);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
p.drawPixmap(QRect(a_coordOver.current(), 0, _cacheOver.width() / retina, st::topBarHeight), _cacheOver, QRect(0, 0, _cacheOver.width(), st::topBarHeight * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
st::slideShadow.fill(p, QRect(a_coordOver.current() - st::slideShadow.width(), 0, st::slideShadow.width(), st::topBarHeight));
|
||||
p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, st::topBarHeight), _cacheOver, QRect(0, 0, _cacheOver.width(), st::topBarHeight * retina));
|
||||
p.setOpacity(shadow);
|
||||
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), st::topBarHeight));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6481,14 +6457,14 @@ void HistoryWidget::onCheckFieldAutocomplete() {
|
|||
void HistoryWidget::updateFieldPlaceholder() {
|
||||
if (_editMsgId) {
|
||||
_field->setPlaceholder(lang(lng_edit_message_text));
|
||||
_send->setIcon(&st::historyEditSaveIcon, &st::historyEditSaveIconOver);
|
||||
_send->setIconOverride(&st::historyEditSaveIcon, &st::historyEditSaveIconOver);
|
||||
} else {
|
||||
if (_inlineBot && _inlineBot != Ui::LookingUpInlineBot) {
|
||||
_field->setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2);
|
||||
} else {
|
||||
_field->setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_silent->checked() ? lng_broadcast_silent_ph : lng_broadcast_ph) : lng_message_ph));
|
||||
}
|
||||
_send->setIcon(nullptr);
|
||||
_send->setIconOverride(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7511,8 +7487,13 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
|||
|
||||
updateField();
|
||||
|
||||
a_recordDown.start(1);
|
||||
_a_record.start();
|
||||
_a_recordActive.start([this] { recordActiveCallback(); }, 0., 1., st::historyComposeButton.duration);
|
||||
|
||||
if (!_recordRipple) {
|
||||
auto mask = Ui::RippleAnimation::ellipseMask(QSize(st::historyAttachEmoji.rippleAreaSize, st::historyAttachEmoji.rippleAreaSize));
|
||||
_recordRipple = std_::make_unique<Ui::RippleAnimation>(st::historyAttachEmoji.ripple, std_::move(mask), [this] { update(_send->geometry()); });
|
||||
}
|
||||
_recordRipple->add(mapFromGlobal(QCursor::pos()) - QPoint(_send->x() + (_send->width() - st::historyAttachEmoji.rippleAreaSize) / 2, _send->y() + st::historyAttachEmoji.rippleAreaPosition.y()));
|
||||
} else if (_inReplyEdit) {
|
||||
Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId());
|
||||
} else if (_inPinnedMsg) {
|
||||
|
@ -8582,7 +8563,7 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
|
|||
Text *from = 0, *text = 0;
|
||||
bool serviceColor = false, hasForward = readyToForward();
|
||||
ImagePtr preview;
|
||||
HistoryItem *drawMsgText = (_editMsgId || _replyToId) ? _replyEditMsg : _kbReplyTo;
|
||||
auto drawMsgText = (_editMsgId || _replyToId) ? _replyEditMsg : _kbReplyTo;
|
||||
if (_editMsgId || _replyToId || (!hasForward && _kbReplyTo)) {
|
||||
if (!_editMsgId && drawMsgText && drawMsgText->author()->nameVersion > _replyToNameVersion) {
|
||||
updateReplyToName();
|
||||
|
@ -8718,10 +8699,16 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::drawRecordButton(Painter &p) {
|
||||
auto down = a_recordDown.current();
|
||||
auto fastIcon = [down, this] {
|
||||
if (down == 1.) {
|
||||
void HistoryWidget::drawRecordButton(Painter &p, float64 recordActive, TimeMs ms) {
|
||||
if (_recordRipple) {
|
||||
auto rippleColor = anim::color(st::historyAttachEmoji.ripple.color, st::historyRecordVoiceRippleBgActive, recordActive);
|
||||
_recordRipple->paint(p, _send->x() + (_send->width() - st::historyAttachEmoji.rippleAreaSize) / 2, _send->y() + st::historyAttachEmoji.rippleAreaPosition.y(), width(), ms, &rippleColor);
|
||||
if (_recordRipple->empty()) {
|
||||
_recordRipple.reset();
|
||||
}
|
||||
}
|
||||
auto fastIcon = [recordActive, this] {
|
||||
if (recordActive == 1.) {
|
||||
return &st::historyRecordVoiceActive;
|
||||
} else if (_inRecord) {
|
||||
return &st::historyRecordVoiceOver;
|
||||
|
@ -8729,19 +8716,19 @@ void HistoryWidget::drawRecordButton(Painter &p) {
|
|||
return &st::historyRecordVoice;
|
||||
};
|
||||
fastIcon()->paintInCenter(p, _send->geometry());
|
||||
if (down > 0. && down < 1.) {
|
||||
p.setOpacity(down);
|
||||
if (recordActive > 0. && recordActive < 1.) {
|
||||
p.setOpacity(recordActive);
|
||||
st::historyRecordVoiceActive.paintInCenter(p, _send->geometry());
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::drawRecording(Painter &p) {
|
||||
void HistoryWidget::drawRecording(Painter &p, float64 recordActive) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::historyRecordSignalColor);
|
||||
|
||||
float64 delta = qMin(float64(a_recordingLevel.current()) / 0x4000, 1.);
|
||||
int32 d = 2 * qRound(st::historyRecordSignalMin + (delta * (st::historyRecordSignalMax - st::historyRecordSignalMin)));
|
||||
auto delta = qMin(a_recordingLevel.current() / 0x4000, 1.);
|
||||
auto d = 2 * qRound(st::historyRecordSignalMin + (delta * (st::historyRecordSignalMax - st::historyRecordSignalMin)));
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawEllipse(_attachToggle->x() + (_attachEmoji->width() - d) / 2, _attachToggle->y() + (_attachToggle->height() - d) / 2, d, d);
|
||||
|
@ -8756,7 +8743,7 @@ void HistoryWidget::drawRecording(Painter &p) {
|
|||
int32 left = _attachToggle->x() + _attachEmoji->width() + st::historyRecordFont->width(duration) + ((_send->width() - st::historyRecordVoice.width()) / 2);
|
||||
int32 right = width() - _send->width();
|
||||
|
||||
p.setPen(anim::pen(st::historyRecordCancel, st::historyRecordCancelActive, a_recordCancelActive.current()));
|
||||
p.setPen(anim::pen(st::historyRecordCancel, st::historyRecordCancelActive, 1. - recordActive));
|
||||
p.drawText(left + (right - left - _recordCancelWidth) / 2, _attachToggle->y() + st::historyRecordTextTop + st::historyRecordFont->ascent, lang(lng_record_cancel));
|
||||
}
|
||||
|
||||
|
@ -8809,18 +8796,24 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
bool hasTopBar = !App::main()->topBar()->isHidden();
|
||||
|
||||
auto ms = getms();
|
||||
auto progress = _a_show.current(ms, 1.);
|
||||
if (_a_show.animating()) {
|
||||
int retina = cIntRetinaFactor();
|
||||
int inCacheTop = hasTopBar ? st::topBarHeight : 0;
|
||||
if (a_coordOver.current() > 0) {
|
||||
p.drawPixmap(QRect(0, 0, a_coordOver.current(), height()), _cacheUnder, QRect(-a_coordUnder.current() * retina, inCacheTop * retina, a_coordOver.current() * retina, height() * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
p.fillRect(0, 0, a_coordOver.current(), height(), st::slideFadeOutBg);
|
||||
auto retina = cIntRetinaFactor();
|
||||
auto inCacheTop = hasTopBar ? st::topBarHeight : 0;
|
||||
auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft);
|
||||
auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
|
||||
auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
|
||||
auto shadow = fromLeft ? (1. - progress) : progress;
|
||||
if (coordOver > 0) {
|
||||
p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * retina, inCacheTop * retina, coordOver * retina, height() * retina));
|
||||
p.setOpacity(shadow);
|
||||
p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
p.drawPixmap(QRect(a_coordOver.current(), 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, inCacheTop * retina, _cacheOver.width(), height() * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
st::slideShadow.fill(p, QRect(a_coordOver.current() - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, inCacheTop * retina, _cacheOver.width(), height() * retina));
|
||||
p.setOpacity(shadow);
|
||||
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8854,8 +8847,9 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
|
|||
if (!_field->isHidden() || _recording) {
|
||||
drawField(p, r);
|
||||
if (_send->isHidden() && (!_inlineBotCancel || _inlineBotCancel->isHidden())) {
|
||||
drawRecordButton(p);
|
||||
if (_recording) drawRecording(p);
|
||||
auto recordActive = _a_recordActive.current(ms, _inField ? 1. : 0.);
|
||||
drawRecordButton(p, recordActive, ms);
|
||||
if (_recording) drawRecording(p, recordActive);
|
||||
}
|
||||
}
|
||||
if (_pinnedBar && !_pinnedBar->cancel->isHidden()) {
|
||||
|
|
|
@ -510,7 +510,7 @@ private:
|
|||
ChildWidget<Ui::RoundButton> _cancel;
|
||||
PeerData *_offered = nullptr;
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
anim::value a_opacity;
|
||||
Animation _a_appearance;
|
||||
|
||||
QRect _box;
|
||||
|
@ -613,8 +613,7 @@ public:
|
|||
return peer() != nullptr;
|
||||
}
|
||||
void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms);
|
||||
void step_show(float64 ms, bool timer);
|
||||
void animStop();
|
||||
void finishAnimation();
|
||||
|
||||
void doneShow();
|
||||
|
||||
|
@ -650,7 +649,6 @@ public:
|
|||
void updatePreview();
|
||||
void previewCancel();
|
||||
|
||||
void step_record(float64 ms, bool timer);
|
||||
void step_recording(float64 ms, bool timer);
|
||||
void stopRecording(bool send);
|
||||
|
||||
|
@ -849,6 +847,8 @@ private slots:
|
|||
void updateField();
|
||||
|
||||
private:
|
||||
void animationCallback();
|
||||
void recordActiveCallback();
|
||||
void chooseAttach();
|
||||
void notifyFileQueryUpdated(const FileDialog::QueryUpdate &update);
|
||||
struct SendingFilesLists {
|
||||
|
@ -931,8 +931,8 @@ private:
|
|||
|
||||
void drawField(Painter &p, const QRect &rect);
|
||||
void paintEditHeader(Painter &p, const QRect &rect, int left, int top) const;
|
||||
void drawRecordButton(Painter &p);
|
||||
void drawRecording(Painter &p);
|
||||
void drawRecordButton(Painter &p, float64 recordActive, TimeMs ms);
|
||||
void drawRecording(Painter &p, float64 recordActive);
|
||||
void drawPinnedBar(Painter &p);
|
||||
|
||||
void updateMouseTracking();
|
||||
|
@ -1122,18 +1122,18 @@ private:
|
|||
ChildWidget<SilentToggle> _silent;
|
||||
bool _cmdStartShown = false;
|
||||
ChildWidget<MessageField> _field;
|
||||
Animation _a_record, _a_recording;
|
||||
Animation _a_recording;
|
||||
bool _recording = false;
|
||||
bool _inRecord = false;
|
||||
bool _inField = false;
|
||||
bool _inReplyEdit = false;
|
||||
bool _inPinnedMsg = false;
|
||||
bool _inClickable = false;
|
||||
anim::ivalue a_recordingLevel = { 0, 0 };
|
||||
int32 _recordingSamples = 0;
|
||||
anim::fvalue a_recordDown = { 0, 0 };
|
||||
anim::fvalue a_recordCancelActive;
|
||||
int32 _recordCancelWidth;
|
||||
anim::value a_recordingLevel;
|
||||
int _recordingSamples = 0;
|
||||
FloatAnimation _a_recordActive;
|
||||
std_::unique_ptr<Ui::RippleAnimation> _recordRipple;
|
||||
int _recordCancelWidth;
|
||||
|
||||
FileDialog::QueryId _attachFilesQueryId = 0;
|
||||
|
||||
|
@ -1163,10 +1163,9 @@ private:
|
|||
bool _titlePeerTextOnline = false;
|
||||
int _titlePeerTextWidth = 0;
|
||||
|
||||
Animation _a_show;
|
||||
FloatAnimation _a_show;
|
||||
Window::SlideDirection _showDirection;
|
||||
QPixmap _cacheUnder, _cacheOver;
|
||||
anim::ivalue a_coordUnder, a_coordOver;
|
||||
anim::fvalue a_progress;
|
||||
|
||||
QTimer _scrollTimer;
|
||||
int32 _scrollDelta = 0;
|
||||
|
|
|
@ -786,7 +786,7 @@ void File::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
|||
} else {
|
||||
if (!_animation) {
|
||||
ensureAnimation();
|
||||
_animation->a_thumbOver = anim::fvalue(1, 1);
|
||||
_animation->a_thumbOver = anim::value(1, 1);
|
||||
}
|
||||
_animation->a_thumbOver.start(0);
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ private:
|
|||
, _a_thumbOver(std_::move(thumbOverCallbacks))
|
||||
, radial(std_::move(radialCallbacks)) {
|
||||
}
|
||||
anim::fvalue a_thumbOver;
|
||||
anim::value a_thumbOver;
|
||||
Animation _a_thumbOver;
|
||||
|
||||
Ui::RadialAnimation radial;
|
||||
|
|
|
@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
using "basic.style";
|
||||
using "ui/widgets/widgets.style";
|
||||
|
||||
countryRipple: defaultRippleAnimation;
|
||||
|
||||
introCoverHeight: 208px;
|
||||
introCoverTopBg: #0f89d0;
|
||||
introCoverBottomBg: #39b0f0;
|
||||
|
@ -84,7 +86,7 @@ introStepHeight: 256px;
|
|||
introStepHeightAdd: 30px;
|
||||
introStepHeightFull: 580px;
|
||||
introSlideDuration: 200;
|
||||
introCoverDuration: 200;
|
||||
introCoverDuration: 300;
|
||||
|
||||
introNextButton: RoundButton(defaultActiveButton) {
|
||||
width: 300px;
|
||||
|
|
|
@ -47,7 +47,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
namespace Intro {
|
||||
|
||||
Widget::Widget(QWidget *parent) : TWidget(parent)
|
||||
, _a_show(animation(this, &Widget::step_show))
|
||||
, _back(this, new Ui::IconButton(this, st::introBackButton), base::lambda<void()>(), st::introSlideDuration)
|
||||
, _settings(this, new Ui::RoundButton(this, lang(lng_menu_settings), st::defaultBoxButton), base::lambda<void()>(), st::introCoverDuration)
|
||||
, _next(this, QString(), st::introNextButton) {
|
||||
|
@ -143,7 +142,7 @@ void Widget::historyMove(Direction direction) {
|
|||
if (wasStep->hasCover() != getStep()->hasCover()) {
|
||||
_nextTopFrom = wasStep->contentTop() + st::introStepHeight;
|
||||
_controlsTopFrom = wasStep->hasCover() ? st::introCoverHeight : 0;
|
||||
_coverShownAnimation.start([this] { updateControlsGeometry(); }, 0., 1., st::introCoverDuration, anim::easeOutCirc);
|
||||
_coverShownAnimation.start([this] { updateControlsGeometry(); }, 0., 1., st::introCoverDuration, wasStep->hasCover() ? anim::linear : anim::easeOutCirc);
|
||||
}
|
||||
|
||||
if (direction == Direction::Forward || direction == Direction::Replace) {
|
||||
|
@ -302,45 +301,29 @@ void Widget::hideControls() {
|
|||
_back->hideFast();
|
||||
}
|
||||
|
||||
void Widget::animShow(const QPixmap &bgAnimCache, bool back) {
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
void Widget::showAnimated(const QPixmap &bgAnimCache, bool back) {
|
||||
_showBack = back;
|
||||
|
||||
(back ? _cacheOver : _cacheUnder) = bgAnimCache;
|
||||
(_showBack ? _cacheOver : _cacheUnder) = bgAnimCache;
|
||||
|
||||
_a_show.stop();
|
||||
_a_show.finish();
|
||||
showControls();
|
||||
(back ? _cacheUnder : _cacheOver) = myGrab(this);
|
||||
(_showBack ? _cacheUnder : _cacheOver) = myGrab(this);
|
||||
hideControls();
|
||||
|
||||
a_coordUnder = back ? anim::ivalue(-st::slideShift, 0) : anim::ivalue(0, -st::slideShift);
|
||||
a_coordOver = back ? anim::ivalue(0, width()) : anim::ivalue(width(), 0);
|
||||
a_shadow = back ? anim::fvalue(1, 0) : anim::fvalue(0, 1);
|
||||
_a_show.start();
|
||||
_a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition());
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
void Widget::step_show(float64 ms, bool timer) {
|
||||
float64 dt = ms / st::slideDuration;
|
||||
if (dt >= 1) {
|
||||
_a_show.stop();
|
||||
|
||||
a_coordUnder.finish();
|
||||
a_coordOver.finish();
|
||||
a_shadow.finish();
|
||||
|
||||
void Widget::animationCallback() {
|
||||
update();
|
||||
if (!_a_show.animating()) {
|
||||
_cacheUnder = _cacheOver = QPixmap();
|
||||
|
||||
showControls();
|
||||
getStep()->activate();
|
||||
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
} else {
|
||||
a_coordUnder.update(dt, Window::SlideAnimation::transition());
|
||||
a_coordOver.update(dt, Window::SlideAnimation::transition());
|
||||
a_shadow.update(dt, Window::SlideAnimation::transition());
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void Widget::paintEvent(QPaintEvent *e) {
|
||||
|
@ -356,16 +339,20 @@ void Widget::paintEvent(QPaintEvent *e) {
|
|||
p.setClipRect(e->rect());
|
||||
}
|
||||
p.fillRect(e->rect(), st::windowBg);
|
||||
auto progress = _a_show.current(getms(), 1.);
|
||||
if (_a_show.animating()) {
|
||||
if (a_coordOver.current() > 0) {
|
||||
p.drawPixmap(QRect(0, 0, a_coordOver.current(), height()), _cacheUnder, QRect(-a_coordUnder.current() * cRetinaFactor(), 0, a_coordOver.current() * cRetinaFactor(), height() * cRetinaFactor()));
|
||||
p.setOpacity(a_shadow.current());
|
||||
p.fillRect(0, 0, a_coordOver.current(), height(), st::slideFadeOutBg);
|
||||
auto coordUnder = _showBack ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
|
||||
auto coordOver = _showBack ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
|
||||
auto shadow = _showBack ? (1. - progress) : progress;
|
||||
if (coordOver > 0) {
|
||||
p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * cRetinaFactor(), 0, coordOver * cRetinaFactor(), height() * cRetinaFactor()));
|
||||
p.setOpacity(shadow);
|
||||
p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
p.drawPixmap(a_coordOver.current(), 0, _cacheOver);
|
||||
p.setOpacity(a_shadow.current());
|
||||
st::slideShadow.fill(p, QRect(a_coordOver.current() - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
p.drawPixmap(coordOver, 0, _cacheOver);
|
||||
p.setOpacity(shadow);
|
||||
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,7 +478,6 @@ void Widget::Step::showFinished() {
|
|||
_slideAnimation.reset();
|
||||
prepareCoverMask();
|
||||
activate();
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
}
|
||||
|
||||
bool Widget::Step::paintAnimated(Painter &p, QRect clip) {
|
||||
|
@ -519,11 +505,11 @@ bool Widget::Step::paintAnimated(Painter &p, QRect clip) {
|
|||
return false;
|
||||
}
|
||||
|
||||
auto easeOut = anim::easeOutCirc(1., dt);
|
||||
auto arrivingAlpha = easeOut;
|
||||
auto departingAlpha = 1. - easeOut;
|
||||
auto showCoverMethod = easeOut;
|
||||
auto hideCoverMethod = easeOut;
|
||||
auto progress = (hasCover() ? anim::easeOutCirc(1., dt) : anim::linear(1., dt));
|
||||
auto arrivingAlpha = progress;
|
||||
auto departingAlpha = 1. - progress;
|
||||
auto showCoverMethod = progress;
|
||||
auto hideCoverMethod = progress;
|
||||
auto coverTop = (hasCover() ? anim::interpolate(-st::introCoverHeight, 0, showCoverMethod) : anim::interpolate(0, -st::introCoverHeight, hideCoverMethod));
|
||||
|
||||
paintCover(p, coverTop);
|
||||
|
@ -718,7 +704,6 @@ QPixmap Widget::Step::prepareSlideAnimation() {
|
|||
|
||||
void Widget::Step::showAnimated(Direction direction) {
|
||||
show();
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
hideChildren();
|
||||
if (_slideAnimation) {
|
||||
auto slideLeft = (direction == Direction::Back);
|
||||
|
|
|
@ -39,7 +39,8 @@ class Widget : public TWidget, public RPCSender {
|
|||
public:
|
||||
Widget(QWidget *parent);
|
||||
|
||||
void animShow(const QPixmap &bgAnimCache, bool back = false);
|
||||
void showAnimated(const QPixmap &bgAnimCache, bool back = false);
|
||||
|
||||
void setInnerFocus();
|
||||
|
||||
~Widget();
|
||||
|
@ -205,7 +206,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
void step_show(float64 ms, bool timer);
|
||||
void animationCallback();
|
||||
|
||||
void changeLanguage(int32 languageId);
|
||||
void updateControlsGeometry();
|
||||
|
@ -225,10 +226,9 @@ private:
|
|||
void resetDone(const MTPBool &result);
|
||||
bool resetFail(const RPCError &error);
|
||||
|
||||
Animation _a_show;
|
||||
FloatAnimation _a_show;
|
||||
bool _showBack = false;
|
||||
QPixmap _cacheUnder, _cacheOver;
|
||||
anim::ivalue a_coordUnder, a_coordOver;
|
||||
anim::fvalue a_shadow;
|
||||
|
||||
QVector<Step*> _stepHistory;
|
||||
Step *getStep(int skip = 0) {
|
||||
|
|
|
@ -453,9 +453,6 @@ void LayerStackWidget::prepareForAnimation() {
|
|||
if (auto layer = currentLayer()) {
|
||||
layer->hide();
|
||||
}
|
||||
if (auto app = App::app()) {
|
||||
app->mtpPause();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerStackWidget::animationDone() {
|
||||
|
@ -477,9 +474,6 @@ void LayerStackWidget::animationDone() {
|
|||
} else {
|
||||
showFinished();
|
||||
}
|
||||
if (auto app = App::app()) {
|
||||
app->mtpUnpause();
|
||||
}
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||
}
|
||||
|
||||
|
@ -613,8 +607,6 @@ LayerStackWidget::~LayerStackWidget() {
|
|||
}
|
||||
|
||||
MediaPreviewWidget::MediaPreviewWidget(QWidget *parent) : TWidget(parent)
|
||||
, a_shown(0, 0)
|
||||
, _a_shown(animation(this, &MediaPreviewWidget::step_shown))
|
||||
, _emojiSize(EmojiSizes[EIndex + 1] / cIntRetinaFactor()) {
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
||||
|
@ -626,8 +618,13 @@ void MediaPreviewWidget::paintEvent(QPaintEvent *e) {
|
|||
|
||||
auto image = currentImage();
|
||||
int w = image.width() / cIntRetinaFactor(), h = image.height() / cIntRetinaFactor();
|
||||
if (_a_shown.animating()) {
|
||||
float64 shown = a_shown.current();
|
||||
auto shown = _a_shown.current(getms(), _hiding ? 0. : 1.);
|
||||
if (!_a_shown.animating()) {
|
||||
if (_hiding) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
p.setOpacity(shown);
|
||||
// w = qMax(qRound(w * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(w % 2), 1);
|
||||
// h = qMax(qRound(h * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(h % 2), 1);
|
||||
|
@ -650,18 +647,6 @@ void MediaPreviewWidget::resizeEvent(QResizeEvent *e) {
|
|||
update();
|
||||
}
|
||||
|
||||
void MediaPreviewWidget::step_shown(float64 ms, bool timer) {
|
||||
float64 dt = ms / st::stickerPreviewDuration;
|
||||
if (dt >= 1) {
|
||||
_a_shown.stop();
|
||||
a_shown.finish();
|
||||
if (a_shown.current() < 0.5) hide();
|
||||
} else {
|
||||
a_shown.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void MediaPreviewWidget::showPreview(DocumentData *document) {
|
||||
if (!document || (!document->isAnimation() && !document->sticker())) {
|
||||
hidePreview();
|
||||
|
@ -692,8 +677,8 @@ void MediaPreviewWidget::startShow() {
|
|||
_cache = QPixmap();
|
||||
if (isHidden() || _a_shown.animating()) {
|
||||
if (isHidden()) show();
|
||||
a_shown.start(1);
|
||||
_a_shown.start();
|
||||
_hiding = false;
|
||||
_a_shown.start([this] { update(); }, 0., 1., st::stickerPreviewDuration);
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
|
@ -704,8 +689,8 @@ void MediaPreviewWidget::hidePreview() {
|
|||
return;
|
||||
}
|
||||
if (_gif) _cache = currentImage();
|
||||
a_shown.start(0);
|
||||
_a_shown.start();
|
||||
_hiding = true;
|
||||
_a_shown.start([this] { update(); }, 1., 0., st::stickerPreviewDuration);
|
||||
_photo = nullptr;
|
||||
_document = nullptr;
|
||||
resetGifAndCache();
|
||||
|
|
|
@ -144,8 +144,6 @@ public:
|
|||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
void step_shown(float64 ms, bool timer);
|
||||
|
||||
void showPreview(DocumentData *document);
|
||||
void showPreview(PhotoData *photo);
|
||||
void hidePreview();
|
||||
|
@ -159,8 +157,8 @@ private:
|
|||
void fillEmojiString();
|
||||
void resetGifAndCache();
|
||||
|
||||
anim::fvalue a_shown;
|
||||
Animation _a_shown;
|
||||
FloatAnimation _a_shown;
|
||||
bool _hiding = false;
|
||||
DocumentData *_document = nullptr;
|
||||
PhotoData *_photo = nullptr;
|
||||
Media::Clip::ReaderPointer _gif;
|
||||
|
|
|
@ -69,7 +69,6 @@ StackItemSection::~StackItemSection() {
|
|||
}
|
||||
|
||||
MainWidget::MainWidget(QWidget *parent) : TWidget(parent)
|
||||
, _a_show(animation(this, &MainWidget::step_show))
|
||||
, _dialogsWidth(st::dialogsWidthMin)
|
||||
, _sideShadow(this, st::shadowColor)
|
||||
, _dialogs(this)
|
||||
|
@ -2231,7 +2230,7 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::Show
|
|||
}
|
||||
|
||||
Window::SectionSlideParams animationParams;
|
||||
if (!_a_show.animating() && ((_history->isHidden() && (_wideSection || _overview)) || (Adaptive::OneColumn() && (_history->isHidden() || !peerId)) || back || (way == Ui::ShowWay::Forward))) {
|
||||
if (!_a_show.animating() && !App::passcoded() && ((_history->isHidden() && (_wideSection || _overview)) || (Adaptive::OneColumn() && (_history->isHidden() || !peerId)) || back || (way == Ui::ShowWay::Forward))) {
|
||||
animationParams = prepareHistoryAnimation(peerId);
|
||||
}
|
||||
if (_history->peer() && _history->peer()->id != peerId && way != Ui::ShowWay::Forward) {
|
||||
|
@ -2258,7 +2257,7 @@ void MainWidget::ui_showPeerHistory(quint64 peerId, qint32 showAtMsgId, Ui::Show
|
|||
_topBar->hide();
|
||||
_history->hide();
|
||||
if (!_a_show.animating()) {
|
||||
if (!animationParams.oldContentCache.isNull() && !App::passcoded()) {
|
||||
if (!animationParams.oldContentCache.isNull()) {
|
||||
_dialogs->showAnimated(back ? Window::SlideDirection::FromLeft : Window::SlideDirection::FromRight, animationParams);
|
||||
} else {
|
||||
_dialogs->showFast();
|
||||
|
@ -2408,7 +2407,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
|
|||
} else {
|
||||
_overview->fastShow();
|
||||
}
|
||||
_history->animStop();
|
||||
_history->finishAnimation();
|
||||
if (back) {
|
||||
clearBotStartToken(_history->peer());
|
||||
}
|
||||
|
@ -2537,7 +2536,7 @@ void MainWidget::showWideSectionAnimated(const Window::SectionMemento *memento,
|
|||
resizeEvent(0);
|
||||
auto direction = back ? Window::SlideDirection::FromLeft : Window::SlideDirection::FromRight;
|
||||
_wideSection->showAnimated(direction, animationParams);
|
||||
_history->animStop();
|
||||
_history->finishAnimation();
|
||||
_history->showHistory(0, 0);
|
||||
_history->hide();
|
||||
if (Adaptive::OneColumn()) _dialogs->hide();
|
||||
|
@ -2651,7 +2650,7 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶m
|
|||
|
||||
void MainWidget::dlgUpdated() {
|
||||
if (_peerInStack) {
|
||||
_dialogs->dlgUpdated(App::history(_peerInStack->id), _msgIdInStack);
|
||||
_dialogs->dlgUpdated(_peerInStack, _msgIdInStack);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2661,12 +2660,12 @@ void MainWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::dlgUpdated(History *row, MsgId msgId) {
|
||||
if (!row) return;
|
||||
if (msgId < 0 && -msgId < ServerMaxMsgId && row->peer->migrateFrom()) {
|
||||
_dialogs->dlgUpdated(App::history(row->peer->migrateFrom()->id), -msgId);
|
||||
void MainWidget::dlgUpdated(PeerData *peer, MsgId msgId) {
|
||||
if (!peer) return;
|
||||
if (msgId < 0 && -msgId < ServerMaxMsgId && peer->migrateFrom()) {
|
||||
_dialogs->dlgUpdated(peer->migrateFrom(), -msgId);
|
||||
} else {
|
||||
_dialogs->dlgUpdated(row, msgId);
|
||||
_dialogs->dlgUpdated(peer, msgId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2719,66 +2718,49 @@ void MainWidget::historyCleared(History *history) {
|
|||
_history->historyCleared(history);
|
||||
}
|
||||
|
||||
void MainWidget::animShow(const QPixmap &bgAnimCache, bool back) {
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
void MainWidget::showAnimated(const QPixmap &bgAnimCache, bool back) {
|
||||
_showBack = back;
|
||||
(_showBack ? _cacheOver : _cacheUnder) = bgAnimCache;
|
||||
|
||||
(back ? _cacheOver : _cacheUnder) = bgAnimCache;
|
||||
|
||||
_a_show.stop();
|
||||
_a_show.finish();
|
||||
|
||||
showAll();
|
||||
(back ? _cacheUnder : _cacheOver) = myGrab(this);
|
||||
(_showBack ? _cacheUnder : _cacheOver) = myGrab(this);
|
||||
hideAll();
|
||||
|
||||
a_coordUnder = back ? anim::ivalue(-st::slideShift, 0) : anim::ivalue(0, -st::slideShift);
|
||||
a_coordOver = back ? anim::ivalue(0, width()) : anim::ivalue(width(), 0);
|
||||
a_shadow = back ? anim::fvalue(1, 0) : anim::fvalue(0, 1);
|
||||
_a_show.start();
|
||||
_a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition());
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
void MainWidget::step_show(float64 ms, bool timer) {
|
||||
float64 dt = ms / st::slideDuration;
|
||||
if (dt >= 1) {
|
||||
_a_show.stop();
|
||||
|
||||
a_coordUnder.finish();
|
||||
a_coordOver.finish();
|
||||
a_shadow.finish();
|
||||
|
||||
void MainWidget::animationCallback() {
|
||||
update();
|
||||
if (!_a_show.animating()) {
|
||||
_cacheUnder = _cacheOver = QPixmap();
|
||||
|
||||
showAll();
|
||||
activate();
|
||||
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
} else {
|
||||
a_coordUnder.update(dt, Window::SlideAnimation::transition());
|
||||
a_coordOver.update(dt, Window::SlideAnimation::transition());
|
||||
a_shadow.update(dt, Window::SlideAnimation::transition());
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void MainWidget::animStop_show() {
|
||||
_a_show.stop();
|
||||
}
|
||||
|
||||
void MainWidget::paintEvent(QPaintEvent *e) {
|
||||
if (_background) checkChatBackground();
|
||||
|
||||
Painter p(this);
|
||||
auto progress = _a_show.current(getms(), 1.);
|
||||
if (_a_show.animating()) {
|
||||
if (a_coordOver.current() > 0) {
|
||||
p.drawPixmap(QRect(0, 0, a_coordOver.current(), height()), _cacheUnder, QRect(-a_coordUnder.current() * cRetinaFactor(), 0, a_coordOver.current() * cRetinaFactor(), height() * cRetinaFactor()));
|
||||
p.setOpacity(a_shadow.current());
|
||||
p.fillRect(0, 0, a_coordOver.current(), height(), st::slideFadeOutBg);
|
||||
auto coordUnder = _showBack ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
|
||||
auto coordOver = _showBack ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
|
||||
auto shadow = _showBack ? (1. - progress) : progress;
|
||||
if (coordOver > 0) {
|
||||
p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * cRetinaFactor(), 0, coordOver * cRetinaFactor(), height() * cRetinaFactor()));
|
||||
p.setOpacity(shadow);
|
||||
p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
p.drawPixmap(a_coordOver.current(), 0, _cacheOver);
|
||||
p.setOpacity(a_shadow.current());
|
||||
st::slideShadow.fill(p, QRect(a_coordOver.current() - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
p.drawPixmap(coordOver, 0, _cacheOver);
|
||||
p.setOpacity(shadow);
|
||||
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3048,7 +3030,7 @@ void MainWidget::onHistoryShown(History *history, MsgId atMsgId) {
|
|||
_topBar->hide();
|
||||
}
|
||||
|
||||
dlgUpdated(history, atMsgId);
|
||||
dlgUpdated(history ? history->peer : nullptr, atMsgId);
|
||||
}
|
||||
|
||||
void MainWidget::searchInPeer(PeerData *peer) {
|
||||
|
|
|
@ -152,9 +152,7 @@ public:
|
|||
|
||||
int contentScrollAddToY() const;
|
||||
|
||||
void animShow(const QPixmap &bgAnimCache, bool back = false);
|
||||
void step_show(float64 ms, bool timer);
|
||||
void animStop_show();
|
||||
void showAnimated(const QPixmap &bgAnimCache, bool back = false);
|
||||
|
||||
void start(const MTPUser &user);
|
||||
|
||||
|
@ -178,7 +176,7 @@ public:
|
|||
void removeDialog(History *history);
|
||||
void dlgUpdated();
|
||||
void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
|
||||
void dlgUpdated(History *row, MsgId msgId);
|
||||
void dlgUpdated(PeerData *peer, MsgId msgId);
|
||||
|
||||
void windowShown();
|
||||
|
||||
|
@ -483,6 +481,7 @@ protected:
|
|||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
private:
|
||||
void animationCallback();
|
||||
void updateAdaptiveLayout();
|
||||
void handleAudioUpdate(const AudioMsgId &audioId);
|
||||
void updateMediaPlayerPosition();
|
||||
|
@ -587,10 +586,9 @@ private:
|
|||
base::Observable<PeerData*> _searchInPeerChanged;
|
||||
base::Observable<PeerData*> _historyPeerChanged;
|
||||
|
||||
Animation _a_show;
|
||||
FloatAnimation _a_show;
|
||||
bool _showBack = false;
|
||||
QPixmap _cacheUnder, _cacheOver;
|
||||
anim::ivalue a_coordUnder, a_coordOver;
|
||||
anim::fvalue a_shadow;
|
||||
|
||||
int _dialogsWidth;
|
||||
|
||||
|
|
|
@ -241,9 +241,9 @@ void MainWindow::clearPasscode() {
|
|||
|
||||
_passcode.destroy();
|
||||
if (_intro) {
|
||||
_intro->animShow(bg, true);
|
||||
_intro->showAnimated(bg, true);
|
||||
} else {
|
||||
_main->animShow(bg, true);
|
||||
_main->showAnimated(bg, true);
|
||||
}
|
||||
notifyUpdateAll();
|
||||
updateGlobalMenu();
|
||||
|
@ -265,7 +265,7 @@ void MainWindow::setupPasscode() {
|
|||
}
|
||||
if (_intro) _intro->hide();
|
||||
if (animated) {
|
||||
_passcode->animShow(bg);
|
||||
_passcode->showAnimated(bg);
|
||||
} else {
|
||||
setInnerFocus();
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ void MainWindow::setupIntro() {
|
|||
updateControlsGeometry();
|
||||
|
||||
if (animated) {
|
||||
_intro->animShow(bg);
|
||||
_intro->showAnimated(bg);
|
||||
} else {
|
||||
setInnerFocus();
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ void MainWindow::setupMain(const MTPUser *self) {
|
|||
updateControlsGeometry();
|
||||
|
||||
if (animated) {
|
||||
_main->animShow(bg);
|
||||
_main->showAnimated(bg);
|
||||
} else {
|
||||
_main->activate();
|
||||
}
|
||||
|
|
|
@ -991,7 +991,7 @@ void AudioPlayerFader::onTimer() {
|
|||
float64 wasAudio = suppressAllGain;
|
||||
if (ms >= _suppressAllStart + notifyLengthMs || ms < _suppressAllStart) {
|
||||
_suppressAll = _suppressAllAnim = false;
|
||||
_suppressAllGain = anim::fvalue(1., 1.);
|
||||
_suppressAllGain = anim::value(1., 1.);
|
||||
} else if (ms > _suppressAllStart + notifyLengthMs - AudioFadeDuration) {
|
||||
if (_suppressAllGain.to() != 1.) _suppressAllGain.start(1.);
|
||||
_suppressAllGain.update(1. - ((_suppressAllStart + notifyLengthMs - ms) / float64(AudioFadeDuration)), anim::linear);
|
||||
|
|
|
@ -257,7 +257,7 @@ private:
|
|||
bool _suppressSong = false;
|
||||
bool _suppressSongAnim = false;
|
||||
bool _songVolumeChanged, _videoVolumeChanged;
|
||||
anim::fvalue _suppressAllGain, _suppressSongGain;
|
||||
anim::value _suppressAllGain, _suppressSongGain;
|
||||
TimeMs _suppressAllStart = 0;
|
||||
TimeMs _suppressSongStart = 0;
|
||||
|
||||
|
|
|
@ -23,17 +23,7 @@ using "basic.style";
|
|||
using "ui/widgets/widgets.style";
|
||||
using "overview/overview.style";
|
||||
|
||||
MediaPlayerButton {
|
||||
playPosition: point;
|
||||
playOuter: size;
|
||||
pausePosition: point;
|
||||
pauseOuter: size;
|
||||
pauseStroke: pixels;
|
||||
cancelPosition: point;
|
||||
cancelOuter: size;
|
||||
cancelStroke: pixels;
|
||||
}
|
||||
|
||||
mediaPlayerBg: windowBg;
|
||||
mediaPlayerActiveFg: windowBgActive;
|
||||
mediaPlayerInactiveFg: #dfebf2;
|
||||
|
||||
|
@ -46,6 +36,12 @@ mediaPlayerButton: MediaPlayerButton {
|
|||
cancelPosition: point(1px, 1px);
|
||||
cancelOuter: size(15px, 15px);
|
||||
cancelStroke: 3px;
|
||||
|
||||
rippleAreaPosition: point(0px, 5px);
|
||||
rippleAreaSize: 25px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: lightButtonBgOver;
|
||||
}
|
||||
}
|
||||
mediaPlayerButtonSize: size(25px, 30px);
|
||||
|
||||
|
@ -76,10 +72,20 @@ mediaPlayerRepeatButton: IconButton {
|
|||
{ "player_repeat", mediaPlayerActiveFg, point(9px, 11px) }
|
||||
};
|
||||
iconPosition: point(0px, 0px);
|
||||
|
||||
rippleAreaPosition: point(3px, 5px);
|
||||
rippleAreaSize: 25px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: lightButtonBgOver;
|
||||
}
|
||||
}
|
||||
mediaPlayerRepeatDisabledIcon: icon {
|
||||
{ "player_repeat", #c8c8c8, point(9px, 11px)}
|
||||
{ "player_repeat", menuIconFg, point(9px, 11px)}
|
||||
};
|
||||
mediaPlayerRepeatDisabledIconOver: icon {
|
||||
{ "player_repeat", menuIconFgOver, point(9px, 11px)}
|
||||
};
|
||||
mediaPlayerRepeatDisabledRippleBg: windowBgOver;
|
||||
mediaPlayerRepeatInactiveIcon: icon {
|
||||
{ "player_repeat", mediaPlayerInactiveFg, point(9px, 11px)}
|
||||
};
|
||||
|
@ -102,6 +108,12 @@ mediaPlayerVolumeToggle: IconButton {
|
|||
|
||||
icon: mediaPlayerVolumeIcon0;
|
||||
iconPosition: point(8px, 11px);
|
||||
|
||||
rippleAreaPosition: point(3px, 5px);
|
||||
rippleAreaSize: 25px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: lightButtonBgOver;
|
||||
}
|
||||
}
|
||||
mediaPlayerVolumeMargin: 10px;
|
||||
mediaPlayerVolumeSize: size(27px, 100px);
|
||||
|
@ -117,6 +129,8 @@ mediaPlayerNextButton: IconButton(mediaPlayerRepeatButton) {
|
|||
icon: icon {
|
||||
{ "player_next", mediaPlayerActiveFg, mediaPlayerSkipIconPosition },
|
||||
};
|
||||
|
||||
rippleAreaPosition: point(0px, 5px);
|
||||
}
|
||||
mediaPlayerNextDisabledIcon: icon {
|
||||
{ "player_next", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition },
|
||||
|
@ -125,13 +139,20 @@ mediaPlayerPreviousButton: IconButton(mediaPlayerNextButton) {
|
|||
icon: icon {
|
||||
{ "player_next-flip_horizontal", mediaPlayerActiveFg, mediaPlayerSkipIconPosition },
|
||||
};
|
||||
rippleAreaPosition: point(1px, 5px);
|
||||
}
|
||||
mediaPlayerPreviousDisabledIcon: icon {
|
||||
{ "player_next-flip_horizontal", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition },
|
||||
};
|
||||
mediaPlayerClose: IconButton(mediaPlayerRepeatButton) {
|
||||
width: 37px;
|
||||
icon: icon {{ "player_close", #c8c8c8, point(10px, 12px) }};
|
||||
icon: icon {{ "player_close", menuIconFg, point(10px, 12px) }};
|
||||
iconOver: icon {{ "player_close", menuIconFgOver, point(10px, 12px) }};
|
||||
|
||||
rippleAreaPosition: point(3px, 5px);
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
}
|
||||
mediaPlayerPlayback: FilledSlider {
|
||||
fullWidth: 6px;
|
||||
|
@ -165,7 +186,8 @@ mediaPlayerCoverHeight: 102px;
|
|||
mediaPlayerPanelClose: IconButton(mediaPlayerClose) {
|
||||
width: 43px;
|
||||
height: 28px;
|
||||
icon: icon {{ "player_close", #c8c8c8, point(16px, 14px) }};
|
||||
icon: icon {{ "player_close", menuIconFg, point(16px, 14px) }};
|
||||
iconOver: icon {{ "player_close", menuIconFgOver, point(16px, 14px) }};
|
||||
}
|
||||
|
||||
mediaPlayerPanelNextButton: IconButton(mediaPlayerRepeatButton) {
|
||||
|
|
|
@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "stdafx.h"
|
||||
#include "media/player/media_player_button.h"
|
||||
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
namespace Media {
|
||||
namespace Player {
|
||||
namespace {
|
||||
|
|
|
@ -234,7 +234,7 @@ void CoverWidget::updateLabelPositions() {
|
|||
}
|
||||
|
||||
void CoverWidget::updateRepeatTrackIcon() {
|
||||
_repeatTrack->setIcon(instance()->repeatEnabled() ? nullptr : &st::mediaPlayerRepeatInactiveIcon);
|
||||
_repeatTrack->setIconOverride(instance()->repeatEnabled() ? nullptr : &st::mediaPlayerRepeatInactiveIcon);
|
||||
}
|
||||
|
||||
void CoverWidget::handleSongUpdate(const UpdatedEvent &e) {
|
||||
|
@ -338,9 +338,9 @@ void CoverWidget::handlePlaylistUpdate() {
|
|||
createPrevNextButtons();
|
||||
auto previousEnabled = (index > 0);
|
||||
auto nextEnabled = (index + 1 < playlist.size());
|
||||
_previousTrack->setIcon(previousEnabled ? nullptr : &st::mediaPlayerPanelPreviousDisabledIcon);
|
||||
_previousTrack->setIconOverride(previousEnabled ? nullptr : &st::mediaPlayerPanelPreviousDisabledIcon);
|
||||
_previousTrack->setCursor(previousEnabled ? style::cur_pointer : style::cur_default);
|
||||
_nextTrack->setIcon(nextEnabled ? nullptr : &st::mediaPlayerPanelNextDisabledIcon);
|
||||
_nextTrack->setIconOverride(nextEnabled ? nullptr : &st::mediaPlayerPanelNextDisabledIcon);
|
||||
_nextTrack->setCursor(nextEnabled ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ void CoverWidget::updateVolumeToggleIcon() {
|
|||
}
|
||||
return nullptr;
|
||||
};
|
||||
_volumeToggle->setIcon(icon());
|
||||
_volumeToggle->setIconOverride(icon());
|
||||
}
|
||||
|
||||
} // namespace Player
|
||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "ui/widgets/continuous_sliders.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "media/media_audio.h"
|
||||
#include "media/view/media_clip_playback.h"
|
||||
#include "media/player/media_player_button.h"
|
||||
|
@ -38,7 +39,7 @@ namespace Player {
|
|||
|
||||
using State = PlayButtonLayout::State;
|
||||
|
||||
class Widget::PlayButton : public Ui::AbstractButton {
|
||||
class Widget::PlayButton : public Ui::RippleButton {
|
||||
public:
|
||||
PlayButton(QWidget *parent);
|
||||
|
||||
|
@ -52,12 +53,15 @@ public:
|
|||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
QPoint prepareRippleStartPosition() const override;
|
||||
|
||||
private:
|
||||
PlayButtonLayout _layout;
|
||||
|
||||
};
|
||||
|
||||
Widget::PlayButton::PlayButton(QWidget *parent) : Ui::AbstractButton(parent)
|
||||
Widget::PlayButton::PlayButton(QWidget *parent) : Ui::RippleButton(parent, st::mediaPlayerButton.ripple)
|
||||
, _layout(st::mediaPlayerButton, [this] { update(); }) {
|
||||
resize(st::mediaPlayerButtonSize);
|
||||
setCursor(style::cur_pointer);
|
||||
|
@ -66,10 +70,20 @@ Widget::PlayButton::PlayButton(QWidget *parent) : Ui::AbstractButton(parent)
|
|||
void Widget::PlayButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
paintRipple(p, st::mediaPlayerButton.rippleAreaPosition.x(), st::mediaPlayerButton.rippleAreaPosition.y(), getms());
|
||||
p.translate(st::mediaPlayerButtonPosition.x(), st::mediaPlayerButtonPosition.y());
|
||||
_layout.paint(p, st::mediaPlayerActiveFg);
|
||||
}
|
||||
|
||||
QImage Widget::PlayButton::prepareRippleMask() const {
|
||||
auto size = QSize(st::mediaPlayerButton.rippleAreaSize, st::mediaPlayerButton.rippleAreaSize);
|
||||
return Ui::RippleAnimation::ellipseMask(size);
|
||||
}
|
||||
|
||||
QPoint Widget::PlayButton::prepareRippleStartPosition() const {
|
||||
return QPoint(mapFromGlobal(QCursor::pos()) - st::mediaPlayerButton.rippleAreaPosition);
|
||||
}
|
||||
|
||||
Widget::Widget(QWidget *parent) : TWidget(parent)
|
||||
, _nameLabel(this, st::mediaPlayerName)
|
||||
, _timeLabel(this, st::mediaPlayerTime)
|
||||
|
@ -146,7 +160,7 @@ void Widget::updateVolumeToggleIcon() {
|
|||
}
|
||||
return nullptr;
|
||||
};
|
||||
_volumeToggle->setIcon(icon());
|
||||
_volumeToggle->setIconOverride(icon());
|
||||
}
|
||||
|
||||
void Widget::setCloseCallback(CloseCallback &&callback) {
|
||||
|
@ -223,7 +237,7 @@ void Widget::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
auto fill = e->rect().intersected(QRect(0, 0, width(), st::mediaPlayerHeight));
|
||||
if (!fill.isEmpty()) {
|
||||
p.fillRect(fill, st::windowBg);
|
||||
p.fillRect(fill, st::mediaPlayerBg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,7 +304,9 @@ void Widget::updateLabelsGeometry() {
|
|||
}
|
||||
|
||||
void Widget::updateRepeatTrackIcon() {
|
||||
_repeatTrack->setIcon(instance()->repeatEnabled() ? nullptr : &st::mediaPlayerRepeatDisabledIcon);
|
||||
auto repeating = instance()->repeatEnabled();
|
||||
_repeatTrack->setIconOverride(repeating ? nullptr : &st::mediaPlayerRepeatDisabledIcon, repeating ? nullptr : &st::mediaPlayerRepeatDisabledIconOver);
|
||||
_repeatTrack->setRippleColorOverride(repeating ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
||||
}
|
||||
|
||||
void Widget::handleSongUpdate(const UpdatedEvent &e) {
|
||||
|
@ -393,9 +409,11 @@ void Widget::handlePlaylistUpdate() {
|
|||
createPrevNextButtons();
|
||||
auto previousEnabled = (index > 0);
|
||||
auto nextEnabled = (index + 1 < playlist.size());
|
||||
_previousTrack->setIcon(previousEnabled ? nullptr : &st::mediaPlayerPreviousDisabledIcon);
|
||||
_previousTrack->setIconOverride(previousEnabled ? nullptr : &st::mediaPlayerPreviousDisabledIcon);
|
||||
_previousTrack->setRippleColorOverride(previousEnabled ? nullptr : &st::mediaPlayerBg);
|
||||
_previousTrack->setCursor(previousEnabled ? style::cur_pointer : style::cur_default);
|
||||
_nextTrack->setIcon(nextEnabled ? nullptr : &st::mediaPlayerNextDisabledIcon);
|
||||
_nextTrack->setIconOverride(nextEnabled ? nullptr : &st::mediaPlayerNextDisabledIcon);
|
||||
_nextTrack->setRippleColorOverride(nextEnabled ? nullptr : &st::mediaPlayerBg);
|
||||
_nextTrack->setCursor(nextEnabled ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ void Controller::updatePlayPauseResumeState(const AudioPlaybackState &playbackSt
|
|||
_showPause = showPause;
|
||||
connect(_playPauseResume, SIGNAL(clicked()), this, _showPause ? SIGNAL(pausePressed()) : SIGNAL(playPressed()));
|
||||
|
||||
_playPauseResume->setIcon(_showPause ? &st::mediaviewPauseIcon : nullptr, _showPause ? &st::mediaviewPauseIconOver : nullptr);
|
||||
_playPauseResume->setIconOverride(_showPause ? &st::mediaviewPauseIcon : nullptr, _showPause ? &st::mediaviewPauseIconOver : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ void Controller::refreshTimeTexts() {
|
|||
}
|
||||
|
||||
void Controller::setInFullScreen(bool inFullScreen) {
|
||||
_fullScreenToggle->setIcon(inFullScreen ? &st::mediaviewFullScreenOutIcon : nullptr, inFullScreen ? &st::mediaviewFullScreenOutIconOver : nullptr);
|
||||
_fullScreenToggle->setIconOverride(inFullScreen ? &st::mediaviewFullScreenOutIcon : nullptr, inFullScreen ? &st::mediaviewFullScreenOutIconOver : nullptr);
|
||||
disconnect(_fullScreenToggle, SIGNAL(clicked()), this, SIGNAL(toFullScreenPressed()));
|
||||
disconnect(_fullScreenToggle, SIGNAL(clicked()), this, SIGNAL(fromFullScreenPressed()));
|
||||
|
||||
|
|
|
@ -2241,7 +2241,7 @@ bool MediaView::updateOverState(OverState newState) {
|
|||
if (i != _animOpacities.end()) {
|
||||
i->start(0);
|
||||
} else {
|
||||
_animOpacities.insert(_over, anim::fvalue(1, 0));
|
||||
_animOpacities.insert(_over, anim::value(1, 0));
|
||||
}
|
||||
if (!_a_state.animating()) _a_state.start();
|
||||
} else {
|
||||
|
@ -2254,7 +2254,7 @@ bool MediaView::updateOverState(OverState newState) {
|
|||
if (i != _animOpacities.end()) {
|
||||
i->start(1);
|
||||
} else {
|
||||
_animOpacities.insert(_over, anim::fvalue(0, 1));
|
||||
_animOpacities.insert(_over, anim::value());
|
||||
}
|
||||
if (!_a_state.animating()) _a_state.start();
|
||||
}
|
||||
|
@ -2492,7 +2492,7 @@ void MediaView::setVisible(bool visible) {
|
|||
if (!visible) {
|
||||
_controlsHideTimer.stop();
|
||||
_controlsState = ControlsShown;
|
||||
a_cOpacity = anim::fvalue(1, 1);
|
||||
a_cOpacity = anim::value(1, 1);
|
||||
}
|
||||
TWidget::setVisible(visible);
|
||||
if (visible) {
|
||||
|
|
|
@ -307,7 +307,7 @@ private:
|
|||
ControlsState _controlsState = ControlsShown;
|
||||
TimeMs _controlsAnimStarted = 0;
|
||||
QTimer _controlsHideTimer;
|
||||
anim::fvalue a_cOpacity;
|
||||
anim::value a_cOpacity;
|
||||
bool _mousePressed = false;
|
||||
|
||||
Ui::PopupMenu *_menu = nullptr;
|
||||
|
@ -328,14 +328,14 @@ private:
|
|||
|
||||
QString _saveMsgFilename;
|
||||
TimeMs _saveMsgStarted = 0;
|
||||
anim::fvalue _saveMsgOpacity = { 0 };
|
||||
anim::value _saveMsgOpacity;
|
||||
QRect _saveMsg;
|
||||
QTimer _saveMsgUpdater;
|
||||
Text _saveMsgText;
|
||||
|
||||
typedef QMap<OverState, TimeMs> Showing;
|
||||
Showing _animations;
|
||||
typedef QMap<OverState, anim::fvalue> ShowingOpacities;
|
||||
typedef QMap<OverState, anim::value> ShowingOpacities;
|
||||
ShowingOpacities _animOpacities;
|
||||
|
||||
int _verticalWheelDelta = 0;
|
||||
|
|
|
@ -358,7 +358,7 @@ namespace {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool _paused = false;
|
||||
int PauseLevel = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -379,7 +379,20 @@ Session *getSession(ShiftedDcId shiftedDcId) {
|
|||
}
|
||||
|
||||
bool paused() {
|
||||
return _paused;
|
||||
return PauseLevel > 0;
|
||||
}
|
||||
|
||||
void pause() {
|
||||
++PauseLevel;
|
||||
}
|
||||
|
||||
void unpause() {
|
||||
--PauseLevel;
|
||||
if (_started) {
|
||||
for_const (auto session, sessions) {
|
||||
session->unpaused();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void registerRequest(mtpRequestId requestId, int32 dcWithShift) {
|
||||
|
@ -685,19 +698,6 @@ void restart(int32 dcMask) {
|
|||
}
|
||||
}
|
||||
|
||||
void pause() {
|
||||
if (!_started) return;
|
||||
_paused = true;
|
||||
}
|
||||
|
||||
void unpause() {
|
||||
if (!_started) return;
|
||||
_paused = false;
|
||||
for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
|
||||
i.value()->unpaused();
|
||||
}
|
||||
}
|
||||
|
||||
void configure(int32 dc, int32 user) {
|
||||
if (_started) return;
|
||||
internal::setDC(dc);
|
||||
|
|
|
@ -25,12 +25,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "core/single_timer.h"
|
||||
|
||||
namespace MTP {
|
||||
|
||||
namespace internal {
|
||||
|
||||
Session *getSession(ShiftedDcId shiftedDcId); // 0 - current set dc
|
||||
|
||||
bool paused();
|
||||
void pause();
|
||||
void unpause();
|
||||
|
||||
void registerRequest(mtpRequestId requestId, int32 dc);
|
||||
void unregisterRequest(mtpRequestId requestId);
|
||||
|
@ -96,27 +97,32 @@ constexpr ShiftedDcId lgtDcId(DcId dcId) {
|
|||
}
|
||||
|
||||
namespace internal {
|
||||
constexpr ShiftedDcId downloadDcId(DcId dcId, int index) {
|
||||
static_assert(MTPDownloadSessionsCount < 0x10, "Too large MTPDownloadSessionsCount!");
|
||||
return shiftDcId(dcId, 0x10 + index);
|
||||
};
|
||||
}
|
||||
|
||||
constexpr ShiftedDcId downloadDcId(DcId dcId, int index) {
|
||||
static_assert(MTPDownloadSessionsCount < 0x10, "Too large MTPDownloadSessionsCount!");
|
||||
return shiftDcId(dcId, 0x10 + index);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// send(req, callbacks, MTP::dldDcId(dc, index)) - for download shifted dc id
|
||||
inline ShiftedDcId dldDcId(DcId dcId, int index) {
|
||||
t_assert(index >= 0 && index < MTPDownloadSessionsCount);
|
||||
return internal::downloadDcId(dcId, index);
|
||||
}
|
||||
|
||||
constexpr bool isDldDcId(ShiftedDcId shiftedDcId) {
|
||||
return (shiftedDcId >= internal::downloadDcId(0, 0)) && (shiftedDcId < internal::downloadDcId(0, MTPDownloadSessionsCount - 1) + DCShift);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
constexpr ShiftedDcId uploadDcId(DcId dcId, int index) {
|
||||
static_assert(MTPUploadSessionsCount < 0x10, "Too large MTPUploadSessionsCount!");
|
||||
return shiftDcId(dcId, 0x20 + index);
|
||||
};
|
||||
}
|
||||
|
||||
constexpr ShiftedDcId uploadDcId(DcId dcId, int index) {
|
||||
static_assert(MTPUploadSessionsCount < 0x10, "Too large MTPUploadSessionsCount!");
|
||||
return shiftDcId(dcId, 0x20 + index);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// send(req, callbacks, MTP::uplDcId(index)) - for upload shifted dc id
|
||||
// uploading always to the main dc so bareDcId == 0
|
||||
|
@ -124,6 +130,7 @@ inline ShiftedDcId uplDcId(int index) {
|
|||
t_assert(index >= 0 && index < MTPUploadSessionsCount);
|
||||
return internal::uploadDcId(0, index);
|
||||
};
|
||||
|
||||
constexpr bool isUplDcId(ShiftedDcId shiftedDcId) {
|
||||
return (shiftedDcId >= internal::uploadDcId(0, 0)) && (shiftedDcId < internal::uploadDcId(0, MTPUploadSessionsCount - 1) + DCShift);
|
||||
}
|
||||
|
@ -133,8 +140,29 @@ bool started();
|
|||
void restart();
|
||||
void restart(int32 dcMask);
|
||||
|
||||
void pause();
|
||||
void unpause();
|
||||
class PauseHolder {
|
||||
public:
|
||||
PauseHolder() {
|
||||
restart();
|
||||
}
|
||||
void restart() {
|
||||
if (!base::take(_paused, true)) {
|
||||
internal::pause();
|
||||
}
|
||||
}
|
||||
void release() {
|
||||
if (base::take(_paused)) {
|
||||
internal::unpause();
|
||||
}
|
||||
}
|
||||
~PauseHolder() {
|
||||
release();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _paused = false;
|
||||
|
||||
};
|
||||
|
||||
void configure(int32 dc, int32 user);
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ protected:
|
|||
}
|
||||
|
||||
Ui::RadialAnimation *_radial;
|
||||
anim::fvalue a_iconOver;
|
||||
anim::value a_iconOver;
|
||||
Animation _a_iconOver;
|
||||
|
||||
};
|
||||
|
|
|
@ -1878,7 +1878,6 @@ OverviewInner::~OverviewInner() {
|
|||
OverviewWidget::OverviewWidget(QWidget *parent, PeerData *peer, MediaOverviewType type) : TWidget(parent)
|
||||
, _scroll(this, st::settingsScroll, false)
|
||||
, _inner(this, _scroll, peer, type)
|
||||
, _a_show(animation(this, &OverviewWidget::step_show))
|
||||
, _topShadow(this, st::shadowColor) {
|
||||
_scroll->setOwnedWidget(_inner);
|
||||
_scroll->move(0, 0);
|
||||
|
@ -1936,18 +1935,23 @@ void OverviewWidget::paintEvent(QPaintEvent *e) {
|
|||
if (App::wnd() && App::wnd()->contentOverlapped(this, e)) return;
|
||||
|
||||
Painter p(this);
|
||||
auto progress = _a_show.current(getms(), 1.);
|
||||
if (_a_show.animating()) {
|
||||
int retina = cIntRetinaFactor();
|
||||
int inCacheTop = st::topBarHeight;
|
||||
if (a_coordOver.current() > 0) {
|
||||
p.drawPixmap(QRect(0, 0, a_coordOver.current(), height()), _cacheUnder, QRect(-a_coordUnder.current() * retina, inCacheTop * retina, a_coordOver.current() * retina, height() * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
p.fillRect(0, 0, a_coordOver.current(), height(), st::slideFadeOutBg);
|
||||
auto retina = cIntRetinaFactor();
|
||||
auto inCacheTop = st::topBarHeight;
|
||||
auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft);
|
||||
auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
|
||||
auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
|
||||
auto shadow = fromLeft ? (1. - progress) : progress;
|
||||
if (coordOver > 0) {
|
||||
p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * retina, inCacheTop * retina, coordOver * retina, height() * retina));
|
||||
p.setOpacity(shadow);
|
||||
p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
p.drawPixmap(QRect(a_coordOver.current(), 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, inCacheTop * retina, _cacheOver.width(), height() * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
st::slideShadow.fill(p, QRect(a_coordOver.current() - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, height()), _cacheOver, QRect(0, inCacheTop * retina, _cacheOver.width(), height() * retina));
|
||||
p.setOpacity(shadow);
|
||||
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1972,16 +1976,21 @@ void OverviewWidget::scrollReset() {
|
|||
|
||||
bool OverviewWidget::paintTopBar(Painter &p, int decreaseWidth) {
|
||||
if (_a_show.animating()) {
|
||||
int retina = cIntRetinaFactor();
|
||||
if (a_coordOver.current() > 0) {
|
||||
p.drawPixmap(QRect(0, 0, a_coordOver.current(), st::topBarHeight), _cacheUnder, QRect(-a_coordUnder.current() * retina, 0, a_coordOver.current() * retina, st::topBarHeight * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
p.fillRect(0, 0, a_coordOver.current(), st::topBarHeight, st::slideFadeOutBg);
|
||||
auto progress = _a_show.current(1.);
|
||||
auto retina = cIntRetinaFactor();
|
||||
auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft);
|
||||
auto coordUnder = fromLeft ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
|
||||
auto coordOver = fromLeft ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
|
||||
auto shadow = fromLeft ? (1. - progress) : progress;
|
||||
if (coordOver > 0) {
|
||||
p.drawPixmap(QRect(0, 0, coordOver, st::topBarHeight), _cacheUnder, QRect(-coordUnder * retina, 0, coordOver * retina, st::topBarHeight * retina));
|
||||
p.setOpacity(shadow);
|
||||
p.fillRect(0, 0, coordOver, st::topBarHeight, st::slideFadeOutBg);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
p.drawPixmap(QRect(a_coordOver.current(), 0, _cacheOver.width() / retina, st::topBarHeight), _cacheOver, QRect(0, 0, _cacheOver.width(), st::topBarHeight * retina));
|
||||
p.setOpacity(a_progress.current());
|
||||
st::slideShadow.fill(p, QRect(a_coordOver.current() - st::slideShadow.width(), 0, st::slideShadow.width(), st::topBarHeight));
|
||||
p.drawPixmap(QRect(coordOver, 0, _cacheOver.width() / retina, st::topBarHeight), _cacheOver, QRect(0, 0, _cacheOver.width(), st::topBarHeight * retina));
|
||||
p.setOpacity(shadow);
|
||||
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), st::topBarHeight));
|
||||
return false;
|
||||
}
|
||||
st::topBarBack.paint(p, (st::topBarArrowPadding.left() - st::topBarBack.width()) / 2, (st::topBarHeight - st::topBarBack.height()) / 2, width());
|
||||
|
@ -2080,8 +2089,6 @@ void OverviewWidget::fastShow(bool back, int32 lastScrollTop) {
|
|||
show();
|
||||
_inner->activate();
|
||||
doneShow();
|
||||
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
}
|
||||
|
||||
void OverviewWidget::setLastScrollTop(int lastScrollTop) {
|
||||
|
@ -2090,10 +2097,11 @@ void OverviewWidget::setLastScrollTop(int lastScrollTop) {
|
|||
}
|
||||
|
||||
void OverviewWidget::showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms) {
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
|
||||
_showDirection = direction;
|
||||
resizeEvent(0);
|
||||
|
||||
_a_show.finish();
|
||||
|
||||
_cacheUnder = params.oldContentCache;
|
||||
show();
|
||||
_topShadow->setVisible(params.withTopBarShadow ? false : true);
|
||||
|
@ -2104,47 +2112,26 @@ void OverviewWidget::showAnimated(Window::SlideDirection direction, const Window
|
|||
_scrollSetAfterShow = _scroll->scrollTop();
|
||||
_scroll->hide();
|
||||
|
||||
int delta = st::slideShift;
|
||||
if (direction == Window::SlideDirection::FromLeft) {
|
||||
a_progress = anim::fvalue(1, 0);
|
||||
if (_showDirection == Window::SlideDirection::FromLeft) {
|
||||
std::swap(_cacheUnder, _cacheOver);
|
||||
a_coordUnder = anim::ivalue(-delta, 0);
|
||||
a_coordOver = anim::ivalue(0, width());
|
||||
} else {
|
||||
a_progress = anim::fvalue(0, 1);
|
||||
a_coordUnder = anim::ivalue(0, -delta);
|
||||
a_coordOver = anim::ivalue(width(), 0);
|
||||
}
|
||||
_a_show.start();
|
||||
_a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition());
|
||||
|
||||
App::main()->topBar()->update();
|
||||
|
||||
activate();
|
||||
}
|
||||
|
||||
void OverviewWidget::step_show(float64 ms, bool timer) {
|
||||
float64 dt = ms / st::slideDuration;
|
||||
if (dt >= 1) {
|
||||
_a_show.stop();
|
||||
void OverviewWidget::animationCallback() {
|
||||
update();
|
||||
App::main()->topBar()->update();
|
||||
if (!_a_show.animating()) {
|
||||
_topShadow->show();
|
||||
|
||||
a_coordUnder.finish();
|
||||
a_coordOver.finish();
|
||||
a_progress.finish();
|
||||
_cacheUnder = _cacheOver = QPixmap();
|
||||
App::main()->topBar()->stopAnim();
|
||||
|
||||
doneShow();
|
||||
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
} else {
|
||||
a_coordUnder.update(dt, Window::SlideAnimation::transition());
|
||||
a_coordOver.update(dt, Window::SlideAnimation::transition());
|
||||
a_progress.update(dt, Window::SlideAnimation::transition());
|
||||
}
|
||||
if (timer) {
|
||||
update();
|
||||
App::main()->topBar()->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -301,7 +301,6 @@ public:
|
|||
}
|
||||
void setLastScrollTop(int lastScrollTop);
|
||||
void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams ¶ms);
|
||||
void step_show(float64 ms, bool timer);
|
||||
|
||||
void doneShow();
|
||||
|
||||
|
@ -355,16 +354,17 @@ public slots:
|
|||
void onClearSelected();
|
||||
|
||||
private:
|
||||
void animationCallback();
|
||||
|
||||
ChildWidget<Ui::ScrollArea> _scroll;
|
||||
ChildWidget<OverviewInner> _inner;
|
||||
bool _noDropResizeIndex = false;
|
||||
|
||||
QString _header;
|
||||
|
||||
Animation _a_show;
|
||||
FloatAnimation _a_show;
|
||||
Window::SlideDirection _showDirection;
|
||||
QPixmap _cacheUnder, _cacheOver;
|
||||
anim::ivalue a_coordUnder, a_coordOver;
|
||||
anim::fvalue a_progress;
|
||||
|
||||
int32 _scrollSetAfterShow = 0;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "window/window_slide_animation.h"
|
||||
|
||||
PasscodeWidget::PasscodeWidget(QWidget *parent) : TWidget(parent)
|
||||
, _a_show(animation(this, &PasscodeWidget::step_show))
|
||||
, _passcode(this, st::passcodeInput)
|
||||
, _submit(this, lang(lng_passcode_submit), st::passcodeSubmit)
|
||||
, _logout(this, lang(lng_passcode_logout)) {
|
||||
|
@ -104,52 +103,30 @@ void PasscodeWidget::onChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
void PasscodeWidget::animShow(const QPixmap &bgAnimCache, bool back) {
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
void PasscodeWidget::showAnimated(const QPixmap &bgAnimCache, bool back) {
|
||||
_showBack = back;
|
||||
(_showBack ? _cacheOver : _cacheUnder) = bgAnimCache;
|
||||
|
||||
(back ? _cacheOver : _cacheUnder) = bgAnimCache;
|
||||
|
||||
_a_show.stop();
|
||||
_a_show.finish();
|
||||
|
||||
showAll();
|
||||
(back ? _cacheUnder : _cacheOver) = myGrab(this);
|
||||
(_showBack ? _cacheUnder : _cacheOver) = myGrab(this);
|
||||
hideAll();
|
||||
|
||||
a_coordUnder = back ? anim::ivalue(-st::slideShift, 0) : anim::ivalue(0, -st::slideShift);
|
||||
a_coordOver = back ? anim::ivalue(0, width()) : anim::ivalue(width(), 0);
|
||||
a_shadow = back ? anim::fvalue(1, 0) : anim::fvalue(0, 1);
|
||||
_a_show.start();
|
||||
|
||||
_a_show.start([this] { animationCallback(); }, 0., 1., st::slideDuration, Window::SlideAnimation::transition());
|
||||
show();
|
||||
}
|
||||
|
||||
void PasscodeWidget::step_show(float64 ms, bool timer) {
|
||||
float64 dt = ms / st::slideDuration;
|
||||
if (dt >= 1) {
|
||||
_a_show.stop();
|
||||
|
||||
a_coordUnder.finish();
|
||||
a_coordOver.finish();
|
||||
a_shadow.finish();
|
||||
|
||||
_cacheUnder = _cacheOver = QPixmap();
|
||||
|
||||
void PasscodeWidget::animationCallback() {
|
||||
update();
|
||||
if (!_a_show.animating()) {
|
||||
showAll();
|
||||
if (App::wnd()) App::wnd()->setInnerFocus();
|
||||
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
|
||||
Ui::showChatsList();
|
||||
} else {
|
||||
a_coordUnder.update(dt, Window::SlideAnimation::transition());
|
||||
a_coordOver.update(dt, Window::SlideAnimation::transition());
|
||||
a_shadow.update(dt, Window::SlideAnimation::transition());
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void PasscodeWidget::stop_show() {
|
||||
_a_show.stop();
|
||||
_cacheUnder = _cacheOver = QPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
void PasscodeWidget::showAll() {
|
||||
|
@ -173,16 +150,20 @@ void PasscodeWidget::paintEvent(QPaintEvent *e) {
|
|||
p.setClipRect(e->rect());
|
||||
}
|
||||
|
||||
auto progress = _a_show.current(getms(), 1.);
|
||||
if (_a_show.animating()) {
|
||||
if (a_coordOver.current() > 0) {
|
||||
p.drawPixmap(QRect(0, 0, a_coordOver.current(), height()), _cacheUnder, QRect(-a_coordUnder.current() * cRetinaFactor(), 0, a_coordOver.current() * cRetinaFactor(), height() * cRetinaFactor()));
|
||||
p.setOpacity(a_shadow.current());
|
||||
p.fillRect(0, 0, a_coordOver.current(), height(), st::slideFadeOutBg);
|
||||
auto coordUnder = _showBack ? anim::interpolate(-st::slideShift, 0, progress) : anim::interpolate(0, -st::slideShift, progress);
|
||||
auto coordOver = _showBack ? anim::interpolate(0, width(), progress) : anim::interpolate(width(), 0, progress);
|
||||
auto shadow = _showBack ? (1. - progress) : progress;
|
||||
if (coordOver > 0) {
|
||||
p.drawPixmap(QRect(0, 0, coordOver, height()), _cacheUnder, QRect(-coordUnder * cRetinaFactor(), 0, coordOver * cRetinaFactor(), height() * cRetinaFactor()));
|
||||
p.setOpacity(shadow);
|
||||
p.fillRect(0, 0, coordOver, height(), st::slideFadeOutBg);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
p.drawPixmap(a_coordOver.current(), 0, _cacheOver);
|
||||
p.setOpacity(a_shadow.current());
|
||||
st::slideShadow.fill(p, QRect(a_coordOver.current() - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
p.drawPixmap(coordOver, 0, _cacheOver);
|
||||
p.setOpacity(shadow);
|
||||
st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), 0, st::slideShadow.width(), height()));
|
||||
} else {
|
||||
p.fillRect(rect(), st::windowBg);
|
||||
|
||||
|
|
|
@ -34,9 +34,7 @@ public:
|
|||
|
||||
void setInnerFocus();
|
||||
|
||||
void animShow(const QPixmap &bgAnimCache, bool back = false);
|
||||
void step_show(float64 ms, bool timer);
|
||||
void stop_show();
|
||||
void showAnimated(const QPixmap &bgAnimCache, bool back = false);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
@ -48,13 +46,14 @@ public slots:
|
|||
void onSubmit();
|
||||
|
||||
private:
|
||||
void animationCallback();
|
||||
|
||||
void showAll();
|
||||
void hideAll();
|
||||
|
||||
Animation _a_show;
|
||||
FloatAnimation _a_show;
|
||||
bool _showBack = false;
|
||||
QPixmap _cacheUnder, _cacheOver;
|
||||
anim::ivalue a_coordUnder, a_coordOver;
|
||||
anim::fvalue a_shadow;
|
||||
|
||||
ChildWidget<Ui::PasswordInput> _passcode;
|
||||
ChildWidget<Ui::RoundButton> _submit;
|
||||
|
|
|
@ -89,9 +89,9 @@ void TitleWidget::onWindowStateChanged(Qt::WindowState state) {
|
|||
|
||||
void TitleWidget::updateMaximizeRestoreButton() {
|
||||
if (_maximized) {
|
||||
_maximizeRestore->setIcon(&st::titleButtonRestoreIcon, &st::titleButtonRestoreIconOver);
|
||||
_maximizeRestore->setIconOverride(&st::titleButtonRestoreIcon, &st::titleButtonRestoreIconOver);
|
||||
} else {
|
||||
_maximizeRestore->setIcon(nullptr, nullptr);
|
||||
_maximizeRestore->setIconOverride(nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ profileMemberNamePosition: point(68px, 11px);
|
|||
profileMemberNameFg: #222222;
|
||||
profileMemberStatusPosition: point(68px, 31px);
|
||||
profileMemberStatusFg: windowSubTextFg;
|
||||
profileMemberStatusFgOver: windowSubTextFgOver;
|
||||
profileMemberStatusFgOver: #7c99b2;
|
||||
profileMemberStatusFgActive: windowActiveTextFg;
|
||||
profileMemberAdminIcon: icon {{ "profile_admin_star", windowBgActive, point(4px, 3px) }};
|
||||
profileLimitReachedLabel: FlatLabel(defaultFlatLabel) {
|
||||
|
|
|
@ -63,7 +63,7 @@ void CommonGroupsWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
|
|||
|
||||
int CommonGroupsWidget::resizeGetHeight(int newWidth) {
|
||||
auto result = PeerListWidget::resizeGetHeight(newWidth);
|
||||
return _height.animating() ? _height.current() : result;
|
||||
return qRound(_height.current(result));
|
||||
}
|
||||
|
||||
void CommonGroupsWidget::paintContents(Painter &p) {
|
||||
|
|
|
@ -65,7 +65,7 @@ private:
|
|||
Item *computeItem(PeerData *group);
|
||||
QMap<PeerData*, Item*> _dataMap;
|
||||
|
||||
IntAnimation _height;
|
||||
FloatAnimation _height;
|
||||
|
||||
int32 _preloadGroupId = 0;
|
||||
mtpRequestId _preloadRequestId = 0;
|
||||
|
|
|
@ -58,13 +58,17 @@ InfoWidget::InfoWidget(QWidget *parent, PeerData *peer) : BlockWidget(parent, pe
|
|||
void InfoWidget::showFinished() {
|
||||
_showFinished = true;
|
||||
if (_commonGroups && _commonGroups->isHidden() && getCommonGroupsCount() > 0) {
|
||||
_commonGroups->show();
|
||||
refreshVisibility();
|
||||
_height.start([this] { contentSizeUpdated(); }, isHidden() ? 0 : height(), resizeGetHeight(width()), st::widgetSlideDuration);
|
||||
contentSizeUpdated();
|
||||
slideCommonGroupsDown();
|
||||
}
|
||||
}
|
||||
|
||||
void InfoWidget::slideCommonGroupsDown() {
|
||||
_commonGroups->show();
|
||||
refreshVisibility();
|
||||
_height.start([this] { contentSizeUpdated(); }, isHidden() ? 0 : height(), resizeGetHeight(width()), st::widgetSlideDuration);
|
||||
contentSizeUpdated();
|
||||
}
|
||||
|
||||
void InfoWidget::restoreState(const SectionMemento *memento) {
|
||||
if (!memento->getCommonGroups().isEmpty()) {
|
||||
onForceHideCommonGroups();
|
||||
|
@ -152,7 +156,7 @@ int InfoWidget::resizeGetHeight(int newWidth) {
|
|||
}
|
||||
|
||||
newHeight += st::profileBlockMarginBottom;
|
||||
return _height.animating() ? _height.current() : newHeight;
|
||||
return qRound(_height.current(newHeight));
|
||||
}
|
||||
|
||||
void InfoWidget::leaveEvent(QEvent *e) {
|
||||
|
@ -258,8 +262,7 @@ void InfoWidget::refreshCommonGroups() {
|
|||
_commonGroups->setClickedCallback([this] { onShowCommonGroups(); });
|
||||
_commonGroups->hide();
|
||||
if (_showFinished) {
|
||||
_height.start([this] { contentSizeUpdated(); }, isHidden() ? 0 : height(), resizeGetHeight(width()), st::widgetSlideDuration);
|
||||
contentSizeUpdated();
|
||||
slideCommonGroupsDown();
|
||||
}
|
||||
}
|
||||
} else if (_commonGroups) {
|
||||
|
|
|
@ -68,6 +68,7 @@ private:
|
|||
int getCommonGroupsCount() const;
|
||||
void onForceHideCommonGroups();
|
||||
void onShowCommonGroups();
|
||||
void slideCommonGroupsDown();
|
||||
|
||||
// labelWidget may be nullptr.
|
||||
void setLabeledText(ChildWidget<Ui::FlatLabel> *labelWidget, const QString &label,
|
||||
|
@ -83,7 +84,7 @@ private:
|
|||
ChildWidget<Ui::FlatLabel> _username = { nullptr };
|
||||
ChildWidget<Ui::LeftOutlineButton> _commonGroups = { nullptr };
|
||||
|
||||
IntAnimation _height;
|
||||
FloatAnimation _height;
|
||||
bool _showFinished = false;
|
||||
|
||||
bool _forceHiddenCommonGroups = false;
|
||||
|
|
|
@ -21,11 +21,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "stdafx.h"
|
||||
#include "profile/profile_block_peer_list.h"
|
||||
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
namespace Profile {
|
||||
|
||||
PeerListWidget::Item::Item(PeerData *peer) : peer(peer) {
|
||||
}
|
||||
|
||||
PeerListWidget::Item::~Item() = default;
|
||||
|
||||
PeerListWidget::PeerListWidget(QWidget *parent, PeerData *peer, const QString &title, const QString &removeText)
|
||||
: BlockWidget(parent, peer, title)
|
||||
, _removeText(removeText)
|
||||
|
@ -54,38 +60,39 @@ void PeerListWidget::setVisibleTopBottom(int visibleTop, int visibleBottom) {
|
|||
}
|
||||
|
||||
void PeerListWidget::paintContents(Painter &p) {
|
||||
int left = getListLeft();
|
||||
int top = getListTop();
|
||||
int memberRowWidth = width() - left;
|
||||
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
|
||||
auto ms = getms();
|
||||
auto left = getListLeft();
|
||||
auto top = getListTop();
|
||||
auto memberRowWidth = rowWidth();
|
||||
|
||||
int from = floorclamp(_visibleTop - top, st::profileMemberHeight, 0, _items.size());
|
||||
int to = ceilclamp(_visibleBottom - top, st::profileMemberHeight, 0, _items.size());
|
||||
for (int i = from; i < to; ++i) {
|
||||
int y = top + i * st::profileMemberHeight;
|
||||
bool selected = (i == _selected);
|
||||
bool selectedRemove = selected && _selectedRemove;
|
||||
if (_pressed >= 0) {
|
||||
if (_pressed != _selected) {
|
||||
selected = selectedRemove = false;
|
||||
} else if (!_pressedRemove) {
|
||||
_selectedRemove = false;
|
||||
}
|
||||
auto from = floorclamp(_visibleTop - top, st::profileMemberHeight, 0, _items.size());
|
||||
auto to = ceilclamp(_visibleBottom - top, st::profileMemberHeight, 0, _items.size());
|
||||
for (auto i = from; i < to; ++i) {
|
||||
auto y = top + i * st::profileMemberHeight;
|
||||
auto selected = (_pressed >= 0) ? (i == _pressed) : (i == _selected);
|
||||
auto selectedRemove = selected && _selectedRemove;
|
||||
if (_pressed >= 0 && !_pressedRemove) {
|
||||
selectedRemove = false;
|
||||
}
|
||||
paintItem(p, left, y, _items[i], selected, selectedRemove);
|
||||
paintItem(p, left, y, _items[i], selected, selectedRemove, ms);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListWidget::paintItem(Painter &p, int x, int y, Item *item, bool selected, bool selectedKick) {
|
||||
void PeerListWidget::paintItem(Painter &p, int x, int y, Item *item, bool selected, bool selectedKick, TimeMs ms) {
|
||||
if (_updateItemCallback) {
|
||||
_updateItemCallback(item);
|
||||
}
|
||||
|
||||
int memberRowWidth = width() - x;
|
||||
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
|
||||
auto memberRowWidth = rowWidth();
|
||||
if (selected) {
|
||||
paintOutlinedRect(p, x, y, memberRowWidth, st::profileMemberHeight);
|
||||
}
|
||||
if (auto &ripple = item->ripple) {
|
||||
ripple->paint(p, x + st::defaultLeftOutlineButton.outlineWidth, y, width(), ms);
|
||||
if (ripple->empty()) {
|
||||
ripple.reset();
|
||||
}
|
||||
}
|
||||
int skip = st::profileMemberPhotoPosition.x();
|
||||
|
||||
item->peer->paintUserpicLeft(p, st::profileMemberPhotoSize, x + st::profileMemberPhotoPosition.x(), y + st::profileMemberPhotoPosition.y(), width());
|
||||
|
@ -136,19 +143,36 @@ void PeerListWidget::mousePressEvent(QMouseEvent *e) {
|
|||
|
||||
_pressed = _selected;
|
||||
_pressedRemove = _selectedRemove;
|
||||
if (_pressed >= 0 && !_pressedRemove) {
|
||||
auto item = _items[_pressed];
|
||||
if (!item->ripple) {
|
||||
auto memberRowWidth = rowWidth();
|
||||
auto mask = Ui::RippleAnimation::rectMask(QSize(memberRowWidth - st::defaultLeftOutlineButton.outlineWidth, st::profileMemberHeight));
|
||||
item->ripple = std_::make_unique<Ui::RippleAnimation>(st::defaultLeftOutlineButton.ripple, std_::move(mask), [this, index = _pressed] {
|
||||
repaintRow(index);
|
||||
});
|
||||
}
|
||||
auto left = getListLeft() + st::defaultLeftOutlineButton.outlineWidth;
|
||||
auto top = getListTop() + st::profileMemberHeight * _pressed;
|
||||
item->ripple->add(e->pos() - QPoint(left, top));
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_mousePosition = e->globalPos();
|
||||
updateSelection();
|
||||
|
||||
auto pressed = _pressed;
|
||||
auto pressedRemove = _pressedRemove;
|
||||
_pressed = -1;
|
||||
_pressedRemove = false;
|
||||
if (pressed >= 0 && pressed < _items.size() && pressed == _selected && pressedRemove == _selectedRemove) {
|
||||
if (auto &callback = (pressedRemove ? _removedCallback : _selectedCallback)) {
|
||||
callback(_items[pressed]->peer);
|
||||
repaintRow(_pressed);
|
||||
auto pressed = base::take(_pressed, -1);
|
||||
auto pressedRemove = base::take(_pressedRemove);
|
||||
if (pressed >= 0 && pressed < _items.size()) {
|
||||
if (auto &ripple = _items[pressed]->ripple) {
|
||||
ripple->lastStop();
|
||||
}
|
||||
if (pressed == _selected && pressedRemove == _selectedRemove) {
|
||||
if (auto &callback = (pressedRemove ? _removedCallback : _selectedCallback)) {
|
||||
callback(_items[pressed]->peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
setCursor(_selectedRemove ? style::cur_pointer : style::cur_default);
|
||||
|
@ -166,15 +190,14 @@ void PeerListWidget::leaveEvent(QEvent *e) {
|
|||
}
|
||||
|
||||
void PeerListWidget::updateSelection() {
|
||||
int selected = -1;
|
||||
bool selectedKick = false;
|
||||
auto selected = -1;
|
||||
auto selectedKick = false;
|
||||
|
||||
auto mouse = mapFromGlobal(_mousePosition);
|
||||
if (rtl()) mouse.setX(width() - mouse.x());
|
||||
int left = getListLeft();
|
||||
int top = getListTop();
|
||||
int memberRowWidth = width() - left;
|
||||
accumulate_min(memberRowWidth, st::profileBlockWideWidthMax);
|
||||
auto left = getListLeft();
|
||||
auto top = getListTop();
|
||||
auto memberRowWidth = rowWidth();
|
||||
if (mouse.x() >= left && mouse.x() < left + memberRowWidth && mouse.y() >= top) {
|
||||
selected = (mouse.y() - top) / st::profileMemberHeight;
|
||||
if (selected >= _items.size()) {
|
||||
|
@ -214,9 +237,13 @@ void PeerListWidget::setSelected(int selected, bool selectedRemove) {
|
|||
}
|
||||
|
||||
void PeerListWidget::repaintSelectedRow() {
|
||||
if (_selected >= 0) {
|
||||
int left = getListLeft();
|
||||
rtlupdate(left, getListTop() + _selected * st::profileMemberHeight, width() - left, st::profileMemberHeight);
|
||||
repaintRow(_selected);
|
||||
}
|
||||
|
||||
void PeerListWidget::repaintRow(int index) {
|
||||
if (index >= 0) {
|
||||
auto left = getListLeft();
|
||||
rtlupdate(left, getListTop() + index * st::profileMemberHeight, width() - left, st::profileMemberHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,6 +251,10 @@ int PeerListWidget::getListLeft() const {
|
|||
return st::profileBlockTitlePosition.x() - st::profileMemberPaddingLeft;
|
||||
}
|
||||
|
||||
int PeerListWidget::rowWidth() const {
|
||||
return qMin(width() - getListLeft(), st::profileBlockWideWidthMax);
|
||||
}
|
||||
|
||||
void PeerListWidget::preloadPhotos() {
|
||||
int top = getListTop();
|
||||
int preloadFor = (_visibleBottom - _visibleTop) * PreloadHeightsCount;
|
||||
|
|
|
@ -22,6 +22,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "profile/profile_block_widget.h"
|
||||
|
||||
namespace Ui {
|
||||
class RippleAnimation;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Notify {
|
||||
struct PeerUpdate;
|
||||
} // namespace Notify
|
||||
|
@ -35,14 +39,16 @@ public:
|
|||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
|
||||
struct Item {
|
||||
explicit Item(PeerData *peer) : peer(peer) {
|
||||
}
|
||||
explicit Item(PeerData *peer);
|
||||
~Item();
|
||||
|
||||
PeerData * const peer;
|
||||
Text name;
|
||||
QString statusText;
|
||||
bool statusHasOnlineColor = false;
|
||||
bool hasAdminStar = false;
|
||||
bool hasRemoveLink = false;
|
||||
std_::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
};
|
||||
virtual int getListTop() const {
|
||||
return contentTop();
|
||||
|
@ -111,9 +117,11 @@ private:
|
|||
void updateSelection();
|
||||
void setSelected(int selected, bool selectedRemove);
|
||||
void repaintSelectedRow();
|
||||
void repaintRow(int index);
|
||||
void preloadPhotos();
|
||||
int rowWidth() const;
|
||||
|
||||
void paintItem(Painter &p, int x, int y, Item *item, bool selected, bool selectedRemove);
|
||||
void paintItem(Painter &p, int x, int y, Item *item, bool selected, bool selectedRemove, TimeMs ms);
|
||||
|
||||
base::lambda<void()> _preloadMoreCallback;
|
||||
base::lambda<void(PeerData*)> _selectedCallback;
|
||||
|
|
|
@ -60,8 +60,8 @@ protected:
|
|||
|
||||
Window::TopBarWidget::paintUnreadCounter(p, width());
|
||||
}
|
||||
void onStateChanged(int oldState, StateChangeSource source) override {
|
||||
if ((_state & StateDown) && !(oldState & StateDown)) {
|
||||
void onStateChanged(State was, StateChangeSource source) override {
|
||||
if (isDown() && !(was & StateFlag::Down)) {
|
||||
emit clicked();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ void EmojiColorPicker::step_appearance(float64 ms, bool timer) {
|
|||
void EmojiColorPicker::hideFast() {
|
||||
clearSelection();
|
||||
if (_a_appearance.animating()) _a_appearance.stop();
|
||||
a_opacity = anim::fvalue(0);
|
||||
a_opacity = anim::value();
|
||||
_cache = QPixmap();
|
||||
hide();
|
||||
emit hidden();
|
||||
|
@ -2899,7 +2899,9 @@ void EmojiPan::paintContent(Painter &p) {
|
|||
paintStickerSettingsIcon(p);
|
||||
|
||||
if (!_icons.isEmpty()) {
|
||||
int x = _iconsLeft, selxrel = _iconsLeft + _iconSelX.current(), selx = selxrel - _iconsX.current();
|
||||
auto x = _iconsLeft;
|
||||
auto selxrel = _iconsLeft + qRound(_iconSelX.current());
|
||||
auto selx = selxrel - qRound(_iconsX.current());
|
||||
|
||||
QRect clip(x, _iconsTop, _iconsLeft + 7 * st::emojiCategory.width - x, st::emojiCategory.height);
|
||||
if (rtl()) clip.moveLeft(width() - x - clip.width());
|
||||
|
@ -2915,9 +2917,10 @@ void EmojiPan::paintContent(Painter &p) {
|
|||
};
|
||||
|
||||
int i = 0;
|
||||
i += _iconsX.current() / int(st::emojiCategory.width);
|
||||
x -= _iconsX.current() % int(st::emojiCategory.width);
|
||||
selxrel -= _iconsX.current();
|
||||
auto iconsX = qRound(_iconsX.current());
|
||||
i += iconsX / int(st::emojiCategory.width);
|
||||
x -= iconsX % int(st::emojiCategory.width);
|
||||
selxrel -= iconsX;
|
||||
for (int l = qMin(_icons.size(), i + 8); i < l; ++i) {
|
||||
auto &s = _icons.at(i);
|
||||
if (s.sticker) {
|
||||
|
@ -2938,13 +2941,13 @@ void EmojiPan::paintContent(Painter &p) {
|
|||
if (rtl()) selx = width() - selx - st::emojiCategory.width;
|
||||
p.fillRect(selx, _iconsTop + st::emojiCategory.height - st::stickerIconPadding, st::emojiCategory.width, st::stickerIconSel, st::stickerIconSelColor);
|
||||
|
||||
float64 o_left = snap(float64(_iconsX.current()) / st::stickerIconLeft.width(), 0., 1.);
|
||||
auto o_left = snap(_iconsX.current() / st::stickerIconLeft.width(), 0., 1.);
|
||||
if (o_left > 0) {
|
||||
p.setOpacity(o_left);
|
||||
st::stickerIconLeft.fill(p, rtlrect(_iconsLeft, _iconsTop, st::stickerIconLeft.width(), st::emojiCategory.height, width()));
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
float64 o_right = snap(float64(_iconsMax - _iconsX.current()) / st::stickerIconRight.width(), 0., 1.);
|
||||
auto o_right = snap((_iconsMax - _iconsX.current()) / st::stickerIconRight.width(), 0., 1.);
|
||||
if (o_right > 0) {
|
||||
p.setOpacity(o_right);
|
||||
st::stickerIconRight.fill(p, rtlrect(_iconsLeft + 7 * st::emojiCategory.width - st::stickerIconRight.width(), _iconsTop, st::stickerIconRight.width(), st::emojiCategory.height, width()));
|
||||
|
@ -3019,7 +3022,7 @@ void EmojiPan::mousePressEvent(QMouseEvent *e) {
|
|||
} else {
|
||||
_iconDown = _iconOver;
|
||||
_iconsMouseDown = _iconsMousePos;
|
||||
_iconsStartX = _iconsX.current();
|
||||
_iconsStartX = qRound(_iconsX.current());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3034,9 +3037,9 @@ void EmojiPan::mouseMoveEvent(QMouseEvent *e) {
|
|||
}
|
||||
}
|
||||
if (_iconsDragging) {
|
||||
int32 newX = snap(_iconsStartX + (rtl() ? -1 : 1) * (_iconsMouseDown.x() - _iconsMousePos.x()), 0, _iconsMax);
|
||||
if (newX != _iconsX.current()) {
|
||||
_iconsX = anim::ivalue(newX, newX);
|
||||
auto newX = snap(_iconsStartX + (rtl() ? -1 : 1) * (_iconsMouseDown.x() - _iconsMousePos.x()), 0, _iconsMax);
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
updateIcons();
|
||||
|
@ -3052,9 +3055,9 @@ void EmojiPan::mouseReleaseEvent(QMouseEvent *e) {
|
|||
|
||||
_iconsMousePos = e ? e->globalPos() : QCursor::pos();
|
||||
if (_iconsDragging) {
|
||||
int32 newX = snap(_iconsStartX + _iconsMouseDown.x() - _iconsMousePos.x(), 0, _iconsMax);
|
||||
if (newX != _iconsX.current()) {
|
||||
_iconsX = anim::ivalue(newX, newX);
|
||||
auto newX = snap(_iconsStartX + _iconsMouseDown.x() - _iconsMousePos.x(), 0, _iconsMax);
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
updateIcons();
|
||||
|
@ -3065,7 +3068,7 @@ void EmojiPan::mouseReleaseEvent(QMouseEvent *e) {
|
|||
updateSelected();
|
||||
|
||||
if (wasDown == _iconOver && _iconOver >= 0 && _iconOver < _icons.size()) {
|
||||
_iconSelX = anim::ivalue(_iconOver * st::emojiCategory.width, _iconOver * st::emojiCategory.width);
|
||||
_iconSelX = anim::value(_iconOver * st::emojiCategory.width, _iconOver * st::emojiCategory.width);
|
||||
s_inner->showStickerSet(_icons.at(_iconOver).setId);
|
||||
}
|
||||
}
|
||||
|
@ -3080,14 +3083,14 @@ bool EmojiPan::event(QEvent *e) {
|
|||
bool hor = (ev->angleDelta().x() != 0 || ev->orientation() == Qt::Horizontal);
|
||||
bool ver = (ev->angleDelta().y() != 0 || ev->orientation() == Qt::Vertical);
|
||||
if (hor) _horizontal = true;
|
||||
int32 newX = _iconsX.current();
|
||||
auto newX = qRound(_iconsX.current());
|
||||
if (/*_horizontal && */hor) {
|
||||
newX = snap(newX - (rtl() ? -1 : 1) * (ev->pixelDelta().x() ? ev->pixelDelta().x() : ev->angleDelta().x()), 0, _iconsMax);
|
||||
} else if (/*!_horizontal && */ver) {
|
||||
newX = snap(newX - (ev->pixelDelta().y() ? ev->pixelDelta().y() : ev->angleDelta().y()), 0, _iconsMax);
|
||||
}
|
||||
if (newX != _iconsX.current()) {
|
||||
_iconsX = anim::ivalue(newX, newX);
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
updateSelected();
|
||||
|
@ -3138,7 +3141,7 @@ void EmojiPan::onRefreshIcons(bool scrollAnimation) {
|
|||
_iconsMax = qMax(int((_icons.size() - 7) * st::emojiCategory.width), 0);
|
||||
}
|
||||
if (_iconsX.current() > _iconsMax) {
|
||||
_iconsX = anim::ivalue(_iconsMax, _iconsMax);
|
||||
_iconsX = anim::value(_iconsMax, _iconsMax);
|
||||
}
|
||||
updatePanelsPositions(s_panels, s_scroll->scrollTop());
|
||||
updateSelected();
|
||||
|
@ -3178,7 +3181,7 @@ void EmojiPan::updateSelected() {
|
|||
newOver = _icons.size();
|
||||
} else if (!_icons.isEmpty()) {
|
||||
if (y >= _iconsTop && y < _iconsTop + st::emojiCategory.height && x >= 0 && x < 7 * st::emojiCategory.width && x < _icons.size() * st::emojiCategory.width) {
|
||||
x += _iconsX.current();
|
||||
x += qRound(_iconsX.current());
|
||||
newOver = qFloor(x / st::emojiCategory.width);
|
||||
}
|
||||
}
|
||||
|
@ -3329,8 +3332,8 @@ void EmojiPan::hideFinished() {
|
|||
s_scroll->scrollToY(0);
|
||||
_iconOver = _iconDown = -1;
|
||||
_iconSel = 0;
|
||||
_iconsX = anim::ivalue(0, 0);
|
||||
_iconSelX = anim::ivalue(0, 0);
|
||||
_iconsX = anim::value();
|
||||
_iconSelX = anim::value();
|
||||
_iconsStartAnim = 0;
|
||||
_a_icons.stop();
|
||||
|
||||
|
@ -3512,14 +3515,14 @@ void EmojiPan::onScrollEmoji() {
|
|||
}
|
||||
|
||||
void EmojiPan::setCurrentTabIcon(DBIEmojiTab tab) {
|
||||
_recent->setIcon((tab == dbietRecent) ? &st::emojiRecentActive : nullptr);
|
||||
_people->setIcon((tab == dbietPeople) ? &st::emojiPeopleActive : nullptr);
|
||||
_nature->setIcon((tab == dbietNature) ? &st::emojiNatureActive : nullptr);
|
||||
_food->setIcon((tab == dbietFood) ? &st::emojiFoodActive : nullptr);
|
||||
_activity->setIcon((tab == dbietActivity) ? &st::emojiActivityActive : nullptr);
|
||||
_travel->setIcon((tab == dbietTravel) ? &st::emojiTravelActive : nullptr);
|
||||
_objects->setIcon((tab == dbietObjects) ? &st::emojiObjectsActive : nullptr);
|
||||
_symbols->setIcon((tab == dbietSymbols) ? &st::emojiSymbolsActive : nullptr);
|
||||
_recent->setIconOverride((tab == dbietRecent) ? &st::emojiRecentActive : nullptr);
|
||||
_people->setIconOverride((tab == dbietPeople) ? &st::emojiPeopleActive : nullptr);
|
||||
_nature->setIconOverride((tab == dbietNature) ? &st::emojiNatureActive : nullptr);
|
||||
_food->setIconOverride((tab == dbietFood) ? &st::emojiFoodActive : nullptr);
|
||||
_activity->setIconOverride((tab == dbietActivity) ? &st::emojiActivityActive : nullptr);
|
||||
_travel->setIconOverride((tab == dbietTravel) ? &st::emojiTravelActive : nullptr);
|
||||
_objects->setIconOverride((tab == dbietObjects) ? &st::emojiObjectsActive : nullptr);
|
||||
_symbols->setIconOverride((tab == dbietSymbols) ? &st::emojiSymbolsActive : nullptr);
|
||||
}
|
||||
|
||||
void EmojiPan::onScrollStickers() {
|
||||
|
@ -3550,11 +3553,11 @@ void EmojiPan::validateSelectedIcon(ValidateIconAnimations animations) {
|
|||
if (animations == ValidateIconAnimations::Full) {
|
||||
_iconSelX.start(iconSelXFinal);
|
||||
} else {
|
||||
_iconSelX = anim::ivalue(iconSelXFinal, iconSelXFinal);
|
||||
_iconSelX = anim::value(iconSelXFinal, iconSelXFinal);
|
||||
}
|
||||
auto iconsXFinal = snap((2 * newSel - 7) * int(st::emojiCategory.width) / 2, 0, _iconsMax);
|
||||
if (animations == ValidateIconAnimations::None) {
|
||||
_iconsX = anim::ivalue(iconsXFinal, iconsXFinal);
|
||||
_iconsX = anim::value(iconsXFinal, iconsXFinal);
|
||||
_a_icons.stop();
|
||||
} else {
|
||||
_iconsX.start(iconsXFinal);
|
||||
|
|
|
@ -108,7 +108,7 @@ private:
|
|||
bool _hiding = false;
|
||||
QPixmap _cache;
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
anim::value a_opacity;
|
||||
Animation _a_appearance;
|
||||
|
||||
QTimer _hideTimer;
|
||||
|
@ -661,8 +661,8 @@ private:
|
|||
int _iconsTop = 0;
|
||||
int _iconsStartX = 0;
|
||||
int _iconsMax = 0;
|
||||
anim::ivalue _iconsX = { 0, 0 };
|
||||
anim::ivalue _iconSelX = { 0, 0 };
|
||||
anim::value _iconsX;
|
||||
anim::value _iconSelX;
|
||||
TimeMs _iconsStartAnim = 0;
|
||||
|
||||
bool _emojiShown = true;
|
||||
|
|
|
@ -190,4 +190,10 @@ hashtagClose: IconButton {
|
|||
icon: simpleCloseIcon;
|
||||
iconOver: simpleCloseIconOver;
|
||||
iconPosition: point(10px, 10px);
|
||||
|
||||
rippleAreaPosition: point(5px, 5px);
|
||||
rippleAreaSize: 20px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,15 +24,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
namespace Ui {
|
||||
|
||||
void AbstractButton::leaveEvent(QEvent *e) {
|
||||
if (_state & StateDown) return;
|
||||
if (_state & StateFlag::Down) return;
|
||||
|
||||
setOver(false, StateChangeSource::ByHover);
|
||||
return TWidget::leaveEvent(e);
|
||||
}
|
||||
|
||||
void AbstractButton::enterEvent(QEvent *e) {
|
||||
auto over = rect().marginsRemoved(getMargins()).contains(mapFromGlobal(QCursor::pos()));
|
||||
setOver(over, StateChangeSource::ByHover);
|
||||
checkIfOver(mapFromGlobal(QCursor::pos()));
|
||||
return TWidget::enterEvent(e);
|
||||
}
|
||||
|
||||
|
@ -40,12 +39,18 @@ void AbstractButton::setAcceptBoth(bool acceptBoth) {
|
|||
_acceptBoth = acceptBoth;
|
||||
}
|
||||
|
||||
void AbstractButton::checkIfOver(QPoint localPos) {
|
||||
auto over = rect().marginsRemoved(getMargins()).contains(localPos);
|
||||
setOver(over, StateChangeSource::ByHover);
|
||||
}
|
||||
|
||||
void AbstractButton::mousePressEvent(QMouseEvent *e) {
|
||||
checkIfOver(e->pos());
|
||||
if (_acceptBoth || (e->buttons() & Qt::LeftButton)) {
|
||||
if ((_state & StateOver) && !(_state & StateDown)) {
|
||||
int oldState = _state;
|
||||
_state |= StateDown;
|
||||
onStateChanged(oldState, StateChangeSource::ByPress);
|
||||
if ((_state & StateFlag::Over) && !(_state & StateFlag::Down)) {
|
||||
auto was = _state;
|
||||
_state |= StateFlag::Down;
|
||||
onStateChanged(was, StateChangeSource::ByPress);
|
||||
|
||||
e->accept();
|
||||
}
|
||||
|
@ -61,11 +66,11 @@ void AbstractButton::mouseMoveEvent(QMouseEvent *e) {
|
|||
}
|
||||
|
||||
void AbstractButton::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (_state & StateDown) {
|
||||
int oldState = _state;
|
||||
_state &= ~StateDown;
|
||||
onStateChanged(oldState, StateChangeSource::ByPress);
|
||||
if (oldState & StateOver) {
|
||||
if (_state & StateFlag::Down) {
|
||||
auto was = _state;
|
||||
_state &= ~State(StateFlag::Down);
|
||||
onStateChanged(was, StateChangeSource::ByPress);
|
||||
if (was & StateFlag::Over) {
|
||||
_modifiers = e->modifiers();
|
||||
if (_clickedCallback) {
|
||||
_clickedCallback();
|
||||
|
@ -73,43 +78,39 @@ void AbstractButton::mouseReleaseEvent(QMouseEvent *e) {
|
|||
emit clicked();
|
||||
}
|
||||
} else {
|
||||
leaveEvent(e);
|
||||
setOver(false, StateChangeSource::ByHover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractButton::setOver(bool over, StateChangeSource source) {
|
||||
setCursor(over ? style::cur_pointer : style::cur_default);
|
||||
if (over && !(_state & StateOver)) {
|
||||
int oldState = _state;
|
||||
_state |= StateOver;
|
||||
onStateChanged(oldState, source);
|
||||
} else if (!over && (_state & StateOver)) {
|
||||
int oldState = _state;
|
||||
_state &= ~StateOver;
|
||||
onStateChanged(oldState, source);
|
||||
if (over && !(_state & StateFlag::Over)) {
|
||||
auto was = _state;
|
||||
_state |= StateFlag::Over;
|
||||
onStateChanged(was, source);
|
||||
} else if (!over && (_state & StateFlag::Over)) {
|
||||
auto was = _state;
|
||||
_state &= ~State(StateFlag::Over);
|
||||
onStateChanged(was, source);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractButton::setDisabled(bool disabled) {
|
||||
int oldState = _state;
|
||||
if (disabled && !(_state & StateDisabled)) {
|
||||
_state |= StateDisabled;
|
||||
onStateChanged(oldState, StateChangeSource::ByUser);
|
||||
} else if (!disabled && (_state & StateDisabled)) {
|
||||
_state &= ~StateDisabled;
|
||||
onStateChanged(oldState, StateChangeSource::ByUser);
|
||||
auto was = _state;
|
||||
if (disabled && !(_state & StateFlag::Disabled)) {
|
||||
_state |= StateFlag::Disabled;
|
||||
onStateChanged(was, StateChangeSource::ByUser);
|
||||
} else if (!disabled && (_state & StateFlag::Disabled)) {
|
||||
_state &= ~State(StateFlag::Disabled);
|
||||
onStateChanged(was, StateChangeSource::ByUser);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractButton::clearState() {
|
||||
int oldState = _state;
|
||||
_state = StateNone;
|
||||
onStateChanged(oldState, StateChangeSource::ByUser);
|
||||
}
|
||||
|
||||
int AbstractButton::getState() const {
|
||||
return _state;
|
||||
auto was = _state;
|
||||
_state = StateFlag::None;
|
||||
onStateChanged(was, StateChangeSource::ByUser);
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -28,34 +28,24 @@ class AbstractButton : public TWidget {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class StateChangeSource {
|
||||
ByUser = 0x00,
|
||||
ByPress = 0x01,
|
||||
ByHover = 0x02,
|
||||
};
|
||||
|
||||
AbstractButton(QWidget *parent) : TWidget(parent) {
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
enum {
|
||||
StateNone = 0x00,
|
||||
StateOver = 0x01,
|
||||
StateDown = 0x02,
|
||||
StateDisabled = 0x04,
|
||||
};
|
||||
|
||||
Qt::KeyboardModifiers clickModifiers() const {
|
||||
return _modifiers;
|
||||
}
|
||||
|
||||
void clearState();
|
||||
int getState() const;
|
||||
|
||||
void setDisabled(bool disabled = true);
|
||||
void setOver(bool over, StateChangeSource source = StateChangeSource::ByUser);
|
||||
bool disabled() const {
|
||||
return (_state & StateDisabled);
|
||||
void clearState();
|
||||
bool isOver() const {
|
||||
return _state & StateFlag::Over;
|
||||
}
|
||||
bool isDown() const {
|
||||
return _state & StateFlag::Down;
|
||||
}
|
||||
bool isDisabled() {
|
||||
return _state & StateFlag::Disabled;
|
||||
}
|
||||
|
||||
void setAcceptBoth(bool acceptBoth = true);
|
||||
|
@ -75,15 +65,41 @@ signals:
|
|||
void clicked();
|
||||
|
||||
protected:
|
||||
virtual void onStateChanged(int oldState, StateChangeSource source) {
|
||||
enum class StateFlag {
|
||||
None = 0x00,
|
||||
Over = 0x01,
|
||||
Down = 0x02,
|
||||
Disabled = 0x04,
|
||||
};
|
||||
Q_DECLARE_FLAGS(State, StateFlag);
|
||||
Q_DECLARE_FRIEND_OPERATORS_FOR_FLAGS(State);
|
||||
|
||||
State state() const {
|
||||
return _state;
|
||||
}
|
||||
|
||||
Qt::KeyboardModifiers _modifiers;
|
||||
int _state = StateNone;
|
||||
enum class StateChangeSource {
|
||||
ByUser = 0x00,
|
||||
ByPress = 0x01,
|
||||
ByHover = 0x02,
|
||||
};
|
||||
void setOver(bool over, StateChangeSource source = StateChangeSource::ByUser);
|
||||
|
||||
virtual void onStateChanged(State was, StateChangeSource source) {
|
||||
}
|
||||
|
||||
private:
|
||||
void checkIfOver(QPoint localPos);
|
||||
|
||||
State _state = StateFlag::None;
|
||||
|
||||
bool _acceptBoth = false;
|
||||
Qt::KeyboardModifiers _modifiers;
|
||||
|
||||
base::lambda<void()> _clickedCallback;
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractButton::State);
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -158,56 +158,6 @@ private:
|
|||
|
||||
};
|
||||
|
||||
using fvalue = value;
|
||||
|
||||
class ivalue { // int animated value
|
||||
public:
|
||||
using ValueType = int;
|
||||
|
||||
ivalue() = default;
|
||||
ivalue(int from) : _cur(from), _from(float64(from)) {
|
||||
}
|
||||
ivalue(int from, int to) : _cur(from), _from(float64(from)), _delta(float64(to - from)) {
|
||||
}
|
||||
void start(int32 to) {
|
||||
_from = float64(_cur);
|
||||
_delta = float64(to) - _from;
|
||||
}
|
||||
void restart() {
|
||||
_delta = _from + _delta - float64(_cur);
|
||||
_from = float64(_cur);
|
||||
}
|
||||
|
||||
int from() const {
|
||||
return _from;
|
||||
}
|
||||
int current() const {
|
||||
return _cur;
|
||||
}
|
||||
int to() const {
|
||||
return qRound(_from + _delta);
|
||||
}
|
||||
void add(int delta) {
|
||||
_from += delta;
|
||||
_cur += delta;
|
||||
}
|
||||
ivalue &update(float64 dt, const transition &func) {
|
||||
_cur = qRound(_from + func(_delta, dt));
|
||||
return *this;
|
||||
}
|
||||
void finish() {
|
||||
_cur = qRound(_from + _delta);
|
||||
_from = _cur;
|
||||
_delta = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int _cur = 0;
|
||||
float64 _from = 0.;
|
||||
float64 _delta = 0.;
|
||||
|
||||
};
|
||||
|
||||
void startManager();
|
||||
void stopManager();
|
||||
void registerClipManager(Media::Clip::Manager *manager);
|
||||
|
@ -639,7 +589,9 @@ public:
|
|||
|
||||
template <typename Lambda>
|
||||
void start(Lambda &&updateCallback, const ValueType &from, const ValueType &to, float64 duration, const anim::transition &transition = anim::linear) {
|
||||
if (!_data) {
|
||||
if (_data) {
|
||||
_data->pause.restart();
|
||||
} else {
|
||||
_data = std_::make_unique<Data>(from, std_::forward<Lambda>(updateCallback));
|
||||
}
|
||||
_data->value.start(to);
|
||||
|
@ -674,6 +626,7 @@ private:
|
|||
if (dt >= 1) {
|
||||
value.finish();
|
||||
a_animation.stop();
|
||||
pause.release();
|
||||
} else {
|
||||
value.update(dt, transition);
|
||||
}
|
||||
|
@ -685,13 +638,13 @@ private:
|
|||
Callback updateCallback;
|
||||
float64 duration = 0.;
|
||||
anim::transition transition = anim::linear;
|
||||
MTP::PauseHolder pause;
|
||||
};
|
||||
mutable std_::unique_ptr<Data> _data;
|
||||
|
||||
};
|
||||
|
||||
using FloatAnimation = SimpleAnimation<anim::fvalue>;
|
||||
using IntAnimation = SimpleAnimation<anim::ivalue>;
|
||||
using FloatAnimation = SimpleAnimation<anim::value>;
|
||||
|
||||
class AnimationManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -55,8 +55,8 @@ void HistoryDownButton::paintEvent(QPaintEvent *e) {
|
|||
return;
|
||||
}
|
||||
p.setOpacity(opacity);
|
||||
auto over = (_state & StateOver);
|
||||
auto down = (_state & StateDown);
|
||||
auto over = isOver();
|
||||
auto down = isDown();
|
||||
((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||
|
@ -118,7 +118,7 @@ void HistoryDownButton::step_arrowOver(float64 ms, bool timer) {
|
|||
if (timer) update();
|
||||
}
|
||||
|
||||
EmojiButton::EmojiButton(QWidget *parent, const style::IconButton &st) : AbstractButton(parent)
|
||||
EmojiButton::EmojiButton(QWidget *parent, const style::IconButton &st) : RippleButton(parent, st.ripple)
|
||||
, _st(st)
|
||||
, _a_loading(animation(this, &EmojiButton::step_loading)) {
|
||||
resize(_st.width, _st.height);
|
||||
|
@ -131,11 +131,12 @@ void EmojiButton::paintEvent(QPaintEvent *e) {
|
|||
auto ms = getms();
|
||||
|
||||
p.fillRect(e->rect(), st::historyComposeAreaBg);
|
||||
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
|
||||
auto loading = a_loading.current(ms, _loading ? 1 : 0);
|
||||
p.setOpacity(1 - loading);
|
||||
|
||||
auto over = (_state & StateOver);
|
||||
auto over = isOver();
|
||||
auto icon = &(over ? _st.iconOver : _st.icon);
|
||||
icon->paint(p, _st.iconPosition, width());
|
||||
|
||||
|
@ -170,11 +171,20 @@ void EmojiButton::setLoading(bool loading) {
|
|||
}
|
||||
}
|
||||
|
||||
void EmojiButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||
auto over = (_state & StateOver);
|
||||
if (over != (oldState & StateOver)) {
|
||||
void EmojiButton::onStateChanged(State was, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
auto wasOver = static_cast<bool>(was & StateFlag::Over);
|
||||
if (isOver() != wasOver) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
QPoint EmojiButton::prepareRippleStartPosition() const {
|
||||
return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||
}
|
||||
|
||||
QImage EmojiButton::prepareRippleMask() const {
|
||||
return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -55,7 +55,7 @@ private:
|
|||
|
||||
bool _shown = false;
|
||||
|
||||
anim::fvalue a_arrowOpacity;
|
||||
anim::value a_arrowOpacity;
|
||||
Animation _a_arrowOver;
|
||||
|
||||
FloatAnimation _a_show;
|
||||
|
@ -64,7 +64,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class EmojiButton : public AbstractButton {
|
||||
class EmojiButton : public RippleButton {
|
||||
public:
|
||||
EmojiButton(QWidget *parent, const style::IconButton &st);
|
||||
|
||||
|
@ -72,7 +72,10 @@ public:
|
|||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
QPoint prepareRippleStartPosition() const override;
|
||||
|
||||
private:
|
||||
const style::IconButton &_st;
|
||||
|
|
|
@ -54,7 +54,7 @@ void NewAvatarButton::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush((_state & StateOver) ? st::defaultActiveButton.textBgOver : st::defaultActiveButton.textBg);
|
||||
p.setBrush(isOver() ? st::defaultActiveButton.textBgOver : st::defaultActiveButton.textBg);
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawEllipse(rect());
|
||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "application.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/multi_select.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "countries.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -283,6 +284,7 @@ void CountrySelectBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
QRect r(e->rect());
|
||||
p.setClipRect(r);
|
||||
|
||||
auto ms = getms();
|
||||
int l = countriesNow->size();
|
||||
if (l) {
|
||||
if (r.intersects(QRect(0, 0, width(), st::countriesSkip))) {
|
||||
|
@ -291,10 +293,16 @@ void CountrySelectBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
int32 from = floorclamp(r.y() - st::countriesSkip, _rowHeight, 0, l);
|
||||
int32 to = ceilclamp(r.y() + r.height() - st::countriesSkip, _rowHeight, 0, l);
|
||||
for (int32 i = from; i < to; ++i) {
|
||||
bool sel = (i == _sel);
|
||||
int32 y = st::countriesSkip + i * _rowHeight;
|
||||
auto selected = (i == (_pressed >= 0 ? _pressed : _selected));
|
||||
auto y = st::countriesSkip + i * _rowHeight;
|
||||
|
||||
p.fillRect(0, y, width(), _rowHeight, sel ? st::countryRowBgOver : st::countryRowBg);
|
||||
p.fillRect(0, y, width(), _rowHeight, selected ? st::countryRowBgOver : st::countryRowBg);
|
||||
if (_ripples.size() > i && _ripples[i]) {
|
||||
_ripples[i]->paint(p, 0, y, width(), ms);
|
||||
if (_ripples[i]->empty()) {
|
||||
_ripples[i].reset();
|
||||
}
|
||||
}
|
||||
|
||||
QString code = QString("+") + (*countriesNow)[i]->code;
|
||||
int32 codeWidth = st::countryRowCodeFont->width(code);
|
||||
|
@ -312,7 +320,7 @@ void CountrySelectBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
p.drawTextLeft(st::countryRowPadding.left(), y + st::countryRowPadding.top(), width(), name);
|
||||
|
||||
p.setFont(st::countryRowCodeFont);
|
||||
p.setPen(sel ? st::countryRowCodeFgOver : st::countryRowCodeFg);
|
||||
p.setPen(selected ? st::countryRowCodeFgOver : st::countryRowCodeFg);
|
||||
p.drawTextLeft(st::countryRowPadding.left() + nameWidth + st::countryRowPadding.right(), y + st::countryRowPadding.top(), width(), code);
|
||||
}
|
||||
} else {
|
||||
|
@ -328,26 +336,49 @@ void CountrySelectBox::Inner::enterEvent(QEvent *e) {
|
|||
}
|
||||
|
||||
void CountrySelectBox::Inner::leaveEvent(QEvent *e) {
|
||||
_mouseSel = false;
|
||||
_mouseSelection = false;
|
||||
setMouseTracking(false);
|
||||
if (_sel >= 0) {
|
||||
if (_selected >= 0) {
|
||||
updateSelectedRow();
|
||||
_sel = -1;
|
||||
_selected = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||
_mouseSel = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSel();
|
||||
_mouseSelection = true;
|
||||
updateSelected(e->pos());
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||
_mouseSel = true;
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSel();
|
||||
_mouseSelection = true;
|
||||
updateSelected(e->pos());
|
||||
|
||||
setPressed(_selected);
|
||||
if (_pressed >= 0 && _pressed < countriesNow->size()) {
|
||||
if (_ripples.size() <= _pressed) {
|
||||
_ripples.reserve(_pressed + 1);
|
||||
while (_ripples.size() <= _pressed) {
|
||||
_ripples.push_back(std_::unique_ptr<Ui::RippleAnimation>());
|
||||
}
|
||||
}
|
||||
if (!_ripples[_pressed]) {
|
||||
auto mask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight));
|
||||
_ripples[_pressed] = std_::make_unique<Ui::RippleAnimation>(st::countryRipple, std_::move(mask), [this, index = _pressed] {
|
||||
updateRow(index);
|
||||
});
|
||||
_ripples[_pressed]->add(e->pos() - QPoint(0, st::countriesSkip + _pressed * _rowHeight));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
auto pressed = _pressed;
|
||||
setPressed(-1);
|
||||
updateSelectedRow();
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
chooseCountry();
|
||||
if ((pressed >= 0) && pressed == _selected) {
|
||||
chooseCountry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,25 +432,25 @@ void CountrySelectBox::Inner::updateFilter(QString filter) {
|
|||
countriesNow = &countriesFiltered;
|
||||
}
|
||||
refresh();
|
||||
_sel = countriesNow->isEmpty() ? -1 : 0;
|
||||
_selected = countriesNow->isEmpty() ? -1 : 0;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::selectSkip(int32 dir) {
|
||||
_mouseSel = false;
|
||||
_mouseSelection = false;
|
||||
|
||||
int cur = (_sel >= 0) ? _sel : -1;
|
||||
int cur = (_selected >= 0) ? _selected : -1;
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_sel = countriesNow->isEmpty() ? -1 : 0;
|
||||
_selected = countriesNow->isEmpty() ? -1 : 0;
|
||||
} else if (cur >= countriesNow->size()) {
|
||||
_sel = -1;
|
||||
_selected = -1;
|
||||
} else {
|
||||
_sel = cur;
|
||||
_selected = cur;
|
||||
}
|
||||
if (_sel >= 0) {
|
||||
emit mustScrollTo(st::countriesSkip + _sel * _rowHeight, st::countriesSkip + (_sel + 1) * _rowHeight);
|
||||
if (_selected >= 0) {
|
||||
emit mustScrollTo(st::countriesSkip + _selected * _rowHeight, st::countriesSkip + (_selected + 1) * _rowHeight);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
@ -433,12 +464,12 @@ void CountrySelectBox::Inner::selectSkipPage(int32 h, int32 dir) {
|
|||
void CountrySelectBox::Inner::chooseCountry() {
|
||||
QString result;
|
||||
if (_filter.isEmpty()) {
|
||||
if (_sel >= 0 && _sel < countriesAll.size()) {
|
||||
result = countriesAll[_sel]->iso2;
|
||||
if (_selected >= 0 && _selected < countriesAll.size()) {
|
||||
result = countriesAll[_selected]->iso2;
|
||||
}
|
||||
} else {
|
||||
if (_sel >= 0 && _sel < countriesFiltered.size()) {
|
||||
result = countriesFiltered[_sel]->iso2;
|
||||
if (_selected >= 0 && _selected < countriesFiltered.size()) {
|
||||
result = countriesFiltered[_selected]->iso2;
|
||||
}
|
||||
}
|
||||
emit countryChosen(result);
|
||||
|
@ -448,22 +479,34 @@ void CountrySelectBox::Inner::refresh() {
|
|||
resize(width(), countriesNow->length() ? (countriesNow->length() * _rowHeight + st::countriesSkip) : st::noContactsHeight);
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::updateSel() {
|
||||
if (!_mouseSel) return;
|
||||
void CountrySelectBox::Inner::updateSelected(QPoint localPos) {
|
||||
if (!_mouseSelection) return;
|
||||
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
|
||||
auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(QCursor::pos()));
|
||||
|
||||
int32 newSel = (in && p.y() >= st::countriesSkip && p.y() < st::countriesSkip + countriesNow->size() * _rowHeight) ? ((p.y() - st::countriesSkip) / _rowHeight) : -1;
|
||||
if (newSel != _sel) {
|
||||
auto selected = (in && localPos.y() >= st::countriesSkip && localPos.y() < st::countriesSkip + countriesNow->size() * _rowHeight) ? ((localPos.y() - st::countriesSkip) / _rowHeight) : -1;
|
||||
if (_selected != selected) {
|
||||
updateSelectedRow();
|
||||
_sel = newSel;
|
||||
_selected = selected;
|
||||
updateSelectedRow();
|
||||
}
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::updateSelectedRow() {
|
||||
if (_sel >= 0) {
|
||||
update(0, st::countriesSkip + _sel * _rowHeight, width(), _rowHeight);
|
||||
updateRow(_selected);
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::updateRow(int index) {
|
||||
if (index >= 0) {
|
||||
update(0, st::countriesSkip + index * _rowHeight, width(), _rowHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void CountrySelectBox::Inner::setPressed(int pressed) {
|
||||
if (_pressed >= 0 && _pressed < _ripples.size() && _ripples[_pressed]) {
|
||||
_ripples[_pressed]->lastStop();
|
||||
}
|
||||
_pressed = pressed;
|
||||
}
|
||||
|
||||
CountrySelectBox::Inner::~Inner() = default;
|
||||
|
|
|
@ -108,29 +108,36 @@ public:
|
|||
|
||||
void refresh();
|
||||
|
||||
~Inner();
|
||||
|
||||
signals:
|
||||
void countryChosen(const QString &iso);
|
||||
void mustScrollTo(int ymin, int ymax);
|
||||
|
||||
public slots:
|
||||
void updateSel();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void enterEvent(QEvent *e) override;
|
||||
void leaveEvent(QEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
void updateSelected() {
|
||||
updateSelected(mapFromGlobal(QCursor::pos()));
|
||||
}
|
||||
void updateSelected(QPoint localPos);
|
||||
void updateSelectedRow();
|
||||
void updateRow(int index);
|
||||
void setPressed(int pressed);
|
||||
|
||||
int _rowHeight;
|
||||
|
||||
int _sel = 0;
|
||||
int _selected = -1;
|
||||
int _pressed = -1;
|
||||
QString _filter;
|
||||
bool _mouseSel = false;
|
||||
bool _mouseSelection = false;
|
||||
|
||||
QPoint _lastMousePos;
|
||||
std_::vector_of_moveable<std_::unique_ptr<Ui::RippleAnimation>> _ripples;
|
||||
|
||||
};
|
||||
|
|
|
@ -24,45 +24,45 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
namespace Ui {
|
||||
|
||||
RadialAnimation::RadialAnimation(AnimationCallbacks &&callbacks)
|
||||
: a_arcEnd(0, 0)
|
||||
, a_arcStart(0, FullArcLength)
|
||||
: a_arcStart(0, FullArcLength)
|
||||
, _animation(std_::move(callbacks)) {
|
||||
}
|
||||
|
||||
void RadialAnimation::start(float64 prg) {
|
||||
_firstStart = _lastStart = _lastTime = getms();
|
||||
int32 iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength), iprgstrict = qRound(prg * AlmostFullArcLength);
|
||||
a_arcEnd = anim::ivalue(iprgstrict, iprg);
|
||||
a_arcEnd = anim::value(iprgstrict, iprg);
|
||||
_animation.start();
|
||||
}
|
||||
|
||||
void RadialAnimation::update(float64 prg, bool finished, TimeMs ms) {
|
||||
int32 iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength);
|
||||
if (iprg != a_arcEnd.to()) {
|
||||
auto iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength);
|
||||
if (iprg != qRound(a_arcEnd.to())) {
|
||||
a_arcEnd.start(iprg);
|
||||
_lastStart = _lastTime;
|
||||
}
|
||||
_lastTime = ms;
|
||||
|
||||
float64 dt = float64(ms - _lastStart), fulldt = float64(ms - _firstStart);
|
||||
auto dt = float64(ms - _lastStart);
|
||||
auto fulldt = float64(ms - _firstStart);
|
||||
_opacity = qMin(fulldt / st::radialDuration, 1.);
|
||||
if (!finished) {
|
||||
a_arcEnd.update(1. - (st::radialDuration / (st::radialDuration + dt)), anim::linear);
|
||||
} else if (dt >= st::radialDuration) {
|
||||
a_arcEnd.update(1, anim::linear);
|
||||
a_arcEnd.update(1., anim::linear);
|
||||
stop();
|
||||
} else {
|
||||
float64 r = dt / st::radialDuration;
|
||||
auto r = dt / st::radialDuration;
|
||||
a_arcEnd.update(r, anim::linear);
|
||||
_opacity *= 1 - r;
|
||||
}
|
||||
float64 fromstart = fulldt / st::radialPeriod;
|
||||
auto fromstart = fulldt / st::radialPeriod;
|
||||
a_arcStart.update(fromstart - std::floor(fromstart), anim::linear);
|
||||
}
|
||||
|
||||
void RadialAnimation::stop() {
|
||||
_firstStart = _lastStart = _lastTime = 0;
|
||||
a_arcEnd = anim::ivalue(0, 0);
|
||||
a_arcEnd = anim::value();
|
||||
_animation.stop();
|
||||
}
|
||||
|
||||
|
@ -79,8 +79,8 @@ void RadialAnimation::draw(Painter &p, const QRect &inner, int32 thickness, cons
|
|||
pen.setCapStyle(Qt::RoundCap);
|
||||
p.setPen(pen);
|
||||
|
||||
int32 len = MinArcLength + a_arcEnd.current();
|
||||
int32 from = QuarterArcLength - a_arcStart.current() - len;
|
||||
auto len = MinArcLength + qRound(a_arcEnd.current());
|
||||
auto from = QuarterArcLength - qRound(a_arcStart.current()) - len;
|
||||
if (rtl()) {
|
||||
from = QuarterArcLength - (from - QuarterArcLength) - len;
|
||||
if (from < 0) from += FullArcLength;
|
||||
|
|
|
@ -49,7 +49,8 @@ private:
|
|||
TimeMs _lastStart = 0;
|
||||
TimeMs _lastTime = 0;
|
||||
float64 _opacity = 0.;
|
||||
anim::ivalue a_arcEnd, a_arcStart;
|
||||
anim::value a_arcEnd;
|
||||
anim::value a_arcStart;
|
||||
Animation _animation;
|
||||
|
||||
};
|
||||
|
|
|
@ -92,7 +92,7 @@ void RippleAnimation::Ripple::paint(QPainter &p, const QPixmap &mask, TimeMs ms,
|
|||
return;
|
||||
}
|
||||
|
||||
if (_cache.isNull()) {
|
||||
if (_cache.isNull() || colorOverride != nullptr) {
|
||||
auto radius = anim::interpolate(_radiusFrom, _radiusTo, _show.current(ms, 1.));
|
||||
_frame.fill(Qt::transparent);
|
||||
{
|
||||
|
@ -110,7 +110,7 @@ void RippleAnimation::Ripple::paint(QPainter &p, const QPixmap &mask, TimeMs ms,
|
|||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p.drawPixmap(0, 0, mask);
|
||||
}
|
||||
if (radius == _radiusTo) {
|
||||
if (radius == _radiusTo && colorOverride == nullptr) {
|
||||
_cache = App::pixmapFromImageInPlace(std_::move(_frame));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,9 +51,9 @@ void WidgetSlideWrap<TWidget>::slideUp() {
|
|||
if (_a_height.animating()) {
|
||||
if (_hiding) return;
|
||||
} else {
|
||||
a_height = anim::ivalue(_realSize.height());
|
||||
a_height = anim::value(_realSize.height());
|
||||
}
|
||||
a_height.start(0);
|
||||
a_height.start(0.);
|
||||
_hiding = true;
|
||||
_a_height.start();
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ void WidgetSlideWrap<TWidget>::slideDown() {
|
|||
if (!_hiding) return;
|
||||
}
|
||||
a_height.start(_realSize.height());
|
||||
_forceHeight = a_height.current();
|
||||
_forceHeight = qRound(a_height.current());
|
||||
_hiding = false;
|
||||
_a_height.start();
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ void WidgetSlideWrap<TWidget>::showFast() {
|
|||
|
||||
void WidgetSlideWrap<TWidget>::hideFast() {
|
||||
_a_height.stop();
|
||||
a_height = anim::ivalue(0);
|
||||
a_height = anim::value();
|
||||
_forceHeight = 0;
|
||||
resizeToWidth(_realSize.width());
|
||||
hide();
|
||||
|
@ -144,7 +144,7 @@ void WidgetSlideWrap<TWidget>::step_height(float64 ms, bool timer) {
|
|||
if (_hiding) hide();
|
||||
} else {
|
||||
a_height.update(dt, anim::linear);
|
||||
_forceHeight = a_height.current();
|
||||
_forceHeight = qRound(a_height.current());
|
||||
}
|
||||
resizeToWidth(_realSize.width());
|
||||
if (_updateCallback) {
|
||||
|
|
|
@ -66,7 +66,7 @@ private:
|
|||
|
||||
style::size _realSize;
|
||||
int _forceHeight = -1;
|
||||
anim::ivalue a_height;
|
||||
anim::value a_height;
|
||||
Animation _a_height;
|
||||
bool _hiding = false;
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ int LinkButton::naturalWidth() const {
|
|||
|
||||
void LinkButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
auto &font = ((_state & StateOver) ? _st.overFont : _st.font);
|
||||
auto &pen = ((_state & StateDown) ? _st.downColor : ((_state & StateOver) ? _st.overColor : _st.color));
|
||||
auto &font = (isOver() ? _st.overFont : _st.font);
|
||||
auto &pen = (isDown() ? _st.downColor : (isOver() ? _st.overColor : _st.color));
|
||||
p.setFont(font);
|
||||
p.setPen(pen);
|
||||
if (_textWidth > width()) {
|
||||
|
@ -58,7 +58,7 @@ void LinkButton::setText(const QString &text) {
|
|||
update();
|
||||
}
|
||||
|
||||
void LinkButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||
void LinkButton::onStateChanged(State was, StateChangeSource source) {
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -95,11 +95,11 @@ void RippleButton::paintRipple(QPainter &p, int x, int y, TimeMs ms, const QColo
|
|||
}
|
||||
}
|
||||
|
||||
void RippleButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||
void RippleButton::onStateChanged(State was, StateChangeSource source) {
|
||||
update();
|
||||
|
||||
auto wasDown = (oldState & StateDown);
|
||||
auto down = (_state & StateDown);
|
||||
auto wasDown = static_cast<bool>(was & StateFlag::Down);
|
||||
auto down = isDown();
|
||||
if (!_st.showDuration || down == wasDown || _forceRippled) {
|
||||
return;
|
||||
}
|
||||
|
@ -187,10 +187,10 @@ void FlatButton::step_appearance(float64 ms, bool timer) {
|
|||
if (timer) update();
|
||||
}
|
||||
|
||||
void FlatButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(oldState, source);
|
||||
void FlatButton::onStateChanged(State was, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
|
||||
a_over.start((_state & StateOver) ? 1. : 0.);
|
||||
a_over.start(isOver() ? 1. : 0.);
|
||||
if (source == StateChangeSource::ByUser || source == StateChangeSource::ByPress) {
|
||||
_a_appearance.stop();
|
||||
a_over.finish();
|
||||
|
@ -211,7 +211,7 @@ void FlatButton::paintEvent(QPaintEvent *e) {
|
|||
auto ms = getms();
|
||||
paintRipple(p, 0, 0, ms);
|
||||
|
||||
p.setFont((_state & StateOver) ? _st.overFont : _st.font);
|
||||
p.setFont(isOver() ? _st.overFont : _st.font);
|
||||
p.setRenderHint(QPainter::TextAntialiasing);
|
||||
p.setPen(anim::pen(_st.color, _st.overColor, a_over.current()));
|
||||
|
||||
|
@ -294,8 +294,8 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
App::roundRect(p, myrtlrect(rounded), _st.textBg, ImageRoundRadius::Small);
|
||||
|
||||
auto over = (_state & StateOver);
|
||||
auto down = (_state & StateDown);
|
||||
auto over = isOver();
|
||||
auto down = isDown();
|
||||
if (over || down) {
|
||||
App::roundRect(p, myrtlrect(rounded), _st.textBgOver, ImageRoundRadius::Small);
|
||||
}
|
||||
|
@ -340,21 +340,25 @@ IconButton::IconButton(QWidget *parent, const style::IconButton &st) : RippleBut
|
|||
setCursor(style::cur_pointer);
|
||||
}
|
||||
|
||||
void IconButton::setIcon(const style::icon *icon, const style::icon *iconOver) {
|
||||
_iconOverride = icon;
|
||||
_iconOverrideOver = iconOver;
|
||||
void IconButton::setIconOverride(const style::icon *iconOverride, const style::icon *iconOverOverride) {
|
||||
_iconOverride = iconOverride;
|
||||
_iconOverrideOver = iconOverOverride;
|
||||
update();
|
||||
}
|
||||
|
||||
void IconButton::setRippleColorOverride(const style::color *colorOverride) {
|
||||
_rippleColorOverride = colorOverride;
|
||||
}
|
||||
|
||||
void IconButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
auto ms = getms();
|
||||
|
||||
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, _rippleColorOverride ? &(*_rippleColorOverride)->c : nullptr);
|
||||
|
||||
auto down = (_state & StateDown);
|
||||
auto overIconOpacity = (down || forceRippled()) ? 1. : _a_over.current(getms(), (_state & StateOver) ? 1. : 0.);
|
||||
auto down = isDown();
|
||||
auto overIconOpacity = (down || forceRippled()) ? 1. : _a_over.current(getms(), isOver() ? 1. : 0.);
|
||||
auto overIcon = [this] {
|
||||
if (_iconOverrideOver) {
|
||||
return _iconOverrideOver;
|
||||
|
@ -389,11 +393,12 @@ void IconButton::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
void IconButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(oldState, source);
|
||||
void IconButton::onStateChanged(State was, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
|
||||
auto over = (_state & StateOver);
|
||||
if (over != (oldState & StateOver)) {
|
||||
auto over = isOver();
|
||||
auto wasOver = static_cast<bool>(was & StateFlag::Over);
|
||||
if (over != wasOver) {
|
||||
if (_st.duration) {
|
||||
auto from = over ? 0. : 1.;
|
||||
auto to = over ? 1. : 0.;
|
||||
|
@ -443,7 +448,8 @@ int LeftOutlineButton::resizeGetHeight(int newWidth) {
|
|||
void LeftOutlineButton::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
bool over = (_state & StateOver), down = (_state & StateDown);
|
||||
auto over = isOver();
|
||||
auto down = isDown();
|
||||
if (width() > _st.outlineWidth) {
|
||||
p.fillRect(rtlrect(_st.outlineWidth, 0, width() - _st.outlineWidth, height(), width()), (over || down) ? _st.textBgOver : _st.textBg);
|
||||
paintRipple(p, 0, 0, getms());
|
||||
|
@ -492,7 +498,7 @@ void CrossButton::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
auto ms = getms();
|
||||
auto over = (_state & StateOver);
|
||||
auto over = isOver();
|
||||
auto shown = _a_show.current(ms, _shown ? 1. : 0.);
|
||||
p.setOpacity(shown);
|
||||
|
||||
|
@ -501,11 +507,12 @@ void CrossButton::paintEvent(QPaintEvent *e) {
|
|||
CrossAnimation::paint(p, _st.cross, over ? _st.crossFgOver : _st.crossFg, _st.crossPosition.x(), _st.crossPosition.y(), width(), shown);
|
||||
}
|
||||
|
||||
void CrossButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(oldState, source);
|
||||
void CrossButton::onStateChanged(State was, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
|
||||
auto over = (_state & StateOver);
|
||||
if (over != (oldState & StateOver)) {
|
||||
auto over = isOver();
|
||||
auto wasOver = static_cast<bool>(was & StateFlag::Over);
|
||||
if (over != wasOver) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "ui/abstract_button.h"
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class RippleAnimation;
|
||||
|
@ -38,7 +40,7 @@ public:
|
|||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
private:
|
||||
QString _text;
|
||||
|
@ -66,7 +68,7 @@ public:
|
|||
protected:
|
||||
void paintRipple(QPainter &p, int x, int y, TimeMs ms, const QColor *colorOverride = nullptr);
|
||||
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
virtual QImage prepareRippleMask() const;
|
||||
virtual QPoint prepareRippleStartPosition() const;
|
||||
|
@ -98,7 +100,7 @@ public:
|
|||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
private:
|
||||
void setOpacity(float64 o);
|
||||
|
@ -109,7 +111,7 @@ private:
|
|||
|
||||
const style::FlatButton &_st;
|
||||
|
||||
anim::fvalue a_over;
|
||||
anim::value a_over;
|
||||
Animation _a_appearance;
|
||||
|
||||
float64 _opacity = 1.;
|
||||
|
@ -162,12 +164,13 @@ public:
|
|||
IconButton(QWidget *parent, const style::IconButton &st);
|
||||
|
||||
// Pass nullptr to restore the default icon.
|
||||
void setIcon(const style::icon *icon, const style::icon *iconOver = nullptr);
|
||||
void setIconOverride(const style::icon *iconOverride, const style::icon *iconOverOverride = nullptr);
|
||||
void setRippleColorOverride(const style::color *colorOverride);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
QPoint prepareRippleStartPosition() const override;
|
||||
|
@ -176,6 +179,7 @@ private:
|
|||
const style::IconButton &_st;
|
||||
const style::icon *_iconOverride = nullptr;
|
||||
const style::icon *_iconOverrideOver = nullptr;
|
||||
const style::color *_rippleColorOverride = nullptr;
|
||||
|
||||
FloatAnimation _a_over;
|
||||
|
||||
|
@ -215,7 +219,7 @@ public:
|
|||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
QPoint prepareRippleStartPosition() const override;
|
||||
|
|
|
@ -163,16 +163,16 @@ void Checkbox::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
void Checkbox::onClicked() {
|
||||
if (_state & StateDisabled) return;
|
||||
if (isDisabled()) return;
|
||||
setChecked(!checked());
|
||||
}
|
||||
|
||||
void Checkbox::onStateChanged(int oldState, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(oldState, source);
|
||||
void Checkbox::onStateChanged(State was, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
|
||||
if ((_state & StateDisabled) && !(oldState & StateDisabled)) {
|
||||
if (isDisabled() && !(was & StateFlag::Disabled)) {
|
||||
setCursor(style::cur_default);
|
||||
} else if (!(_state & StateDisabled) && (oldState & StateDisabled)) {
|
||||
} else if (!isDisabled() && (was & StateFlag::Disabled)) {
|
||||
setCursor(style::cur_pointer);
|
||||
}
|
||||
}
|
||||
|
@ -284,16 +284,16 @@ void Radiobutton::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
void Radiobutton::onClicked() {
|
||||
if (_state & StateDisabled) return;
|
||||
if (isDisabled()) return;
|
||||
setChecked(!checked());
|
||||
}
|
||||
|
||||
void Radiobutton::onStateChanged(int oldState, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(oldState, source);
|
||||
void Radiobutton::onStateChanged(State was, StateChangeSource source) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
|
||||
if ((_state & StateDisabled) && !(oldState & StateDisabled)) {
|
||||
if (isDisabled() && !(was & StateFlag::Disabled)) {
|
||||
setCursor(style::cur_default);
|
||||
} else if (!(_state & StateDisabled) && (oldState & StateDisabled)) {
|
||||
} else if (!isDisabled() && (was & StateFlag::Disabled)) {
|
||||
setCursor(style::cur_pointer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
|
@ -95,7 +95,7 @@ public:
|
|||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
QImage prepareRippleMask() const override;
|
||||
|
|
|
@ -65,7 +65,7 @@ void ContinuousSlider::setValue(float64 value, bool animated) {
|
|||
a_value.start(value);
|
||||
_a_value.start();
|
||||
} else {
|
||||
a_value = anim::fvalue(value, value);
|
||||
a_value = anim::value(value, value);
|
||||
_a_value.stop();
|
||||
}
|
||||
update();
|
||||
|
@ -116,7 +116,7 @@ void ContinuousSlider::mouseReleaseEvent(QMouseEvent *e) {
|
|||
if (_changeFinishedCallback) {
|
||||
_changeFinishedCallback(_downValue);
|
||||
}
|
||||
a_value = anim::fvalue(_downValue, _downValue);
|
||||
a_value = anim::value(_downValue, _downValue);
|
||||
_a_value.stop();
|
||||
update();
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ private:
|
|||
bool _over = false;
|
||||
FloatAnimation _a_over;
|
||||
|
||||
anim::fvalue a_value = { 0., 0. };
|
||||
anim::value a_value;
|
||||
Animation _a_value;
|
||||
|
||||
bool _mouseDown = false;
|
||||
|
|
|
@ -1716,11 +1716,6 @@ InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString
|
|||
|
||||
, _placeholderFull(ph)
|
||||
, _placeholderVisible(val.isEmpty())
|
||||
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
|
||||
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
|
||||
, a_placeholderFgActive(0)
|
||||
, _a_placeholderFg(animation(this, &InputArea::step_placeholderFg))
|
||||
, _a_placeholderShift(animation(this, &InputArea::step_placeholderShift))
|
||||
|
||||
, a_borderOpacityActive(0)
|
||||
, a_borderFgActive(0)
|
||||
|
@ -1878,21 +1873,21 @@ void InputArea::paintEvent(QPaintEvent *e) {
|
|||
p.setOpacity(1);
|
||||
}
|
||||
|
||||
bool drawPlaceholder = _placeholderVisible;
|
||||
if (_a_placeholderShift.animating()) {
|
||||
p.setOpacity(a_placeholderOpacity.current());
|
||||
drawPlaceholder = true;
|
||||
}
|
||||
if (drawPlaceholder) {
|
||||
auto ms = getms();
|
||||
auto placeholderOpacity = _a_placeholderVisible.current(ms, _placeholderVisible ? 1. : 0.);
|
||||
if (placeholderOpacity > 0.) {
|
||||
p.setOpacity(placeholderOpacity);
|
||||
p.save();
|
||||
p.setClipRect(r);
|
||||
|
||||
auto placeholderLeft = anim::interpolate(_st.placeholderShift, 0, placeholderOpacity);
|
||||
|
||||
QRect r(rect().marginsRemoved(_st.textMargins + _st.placeholderMargins));
|
||||
r.moveLeft(r.left() + a_placeholderLeft.current());
|
||||
r.moveLeft(r.left() + placeholderLeft);
|
||||
if (rtl()) r.moveLeft(width() - r.left() - r.width());
|
||||
|
||||
p.setFont(_st.font);
|
||||
p.setPen(anim::pen(_st.placeholderFg, _st.placeholderFgActive, a_placeholderFgActive.current()));
|
||||
p.setPen(anim::pen(_st.placeholderFg, _st.placeholderFgActive, _a_placeholderFocused.current(ms, hasFocus() ? 1. : 0.)));
|
||||
p.drawText(r, _placeholder, _st.placeholderAlign);
|
||||
|
||||
p.restore();
|
||||
|
@ -1929,8 +1924,7 @@ void InputArea::focusInInner() {
|
|||
if (!_focused) {
|
||||
_focused = true;
|
||||
|
||||
a_placeholderFgActive.start(1.);
|
||||
_a_placeholderFg.start();
|
||||
_a_placeholderFocused.start([this] { update(); }, 0., 1., _st.duration);
|
||||
|
||||
startBorderAnimation();
|
||||
}
|
||||
|
@ -1946,8 +1940,7 @@ void InputArea::focusOutInner() {
|
|||
if (_focused) {
|
||||
_focused = false;
|
||||
|
||||
a_placeholderFgActive.start(0.);
|
||||
_a_placeholderFg.start();
|
||||
_a_placeholderFocused.start([this] { update(); }, 1., 0., _st.duration);
|
||||
|
||||
startBorderAnimation();
|
||||
}
|
||||
|
@ -2273,30 +2266,6 @@ void InputArea::onRedoAvailable(bool avail) {
|
|||
if (App::wnd()) App::wnd()->updateGlobalMenu();
|
||||
}
|
||||
|
||||
void InputArea::step_placeholderFg(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
_a_placeholderFg.stop();
|
||||
a_placeholderFgActive.finish();
|
||||
} else {
|
||||
a_placeholderFgActive.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void InputArea::step_placeholderShift(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
_a_placeholderShift.stop();
|
||||
a_placeholderLeft.finish();
|
||||
a_placeholderOpacity.finish();
|
||||
} else {
|
||||
a_placeholderLeft.update(dt, anim::linear);
|
||||
a_placeholderOpacity.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void InputArea::step_border(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
bool res = true;
|
||||
|
@ -2314,13 +2283,10 @@ void InputArea::step_border(float64 ms, bool timer) {
|
|||
}
|
||||
|
||||
void InputArea::updatePlaceholder() {
|
||||
bool placeholderVisible = _oldtext.isEmpty();
|
||||
if (placeholderVisible != _placeholderVisible) {
|
||||
auto placeholderVisible = _oldtext.isEmpty();
|
||||
if (_placeholderVisible != placeholderVisible) {
|
||||
_placeholderVisible = placeholderVisible;
|
||||
|
||||
a_placeholderLeft.start(_placeholderVisible ? 0 : _st.placeholderShift);
|
||||
a_placeholderOpacity.start(_placeholderVisible ? 1 : 0);
|
||||
_a_placeholderShift.start();
|
||||
_a_placeholderVisible.start([this] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., _st.duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2445,11 +2411,6 @@ InputField::InputField(QWidget *parent, const style::InputField &st, const QStri
|
|||
|
||||
, _placeholderFull(ph)
|
||||
, _placeholderVisible(val.isEmpty())
|
||||
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
|
||||
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
|
||||
, a_placeholderFgActive(0)
|
||||
, _a_placeholderFg(animation(this, &InputField::step_placeholderFg))
|
||||
, _a_placeholderShift(animation(this, &InputField::step_placeholderShift))
|
||||
|
||||
, a_borderOpacityActive(0)
|
||||
, a_borderFgActive(0)
|
||||
|
@ -2571,13 +2532,6 @@ void InputField::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
auto ms = getms();
|
||||
if (_a_placeholderShift.animating()) {
|
||||
_a_placeholderShift.step(ms);
|
||||
}
|
||||
if (_a_placeholderFg.animating()) {
|
||||
_a_placeholderFg.step(ms);
|
||||
}
|
||||
|
||||
QRect r(rect().intersected(e->rect()));
|
||||
if (_st.textBg->c.alphaF() > 0.) {
|
||||
p.fillRect(r, _st.textBg);
|
||||
|
@ -2593,21 +2547,21 @@ void InputField::paintEvent(QPaintEvent *e) {
|
|||
p.setOpacity(1);
|
||||
}
|
||||
|
||||
bool drawPlaceholder = _placeholderVisible;
|
||||
if (_a_placeholderShift.animating()) {
|
||||
p.setOpacity(a_placeholderOpacity.current());
|
||||
drawPlaceholder = true;
|
||||
}
|
||||
if (drawPlaceholder) {
|
||||
auto placeholderOpacity = _a_placeholderVisible.current(ms, _placeholderVisible ? 1. : 0.);
|
||||
if (placeholderOpacity > 0.) {
|
||||
p.setOpacity(placeholderOpacity);
|
||||
p.save();
|
||||
p.setClipRect(r);
|
||||
|
||||
auto placeholderLeft = anim::interpolate(_st.placeholderShift, 0, placeholderOpacity);
|
||||
|
||||
|
||||
QRect r(rect().marginsRemoved(_st.textMargins + _st.placeholderMargins));
|
||||
r.moveLeft(r.left() + a_placeholderLeft.current());
|
||||
r.moveLeft(r.left() + placeholderLeft);
|
||||
if (rtl()) r.moveLeft(width() - r.left() - r.width());
|
||||
|
||||
p.setFont(_st.font);
|
||||
p.setPen(anim::pen(_st.placeholderFg, _st.placeholderFgActive, a_placeholderFgActive.current()));
|
||||
p.setPen(anim::pen(_st.placeholderFg, _st.placeholderFgActive, _a_placeholderFocused.current(ms, hasFocus() ? 1. : 0.)));
|
||||
p.drawText(r, _placeholder, _st.placeholderAlign);
|
||||
|
||||
p.restore();
|
||||
|
@ -2644,8 +2598,7 @@ void InputField::focusInInner() {
|
|||
if (!_focused) {
|
||||
_focused = true;
|
||||
|
||||
a_placeholderFgActive.start(1.);
|
||||
_a_placeholderFg.start();
|
||||
_a_placeholderFocused.start([this] { update(); }, 0., 1., _st.duration);
|
||||
|
||||
startBorderAnimation();
|
||||
}
|
||||
|
@ -2661,8 +2614,7 @@ void InputField::focusOutInner() {
|
|||
if (_focused) {
|
||||
_focused = false;
|
||||
|
||||
a_placeholderFgActive.start(0.);
|
||||
_a_placeholderFg.start();
|
||||
_a_placeholderFocused.start([this] { update(); }, 1., 0., _st.duration);
|
||||
|
||||
startBorderAnimation();
|
||||
}
|
||||
|
@ -3019,32 +2971,9 @@ void InputField::selectAll() {
|
|||
_inner.setTextCursor(c);
|
||||
}
|
||||
|
||||
void InputField::step_placeholderFg(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
_a_placeholderFg.stop();
|
||||
a_placeholderFgActive.finish();
|
||||
} else {
|
||||
a_placeholderFgActive.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void InputField::step_placeholderShift(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
finishPlaceholderAnimation();
|
||||
} else {
|
||||
a_placeholderLeft.update(dt, anim::linear);
|
||||
a_placeholderOpacity.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void InputField::finishPlaceholderAnimation() {
|
||||
_a_placeholderShift.stop();
|
||||
a_placeholderLeft.finish();
|
||||
a_placeholderOpacity.finish();
|
||||
_a_placeholderVisible.finish();
|
||||
_a_placeholderFocused.finish();
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -3064,13 +2993,10 @@ void InputField::step_border(float64 ms, bool timer) {
|
|||
}
|
||||
|
||||
void InputField::updatePlaceholder() {
|
||||
bool placeholderVisible = _oldtext.isEmpty() && !_forcePlaceholderHidden;
|
||||
if (placeholderVisible != _placeholderVisible) {
|
||||
auto placeholderVisible = _oldtext.isEmpty();
|
||||
if (_placeholderVisible != placeholderVisible) {
|
||||
_placeholderVisible = placeholderVisible;
|
||||
|
||||
a_placeholderLeft.start(_placeholderVisible ? 0 : _st.placeholderShift);
|
||||
a_placeholderOpacity.start(_placeholderVisible ? 1 : 0);
|
||||
_a_placeholderShift.start();
|
||||
_a_placeholderVisible.start([this] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., _st.duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3198,11 +3124,6 @@ MaskedInputField::MaskedInputField(QWidget *parent, const style::InputField &st,
|
|||
, _placeholderFull(placeholder)
|
||||
, _placeholderVisible(val.isEmpty())
|
||||
, _placeholderFast(false)
|
||||
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
|
||||
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
|
||||
, a_placeholderFgActive(0)
|
||||
, _a_placeholderFg(animation(this, &MaskedInputField::step_placeholderFg))
|
||||
, _a_placeholderShift(animation(this, &MaskedInputField::step_placeholderShift))
|
||||
|
||||
, a_borderOpacityActive(0)
|
||||
, a_borderFgActive(0)
|
||||
|
@ -3345,7 +3266,7 @@ void MaskedInputField::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
p.setClipRect(r);
|
||||
paintPlaceholder(p);
|
||||
paintPlaceholder(p, getms());
|
||||
|
||||
QLineEdit::paintEvent(e);
|
||||
}
|
||||
|
@ -3361,8 +3282,7 @@ void MaskedInputField::focusInEvent(QFocusEvent *e) {
|
|||
if (!_focused) {
|
||||
_focused = true;
|
||||
|
||||
a_placeholderFgActive.start(1.);
|
||||
_a_placeholderFg.start();
|
||||
_a_placeholderFocused.start([this] { update(); }, 0., 1., _st.duration);
|
||||
|
||||
startBorderAnimation();
|
||||
}
|
||||
|
@ -3374,8 +3294,7 @@ void MaskedInputField::focusOutEvent(QFocusEvent *e) {
|
|||
if (_focused) {
|
||||
_focused = false;
|
||||
|
||||
a_placeholderFgActive.start(0.);
|
||||
_a_placeholderFg.start();
|
||||
_a_placeholderFocused.start([this] { update(); }, 1., 0., _st.duration);
|
||||
|
||||
startBorderAnimation();
|
||||
}
|
||||
|
@ -3416,30 +3335,6 @@ QSize MaskedInputField::minimumSizeHint() const {
|
|||
return geometry().size();
|
||||
}
|
||||
|
||||
void MaskedInputField::step_placeholderFg(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
_a_placeholderFg.stop();
|
||||
a_placeholderFgActive.finish();
|
||||
} else {
|
||||
a_placeholderFgActive.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void MaskedInputField::step_placeholderShift(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
_a_placeholderShift.stop();
|
||||
a_placeholderLeft.finish();
|
||||
a_placeholderOpacity.finish();
|
||||
} else {
|
||||
a_placeholderLeft.update(dt, anim::linear);
|
||||
a_placeholderOpacity.update(dt, anim::linear);
|
||||
}
|
||||
if (timer) update();
|
||||
}
|
||||
|
||||
void MaskedInputField::step_border(float64 ms, bool timer) {
|
||||
float64 dt = ms / _st.duration;
|
||||
if (dt >= 1) {
|
||||
|
@ -3467,25 +3362,18 @@ bool MaskedInputField::setPlaceholder(const QString &placeholder) {
|
|||
void MaskedInputField::setPlaceholderFast(bool fast) {
|
||||
_placeholderFast = fast;
|
||||
if (_placeholderFast) {
|
||||
a_placeholderLeft = anim::ivalue(_placeholderVisible ? 0 : _st.placeholderShift, _placeholderVisible ? 0 : _st.placeholderShift);
|
||||
a_placeholderOpacity = anim::fvalue(_placeholderVisible ? 1 : 0, _placeholderVisible ? 1 : 0);
|
||||
_a_placeholderVisible.finish();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void MaskedInputField::updatePlaceholder() {
|
||||
bool placeholderVisible = _oldtext.isEmpty();
|
||||
if (placeholderVisible != _placeholderVisible) {
|
||||
auto placeholderVisible = _oldtext.isEmpty();
|
||||
if (_placeholderVisible != placeholderVisible) {
|
||||
_placeholderVisible = placeholderVisible;
|
||||
|
||||
_a_placeholderVisible.start([this] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., _st.duration);
|
||||
if (_placeholderFast) {
|
||||
a_placeholderLeft = anim::ivalue(_placeholderVisible ? 0 : _st.placeholderShift, _placeholderVisible ? 0 : _st.placeholderShift);
|
||||
a_placeholderOpacity = anim::fvalue(_placeholderVisible ? 1 : 0, _placeholderVisible ? 1 : 0);
|
||||
update();
|
||||
} else {
|
||||
a_placeholderLeft.start(_placeholderVisible ? 0 : _st.placeholderShift);
|
||||
a_placeholderOpacity.start(_placeholderVisible ? 1 : 0);
|
||||
_a_placeholderShift.start();
|
||||
_a_placeholderVisible.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3498,29 +3386,28 @@ QRect MaskedInputField::placeholderRect() const {
|
|||
return rect().marginsRemoved(_st.textMargins + _st.placeholderMargins);
|
||||
}
|
||||
|
||||
void MaskedInputField::paintPlaceholder(Painter &p) {
|
||||
bool drawPlaceholder = _placeholderVisible;
|
||||
if (_a_placeholderShift.animating()) {
|
||||
p.setOpacity(a_placeholderOpacity.current());
|
||||
drawPlaceholder = true;
|
||||
}
|
||||
if (drawPlaceholder) {
|
||||
void MaskedInputField::paintPlaceholder(Painter &p, TimeMs ms) {
|
||||
auto placeholderOpacity = _a_placeholderVisible.current(ms, _placeholderVisible ? 1. : 0.);
|
||||
if (placeholderOpacity > 0.) {
|
||||
p.setOpacity(placeholderOpacity);
|
||||
p.save();
|
||||
|
||||
auto placeholderLeft = anim::interpolate(_st.placeholderShift, 0, placeholderOpacity);
|
||||
|
||||
QRect phRect(placeholderRect());
|
||||
phRect.moveLeft(phRect.left() + a_placeholderLeft.current());
|
||||
phRect.moveLeft(phRect.left() + placeholderLeft);
|
||||
if (rtl()) phRect.moveLeft(width() - phRect.left() - phRect.width());
|
||||
|
||||
placeholderPreparePaint(p);
|
||||
placeholderPreparePaint(p, ms);
|
||||
p.drawText(phRect, _placeholder, _st.placeholderAlign);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
}
|
||||
|
||||
void MaskedInputField::placeholderPreparePaint(Painter &p) {
|
||||
void MaskedInputField::placeholderPreparePaint(Painter &p, TimeMs ms) {
|
||||
p.setFont(_st.font);
|
||||
p.setPen(anim::pen(_st.placeholderFg, _st.placeholderFgActive, a_placeholderFgActive.current()));
|
||||
p.setPen(anim::pen(_st.placeholderFg, _st.placeholderFgActive, _a_placeholderFocused.current(ms, hasFocus() ? 1. : 0.)));
|
||||
}
|
||||
|
||||
void MaskedInputField::keyPressEvent(QKeyEvent *e) {
|
||||
|
@ -3648,7 +3535,7 @@ void CountryCodeInput::correctValue(const QString &was, int32 wasCursor, QString
|
|||
PhonePartInput::PhonePartInput(QWidget *parent, const style::InputField &st) : MaskedInputField(parent, st, lang(lng_phone_ph)) {
|
||||
}
|
||||
|
||||
void PhonePartInput::paintPlaceholder(Painter &p) {
|
||||
void PhonePartInput::paintPlaceholder(Painter &p, TimeMs ms) {
|
||||
auto t = getLastText();
|
||||
if (!_pattern.isEmpty() && !t.isEmpty()) {
|
||||
auto ph = placeholder().mid(t.size());
|
||||
|
@ -3658,12 +3545,12 @@ void PhonePartInput::paintPlaceholder(Painter &p) {
|
|||
int tw = phFont()->width(t);
|
||||
if (tw < phRect.width()) {
|
||||
phRect.setLeft(phRect.left() + tw);
|
||||
placeholderPreparePaint(p);
|
||||
placeholderPreparePaint(p, ms);
|
||||
p.drawText(phRect, ph, style::al_topleft);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MaskedInputField::paintPlaceholder(p);
|
||||
MaskedInputField::paintPlaceholder(p, ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3812,9 +3699,9 @@ _linkPlaceholder(isLink ? qsl("telegram.me/") : QString()) {
|
|||
}
|
||||
}
|
||||
|
||||
void UsernameInput::paintPlaceholder(Painter &p) {
|
||||
void UsernameInput::paintPlaceholder(Painter &p, TimeMs ms) {
|
||||
if (_linkPlaceholder.isEmpty()) {
|
||||
MaskedInputField::paintPlaceholder(p);
|
||||
MaskedInputField::paintPlaceholder(p, ms);
|
||||
} else {
|
||||
p.setFont(_st.font);
|
||||
p.setPen(_st.placeholderFg);
|
||||
|
@ -3872,7 +3759,7 @@ void PhoneInput::clearText() {
|
|||
correctValue(QString(), 0, phone, pos);
|
||||
}
|
||||
|
||||
void PhoneInput::paintPlaceholder(Painter &p) {
|
||||
void PhoneInput::paintPlaceholder(Painter &p, TimeMs ms) {
|
||||
auto t = getLastText();
|
||||
if (!_pattern.isEmpty() && !t.isEmpty()) {
|
||||
auto ph = placeholder().mid(t.size());
|
||||
|
@ -3882,12 +3769,12 @@ void PhoneInput::paintPlaceholder(Painter &p) {
|
|||
int tw = phFont()->width(t);
|
||||
if (tw < phRect.width()) {
|
||||
phRect.setLeft(phRect.left() + tw);
|
||||
placeholderPreparePaint(p);
|
||||
placeholderPreparePaint(p, ms);
|
||||
p.drawText(phRect, ph, style::al_topleft);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MaskedInputField::paintPlaceholder(p);
|
||||
MaskedInputField::paintPlaceholder(p, ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -347,8 +347,6 @@ public:
|
|||
}
|
||||
void updatePlaceholder();
|
||||
|
||||
void step_placeholderFg(float64 ms, bool timer);
|
||||
void step_placeholderShift(float64 ms, bool timer);
|
||||
void step_border(float64 ms, bool timer);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
@ -470,14 +468,12 @@ private:
|
|||
|
||||
QString _placeholder, _placeholderFull;
|
||||
bool _placeholderVisible;
|
||||
anim::ivalue a_placeholderLeft;
|
||||
anim::fvalue a_placeholderOpacity;
|
||||
anim::fvalue a_placeholderFgActive;
|
||||
Animation _a_placeholderFg, _a_placeholderShift;
|
||||
FloatAnimation _a_placeholderFocused;
|
||||
FloatAnimation _a_placeholderVisible;
|
||||
|
||||
anim::fvalue a_borderOpacityActive;
|
||||
anim::fvalue a_borderFgActive;
|
||||
anim::fvalue a_borderFgError;
|
||||
anim::value a_borderOpacityActive;
|
||||
anim::value a_borderFgActive;
|
||||
anim::value a_borderFgError;
|
||||
Animation _a_border;
|
||||
|
||||
bool _focused, _error;
|
||||
|
@ -511,8 +507,6 @@ public:
|
|||
void setPlaceholderHidden(bool forcePlaceholderHidden);
|
||||
void finishPlaceholderAnimation();
|
||||
|
||||
void step_placeholderFg(float64 ms, bool timer);
|
||||
void step_placeholderShift(float64 ms, bool timer);
|
||||
void step_border(float64 ms, bool timer);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
@ -640,14 +634,12 @@ private:
|
|||
|
||||
QString _placeholder, _placeholderFull;
|
||||
bool _placeholderVisible;
|
||||
anim::ivalue a_placeholderLeft;
|
||||
anim::fvalue a_placeholderOpacity;
|
||||
anim::fvalue a_placeholderFgActive;
|
||||
Animation _a_placeholderFg, _a_placeholderShift;
|
||||
FloatAnimation _a_placeholderFocused;
|
||||
FloatAnimation _a_placeholderVisible;
|
||||
|
||||
anim::fvalue a_borderOpacityActive;
|
||||
anim::fvalue a_borderFgActive;
|
||||
anim::fvalue a_borderFgError;
|
||||
anim::value a_borderOpacityActive;
|
||||
anim::value a_borderFgActive;
|
||||
anim::value a_borderFgError;
|
||||
Animation _a_border;
|
||||
|
||||
bool _focused, _error;
|
||||
|
@ -676,8 +668,6 @@ public:
|
|||
|
||||
QRect getTextRect() const;
|
||||
|
||||
void step_placeholderFg(float64 ms, bool timer);
|
||||
void step_placeholderShift(float64 ms, bool timer);
|
||||
void step_border(float64 ms, bool timer);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
@ -736,13 +726,13 @@ protected:
|
|||
}
|
||||
void setCorrectedText(QString &now, int &nowCursor, const QString &newText, int newPos);
|
||||
|
||||
virtual void paintPlaceholder(Painter &p);
|
||||
virtual void paintPlaceholder(Painter &p, TimeMs ms);
|
||||
|
||||
style::font phFont() {
|
||||
return _st.font;
|
||||
}
|
||||
|
||||
void placeholderPreparePaint(Painter &p);
|
||||
void placeholderPreparePaint(Painter &p, TimeMs ms);
|
||||
const QString &placeholder() const;
|
||||
QRect placeholderRect() const;
|
||||
|
||||
|
@ -764,14 +754,12 @@ private:
|
|||
|
||||
QString _placeholder, _placeholderFull;
|
||||
bool _placeholderVisible, _placeholderFast;
|
||||
anim::ivalue a_placeholderLeft;
|
||||
anim::fvalue a_placeholderOpacity;
|
||||
anim::fvalue a_placeholderFgActive;
|
||||
Animation _a_placeholderFg, _a_placeholderShift;
|
||||
FloatAnimation _a_placeholderFocused;
|
||||
FloatAnimation _a_placeholderVisible;
|
||||
|
||||
anim::fvalue a_borderOpacityActive;
|
||||
anim::fvalue a_borderFgActive;
|
||||
anim::fvalue a_borderFgError;
|
||||
anim::value a_borderOpacityActive;
|
||||
anim::value a_borderFgActive;
|
||||
anim::value a_borderFgError;
|
||||
Animation _a_border;
|
||||
|
||||
bool _focused, _error;
|
||||
|
@ -822,7 +810,7 @@ protected:
|
|||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
|
||||
void paintPlaceholder(Painter &p) override;
|
||||
void paintPlaceholder(Painter &p, TimeMs ms) override;
|
||||
|
||||
private:
|
||||
QVector<int> _pattern;
|
||||
|
@ -850,7 +838,7 @@ public:
|
|||
|
||||
protected:
|
||||
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
|
||||
void paintPlaceholder(Painter &p) override;
|
||||
void paintPlaceholder(Painter &p, TimeMs ms) override;
|
||||
|
||||
private:
|
||||
QString _linkPlaceholder;
|
||||
|
@ -867,7 +855,7 @@ protected:
|
|||
void focusInEvent(QFocusEvent *e) override;
|
||||
|
||||
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
|
||||
void paintPlaceholder(Painter &p) override;
|
||||
void paintPlaceholder(Painter &p, TimeMs ms) override;
|
||||
|
||||
private:
|
||||
QString _defaultPlaceholder;
|
||||
|
|
|
@ -95,7 +95,7 @@ private:
|
|||
, y(y) {
|
||||
x.start(updateCallback, fromX, toX, duration);
|
||||
}
|
||||
IntAnimation x;
|
||||
FloatAnimation x;
|
||||
int fromX, toX;
|
||||
int y;
|
||||
};
|
||||
|
@ -143,7 +143,7 @@ void MultiSelect::Inner::Item::paint(Painter &p, int outerWidth, TimeMs ms) {
|
|||
paintOnce(p, _x, _y, outerWidth, ms);
|
||||
} else {
|
||||
for (auto i = _copies.begin(), e = _copies.end(); i != e;) {
|
||||
auto x = i->x.current(getms(), _x);
|
||||
auto x = qRound(i->x.current(getms(), _x));
|
||||
auto y = i->y;
|
||||
auto animating = i->x.animating();
|
||||
if (animating || (y == _y)) {
|
||||
|
@ -748,7 +748,7 @@ void MultiSelect::Inner::updateItemsGeometry() {
|
|||
}
|
||||
|
||||
void MultiSelect::Inner::updateHeightStep() {
|
||||
auto newHeight = _height.current(_newHeight);
|
||||
auto newHeight = qRound(_height.current(_newHeight));
|
||||
if (auto heightDelta = newHeight - height()) {
|
||||
resize(width(), newHeight);
|
||||
if (_resizedCallback) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue