Simplify main menu cover according to the mockup.

This commit is contained in:
John Preston 2022-02-10 14:03:07 +03:00
parent adb25d65c2
commit d7c63b85ed
4 changed files with 50 additions and 149 deletions

View file

@ -63,6 +63,7 @@ void PaintCollapsedRow(
enum UnreadBadgeSize { enum UnreadBadgeSize {
UnreadBadgeInDialogs = 0, UnreadBadgeInDialogs = 0,
UnreadBadgeInMainMenu,
UnreadBadgeInHistoryToDown, UnreadBadgeInHistoryToDown,
UnreadBadgeInStickersPanel, UnreadBadgeInStickersPanel,
UnreadBadgeInStickersBox, UnreadBadgeInStickersBox,

View file

@ -144,6 +144,8 @@ mainMenuShadow: icon {{ "menu_shadow", windowShadowFg }};
mainMenuAddAccount: icon {{ "settings/add", settingsIconFg }}; mainMenuAddAccount: icon {{ "settings/add", settingsIconFg }};
mainMenuAccountSize: 26px; mainMenuAccountSize: 26px;
mainMenuAccountLine: 2px; mainMenuAccountLine: 2px;
mainMenuBadgeFont: font(11px bold);
mainMenuBadgeSize: 18px;
mainMenuFooterLeft: 25px; mainMenuFooterLeft: 25px;
mainMenuTelegramLabel: FlatLabel(defaultFlatLabel) { mainMenuTelegramLabel: FlatLabel(defaultFlatLabel) {

View file

@ -62,37 +62,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <QtGui/QScreen> #include <QtGui/QScreen>
namespace Window {
namespace { namespace {
constexpr auto kMinDiffIntensity = 0.25;
[[nodiscard]] float64 IntensityOfColor(QColor color) {
return (0.299 * color.red()
+ 0.587 * color.green()
+ 0.114 * color.blue()) / 255.0;
}
[[nodiscard]] bool IsShadowShown(const QImage &img, const QRect r, float64 intensityText) {
for (auto x = r.x(); x < r.x() + r.width(); x++) {
for (auto y = r.y(); y < r.y() + r.height(); y++) {
const auto intensity = IntensityOfColor(QColor(img.pixel(x, y)));
if ((std::abs(intensity - intensityText)) < kMinDiffIntensity) {
return true;
}
}
}
return false;
}
[[nodiscard]] bool IsFilledCover() {
const auto background = Window::Theme::Background();
return background->tile()
|| background->colorForFill().has_value()
|| !background->gradientForFill().isNull()
|| background->paper().isPattern()
|| Data::IsLegacy1DefaultWallPaper(background->paper());
}
[[nodiscard]] bool IsAltShift(Qt::KeyboardModifiers modifiers) { [[nodiscard]] bool IsAltShift(Qt::KeyboardModifiers modifiers) {
return (modifiers & Qt::ShiftModifier) && (modifiers & Qt::AltModifier); return (modifiers & Qt::ShiftModifier) && (modifiers & Qt::AltModifier);
} }
@ -159,15 +131,19 @@ void ShowCallsBox(not_null<Window::SessionController*> window) {
return accounts; return accounts;
} }
} // namespace
namespace Window {
struct UnreadBadge { struct UnreadBadge {
int count = 0; int count = 0;
bool muted = false; bool muted = false;
}; };
[[nodiscard]] Dialogs::Ui::UnreadBadgeStyle BadgeStyle() {
auto result = Dialogs::Ui::UnreadBadgeStyle();
result.font = st::mainMenuBadgeFont;
result.size = st::mainMenuBadgeSize;
result.sizeId = Dialogs::Ui::UnreadBadgeInMainMenu;
return result;
}
void AddUnreadBadge( void AddUnreadBadge(
not_null<Ui::SettingsButton*> button, not_null<Ui::SettingsButton*> button,
rpl::producer<UnreadBadge> value) { rpl::producer<UnreadBadge> value) {
@ -177,7 +153,7 @@ void AddUnreadBadge(
} }
Ui::RpWidget widget; Ui::RpWidget widget;
Dialogs::Ui::UnreadBadgeStyle st; Dialogs::Ui::UnreadBadgeStyle st = BadgeStyle();
int count = 0; int count = 0;
QString string; QString string;
}; };
@ -359,27 +335,28 @@ void AddUnreadBadge(
return result; return result;
} }
} // namespace
class MainMenu::ToggleAccountsButton final : public Ui::AbstractButton { class MainMenu::ToggleAccountsButton final : public Ui::AbstractButton {
public: public:
explicit ToggleAccountsButton(QWidget *parent); explicit ToggleAccountsButton(QWidget *parent);
[[nodiscard]] int rightSkip() const { [[nodiscard]] int rightSkip() const {
return _rightSkip.current(); return _rightSkip;
} }
private: private:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void paintUnreadBadge(QPainter &p); void paintUnreadBadge(Painter &p);
void validateUnreadBadge(); void validateUnreadBadge();
[[nodiscard]] QString computeUnreadBadge() const; [[nodiscard]] QString computeUnreadBadge() const;
rpl::variable<int> _rightSkip; int _rightSkip = 0;
Ui::Animations::Simple _toggledAnimation; Ui::Animations::Simple _toggledAnimation;
bool _toggled = false; bool _toggled = false;
QString _unreadBadge; QString _unreadBadge;
int _unreadBadgeWidth = 0;
bool _unreadBadgeStale = false; bool _unreadBadgeStale = false;
}; };
@ -468,12 +445,12 @@ void MainMenu::ToggleAccountsButton::paintEvent(QPaintEvent *e) {
path.lineTo(points[0]); path.lineTo(points[0]);
auto hq = PainterHighQualityEnabler(p); auto hq = PainterHighQualityEnabler(p);
p.fillPath(path, st::mainMenuCoverFg); p.fillPath(path, st::windowSubTextFg);
paintUnreadBadge(p); paintUnreadBadge(p);
} }
void MainMenu::ToggleAccountsButton::paintUnreadBadge(QPainter &p) { void MainMenu::ToggleAccountsButton::paintUnreadBadge(Painter &p) {
const auto progress = 1. - _toggledAnimation.value(_toggled ? 1. : 0.); const auto progress = 1. - _toggledAnimation.value(_toggled ? 1. : 0.);
if (!progress) { if (!progress) {
return; return;
@ -482,31 +459,16 @@ void MainMenu::ToggleAccountsButton::paintUnreadBadge(QPainter &p) {
if (_unreadBadge.isEmpty()) { if (_unreadBadge.isEmpty()) {
return; return;
} }
Dialogs::Ui::UnreadBadgeStyle st;
const auto right = width() - st::mainMenuTogglePosition.x() - st::mainMenuToggleSize * 2; auto st = BadgeStyle();
const auto top = height() - st::mainMenuTogglePosition.y() - st::mainMenuToggleSize; const auto right = width()
const auto width = _unreadBadgeWidth; - st::mainMenuTogglePosition.x()
const auto rectHeight = st.size; - st::mainMenuToggleSize * 3;
const auto rectWidth = std::max(width + 2 * st.padding, rectHeight); const auto top = height()
const auto left = right - rectWidth; - st::mainMenuTogglePosition.y()
const auto textLeft = left + (rectWidth - width) / 2; - st::mainMenuBadgeSize / 2;
const auto textTop = top + (st.textTop ? st.textTop : (rectHeight - st.font->height) / 2); p.setOpacity(progress);
Dialogs::Ui::PaintUnreadBadge(p, _unreadBadge, right, top, st);
const auto isFill = IsFilledCover();
auto hq = PainterHighQualityEnabler(p);
auto brush = (isFill ? st::mainMenuCloudBg : st::msgServiceBg)->c;
brush.setAlphaF(progress * brush.alphaF());
p.setBrush(brush);
p.setPen(Qt::NoPen);
p.drawRoundedRect(left, top, rectWidth, rectHeight, rectHeight / 2, rectHeight / 2);
p.setFont(st.font);
auto pen = (isFill ? st::mainMenuCloudFg : st::msgServiceFg)->c;
pen.setAlphaF(progress * pen.alphaF());
p.setPen(pen);
p.drawText(textLeft, textTop + st.font->ascent, _unreadBadge);
} }
void MainMenu::ToggleAccountsButton::validateUnreadBadge() { void MainMenu::ToggleAccountsButton::validateUnreadBadge() {
@ -520,13 +482,10 @@ void MainMenu::ToggleAccountsButton::validateUnreadBadge() {
} }
_unreadBadge = computeUnreadBadge(); _unreadBadge = computeUnreadBadge();
Dialogs::Ui::UnreadBadgeStyle st; auto st = BadgeStyle();
_unreadBadgeWidth = st.font->width(_unreadBadge); _rightSkip = base
const auto rectHeight = st.size; + Dialogs::Ui::CountUnreadBadgeSize(_unreadBadge, st).width()
const auto rectWidth = std::max( + 2 * st::mainMenuToggleSize;
_unreadBadgeWidth + 2 * st.padding,
rectHeight);
_rightSkip = base + rectWidth + st::mainMenuToggleSize;
} }
QString MainMenu::ToggleAccountsButton::computeUnreadBadge() const { QString MainMenu::ToggleAccountsButton::computeUnreadBadge() const {
@ -597,6 +556,8 @@ MainMenu::MainMenu(
, _scroll(this, st::defaultSolidScroll) , _scroll(this, st::defaultSolidScroll)
, _inner(_scroll->setOwnedWidget( , _inner(_scroll->setOwnedWidget(
object_ptr<Ui::VerticalLayout>(_scroll.data()))) object_ptr<Ui::VerticalLayout>(_scroll.data())))
, _topShadowSkip(_inner->add(
object_ptr<Ui::FixedHeightWidget>(_inner.get(), st::lineWidth)))
, _accounts(_inner->add(object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>( , _accounts(_inner->add(object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_inner.get(), _inner.get(),
object_ptr<Ui::VerticalLayout>(_inner.get())))) object_ptr<Ui::VerticalLayout>(_inner.get()))))
@ -621,6 +582,13 @@ MainMenu::MainMenu(
setupArchive(); setupArchive();
setupMenu(); setupMenu();
const auto shadow = Ui::CreateChild<Ui::PlainShadow>(this);
widthValue(
) | rpl::start_with_next([=](int width) {
const auto line = st::lineWidth;
shadow->setGeometry(0, st::mainMenuCoverHeight - line, width, line);
}, shadow->lifetime());
_nightThemeSwitch.setCallback([this] { _nightThemeSwitch.setCallback([this] {
Expects(_nightThemeToggle != nullptr); Expects(_nightThemeToggle != nullptr);
@ -645,7 +613,6 @@ MainMenu::MainMenu(
}, _inner->lifetime()); }, _inner->lifetime());
parentResized(); parentResized();
refreshBackground();
_telegram->setMarkedText(Ui::Text::Link( _telegram->setMarkedText(Ui::Text::Link(
qsl("Telegram Desktop"), qsl("Telegram Desktop"),
@ -683,16 +650,6 @@ MainMenu::MainMenu(
updatePhone(); updatePhone();
}, lifetime()); }, lifetime());
using Window::Theme::BackgroundUpdate;
Window::Theme::Background()->updates(
) | rpl::start_with_next([=](const BackgroundUpdate &update) {
if (update.type == BackgroundUpdate::Type::ApplyingTheme) {
_nightThemeSwitches.fire(Window::Theme::IsNightMode());
}
if (update.type == BackgroundUpdate::Type::New) {
refreshBackground();
}
}, lifetime());
updatePhone(); updatePhone();
initResetScaleButton(); initResetScaleButton();
} }
@ -1106,53 +1063,6 @@ void MainMenu::setupMenu() {
updatePhone(); updatePhone();
} }
void MainMenu::refreshBackground() {
if (IsFilledCover()) {
return;
}
const auto fill = QSize(st::mainMenuWidth, st::mainMenuCoverHeight);
const auto intensityText = IntensityOfColor(st::mainMenuCoverFg->c);
const auto background = Window::Theme::Background();
const auto &prepared = background->prepared();
const auto rects = Ui::ComputeChatBackgroundRects(
fill,
prepared.size());
auto backgroundImage = QImage(
fill * cIntRetinaFactor(),
QImage::Format_ARGB32_Premultiplied);
QPainter p(&backgroundImage);
const auto drawShadow = [](QPainter &p) {
st::mainMenuShadow.paint(
p,
0,
st::mainMenuCoverHeight - st::mainMenuShadow.height(),
st::mainMenuWidth,
IntensityOfColor(st::mainMenuCoverFg->c) < 0.5
? Qt::white
: Qt::black);
};
// Background image.
p.drawImage(rects.to, prepared, rects.from);
// Cut off the part of the background that is under text.
const QRect underText(
st::mainMenuCoverNameLeft,
st::mainMenuCoverNameTop,
std::max(
st::semiboldFont->width(
_controller->session().user()->nameText().toString()),
st::normalFont->width(_phoneText)),
st::semiboldFont->height * 2);
if (IsShadowShown(backgroundImage, underText, intensityText)) {
drawShadow(p);
}
_background = backgroundImage;
}
void MainMenu::resizeEvent(QResizeEvent *e) { void MainMenu::resizeEvent(QResizeEvent *e) {
_inner->resizeToWidth(width()); _inner->resizeToWidth(width());
updateControlsGeometry(); updateControlsGeometry();
@ -1170,7 +1080,8 @@ void MainMenu::updateControlsGeometry() {
st::mainMenuCoverNameTop, st::mainMenuCoverNameTop,
width(), width(),
st::mainMenuCoverHeight - st::mainMenuCoverNameTop); st::mainMenuCoverHeight - st::mainMenuCoverNameTop);
const auto top = st::mainMenuCoverHeight; // Allow cover shadow over the scrolled content.
const auto top = st::mainMenuCoverHeight - st::lineWidth;
_scroll->setGeometry(0, top, width(), height() - top); _scroll->setGeometry(0, top, width(), height() - top);
updateInnerControlsGeometry(); updateInnerControlsGeometry();
} }
@ -1197,25 +1108,16 @@ void MainMenu::updatePhone() {
void MainMenu::paintEvent(QPaintEvent *e) { void MainMenu::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
const auto clip = e->rect(); const auto clip = e->rect();
const auto cover = QRect(0, 0, width(), st::mainMenuCoverHeight) const auto cover = QRect(0, 0, width(), st::mainMenuCoverHeight);
.intersected(e->rect());
const auto isFill = IsFilledCover(); p.fillRect(clip, st::mainMenuBg);
if (!isFill && !_background.isNull()) { if (cover.intersects(clip)) {
PainterHighQualityEnabler hq(p);
p.drawImage(0, 0, _background);
}
if (!cover.isEmpty()) {
const auto widthText = width() const auto widthText = width()
- st::mainMenuCoverNameLeft - st::mainMenuCoverNameLeft
- _toggleAccounts->rightSkip(); - _toggleAccounts->rightSkip();
if (isFill) {
p.fillRect(cover, st::mainMenuCoverBg);
}
p.setPen(st::mainMenuCoverFg);
p.setFont(st::semiboldFont); p.setFont(st::semiboldFont);
p.setPen(st::windowBoldFg);
_controller->session().user()->nameText().drawLeftElided( _controller->session().user()->nameText().drawLeftElided(
p, p,
st::mainMenuCoverNameLeft, st::mainMenuCoverNameLeft,
@ -1223,16 +1125,13 @@ void MainMenu::paintEvent(QPaintEvent *e) {
widthText, widthText,
width()); width());
p.setFont(st::normalFont); p.setFont(st::normalFont);
p.setPen(st::windowSubTextFg);
p.drawTextLeft( p.drawTextLeft(
st::mainMenuCoverStatusLeft, st::mainMenuCoverStatusLeft,
st::mainMenuCoverStatusTop, st::mainMenuCoverStatusTop,
width(), width(),
_phoneText); _phoneText);
} }
auto other = QRect(0, st::mainMenuCoverHeight, width(), height() - st::mainMenuCoverHeight).intersected(clip);
if (!other.isEmpty()) {
p.fillRect(other, st::mainMenuBg);
}
} }
void MainMenu::initResetScaleButton() { void MainMenu::initResetScaleButton() {

View file

@ -67,7 +67,6 @@ private:
void updateInnerControlsGeometry(); void updateInnerControlsGeometry();
void updatePhone(); void updatePhone();
void initResetScaleButton(); void initResetScaleButton();
void refreshBackground();
void toggleAccounts(); void toggleAccounts();
const not_null<SessionController*> _controller; const not_null<SessionController*> _controller;
@ -79,6 +78,7 @@ private:
base::flat_map< base::flat_map<
not_null<Main::Account*>, not_null<Main::Account*>,
base::unique_qptr<Ui::SettingsButton>> _watched; base::unique_qptr<Ui::SettingsButton>> _watched;
not_null<Ui::RpWidget*> _topShadowSkip;
not_null<Ui::SlideWrap<Ui::VerticalLayout>*> _accounts; not_null<Ui::SlideWrap<Ui::VerticalLayout>*> _accounts;
Ui::SlideWrap<Ui::SettingsButton> *_addAccount = nullptr; Ui::SlideWrap<Ui::SettingsButton> *_addAccount = nullptr;
not_null<Ui::SlideWrap<Ui::PlainShadow>*> _shadow; not_null<Ui::SlideWrap<Ui::PlainShadow>*> _shadow;
@ -97,7 +97,6 @@ private:
base::binary_guard _accountSwitchGuard; base::binary_guard _accountSwitchGuard;
QString _phoneText; QString _phoneText;
QImage _background;
}; };