Add an 'Update your OS' top bar.

Set EOL for Windows XP / Vista version at September 1, 2019.
This commit is contained in:
John Preston 2019-06-04 01:34:34 +03:00
parent 3355e6da0c
commit 1fb529803e
14 changed files with 299 additions and 8 deletions

View File

@ -553,3 +553,7 @@ callBarFg: dialogsNameFgActive; // phone call bar text and icons
importantTooltipBg: toastBg;
importantTooltipFg: toastFg;
importantTooltipFgLink: mediaviewTextLinkFg;
outdatedFg: #ffffff;
outdateSoonBg: #e08543;
outdatedBg: #e05745;

View File

@ -2020,6 +2020,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_polls_create_maximum" = "You have added the maximum number of options.";
"lng_polls_create_button" = "Create";
"lng_outdated_title" = "PLEASE UPDATE YOUR OPERATING SYSTEM.";
"lng_outdated_soon" = "Otherwise, Telegram Desktop will stop updating on {date}.";
"lng_outdated_now" = "So that Telegram Desktop can update to newer versions.";
// Wnd specific
"lng_wnd_choose_program_menu" = "Choose Default Program...";

View File

@ -32,4 +32,8 @@ QString SystemLanguage() {
return QString();
}
QDate WhenSystemBecomesOutdated() {
return QDate();
}
} // namespace Platform

View File

@ -114,6 +114,10 @@ QString SystemLanguage() {
return QString();
}
QDate WhenSystemBecomesOutdated() {
return QDate();
}
bool IsMac10_6OrGreater() {
return IsMacThatOrGreater<6>();
}

View File

@ -13,6 +13,7 @@ namespace Platform {
[[nodiscard]] QString SystemVersionPretty();
[[nodiscard]] QString SystemCountry();
[[nodiscard]] QString SystemLanguage();
[[nodiscard]] QDate WhenSystemBecomesOutdated();
[[nodiscard]] constexpr bool IsWindows();
[[nodiscard]] constexpr bool IsWindowsStoreBuild();

View File

@ -211,6 +211,13 @@ QString SystemLanguage() {
return QString();
}
QDate WhenSystemBecomesOutdated() {
if (!IsWindows7OrGreater()) {
return QDate(2019, 9, 1);
}
return QDate();
}
bool IsWindowsXPOrGreater() {
static const auto result = ::IsWindowsXPOrGreater();
return result;

View File

@ -231,11 +231,14 @@ void FlatLabel::setBreakEverywhere(bool breakEverywhere) {
_breakEverywhere = breakEverywhere;
}
void FlatLabel::setTryMakeSimilarLines(bool tryMakeSimilarLines) {
_tryMakeSimilarLines = tryMakeSimilarLines;
}
int FlatLabel::resizeGetHeight(int newWidth) {
_allowedWidth = newWidth;
int textWidth = countTextWidth();
int textHeight = countTextHeight(textWidth);
return textHeight;
_textWidth = countTextWidth();
return countTextHeight(_textWidth);
}
int FlatLabel::naturalWidth() const {
@ -247,9 +250,26 @@ QMargins FlatLabel::getMargins() const {
}
int FlatLabel::countTextWidth() const {
return _allowedWidth
const auto available = _allowedWidth
? _allowedWidth
: (_st.minWidth ? _st.minWidth : _text.maxWidth());
if (_allowedWidth > 0
&& _allowedWidth < _text.maxWidth()
&& _tryMakeSimilarLines) {
auto large = _allowedWidth;
auto small = _allowedWidth / 2;
const auto largeHeight = _text.countHeight(large);
while (large - small > 1) {
const auto middle = (large + small) / 2;
if (largeHeight == _text.countHeight(middle)) {
large = middle;
} else {
small = middle;
}
}
return large;
}
return available;
}
int FlatLabel::countTextHeight(int textWidth) {
@ -816,16 +836,25 @@ void FlatLabel::paintEvent(QPaintEvent *e) {
p.setPen(_st.textFg);
}
p.setTextPalette(_st.palette);
int textWidth = width() - _st.margin.left() - _st.margin.right();
const auto textWidth = _textWidth
? _textWidth
: (width() - _st.margin.left() - _st.margin.right());
const auto textLeft = _textWidth
? ((_st.align & Qt::AlignLeft)
? _st.margin.left()
: (_st.align & Qt::AlignHCenter)
? ((width() - _textWidth) / 2)
: (width() - _st.margin.right() - _textWidth))
: _st.margin.left();
auto selection = _selection.empty() ? (_contextMenu ? _savedSelection : _selection) : _selection;
bool heightExceeded = _st.maxHeight && (_st.maxHeight < _fullTextHeight || textWidth < _text.maxWidth());
bool renderElided = _breakEverywhere || heightExceeded;
if (renderElided) {
auto lineHeight = qMax(_st.style.lineHeight, _st.style.font->height);
auto lines = _st.maxHeight ? qMax(_st.maxHeight / lineHeight, 1) : ((height() / lineHeight) + 2);
_text.drawElided(p, _st.margin.left(), _st.margin.top(), textWidth, lines, _st.align, e->rect().y(), e->rect().bottom(), 0, _breakEverywhere, selection);
_text.drawElided(p, textLeft, _st.margin.top(), textWidth, lines, _st.align, e->rect().y(), e->rect().bottom(), 0, _breakEverywhere, selection);
} else {
_text.draw(p, _st.margin.left(), _st.margin.top(), textWidth, _st.align, e->rect().y(), e->rect().bottom(), selection);
_text.draw(p, textLeft, _st.margin.top(), textWidth, _st.align, e->rect().y(), e->rect().bottom(), selection);
}
}

View File

@ -106,6 +106,7 @@ public:
void setDoubleClickSelectsParagraph(bool doubleClickSelectsParagraph);
void setContextCopyText(const QString &copyText);
void setBreakEverywhere(bool breakEverywhere);
void setTryMakeSimilarLines(bool tryMakeSimilarLines);
int naturalWidth() const override;
QMargins getMargins() const override;
@ -179,8 +180,10 @@ private:
float64 _opacity = 1.;
int _allowedWidth = 0;
int _textWidth = 0;
int _fullTextHeight = 0;
bool _breakEverywhere = false;
bool _tryMakeSimilarLines = false;
style::cursor _cursor = style::cur_default;
bool _selectable = false;

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/themes/window_theme.h"
#include "window/window_controller.h"
#include "window/window_lock_widgets.h"
#include "window/window_outdated_bar.h"
#include "boxes/confirm_box.h"
#include "core/click_handler_types.h"
#include "core/application.h"
@ -108,6 +109,7 @@ QIcon CreateIcon() {
MainWindow::MainWindow()
: _positionUpdatedTimer([=] { savePosition(); })
, _outdated(CreateOutdatedBar(this))
, _body(this)
, _icon(CreateIcon())
, _titleText(qsl("Telegram")) {
@ -134,6 +136,18 @@ MainWindow::MainWindow()
checkLockByTerms();
}, lifetime());
if (_outdated) {
_outdated->heightValue(
) | rpl::filter([=] {
return window()->windowHandle() != nullptr;
}) | rpl::start_with_next([=](int height) {
if (!height) {
crl::on_main(this, [=] { _outdated.destroy(); });
}
updateControlsGeometry();
}, _outdated->lifetime());
}
_isActiveTimer.setCallback([this] { updateIsActive(0); });
_inactivePressTimer.setCallback([this] { setInactivePress(false); });
}
@ -341,7 +355,14 @@ HitTestResult MainWindow::hitTest(const QPoint &p) const {
int MainWindow::computeMinHeight() const {
const auto title = _title ? _title->height() : 0;
return title + st::windowMinHeight;
const auto outdated = [&] {
if (!_outdated) {
return 0;
}
_outdated->resizeToWidth(st::windowMinWidth);
return _outdated->height();
}();
return title + outdated + st::windowMinHeight;
}
void MainWindow::initSize() {
@ -446,6 +467,12 @@ void MainWindow::updateControlsGeometry() {
_title->setGeometry(0, bodyTop, width(), _title->height());
bodyTop += _title->height();
}
if (_outdated) {
Ui::SendPendingMoveResizeEvents(_outdated.data());
_outdated->resizeToWidth(width());
_outdated->moveToLeft(0, bodyTop);
bodyTop += _outdated->height();
}
if (_rightColumn) {
bodyWidth -= _rightColumn->width();
_rightColumn->setGeometry(bodyWidth, bodyTop, width() - bodyWidth, height() - bodyTop);

View File

@ -165,6 +165,7 @@ private:
std::unique_ptr<Window::Controller> _controller;
object_ptr<TitleWidget> _title = { nullptr };
object_ptr<Ui::RpWidget> _outdated;
object_ptr<TWidget> _body;
object_ptr<TWidget> _rightColumn = { nullptr };
QPointer<BoxContent> _termsBox;

View File

@ -278,6 +278,24 @@ connectingProxyOff: icon {{ "proxy_off", menuIconFg }};
connectingProxyOn: icon {{ "proxy_on", windowBgActive }};
connectingDuration: 150;
windowOutdatedDetails: FlatLabel(defaultFlatLabel) {
align: align(top);
minWidth: 100px;
textFg: outdatedFg;
}
windowOutdatedTitle: FlatLabel(windowOutdatedDetails) {
style: semiboldTextStyle;
}
windowOutdatedPadding: margins(10px, 10px, 10px, 10px);
windowOutdatedSkip: 6px;
windowOutdatedClose: IconButton(defaultIconButton) {
width: 60px;
height: 60px;
icon: icon {{ "info_close", outdatedFg }};
iconOver: icon {{ "info_close", outdatedFg }};
iconPosition: point(-1px, -1px);
}
// Mac specific
macAccessoryWidth: 450.;

View File

@ -0,0 +1,169 @@
/*
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 "window/window_outdated_bar.h"
#include "ui/widgets/labels.h" // Ui::FlatLabel
#include "ui/widgets/buttons.h" // Ui::IconButton
#include "ui/wrap/slide_wrap.h" // Ui::SlideWrap
#include "info/profile/info_profile_values.h" // Info::Profile::ToUpperValue
#include "platform/platform_info.h"
#include "lang/lang_keys.h"
#include "styles/style_window.h"
namespace Window {
namespace {
constexpr auto kMinimalSkip = 7;
constexpr auto kSoonSkip = 30;
constexpr auto kNowSkip = 90;
class Bar : public Ui::RpWidget {
public:
Bar(not_null<QWidget*> parent, QDate date);
int resizeGetHeight(int newWidth);
rpl::producer<> hideClicks() const;
protected:
void paintEvent(QPaintEvent *e) override;
private:
QDate _date;
object_ptr<Ui::FlatLabel> _title;
object_ptr<Ui::FlatLabel> _details;
object_ptr<Ui::IconButton> _close;
bool _soon = false;
};
Bar::Bar(not_null<QWidget*> parent, QDate date)
: _date(date)
, _title(
this,
Lang::Viewer(lng_outdated_title) | Info::Profile::ToUpperValue(),
st::windowOutdatedTitle)
, _details(this,
QString(),
Ui::FlatLabel::InitType::Simple,
st::windowOutdatedDetails)
, _close(this, st::windowOutdatedClose)
, _soon(_date >= QDate::currentDate()) {
_title->setTryMakeSimilarLines(true);
_details->setTryMakeSimilarLines(true);
_details->setText(_soon
? lng_outdated_soon(lt_date, langDayOfMonthFull(date))
: lang(lng_outdated_now));
}
rpl::producer<> Bar::hideClicks() const {
return _close->clicks() | rpl::map([] {
return rpl::empty_value();
});
}
int Bar::resizeGetHeight(int newWidth) {
const auto padding = st::windowOutdatedPadding;
const auto skip = _close->width();
const auto available = newWidth - 2 * skip;
_title->resizeToWidth(available);
_title->moveToLeft(skip, padding.top(), newWidth);
_details->resizeToWidth(available);
_details->moveToLeft(
skip,
_title->y() + _title->height() + st::windowOutdatedSkip,
newWidth);
_close->moveToRight(0, 0, newWidth);
return _details->y() + _details->height() + padding.bottom();
}
void Bar::paintEvent(QPaintEvent *e) {
QPainter(this).fillRect(
e->rect(),
_soon ? st::outdateSoonBg : st::outdatedBg);
}
QString LastHiddenPath() {
return cWorkingDir() + qsl("tdata/outdated_hidden");
}
[[nodiscard]] bool Skip(const QDate &date) {
auto file = QFile(LastHiddenPath());
if (!file.open(QIODevice::ReadOnly) || file.size() != sizeof(qint32)) {
return false;
}
const auto content = file.readAll();
if (content.size() != sizeof(qint32)) {
return false;
}
const auto value = *reinterpret_cast<const qint32*>(content.constData());
const auto year = (value / 10000);
const auto month = (value % 10000) / 100;
const auto day = (value % 100);
const auto last = QDate(year, month, day);
if (!last.isValid()) {
return false;
}
const auto today = QDate::currentDate();
if (last > today) {
return false;
}
const auto skipped = last.daysTo(today);
if (today > date && last <= date) {
return (skipped < kMinimalSkip);
} else if (today <= date) {
return (skipped < kSoonSkip);
} else {
return (skipped < kNowSkip);
}
}
void Closed() {
auto file = QFile(LastHiddenPath());
if (!file.open(QIODevice::WriteOnly)) {
return;
}
const auto today = QDate::currentDate();
const auto value = qint32(0
+ today.year() * 10000
+ today.month() * 100
+ today.day());
file.write(QByteArray::fromRawData(
reinterpret_cast<const char*>(&value),
sizeof(qint32)));
}
} // namespace
object_ptr<Ui::RpWidget> CreateOutdatedBar(not_null<QWidget*> parent) {
const auto date = Platform::WhenSystemBecomesOutdated();
if (date.isNull()) {
return { nullptr };
} else if (Skip(date)) {
return { nullptr };
}
auto result = object_ptr<Ui::SlideWrap<Bar>>(
parent.get(),
object_ptr<Bar>(parent.get(), date));
const auto wrap = result.data();
wrap->entity()->hideClicks(
) | rpl::start_with_next([=] {
wrap->toggle(false, anim::type::normal);
Closed();
}, wrap->lifetime());
return std::move(result);
}
} // namespace Window

View File

@ -0,0 +1,18 @@
/*
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 Ui {
class RpWidget;
} // namespace Ui
namespace Window {
object_ptr<Ui::RpWidget> CreateOutdatedBar(not_null<QWidget*> parent);
} // namespace Window

View File

@ -831,6 +831,8 @@
<(src_loc)/window/window_lock_widgets.h
<(src_loc)/window/window_main_menu.cpp
<(src_loc)/window/window_main_menu.h
<(src_loc)/window/window_outdated_bar.cpp
<(src_loc)/window/window_outdated_bar.h
<(src_loc)/window/window_peer_menu.cpp
<(src_loc)/window/window_peer_menu.h
<(src_loc)/window/window_slide_animation.cpp