Added initial dummy draft for top bar suggestions in dialogs.

This commit is contained in:
23rd 2025-03-29 23:13:41 +03:00 committed by John Preston
parent e0b1ed87e8
commit 3a622f111a
9 changed files with 320 additions and 8 deletions

View file

@ -690,6 +690,8 @@ PRIVATE
dialogs/dialogs_search_from_controllers.h
dialogs/dialogs_search_tags.cpp
dialogs/dialogs_search_tags.h
dialogs/dialogs_top_bar_suggestion.cpp
dialogs/dialogs_top_bar_suggestion.h
dialogs/dialogs_widget.cpp
dialogs/dialogs_widget.h
editor/color_picker.cpp

View file

@ -3863,6 +3863,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_dialogs_skip_archive_in_search" = "Skip results from archive";
"lng_dialogs_show_archive_in_search" = "With results from archive";
"lng_dialogs_top_bar_suggestions_birthday_title" = "Add your birthday! 🎂";
"lng_dialogs_top_bar_suggestions_birthday_about" = "Let your contacts know when youre celebrating.";
"lng_about_random" = "Send a {emoji} emoji to any chat to try your luck.";
"lng_about_random_send" = "Send";

View file

@ -0,0 +1,44 @@
/*
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 "dialogs/dialogs_top_bar_suggestion.h"
#include "dialogs/ui/dialogs_top_bar_suggestion_content.h"
#include "lang/lang_keys.h"
#include "ui/text/text_utilities.h"
#include "ui/wrap/slide_wrap.h"
namespace Dialogs {
object_ptr<Ui::SlideWrap<Ui::RpWidget>> CreateTopBarSuggestion(
not_null<Ui::RpWidget*> parent,
not_null<Main::Session*> session) {
const auto content = Ui::CreateChild<TopBarSuggestionContent>(parent);
auto result = object_ptr<Ui::SlideWrap<Ui::RpWidget>>(
parent,
object_ptr<Ui::RpWidget>::fromRaw(content));
const auto wrap = result.data();
content->setContent(
tr::lng_dialogs_top_bar_suggestions_birthday_title(
tr::now,
Ui::Text::Bold),
tr::lng_dialogs_top_bar_suggestions_birthday_about(
tr::now,
TextWithEntities::Simple));
rpl::combine(
parent->widthValue(),
content->desiredHeightValue()
) | rpl::start_with_next([=](int width, int height) {
content->resize(width, height);
}, content->lifetime());
return result;
}
} // namespace Dialogs

View file

@ -0,0 +1,30 @@
/*
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
template <typename Object>
class object_ptr;
namespace Main {
class Session;
} // namespace Main
namespace Ui {
class RpWidget;
template <typename Widget>
class SlideWrap;
} // namespace Ui
namespace Dialogs {
[[nodiscard]] object_ptr<Ui::SlideWrap<Ui::RpWidget>> CreateTopBarSuggestion(
not_null<Ui::RpWidget*> parent,
not_null<Main::Session*>);
} // namespace Dialogs

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "dialogs/ui/dialogs_suggestions.h"
#include "dialogs/dialogs_inner_widget.h"
#include "dialogs/dialogs_search_from_controllers.h"
#include "dialogs/dialogs_top_bar_suggestion.h"
#include "dialogs/dialogs_quick_action.h"
#include "dialogs/dialogs_key.h"
#include "history/history.h"
@ -31,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/elastic_scroll.h"
#include "ui/widgets/fields/input_field.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/effects/radial_animation.h"
#include "ui/chat/requests_bar.h"
#include "ui/chat/group_call_bar.h"
@ -375,20 +377,42 @@ Widget::Widget(
_scroll->setOverscrollTypes(
_stories ? OverscrollType::Virtual : OverscrollType::Real,
OverscrollType::Real);
_inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(
this,
const auto innerList = _scroll->setOwnedWidget(
object_ptr<Ui::VerticalLayout>(this));
if (_layout != Layout::Child) {
_topBarSuggestion = innerList->add(CreateTopBarSuggestion(
innerList,
&session()));
rpl::combine(
_topBarSuggestion->entity()->desiredHeightValue(),
_childListShown.value()
) | rpl::start_with_next([=](int desiredHeight, float64 shown) {
const auto newHeight = desiredHeight * (1. - shown);
_topBarSuggestion->entity()->setMaximumHeight(newHeight);
_topBarSuggestion->entity()->setMinimumWidth(width());
_topBarSuggestion->entity()->resize(width(), newHeight);
}, _topBarSuggestion->lifetime());
}
_inner = innerList->add(object_ptr<InnerWidget>(
innerList,
controller,
rpl::combine(
_childListPeerId.value(),
_childListShown.value(),
makeChildListShown)));
_scroll->heightValue() | rpl::start_with_next([=](int height) {
_inner->setMinimumHeight(height);
innerList->setMinimumHeight(height);
_inner->setMinimumHeight(height
- (_topBarSuggestion ? _topBarSuggestion->height() : 0));
_inner->refresh();
}, _inner->lifetime());
}, innerList->lifetime());
_scroll->widthValue() | rpl::start_with_next([=](int width) {
innerList->resizeToWidth(width);
}, innerList->lifetime());
_scrollToTop->raise();
_lockUnlock->toggle(false, anim::type::instant);
_inner->updated(
) | rpl::start_with_next([=] {
listScrollUpdated();
@ -1022,6 +1046,18 @@ void Widget::updateFrozenAccountBar() {
}
}
void Widget::updateTopBarSuggestions() {
if (_topBarSuggestion) {
if ((_layout == Layout::Child)
|| _openedForum
|| _openedFolder) {
_topBarSuggestion->toggle(false, anim::type::instant);
} else {
_topBarSuggestion->toggle(true, anim::type::instant);
}
}
}
void Widget::setupMoreChatsBar() {
if (_layout == Layout::Child) {
return;
@ -1454,7 +1490,7 @@ void Widget::updateControlsVisibility(bool fast) {
_frozenAccountBar->show();
}
if (_chatFilters) {
_chatFilters->show();
_chatFilters->setVisible(!_openedForum);
}
if (_openedFolder || _openedForum) {
_subsectionTopBar->show();
@ -1772,6 +1808,7 @@ void Widget::changeOpenedFolder(Data::Folder *folder, anim::type animated) {
storiesExplicitCollapse();
}
updateFrozenAccountBar();
updateTopBarSuggestions();
}, (folder != nullptr), animated);
}
@ -1829,6 +1866,7 @@ void Widget::changeOpenedForum(Data::Forum *forum, anim::type animated) {
_inner->changeOpenedForum(forum);
storiesToggleExplicitExpand(false);
updateFrozenAccountBar();
updateTopBarSuggestions();
updateStoriesVisibility();
}, (forum != nullptr), animated);
}
@ -3402,7 +3440,8 @@ bool Widget::applySearchState(SearchState state) {
: nullptr;
_searchState = state;
if (_chatFilters && queryEmptyChanged) {
_chatFilters->setVisible(_searchState.query.isEmpty());
_chatFilters->setVisible(_searchState.query.isEmpty()
&& !_openedForum);
updateControlsGeometry();
}
_searchWithPostsPreview = computeSearchWithPostsPreview();
@ -3829,7 +3868,7 @@ void Widget::updateControlsGeometry() {
_chatFilters->move(0, chatFiltersTop);
}
const auto scrollTop = chatFiltersTop
+ ((_chatFilters && _searchState.query.isEmpty())
+ ((_chatFilters && _searchState.query.isEmpty() && !_openedForum)
? (_chatFilters->height() * (1. - narrowRatio))
: 0);
const auto scrollHeight = height() - scrollTop - bottomSkip;

View file

@ -53,6 +53,8 @@ class JumpDownButton;
class ElasticScroll;
template <typename Widget>
class FadeWrapScaled;
template <typename Widget>
class SlideWrap;
} // namespace Ui
namespace Window {
@ -223,6 +225,7 @@ private:
void showMainMenu();
void clearSearchCache(bool clearPosts);
void setSearchQuery(const QString &query, int cursorPosition = -1);
void updateTopBarSuggestions();
void updateFrozenAccountBar();
void updateControlsVisibility(bool fast = false);
void updateLockUnlockVisibility(
@ -313,7 +316,7 @@ private:
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _chooseFromUser;
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _jumpToDate;
object_ptr<Ui::CrossButton> _cancelSearch;
object_ptr< Ui::FadeWrapScaled<Ui::IconButton>> _lockUnlock;
object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _lockUnlock;
std::unique_ptr<Ui::MoreChatsBar> _moreChatsBar;
@ -324,6 +327,8 @@ private:
base::unique_qptr<Ui::RpWidget> _chatFilters;
Ui::SlideWrap<Ui::RpWidget> *_topBarSuggestion = nullptr;
object_ptr<Ui::ElasticScroll> _scroll;
QPointer<InnerWidget> _inner;
std::unique_ptr<Suggestions> _suggestions;

View file

@ -0,0 +1,136 @@
/*
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 "dialogs/ui/dialogs_top_bar_suggestion_content.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_dialogs.h"
namespace Dialogs {
namespace {
} // namespace
TopBarSuggestionContent::TopBarSuggestionContent(not_null<Ui::RpWidget*> p)
: Ui::RippleButton(p, st::defaultRippleAnimationBgOver)
, _titleSt(st::semiboldTextStyle)
, _contentTitleSt(st::semiboldTextStyle)
, _contentTextSt(st::defaultTextStyle) {
}
void TopBarSuggestionContent::draw(QPainter &p) {
const auto kLinesForPhoto = 3;
const auto rightPhotoSize = _titleSt.font->ascent * kLinesForPhoto;
const auto rightPhotoPlaceholder = _titleSt.font->height * kLinesForPhoto;
const auto r = Ui::RpWidget::rect();
p.fillRect(r, st::historyPinnedBg);
Ui::RippleButton::paintRipple(p, 0, 0);
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
- (_rightHide ? _rightHide->width() : 0);
const auto titleRight = leftPadding
+ _titleSt.font->spacew * 2;
const auto hasSecondLineTitle = (titleRight
> (availableWidth - _contentTitle.maxWidth()));
p.setPen(st::windowActiveTextFg);
p.setPen(st::windowFg);
{
const auto left = hasSecondLineTitle ? leftPadding : titleRight;
const auto top = hasSecondLineTitle
? (topPadding + _titleSt.font->height)
: topPadding;
_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
+ _titleSt.font->height
+ _contentTitleSt.font->height)
: topPadding + _titleSt.font->height;
auto lastContentLineAmount = 0;
const auto lineHeight = _contentTextSt.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 {};
}
line += (hasSecondLineTitle ? 2 : 1) + 1;
return {
.width = (line > kLinesForPhoto)
? availableWidthNoPhoto
: availableWidth,
};
};
_contentText.draw(p, {
.position = QPoint(left, top),
.outerWidth = availableWidth,
.availableWidth = availableWidth,
.geometry = Ui::Text::GeometryDescriptor{
.layout = std::move(lineLayout),
},
});
_lastPaintedContentTop = top;
_lastPaintedContentLineAmount = lastContentLineAmount;
}
}
void TopBarSuggestionContent::setContent(
TextWithEntities title,
TextWithEntities description) {
_contentTitle.setMarkedText(_contentTitleSt, std::move(title));
_contentText.setMarkedText(_contentTextSt, std::move(description));
}
void TopBarSuggestionContent::paintEvent(QPaintEvent *) {
auto p = QPainter(this);
draw(p);
}
rpl::producer<int> TopBarSuggestionContent::desiredHeightValue() const {
const auto kLinesForPhoto = 3;
const auto rightPhotoSize = _titleSt.font->ascent * kLinesForPhoto;
const auto rightPhotoPlaceholder = _titleSt.font->height * kLinesForPhoto;
return rpl::combine(
_lastPaintedContentTop.value(),
_lastPaintedContentLineAmount.value()
) | rpl::distinct_until_changed() | rpl::map([=](
int lastTop,
int lastLines) {
const auto bottomPadding = st::msgReplyPadding.top();
const auto desiredHeight = lastTop
+ (lastLines * _contentTextSt.font->height)
+ bottomPadding;
const auto minHeight = desiredHeight;
return std::clamp(
desiredHeight,
minHeight,
st::sponsoredMessageBarMaxHeight);
});
}
} // namespace Dialogs

View file

@ -0,0 +1,51 @@
/*
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/widgets/buttons.h"
namespace Ui {
class DynamicImage;
class IconButton;
} // namespace Ui
namespace Dialogs {
class TopBarSuggestionContent : public Ui::RippleButton {
public:
TopBarSuggestionContent(not_null<Ui::RpWidget*>);
void setContent(
TextWithEntities title,
TextWithEntities description);
[[nodiscard]] rpl::producer<int> desiredHeightValue() const override;
protected:
void paintEvent(QPaintEvent *) override;
private:
void draw(QPainter &p);
const style::TextStyle &_titleSt;
const style::TextStyle &_contentTitleSt;
const style::TextStyle &_contentTextSt;
Ui::Text::String _contentTitle;
Ui::Text::String _contentText;
rpl::variable<int> _lastPaintedContentLineAmount = 0;
rpl::variable<int> _lastPaintedContentTop = 0;
base::unique_qptr<Ui::IconButton> _rightHide;
std::shared_ptr<Ui::DynamicImage> _rightPhoto;
QImage _rightPhotoImage;
};
} // namespace Dialogs

View file

@ -105,6 +105,8 @@ PRIVATE
dialogs/ui/dialogs_quick_action.h
dialogs/ui/dialogs_stories_list.cpp
dialogs/ui/dialogs_stories_list.h
dialogs/ui/dialogs_top_bar_suggestion_content.cpp
dialogs/ui/dialogs_top_bar_suggestion_content.h
dialogs/ui/top_peers_strip.cpp
dialogs/ui/top_peers_strip.h