changelogs.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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 "core/changelogs.h"
  8. #include "lang/lang_keys.h"
  9. #include "core/application.h"
  10. #include "main/main_domain.h"
  11. #include "main/main_session.h"
  12. #include "storage/storage_domain.h"
  13. #include "data/data_session.h"
  14. #include "base/qt/qt_common_adapters.h"
  15. #include "mainwindow.h"
  16. #include "apiwrap.h"
  17. namespace Core {
  18. namespace {
  19. std::map<int, const char*> BetaLogs() {
  20. return {
  21. {
  22. 4008011,
  23. "- Fix initial video playback speed.\n"
  24. "- Use native window resize on Windows 11.\n"
  25. "- Fix memory leak in Direct3D 11 media viewer on Windows.\n"
  26. },
  27. {
  28. 4010004,
  29. "- Statistics in channels and group chats.\n"
  30. "- Nice looking code blocks with syntax highlight.\n"
  31. "- Copy full code block by click on its header.\n"
  32. "- Send a highlighted code block using ```language syntax.\n"
  33. }
  34. };
  35. };
  36. } // namespace
  37. Changelogs::Changelogs(not_null<Main::Session*> session, int oldVersion)
  38. : _session(session)
  39. , _oldVersion(oldVersion) {
  40. _session->data().chatsListChanges(
  41. ) | rpl::filter([](Data::Folder *folder) {
  42. return !folder;
  43. }) | rpl::start_with_next([=] {
  44. requestCloudLogs();
  45. }, _chatsSubscription);
  46. }
  47. std::unique_ptr<Changelogs> Changelogs::Create(
  48. not_null<Main::Session*> session) {
  49. auto &local = Core::App().domain().local();
  50. const auto oldVersion = local.oldVersion();
  51. local.clearOldVersion();
  52. return (oldVersion > 0 && oldVersion < AppVersion)
  53. ? std::make_unique<Changelogs>(session, oldVersion)
  54. : nullptr;
  55. }
  56. void Changelogs::requestCloudLogs() {
  57. _chatsSubscription.destroy();
  58. const auto callback = [this](const MTPUpdates &result) {
  59. _session->api().applyUpdates(result);
  60. auto resultEmpty = true;
  61. switch (result.type()) {
  62. case mtpc_updateShortMessage:
  63. case mtpc_updateShortChatMessage:
  64. case mtpc_updateShort:
  65. resultEmpty = false;
  66. break;
  67. case mtpc_updatesCombined:
  68. resultEmpty = result.c_updatesCombined().vupdates().v.isEmpty();
  69. break;
  70. case mtpc_updates:
  71. resultEmpty = result.c_updates().vupdates().v.isEmpty();
  72. break;
  73. case mtpc_updatesTooLong:
  74. case mtpc_updateShortSentMessage:
  75. LOG(("API Error: Bad updates type in app changelog."));
  76. break;
  77. }
  78. if (resultEmpty) {
  79. addLocalLogs();
  80. }
  81. };
  82. _session->api().requestChangelog(
  83. FormatVersionPrecise(_oldVersion),
  84. crl::guard(this, callback));
  85. }
  86. void Changelogs::addLocalLogs() {
  87. if (AppBetaVersion || cAlphaVersion()) {
  88. addBetaLogs();
  89. }
  90. if (!_addedSomeLocal) {
  91. const auto text = tr::lng_new_version_wrap(
  92. tr::now,
  93. lt_version,
  94. QString::fromLatin1(AppVersionStr),
  95. lt_changes,
  96. tr::lng_new_version_minor(tr::now),
  97. lt_link,
  98. Core::App().changelogLink());
  99. addLocalLog(text.trimmed());
  100. }
  101. }
  102. void Changelogs::addLocalLog(const QString &text) {
  103. auto textWithEntities = TextWithEntities{ text };
  104. TextUtilities::ParseEntities(textWithEntities, TextParseLinks);
  105. _session->data().serviceNotification(textWithEntities);
  106. _addedSomeLocal = true;
  107. };
  108. void Changelogs::addBetaLogs() {
  109. for (const auto &[version, changes] : BetaLogs()) {
  110. addBetaLog(version, changes);
  111. }
  112. }
  113. void Changelogs::addBetaLog(int changeVersion, const char *changes) {
  114. if (_oldVersion >= changeVersion) {
  115. return;
  116. }
  117. const auto text = [&] {
  118. static const auto simple = u"\n- "_q;
  119. static const auto separator = QString::fromUtf8("\n\xE2\x80\xA2 ");
  120. auto result = QString::fromUtf8(changes).trimmed();
  121. if (result.startsWith(base::StringViewMid(simple, 1))) {
  122. result = separator.mid(1) + result.mid(simple.size() - 1);
  123. }
  124. return result.replace(simple, separator);
  125. }();
  126. const auto version = FormatVersionDisplay(changeVersion);
  127. const auto log = u"New in version %1 beta:\n\n"_q.arg(version) + text;
  128. addLocalLog(log);
  129. }
  130. QString FormatVersionDisplay(int version) {
  131. return QString::number(version / 1000000)
  132. + '.' + QString::number((version % 1000000) / 1000)
  133. + ((version % 1000)
  134. ? ('.' + QString::number(version % 1000))
  135. : QString());
  136. }
  137. QString FormatVersionPrecise(int version) {
  138. return QString::number(version / 1000000)
  139. + '.' + QString::number((version % 1000000) / 1000)
  140. + '.' + QString::number(version % 1000);
  141. }
  142. } // namespace Core