mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-05 13:57:52 +00:00
Add a nice countdown to scheduled voice chat panel.
This commit is contained in:
parent
66e7f05df1
commit
d7e90fec1a
@ -1098,8 +1098,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_action_invite_user_chat" = "the voice chat";
|
||||
"lng_action_invite_users_and_one" = "{accumulated}, {user}";
|
||||
"lng_action_invite_users_and_last" = "{accumulated} and {user}";
|
||||
"lng_action_group_call_started" = "{from} started {chat}";
|
||||
"lng_action_group_call_started_chat" = "a voice chat";
|
||||
"lng_action_group_call_started_group" = "{from} started a voice chat";
|
||||
"lng_action_group_call_started_channel" = "Voice chat started";
|
||||
"lng_action_group_call_scheduled_group" = "{from} scheduled a voice chat";
|
||||
"lng_action_group_call_scheduled_channel" = "Voice chat scheduled";
|
||||
"lng_action_group_call_finished" = "Voice chat finished ({duration})";
|
||||
"lng_action_add_user" = "{from} added {user}";
|
||||
"lng_action_add_users_many" = "{from} added {users}";
|
||||
@ -2073,6 +2075,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_group_call_starts_tomorrow" = "tomorrow at {time}";
|
||||
"lng_group_call_starts_date" = "{date} at {time}";
|
||||
"lng_group_call_starts_in" = "Starts in";
|
||||
"lng_group_call_starts_short_today" = "Today, {time}";
|
||||
"lng_group_call_starts_short_tomorrow" = "Tomorrow, {time}";
|
||||
"lng_group_call_starts_short_date" = "{date}, {time}";
|
||||
"lng_group_call_start_now" = "Start Now";
|
||||
"lng_group_call_set_reminder" = "Set Reminder";
|
||||
"lng_group_call_cancel_reminder" = "Cancel Reminder";
|
||||
|
@ -945,3 +945,18 @@ callTopBarMuteCrossLine: CrossLineAnimation {
|
||||
endPosition: point(26px, 23px);
|
||||
stroke: 2px;
|
||||
}
|
||||
|
||||
groupCallStartsIn: FlatLabel(defaultFlatLabel) {
|
||||
style: TextStyle(defaultTextStyle) {
|
||||
font: font(20px semibold);
|
||||
linkFont: font(20px semibold);
|
||||
linkFontOver: font(20px semibold underline);
|
||||
}
|
||||
textFg: groupCallMembersFg;
|
||||
}
|
||||
groupCallScheduledBodyHeight: 200px;
|
||||
groupCallStartsWhen: groupCallStartsIn;
|
||||
groupCallStartsInTop: 10px;
|
||||
groupCallStartsWhenTop: 160px;
|
||||
groupCallCountdownFont: font(64px semibold);
|
||||
groupCallCountdownTop: 52px;
|
||||
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/chat/group_call_bar.h"
|
||||
#include "ui/layers/layer_manager.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
@ -41,6 +42,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/peers/add_participants_box.h"
|
||||
#include "boxes/peer_lists_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "base/timer_rpl.h"
|
||||
#include "app.h"
|
||||
#include "apiwrap.h" // api().kickParticipant.
|
||||
#include "styles/style_calls.h"
|
||||
@ -116,6 +119,122 @@ private:
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> StartsWhenText(
|
||||
rpl::producer<TimeId> date) {
|
||||
return std::move(
|
||||
date
|
||||
) | rpl::map([](TimeId date) -> rpl::producer<QString> {
|
||||
const auto parsedDate = base::unixtime::parse(date);
|
||||
const auto dateDay = QDateTime(parsedDate.date(), QTime(0, 0));
|
||||
const auto previousDay = QDateTime(
|
||||
parsedDate.date().addDays(-1),
|
||||
QTime(0, 0));
|
||||
const auto now = QDateTime::currentDateTime();
|
||||
const auto kDay = int64(24 * 60 * 60);
|
||||
const auto tillTomorrow = int64(now.secsTo(previousDay));
|
||||
const auto tillToday = tillTomorrow + kDay;
|
||||
const auto tillAfter = tillToday + kDay;
|
||||
|
||||
const auto time = parsedDate.time().toString(
|
||||
QLocale::system().timeFormat(QLocale::ShortFormat));
|
||||
auto exact = tr::lng_group_call_starts_short_date(
|
||||
lt_date,
|
||||
rpl::single(langDayOfMonthFull(dateDay.date())),
|
||||
lt_time,
|
||||
rpl::single(time));
|
||||
auto tomorrow = tr::lng_group_call_starts_short_tomorrow(
|
||||
lt_time,
|
||||
rpl::single(time));
|
||||
auto today = tr::lng_group_call_starts_short_today(
|
||||
lt_time,
|
||||
rpl::single(time));
|
||||
|
||||
auto todayAndAfter = rpl::single(
|
||||
std::move(today)
|
||||
) | rpl::then(base::timer_once(
|
||||
std::min(tillAfter, kDay) * crl::time(1000)
|
||||
) | rpl::map([=] {
|
||||
return rpl::duplicate(exact);
|
||||
})) | rpl::flatten_latest();
|
||||
|
||||
auto tomorrowAndAfter = rpl::single(
|
||||
std::move(tomorrow)
|
||||
) | rpl::then(base::timer_once(
|
||||
std::min(tillToday, kDay) * crl::time(1000)
|
||||
) | rpl::map([=] {
|
||||
return rpl::duplicate(todayAndAfter);
|
||||
})) | rpl::flatten_latest();
|
||||
|
||||
auto full = rpl::single(
|
||||
rpl::duplicate(exact)
|
||||
) | rpl::then(base::timer_once(
|
||||
tillTomorrow * crl::time(1000)
|
||||
) | rpl::map([=] {
|
||||
return rpl::duplicate(tomorrowAndAfter);
|
||||
})) | rpl::flatten_latest();
|
||||
|
||||
if (tillTomorrow > 0) {
|
||||
return std::move(full);
|
||||
} else if (tillToday > 0) {
|
||||
return std::move(tomorrowAndAfter);
|
||||
} else if (tillAfter > 0) {
|
||||
return std::move(todayAndAfter);
|
||||
} else {
|
||||
return std::move(exact);
|
||||
}
|
||||
}) | rpl::flatten_latest();
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> CreateGradientLabel(
|
||||
QWidget *parent,
|
||||
rpl::producer<QString> text) {
|
||||
struct State {
|
||||
QBrush brush;
|
||||
QPainterPath path;
|
||||
};
|
||||
auto result = object_ptr<Ui::RpWidget>(parent);
|
||||
const auto raw = result.data();
|
||||
const auto state = raw->lifetime().make_state<State>();
|
||||
|
||||
std::move(
|
||||
text
|
||||
) | rpl::start_with_next([=](const QString &text) {
|
||||
state->path = QPainterPath();
|
||||
const auto &font = st::groupCallCountdownFont;
|
||||
state->path.addText(0, font->ascent, font->f, text);
|
||||
const auto width = font->width(text);
|
||||
raw->resize(width, font->height);
|
||||
auto gradient = QLinearGradient(QPoint(width, 0), QPoint());
|
||||
gradient.setStops(QGradientStops{
|
||||
{ 0.0, st::groupCallForceMutedBar1->c },
|
||||
{ .7, st::groupCallForceMutedBar2->c },
|
||||
{ 1.0, st::groupCallForceMutedBar3->c }
|
||||
});
|
||||
state->brush = QBrush(std::move(gradient));
|
||||
raw->update();
|
||||
}, raw->lifetime());
|
||||
|
||||
raw->paintRequest(
|
||||
) | rpl::start_with_next([=] {
|
||||
auto p = QPainter(raw);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto skip = st::groupCallWidth / 20;
|
||||
const auto available = parent->width() - 2 * skip;
|
||||
const auto full = raw->width();
|
||||
if (available > 0 && full > available) {
|
||||
const auto scale = available / float64(full);
|
||||
const auto shift = raw->rect().center();
|
||||
p.translate(shift);
|
||||
p.scale(scale, scale);
|
||||
p.translate(-shift);
|
||||
}
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(state->brush);
|
||||
p.drawPath(state->path);
|
||||
}, raw->lifetime());
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> CreateSectionSubtitle(
|
||||
QWidget *parent,
|
||||
rpl::producer<QString> text) {
|
||||
@ -451,18 +570,23 @@ void Panel::initControls() {
|
||||
});
|
||||
|
||||
_settings->setText(tr::lng_group_call_settings());
|
||||
const auto scheduled = (_call->scheduleDate() != 0);
|
||||
_hangup->setText(scheduled
|
||||
const auto scheduleDate = _call->scheduleDate();
|
||||
_hangup->setText(scheduleDate
|
||||
? tr::lng_group_call_close()
|
||||
: tr::lng_group_call_leave());
|
||||
if (scheduled) {
|
||||
_call->real(
|
||||
if (scheduleDate) {
|
||||
auto changes = _call->real(
|
||||
) | rpl::map([=](not_null<Data::GroupCall*> real) {
|
||||
return real->scheduleDateValue();
|
||||
}) | rpl::flatten_latest() | rpl::filter([](TimeId date) {
|
||||
}) | rpl::flatten_latest();
|
||||
setupScheduledLabels(rpl::single(
|
||||
scheduleDate
|
||||
) | rpl::then(rpl::duplicate(changes)));
|
||||
std::move(changes) | rpl::filter([](TimeId date) {
|
||||
return (date == 0);
|
||||
}) | rpl::take(1) | rpl::start_with_next([=] {
|
||||
_hangup->setText(tr::lng_group_call_leave());
|
||||
setupMembers();
|
||||
}, _callLifetime);
|
||||
}
|
||||
|
||||
@ -553,8 +677,66 @@ void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
|
||||
}, _callLifetime);
|
||||
}
|
||||
|
||||
void Panel::setupScheduledLabels(rpl::producer<TimeId> date) {
|
||||
using namespace rpl::mappers;
|
||||
_startsIn.create(
|
||||
widget(),
|
||||
tr::lng_group_call_starts_in(),
|
||||
st::groupCallStartsIn);
|
||||
date = std::move(date) | rpl::take_while(_1 != 0);
|
||||
_startsWhen.create(
|
||||
widget(),
|
||||
StartsWhenText(rpl::duplicate(date)),
|
||||
st::groupCallStartsWhen);
|
||||
_countdown = CreateGradientLabel(widget(), std::move(
|
||||
date
|
||||
) | rpl::map([=](TimeId date) {
|
||||
_countdownData = std::make_shared<Ui::GroupCallScheduledLeft>(date);
|
||||
return _countdownData->text();
|
||||
}) | rpl::flatten_latest());
|
||||
|
||||
const auto top = [=] {
|
||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
||||
const auto membersTop = st::groupCallMembersTop;
|
||||
const auto height = st::groupCallScheduledBodyHeight;
|
||||
return (membersTop + (muteTop - membersTop - height) / 2);
|
||||
};
|
||||
rpl::combine(
|
||||
widget()->sizeValue(),
|
||||
_startsIn->widthValue()
|
||||
) | rpl::start_with_next([=](QSize size, int width) {
|
||||
_startsIn->move(
|
||||
(size.width() - width) / 2,
|
||||
top() + st::groupCallStartsInTop);
|
||||
}, _startsIn->lifetime());
|
||||
|
||||
rpl::combine(
|
||||
widget()->sizeValue(),
|
||||
_startsWhen->widthValue()
|
||||
) | rpl::start_with_next([=](QSize size, int width) {
|
||||
_startsWhen->move(
|
||||
(size.width() - width) / 2,
|
||||
top() + st::groupCallStartsWhenTop);
|
||||
}, _startsWhen->lifetime());
|
||||
|
||||
rpl::combine(
|
||||
widget()->sizeValue(),
|
||||
_countdown->widthValue()
|
||||
) | rpl::start_with_next([=](QSize size, int width) {
|
||||
_countdown->move(
|
||||
(size.width() - width) / 2,
|
||||
top() + st::groupCallCountdownTop);
|
||||
}, _startsWhen->lifetime());
|
||||
}
|
||||
|
||||
void Panel::setupMembers() {
|
||||
Expects(!_members);
|
||||
if (_members) {
|
||||
return;
|
||||
}
|
||||
|
||||
_startsIn.destroy();
|
||||
_countdown.destroy();
|
||||
_startsWhen.destroy();
|
||||
|
||||
_members.create(widget(), _call);
|
||||
|
||||
|
@ -38,6 +38,7 @@ class Window;
|
||||
class ScrollArea;
|
||||
class GenericBox;
|
||||
class LayerManager;
|
||||
class GroupCallScheduledLeft;
|
||||
namespace Platform {
|
||||
class TitleControls;
|
||||
} // namespace Platform
|
||||
@ -75,6 +76,7 @@ private:
|
||||
void initControls();
|
||||
void initLayout();
|
||||
void initGeometry();
|
||||
void setupScheduledLabels(rpl::producer<TimeId> date);
|
||||
void setupMembers();
|
||||
void setupJoinAsChangedToasts();
|
||||
void setupTitleChangedToasts();
|
||||
@ -124,6 +126,7 @@ private:
|
||||
object_ptr<Members> _members = { nullptr };
|
||||
object_ptr<Ui::FlatLabel> _startsIn = { nullptr };
|
||||
object_ptr<Ui::RpWidget> _countdown = { nullptr };
|
||||
std::shared_ptr<Ui::GroupCallScheduledLeft> _countdownData;
|
||||
object_ptr<Ui::FlatLabel> _startsWhen = { nullptr };
|
||||
ChooseJoinAsProcess _joinAsProcess;
|
||||
|
||||
|
@ -72,17 +72,6 @@ constexpr auto kPinnedMessageTextLimit = 16;
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<bool> PeerHasThisCall(
|
||||
not_null<PeerData*> peer,
|
||||
uint64 id) {
|
||||
const auto call = peer->groupCall();
|
||||
return call
|
||||
? std::make_optional(call->id() == id)
|
||||
: PeerCallKnown(peer)
|
||||
? std::make_optional(false)
|
||||
: std::nullopt;
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64 CallIdFromInput(const MTPInputGroupCall &data) {
|
||||
return data.match([&](const MTPDinputGroupCall &data) {
|
||||
return data.vid().v;
|
||||
@ -348,14 +337,30 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) {
|
||||
|
||||
auto prepareGroupCall = [this](const MTPDmessageActionGroupCall &action) {
|
||||
if (const auto duration = action.vduration()) {
|
||||
return prepareDiscardedCallText(duration->v);
|
||||
const auto seconds = duration->v;
|
||||
const auto days = seconds / 86400;
|
||||
const auto hours = seconds / 3600;
|
||||
const auto minutes = seconds / 60;
|
||||
auto text = (days > 1)
|
||||
? tr::lng_group_call_duration_days(tr::now, lt_count, days)
|
||||
: (hours > 1)
|
||||
? tr::lng_group_call_duration_hours(tr::now, lt_count, hours)
|
||||
: (minutes > 1)
|
||||
? tr::lng_group_call_duration_minutes(tr::now, lt_count, minutes)
|
||||
: tr::lng_group_call_duration_seconds(tr::now, lt_count, seconds);
|
||||
return PreparedText{ tr::lng_action_group_call_finished(tr::now, lt_duration, text) };
|
||||
}
|
||||
const auto callId = CallIdFromInput(action.vcall());
|
||||
const auto peer = history()->peer;
|
||||
const auto linkCallId = PeerHasThisCall(peer, callId).value_or(false)
|
||||
? callId
|
||||
: 0;
|
||||
return prepareStartedCallText(linkCallId);
|
||||
auto result = PreparedText{};
|
||||
if (history()->peer->isBroadcast()) {
|
||||
result.text = tr::lng_action_group_call_started_channel(tr::now);
|
||||
} else {
|
||||
result.links.push_back(fromLink());
|
||||
result.text = tr::lng_action_group_call_started_group(
|
||||
tr::now,
|
||||
lt_from,
|
||||
fromLinkText());
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto prepareInviteToGroupCall = [this](const MTPDmessageActionInviteToGroupCall &action) {
|
||||
@ -406,12 +411,17 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) {
|
||||
};
|
||||
|
||||
auto prepareGroupCallScheduled = [this](const MTPDmessageActionGroupCallScheduled &action) {
|
||||
const auto callId = CallIdFromInput(action.vcall());
|
||||
const auto peer = history()->peer;
|
||||
const auto linkCallId = PeerHasThisCall(peer, callId).value_or(false)
|
||||
? callId
|
||||
: 0;
|
||||
return prepareStartedCallText(linkCallId);
|
||||
auto result = PreparedText{};
|
||||
if (history()->peer->isBroadcast()) {
|
||||
result.text = tr::lng_action_group_call_scheduled_channel(tr::now);
|
||||
} else {
|
||||
result.links.push_back(fromLink());
|
||||
result.text = tr::lng_action_group_call_scheduled_group(
|
||||
tr::now,
|
||||
lt_from,
|
||||
fromLinkText());
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const auto messageText = action.match([&](
|
||||
@ -577,41 +587,6 @@ bool HistoryService::updateDependent(bool force) {
|
||||
return (dependent->msg || !dependent->msgId);
|
||||
}
|
||||
|
||||
HistoryService::PreparedText HistoryService::prepareDiscardedCallText(
|
||||
int duration) {
|
||||
const auto seconds = duration;
|
||||
const auto days = seconds / 86400;
|
||||
const auto hours = seconds / 3600;
|
||||
const auto minutes = seconds / 60;
|
||||
auto text = (days > 1)
|
||||
? tr::lng_group_call_duration_days(tr::now, lt_count, days)
|
||||
: (hours > 1)
|
||||
? tr::lng_group_call_duration_hours(tr::now, lt_count, hours)
|
||||
: (minutes > 1)
|
||||
? tr::lng_group_call_duration_minutes(tr::now, lt_count, minutes)
|
||||
: tr::lng_group_call_duration_seconds(tr::now, lt_count, seconds);
|
||||
return PreparedText{ tr::lng_action_group_call_finished(tr::now, lt_duration, text) };
|
||||
}
|
||||
|
||||
HistoryService::PreparedText HistoryService::prepareStartedCallText(
|
||||
uint64 linkCallId) {
|
||||
auto result = PreparedText{};
|
||||
result.links.push_back(fromLink());
|
||||
auto chatText = tr::lng_action_group_call_started_chat(tr::now);
|
||||
if (linkCallId) {
|
||||
const auto peer = history()->peer;
|
||||
result.links.push_back(GroupCallClickHandler(peer, linkCallId));
|
||||
chatText = textcmdLink(2, chatText);
|
||||
}
|
||||
result.text = tr::lng_action_group_call_started(
|
||||
tr::now,
|
||||
lt_from,
|
||||
fromLinkText(),
|
||||
lt_chat,
|
||||
chatText);
|
||||
return result;
|
||||
}
|
||||
|
||||
HistoryService::PreparedText HistoryService::prepareInvitedToCallText(
|
||||
const QVector<MTPint> &users,
|
||||
uint64 linkCallId) {
|
||||
@ -973,11 +948,12 @@ void HistoryService::createFromMtp(const MTPDmessage &message) {
|
||||
}
|
||||
|
||||
void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
||||
if (message.vaction().type() == mtpc_messageActionGameScore) {
|
||||
const auto type = message.vaction().type();
|
||||
if (type == mtpc_messageActionGameScore) {
|
||||
const auto &data = message.vaction().c_messageActionGameScore();
|
||||
UpdateComponents(HistoryServiceGameScore::Bit());
|
||||
Get<HistoryServiceGameScore>()->score = data.vscore().v;
|
||||
} else if (message.vaction().type() == mtpc_messageActionPaymentSent) {
|
||||
} else if (type == mtpc_messageActionPaymentSent) {
|
||||
const auto &data = message.vaction().c_messageActionPaymentSent();
|
||||
UpdateComponents(HistoryServicePayment::Bit());
|
||||
const auto amount = data.vtotal_amount().v;
|
||||
@ -998,36 +974,24 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
||||
crl::guard(weak, [=] { weak->window().activate(); }));
|
||||
}
|
||||
});
|
||||
} else if (message.vaction().type() == mtpc_messageActionGroupCall) {
|
||||
const auto &data = message.vaction().c_messageActionGroupCall();
|
||||
if (data.vduration()) {
|
||||
} else if (type == mtpc_messageActionGroupCall
|
||||
|| type == mtpc_messageActionGroupCallScheduled) {
|
||||
const auto started = (type == mtpc_messageActionGroupCall);
|
||||
const auto &callData = started
|
||||
? message.vaction().c_messageActionGroupCall().vcall()
|
||||
: message.vaction().c_messageActionGroupCallScheduled().vcall();
|
||||
const auto duration = started
|
||||
? message.vaction().c_messageActionGroupCall().vduration()
|
||||
: tl::conditional<MTPint>();
|
||||
if (duration) {
|
||||
RemoveComponents(HistoryServiceOngoingCall::Bit());
|
||||
} else {
|
||||
UpdateComponents(HistoryServiceOngoingCall::Bit());
|
||||
const auto call = Get<HistoryServiceOngoingCall>();
|
||||
const auto id = CallIdFromInput(data.vcall());
|
||||
call->lifetime.destroy();
|
||||
|
||||
const auto peer = history()->peer;
|
||||
const auto has = PeerHasThisCall(peer, id);
|
||||
if (!has.has_value()) {
|
||||
PeerHasThisCallValue(
|
||||
peer,
|
||||
id
|
||||
) | rpl::start_with_next([=](bool has) {
|
||||
updateText(prepareStartedCallText(has ? id : 0));
|
||||
}, call->lifetime);
|
||||
} else if (*has) {
|
||||
PeerHasThisCallValue(
|
||||
peer,
|
||||
id
|
||||
) | rpl::skip(1) | rpl::start_with_next([=](bool has) {
|
||||
Assert(!has);
|
||||
updateText(prepareStartedCallText(0));
|
||||
}, call->lifetime);
|
||||
}
|
||||
call->id = CallIdFromInput(callData);
|
||||
call->link = GroupCallClickHandler(history()->peer, call->id);
|
||||
}
|
||||
} else if (message.vaction().type() == mtpc_messageActionInviteToGroupCall) {
|
||||
} else if (type == mtpc_messageActionInviteToGroupCall) {
|
||||
const auto &data = message.vaction().c_messageActionInviteToGroupCall();
|
||||
const auto id = CallIdFromInput(data.vcall());
|
||||
const auto peer = history()->peer;
|
||||
@ -1044,6 +1008,7 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
||||
} else {
|
||||
UpdateComponents(HistoryServiceOngoingCall::Bit());
|
||||
const auto call = Get<HistoryServiceOngoingCall>();
|
||||
call->id = id;
|
||||
call->lifetime.destroy();
|
||||
|
||||
const auto users = data.vusers().v;
|
||||
@ -1207,3 +1172,14 @@ not_null<HistoryService*> GenerateJoinedMessage(
|
||||
GenerateJoinedText(history, inviter),
|
||||
flags);
|
||||
}
|
||||
|
||||
std::optional<bool> PeerHasThisCall(
|
||||
not_null<PeerData*> peer,
|
||||
uint64 id) {
|
||||
const auto call = peer->groupCall();
|
||||
return call
|
||||
? std::make_optional(call->id() == id)
|
||||
: PeerCallKnown(peer)
|
||||
? std::make_optional(false)
|
||||
: std::nullopt;
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ struct HistoryServiceSelfDestruct
|
||||
struct HistoryServiceOngoingCall
|
||||
: public RuntimeComponent<HistoryServiceOngoingCall, HistoryItem> {
|
||||
uint64 id = 0;
|
||||
ClickHandlerPtr link;
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
@ -160,8 +161,6 @@ private:
|
||||
PreparedText preparePinnedText();
|
||||
PreparedText prepareGameScoreText();
|
||||
PreparedText preparePaymentSentText();
|
||||
PreparedText prepareDiscardedCallText(int duration);
|
||||
PreparedText prepareStartedCallText(uint64 linkCallId);
|
||||
PreparedText prepareInvitedToCallText(
|
||||
const QVector<MTPint> &users,
|
||||
uint64 linkCallId);
|
||||
@ -170,8 +169,11 @@ private:
|
||||
|
||||
};
|
||||
|
||||
not_null<HistoryService*> GenerateJoinedMessage(
|
||||
[[nodiscard]] not_null<HistoryService*> GenerateJoinedMessage(
|
||||
not_null<History*> history,
|
||||
TimeId inviteDate,
|
||||
not_null<UserData*> inviter,
|
||||
MTPDmessage::Flags flags);
|
||||
[[nodiscard]] std::optional<bool> PeerHasThisCall(
|
||||
not_null<PeerData*> peer,
|
||||
uint64 id);
|
||||
|
@ -513,17 +513,18 @@ TextState Service::textState(QPoint point, StateRequest request) const {
|
||||
point - trect.topLeft(),
|
||||
trect.width(),
|
||||
textRequest));
|
||||
if (auto gamescore = item->Get<HistoryServiceGameScore>()) {
|
||||
if (!result.link
|
||||
&& result.cursor == CursorState::Text
|
||||
&& g.contains(point)) {
|
||||
if (!result.link
|
||||
&& result.cursor == CursorState::Text
|
||||
&& g.contains(point)) {
|
||||
if (const auto gamescore = item->Get<HistoryServiceGameScore>()) {
|
||||
result.link = gamescore->lnk;
|
||||
}
|
||||
} else if (auto payment = item->Get<HistoryServicePayment>()) {
|
||||
if (!result.link
|
||||
&& result.cursor == CursorState::Text
|
||||
&& g.contains(point)) {
|
||||
} else if (const auto payment = item->Get<HistoryServicePayment>()) {
|
||||
result.link = payment->invoiceLink;
|
||||
} else if (const auto call = item->Get<HistoryServiceOngoingCall>()) {
|
||||
const auto peer = history()->peer;
|
||||
if (PeerHasThisCall(peer, call->id).value_or(false)) {
|
||||
result.link = call->link;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (media) {
|
||||
|
@ -152,10 +152,10 @@ void GroupCallBar::refreshOpenBrush() {
|
||||
if (_openBrushForWidth == width) {
|
||||
return;
|
||||
}
|
||||
auto gradient = QLinearGradient(QPoint(width, 0), QPoint(-width, 0));
|
||||
auto gradient = QLinearGradient(QPoint(width, 0), QPoint(0, 0));
|
||||
gradient.setStops(QGradientStops{
|
||||
{ 0.0, st::groupCallForceMutedBar1->c },
|
||||
{ .35, st::groupCallForceMutedBar2->c },
|
||||
{ .7, st::groupCallForceMutedBar2->c },
|
||||
{ 1.0, st::groupCallForceMutedBar3->c }
|
||||
});
|
||||
_openBrushOverride = QBrush(std::move(gradient));
|
||||
@ -169,6 +169,7 @@ void GroupCallBar::refreshScheduledProcess() {
|
||||
if (_scheduledProcess) {
|
||||
_scheduledProcess = nullptr;
|
||||
_open = nullptr;
|
||||
_openBrushForWidth = 0;
|
||||
_join = std::make_unique<RoundButton>(
|
||||
_inner.get(),
|
||||
tr::lng_group_call_join(),
|
||||
|
Loading…
Reference in New Issue
Block a user