mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +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/peers/edit_participant_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 "boxes/max_invite_box.h"
|
||||
#include "boxes/add_contact_box.h"
|
||||
|
@ -1434,7 +1435,10 @@ void ParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
|||
showRestricted(user);
|
||||
} else {
|
||||
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/image/image_prepare.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/streaming/media_streaming_player.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_info.h"
|
||||
|
@ -23,11 +24,13 @@ PeerShortInfoBox::PeerShortInfoBox(
|
|||
PeerShortInfoType type,
|
||||
rpl::producer<PeerShortInfoFields> fields,
|
||||
rpl::producer<QString> status,
|
||||
rpl::producer<PeerShortInfoUserpic> userpic)
|
||||
rpl::producer<PeerShortInfoUserpic> userpic,
|
||||
Fn<bool()> videoPaused)
|
||||
: _type(type)
|
||||
, _fields(std::move(fields))
|
||||
, _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(
|
||||
userpic
|
||||
) | rpl::start_with_next([=](PeerShortInfoUserpic &&value) {
|
||||
|
@ -66,17 +69,42 @@ void PeerShortInfoBox::resizeEvent(QResizeEvent *e) {
|
|||
void PeerShortInfoBox::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
|
||||
const auto coverSize = st::shortInfoWidth;
|
||||
if (_userpicImage.isNull()) {
|
||||
const auto size = coverSize * style::DevicePixelRatio();
|
||||
auto image = QImage(size, size, QImage::Format_ARGB32_Premultiplied);
|
||||
checkStreamedIsStarted();
|
||||
const auto frame = currentVideoFrame();
|
||||
auto paused = _videoPaused && _videoPaused();
|
||||
if (frame.isNull() && _userpicImage.isNull()) {
|
||||
auto image = QImage(
|
||||
coverRect().size() * style::DevicePixelRatio(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(Qt::black);
|
||||
Images::prepareRound(
|
||||
image,
|
||||
ImageRoundRadius::Small,
|
||||
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 {
|
||||
|
@ -91,4 +119,91 @@ void PeerShortInfoBox::applyUserpic(PeerShortInfoUserpic &&value) {
|
|||
_userpicImage = std::move(value.photo);
|
||||
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 {
|
||||
class Document;
|
||||
class Instance;
|
||||
struct Update;
|
||||
enum class Error;
|
||||
struct Information;
|
||||
} // namespace Media::Streaming
|
||||
|
||||
enum class PeerShortInfoType {
|
||||
|
@ -35,6 +38,7 @@ struct PeerShortInfoUserpic {
|
|||
QImage photo;
|
||||
float64 photoLoadingProgress = 0.;
|
||||
std::shared_ptr<Media::Streaming::Document> videoDocument;
|
||||
crl::time videoStartPosition = 0;
|
||||
};
|
||||
|
||||
class PeerShortInfoBox final : public Ui::BoxContent {
|
||||
|
@ -44,7 +48,8 @@ public:
|
|||
PeerShortInfoType type,
|
||||
rpl::producer<PeerShortInfoFields> fields,
|
||||
rpl::producer<QString> status,
|
||||
rpl::producer<PeerShortInfoUserpic> userpic);
|
||||
rpl::producer<PeerShortInfoUserpic> userpic,
|
||||
Fn<bool()> videoPaused);
|
||||
~PeerShortInfoBox();
|
||||
|
||||
[[nodiscard]] rpl::producer<> openRequests() const;
|
||||
|
@ -56,8 +61,18 @@ private:
|
|||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
[[nodiscard]] QImage currentVideoFrame() const;
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> nameValue() const;
|
||||
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;
|
||||
|
||||
|
@ -68,6 +83,8 @@ private:
|
|||
|
||||
QImage _userpicImage;
|
||||
std::unique_ptr<Media::Streaming::Instance> _videoInstance;
|
||||
crl::time _videoStartPosition = 0;
|
||||
Fn<bool()> _videoPaused;
|
||||
|
||||
rpl::event_stream<> _openRequests;
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ void GenerateImage(
|
|||
size * factor,
|
||||
size * factor,
|
||||
options,
|
||||
size * factor,
|
||||
size * factor);
|
||||
size,
|
||||
size);
|
||||
}
|
||||
|
||||
void GenerateImage(
|
||||
|
@ -134,6 +134,7 @@ void ProcessFullPhoto(
|
|||
state->current.videoDocument = peer->owner().streaming().sharedDocument(
|
||||
photo,
|
||||
origin);
|
||||
state->current.videoStartPosition = photo->videoStartPosition();
|
||||
state->photoView = nullptr;
|
||||
state->current.photoLoadingProgress = 1.;
|
||||
}
|
||||
|
@ -274,7 +275,8 @@ void ProcessFullPhoto(
|
|||
|
||||
object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> open) {
|
||||
Fn<void()> open,
|
||||
Fn<bool()> videoPaused) {
|
||||
const auto type = peer->isUser()
|
||||
? PeerShortInfoType::User
|
||||
: peer->isBroadcast()
|
||||
|
@ -284,7 +286,8 @@ object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
|||
type,
|
||||
FieldsValue(peer),
|
||||
StatusValue(peer),
|
||||
UserpicValue(peer));
|
||||
UserpicValue(peer),
|
||||
std::move(videoPaused));
|
||||
|
||||
result->openRequests(
|
||||
) | rpl::start_with_next(open, result->lifetime());
|
||||
|
@ -295,7 +298,13 @@ object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
|||
object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<Window::SessionNavigation*> navigation) {
|
||||
const auto open = [=] { navigation->showPeerHistory(peer); };
|
||||
const auto videoIsPaused = [=] {
|
||||
return navigation->parentController()->isGifPausedAtLeastFor(
|
||||
Window::GifPauseReason::Layer);
|
||||
};
|
||||
return PrepareShortInfoBox(
|
||||
peer,
|
||||
[=] { navigation->showPeerHistory(peer); });
|
||||
open,
|
||||
videoIsPaused);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ class SessionNavigation;
|
|||
|
||||
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> open);
|
||||
Fn<void()> open,
|
||||
Fn<bool()> videoPaused);
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
|
||||
not_null<PeerData*> peer,
|
||||
|
|
Loading…
Add table
Reference in a new issue