mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Prepared messages sharing from miniapp.
This commit is contained in:
parent
3d77bff0c9
commit
2d1fb0562d
20 changed files with 465 additions and 63 deletions
|
@ -1040,6 +1040,8 @@ PRIVATE
|
||||||
info/info_wrap_widget.h
|
info/info_wrap_widget.h
|
||||||
inline_bots/bot_attach_web_view.cpp
|
inline_bots/bot_attach_web_view.cpp
|
||||||
inline_bots/bot_attach_web_view.h
|
inline_bots/bot_attach_web_view.h
|
||||||
|
inline_bots/inline_bot_confirm_prepared.cpp
|
||||||
|
inline_bots/inline_bot_confirm_prepared.h
|
||||||
inline_bots/inline_bot_layout_internal.cpp
|
inline_bots/inline_bot_layout_internal.cpp
|
||||||
inline_bots/inline_bot_layout_internal.h
|
inline_bots/inline_bot_layout_internal.h
|
||||||
inline_bots/inline_bot_layout_item.cpp
|
inline_bots/inline_bot_layout_item.cpp
|
||||||
|
|
|
@ -3425,6 +3425,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_bot_emoji_status_text" = "Do you want to set this emoji status suggested by {bot}?";
|
"lng_bot_emoji_status_text" = "Do you want to set this emoji status suggested by {bot}?";
|
||||||
"lng_bot_emoji_status_access_text" = "{bot} requests access to set your **emoji status**. You will be able to revoke this access in the profile page of {name}.";
|
"lng_bot_emoji_status_access_text" = "{bot} requests access to set your **emoji status**. You will be able to revoke this access in the profile page of {name}.";
|
||||||
"lng_bot_emoji_status_access_allow" = "Allow";
|
"lng_bot_emoji_status_access_allow" = "Allow";
|
||||||
|
"lng_bot_share_prepared_title" = "Share Message";
|
||||||
|
"lng_bot_share_prepared_about" = "{bot} mini app suggests you to send this message to a chat you select.";
|
||||||
|
"lng_bot_share_prepared_button" = "Share With...";
|
||||||
|
|
||||||
"lng_bot_status_users#one" = "{count} monthly user";
|
"lng_bot_status_users#one" = "{count} monthly user";
|
||||||
"lng_bot_status_users#other" = "{count} monthly users";
|
"lng_bot_status_users#other" = "{count} monthly users";
|
||||||
|
|
|
@ -3947,7 +3947,8 @@ void ApiWrap::sendInlineResult(
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
not_null<InlineBots::Result*> data,
|
not_null<InlineBots::Result*> data,
|
||||||
const SendAction &action,
|
const SendAction &action,
|
||||||
std::optional<MsgId> localMessageId) {
|
std::optional<MsgId> localMessageId,
|
||||||
|
Fn<void(bool)> done) {
|
||||||
sendAction(action);
|
sendAction(action);
|
||||||
|
|
||||||
const auto history = action.history;
|
const auto history = action.history;
|
||||||
|
@ -4027,11 +4028,13 @@ void ApiWrap::sendInlineResult(
|
||||||
history->finishSavingCloudDraft(
|
history->finishSavingCloudDraft(
|
||||||
topicRootId,
|
topicRootId,
|
||||||
UnixtimeFromMsgId(response.outerMsgId));
|
UnixtimeFromMsgId(response.outerMsgId));
|
||||||
|
done(true);
|
||||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||||
sendMessageFail(error, peer, randomId, newId);
|
sendMessageFail(error, peer, randomId, newId);
|
||||||
history->finishSavingCloudDraft(
|
history->finishSavingCloudDraft(
|
||||||
topicRootId,
|
topicRootId,
|
||||||
UnixtimeFromMsgId(response.outerMsgId));
|
UnixtimeFromMsgId(response.outerMsgId));
|
||||||
|
done(false);
|
||||||
});
|
});
|
||||||
finishForwarding(action);
|
finishForwarding(action);
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,7 +361,8 @@ public:
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
not_null<InlineBots::Result*> data,
|
not_null<InlineBots::Result*> data,
|
||||||
const SendAction &action,
|
const SendAction &action,
|
||||||
std::optional<MsgId> localMessageId);
|
std::optional<MsgId> localMessageId,
|
||||||
|
Fn<void(bool)> done = nullptr);
|
||||||
void sendMessageFail(
|
void sendMessageFail(
|
||||||
const MTP::Error &error,
|
const MTP::Error &error,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
|
|
@ -712,6 +712,14 @@ not_null<HistoryItem*> History::addNewLocalMessage(
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
not_null<HistoryItem*> History::addNewLocalMessage(
|
||||||
|
not_null<HistoryItem*> item) {
|
||||||
|
Expects(item->history() == this);
|
||||||
|
Expects(item->isLocal());
|
||||||
|
|
||||||
|
return addNewItem(item, true);
|
||||||
|
}
|
||||||
|
|
||||||
not_null<HistoryItem*> History::addSponsoredMessage(
|
not_null<HistoryItem*> History::addSponsoredMessage(
|
||||||
MsgId id,
|
MsgId id,
|
||||||
Data::SponsoredFrom from,
|
Data::SponsoredFrom from,
|
||||||
|
|
|
@ -180,6 +180,7 @@ public:
|
||||||
not_null<HistoryItem*> addNewLocalMessage(
|
not_null<HistoryItem*> addNewLocalMessage(
|
||||||
HistoryItemCommonFields &&fields,
|
HistoryItemCommonFields &&fields,
|
||||||
not_null<GameData*> game);
|
not_null<GameData*> game);
|
||||||
|
not_null<HistoryItem*> addNewLocalMessage(not_null<HistoryItem*> item);
|
||||||
|
|
||||||
not_null<HistoryItem*> addSponsoredMessage(
|
not_null<HistoryItem*> addSponsoredMessage(
|
||||||
MsgId id,
|
MsgId id,
|
||||||
|
|
|
@ -14,28 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
[[nodiscard]] InlineBots::PeerTypes PeerTypesFromMTP(
|
|
||||||
const MTPvector<MTPInlineQueryPeerType> &types) {
|
|
||||||
using namespace InlineBots;
|
|
||||||
auto result = PeerTypes(0);
|
|
||||||
for (const auto &type : types.v) {
|
|
||||||
result |= type.match([&](const MTPDinlineQueryPeerTypePM &data) {
|
|
||||||
return PeerType::User;
|
|
||||||
}, [&](const MTPDinlineQueryPeerTypeChat &data) {
|
|
||||||
return PeerType::Group;
|
|
||||||
}, [&](const MTPDinlineQueryPeerTypeMegagroup &data) {
|
|
||||||
return PeerType::Group;
|
|
||||||
}, [&](const MTPDinlineQueryPeerTypeBroadcast &data) {
|
|
||||||
return PeerType::Broadcast;
|
|
||||||
}, [&](const MTPDinlineQueryPeerTypeBotPM &data) {
|
|
||||||
return PeerType::Bot;
|
|
||||||
}, [&](const MTPDinlineQueryPeerTypeSameBotPM &data) {
|
|
||||||
return PeerType();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] RequestPeerQuery RequestPeerQueryFromTL(
|
[[nodiscard]] RequestPeerQuery RequestPeerQueryFromTL(
|
||||||
const MTPDkeyboardButtonRequestPeer &query) {
|
const MTPDkeyboardButtonRequestPeer &query) {
|
||||||
using Type = RequestPeerQuery::Type;
|
using Type = RequestPeerQuery::Type;
|
||||||
|
@ -76,6 +54,28 @@ namespace {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
InlineBots::PeerTypes PeerTypesFromMTP(
|
||||||
|
const MTPvector<MTPInlineQueryPeerType> &types) {
|
||||||
|
using namespace InlineBots;
|
||||||
|
auto result = PeerTypes(0);
|
||||||
|
for (const auto &type : types.v) {
|
||||||
|
result |= type.match([&](const MTPDinlineQueryPeerTypePM &data) {
|
||||||
|
return PeerType::User;
|
||||||
|
}, [&](const MTPDinlineQueryPeerTypeChat &data) {
|
||||||
|
return PeerType::Group;
|
||||||
|
}, [&](const MTPDinlineQueryPeerTypeMegagroup &data) {
|
||||||
|
return PeerType::Group;
|
||||||
|
}, [&](const MTPDinlineQueryPeerTypeBroadcast &data) {
|
||||||
|
return PeerType::Broadcast;
|
||||||
|
}, [&](const MTPDinlineQueryPeerTypeBotPM &data) {
|
||||||
|
return PeerType::Bot;
|
||||||
|
}, [&](const MTPDinlineQueryPeerTypeSameBotPM &data) {
|
||||||
|
return PeerType();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
HistoryMessageMarkupButton::HistoryMessageMarkupButton(
|
HistoryMessageMarkupButton::HistoryMessageMarkupButton(
|
||||||
Type type,
|
Type type,
|
||||||
const QString &text,
|
const QString &text,
|
||||||
|
|
|
@ -19,6 +19,9 @@ enum class PeerType : uint8;
|
||||||
using PeerTypes = base::flags<PeerType>;
|
using PeerTypes = base::flags<PeerType>;
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
||||||
|
[[nodiscard]] InlineBots::PeerTypes PeerTypesFromMTP(
|
||||||
|
const MTPvector<MTPInlineQueryPeerType> &types);
|
||||||
|
|
||||||
enum class ReplyMarkupFlag : uint32 {
|
enum class ReplyMarkupFlag : uint32 {
|
||||||
None = (1U << 0),
|
None = (1U << 0),
|
||||||
ForceReply = (1U << 1),
|
ForceReply = (1U << 1),
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/qthelp_url.h"
|
#include "base/qthelp_url.h"
|
||||||
#include "base/random.h"
|
#include "base/random.h"
|
||||||
#include "base/timer_rpl.h"
|
#include "base/timer_rpl.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "boxes/share_box.h"
|
#include "boxes/share_box.h"
|
||||||
#include "chat_helpers/stickers_lottie.h"
|
#include "chat_helpers/stickers_lottie.h"
|
||||||
|
@ -38,6 +39,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "info/profile/info_profile_values.h"
|
#include "info/profile/info_profile_values.h"
|
||||||
|
#include "inline_bots/inline_bot_result.h"
|
||||||
|
#include "inline_bots/inline_bot_confirm_prepared.h"
|
||||||
#include "iv/iv_instance.h"
|
#include "iv/iv_instance.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_app_config.h"
|
#include "main/main_app_config.h"
|
||||||
|
@ -1730,6 +1733,88 @@ void WebViewInstance::botInvokeCustomMethod(
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebViewInstance::botSendPreparedMessage(
|
||||||
|
Ui::BotWebView::SendPreparedMessageRequest request) {
|
||||||
|
const auto bot = _bot;
|
||||||
|
const auto id = request.id;
|
||||||
|
const auto panel = _panel.get();
|
||||||
|
const auto weak = base::make_weak(panel);
|
||||||
|
const auto callback = request.callback;
|
||||||
|
if (!panel) {
|
||||||
|
callback(u"UNKNOWN_ERROR"_q);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_session->api().request(MTPmessages_GetPreparedInlineMessage(
|
||||||
|
bot->inputUser,
|
||||||
|
MTP_string(request.id)
|
||||||
|
)).done([=](const MTPmessages_PreparedInlineMessage &result) {
|
||||||
|
const auto panel = weak.get();
|
||||||
|
const auto &data = result.data();
|
||||||
|
bot->owner().processUsers(data.vusers());
|
||||||
|
const auto parsed = std::shared_ptr<Result>(Result::Create(
|
||||||
|
&bot->session(),
|
||||||
|
data.vquery_id().v,
|
||||||
|
data.vresult()));
|
||||||
|
if (!parsed || !panel) {
|
||||||
|
callback(u"UNKNOWN_ERROR"_q);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto types = PeerTypesFromMTP(data.vpeer_types());
|
||||||
|
const auto history = bot->owner().history(bot->session().user());
|
||||||
|
const auto item = parsed->makeMessage(history, {
|
||||||
|
.id = bot->owner().nextNonHistoryEntryId(),
|
||||||
|
.flags = MessageFlag::FakeHistoryItem,
|
||||||
|
.from = bot->session().userPeerId(),
|
||||||
|
.date = base::unixtime::now(),
|
||||||
|
.viaBotId = peerToUser(bot->id),
|
||||||
|
});
|
||||||
|
struct State {
|
||||||
|
QPointer<Ui::BoxContent> preview;
|
||||||
|
bool sent = false;
|
||||||
|
};
|
||||||
|
const auto state = std::make_shared<State>();
|
||||||
|
auto box = Box(PreparedPreviewBox, item, [=] {
|
||||||
|
const auto chosen = [=](not_null<Data::Thread*> thread) {
|
||||||
|
auto action = Api::SendAction(thread);
|
||||||
|
const auto done = [=](bool success) {
|
||||||
|
if (success) {
|
||||||
|
callback(QString());
|
||||||
|
} else {
|
||||||
|
callback(u"MESSAGE_SEND_FAILED"_q);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bot->session().api().sendInlineResult(
|
||||||
|
bot,
|
||||||
|
parsed.get(),
|
||||||
|
action,
|
||||||
|
std::nullopt,
|
||||||
|
done);
|
||||||
|
state->sent = true;
|
||||||
|
if (const auto strong = state->preview.data()) {
|
||||||
|
strong->closeBox();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
auto box = Window::PrepareChooseRecipientBox(
|
||||||
|
&bot->session(),
|
||||||
|
chosen,
|
||||||
|
tr::lng_inline_switch_choose(),
|
||||||
|
nullptr,
|
||||||
|
types);
|
||||||
|
panel->showBox(std::move(box));
|
||||||
|
});
|
||||||
|
box->boxClosing() | rpl::start_with_next([=] {
|
||||||
|
if (!state->sent) {
|
||||||
|
callback("USER_DECLINED");
|
||||||
|
}
|
||||||
|
}, box->lifetime());
|
||||||
|
state->preview = box.data();
|
||||||
|
panel->showBox(std::move(box));
|
||||||
|
}).fail([=] {
|
||||||
|
callback(u"MESSAGE_EXPIRED"_q);
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
void WebViewInstance::botSetEmojiStatus(
|
void WebViewInstance::botSetEmojiStatus(
|
||||||
Ui::BotWebView::SetEmojiStatusRequest request) {
|
Ui::BotWebView::SetEmojiStatusRequest request) {
|
||||||
const auto bot = _bot;
|
const auto bot = _bot;
|
||||||
|
|
|
@ -265,6 +265,8 @@ private:
|
||||||
void botSharePhone(Fn<void(bool shared)> callback) override;
|
void botSharePhone(Fn<void(bool shared)> callback) override;
|
||||||
void botInvokeCustomMethod(
|
void botInvokeCustomMethod(
|
||||||
Ui::BotWebView::CustomMethodRequest request) override;
|
Ui::BotWebView::CustomMethodRequest request) override;
|
||||||
|
void botSendPreparedMessage(
|
||||||
|
Ui::BotWebView::SendPreparedMessageRequest request) override;
|
||||||
void botSetEmojiStatus(
|
void botSetEmojiStatus(
|
||||||
Ui::BotWebView::SetEmojiStatusRequest request) override;
|
Ui::BotWebView::SetEmojiStatusRequest request) override;
|
||||||
void botOpenPrivacyPolicy() override;
|
void botOpenPrivacyPolicy() override;
|
||||||
|
|
196
Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.cpp
Normal file
196
Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.cpp
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "inline_bots/inline_bot_confirm_prepared.h"
|
||||||
|
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "history/admin_log/history_admin_log_item.h"
|
||||||
|
#include "history/view/history_view_element.h"
|
||||||
|
#include "history/history.h"
|
||||||
|
#include "history/history_item.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "ui/chat/chat_style.h"
|
||||||
|
#include "ui/chat/chat_theme.h"
|
||||||
|
#include "ui/effects/path_shift_gradient.h"
|
||||||
|
#include "ui/layers/generic_box.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
|
#include "ui/vertical_list.h"
|
||||||
|
#include "window/themes/window_theme.h"
|
||||||
|
#include "window/section_widget.h"
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
|
namespace InlineBots {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace HistoryView;
|
||||||
|
|
||||||
|
class PreviewDelegate final : public DefaultElementDelegate {
|
||||||
|
public:
|
||||||
|
PreviewDelegate(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
not_null<Ui::ChatStyle*> st,
|
||||||
|
Fn<void()> update);
|
||||||
|
|
||||||
|
bool elementAnimationsPaused() override;
|
||||||
|
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
|
||||||
|
Context elementContext() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const not_null<QWidget*> _parent;
|
||||||
|
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class PreviewWrap final : public Ui::RpWidget {
|
||||||
|
public:
|
||||||
|
PreviewWrap(not_null<QWidget*> parent, not_null<HistoryItem*> item);
|
||||||
|
~PreviewWrap();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
void resizeTo(int width);
|
||||||
|
void prepare(not_null<HistoryItem*> item);
|
||||||
|
|
||||||
|
const not_null<History*> _history;
|
||||||
|
const std::unique_ptr<Ui::ChatTheme> _theme;
|
||||||
|
const std::unique_ptr<Ui::ChatStyle> _style;
|
||||||
|
const std::unique_ptr<PreviewDelegate> _delegate;
|
||||||
|
AdminLog::OwnedItem _item;
|
||||||
|
QPoint _position;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
PreviewDelegate::PreviewDelegate(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
not_null<Ui::ChatStyle*> st,
|
||||||
|
Fn<void()> update)
|
||||||
|
: _parent(parent)
|
||||||
|
, _pathGradient(MakePathShiftGradient(st, update)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PreviewDelegate::elementAnimationsPaused() {
|
||||||
|
return _parent->window()->isActiveWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PreviewDelegate::elementPathShiftGradient()
|
||||||
|
-> not_null<Ui::PathShiftGradient*> {
|
||||||
|
return _pathGradient.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Context PreviewDelegate::elementContext() {
|
||||||
|
return Context::History;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewWrap::PreviewWrap(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
not_null<HistoryItem*> item)
|
||||||
|
: RpWidget(parent)
|
||||||
|
, _history(item->history())
|
||||||
|
, _theme(Window::Theme::DefaultChatThemeOn(lifetime()))
|
||||||
|
, _style(std::make_unique<Ui::ChatStyle>(
|
||||||
|
_history->session().colorIndicesValue()))
|
||||||
|
, _delegate(std::make_unique<PreviewDelegate>(
|
||||||
|
parent,
|
||||||
|
_style.get(),
|
||||||
|
[=] { update(); }))
|
||||||
|
, _position(0, st::msgMargin.bottom()) {
|
||||||
|
_style->apply(_theme.get());
|
||||||
|
|
||||||
|
using namespace HistoryView;
|
||||||
|
_history->owner().viewRepaintRequest(
|
||||||
|
) | rpl::start_with_next([=](not_null<const Element*> view) {
|
||||||
|
if (view == _item.get()) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_history->session().downloaderTaskFinished() | rpl::start_with_next([=] {
|
||||||
|
update();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
prepare(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewWrap::~PreviewWrap() {
|
||||||
|
_item = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewWrap::prepare(not_null<HistoryItem*> item) {
|
||||||
|
_item = AdminLog::OwnedItem(_delegate.get(), item);
|
||||||
|
if (width() >= st::msgMinWidth) {
|
||||||
|
resizeTo(width());
|
||||||
|
}
|
||||||
|
|
||||||
|
widthValue(
|
||||||
|
) | rpl::filter([=](int width) {
|
||||||
|
return width >= st::msgMinWidth;
|
||||||
|
}) | rpl::start_with_next([=](int width) {
|
||||||
|
resizeTo(width);
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewWrap::resizeTo(int width) {
|
||||||
|
const auto height = _position.y()
|
||||||
|
+ _item->resizeGetHeight(width)
|
||||||
|
+ _position.y()
|
||||||
|
+ st::msgServiceMargin.top()
|
||||||
|
+ st::msgServiceGiftBoxTopSkip
|
||||||
|
- st::msgServiceMargin.bottom();
|
||||||
|
resize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewWrap::paintEvent(QPaintEvent *e) {
|
||||||
|
auto p = Painter(this);
|
||||||
|
|
||||||
|
const auto clip = e->rect();
|
||||||
|
if (!clip.isEmpty()) {
|
||||||
|
p.setClipRect(clip);
|
||||||
|
Window::SectionWidget::PaintBackground(
|
||||||
|
p,
|
||||||
|
_theme.get(),
|
||||||
|
QSize(width(), window()->height()),
|
||||||
|
clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto context = _theme->preparePaintContext(
|
||||||
|
_style.get(),
|
||||||
|
rect(),
|
||||||
|
e->rect(),
|
||||||
|
!window()->isActiveWindow());
|
||||||
|
p.translate(_position);
|
||||||
|
_item->draw(p, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namesace
|
||||||
|
|
||||||
|
void PreparedPreviewBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
Fn<void()> share) {
|
||||||
|
box->setTitle(tr::lng_bot_share_prepared_title());
|
||||||
|
const auto container = box->verticalLayout();
|
||||||
|
container->add(object_ptr<PreviewWrap>(container, item));
|
||||||
|
const auto bot = item->viaBot();
|
||||||
|
const auto name = bot ? bot->name() : u"Bot"_q;
|
||||||
|
Ui::AddDividerText(
|
||||||
|
container,
|
||||||
|
tr::lng_bot_share_prepared_about(lt_bot, rpl::single(name))),
|
||||||
|
box->addButton(tr::lng_bot_share_prepared_button(), share);
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
|
||||||
|
item->history()->owner().itemRemoved(
|
||||||
|
) | rpl::start_with_next([=](not_null<const HistoryItem*> removed) {
|
||||||
|
if (removed == item) {
|
||||||
|
box->closeBox();
|
||||||
|
}
|
||||||
|
}, box->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace InlineBots
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class GenericBox;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace InlineBots {
|
||||||
|
|
||||||
|
void PreparedPreviewBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
Fn<void()> share);
|
||||||
|
|
||||||
|
} // namespace InlineBots
|
|
@ -378,14 +378,20 @@ bool Result::hasThumbDisplay() const {
|
||||||
void Result::addToHistory(
|
void Result::addToHistory(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const {
|
HistoryItemCommonFields &&fields) const {
|
||||||
fields.flags |= MessageFlag::FromInlineBot;
|
history->addNewLocalMessage(makeMessage(history, std::move(fields)));
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<HistoryItem*> Result::makeMessage(
|
||||||
|
not_null<History*> history,
|
||||||
|
HistoryItemCommonFields &&fields) const {
|
||||||
|
fields.flags |= MessageFlag::FromInlineBot | MessageFlag::Local;
|
||||||
if (_replyMarkup) {
|
if (_replyMarkup) {
|
||||||
fields.markup = *_replyMarkup;
|
fields.markup = *_replyMarkup;
|
||||||
if (!fields.markup.isNull()) {
|
if (!fields.markup.isNull()) {
|
||||||
fields.flags |= MessageFlag::HasReplyMarkup;
|
fields.flags |= MessageFlag::HasReplyMarkup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendData->addToHistory(this, history, std::move(fields));
|
return sendData->makeMessage(this, history, std::move(fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Result::getErrorOnSend(not_null<History*> history) const {
|
QString Result::getErrorOnSend(not_null<History*> history) const {
|
||||||
|
|
|
@ -66,6 +66,9 @@ public:
|
||||||
void addToHistory(
|
void addToHistory(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const;
|
HistoryItemCommonFields &&fields) const;
|
||||||
|
[[nodiscard]] not_null<HistoryItem*> makeMessage(
|
||||||
|
not_null<History*> history,
|
||||||
|
HistoryItemCommonFields &&fields) const;
|
||||||
QString getErrorOnSend(not_null<History*> history) const;
|
QString getErrorOnSend(not_null<History*> history) const;
|
||||||
|
|
||||||
// interface for Layout:: usage
|
// interface for Layout:: usage
|
||||||
|
|
|
@ -28,7 +28,7 @@ QString SendData::getLayoutDescription(const Result *owner) const {
|
||||||
return owner->_description;
|
return owner->_description;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendDataCommon::addToHistory(
|
not_null<HistoryItem*> SendDataCommon::makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const {
|
HistoryItemCommonFields &&fields) const {
|
||||||
|
@ -36,7 +36,7 @@ void SendDataCommon::addToHistory(
|
||||||
if (fields.replyTo) {
|
if (fields.replyTo) {
|
||||||
fields.flags |= MessageFlag::HasReplyInfo;
|
fields.flags |= MessageFlag::HasReplyInfo;
|
||||||
}
|
}
|
||||||
history->addNewLocalMessage(
|
return history->makeMessage(
|
||||||
std::move(fields),
|
std::move(fields),
|
||||||
std::move(distinct.text),
|
std::move(distinct.text),
|
||||||
std::move(distinct.media));
|
std::move(distinct.media));
|
||||||
|
@ -96,14 +96,14 @@ QString SendContact::getLayoutDescription(const Result *owner) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendPhoto::addToHistory(
|
not_null<HistoryItem*> SendPhoto::makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const {
|
HistoryItemCommonFields &&fields) const {
|
||||||
history->addNewLocalMessage(
|
return history->makeMessage(
|
||||||
std::move(fields),
|
std::move(fields),
|
||||||
_photo,
|
_photo,
|
||||||
{ _message, _entities });
|
TextWithEntities{ _message, _entities });
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SendPhoto::getErrorOnSend(
|
QString SendPhoto::getErrorOnSend(
|
||||||
|
@ -113,14 +113,14 @@ QString SendPhoto::getErrorOnSend(
|
||||||
return Data::RestrictionError(history->peer, type).value_or(QString());
|
return Data::RestrictionError(history->peer, type).value_or(QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFile::addToHistory(
|
not_null<HistoryItem*> SendFile::makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const {
|
HistoryItemCommonFields &&fields) const {
|
||||||
history->addNewLocalMessage(
|
return history->makeMessage(
|
||||||
std::move(fields),
|
std::move(fields),
|
||||||
_document,
|
_document,
|
||||||
{ _message, _entities });
|
TextWithEntities{ _message, _entities });
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SendFile::getErrorOnSend(
|
QString SendFile::getErrorOnSend(
|
||||||
|
@ -130,11 +130,11 @@ QString SendFile::getErrorOnSend(
|
||||||
return Data::RestrictionError(history->peer, type).value_or(QString());
|
return Data::RestrictionError(history->peer, type).value_or(QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendGame::addToHistory(
|
not_null<HistoryItem*> SendGame::makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const {
|
HistoryItemCommonFields &&fields) const {
|
||||||
history->addNewLocalMessage(std::move(fields), _game);
|
return history->addNewLocalMessage(std::move(fields), _game);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SendGame::getErrorOnSend(
|
QString SendGame::getErrorOnSend(
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
|
|
||||||
virtual bool isValid() const = 0;
|
virtual bool isValid() const = 0;
|
||||||
|
|
||||||
virtual void addToHistory(
|
virtual not_null<HistoryItem*> makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const = 0;
|
HistoryItemCommonFields &&fields) const = 0;
|
||||||
|
@ -75,7 +75,7 @@ public:
|
||||||
};
|
};
|
||||||
virtual SentMessageFields getSentMessageFields() const = 0;
|
virtual SentMessageFields getSentMessageFields() const = 0;
|
||||||
|
|
||||||
void addToHistory(
|
not_null<HistoryItem*> makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
@ -236,7 +236,7 @@ public:
|
||||||
return _photo != nullptr;
|
return _photo != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addToHistory(
|
not_null<HistoryItem*> makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
@ -270,7 +270,7 @@ public:
|
||||||
return _document != nullptr;
|
return _document != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addToHistory(
|
not_null<HistoryItem*> makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
@ -298,7 +298,7 @@ public:
|
||||||
return _game != nullptr;
|
return _game != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addToHistory(
|
not_null<HistoryItem*> makeMessage(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
|
|
@ -183,7 +183,8 @@ struct Panel::WebviewWithLifetime {
|
||||||
Webview::WindowConfig config = Webview::WindowConfig());
|
Webview::WindowConfig config = Webview::WindowConfig());
|
||||||
|
|
||||||
Webview::Window window;
|
Webview::Window window;
|
||||||
QPointer<RpWidget> lastHidingBox;
|
std::vector<QPointer<RpWidget>> boxes;
|
||||||
|
rpl::lifetime boxesLifetime;
|
||||||
rpl::lifetime lifetime;
|
rpl::lifetime lifetime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -824,6 +825,8 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
||||||
processHeaderColor(arguments);
|
processHeaderColor(arguments);
|
||||||
} else if (command == "web_app_set_bottom_bar_color") {
|
} else if (command == "web_app_set_bottom_bar_color") {
|
||||||
processBottomBarColor(arguments);
|
processBottomBarColor(arguments);
|
||||||
|
} else if (command == "web_app_send_prepared_message") {
|
||||||
|
processSendMessageRequest(arguments);
|
||||||
} else if (command == "web_app_set_emoji_status") {
|
} else if (command == "web_app_set_emoji_status") {
|
||||||
processEmojiStatusRequest(arguments);
|
processEmojiStatusRequest(arguments);
|
||||||
} else if (command == "web_app_request_emoji_status_access") {
|
} else if (command == "web_app_request_emoji_status_access") {
|
||||||
|
@ -967,6 +970,27 @@ void Panel::switchInlineQueryMessage(const QJsonObject &args) {
|
||||||
_delegate->botSwitchInlineQuery(types, query);
|
_delegate->botSwitchInlineQuery(types, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Panel::processSendMessageRequest(const QJsonObject &args) {
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
_delegate->botClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto id = args["id"].toString();
|
||||||
|
auto callback = crl::guard(this, [=](QString error) {
|
||||||
|
if (error.isEmpty()) {
|
||||||
|
postEvent("prepared_message_sent");
|
||||||
|
} else {
|
||||||
|
postEvent(
|
||||||
|
"prepared_message_failed",
|
||||||
|
u"{ error: \"%1\" }"_q.arg(error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_delegate->botSendPreparedMessage({
|
||||||
|
.id = id,
|
||||||
|
.callback = std::move(callback),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Panel::processEmojiStatusRequest(const QJsonObject &args) {
|
void Panel::processEmojiStatusRequest(const QJsonObject &args) {
|
||||||
if (args.isEmpty()) {
|
if (args.isEmpty()) {
|
||||||
_delegate->botClose();
|
_delegate->botClose();
|
||||||
|
@ -1502,9 +1526,11 @@ void Panel::layoutButtons() {
|
||||||
return button && !button->isHidden();
|
return button && !button->isHidden();
|
||||||
};
|
};
|
||||||
const auto any = shown(_mainButton) || shown(_secondaryButton);
|
const auto any = shown(_mainButton) || shown(_secondaryButton);
|
||||||
_webviewBottom->setVisible(!any && !_fullscreen.current());
|
_webviewBottom->setVisible(!any
|
||||||
|
&& !_fullscreen.current()
|
||||||
|
&& !_layerShown);
|
||||||
if (any) {
|
if (any) {
|
||||||
_bottomButtonsBg->show();
|
_bottomButtonsBg->setVisible(!_layerShown);
|
||||||
|
|
||||||
const auto one = shown(_mainButton)
|
const auto one = shown(_mainButton)
|
||||||
? _mainButton.get()
|
? _mainButton.get()
|
||||||
|
@ -1570,7 +1596,9 @@ void Panel::layoutButtons() {
|
||||||
} else if (_bottomButtonsBg) {
|
} else if (_bottomButtonsBg) {
|
||||||
_bottomButtonsBg->hide();
|
_bottomButtonsBg->hide();
|
||||||
}
|
}
|
||||||
_footerHeight = any
|
_footerHeight = _layerShown
|
||||||
|
? 0
|
||||||
|
: any
|
||||||
? _bottomButtonsBg->height()
|
? _bottomButtonsBg->height()
|
||||||
: _fullscreen.current()
|
: _fullscreen.current()
|
||||||
? 0
|
? 0
|
||||||
|
@ -1586,25 +1614,34 @@ void Panel::showBox(
|
||||||
LayerOptions options,
|
LayerOptions options,
|
||||||
anim::type animated) {
|
anim::type animated) {
|
||||||
if (const auto widget = _webview ? _webview->window.widget() : nullptr) {
|
if (const auto widget = _webview ? _webview->window.widget() : nullptr) {
|
||||||
|
_layerShown = true;
|
||||||
const auto hideNow = !widget->isHidden();
|
const auto hideNow = !widget->isHidden();
|
||||||
if (hideNow || _webview->lastHidingBox) {
|
const auto raw = box.data();
|
||||||
const auto raw = _webview->lastHidingBox = box.data();
|
_webview->boxes.push_back(raw);
|
||||||
box->boxClosing(
|
raw->boxClosing(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::filter([=] {
|
||||||
|
return _webview != nullptr;
|
||||||
|
}) | rpl::start_with_next([=] {
|
||||||
|
auto &list = _webview->boxes;
|
||||||
|
list.erase(ranges::remove_if(list, [&](QPointer<RpWidget> b) {
|
||||||
|
return !b || (b == raw);
|
||||||
|
}), end(list));
|
||||||
|
if (list.empty()) {
|
||||||
|
_webview->boxesLifetime.destroy();
|
||||||
|
_layerShown = false;
|
||||||
const auto widget = _webview
|
const auto widget = _webview
|
||||||
? _webview->window.widget()
|
? _webview->window.widget()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (widget
|
if (widget && widget->isHidden()) {
|
||||||
&& widget->isHidden()
|
|
||||||
&& _webview->lastHidingBox == raw) {
|
|
||||||
widget->show();
|
widget->show();
|
||||||
_webviewBottom->setVisible(!_fullscreen.current());
|
layoutButtons();
|
||||||
}
|
}
|
||||||
}, _webview->lifetime);
|
|
||||||
if (hideNow) {
|
|
||||||
widget->hide();
|
|
||||||
_webviewBottom->hide();
|
|
||||||
}
|
}
|
||||||
|
}, _webview->boxesLifetime);
|
||||||
|
|
||||||
|
if (hideNow) {
|
||||||
|
widget->hide();
|
||||||
|
layoutButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto raw = box.data();
|
const auto raw = box.data();
|
||||||
|
|
|
@ -57,6 +57,11 @@ struct SetEmojiStatusRequest {
|
||||||
Fn<void(QString)> callback;
|
Fn<void(QString)> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SendPreparedMessageRequest {
|
||||||
|
QString id = 0;
|
||||||
|
Fn<void(QString)> callback;
|
||||||
|
};
|
||||||
|
|
||||||
class Delegate {
|
class Delegate {
|
||||||
public:
|
public:
|
||||||
virtual Webview::ThemeParams botThemeParams() = 0;
|
virtual Webview::ThemeParams botThemeParams() = 0;
|
||||||
|
@ -76,6 +81,8 @@ public:
|
||||||
virtual void botSharePhone(Fn<void(bool shared)> callback) = 0;
|
virtual void botSharePhone(Fn<void(bool shared)> callback) = 0;
|
||||||
virtual void botInvokeCustomMethod(CustomMethodRequest request) = 0;
|
virtual void botInvokeCustomMethod(CustomMethodRequest request) = 0;
|
||||||
virtual void botSetEmojiStatus(SetEmojiStatusRequest request) = 0;
|
virtual void botSetEmojiStatus(SetEmojiStatusRequest request) = 0;
|
||||||
|
virtual void botSendPreparedMessage(
|
||||||
|
SendPreparedMessageRequest request) = 0;
|
||||||
virtual void botOpenPrivacyPolicy() = 0;
|
virtual void botOpenPrivacyPolicy() = 0;
|
||||||
virtual void botClose() = 0;
|
virtual void botClose() = 0;
|
||||||
};
|
};
|
||||||
|
@ -132,6 +139,7 @@ private:
|
||||||
void setTitle(rpl::producer<QString> title);
|
void setTitle(rpl::producer<QString> title);
|
||||||
void sendDataMessage(const QJsonObject &args);
|
void sendDataMessage(const QJsonObject &args);
|
||||||
void switchInlineQueryMessage(const QJsonObject &args);
|
void switchInlineQueryMessage(const QJsonObject &args);
|
||||||
|
void processSendMessageRequest(const QJsonObject &args);
|
||||||
void processEmojiStatusRequest(const QJsonObject &args);
|
void processEmojiStatusRequest(const QJsonObject &args);
|
||||||
void processEmojiStatusAccessRequest();
|
void processEmojiStatusAccessRequest();
|
||||||
void processButtonMessage(
|
void processButtonMessage(
|
||||||
|
@ -195,6 +203,7 @@ private:
|
||||||
rpl::lifetime _headerColorLifetime;
|
rpl::lifetime _headerColorLifetime;
|
||||||
rpl::lifetime _bottomBarColorLifetime;
|
rpl::lifetime _bottomBarColorLifetime;
|
||||||
rpl::variable<bool> _fullscreen = false;
|
rpl::variable<bool> _fullscreen = false;
|
||||||
|
bool _layerShown = false;
|
||||||
bool _webviewProgress = false;
|
bool _webviewProgress = false;
|
||||||
bool _themeUpdateScheduled = false;
|
bool _themeUpdateScheduled = false;
|
||||||
bool _hiddenForPayment = false;
|
bool _hiddenForPayment = false;
|
||||||
|
|
|
@ -1881,8 +1881,8 @@ void BlockSenderFromRepliesBox(
|
||||||
Window::ClearReply{ id });
|
Window::ClearReply{ id });
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer<Ui::BoxContent> ShowChooseRecipientBox(
|
object_ptr<Ui::BoxContent> PrepareChooseRecipientBox(
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Main::Session*> session,
|
||||||
FnMut<bool(not_null<Data::Thread*>)> &&chosen,
|
FnMut<bool(not_null<Data::Thread*>)> &&chosen,
|
||||||
rpl::producer<QString> titleOverride,
|
rpl::producer<QString> titleOverride,
|
||||||
FnMut<void()> &&successCallback,
|
FnMut<void()> &&successCallback,
|
||||||
|
@ -1927,15 +1927,30 @@ QPointer<Ui::BoxContent> ShowChooseRecipientBox(
|
||||||
box->setTitle(std::move(titleOverride));
|
box->setTitle(std::move(titleOverride));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*weak = navigation->parentController()->show(Box<PeerListBox>(
|
auto result = Box<PeerListBox>(
|
||||||
std::make_unique<ChooseRecipientBoxController>(ChooseRecipientArgs{
|
std::make_unique<ChooseRecipientBoxController>(ChooseRecipientArgs{
|
||||||
.session = &navigation->session(),
|
.session = session,
|
||||||
.callback = std::move(callback),
|
.callback = std::move(callback),
|
||||||
.filter = std::move(filter),
|
.filter = std::move(filter),
|
||||||
.premiumRequiredError = WritePremiumRequiredError,
|
.premiumRequiredError = WritePremiumRequiredError,
|
||||||
}),
|
}),
|
||||||
std::move(initBox)));
|
std::move(initBox));
|
||||||
return weak->data();
|
*weak = result.data();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointer<Ui::BoxContent> ShowChooseRecipientBox(
|
||||||
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
|
FnMut<bool(not_null<Data::Thread*>)> &&chosen,
|
||||||
|
rpl::producer<QString> titleOverride,
|
||||||
|
FnMut<void()> &&successCallback,
|
||||||
|
InlineBots::PeerTypes typesRestriction) {
|
||||||
|
return navigation->parentController()->show(PrepareChooseRecipientBox(
|
||||||
|
&navigation->session(),
|
||||||
|
std::move(chosen),
|
||||||
|
std::move(titleOverride),
|
||||||
|
std::move(successCallback),
|
||||||
|
typesRestriction));
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer<Ui::BoxContent> ShowForwardMessagesBox(
|
QPointer<Ui::BoxContent> ShowForwardMessagesBox(
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "api/api_common.h"
|
#include "api/api_common.h"
|
||||||
|
#include "base/object_ptr.h"
|
||||||
#include "menu/menu_send.h"
|
#include "menu/menu_send.h"
|
||||||
#include "data/data_poll.h"
|
#include "data/data_poll.h"
|
||||||
#include "ui/widgets/menu/menu_add_action_callback.h"
|
#include "ui/widgets/menu/menu_add_action_callback.h"
|
||||||
|
@ -138,6 +139,12 @@ Fn<void()> DeleteAndLeaveHandler(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
object_ptr<Ui::BoxContent> PrepareChooseRecipientBox(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
FnMut<bool(not_null<Data::Thread*>)> &&chosen,
|
||||||
|
rpl::producer<QString> titleOverride = nullptr,
|
||||||
|
FnMut<void()> &&successCallback = nullptr,
|
||||||
|
InlineBots::PeerTypes typesRestriction = 0);
|
||||||
QPointer<Ui::BoxContent> ShowChooseRecipientBox(
|
QPointer<Ui::BoxContent> ShowChooseRecipientBox(
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
FnMut<bool(not_null<Data::Thread*>)> &&chosen,
|
FnMut<bool(not_null<Data::Thread*>)> &&chosen,
|
||||||
|
|
Loading…
Add table
Reference in a new issue