mirror of https://github.com/procxx/kepka.git
Game sharing and inline results supported. Qt patch updated.
Qt patch now disables QT_SCALE_FACTOR and other HighDpi environment variables reading because tdesktop doesn't support them.
This commit is contained in:
parent
5529e24000
commit
344890c533
|
@ -47,6 +47,20 @@ index 14e4fd1..c31c62b 100644
|
||||||
{ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 14, 9, 11, 11 },
|
{ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 14, 9, 11, 11 },
|
||||||
{ 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 14, 9, 11, 11 },
|
{ 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 14, 9, 11, 11 },
|
||||||
{ 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 14, 9, 11, 11 },
|
{ 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 14, 9, 11, 11 },
|
||||||
|
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
|
||||||
|
index b0ef2a2..7d5f7bc 100644
|
||||||
|
--- a/src/gui/kernel/qhighdpiscaling.cpp
|
||||||
|
+++ b/src/gui/kernel/qhighdpiscaling.cpp
|
||||||
|
@@ -51,6 +51,9 @@ static const char screenFactorsEnvVar[] = "QT_SCREEN_SCALE_FACTORS";
|
||||||
|
|
||||||
|
static inline qreal initialGlobalScaleFactor()
|
||||||
|
{
|
||||||
|
+ // Disable environment variable dpi scaling changing.
|
||||||
|
+ // It is not supported by Telegram Desktop :(
|
||||||
|
+ return 1.;
|
||||||
|
|
||||||
|
qreal result = 1;
|
||||||
|
if (qEnvironmentVariableIsSet(scaleFactorEnvVar)) {
|
||||||
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
|
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
|
||||||
index 5b2f4ec..346a26f 100644
|
index 5b2f4ec..346a26f 100644
|
||||||
--- a/src/gui/kernel/qplatformdialoghelper.h
|
--- a/src/gui/kernel/qplatformdialoghelper.h
|
||||||
|
|
|
@ -580,6 +580,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_action_pinned_media_contact" = "a contact information";
|
"lng_action_pinned_media_contact" = "a contact information";
|
||||||
"lng_action_pinned_media_location" = "a location mark";
|
"lng_action_pinned_media_location" = "a location mark";
|
||||||
"lng_action_pinned_media_sticker" = "a sticker";
|
"lng_action_pinned_media_sticker" = "a sticker";
|
||||||
|
"lng_action_pinned_media_emoji_sticker" = "a {emoji} sticker";
|
||||||
|
"lng_action_pinned_media_game" = "a game «{game}»";
|
||||||
"lng_action_game_score" = "{from} scored {count:#|#|#} in {game}";
|
"lng_action_game_score" = "{from} scored {count:#|#|#} in {game}";
|
||||||
|
|
||||||
"lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached";
|
"lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached";
|
||||||
|
@ -774,6 +776,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_bot_groups_not_found" = "No groups found";
|
"lng_bot_groups_not_found" = "No groups found";
|
||||||
"lng_bot_sure_invite" = "Add the bot to «{group}»?";
|
"lng_bot_sure_invite" = "Add the bot to «{group}»?";
|
||||||
"lng_bot_already_in_group" = "The bot is already a member of the group.";
|
"lng_bot_already_in_group" = "The bot is already a member of the group.";
|
||||||
|
"lng_bot_choose_chat" = "Choose Chat";
|
||||||
|
"lng_bot_no_chats" = "You have no chats";
|
||||||
|
"lng_bot_chats_not_found" = "No chats found";
|
||||||
|
"lng_bot_sure_share_game" = "Share the game with {user}?";
|
||||||
|
"lng_bot_sure_share_game_group" = "Share the game with «{group}»?";
|
||||||
|
|
||||||
"lng_typing" = "typing";
|
"lng_typing" = "typing";
|
||||||
"lng_user_typing" = "{user} is typing";
|
"lng_user_typing" = "{user} is typing";
|
||||||
|
|
|
@ -1856,8 +1856,9 @@ namespace {
|
||||||
gamesData.erase(i);
|
gamesData.erase(i);
|
||||||
}
|
}
|
||||||
convert->id = game;
|
convert->id = game;
|
||||||
|
convert->accessHash = 0;
|
||||||
}
|
}
|
||||||
if (convert->shortName.isEmpty() && !shortName.isEmpty()) {
|
if (!convert->accessHash && accessHash) {
|
||||||
convert->accessHash = accessHash;
|
convert->accessHash = accessHash;
|
||||||
convert->shortName = textClean(shortName);
|
convert->shortName = textClean(shortName);
|
||||||
convert->title = textOneLine(textClean(title));
|
convert->title = textOneLine(textClean(title));
|
||||||
|
@ -1879,7 +1880,7 @@ namespace {
|
||||||
} else {
|
} else {
|
||||||
result = i.value();
|
result = i.value();
|
||||||
if (result != convert) {
|
if (result != convert) {
|
||||||
if (result->shortName.isEmpty() && !shortName.isEmpty()) {
|
if (!result->accessHash && accessHash) {
|
||||||
result->accessHash = accessHash;
|
result->accessHash = accessHash;
|
||||||
result->shortName = textClean(shortName);
|
result->shortName = textClean(shortName);
|
||||||
result->title = textOneLine(textClean(title));
|
result->title = textOneLine(textClean(title));
|
||||||
|
|
|
@ -650,9 +650,17 @@ namespace Sandbox {
|
||||||
cSetScreenScale(dbisTwo);
|
cSetScreenScale(dbisTwo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (application()->devicePixelRatio() > 1) {
|
auto devicePixelRatio = application()->devicePixelRatio();
|
||||||
|
if (devicePixelRatio > 1.) {
|
||||||
|
if ((cPlatform() != dbipMac && cPlatform() != dbipMacOld) || (devicePixelRatio != 2.)) {
|
||||||
|
LOG(("Found non-trivial Device Pixel Ratio: %1").arg(devicePixelRatio));
|
||||||
|
LOG(("Environmental variables: QT_DEVICE_PIXEL_RATIO='%1'").arg(QString::fromLatin1(qgetenv("QT_DEVICE_PIXEL_RATIO"))));
|
||||||
|
LOG(("Environmental variables: QT_SCALE_FACTOR='%1'").arg(QString::fromLatin1(qgetenv("QT_SCALE_FACTOR"))));
|
||||||
|
LOG(("Environmental variables: QT_AUTO_SCREEN_SCALE_FACTOR='%1'").arg(QString::fromLatin1(qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR"))));
|
||||||
|
LOG(("Environmental variables: QT_SCREEN_SCALE_FACTORS='%1'").arg(QString::fromLatin1(qgetenv("QT_SCREEN_SCALE_FACTORS"))));
|
||||||
|
}
|
||||||
cSetRetina(true);
|
cSetRetina(true);
|
||||||
cSetRetinaFactor(application()->devicePixelRatio());
|
cSetRetinaFactor(devicePixelRatio);
|
||||||
cSetIntRetinaFactor(int32(cRetinaFactor()));
|
cSetIntRetinaFactor(int32(cRetinaFactor()));
|
||||||
cSetConfigScale(dbisOne);
|
cSetConfigScale(dbisOne);
|
||||||
cSetRealScale(dbisOne);
|
cSetRealScale(dbisOne);
|
||||||
|
|
|
@ -86,6 +86,17 @@ ContactsInner::ContactsInner(ChatData *chat, MembersFilter membersFilter) : TWid
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename FilterCallback>
|
||||||
|
void ContactsInner::addDialogsToList(FilterCallback callback) {
|
||||||
|
auto v = App::main()->dialogsList();
|
||||||
|
for_const (auto row, *v) {
|
||||||
|
auto peer = row->history()->peer;
|
||||||
|
if (callback(peer)) {
|
||||||
|
_contacts->addToEnd(row->history());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ContactsInner::ContactsInner(UserData *bot) : TWidget()
|
ContactsInner::ContactsInner(UserData *bot) : TWidget()
|
||||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||||
, _bot(bot)
|
, _bot(bot)
|
||||||
|
@ -93,14 +104,25 @@ ContactsInner::ContactsInner(UserData *bot) : TWidget()
|
||||||
, _customList(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add))
|
, _customList(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add))
|
||||||
, _contacts(_customList.get())
|
, _contacts(_customList.get())
|
||||||
, _addContactLnk(this, lang(lng_add_contact_button)) {
|
, _addContactLnk(this, lang(lng_add_contact_button)) {
|
||||||
auto v = App::main()->dialogsList();
|
if (sharingBotGame()) {
|
||||||
for_const (auto row, *v) {
|
addDialogsToList([](PeerData *peer) {
|
||||||
auto peer = row->history()->peer;
|
if (peer->canWrite()) {
|
||||||
if (peer->isChat() && peer->asChat()->canEdit()) {
|
if (auto channel = peer->asChannel()) {
|
||||||
_contacts->addToEnd(row->history());
|
return !channel->isBroadcast();
|
||||||
} else if (peer->isMegagroup() && (peer->asChannel()->amCreator() || peer->asChannel()->amEditor())) {
|
}
|
||||||
_contacts->addToEnd(row->history());
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addDialogsToList([](PeerData *peer) {
|
||||||
|
if (peer->isChat() && peer->asChat()->canEdit()) {
|
||||||
|
return true;
|
||||||
|
} else if (peer->isMegagroup() && (peer->asChannel()->amCreator() || peer->asChannel()->amEditor())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
@ -166,8 +188,22 @@ void ContactsInner::onPeerNameChanged(PeerData *peer, const PeerData::Names &old
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsInner::onAddBot() {
|
void ContactsInner::onAddBot() {
|
||||||
if (_bot->botInfo && !_bot->botInfo->startGroupToken.isEmpty()) {
|
if (auto &info = _bot->botInfo) {
|
||||||
MTP::send(MTPmessages_StartBot(_bot->inputUser, _addToPeer->input, MTP_long(rand_value<uint64>()), MTP_string(_bot->botInfo->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _bot));
|
if (!info->shareGameShortName.isEmpty()) {
|
||||||
|
MTPmessages_SendMedia::Flags sendFlags = 0;
|
||||||
|
|
||||||
|
auto history = App::historyLoaded(_addToPeer);
|
||||||
|
auto afterRequestId = history ? history->sendRequestId : 0;
|
||||||
|
auto randomId = rand_value<uint64>();
|
||||||
|
auto requestId = MTP::send(MTPmessages_SendMedia(MTP_flags(sendFlags), _addToPeer->input, MTP_int(0), MTP_inputMediaGame(MTP_inputGameShortName(_bot->inputUser, MTP_string(info->shareGameShortName))), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, afterRequestId);
|
||||||
|
if (history) {
|
||||||
|
history->sendRequestId = requestId;
|
||||||
|
}
|
||||||
|
} else if (!info->startGroupToken.isEmpty()) {
|
||||||
|
MTP::send(MTPmessages_StartBot(_bot->inputUser, _addToPeer->input, MTP_long(rand_value<uint64>()), MTP_string(info->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _bot));
|
||||||
|
} else {
|
||||||
|
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
||||||
}
|
}
|
||||||
|
@ -511,7 +547,7 @@ void ContactsInner::paintEvent(QPaintEvent *e) {
|
||||||
QString text;
|
QString text;
|
||||||
int32 skip = 0;
|
int32 skip = 0;
|
||||||
if (bot()) {
|
if (bot()) {
|
||||||
text = lang(cDialogsReceived() ? lng_bot_no_groups : lng_contacts_loading);
|
text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups) : lng_contacts_loading);
|
||||||
} else if (_chat && _membersFilter == MembersFilterAdmins) {
|
} else if (_chat && _membersFilter == MembersFilterAdmins) {
|
||||||
text = lang(lng_contacts_loading);
|
text = lang(lng_contacts_loading);
|
||||||
p.fillRect(0, 0, width(), _newItemHeight - st::contactsPadding.bottom() - st::lineWidth, st::contactsAboutBg);
|
p.fillRect(0, 0, width(), _newItemHeight - st::contactsPadding.bottom() - st::lineWidth, st::contactsAboutBg);
|
||||||
|
@ -538,7 +574,7 @@ void ContactsInner::paintEvent(QPaintEvent *e) {
|
||||||
p.setPen(st::noContactsColor->p);
|
p.setPen(st::noContactsColor->p);
|
||||||
QString text;
|
QString text;
|
||||||
if (bot()) {
|
if (bot()) {
|
||||||
text = lang(cDialogsReceived() ? lng_bot_groups_not_found : lng_contacts_loading);
|
text = lang((cDialogsReceived() && !_searching) ? (sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found) : lng_contacts_loading);
|
||||||
} else if (_chat && _membersFilter == MembersFilterAdmins) {
|
} else if (_chat && _membersFilter == MembersFilterAdmins) {
|
||||||
text = lang(_chat->participants.isEmpty() ? lng_contacts_loading : lng_contacts_not_found);
|
text = lang(_chat->participants.isEmpty() ? lng_contacts_loading : lng_contacts_not_found);
|
||||||
} else {
|
} else {
|
||||||
|
@ -702,11 +738,22 @@ void ContactsInner::chooseParticipant() {
|
||||||
connect(_addAdminBox, SIGNAL(confirmed()), this, SLOT(onAddAdmin()));
|
connect(_addAdminBox, SIGNAL(confirmed()), this, SLOT(onAddAdmin()));
|
||||||
connect(_addAdminBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoAddAdminBox(QObject*)));
|
connect(_addAdminBox, SIGNAL(destroyed(QObject*)), this, SLOT(onNoAddAdminBox(QObject*)));
|
||||||
Ui::showLayer(_addAdminBox, KeepOtherLayers);
|
Ui::showLayer(_addAdminBox, KeepOtherLayers);
|
||||||
|
} else if (sharingBotGame()) {
|
||||||
|
_addToPeer = peer;
|
||||||
|
auto confirmText = [peer] {
|
||||||
|
if (peer->isUser()) {
|
||||||
|
return lng_bot_sure_share_game(lt_user, App::peerName(peer));
|
||||||
|
}
|
||||||
|
return lng_bot_sure_share_game_group(lt_group, peer->name);
|
||||||
|
};
|
||||||
|
auto box = std_::make_unique<ConfirmBox>(confirmText());
|
||||||
|
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot()));
|
||||||
|
Ui::showLayer(box.release(), KeepOtherLayers);
|
||||||
} else if (bot() && (peer->isChat() || peer->isMegagroup())) {
|
} else if (bot() && (peer->isChat() || peer->isMegagroup())) {
|
||||||
_addToPeer = peer;
|
_addToPeer = peer;
|
||||||
ConfirmBox *box = new ConfirmBox(lng_bot_sure_invite(lt_group, peer->name));
|
auto box = std_::make_unique<ConfirmBox>(lng_bot_sure_invite(lt_group, peer->name));
|
||||||
connect(box, SIGNAL(confirmed()), this, SLOT(onAddBot()));
|
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onAddBot()));
|
||||||
Ui::showLayer(box, KeepOtherLayers);
|
Ui::showLayer(box.release(), KeepOtherLayers);
|
||||||
} else {
|
} else {
|
||||||
Ui::hideSettingsAndLayer(true);
|
Ui::hideSettingsAndLayer(true);
|
||||||
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
|
App::main()->choosePeer(peer->id, ShowAtUnreadMsgId);
|
||||||
|
@ -899,7 +946,7 @@ void ContactsInner::updateFilter(QString filter) {
|
||||||
_mouseSel = false;
|
_mouseSel = false;
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
if (!bot() && (!_chat || _membersFilter != MembersFilterAdmins)) {
|
if ((!bot() || sharingBotGame()) && (!_chat || _membersFilter != MembersFilterAdmins)) {
|
||||||
_searching = true;
|
_searching = true;
|
||||||
emit searchByUsername();
|
emit searchByUsername();
|
||||||
}
|
}
|
||||||
|
@ -966,6 +1013,15 @@ void ContactsInner::peopleReceived(const QString &query, const QVector<MTPPeer>
|
||||||
} else {
|
} else {
|
||||||
continue; // skip
|
continue; // skip
|
||||||
}
|
}
|
||||||
|
} else if (sharingBotGame()) {
|
||||||
|
if (!p->canWrite()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (auto channel = p->asChannel()) {
|
||||||
|
if (channel->isBroadcast()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactData *d = new ContactData();
|
ContactData *d = new ContactData();
|
||||||
|
@ -1032,6 +1088,10 @@ UserData *ContactsInner::bot() const {
|
||||||
return _bot;
|
return _bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ContactsInner::sharingBotGame() const {
|
||||||
|
return (_bot && _bot->botInfo) ? !_bot->botInfo->shareGameShortName.isEmpty() : false;
|
||||||
|
}
|
||||||
|
|
||||||
CreatingGroupType ContactsInner::creating() const {
|
CreatingGroupType ContactsInner::creating() const {
|
||||||
return _creating;
|
return _creating;
|
||||||
}
|
}
|
||||||
|
@ -1040,8 +1100,11 @@ ContactsInner::~ContactsInner() {
|
||||||
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
|
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
if (_bot || (_chat && _membersFilter == MembersFilterAdmins)) {
|
if (_bot) {
|
||||||
if (_bot && _bot->botInfo) _bot->botInfo->startGroupToken = QString();
|
if (auto &info = _bot->botInfo) {
|
||||||
|
info->startGroupToken = QString();
|
||||||
|
info->shareGameShortName = QString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1499,6 +1562,8 @@ void ContactsBox::paintEvent(QPaintEvent *e) {
|
||||||
QString title(lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant));
|
QString title(lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant));
|
||||||
QString additional((addingAdmin || (_inner.channel() && !_inner.channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner.selectedCount()).arg(Global::MegagroupSizeMax()));
|
QString additional((addingAdmin || (_inner.channel() && !_inner.channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner.selectedCount()).arg(Global::MegagroupSizeMax()));
|
||||||
paintTitle(p, title, additional);
|
paintTitle(p, title, additional);
|
||||||
|
} else if (_inner.sharingBotGame()) {
|
||||||
|
paintTitle(p, lang(lng_bot_choose_chat));
|
||||||
} else if (_inner.bot()) {
|
} else if (_inner.bot()) {
|
||||||
paintTitle(p, lang(lng_bot_choose_group));
|
paintTitle(p, lang(lng_bot_choose_group));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -78,6 +78,8 @@ public:
|
||||||
UserData *bot() const;
|
UserData *bot() const;
|
||||||
CreatingGroupType creating() const;
|
CreatingGroupType creating() const;
|
||||||
|
|
||||||
|
bool sharingBotGame() const;
|
||||||
|
|
||||||
int32 selectedCount() const;
|
int32 selectedCount() const;
|
||||||
bool hasAlreadyMembersInChannel() const {
|
bool hasAlreadyMembersInChannel() const {
|
||||||
return !_already.isEmpty();
|
return !_already.isEmpty();
|
||||||
|
@ -121,6 +123,9 @@ private:
|
||||||
void addAdminDone(const MTPUpdates &result, mtpRequestId req);
|
void addAdminDone(const MTPUpdates &result, mtpRequestId req);
|
||||||
bool addAdminFail(const RPCError &error, mtpRequestId req);
|
bool addAdminFail(const RPCError &error, mtpRequestId req);
|
||||||
|
|
||||||
|
template <typename FilterCallback>
|
||||||
|
void addDialogsToList(FilterCallback callback);
|
||||||
|
|
||||||
int32 _rowHeight;
|
int32 _rowHeight;
|
||||||
int _newItemHeight = 0;
|
int _newItemHeight = 0;
|
||||||
bool _newItemSel = false;
|
bool _newItemSel = false;
|
||||||
|
|
|
@ -87,7 +87,7 @@ void ReportBox::onChange() {
|
||||||
_reasonOtherText.destroy();
|
_reasonOtherText.destroy();
|
||||||
updateMaxHeight();
|
updateMaxHeight();
|
||||||
}
|
}
|
||||||
if (App::wnd()) App::wnd()->setInnerFocus();
|
_reasonOtherText->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReportBox::doSetInnerFocus() {
|
void ReportBox::doSetInnerFocus() {
|
||||||
|
|
|
@ -32,11 +32,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
|
#include "history/history_media_types.h"
|
||||||
|
|
||||||
ShareBox::ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback) : ItemListBox(st::boxScroll)
|
ShareBox::ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback) : ItemListBox(st::boxScroll)
|
||||||
, _copyCallback(std_::move(copyCallback))
|
, _copyCallback(std_::move(copyCallback))
|
||||||
, _submitCallback(std_::move(submitCallback))
|
, _submitCallback(std_::move(submitCallback))
|
||||||
, _inner(this)
|
, _inner(this, std_::move(filterCallback))
|
||||||
, _filter(this, st::boxSearchField, lang(lng_participant_filter))
|
, _filter(this, st::boxSearchField, lang(lng_participant_filter))
|
||||||
, _filterCancel(this, st::boxSearchCancel)
|
, _filterCancel(this, st::boxSearchCancel)
|
||||||
, _copy(this, lang(lng_share_copy_link), st::defaultBoxButton)
|
, _copy(this, lang(lng_share_copy_link), st::defaultBoxButton)
|
||||||
|
@ -241,7 +242,8 @@ void ShareBox::onScroll() {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
ShareInner::ShareInner(QWidget *parent) : ScrolledWidget(parent)
|
ShareInner::ShareInner(QWidget *parent, ShareBox::FilterCallback &&filterCallback) : ScrolledWidget(parent)
|
||||||
|
, _filterCallback(std_::move(filterCallback))
|
||||||
, _chatsIndexed(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) {
|
, _chatsIndexed(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) {
|
||||||
_rowsTop = st::shareRowsTop;
|
_rowsTop = st::shareRowsTop;
|
||||||
_rowHeight = st::shareRowHeight;
|
_rowHeight = st::shareRowHeight;
|
||||||
|
@ -250,7 +252,7 @@ ShareInner::ShareInner(QWidget *parent) : ScrolledWidget(parent)
|
||||||
auto dialogs = App::main()->dialogsList();
|
auto dialogs = App::main()->dialogsList();
|
||||||
for_const (auto row, dialogs->all()) {
|
for_const (auto row, dialogs->all()) {
|
||||||
auto history = row->history();
|
auto history = row->history();
|
||||||
if (history->peer->canWrite()) {
|
if (_filterCallback(history->peer)) {
|
||||||
_chatsIndexed->addToEnd(history);
|
_chatsIndexed->addToEnd(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -863,7 +865,7 @@ void ShareInner::peopleReceived(const QString &query, const QVector<MTPPeer> &pe
|
||||||
}
|
}
|
||||||
if (j == already) {
|
if (j == already) {
|
||||||
auto *peer = App::peer(peerId);
|
auto *peer = App::peer(peerId);
|
||||||
if (!peer || !peer->canWrite()) continue;
|
if (!peer || !_filterCallback(peer)) continue;
|
||||||
|
|
||||||
auto chat = new Chat(peer);
|
auto chat = new Chat(peer);
|
||||||
updateChatName(chat, peer);
|
updateChatName(chat, peer);
|
||||||
|
@ -958,24 +960,15 @@ void shareGameScoreFromItem(HistoryItem *item) {
|
||||||
if (auto main = App::main()) {
|
if (auto main = App::main()) {
|
||||||
if (auto item = App::histItemById(data->msgId)) {
|
if (auto item = App::histItemById(data->msgId)) {
|
||||||
if (auto bot = item->getMessageBot()) {
|
if (auto bot = item->getMessageBot()) {
|
||||||
if (auto markup = item->Get<HistoryMessageReplyMarkup>()) {
|
if (auto media = item->getMedia()) {
|
||||||
for (int i = 0, rowsCount = markup->rows.size(); i != rowsCount; ++i) {
|
if (media->type() == MediaTypeGame) {
|
||||||
auto &row = markup->rows[i];
|
auto shortName = static_cast<HistoryGame*>(media)->game()->shortName;
|
||||||
for (int j = 0, buttonsCount = row.size(); j != buttonsCount; ++j) {
|
|
||||||
auto &button = row[j];
|
|
||||||
if (button.type == HistoryMessageReplyMarkup::Button::Type::Game) {
|
|
||||||
auto strData = QString::fromUtf8(button.data);
|
|
||||||
auto parts = strData.split(',');
|
|
||||||
t_assert(parts.size() > 1);
|
|
||||||
|
|
||||||
QApplication::clipboard()->setText(qsl("https://telegram.me/") + bot->username + qsl("?start=") + parts[1]);
|
QApplication::clipboard()->setText(qsl("https://telegram.me/") + bot->username + qsl("?game=") + shortName);
|
||||||
|
|
||||||
Ui::Toast::Config toast;
|
Ui::Toast::Config toast;
|
||||||
toast.text = lang(lng_share_game_link_copied);
|
toast.text = lang(lng_share_game_link_copied);
|
||||||
Ui::Toast::Show(App::wnd(), toast);
|
Ui::Toast::Show(App::wnd(), toast);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1015,7 +1008,16 @@ void shareGameScoreFromItem(HistoryItem *item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback)));
|
auto filterCallback = [](PeerData *peer) {
|
||||||
|
if (peer->canWrite()) {
|
||||||
|
if (auto channel = peer->asChannel()) {
|
||||||
|
return !channel->isBroadcast();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback), std_::move(filterCallback)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -47,7 +47,8 @@ class ShareBox : public ItemListBox, public RPCSender {
|
||||||
public:
|
public:
|
||||||
using CopyCallback = base::lambda_unique<void()>;
|
using CopyCallback = base::lambda_unique<void()>;
|
||||||
using SubmitCallback = base::lambda_unique<void(const QVector<PeerData*> &)>;
|
using SubmitCallback = base::lambda_unique<void(const QVector<PeerData*> &)>;
|
||||||
ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback);
|
using FilterCallback = base::lambda_unique<bool(PeerData*)>;
|
||||||
|
ShareBox(CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onFilterUpdate();
|
void onFilterUpdate();
|
||||||
|
@ -112,7 +113,7 @@ class ShareInner : public ScrolledWidget, public RPCSender, private base::Subscr
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShareInner(QWidget *parent);
|
ShareInner(QWidget *parent, ShareBox::FilterCallback &&filterCallback);
|
||||||
|
|
||||||
QVector<PeerData*> selected() const;
|
QVector<PeerData*> selected() const;
|
||||||
bool hasSelected() const;
|
bool hasSelected() const;
|
||||||
|
@ -197,6 +198,7 @@ private:
|
||||||
int _active = -1;
|
int _active = -1;
|
||||||
int _upon = -1;
|
int _upon = -1;
|
||||||
|
|
||||||
|
ShareBox::FilterCallback _filterCallback;
|
||||||
std_::unique_ptr<Dialogs::IndexedList> _chatsIndexed;
|
std_::unique_ptr<Dialogs::IndexedList> _chatsIndexed;
|
||||||
QString _filter;
|
QString _filter;
|
||||||
using FilteredDialogs = QVector<Dialogs::Row*>;
|
using FilteredDialogs = QVector<Dialogs::Row*>;
|
||||||
|
|
|
@ -881,6 +881,10 @@ HistoryItem *History::createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32
|
||||||
return HistoryMessage::create(this, id, flags, replyTo, viaBotId, date, from, photo, caption, markup);
|
return HistoryMessage::create(this, id, flags, replyTo, viaBotId, date, from, photo, caption, markup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HistoryItem *History::createItemGame(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, GameData *game, const MTPReplyMarkup &markup) {
|
||||||
|
return HistoryMessage::create(this, id, flags, replyTo, viaBotId, date, from, game, markup);
|
||||||
|
}
|
||||||
|
|
||||||
HistoryItem *History::addNewService(MsgId msgId, QDateTime date, const QString &text, MTPDmessage::Flags flags, bool newMsg) {
|
HistoryItem *History::addNewService(MsgId msgId, QDateTime date, const QString &text, MTPDmessage::Flags flags, bool newMsg) {
|
||||||
return addNewItem(HistoryService::create(this, msgId, date, text, flags), newMsg);
|
return addNewItem(HistoryService::create(this, msgId, date, text, flags), newMsg);
|
||||||
}
|
}
|
||||||
|
@ -928,6 +932,10 @@ HistoryItem *History::addNewPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaB
|
||||||
return addNewItem(createItemPhoto(id, flags, viaBotId, replyTo, date, from, photo, caption, markup), true);
|
return addNewItem(createItemPhoto(id, flags, viaBotId, replyTo, date, from, photo, caption, markup), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HistoryItem *History::addNewGame(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, GameData *game, const MTPReplyMarkup &markup) {
|
||||||
|
return addNewItem(createItemGame(id, flags, viaBotId, replyTo, date, from, game, markup), true);
|
||||||
|
}
|
||||||
|
|
||||||
bool History::addToOverview(MediaOverviewType type, MsgId msgId, AddToOverviewMethod method) {
|
bool History::addToOverview(MediaOverviewType type, MsgId msgId, AddToOverviewMethod method) {
|
||||||
bool adding = false;
|
bool adding = false;
|
||||||
switch (method) {
|
switch (method) {
|
||||||
|
|
|
@ -205,6 +205,7 @@ public:
|
||||||
HistoryItem *addNewForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *item);
|
HistoryItem *addNewForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *item);
|
||||||
HistoryItem *addNewDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption, const MTPReplyMarkup &markup);
|
HistoryItem *addNewDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption, const MTPReplyMarkup &markup);
|
||||||
HistoryItem *addNewPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup);
|
HistoryItem *addNewPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup);
|
||||||
|
HistoryItem *addNewGame(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, GameData *game, const MTPReplyMarkup &markup);
|
||||||
|
|
||||||
void addOlderSlice(const QVector<MTPMessage> &slice);
|
void addOlderSlice(const QVector<MTPMessage> &slice);
|
||||||
void addNewerSlice(const QVector<MTPMessage> &slice);
|
void addNewerSlice(const QVector<MTPMessage> &slice);
|
||||||
|
@ -463,6 +464,7 @@ protected:
|
||||||
HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg);
|
HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg);
|
||||||
HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption, const MTPReplyMarkup &markup);
|
HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption, const MTPReplyMarkup &markup);
|
||||||
HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup);
|
HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup);
|
||||||
|
HistoryItem *createItemGame(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, GameData *game, const MTPReplyMarkup &markup);
|
||||||
|
|
||||||
HistoryItem *addNewItem(HistoryItem *adding, bool newMsg);
|
HistoryItem *addNewItem(HistoryItem *adding, bool newMsg);
|
||||||
HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex);
|
HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex);
|
||||||
|
|
|
@ -69,7 +69,7 @@ inline void initTextOptions() {
|
||||||
|
|
||||||
bool needReSetInlineResultDocument(const MTPMessageMedia &media, DocumentData *existing) {
|
bool needReSetInlineResultDocument(const MTPMessageMedia &media, DocumentData *existing) {
|
||||||
if (media.type() == mtpc_messageMediaDocument) {
|
if (media.type() == mtpc_messageMediaDocument) {
|
||||||
if (DocumentData *document = App::feedDocument(media.c_messageMediaDocument().vdocument)) {
|
if (auto document = App::feedDocument(media.c_messageMediaDocument().vdocument)) {
|
||||||
if (document == existing) {
|
if (document == existing) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1964,8 +1964,6 @@ private:
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
HistorySticker::HistorySticker(HistoryItem *parent, DocumentData *document) : HistoryMedia(parent)
|
HistorySticker::HistorySticker(HistoryItem *parent, DocumentData *document) : HistoryMedia(parent)
|
||||||
, _pixw(1)
|
|
||||||
, _pixh(1)
|
|
||||||
, _data(document)
|
, _data(document)
|
||||||
, _emoji(_data->sticker()->alt) {
|
, _emoji(_data->sticker()->alt) {
|
||||||
_data->thumb->load();
|
_data->thumb->load();
|
||||||
|
@ -3103,11 +3101,12 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, uint
|
||||||
p.translate(attachLeft, attachTop);
|
p.translate(attachLeft, attachTop);
|
||||||
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
|
||||||
auto pixwidth = _attach->currentWidth();
|
auto pixwidth = _attach->currentWidth();
|
||||||
|
auto pixheight = _attach->height();
|
||||||
|
|
||||||
auto gameX = st::msgDateImgDelta;
|
|
||||||
auto gameY = st::msgDateImgDelta;
|
|
||||||
auto gameW = _gameTagWidth + 2 * st::msgDateImgPadding.x();
|
auto gameW = _gameTagWidth + 2 * st::msgDateImgPadding.x();
|
||||||
auto gameH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
|
auto gameH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
|
||||||
|
auto gameX = pixwidth - st::msgDateImgDelta - gameW;
|
||||||
|
auto gameY = pixheight - st::msgDateImgDelta - gameH;
|
||||||
|
|
||||||
App::roundRect(p, rtlrect(gameX, gameY, gameW, gameH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
App::roundRect(p, rtlrect(gameX, gameY, gameW, gameH, pixwidth), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
||||||
|
|
||||||
|
@ -3214,12 +3213,25 @@ void HistoryGame::detachFromParent() {
|
||||||
if (_attach) _attach->detachFromParent();
|
if (_attach) _attach->detachFromParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HistoryGame::notificationText() const {
|
void HistoryGame::updateSentMedia(const MTPMessageMedia &media) {
|
||||||
return _data->title;
|
if (media.type() == mtpc_messageMediaGame) {
|
||||||
|
auto &game = media.c_messageMediaGame().vgame;
|
||||||
|
if (game.type() == mtpc_game) {
|
||||||
|
App::feedGame(game.c_game(), _data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HistoryGame::inDialogsText() const {
|
bool HistoryGame::needReSetInlineResultMedia(const MTPMessageMedia &media) {
|
||||||
return textcmdLink(1, _data->title);
|
updateSentMedia(media);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HistoryGame::notificationText() const {
|
||||||
|
QString result; // add a game controller emoji before game title
|
||||||
|
result.reserve(_data->title.size() + 3);
|
||||||
|
result.append(QChar(0xD83C)).append(QChar(0xDFAE)).append(QChar(' ')).append(_data->title);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextWithEntities HistoryGame::selectedText(TextSelection selection) const {
|
TextWithEntities HistoryGame::selectedText(TextSelection selection) const {
|
||||||
|
|
|
@ -552,6 +552,9 @@ public:
|
||||||
bool customInfoLayout() const override {
|
bool customInfoLayout() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
QString emoji() const {
|
||||||
|
return _emoji;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int additionalWidth(const HistoryMessageVia *via, const HistoryMessageReply *reply) const;
|
int additionalWidth(const HistoryMessageVia *via, const HistoryMessageReply *reply) const;
|
||||||
|
@ -560,7 +563,8 @@ private:
|
||||||
}
|
}
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
int16 _pixw, _pixh;
|
int16 _pixw = 1;
|
||||||
|
int16 _pixh = 1;
|
||||||
ClickHandlerPtr _packLink;
|
ClickHandlerPtr _packLink;
|
||||||
DocumentData *_data;
|
DocumentData *_data;
|
||||||
QString _emoji;
|
QString _emoji;
|
||||||
|
@ -762,7 +766,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
QString notificationText() const override;
|
QString notificationText() const override;
|
||||||
QString inDialogsText() const override;
|
|
||||||
TextWithEntities selectedText(TextSelection selection) const override;
|
TextWithEntities selectedText(TextSelection selection) const override;
|
||||||
|
|
||||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||||
|
@ -793,6 +796,9 @@ public:
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateSentMedia(const MTPMessageMedia &media) override;
|
||||||
|
bool needReSetInlineResultMedia(const MTPMessageMedia &media) override;
|
||||||
|
|
||||||
bool needsBubble() const override {
|
bool needsBubble() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ MediaOverviewType messageMediaToOverviewType(HistoryMedia *media) {
|
||||||
case MediaTypePhoto: return OverviewPhotos;
|
case MediaTypePhoto: return OverviewPhotos;
|
||||||
case MediaTypeVideo: return OverviewVideos;
|
case MediaTypeVideo: return OverviewVideos;
|
||||||
case MediaTypeFile: return OverviewFiles;
|
case MediaTypeFile: return OverviewFiles;
|
||||||
case MediaTypeMusicFile: return media->getDocument()->isMusic() ? OverviewMusicFiles : OverviewFiles;
|
case MediaTypeMusicFile: return media->getDocument()->isMusic() ? OverviewMusicFiles : OverviewCount;
|
||||||
case MediaTypeVoiceFile: return OverviewVoiceFiles;
|
case MediaTypeVoiceFile: return OverviewVoiceFiles;
|
||||||
case MediaTypeGif: return media->getDocument()->isGifv() ? OverviewCount : OverviewFiles;
|
case MediaTypeGif: return media->getDocument()->isGifv() ? OverviewCount : OverviewFiles;
|
||||||
default: break;
|
default: break;
|
||||||
|
@ -465,6 +465,14 @@ HistoryMessage::HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags
|
||||||
setText(TextWithEntities());
|
setText(TextWithEntities());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HistoryMessage::HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, GameData *game, const MTPReplyMarkup &markup)
|
||||||
|
: HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) {
|
||||||
|
createComponentsHelper(flags, replyTo, viaBotId, markup);
|
||||||
|
|
||||||
|
_media.reset(new HistoryGame(this, game));
|
||||||
|
setText(TextWithEntities());
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryMessage::createComponentsHelper(MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, const MTPReplyMarkup &markup) {
|
void HistoryMessage::createComponentsHelper(MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, const MTPReplyMarkup &markup) {
|
||||||
CreateConfig config;
|
CreateConfig config;
|
||||||
|
|
||||||
|
@ -1899,7 +1907,7 @@ bool HistoryService::preparePinnedText(const QString &from, QString *outText, Li
|
||||||
ClickHandlerPtr second;
|
ClickHandlerPtr second;
|
||||||
auto pinned = Get<HistoryServicePinned>();
|
auto pinned = Get<HistoryServicePinned>();
|
||||||
if (pinned && pinned->msg) {
|
if (pinned && pinned->msg) {
|
||||||
HistoryMedia *media = pinned->msg->getMedia();
|
auto media = pinned->msg->getMedia();
|
||||||
QString mediaText;
|
QString mediaText;
|
||||||
switch (media ? media->type() : MediaTypeCount) {
|
switch (media ? media->type() : MediaTypeCount) {
|
||||||
case MediaTypePhoto: mediaText = lang(lng_action_pinned_media_photo); break;
|
case MediaTypePhoto: mediaText = lang(lng_action_pinned_media_photo); break;
|
||||||
|
@ -1907,10 +1915,21 @@ bool HistoryService::preparePinnedText(const QString &from, QString *outText, Li
|
||||||
case MediaTypeContact: mediaText = lang(lng_action_pinned_media_contact); break;
|
case MediaTypeContact: mediaText = lang(lng_action_pinned_media_contact); break;
|
||||||
case MediaTypeFile: mediaText = lang(lng_action_pinned_media_file); break;
|
case MediaTypeFile: mediaText = lang(lng_action_pinned_media_file); break;
|
||||||
case MediaTypeGif: mediaText = lang(lng_action_pinned_media_gif); break;
|
case MediaTypeGif: mediaText = lang(lng_action_pinned_media_gif); break;
|
||||||
case MediaTypeSticker: mediaText = lang(lng_action_pinned_media_sticker); break;
|
case MediaTypeSticker: {
|
||||||
|
auto emoji = static_cast<HistorySticker*>(media)->emoji();
|
||||||
|
if (emoji.isEmpty()) {
|
||||||
|
mediaText = lang(lng_action_pinned_media_sticker);
|
||||||
|
} else {
|
||||||
|
mediaText = lng_action_pinned_media_emoji_sticker(lt_emoji, emoji);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case MediaTypeLocation: mediaText = lang(lng_action_pinned_media_location); break;
|
case MediaTypeLocation: mediaText = lang(lng_action_pinned_media_location); break;
|
||||||
case MediaTypeMusicFile: mediaText = lang(lng_action_pinned_media_audio); break;
|
case MediaTypeMusicFile: mediaText = lang(lng_action_pinned_media_audio); break;
|
||||||
case MediaTypeVoiceFile: mediaText = lang(lng_action_pinned_media_voice); break;
|
case MediaTypeVoiceFile: mediaText = lang(lng_action_pinned_media_voice); break;
|
||||||
|
case MediaTypeGame: {
|
||||||
|
auto title = static_cast<HistoryGame*>(media)->game()->title;
|
||||||
|
mediaText = lng_action_pinned_media_game(lt_game, title);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
if (mediaText.isEmpty()) {
|
if (mediaText.isEmpty()) {
|
||||||
QString original = pinned->msg->originalText().text;
|
QString original = pinned->msg->originalText().text;
|
||||||
|
|
|
@ -39,6 +39,9 @@ public:
|
||||||
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup) {
|
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup) {
|
||||||
return _create(history, msgId, flags, replyTo, viaBotId, date, from, photo, caption, markup);
|
return _create(history, msgId, flags, replyTo, viaBotId, date, from, photo, caption, markup);
|
||||||
}
|
}
|
||||||
|
static HistoryMessage *create(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, GameData *game, const MTPReplyMarkup &markup) {
|
||||||
|
return _create(history, msgId, flags, replyTo, viaBotId, date, from, game, markup);
|
||||||
|
}
|
||||||
|
|
||||||
void initTime();
|
void initTime();
|
||||||
void initMedia(const MTPMessageMedia *media);
|
void initMedia(const MTPMessageMedia *media);
|
||||||
|
@ -164,6 +167,7 @@ private:
|
||||||
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, const TextWithEntities &textWithEntities); // local message
|
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, const TextWithEntities &textWithEntities); // local message
|
||||||
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption, const MTPReplyMarkup &markup); // local document
|
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption, const MTPReplyMarkup &markup); // local document
|
||||||
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup); // local photo
|
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption, const MTPReplyMarkup &markup); // local photo
|
||||||
|
HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, GameData *game, const MTPReplyMarkup &markup); // local game
|
||||||
friend class HistoryItemInstantiated<HistoryMessage>;
|
friend class HistoryItemInstantiated<HistoryMessage>;
|
||||||
|
|
||||||
void setEmptyText();
|
void setEmptyText();
|
||||||
|
|
|
@ -134,7 +134,7 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons
|
||||||
|
|
||||||
bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading();
|
bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading();
|
||||||
if (loaded && !gif() && _gif != Media::Clip::BadReader) {
|
if (loaded && !gif() && _gif != Media::Clip::BadReader) {
|
||||||
Gif *that = const_cast<Gif*>(this);
|
auto that = const_cast<Gif*>(this);
|
||||||
that->_gif = new Media::Clip::Reader(document->location(), document->data(), [that](Media::Clip::Notification notification) {
|
that->_gif = new Media::Clip::Reader(document->location(), document->data(), [that](Media::Clip::Notification notification) {
|
||||||
that->clipCallback(notification);
|
that->clipCallback(notification);
|
||||||
});
|
});
|
||||||
|
@ -276,7 +276,6 @@ QSize Gif::countFrameSize() const {
|
||||||
|
|
||||||
Gif::~Gif() {
|
Gif::~Gif() {
|
||||||
if (gif()) deleteAndMark(_gif);
|
if (gif()) deleteAndMark(_gif);
|
||||||
deleteAndMark(_animation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gif::prepareThumb(int32 width, int32 height, const QSize &frame) const {
|
void Gif::prepareThumb(int32 width, int32 height, const QSize &frame) const {
|
||||||
|
@ -306,7 +305,7 @@ void Gif::prepareThumb(int32 width, int32 height, const QSize &frame) const {
|
||||||
|
|
||||||
void Gif::ensureAnimation() const {
|
void Gif::ensureAnimation() const {
|
||||||
if (!_animation) {
|
if (!_animation) {
|
||||||
_animation = new AnimationData(animation(const_cast<Gif*>(this), &Gif::step_radial));
|
_animation = std_::make_unique<AnimationData>(animation(const_cast<Gif*>(this), &Gif::step_radial));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,8 +323,7 @@ void Gif::step_radial(uint64 ms, bool timer) {
|
||||||
DocumentData *document = getShownDocument();
|
DocumentData *document = getShownDocument();
|
||||||
_animation->radial.update(document->progress(), !document->loading() || document->loaded(), ms);
|
_animation->radial.update(document->progress(), !document->loading() || document->loaded(), ms);
|
||||||
if (!_animation->radial.animating() && document->loaded()) {
|
if (!_animation->radial.animating() && document->loaded()) {
|
||||||
delete _animation;
|
_animation.reset();
|
||||||
_animation = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1140,6 +1138,239 @@ void Article::prepareThumb(int width, int height) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Game::Game(Result *result) : ItemBase(result)
|
||||||
|
, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip)
|
||||||
|
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) {
|
||||||
|
countFrameSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::countFrameSize() {
|
||||||
|
if (auto document = getResultDocument()) {
|
||||||
|
if (document->isAnimation()) {
|
||||||
|
auto documentSize = document->dimensions;
|
||||||
|
if (documentSize.isEmpty()) {
|
||||||
|
documentSize = QSize(st::inlineThumbSize, st::inlineThumbSize);
|
||||||
|
}
|
||||||
|
auto resizeByHeight1 = (documentSize.width() > documentSize.height()) && (documentSize.height() >= st::inlineThumbSize);
|
||||||
|
auto resizeByHeight2 = (documentSize.height() >= documentSize.width()) && (documentSize.width() < st::inlineThumbSize);
|
||||||
|
if (resizeByHeight1 || resizeByHeight2) {
|
||||||
|
if (documentSize.height() > st::inlineThumbSize) {
|
||||||
|
_frameSize = QSize((documentSize.width() * st::inlineThumbSize) / documentSize.height(), st::inlineThumbSize);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (documentSize.width() > st::inlineThumbSize) {
|
||||||
|
_frameSize = QSize(st::inlineThumbSize, (documentSize.height() * st::inlineThumbSize) / documentSize.width());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_frameSize.width()) {
|
||||||
|
_frameSize.setWidth(1);
|
||||||
|
}
|
||||||
|
if (!_frameSize.height()) {
|
||||||
|
_frameSize.setHeight(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::initDimensions() {
|
||||||
|
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
|
||||||
|
int32 textWidth = _maxw - (st::inlineThumbSize + st::inlineThumbSkip);
|
||||||
|
TextParseOptions titleOpts = { 0, _maxw, 2 * st::semiboldFont->height, Qt::LayoutDirectionAuto };
|
||||||
|
_title.setText(st::semiboldFont, textOneLine(_result->getLayoutTitle()), titleOpts);
|
||||||
|
int32 titleHeight = qMin(_title.countHeight(_maxw), 2 * st::semiboldFont->height);
|
||||||
|
|
||||||
|
int32 descriptionLines = 2;
|
||||||
|
QString description = _result->getLayoutDescription();
|
||||||
|
TextParseOptions descriptionOpts = { TextParseMultiline, _maxw, descriptionLines * st::normalFont->height, Qt::LayoutDirectionAuto };
|
||||||
|
_description.setText(st::normalFont, description, descriptionOpts);
|
||||||
|
int32 descriptionHeight = qMin(_description.countHeight(_maxw), descriptionLines * st::normalFont->height);
|
||||||
|
|
||||||
|
_minh = titleHeight + descriptionHeight;
|
||||||
|
accumulate_max(_minh, st::inlineThumbSize);
|
||||||
|
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::setPosition(int32 position) {
|
||||||
|
ItemBase::setPosition(position);
|
||||||
|
if (_position < 0) {
|
||||||
|
if (gif()) delete _gif;
|
||||||
|
_gif = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||||
|
int32 left = st::emojiPanHeaderLeft - st::inlineResultsLeft;
|
||||||
|
|
||||||
|
left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||||
|
auto rthumb = rtlrect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize, _width);
|
||||||
|
|
||||||
|
// Gif thumb
|
||||||
|
auto thumbDisplayed = false, radial = false;
|
||||||
|
auto document = getResultDocument();
|
||||||
|
auto animatedThumb = document && document->isAnimation();
|
||||||
|
if (animatedThumb) {
|
||||||
|
document->automaticLoad(nullptr);
|
||||||
|
|
||||||
|
bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading();
|
||||||
|
if (loaded && !gif() && _gif != Media::Clip::BadReader) {
|
||||||
|
auto that = const_cast<Game*>(this);
|
||||||
|
that->_gif = new Media::Clip::Reader(document->location(), document->data(), [that](Media::Clip::Notification notification) {
|
||||||
|
that->clipCallback(notification);
|
||||||
|
});
|
||||||
|
if (gif()) _gif->setAutoplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool animating = (gif() && _gif->started());
|
||||||
|
if (displayLoading) {
|
||||||
|
if (!_radial) {
|
||||||
|
_radial = std_::make_unique<Ui::RadialAnimation>(animation(const_cast<Game*>(this), &Game::step_radial));
|
||||||
|
}
|
||||||
|
if (!_radial->animating()) {
|
||||||
|
_radial->start(document->progress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
radial = isRadialAnimation(context->ms);
|
||||||
|
|
||||||
|
if (animating) {
|
||||||
|
if (!_thumb.isNull()) _thumb = QPixmap();
|
||||||
|
auto animationThumb = _gif->current(_frameSize.width(), _frameSize.height(), st::inlineThumbSize, st::inlineThumbSize, context->paused ? 0 : context->ms);
|
||||||
|
p.drawPixmapLeft(rthumb.topLeft(), _width, animationThumb);
|
||||||
|
thumbDisplayed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thumbDisplayed) {
|
||||||
|
prepareThumb(st::inlineThumbSize, st::inlineThumbSize);
|
||||||
|
if (_thumb.isNull()) {
|
||||||
|
p.fillRect(rthumb, st::overviewPhotoBg);
|
||||||
|
} else {
|
||||||
|
p.drawPixmapLeft(rthumb.topLeft(), _width, _thumb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (radial) {
|
||||||
|
p.fillRect(rthumb, st::msgDateImgBg);
|
||||||
|
QRect inner((st::inlineThumbSize - st::msgFileSize) / 2, (st::inlineThumbSize - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||||
|
if (radial) {
|
||||||
|
p.setOpacity(1);
|
||||||
|
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||||
|
_radial->draw(p, rinner, st::msgFileRadialLine, st::msgInBg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.setPen(st::black);
|
||||||
|
_title.drawLeftElided(p, left, st::inlineRowMargin, _width - left, _width, 2);
|
||||||
|
int32 titleHeight = qMin(_title.countHeight(_width - left), st::semiboldFont->height * 2);
|
||||||
|
|
||||||
|
p.setPen(st::inlineDescriptionFg);
|
||||||
|
int32 descriptionLines = 2;
|
||||||
|
_description.drawLeftElided(p, left, st::inlineRowMargin + titleHeight, _width - left, _width, descriptionLines);
|
||||||
|
|
||||||
|
if (!context->lastRow) {
|
||||||
|
p.fillRect(rtlrect(left, _height - st::inlineRowBorder, _width - left, st::inlineRowBorder, _width), st::inlineRowBorderFg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
|
||||||
|
int left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||||
|
if (x >= 0 && x < left - st::inlineThumbSkip && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::inlineThumbSize) {
|
||||||
|
link = _send;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (x >= left && x < _width && y >= 0 && y < _height) {
|
||||||
|
link = _send;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::prepareThumb(int width, int height) const {
|
||||||
|
auto thumb = ([this]() {
|
||||||
|
if (auto photo = getResultPhoto()) {
|
||||||
|
return photo->medium;
|
||||||
|
} else if (auto document = getResultDocument()) {
|
||||||
|
return document->thumb;
|
||||||
|
}
|
||||||
|
return ImagePtr();
|
||||||
|
})();
|
||||||
|
if (thumb->isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thumb->loaded()) {
|
||||||
|
if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) {
|
||||||
|
int w = qMax(convertScale(thumb->width()), 1), h = qMax(convertScale(thumb->height()), 1);
|
||||||
|
auto resizeByHeight1 = (w * height > h * width) && (h >= height);
|
||||||
|
auto resizeByHeight2 = (h * width >= w * height) && (w < width);
|
||||||
|
if (resizeByHeight1 || resizeByHeight2) {
|
||||||
|
if (h > height) {
|
||||||
|
w = w * height / h;
|
||||||
|
h = height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (w > width) {
|
||||||
|
h = h * width / w;
|
||||||
|
w = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_thumb = thumb->pixNoCache(w * cIntRetinaFactor(), h * cIntRetinaFactor(), ImagePixSmooth, width, height);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
thumb->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Game::isRadialAnimation(uint64 ms) const {
|
||||||
|
if (!_radial || !_radial->animating()) return false;
|
||||||
|
|
||||||
|
_radial->step(ms);
|
||||||
|
return _radial && _radial->animating();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::step_radial(uint64 ms, bool timer) {
|
||||||
|
if (timer) {
|
||||||
|
update();
|
||||||
|
} else {
|
||||||
|
auto document = getResultDocument();
|
||||||
|
_radial->update(document->progress(), !document->loading() || document->loaded(), ms);
|
||||||
|
if (!_radial->animating() && document->loaded()) {
|
||||||
|
_radial.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::clipCallback(Media::Clip::Notification notification) {
|
||||||
|
using namespace Media::Clip;
|
||||||
|
switch (notification) {
|
||||||
|
case NotificationReinit: {
|
||||||
|
if (gif()) {
|
||||||
|
if (_gif->state() == State::Error) {
|
||||||
|
delete _gif;
|
||||||
|
_gif = BadReader;
|
||||||
|
getResultDocument()->forget();
|
||||||
|
} else if (_gif->ready() && !_gif->started()) {
|
||||||
|
_gif->start(_frameSize.width(), _frameSize.height(), st::inlineThumbSize, st::inlineThumbSize, ImageRoundRadius::None);
|
||||||
|
} else if (_gif->autoPausedGif() && !Ui::isInlineItemVisible(this)) {
|
||||||
|
delete _gif;
|
||||||
|
_gif = nullptr;
|
||||||
|
getResultDocument()->forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NotificationRepaint: {
|
||||||
|
if (gif() && !_gif->currentDisplayed()) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::~Game() {
|
||||||
|
if (gif()) deleteAndMark(_gif);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace Layout
|
} // namespace Layout
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -116,7 +116,7 @@ private:
|
||||||
FloatAnimation _a_over;
|
FloatAnimation _a_over;
|
||||||
Ui::RadialAnimation radial;
|
Ui::RadialAnimation radial;
|
||||||
};
|
};
|
||||||
mutable AnimationData *_animation = nullptr;
|
mutable std_::unique_ptr<AnimationData> _animation;
|
||||||
mutable FloatAnimation _a_deleteOver;
|
mutable FloatAnimation _a_deleteOver;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -339,6 +339,40 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Game : public ItemBase {
|
||||||
|
public:
|
||||||
|
Game(Result *result);
|
||||||
|
|
||||||
|
void setPosition(int32 position) override;
|
||||||
|
void initDimensions() override;
|
||||||
|
|
||||||
|
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||||
|
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||||
|
|
||||||
|
~Game();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void countFrameSize();
|
||||||
|
|
||||||
|
bool gif() const {
|
||||||
|
return (!_gif || _gif == Media::Clip::BadReader) ? false : true;
|
||||||
|
}
|
||||||
|
void prepareThumb(int32 width, int32 height) const;
|
||||||
|
|
||||||
|
bool isRadialAnimation(uint64 ms) const;
|
||||||
|
void step_radial(uint64 ms, bool timer);
|
||||||
|
|
||||||
|
void clipCallback(Media::Clip::Notification notification);
|
||||||
|
|
||||||
|
Media::Clip::Reader *_gif = nullptr;
|
||||||
|
mutable QPixmap _thumb;
|
||||||
|
mutable std_::unique_ptr<Ui::RadialAnimation> _radial;
|
||||||
|
Text _title, _description;
|
||||||
|
|
||||||
|
QSize _frameSize;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace Layout
|
} // namespace Layout
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -113,6 +113,7 @@ std_::unique_ptr<ItemBase> ItemBase::createLayout(Result *result, bool forceThum
|
||||||
case Type::Article:
|
case Type::Article:
|
||||||
case Type::Geo:
|
case Type::Geo:
|
||||||
case Type::Venue: return std_::make_unique<internal::Article>(result, forceThumb); break;
|
case Type::Venue: return std_::make_unique<internal::Article>(result, forceThumb); break;
|
||||||
|
case Type::Game: return std_::make_unique<internal::Game>(result); break;
|
||||||
case Type::Contact: return std_::make_unique<internal::Contact>(result); break;
|
case Type::Contact: return std_::make_unique<internal::Contact>(result); break;
|
||||||
}
|
}
|
||||||
return std_::unique_ptr<ItemBase>();
|
return std_::unique_ptr<ItemBase>();
|
||||||
|
|
|
@ -47,6 +47,7 @@ std_::unique_ptr<Result> Result::create(uint64 queryId, const MTPBotInlineResult
|
||||||
result->insert(qsl("contact"), Result::Type::Contact);
|
result->insert(qsl("contact"), Result::Type::Contact);
|
||||||
result->insert(qsl("venue"), Result::Type::Venue);
|
result->insert(qsl("venue"), Result::Type::Venue);
|
||||||
result->insert(qsl("geo"), Result::Type::Geo);
|
result->insert(qsl("geo"), Result::Type::Geo);
|
||||||
|
result->insert(qsl("game"), Result::Type::Game);
|
||||||
return result.release();
|
return result.release();
|
||||||
})() };
|
})() };
|
||||||
|
|
||||||
|
@ -122,6 +123,9 @@ std_::unique_ptr<Result> Result::create(uint64 queryId, const MTPBotInlineResult
|
||||||
if (result->_type == Type::Photo) {
|
if (result->_type == Type::Photo) {
|
||||||
result->createPhoto();
|
result->createPhoto();
|
||||||
result->sendData.reset(new internal::SendPhoto(result->_photo, qs(r.vcaption)));
|
result->sendData.reset(new internal::SendPhoto(result->_photo, qs(r.vcaption)));
|
||||||
|
} else if (result->_type == Type::Game) {
|
||||||
|
result->createGame();
|
||||||
|
result->sendData.reset(new internal::SendGame(result->_game));
|
||||||
} else {
|
} else {
|
||||||
result->createDocument();
|
result->createDocument();
|
||||||
result->sendData.reset(new internal::SendFile(result->_document, qs(r.vcaption)));
|
result->sendData.reset(new internal::SendFile(result->_document, qs(r.vcaption)));
|
||||||
|
@ -313,7 +317,7 @@ void Result::createPhoto() {
|
||||||
ImagePtr medium = ImagePtr(mediumsize.width(), mediumsize.height());
|
ImagePtr medium = ImagePtr(mediumsize.width(), mediumsize.height());
|
||||||
|
|
||||||
ImagePtr full = ImagePtr(_content_url, _width, _height);
|
ImagePtr full = ImagePtr(_content_url, _width, _height);
|
||||||
uint64 photoId = rand_value<uint64>();
|
auto photoId = rand_value<PhotoId>();
|
||||||
_photo = App::photoSet(photoId, 0, 0, unixtime(), _thumb, medium, full);
|
_photo = App::photoSet(photoId, 0, 0, unixtime(), _thumb, medium, full);
|
||||||
_photo->thumb = _thumb;
|
_photo->thumb = _thumb;
|
||||||
}
|
}
|
||||||
|
@ -321,8 +325,6 @@ void Result::createPhoto() {
|
||||||
void Result::createDocument() {
|
void Result::createDocument() {
|
||||||
if (_document) return;
|
if (_document) return;
|
||||||
|
|
||||||
uint64 docId = rand_value<uint64>();
|
|
||||||
|
|
||||||
if (!_thumb_url.isEmpty()) {
|
if (!_thumb_url.isEmpty()) {
|
||||||
_thumb = ImagePtr(_thumb_url, QSize(90, 90));
|
_thumb = ImagePtr(_thumb_url, QSize(90, 90));
|
||||||
}
|
}
|
||||||
|
@ -352,16 +354,16 @@ void Result::createDocument() {
|
||||||
attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes()));
|
attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(0), MTP_photoSizeEmpty(MTP_string("")), MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
|
auto documentId = rand_value<DocumentId>();
|
||||||
|
_document = App::documentSet(documentId, nullptr, 0, 0, unixtime(), attributes, mime, _thumb, MTP::maindc(), 0, StorageImageLocation());
|
||||||
_document = App::feedDocument(document);
|
|
||||||
_document->setContentUrl(_content_url);
|
_document->setContentUrl(_content_url);
|
||||||
if (!_thumb->isNull()) {
|
|
||||||
_document->thumb = _thumb;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result::~Result() {
|
void Result::createGame() {
|
||||||
|
if (_game) return;
|
||||||
|
|
||||||
|
auto gameId = rand_value<GameId>();
|
||||||
|
_game = App::gameSet(gameId, nullptr, 0, QString(), _title, _description, _photo, _document);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -74,11 +74,10 @@ public:
|
||||||
QString getLayoutTitle() const;
|
QString getLayoutTitle() const;
|
||||||
QString getLayoutDescription() const;
|
QString getLayoutDescription() const;
|
||||||
|
|
||||||
~Result();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createPhoto();
|
void createPhoto();
|
||||||
void createDocument();
|
void createDocument();
|
||||||
|
void createGame();
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
@ -92,6 +91,7 @@ private:
|
||||||
Contact,
|
Contact,
|
||||||
Geo,
|
Geo,
|
||||||
Venue,
|
Venue,
|
||||||
|
Game,
|
||||||
};
|
};
|
||||||
|
|
||||||
friend class internal::SendData;
|
friend class internal::SendData;
|
||||||
|
@ -112,6 +112,7 @@ private:
|
||||||
|
|
||||||
DocumentData *_document = nullptr;
|
DocumentData *_document = nullptr;
|
||||||
PhotoData *_photo = nullptr;
|
PhotoData *_photo = nullptr;
|
||||||
|
GameData *_game = nullptr;
|
||||||
|
|
||||||
std_::unique_ptr<MTPReplyMarkup> _mtpKeyboard;
|
std_::unique_ptr<MTPReplyMarkup> _mtpKeyboard;
|
||||||
|
|
||||||
|
|
|
@ -90,5 +90,11 @@ UserId viaBotId, MsgId replyToId, const MTPReplyMarkup &markup) const {
|
||||||
history->addNewDocument(msgId, flags, viaBotId, replyToId, date(mtpDate), fromId, _document, _caption, markup);
|
history->addNewDocument(msgId, flags, viaBotId, replyToId, date(mtpDate), fromId, _document, _caption, markup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendGame::addToHistory(const Result *owner, History *history,
|
||||||
|
MTPDmessage::Flags flags, MsgId msgId, UserId fromId, MTPint mtpDate,
|
||||||
|
UserId viaBotId, MsgId replyToId, const MTPReplyMarkup &markup) const {
|
||||||
|
history->addNewGame(msgId, flags, viaBotId, replyToId, date(mtpDate), fromId, _game, markup);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -221,5 +221,25 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Message with game.
|
||||||
|
class SendGame : public SendData {
|
||||||
|
public:
|
||||||
|
SendGame(GameData *game)
|
||||||
|
: _game(game) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid() const override {
|
||||||
|
return _game != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToHistory(const Result *owner, History *history,
|
||||||
|
MTPDmessage::Flags flags, MsgId msgId, UserId fromId, MTPint mtpDate,
|
||||||
|
UserId viaBotId, MsgId replyToId, const MTPReplyMarkup &markup) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GameData *_game;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -3349,7 +3349,7 @@ void MainWidget::openLocalUrl(const QString &url) {
|
||||||
} else if (auto usernameMatch = regex_match(qsl("^resolve/?\\?(.+)(#|$)"), command, matchOptions)) {
|
} else if (auto usernameMatch = regex_match(qsl("^resolve/?\\?(.+)(#|$)"), command, matchOptions)) {
|
||||||
auto params = url_parse_params(usernameMatch->captured(1), UrlParamNameTransform::ToLower);
|
auto params = url_parse_params(usernameMatch->captured(1), UrlParamNameTransform::ToLower);
|
||||||
auto domain = params.value(qsl("domain"));
|
auto domain = params.value(qsl("domain"));
|
||||||
if (auto domainMatch = regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), domain, matchOptions)) {
|
if (regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), domain, matchOptions)) {
|
||||||
auto start = qsl("start");
|
auto start = qsl("start");
|
||||||
auto startToken = params.value(start);
|
auto startToken = params.value(start);
|
||||||
if (startToken.isEmpty()) {
|
if (startToken.isEmpty()) {
|
||||||
|
@ -3364,6 +3364,11 @@ void MainWidget::openLocalUrl(const QString &url) {
|
||||||
if (auto postId = postParam.toInt()) {
|
if (auto postId = postParam.toInt()) {
|
||||||
post = postId;
|
post = postId;
|
||||||
}
|
}
|
||||||
|
auto gameParam = params.value(qsl("game"));
|
||||||
|
if (!gameParam.isEmpty() && regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), gameParam, matchOptions)) {
|
||||||
|
startToken = gameParam;
|
||||||
|
post = ShowAtGameShareMsgId;
|
||||||
|
}
|
||||||
openPeerByName(domain, post, startToken);
|
openPeerByName(domain, post, startToken);
|
||||||
}
|
}
|
||||||
} else if (auto shareGameScoreMatch = regex_match(qsl("^share_game_score/?\\?(.+)(#|$)"), command, matchOptions)) {
|
} else if (auto shareGameScoreMatch = regex_match(qsl("^share_game_score/?\\?(.+)(#|$)"), command, matchOptions)) {
|
||||||
|
@ -3377,7 +3382,14 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr
|
||||||
|
|
||||||
PeerData *peer = App::peerByName(username);
|
PeerData *peer = App::peerByName(username);
|
||||||
if (peer) {
|
if (peer) {
|
||||||
if (msgId == ShowAtProfileMsgId && !peer->isChannel()) {
|
if (msgId == ShowAtGameShareMsgId) {
|
||||||
|
if (peer->isUser() && peer->asUser()->botInfo && !startToken.isEmpty()) {
|
||||||
|
peer->asUser()->botInfo->shareGameShortName = startToken;
|
||||||
|
Ui::showLayer(new ContactsBox(peer->asUser()));
|
||||||
|
} else {
|
||||||
|
Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward);
|
||||||
|
}
|
||||||
|
} else if (msgId == ShowAtProfileMsgId && !peer->isChannel()) {
|
||||||
if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) {
|
if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) {
|
||||||
peer->asUser()->botInfo->startGroupToken = startToken;
|
peer->asUser()->botInfo->startGroupToken = startToken;
|
||||||
Ui::showLayer(new ContactsBox(peer->asUser()));
|
Ui::showLayer(new ContactsBox(peer->asUser()));
|
||||||
|
|
|
@ -163,6 +163,7 @@ constexpr const MsgId ShowAtTheEndMsgId = -0x40000000;
|
||||||
constexpr const MsgId SwitchAtTopMsgId = -0x3FFFFFFF;
|
constexpr const MsgId SwitchAtTopMsgId = -0x3FFFFFFF;
|
||||||
constexpr const MsgId ShowAtProfileMsgId = -0x3FFFFFFE;
|
constexpr const MsgId ShowAtProfileMsgId = -0x3FFFFFFE;
|
||||||
constexpr const MsgId ShowAndStartBotMsgId = -0x3FFFFFD;
|
constexpr const MsgId ShowAndStartBotMsgId = -0x3FFFFFD;
|
||||||
|
constexpr const MsgId ShowAtGameShareMsgId = -0x3FFFFFC;
|
||||||
constexpr const MsgId ServerMaxMsgId = 0x3FFFFFFF;
|
constexpr const MsgId ServerMaxMsgId = 0x3FFFFFFF;
|
||||||
constexpr const MsgId ShowAtUnreadMsgId = 0;
|
constexpr const MsgId ShowAtUnreadMsgId = 0;
|
||||||
|
|
||||||
|
@ -385,7 +386,7 @@ struct BotInfo {
|
||||||
QList<BotCommand> commands;
|
QList<BotCommand> commands;
|
||||||
Text text = Text{ int(st::msgMinWidth) }; // description
|
Text text = Text{ int(st::msgMinWidth) }; // description
|
||||||
|
|
||||||
QString startToken, startGroupToken;
|
QString startToken, startGroupToken, shareGameShortName;
|
||||||
PeerId inlineReturnPeerId = 0;
|
PeerId inlineReturnPeerId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1141,7 +1142,7 @@ public:
|
||||||
return (type == AnimatedDocument) && !mime.compare(qstr("video/mp4"), Qt::CaseInsensitive);
|
return (type == AnimatedDocument) && !mime.compare(qstr("video/mp4"), Qt::CaseInsensitive);
|
||||||
}
|
}
|
||||||
bool isMusic() const {
|
bool isMusic() const {
|
||||||
return (type == SongDocument) ? !static_cast<SongData*>(_additional.get())->title.isEmpty() : false;
|
return (type == SongDocument) ? (static_cast<SongData*>(_additional.get())->duration != 0) : false;
|
||||||
}
|
}
|
||||||
bool isVideo() const {
|
bool isVideo() const {
|
||||||
return (type == VideoDocument);
|
return (type == VideoDocument);
|
||||||
|
|
Loading…
Reference in New Issue