mirror of https://github.com/procxx/kepka.git
Autoplay full-width videos in albums.
This commit is contained in:
parent
a8935178a2
commit
a4ea4689a2
|
@ -419,8 +419,6 @@ PRIVATE
|
||||||
history/view/media/history_view_sticker.cpp
|
history/view/media/history_view_sticker.cpp
|
||||||
history/view/media/history_view_theme_document.h
|
history/view/media/history_view_theme_document.h
|
||||||
history/view/media/history_view_theme_document.cpp
|
history/view/media/history_view_theme_document.cpp
|
||||||
history/view/media/history_view_video.h
|
|
||||||
history/view/media/history_view_video.cpp
|
|
||||||
history/view/media/history_view_web_page.h
|
history/view/media/history_view_web_page.h
|
||||||
history/view/media/history_view_web_page.cpp
|
history/view/media/history_view_web_page.cpp
|
||||||
history/view/history_view_compose_controls.cpp
|
history/view/history_view_compose_controls.cpp
|
||||||
|
|
|
@ -416,7 +416,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_performance" = "Performance";
|
"lng_settings_performance" = "Performance";
|
||||||
"lng_settings_enable_animations" = "Enable animations";
|
"lng_settings_enable_animations" = "Enable animations";
|
||||||
"lng_settings_autoplay_gifs" = "Autoplay GIFs";
|
"lng_settings_autoplay_gifs" = "Autoplay GIFs";
|
||||||
"lng_settings_autoplay_videos" = "Autoplay video files";
|
"lng_settings_autoplay_videos" = "Autoplay Videos";
|
||||||
"lng_settings_sensitive_title" = "Sensitive content";
|
"lng_settings_sensitive_title" = "Sensitive content";
|
||||||
"lng_settings_sensitive_disable_filtering" = "Disable filtering";
|
"lng_settings_sensitive_disable_filtering" = "Disable filtering";
|
||||||
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
|
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
|
||||||
|
|
|
@ -14,7 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/media/history_view_photo.h"
|
#include "history/view/media/history_view_photo.h"
|
||||||
#include "history/view/media/history_view_sticker.h"
|
#include "history/view/media/history_view_sticker.h"
|
||||||
#include "history/view/media/history_view_gif.h"
|
#include "history/view/media/history_view_gif.h"
|
||||||
#include "history/view/media/history_view_video.h"
|
|
||||||
#include "history/view/media/history_view_document.h"
|
#include "history/view/media/history_view_document.h"
|
||||||
#include "history/view/media/history_view_contact.h"
|
#include "history/view/media/history_view_contact.h"
|
||||||
#include "history/view/media/history_view_location.h"
|
#include "history/view/media/history_view_location.h"
|
||||||
|
|
|
@ -247,8 +247,8 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
|
|
||||||
const auto item = _parent->data();
|
const auto item = _parent->data();
|
||||||
auto displayLoading = (item->id < 0) || _data->displayLoading();
|
const auto displayLoading = (item->id < 0) || _data->displayLoading();
|
||||||
auto selected = (selection == FullSelection);
|
const auto selected = (selection == FullSelection);
|
||||||
const auto autoPaused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
|
const auto autoPaused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
|
||||||
const auto cornerDownload = downloadInCorner();
|
const auto cornerDownload = downloadInCorner();
|
||||||
const auto canBePlayed = _data->canBePlayed();
|
const auto canBePlayed = _data->canBePlayed();
|
||||||
|
@ -493,7 +493,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isRound) {
|
if (!isRound) {
|
||||||
drawCornerStatus(p, selected);
|
drawCornerStatus(p, selected, QPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inWebPage && isRound) {
|
if (!inWebPage && isRound) {
|
||||||
|
@ -597,7 +597,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gif::drawCornerStatus(Painter &p, bool selected) const {
|
void Gif::drawCornerStatus(Painter &p, bool selected, QPoint position) const {
|
||||||
if (!needInfoDisplay()) {
|
if (!needInfoDisplay()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -614,8 +614,8 @@ void Gif::drawCornerStatus(Painter &p, bool selected) const {
|
||||||
const auto downloadWidth = cornerDownload ? st::normalFont->width(_downloadSize) : 0;
|
const auto downloadWidth = cornerDownload ? st::normalFont->width(_downloadSize) : 0;
|
||||||
const auto statusW = std::max(downloadWidth, st::normalFont->width(text)) + 2 * padding.x() + addLeft + addRight;
|
const auto statusW = std::max(downloadWidth, st::normalFont->width(text)) + 2 * padding.x() + addLeft + addRight;
|
||||||
const auto statusH = cornerDownload ? (st::historyVideoDownloadSize + 2 * padding.y()) : (st::normalFont->height + 2 * padding.y());
|
const auto statusH = cornerDownload ? (st::historyVideoDownloadSize + 2 * padding.y()) : (st::normalFont->height + 2 * padding.y());
|
||||||
const auto statusX = st::msgDateImgDelta + padding.x();
|
const auto statusX = position.x() + st::msgDateImgDelta + padding.x();
|
||||||
const auto statusY = st::msgDateImgDelta + padding.y();
|
const auto statusY = position.y() + st::msgDateImgDelta + padding.y();
|
||||||
const auto around = style::rtlrect(statusX - padding.x(), statusY - padding.y(), statusW, statusH, width());
|
const auto around = style::rtlrect(statusX - padding.x(), statusY - padding.y(), statusW, statusH, width());
|
||||||
const auto statusTextTop = statusY + (cornerDownload ? (((statusH - 2 * st::normalFont->height) / 3) - padding.y()) : 0);
|
const auto statusTextTop = statusY + (cornerDownload ? (((statusH - 2 * st::normalFont->height) / 3) - padding.y()) : 0);
|
||||||
App::roundRect(p, around, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
App::roundRect(p, around, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
||||||
|
@ -646,14 +646,16 @@ void Gif::drawCornerStatus(Painter &p, bool selected) const {
|
||||||
|
|
||||||
TextState Gif::cornerStatusTextState(
|
TextState Gif::cornerStatusTextState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const {
|
StateRequest request,
|
||||||
|
QPoint position) const {
|
||||||
auto result = TextState(_parent);
|
auto result = TextState(_parent);
|
||||||
if (!needInfoDisplay() || !downloadInCorner() || _data->loaded()) {
|
if (!needInfoDisplay() || !downloadInCorner() || _data->loaded()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
const auto padding = st::msgDateImgPadding;
|
const auto padding = st::msgDateImgPadding;
|
||||||
const auto addWidth = st::historyVideoDownloadSize + 2 * padding.y() - padding.x();
|
const auto addWidth = st::historyVideoDownloadSize + 2 * padding.y() - padding.x();
|
||||||
const auto statusX = st::msgDateImgDelta + padding.x(), statusY = st::msgDateImgDelta + padding.y();
|
const auto statusX = position.x() + st::msgDateImgDelta + padding.x();
|
||||||
|
const auto statusY = position.y() + st::msgDateImgDelta + padding.y();
|
||||||
const auto inner = QRect(statusX + padding.y() - padding.x(), statusY, st::historyVideoDownloadSize, st::historyVideoDownloadSize);
|
const auto inner = QRect(statusX + padding.y() - padding.x(), statusY, st::historyVideoDownloadSize, st::historyVideoDownloadSize);
|
||||||
if (inner.contains(point)) {
|
if (inner.contains(point)) {
|
||||||
result.link = _data->loading() ? _cancell : _savel;
|
result.link = _data->loading() ? _cancell : _savel;
|
||||||
|
@ -760,21 +762,21 @@ TextState Gif::textState(QPoint point, StateRequest request) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isRound) {
|
if (!isRound) {
|
||||||
if (const auto state = cornerStatusTextState(point, request); state.link) {
|
if (const auto state = cornerStatusTextState(point, request, QPoint()); state.link) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (QRect(usex + paintx, painty, usew, painth).contains(point)) {
|
if (QRect(usex + paintx, painty, usew, painth).contains(point)) {
|
||||||
if (_data->uploading()) {
|
result.link = _data->uploading()
|
||||||
result.link = _cancell;
|
? _cancell
|
||||||
} else {
|
: !IsServerMsgId(_realParent->id)
|
||||||
result.link = (_data->loaded() || _data->canBePlayed())
|
? nullptr
|
||||||
? _openl :
|
: (_data->loaded() || _data->canBePlayed())
|
||||||
_data->loading()
|
? _openl
|
||||||
|
: _data->loading()
|
||||||
? _cancell
|
? _cancell
|
||||||
: _savel;
|
: _savel;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (isRound || _caption.isEmpty()) {
|
if (isRound || _caption.isEmpty()) {
|
||||||
auto fullRight = usex + paintx + usew;
|
auto fullRight = usex + paintx + usew;
|
||||||
auto fullBottom = painty + painth;
|
auto fullBottom = painty + painth;
|
||||||
|
@ -818,6 +820,10 @@ TextForMimeData Gif::selectedText(TextSelection selection) const {
|
||||||
return _caption.toTextForMimeData(selection);
|
return _caption.toTextForMimeData(selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Gif::fullFeaturedGrouped(RectParts sides) const {
|
||||||
|
return (sides & RectPart::Left) && (sides & RectPart::Right);
|
||||||
|
}
|
||||||
|
|
||||||
QSize Gif::sizeForGrouping() const {
|
QSize Gif::sizeForGrouping() const {
|
||||||
return sizeForAspectRatio();
|
return sizeForAspectRatio();
|
||||||
}
|
}
|
||||||
|
@ -828,39 +834,104 @@ void Gif::drawGrouped(
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
crl::time ms,
|
crl::time ms,
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache) const {
|
not_null<QPixmap*> cache) const {
|
||||||
validateGroupedCache(geometry, corners, cacheKey, cache);
|
const auto item = _parent->data();
|
||||||
|
const auto displayLoading = (item->id < 0) || _data->displayLoading();
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (selection == FullSelection);
|
||||||
const auto loaded = _data->loaded();
|
const auto autoPaused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
|
||||||
const auto displayLoading = _data->displayLoading();
|
const auto fullFeatured = fullFeaturedGrouped(sides);
|
||||||
const auto bubble = _parent->hasBubble();
|
const auto cornerDownload = fullFeatured && downloadInCorner();
|
||||||
|
const auto canBePlayed = _data->canBePlayed();
|
||||||
|
const auto autoplay = fullFeatured && autoplayEnabled() && canBePlayed;
|
||||||
|
const auto startPlayAsync = autoplay && !_streamed;
|
||||||
|
if (startPlayAsync) {
|
||||||
|
if (!autoPaused) {
|
||||||
|
const_cast<Gif*>(this)->playAnimation(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
checkStreamedIsStarted();
|
||||||
|
}
|
||||||
|
const auto streamingMode = _streamed || autoplay;
|
||||||
|
const auto activeOwnPlaying = activeOwnStreamed();
|
||||||
|
|
||||||
if (displayLoading) {
|
auto paintx = geometry.x(), painty = geometry.y(), paintw = geometry.width(), painth = geometry.height();
|
||||||
|
|
||||||
|
auto displayMute = false;
|
||||||
|
const auto streamed = activeOwnPlaying
|
||||||
|
? &activeOwnPlaying->instance
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (displayLoading
|
||||||
|
&& (!streamed
|
||||||
|
|| item->isSending()
|
||||||
|
|| (cornerDownload && _data->loading()))) {
|
||||||
ensureAnimation();
|
ensureAnimation();
|
||||||
if (!_animation->radial.animating()) {
|
if (!_animation->radial.animating()) {
|
||||||
_animation->radial.start(_data->progress());
|
_animation->radial.start(dataProgress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto radial = isRadialAnimation();
|
updateStatusText();
|
||||||
|
const auto radial = isRadialAnimation()
|
||||||
|
|| (streamed && streamed->waitingShown());
|
||||||
|
|
||||||
if (!bubble) {
|
|
||||||
// App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
|
|
||||||
}
|
|
||||||
p.drawPixmap(geometry.topLeft(), *cache);
|
|
||||||
if (selected) {
|
|
||||||
const auto roundRadius = ImageRoundRadius::Large;
|
const auto roundRadius = ImageRoundRadius::Large;
|
||||||
|
|
||||||
|
if (streamed) {
|
||||||
|
const auto paused = autoPaused;
|
||||||
|
auto request = ::Media::Streaming::FrameRequest();
|
||||||
|
const auto original = sizeForAspectRatio();
|
||||||
|
const auto originalWidth = style::ConvertScale(original.width());
|
||||||
|
const auto originalHeight = style::ConvertScale(original.height());
|
||||||
|
const auto pixSize = Ui::GetImageScaleSizeForGeometry(
|
||||||
|
{ originalWidth, originalHeight },
|
||||||
|
{ geometry.width(), geometry.height() });
|
||||||
|
request.outer = geometry.size() * cIntRetinaFactor();
|
||||||
|
request.resize = pixSize * cIntRetinaFactor();
|
||||||
|
request.corners = corners;
|
||||||
|
request.radius = roundRadius;
|
||||||
|
if (activeOwnPlaying->instance.playerLocked()) {
|
||||||
|
if (activeOwnPlaying->frozenFrame.isNull()) {
|
||||||
|
activeOwnPlaying->frozenRequest = request;
|
||||||
|
activeOwnPlaying->frozenFrame = streamed->frame(request);
|
||||||
|
activeOwnPlaying->frozenStatusText = _statusText;
|
||||||
|
} else if (activeOwnPlaying->frozenRequest != request) {
|
||||||
|
activeOwnPlaying->frozenRequest = request;
|
||||||
|
activeOwnPlaying->frozenFrame = streamed->frame(request);
|
||||||
|
}
|
||||||
|
p.drawImage(geometry, activeOwnPlaying->frozenFrame);
|
||||||
|
} else {
|
||||||
|
if (activeOwnPlaying) {
|
||||||
|
activeOwnPlaying->frozenFrame = QImage();
|
||||||
|
activeOwnPlaying->frozenStatusText = QString();
|
||||||
|
}
|
||||||
|
p.drawImage(geometry, streamed->frame(request));
|
||||||
|
if (!paused) {
|
||||||
|
streamed->markFrameShown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
validateGroupedCache(geometry, corners, cacheKey, cache);
|
||||||
|
p.drawPixmap(geometry, *cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected) {
|
||||||
App::complexOverlayRect(p, geometry, roundRadius, corners);
|
App::complexOverlayRect(p, geometry, roundRadius, corners);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto radialOpacity = radial
|
if (radial
|
||||||
|
|| (!streamingMode
|
||||||
|
&& ((!_data->loaded() && !_data->loading())
|
||||||
|
|| !autoplayEnabled()))) {
|
||||||
|
const auto radialOpacity = item->isSending()
|
||||||
|
? 1.
|
||||||
|
: streamed
|
||||||
|
? streamed->waitingOpacity()
|
||||||
|
: (radial && _data->loaded())
|
||||||
? _animation->radial.opacity()
|
? _animation->radial.opacity()
|
||||||
: 1.;
|
: 1.;
|
||||||
const auto backOpacity = (loaded && !_data->uploading())
|
|
||||||
? radialOpacity
|
|
||||||
: 1.;
|
|
||||||
const auto radialSize = st::historyGroupRadialSize;
|
const auto radialSize = st::historyGroupRadialSize;
|
||||||
const auto inner = QRect(
|
const auto inner = QRect(
|
||||||
geometry.x() + (geometry.width() - radialSize) / 2,
|
geometry.x() + (geometry.width() - radialSize) / 2,
|
||||||
|
@ -877,23 +948,26 @@ void Gif::drawGrouped(
|
||||||
auto over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel);
|
auto over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel);
|
||||||
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
|
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
|
||||||
}
|
}
|
||||||
|
p.setOpacity(radialOpacity * p.opacity());
|
||||||
p.setOpacity(backOpacity * p.opacity());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
p.drawEllipse(inner);
|
p.drawEllipse(inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto icon = [&]() -> const style::icon * {
|
p.setOpacity(radialOpacity);
|
||||||
|
const auto icon = [&]() -> const style::icon * {
|
||||||
if (_data->waitingForAlbum()) {
|
if (_data->waitingForAlbum()) {
|
||||||
return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting);
|
return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting);
|
||||||
} else if (_data->loading() || _data->uploading()) {
|
} else if (streamingMode && !_data->uploading()) {
|
||||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
|
||||||
} else if (!IsServerMsgId(_realParent->id)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (loaded || _data->canBePlayed()) {
|
} else if ((_data->loaded() || canBePlayed) && (!radial || cornerDownload)) {
|
||||||
return &(selected ? st::historyFileThumbPlaySelected : st::historyFileThumbPlay);
|
return &(selected ? st::historyFileThumbPlaySelected : st::historyFileThumbPlay);
|
||||||
|
} else if (radial || _data->loading()) {
|
||||||
|
if (!item->isSending() || _data->uploading()) {
|
||||||
|
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload);
|
return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload);
|
||||||
}();
|
}();
|
||||||
|
@ -903,7 +977,6 @@ void Gif::drawGrouped(
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}();
|
}();
|
||||||
p.setOpacity(backOpacity);
|
|
||||||
if (icon) {
|
if (icon) {
|
||||||
if (previous && radialOpacity > 0. && radialOpacity < 1.) {
|
if (previous && radialOpacity > 0. && radialOpacity < 1.) {
|
||||||
PaintInterpolatedIcon(p, *icon, *previous, radialOpacity, inner);
|
PaintInterpolatedIcon(p, *icon, *previous, radialOpacity, inner);
|
||||||
|
@ -915,26 +988,53 @@ void Gif::drawGrouped(
|
||||||
if (radial) {
|
if (radial) {
|
||||||
const auto line = st::historyGroupRadialLine;
|
const auto line = st::historyGroupRadialLine;
|
||||||
const auto rinner = inner.marginsRemoved({ line, line, line, line });
|
const auto rinner = inner.marginsRemoved({ line, line, line, line });
|
||||||
const auto color = selected
|
const auto fg = selected
|
||||||
? st::historyFileThumbRadialFgSelected
|
? st::historyFileThumbRadialFgSelected
|
||||||
: st::historyFileThumbRadialFg;
|
: st::historyFileThumbRadialFg;
|
||||||
_animation->radial.draw(p, rinner, line, color);
|
if (streamed && !_data->uploading()) {
|
||||||
|
Ui::InfiniteRadialAnimation::Draw(
|
||||||
|
p,
|
||||||
|
streamed->waitingState(),
|
||||||
|
rinner.topLeft(),
|
||||||
|
rinner.size(),
|
||||||
|
width(),
|
||||||
|
fg,
|
||||||
|
st::msgFileRadialLine);
|
||||||
|
} else if (!cornerDownload) {
|
||||||
|
_animation->radial.draw(
|
||||||
|
p,
|
||||||
|
rinner,
|
||||||
|
st::msgFileRadialLine,
|
||||||
|
fg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fullFeatured) {
|
||||||
|
drawCornerStatus(p, selected, geometry.topLeft());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextState Gif::getStateGrouped(
|
TextState Gif::getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const {
|
StateRequest request) const {
|
||||||
if (!geometry.contains(point)) {
|
if (!geometry.contains(point)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return TextState(_parent, (_data->loading() || _data->uploading())
|
if (fullFeaturedGrouped(sides)) {
|
||||||
|
if (const auto state = cornerStatusTextState(point, request, geometry.topLeft()); state.link) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TextState(_parent, _data->uploading()
|
||||||
? _cancell
|
? _cancell
|
||||||
: !IsServerMsgId(_realParent->id)
|
: !IsServerMsgId(_realParent->id)
|
||||||
? nullptr
|
? nullptr
|
||||||
: (_data->loaded() || _data->canBePlayed())
|
: (_data->loaded() || _data->canBePlayed())
|
||||||
? _openl
|
? _openl
|
||||||
|
: _data->loading()
|
||||||
|
? _cancell
|
||||||
: _savel);
|
: _savel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fullFeaturedGrouped(RectParts sides) const;
|
||||||
QSize sizeForGrouping() const override;
|
QSize sizeForGrouping() const override;
|
||||||
void drawGrouped(
|
void drawGrouped(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
@ -70,11 +71,13 @@ public:
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
crl::time ms,
|
crl::time ms,
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache) const override;
|
not_null<QPixmap*> cache) const override;
|
||||||
TextState getStateGrouped(
|
TextState getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const override;
|
StateRequest request) const override;
|
||||||
|
|
||||||
|
@ -147,10 +150,11 @@ private:
|
||||||
QSize sizeForAspectRatio() const;
|
QSize sizeForAspectRatio() const;
|
||||||
|
|
||||||
[[nodiscard]] bool downloadInCorner() const;
|
[[nodiscard]] bool downloadInCorner() const;
|
||||||
void drawCornerStatus(Painter &p, bool selected) const;
|
void drawCornerStatus(Painter &p, bool selected, QPoint position) const;
|
||||||
[[nodiscard]] TextState cornerStatusTextState(
|
[[nodiscard]] TextState cornerStatusTextState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const;
|
StateRequest request,
|
||||||
|
QPoint position) const;
|
||||||
|
|
||||||
not_null<DocumentData*> _data;
|
not_null<DocumentData*> _data;
|
||||||
int _thumbw = 1;
|
int _thumbw = 1;
|
||||||
|
|
|
@ -66,6 +66,7 @@ PointState Media::pointState(QPoint point) const {
|
||||||
|
|
||||||
TextState Media::getStateGrouped(
|
TextState Media::getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const {
|
StateRequest request) const {
|
||||||
Unexpected("Grouping method call.");
|
Unexpected("Grouping method call.");
|
||||||
|
|
|
@ -145,6 +145,7 @@ public:
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
crl::time ms,
|
crl::time ms,
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache) const {
|
not_null<QPixmap*> cache) const {
|
||||||
|
@ -152,6 +153,7 @@ public:
|
||||||
}
|
}
|
||||||
[[nodiscard]] virtual TextState getStateGrouped(
|
[[nodiscard]] virtual TextState getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const;
|
StateRequest request) const;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/media/history_view_gif.h"
|
#include "history/view/media/history_view_gif.h"
|
||||||
#include "history/view/media/history_view_document.h"
|
#include "history/view/media/history_view_document.h"
|
||||||
#include "history/view/media/history_view_sticker.h"
|
#include "history/view/media/history_view_sticker.h"
|
||||||
#include "history/view/media/history_view_video.h"
|
|
||||||
#include "history/view/media/history_view_theme_document.h"
|
#include "history/view/media/history_view_theme_document.h"
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,17 @@ void GroupedMedia::refreshParentId(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RectParts GroupedMedia::cornersFromSides(RectParts sides) const {
|
||||||
|
auto result = Ui::GetCornersFromSides(sides);
|
||||||
|
if (!isBubbleTop()) {
|
||||||
|
result &= ~(RectPart::TopLeft | RectPart::TopRight);
|
||||||
|
}
|
||||||
|
if (!isBubbleBottom() || !_caption.isEmpty()) {
|
||||||
|
result &= ~(RectPart::BottomLeft | RectPart::BottomRight);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void GroupedMedia::draw(
|
void GroupedMedia::draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const QRect &clip,
|
const QRect &clip,
|
||||||
|
@ -172,20 +183,14 @@ void GroupedMedia::draw(
|
||||||
: IsGroupItemSelection(selection, i)
|
: IsGroupItemSelection(selection, i)
|
||||||
? FullSelection
|
? FullSelection
|
||||||
: TextSelection();
|
: TextSelection();
|
||||||
auto corners = Ui::GetCornersFromSides(part.sides);
|
|
||||||
if (!isBubbleTop()) {
|
|
||||||
corners &= ~(RectPart::TopLeft | RectPart::TopRight);
|
|
||||||
}
|
|
||||||
if (!isBubbleBottom() || !_caption.isEmpty()) {
|
|
||||||
corners &= ~(RectPart::BottomLeft | RectPart::BottomRight);
|
|
||||||
}
|
|
||||||
part.content->drawGrouped(
|
part.content->drawGrouped(
|
||||||
p,
|
p,
|
||||||
clip,
|
clip,
|
||||||
partSelection,
|
partSelection,
|
||||||
ms,
|
ms,
|
||||||
part.geometry,
|
part.geometry,
|
||||||
corners,
|
part.sides,
|
||||||
|
cornersFromSides(part.sides),
|
||||||
&part.cacheKey,
|
&part.cacheKey,
|
||||||
&part.cache);
|
&part.cache);
|
||||||
}
|
}
|
||||||
|
@ -221,6 +226,7 @@ TextState GroupedMedia::getPartState(
|
||||||
if (part.geometry.contains(point)) {
|
if (part.geometry.contains(point)) {
|
||||||
auto result = part.content->getStateGrouped(
|
auto result = part.content->getStateGrouped(
|
||||||
part.geometry,
|
part.geometry,
|
||||||
|
part.sides,
|
||||||
point,
|
point,
|
||||||
request);
|
request);
|
||||||
result.itemId = part.item->fullId();
|
result.itemId = part.item->fullId();
|
||||||
|
|
|
@ -121,6 +121,8 @@ private:
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const;
|
StateRequest request) const;
|
||||||
|
|
||||||
|
[[nodiscard]] RectParts cornersFromSides(RectParts sides) const;
|
||||||
|
|
||||||
Ui::Text::String _caption;
|
Ui::Text::String _caption;
|
||||||
std::vector<Part> _parts;
|
std::vector<Part> _parts;
|
||||||
bool _needBubble = false;
|
bool _needBubble = false;
|
||||||
|
|
|
@ -345,6 +345,7 @@ void Photo::drawGrouped(
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
crl::time ms,
|
crl::time ms,
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache) const {
|
not_null<QPixmap*> cache) const {
|
||||||
|
@ -448,6 +449,7 @@ void Photo::drawGrouped(
|
||||||
|
|
||||||
TextState Photo::getStateGrouped(
|
TextState Photo::getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const {
|
StateRequest request) const {
|
||||||
if (!geometry.contains(point)) {
|
if (!geometry.contains(point)) {
|
||||||
|
|
|
@ -51,11 +51,13 @@ public:
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
crl::time ms,
|
crl::time ms,
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache) const override;
|
not_null<QPixmap*> cache) const override;
|
||||||
TextState getStateGrouped(
|
TextState getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const override;
|
StateRequest request) const override;
|
||||||
|
|
||||||
|
|
|
@ -1,622 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop application for the Telegram messaging service.
|
|
||||||
|
|
||||||
For license and copyright information please follow this link:
|
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
||||||
*/
|
|
||||||
#include "history/view/media/history_view_video.h"
|
|
||||||
|
|
||||||
#include "history/view/media/history_view_media_common.h"
|
|
||||||
#include "layout.h"
|
|
||||||
#include "history/history_item_components.h"
|
|
||||||
#include "history/history_item.h"
|
|
||||||
#include "history/history.h"
|
|
||||||
#include "history/view/history_view_element.h"
|
|
||||||
#include "history/view/history_view_cursor_state.h"
|
|
||||||
#include "ui/image/image.h"
|
|
||||||
#include "ui/grouped_layout.h"
|
|
||||||
#include "data/data_session.h"
|
|
||||||
#include "data/data_document.h"
|
|
||||||
#include "data/data_file_origin.h"
|
|
||||||
#include "app.h"
|
|
||||||
#include "styles/style_history.h"
|
|
||||||
|
|
||||||
namespace HistoryView {
|
|
||||||
|
|
||||||
Video::Video(
|
|
||||||
not_null<Element*> parent,
|
|
||||||
not_null<HistoryItem*> realParent,
|
|
||||||
not_null<DocumentData*> document)
|
|
||||||
: File(parent, realParent)
|
|
||||||
, _data(document)
|
|
||||||
, _thumbw(1)
|
|
||||||
, _caption(st::minPhotoSize - st::msgPadding.left() - st::msgPadding.right()) {
|
|
||||||
_caption = createCaption(realParent);
|
|
||||||
|
|
||||||
setDocumentLinks(_data, realParent);
|
|
||||||
|
|
||||||
setStatusSize(FileStatusSizeReady);
|
|
||||||
_downloadSize = formatSizeText(_data->size);
|
|
||||||
|
|
||||||
_data->loadThumbnail(realParent->fullId());
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize Video::sizeForAspectRatio() const {
|
|
||||||
// We use size only for aspect ratio and we want to have it
|
|
||||||
// as close to the thumbnail as possible.
|
|
||||||
//if (!_data->dimensions.isEmpty()) {
|
|
||||||
// return _data->dimensions;
|
|
||||||
//}
|
|
||||||
if (const auto thumb = _data->thumbnail()) {
|
|
||||||
if (!thumb->size().isEmpty()) {
|
|
||||||
return thumb->size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { 1, 1 };
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize Video::countOptimalDimensions() const {
|
|
||||||
const auto desired = style::ConvertScale(_data->dimensions);
|
|
||||||
const auto size = desired.isEmpty() ? sizeForAspectRatio() : desired;
|
|
||||||
auto tw = size.width();
|
|
||||||
auto th = size.height();
|
|
||||||
if (!tw || !th) {
|
|
||||||
tw = th = 1;
|
|
||||||
} else if (tw >= th && tw > st::maxMediaSize) {
|
|
||||||
th = qRound((st::maxMediaSize / float64(tw)) * th);
|
|
||||||
tw = st::maxMediaSize;
|
|
||||||
} else if (tw < th && th > st::maxMediaSize) {
|
|
||||||
tw = qRound((st::maxMediaSize / float64(th)) * tw);
|
|
||||||
th = st::maxMediaSize;
|
|
||||||
} else if ((tw < st::msgVideoSize.width())
|
|
||||||
&& (tw * st::msgVideoSize.height()
|
|
||||||
>= th * st::msgVideoSize.width())) {
|
|
||||||
th = qRound((st::msgVideoSize.width() / float64(tw)) * th);
|
|
||||||
tw = st::msgVideoSize.width();
|
|
||||||
} else if ((th < st::msgVideoSize.height())
|
|
||||||
&& (tw * st::msgVideoSize.height()
|
|
||||||
< th * st::msgVideoSize.width())) {
|
|
||||||
tw = qRound((st::msgVideoSize.height() / float64(th)) * tw);
|
|
||||||
th = st::msgVideoSize.height();
|
|
||||||
}
|
|
||||||
return QSize(tw, th);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize Video::countOptimalSize() {
|
|
||||||
if (_parent->media() != this) {
|
|
||||||
_caption = Ui::Text::String();
|
|
||||||
} else if (_caption.hasSkipBlock()) {
|
|
||||||
_caption.updateSkipBlock(
|
|
||||||
_parent->skipBlockWidth(),
|
|
||||||
_parent->skipBlockHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto size = countOptimalDimensions();
|
|
||||||
const auto tw = size.width();
|
|
||||||
const auto th = size.height();
|
|
||||||
_thumbw = qMax(tw, 1);
|
|
||||||
_thumbh = qMax(th, 1);
|
|
||||||
|
|
||||||
auto minWidth = qMax(st::minVideoSize, _parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
|
||||||
minWidth = qMax(minWidth, documentMaxStatusWidth(_data) + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
|
||||||
auto maxWidth = qMax(_thumbw, minWidth);
|
|
||||||
auto minHeight = qMax(th, st::minVideoSize);
|
|
||||||
if (_parent->hasBubble() && !_caption.isEmpty()) {
|
|
||||||
const auto captionw = maxWidth
|
|
||||||
- st::msgPadding.left()
|
|
||||||
- st::msgPadding.right();
|
|
||||||
minHeight += st::mediaCaptionSkip + _caption.countHeight(captionw);
|
|
||||||
if (isBubbleBottom()) {
|
|
||||||
minHeight += st::msgPadding.bottom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { maxWidth, minHeight };
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize Video::countCurrentSize(int newWidth) {
|
|
||||||
const auto size = countOptimalDimensions();
|
|
||||||
auto tw = size.width();
|
|
||||||
auto th = size.height();
|
|
||||||
if (newWidth < tw) {
|
|
||||||
th = qRound((newWidth / float64(tw)) * th);
|
|
||||||
tw = newWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
_thumbw = qMax(tw, 1);
|
|
||||||
_thumbh = qMax(th, 1);
|
|
||||||
auto minWidth = qMax(st::minPhotoSize, _parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
|
||||||
minWidth = qMax(minWidth, documentMaxStatusWidth(_data) + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
|
|
||||||
newWidth = qMax(_thumbw, minWidth);
|
|
||||||
auto newHeight = qMax(th, st::minPhotoSize);
|
|
||||||
if (_parent->hasBubble() && !_caption.isEmpty()) {
|
|
||||||
const auto captionw = newWidth
|
|
||||||
- st::msgPadding.left()
|
|
||||||
- st::msgPadding.right();
|
|
||||||
newHeight += st::mediaCaptionSkip + _caption.countHeight(captionw);
|
|
||||||
if (isBubbleBottom()) {
|
|
||||||
newHeight += st::msgPadding.bottom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { newWidth, newHeight };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::downloadInCorner() const {
|
|
||||||
return _data->canBeStreamed()
|
|
||||||
&& !_data->inappPlaybackFailed()
|
|
||||||
&& IsServerMsgId(_parent->data()->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
|
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
|
||||||
|
|
||||||
_data->automaticLoad(_realParent->fullId(), _parent->data());
|
|
||||||
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
|
|
||||||
bool selected = (selection == FullSelection);
|
|
||||||
|
|
||||||
auto paintx = 0, painty = 0, paintw = width(), painth = height();
|
|
||||||
bool bubble = _parent->hasBubble();
|
|
||||||
const auto cornerDownload = downloadInCorner();
|
|
||||||
|
|
||||||
int captionw = paintw - st::msgPadding.left() - st::msgPadding.right();
|
|
||||||
|
|
||||||
if (displayLoading) {
|
|
||||||
ensureAnimation();
|
|
||||||
if (!_animation->radial.animating()) {
|
|
||||||
_animation->radial.start(_data->progress());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateStatusText();
|
|
||||||
const auto radial = isRadialAnimation();
|
|
||||||
|
|
||||||
if (bubble) {
|
|
||||||
if (!_caption.isEmpty()) {
|
|
||||||
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
|
|
||||||
if (isBubbleBottom()) {
|
|
||||||
painth -= st::msgPadding.bottom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto inWebPage = (_parent->media() != this);
|
|
||||||
auto roundRadius = inWebPage ? ImageRoundRadius::Small : ImageRoundRadius::Large;
|
|
||||||
auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None)
|
|
||||||
| ((isBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None));
|
|
||||||
QRect rthumb(style::rtlrect(paintx, painty, paintw, painth, width()));
|
|
||||||
|
|
||||||
const auto good = _data->goodThumbnail();
|
|
||||||
if (good && good->loaded()) {
|
|
||||||
p.drawPixmap(rthumb.topLeft(), good->pixSingle({}, _thumbw, _thumbh, paintw, painth, roundRadius, roundCorners));
|
|
||||||
} else {
|
|
||||||
if (good) {
|
|
||||||
good->load({});
|
|
||||||
}
|
|
||||||
const auto normal = _data->thumbnail();
|
|
||||||
if (normal && normal->loaded()) {
|
|
||||||
p.drawPixmap(rthumb.topLeft(), normal->pixSingle(_realParent->fullId(), _thumbw, _thumbh, paintw, painth, roundRadius, roundCorners));
|
|
||||||
} else if (const auto blurred = _data->thumbnailInline()) {
|
|
||||||
p.drawPixmap(rthumb.topLeft(), blurred->pixBlurredSingle(_realParent->fullId(), _thumbw, _thumbh, paintw, painth, roundRadius, roundCorners));
|
|
||||||
} else {
|
|
||||||
const auto roundTop = (roundCorners & RectPart::TopLeft);
|
|
||||||
const auto roundBottom = (roundCorners & RectPart::BottomLeft);
|
|
||||||
const auto margin = inWebPage
|
|
||||||
? st::buttonRadius
|
|
||||||
: st::historyMessageRadius;
|
|
||||||
const auto parts = roundCorners
|
|
||||||
| RectPart::NoTopBottom
|
|
||||||
| (roundTop ? RectPart::Top : RectPart::None)
|
|
||||||
| (roundBottom ? RectPart::Bottom : RectPart::None);
|
|
||||||
App::roundRect(p, rthumb.marginsAdded({ 0, roundTop ? 0 : margin, 0, roundBottom ? 0 : margin }), st::imageBg, roundRadius, parts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selected) {
|
|
||||||
App::complexOverlayRect(p, rthumb, roundRadius, roundCorners);
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
if (selected) {
|
|
||||||
p.setBrush(st::msgDateImgBgSelected);
|
|
||||||
} else if (isThumbAnimation()) {
|
|
||||||
auto over = _animation->a_thumbOver.value(1.);
|
|
||||||
p.setBrush(anim::brush(st::msgDateImgBg, st::msgDateImgBgOver, over));
|
|
||||||
} else {
|
|
||||||
bool over = ClickHandler::showAsActive((_data->loading() || _data->uploading()) ? _cancell : _savel);
|
|
||||||
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
PainterHighQualityEnabler hq(p);
|
|
||||||
p.drawEllipse(inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto icon = [&]() -> const style::icon * {
|
|
||||||
if (!cornerDownload && (_data->loading() || _data->uploading())) {
|
|
||||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
|
||||||
} else if (!IsServerMsgId(_parent->data()->id)) {
|
|
||||||
return nullptr;
|
|
||||||
} else if (loaded || _data->canBePlayed()) {
|
|
||||||
return &(selected ? st::historyFileThumbPlaySelected : st::historyFileThumbPlay);
|
|
||||||
}
|
|
||||||
return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload);
|
|
||||||
}();
|
|
||||||
if (icon) {
|
|
||||||
icon->paintInCenter(p, inner);
|
|
||||||
}
|
|
||||||
if (radial && !cornerDownload) {
|
|
||||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
|
||||||
_animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::historyFileThumbRadialFgSelected : st::historyFileThumbRadialFg);
|
|
||||||
}
|
|
||||||
|
|
||||||
drawCornerStatus(p, selected);
|
|
||||||
|
|
||||||
// date
|
|
||||||
if (!_caption.isEmpty()) {
|
|
||||||
auto outbg = _parent->hasOutLayout();
|
|
||||||
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
|
|
||||||
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection);
|
|
||||||
} else if (_parent->media() == this) {
|
|
||||||
auto fullRight = paintx + paintw, fullBottom = painty + painth;
|
|
||||||
_parent->drawInfo(p, fullRight, fullBottom, 2 * paintx + paintw, selected, InfoDisplayType::Image);
|
|
||||||
if (!bubble && _parent->displayRightAction()) {
|
|
||||||
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
|
|
||||||
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
|
|
||||||
_parent->drawRightAction(p, fastShareLeft, fastShareTop, 2 * paintx + paintw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::drawCornerStatus(Painter &p, bool selected) const {
|
|
||||||
const auto padding = st::msgDateImgPadding;
|
|
||||||
const auto radial = _animation && _animation->radial.animating();
|
|
||||||
const auto cornerDownload = downloadInCorner() && !_data->loaded() && !_data->loadedInMediaCache();
|
|
||||||
const auto addWidth = cornerDownload ? (st::historyVideoDownloadSize + 2 * padding.y()) : 0;
|
|
||||||
const auto downloadWidth = cornerDownload ? st::normalFont->width(_downloadSize) : 0;
|
|
||||||
const auto statusW = std::max(downloadWidth, st::normalFont->width(_statusText)) + 2 * padding.x() + addWidth;
|
|
||||||
const auto statusH = cornerDownload ? (st::historyVideoDownloadSize + 2 * padding.y()) : (st::normalFont->height + 2 * padding.y());
|
|
||||||
const auto statusX = st::msgDateImgDelta + padding.x();
|
|
||||||
const auto statusY = st::msgDateImgDelta + padding.y();
|
|
||||||
const auto around = style::rtlrect(statusX - padding.x(), statusY - padding.y(), statusW, statusH, width());
|
|
||||||
const auto statusTextTop = statusY + (cornerDownload ? (((statusH - 2 * st::normalFont->height) / 3) - padding.y()) : 0);
|
|
||||||
App::roundRect(p, around, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
|
|
||||||
p.setFont(st::normalFont);
|
|
||||||
p.setPen(st::msgDateImgFg);
|
|
||||||
p.drawTextLeft(statusX + addWidth, statusTextTop, width(), _statusText, statusW - 2 * padding.x());
|
|
||||||
if (cornerDownload) {
|
|
||||||
const auto downloadTextTop = statusY + st::normalFont->height + (2 * (statusH - 2 * st::normalFont->height) / 3) - padding.y();
|
|
||||||
p.drawTextLeft(statusX + addWidth, downloadTextTop, width(), _downloadSize, statusW - 2 * padding.x());
|
|
||||||
const auto inner = QRect(statusX + padding.y() - padding.x(), statusY, st::historyVideoDownloadSize, st::historyVideoDownloadSize);
|
|
||||||
const auto icon = [&]() -> const style::icon * {
|
|
||||||
if (_data->loading()) {
|
|
||||||
return &(selected ? st::historyVideoCancelSelected : st::historyVideoCancel);
|
|
||||||
}
|
|
||||||
return &(selected ? st::historyVideoDownloadSelected : st::historyVideoDownload);
|
|
||||||
}();
|
|
||||||
if (icon) {
|
|
||||||
icon->paintInCenter(p, inner);
|
|
||||||
}
|
|
||||||
if (radial) {
|
|
||||||
QRect rinner(inner.marginsRemoved(QMargins(st::historyVideoRadialLine, st::historyVideoRadialLine, st::historyVideoRadialLine, st::historyVideoRadialLine)));
|
|
||||||
_animation->radial.draw(p, rinner, st::historyVideoRadialLine, selected ? st::historyFileThumbRadialFgSelected : st::historyFileThumbRadialFg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextState Video::cornerStatusTextState(
|
|
||||||
QPoint point,
|
|
||||||
StateRequest request) const {
|
|
||||||
auto result = TextState(_parent);
|
|
||||||
if (!downloadInCorner() || _data->loaded()) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
const auto padding = st::msgDateImgPadding;
|
|
||||||
const auto addWidth = st::historyVideoDownloadSize + 2 * padding.y() - padding.x();
|
|
||||||
const auto statusX = st::msgDateImgDelta + padding.x(), statusY = st::msgDateImgDelta + padding.y();
|
|
||||||
const auto inner = QRect(statusX + padding.y() - padding.x(), statusY, st::historyVideoDownloadSize, st::historyVideoDownloadSize);
|
|
||||||
if (inner.contains(point)) {
|
|
||||||
result.link = _data->loading() ? _cancell : _savel;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextState Video::textState(QPoint point, StateRequest request) const {
|
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = TextState(_parent);
|
|
||||||
|
|
||||||
auto paintx = 0, painty = 0, paintw = width(), painth = height();
|
|
||||||
bool bubble = _parent->hasBubble();
|
|
||||||
|
|
||||||
if (bubble && !_caption.isEmpty()) {
|
|
||||||
const auto captionw = paintw
|
|
||||||
- st::msgPadding.left()
|
|
||||||
- st::msgPadding.right();
|
|
||||||
painth -= _caption.countHeight(captionw);
|
|
||||||
if (isBubbleBottom()) {
|
|
||||||
painth -= st::msgPadding.bottom();
|
|
||||||
}
|
|
||||||
if (QRect(st::msgPadding.left(), painth, captionw, height() - painth).contains(point)) {
|
|
||||||
result = TextState(_parent, _caption.getState(
|
|
||||||
point - QPoint(st::msgPadding.left(), painth),
|
|
||||||
captionw,
|
|
||||||
request.forText()));
|
|
||||||
}
|
|
||||||
painth -= st::mediaCaptionSkip;
|
|
||||||
}
|
|
||||||
if (const auto state = cornerStatusTextState(point, request); state.link) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
if (QRect(paintx, painty, paintw, painth).contains(point)) {
|
|
||||||
if (!downloadInCorner() && (_data->loading() || _data->uploading())) {
|
|
||||||
result.link = _cancell;
|
|
||||||
} else if (!IsServerMsgId(_parent->data()->id)) {
|
|
||||||
} else if (_data->loaded() || _data->canBePlayed()) {
|
|
||||||
result.link = _openl;
|
|
||||||
} else {
|
|
||||||
result.link = _savel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_caption.isEmpty() && _parent->media() == this) {
|
|
||||||
auto fullRight = paintx + paintw;
|
|
||||||
auto fullBottom = painty + painth;
|
|
||||||
if (_parent->pointInTime(fullRight, fullBottom, point, InfoDisplayType::Image)) {
|
|
||||||
result.cursor = CursorState::Date;
|
|
||||||
}
|
|
||||||
if (!bubble && _parent->displayRightAction()) {
|
|
||||||
auto fastShareLeft = (fullRight + st::historyFastShareLeft);
|
|
||||||
auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize);
|
|
||||||
if (QRect(fastShareLeft, fastShareTop, st::historyFastShareSize, st::historyFastShareSize).contains(point)) {
|
|
||||||
result.link = _parent->rightActionLink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize Video::sizeForGrouping() const {
|
|
||||||
return sizeForAspectRatio();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::drawGrouped(
|
|
||||||
Painter &p,
|
|
||||||
const QRect &clip,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
|
||||||
RectParts corners,
|
|
||||||
not_null<uint64*> cacheKey,
|
|
||||||
not_null<QPixmap*> cache) const {
|
|
||||||
_data->automaticLoad(_realParent->fullId(), _parent->data());
|
|
||||||
|
|
||||||
validateGroupedCache(geometry, corners, cacheKey, cache);
|
|
||||||
|
|
||||||
const auto selected = (selection == FullSelection);
|
|
||||||
const auto loaded = _data->loaded();
|
|
||||||
const auto displayLoading = _data->displayLoading();
|
|
||||||
const auto bubble = _parent->hasBubble();
|
|
||||||
|
|
||||||
if (displayLoading) {
|
|
||||||
ensureAnimation();
|
|
||||||
if (!_animation->radial.animating()) {
|
|
||||||
_animation->radial.start(_data->progress());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto radial = isRadialAnimation();
|
|
||||||
|
|
||||||
if (!bubble) {
|
|
||||||
// App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
|
|
||||||
}
|
|
||||||
p.drawPixmap(geometry.topLeft(), *cache);
|
|
||||||
if (selected) {
|
|
||||||
const auto roundRadius = ImageRoundRadius::Large;
|
|
||||||
App::complexOverlayRect(p, geometry, roundRadius, corners);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto radialOpacity = radial
|
|
||||||
? _animation->radial.opacity()
|
|
||||||
: 1.;
|
|
||||||
const auto backOpacity = (loaded && !_data->uploading())
|
|
||||||
? radialOpacity
|
|
||||||
: 1.;
|
|
||||||
const auto radialSize = st::historyGroupRadialSize;
|
|
||||||
const auto inner = QRect(
|
|
||||||
geometry.x() + (geometry.width() - radialSize) / 2,
|
|
||||||
geometry.y() + (geometry.height() - radialSize) / 2,
|
|
||||||
radialSize,
|
|
||||||
radialSize);
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
if (selected) {
|
|
||||||
p.setBrush(st::msgDateImgBgSelected);
|
|
||||||
} else if (isThumbAnimation()) {
|
|
||||||
auto over = _animation->a_thumbOver.value(1.);
|
|
||||||
p.setBrush(anim::brush(st::msgDateImgBg, st::msgDateImgBgOver, over));
|
|
||||||
} else {
|
|
||||||
auto over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel);
|
|
||||||
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setOpacity(backOpacity * p.opacity());
|
|
||||||
|
|
||||||
{
|
|
||||||
PainterHighQualityEnabler hq(p);
|
|
||||||
p.drawEllipse(inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto icon = [&]() -> const style::icon * {
|
|
||||||
if (_data->waitingForAlbum()) {
|
|
||||||
return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting);
|
|
||||||
} else if (_data->loading() || _data->uploading()) {
|
|
||||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
|
||||||
} else if (!IsServerMsgId(_realParent->id)) {
|
|
||||||
return nullptr;
|
|
||||||
} else if (loaded || _data->canBePlayed()) {
|
|
||||||
return &(selected ? st::historyFileThumbPlaySelected : st::historyFileThumbPlay);
|
|
||||||
}
|
|
||||||
return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload);
|
|
||||||
}();
|
|
||||||
const auto previous = [&]() -> const style::icon* {
|
|
||||||
if (_data->waitingForAlbum()) {
|
|
||||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}();
|
|
||||||
p.setOpacity(backOpacity);
|
|
||||||
if (icon) {
|
|
||||||
if (previous && radialOpacity > 0. && radialOpacity < 1.) {
|
|
||||||
PaintInterpolatedIcon(p, *icon, *previous, radialOpacity, inner);
|
|
||||||
} else {
|
|
||||||
icon->paintInCenter(p, inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.setOpacity(1);
|
|
||||||
if (radial) {
|
|
||||||
const auto line = st::historyGroupRadialLine;
|
|
||||||
const auto rinner = inner.marginsRemoved({ line, line, line, line });
|
|
||||||
const auto color = selected
|
|
||||||
? st::historyFileThumbRadialFgSelected
|
|
||||||
: st::historyFileThumbRadialFg;
|
|
||||||
_animation->radial.draw(p, rinner, line, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextState Video::getStateGrouped(
|
|
||||||
const QRect &geometry,
|
|
||||||
QPoint point,
|
|
||||||
StateRequest request) const {
|
|
||||||
if (!geometry.contains(point)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return TextState(_parent, (_data->loading() || _data->uploading())
|
|
||||||
? _cancell
|
|
||||||
: !IsServerMsgId(_realParent->id)
|
|
||||||
? nullptr
|
|
||||||
: (_data->loaded() || _data->canBePlayed())
|
|
||||||
? _openl
|
|
||||||
: _savel);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::uploading() const {
|
|
||||||
return _data->uploading();
|
|
||||||
}
|
|
||||||
|
|
||||||
float64 Video::dataProgress() const {
|
|
||||||
return _data->progress();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::dataFinished() const {
|
|
||||||
return !_data->loading()
|
|
||||||
&& (!_data->uploading() || _data->waitingForAlbum());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::dataLoaded() const {
|
|
||||||
return _data->loaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::validateGroupedCache(
|
|
||||||
const QRect &geometry,
|
|
||||||
RectParts corners,
|
|
||||||
not_null<uint64*> cacheKey,
|
|
||||||
not_null<QPixmap*> cache) const {
|
|
||||||
using Option = Images::Option;
|
|
||||||
const auto good = _data->goodThumbnail();
|
|
||||||
const auto useGood = (good && good->loaded());
|
|
||||||
const auto thumb = _data->thumbnail();
|
|
||||||
const auto useThumb = (thumb && thumb->loaded());
|
|
||||||
const auto image = useGood
|
|
||||||
? good
|
|
||||||
: useThumb
|
|
||||||
? thumb
|
|
||||||
: _data->thumbnailInline();
|
|
||||||
if (good && !useGood) {
|
|
||||||
good->load({});
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto loadLevel = useGood ? 3 : useThumb ? 2 : image ? 1 : 0;
|
|
||||||
const auto width = geometry.width();
|
|
||||||
const auto height = geometry.height();
|
|
||||||
const auto options = Option::Smooth
|
|
||||||
| Option::RoundedLarge
|
|
||||||
| (useGood ? Option(0) : Option::Blurred)
|
|
||||||
| ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None)
|
|
||||||
| ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None)
|
|
||||||
| ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None)
|
|
||||||
| ((corners & RectPart::BottomRight) ? Option::RoundedBottomRight : Option::None);
|
|
||||||
const auto key = (uint64(width) << 48)
|
|
||||||
| (uint64(height) << 32)
|
|
||||||
| (uint64(options) << 16)
|
|
||||||
| (uint64(loadLevel));
|
|
||||||
if (*cacheKey == key) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto original = sizeForAspectRatio();
|
|
||||||
const auto originalWidth = style::ConvertScale(original.width());
|
|
||||||
const auto originalHeight = style::ConvertScale(original.height());
|
|
||||||
const auto pixSize = Ui::GetImageScaleSizeForGeometry(
|
|
||||||
{ originalWidth, originalHeight },
|
|
||||||
{ width, height });
|
|
||||||
const auto pixWidth = pixSize.width() * cIntRetinaFactor();
|
|
||||||
const auto pixHeight = pixSize.height() * cIntRetinaFactor();
|
|
||||||
|
|
||||||
*cacheKey = key;
|
|
||||||
*cache = (image ? image : Image::BlankMedia().get())->pixNoCache(
|
|
||||||
_realParent->fullId(),
|
|
||||||
pixWidth,
|
|
||||||
pixHeight,
|
|
||||||
options,
|
|
||||||
width,
|
|
||||||
height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::setStatusSize(int newSize) const {
|
|
||||||
File::setStatusSize(newSize, _data->size, _data->getDuration(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextForMimeData Video::selectedText(TextSelection selection) const {
|
|
||||||
return _caption.toTextForMimeData(selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::needsBubble() const {
|
|
||||||
if (!_caption.isEmpty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const auto item = _parent->data();
|
|
||||||
return item->viaBot()
|
|
||||||
|| item->Has<HistoryMessageReply>()
|
|
||||||
|| _parent->displayForwardedFrom()
|
|
||||||
|| _parent->displayFromName();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::parentTextUpdated() {
|
|
||||||
_caption = (_parent->media() == this)
|
|
||||||
? createCaption(_parent->data())
|
|
||||||
: Ui::Text::String();
|
|
||||||
history()->owner().requestViewResize(_parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::updateStatusText() const {
|
|
||||||
auto showPause = false;
|
|
||||||
auto statusSize = 0;
|
|
||||||
auto realDuration = 0;
|
|
||||||
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
|
||||||
statusSize = FileStatusSizeFailed;
|
|
||||||
} else if (_data->uploading()) {
|
|
||||||
statusSize = _data->uploadingData->offset;
|
|
||||||
} else if (!downloadInCorner() && _data->loading()) {
|
|
||||||
statusSize = _data->loadOffset();
|
|
||||||
} else if (_data->canBePlayed()) {
|
|
||||||
statusSize = FileStatusSizeLoaded;
|
|
||||||
} else {
|
|
||||||
statusSize = FileStatusSizeReady;
|
|
||||||
}
|
|
||||||
if (statusSize != _statusSize) {
|
|
||||||
setStatusSize(statusSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace HistoryView
|
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop application for the Telegram messaging service.
|
|
||||||
|
|
||||||
For license and copyright information please follow this link:
|
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "history/view/media/history_view_file.h"
|
|
||||||
|
|
||||||
namespace HistoryView {
|
|
||||||
|
|
||||||
class Video : public File {
|
|
||||||
public:
|
|
||||||
Video(
|
|
||||||
not_null<Element*> parent,
|
|
||||||
not_null<HistoryItem*> realParent,
|
|
||||||
not_null<DocumentData*> document);
|
|
||||||
|
|
||||||
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
|
|
||||||
TextState textState(QPoint point, StateRequest request) const override;
|
|
||||||
|
|
||||||
[[nodiscard]] TextSelection adjustSelection(
|
|
||||||
TextSelection selection,
|
|
||||||
TextSelectType type) const override {
|
|
||||||
return _caption.adjustSelection(selection, type);
|
|
||||||
}
|
|
||||||
uint16 fullSelectionLength() const override {
|
|
||||||
return _caption.length();
|
|
||||||
}
|
|
||||||
bool hasTextForCopy() const override {
|
|
||||||
return !_caption.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextForMimeData selectedText(TextSelection selection) const override;
|
|
||||||
|
|
||||||
DocumentData *getDocument() const override {
|
|
||||||
return _data;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize sizeForGrouping() const override;
|
|
||||||
void drawGrouped(
|
|
||||||
Painter &p,
|
|
||||||
const QRect &clip,
|
|
||||||
TextSelection selection,
|
|
||||||
crl::time ms,
|
|
||||||
const QRect &geometry,
|
|
||||||
RectParts corners,
|
|
||||||
not_null<uint64*> cacheKey,
|
|
||||||
not_null<QPixmap*> cache) const override;
|
|
||||||
TextState getStateGrouped(
|
|
||||||
const QRect &geometry,
|
|
||||||
QPoint point,
|
|
||||||
StateRequest request) const override;
|
|
||||||
|
|
||||||
bool uploading() const override;
|
|
||||||
|
|
||||||
TextWithEntities getCaption() const override {
|
|
||||||
return _caption.toTextWithEntities();
|
|
||||||
}
|
|
||||||
bool needsBubble() const override;
|
|
||||||
bool customInfoLayout() const override {
|
|
||||||
return _caption.isEmpty();
|
|
||||||
}
|
|
||||||
bool skipBubbleTail() const override {
|
|
||||||
return isBubbleBottom() && _caption.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void parentTextUpdated() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
float64 dataProgress() const override;
|
|
||||||
bool dataFinished() const override;
|
|
||||||
bool dataLoaded() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
[[nodiscard]] QSize countOptimalSize() override;
|
|
||||||
[[nodiscard]] QSize countCurrentSize(int newWidth) override;
|
|
||||||
[[nodiscard]] QSize countOptimalDimensions() const;
|
|
||||||
[[nodiscard]] bool downloadInCorner() const;
|
|
||||||
|
|
||||||
void drawCornerStatus(Painter &p, bool selected) const;
|
|
||||||
[[nodiscard]] TextState cornerStatusTextState(
|
|
||||||
QPoint point,
|
|
||||||
StateRequest request) const;
|
|
||||||
|
|
||||||
void validateGroupedCache(
|
|
||||||
const QRect &geometry,
|
|
||||||
RectParts corners,
|
|
||||||
not_null<uint64*> cacheKey,
|
|
||||||
not_null<QPixmap*> cache) const;
|
|
||||||
void setStatusSize(int newSize) const;
|
|
||||||
void updateStatusText() const;
|
|
||||||
QSize sizeForAspectRatio() const;
|
|
||||||
|
|
||||||
not_null<DocumentData*> _data;
|
|
||||||
int _thumbw = 1;
|
|
||||||
int _thumbh = 1;
|
|
||||||
Ui::Text::String _caption;
|
|
||||||
|
|
||||||
QString _downloadSize;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace HistoryView
|
|
Loading…
Reference in New Issue