mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-08-12 14:43:54 +00:00
Support choosing send_as in video streams.
This commit is contained in:
@@ -743,22 +743,6 @@ groupCallJoinAsList: PeerList(groupCallInviteMembersList) {
|
||||
statusPosition: point(73px, 28px);
|
||||
}
|
||||
}
|
||||
peerListJoinAsList: PeerList(peerListBox) {
|
||||
item: PeerListItem(peerListBoxItem) {
|
||||
height: 56px;
|
||||
checkbox: RoundImageCheckbox(defaultPeerListCheckbox) {
|
||||
check: RoundCheckbox(defaultRoundCheckbox) {
|
||||
size: 0px;
|
||||
}
|
||||
imageRadius: 19px;
|
||||
imageSmallRadius: 15px;
|
||||
}
|
||||
photoSize: 38px;
|
||||
photoPosition: point(24px, 9px);
|
||||
namePosition: point(73px, 9px);
|
||||
statusPosition: point(73px, 28px);
|
||||
}
|
||||
}
|
||||
groupCallMultiSelect: MultiSelect(defaultMultiSelect) {
|
||||
bg: groupCallMembersBg;
|
||||
item: MultiSelectItem(defaultMultiSelectItem) {
|
||||
|
||||
@@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
||||
namespace Calls::Group {
|
||||
namespace {
|
||||
@@ -224,7 +225,7 @@ void ChooseJoinAsBox(
|
||||
&st::groupCallMultiSelect);
|
||||
} else {
|
||||
controller->setStyleOverrides(
|
||||
&st::peerListJoinAsList,
|
||||
&st::defaultChooseSendAs.list,
|
||||
nullptr);
|
||||
}
|
||||
const auto content = box->addRow(
|
||||
|
||||
@@ -1200,7 +1200,12 @@ void GroupCall::playConnectingSoundOnce() {
|
||||
}
|
||||
|
||||
not_null<PeerData*> GroupCall::messagesFrom() const {
|
||||
return joinAs();
|
||||
if (!videoStream()) {
|
||||
return joinAs();
|
||||
} else if (const auto real = lookupReal()) {
|
||||
return real->resolveSendAs();
|
||||
}
|
||||
return _peer->session().user();
|
||||
}
|
||||
|
||||
bool GroupCall::showChooseJoinAs() const {
|
||||
|
||||
@@ -902,40 +902,11 @@ void MessagesUi::setupMessagesWidget() {
|
||||
updateBottomFade();
|
||||
}, scroll->lifetime());
|
||||
|
||||
ReceiveSomeMouseEvents(scroll, [=](QPoint point) {
|
||||
for (const auto &entry : _views) {
|
||||
if (entry.failed || entry.top + entry.height <= point.y()) {
|
||||
continue;
|
||||
} else if (entry.top >= point.y()
|
||||
|| entry.left >= point.x()
|
||||
|| entry.left + entry.width <= point.x()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto padding = st::groupCallMessagePadding;
|
||||
const auto userpicSize = st::groupCallUserpic;
|
||||
const auto userpicPadding = st::groupCallUserpicPadding;
|
||||
const auto leftSkip = userpicPadding.left()
|
||||
+ userpicSize
|
||||
+ userpicPadding.right();
|
||||
const auto userpic = QRect(
|
||||
entry.left + userpicPadding.left(),
|
||||
entry.top + userpicPadding.top(),
|
||||
userpicSize,
|
||||
userpicSize);
|
||||
const auto link = userpic.contains(point)
|
||||
? entry.fromLink
|
||||
: entry.text.getState(point - QPoint(
|
||||
entry.left + leftSkip,
|
||||
entry.top + padding.top()
|
||||
), entry.width - leftSkip - padding.right()).link;
|
||||
if (link) {
|
||||
ActivateClickHandler(_messages, link, Qt::LeftButton);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (_mode == MessagesMode::GroupCall) {
|
||||
receiveSomeMouseEvents();
|
||||
} else {
|
||||
receiveAllMouseEvents();
|
||||
}
|
||||
|
||||
_messages->paintRequest() | rpl::start_with_next([=](QRect clip) {
|
||||
const auto start = scroll->scrollTop();
|
||||
@@ -1116,6 +1087,47 @@ void MessagesUi::setupMessagesWidget() {
|
||||
applyGeometry();
|
||||
}
|
||||
|
||||
void MessagesUi::receiveSomeMouseEvents() {
|
||||
ReceiveSomeMouseEvents(_scroll.get(), [=](QPoint point) {
|
||||
for (const auto &entry : _views) {
|
||||
if (entry.failed || entry.top + entry.height <= point.y()) {
|
||||
continue;
|
||||
} else if (entry.top >= point.y()
|
||||
|| entry.left >= point.x()
|
||||
|| entry.left + entry.width <= point.x()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto padding = st::groupCallMessagePadding;
|
||||
const auto userpicSize = st::groupCallUserpic;
|
||||
const auto userpicPadding = st::groupCallUserpicPadding;
|
||||
const auto leftSkip = userpicPadding.left()
|
||||
+ userpicSize
|
||||
+ userpicPadding.right();
|
||||
const auto userpic = QRect(
|
||||
entry.left + userpicPadding.left(),
|
||||
entry.top + userpicPadding.top(),
|
||||
userpicSize,
|
||||
userpicSize);
|
||||
const auto link = userpic.contains(point)
|
||||
? entry.fromLink
|
||||
: entry.text.getState(point - QPoint(
|
||||
entry.left + leftSkip,
|
||||
entry.top + padding.top()
|
||||
), entry.width - leftSkip - padding.right()).link;
|
||||
if (link) {
|
||||
ActivateClickHandler(_messages, link, Qt::LeftButton);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void MessagesUi::receiveAllMouseEvents() {
|
||||
|
||||
}
|
||||
|
||||
void MessagesUi::setupPinnedWidget() {
|
||||
_pinnedScroll = std::make_unique<Ui::ElasticScroll>(
|
||||
_parent,
|
||||
|
||||
@@ -122,6 +122,9 @@ private:
|
||||
void updateLeftFade();
|
||||
void updateRightFade();
|
||||
|
||||
void receiveSomeMouseEvents();
|
||||
void receiveAllMouseEvents();
|
||||
|
||||
const not_null<QWidget*> _parent;
|
||||
const std::shared_ptr<ChatHelpers::Show> _show;
|
||||
const MessagesMode _mode;
|
||||
|
||||
@@ -201,6 +201,22 @@ ComposeFiles {
|
||||
statusFg: color;
|
||||
}
|
||||
|
||||
SendAsButton {
|
||||
width: pixels;
|
||||
height: pixels;
|
||||
size: pixels;
|
||||
activeBg: color;
|
||||
activeFg: color;
|
||||
cross: CrossAnimation;
|
||||
duration: int;
|
||||
}
|
||||
|
||||
ChooseSendAs {
|
||||
button: SendAsButton;
|
||||
label: FlatLabel;
|
||||
list: PeerList;
|
||||
}
|
||||
|
||||
ComposeControls {
|
||||
bg: color;
|
||||
radius: pixels;
|
||||
@@ -232,6 +248,7 @@ ComposeControls {
|
||||
boxField: InputField;
|
||||
restrictionLabel: FlatLabel;
|
||||
premiumRequired: ComposePremiumRequired;
|
||||
chooseSendAs: ChooseSendAs;
|
||||
}
|
||||
|
||||
ReportBox {
|
||||
@@ -1436,6 +1453,42 @@ defaultRestrictionLabel: FlatLabel(defaultFlatLabel) {
|
||||
textFg: placeholderFg;
|
||||
align: align(top);
|
||||
}
|
||||
defaultSendAsButton: SendAsButton {
|
||||
width: 44px;
|
||||
height: 46px;
|
||||
size: 28px;
|
||||
activeBg: activeButtonBg;
|
||||
activeFg: activeButtonFg;
|
||||
cross: CrossAnimation {
|
||||
size: 28px;
|
||||
skip: 10px;
|
||||
stroke: 1.5;
|
||||
minScale: 0.3;
|
||||
}
|
||||
duration: 150;
|
||||
}
|
||||
defaultChooseSendAs: ChooseSendAs {
|
||||
button: defaultSendAsButton;
|
||||
label: FlatLabel(defaultFlatLabel) {
|
||||
minWidth: 272px;
|
||||
}
|
||||
list: PeerList(peerListBox) {
|
||||
item: PeerListItem(peerListBoxItem) {
|
||||
height: 56px;
|
||||
checkbox: RoundImageCheckbox(defaultPeerListCheckbox) {
|
||||
check: RoundCheckbox(defaultRoundCheckbox) {
|
||||
size: 0px;
|
||||
}
|
||||
imageRadius: 19px;
|
||||
imageSmallRadius: 15px;
|
||||
}
|
||||
photoSize: 38px;
|
||||
photoPosition: point(24px, 9px);
|
||||
namePosition: point(73px, 9px);
|
||||
statusPosition: point(73px, 28px);
|
||||
}
|
||||
}
|
||||
}
|
||||
defaultComposeControls: ComposeControls {
|
||||
bg: historyComposeAreaBg;
|
||||
radius: 0px;
|
||||
@@ -1454,6 +1507,7 @@ defaultComposeControls: ComposeControls {
|
||||
premium: defaultPremiumLimits;
|
||||
boxField: defaultInputField;
|
||||
restrictionLabel: defaultRestrictionLabel;
|
||||
chooseSendAs: defaultChooseSendAs;
|
||||
}
|
||||
|
||||
moreChatsBarHeight: 48px;
|
||||
|
||||
@@ -30,6 +30,7 @@ struct ComposeFeatures {
|
||||
bool recordMediaMessage : 1 = true;
|
||||
bool editMessageStars : 1 = false;
|
||||
bool emojiOnlyPanel : 1 = false;
|
||||
bool videoStream : 1 = false;
|
||||
};
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
||||
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "main/main_session.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "calls/group/calls_group_call.h"
|
||||
@@ -70,6 +71,7 @@ GroupCall::GroupCall(
|
||||
, _reloadByQueuedUpdatesTimer([=] { reload(); })
|
||||
, _speakingByActiveFinishTimer([=] { checkFinishSpeakingByActive(); })
|
||||
, _scheduleDate(scheduleDate)
|
||||
, _savedSendAs(peer->session().user())
|
||||
, _rtmp(rtmp)
|
||||
, _conference(origin == GroupCallOrigin::Conference)
|
||||
, _videoStream(origin == GroupCallOrigin::VideoStream)
|
||||
@@ -548,6 +550,9 @@ void GroupCall::applyCallFields(const MTPDgroupCall &data) {
|
||||
_allParticipantsLoaded
|
||||
= (_serverParticipantsCount == _participants.size());
|
||||
_conferenceInviteLink = qs(data.vinvite_link().value_or_empty());
|
||||
if (const auto as = data.vdefault_send_as()) {
|
||||
_savedSendAs = _peer->owner().peer(peerFromMTP(*as));
|
||||
}
|
||||
}
|
||||
|
||||
void GroupCall::applyLocalUpdate(
|
||||
@@ -1129,4 +1134,12 @@ ApiWrap &GroupCall::api() const {
|
||||
return session().api();
|
||||
}
|
||||
|
||||
void GroupCall::saveSendAs(not_null<PeerData*> peer) {
|
||||
_savedSendAs = peer;
|
||||
api().request(MTPphone_SaveDefaultSendAs(
|
||||
input(),
|
||||
peer->input
|
||||
)).send();
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
||||
@@ -213,6 +213,14 @@ public:
|
||||
return _messagesMinPrice.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] not_null<PeerData*> resolveSendAs() const {
|
||||
return _savedSendAs.current();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<not_null<PeerData*>> sendAsValue() const {
|
||||
return _savedSendAs.value();
|
||||
}
|
||||
void saveSendAs(not_null<PeerData*> peer);
|
||||
|
||||
private:
|
||||
enum class ApplySliceSource {
|
||||
FullReloaded,
|
||||
@@ -296,6 +304,8 @@ private:
|
||||
rpl::event_stream<base::flat_set<UserId>> _staleParticipantIds;
|
||||
rpl::lifetime _checkStaleLifetime;
|
||||
|
||||
rpl::variable<not_null<PeerData*>> _savedSendAs;
|
||||
|
||||
bool _creator : 1 = false;
|
||||
bool _joinMuted : 1 = false;
|
||||
bool _recordVideo : 1 = false;
|
||||
|
||||
@@ -3286,8 +3286,9 @@ void HistoryWidget::refreshSuggestPostToggle() {
|
||||
|
||||
void HistoryWidget::setupSendAsToggle() {
|
||||
session().sendAsPeers().updated(
|
||||
) | rpl::filter([=](not_null<PeerData*> peer) {
|
||||
return (peer == _peer);
|
||||
) | rpl::filter([=](Main::SendAsKey key) {
|
||||
return (key.peer == _peer)
|
||||
&& (key.type == Main::SendAsType::Message);
|
||||
}) | rpl::start_with_next([=] {
|
||||
refreshSendAsToggle();
|
||||
updateControlsVisibility();
|
||||
@@ -3299,22 +3300,24 @@ void HistoryWidget::setupSendAsToggle() {
|
||||
void HistoryWidget::refreshSendAsToggle() {
|
||||
Expects(_peer != nullptr);
|
||||
|
||||
if (_editMsgId || !session().sendAsPeers().shouldChoose(_peer)) {
|
||||
const auto key = Main::SendAsKey{ _peer, Main::SendAsType::Message };
|
||||
if (_editMsgId || !session().sendAsPeers().shouldChoose(key)) {
|
||||
_sendAs.destroy();
|
||||
return;
|
||||
} else if (_sendAs) {
|
||||
return;
|
||||
}
|
||||
_sendAs.create(this, st::sendAsButton);
|
||||
Ui::SetupSendAsButton(_sendAs.data(), controller());
|
||||
const auto &st = st::defaultComposeControls.chooseSendAs;
|
||||
_sendAs.create(this, st.button);
|
||||
Ui::SetupSendAsButton(_sendAs.data(), st, controller());
|
||||
}
|
||||
|
||||
bool HistoryWidget::contentOverlapped(const QRect &globalRect) {
|
||||
return (_attachDragAreas.document->overlaps(globalRect)
|
||||
|| _attachDragAreas.photo->overlaps(globalRect)
|
||||
|| (_autocomplete && _autocomplete->overlaps(globalRect))
|
||||
|| (_tabbedPanel && _tabbedPanel->overlaps(globalRect))
|
||||
|| (_inlineResults && _inlineResults->overlaps(globalRect)));
|
||||
return _attachDragAreas.document->overlaps(globalRect)
|
||||
|| _attachDragAreas.photo->overlaps(globalRect)
|
||||
|| (_autocomplete && _autocomplete->overlaps(globalRect))
|
||||
|| (_tabbedPanel && _tabbedPanel->overlaps(globalRect))
|
||||
|| (_inlineResults && _inlineResults->overlaps(globalRect));
|
||||
}
|
||||
|
||||
bool HistoryWidget::canWriteMessage() const {
|
||||
|
||||
@@ -14,6 +14,10 @@ enum class SendProgressType;
|
||||
struct SendAction;
|
||||
} // namespace Api
|
||||
|
||||
namespace Data {
|
||||
class GroupCall;
|
||||
} // namespace Data
|
||||
|
||||
class History;
|
||||
|
||||
namespace HistoryView::Controls {
|
||||
@@ -66,6 +70,7 @@ struct WriteRestriction {
|
||||
|
||||
struct SetHistoryArgs {
|
||||
required<History*> history;
|
||||
std::shared_ptr<Data::GroupCall> videoStream;
|
||||
MsgId topicRootId = 0;
|
||||
PeerId monoforumPeerId = 0;
|
||||
Fn<bool()> showSlowmodeError;
|
||||
|
||||
@@ -1056,7 +1056,7 @@ void ComposeControls::setHistory(SetHistoryArgs &&args) {
|
||||
return;
|
||||
}
|
||||
const auto peer = _history->peer;
|
||||
initSendAsButton(peer);
|
||||
initSendAsButton(peer, args.videoStream);
|
||||
if (peer->isChat() && peer->asChat()->noParticipantInfo()) {
|
||||
session().api().requestFullPeer(peer);
|
||||
} else if (const auto channel = peer->asMegagroup()) {
|
||||
@@ -1686,7 +1686,7 @@ void ComposeControls::init() {
|
||||
) | rpl::start_with_next([=](const auto &id) {
|
||||
unregisterDraftSources();
|
||||
updateSendButtonType();
|
||||
if (_history && updateSendAsButton()) {
|
||||
if (_history && updateSendAsButton(nullptr)) {
|
||||
updateControlsVisibility();
|
||||
updateControlsGeometry(_wrap->size());
|
||||
orderControls();
|
||||
@@ -2529,24 +2529,33 @@ void ComposeControls::initSendButton() {
|
||||
}, _send->lifetime());
|
||||
}
|
||||
|
||||
void ComposeControls::initSendAsButton(not_null<PeerData*> peer) {
|
||||
void ComposeControls::initSendAsButton(
|
||||
not_null<PeerData*> peer,
|
||||
std::shared_ptr<Data::GroupCall> videoStream) {
|
||||
using namespace rpl::mappers;
|
||||
using namespace Main;
|
||||
|
||||
// SendAsPeers::shouldChoose checks Data::CanSendAnything(PeerData*).
|
||||
const auto key = SendAsKey{
|
||||
peer,
|
||||
videoStream ? SendAsType::VideoStream : SendAsType::Message,
|
||||
};
|
||||
rpl::combine(
|
||||
rpl::single(peer) | rpl::then(
|
||||
session().sendAsPeers().updated() | rpl::filter(_1 == peer)
|
||||
rpl::single(key) | rpl::then(
|
||||
session().sendAsPeers().updated() | rpl::filter(_1 == key)
|
||||
),
|
||||
Data::CanSendAnythingValue(peer, false)
|
||||
(videoStream
|
||||
? rpl::single(true)
|
||||
: Data::CanSendAnythingValue(key.peer, false))
|
||||
) | rpl::skip(1) | rpl::start_with_next([=] {
|
||||
if (updateSendAsButton()) {
|
||||
if (updateSendAsButton(videoStream)) {
|
||||
updateControlsVisibility();
|
||||
updateControlsGeometry(_wrap->size());
|
||||
orderControls();
|
||||
}
|
||||
}, _historyLifetime);
|
||||
|
||||
updateSendAsButton();
|
||||
updateSendAsButton(videoStream);
|
||||
}
|
||||
|
||||
void ComposeControls::cancelInlineBot() {
|
||||
@@ -3155,13 +3164,16 @@ void ComposeControls::updateMessagesTTLShown() {
|
||||
}
|
||||
}
|
||||
|
||||
bool ComposeControls::updateSendAsButton() {
|
||||
bool ComposeControls::updateSendAsButton(
|
||||
std::shared_ptr<Data::GroupCall> videoStream) {
|
||||
const auto peer = _history ? _history->peer.get() : nullptr;
|
||||
const auto type = videoStream
|
||||
? Main::SendAsType::VideoStream
|
||||
: Main::SendAsType::Message;
|
||||
if (!_features.sendAs
|
||||
|| !peer
|
||||
|| !_regularWindow
|
||||
|| isEditingMessage()
|
||||
|| !session().sendAsPeers().shouldChoose(peer)) {
|
||||
|| !session().sendAsPeers().shouldChoose({ peer, type })) {
|
||||
if (!_sendAs) {
|
||||
return false;
|
||||
}
|
||||
@@ -3170,13 +3182,13 @@ bool ComposeControls::updateSendAsButton() {
|
||||
} else if (_sendAs) {
|
||||
return false;
|
||||
}
|
||||
_sendAs = std::make_unique<Ui::SendAsButton>(
|
||||
_wrap.get(),
|
||||
st::sendAsButton);
|
||||
Ui::SetupSendAsButton(
|
||||
_sendAs.get(),
|
||||
rpl::single(peer),
|
||||
_regularWindow);
|
||||
const auto &st = _st.chooseSendAs;
|
||||
_sendAs = std::make_unique<Ui::SendAsButton>(_wrap.get(), st.button);
|
||||
if (videoStream) {
|
||||
Ui::SetupSendAsButton(_sendAs.get(), st, videoStream, _show);
|
||||
} else {
|
||||
Ui::SetupSendAsButton(_sendAs.get(), st, rpl::single(peer), _show);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ struct MessagePosition;
|
||||
struct Draft;
|
||||
class DraftKey;
|
||||
class PhotoMedia;
|
||||
class GroupCall;
|
||||
struct WebPageDraft;
|
||||
struct MessageReactionsTopPaid;
|
||||
} // namespace Data
|
||||
@@ -77,6 +78,7 @@ class SuggestionsController;
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
struct SendAsKey;
|
||||
} // namespace Main
|
||||
|
||||
namespace Webrtc {
|
||||
@@ -296,7 +298,9 @@ private:
|
||||
void initFieldAutocomplete();
|
||||
void initTabbedSelector();
|
||||
void initSendButton();
|
||||
void initSendAsButton(not_null<PeerData*> peer);
|
||||
void initSendAsButton(
|
||||
not_null<PeerData*> peer,
|
||||
std::shared_ptr<Data::GroupCall> videoStream);
|
||||
void initWebpageProcess();
|
||||
void initForwardProcess();
|
||||
void initWriteRestriction();
|
||||
@@ -308,7 +312,7 @@ private:
|
||||
void updateSubmitSettings();
|
||||
void updateSendButtonType();
|
||||
void updateMessagesTTLShown();
|
||||
bool updateSendAsButton();
|
||||
bool updateSendAsButton(std::shared_ptr<Data::GroupCall> videoStream);
|
||||
void updateAttachBotsMenu();
|
||||
void updateHeight();
|
||||
void updateWrappingVisibility();
|
||||
|
||||
@@ -44,44 +44,47 @@ SendAsPeers::SendAsPeers(not_null<Session*> session)
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
bool SendAsPeers::shouldChoose(not_null<PeerData*> peer) {
|
||||
refresh(peer);
|
||||
const auto channel = peer->asBroadcast();
|
||||
return Data::CanSendAnything(peer, false)
|
||||
&& (list(peer).size() > 1)
|
||||
bool SendAsPeers::shouldChoose(SendAsKey key) {
|
||||
refresh(key);
|
||||
if (list(key).size() < 2) {
|
||||
return false;
|
||||
}
|
||||
if (key.type == SendAsType::VideoStream) {
|
||||
return true;
|
||||
}
|
||||
const auto channel = key.peer->asBroadcast();
|
||||
return Data::CanSendAnything(key.peer, false)
|
||||
&& (!channel
|
||||
|| channel->addsSignature()
|
||||
|| channel->signatureProfiles());
|
||||
}
|
||||
|
||||
void SendAsPeers::refresh(not_null<PeerData*> peer, bool force) {
|
||||
if (!peer->isChannel()) {
|
||||
void SendAsPeers::refresh(SendAsKey key, bool force) {
|
||||
if (key.type != SendAsType::VideoStream && !key.peer->isChannel()) {
|
||||
return;
|
||||
}
|
||||
const auto now = crl::now();
|
||||
const auto i = _lastRequestTime.find(peer);
|
||||
const auto i = _lastRequestTime.find(key);
|
||||
const auto when = (i == end(_lastRequestTime)) ? -1 : i->second;
|
||||
if (!force && (when >= 0 && now < when + kRequestEach)) {
|
||||
return;
|
||||
}
|
||||
_lastRequestTime[peer] = now;
|
||||
request(peer);
|
||||
request(peer, true);
|
||||
_lastRequestTime[key] = now;
|
||||
request(key);
|
||||
if (key.type == SendAsType::Message) {
|
||||
request({ key.peer, SendAsType::PaidReaction });
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<SendAsPeer> &SendAsPeers::list(
|
||||
not_null<PeerData*> peer) const {
|
||||
const auto i = _lists.find(peer);
|
||||
const std::vector<SendAsPeer> &SendAsPeers::list(SendAsKey key) const {
|
||||
if (key.type != SendAsType::VideoStream && !key.peer->isChannel()) {
|
||||
return _onlyMe;
|
||||
}
|
||||
const auto i = _lists.find(key);
|
||||
return (i != end(_lists)) ? i->second : _onlyMe;
|
||||
}
|
||||
|
||||
const std::vector<not_null<PeerData*>> &SendAsPeers::paidReactionList(
|
||||
not_null<PeerData*> peer) const {
|
||||
const auto i = _paidReactionLists.find(peer);
|
||||
return (i != end(_paidReactionLists)) ? i->second : _onlyMePaid;
|
||||
}
|
||||
|
||||
rpl::producer<not_null<PeerData*>> SendAsPeers::updated() const {
|
||||
rpl::producer<SendAsKey> SendAsPeers::updated() const {
|
||||
return _updates.events();
|
||||
}
|
||||
|
||||
@@ -108,7 +111,7 @@ void SendAsPeers::setChosen(not_null<PeerData*> peer, PeerId chosenId) {
|
||||
} else {
|
||||
_chosen[peer] = chosenId;
|
||||
}
|
||||
_updates.fire_copy(peer);
|
||||
_updates.fire({ peer });
|
||||
}
|
||||
|
||||
PeerId SendAsPeers::chosen(not_null<PeerData*> peer) const {
|
||||
@@ -118,7 +121,7 @@ PeerId SendAsPeers::chosen(not_null<PeerData*> peer) const {
|
||||
|
||||
not_null<PeerData*> SendAsPeers::resolveChosen(
|
||||
not_null<PeerData*> peer) const {
|
||||
return ResolveChosen(peer, list(peer), chosen(peer));
|
||||
return ResolveChosen(peer, list({ peer }), chosen(peer));
|
||||
}
|
||||
|
||||
not_null<PeerData*> SendAsPeers::ResolveChosen(
|
||||
@@ -141,14 +144,18 @@ not_null<PeerData*> SendAsPeers::ResolveChosen(
|
||||
: fallback;
|
||||
}
|
||||
|
||||
void SendAsPeers::request(not_null<PeerData*> peer, bool forPaidReactions) {
|
||||
void SendAsPeers::request(SendAsKey key) {
|
||||
using Flag = MTPchannels_GetSendAs::Flag;
|
||||
peer->session().api().request(MTPchannels_GetSendAs(
|
||||
MTP_flags(forPaidReactions ? Flag::f_for_paid_reactions : Flag()),
|
||||
peer->input
|
||||
key.peer->session().api().request(MTPchannels_GetSendAs(
|
||||
MTP_flags((key.type == SendAsType::PaidReaction)
|
||||
? Flag::f_for_paid_reactions
|
||||
: (key.type == SendAsType::VideoStream)
|
||||
? Flag::f_for_live_stories
|
||||
: Flag()),
|
||||
key.peer->input
|
||||
)).done([=](const MTPchannels_SendAsPeers &result) {
|
||||
auto parsed = std::vector<SendAsPeer>();
|
||||
auto &owner = peer->owner();
|
||||
auto &owner = key.peer->owner();
|
||||
result.match([&](const MTPDchannels_sendAsPeers &data) {
|
||||
owner.processUsers(data.vusers());
|
||||
owner.processChats(data.vchats());
|
||||
@@ -165,26 +172,15 @@ void SendAsPeers::request(not_null<PeerData*> peer, bool forPaidReactions) {
|
||||
}
|
||||
}
|
||||
});
|
||||
if (forPaidReactions) {
|
||||
auto peers = parsed | ranges::views::transform(
|
||||
&SendAsPeer::peer
|
||||
) | ranges::to_vector;
|
||||
if (!peers.empty()) {
|
||||
_paidReactionLists[peer] = std::move(peers);
|
||||
} else {
|
||||
_paidReactionLists.remove(peer);
|
||||
}
|
||||
} else {
|
||||
if (parsed.size() > 1) {
|
||||
auto &now = _lists[peer];
|
||||
if (now != parsed) {
|
||||
now = std::move(parsed);
|
||||
_updates.fire_copy(peer);
|
||||
}
|
||||
} else if (const auto i = _lists.find(peer); i != end(_lists)) {
|
||||
_lists.erase(i);
|
||||
_updates.fire_copy(peer);
|
||||
if (parsed.size() > 1) {
|
||||
auto &now = _lists[key];
|
||||
if (now != parsed) {
|
||||
now = std::move(parsed);
|
||||
_updates.fire_copy(key);
|
||||
}
|
||||
} else if (const auto i = _lists.find(key); i != end(_lists)) {
|
||||
_lists.erase(i);
|
||||
_updates.fire_copy(key);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
@@ -20,15 +20,35 @@ struct SendAsPeer {
|
||||
friend inline auto operator<=>(SendAsPeer, SendAsPeer) = default;
|
||||
};
|
||||
|
||||
enum class SendAsType : uchar {
|
||||
Message,
|
||||
PaidReaction,
|
||||
VideoStream,
|
||||
};
|
||||
|
||||
struct SendAsKey {
|
||||
SendAsKey(
|
||||
not_null<PeerData*> peer,
|
||||
SendAsType type = SendAsType::Message)
|
||||
: peer(peer)
|
||||
, type(type) {
|
||||
}
|
||||
|
||||
friend inline auto operator<=>(SendAsKey, SendAsKey) = default;
|
||||
friend inline bool operator==(SendAsKey, SendAsKey) = default;
|
||||
|
||||
not_null<PeerData*> peer;
|
||||
SendAsType type = SendAsType::Message;
|
||||
};
|
||||
|
||||
class SendAsPeers final {
|
||||
public:
|
||||
explicit SendAsPeers(not_null<Session*> session);
|
||||
|
||||
bool shouldChoose(not_null<PeerData*> peer);
|
||||
void refresh(not_null<PeerData*> peer, bool force = false);
|
||||
[[nodiscard]] const std::vector<SendAsPeer> &list(
|
||||
not_null<PeerData*> peer) const;
|
||||
[[nodiscard]] rpl::producer<not_null<PeerData*>> updated() const;
|
||||
bool shouldChoose(SendAsKey key);
|
||||
void refresh(SendAsKey key, bool force = false);
|
||||
[[nodiscard]] const std::vector<SendAsPeer> &list(SendAsKey key) const;
|
||||
[[nodiscard]] rpl::producer<SendAsKey> updated() const;
|
||||
|
||||
void saveChosen(not_null<PeerData*> peer, not_null<PeerData*> chosen);
|
||||
void setChosen(not_null<PeerData*> peer, PeerId chosenId);
|
||||
@@ -47,20 +67,17 @@ public:
|
||||
PeerId chosen);
|
||||
|
||||
private:
|
||||
void request(not_null<PeerData*> peer, bool forPaidReactions = false);
|
||||
void request(SendAsKey key);
|
||||
|
||||
const not_null<Session*> _session;
|
||||
const std::vector<SendAsPeer> _onlyMe;
|
||||
const std::vector<not_null<PeerData*>> _onlyMePaid;
|
||||
|
||||
base::flat_map<not_null<PeerData*>, std::vector<SendAsPeer>> _lists;
|
||||
base::flat_map<not_null<PeerData*>, crl::time> _lastRequestTime;
|
||||
base::flat_map<SendAsKey, std::vector<SendAsPeer>> _lists;
|
||||
base::flat_map<SendAsKey, crl::time> _lastRequestTime;
|
||||
base::flat_map<not_null<PeerData*>, PeerId> _chosen;
|
||||
base::flat_map<
|
||||
not_null<PeerData*>,
|
||||
std::vector<not_null<PeerData*>>> _paidReactionLists;
|
||||
|
||||
rpl::event_stream<not_null<PeerData*>> _updates;
|
||||
rpl::event_stream<SendAsKey> _updates;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
|
||||
@@ -818,7 +818,7 @@ void Controller::rebuildFromContext(
|
||||
_slider->show({
|
||||
.index = _sliderCount ? _sliderIndex : _index,
|
||||
.total = _sliderCount ? _sliderCount : shownCount(),
|
||||
.videoStream = _videoStream,
|
||||
.videoStream = videoStream(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -856,7 +856,7 @@ void Controller::show(
|
||||
_context = context;
|
||||
_waitingForId = {};
|
||||
_waitingForDelta = 0;
|
||||
_videoStream = (story->call() != nullptr);
|
||||
_videoStream = story->call();
|
||||
if (!_videoStream) {
|
||||
clearVideoStreamCall();
|
||||
}
|
||||
@@ -921,7 +921,7 @@ void Controller::show(
|
||||
.privacy = story->privacy(),
|
||||
.edited = story->edited(),
|
||||
.video = (document != nullptr),
|
||||
.videoStream = _videoStream,
|
||||
.videoStream = videoStream(),
|
||||
.silent = (document && document->isSilentVideo()),
|
||||
});
|
||||
uiShow()->hideLayer(anim::type::instant);
|
||||
@@ -943,7 +943,7 @@ void Controller::show(
|
||||
.forwards = story->forwards(),
|
||||
.views = story->views(),
|
||||
.total = story->interactions(),
|
||||
.type = RecentViewsTypeFor(peer, _videoStream),
|
||||
.type = RecentViewsTypeFor(peer, videoStream()),
|
||||
.canViewReactions = (!_videoStream
|
||||
&& CanViewReactionsFor(peer)
|
||||
&& !peer->isMegagroup()),
|
||||
@@ -1052,7 +1052,7 @@ void Controller::subscribeToSession() {
|
||||
.forwards = update.story->forwards(),
|
||||
.views = update.story->views(),
|
||||
.total = update.story->interactions(),
|
||||
.type = RecentViewsTypeFor(peer, _videoStream),
|
||||
.type = RecentViewsTypeFor(peer, videoStream()),
|
||||
.canViewReactions = (!_videoStream
|
||||
&& CanViewReactionsFor(peer)
|
||||
&& !peer->isMegagroup()),
|
||||
@@ -1932,7 +1932,7 @@ void Controller::clearVideoStreamCall() {
|
||||
}
|
||||
|
||||
bool Controller::videoStream() const {
|
||||
return _videoStream;
|
||||
return _videoStream != nullptr;
|
||||
}
|
||||
|
||||
rpl::lifetime &Controller::lifetime() {
|
||||
|
||||
@@ -306,6 +306,7 @@ private:
|
||||
std::unique_ptr<CaptionFullView> _captionFullView;
|
||||
std::unique_ptr<RepostView> _repostView;
|
||||
|
||||
std::shared_ptr<Data::GroupCall> _videoStream;
|
||||
base::weak_ptr<Calls::GroupCall> _videoStreamCall;
|
||||
std::unique_ptr<PaidReactionToast> _paidReactionToast;
|
||||
rpl::lifetime _videoStreamLifetime;
|
||||
@@ -318,7 +319,6 @@ private:
|
||||
bool _layerShown = false;
|
||||
bool _menuShown = false;
|
||||
bool _tooltipShown = false;
|
||||
bool _videoStream = false;
|
||||
bool _paused = false;
|
||||
|
||||
FullStoryId _shown;
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace {
|
||||
[[nodiscard]] ChatHelpers::ComposeFeatures Features(bool videoStream) {
|
||||
return {
|
||||
.likes = !videoStream,
|
||||
.sendAs = false,
|
||||
.sendAs = videoStream,
|
||||
.ttlInfo = false,
|
||||
.attachments = !videoStream,
|
||||
.botCommandSend = false,
|
||||
@@ -858,7 +858,7 @@ void ReplyArea::show(
|
||||
const auto streamChanged = (_data.videoStream != data.videoStream);
|
||||
_data = data;
|
||||
if (streamChanged) {
|
||||
_controls->updateFeatures(Features(_data.videoStream));
|
||||
_controls->updateFeatures(Features(_data.videoStream != nullptr));
|
||||
_controls->setToggleCommentsButton(_data.videoStream
|
||||
? _controller->commentsStateValue()
|
||||
: nullptr);
|
||||
@@ -917,6 +917,7 @@ void ReplyArea::show(
|
||||
using namespace HistoryView;
|
||||
_controls->setHistory({
|
||||
.history = history,
|
||||
.videoStream = _data.videoStream,
|
||||
.showSlowmodeError = [=] { return showSlowmodeError(); },
|
||||
.sendActionFactory = [=] { return prepareSendAction({}); },
|
||||
.slowmodeSecondsLeft = SlowmodeSecondsLeft(history->peer),
|
||||
|
||||
@@ -24,6 +24,7 @@ class GroupCall;
|
||||
} // namespace Calls
|
||||
|
||||
namespace Data {
|
||||
class GroupCall;
|
||||
struct ReactionId;
|
||||
} // namespace Data
|
||||
|
||||
@@ -61,7 +62,7 @@ class Controller;
|
||||
struct ReplyAreaData {
|
||||
PeerData *peer = nullptr;
|
||||
StoryId id = 0;
|
||||
bool videoStream = false;
|
||||
std::shared_ptr<Data::GroupCall> videoStream;
|
||||
|
||||
friend inline auto operator<=>(ReplyAreaData, ReplyAreaData) = default;
|
||||
friend inline bool operator==(ReplyAreaData, ReplyAreaData) = default;
|
||||
|
||||
@@ -689,6 +689,17 @@ storiesBoxInputField: InputField(defaultComposeFilesField) {
|
||||
borderFgActive: storiesComposeBlue;
|
||||
menu: storiesPopupMenu;
|
||||
}
|
||||
storiesChooseSendAs: ChooseSendAs(defaultChooseSendAs) {
|
||||
button: SendAsButton(defaultSendAsButton) {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
}
|
||||
label: FlatLabel(defaultFlatLabel) {
|
||||
minWidth: 272px;
|
||||
textFg: storiesComposeWhiteText;
|
||||
}
|
||||
list: groupCallJoinAsList;
|
||||
}
|
||||
storiesComposeControls: ComposeControls(defaultComposeControls) {
|
||||
bg: storiesComposeBg;
|
||||
radius: 21px;
|
||||
@@ -866,6 +877,7 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
||||
position: point(37px, 14px);
|
||||
icon: icon{{ "emoji/premium_lock", storiesComposeGrayIcon, point(13px, 14px) }};
|
||||
}
|
||||
chooseSendAs: storiesChooseSendAs;
|
||||
}
|
||||
storiesViewsMenu: PopupMenu(storiesPopupMenuWithIcons) {
|
||||
scrollPadding: margins(0px, 6px, 0px, 4px);
|
||||
|
||||
@@ -245,7 +245,11 @@ void ShowPaidReactionDetails(
|
||||
};
|
||||
const auto linked = item->discussionPostOriginalSender();
|
||||
const auto channel = (linked ? linked : item->history()->peer.get());
|
||||
const auto channels = session->sendAsPeers().paidReactionList(channel);
|
||||
const auto channels = session->sendAsPeers().list(
|
||||
{ channel, Main::SendAsType::PaidReaction }
|
||||
) | ranges::views::transform(
|
||||
&Main::SendAsPeer::peer
|
||||
) | ranges::to_vector;
|
||||
const auto topPaid = item->topPaidReactionsWithLocal();
|
||||
top.reserve(topPaid.size() + 2 + channels.size());
|
||||
for (const auto &entry : topPaid) {
|
||||
|
||||
@@ -848,31 +848,6 @@ reactionsTabs: MultiSelect(defaultMultiSelect) {
|
||||
}
|
||||
reactionsTabIconSkip: 3px;
|
||||
|
||||
SendAsButton {
|
||||
width: pixels;
|
||||
height: pixels;
|
||||
size: pixels;
|
||||
activeBg: color;
|
||||
activeFg: color;
|
||||
cross: CrossAnimation;
|
||||
duration: int;
|
||||
}
|
||||
|
||||
sendAsButton: SendAsButton {
|
||||
width: 44px;
|
||||
height: 46px;
|
||||
size: 28px;
|
||||
activeBg: activeButtonBg;
|
||||
activeFg: activeButtonFg;
|
||||
cross: CrossAnimation {
|
||||
size: 28px;
|
||||
skip: 10px;
|
||||
stroke: 1.5;
|
||||
minScale: 0.3;
|
||||
}
|
||||
duration: 150;
|
||||
}
|
||||
|
||||
reactionInlinePadding: margins(5px, 2px, 7px, 2px);
|
||||
reactionInlineSize: 18px;
|
||||
reactionInlineImage: 32px;
|
||||
|
||||
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/chat/choose_send_as.h"
|
||||
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "data/data_group_call.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_peer_values.h"
|
||||
@@ -21,7 +22,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_keys.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
||||
@@ -171,6 +171,7 @@ rpl::producer<not_null<PeerData*>> ListController::clicked() const {
|
||||
|
||||
void ChooseSendAsBox(
|
||||
not_null<GenericBox*> box,
|
||||
const style::ChooseSendAs &st,
|
||||
std::vector<Main::SendAsPeer> list,
|
||||
not_null<PeerData*> chosen,
|
||||
Fn<bool(not_null<PeerData*>)> done) {
|
||||
@@ -179,11 +180,10 @@ void ChooseSendAsBox(
|
||||
|
||||
box->setWidth(st::groupCallJoinAsWidth);
|
||||
box->setTitle(tr::lng_send_as_title());
|
||||
const auto &labelSt = st::confirmPhoneAboutLabel;
|
||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
tr::lng_group_call_join_as_about(),
|
||||
labelSt));
|
||||
st.label));
|
||||
|
||||
auto &lifetime = box->lifetime();
|
||||
const auto delegate = lifetime.make_state<
|
||||
@@ -192,9 +192,7 @@ void ChooseSendAsBox(
|
||||
const auto controller = lifetime.make_state<ListController>(
|
||||
list,
|
||||
chosen);
|
||||
controller->setStyleOverrides(
|
||||
&st::peerListJoinAsList,
|
||||
nullptr);
|
||||
controller->setStyleOverrides(&st.list, nullptr);
|
||||
|
||||
controller->clicked(
|
||||
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
||||
@@ -214,19 +212,21 @@ void ChooseSendAsBox(
|
||||
|
||||
void SetupSendAsButton(
|
||||
not_null<SendAsButton*> button,
|
||||
const style::ChooseSendAs &st,
|
||||
rpl::producer<PeerData*> active,
|
||||
not_null<Window::SessionController*> window) {
|
||||
std::shared_ptr<ChatHelpers::Show> show) {
|
||||
using namespace rpl::mappers;
|
||||
const auto current = button->lifetime().make_state<
|
||||
rpl::variable<PeerData*>
|
||||
>(std::move(active));
|
||||
button->setClickedCallback([=] {
|
||||
button->setClickedCallback([=, &st] {
|
||||
const auto peer = current->current();
|
||||
if (!peer) {
|
||||
return;
|
||||
}
|
||||
const auto key = Main::SendAsKey{ peer, Main::SendAsType::Message };
|
||||
const auto session = &peer->session();
|
||||
const auto &list = session->sendAsPeers().list(peer);
|
||||
const auto &list = session->sendAsPeers().list(key);
|
||||
if (list.size() < 2) {
|
||||
return;
|
||||
}
|
||||
@@ -239,7 +239,7 @@ void SetupSendAsButton(
|
||||
&& i->premiumRequired
|
||||
&& !sendAs->session().premium()) {
|
||||
Settings::ShowPremiumPromoToast(
|
||||
window->uiShow(),
|
||||
show,
|
||||
tr::lng_send_as_premium_required(
|
||||
tr::now,
|
||||
lt_link,
|
||||
@@ -254,13 +254,15 @@ void SetupSendAsButton(
|
||||
session->sendAsPeers().saveChosen(peer, sendAs);
|
||||
return true;
|
||||
};
|
||||
window->show(Box(
|
||||
show->show(Box(
|
||||
Ui::ChooseSendAsBox,
|
||||
st,
|
||||
list,
|
||||
session->sendAsPeers().resolveChosen(peer),
|
||||
done));
|
||||
});
|
||||
|
||||
const auto size = st.button.size;
|
||||
auto userpic = current->value(
|
||||
) | rpl::filter([=](PeerData *peer) {
|
||||
return peer && peer->isChannel();
|
||||
@@ -271,7 +273,7 @@ void SetupSendAsButton(
|
||||
rpl::empty
|
||||
) | rpl::then(channel->session().sendAsPeers().updated(
|
||||
) | rpl::filter(
|
||||
_1 == channel
|
||||
_1 == Main::SendAsKey(channel, Main::SendAsType::Message)
|
||||
) | rpl::to_empty);
|
||||
|
||||
return rpl::combine(
|
||||
@@ -283,7 +285,7 @@ void SetupSendAsButton(
|
||||
) | rpl::map([=](not_null<PeerData*> chosen) {
|
||||
return Data::PeerUserpicImageValue(
|
||||
chosen,
|
||||
st::sendAsButton.size * style::DevicePixelRatio());
|
||||
size * style::DevicePixelRatio());
|
||||
}) | rpl::flatten_latest();
|
||||
}) | rpl::flatten_latest();
|
||||
|
||||
@@ -296,12 +298,55 @@ void SetupSendAsButton(
|
||||
|
||||
void SetupSendAsButton(
|
||||
not_null<SendAsButton*> button,
|
||||
const style::ChooseSendAs &st,
|
||||
std::shared_ptr<Data::GroupCall> videoStream,
|
||||
std::shared_ptr<ChatHelpers::Show> show) {
|
||||
const auto peer = videoStream->peer();
|
||||
const auto type = Main::SendAsType::VideoStream;
|
||||
const auto key = Main::SendAsKey{ peer, type };
|
||||
button->setClickedCallback([=, &st] {
|
||||
const auto session = &peer->session();
|
||||
const auto &list = session->sendAsPeers().list(key);
|
||||
if (list.size() < 2) {
|
||||
return;
|
||||
}
|
||||
const auto done = [=](not_null<PeerData*> sendAs) {
|
||||
videoStream->saveSendAs(sendAs);
|
||||
return true;
|
||||
};
|
||||
show->show(Box(
|
||||
Ui::ChooseSendAsBox,
|
||||
st,
|
||||
list,
|
||||
videoStream->resolveSendAs(),
|
||||
done));
|
||||
});
|
||||
|
||||
const auto size = st.button.size;
|
||||
auto userpic = videoStream->sendAsValue(
|
||||
) | rpl::distinct_until_changed(
|
||||
) | rpl::map([=](not_null<PeerData*> chosen) {
|
||||
return Data::PeerUserpicImageValue(
|
||||
chosen,
|
||||
size * style::DevicePixelRatio());
|
||||
}) | rpl::flatten_latest();
|
||||
|
||||
std::move(
|
||||
userpic
|
||||
) | rpl::start_with_next([=](QImage &&userpic) {
|
||||
button->setUserpic(std::move(userpic));
|
||||
}, button->lifetime());
|
||||
}
|
||||
|
||||
void SetupSendAsButton(
|
||||
not_null<SendAsButton*> button,
|
||||
const style::ChooseSendAs &st,
|
||||
not_null<Window::SessionController*> window) {
|
||||
auto active = window->activeChatValue(
|
||||
) | rpl::map([=](Dialogs::Key key) {
|
||||
return key.history() ? key.history()->peer.get() : nullptr;
|
||||
});
|
||||
SetupSendAsButton(button, std::move(active), window);
|
||||
SetupSendAsButton(button, st, std::move(active), window->uiShow());
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
||||
@@ -12,6 +12,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
class PeerData;
|
||||
|
||||
namespace style {
|
||||
struct ChooseSendAs;
|
||||
} // namespace style
|
||||
|
||||
namespace Data {
|
||||
class GroupCall;
|
||||
} // namespace Data
|
||||
|
||||
namespace ChatHelpers {
|
||||
class Show;
|
||||
} // namespace ChatHelpers
|
||||
|
||||
namespace Main {
|
||||
struct SendAsPeer;
|
||||
} // namespace Main
|
||||
@@ -26,17 +38,26 @@ class SendAsButton;
|
||||
|
||||
void ChooseSendAsBox(
|
||||
not_null<GenericBox*> box,
|
||||
const style::ChooseSendAs &st,
|
||||
std::vector<Main::SendAsPeer> list,
|
||||
not_null<PeerData*> chosen,
|
||||
Fn<bool(not_null<PeerData*>)> done);
|
||||
|
||||
void SetupSendAsButton(
|
||||
not_null<SendAsButton*> button,
|
||||
const style::ChooseSendAs &st,
|
||||
rpl::producer<PeerData*> active,
|
||||
not_null<Window::SessionController*> window);
|
||||
std::shared_ptr<ChatHelpers::Show> show);
|
||||
|
||||
void SetupSendAsButton(
|
||||
not_null<SendAsButton*> button,
|
||||
const style::ChooseSendAs &st,
|
||||
std::shared_ptr<Data::GroupCall> videoStream,
|
||||
std::shared_ptr<ChatHelpers::Show> show);
|
||||
|
||||
void SetupSendAsButton(
|
||||
not_null<SendAsButton*> button,
|
||||
const style::ChooseSendAs &st,
|
||||
not_null<Window::SessionController*> window);
|
||||
|
||||
} // namespace Ui
|
||||
|
||||
@@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "ui/effects/cross_animation.h"
|
||||
#include "ui/painter.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
||||
namespace Ui {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user