mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Show profile video in PeerShortInfoBox.
This commit is contained in:
parent
61ac7e6c1d
commit
24e0ea2a59
5 changed files with 161 additions and 15 deletions
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "boxes/peers/edit_participant_box.h"
|
#include "boxes/peers/edit_participant_box.h"
|
||||||
#include "boxes/peers/add_participants_box.h"
|
#include "boxes/peers/add_participants_box.h"
|
||||||
|
#include "boxes/peers/prepare_short_info_box.h" // PrepareShortInfoBox
|
||||||
#include "ui/boxes/confirm_box.h"
|
#include "ui/boxes/confirm_box.h"
|
||||||
#include "boxes/max_invite_box.h"
|
#include "boxes/max_invite_box.h"
|
||||||
#include "boxes/add_contact_box.h"
|
#include "boxes/add_contact_box.h"
|
||||||
|
@ -1434,7 +1435,10 @@ void ParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
showRestricted(user);
|
showRestricted(user);
|
||||||
} else {
|
} else {
|
||||||
Assert(_navigation != nullptr);
|
Assert(_navigation != nullptr);
|
||||||
_navigation->showPeerInfo(participant);
|
AssertIsDebug();
|
||||||
|
_navigation->parentController()->show(PrepareShortInfoBox(
|
||||||
|
participant,
|
||||||
|
_navigation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/image/image_prepare.h"
|
#include "ui/image/image_prepare.h"
|
||||||
#include "media/streaming/media_streaming_instance.h"
|
#include "media/streaming/media_streaming_instance.h"
|
||||||
|
#include "media/streaming/media_streaming_player.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_info.h"
|
#include "styles/style_info.h"
|
||||||
|
@ -23,11 +24,13 @@ PeerShortInfoBox::PeerShortInfoBox(
|
||||||
PeerShortInfoType type,
|
PeerShortInfoType type,
|
||||||
rpl::producer<PeerShortInfoFields> fields,
|
rpl::producer<PeerShortInfoFields> fields,
|
||||||
rpl::producer<QString> status,
|
rpl::producer<QString> status,
|
||||||
rpl::producer<PeerShortInfoUserpic> userpic)
|
rpl::producer<PeerShortInfoUserpic> userpic,
|
||||||
|
Fn<bool()> videoPaused)
|
||||||
: _type(type)
|
: _type(type)
|
||||||
, _fields(std::move(fields))
|
, _fields(std::move(fields))
|
||||||
, _name(this, nameValue(), st::shortInfoName)
|
, _name(this, nameValue(), st::shortInfoName)
|
||||||
, _status(this, std::move(status), st::shortInfoStatus) {
|
, _status(this, std::move(status), st::shortInfoStatus)
|
||||||
|
, _videoPaused(std::move(videoPaused)) {
|
||||||
std::move(
|
std::move(
|
||||||
userpic
|
userpic
|
||||||
) | rpl::start_with_next([=](PeerShortInfoUserpic &&value) {
|
) | rpl::start_with_next([=](PeerShortInfoUserpic &&value) {
|
||||||
|
@ -66,17 +69,42 @@ void PeerShortInfoBox::resizeEvent(QResizeEvent *e) {
|
||||||
void PeerShortInfoBox::paintEvent(QPaintEvent *e) {
|
void PeerShortInfoBox::paintEvent(QPaintEvent *e) {
|
||||||
auto p = QPainter(this);
|
auto p = QPainter(this);
|
||||||
|
|
||||||
const auto coverSize = st::shortInfoWidth;
|
checkStreamedIsStarted();
|
||||||
if (_userpicImage.isNull()) {
|
const auto frame = currentVideoFrame();
|
||||||
const auto size = coverSize * style::DevicePixelRatio();
|
auto paused = _videoPaused && _videoPaused();
|
||||||
auto image = QImage(size, size, QImage::Format_ARGB32_Premultiplied);
|
if (frame.isNull() && _userpicImage.isNull()) {
|
||||||
|
auto image = QImage(
|
||||||
|
coverRect().size() * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
image.fill(Qt::black);
|
image.fill(Qt::black);
|
||||||
Images::prepareRound(
|
Images::prepareRound(
|
||||||
image,
|
image,
|
||||||
ImageRoundRadius::Small,
|
ImageRoundRadius::Small,
|
||||||
RectPart::TopLeft | RectPart::TopRight);
|
RectPart::TopLeft | RectPart::TopRight);
|
||||||
|
_userpicImage = std::move(image);
|
||||||
}
|
}
|
||||||
p.drawImage(QRect(0, 0, coverSize, coverSize), _userpicImage);
|
p.drawImage(
|
||||||
|
coverRect(),
|
||||||
|
frame.isNull() ? _userpicImage : frame);
|
||||||
|
if (_videoInstance && _videoInstance->ready() && !paused) {
|
||||||
|
_videoInstance->markFrameShown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage PeerShortInfoBox::currentVideoFrame() const {
|
||||||
|
const auto coverSize = st::shortInfoWidth;
|
||||||
|
const auto size = QSize(coverSize, coverSize);
|
||||||
|
const auto request = Media::Streaming::FrameRequest{
|
||||||
|
.resize = size * style::DevicePixelRatio(),
|
||||||
|
.outer = size,
|
||||||
|
.radius = ImageRoundRadius::Small,
|
||||||
|
.corners = RectPart::TopLeft | RectPart::TopRight,
|
||||||
|
};
|
||||||
|
return (_videoInstance
|
||||||
|
&& _videoInstance->player().ready()
|
||||||
|
&& !_videoInstance->player().videoSize().isEmpty())
|
||||||
|
? _videoInstance->frame(request)
|
||||||
|
: QImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<QString> PeerShortInfoBox::nameValue() const {
|
rpl::producer<QString> PeerShortInfoBox::nameValue() const {
|
||||||
|
@ -91,4 +119,91 @@ void PeerShortInfoBox::applyUserpic(PeerShortInfoUserpic &&value) {
|
||||||
_userpicImage = std::move(value.photo);
|
_userpicImage = std::move(value.photo);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
if (value.videoDocument
|
||||||
|
&& (!_videoInstance
|
||||||
|
|| _videoInstance->shared() != value.videoDocument)) {
|
||||||
|
const auto frame = currentVideoFrame();
|
||||||
|
if (!frame.isNull()) {
|
||||||
|
_userpicImage = frame;
|
||||||
|
}
|
||||||
|
using namespace Media::Streaming;
|
||||||
|
_videoInstance = std::make_unique<Instance>(
|
||||||
|
std::move(value.videoDocument),
|
||||||
|
[=] { videoWaiting(); });
|
||||||
|
_videoStartPosition = value.videoStartPosition;
|
||||||
|
_videoInstance->lockPlayer();
|
||||||
|
_videoInstance->player().updates(
|
||||||
|
) | rpl::start_with_next_error([=](Update &&update) {
|
||||||
|
handleStreamingUpdate(std::move(update));
|
||||||
|
}, [=](Error &&error) {
|
||||||
|
handleStreamingError(std::move(error));
|
||||||
|
}, _videoInstance->lifetime());
|
||||||
|
if (_videoInstance->ready()) {
|
||||||
|
streamingReady(base::duplicate(_videoInstance->info()));
|
||||||
|
}
|
||||||
|
if (!_videoInstance->valid()) {
|
||||||
|
_videoInstance = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerShortInfoBox::checkStreamedIsStarted() {
|
||||||
|
if (!_videoInstance) {
|
||||||
|
return;
|
||||||
|
} else if (_videoInstance->paused()) {
|
||||||
|
_videoInstance->resume();
|
||||||
|
}
|
||||||
|
if (!_videoInstance
|
||||||
|
|| _videoInstance->active()
|
||||||
|
|| _videoInstance->failed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto options = Media::Streaming::PlaybackOptions();
|
||||||
|
options.position = _videoStartPosition;
|
||||||
|
options.mode = Media::Streaming::Mode::Video;
|
||||||
|
options.loop = true;
|
||||||
|
_videoInstance->play(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerShortInfoBox::handleStreamingUpdate(
|
||||||
|
Media::Streaming::Update &&update) {
|
||||||
|
using namespace Media::Streaming;
|
||||||
|
|
||||||
|
v::match(update.data, [&](Information &update) {
|
||||||
|
streamingReady(std::move(update));
|
||||||
|
}, [&](const PreloadedVideo &update) {
|
||||||
|
}, [&](const UpdateVideo &update) {
|
||||||
|
this->update(coverRect());
|
||||||
|
}, [&](const PreloadedAudio &update) {
|
||||||
|
}, [&](const UpdateAudio &update) {
|
||||||
|
}, [&](const WaitingForData &update) {
|
||||||
|
}, [&](MutedByOther) {
|
||||||
|
}, [&](Finished) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerShortInfoBox::handleStreamingError(
|
||||||
|
Media::Streaming::Error &&error) {
|
||||||
|
//_streamedPhoto->setVideoPlaybackFailed();
|
||||||
|
//_streamedPhoto = nullptr;
|
||||||
|
_videoInstance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerShortInfoBox::streamingReady(Media::Streaming::Information &&info) {
|
||||||
|
update(coverRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect PeerShortInfoBox::coverRect() const {
|
||||||
|
return QRect(0, 0, st::shortInfoWidth, st::shortInfoWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect PeerShortInfoBox::radialRect() const {
|
||||||
|
const auto cover = coverRect();
|
||||||
|
return cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerShortInfoBox::videoWaiting() {
|
||||||
|
if (!anim::Disabled()) {
|
||||||
|
update(radialRect());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Media::Streaming {
|
namespace Media::Streaming {
|
||||||
class Document;
|
class Document;
|
||||||
class Instance;
|
class Instance;
|
||||||
|
struct Update;
|
||||||
|
enum class Error;
|
||||||
|
struct Information;
|
||||||
} // namespace Media::Streaming
|
} // namespace Media::Streaming
|
||||||
|
|
||||||
enum class PeerShortInfoType {
|
enum class PeerShortInfoType {
|
||||||
|
@ -35,6 +38,7 @@ struct PeerShortInfoUserpic {
|
||||||
QImage photo;
|
QImage photo;
|
||||||
float64 photoLoadingProgress = 0.;
|
float64 photoLoadingProgress = 0.;
|
||||||
std::shared_ptr<Media::Streaming::Document> videoDocument;
|
std::shared_ptr<Media::Streaming::Document> videoDocument;
|
||||||
|
crl::time videoStartPosition = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PeerShortInfoBox final : public Ui::BoxContent {
|
class PeerShortInfoBox final : public Ui::BoxContent {
|
||||||
|
@ -44,7 +48,8 @@ public:
|
||||||
PeerShortInfoType type,
|
PeerShortInfoType type,
|
||||||
rpl::producer<PeerShortInfoFields> fields,
|
rpl::producer<PeerShortInfoFields> fields,
|
||||||
rpl::producer<QString> status,
|
rpl::producer<QString> status,
|
||||||
rpl::producer<PeerShortInfoUserpic> userpic);
|
rpl::producer<PeerShortInfoUserpic> userpic,
|
||||||
|
Fn<bool()> videoPaused);
|
||||||
~PeerShortInfoBox();
|
~PeerShortInfoBox();
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<> openRequests() const;
|
[[nodiscard]] rpl::producer<> openRequests() const;
|
||||||
|
@ -56,8 +61,18 @@ private:
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
[[nodiscard]] QImage currentVideoFrame() const;
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<QString> nameValue() const;
|
[[nodiscard]] rpl::producer<QString> nameValue() const;
|
||||||
void applyUserpic(PeerShortInfoUserpic &&value);
|
void applyUserpic(PeerShortInfoUserpic &&value);
|
||||||
|
QRect coverRect() const;
|
||||||
|
QRect radialRect() const;
|
||||||
|
|
||||||
|
void videoWaiting();
|
||||||
|
void checkStreamedIsStarted();
|
||||||
|
void handleStreamingUpdate(Media::Streaming::Update &&update);
|
||||||
|
void handleStreamingError(Media::Streaming::Error &&error);
|
||||||
|
void streamingReady(Media::Streaming::Information &&info);
|
||||||
|
|
||||||
const PeerShortInfoType _type = PeerShortInfoType::User;
|
const PeerShortInfoType _type = PeerShortInfoType::User;
|
||||||
|
|
||||||
|
@ -68,6 +83,8 @@ private:
|
||||||
|
|
||||||
QImage _userpicImage;
|
QImage _userpicImage;
|
||||||
std::unique_ptr<Media::Streaming::Instance> _videoInstance;
|
std::unique_ptr<Media::Streaming::Instance> _videoInstance;
|
||||||
|
crl::time _videoStartPosition = 0;
|
||||||
|
Fn<bool()> _videoPaused;
|
||||||
|
|
||||||
rpl::event_stream<> _openRequests;
|
rpl::event_stream<> _openRequests;
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ void GenerateImage(
|
||||||
size * factor,
|
size * factor,
|
||||||
size * factor,
|
size * factor,
|
||||||
options,
|
options,
|
||||||
size * factor,
|
size,
|
||||||
size * factor);
|
size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateImage(
|
void GenerateImage(
|
||||||
|
@ -134,6 +134,7 @@ void ProcessFullPhoto(
|
||||||
state->current.videoDocument = peer->owner().streaming().sharedDocument(
|
state->current.videoDocument = peer->owner().streaming().sharedDocument(
|
||||||
photo,
|
photo,
|
||||||
origin);
|
origin);
|
||||||
|
state->current.videoStartPosition = photo->videoStartPosition();
|
||||||
state->photoView = nullptr;
|
state->photoView = nullptr;
|
||||||
state->current.photoLoadingProgress = 1.;
|
state->current.photoLoadingProgress = 1.;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +275,8 @@ void ProcessFullPhoto(
|
||||||
|
|
||||||
object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Fn<void()> open) {
|
Fn<void()> open,
|
||||||
|
Fn<bool()> videoPaused) {
|
||||||
const auto type = peer->isUser()
|
const auto type = peer->isUser()
|
||||||
? PeerShortInfoType::User
|
? PeerShortInfoType::User
|
||||||
: peer->isBroadcast()
|
: peer->isBroadcast()
|
||||||
|
@ -284,7 +286,8 @@ object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||||
type,
|
type,
|
||||||
FieldsValue(peer),
|
FieldsValue(peer),
|
||||||
StatusValue(peer),
|
StatusValue(peer),
|
||||||
UserpicValue(peer));
|
UserpicValue(peer),
|
||||||
|
std::move(videoPaused));
|
||||||
|
|
||||||
result->openRequests(
|
result->openRequests(
|
||||||
) | rpl::start_with_next(open, result->lifetime());
|
) | rpl::start_with_next(open, result->lifetime());
|
||||||
|
@ -295,7 +298,13 @@ object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||||
object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
not_null<Window::SessionNavigation*> navigation) {
|
not_null<Window::SessionNavigation*> navigation) {
|
||||||
|
const auto open = [=] { navigation->showPeerHistory(peer); };
|
||||||
|
const auto videoIsPaused = [=] {
|
||||||
|
return navigation->parentController()->isGifPausedAtLeastFor(
|
||||||
|
Window::GifPauseReason::Layer);
|
||||||
|
};
|
||||||
return PrepareShortInfoBox(
|
return PrepareShortInfoBox(
|
||||||
peer,
|
peer,
|
||||||
[=] { navigation->showPeerHistory(peer); });
|
open,
|
||||||
|
videoIsPaused);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ class SessionNavigation;
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Fn<void()> open);
|
Fn<void()> open,
|
||||||
|
Fn<bool()> videoPaused);
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
|
Loading…
Add table
Reference in a new issue