mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Show captions with darkening over stories.
This commit is contained in:
parent
0d3df824e3
commit
0331955ce7
12 changed files with 151 additions and 72 deletions
|
@ -28,7 +28,7 @@ namespace {
|
||||||
|
|
||||||
constexpr auto kPhotoProgressInterval = crl::time(100);
|
constexpr auto kPhotoProgressInterval = crl::time(100);
|
||||||
constexpr auto kPhotoDuration = 5 * crl::time(1000);
|
constexpr auto kPhotoDuration = 5 * crl::time(1000);
|
||||||
constexpr auto kFullContentFade = 0.2;
|
constexpr auto kFullContentFade = 0.35;
|
||||||
constexpr auto kSiblingMultiplier = 0.448;
|
constexpr auto kSiblingMultiplier = 0.448;
|
||||||
constexpr auto kSiblingOutsidePart = 0.24;
|
constexpr auto kSiblingOutsidePart = 0.24;
|
||||||
constexpr auto kSiblingUserpicSize = 0.3;
|
constexpr auto kSiblingUserpicSize = 0.3;
|
||||||
|
@ -276,14 +276,22 @@ rpl::producer<Layout> Controller::layoutValue() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentLayout Controller::contentLayout() const {
|
ContentLayout Controller::contentLayout() const {
|
||||||
|
const auto ¤t = _layout.current();
|
||||||
|
Assert(current.has_value());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
.geometry = _layout.current()->content,
|
.geometry = current->content,
|
||||||
.fade = (_contentFadeAnimation.value(_contentFaded ? 1. : 0.)
|
.fade = (_contentFadeAnimation.value(_contentFaded ? 1. : 0.)
|
||||||
* kFullContentFade),
|
* kFullContentFade),
|
||||||
.radius = float64(st::storiesRadius),
|
.radius = st::storiesRadius,
|
||||||
|
.headerOutside = (current->headerLayout == HeaderLayout::Outside),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextWithEntities Controller::captionText() const {
|
||||||
|
return _captionText;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<ChatHelpers::Show> Controller::uiShow() const {
|
std::shared_ptr<ChatHelpers::Show> Controller::uiShow() const {
|
||||||
return _delegate->storiesShow();
|
return _delegate->storiesShow();
|
||||||
}
|
}
|
||||||
|
@ -325,6 +333,7 @@ void Controller::show(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_shown = id;
|
_shown = id;
|
||||||
|
_captionText = item.caption;
|
||||||
|
|
||||||
_header->show({ .user = list.user, .date = item.date });
|
_header->show({ .user = list.user, .date = item.date });
|
||||||
_slider->show({ .index = _index, .total = list.total });
|
_slider->show({ .index = _index, .total = list.total });
|
||||||
|
|
|
@ -77,6 +77,7 @@ public:
|
||||||
[[nodiscard]] Layout layout() const;
|
[[nodiscard]] Layout layout() const;
|
||||||
[[nodiscard]] rpl::producer<Layout> layoutValue() const;
|
[[nodiscard]] rpl::producer<Layout> layoutValue() const;
|
||||||
[[nodiscard]] ContentLayout contentLayout() const;
|
[[nodiscard]] ContentLayout contentLayout() const;
|
||||||
|
[[nodiscard]] TextWithEntities captionText() const;
|
||||||
|
|
||||||
[[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
|
[[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
|
||||||
[[nodiscard]] auto stickerOrEmojiChosen() const
|
[[nodiscard]] auto stickerOrEmojiChosen() const
|
||||||
|
@ -134,6 +135,7 @@ private:
|
||||||
bool _contentFaded = false;
|
bool _contentFaded = false;
|
||||||
|
|
||||||
Data::FullStoryId _shown;
|
Data::FullStoryId _shown;
|
||||||
|
TextWithEntities _captionText;
|
||||||
std::optional<Data::StoriesList> _list;
|
std::optional<Data::StoriesList> _list;
|
||||||
int _index = 0;
|
int _index = 0;
|
||||||
bool _started = false;
|
bool _started = false;
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Media::Stories {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kNameOpacity = 1.;
|
constexpr auto kNameOpacity = 1.;
|
||||||
constexpr auto kDateOpacity = 0.6;
|
constexpr auto kDateOpacity = 0.8;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -256,7 +256,7 @@ SiblingView Sibling::view(const SiblingLayout &layout, float64 over) {
|
||||||
.layout = {
|
.layout = {
|
||||||
.geometry = layout.geometry,
|
.geometry = layout.geometry,
|
||||||
.fade = kSiblingFade * (1 - over) + kSiblingFadeOver * over,
|
.fade = kSiblingFade * (1 - over) + kSiblingFadeOver * over,
|
||||||
.radius = float64(st::storiesRadius),
|
.radius = st::storiesRadius,
|
||||||
},
|
},
|
||||||
.userpic = userpicImage(layout),
|
.userpic = userpicImage(layout),
|
||||||
.userpicPosition = layout.userpic.topLeft(),
|
.userpicPosition = layout.userpic.topLeft(),
|
||||||
|
|
|
@ -79,6 +79,10 @@ SiblingView View::sibling(SiblingType type) const {
|
||||||
return _controller->sibling(type);
|
return _controller->sibling(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextWithEntities View::captionText() const {
|
||||||
|
return _controller->captionText();
|
||||||
|
}
|
||||||
|
|
||||||
rpl::lifetime &View::lifetime() {
|
rpl::lifetime &View::lifetime() {
|
||||||
return _controller->lifetime();
|
return _controller->lifetime();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@ class Controller;
|
||||||
struct ContentLayout {
|
struct ContentLayout {
|
||||||
QRect geometry;
|
QRect geometry;
|
||||||
float64 fade = 0.;
|
float64 fade = 0.;
|
||||||
float64 radius = 0.;
|
int radius = 0;
|
||||||
|
bool headerOutside = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SiblingType;
|
enum class SiblingType;
|
||||||
|
@ -61,6 +62,7 @@ public:
|
||||||
[[nodiscard]] rpl::producer<QRect> finalShownGeometryValue() const;
|
[[nodiscard]] rpl::producer<QRect> finalShownGeometryValue() const;
|
||||||
[[nodiscard]] ContentLayout contentLayout() const;
|
[[nodiscard]] ContentLayout contentLayout() const;
|
||||||
[[nodiscard]] SiblingView sibling(SiblingType type) const;
|
[[nodiscard]] SiblingView sibling(SiblingType type) const;
|
||||||
|
[[nodiscard]] TextWithEntities captionText() const;
|
||||||
|
|
||||||
void updatePlayback(const Player::TrackState &state);
|
void updatePlayback(const Player::TrackState &state);
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,7 @@ mediaviewSaveMsgStyle: TextStyle(defaultTextStyle) {
|
||||||
mediaviewTextPalette: TextPalette(defaultTextPalette) {
|
mediaviewTextPalette: TextPalette(defaultTextPalette) {
|
||||||
linkFg: mediaviewTextLinkFg;
|
linkFg: mediaviewTextLinkFg;
|
||||||
monoFg: mediaviewCaptionFg;
|
monoFg: mediaviewCaptionFg;
|
||||||
|
spoilerFg: mediaviewCaptionFg;
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaviewCaptionStyle: defaultTextStyle;
|
mediaviewCaptionStyle: defaultTextStyle;
|
||||||
|
@ -429,6 +430,8 @@ storiesHeaderDate: FlatLabel(defaultFlatLabel) {
|
||||||
textFg: mediaviewControlFg;
|
textFg: mediaviewControlFg;
|
||||||
}
|
}
|
||||||
storiesHeaderDatePosition: point(50px, 17px);
|
storiesHeaderDatePosition: point(50px, 17px);
|
||||||
|
storiesShadowTop: icon{{ "mediaview/shadow_bottom-flip_vertical", windowShadowFg }};
|
||||||
|
storiesShadowBottom: mediaviewShadowBottom;
|
||||||
storiesControlsMinWidth: 200px;
|
storiesControlsMinWidth: 200px;
|
||||||
storiesFieldMargin: margins(0px, 14px, 0px, 16px);
|
storiesFieldMargin: margins(0px, 14px, 0px, 16px);
|
||||||
storiesAttach: IconButton(defaultIconButton) {
|
storiesAttach: IconButton(defaultIconButton) {
|
||||||
|
|
|
@ -36,13 +36,14 @@ constexpr auto kControlValues = 4 * 4 + 4 * 4; // over + icon
|
||||||
.header = R"(
|
.header = R"(
|
||||||
uniform sampler2D f_texture;
|
uniform sampler2D f_texture;
|
||||||
uniform vec4 shadowTopRect;
|
uniform vec4 shadowTopRect;
|
||||||
uniform vec3 shadowBottomOpacityFullFade;
|
uniform vec4 shadowBottomSkipOpacityFullFade;
|
||||||
)",
|
)",
|
||||||
.body = R"(
|
.body = R"(
|
||||||
float topHeight = shadowTopRect.w;
|
float topHeight = shadowTopRect.w;
|
||||||
float bottomHeight = shadowBottomOpacityFullFade.x;
|
float bottomHeight = shadowBottomSkipOpacityFullFade.x;
|
||||||
float opacity = shadowBottomOpacityFullFade.y;
|
float bottomSkip = shadowBottomSkipOpacityFullFade.y;
|
||||||
float fullFade = shadowBottomOpacityFullFade.z;
|
float opacity = shadowBottomSkipOpacityFullFade.z;
|
||||||
|
float fullFade = shadowBottomSkipOpacityFullFade.w;
|
||||||
float viewportHeight = shadowTopRect.y + topHeight;
|
float viewportHeight = shadowTopRect.y + topHeight;
|
||||||
float fullHeight = topHeight + bottomHeight;
|
float fullHeight = topHeight + bottomHeight;
|
||||||
float topY = min(
|
float topY = min(
|
||||||
|
@ -50,7 +51,8 @@ uniform vec3 shadowBottomOpacityFullFade;
|
||||||
topHeight / fullHeight);
|
topHeight / fullHeight);
|
||||||
float topX = (gl_FragCoord.x - shadowTopRect.x) / shadowTopRect.z;
|
float topX = (gl_FragCoord.x - shadowTopRect.x) / shadowTopRect.z;
|
||||||
vec4 fadeTop = texture2D(f_texture, vec2(topX, topY)) * opacity;
|
vec4 fadeTop = texture2D(f_texture, vec2(topX, topY)) * opacity;
|
||||||
float bottomY = max(fullHeight - gl_FragCoord.y, topHeight) / fullHeight;
|
float bottomY = max(bottomSkip + fullHeight - gl_FragCoord.y, topHeight)
|
||||||
|
/ fullHeight;
|
||||||
vec4 fadeBottom = texture2D(f_texture, vec2(0.5, bottomY)) * opacity;
|
vec4 fadeBottom = texture2D(f_texture, vec2(0.5, bottomY)) * opacity;
|
||||||
float fade = min((1. - fadeTop.a) * (1. - fadeBottom.a), fullFade);
|
float fade = min((1. - fadeTop.a) * (1. - fadeBottom.a), fullFade);
|
||||||
result.rgb = result.rgb * fade;
|
result.rgb = result.rgb * fade;
|
||||||
|
@ -496,16 +498,30 @@ void OverlayWidget::RendererGL::paintTransformedContent(
|
||||||
_contentBuffer->write(0, coords, sizeof(coords));
|
_contentBuffer->write(0, coords, sizeof(coords));
|
||||||
|
|
||||||
program->setUniformValue("viewport", _uniformViewport);
|
program->setUniformValue("viewport", _uniformViewport);
|
||||||
const auto &top = st::mediaviewShadowTop.size();
|
if (_owner->_stories) {
|
||||||
const auto point = QPoint(
|
const auto &top = st::storiesShadowTop.size();
|
||||||
_shadowTopFlip ? 0 : (_viewport.width() - top.width()),
|
const auto shadowTop = geometry.topShadowShown
|
||||||
0);
|
? geometry.rect.y()
|
||||||
program->setUniformValue(
|
: geometry.rect.y() - top.height();
|
||||||
"shadowTopRect",
|
program->setUniformValue(
|
||||||
Uniform(transformRect(QRect(point, top))));
|
"shadowTopRect",
|
||||||
const auto &bottom = st::mediaviewShadowBottom;
|
Uniform(transformRect(
|
||||||
program->setUniformValue("shadowBottomOpacityFullFade", QVector3D(
|
QRect(QPoint(geometry.rect.x(), shadowTop), top))));
|
||||||
|
} else {
|
||||||
|
const auto &top = st::mediaviewShadowTop.size();
|
||||||
|
const auto point = QPoint(
|
||||||
|
_shadowTopFlip ? 0 : (_viewport.width() - top.width()),
|
||||||
|
0);
|
||||||
|
program->setUniformValue(
|
||||||
|
"shadowTopRect",
|
||||||
|
Uniform(transformRect(QRect(point, top))));
|
||||||
|
}
|
||||||
|
const auto &bottom = _owner->_stories
|
||||||
|
? st::storiesShadowBottom
|
||||||
|
: st::mediaviewShadowBottom;
|
||||||
|
program->setUniformValue("shadowBottomSkipOpacityFullFade", QVector4D(
|
||||||
bottom.height() * _factor,
|
bottom.height() * _factor,
|
||||||
|
geometry.bottomShadowSkip * _factor,
|
||||||
geometry.controlsOpacity,
|
geometry.controlsOpacity,
|
||||||
1.f - float(geometry.fade)));
|
1.f - float(geometry.fade)));
|
||||||
if (!fillTransparentBackground) {
|
if (!fillTransparentBackground) {
|
||||||
|
@ -733,14 +749,23 @@ void OverlayWidget::RendererGL::invalidateControls() {
|
||||||
|
|
||||||
void OverlayWidget::RendererGL::validateControlsFade() {
|
void OverlayWidget::RendererGL::validateControlsFade() {
|
||||||
const auto flip = !_owner->topShadowOnTheRight();
|
const auto flip = !_owner->topShadowOnTheRight();
|
||||||
|
const auto forStories = (_owner->_stories != nullptr);
|
||||||
if (!_controlsFadeImage.image().isNull()
|
if (!_controlsFadeImage.image().isNull()
|
||||||
&& _shadowTopFlip == flip) {
|
&& _shadowTopFlip == flip
|
||||||
|
&& _shadowsForStories == forStories) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_shadowTopFlip = flip;
|
_shadowTopFlip = flip;
|
||||||
const auto width = st::mediaviewShadowTop.width();
|
_shadowsForStories = forStories;
|
||||||
const auto bottomTop = st::mediaviewShadowTop.height();
|
const auto &top = _shadowsForStories
|
||||||
const auto height = bottomTop + st::mediaviewShadowBottom.height();
|
? st::storiesShadowTop
|
||||||
|
: st::mediaviewShadowTop;
|
||||||
|
const auto &bottom = _shadowsForStories
|
||||||
|
? st::storiesShadowBottom
|
||||||
|
: st::mediaviewShadowBottom;
|
||||||
|
const auto width = top.width();
|
||||||
|
const auto bottomTop = top.height();
|
||||||
|
const auto height = bottomTop + bottom.height();
|
||||||
|
|
||||||
auto image = QImage(
|
auto image = QImage(
|
||||||
QSize(width, height) * _factor,
|
QSize(width, height) * _factor,
|
||||||
|
@ -749,10 +774,10 @@ void OverlayWidget::RendererGL::validateControlsFade() {
|
||||||
image.setDevicePixelRatio(_factor);
|
image.setDevicePixelRatio(_factor);
|
||||||
|
|
||||||
auto p = QPainter(&image);
|
auto p = QPainter(&image);
|
||||||
st::mediaviewShadowTop.paint(p, 0, 0, width);
|
top.paint(p, 0, 0, width);
|
||||||
st::mediaviewShadowBottom.fill(
|
bottom.fill(
|
||||||
p,
|
p,
|
||||||
QRect(0, bottomTop, width, st::mediaviewShadowBottom.height()));
|
QRect(0, bottomTop, width, bottom.height()));
|
||||||
p.end();
|
p.end();
|
||||||
|
|
||||||
if (flip) {
|
if (flip) {
|
||||||
|
@ -760,12 +785,6 @@ void OverlayWidget::RendererGL::validateControlsFade() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_controlsFadeImage.setImage(std::move(image));
|
_controlsFadeImage.setImage(std::move(image));
|
||||||
_shadowTopTexture = QRect(
|
|
||||||
QPoint(),
|
|
||||||
QSize(width, st::mediaviewShadowTop.height()) * _factor);
|
|
||||||
_shadowBottomTexture = QRect(
|
|
||||||
QPoint(0, bottomTop) * _factor,
|
|
||||||
QSize(width, st::mediaviewShadowBottom.height()) * _factor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::RendererGL::paintFooter(QRect outer, float64 opacity) {
|
void OverlayWidget::RendererGL::paintFooter(QRect outer, float64 opacity) {
|
||||||
|
|
|
@ -153,10 +153,8 @@ private:
|
||||||
// Last one is for the over circle image.
|
// Last one is for the over circle image.
|
||||||
std::array<QRect, kControlsCount + 1> _controlsTextures;
|
std::array<QRect, kControlsCount + 1> _controlsTextures;
|
||||||
|
|
||||||
QRect _shadowTopTexture;
|
bool _shadowTopFlip = false;
|
||||||
QRect _shadowBottomTexture;
|
bool _shadowsForStories = false;
|
||||||
|
|
||||||
bool _shadowTopFlip;
|
|
||||||
bool _blendingEnabled = false;
|
bool _blendingEnabled = false;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
|
@ -113,11 +113,16 @@ void OverlayWidget::RendererSW::paintControlsFade(
|
||||||
_p->setOpacity(opacity);
|
_p->setOpacity(opacity);
|
||||||
_p->setClipRect(geometry);
|
_p->setClipRect(geometry);
|
||||||
const auto width = _owner->width();
|
const auto width = _owner->width();
|
||||||
const auto &top = st::mediaviewShadowTop;
|
|
||||||
const auto flip = !_owner->topShadowOnTheRight();
|
const auto flip = !_owner->topShadowOnTheRight();
|
||||||
const auto topShadow = QRect(
|
const auto stories = (_owner->_stories != nullptr);
|
||||||
QPoint(flip ? 0 : (width - top.width()), 0),
|
const auto &top = stories
|
||||||
top.size());
|
? st::storiesShadowTop
|
||||||
|
: st::mediaviewShadowTop;
|
||||||
|
const auto topShadow = stories
|
||||||
|
? QRect(geometry.topLeft(), QSize(geometry.width(), top.height()))
|
||||||
|
: QRect(
|
||||||
|
QPoint(flip ? 0 : (width - top.width()), 0),
|
||||||
|
top.size());
|
||||||
if (topShadow.intersected(geometry).intersects(_clipOuter)) {
|
if (topShadow.intersected(geometry).intersects(_clipOuter)) {
|
||||||
if (flip) {
|
if (flip) {
|
||||||
if (_topShadowCache.isNull()
|
if (_topShadowCache.isNull()
|
||||||
|
@ -131,7 +136,9 @@ void OverlayWidget::RendererSW::paintControlsFade(
|
||||||
top.paint(*_p, topShadow.topLeft(), width);
|
top.paint(*_p, topShadow.topLeft(), width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto &bottom = st::mediaviewShadowBottom;
|
const auto &bottom = stories
|
||||||
|
? st::storiesShadowBottom
|
||||||
|
: st::mediaviewShadowBottom;
|
||||||
const auto bottomShadow = QRect(
|
const auto bottomShadow = QRect(
|
||||||
QPoint(0, _owner->height() - bottom.height()),
|
QPoint(0, _owner->height() - bottom.height()),
|
||||||
QSize(width, bottom.height()));
|
QSize(width, bottom.height()));
|
||||||
|
|
|
@ -127,6 +127,7 @@ constexpr auto kIdsPreloadAfter = 28;
|
||||||
|
|
||||||
constexpr auto kLeftSiblingTextureIndex = 1;
|
constexpr auto kLeftSiblingTextureIndex = 1;
|
||||||
constexpr auto kRightSiblingTextureIndex = 2;
|
constexpr auto kRightSiblingTextureIndex = 2;
|
||||||
|
constexpr auto kStoriesControlsOpacity = 1.;
|
||||||
|
|
||||||
class PipDelegate final : public Pip::Delegate {
|
class PipDelegate final : public Pip::Delegate {
|
||||||
public:
|
public:
|
||||||
|
@ -1200,27 +1201,35 @@ void OverlayWidget::refreshCaptionGeometry() {
|
||||||
_groupThumbs = nullptr;
|
_groupThumbs = nullptr;
|
||||||
_groupThumbsRect = QRect();
|
_groupThumbsRect = QRect();
|
||||||
}
|
}
|
||||||
const auto captionBottom = (_streamed && _streamed->controls)
|
const auto captionBottom = _stories
|
||||||
|
? (_y + _h)
|
||||||
|
: (_streamed && _streamed->controls)
|
||||||
? (_streamed->controls->y() - st::mediaviewCaptionMargin.height())
|
? (_streamed->controls->y() - st::mediaviewCaptionMargin.height())
|
||||||
: _groupThumbs
|
: _groupThumbs
|
||||||
? _groupThumbsTop
|
? _groupThumbsTop
|
||||||
: height() - st::mediaviewCaptionMargin.height();
|
: height() - st::mediaviewCaptionMargin.height();
|
||||||
const auto captionWidth = std::min(
|
const auto captionWidth = _stories
|
||||||
_groupThumbsAvailableWidth
|
? (_w
|
||||||
- st::mediaviewCaptionPadding.left()
|
- st::mediaviewCaptionPadding.left()
|
||||||
- st::mediaviewCaptionPadding.right(),
|
- st::mediaviewCaptionPadding.right())
|
||||||
_caption.maxWidth());
|
: std::min(
|
||||||
const auto captionHeight = std::min(
|
(_groupThumbsAvailableWidth
|
||||||
_caption.countHeight(captionWidth),
|
- st::mediaviewCaptionPadding.left()
|
||||||
height() / 4
|
- st::mediaviewCaptionPadding.right()),
|
||||||
|
_caption.maxWidth());
|
||||||
|
const auto maxHeight = (_stories ? (_h / 3) : (height() / 4))
|
||||||
- st::mediaviewCaptionPadding.top()
|
- st::mediaviewCaptionPadding.top()
|
||||||
- st::mediaviewCaptionPadding.bottom()
|
- st::mediaviewCaptionPadding.bottom()
|
||||||
- 2 * st::mediaviewCaptionMargin.height());
|
- (_stories ? 0 : (2 * st::mediaviewCaptionMargin.height()));
|
||||||
|
const auto lineHeight = st::mediaviewCaptionStyle.font->height;
|
||||||
|
const auto captionHeight = std::min(
|
||||||
|
_caption.countHeight(captionWidth),
|
||||||
|
(maxHeight / lineHeight) * lineHeight);
|
||||||
_captionRect = QRect(
|
_captionRect = QRect(
|
||||||
(width() - captionWidth) / 2,
|
(width() - captionWidth) / 2,
|
||||||
captionBottom
|
(captionBottom
|
||||||
- captionHeight
|
- captionHeight
|
||||||
- st::mediaviewCaptionPadding.bottom(),
|
- st::mediaviewCaptionPadding.bottom()),
|
||||||
captionWidth,
|
captionWidth,
|
||||||
captionHeight);
|
captionHeight);
|
||||||
}
|
}
|
||||||
|
@ -1497,7 +1506,14 @@ QRect OverlayWidget::finalContentRect() const {
|
||||||
|
|
||||||
OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
|
OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
|
||||||
if (_stories) {
|
if (_stories) {
|
||||||
return storiesContentGeometry(_stories->contentLayout());
|
auto result = storiesContentGeometry(_stories->contentLayout());
|
||||||
|
if (!_caption.isEmpty()) {
|
||||||
|
result.bottomShadowSkip = _widget->height()
|
||||||
|
- _captionRect.y()
|
||||||
|
+ st::mediaviewCaptionStyle.font->height
|
||||||
|
- st::storiesShadowBottom.height();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
const auto controlsOpacity = _controlsOpacity.current();
|
const auto controlsOpacity = _controlsOpacity.current();
|
||||||
const auto toRotation = qreal(finalContentRotation());
|
const auto toRotation = qreal(finalContentRotation());
|
||||||
|
@ -1541,9 +1557,10 @@ OverlayWidget::ContentGeometry OverlayWidget::storiesContentGeometry(
|
||||||
const Stories::ContentLayout &layout) const {
|
const Stories::ContentLayout &layout) const {
|
||||||
return {
|
return {
|
||||||
.rect = QRectF(layout.geometry),
|
.rect = QRectF(layout.geometry),
|
||||||
.controlsOpacity = 0., // #TODO stories ?..
|
.controlsOpacity = kStoriesControlsOpacity,
|
||||||
.fade = layout.fade,
|
.fade = layout.fade,
|
||||||
.roundRadius = layout.radius,
|
.roundRadius = layout.radius,
|
||||||
|
.topShadowShown = !layout.headerOutside,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2708,21 +2725,26 @@ void OverlayWidget::refreshFromLabel() {
|
||||||
|
|
||||||
void OverlayWidget::refreshCaption() {
|
void OverlayWidget::refreshCaption() {
|
||||||
_caption = Ui::Text::String();
|
_caption = Ui::Text::String();
|
||||||
if (!_message) {
|
const auto caption = [&] {
|
||||||
return;
|
if (_message) {
|
||||||
} else if (const auto media = _message->media()) {
|
if (const auto media = _message->media()) {
|
||||||
if (media->webpage()) {
|
if (media->webpage()) {
|
||||||
return;
|
return TextWithEntities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _message->translatedText();
|
||||||
|
} else if (_stories) {
|
||||||
|
return _stories->captionText();
|
||||||
}
|
}
|
||||||
}
|
return TextWithEntities();
|
||||||
const auto caption = _message->translatedText();
|
}();
|
||||||
if (caption.text.isEmpty()) {
|
if (caption.text.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace HistoryView;
|
using namespace HistoryView;
|
||||||
_caption = Ui::Text::String(st::msgMinWidth);
|
_caption = Ui::Text::String(st::msgMinWidth);
|
||||||
const auto duration = (_streamed && _document)
|
const auto duration = (_streamed && _document && _message)
|
||||||
? DurationForTimestampLinks(_document)
|
? DurationForTimestampLinks(_document)
|
||||||
: 0;
|
: 0;
|
||||||
const auto base = duration
|
const auto base = duration
|
||||||
|
@ -2735,7 +2757,9 @@ void OverlayWidget::refreshCaption() {
|
||||||
update(captionGeometry());
|
update(captionGeometry());
|
||||||
};
|
};
|
||||||
const auto context = Core::MarkedTextContext{
|
const auto context = Core::MarkedTextContext{
|
||||||
.session = &_message->history()->session(),
|
.session = (_stories
|
||||||
|
? _storiesSession
|
||||||
|
: &_message->history()->session()),
|
||||||
.customEmojiRepaint = captionRepaint,
|
.customEmojiRepaint = captionRepaint,
|
||||||
};
|
};
|
||||||
_caption.setMarkedText(
|
_caption.setMarkedText(
|
||||||
|
@ -2743,7 +2767,9 @@ void OverlayWidget::refreshCaption() {
|
||||||
(base.isEmpty()
|
(base.isEmpty()
|
||||||
? caption
|
? caption
|
||||||
: AddTimestampLinks(caption, duration, base)),
|
: AddTimestampLinks(caption, duration, base)),
|
||||||
Ui::ItemTextOptions(_message),
|
(_message
|
||||||
|
? Ui::ItemTextOptions(_message)
|
||||||
|
: Ui::ItemTextDefaultOptions()),
|
||||||
context);
|
context);
|
||||||
if (_caption.hasSpoilers()) {
|
if (_caption.hasSpoilers()) {
|
||||||
const auto weak = Ui::MakeWeak(widget());
|
const auto weak = Ui::MakeWeak(widget());
|
||||||
|
@ -4627,10 +4653,15 @@ void OverlayWidget::paintCaptionContent(
|
||||||
QRect clip,
|
QRect clip,
|
||||||
float64 opacity) {
|
float64 opacity) {
|
||||||
const auto inner = outer.marginsRemoved(st::mediaviewCaptionPadding);
|
const auto inner = outer.marginsRemoved(st::mediaviewCaptionPadding);
|
||||||
p.setOpacity(opacity);
|
if (!_stories) {
|
||||||
p.setBrush(st::mediaviewCaptionBg);
|
p.setOpacity(opacity);
|
||||||
p.setPen(Qt::NoPen);
|
p.setBrush(st::mediaviewCaptionBg);
|
||||||
p.drawRoundedRect(outer, st::mediaviewCaptionRadius, st::mediaviewCaptionRadius);
|
p.setPen(Qt::NoPen);
|
||||||
|
p.drawRoundedRect(
|
||||||
|
outer,
|
||||||
|
st::mediaviewCaptionRadius,
|
||||||
|
st::mediaviewCaptionRadius);
|
||||||
|
}
|
||||||
if (inner.intersects(clip)) {
|
if (inner.intersects(clip)) {
|
||||||
p.setPen(st::mediaviewCaptionFg);
|
p.setPen(st::mediaviewCaptionFg);
|
||||||
_caption.draw(p, {
|
_caption.draw(p, {
|
||||||
|
|
|
@ -166,8 +166,12 @@ private:
|
||||||
QRectF rect;
|
QRectF rect;
|
||||||
qreal rotation = 0.;
|
qreal rotation = 0.;
|
||||||
qreal controlsOpacity = 0.;
|
qreal controlsOpacity = 0.;
|
||||||
|
|
||||||
|
// Stories.
|
||||||
qreal fade = 0.;
|
qreal fade = 0.;
|
||||||
qreal roundRadius = 0.;
|
int bottomShadowSkip = 0;
|
||||||
|
int roundRadius = 0;
|
||||||
|
bool topShadowShown = false;
|
||||||
};
|
};
|
||||||
struct StartStreaming {
|
struct StartStreaming {
|
||||||
StartStreaming() : continueStreaming(false), startTime(0) {
|
StartStreaming() : continueStreaming(false), startTime(0) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue