mirror of https://github.com/procxx/kepka.git
New design of a chat invite link import box with title, photo, users.
This commit is contained in:
parent
cd36d367ed
commit
66e2fce8d5
|
@ -602,6 +602,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
"lng_group_invite_want_join_channel" = "Do you want to join the channel «{title}»?";
|
||||
"lng_group_invite_join" = "Join";
|
||||
|
||||
"lng_group_invite_members" = "{count:_not_used_|# member|# members}, among them:";
|
||||
|
||||
"lng_group_invite_link" = "Invite link:";
|
||||
"lng_group_invite_create" = "Create an invite link";
|
||||
"lng_group_invite_about" = "Telegram users will be able to join\nyour group by following this link.";
|
||||
|
|
|
@ -383,9 +383,7 @@ namespace {
|
|||
return (online > now);
|
||||
}
|
||||
|
||||
UserData *feedUsers(const MTPVector<MTPUser> &users) {
|
||||
UserData *result = nullptr;
|
||||
for_const (auto &user, users.c_vector().v) {
|
||||
UserData *feedUser(const MTPUser &user) {
|
||||
UserData *data = nullptr;
|
||||
bool wasContact = false, minimal = false;
|
||||
const MTPUserStatus *status = 0, emptyStatus = MTP_userStatusEmpty();
|
||||
|
@ -395,7 +393,7 @@ namespace {
|
|||
|
||||
switch (user.type()) {
|
||||
case mtpc_userEmpty: {
|
||||
const auto &d(user.c_userEmpty());
|
||||
auto &d(user.c_userEmpty());
|
||||
|
||||
PeerId peer(peerFromUser(d.vid.v));
|
||||
data = App::user(peer);
|
||||
|
@ -416,7 +414,7 @@ namespace {
|
|||
if (wasContact != data->isContact()) update.flags |= UpdateFlag::UserIsContact;
|
||||
} break;
|
||||
case mtpc_user: {
|
||||
const auto &d(user.c_user());
|
||||
auto &d(user.c_user());
|
||||
minimal = d.is_min();
|
||||
|
||||
PeerId peer(peerFromUser(d.vid.v));
|
||||
|
@ -518,7 +516,9 @@ namespace {
|
|||
} break;
|
||||
}
|
||||
|
||||
if (!data) continue;
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (minimal) {
|
||||
if (data->loadedStatus == PeerData::NotLoaded) {
|
||||
|
@ -559,15 +559,21 @@ namespace {
|
|||
Notify::peerUpdatedDelayed(update);
|
||||
}
|
||||
}
|
||||
result = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
UserData *feedUsers(const MTPVector<MTPUser> &users) {
|
||||
UserData *result = nullptr;
|
||||
for_const (auto &user, users.c_vector().v) {
|
||||
if (auto feededUser = feedUser(user)) {
|
||||
result = feededUser;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PeerData *feedChats(const MTPVector<MTPChat> &chats) {
|
||||
PeerData *result = nullptr;
|
||||
for_const (auto &chat, chats.c_vector().v) {
|
||||
PeerData *feedChat(const MTPChat &chat) {
|
||||
PeerData *data = nullptr;
|
||||
bool minimal = false;
|
||||
|
||||
|
@ -667,7 +673,7 @@ namespace {
|
|||
if (minimal) {
|
||||
data = App::channelLoaded(peerId);
|
||||
if (!data) {
|
||||
continue; // minimal is not loaded, need to make getDifference
|
||||
return nullptr; // minimal is not loaded, need to make getDifference
|
||||
}
|
||||
} else {
|
||||
data = App::channel(peerId);
|
||||
|
@ -757,7 +763,9 @@ namespace {
|
|||
}
|
||||
} break;
|
||||
}
|
||||
if (!data) continue;
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (minimal) {
|
||||
if (data->loadedStatus == PeerData::NotLoaded) {
|
||||
|
@ -773,7 +781,15 @@ namespace {
|
|||
Notify::peerUpdatedDelayed(update);
|
||||
}
|
||||
}
|
||||
result = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
PeerData *feedChats(const MTPVector<MTPChat> &chats) {
|
||||
PeerData *result = nullptr;
|
||||
for_const (auto &chat, chats.c_vector().v) {
|
||||
if (auto feededChat = feedChat(chat)) {
|
||||
result = feededChat;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,9 @@ namespace App {
|
|||
bool onlineColorUse(UserData *user, TimeId now);
|
||||
bool onlineColorUse(TimeId online, TimeId now);
|
||||
|
||||
UserData *feedUser(const MTPUser &user);
|
||||
UserData *feedUsers(const MTPVector<MTPUser> &users); // returns last user
|
||||
PeerData *feedChat(const MTPChat &chat);
|
||||
PeerData *feedChats(const MTPVector<MTPChat> &chats); // returns last chat
|
||||
|
||||
void feedParticipants(const MTPChatParticipants &p, bool requestBotInfos, bool emitPeerUpdated = true);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
using "basic.style";
|
||||
|
||||
confirmInviteTitle: flatLabel(labelDefFlat) {
|
||||
font: font(16px semibold);
|
||||
align: align(center);
|
||||
width: 320px;
|
||||
maxHeight: 24px;
|
||||
textFg: #333333;
|
||||
}
|
||||
confirmInviteStatus: flatLabel(labelDefFlat) {
|
||||
font: font(boxFontSize);
|
||||
align: align(center);
|
||||
width: 320px;
|
||||
maxHeight: 20px;
|
||||
textFg: windowSubTextFg;
|
||||
}
|
||||
confirmInviteTitleTop: 106px;
|
||||
confirmInvitePhotoSize: 76px;
|
||||
confirmInvitePhotoTop: 20px;
|
||||
confirmInviteStatusTop: 136px;
|
||||
confirmInviteUserHeight: 80px;
|
||||
confirmInviteUserPhotoSize: 56px;
|
||||
confirmInviteUserPhotoTop: 166px;
|
||||
confirmInviteUserName: flatLabel(labelDefFlat) {
|
||||
font: normalFont;
|
||||
align: align(center);
|
||||
width: 66px;
|
||||
maxHeight: 20px;
|
||||
}
|
||||
confirmInviteUserNameTop: 227px;
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "apiwrap.h"
|
||||
#include "application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
TextParseOptions _confirmBoxTextOptions = {
|
||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||
|
@ -520,3 +521,86 @@ void KickMemberBox::onConfirm() {
|
|||
App::api()->kickParticipant(channel, _member);
|
||||
}
|
||||
}
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants) : AbstractBox()
|
||||
, _title(this, st::confirmInviteTitle)
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _photo(chatDefPhoto(0))
|
||||
, _participants(participants)
|
||||
, _join(this, lang(lng_group_invite_join), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||
if (_participants.size() > 4) {
|
||||
_participants.resize(4);
|
||||
}
|
||||
|
||||
_title->setText(title);
|
||||
QString status;
|
||||
if (_participants.isEmpty() || _participants.size() >= count) {
|
||||
status = lng_chat_status_members(lt_count, count);
|
||||
} else {
|
||||
status = lng_group_invite_members(lt_count, count);
|
||||
}
|
||||
_status->setText(status);
|
||||
if (photo.type() == mtpc_chatPhoto) {
|
||||
auto &d = photo.c_chatPhoto();
|
||||
auto location = App::imageLocation(160, 160, d.vphoto_small);
|
||||
if (!location.isNull()) {
|
||||
_photo = ImagePtr(location);
|
||||
if (!_photo->loaded()) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
_photo->load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int h = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _join->height() + st::boxButtonPadding.bottom();
|
||||
if (!_participants.isEmpty()) {
|
||||
int skip = (width() - 4 * st::confirmInviteUserPhotoSize) / 5;
|
||||
int padding = skip / 2;
|
||||
_userWidth = (st::confirmInviteUserPhotoSize + 2 * padding);
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (width() - sumWidth) / 2;
|
||||
for_const (auto user, _participants) {
|
||||
auto name = new FlatLabel(this, st::confirmInviteUserName);
|
||||
name->resizeToWidth(st::confirmInviteUserPhotoSize + padding);
|
||||
name->setText(user->firstName.isEmpty() ? App::peerName(user) : user->firstName);
|
||||
name->moveToLeft(left + (padding / 2), st::confirmInviteUserNameTop);
|
||||
left += _userWidth;
|
||||
}
|
||||
|
||||
h += st::confirmInviteUserHeight;
|
||||
}
|
||||
setMaxHeight(h);
|
||||
|
||||
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
connect(_join, SIGNAL(clicked()), App::main(), SLOT(onInviteImport()));
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
|
||||
_title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop);
|
||||
_status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop);
|
||||
_join->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _join->height());
|
||||
_cancel->moveToRight(st::boxButtonPadding.right() + _join->width() + st::boxButtonPadding.left(), _join->y());
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (paint(p)) return;
|
||||
|
||||
p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize));
|
||||
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (width() - sumWidth) / 2;
|
||||
for_const (auto user, _participants) {
|
||||
user->paintUserpicLeft(p, st::confirmInviteUserPhotoSize, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width());
|
||||
left += _userWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::showAll() {
|
||||
showChildren();
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::hideAll() {
|
||||
hideChildren();
|
||||
}
|
||||
|
|
|
@ -266,3 +266,26 @@ private:
|
|||
UserData *_member;
|
||||
|
||||
};
|
||||
|
||||
class ConfirmInviteBox : public AbstractBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConfirmInviteBox(const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void showAll();
|
||||
void hideAll();
|
||||
|
||||
private:
|
||||
ChildWidget<FlatLabel> _title, _status;
|
||||
ImagePtr _photo;
|
||||
QVector<UserData*> _participants;
|
||||
|
||||
ChildWidget<BoxButton> _join, _cancel;
|
||||
int _userWidth = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -530,9 +530,9 @@ void StickersInner::paintRow(Painter &p, int32 index) {
|
|||
int addy = st::contactsPadding.top() + (st::contactsPhotoSize - st::defaultActiveButton.height) / 2;
|
||||
QRect add(myrtlrect(addx, addy, addw, st::defaultActiveButton.height));
|
||||
|
||||
App::roundRect(p, add, st::defaultActiveButton.textBgOver, ImageRoundRadius::Small);
|
||||
App::roundRect(p, add, st::defaultActiveButton.textBg, ImageRoundRadius::Small);
|
||||
p.setFont(st::defaultActiveButton.font);
|
||||
p.setPen(st::defaultActiveButton.textFg);
|
||||
p.setPen(st::defaultActiveButton.textFg); // textBgOver / downTextTop
|
||||
p.drawTextLeft(addx - st::defaultActiveButton.width / 2, addy + st::defaultActiveButton.textTop, width(), _addText, _addWidth);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,8 +85,8 @@ dialogsTextStyleActive: textStyle(dialogsTextStyle) {
|
|||
linkFgDown: dialogsTextFgActive;
|
||||
}
|
||||
dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) {
|
||||
linkFg: #ffd6d6;
|
||||
linkFgDown: #ffd6d6;
|
||||
linkFg: #c6e1f7;
|
||||
linkFgDown: #c6e1f7;
|
||||
}
|
||||
|
||||
dialogsNewChatIcon: icon {
|
||||
|
|
|
@ -3487,11 +3487,22 @@ bool MainWidget::usernameResolveFail(QString name, const RPCError &error) {
|
|||
void MainWidget::inviteCheckDone(QString hash, const MTPChatInvite &invite) {
|
||||
switch (invite.type()) {
|
||||
case mtpc_chatInvite: {
|
||||
const auto &d(invite.c_chatInvite());
|
||||
ConfirmBox *box = new ConfirmBox(((d.is_channel() && !d.is_megagroup()) ? lng_group_invite_want_join_channel : lng_group_invite_want_join)(lt_title, qs(d.vtitle)), lang(lng_group_invite_join));
|
||||
auto &d(invite.c_chatInvite());
|
||||
((d.is_channel() && !d.is_megagroup()) ? lng_group_invite_want_join_channel : lng_group_invite_want_join)(lt_title, qs(d.vtitle)), lang(lng_group_invite_join);
|
||||
|
||||
QVector<UserData*> participants;
|
||||
if (d.has_participants()) {
|
||||
auto &v = d.vparticipants.c_vector().v;
|
||||
participants.reserve(v.size());
|
||||
for_const (auto &user, v) {
|
||||
if (auto feededUser = App::feedUser(user)) {
|
||||
participants.push_back(feededUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto box = std_::make_unique<ConfirmInviteBox>(qs(d.vtitle), d.vphoto, 3, participants);
|
||||
_inviteHash = hash;
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onInviteImport()));
|
||||
Ui::showLayer(box);
|
||||
Ui::showLayer(box.release());
|
||||
} break;
|
||||
|
||||
case mtpc_chatInviteAlready: {
|
||||
|
|
|
@ -1185,6 +1185,7 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\styles\style_basic.cpp" />
|
||||
<ClCompile Include="GeneratedFiles\styles\style_basic_types.cpp" />
|
||||
<ClCompile Include="GeneratedFiles\styles\style_boxes.cpp" />
|
||||
<ClCompile Include="GeneratedFiles\styles\style_dialogs.cpp" />
|
||||
<ClCompile Include="GeneratedFiles\styles\style_history.cpp" />
|
||||
<ClCompile Include="GeneratedFiles\styles\style_overview.cpp" />
|
||||
|
@ -1457,6 +1458,7 @@
|
|||
<ClInclude Include="GeneratedFiles\numbers.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_basic.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_basic_types.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_boxes.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_dialogs.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_history.h" />
|
||||
<ClInclude Include="GeneratedFiles\styles\style_overview.h" />
|
||||
|
@ -2876,6 +2878,7 @@
|
|||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling style %(Identity)...</Message>
|
||||
</CustomBuild>
|
||||
<CodegenStyleItem Include="Resources\basic_types.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\boxes\boxes.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\dialogs\dialogs.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\history\history.style" />
|
||||
<CodegenStyleItem Include="SourceFiles\overview\overview.style" />
|
||||
|
|
|
@ -1344,6 +1344,9 @@
|
|||
<ClCompile Include="SourceFiles\platform\linux\linux_libs.cpp">
|
||||
<Filter>SourceFiles\platform\linux</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\styles\style_boxes.cpp">
|
||||
<Filter>GeneratedFiles\styles</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SourceFiles\stdafx.h">
|
||||
|
@ -1595,6 +1598,9 @@
|
|||
<ClInclude Include="SourceFiles\platform\linux\linux_libs.h">
|
||||
<Filter>SourceFiles\platform\linux</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GeneratedFiles\styles\style_boxes.h">
|
||||
<Filter>GeneratedFiles\styles</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="SourceFiles\application.h">
|
||||
|
@ -1966,6 +1972,9 @@
|
|||
<CodegenStyleItem Include="SourceFiles\profile\profile.style">
|
||||
<Filter>SourceFiles\profile</Filter>
|
||||
</CodegenStyleItem>
|
||||
<CodegenStyleItem Include="SourceFiles\boxes\boxes.style">
|
||||
<Filter>SourceFiles\boxes</Filter>
|
||||
</CodegenStyleItem>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Resources\winrc\Telegram.rc">
|
||||
|
|
Loading…
Reference in New Issue