mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added initial implementation of top bar for sponsored messages.
This commit is contained in:
parent
c857c24a64
commit
8a1cf2bb3a
8 changed files with 322 additions and 2 deletions
|
@ -1503,6 +1503,8 @@ PRIVATE
|
||||||
ui/chat/choose_send_as.h
|
ui/chat/choose_send_as.h
|
||||||
ui/chat/choose_theme_controller.cpp
|
ui/chat/choose_theme_controller.cpp
|
||||||
ui/chat/choose_theme_controller.h
|
ui/chat/choose_theme_controller.h
|
||||||
|
ui/chat/sponsored_message_bar.cpp
|
||||||
|
ui/chat/sponsored_message_bar.h
|
||||||
ui/controls/emoji_button_factory.cpp
|
ui/controls/emoji_button_factory.cpp
|
||||||
ui/controls/emoji_button_factory.h
|
ui/controls/emoji_button_factory.h
|
||||||
ui/controls/location_picker.cpp
|
ui/controls/location_picker.cpp
|
||||||
|
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/history_view_element.h"
|
#include "history/view/history_view_element.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
#include "ui/chat/sponsored_message_bar.h"
|
||||||
#include "ui/text/text_utilities.h" // Ui::Text::RichLangValue.
|
#include "ui/text/text_utilities.h" // Ui::Text::RichLangValue.
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
@ -260,12 +261,33 @@ void SponsoredMessages::parse(
|
||||||
list.postsBetween = postsBetween->v;
|
list.postsBetween = postsBetween->v;
|
||||||
list.state = State::InjectToMiddle;
|
list.state = State::InjectToMiddle;
|
||||||
} else {
|
} else {
|
||||||
list.state = State::AppendToEnd;
|
list.state = history->peer->isChannel()
|
||||||
|
? State::AppendToEnd
|
||||||
|
: State::AppendToTopBar;
|
||||||
}
|
}
|
||||||
}, [](const MTPDmessages_sponsoredMessagesEmpty &) {
|
}, [](const MTPDmessages_sponsoredMessagesEmpty &) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SponsoredMessages::fillTopBar(
|
||||||
|
not_null<History*> history,
|
||||||
|
not_null<Ui::RpWidget*> widget) {
|
||||||
|
const auto it = _data.find(history);
|
||||||
|
if (it == end(_data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto &list = it->second;
|
||||||
|
if (list.entries.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ui::FillSponsoredMessageBar(
|
||||||
|
widget,
|
||||||
|
_session,
|
||||||
|
list.entries.front().itemFullId,
|
||||||
|
list.entries.front().sponsored.from,
|
||||||
|
list.entries.front().sponsored.textWithEntities);
|
||||||
|
}
|
||||||
|
|
||||||
void SponsoredMessages::append(
|
void SponsoredMessages::append(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
List &list,
|
List &list,
|
||||||
|
|
|
@ -18,6 +18,10 @@ namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RpWidget;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
class MediaPreload;
|
class MediaPreload;
|
||||||
|
@ -76,6 +80,7 @@ public:
|
||||||
None,
|
None,
|
||||||
AppendToEnd,
|
AppendToEnd,
|
||||||
InjectToMiddle,
|
InjectToMiddle,
|
||||||
|
AppendToTopBar,
|
||||||
};
|
};
|
||||||
struct Details {
|
struct Details {
|
||||||
std::vector<TextWithEntities> info;
|
std::vector<TextWithEntities> info;
|
||||||
|
@ -98,6 +103,9 @@ public:
|
||||||
void clearItems(not_null<History*> history);
|
void clearItems(not_null<History*> history);
|
||||||
[[nodiscard]] Details lookupDetails(const FullMsgId &fullId) const;
|
[[nodiscard]] Details lookupDetails(const FullMsgId &fullId) const;
|
||||||
void clicked(const FullMsgId &fullId, bool isMedia, bool isFullscreen);
|
void clicked(const FullMsgId &fullId, bool isMedia, bool isFullscreen);
|
||||||
|
void fillTopBar(
|
||||||
|
not_null<History*> history,
|
||||||
|
not_null<Ui::RpWidget*> widget);
|
||||||
|
|
||||||
[[nodiscard]] AppendResult append(not_null<History*> history);
|
[[nodiscard]] AppendResult append(not_null<History*> history);
|
||||||
void inject(
|
void inject(
|
||||||
|
|
|
@ -1611,6 +1611,9 @@ void HistoryWidget::orderWidgets() {
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
_translateBar->raise();
|
_translateBar->raise();
|
||||||
}
|
}
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
_sponsoredMessageBar->raise();
|
||||||
|
}
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
_pinnedBar->raise();
|
_pinnedBar->raise();
|
||||||
}
|
}
|
||||||
|
@ -2284,6 +2287,7 @@ void HistoryWidget::showHistory(
|
||||||
_history->showAtMsgId = _showAtMsgId;
|
_history->showAtMsgId = _showAtMsgId;
|
||||||
|
|
||||||
destroyUnreadBarOnClose();
|
destroyUnreadBarOnClose();
|
||||||
|
_sponsoredMessageBar = nullptr;
|
||||||
_pinnedBar = nullptr;
|
_pinnedBar = nullptr;
|
||||||
_translateBar = nullptr;
|
_translateBar = nullptr;
|
||||||
_pinnedTracker = nullptr;
|
_pinnedTracker = nullptr;
|
||||||
|
@ -2520,6 +2524,26 @@ void HistoryWidget::showHistory(
|
||||||
session().sponsoredMessages().canHaveFor(_history));
|
session().sponsoredMessages().canHaveFor(_history));
|
||||||
} else if (state == State::InjectToMiddle) {
|
} else if (state == State::InjectToMiddle) {
|
||||||
injectSponsoredMessages();
|
injectSponsoredMessages();
|
||||||
|
} else if (state == State::AppendToTopBar) {
|
||||||
|
_sponsoredMessageBar
|
||||||
|
= base::make_unique_q<Ui::SlideWrap<>>(
|
||||||
|
this,
|
||||||
|
object_ptr<Ui::RpWidget>(this));
|
||||||
|
session().sponsoredMessages().fillTopBar(
|
||||||
|
_history,
|
||||||
|
_sponsoredMessageBar->entity());
|
||||||
|
_sponsoredMessageBarHeight = 0;
|
||||||
|
_sponsoredMessageBar->heightValue(
|
||||||
|
) | rpl::start_with_next([=](int height) {
|
||||||
|
_topDelta = _preserveScrollTop
|
||||||
|
? 0
|
||||||
|
: (height - _sponsoredMessageBarHeight);
|
||||||
|
_sponsoredMessageBarHeight = height;
|
||||||
|
updateHistoryGeometry();
|
||||||
|
updateControlsGeometry();
|
||||||
|
_topDelta = 0;
|
||||||
|
}, _sponsoredMessageBar->lifetime());
|
||||||
|
_sponsoredMessageBar->show(anim::type::normal);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
session().sponsoredMessages().request(_history, checkState);
|
session().sponsoredMessages().request(_history, checkState);
|
||||||
|
@ -2931,6 +2955,9 @@ void HistoryWidget::updateControlsVisibility() {
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
_pinnedBar->show();
|
_pinnedBar->show();
|
||||||
}
|
}
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
_sponsoredMessageBar->show(anim::type::instant);
|
||||||
|
}
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
_translateBar->show();
|
_translateBar->show();
|
||||||
}
|
}
|
||||||
|
@ -4128,6 +4155,9 @@ void HistoryWidget::hideChildWidgets() {
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
_pinnedBar->hide();
|
_pinnedBar->hide();
|
||||||
}
|
}
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
_sponsoredMessageBar->hide(anim::type::instant);
|
||||||
|
}
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
_translateBar->hide();
|
_translateBar->hide();
|
||||||
}
|
}
|
||||||
|
@ -4414,6 +4444,9 @@ void HistoryWidget::showAnimated(
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
_pinnedBar->finishAnimating();
|
_pinnedBar->finishAnimating();
|
||||||
}
|
}
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
_sponsoredMessageBar->finishAnimating();
|
||||||
|
}
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
_translateBar->finishAnimating();
|
_translateBar->finishAnimating();
|
||||||
}
|
}
|
||||||
|
@ -4452,6 +4485,9 @@ void HistoryWidget::showFinished() {
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
_pinnedBar->finishAnimating();
|
_pinnedBar->finishAnimating();
|
||||||
}
|
}
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
_sponsoredMessageBar->finishAnimating();
|
||||||
|
}
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
_translateBar->finishAnimating();
|
_translateBar->finishAnimating();
|
||||||
}
|
}
|
||||||
|
@ -4484,6 +4520,9 @@ void HistoryWidget::doneShow() {
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
_pinnedBar->finishAnimating();
|
_pinnedBar->finishAnimating();
|
||||||
}
|
}
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
_sponsoredMessageBar->finishAnimating();
|
||||||
|
}
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
_translateBar->finishAnimating();
|
_translateBar->finishAnimating();
|
||||||
}
|
}
|
||||||
|
@ -5999,8 +6038,14 @@ void HistoryWidget::updateControlsGeometry() {
|
||||||
_pinnedBar->move(0, pinnedBarTop);
|
_pinnedBar->move(0, pinnedBarTop);
|
||||||
_pinnedBar->resizeToWidth(width());
|
_pinnedBar->resizeToWidth(width());
|
||||||
}
|
}
|
||||||
const auto translateTop = pinnedBarTop
|
const auto sponsoredMessageBarTop = pinnedBarTop
|
||||||
+ (_pinnedBar ? _pinnedBar->height() : 0);
|
+ (_pinnedBar ? _pinnedBar->height() : 0);
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
_sponsoredMessageBar->move(0, sponsoredMessageBarTop);
|
||||||
|
_sponsoredMessageBar->resizeToWidth(width());
|
||||||
|
}
|
||||||
|
const auto translateTop = sponsoredMessageBarTop
|
||||||
|
+ (_sponsoredMessageBar ? _sponsoredMessageBar->height() : 0);
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
_translateBar->move(0, translateTop);
|
_translateBar->move(0, translateTop);
|
||||||
_translateBar->resizeToWidth(width());
|
_translateBar->resizeToWidth(width());
|
||||||
|
@ -6245,6 +6290,9 @@ void HistoryWidget::updateHistoryGeometry(
|
||||||
if (_translateBar) {
|
if (_translateBar) {
|
||||||
newScrollHeight -= _translateBar->height();
|
newScrollHeight -= _translateBar->height();
|
||||||
}
|
}
|
||||||
|
if (_sponsoredMessageBar) {
|
||||||
|
newScrollHeight -= _sponsoredMessageBar->height();
|
||||||
|
}
|
||||||
if (_pinnedBar) {
|
if (_pinnedBar) {
|
||||||
newScrollHeight -= _pinnedBar->height();
|
newScrollHeight -= _pinnedBar->height();
|
||||||
}
|
}
|
||||||
|
@ -6662,6 +6710,7 @@ int HistoryWidget::computeMaxFieldHeight() const {
|
||||||
- _topBar->height()
|
- _topBar->height()
|
||||||
- (_contactStatus ? _contactStatus->bar().height() : 0)
|
- (_contactStatus ? _contactStatus->bar().height() : 0)
|
||||||
- (_businessBotStatus ? _businessBotStatus->bar().height() : 0)
|
- (_businessBotStatus ? _businessBotStatus->bar().height() : 0)
|
||||||
|
- (_sponsoredMessageBar ? _sponsoredMessageBar->height() : 0)
|
||||||
- (_pinnedBar ? _pinnedBar->height() : 0)
|
- (_pinnedBar ? _pinnedBar->height() : 0)
|
||||||
- (_groupCallBar ? _groupCallBar->height() : 0)
|
- (_groupCallBar ? _groupCallBar->height() : 0)
|
||||||
- (_requestsBar ? _requestsBar->height() : 0)
|
- (_requestsBar ? _requestsBar->height() : 0)
|
||||||
|
|
|
@ -73,6 +73,8 @@ class SpoilerAnimation;
|
||||||
class ChooseThemeController;
|
class ChooseThemeController;
|
||||||
class ContinuousScroll;
|
class ContinuousScroll;
|
||||||
struct ChatPaintHighlight;
|
struct ChatPaintHighlight;
|
||||||
|
template <typename Widget>
|
||||||
|
class SlideWrap;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Ui::Emoji {
|
namespace Ui::Emoji {
|
||||||
|
@ -687,6 +689,9 @@ private:
|
||||||
std::unique_ptr<Ui::RequestsBar> _requestsBar;
|
std::unique_ptr<Ui::RequestsBar> _requestsBar;
|
||||||
int _requestsBarHeight = 0;
|
int _requestsBarHeight = 0;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::SlideWrap<Ui::RpWidget>> _sponsoredMessageBar;
|
||||||
|
int _sponsoredMessageBarHeight = 0;
|
||||||
|
|
||||||
bool _preserveScrollTop = false;
|
bool _preserveScrollTop = false;
|
||||||
bool _repaintFieldScheduled = false;
|
bool _repaintFieldScheduled = false;
|
||||||
|
|
||||||
|
|
|
@ -1153,3 +1153,5 @@ purchasedTagPadding: margins(3px, 2px, 6px, 2px);
|
||||||
msgSelectionCheck: RoundCheckbox(defaultPeerListCheck) {
|
msgSelectionCheck: RoundCheckbox(defaultPeerListCheck) {
|
||||||
bgActive: boxTextFgGood;
|
bgActive: boxTextFgGood;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sponsoredMessageBarMaxHeight: 156px;
|
||||||
|
|
203
Telegram/SourceFiles/ui/chat/sponsored_message_bar.cpp
Normal file
203
Telegram/SourceFiles/ui/chat/sponsored_message_bar.cpp
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
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 "ui/chat/sponsored_message_bar.h"
|
||||||
|
|
||||||
|
#include "core/ui_integration.h" // Core::MarkedTextContext.
|
||||||
|
#include "data/components/sponsored_messages.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "ui/dynamic_image.h"
|
||||||
|
#include "ui/dynamic_thumbnails.h"
|
||||||
|
#include "ui/image/image_prepare.h"
|
||||||
|
#include "ui/rect.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/widgets/shadow.h"
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
#include "styles/style_chat_helpers.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
|
||||||
|
void FillSponsoredMessageBar(
|
||||||
|
not_null<RpWidget*> widget,
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
FullMsgId fullId,
|
||||||
|
Data::SponsoredFrom from,
|
||||||
|
const TextWithEntities &textWithEntities) {
|
||||||
|
struct State final {
|
||||||
|
Ui::Text::String title;
|
||||||
|
Ui::Text::String contentTitle;
|
||||||
|
Ui::Text::String contentText;
|
||||||
|
rpl::variable<int> lastPaintedContentLineAmount = 0;
|
||||||
|
rpl::variable<int> lastPaintedContentTop = 0;
|
||||||
|
|
||||||
|
std::shared_ptr<Ui::DynamicImage> rightPhoto;
|
||||||
|
QImage rightPhotoImage;
|
||||||
|
};
|
||||||
|
const auto state = widget->lifetime().make_state<State>();
|
||||||
|
state->title.setText(
|
||||||
|
st::semiboldTextStyle,
|
||||||
|
from.isRecommended
|
||||||
|
? tr::lng_recommended_message_title(tr::now)
|
||||||
|
: tr::lng_sponsored_message_title(tr::now));
|
||||||
|
state->contentTitle.setText(st::semiboldTextStyle, from.title);
|
||||||
|
state->contentText.setMarkedText(
|
||||||
|
st::defaultTextStyle,
|
||||||
|
textWithEntities,
|
||||||
|
kMarkupTextOptions,
|
||||||
|
Core::MarkedTextContext{
|
||||||
|
.session = session,
|
||||||
|
.customEmojiRepaint = [=] { widget->update(); },
|
||||||
|
});
|
||||||
|
const auto kLinesForPhoto = 3;
|
||||||
|
const auto rightPhotoSize = state->title.style()->font->ascent
|
||||||
|
* kLinesForPhoto;
|
||||||
|
const auto rightPhotoPlaceholder = state->title.style()->font->height
|
||||||
|
* kLinesForPhoto;
|
||||||
|
const auto hasRightPhoto = from.photoId > 0;
|
||||||
|
if (hasRightPhoto) {
|
||||||
|
state->rightPhoto = Ui::MakePhotoThumbnail(
|
||||||
|
session->data().photo(from.photoId),
|
||||||
|
fullId);
|
||||||
|
const auto callback = [=] {
|
||||||
|
state->rightPhotoImage = Images::Round(
|
||||||
|
state->rightPhoto->image(rightPhotoSize),
|
||||||
|
ImageRoundRadius::Small);
|
||||||
|
widget->update();
|
||||||
|
};
|
||||||
|
state->rightPhoto->subscribeToUpdates(callback);
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
widget->paintRequest(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
auto p = QPainter(widget);
|
||||||
|
const auto r = widget->rect();
|
||||||
|
p.fillRect(r, st::historyPinnedBg);
|
||||||
|
const auto leftPadding = st::msgReplyBarSkip + st::msgReplyBarSkip;
|
||||||
|
const auto rightPadding = st::msgReplyBarSkip;
|
||||||
|
const auto topPadding = st::msgReplyPadding.top();
|
||||||
|
const auto availableWidthNoPhoto = r.width()
|
||||||
|
- leftPadding
|
||||||
|
- rightPadding;
|
||||||
|
const auto availableWidth = availableWidthNoPhoto
|
||||||
|
- (hasRightPhoto ? (rightPadding + rightPhotoSize) : 0);
|
||||||
|
const auto titleRight = leftPadding
|
||||||
|
+ state->title.maxWidth()
|
||||||
|
+ state->title.style()->font->spacew * 2;
|
||||||
|
const auto hasSecondLineTitle
|
||||||
|
= (availableWidth - state->contentTitle.maxWidth() < titleRight);
|
||||||
|
p.setPen(st::windowActiveTextFg);
|
||||||
|
state->title.draw(p, {
|
||||||
|
.position = QPoint(leftPadding, topPadding),
|
||||||
|
.outerWidth = availableWidth,
|
||||||
|
.availableWidth = availableWidth,
|
||||||
|
});
|
||||||
|
p.setPen(st::windowFg);
|
||||||
|
{
|
||||||
|
const auto left = hasSecondLineTitle ? leftPadding : titleRight;
|
||||||
|
const auto top = hasSecondLineTitle
|
||||||
|
? (topPadding + state->title.style()->font->height)
|
||||||
|
: topPadding;
|
||||||
|
state->contentTitle.draw(p, {
|
||||||
|
.position = QPoint(left, top),
|
||||||
|
.outerWidth = hasSecondLineTitle
|
||||||
|
? availableWidth
|
||||||
|
: (availableWidth - titleRight),
|
||||||
|
.availableWidth = availableWidth,
|
||||||
|
.elisionLines = 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto left = leftPadding;
|
||||||
|
const auto top = hasSecondLineTitle
|
||||||
|
? (topPadding
|
||||||
|
+ state->title.style()->font->height
|
||||||
|
+ state->contentTitle.style()->font->height)
|
||||||
|
: topPadding + state->title.style()->font->height;
|
||||||
|
auto lastContentLineAmount = 0;
|
||||||
|
const auto lineHeight = state->contentText.style()->font->height;
|
||||||
|
const auto lineLayout = [&](int line) -> Ui::Text::LineGeometry {
|
||||||
|
line++;
|
||||||
|
lastContentLineAmount = line;
|
||||||
|
const auto diff = (st::sponsoredMessageBarMaxHeight)
|
||||||
|
- line * lineHeight;
|
||||||
|
if (diff < 3 * lineHeight) {
|
||||||
|
return {
|
||||||
|
.width = availableWidthNoPhoto,
|
||||||
|
.elided = true,
|
||||||
|
};
|
||||||
|
} else if (diff < 2 * lineHeight) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (hasRightPhoto) {
|
||||||
|
line += (hasSecondLineTitle ? 2 : 1);
|
||||||
|
return {
|
||||||
|
.width = (line > kLinesForPhoto)
|
||||||
|
? availableWidthNoPhoto
|
||||||
|
: availableWidth,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return { .width = availableWidth };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
state->contentText.draw(p, {
|
||||||
|
.position = QPoint(left, top),
|
||||||
|
.outerWidth = availableWidth,
|
||||||
|
.availableWidth = availableWidth,
|
||||||
|
.geometry = Ui::Text::GeometryDescriptor{
|
||||||
|
.layout = std::move(lineLayout),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
state->lastPaintedContentTop = top;
|
||||||
|
state->lastPaintedContentLineAmount = lastContentLineAmount;
|
||||||
|
}
|
||||||
|
if (hasRightPhoto) {
|
||||||
|
p.drawImage(
|
||||||
|
r.width() - rightPadding - rightPhotoSize,
|
||||||
|
topPadding + (rightPhotoPlaceholder - rightPhotoSize) / 2,
|
||||||
|
state->rightPhotoImage);
|
||||||
|
}
|
||||||
|
}, widget->lifetime());
|
||||||
|
rpl::combine(
|
||||||
|
state->lastPaintedContentTop.value(),
|
||||||
|
state->lastPaintedContentLineAmount.value()
|
||||||
|
) | rpl::distinct_until_changed() | rpl::start_with_next([=](
|
||||||
|
int lastTop,
|
||||||
|
int lastLines) {
|
||||||
|
const auto bottomPadding = st::msgReplyPadding.top();
|
||||||
|
const auto desiredHeight = lastTop
|
||||||
|
+ (lastLines * state->contentText.style()->font->height)
|
||||||
|
+ bottomPadding;
|
||||||
|
const auto minHeight = hasRightPhoto
|
||||||
|
? (rightPhotoPlaceholder + bottomPadding * 2)
|
||||||
|
: desiredHeight;
|
||||||
|
widget->resize(
|
||||||
|
widget->width(),
|
||||||
|
std::clamp(
|
||||||
|
desiredHeight,
|
||||||
|
minHeight,
|
||||||
|
st::sponsoredMessageBarMaxHeight));
|
||||||
|
}, widget->lifetime());
|
||||||
|
widget->resize(widget->width(), 1);
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto top = Ui::CreateChild<PlainShadow>(widget);
|
||||||
|
const auto bottom = Ui::CreateChild<PlainShadow>(widget);
|
||||||
|
widget->sizeValue() | rpl::start_with_next([=] (const QSize &s) {
|
||||||
|
top->show();
|
||||||
|
top->raise();
|
||||||
|
top->resizeToWidth(s.width());
|
||||||
|
bottom->show();
|
||||||
|
bottom->raise();
|
||||||
|
bottom->resizeToWidth(s.width());
|
||||||
|
bottom->moveToLeft(0, s.height() - bottom->height());
|
||||||
|
}, top->lifetime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ui
|
29
Telegram/SourceFiles/ui/chat/sponsored_message_bar.h
Normal file
29
Telegram/SourceFiles/ui/chat/sponsored_message_bar.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
struct SponsoredFrom;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
|
namespace Main {
|
||||||
|
class Session;
|
||||||
|
} // namespace Main
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
|
||||||
|
class RpWidget;
|
||||||
|
|
||||||
|
void FillSponsoredMessageBar(
|
||||||
|
not_null<RpWidget*> widget,
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
FullMsgId fullId,
|
||||||
|
Data::SponsoredFrom from,
|
||||||
|
const TextWithEntities &textWithEntities);
|
||||||
|
|
||||||
|
} // namespace Ui
|
Loading…
Add table
Reference in a new issue