mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added list of active group calls to Calls box.
This commit is contained in:
parent
cd032f5c16
commit
37454b4ff4
5 changed files with 248 additions and 1 deletions
|
@ -2694,6 +2694,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_call_box_clear_all" = "Clear All";
|
"lng_call_box_clear_all" = "Clear All";
|
||||||
"lng_call_box_clear_sure" = "Are you sure you want to completely clear your calls log?";
|
"lng_call_box_clear_sure" = "Are you sure you want to completely clear your calls log?";
|
||||||
"lng_call_box_clear_button" = "Clear";
|
"lng_call_box_clear_button" = "Clear";
|
||||||
|
"lng_call_box_groupcalls_subtitle" = "Active video chats";
|
||||||
|
|
||||||
"lng_call_outgoing" = "Outgoing call";
|
"lng_call_outgoing" = "Outgoing call";
|
||||||
"lng_call_video_outgoing" = "Outgoing video call";
|
"lng_call_video_outgoing" = "Outgoing video call";
|
||||||
|
|
|
@ -369,6 +369,10 @@ callCameraReDial: IconButton(callReDial) {
|
||||||
icon: icon {{ "calls/call_camera_active", menuIconFg }};
|
icon: icon {{ "calls/call_camera_active", menuIconFg }};
|
||||||
iconOver: icon {{ "calls/call_camera_active", menuIconFgOver }};
|
iconOver: icon {{ "calls/call_camera_active", menuIconFgOver }};
|
||||||
}
|
}
|
||||||
|
callGroupCall: IconButton(callCameraReDial) {
|
||||||
|
icon: icon {{ "top_bar_group_call", menuIconFg }};
|
||||||
|
iconOver: icon {{ "top_bar_group_call", menuIconFgOver }};
|
||||||
|
}
|
||||||
|
|
||||||
callRatingPadding: margins(24px, 12px, 24px, 0px);
|
callRatingPadding: margins(24px, 12px, 24px, 0px);
|
||||||
callRatingStar: IconButton {
|
callRatingStar: IconButton {
|
||||||
|
|
|
@ -25,6 +25,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
#include "data/data_media_types.h"
|
#include "data/data_media_types.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
|
#include "data/data_peer_values.h" // Data::ChannelHasActiveCall.
|
||||||
|
#include "data/data_group_call.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
#include "boxes/delete_messages_box.h"
|
#include "boxes/delete_messages_box.h"
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "api/api_updates.h"
|
#include "api/api_updates.h"
|
||||||
|
@ -40,8 +43,201 @@ namespace {
|
||||||
constexpr auto kFirstPageCount = 20;
|
constexpr auto kFirstPageCount = 20;
|
||||||
constexpr auto kPerPageCount = 100;
|
constexpr auto kPerPageCount = 100;
|
||||||
|
|
||||||
|
class GroupCallRow final : public PeerListRow {
|
||||||
|
public:
|
||||||
|
GroupCallRow(not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
void rightActionAddRipple(
|
||||||
|
QPoint point,
|
||||||
|
Fn<void()> updateCallback) override;
|
||||||
|
void rightActionStopLastRipple() override;
|
||||||
|
|
||||||
|
int paintNameIconGetWidth(
|
||||||
|
Painter &p,
|
||||||
|
Fn<void()> repaint,
|
||||||
|
crl::time now,
|
||||||
|
int nameLeft,
|
||||||
|
int nameTop,
|
||||||
|
int nameWidth,
|
||||||
|
int availableWidth,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
QSize rightActionSize() const override {
|
||||||
|
return peer()->isChannel() ? QSize(_st.width, _st.height) : QSize();
|
||||||
|
}
|
||||||
|
QMargins rightActionMargins() const override {
|
||||||
|
return QMargins(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
st::defaultPeerListItem.photoPosition.x(),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
void rightActionPaint(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
bool actionSelected) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const style::IconButton &_st;
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> _actionRipple;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GroupCallRow::GroupCallRow(not_null<PeerData*> peer)
|
||||||
|
: PeerListRow(peer)
|
||||||
|
, _st(st::callGroupCall) {
|
||||||
|
if (const auto channel = peer->asChannel()) {
|
||||||
|
const auto status = (channel->isMegagroup()
|
||||||
|
? (channel->isPublic()
|
||||||
|
? tr::lng_create_public_channel_title
|
||||||
|
: tr::lng_create_private_channel_title)
|
||||||
|
: (channel->isPublic()
|
||||||
|
? tr::lng_create_public_group_title
|
||||||
|
: tr::lng_create_private_group_title))(tr::now);
|
||||||
|
setCustomStatus(status.toLower());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupCallRow::rightActionPaint(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
bool actionSelected) {
|
||||||
|
auto size = rightActionSize();
|
||||||
|
if (_actionRipple) {
|
||||||
|
_actionRipple->paint(
|
||||||
|
p,
|
||||||
|
x + _st.rippleAreaPosition.x(),
|
||||||
|
y + _st.rippleAreaPosition.y(),
|
||||||
|
outerWidth);
|
||||||
|
if (_actionRipple->empty()) {
|
||||||
|
_actionRipple.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_st.icon.paintInCenter(
|
||||||
|
p,
|
||||||
|
style::rtlrect(x, y, size.width(), size.height(), outerWidth));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupCallRow::rightActionAddRipple(
|
||||||
|
QPoint point,
|
||||||
|
Fn<void()> updateCallback) {
|
||||||
|
if (!_actionRipple) {
|
||||||
|
auto mask = Ui::RippleAnimation::EllipseMask(
|
||||||
|
QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||||
|
_actionRipple = std::make_unique<Ui::RippleAnimation>(
|
||||||
|
_st.ripple,
|
||||||
|
std::move(mask),
|
||||||
|
std::move(updateCallback));
|
||||||
|
}
|
||||||
|
_actionRipple->add(point - _st.rippleAreaPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupCallRow::rightActionStopLastRipple() {
|
||||||
|
if (_actionRipple) {
|
||||||
|
_actionRipple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace GroupCalls {
|
||||||
|
|
||||||
|
ListController::ListController(not_null<Window::SessionController*> window)
|
||||||
|
: _window(window) {
|
||||||
|
setStyleOverrides(&st::peerListSingleRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
Main::Session &ListController::session() const {
|
||||||
|
return _window->session();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListController::prepare() {
|
||||||
|
const auto removeRow = [=](not_null<PeerData*> peer) {
|
||||||
|
const auto it = _groupCalls.find(peer->id);
|
||||||
|
if (it != end(_groupCalls)) {
|
||||||
|
const auto &row = it->second;
|
||||||
|
delegate()->peerListRemoveRow(row);
|
||||||
|
_groupCalls.erase(it);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto createRow = [=](not_null<PeerData*> peer) {
|
||||||
|
const auto it = _groupCalls.find(peer->id);
|
||||||
|
if (it == end(_groupCalls)) {
|
||||||
|
auto row = std::make_unique<GroupCallRow>(peer);
|
||||||
|
_groupCalls.emplace(peer->id, row.get());
|
||||||
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto processPeer = [=](PeerData *peer) {
|
||||||
|
if (!peer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto channel = peer->asChannel();
|
||||||
|
if (channel && Data::ChannelHasActiveCall(channel)) {
|
||||||
|
createRow(peer);
|
||||||
|
} else {
|
||||||
|
removeRow(peer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto finishProcess = [=] {
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
|
_fullCount = delegate()->peerListFullRowsCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
session().changes().peerUpdates(
|
||||||
|
Data::PeerUpdate::Flag::GroupCall
|
||||||
|
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||||
|
processPeer(update.peer);
|
||||||
|
finishProcess();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
{
|
||||||
|
auto count = 0;
|
||||||
|
const auto list = session().data().chatsList(nullptr);
|
||||||
|
for (const auto &key : list->pinned()->order()) {
|
||||||
|
processPeer(key.peer());
|
||||||
|
}
|
||||||
|
for (const auto &key : list->indexed()->all()) {
|
||||||
|
if (count > kFirstPageCount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
processPeer(key->key().peer());
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
finishProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> ListController::shownValue() const {
|
||||||
|
return _fullCount.value(
|
||||||
|
) | rpl::map(rpl::mappers::_1 > 0) | rpl::distinct_until_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
const auto window = _window;
|
||||||
|
const auto peer = row->peer();
|
||||||
|
crl::on_main(window, [=, peer = row->peer()] {
|
||||||
|
window->showPeerHistory(
|
||||||
|
peer,
|
||||||
|
Window::SectionShow::Way::ClearStack);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListController::rowRightActionClicked(not_null<PeerListRow*> row) {
|
||||||
|
_window->startOrJoinGroupCall(row->peer());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace GroupCalls
|
||||||
|
|
||||||
class BoxController::Row : public PeerListRow {
|
class BoxController::Row : public PeerListRow {
|
||||||
public:
|
public:
|
||||||
Row(not_null<HistoryItem*> item);
|
Row(not_null<HistoryItem*> item);
|
||||||
|
|
|
@ -15,6 +15,27 @@ class SessionController;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
namespace Calls {
|
namespace Calls {
|
||||||
|
namespace GroupCalls {
|
||||||
|
|
||||||
|
class ListController : public PeerListController {
|
||||||
|
public:
|
||||||
|
explicit ListController(not_null<Window::SessionController*> window);
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<bool> shownValue() const;
|
||||||
|
|
||||||
|
Main::Session &session() const override;
|
||||||
|
void prepare() override;
|
||||||
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
void rowRightActionClicked(not_null<PeerListRow*> row) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const not_null<Window::SessionController*> _window;
|
||||||
|
base::flat_map<PeerId, not_null<PeerListRow*>> _groupCalls;
|
||||||
|
rpl::variable<int> _fullCount;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace GroupCalls
|
||||||
|
|
||||||
class BoxController : public PeerListController {
|
class BoxController : public PeerListController {
|
||||||
public:
|
public:
|
||||||
|
@ -34,6 +55,7 @@ private:
|
||||||
void receivedCalls(const QVector<MTPMessage> &result);
|
void receivedCalls(const QVector<MTPMessage> &result);
|
||||||
void refreshAbout();
|
void refreshAbout();
|
||||||
|
|
||||||
|
class GroupCallRow;
|
||||||
class Row;
|
class Row;
|
||||||
Row *rowForItem(not_null<const HistoryItem*> item);
|
Row *rowForItem(not_null<const HistoryItem*> item);
|
||||||
|
|
||||||
|
|
|
@ -96,16 +96,40 @@ constexpr auto kPlayStatusLimit = 2;
|
||||||
void ShowCallsBox(not_null<Window::SessionController*> window) {
|
void ShowCallsBox(not_null<Window::SessionController*> window) {
|
||||||
struct State {
|
struct State {
|
||||||
State(not_null<Window::SessionController*> window)
|
State(not_null<Window::SessionController*> window)
|
||||||
: callsController(window) {
|
: callsController(window)
|
||||||
|
, groupCallsController(window) {
|
||||||
}
|
}
|
||||||
Calls::BoxController callsController;
|
Calls::BoxController callsController;
|
||||||
PeerListContentDelegateSimple callsDelegate;
|
PeerListContentDelegateSimple callsDelegate;
|
||||||
|
|
||||||
|
Calls::GroupCalls::ListController groupCallsController;
|
||||||
|
PeerListContentDelegateSimple groupCallsDelegate;
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> menu;
|
base::unique_qptr<Ui::PopupMenu> menu;
|
||||||
};
|
};
|
||||||
|
|
||||||
window->show(Box([=](not_null<Ui::GenericBox*> box) {
|
window->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||||
const auto state = box->lifetime().make_state<State>(window);
|
const auto state = box->lifetime().make_state<State>(window);
|
||||||
|
|
||||||
|
const auto groupCalls = box->addRow(
|
||||||
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
box,
|
||||||
|
object_ptr<Ui::VerticalLayout>(box)),
|
||||||
|
{});
|
||||||
|
groupCalls->hide(anim::type::instant);
|
||||||
|
groupCalls->toggleOn(state->groupCallsController.shownValue());
|
||||||
|
|
||||||
|
Settings::AddSubsectionTitle(
|
||||||
|
groupCalls->entity(),
|
||||||
|
tr::lng_call_box_groupcalls_subtitle());
|
||||||
|
state->groupCallsDelegate.setContent(groupCalls->entity()->add(
|
||||||
|
object_ptr<PeerListContent>(box, &state->groupCallsController),
|
||||||
|
{}));
|
||||||
|
state->groupCallsController.setDelegate(&state->groupCallsDelegate);
|
||||||
|
Settings::AddSkip(groupCalls->entity());
|
||||||
|
Settings::AddDivider(groupCalls->entity());
|
||||||
|
Settings::AddSkip(groupCalls->entity());
|
||||||
|
|
||||||
const auto content = box->addRow(
|
const auto content = box->addRow(
|
||||||
object_ptr<PeerListContent>(box, &state->callsController),
|
object_ptr<PeerListContent>(box, &state->callsController),
|
||||||
{});
|
{});
|
||||||
|
|
Loading…
Add table
Reference in a new issue