mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Implement nice expandable story caption viewer.
This commit is contained in:
parent
8cc90c3373
commit
5aa6102903
11 changed files with 259 additions and 137 deletions
|
@ -3846,6 +3846,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_stories_click_to_view" = "Click here to view updates from {users}.";
|
||||
"lng_stories_click_to_view_and_one" = "{accumulated}, {user}";
|
||||
"lng_stories_click_to_view_and_last" = "{accumulated} and {user}";
|
||||
"lng_stories_show_more" = "Show more";
|
||||
|
||||
"lng_stories_my_title" = "Saved Stories";
|
||||
"lng_stories_archive_button" = "Stories Archive";
|
||||
|
|
|
@ -147,6 +147,7 @@ void HiddenUrlClickHandler::Open(QString url, QVariant context) {
|
|||
my.show->showBox(std::move(box));
|
||||
} else if (use) {
|
||||
use->show(std::move(box));
|
||||
use->activate();
|
||||
}
|
||||
} else {
|
||||
open();
|
||||
|
|
|
@ -7,79 +7,168 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "media/stories/media_stories_caption_full_view.h"
|
||||
|
||||
#include "base/event_filter.h"
|
||||
#include "core/ui_integration.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "chat_helpers/compose/compose_show.h"
|
||||
#include "media/stories/media_stories_controller.h"
|
||||
#include "media/stories/media_stories_view.h"
|
||||
#include "ui/widgets/elastic_scroll.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/click_handler.h"
|
||||
#include "styles/style_media_view.h"
|
||||
|
||||
namespace Media::Stories {
|
||||
|
||||
CaptionFullView::CaptionFullView(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Main::Session*> session,
|
||||
const TextWithEntities &text,
|
||||
Fn<void()> close)
|
||||
: RpWidget(parent)
|
||||
, _scroll(std::make_unique<Ui::ScrollArea>((RpWidget*)this))
|
||||
, _text(_scroll->setOwnedWidget(
|
||||
CaptionFullView::CaptionFullView(not_null<Controller*> controller)
|
||||
: _controller(controller)
|
||||
, _scroll(std::make_unique<Ui::ElasticScroll>(controller->wrap()))
|
||||
, _wrap(_scroll->setOwnedWidget(
|
||||
object_ptr<Ui::PaddingWrap<Ui::FlatLabel>>(
|
||||
_scroll.get(),
|
||||
object_ptr<Ui::FlatLabel>(_scroll.get(), st::storiesCaptionFull),
|
||||
st::mediaviewCaptionPadding))->entity())
|
||||
, _close(std::move(close))
|
||||
, _background(st::storiesRadius, st::mediaviewCaptionBg) {
|
||||
_text->setMarkedText(text, Core::MarkedTextContext{
|
||||
.session = session,
|
||||
st::mediaviewCaptionPadding)))
|
||||
, _text(_wrap->entity()) {
|
||||
_text->setMarkedText(controller->captionText(), Core::MarkedTextContext{
|
||||
.session = &controller->uiShow()->session(),
|
||||
.customEmojiRepaint = [=] { _text->update(); },
|
||||
});
|
||||
|
||||
parent->sizeValue() | rpl::start_with_next([=](QSize size) {
|
||||
setGeometry(QRect(QPoint(), size));
|
||||
}, lifetime());
|
||||
startAnimation();
|
||||
_controller->layoutValue(
|
||||
) | rpl::start_with_next([=](const Layout &layout) {
|
||||
if (_outer != layout.content) {
|
||||
const auto skip = layout.header.y()
|
||||
+ layout.header.height()
|
||||
- layout.content.y();
|
||||
_outer = layout.content.marginsRemoved({ 0, skip, 0, 0 });
|
||||
updateGeometry();
|
||||
}
|
||||
}, _scroll->lifetime());
|
||||
|
||||
show();
|
||||
setFocus();
|
||||
const auto filter = [=](not_null<QEvent*> e) {
|
||||
const auto mouse = [&] {
|
||||
return static_cast<QMouseEvent*>(e.get());
|
||||
};
|
||||
const auto type = e->type();
|
||||
if (type == QEvent::MouseButtonPress
|
||||
&& mouse()->button() == Qt::LeftButton
|
||||
&& !ClickHandler::getActive()) {
|
||||
_down = true;
|
||||
} else if (type == QEvent::MouseButtonRelease && _down) {
|
||||
_down = false;
|
||||
if (!ClickHandler::getPressed()) {
|
||||
close();
|
||||
}
|
||||
} else if (type == QEvent::KeyPress
|
||||
&& static_cast<QKeyEvent*>(e.get())->key() == Qt::Key_Escape) {
|
||||
close();
|
||||
return base::EventFilterResult::Cancel;
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
};
|
||||
base::install_event_filter(_text.get(), filter);
|
||||
base::install_event_filter(_wrap.get(), filter);
|
||||
|
||||
using Type = Ui::ElasticScroll::OverscrollType;
|
||||
|
||||
rpl::combine(
|
||||
_scroll->positionValue(),
|
||||
_scroll->movementValue()
|
||||
) | rpl::filter([=] {
|
||||
return !_closing;
|
||||
}) | rpl::start_with_next([=](
|
||||
Ui::ElasticScrollPosition position,
|
||||
Ui::ElasticScrollMovement movement) {
|
||||
const auto overscrollTop = std::max(-position.overscroll, 0);
|
||||
using Phase = Ui::ElasticScrollMovement;
|
||||
if (movement == Phase::Progress) {
|
||||
if (overscrollTop > 0) {
|
||||
_pulling = true;
|
||||
} else {
|
||||
_pulling = false;
|
||||
}
|
||||
} else if (_pulling
|
||||
&& (movement == Phase::Momentum
|
||||
|| movement == Phase::Returning)) {
|
||||
_pulling = false;
|
||||
if (overscrollTop > st::storiesCaptionPullThreshold) {
|
||||
_closingTopAdded = overscrollTop;
|
||||
_scroll->setOverscrollTypes(Type::None, Type::Real);
|
||||
close();
|
||||
updateGeometry();
|
||||
}
|
||||
}
|
||||
}, _scroll->lifetime());
|
||||
|
||||
_scroll->show();
|
||||
_scroll->setOverscrollBg(QColor(0, 0, 0, 0));
|
||||
_scroll->setOverscrollTypes(Type::Real, Type::Real);
|
||||
_text->show();
|
||||
_text->setFocus();
|
||||
}
|
||||
|
||||
CaptionFullView::~CaptionFullView() = default;
|
||||
|
||||
void CaptionFullView::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
_background.paint(p, _scroll->geometry());
|
||||
_background.paint(p, _scroll->geometry());
|
||||
bool CaptionFullView::closing() const {
|
||||
return _closing;
|
||||
}
|
||||
|
||||
void CaptionFullView::resizeEvent(QResizeEvent *e) {
|
||||
const auto wanted = _text->naturalWidth();
|
||||
bool CaptionFullView::focused() const {
|
||||
return Ui::InFocusChain(_scroll.get());
|
||||
}
|
||||
|
||||
void CaptionFullView::close() {
|
||||
if (_closing) {
|
||||
return;
|
||||
}
|
||||
_closing = true;
|
||||
_controller->captionClosing();
|
||||
startAnimation();
|
||||
}
|
||||
|
||||
void CaptionFullView::updateGeometry() {
|
||||
if (_outer.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const auto lineHeight = st::mediaviewCaptionStyle.font->height;
|
||||
const auto padding = st::mediaviewCaptionPadding;
|
||||
const auto margin = st::mediaviewCaptionMargin * 2;
|
||||
const auto available = (rect() - padding).width()
|
||||
- (margin.width() * 2);
|
||||
const auto use = std::min(wanted, available);
|
||||
_text->resizeToWidth(use);
|
||||
const auto fullw = use + padding.left() + padding.right();
|
||||
const auto fullh = std::min(
|
||||
_text->height() + padding.top() + padding.bottom(),
|
||||
height() - (margin.height() * 2));
|
||||
const auto left = (width() - fullw) / 2;
|
||||
const auto top = (height() - fullh) / 2;
|
||||
_scroll->setGeometry(left, top, fullw, fullh);
|
||||
}
|
||||
|
||||
void CaptionFullView::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Escape) {
|
||||
if (const auto onstack = _close) {
|
||||
onstack();
|
||||
}
|
||||
_text->resizeToWidth(_outer.width() - padding.left() - padding.right());
|
||||
const auto add = padding.top() + padding.bottom();
|
||||
const auto maxShownHeight = lineHeight * kMaxShownCaptionLines;
|
||||
const auto shownHeight = (_text->height() > maxShownHeight)
|
||||
? (lineHeight * kCollapsedCaptionLines)
|
||||
: _text->height();
|
||||
const auto collapsedHeight = shownHeight + add;
|
||||
const auto addedToBottom = lineHeight;
|
||||
const auto expandedHeight = _text->height() + add + addedToBottom;
|
||||
const auto fullHeight = std::min(expandedHeight, _outer.height());
|
||||
const auto shown = _animation.value(_closing ? 0. : 1.);
|
||||
const auto height = (_closing || _animation.animating())
|
||||
? anim::interpolate(collapsedHeight, fullHeight, shown)
|
||||
: _outer.height();
|
||||
const auto added = anim::interpolate(0, _closingTopAdded, shown);
|
||||
const auto bottomPadding = anim::interpolate(0, addedToBottom, shown);
|
||||
const auto use = padding + ((_closing || _animation.animating())
|
||||
? QMargins(0, 0, 0, bottomPadding)
|
||||
: QMargins(0, height - fullHeight, 0, bottomPadding));
|
||||
_wrap->setPadding(use);
|
||||
_scroll->setGeometry(
|
||||
_outer.x(),
|
||||
added + _outer.y() + _outer.height() - height,
|
||||
_outer.width(),
|
||||
std::max(height - added, 0));
|
||||
if (_closing && !_animation.animating()) {
|
||||
_controller->captionClosed();
|
||||
}
|
||||
}
|
||||
|
||||
void CaptionFullView::mousePressEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
if (const auto onstack = _close) {
|
||||
onstack();
|
||||
}
|
||||
}
|
||||
void CaptionFullView::startAnimation() {
|
||||
_animation.start(
|
||||
[=] { updateGeometry(); },
|
||||
_closing ? 1. : 0.,
|
||||
_closing ? 0. : 1.,
|
||||
st::fadeWrapDuration,
|
||||
anim::sineInOut);
|
||||
}
|
||||
|
||||
} // namespace Media::Stories
|
||||
|
|
|
@ -7,8 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/round_rect.h"
|
||||
#include "ui/effects/animations.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
|
@ -16,30 +15,38 @@ class Session;
|
|||
|
||||
namespace Ui {
|
||||
class FlatLabel;
|
||||
class ScrollArea;
|
||||
class ElasticScroll;
|
||||
template <typename Widget>
|
||||
class PaddingWrap;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Media::Stories {
|
||||
|
||||
class CaptionFullView final : private Ui::RpWidget {
|
||||
class Controller;
|
||||
|
||||
class CaptionFullView final {
|
||||
public:
|
||||
CaptionFullView(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Main::Session*> session,
|
||||
const TextWithEntities &text,
|
||||
Fn<void()> close);
|
||||
explicit CaptionFullView(not_null<Controller*> controller);
|
||||
~CaptionFullView();
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void close();
|
||||
[[nodiscard]] bool closing() const;
|
||||
[[nodiscard]] bool focused() const;
|
||||
|
||||
std::unique_ptr<Ui::ScrollArea> _scroll;
|
||||
private:
|
||||
void updateGeometry();
|
||||
void startAnimation();
|
||||
|
||||
const not_null<Controller*> _controller;
|
||||
const std::unique_ptr<Ui::ElasticScroll> _scroll;
|
||||
const not_null<Ui::PaddingWrap<Ui::FlatLabel>*> _wrap;
|
||||
const not_null<Ui::FlatLabel*> _text;
|
||||
Fn<void()> _close;
|
||||
Ui::RoundRect _background;
|
||||
Ui::Animations::Simple _animation;
|
||||
QRect _outer;
|
||||
int _closingTopAdded = 0;
|
||||
bool _pulling = false;
|
||||
bool _closing = false;
|
||||
bool _down = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -280,9 +280,6 @@ Controller::Controller(not_null<Delegate*> delegate)
|
|||
_1 || _2
|
||||
) | rpl::distinct_until_changed(
|
||||
) | rpl::start_with_next([=](bool active) {
|
||||
if (active) {
|
||||
_captionFullView = nullptr;
|
||||
}
|
||||
_replyActive = active;
|
||||
updateContentFaded();
|
||||
}, _lifetime);
|
||||
|
@ -355,7 +352,8 @@ Controller::~Controller() {
|
|||
}
|
||||
|
||||
void Controller::updateContentFaded() {
|
||||
const auto faded = _replyActive || _captionFullView || _captionExpanded;
|
||||
const auto faded = _replyActive
|
||||
|| (_captionFullView && !_captionFullView->closing());
|
||||
if (_contentFaded == faded) {
|
||||
return;
|
||||
}
|
||||
|
@ -584,26 +582,31 @@ TextWithEntities Controller::captionText() const {
|
|||
return _captionText;
|
||||
}
|
||||
|
||||
void Controller::setCaptionExpanded(bool expanded) {
|
||||
if (_captionExpanded == expanded) {
|
||||
return;
|
||||
}
|
||||
_captionExpanded = expanded;
|
||||
updateContentFaded();
|
||||
bool Controller::skipCaption() const {
|
||||
return _captionFullView != nullptr;
|
||||
}
|
||||
|
||||
void Controller::showFullCaption() {
|
||||
if (_captionText.empty()) {
|
||||
return;
|
||||
}
|
||||
_captionFullView = std::make_unique<CaptionFullView>(
|
||||
wrap(),
|
||||
&_delegate->storiesShow()->session(),
|
||||
_captionText,
|
||||
[=] { _captionFullView = nullptr; updateContentFaded(); });
|
||||
_captionFullView = std::make_unique<CaptionFullView>(this);
|
||||
updateContentFaded();
|
||||
}
|
||||
|
||||
void Controller::captionClosing() {
|
||||
updateContentFaded();
|
||||
}
|
||||
|
||||
void Controller::captionClosed() {
|
||||
if (!_captionFullView) {
|
||||
return;
|
||||
} else if (_captionFullView->focused()) {
|
||||
_wrap->setFocus();
|
||||
}
|
||||
_captionFullView = nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatHelpers::Show> Controller::uiShow() const {
|
||||
return _delegate->storiesShow();
|
||||
}
|
||||
|
@ -820,9 +823,8 @@ void Controller::show(
|
|||
_slider->raise();
|
||||
}
|
||||
|
||||
captionClosed();
|
||||
_captionText = story->caption();
|
||||
_captionFullView = nullptr;
|
||||
_captionExpanded = false;
|
||||
_contentFaded = false;
|
||||
_contentFadeAnimation.stop();
|
||||
const auto document = story->document();
|
||||
|
@ -972,17 +974,13 @@ void Controller::updatePlayingAllowed() {
|
|||
&& _windowActive
|
||||
&& !_paused
|
||||
&& !_replyActive
|
||||
&& !_captionFullView
|
||||
&& !_captionExpanded
|
||||
&& (!_captionFullView || _captionFullView->closing())
|
||||
&& !_layerShown
|
||||
&& !_menuShown
|
||||
&& !_tooltipShown);
|
||||
}
|
||||
|
||||
void Controller::setPlayingAllowed(bool allowed) {
|
||||
if (allowed) {
|
||||
_captionFullView = nullptr;
|
||||
}
|
||||
if (_photoPlayback) {
|
||||
_photoPlayback->togglePaused(!allowed);
|
||||
} else {
|
||||
|
@ -1192,6 +1190,9 @@ void Controller::togglePaused(bool paused) {
|
|||
|
||||
void Controller::contentPressed(bool pressed) {
|
||||
togglePaused(pressed);
|
||||
if (_captionFullView) {
|
||||
_captionFullView->close();
|
||||
}
|
||||
if (pressed) {
|
||||
_reactions->collapse();
|
||||
}
|
||||
|
|
|
@ -122,8 +122,10 @@ public:
|
|||
[[nodiscard]] bool closeByClickAt(QPoint position) const;
|
||||
[[nodiscard]] Data::FileOrigin fileOrigin() const;
|
||||
[[nodiscard]] TextWithEntities captionText() const;
|
||||
void setCaptionExpanded(bool expanded);
|
||||
[[nodiscard]] bool skipCaption() const;
|
||||
void showFullCaption();
|
||||
void captionClosing();
|
||||
void captionClosed();
|
||||
|
||||
[[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
|
||||
[[nodiscard]] auto stickerOrEmojiChosen() const
|
||||
|
@ -250,7 +252,6 @@ private:
|
|||
Ui::Animations::Simple _contentFadeAnimation;
|
||||
bool _contentFaded = false;
|
||||
|
||||
bool _captionExpanded = false;
|
||||
bool _windowActive = false;
|
||||
bool _replyFocused = false;
|
||||
bool _replyActive = false;
|
||||
|
|
|
@ -123,8 +123,8 @@ TextWithEntities View::captionText() const {
|
|||
return _controller->captionText();
|
||||
}
|
||||
|
||||
void View::setCaptionExpanded(bool expanded) {
|
||||
_controller->setCaptionExpanded(expanded);
|
||||
bool View::skipCaption() const {
|
||||
return _controller->skipCaption();
|
||||
}
|
||||
|
||||
void View::showFullCaption() {
|
||||
|
|
|
@ -48,6 +48,9 @@ struct SiblingView {
|
|||
}
|
||||
};
|
||||
|
||||
inline constexpr auto kCollapsedCaptionLines = 2;
|
||||
inline constexpr auto kMaxShownCaptionLines = 4;
|
||||
|
||||
class View final {
|
||||
public:
|
||||
explicit View(not_null<Delegate*> delegate);
|
||||
|
@ -64,7 +67,7 @@ public:
|
|||
[[nodiscard]] SiblingView sibling(SiblingType type) const;
|
||||
[[nodiscard]] Data::FileOrigin fileOrigin() const;
|
||||
[[nodiscard]] TextWithEntities captionText() const;
|
||||
void setCaptionExpanded(bool expanded);
|
||||
[[nodiscard]] bool skipCaption() const;
|
||||
void showFullCaption();
|
||||
|
||||
void updatePlayback(const Player::TrackState &state);
|
||||
|
|
|
@ -445,7 +445,8 @@ storiesSideSkip: 145px;
|
|||
storiesCaptionFull: FlatLabel(defaultFlatLabel) {
|
||||
style: mediaviewCaptionStyle;
|
||||
textFg: mediaviewCaptionFg;
|
||||
minWidth: 360px;
|
||||
palette: mediaviewTextPalette;
|
||||
minWidth: 36px;
|
||||
}
|
||||
storiesComposeBg: groupCallMembersBg;
|
||||
storiesComposeBgOver: groupCallMembersBgOver;
|
||||
|
@ -908,3 +909,6 @@ storiesVolumeSlider: MediaSlider {
|
|||
storiesInfoTooltipLabel: defaultImportantTooltipLabel;
|
||||
storiesInfoTooltip: defaultImportantTooltip;
|
||||
storiesInfoTooltipMaxWidth: 360px;
|
||||
storiesCaptionPullThreshold: 50px;
|
||||
storiesShowMorePadding: margins(6px, 4px, 6px, 4px);
|
||||
storiesShowMoreFont: semiboldFont;
|
||||
|
|
|
@ -1383,6 +1383,10 @@ void OverlayWidget::resizeCenteredControls() {
|
|||
}
|
||||
|
||||
void OverlayWidget::refreshCaptionGeometry() {
|
||||
_caption.updateSkipBlock(0, 0);
|
||||
_captionShowMoreWidth = 0;
|
||||
_captionSkipBlockWidth = 0;
|
||||
|
||||
if (_caption.isEmpty()) {
|
||||
_captionRect = QRect();
|
||||
return;
|
||||
|
@ -1408,32 +1412,28 @@ void OverlayWidget::refreshCaptionGeometry() {
|
|||
- st::mediaviewCaptionPadding.left()
|
||||
- st::mediaviewCaptionPadding.right()),
|
||||
_caption.maxWidth());
|
||||
const auto maxExpandedOuterHeight = (_stories
|
||||
? (_h - st::storiesShadowTop.height())
|
||||
: _maxUsedHeight);
|
||||
const auto maxCollapsedOuterHeight = !_stories
|
||||
? (_maxUsedHeight / 4)
|
||||
: (_h / 3);
|
||||
const auto maxExpandedHeight = maxExpandedOuterHeight
|
||||
- st::mediaviewCaptionPadding.top()
|
||||
- st::mediaviewCaptionPadding.bottom();
|
||||
const auto maxCollapsedHeight = maxCollapsedOuterHeight
|
||||
- st::mediaviewCaptionPadding.top()
|
||||
- st::mediaviewCaptionPadding.bottom();
|
||||
const auto lineHeight = st::mediaviewCaptionStyle.font->height;
|
||||
const auto wantedHeight = _caption.countHeight(captionWidth);
|
||||
const auto maxHeight = _captionExpanded
|
||||
? maxExpandedHeight
|
||||
: maxCollapsedHeight;
|
||||
const auto maxHeight = !_stories
|
||||
? (_maxUsedHeight / 4)
|
||||
: (wantedHeight > lineHeight * Stories::kMaxShownCaptionLines)
|
||||
? (lineHeight * Stories::kCollapsedCaptionLines)
|
||||
: wantedHeight;
|
||||
const auto captionHeight = std::min(
|
||||
wantedHeight,
|
||||
(maxHeight / lineHeight) * lineHeight);
|
||||
_captionFitsIfExpanded = _stories
|
||||
&& (wantedHeight <= maxExpandedHeight);
|
||||
_captionShownFull = (wantedHeight <= maxCollapsedHeight);
|
||||
if (_captionShownFull && _captionExpanded && _stories) {
|
||||
_captionExpanded = false;
|
||||
_stories->setCaptionExpanded(false);
|
||||
if (_stories && captionHeight < wantedHeight) {
|
||||
const auto padding = st::storiesShowMorePadding;
|
||||
_captionShowMoreWidth = st::storiesShowMoreFont->width(
|
||||
tr::lng_stories_show_more(tr::now));
|
||||
_captionSkipBlockWidth = _captionShowMoreWidth
|
||||
+ padding.left()
|
||||
+ padding.right()
|
||||
- st::mediaviewCaptionPadding.right();
|
||||
const auto skiph = st::storiesShowMoreFont->height
|
||||
+ padding.bottom()
|
||||
- st::mediaviewCaptionPadding.bottom();
|
||||
_caption.updateSkipBlock(_captionSkipBlockWidth, skiph);
|
||||
}
|
||||
_captionRect = QRect(
|
||||
(width() - captionWidth) / 2,
|
||||
|
@ -3495,7 +3495,6 @@ void OverlayWidget::updateThemePreviewGeometry() {
|
|||
}
|
||||
|
||||
void OverlayWidget::displayFinished(anim::activation activation) {
|
||||
_captionExpanded = _captionFitsIfExpanded = _captionShownFull = false;
|
||||
updateControls();
|
||||
if (isHidden()) {
|
||||
_helper->beforeShow(_fullscreen);
|
||||
|
@ -4502,7 +4501,8 @@ void OverlayWidget::paint(not_null<Renderer*> renderer) {
|
|||
if (!_stories) {
|
||||
renderer->paintFooter(footerGeometry(), opacity);
|
||||
}
|
||||
if (!_caption.isEmpty()) {
|
||||
if (!_caption.isEmpty()
|
||||
&& (!_stories || !_stories->skipCaption())) {
|
||||
renderer->paintCaption(captionGeometry(), opacity);
|
||||
}
|
||||
if (_groupThumbs) {
|
||||
|
@ -4912,6 +4912,7 @@ void OverlayWidget::paintCaptionContent(
|
|||
}
|
||||
if (inner.intersects(clip)) {
|
||||
p.setPen(st::mediaviewCaptionFg);
|
||||
const auto lineHeight = st::mediaviewCaptionStyle.font->height;
|
||||
_caption.draw(p, {
|
||||
.position = inner.topLeft(),
|
||||
.availableWidth = inner.width(),
|
||||
|
@ -4919,8 +4920,31 @@ void OverlayWidget::paintCaptionContent(
|
|||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||
.pausedEmoji = On(PowerSaving::kEmojiChat),
|
||||
.pausedSpoiler = On(PowerSaving::kChatSpoiler),
|
||||
.elisionLines = inner.height() / st::mediaviewCaptionStyle.font->height,
|
||||
.elisionLines = inner.height() / lineHeight,
|
||||
.elisionRemoveFromEnd = _captionSkipBlockWidth,
|
||||
});
|
||||
|
||||
if (_captionShowMoreWidth > 0) {
|
||||
const auto padding = st::storiesShowMorePadding;
|
||||
const auto showMoreLeft = outer.x()
|
||||
+ outer.width()
|
||||
- padding.right()
|
||||
- _captionShowMoreWidth;
|
||||
const auto showMoreTop = outer.y()
|
||||
+ outer.height()
|
||||
- padding.bottom()
|
||||
- st::storiesShowMoreFont->height;
|
||||
const auto underline = _captionExpandLink
|
||||
&& ClickHandler::showAsActive(_captionExpandLink);
|
||||
p.setFont(underline
|
||||
? st::storiesShowMoreFont->underline()
|
||||
: st::storiesShowMoreFont);
|
||||
p.drawTextLeft(
|
||||
showMoreLeft,
|
||||
showMoreTop,
|
||||
width(),
|
||||
tr::lng_stories_show_more(tr::now));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5545,9 +5569,13 @@ void OverlayWidget::updateOver(QPoint pos) {
|
|||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
} else if (_captionRect.contains(pos)) {
|
||||
auto textState = _caption.getState(pos - _captionRect.topLeft(), _captionRect.width());
|
||||
auto request = Ui::Text::StateRequestElided();
|
||||
const auto lineHeight = st::mediaviewCaptionStyle.font->height;
|
||||
request.lines = _captionRect.height() / lineHeight;
|
||||
request.removeFromEnd = _captionSkipBlockWidth;
|
||||
auto textState = _caption.getStateElided(pos - _captionRect.topLeft(), _captionRect.width(), request);
|
||||
lnk = textState.link;
|
||||
if (_stories && !_captionShownFull && !lnk) {
|
||||
if (_stories && !lnk) {
|
||||
lnk = ensureCaptionExpandLink();
|
||||
}
|
||||
lnkhost = this;
|
||||
|
@ -5626,19 +5654,7 @@ void OverlayWidget::updateOver(QPoint pos) {
|
|||
ClickHandlerPtr OverlayWidget::ensureCaptionExpandLink() {
|
||||
if (!_captionExpandLink) {
|
||||
const auto toggle = crl::guard(_widget, [=] {
|
||||
if (!_stories) {
|
||||
return;
|
||||
} else if (_captionExpanded) {
|
||||
_captionExpanded = false;
|
||||
_stories->setCaptionExpanded(false);
|
||||
refreshCaptionGeometry();
|
||||
update();
|
||||
} else if (_captionFitsIfExpanded) {
|
||||
_captionExpanded = true;
|
||||
_stories->setCaptionExpanded(true);
|
||||
refreshCaptionGeometry();
|
||||
update();
|
||||
} else {
|
||||
if (_stories) {
|
||||
_stories->showFullCaption();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -587,9 +587,8 @@ private:
|
|||
Ui::Text::String _caption;
|
||||
QRect _captionRect;
|
||||
ClickHandlerPtr _captionExpandLink;
|
||||
bool _captionShownFull = false;
|
||||
bool _captionFitsIfExpanded = false;
|
||||
bool _captionExpanded = false;
|
||||
int _captionShowMoreWidth = 0;
|
||||
int _captionSkipBlockWidth = 0;
|
||||
|
||||
int _topNotchSize = 0;
|
||||
int _width = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue