window_outdated_bar.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "ui/controls/window_outdated_bar.h"
  8. #include "ui/widgets/labels.h" // Ui::FlatLabel
  9. #include "ui/widgets/buttons.h" // Ui::IconButton
  10. #include "ui/wrap/slide_wrap.h" // Ui::SlideWrap
  11. #include "ui/text/text_utilities.h" // Ui::Text::ToUpper
  12. #include "base/platform/base_platform_info.h"
  13. #include "lang/lang_keys.h"
  14. #include "styles/style_window.h"
  15. #include <QtCore/QFile>
  16. namespace Ui {
  17. namespace {
  18. constexpr auto kMinimalSkip = 7;
  19. constexpr auto kSoonSkip = 30;
  20. constexpr auto kNowSkip = 90;
  21. class Bar final : public RpWidget {
  22. public:
  23. Bar(not_null<QWidget*> parent, QDate date);
  24. int resizeGetHeight(int newWidth) override;
  25. [[nodiscard]] rpl::producer<> hideClicks() const;
  26. protected:
  27. void paintEvent(QPaintEvent *e) override;
  28. private:
  29. QDate _date;
  30. object_ptr<FlatLabel> _title;
  31. object_ptr<FlatLabel> _details;
  32. object_ptr<IconButton> _close;
  33. bool _soon = false;
  34. };
  35. [[nodiscard]] rpl::producer<QString> OutdatedReasonPhrase() {
  36. const auto why = Platform::WhySystemBecomesOutdated();
  37. return (why == Platform::OutdateReason::Is32Bit)
  38. ? tr::lng_outdated_title_bits()
  39. : tr::lng_outdated_title();
  40. }
  41. Bar::Bar(not_null<QWidget*> parent, QDate date)
  42. : _date(date)
  43. , _title(
  44. this,
  45. OutdatedReasonPhrase() | Text::ToUpper(),
  46. st::windowOutdatedTitle)
  47. , _details(this,
  48. QString(),
  49. st::windowOutdatedDetails)
  50. , _close(this, st::windowOutdatedClose)
  51. , _soon(_date >= QDate::currentDate()) {
  52. _title->setTryMakeSimilarLines(true);
  53. _details->setTryMakeSimilarLines(true);
  54. _details->setText(_soon
  55. ? tr::lng_outdated_soon(tr::now, lt_date, langDayOfMonthFull(date))
  56. : tr::lng_outdated_now(tr::now));
  57. }
  58. rpl::producer<> Bar::hideClicks() const {
  59. return _close->clicks() | rpl::to_empty;
  60. }
  61. int Bar::resizeGetHeight(int newWidth) {
  62. const auto padding = st::windowOutdatedPadding;
  63. const auto skip = _close->width();
  64. const auto available = newWidth - 2 * skip;
  65. _title->resizeToWidth(available);
  66. _title->moveToLeft(skip, padding.top(), newWidth);
  67. _details->resizeToWidth(available);
  68. _details->moveToLeft(
  69. skip,
  70. _title->y() + _title->height() + st::windowOutdatedSkip,
  71. newWidth);
  72. _close->moveToRight(0, 0, newWidth);
  73. return _details->y() + _details->height() + padding.bottom();
  74. }
  75. void Bar::paintEvent(QPaintEvent *e) {
  76. QPainter(this).fillRect(
  77. e->rect(),
  78. _soon ? st::outdateSoonBg : st::outdatedBg);
  79. }
  80. [[nodiscard]] QString LastHiddenPath(const QString &workingDir) {
  81. return workingDir + u"tdata/outdated_hidden"_q;
  82. }
  83. [[nodiscard]] bool Skip(const QDate &date, const QString &workingDir) {
  84. auto file = QFile(LastHiddenPath(workingDir));
  85. if (!file.open(QIODevice::ReadOnly) || file.size() != sizeof(qint32)) {
  86. return false;
  87. }
  88. const auto content = file.readAll();
  89. if (content.size() != sizeof(qint32)) {
  90. return false;
  91. }
  92. const auto value = *reinterpret_cast<const qint32*>(content.constData());
  93. const auto year = (value / 10000);
  94. const auto month = (value % 10000) / 100;
  95. const auto day = (value % 100);
  96. const auto last = QDate(year, month, day);
  97. if (!last.isValid()) {
  98. return false;
  99. }
  100. const auto today = QDate::currentDate();
  101. if (last > today) {
  102. return false;
  103. }
  104. const auto skipped = last.daysTo(today);
  105. if (today > date && last <= date) {
  106. return (skipped < kMinimalSkip);
  107. } else if (today <= date) {
  108. return (skipped < kSoonSkip);
  109. } else {
  110. return (skipped < kNowSkip);
  111. }
  112. }
  113. void Closed(const QString &workingDir) {
  114. auto file = QFile(LastHiddenPath(workingDir));
  115. if (!file.open(QIODevice::WriteOnly)) {
  116. return;
  117. }
  118. const auto today = QDate::currentDate();
  119. const auto value = qint32(0
  120. + today.year() * 10000
  121. + today.month() * 100
  122. + today.day());
  123. file.write(QByteArray::fromRawData(
  124. reinterpret_cast<const char*>(&value),
  125. sizeof(qint32)));
  126. }
  127. } // namespace
  128. object_ptr<RpWidget> CreateOutdatedBar(
  129. not_null<QWidget*> parent,
  130. const QString &workingPath) {
  131. const auto date = Platform::WhenSystemBecomesOutdated();
  132. if (date.isNull()) {
  133. return { nullptr };
  134. } else if (Skip(date, workingPath)) {
  135. return { nullptr };
  136. }
  137. auto result = object_ptr<SlideWrap<Bar>>(
  138. parent.get(),
  139. object_ptr<Bar>(parent.get(), date));
  140. const auto wrap = result.data();
  141. wrap->entity()->hideClicks(
  142. ) | rpl::start_with_next([=] {
  143. wrap->toggle(false, anim::type::normal);
  144. Closed(workingPath);
  145. }, wrap->lifetime());
  146. wrap->entity()->resizeToWidth(st::windowMinWidth);
  147. wrap->show(anim::type::instant);
  148. return result;
  149. }
  150. } // namespace Ui