mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Display full caption if it doesn't fit.
This commit is contained in:
parent
0331955ce7
commit
a745c9ff75
10 changed files with 246 additions and 15 deletions
|
@ -962,6 +962,8 @@ PRIVATE
|
|||
media/player/media_player_volume_controller.h
|
||||
media/player/media_player_widget.cpp
|
||||
media/player/media_player_widget.h
|
||||
media/stories/media_stories_caption_full_view.cpp
|
||||
media/stories/media_stories_caption_full_view.h
|
||||
media/stories/media_stories_controller.cpp
|
||||
media/stories/media_stories_controller.h
|
||||
media/stories/media_stories_delegate.cpp
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
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 "media/stories/media_stories_caption_full_view.h"
|
||||
|
||||
#include "core/ui_integration.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/labels.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(
|
||||
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,
|
||||
.customEmojiRepaint = [=] { _text->update(); },
|
||||
});
|
||||
|
||||
parent->sizeValue() | rpl::start_with_next([=](QSize size) {
|
||||
setGeometry(QRect(QPoint(), size));
|
||||
}, lifetime());
|
||||
|
||||
show();
|
||||
setFocus();
|
||||
}
|
||||
|
||||
CaptionFullView::~CaptionFullView() = default;
|
||||
|
||||
void CaptionFullView::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
_background.paint(p, _scroll->geometry());
|
||||
_background.paint(p, _scroll->geometry());
|
||||
}
|
||||
|
||||
void CaptionFullView::resizeEvent(QResizeEvent *e) {
|
||||
const auto wanted = _text->naturalWidth();
|
||||
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) {
|
||||
_close();
|
||||
}
|
||||
}
|
||||
|
||||
void CaptionFullView::mousePressEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
_close();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Media::Stories
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
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 "ui/rp_widget.h"
|
||||
#include "ui/round_rect.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Ui {
|
||||
class FlatLabel;
|
||||
class ScrollArea;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Media::Stories {
|
||||
|
||||
class CaptionFullView final : private Ui::RpWidget {
|
||||
public:
|
||||
CaptionFullView(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Main::Session*> session,
|
||||
const TextWithEntities &text,
|
||||
Fn<void()> close);
|
||||
~CaptionFullView();
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
|
||||
std::unique_ptr<Ui::ScrollArea> _scroll;
|
||||
const not_null<Ui::FlatLabel*> _text;
|
||||
Fn<void()> _close;
|
||||
Ui::RoundRect _background;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Media::Stories
|
|
@ -9,8 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "base/timer.h"
|
||||
#include "base/power_save_blocker.h"
|
||||
#include "chat_helpers/compose/compose_show.h"
|
||||
#include "data/data_stories.h"
|
||||
#include "data/data_user.h"
|
||||
#include "media/stories/media_stories_caption_full_view.h"
|
||||
#include "media/stories/media_stories_delegate.h"
|
||||
#include "media/stories/media_stories_header.h"
|
||||
#include "media/stories/media_stories_sibling.h"
|
||||
|
@ -115,6 +117,9 @@ Controller::Controller(not_null<Delegate*> delegate)
|
|||
|
||||
_replyArea->focusedValue(
|
||||
) | rpl::start_with_next([=](bool focused) {
|
||||
if (focused) {
|
||||
_captionFullView = nullptr;
|
||||
}
|
||||
_contentFaded = focused;
|
||||
_contentFadeAnimation.start(
|
||||
[=] { _delegate->storiesRepaint(); },
|
||||
|
@ -292,6 +297,18 @@ TextWithEntities Controller::captionText() const {
|
|||
return _captionText;
|
||||
}
|
||||
|
||||
void Controller::showFullCaption() {
|
||||
if (_captionText.empty()) {
|
||||
return;
|
||||
}
|
||||
togglePaused(true);
|
||||
_captionFullView = std::make_unique<CaptionFullView>(
|
||||
wrap(),
|
||||
&_delegate->storiesShow()->session(),
|
||||
_captionText,
|
||||
[=] { togglePaused(false); });
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatHelpers::Show> Controller::uiShow() const {
|
||||
return _delegate->storiesShow();
|
||||
}
|
||||
|
@ -334,10 +351,15 @@ void Controller::show(
|
|||
}
|
||||
_shown = id;
|
||||
_captionText = item.caption;
|
||||
_captionFullView = nullptr;
|
||||
|
||||
_header->show({ .user = list.user, .date = item.date });
|
||||
_slider->show({ .index = _index, .total = list.total });
|
||||
_replyArea->show({ .user = list.user });
|
||||
|
||||
if (_contentFaded) {
|
||||
togglePaused(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::showSiblings(
|
||||
|
@ -447,6 +469,9 @@ bool Controller::paused() const {
|
|||
}
|
||||
|
||||
void Controller::togglePaused(bool paused) {
|
||||
if (!paused) {
|
||||
_captionFullView = nullptr;
|
||||
}
|
||||
if (_photoPlayback) {
|
||||
_photoPlayback->togglePaused(paused);
|
||||
} else {
|
||||
|
|
|
@ -41,6 +41,7 @@ class Delegate;
|
|||
struct SiblingView;
|
||||
enum class SiblingType;
|
||||
struct ContentLayout;
|
||||
class CaptionFullView;
|
||||
|
||||
enum class HeaderLayout {
|
||||
Normal,
|
||||
|
@ -78,6 +79,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<Layout> layoutValue() const;
|
||||
[[nodiscard]] ContentLayout contentLayout() const;
|
||||
[[nodiscard]] TextWithEntities captionText() const;
|
||||
void showFullCaption();
|
||||
|
||||
[[nodiscard]] std::shared_ptr<ChatHelpers::Show> uiShow() const;
|
||||
[[nodiscard]] auto stickerOrEmojiChosen() const
|
||||
|
@ -130,6 +132,7 @@ private:
|
|||
const std::unique_ptr<Slider> _slider;
|
||||
const std::unique_ptr<ReplyArea> _replyArea;
|
||||
std::unique_ptr<PhotoPlayback> _photoPlayback;
|
||||
std::unique_ptr<CaptionFullView> _captionFullView;
|
||||
|
||||
Ui::Animations::Simple _contentFadeAnimation;
|
||||
bool _contentFaded = false;
|
||||
|
|
|
@ -83,6 +83,10 @@ TextWithEntities View::captionText() const {
|
|||
return _controller->captionText();
|
||||
}
|
||||
|
||||
void View::showFullCaption() {
|
||||
_controller->showFullCaption();
|
||||
}
|
||||
|
||||
rpl::lifetime &View::lifetime() {
|
||||
return _controller->lifetime();
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
[[nodiscard]] ContentLayout contentLayout() const;
|
||||
[[nodiscard]] SiblingView sibling(SiblingType type) const;
|
||||
[[nodiscard]] TextWithEntities captionText() const;
|
||||
void showFullCaption();
|
||||
|
||||
void updatePlayback(const Player::TrackState &state);
|
||||
|
||||
|
|
|
@ -448,3 +448,8 @@ storiesAttach: IconButton(defaultIconButton) {
|
|||
}
|
||||
}
|
||||
storiesSideSkip: 145px;
|
||||
storiesCaptionFull: FlatLabel(defaultFlatLabel) {
|
||||
style: mediaviewCaptionStyle;
|
||||
textFg: mediaviewCaptionFg;
|
||||
minWidth: 360px;
|
||||
}
|
||||
|
|
|
@ -1217,14 +1217,32 @@ void OverlayWidget::refreshCaptionGeometry() {
|
|||
- st::mediaviewCaptionPadding.left()
|
||||
- st::mediaviewCaptionPadding.right()),
|
||||
_caption.maxWidth());
|
||||
const auto maxHeight = (_stories ? (_h / 3) : (height() / 4))
|
||||
const auto maxExpandedOuterHeight = (_stories
|
||||
? (_h - st::storiesShadowTop.height())
|
||||
: height());
|
||||
const auto maxCollapsedOuterHeight = !_stories
|
||||
? (height() / 4)
|
||||
: (_h / 3);
|
||||
const auto maxExpandedHeight = maxExpandedOuterHeight
|
||||
- st::mediaviewCaptionPadding.top()
|
||||
- st::mediaviewCaptionPadding.bottom()
|
||||
- (_stories ? 0 : (2 * st::mediaviewCaptionMargin.height()));
|
||||
- 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 captionHeight = std::min(
|
||||
_caption.countHeight(captionWidth),
|
||||
wantedHeight,
|
||||
(maxHeight / lineHeight) * lineHeight);
|
||||
_captionFitsIfExpanded = _stories
|
||||
&& (wantedHeight <= maxExpandedHeight);
|
||||
_captionShownFull = (wantedHeight <= maxCollapsedHeight);
|
||||
if (_captionShownFull) {
|
||||
_captionExpanded = false;
|
||||
}
|
||||
_captionRect = QRect(
|
||||
(width() - captionWidth) / 2,
|
||||
(captionBottom
|
||||
|
@ -3000,6 +3018,7 @@ void OverlayWidget::show(OpenRequest request) {
|
|||
_streamingStartPaused = false;
|
||||
displayDocument(
|
||||
document,
|
||||
anim::activation::normal,
|
||||
request.cloudTheme()
|
||||
? *request.cloudTheme()
|
||||
: Data::CloudTheme(),
|
||||
|
@ -3014,9 +3033,11 @@ void OverlayWidget::show(OpenRequest request) {
|
|||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::displayPhoto(not_null<PhotoData*> photo) {
|
||||
void OverlayWidget::displayPhoto(
|
||||
not_null<PhotoData*> photo,
|
||||
anim::activation activation) {
|
||||
if (photo->isNull()) {
|
||||
displayDocument(nullptr);
|
||||
displayDocument(nullptr, activation);
|
||||
return;
|
||||
}
|
||||
_touchbarDisplay.fire(TouchBarItemType::Photo);
|
||||
|
@ -3055,7 +3076,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo) {
|
|||
}
|
||||
contentSizeChanged();
|
||||
refreshFromLabel();
|
||||
displayFinished();
|
||||
displayFinished(activation);
|
||||
}
|
||||
|
||||
void OverlayWidget::destroyThemePreview() {
|
||||
|
@ -3071,15 +3092,16 @@ void OverlayWidget::redisplayContent() {
|
|||
if (isHidden() || !_session) {
|
||||
return;
|
||||
} else if (_photo) {
|
||||
displayPhoto(_photo);
|
||||
displayPhoto(_photo, anim::activation::background);
|
||||
} else {
|
||||
displayDocument(_document);
|
||||
displayDocument(_document, anim::activation::background);
|
||||
}
|
||||
}
|
||||
|
||||
// Empty messages shown as docs: doc can be nullptr.
|
||||
void OverlayWidget::displayDocument(
|
||||
DocumentData *doc,
|
||||
anim::activation activation,
|
||||
const Data::CloudTheme &cloud,
|
||||
const StartStreaming &startStreaming) {
|
||||
_fullScreenVideo = false;
|
||||
|
@ -3209,7 +3231,7 @@ void OverlayWidget::displayDocument(
|
|||
if (_showAsPip && _streamed && _streamed->controls) {
|
||||
switchToPip();
|
||||
} else {
|
||||
displayFinished();
|
||||
displayFinished(activation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3236,7 +3258,8 @@ void OverlayWidget::updateThemePreviewGeometry() {
|
|||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::displayFinished() {
|
||||
void OverlayWidget::displayFinished(anim::activation activation) {
|
||||
_captionExpanded = _captionFitsIfExpanded = _captionShownFull = false;
|
||||
updateControls();
|
||||
if (isHidden()) {
|
||||
_helper->beforeShow(_fullscreen);
|
||||
|
@ -3247,6 +3270,8 @@ void OverlayWidget::displayFinished() {
|
|||
//setAttribute(Qt::WA_DontShowOnScreen, false);
|
||||
//Ui::Platform::UpdateOverlayed(_window);
|
||||
showAndActivate();
|
||||
} else if (activation == anim::activation::background) {
|
||||
return;
|
||||
} else if (isMinimized()) {
|
||||
_helper->beforeShow(_fullscreen);
|
||||
showAndActivate();
|
||||
|
@ -4015,10 +4040,11 @@ void OverlayWidget::storiesJumpTo(Data::FullStoryId id) {
|
|||
clearStreaming();
|
||||
_streamingStartPaused = false;
|
||||
const auto &data = j->media.data;
|
||||
const auto activation = anim::activation::background;
|
||||
if (const auto photo = std::get_if<not_null<PhotoData*>>(&data)) {
|
||||
displayPhoto(*photo);
|
||||
displayPhoto(*photo, activation);
|
||||
} else {
|
||||
displayDocument(v::get<not_null<DocumentData*>>(data));
|
||||
displayDocument(v::get<not_null<DocumentData*>>(data), activation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5302,6 +5328,9 @@ void OverlayWidget::updateOver(QPoint pos) {
|
|||
} else if (_captionRect.contains(pos)) {
|
||||
auto textState = _caption.getState(pos - _captionRect.topLeft(), _captionRect.width());
|
||||
lnk = textState.link;
|
||||
if (_stories && !_captionShownFull && !lnk) {
|
||||
lnk = ensureCaptionExpandLink();
|
||||
}
|
||||
lnkhost = this;
|
||||
} else if (_groupThumbs && _groupThumbsRect.contains(pos)) {
|
||||
const auto point = pos - QPoint(_groupThumbsLeft, _groupThumbsTop);
|
||||
|
@ -5373,6 +5402,28 @@ void OverlayWidget::updateOver(QPoint pos) {
|
|||
}
|
||||
}
|
||||
|
||||
ClickHandlerPtr OverlayWidget::ensureCaptionExpandLink() {
|
||||
if (!_captionExpandLink) {
|
||||
const auto toggle = crl::guard(_widget, [=] {
|
||||
if (!_stories) {
|
||||
return;
|
||||
} else if (_captionExpanded) {
|
||||
_captionExpanded = false;
|
||||
refreshCaptionGeometry();
|
||||
update();
|
||||
} else if (_captionFitsIfExpanded) {
|
||||
_captionExpanded = true;
|
||||
refreshCaptionGeometry();
|
||||
update();
|
||||
} else {
|
||||
_stories->showFullCaption();
|
||||
}
|
||||
});
|
||||
_captionExpandLink = std::make_shared<LambdaClickHandler>(toggle);
|
||||
}
|
||||
return _captionExpandLink;
|
||||
}
|
||||
|
||||
void OverlayWidget::handleMouseRelease(
|
||||
QPoint position,
|
||||
Qt::MouseButton button) {
|
||||
|
|
|
@ -23,6 +23,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class History;
|
||||
|
||||
namespace anim {
|
||||
enum class activation : uchar;
|
||||
} // namespace anim
|
||||
|
||||
namespace Data {
|
||||
class PhotoMedia;
|
||||
class DocumentMedia;
|
||||
|
@ -148,6 +152,7 @@ private:
|
|||
OverMore,
|
||||
OverIcon,
|
||||
OverVideo,
|
||||
OverCaption,
|
||||
};
|
||||
struct Entity {
|
||||
std::variant<
|
||||
|
@ -356,12 +361,15 @@ private:
|
|||
void resizeContentByScreenSize();
|
||||
void recountSkipTop();
|
||||
|
||||
void displayPhoto(not_null<PhotoData*> photo);
|
||||
void displayPhoto(
|
||||
not_null<PhotoData*> photo,
|
||||
anim::activation activation = anim::activation::normal);
|
||||
void displayDocument(
|
||||
DocumentData *document,
|
||||
anim::activation activation = anim::activation::normal,
|
||||
const Data::CloudTheme &cloud = Data::CloudTheme(),
|
||||
const StartStreaming &startStreaming = StartStreaming());
|
||||
void displayFinished();
|
||||
void displayFinished(anim::activation activation);
|
||||
void redisplayContent();
|
||||
void findCurrent();
|
||||
|
||||
|
@ -496,6 +504,7 @@ private:
|
|||
|
||||
[[nodiscard]] bool topShadowOnTheRight() const;
|
||||
void applyHideWindowWorkaround();
|
||||
[[nodiscard]] ClickHandlerPtr ensureCaptionExpandLink();
|
||||
|
||||
Window::SessionController *findWindow(bool switchTo = true) const;
|
||||
|
||||
|
@ -558,6 +567,10 @@ private:
|
|||
int _groupThumbsTop = 0;
|
||||
Ui::Text::String _caption;
|
||||
QRect _captionRect;
|
||||
ClickHandlerPtr _captionExpandLink;
|
||||
bool _captionShownFull = false;
|
||||
bool _captionFitsIfExpanded = false;
|
||||
bool _captionExpanded = false;
|
||||
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue