mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
add users to groups by usernames, copy username from context menu in profile, 0.7.25.dev version
This commit is contained in:
parent
489b151d49
commit
8c7a35c973
18 changed files with 963 additions and 245 deletions
|
@ -1,9 +1,9 @@
|
|||
@echo OFF
|
||||
|
||||
set "AppVersion=7024"
|
||||
set "AppVersionStrSmall=0.7.24"
|
||||
set "AppVersionStr=0.7.24"
|
||||
set "AppVersionStrFull=0.7.24.0"
|
||||
set "AppVersion=7025"
|
||||
set "AppVersionStrSmall=0.7.25"
|
||||
set "AppVersionStr=0.7.25"
|
||||
set "AppVersionStrFull=0.7.25.0"
|
||||
set "DevChannel=1"
|
||||
|
||||
if %DevChannel% neq 0 goto preparedev
|
||||
|
|
|
@ -313,6 +313,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
"lng_create_group_next" = "Next";
|
||||
"lng_create_group_title" = "New Group";
|
||||
|
||||
"lng_failed_add_participant" = "Could not add user. Try again later.";
|
||||
|
||||
"lng_sure_delete_contact" = "Are you sure, you want to delete {contact} from your contact list?";
|
||||
"lng_sure_delete_history" = "Are you sure, you want to delete all message history with {contact}?\n\nThis action cannot be undone.";
|
||||
|
||||
|
@ -489,8 +491,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
||||
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
||||
"lng_new_version7022" = "— Reply to specific messages in groups\n— Mention @usernames in groups to notify multiple users";
|
||||
"lng_new_version7022_appstore" = "— Reply to specific messages in groups\n— Mention @usernames in groups to notify multiple users";
|
||||
"lng_new_version7026" = "— Add a comment before forwarded messages\n— Hashtags suggestions in new message and search fields (based on recent searches)\n— Button to jump back to a reply after viewing the original message\n— Add people to groups by username";
|
||||
"lng_new_version7026_appstore" = "— Add a comment before forwarded messages\n— Hashtags suggestions in new message and search fields (based on recent searches)\n— Button to jump back to a reply after viewing the original message\n— Add people to groups by username";
|
||||
|
||||
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
||||
|
||||
|
|
|
@ -653,10 +653,10 @@ void Application::checkMapVersion() {
|
|||
psRegisterCustomScheme();
|
||||
if (Local::oldMapVersion()) {
|
||||
QString versionFeatures;
|
||||
if (DevChannel && Local::oldMapVersion() < 7024) {
|
||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Forward messages with comment or sticker before them\n\xe2\x80\x94 Recent hashtags autocomplete in message and search fields\n\xe2\x80\x94 Move from reply to original message and back");
|
||||
} else if (!DevChannel && Local::oldMapVersion() < 7023) {
|
||||
versionFeatures = lang(lng_new_version7022).trimmed().replace('@', qsl("@") + QChar(0x200D));
|
||||
if (DevChannel && Local::oldMapVersion() < 7025) {
|
||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Add people to groups by username\n\xe2\x80\x94 Copy @username from profile context menu").replace('@', qsl("@") + QChar(0x200D));
|
||||
} else if (!DevChannel && Local::oldMapVersion() < 7026) {
|
||||
versionFeatures = lang(lng_new_version7026).trimmed();
|
||||
}
|
||||
if (!versionFeatures.isEmpty()) {
|
||||
versionFeatures = lng_new_version_wrap(lt_version, QString::fromStdWString(AppVersionStr), lt_changes, versionFeatures, lt_link, qsl("https://desktop.telegram.org/#changelog"));
|
||||
|
|
|
@ -28,6 +28,8 @@ _sel(0),
|
|||
_filteredSel(-1),
|
||||
_mouseSel(false),
|
||||
_selCount(0),
|
||||
_searching(false),
|
||||
_byUsernameSel(-1),
|
||||
_addContactLnk(this, lang(lng_add_contact_button)) {
|
||||
|
||||
connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
|
||||
|
@ -101,6 +103,16 @@ void AddParticipantInner::loadProfilePhotos(int32 yFrom) {
|
|||
preloadFrom->history->peer->photo->load();
|
||||
}
|
||||
}
|
||||
yFrom -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
yTo -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
int32 from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsername.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsername.size()) to = _byUsername.size();
|
||||
for (; from < to; ++from) {
|
||||
_byUsername[from]->photo->load();
|
||||
}
|
||||
}
|
||||
} else if (!_filtered.isEmpty()) {
|
||||
int32 from = yFrom / rh;
|
||||
if (from < 0) from = 0;
|
||||
|
@ -112,6 +124,16 @@ void AddParticipantInner::loadProfilePhotos(int32 yFrom) {
|
|||
_filtered[from]->history->peer->photo->load();
|
||||
}
|
||||
}
|
||||
yFrom -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
yTo -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsernameFiltered.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size();
|
||||
for (; from < to; ++from) {
|
||||
_byUsernameFiltered[from]->photo->load();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +144,7 @@ AddParticipantInner::ContactData *AddParticipantInner::contactData(DialogRow *ro
|
|||
ContactsData::const_iterator i = _contactsData.constFind(user);
|
||||
if (i == _contactsData.cend()) {
|
||||
_contactsData.insert(user, data = new ContactData());
|
||||
data->inchat = _chat->participants.constFind(user) != _chat->participants.cend();
|
||||
data->inchat = _chat->participants.contains(user);
|
||||
data->check = false;
|
||||
data->name.setText(st::profileListNameFont, user->name, _textNameOptions);
|
||||
data->online = App::onlineText(user, _time);
|
||||
|
@ -134,12 +156,9 @@ AddParticipantInner::ContactData *AddParticipantInner::contactData(DialogRow *ro
|
|||
return data;
|
||||
}
|
||||
|
||||
void AddParticipantInner::paintDialog(QPainter &p, DialogRow *row, bool sel) {
|
||||
void AddParticipantInner::paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel) {
|
||||
int32 left = st::profileListPadding.width();
|
||||
|
||||
UserData *user = row->history->peer->asUser();
|
||||
ContactData *data = contactData(row);
|
||||
|
||||
if (data->inchat || data->check || _selCount + _chat->count >= cMaxGroupCount()) {
|
||||
sel = false;
|
||||
}
|
||||
|
@ -161,13 +180,29 @@ void AddParticipantInner::paintDialog(QPainter &p, DialogRow *row, bool sel) {
|
|||
p.drawPixmap(QPoint(width() - st::profileCheckRect.pxWidth() - st::profileCheckDeltaX, st::profileListPadding.height() + (st::profileListPhotoSize - st::profileCheckRect.pxHeight()) / 2 - st::profileCheckDeltaY), App::sprite(), (data->check ? st::profileCheckActiveRect : st::profileCheckRect));
|
||||
}
|
||||
|
||||
bool uname = (data->online.at(0) == '@');
|
||||
p.setFont(st::profileSubFont->f);
|
||||
if (data->inchat || data->check) {
|
||||
p.setPen(st::white->p);
|
||||
if (uname && !data->inchat && !data->check && !_lastQuery.isEmpty() && user->username.startsWith(_lastQuery, Qt::CaseInsensitive)) {
|
||||
int32 availw = width() - (left + st::profileListPhotoSize + st::profileListPadding.width() * 2);
|
||||
QString first = '@' + user->username.mid(0, _lastQuery.size()), second = user->username.mid(_lastQuery.size());
|
||||
int32 w = st::profileSubFont->m.width(first);
|
||||
if (w >= availw || second.isEmpty()) {
|
||||
p.setPen(st::profileOnlineColor->p);
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(first, Qt::ElideRight, availw));
|
||||
} else {
|
||||
p.setPen(st::profileOnlineColor->p);
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, first);
|
||||
p.setPen(st::profileOfflineColor->p);
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width() + w, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(second, Qt::ElideRight, availw - w));
|
||||
}
|
||||
} else {
|
||||
p.setPen((App::onlineColorUse(user->onlineTill, _time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
|
||||
if (data->inchat || data->check) {
|
||||
p.setPen(st::white->p);
|
||||
} else {
|
||||
p.setPen(((uname || App::onlineColorUse(user->onlineTill, _time)) ? st::profileOnlineColor : st::profileOfflineColor)->p);
|
||||
}
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online);
|
||||
}
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online);
|
||||
}
|
||||
|
||||
void AddParticipantInner::paintEvent(QPaintEvent *e) {
|
||||
|
@ -177,40 +212,85 @@ void AddParticipantInner::paintEvent(QPaintEvent *e) {
|
|||
_time = unixtime();
|
||||
p.fillRect(r, st::white->b);
|
||||
|
||||
int32 yFrom = r.top();
|
||||
int32 yFrom = r.top(), yTo = r.bottom();
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2;
|
||||
if (_filter.isEmpty()) {
|
||||
if (_contacts->list.count) {
|
||||
_contacts->list.adjustCurrent(yFrom, rh);
|
||||
if (_contacts->list.count || !_byUsername.isEmpty()) {
|
||||
if (_contacts->list.count) {
|
||||
_contacts->list.adjustCurrent(yFrom, rh);
|
||||
|
||||
DialogRow *drawFrom = _contacts->list.current;
|
||||
p.translate(0, drawFrom->pos * rh);
|
||||
while (drawFrom != _contacts->list.end && drawFrom->pos * rh < r.bottom()) {
|
||||
paintDialog(p, drawFrom, (drawFrom == _sel));
|
||||
p.translate(0, rh);
|
||||
drawFrom = drawFrom->next;
|
||||
DialogRow *drawFrom = _contacts->list.current;
|
||||
p.translate(0, drawFrom->pos * rh);
|
||||
while (drawFrom != _contacts->list.end && drawFrom->pos * rh < yTo) {
|
||||
paintDialog(p, drawFrom->history->peer->asUser(), contactData(drawFrom), (drawFrom == _sel));
|
||||
p.translate(0, rh);
|
||||
drawFrom = drawFrom->next;
|
||||
}
|
||||
}
|
||||
if (!_byUsername.isEmpty()) {
|
||||
p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b);
|
||||
p.setFont(st::searchedBarFont->f);
|
||||
p.setPen(st::searchedBarColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center);
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
|
||||
yFrom -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
yTo -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
int32 from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsername.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsername.size()) to = _byUsername.size();
|
||||
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _byUsername[from], d_byUsername[from], (_byUsernameSel == from));
|
||||
p.translate(0, rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
p.setPen(st::noContactsColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_contacts : lng_contacts_loading), style::al_center);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight - ((cContactsReceived() && !_searching) ? st::noContactsFont->height : 0)), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_loading), style::al_center);
|
||||
}
|
||||
} else {
|
||||
if (_filtered.isEmpty()) {
|
||||
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
p.setPen(st::noContactsColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_not_found), style::al_center);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_loading), style::al_center);
|
||||
} else {
|
||||
int32 from = yFrom / rh;
|
||||
if (from < 0) from = 0;
|
||||
if (from < _filtered.size()) {
|
||||
int32 to = (r.bottom() / rh) + 1;
|
||||
if (to > _filtered.size()) to = _filtered.size();
|
||||
if (!_filtered.isEmpty()) {
|
||||
int32 from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _filtered.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _filtered.size()) to = _filtered.size();
|
||||
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _filtered[from], (_filteredSel == from));
|
||||
p.translate(0, rh);
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _filtered[from]->history->peer->asUser(), contactData(_filtered[from]), (_filteredSel == from));
|
||||
p.translate(0, rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_byUsernameFiltered.isEmpty()) {
|
||||
p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b);
|
||||
p.setFont(st::searchedBarFont->f);
|
||||
p.setPen(st::searchedBarColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center);
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
|
||||
yFrom -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
yTo -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
int32 from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsernameFiltered.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size();
|
||||
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _byUsernameFiltered[from], d_byUsernameFiltered[from], (_byUsernameSel == from));
|
||||
p.translate(0, rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +303,11 @@ void AddParticipantInner::enterEvent(QEvent *e) {
|
|||
|
||||
void AddParticipantInner::leaveEvent(QEvent *e) {
|
||||
setMouseTracking(false);
|
||||
updateSel();
|
||||
if (_sel || _filteredSel >= 0 || _byUsernameSel >= 0) {
|
||||
_sel = 0;
|
||||
_filteredSel = _byUsernameSel = -1;
|
||||
parentWidget()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void AddParticipantInner::mouseMoveEvent(QMouseEvent *e) {
|
||||
|
@ -245,30 +329,112 @@ void AddParticipantInner::chooseParticipant() {
|
|||
_time = unixtime();
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from;
|
||||
if (_filter.isEmpty()) {
|
||||
if (!_sel || contactData(_sel)->inchat) return;
|
||||
changeCheckState(_sel);
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) {
|
||||
if (d_byUsername[_byUsernameSel]->inchat) return;
|
||||
changeCheckState(d_byUsername[_byUsernameSel]);
|
||||
} else {
|
||||
if (!_sel || contactData(_sel)->inchat) return;
|
||||
changeCheckState(_sel);
|
||||
}
|
||||
} else {
|
||||
if (_filteredSel < 0 || _filteredSel >= _filtered.size() || contactData(_filtered[_filteredSel])->inchat) return;
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) {
|
||||
if (d_byUsernameFiltered[_byUsernameSel]->inchat) return;
|
||||
changeCheckState(d_byUsernameFiltered[_byUsernameSel]);
|
||||
|
||||
DialogRow *row = _filtered[_filteredSel];
|
||||
changeCheckState(row);
|
||||
|
||||
PeerData *peer = row->history->peer;
|
||||
ContactData *moving = d_byUsernameFiltered[_byUsernameSel];
|
||||
int32 i = 0, l = d_byUsername.size();
|
||||
for (; i < l; ++i) {
|
||||
if (d_byUsername[i] == moving) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == l) {
|
||||
d_byUsername.push_back(moving);
|
||||
_byUsername.push_back(_byUsernameFiltered[_byUsernameSel]);
|
||||
for (i = 0, l = _byUsernameDatas.size(); i < l;) {
|
||||
if (_byUsernameDatas[i] == moving) {
|
||||
_byUsernameDatas.removeAt(i);
|
||||
--l;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_filteredSel < 0 || _filteredSel >= _filtered.size() || contactData(_filtered[_filteredSel])->inchat) return;
|
||||
changeCheckState(_filtered[_filteredSel]);
|
||||
}
|
||||
emit selectAllQuery();
|
||||
}
|
||||
parentWidget()->update();
|
||||
}
|
||||
|
||||
void AddParticipantInner::changeCheckState(DialogRow *row) {
|
||||
if (contactData(row)->check) {
|
||||
contactData(row)->check = false;
|
||||
changeCheckState(contactData(row));
|
||||
}
|
||||
|
||||
void AddParticipantInner::changeCheckState(ContactData *data) {
|
||||
if (data->check) {
|
||||
data->check = false;
|
||||
--_selCount;
|
||||
} else if (_selCount + _chat->count < cMaxGroupCount()) {
|
||||
contactData(row)->check = true;
|
||||
data->check = true;
|
||||
++_selCount;
|
||||
}
|
||||
}
|
||||
|
||||
void AddParticipantInner::peopleReceived(const QString &query, const QVector<MTPContactFound> &people) {
|
||||
_lastQuery = query.toLower().trimmed();
|
||||
if (_lastQuery.at(0) == '@') _lastQuery = _lastQuery.mid(1);
|
||||
int32 already = _byUsernameFiltered.size();
|
||||
_byUsernameFiltered.reserve(already + people.size());
|
||||
d_byUsernameFiltered.reserve(already + people.size());
|
||||
for (QVector<MTPContactFound>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
|
||||
int32 uid = i->c_contactFound().vuser_id.v, j = 0;
|
||||
for (; j < already; ++j) {
|
||||
if (_byUsernameFiltered[j]->id == uid) break;
|
||||
}
|
||||
if (j == already) {
|
||||
UserData *u = App::user(uid);
|
||||
ContactData *d = new ContactData();
|
||||
_byUsernameDatas.push_back(d);
|
||||
d->inchat = _chat->participants.contains(u);
|
||||
d->check = false;
|
||||
d->name.setText(st::profileListNameFont, u->name, _textNameOptions);
|
||||
d->online = '@' + u->username;
|
||||
|
||||
_byUsernameFiltered.push_back(u);
|
||||
d_byUsernameFiltered.push_back(d);
|
||||
}
|
||||
}
|
||||
_searching = false;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void AddParticipantInner::refresh() {
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2;
|
||||
if (_filter.isEmpty()) {
|
||||
if (_contacts->list.count || !_byUsername.isEmpty()) {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
resize(width(), (_contacts->list.count * rh) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * rh)));
|
||||
} else {
|
||||
if (cContactsReceived()) {
|
||||
if (_addContactLnk.isHidden()) _addContactLnk.show();
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
}
|
||||
resize(width(), st::noContactsHeight);
|
||||
}
|
||||
} else {
|
||||
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
resize(width(), st::noContactsHeight);
|
||||
} else {
|
||||
resize(width(), (_filtered.size() * rh) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * rh)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatData *AddParticipantInner::chat() {
|
||||
return _chat;
|
||||
}
|
||||
|
@ -281,6 +447,11 @@ QVector<UserData*> AddParticipantInner::selected() {
|
|||
result.push_back(i.key());
|
||||
}
|
||||
}
|
||||
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
if (d_byUsername[i]->check) {
|
||||
result.push_back(_byUsername[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -288,23 +459,31 @@ void AddParticipantInner::updateSel() {
|
|||
if (!_mouseSel) return;
|
||||
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2;
|
||||
if (_filter.isEmpty()) {
|
||||
DialogRow *newSel = rect().contains(p) ? _contacts->list.rowAtY(p.y(), rh) : 0;
|
||||
if (newSel != _sel) {
|
||||
DialogRow *newSel = (in && (p.y() >= 0) && (p.y() < _contacts->list.count * rh)) ? _contacts->list.rowAtY(p.y(), rh) : 0;
|
||||
int32 byUsernameSel = (in && p.y() >= _contacts->list.count * rh + st::searchedBarHeight) ? ((p.y() - _contacts->list.count * rh - st::searchedBarHeight) / rh) : -1;
|
||||
if (byUsernameSel >= _byUsername.size()) byUsernameSel = -1;
|
||||
if (newSel != _sel || byUsernameSel != _byUsernameSel) {
|
||||
_sel = newSel;
|
||||
_byUsernameSel = byUsernameSel;
|
||||
parentWidget()->update();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int32 newFilteredSel = (p.y() >= 0 && rect().contains(p)) ? (p.y() / rh) : -1;
|
||||
if (newFilteredSel != _filteredSel) {
|
||||
int32 newFilteredSel = (in && p.y() >= 0 && p.y() < _filtered.size() * rh) ? (p.y() / rh) : -1;
|
||||
int32 byUsernameSel = (in && p.y() >= _filtered.size() * rh + st::searchedBarHeight) ? ((p.y() - _filtered.size() * rh - st::searchedBarHeight) / rh) : -1;
|
||||
if (byUsernameSel >= _byUsernameFiltered.size()) byUsernameSel = -1;
|
||||
if (newFilteredSel != _filteredSel || byUsernameSel != _byUsernameSel) {
|
||||
_filteredSel = newFilteredSel;
|
||||
_byUsernameSel = byUsernameSel;
|
||||
parentWidget()->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddParticipantInner::updateFilter(QString filter) {
|
||||
_lastQuery = filter.toLower().trimmed();
|
||||
filter = textSearchKey(filter);
|
||||
|
||||
_time = unixtime();
|
||||
|
@ -324,22 +503,32 @@ void AddParticipantInner::updateFilter(QString filter) {
|
|||
if (_filter != filter) {
|
||||
int32 rh = (st::profileListPhotoSize + st::profileListPadding.height() * 2);
|
||||
_filter = filter;
|
||||
|
||||
_byUsernameFiltered.clear();
|
||||
d_byUsernameFiltered.clear();
|
||||
for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) {
|
||||
delete _byUsernameDatas[i];
|
||||
}
|
||||
_byUsernameDatas.clear();
|
||||
|
||||
if (_filter.isEmpty()) {
|
||||
_sel = 0;
|
||||
if (_contacts->list.count) {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
resize(width(), _contacts->list.count * rh);
|
||||
_sel = _contacts->list.begin;
|
||||
while (_sel->next->next &&& contactData(_sel)->inchat) {
|
||||
_sel = _sel->next;
|
||||
}
|
||||
} else {
|
||||
resize(width(), st::noContactsHeight);
|
||||
if (cContactsReceived()) {
|
||||
if (_addContactLnk.isHidden()) _addContactLnk.show();
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
}
|
||||
}
|
||||
if (!_sel && !_byUsername.isEmpty()) {
|
||||
_byUsernameSel = 0;
|
||||
while (_byUsernameSel < _byUsername.size() && d_byUsername[_byUsernameSel]->inchat) {
|
||||
++_byUsernameSel;
|
||||
}
|
||||
if (_byUsernameSel == _byUsername.size()) _byUsernameSel = -1;
|
||||
} else {
|
||||
_byUsernameSel = -1;
|
||||
}
|
||||
refresh();
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi;
|
||||
|
@ -381,17 +570,48 @@ void AddParticipantInner::updateFilter(QString filter) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
_byUsernameFiltered.reserve(_byUsername.size());
|
||||
d_byUsernameFiltered.reserve(d_byUsername.size());
|
||||
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
const PeerData::Names &names(_byUsername[i]->names);
|
||||
PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni;
|
||||
for (fi = fb; fi != fe; ++fi) {
|
||||
QString filterName(*fi);
|
||||
for (ni = nb; ni != ne; ++ni) {
|
||||
if (ni->startsWith(*fi)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ni == ne) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fi == fe) {
|
||||
_byUsernameFiltered.push_back(_byUsername[i]);
|
||||
d_byUsernameFiltered.push_back(d_byUsername[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
_filteredSel = _filtered.isEmpty() ? -1 : 0;
|
||||
while (_filteredSel < _filtered.size() - 1 && contactData(_filtered[_filteredSel])->inchat) {
|
||||
++_filteredSel;
|
||||
_filteredSel = -1;
|
||||
if (!_filtered.isEmpty()) {
|
||||
for (_filteredSel = 0; (_filteredSel < _filtered.size()) && contactData(_filtered[_filteredSel])->inchat;) {
|
||||
++_filteredSel;
|
||||
}
|
||||
if (_filteredSel == _filtered.size()) _filteredSel = -1;
|
||||
}
|
||||
_byUsernameSel = -1;
|
||||
if (_filteredSel < 0 && !_byUsernameFiltered.isEmpty()) {
|
||||
for (_byUsernameSel = 0; (_byUsernameSel < _byUsernameFiltered.size()) && d_byUsernameFiltered[_byUsernameSel]->inchat;) {
|
||||
++_byUsernameSel;
|
||||
}
|
||||
if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1;
|
||||
}
|
||||
|
||||
if (!_filtered.isEmpty()) {
|
||||
resize(width(), _filtered.size() * rh);
|
||||
} else {
|
||||
resize(width(), st::noContactsHeight);
|
||||
}
|
||||
refresh();
|
||||
|
||||
_searching = true;
|
||||
emit searchByUsername();
|
||||
}
|
||||
if (parentWidget()) parentWidget()->update();
|
||||
loadProfilePhotos(0);
|
||||
|
@ -427,7 +647,13 @@ void AddParticipantInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newR
|
|||
}
|
||||
|
||||
AddParticipantInner::~AddParticipantInner() {
|
||||
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
|
||||
for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
for (ByUsernameDatas::const_iterator i = d_byUsername.cbegin(), e = d_byUsername.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
for (ByUsernameDatas::const_iterator i = _byUsernameDatas.cbegin(), e = _byUsernameDatas.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
@ -441,82 +667,106 @@ void AddParticipantInner::selectSkip(int32 dir) {
|
|||
_mouseSel = false;
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, origDir = dir;
|
||||
if (_filter.isEmpty()) {
|
||||
int cur = 0;
|
||||
if (_sel) {
|
||||
if (dir > 0) {
|
||||
while (dir && _sel->next->next) {
|
||||
_sel = _sel->next;
|
||||
--dir;
|
||||
for (DialogRow *i = _contacts->list.begin; i != _sel; i = i->next) {
|
||||
++cur;
|
||||
}
|
||||
} else {
|
||||
cur = (_byUsernameSel >= 0) ? (_contacts->list.count + _byUsernameSel) : -1;
|
||||
}
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_sel = _contacts->list.count ? _contacts->list.begin : 0;
|
||||
_byUsernameSel = (!_contacts->list.count && !_byUsername.isEmpty()) ? 0 : -1;
|
||||
} else if (cur >= _contacts->list.count) {
|
||||
_sel = 0;
|
||||
_byUsernameSel = cur - _contacts->list.count;
|
||||
if (_byUsernameSel >= _byUsername.size()) _byUsernameSel = _byUsername.size() - 1;
|
||||
} else {
|
||||
for (_sel = _contacts->list.begin; cur; _sel = _sel->next) {
|
||||
--cur;
|
||||
}
|
||||
_byUsernameSel = -1;
|
||||
}
|
||||
if (dir > 0) {
|
||||
while (_sel && _sel->next && contactData(_sel)->inchat) {
|
||||
_sel = _sel->next;
|
||||
}
|
||||
if (!_sel || !_sel->next) {
|
||||
_sel = 0;
|
||||
if (!_byUsername.isEmpty()) {
|
||||
if (_byUsernameSel < 0) _byUsernameSel = 0;
|
||||
for (; _byUsernameSel < _byUsername.size() && d_byUsername[_byUsernameSel]->inchat;) {
|
||||
++_byUsernameSel;
|
||||
}
|
||||
if (_byUsernameSel == _byUsername.size()) _byUsernameSel = -1;
|
||||
}
|
||||
while (contactData(_sel)->inchat && _sel->next->next) {
|
||||
_sel = _sel->next;
|
||||
}
|
||||
if (contactData(_sel)->inchat) {
|
||||
while (contactData(_sel)->inchat && _sel->prev) {
|
||||
}
|
||||
} else {
|
||||
while (_byUsernameSel >= 0 && d_byUsername[_byUsernameSel]->inchat) {
|
||||
--_byUsernameSel;
|
||||
}
|
||||
if (_byUsernameSel < 0) {
|
||||
if (_contacts->list.count) {
|
||||
if (!_sel) _sel = _contacts->list.end->prev;
|
||||
for (; _sel && contactData(_sel)->inchat;) {
|
||||
_sel = _sel->prev;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (dir && _sel->prev) {
|
||||
_sel = _sel->prev;
|
||||
++dir;
|
||||
}
|
||||
while (contactData(_sel)->inchat && _sel->prev) {
|
||||
_sel = _sel->prev;
|
||||
}
|
||||
if (contactData(_sel)->inchat) {
|
||||
while (contactData(_sel)->inchat && _sel->next->next) {
|
||||
_sel = _sel->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (dir > 0 && _contacts->list.count) {
|
||||
_sel = _contacts->list.begin;
|
||||
while (contactData(_sel)->inchat && _sel->next->next) {
|
||||
_sel = _sel->next;
|
||||
}
|
||||
}
|
||||
if (_sel) {
|
||||
if (contactData(_sel)->inchat) {
|
||||
_sel = 0;
|
||||
} else {
|
||||
emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh);
|
||||
}
|
||||
emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
emit mustScrollTo((_contacts->list.count + _byUsernameSel) * rh + st::searchedBarHeight, (_contacts->list.count + _byUsernameSel + 1) * rh + st::searchedBarHeight);
|
||||
}
|
||||
} else {
|
||||
int cur = (_filteredSel >= 0) ? _filteredSel : ((_byUsernameSel >= 0) ? (_filtered.size() + _byUsernameSel) : -1);
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_filteredSel = _filtered.isEmpty() ? -1 : 0;
|
||||
_byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1;
|
||||
} else if (cur >= _filtered.size()) {
|
||||
_filteredSel = -1;
|
||||
_byUsernameSel = cur - _filtered.size();
|
||||
if (_byUsernameSel >= _byUsernameFiltered.size()) _byUsernameSel = _byUsernameFiltered.size() - 1;
|
||||
} else {
|
||||
_filteredSel = cur;
|
||||
_byUsernameSel = -1;
|
||||
}
|
||||
if (dir > 0) {
|
||||
if (_filteredSel < 0 && dir > 1) {
|
||||
_filteredSel = 0;
|
||||
}
|
||||
_filteredSel += dir;
|
||||
while (_filteredSel < _filtered.size() - 1 && contactData(_filtered[_filteredSel])->inchat) {
|
||||
while (_filteredSel >= 0 && _filteredSel < _filtered.size() && contactData(_filtered[_filteredSel])->inchat) {
|
||||
++_filteredSel;
|
||||
}
|
||||
if (_filteredSel >= _filtered.size()) {
|
||||
_filteredSel = _filtered.size() - 1;
|
||||
}
|
||||
while (_filteredSel > 0 && contactData(_filtered[_filteredSel])->inchat) {
|
||||
--_filteredSel;
|
||||
}
|
||||
} else if (_filteredSel > 0) {
|
||||
_filteredSel += dir;
|
||||
if (_filteredSel < 0) {
|
||||
_filteredSel = 0;
|
||||
}
|
||||
if (_filteredSel < _filtered.size() - 1) {
|
||||
while (_filteredSel > 0 && contactData(_filtered[_filteredSel])->inchat) {
|
||||
--_filteredSel;
|
||||
if (_filteredSel < 0 || _filteredSel >= _filtered.size()) {
|
||||
_filteredSel = -1;
|
||||
if (!_byUsernameFiltered.isEmpty()) {
|
||||
if (_byUsernameSel < 0) _byUsernameSel = 0;
|
||||
for (; _byUsernameSel < _byUsernameFiltered.size() && d_byUsernameFiltered[_byUsernameSel]->inchat;) {
|
||||
++_byUsernameSel;
|
||||
}
|
||||
if (_byUsernameSel == _byUsernameFiltered.size()) _byUsernameSel = -1;
|
||||
}
|
||||
}
|
||||
while (_filteredSel < _filtered.size() - 1 && contactData(_filtered[_filteredSel])->inchat) {
|
||||
++_filteredSel;
|
||||
} else {
|
||||
while (_byUsernameSel >= 0 && d_byUsernameFiltered[_byUsernameSel]->inchat) {
|
||||
--_byUsernameSel;
|
||||
}
|
||||
if (_byUsernameSel < 0) {
|
||||
if (!_filtered.isEmpty()) {
|
||||
if (_filteredSel < 0) _filteredSel = _filtered.size() - 1;
|
||||
for (; _filteredSel >= 0 && contactData(_filtered[_filteredSel])->inchat;) {
|
||||
--_filteredSel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_filteredSel >= 0) {
|
||||
if (contactData(_filtered[_filteredSel])->inchat) {
|
||||
_filteredSel = -1;
|
||||
} else {
|
||||
emit mustScrollTo(_filteredSel * rh, (_filteredSel + 1) * rh);
|
||||
}
|
||||
emit mustScrollTo(_filteredSel * rh, (_filteredSel + 1) * rh);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
int skip = _filtered.size() * rh + st::searchedBarHeight;
|
||||
emit mustScrollTo(skip + _byUsernameSel * rh, skip + (_byUsernameSel + 1) * rh);
|
||||
}
|
||||
}
|
||||
parentWidget()->update();
|
||||
|
@ -534,7 +784,7 @@ AddParticipantBox::AddParticipantBox(ChatData *chat) :
|
|||
_filter(this, st::contactsFilter, lang(lng_participant_filter)),
|
||||
_invite(this, lang(lng_participant_invite), st::btnSelectDone),
|
||||
_cancel(this, lang(lng_cancel), st::btnSelectCancel),
|
||||
_hiding(false), a_opacity(0, 1), af_opacity(anim::linear) {
|
||||
_hiding(false), a_opacity(0, 1) {
|
||||
|
||||
_width = st::participantWidth;
|
||||
_height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom();
|
||||
|
@ -553,12 +803,81 @@ AddParticipantBox::AddParticipantBox(ChatData *chat) :
|
|||
connect(&_filter, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||
connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int)));
|
||||
connect(&_inner, SIGNAL(selectAllQuery()), &_filter, SLOT(selectAll()));
|
||||
connect(&_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
||||
|
||||
_searchTimer.setSingleShot(true);
|
||||
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
|
||||
|
||||
showAll();
|
||||
_cache = myGrab(this, rect());
|
||||
hideAll();
|
||||
}
|
||||
|
||||
bool AddParticipantBox::onSearchByUsername(bool searchCache) {
|
||||
QString q = _filter.text().trimmed();
|
||||
if (q.isEmpty()) {
|
||||
if (_peopleRequest) {
|
||||
_peopleRequest = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (q.size() >= MinUsernameLength) {
|
||||
if (searchCache) {
|
||||
PeopleCache::const_iterator i = _peopleCache.constFind(q);
|
||||
if (i != _peopleCache.cend()) {
|
||||
_peopleQuery = q;
|
||||
_peopleRequest = 0;
|
||||
peopleReceived(i.value(), 0);
|
||||
return true;
|
||||
}
|
||||
} else if (_peopleQuery != q) {
|
||||
_peopleQuery = q;
|
||||
_peopleFull = false;
|
||||
_peopleRequest = MTP::send(MTPcontacts_Search(MTP_string(_peopleQuery), MTP_int(SearchPeopleLimit)), rpcDone(&AddParticipantBox::peopleReceived), rpcFail(&AddParticipantBox::peopleFailed));
|
||||
_peopleQueries.insert(_peopleRequest, _peopleQuery);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddParticipantBox::onNeedSearchByUsername() {
|
||||
if (!onSearchByUsername(true)) {
|
||||
_searchTimer.start(AutoSearchTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void AddParticipantBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId req) {
|
||||
QString q = _peopleQuery;
|
||||
|
||||
PeopleQueries::iterator i = _peopleQueries.find(req);
|
||||
if (i != _peopleQueries.cend()) {
|
||||
q = i.value();
|
||||
_peopleCache[q] = result;
|
||||
_peopleQueries.erase(i);
|
||||
}
|
||||
|
||||
if (_peopleRequest == req) {
|
||||
switch (result.type()) {
|
||||
case mtpc_contacts_found: {
|
||||
App::feedUsers(result.c_contacts_found().vusers);
|
||||
_inner.peopleReceived(q, result.c_contacts_found().vresults.c_vector().v);
|
||||
} break;
|
||||
}
|
||||
|
||||
_peopleRequest = 0;
|
||||
_inner.updateSel();
|
||||
onScroll();
|
||||
}
|
||||
}
|
||||
|
||||
bool AddParticipantBox::peopleFailed(const RPCError &error, mtpRequestId req) {
|
||||
if (_peopleRequest == req) {
|
||||
_peopleRequest = 0;
|
||||
_peopleFull = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddParticipantBox::hideAll() {
|
||||
_filter.hide();
|
||||
_scroll.hide();
|
||||
|
@ -643,7 +962,7 @@ void AddParticipantBox::animStep(float64 dt) {
|
|||
_filter.setFocus();
|
||||
}
|
||||
} else {
|
||||
a_opacity.update(dt, af_opacity);
|
||||
a_opacity.update(dt, anim::linear);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
class AddParticipantInner : public QWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
struct ContactData;
|
||||
|
||||
public:
|
||||
|
||||
AddParticipantInner(ChatData *chat);
|
||||
|
@ -33,7 +37,7 @@ public:
|
|||
void mousePressEvent(QMouseEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
void paintDialog(QPainter &p, DialogRow *row, bool sel);
|
||||
void paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel);
|
||||
void updateFilter(QString filter = QString());
|
||||
|
||||
void selectSkip(int32 dir);
|
||||
|
@ -42,6 +46,11 @@ public:
|
|||
void loadProfilePhotos(int32 yFrom);
|
||||
void chooseParticipant();
|
||||
void changeCheckState(DialogRow *row);
|
||||
void changeCheckState(ContactData *data);
|
||||
|
||||
void peopleReceived(const QString &query, const QVector<MTPContactFound> &people);
|
||||
|
||||
void refresh();
|
||||
|
||||
ChatData *chat();
|
||||
QVector<UserData*> selected();
|
||||
|
@ -52,6 +61,7 @@ signals:
|
|||
|
||||
void mustScrollTo(int ymin, int ymax);
|
||||
void selectAllQuery();
|
||||
void searchByUsername();
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -76,23 +86,32 @@ private:
|
|||
|
||||
int32 _selCount;
|
||||
|
||||
typedef struct {
|
||||
struct ContactData {
|
||||
Text name;
|
||||
QString online;
|
||||
bool inchat;
|
||||
bool check;
|
||||
} ContactData;
|
||||
};
|
||||
typedef QMap<UserData*, ContactData*> ContactsData;
|
||||
ContactsData _contactsData;
|
||||
|
||||
ContactData *contactData(DialogRow *row);
|
||||
|
||||
bool _searching;
|
||||
QString _lastQuery;
|
||||
typedef QVector<UserData*> ByUsernameRows;
|
||||
typedef QVector<ContactData*> ByUsernameDatas;
|
||||
ByUsernameRows _byUsername, _byUsernameFiltered;
|
||||
ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas
|
||||
ByUsernameDatas _byUsernameDatas;
|
||||
int32 _byUsernameSel;
|
||||
|
||||
QPoint _lastMousePos;
|
||||
LinkButton _addContactLnk;
|
||||
|
||||
};
|
||||
|
||||
class AddParticipantBox : public LayeredWidget {
|
||||
class AddParticipantBox : public LayeredWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -113,6 +132,9 @@ public slots:
|
|||
void onScroll();
|
||||
void onInvite();
|
||||
|
||||
bool onSearchByUsername(bool searchCache = false);
|
||||
void onNeedSearchByUsername();
|
||||
|
||||
private:
|
||||
|
||||
void hideAll();
|
||||
|
@ -129,5 +151,18 @@ private:
|
|||
QPixmap _cache;
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
anim::transition af_opacity;
|
||||
|
||||
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
|
||||
bool peopleFailed(const RPCError &error, mtpRequestId req);
|
||||
|
||||
QTimer _searchTimer;
|
||||
QString _peopleQuery;
|
||||
bool _peopleFull;
|
||||
mtpRequestId _peopleRequest;
|
||||
|
||||
typedef QMap<QString, MTPcontacts_Found> PeopleCache;
|
||||
PeopleCache _peopleCache;
|
||||
|
||||
typedef QMap<mtpRequestId, QString> PeopleQueries;
|
||||
PeopleQueries _peopleQueries;
|
||||
};
|
||||
|
|
|
@ -22,12 +22,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "confirmbox.h"
|
||||
|
||||
NewGroupInner::NewGroupInner() :
|
||||
_contacts(&App::main()->contactsList()),
|
||||
_sel(0),
|
||||
_filteredSel(-1),
|
||||
_mouseSel(false),
|
||||
_selCount(0),
|
||||
_searching(false),
|
||||
_byUsernameSel(-1),
|
||||
_addContactLnk(this, lang(lng_add_contact_button)) {
|
||||
|
||||
connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
|
||||
|
@ -88,6 +92,16 @@ void NewGroupInner::loadProfilePhotos(int32 yFrom) {
|
|||
preloadFrom->history->peer->photo->load();
|
||||
}
|
||||
}
|
||||
yFrom -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
yTo -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
int32 from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsername.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsername.size()) to = _byUsername.size();
|
||||
for (; from < to; ++from) {
|
||||
_byUsername[from]->photo->load();
|
||||
}
|
||||
}
|
||||
} else if (!_filtered.isEmpty()) {
|
||||
int32 from = yFrom / rh;
|
||||
if (from < 0) from = 0;
|
||||
|
@ -99,6 +113,16 @@ void NewGroupInner::loadProfilePhotos(int32 yFrom) {
|
|||
_filtered[from]->history->peer->photo->load();
|
||||
}
|
||||
}
|
||||
yFrom -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
yTo -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsernameFiltered.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size();
|
||||
for (; from < to; ++from) {
|
||||
_byUsernameFiltered[from]->photo->load();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,12 +144,9 @@ NewGroupInner::ContactData *NewGroupInner::contactData(DialogRow *row) {
|
|||
return data;
|
||||
}
|
||||
|
||||
void NewGroupInner::paintDialog(QPainter &p, DialogRow *row, bool sel) {
|
||||
void NewGroupInner::paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel) {
|
||||
int32 left = st::profileListPadding.width();
|
||||
|
||||
UserData *user = row->history->peer->asUser();
|
||||
ContactData *data = contactData(row);
|
||||
|
||||
if (_selCount >= cMaxGroupCount() && !data->check) {
|
||||
sel = false;
|
||||
}
|
||||
|
@ -147,13 +168,29 @@ void NewGroupInner::paintDialog(QPainter &p, DialogRow *row, bool sel) {
|
|||
p.drawPixmap(QPoint(width() - st::profileCheckRect.pxWidth() - st::profileCheckDeltaX, st::profileListPadding.height() + (st::profileListPhotoSize - st::profileCheckRect.pxHeight()) / 2 - st::profileCheckDeltaY), App::sprite(), (data->check ? st::profileCheckActiveRect : st::profileCheckRect));
|
||||
}
|
||||
|
||||
bool uname = (data->online.at(0) == '@');
|
||||
p.setFont(st::profileSubFont->f);
|
||||
if (data->check) {
|
||||
p.setPen(st::white->p);
|
||||
if (uname && !data->check && !_lastQuery.isEmpty() && user->username.startsWith(_lastQuery, Qt::CaseInsensitive)) {
|
||||
int32 availw = width() - (left + st::profileListPhotoSize + st::profileListPadding.width() * 2);
|
||||
QString first = '@' + user->username.mid(0, _lastQuery.size()), second = user->username.mid(_lastQuery.size());
|
||||
int32 w = st::profileSubFont->m.width(first);
|
||||
if (w >= availw || second.isEmpty()) {
|
||||
p.setPen(st::profileOnlineColor->p);
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(first, Qt::ElideRight, availw));
|
||||
} else {
|
||||
p.setPen(st::profileOnlineColor->p);
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width(), st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, first);
|
||||
p.setPen(st::profileOfflineColor->p);
|
||||
p.drawText(left + st::profileListPhotoSize + st::profileListPadding.width() + w, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, st::profileSubFont->m.elidedText(second, Qt::ElideRight, availw - w));
|
||||
}
|
||||
} else {
|
||||
p.setPen((App::onlineColorUse(user->onlineTill, _time) ? st::profileOnlineColor : st::profileOfflineColor)->p);
|
||||
if (data->check) {
|
||||
p.setPen(st::white->p);
|
||||
} else {
|
||||
p.setPen(((uname || App::onlineColorUse(user->onlineTill, _time)) ? st::profileOnlineColor : st::profileOfflineColor)->p);
|
||||
}
|
||||
p.drawText(left + st::profileListPhotoSize + st::participantDelta, st::profileListPadding.height() + st::profileListPhotoSize - st::profileListStatusBottom, data->online);
|
||||
}
|
||||
p.drawText(left + st::profileListPhotoSize + st::participantDelta, st::profileListPadding.height() + st::profileListPhotoSize - 6, data->online);
|
||||
}
|
||||
|
||||
void NewGroupInner::paintEvent(QPaintEvent *e) {
|
||||
|
@ -163,40 +200,86 @@ void NewGroupInner::paintEvent(QPaintEvent *e) {
|
|||
_time = unixtime();
|
||||
p.fillRect(r, st::white->b);
|
||||
|
||||
int32 yFrom = r.top();
|
||||
int32 yFrom = r.top(), yTo = r.bottom();
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2;
|
||||
if (_filter.isEmpty()) {
|
||||
if (_contacts->list.count) {
|
||||
_contacts->list.adjustCurrent(yFrom, rh);
|
||||
if (_contacts->list.count || !_byUsername.isEmpty()) {
|
||||
if (_contacts->list.count) {
|
||||
_contacts->list.adjustCurrent(yFrom, rh);
|
||||
|
||||
DialogRow *drawFrom = _contacts->list.current;
|
||||
p.translate(0, drawFrom->pos * rh);
|
||||
while (drawFrom != _contacts->list.end && drawFrom->pos * rh < r.bottom()) {
|
||||
paintDialog(p, drawFrom, (drawFrom == _sel));
|
||||
p.translate(0, rh);
|
||||
drawFrom = drawFrom->next;
|
||||
DialogRow *drawFrom = _contacts->list.current;
|
||||
p.translate(0, drawFrom->pos * rh);
|
||||
while (drawFrom != _contacts->list.end && drawFrom->pos * rh < r.bottom()) {
|
||||
paintDialog(p, drawFrom->history->peer->asUser(), contactData(drawFrom), (drawFrom == _sel));
|
||||
p.translate(0, rh);
|
||||
drawFrom = drawFrom->next;
|
||||
}
|
||||
}
|
||||
if (!_byUsername.isEmpty()) {
|
||||
p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b);
|
||||
p.setFont(st::searchedBarFont->f);
|
||||
p.setPen(st::searchedBarColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center);
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
|
||||
yFrom -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
yTo -= _contacts->list.count * rh + st::searchedBarHeight;
|
||||
int32 from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsername.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsername.size()) to = _byUsername.size();
|
||||
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _byUsername[from], d_byUsername[from], (_byUsernameSel == from));
|
||||
p.translate(0, rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
p.setPen(st::noContactsColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_contacts : lng_contacts_loading), style::al_center);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight - ((cContactsReceived() && !_searching) ? st::noContactsFont->height : 0)), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_loading), style::al_center);
|
||||
}
|
||||
} else {
|
||||
if (_filtered.isEmpty()) {
|
||||
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
p.setPen(st::noContactsColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_not_found), style::al_center);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang((cContactsReceived() && !_searching) ? lng_no_contacts : lng_contacts_not_found), style::al_center);
|
||||
} else {
|
||||
int32 from = yFrom / rh;
|
||||
if (from < 0) from = 0;
|
||||
if (from < _filtered.size()) {
|
||||
int32 to = (r.bottom() / rh) + 1;
|
||||
if (to > _filtered.size()) to = _filtered.size();
|
||||
if (!_filtered.isEmpty()) {
|
||||
int32 from = yFrom / rh;
|
||||
if (from < 0) from = 0;
|
||||
if (from < _filtered.size()) {
|
||||
int32 to = (r.bottom() / rh) + 1;
|
||||
if (to > _filtered.size()) to = _filtered.size();
|
||||
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _filtered[from], (_filteredSel == from));
|
||||
p.translate(0, rh);
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _filtered[from]->history->peer->asUser(), contactData(_filtered[from]), (_filteredSel == from));
|
||||
p.translate(0, rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_byUsernameFiltered.isEmpty()) {
|
||||
p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b);
|
||||
p.setFont(st::searchedBarFont->f);
|
||||
p.setPen(st::searchedBarColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_search_global_results), style::al_center);
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
|
||||
yFrom -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
yTo -= _filtered.size() * rh + st::searchedBarHeight;
|
||||
int32 from = (yFrom >= 0) ? (yFrom / rh) : 0;
|
||||
if (from < _byUsernameFiltered.size()) {
|
||||
int32 to = (yTo / rh) + 1;
|
||||
if (to > _byUsernameFiltered.size()) to = _byUsernameFiltered.size();
|
||||
|
||||
p.translate(0, from * rh);
|
||||
for (; from < to; ++from) {
|
||||
paintDialog(p, _byUsernameFiltered[from], d_byUsernameFiltered[from], (_byUsernameSel == from));
|
||||
p.translate(0, rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +292,11 @@ void NewGroupInner::enterEvent(QEvent *e) {
|
|||
|
||||
void NewGroupInner::leaveEvent(QEvent *e) {
|
||||
setMouseTracking(false);
|
||||
updateSel();
|
||||
if (_sel || _filteredSel >= 0 || _byUsernameSel >= 0) {
|
||||
_sel = 0;
|
||||
_filteredSel = _byUsernameSel = -1;
|
||||
parentWidget()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void NewGroupInner::mouseMoveEvent(QMouseEvent *e) {
|
||||
|
@ -228,11 +315,15 @@ void NewGroupInner::mousePressEvent(QMouseEvent *e) {
|
|||
}
|
||||
|
||||
void NewGroupInner::changeCheckState(DialogRow *row) {
|
||||
if (contactData(row)->check) {
|
||||
contactData(row)->check = false;
|
||||
changeCheckState(contactData(row));
|
||||
}
|
||||
|
||||
void NewGroupInner::changeCheckState(ContactData *data) {
|
||||
if (data->check) {
|
||||
data->check = false;
|
||||
--_selCount;
|
||||
} else if (_selCount < cMaxGroupCount()) {
|
||||
contactData(row)->check = true;
|
||||
data->check = true;
|
||||
++_selCount;
|
||||
}
|
||||
}
|
||||
|
@ -240,42 +331,125 @@ void NewGroupInner::changeCheckState(DialogRow *row) {
|
|||
void NewGroupInner::chooseParticipant() {
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from;
|
||||
if (_filter.isEmpty()) {
|
||||
if (!_sel) return;
|
||||
changeCheckState(_sel);
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) {
|
||||
changeCheckState(d_byUsername[_byUsernameSel]);
|
||||
} else {
|
||||
if (!_sel) return;
|
||||
changeCheckState(_sel);
|
||||
}
|
||||
} else {
|
||||
if (_filteredSel < 0 || _filteredSel >= _filtered.size()) return;
|
||||
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) {
|
||||
changeCheckState(d_byUsernameFiltered[_byUsernameSel]);
|
||||
|
||||
DialogRow *row = _filtered[_filteredSel];
|
||||
changeCheckState(row);
|
||||
|
||||
PeerData *peer = row->history->peer;
|
||||
ContactData *moving = d_byUsernameFiltered[_byUsernameSel];
|
||||
int32 i = 0, l = d_byUsername.size();
|
||||
for (; i < l; ++i) {
|
||||
if (d_byUsername[i] == moving) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == l) {
|
||||
d_byUsername.push_back(moving);
|
||||
_byUsername.push_back(_byUsernameFiltered[_byUsernameSel]);
|
||||
for (i = 0, l = _byUsernameDatas.size(); i < l;) {
|
||||
if (_byUsernameDatas[i] == moving) {
|
||||
_byUsernameDatas.removeAt(i);
|
||||
--l;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_filteredSel < 0 || _filteredSel >= _filtered.size()) return;
|
||||
changeCheckState(_filtered[_filteredSel]);
|
||||
}
|
||||
emit selectAllQuery();
|
||||
}
|
||||
|
||||
parentWidget()->update();
|
||||
}
|
||||
|
||||
void NewGroupInner::peopleReceived(const QString &query, const QVector<MTPContactFound> &people) {
|
||||
_lastQuery = query.toLower().trimmed();
|
||||
if (_lastQuery.at(0) == '@') _lastQuery = _lastQuery.mid(1);
|
||||
int32 already = _byUsernameFiltered.size();
|
||||
_byUsernameFiltered.reserve(already + people.size());
|
||||
d_byUsernameFiltered.reserve(already + people.size());
|
||||
for (QVector<MTPContactFound>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
|
||||
int32 uid = i->c_contactFound().vuser_id.v, j = 0;
|
||||
for (; j < already; ++j) {
|
||||
if (_byUsernameFiltered[j]->id == uid) break;
|
||||
}
|
||||
if (j == already) {
|
||||
UserData *u = App::user(uid);
|
||||
ContactData *d = new ContactData();
|
||||
_byUsernameDatas.push_back(d);
|
||||
d->check = false;
|
||||
d->name.setText(st::profileListNameFont, u->name, _textNameOptions);
|
||||
d->online = '@' + u->username;
|
||||
|
||||
_byUsernameFiltered.push_back(u);
|
||||
d_byUsernameFiltered.push_back(d);
|
||||
}
|
||||
}
|
||||
_searching = false;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void NewGroupInner::refresh() {
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2;
|
||||
if (_filter.isEmpty()) {
|
||||
if (_contacts->list.count || !_byUsername.isEmpty()) {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
resize(width(), (_contacts->list.count * rh) + (_byUsername.isEmpty() ? 0 : (st::searchedBarHeight + _byUsername.size() * rh)));
|
||||
} else {
|
||||
if (cContactsReceived()) {
|
||||
if (_addContactLnk.isHidden()) _addContactLnk.show();
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
}
|
||||
resize(width(), st::noContactsHeight);
|
||||
}
|
||||
} else {
|
||||
if (_filtered.isEmpty() && _byUsernameFiltered.isEmpty()) {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
resize(width(), st::noContactsHeight);
|
||||
} else {
|
||||
resize(width(), (_filtered.size() * rh) + (_byUsernameFiltered.isEmpty() ? 0 : (st::searchedBarHeight + _byUsernameFiltered.size() * rh)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewGroupInner::updateSel() {
|
||||
if (!_mouseSel) return;
|
||||
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2;
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
bool in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePos));
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2;
|
||||
if (_filter.isEmpty()) {
|
||||
DialogRow *newSel = rect().contains(p) ? _contacts->list.rowAtY(p.y(), rh) : 0;
|
||||
if (newSel != _sel) {
|
||||
DialogRow *newSel = (in && (p.y() >= 0) && (p.y() < _contacts->list.count * rh)) ? _contacts->list.rowAtY(p.y(), rh) : 0;
|
||||
int32 byUsernameSel = (in && p.y() >= _contacts->list.count * rh + st::searchedBarHeight) ? ((p.y() - _contacts->list.count * rh - st::searchedBarHeight) / rh) : -1;
|
||||
if (byUsernameSel >= _byUsername.size()) byUsernameSel = -1;
|
||||
if (newSel != _sel || byUsernameSel != _byUsernameSel) {
|
||||
_sel = newSel;
|
||||
_byUsernameSel = byUsernameSel;
|
||||
parentWidget()->update();
|
||||
}
|
||||
} else {
|
||||
int32 newFilteredSel = (p.y() >= 0 && rect().contains(p)) ? (p.y() / rh) : -1;
|
||||
if (newFilteredSel != _filteredSel) {
|
||||
int32 newFilteredSel = (in && p.y() >= 0 && p.y() < _filtered.size() * rh) ? (p.y() / rh) : -1;
|
||||
int32 byUsernameSel = (in && p.y() >= _filtered.size() * rh + st::searchedBarHeight) ? ((p.y() - _filtered.size() * rh - st::searchedBarHeight) / rh) : -1;
|
||||
if (byUsernameSel >= _byUsernameFiltered.size()) byUsernameSel = -1;
|
||||
if (newFilteredSel != _filteredSel || byUsernameSel != _byUsernameSel) {
|
||||
_filteredSel = newFilteredSel;
|
||||
_byUsernameSel = byUsernameSel;
|
||||
parentWidget()->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewGroupInner::updateFilter(QString filter) {
|
||||
_lastQuery = filter.toLower().trimmed();
|
||||
filter = textSearchKey(filter);
|
||||
|
||||
QStringList f;
|
||||
|
@ -294,20 +468,23 @@ void NewGroupInner::updateFilter(QString filter) {
|
|||
if (_filter != filter) {
|
||||
int32 rh = (st::profileListPhotoSize + st::profileListPadding.height() * 2);
|
||||
_filter = filter;
|
||||
|
||||
_byUsernameFiltered.clear();
|
||||
d_byUsernameFiltered.clear();
|
||||
for (int i = 0, l = _byUsernameDatas.size(); i < l; ++i) {
|
||||
delete _byUsernameDatas[i];
|
||||
}
|
||||
_byUsernameDatas.clear();
|
||||
|
||||
if (_filter.isEmpty()) {
|
||||
resize(width(), _contacts->list.count * rh);
|
||||
_sel = 0;
|
||||
if (_contacts->list.count) {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
resize(width(), _contacts->list.count * rh);
|
||||
_sel = _contacts->list.begin;
|
||||
} else {
|
||||
resize(width(), st::noContactsHeight);
|
||||
if (cContactsReceived()) {
|
||||
if (_addContactLnk.isHidden()) _addContactLnk.show();
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
}
|
||||
}
|
||||
if (!_sel && !_byUsername.isEmpty()) {
|
||||
_byUsernameSel = 0;
|
||||
}
|
||||
refresh();
|
||||
} else {
|
||||
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
|
||||
QStringList::const_iterator fb = f.cbegin(), fe = f.cend(), fi;
|
||||
|
@ -349,14 +526,36 @@ void NewGroupInner::updateFilter(QString filter) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
_byUsernameFiltered.reserve(_byUsername.size());
|
||||
d_byUsernameFiltered.reserve(d_byUsername.size());
|
||||
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
const PeerData::Names &names(_byUsername[i]->names);
|
||||
PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni;
|
||||
for (fi = fb; fi != fe; ++fi) {
|
||||
QString filterName(*fi);
|
||||
for (ni = nb; ni != ne; ++ni) {
|
||||
if (ni->startsWith(*fi)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ni == ne) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fi == fe) {
|
||||
_byUsernameFiltered.push_back(_byUsername[i]);
|
||||
d_byUsernameFiltered.push_back(d_byUsername[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
_filteredSel = _filtered.isEmpty() ? -1 : 0;
|
||||
_byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1;
|
||||
|
||||
if (!_filtered.isEmpty()) {
|
||||
resize(width(), _filtered.size() * rh);
|
||||
} else {
|
||||
resize(width(), st::noContactsHeight);
|
||||
}
|
||||
refresh();
|
||||
|
||||
_searching = true;
|
||||
emit searchByUsername();
|
||||
}
|
||||
if (parentWidget()) parentWidget()->update();
|
||||
loadProfilePhotos(0);
|
||||
|
@ -392,7 +591,13 @@ void NewGroupInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) {
|
|||
}
|
||||
|
||||
NewGroupInner::~NewGroupInner() {
|
||||
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
|
||||
for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
for (ByUsernameDatas::const_iterator i = d_byUsername.cbegin(), e = d_byUsername.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
for (ByUsernameDatas::const_iterator i = _byUsernameDatas.cbegin(), e = _byUsernameDatas.cend(); i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
@ -405,41 +610,52 @@ void NewGroupInner::selectSkip(int32 dir) {
|
|||
_mouseSel = false;
|
||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, origDir = dir;
|
||||
if (_filter.isEmpty()) {
|
||||
int cur = 0;
|
||||
if (_sel) {
|
||||
if (dir > 0) {
|
||||
while (dir && _sel->next->next) {
|
||||
_sel = _sel->next;
|
||||
--dir;
|
||||
}
|
||||
} else {
|
||||
while (dir && _sel->prev) {
|
||||
_sel = _sel->prev;
|
||||
++dir;
|
||||
}
|
||||
for (DialogRow *i = _contacts->list.begin; i != _sel; i = i->next) {
|
||||
++cur;
|
||||
}
|
||||
} else if (dir > 0 && _contacts->list.count) {
|
||||
_sel = _contacts->list.begin;
|
||||
} else {
|
||||
cur = (_byUsernameSel >= 0) ? (_contacts->list.count + _byUsernameSel) : -1;
|
||||
}
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_sel = _contacts->list.count ? _contacts->list.begin : 0;
|
||||
_byUsernameSel = (!_contacts->list.count && !_byUsername.isEmpty()) ? 0 : -1;
|
||||
} else if (cur >= _contacts->list.count) {
|
||||
_sel = 0;
|
||||
_byUsernameSel = cur - _contacts->list.count;
|
||||
if (_byUsernameSel >= _byUsername.size()) _byUsernameSel = _byUsername.size() - 1;
|
||||
} else {
|
||||
for (_sel = _contacts->list.begin; cur; _sel = _sel->next) {
|
||||
--cur;
|
||||
}
|
||||
_byUsernameSel = -1;
|
||||
}
|
||||
if (_sel) {
|
||||
emit mustScrollTo(_sel->pos * rh, (_sel->pos + 1) * rh);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
emit mustScrollTo((_contacts->list.count + _byUsernameSel) * rh + st::searchedBarHeight, (_contacts->list.count + _byUsernameSel + 1) * rh + st::searchedBarHeight);
|
||||
}
|
||||
} else {
|
||||
if (dir > 0) {
|
||||
if (_filteredSel < 0 && dir > 1) {
|
||||
_filteredSel = 0;
|
||||
}
|
||||
_filteredSel += dir;
|
||||
if (_filteredSel >= _filtered.size()) {
|
||||
_filteredSel = _filtered.size() - 1;
|
||||
}
|
||||
} else if (_filteredSel > 0) {
|
||||
_filteredSel += dir;
|
||||
if (_filteredSel < 0) {
|
||||
_filteredSel = 0;
|
||||
}
|
||||
int cur = (_filteredSel >= 0) ? _filteredSel : ((_byUsernameSel >= 0) ? (_filtered.size() + _byUsernameSel) : -1);
|
||||
cur += dir;
|
||||
if (cur <= 0) {
|
||||
_filteredSel = _filtered.isEmpty() ? -1 : 0;
|
||||
_byUsernameSel = (_filtered.isEmpty() && !_byUsernameFiltered.isEmpty()) ? 0 : -1;
|
||||
} else if (cur >= _filtered.size()) {
|
||||
_filteredSel = -1;
|
||||
_byUsernameSel = cur - _filtered.size();
|
||||
if (_byUsernameSel >= _byUsernameFiltered.size()) _byUsernameSel = _byUsernameFiltered.size() - 1;
|
||||
} else {
|
||||
_filteredSel = cur;
|
||||
_byUsernameSel = -1;
|
||||
}
|
||||
if (_filteredSel >= 0) {
|
||||
emit mustScrollTo(_filteredSel * rh, (_filteredSel + 1) * rh);
|
||||
} else if (_byUsernameSel >= 0) {
|
||||
int skip = _filtered.size() * rh + st::searchedBarHeight;
|
||||
emit mustScrollTo(skip + _byUsernameSel * rh, skip + (_byUsernameSel + 1) * rh);
|
||||
}
|
||||
}
|
||||
parentWidget()->update();
|
||||
|
@ -460,6 +676,11 @@ QVector<MTPInputUser> NewGroupInner::selectedInputs() {
|
|||
result.push_back(i.key()->inputUser);
|
||||
}
|
||||
}
|
||||
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
if (d_byUsername[i]->check) {
|
||||
result.push_back(_byUsername[i]->inputUser);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -469,6 +690,11 @@ PeerData *NewGroupInner::selectedUser() {
|
|||
return i.key();
|
||||
}
|
||||
}
|
||||
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
|
||||
if (d_byUsername[i]->check) {
|
||||
return _byUsername[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -495,12 +721,81 @@ NewGroupBox::NewGroupBox() : _scroll(this, st::newGroupScroll), _inner(),
|
|||
connect(&_filter, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||
connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int)));
|
||||
connect(&_inner, SIGNAL(selectAllQuery()), &_filter, SLOT(selectAll()));
|
||||
connect(&_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
||||
|
||||
_searchTimer.setSingleShot(true);
|
||||
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
|
||||
|
||||
showAll();
|
||||
_cache = myGrab(this, rect());
|
||||
hideAll();
|
||||
}
|
||||
|
||||
bool NewGroupBox::onSearchByUsername(bool searchCache) {
|
||||
QString q = _filter.text().trimmed();
|
||||
if (q.isEmpty()) {
|
||||
if (_peopleRequest) {
|
||||
_peopleRequest = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (q.size() >= MinUsernameLength) {
|
||||
if (searchCache) {
|
||||
PeopleCache::const_iterator i = _peopleCache.constFind(q);
|
||||
if (i != _peopleCache.cend()) {
|
||||
_peopleQuery = q;
|
||||
_peopleRequest = 0;
|
||||
peopleReceived(i.value(), 0);
|
||||
return true;
|
||||
}
|
||||
} else if (_peopleQuery != q) {
|
||||
_peopleQuery = q;
|
||||
_peopleFull = false;
|
||||
_peopleRequest = MTP::send(MTPcontacts_Search(MTP_string(_peopleQuery), MTP_int(SearchPeopleLimit)), rpcDone(&NewGroupBox::peopleReceived), rpcFail(&NewGroupBox::peopleFailed));
|
||||
_peopleQueries.insert(_peopleRequest, _peopleQuery);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NewGroupBox::onNeedSearchByUsername() {
|
||||
if (!onSearchByUsername(true)) {
|
||||
_searchTimer.start(AutoSearchTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void NewGroupBox::peopleReceived(const MTPcontacts_Found &result, mtpRequestId req) {
|
||||
QString q = _peopleQuery;
|
||||
|
||||
PeopleQueries::iterator i = _peopleQueries.find(req);
|
||||
if (i != _peopleQueries.cend()) {
|
||||
q = i.value();
|
||||
_peopleCache[q] = result;
|
||||
_peopleQueries.erase(i);
|
||||
}
|
||||
|
||||
if (_peopleRequest == req) {
|
||||
switch (result.type()) {
|
||||
case mtpc_contacts_found: {
|
||||
App::feedUsers(result.c_contacts_found().vusers);
|
||||
_inner.peopleReceived(q, result.c_contacts_found().vresults.c_vector().v);
|
||||
} break;
|
||||
}
|
||||
|
||||
_peopleRequest = 0;
|
||||
_inner.updateSel();
|
||||
onScroll();
|
||||
}
|
||||
}
|
||||
|
||||
bool NewGroupBox::peopleFailed(const RPCError &error, mtpRequestId req) {
|
||||
if (_peopleRequest == req) {
|
||||
_peopleRequest = 0;
|
||||
_peopleFull = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void NewGroupBox::hideAll() {
|
||||
_filter.hide();
|
||||
_scroll.hide();
|
||||
|
|
|
@ -22,6 +22,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
class NewGroupInner : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
struct ContactData;
|
||||
|
||||
public:
|
||||
|
||||
NewGroupInner();
|
||||
|
@ -33,7 +37,7 @@ public:
|
|||
void mousePressEvent(QMouseEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
void paintDialog(QPainter &p, DialogRow *row, bool sel);
|
||||
void paintDialog(QPainter &p, UserData *user, ContactData *data, bool sel);
|
||||
void updateFilter(QString filter = QString());
|
||||
|
||||
void selectSkip(int32 dir);
|
||||
|
@ -45,6 +49,11 @@ public:
|
|||
void loadProfilePhotos(int32 yFrom);
|
||||
|
||||
void changeCheckState(DialogRow *row);
|
||||
void changeCheckState(ContactData *data);
|
||||
|
||||
void peopleReceived(const QString &query, const QVector<MTPContactFound> &people);
|
||||
|
||||
void refresh();
|
||||
|
||||
~NewGroupInner();
|
||||
|
||||
|
@ -52,6 +61,7 @@ signals:
|
|||
|
||||
void mustScrollTo(int ymin, int ymax);
|
||||
void selectAllQuery();
|
||||
void searchByUsername();
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -74,17 +84,26 @@ private:
|
|||
int32 _filteredSel;
|
||||
bool _mouseSel;
|
||||
|
||||
typedef struct {
|
||||
struct ContactData {
|
||||
Text name;
|
||||
QString online;
|
||||
bool check;
|
||||
} ContactData;
|
||||
};
|
||||
typedef QMap<UserData*, ContactData*> ContactsData;
|
||||
ContactsData _contactsData;
|
||||
int32 _selCount;
|
||||
|
||||
ContactData *contactData(DialogRow *row);
|
||||
|
||||
bool _searching;
|
||||
QString _lastQuery;
|
||||
typedef QVector<UserData*> ByUsernameRows;
|
||||
typedef QVector<ContactData*> ByUsernameDatas;
|
||||
ByUsernameRows _byUsername, _byUsernameFiltered;
|
||||
ByUsernameDatas d_byUsername, d_byUsernameFiltered; // filtered is partly subset of d_byUsername, partly subset of _byUsernameDatas
|
||||
ByUsernameDatas _byUsernameDatas;
|
||||
int32 _byUsernameSel;
|
||||
|
||||
QPoint _lastMousePos;
|
||||
LinkButton _addContactLnk;
|
||||
|
||||
|
@ -111,6 +130,9 @@ public slots:
|
|||
void onNext();
|
||||
void onScroll();
|
||||
|
||||
bool onSearchByUsername(bool searchCache = false);
|
||||
void onNeedSearchByUsername();
|
||||
|
||||
private:
|
||||
|
||||
void hideAll();
|
||||
|
@ -126,6 +148,20 @@ private:
|
|||
QPixmap _cache;
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
|
||||
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
|
||||
bool peopleFailed(const RPCError &error, mtpRequestId req);
|
||||
|
||||
QTimer _searchTimer;
|
||||
QString _peopleQuery;
|
||||
bool _peopleFull;
|
||||
mtpRequestId _peopleRequest;
|
||||
|
||||
typedef QMap<QString, MTPcontacts_Found> PeopleCache;
|
||||
PeopleCache _peopleCache;
|
||||
|
||||
typedef QMap<mtpRequestId, QString> PeopleQueries;
|
||||
PeopleQueries _peopleQueries;
|
||||
};
|
||||
|
||||
class CreateGroupBox : public LayeredWidget, public RPCSender {
|
||||
|
|
|
@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
static const int32 AppVersion = 7024;
|
||||
static const wchar_t *AppVersionStr = L"0.7.24";
|
||||
static const int32 AppVersion = 7025;
|
||||
static const wchar_t *AppVersionStr = L"0.7.25";
|
||||
static const bool DevChannel = true;
|
||||
|
||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||
|
|
|
@ -900,26 +900,40 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
|
|||
int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2;
|
||||
if (_rows->isEmpty()) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon);
|
||||
}
|
||||
p.setPen(st::black->p);
|
||||
if (_rows->isEmpty()) {
|
||||
QString tag = st::mentionFont->m.elidedText('#' + _hrows->at(last - i - 1), Qt::ElideRight, htagwidth);
|
||||
p.setFont(st::mentionFont->f);
|
||||
p.drawText(htagleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, tag);
|
||||
} else {
|
||||
UserData *user = _rows->at(last - i - 1);
|
||||
QString uname = user->username;
|
||||
int32 unamewidth = atwidth + st::mentionFont->m.width(uname), namewidth = user->nameText.maxWidth();
|
||||
QString first = (_parent->filter().size() < 2) ? QString() : ('@' + user->username.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('@' + user->username) : user->username.mid(_parent->filter().size() - 1);
|
||||
int32 firstwidth = st::mentionFont->m.width(first), secondwidth = st::mentionFont->m.width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth();
|
||||
if (availwidth < unamewidth + namewidth) {
|
||||
namewidth = (availwidth * namewidth) / (namewidth + unamewidth);
|
||||
unamewidth = availwidth - namewidth;
|
||||
uname = st::mentionFont->m.elidedText('@' + uname, Qt::ElideRight, unamewidth);
|
||||
} else {
|
||||
uname = '@' + uname;
|
||||
if (firstwidth <= unamewidth) {
|
||||
if (firstwidth < unamewidth) {
|
||||
first = st::mentionFont->m.elidedText(first, Qt::ElideRight, unamewidth);
|
||||
} else if (!second.isEmpty()) {
|
||||
first = st::mentionFont->m.elidedText(first + second, Qt::ElideRight, unamewidth);
|
||||
second = QString();
|
||||
}
|
||||
} else {
|
||||
second = st::mentionFont->m.elidedText(second, Qt::ElideRight, unamewidth - firstwidth);
|
||||
}
|
||||
}
|
||||
user->photo->load();
|
||||
p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pix(st::mentionPhotoSize));
|
||||
user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth);
|
||||
p.setFont(st::mentionFont->f);
|
||||
p.drawText(2 * st::mentionPadding.left() + st::mentionPhotoSize + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, uname);
|
||||
|
||||
p.setPen(st::profileOnlineColor->p);
|
||||
p.drawText(2 * st::mentionPadding.left() + st::mentionPhotoSize + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
|
||||
if (!second.isEmpty()) {
|
||||
p.setPen(st::profileOfflineColor->p);
|
||||
p.drawText(2 * st::mentionPadding.left() + st::mentionPhotoSize + namewidth + st::mentionPadding.right() + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1240,6 +1254,10 @@ bool MentionsDropdown::animStep(float64 ms) {
|
|||
return res;
|
||||
}
|
||||
|
||||
const QString &MentionsDropdown::filter() const {
|
||||
return _filter;
|
||||
}
|
||||
|
||||
int32 MentionsDropdown::innerTop() {
|
||||
return _scroll.scrollTop();
|
||||
}
|
||||
|
@ -1257,7 +1275,7 @@ bool MentionsDropdown::eventFilter(QObject *obj, QEvent *e) {
|
|||
return true;
|
||||
} else if (ev->key() == Qt::Key_Down) {
|
||||
return _inner.moveSel(1);
|
||||
} else if (ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return) {
|
||||
} else if (ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return || ev->key() == Qt::Key_Space) {
|
||||
return _inner.select();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,6 +291,8 @@ public:
|
|||
|
||||
bool animStep(float64 ms);
|
||||
|
||||
const QString &filter() const;
|
||||
|
||||
int32 innerTop();
|
||||
int32 innerBottom();
|
||||
|
||||
|
|
|
@ -718,6 +718,8 @@ void MainWidget::addParticipantDone(ChatData *chat, const MTPmessages_StatedMess
|
|||
}
|
||||
|
||||
bool MainWidget::addParticipantFail(ChatData *chat, const RPCError &e) {
|
||||
ConfirmBox *box = new ConfirmBox(lang(lng_failed_add_participant), true);
|
||||
App::wnd()->showLayer(box);
|
||||
if (e.type() == "USER_LEFT_CHAT") { // trying to return banned user to his group
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -200,6 +200,7 @@ namespace {
|
|||
}
|
||||
} else {
|
||||
secs = m.captured(1).toInt();
|
||||
if (secs >= 60) return false;
|
||||
}
|
||||
uint64 sendAt = getms(true) + secs * 1000 + 10;
|
||||
DelayedRequestsList::iterator i = delayedRequests.begin(), e = delayedRequests.end();
|
||||
|
|
|
@ -717,6 +717,9 @@ void ProfileInner::contextMenuEvent(QContextMenuEvent *e) {
|
|||
if (info.contains(mapFromGlobal(e->globalPos()))) {
|
||||
_menu = new ContextMenu(this);
|
||||
_menu->addAction(lang(lng_profile_copy_phone), this, SLOT(onCopyPhone()))->setEnabled(true);
|
||||
if (_peerUser && !_peerUser->username.isEmpty()) {
|
||||
_menu->addAction(lang(lng_context_copy_mention), this, SLOT(onCopyUsername()))->setEnabled(true);
|
||||
}
|
||||
_menu->deleteOnHide();
|
||||
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
|
||||
_menu->popup(e->globalPos());
|
||||
|
@ -735,6 +738,10 @@ void ProfileInner::onCopyPhone() {
|
|||
QApplication::clipboard()->setText(_phoneText);
|
||||
}
|
||||
|
||||
void ProfileInner::onCopyUsername() {
|
||||
QApplication::clipboard()->setText('@' + _peerUser->username);
|
||||
}
|
||||
|
||||
bool ProfileInner::animStep(float64 ms) {
|
||||
float64 dt = ms / st::setPhotoDuration;
|
||||
bool res = true;
|
||||
|
|
|
@ -91,6 +91,7 @@ public slots:
|
|||
|
||||
void onMenuDestroy(QObject *obj);
|
||||
void onCopyPhone();
|
||||
void onCopyUsername();
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.7.24</string>
|
||||
<string>0.7.25</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
Binary file not shown.
|
@ -1667,7 +1667,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.7.24;
|
||||
CURRENT_PROJECT_VERSION = 0.7.25;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
@ -1685,7 +1685,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 0.7.24;
|
||||
CURRENT_PROJECT_VERSION = 0.7.25;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
||||
|
@ -1711,10 +1711,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.7.24;
|
||||
CURRENT_PROJECT_VERSION = 0.7.25;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.7;
|
||||
DYLIB_CURRENT_VERSION = 0.7.24;
|
||||
DYLIB_CURRENT_VERSION = 0.7.25;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
|
@ -1852,10 +1852,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.7.24;
|
||||
CURRENT_PROJECT_VERSION = 0.7.25;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.7;
|
||||
DYLIB_CURRENT_VERSION = 0.7.24;
|
||||
DYLIB_CURRENT_VERSION = 0.7.25;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
echo 7024 0.7.24 1
|
||||
echo 7025 0.7.25 1
|
||||
# AppVersion AppVersionStr DevChannel
|
||||
|
|
Loading…
Add table
Reference in a new issue