mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Hide member rows with active small videos.
This commit is contained in:
parent
8a693bc932
commit
38506d27a1
14 changed files with 359 additions and 85 deletions
|
@ -776,6 +776,10 @@ void PeerListContent::appendRow(std::unique_ptr<PeerListRow> row) {
|
|||
if (_rowsById.find(row->id()) == _rowsById.cend()) {
|
||||
row->setAbsoluteIndex(_rows.size());
|
||||
addRowEntry(row.get());
|
||||
if (!_hiddenRows.empty()) {
|
||||
Assert(!row->hidden());
|
||||
_filterResults.push_back(row.get());
|
||||
}
|
||||
_rows.push_back(std::move(row));
|
||||
}
|
||||
}
|
||||
|
@ -813,6 +817,17 @@ void PeerListContent::changeCheckState(
|
|||
[=] { updateRow(row); });
|
||||
}
|
||||
|
||||
void PeerListContent::setRowHidden(not_null<PeerListRow*> row, bool hidden) {
|
||||
Expects(!row->isSearchResult());
|
||||
|
||||
row->setHidden(hidden);
|
||||
if (hidden) {
|
||||
_hiddenRows.emplace(row);
|
||||
} else {
|
||||
_hiddenRows.remove(row);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListContent::addRowEntry(not_null<PeerListRow*> row) {
|
||||
if (_controller->respectSavedMessagesChat() && !row->special()) {
|
||||
if (row->peer()->isSelf()) {
|
||||
|
@ -879,6 +894,10 @@ void PeerListContent::prependRow(std::unique_ptr<PeerListRow> row) {
|
|||
|
||||
if (_rowsById.find(row->id()) == _rowsById.cend()) {
|
||||
addRowEntry(row.get());
|
||||
if (!_hiddenRows.empty()) {
|
||||
Assert(!row->hidden());
|
||||
_filterResults.insert(_filterResults.begin(), row.get());
|
||||
}
|
||||
_rows.insert(_rows.begin(), std::move(row));
|
||||
refreshIndices();
|
||||
}
|
||||
|
@ -894,6 +913,10 @@ void PeerListContent::prependRowFromSearchResult(not_null<PeerListRow*> row) {
|
|||
Assert(_searchRows[index].get() == row);
|
||||
|
||||
row->setIsSearchResult(false);
|
||||
if (!_hiddenRows.empty()) {
|
||||
Assert(!row->hidden());
|
||||
_filterResults.insert(_filterResults.begin(), row);
|
||||
}
|
||||
_rows.insert(_rows.begin(), std::move(_searchRows[index]));
|
||||
refreshIndices();
|
||||
removeRowAtIndex(_searchRows, index);
|
||||
|
@ -947,6 +970,7 @@ void PeerListContent::removeRow(not_null<PeerListRow*> row) {
|
|||
_filterResults.erase(
|
||||
ranges::remove(_filterResults, row),
|
||||
end(_filterResults));
|
||||
_hiddenRows.remove(row);
|
||||
removeRowAtIndex(eraseFrom, index);
|
||||
|
||||
restoreSelection();
|
||||
|
@ -984,7 +1008,9 @@ void PeerListContent::convertRowToSearchResult(not_null<PeerListRow*> row) {
|
|||
|
||||
removeFromSearchIndex(row);
|
||||
row->setIsSearchResult(true);
|
||||
row->setHidden(false);
|
||||
row->setAbsoluteIndex(_searchRows.size());
|
||||
_hiddenRows.remove(row);
|
||||
_searchRows.push_back(std::move(_rows[index]));
|
||||
removeRowAtIndex(_rows, index);
|
||||
}
|
||||
|
@ -1069,6 +1095,14 @@ int PeerListContent::labelHeight() const {
|
|||
}
|
||||
|
||||
void PeerListContent::refreshRows() {
|
||||
if (!_hiddenRows.empty()) {
|
||||
_filterResults.clear();
|
||||
for (const auto &row : _rows) {
|
||||
if (!row->hidden()) {
|
||||
_filterResults.push_back(row.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
resizeToWidth(width());
|
||||
if (_visibleBottom > 0) {
|
||||
checkScrollForPreload();
|
||||
|
@ -1082,7 +1116,7 @@ void PeerListContent::refreshRows() {
|
|||
void PeerListContent::setSearchMode(PeerListSearchMode mode) {
|
||||
if (_searchMode != mode) {
|
||||
if (!addingToSearchIndex()) {
|
||||
for_const (auto &row, _rows) {
|
||||
for (const auto &row : _rows) {
|
||||
addToSearchIndex(row.get());
|
||||
}
|
||||
}
|
||||
|
@ -1284,13 +1318,22 @@ void PeerListContent::mousePressReleased(Qt::MouseButton button) {
|
|||
|
||||
void PeerListContent::showRowMenu(
|
||||
not_null<PeerListRow*> row,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed) {
|
||||
showRowMenu(findRowIndex(row), QCursor::pos(), std::move(destroyed));
|
||||
const auto index = findRowIndex(row);
|
||||
showRowMenu(
|
||||
index,
|
||||
row,
|
||||
QCursor::pos(),
|
||||
highlightRow,
|
||||
std::move(destroyed));
|
||||
}
|
||||
|
||||
bool PeerListContent::showRowMenu(
|
||||
RowIndex index,
|
||||
PeerListRow *row,
|
||||
QPoint globalPos,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed) {
|
||||
if (_contextMenu) {
|
||||
_contextMenu->setDestroyedCallback(nullptr);
|
||||
|
@ -1301,7 +1344,9 @@ bool PeerListContent::showRowMenu(
|
|||
mousePressReleased(_pressButton);
|
||||
}
|
||||
|
||||
const auto row = getRow(index);
|
||||
if (highlightRow) {
|
||||
row = getRow(index);
|
||||
}
|
||||
if (!row) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1312,11 +1357,15 @@ bool PeerListContent::showRowMenu(
|
|||
return false;
|
||||
}
|
||||
|
||||
setContexted({ index, false });
|
||||
if (highlightRow) {
|
||||
setContexted({ index, false });
|
||||
}
|
||||
raw->setDestroyedCallback(crl::guard(
|
||||
this,
|
||||
[=] {
|
||||
setContexted(Selected());
|
||||
if (highlightRow) {
|
||||
setContexted(Selected());
|
||||
}
|
||||
handleMouseMove(QCursor::pos());
|
||||
if (destroyed) {
|
||||
destroyed(raw);
|
||||
|
@ -1330,7 +1379,7 @@ void PeerListContent::contextMenuEvent(QContextMenuEvent *e) {
|
|||
if (e->reason() == QContextMenuEvent::Mouse) {
|
||||
handleMouseMove(e->globalPos());
|
||||
}
|
||||
if (showRowMenu(_selected.index, e->globalPos())) {
|
||||
if (showRowMenu(_selected.index, nullptr, e->globalPos(), true)) {
|
||||
e->accept();
|
||||
}
|
||||
}
|
||||
|
@ -1607,6 +1656,8 @@ void PeerListContent::searchQueryChanged(QString query) {
|
|||
if (_normalizedSearchQuery != normalizedQuery) {
|
||||
setSearchQuery(query, normalizedQuery);
|
||||
if (_controller->searchInLocal() && !searchWordsList.isEmpty()) {
|
||||
Assert(_hiddenRows.empty());
|
||||
|
||||
auto minimalList = (const std::vector<not_null<PeerListRow*>>*)nullptr;
|
||||
for (const auto &searchWord : searchWordsList) {
|
||||
auto searchWordStart = searchWord[0].toLower();
|
||||
|
@ -1656,15 +1707,17 @@ void PeerListContent::searchQueryChanged(QString query) {
|
|||
}
|
||||
|
||||
std::unique_ptr<PeerListState> PeerListContent::saveState() const {
|
||||
Expects(_hiddenRows.empty());
|
||||
|
||||
auto result = std::make_unique<PeerListState>();
|
||||
result->controllerState
|
||||
= std::make_unique<PeerListController::SavedStateBase>();
|
||||
result->list.reserve(_rows.size());
|
||||
for (auto &row : _rows) {
|
||||
for (const auto &row : _rows) {
|
||||
result->list.push_back(row->peer());
|
||||
}
|
||||
result->filterResults.reserve(_filterResults.size());
|
||||
for (auto &row : _filterResults) {
|
||||
for (const auto &row : _filterResults) {
|
||||
result->filterResults.push_back(row->peer());
|
||||
}
|
||||
result->searchQuery = _searchQuery;
|
||||
|
@ -1844,8 +1897,7 @@ void PeerListContent::updateRow(RowIndex index) {
|
|||
if (index.value < 0) {
|
||||
return;
|
||||
}
|
||||
auto row = getRow(index);
|
||||
if (row->disabled()) {
|
||||
if (const auto row = getRow(index); row && row->disabled()) {
|
||||
if (index == _selected.index) {
|
||||
setSelected(Selected());
|
||||
}
|
||||
|
@ -1940,3 +1992,10 @@ PeerListContent::~PeerListContent() {
|
|||
_contextMenu->setDestroyedCallback(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListContentDelegate::peerListShowRowMenu(
|
||||
not_null<PeerListRow*> row,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu *>)> destroyed) {
|
||||
_content->showRowMenu(row, highlightRow, std::move(destroyed));
|
||||
}
|
|
@ -161,7 +161,7 @@ public:
|
|||
template <typename UpdateCallback>
|
||||
void setChecked(
|
||||
bool checked,
|
||||
const style::RoundImageCheckbox &st,
|
||||
const style::RoundImageCheckbox &st,
|
||||
anim::type animated,
|
||||
UpdateCallback callback) {
|
||||
if (checked && !_checkbox) {
|
||||
|
@ -169,6 +169,12 @@ public:
|
|||
}
|
||||
setCheckedInternal(checked, animated);
|
||||
}
|
||||
void setHidden(bool hidden) {
|
||||
_hidden = hidden;
|
||||
}
|
||||
[[nodiscard]] bool hidden() const {
|
||||
return _hidden;
|
||||
}
|
||||
void finishCheckedAnimation();
|
||||
void invalidatePixmapsCache();
|
||||
|
||||
|
@ -237,6 +243,7 @@ private:
|
|||
base::flat_set<QChar> _nameFirstLetters;
|
||||
int _absoluteIndex = -1;
|
||||
State _disabledState = State::Active;
|
||||
bool _hidden = false;
|
||||
bool _initialized : 1;
|
||||
bool _isSearchResult : 1;
|
||||
bool _isSavedMessagesChat : 1;
|
||||
|
@ -274,6 +281,7 @@ public:
|
|||
virtual void peerListConvertRowToSearchResult(not_null<PeerListRow*> row) = 0;
|
||||
virtual bool peerListIsRowChecked(not_null<PeerListRow*> row) = 0;
|
||||
virtual void peerListSetRowChecked(not_null<PeerListRow*> row, bool checked) = 0;
|
||||
virtual void peerListSetRowHidden(not_null<PeerListRow*> row, bool hidden) = 0;
|
||||
virtual void peerListSetForeignRowChecked(
|
||||
not_null<PeerListRow*> row,
|
||||
bool checked,
|
||||
|
@ -304,6 +312,7 @@ public:
|
|||
|
||||
virtual void peerListShowRowMenu(
|
||||
not_null<PeerListRow*> row,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) = 0;
|
||||
virtual int peerListSelectedRowsCount() = 0;
|
||||
virtual std::unique_ptr<PeerListState> peerListSaveState() const = 0;
|
||||
|
@ -577,6 +586,9 @@ public:
|
|||
not_null<PeerListRow*> row,
|
||||
bool checked,
|
||||
anim::type animated);
|
||||
void setRowHidden(
|
||||
not_null<PeerListRow*> row,
|
||||
bool hidden);
|
||||
|
||||
template <typename ReorderCallback>
|
||||
void reorderRows(ReorderCallback &&callback) {
|
||||
|
@ -585,6 +597,9 @@ public:
|
|||
callback(searchEntity.second.begin(), searchEntity.second.end());
|
||||
}
|
||||
refreshIndices();
|
||||
if (!_hiddenRows.empty()) {
|
||||
callback(_filterResults.begin(), _filterResults.end());
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -593,6 +608,7 @@ public:
|
|||
|
||||
void showRowMenu(
|
||||
not_null<PeerListRow*> row,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed);
|
||||
|
||||
auto scrollToRequests() const {
|
||||
|
@ -680,7 +696,9 @@ private:
|
|||
|
||||
bool showRowMenu(
|
||||
RowIndex index,
|
||||
PeerListRow *row,
|
||||
QPoint globalPos,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr);
|
||||
|
||||
crl::time paintRow(Painter &p, crl::time now, RowIndex index);
|
||||
|
@ -691,7 +709,7 @@ private:
|
|||
void removeFromSearchIndex(not_null<PeerListRow*> row);
|
||||
void setSearchQuery(const QString &query, const QString &normalizedQuery);
|
||||
bool showingSearch() const {
|
||||
return !_searchQuery.isEmpty();
|
||||
return !_hiddenRows.empty() || !_searchQuery.isEmpty();
|
||||
}
|
||||
int shownRowsCount() const {
|
||||
return showingSearch() ? _filterResults.size() : _rows.size();
|
||||
|
@ -737,6 +755,7 @@ private:
|
|||
QString _normalizedSearchQuery;
|
||||
QString _mentionHighlight;
|
||||
std::vector<not_null<PeerListRow*>> _filterResults;
|
||||
base::flat_set<not_null<PeerListRow*>> _hiddenRows;
|
||||
|
||||
int _aboveHeight = 0;
|
||||
int _belowHeight = 0;
|
||||
|
@ -801,6 +820,11 @@ public:
|
|||
bool checked) override {
|
||||
_content->changeCheckState(row, checked, anim::type::normal);
|
||||
}
|
||||
void peerListSetRowHidden(
|
||||
not_null<PeerListRow*> row,
|
||||
bool hidden) override {
|
||||
_content->setRowHidden(row, hidden);
|
||||
}
|
||||
void peerListSetForeignRowChecked(
|
||||
not_null<PeerListRow*> row,
|
||||
bool checked,
|
||||
|
@ -871,10 +895,9 @@ public:
|
|||
_content->restoreState(std::move(state));
|
||||
}
|
||||
void peerListShowRowMenu(
|
||||
not_null<PeerListRow*> row,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) override {
|
||||
_content->showRowMenu(row, std::move(destroyed));
|
||||
}
|
||||
not_null<PeerListRow*> row,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) override;
|
||||
|
||||
protected:
|
||||
not_null<PeerListContent*> content() const {
|
||||
|
|
|
@ -533,7 +533,7 @@ void LinksController::rowClicked(not_null<PeerListRow*> row) {
|
|||
}
|
||||
|
||||
void LinksController::rowActionClicked(not_null<PeerListRow*> row) {
|
||||
delegate()->peerListShowRowMenu(row, nullptr);
|
||||
delegate()->peerListShowRowMenu(row, true);
|
||||
}
|
||||
|
||||
base::unique_qptr<Ui::PopupMenu> LinksController::rowContextMenu(
|
||||
|
|
|
@ -446,7 +446,7 @@ void Panel::refreshIncomingGeometry() {
|
|||
to,
|
||||
Qt::KeepAspectRatioByExpanding);
|
||||
|
||||
// If we cut out no more than 0.33 of the original, let's use expanding.
|
||||
// If we cut out no more than 0.25 of the original, let's use expanding.
|
||||
const auto use = ((big.width() * 3 <= to.width() * 4)
|
||||
&& (big.height() * 3 <= to.height() * 4))
|
||||
? big
|
||||
|
|
|
@ -529,11 +529,15 @@ void GroupCall::toggleScreenSharing(std::optional<QString> uniqueId) {
|
|||
}
|
||||
|
||||
bool GroupCall::hasVideoWithFrames() const {
|
||||
return _hasVideoWithFrames.current();
|
||||
return !_shownVideoTracks.empty();
|
||||
}
|
||||
|
||||
rpl::producer<bool> GroupCall::hasVideoWithFramesValue() const {
|
||||
return _hasVideoWithFrames.value();
|
||||
return _videoStreamShownUpdates.events_starting_with(
|
||||
VideoActiveToggle()
|
||||
) | rpl::map([=] {
|
||||
return hasVideoWithFrames();
|
||||
}) | rpl::distinct_until_changed();
|
||||
}
|
||||
|
||||
void GroupCall::setScheduledDate(TimeId date) {
|
||||
|
@ -586,8 +590,16 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
|
|||
? regularEndpoint(data.now->cameraEndpoint())
|
||||
: EmptyString();
|
||||
if (wasCameraEndpoint != nowCameraEndpoint) {
|
||||
markEndpointActive({ peer, nowCameraEndpoint }, true);
|
||||
markEndpointActive({ peer, wasCameraEndpoint }, false);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Camera,
|
||||
peer,
|
||||
nowCameraEndpoint
|
||||
}, true);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Camera,
|
||||
peer,
|
||||
wasCameraEndpoint
|
||||
}, false);
|
||||
}
|
||||
const auto &wasScreenEndpoint = data.was
|
||||
? regularEndpoint(data.was->screenEndpoint())
|
||||
|
@ -596,8 +608,16 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
|
|||
? regularEndpoint(data.now->screenEndpoint())
|
||||
: EmptyString();
|
||||
if (wasScreenEndpoint != nowScreenEndpoint) {
|
||||
markEndpointActive({ peer, nowScreenEndpoint }, true);
|
||||
markEndpointActive({ peer, wasScreenEndpoint }, false);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Screen,
|
||||
peer,
|
||||
nowScreenEndpoint
|
||||
}, true);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Screen,
|
||||
peer,
|
||||
wasScreenEndpoint
|
||||
}, false);
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
|
@ -792,14 +812,22 @@ void GroupCall::setScreenEndpoint(std::string endpoint) {
|
|||
return;
|
||||
}
|
||||
if (!_screenEndpoint.empty()) {
|
||||
markEndpointActive({ _joinAs, _screenEndpoint }, false);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Screen,
|
||||
_joinAs,
|
||||
_screenEndpoint
|
||||
}, false);
|
||||
}
|
||||
_screenEndpoint = std::move(endpoint);
|
||||
if (_screenEndpoint.empty()) {
|
||||
return;
|
||||
}
|
||||
if (isSharingScreen()) {
|
||||
markEndpointActive({ _joinAs, _screenEndpoint }, true);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Screen,
|
||||
_joinAs,
|
||||
_screenEndpoint
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -808,14 +836,22 @@ void GroupCall::setCameraEndpoint(std::string endpoint) {
|
|||
return;
|
||||
}
|
||||
if (!_cameraEndpoint.empty()) {
|
||||
markEndpointActive({ _joinAs, _cameraEndpoint }, false);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Camera,
|
||||
_joinAs,
|
||||
_cameraEndpoint
|
||||
}, false);
|
||||
}
|
||||
_cameraEndpoint = std::move(endpoint);
|
||||
if (_cameraEndpoint.empty()) {
|
||||
return;
|
||||
}
|
||||
if (isSharingCamera()) {
|
||||
markEndpointActive({ _joinAs, _cameraEndpoint }, true);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Camera,
|
||||
_joinAs,
|
||||
_cameraEndpoint
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -848,7 +884,7 @@ void GroupCall::markEndpointActive(VideoEndpoint endpoint, bool active) {
|
|||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
auto hasVideoWithFrames = _hasVideoWithFrames.current();
|
||||
auto shown = false;
|
||||
if (active) {
|
||||
const auto i = _activeVideoTracks.emplace(
|
||||
endpoint,
|
||||
|
@ -862,11 +898,11 @@ void GroupCall::markEndpointActive(VideoEndpoint endpoint, bool active) {
|
|||
track->renderNextFrame(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (!track->frameSize().isEmpty()) {
|
||||
_hasVideoWithFrames = true;
|
||||
markTrackShown(endpoint, true);
|
||||
}
|
||||
}, i->second.lifetime);
|
||||
if (!track->frameSize().isEmpty()) {
|
||||
hasVideoWithFrames = true;
|
||||
shown = true;
|
||||
}
|
||||
addVideoOutput(i->first.id, { track->sink() });
|
||||
} else {
|
||||
|
@ -874,17 +910,17 @@ void GroupCall::markEndpointActive(VideoEndpoint endpoint, bool active) {
|
|||
_videoEndpointPinned = VideoEndpoint();
|
||||
}
|
||||
_activeVideoTracks.erase(i);
|
||||
hasVideoWithFrames = false;
|
||||
for (const auto &[endpoint, track] : _activeVideoTracks) {
|
||||
if (!track.track->frameSize().isEmpty()) {
|
||||
hasVideoWithFrames = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateRequestedVideoChannelsDelayed();
|
||||
_videoStreamActiveUpdates.fire(std::move(endpoint));
|
||||
_hasVideoWithFrames = hasVideoWithFrames;
|
||||
_videoStreamActiveUpdates.fire({ endpoint, active });
|
||||
markTrackShown(endpoint, shown);
|
||||
}
|
||||
|
||||
void GroupCall::markTrackShown(const VideoEndpoint &endpoint, bool shown) {
|
||||
if ((shown && _shownVideoTracks.emplace(endpoint).second)
|
||||
|| (!shown && _shownVideoTracks.remove(endpoint))) {
|
||||
_videoStreamShownUpdates.fire_copy({ endpoint, shown });
|
||||
}
|
||||
}
|
||||
|
||||
void GroupCall::rejoin() {
|
||||
|
@ -1746,7 +1782,11 @@ void GroupCall::ensureOutgoingVideo() {
|
|||
_cameraCapture->setState(tgcalls::VideoState::Inactive);
|
||||
}
|
||||
_isSharingCamera = active;
|
||||
markEndpointActive({ _joinAs, _cameraEndpoint }, active);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Camera,
|
||||
_joinAs,
|
||||
_cameraEndpoint
|
||||
}, active);
|
||||
sendSelfUpdate(SendUpdateType::VideoMuted);
|
||||
applyMeInCallLocally();
|
||||
}, _lifetime);
|
||||
|
@ -1785,7 +1825,11 @@ void GroupCall::ensureOutgoingVideo() {
|
|||
_screenCapture->setState(tgcalls::VideoState::Inactive);
|
||||
}
|
||||
_isSharingScreen = active;
|
||||
markEndpointActive({ _joinAs, _screenEndpoint }, active);
|
||||
markEndpointActive({
|
||||
VideoEndpointType::Screen,
|
||||
_joinAs,
|
||||
_screenEndpoint
|
||||
}, active);
|
||||
_screenJoinState.nextActionPending = true;
|
||||
checkNextJoinAction();
|
||||
}, _lifetime);
|
||||
|
@ -2172,22 +2216,23 @@ void GroupCall::fillActiveVideoEndpoints() {
|
|||
markEndpointActive(std::move(endpoint), true);
|
||||
}
|
||||
};
|
||||
using Type = VideoEndpointType;
|
||||
for (const auto &participant : participants) {
|
||||
const auto camera = participant.cameraEndpoint();
|
||||
if (camera != _cameraEndpoint
|
||||
&& camera != _screenEndpoint
|
||||
&& participant.peer != _joinAs) {
|
||||
feedOne({ participant.peer, camera });
|
||||
feedOne({ Type::Camera, participant.peer, camera });
|
||||
}
|
||||
const auto screen = participant.screenEndpoint();
|
||||
if (screen != _cameraEndpoint
|
||||
&& screen != _screenEndpoint
|
||||
&& participant.peer != _joinAs) {
|
||||
feedOne({ participant.peer, screen });
|
||||
feedOne({ Type::Screen, participant.peer, screen });
|
||||
}
|
||||
}
|
||||
feedOne({ _joinAs, cameraSharingEndpoint() });
|
||||
feedOne({ _joinAs, screenSharingEndpoint() });
|
||||
feedOne({ Type::Camera, _joinAs, cameraSharingEndpoint() });
|
||||
feedOne({ Type::Screen, _joinAs, screenSharingEndpoint() });
|
||||
if (pinned && !pinnedFound) {
|
||||
_videoEndpointPinned = VideoEndpoint();
|
||||
}
|
||||
|
|
|
@ -76,7 +76,13 @@ struct LevelUpdate {
|
|||
bool me = false;
|
||||
};
|
||||
|
||||
enum class VideoEndpointType {
|
||||
Camera,
|
||||
Screen,
|
||||
};
|
||||
|
||||
struct VideoEndpoint {
|
||||
VideoEndpointType type = VideoEndpointType::Camera;
|
||||
PeerData *peer = nullptr;
|
||||
std::string id;
|
||||
|
||||
|
@ -130,6 +136,11 @@ struct VideoPinToggle {
|
|||
bool pinned = false;
|
||||
};
|
||||
|
||||
struct VideoActiveToggle {
|
||||
VideoEndpoint endpoint;
|
||||
bool active = false;
|
||||
};
|
||||
|
||||
struct VideoQualityRequest {
|
||||
VideoEndpoint endpoint;
|
||||
Group::VideoQuality quality = Group::VideoQuality();
|
||||
|
@ -283,9 +294,13 @@ public:
|
|||
return _levelUpdates.events();
|
||||
}
|
||||
[[nodiscard]] auto videoStreamActiveUpdates() const
|
||||
-> rpl::producer<VideoEndpoint> {
|
||||
-> rpl::producer<VideoActiveToggle> {
|
||||
return _videoStreamActiveUpdates.events();
|
||||
}
|
||||
[[nodiscard]] auto videoStreamShownUpdates() const
|
||||
-> rpl::producer<VideoActiveToggle> {
|
||||
return _videoStreamShownUpdates.events();
|
||||
}
|
||||
void pinVideoEndpoint(VideoEndpoint endpoint);
|
||||
void requestVideoQuality(
|
||||
const VideoEndpoint &endpoint,
|
||||
|
@ -317,6 +332,10 @@ public:
|
|||
-> const base::flat_map<VideoEndpoint, VideoTrack> & {
|
||||
return _activeVideoTracks;
|
||||
}
|
||||
[[nodiscard]] auto shownVideoTracks() const
|
||||
-> const base::flat_set<VideoEndpoint> & {
|
||||
return _shownVideoTracks;
|
||||
}
|
||||
[[nodiscard]] rpl::producer<Group::RejoinEvent> rejoinEvents() const {
|
||||
return _rejoinEvents.events();
|
||||
}
|
||||
|
@ -491,6 +510,7 @@ private:
|
|||
void addVideoOutput(const std::string &endpoint, SinkPointer sink);
|
||||
|
||||
void markEndpointActive(VideoEndpoint endpoint, bool active);
|
||||
void markTrackShown(const VideoEndpoint &endpoint, bool shown);
|
||||
|
||||
[[nodiscard]] MTPInputGroupCall inputCall() const;
|
||||
|
||||
|
@ -560,10 +580,11 @@ private:
|
|||
bool _requireARGB32 = true;
|
||||
|
||||
rpl::event_stream<LevelUpdate> _levelUpdates;
|
||||
rpl::event_stream<VideoEndpoint> _videoStreamActiveUpdates;
|
||||
rpl::event_stream<VideoActiveToggle> _videoStreamActiveUpdates;
|
||||
rpl::event_stream<VideoActiveToggle> _videoStreamShownUpdates;
|
||||
base::flat_map<VideoEndpoint, VideoTrack> _activeVideoTracks;
|
||||
base::flat_set<VideoEndpoint> _shownVideoTracks;
|
||||
rpl::variable<VideoEndpoint> _videoEndpointPinned;
|
||||
rpl::variable<bool> _hasVideoWithFrames = false;
|
||||
base::flat_map<uint32, Data::LastSpokeTimes> _lastSpoke;
|
||||
rpl::event_stream<Group::RejoinEvent> _rejoinEvents;
|
||||
rpl::event_stream<> _allowedToSpeakNotifications;
|
||||
|
|
|
@ -171,7 +171,7 @@ private:
|
|||
// not_null<Row*> row,
|
||||
// const std::string &endpoint);
|
||||
bool toggleRowVideo(not_null<PeerListRow*> row);
|
||||
void showRowMenu(not_null<PeerListRow*> row);
|
||||
void showRowMenu(not_null<PeerListRow*> row, bool highlightRow);
|
||||
|
||||
void toggleVideoEndpointActive(
|
||||
const VideoEndpoint &endpoint,
|
||||
|
@ -180,6 +180,11 @@ private:
|
|||
void appendInvitedUsers();
|
||||
void scheduleRaisedHandStatusRemove();
|
||||
|
||||
void hideRowsWithVideoExcept(const VideoEndpoint &pinned);
|
||||
void showAllHiddenRows();
|
||||
void hideRowWithVideo(const VideoEndpoint &endpoint);
|
||||
void showRowWithVideo(const VideoEndpoint &endpoint);
|
||||
|
||||
const not_null<GroupCall*> _call;
|
||||
not_null<PeerData*> _peer;
|
||||
std::string _largeEndpoint;
|
||||
|
@ -412,6 +417,27 @@ void Members::Controller::setupListChangeViewers() {
|
|||
// }
|
||||
//}, _lifetime);
|
||||
|
||||
_call->videoEndpointPinnedValue(
|
||||
) | rpl::start_with_next([=](const VideoEndpoint &pinned) {
|
||||
if (pinned) {
|
||||
hideRowsWithVideoExcept(pinned);
|
||||
} else {
|
||||
showAllHiddenRows();
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
_call->videoStreamShownUpdates(
|
||||
) | rpl::filter([=](const VideoActiveToggle &update) {
|
||||
const auto &pinned = _call->videoEndpointPinned();
|
||||
return pinned && (update.endpoint != pinned);
|
||||
}) | rpl::start_with_next([=](const VideoActiveToggle &update) {
|
||||
if (update.active) {
|
||||
hideRowWithVideo(update.endpoint);
|
||||
} else {
|
||||
showRowWithVideo(update.endpoint);
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
_call->rejoinEvents(
|
||||
) | rpl::start_with_next([=](const Group::RejoinEvent &event) {
|
||||
const auto guard = gsl::finally([&] {
|
||||
|
@ -428,6 +454,59 @@ void Members::Controller::setupListChangeViewers() {
|
|||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Members::Controller::hideRowsWithVideoExcept(
|
||||
const VideoEndpoint &pinned) {
|
||||
auto hidden = false;
|
||||
for (const auto &endpoint : _call->shownVideoTracks()) {
|
||||
if (endpoint != pinned) {
|
||||
if (const auto row = findRow(endpoint.peer)) {
|
||||
delegate()->peerListSetRowHidden(row, true);
|
||||
hidden = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hidden) {
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
}
|
||||
|
||||
void Members::Controller::showAllHiddenRows() {
|
||||
auto shown = false;
|
||||
for (const auto &endpoint : _call->shownVideoTracks()) {
|
||||
if (const auto row = findRow(endpoint.peer)) {
|
||||
delegate()->peerListSetRowHidden(row, false);
|
||||
shown = true;
|
||||
}
|
||||
}
|
||||
if (shown) {
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
}
|
||||
|
||||
void Members::Controller::hideRowWithVideo(const VideoEndpoint &endpoint) {
|
||||
if (const auto row = findRow(endpoint.peer)) {
|
||||
delegate()->peerListSetRowHidden(row, true);
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
}
|
||||
|
||||
void Members::Controller::showRowWithVideo(const VideoEndpoint &endpoint) {
|
||||
const auto peer = endpoint.peer;
|
||||
const auto &pinned = _call->videoEndpointPinned();
|
||||
if (pinned) {
|
||||
for (const auto &endpoint : _call->shownVideoTracks()) {
|
||||
if (endpoint != pinned && endpoint.peer == peer) {
|
||||
// Still hidden with another video.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (const auto row = findRow(endpoint.peer)) {
|
||||
delegate()->peerListSetRowHidden(row, false);
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
}
|
||||
|
||||
void Members::Controller::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||
_fullCount = real->fullCountValue();
|
||||
|
||||
|
@ -463,9 +542,8 @@ void Members::Controller::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
|||
toggleVideoEndpointActive(endpoint, true);
|
||||
}
|
||||
_call->videoStreamActiveUpdates(
|
||||
) | rpl::start_with_next([=](const VideoEndpoint &endpoint) {
|
||||
const auto active = _call->activeVideoTracks().contains(endpoint);
|
||||
toggleVideoEndpointActive(endpoint, active);
|
||||
) | rpl::start_with_next([=](const VideoActiveToggle &update) {
|
||||
toggleVideoEndpointActive(update.endpoint, update.active);
|
||||
}, _lifetime);
|
||||
|
||||
if (_prepared) {
|
||||
|
@ -822,9 +900,8 @@ Main::Session &Members::Controller::session() const {
|
|||
|
||||
void Members::Controller::prepare() {
|
||||
delegate()->peerListSetSearchMode(PeerListSearchMode::Disabled);
|
||||
//delegate()->peerListSetTitle(std::move(title));
|
||||
setDescriptionText(tr::lng_contacts_loading(tr::now));
|
||||
setSearchNoResultsText(tr::lng_blocked_list_not_found(tr::now));
|
||||
setDescription(nullptr);
|
||||
setSearchNoResults(nullptr);
|
||||
|
||||
if (const auto real = _call->lookupReal()) {
|
||||
prepareRows(real);
|
||||
|
@ -1155,7 +1232,7 @@ bool Members::Controller::rowIsNarrow() {
|
|||
}
|
||||
|
||||
void Members::Controller::rowShowContextMenu(not_null<PeerListRow*> row) {
|
||||
showRowMenu(row);
|
||||
showRowMenu(row, false);
|
||||
}
|
||||
|
||||
//void Members::Controller::rowPaintNarrowBackground(
|
||||
|
@ -1253,12 +1330,14 @@ auto Members::Controller::kickParticipantRequests() const
|
|||
|
||||
void Members::Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||
if (!toggleRowVideo(row)) {
|
||||
showRowMenu(row);
|
||||
showRowMenu(row, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Members::Controller::showRowMenu(not_null<PeerListRow*> row) {
|
||||
delegate()->peerListShowRowMenu(row, [=](not_null<Ui::PopupMenu*> menu) {
|
||||
void Members::Controller::showRowMenu(
|
||||
not_null<PeerListRow*> row,
|
||||
bool highlightRow) {
|
||||
const auto cleanup = [=](not_null<Ui::PopupMenu*> menu) {
|
||||
if (!_menu || _menu.get() != menu) {
|
||||
return;
|
||||
}
|
||||
|
@ -1269,7 +1348,8 @@ void Members::Controller::showRowMenu(not_null<PeerListRow*> row) {
|
|||
}
|
||||
}
|
||||
_menu = std::move(saved);
|
||||
});
|
||||
};
|
||||
delegate()->peerListShowRowMenu(row, highlightRow, cleanup);
|
||||
}
|
||||
|
||||
bool Members::Controller::toggleRowVideo(not_null<PeerListRow*> row) {
|
||||
|
@ -1317,7 +1397,7 @@ bool Members::Controller::toggleRowVideo(not_null<PeerListRow*> row) {
|
|||
|
||||
void Members::Controller::rowActionClicked(
|
||||
not_null<PeerListRow*> row) {
|
||||
showRowMenu(row);
|
||||
showRowMenu(row, true);
|
||||
}
|
||||
|
||||
base::unique_qptr<Ui::PopupMenu> Members::Controller::rowContextMenu(
|
||||
|
@ -1414,6 +1494,7 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
|
|||
result->addAction(
|
||||
tr::lng_group_call_context_pin_camera(tr::now),
|
||||
[=] { _call->pinVideoEndpoint(VideoEndpoint{
|
||||
VideoEndpointType::Camera,
|
||||
participantPeer,
|
||||
camera }); });
|
||||
}
|
||||
|
@ -1427,6 +1508,7 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
|
|||
result->addAction(
|
||||
tr::lng_group_call_context_pin_screen(tr::now),
|
||||
[=] { _call->pinVideoEndpoint(VideoEndpoint{
|
||||
VideoEndpointType::Screen,
|
||||
participantPeer,
|
||||
screen }); });
|
||||
}
|
||||
|
@ -1828,7 +1910,7 @@ QRect Members::getInnerGeometry() const {
|
|||
0,
|
||||
-_scroll->scrollTop(),
|
||||
width(),
|
||||
_list->y() + _list->height() + add);
|
||||
_list->y() + _list->height() + _bottomSkip->height() + add);
|
||||
}
|
||||
|
||||
rpl::producer<int> Members::fullCountValue() const {
|
||||
|
@ -1837,18 +1919,38 @@ rpl::producer<int> Members::fullCountValue() const {
|
|||
|
||||
void Members::setupList() {
|
||||
_listController->setStyleOverrides(&st::groupCallMembersList);
|
||||
_topSkip = _layout->add(
|
||||
object_ptr<Ui::FixedHeightWidget>(
|
||||
_layout.get(),
|
||||
st::groupCallMembersTopSkip));
|
||||
_topSkip->paintRequest(
|
||||
) | rpl::start_with_next([=](QRect clip) {
|
||||
QPainter(_topSkip).fillRect(clip, st::groupCallMembersBg);
|
||||
}, _topSkip->lifetime());
|
||||
const auto addSkip = [&] {
|
||||
const auto result = _layout->add(
|
||||
object_ptr<Ui::FixedHeightWidget>(
|
||||
_layout.get(),
|
||||
st::groupCallMembersTopSkip));
|
||||
result->paintRequest(
|
||||
) | rpl::start_with_next([=](QRect clip) {
|
||||
QPainter(result).fillRect(clip, st::groupCallMembersBg);
|
||||
}, result->lifetime());
|
||||
return result;
|
||||
};
|
||||
_topSkip = addSkip();
|
||||
_list = _layout->add(
|
||||
object_ptr<ListWidget>(
|
||||
_layout.get(),
|
||||
_listController.get()));
|
||||
_bottomSkip = addSkip();
|
||||
|
||||
using namespace rpl::mappers;
|
||||
rpl::combine(
|
||||
_list->heightValue() | rpl::map(_1 > 0),
|
||||
_addMemberButton.value() | rpl::map(_1 != nullptr)
|
||||
) | rpl::distinct_until_changed(
|
||||
) | rpl::start_with_next([=](bool hasList, bool hasAddMembers) {
|
||||
_topSkip->resize(
|
||||
_topSkip->width(),
|
||||
hasList ? st::groupCallMembersTopSkip : 0);
|
||||
_bottomSkip->resize(
|
||||
_bottomSkip->width(),
|
||||
(hasList && !hasAddMembers) ? st::groupCallMembersTopSkip : 0);
|
||||
}, _list->lifetime());
|
||||
|
||||
const auto skip = _layout->add(object_ptr<Ui::RpWidget>(_layout.get()));
|
||||
_mode.value(
|
||||
) | rpl::start_with_next([=](PanelMode mode) {
|
||||
|
@ -1997,6 +2099,7 @@ void Members::setupFakeRoundCorners() {
|
|||
const auto bottom = top
|
||||
+ _topSkip->height()
|
||||
+ list.height()
|
||||
+ _bottomSkip->height()
|
||||
+ addMembers
|
||||
- bottomleft->height();
|
||||
topleft->move(left, top);
|
||||
|
|
|
@ -102,6 +102,7 @@ private:
|
|||
rpl::event_stream<> _enlargeVideoClicks;
|
||||
rpl::variable<Ui::RpWidget*> _addMemberButton = nullptr;
|
||||
RpWidget *_topSkip = nullptr;
|
||||
RpWidget *_bottomSkip = nullptr;
|
||||
ListWidget *_list = nullptr;
|
||||
rpl::event_stream<> _addMemberRequests;
|
||||
|
||||
|
|
|
@ -399,7 +399,7 @@ bool MembersRow::paintVideo(
|
|||
// .outer = QSize(sizew, sizeh) * cIntRetinaFactor(),
|
||||
//};
|
||||
//const auto frame = _videoTrackShown->frame(request);
|
||||
//auto copy = frame; // #TODO calls optimize.
|
||||
//auto copy = frame; // TODO calls optimize.
|
||||
//copy.detach();
|
||||
//if (mode == PanelMode::Default) {
|
||||
// Images::prepareCircle(copy);
|
||||
|
|
|
@ -254,7 +254,7 @@ private:
|
|||
//std::unique_ptr<Webrtc::VideoTrack> _videoTrack;
|
||||
//Webrtc::VideoTrack *_videoTrackShown = nullptr;
|
||||
//std::string _videoTrackEndpoint;
|
||||
//rpl::lifetime _videoTrackLifetime; // #TODO calls move to unique_ptr.
|
||||
//rpl::lifetime _videoTrackLifetime; // TODO calls move to unique_ptr.
|
||||
Ui::Animations::Simple _speakingAnimation; // For gray-red/green icon.
|
||||
Ui::Animations::Simple _mutedAnimation; // For gray/red icon.
|
||||
Ui::Animations::Simple _activeAnimation; // For icon cross animation.
|
||||
|
|
|
@ -977,8 +977,14 @@ void Panel::setupMembers() {
|
|||
_startsWhen.destroy();
|
||||
|
||||
_members.create(widget(), _call, mode());
|
||||
|
||||
setupVideo(_viewport.get());
|
||||
setupVideo(_members->viewport());
|
||||
_viewport->mouseInsideValue(
|
||||
) | rpl::start_with_next([=](bool inside) {
|
||||
toggleWideControls(inside);
|
||||
}, _viewport->lifetime());
|
||||
|
||||
_members->show();
|
||||
|
||||
refreshControlsBackground();
|
||||
|
@ -1135,9 +1141,10 @@ void Panel::setupVideo(not_null<Viewport*> viewport) {
|
|||
setupTile(endpoint, track);
|
||||
}
|
||||
_call->videoStreamActiveUpdates(
|
||||
) | rpl::start_with_next([=](const VideoEndpoint &endpoint) {
|
||||
if (_call->activeVideoTracks().contains(endpoint)) {
|
||||
) | rpl::start_with_next([=](const VideoActiveToggle &update) {
|
||||
if (update.active) {
|
||||
// Add async (=> the participant row is definitely in Members).
|
||||
const auto endpoint = update.endpoint;
|
||||
crl::on_main(viewport->widget(), [=] {
|
||||
const auto &tracks = _call->activeVideoTracks();
|
||||
const auto i = tracks.find(endpoint);
|
||||
|
@ -1147,7 +1154,7 @@ void Panel::setupVideo(not_null<Viewport*> viewport) {
|
|||
});
|
||||
} else {
|
||||
// Remove sync.
|
||||
viewport->remove(endpoint);
|
||||
viewport->remove(update.endpoint);
|
||||
}
|
||||
}, viewport->lifetime());
|
||||
|
||||
|
@ -1168,11 +1175,6 @@ void Panel::setupVideo(not_null<Viewport*> viewport) {
|
|||
) | rpl::start_with_next([=](const VideoQualityRequest &request) {
|
||||
_call->requestVideoQuality(request.endpoint, request.quality);
|
||||
}, viewport->lifetime());
|
||||
|
||||
viewport->mouseInsideValue(
|
||||
) | rpl::start_with_next([=](bool inside) {
|
||||
toggleWideControls(inside);
|
||||
}, viewport->lifetime());
|
||||
}
|
||||
|
||||
void Panel::toggleWideControls(bool shown) {
|
||||
|
|
|
@ -26,8 +26,11 @@ constexpr auto kScaleForBlurTextureIndex = 3;
|
|||
constexpr auto kFirstBlurPassTextureIndex = 4;
|
||||
constexpr auto kBlurTextureSizeFactor = 1.7;
|
||||
constexpr auto kBlurOpacity = 0.7;
|
||||
constexpr auto kMinCameraVisiblePart = 0.75;
|
||||
|
||||
ShaderPart FragmentBlurTexture(bool vertical, char prefix = 'v') {
|
||||
[[nodiscard]] ShaderPart FragmentBlurTexture(
|
||||
bool vertical,
|
||||
char prefix = 'v') {
|
||||
const auto offsets = (vertical ? QString("0, 1") : QString("1, 0"));
|
||||
const auto name = prefix + QString("_texcoord");
|
||||
return {
|
||||
|
@ -94,6 +97,16 @@ vec4 background() {
|
|||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] bool UseExpandForCamera(QSize original, QSize viewport) {
|
||||
const auto big = original.scaled(
|
||||
viewport,
|
||||
Qt::KeepAspectRatioByExpanding);
|
||||
|
||||
// If we cut out no more than 0.25 of the original, let's use expanding.
|
||||
return (big.width() * kMinCameraVisiblePart <= viewport.width())
|
||||
&& (big.height() * kMinCameraVisiblePart <= viewport.height());
|
||||
}
|
||||
|
||||
[[nodiscard]] QSize NonEmpty(QSize size) {
|
||||
return QSize(std::max(size.width(), 1), std::max(size.height(), 1));
|
||||
}
|
||||
|
@ -440,12 +453,14 @@ void Viewport::RendererGL::paintTile(
|
|||
const auto unscaled = Media::View::FlipSizeByRotation(
|
||||
data.yuv420->size,
|
||||
data.rotation);
|
||||
const auto tileSize = geometry.size();
|
||||
const auto swap = (((data.rotation / 90) % 2) == 1);
|
||||
const auto expand = !_owner->wide()/* && !tile->screencast()*/;
|
||||
auto texCoords = CountTexCoords(unscaled, geometry.size(), expand, swap);
|
||||
const auto expand = !tile->screencast()
|
||||
&& (!_owner->wide() || UseExpandForCamera(unscaled, tileSize));
|
||||
auto texCoords = CountTexCoords(unscaled, tileSize, expand, swap);
|
||||
auto blurTexCoords = expand
|
||||
? texCoords
|
||||
: CountTexCoords(unscaled, geometry.size(), true);
|
||||
: CountTexCoords(unscaled, tileSize, true);
|
||||
const auto rect = transformRect(geometry);
|
||||
auto toBlurTexCoords = std::array<std::array<GLfloat, 2>, 4> { {
|
||||
{ { 0.f, 1.f } },
|
||||
|
|
|
@ -46,6 +46,10 @@ int Viewport::VideoTile::pinSlide() const {
|
|||
_pinShownAnimation.value(_pinShown ? 1. : 0.));
|
||||
}
|
||||
|
||||
bool Viewport::VideoTile::screencast() const {
|
||||
return (_endpoint.type == VideoEndpointType::Screen);
|
||||
}
|
||||
|
||||
void Viewport::VideoTile::setGeometry(QRect geometry) {
|
||||
_geometry = geometry;
|
||||
updatePinnedGeometry();
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
return _trackSize.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool screencast() const;
|
||||
void setGeometry(QRect geometry);
|
||||
void togglePinShown(bool shown);
|
||||
bool updateRequestedQuality(VideoQuality quality);
|
||||
|
|
Loading…
Add table
Reference in a new issue