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 {
UnreadBadgeInDialogs = 0,
UnreadBadgeInMainMenu,
UnreadBadgeInHistoryToDown,
UnreadBadgeInStickersPanel,
UnreadBadgeInStickersBox,

View file

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

View file

@ -62,37 +62,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtGui/QWindow>
#include <QtGui/QScreen>
namespace Window {
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) {
return (modifiers & Qt::ShiftModifier) && (modifiers & Qt::AltModifier);
}
@ -159,15 +131,19 @@ void ShowCallsBox(not_null<Window::SessionController*> window) {
return accounts;
}
} // namespace
namespace Window {
struct UnreadBadge {
int count = 0;
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(
not_null<Ui::SettingsButton*> button,
rpl::producer<UnreadBadge> value) {
@ -177,7 +153,7 @@ void AddUnreadBadge(
}
Ui::RpWidget widget;
Dialogs::Ui::UnreadBadgeStyle st;
Dialogs::Ui::UnreadBadgeStyle st = BadgeStyle();
int count = 0;
QString string;
};
@ -359,27 +335,28 @@ void AddUnreadBadge(
return result;
}
} // namespace
class MainMenu::ToggleAccountsButton final : public Ui::AbstractButton {
public:
explicit ToggleAccountsButton(QWidget *parent);
[[nodiscard]] int rightSkip() const {
return _rightSkip.current();
return _rightSkip;
}
private:
void paintEvent(QPaintEvent *e) override;
void paintUnreadBadge(QPainter &p);
void paintUnreadBadge(Painter &p);
void validateUnreadBadge();
[[nodiscard]] QString computeUnreadBadge() const;
rpl::variable<int> _rightSkip;
int _rightSkip = 0;
Ui::Animations::Simple _toggledAnimation;
bool _toggled = false;
QString _unreadBadge;
int _unreadBadgeWidth = 0;
bool _unreadBadgeStale = false;
};
@ -468,12 +445,12 @@ void MainMenu::ToggleAccountsButton::paintEvent(QPaintEvent *e) {
path.lineTo(points[0]);
auto hq = PainterHighQualityEnabler(p);
p.fillPath(path, st::mainMenuCoverFg);
p.fillPath(path, st::windowSubTextFg);
paintUnreadBadge(p);
}
void MainMenu::ToggleAccountsButton::paintUnreadBadge(QPainter &p) {
void MainMenu::ToggleAccountsButton::paintUnreadBadge(Painter &p) {
const auto progress = 1. - _toggledAnimation.value(_toggled ? 1. : 0.);
if (!progress) {
return;
@ -482,31 +459,16 @@ void MainMenu::ToggleAccountsButton::paintUnreadBadge(QPainter &p) {
if (_unreadBadge.isEmpty()) {
return;
}
Dialogs::Ui::UnreadBadgeStyle st;
const auto right = width() - st::mainMenuTogglePosition.x() - st::mainMenuToggleSize * 2;
const auto top = height() - st::mainMenuTogglePosition.y() - st::mainMenuToggleSize;
const auto width = _unreadBadgeWidth;
const auto rectHeight = st.size;
const auto rectWidth = std::max(width + 2 * st.padding, rectHeight);
const auto left = right - rectWidth;
const auto textLeft = left + (rectWidth - width) / 2;
const auto textTop = top + (st.textTop ? st.textTop : (rectHeight - st.font->height) / 2);
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);
auto st = BadgeStyle();
const auto right = width()
- st::mainMenuTogglePosition.x()
- st::mainMenuToggleSize * 3;
const auto top = height()
- st::mainMenuTogglePosition.y()
- st::mainMenuBadgeSize / 2;
p.setOpacity(progress);
Dialogs::Ui::PaintUnreadBadge(p, _unreadBadge, right, top, st);
}
void MainMenu::ToggleAccountsButton::validateUnreadBadge() {
@ -520,13 +482,10 @@ void MainMenu::ToggleAccountsButton::validateUnreadBadge() {
}
_unreadBadge = computeUnreadBadge();
Dialogs::Ui::UnreadBadgeStyle st;
_unreadBadgeWidth = st.font->width(_unreadBadge);
const auto rectHeight = st.size;
const auto rectWidth = std::max(
_unreadBadgeWidth + 2 * st.padding,
rectHeight);
_rightSkip = base + rectWidth + st::mainMenuToggleSize;
auto st = BadgeStyle();
_rightSkip = base
+ Dialogs::Ui::CountUnreadBadgeSize(_unreadBadge, st).width()
+ 2 * st::mainMenuToggleSize;
}
QString MainMenu::ToggleAccountsButton::computeUnreadBadge() const {
@ -597,6 +556,8 @@ MainMenu::MainMenu(
, _scroll(this, st::defaultSolidScroll)
, _inner(_scroll->setOwnedWidget(
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>>(
_inner.get(),
object_ptr<Ui::VerticalLayout>(_inner.get()))))
@ -621,6 +582,13 @@ MainMenu::MainMenu(
setupArchive();
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] {
Expects(_nightThemeToggle != nullptr);
@ -645,7 +613,6 @@ MainMenu::MainMenu(
}, _inner->lifetime());
parentResized();
refreshBackground();
_telegram->setMarkedText(Ui::Text::Link(
qsl("Telegram Desktop"),
@ -683,16 +650,6 @@ MainMenu::MainMenu(
updatePhone();
}, 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();
initResetScaleButton();
}
@ -1106,53 +1063,6 @@ void MainMenu::setupMenu() {
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) {
_inner->resizeToWidth(width());
updateControlsGeometry();
@ -1170,7 +1080,8 @@ void MainMenu::updateControlsGeometry() {
st::mainMenuCoverNameTop,
width(),
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);
updateInnerControlsGeometry();
}
@ -1197,25 +1108,16 @@ void MainMenu::updatePhone() {
void MainMenu::paintEvent(QPaintEvent *e) {
Painter p(this);
const auto clip = e->rect();
const auto cover = QRect(0, 0, width(), st::mainMenuCoverHeight)
.intersected(e->rect());
const auto cover = QRect(0, 0, width(), st::mainMenuCoverHeight);
const auto isFill = IsFilledCover();
if (!isFill && !_background.isNull()) {
PainterHighQualityEnabler hq(p);
p.drawImage(0, 0, _background);
}
if (!cover.isEmpty()) {
p.fillRect(clip, st::mainMenuBg);
if (cover.intersects(clip)) {
const auto widthText = width()
- st::mainMenuCoverNameLeft
- _toggleAccounts->rightSkip();
if (isFill) {
p.fillRect(cover, st::mainMenuCoverBg);
}
p.setPen(st::mainMenuCoverFg);
p.setFont(st::semiboldFont);
p.setPen(st::windowBoldFg);
_controller->session().user()->nameText().drawLeftElided(
p,
st::mainMenuCoverNameLeft,
@ -1223,16 +1125,13 @@ void MainMenu::paintEvent(QPaintEvent *e) {
widthText,
width());
p.setFont(st::normalFont);
p.setPen(st::windowSubTextFg);
p.drawTextLeft(
st::mainMenuCoverStatusLeft,
st::mainMenuCoverStatusTop,
width(),
_phoneText);
}
auto other = QRect(0, st::mainMenuCoverHeight, width(), height() - st::mainMenuCoverHeight).intersected(clip);
if (!other.isEmpty()) {
p.fillRect(other, st::mainMenuBg);
}
}
void MainMenu::initResetScaleButton() {

View file

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