auto_download_box.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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 "boxes/auto_download_box.h"
  8. #include "lang/lang_keys.h"
  9. #include "main/main_session.h"
  10. #include "main/main_session_settings.h"
  11. #include "data/data_session.h"
  12. #include "data/data_auto_download.h"
  13. #include "ui/vertical_list.h"
  14. #include "ui/widgets/continuous_sliders.h"
  15. #include "ui/widgets/buttons.h"
  16. #include "ui/wrap/vertical_layout.h"
  17. #include "ui/wrap/wrap.h"
  18. #include "storage/localstorage.h"
  19. #include "settings/settings_common.h"
  20. #include "export/view/export_view_settings.h"
  21. #include "styles/style_layers.h"
  22. #include "styles/style_boxes.h"
  23. #include "styles/style_settings.h"
  24. namespace {
  25. constexpr auto kMegabyte = 1024 * 1024;
  26. constexpr auto kDefaultDownloadLimit = 10 * kMegabyte;
  27. constexpr auto kDefaultAutoPlayLimit = 50 * kMegabyte;
  28. using Type = Data::AutoDownload::Type;
  29. not_null<int64*> AddSizeLimitSlider(
  30. not_null<Ui::VerticalLayout*> container,
  31. const base::flat_map<Type, int64> &values,
  32. int64 defaultValue) {
  33. using Pair = base::flat_map<Type, int64>::value_type;
  34. const auto limits = Ui::CreateChild<rpl::event_stream<int64>>(
  35. container.get());
  36. const auto currentLimit = ranges::max_element(
  37. values,
  38. std::less<>(),
  39. [](Pair pair) { return pair.second; })->second;
  40. const auto startLimit = currentLimit ? currentLimit : defaultValue;
  41. const auto result = Ui::CreateChild<int64>(container.get(), startLimit);
  42. Settings::AddButtonWithLabel(
  43. container,
  44. tr::lng_media_size_limit(),
  45. limits->events_starting_with_copy(
  46. startLimit
  47. ) | rpl::map([](int64 value) {
  48. return tr::lng_media_size_up_to(
  49. tr::now,
  50. lt_size,
  51. QString::number(value / kMegabyte) + " MB");
  52. }),
  53. st::autoDownloadLimitButton
  54. )->setAttribute(Qt::WA_TransparentForMouseEvents);
  55. const auto slider = container->add(
  56. object_ptr<Ui::MediaSlider>(container, st::autoDownloadLimitSlider),
  57. st::autoDownloadLimitPadding);
  58. slider->resize(st::autoDownloadLimitSlider.seekSize);
  59. slider->setPseudoDiscrete(
  60. Export::View::kSizeValueCount,
  61. Export::View::SizeLimitByIndex,
  62. *result,
  63. [=](int64 value) {
  64. *result = value;
  65. limits->fire_copy(value);
  66. });
  67. return result;
  68. }
  69. } // namespace
  70. AutoDownloadBox::AutoDownloadBox(
  71. QWidget*,
  72. not_null<Main::Session*> session,
  73. Data::AutoDownload::Source source)
  74. : _session(session)
  75. , _source(source) {
  76. }
  77. void AutoDownloadBox::prepare() {
  78. setupContent();
  79. }
  80. void AutoDownloadBox::setupContent() {
  81. using namespace rpl::mappers;
  82. using namespace Settings;
  83. using namespace Data::AutoDownload;
  84. using Type = Data::AutoDownload::Type;
  85. using Pair = base::flat_map<Type, int64>::value_type;
  86. setTitle(tr::lng_profile_settings_section());
  87. const auto settings = &_session->settings().autoDownload();
  88. auto wrap = object_ptr<Ui::VerticalLayout>(this);
  89. const auto content = wrap.data();
  90. setInnerWidget(object_ptr<Ui::OverrideMargins>(
  91. this,
  92. std::move(wrap)));
  93. const auto add = [&](
  94. not_null<base::flat_map<Type, int64>*> values,
  95. Type type,
  96. rpl::producer<QString> label) {
  97. const auto value = settings->bytesLimit(_source, type);
  98. content->add(object_ptr<Ui::SettingsButton>(
  99. content,
  100. std::move(label),
  101. st::settingsButtonNoIcon
  102. ))->toggleOn(
  103. rpl::single(value > 0)
  104. )->toggledChanges(
  105. ) | rpl::start_with_next([=](bool enabled) {
  106. (*values)[type] = enabled ? 1 : 0;
  107. }, content->lifetime());
  108. values->emplace(type, value);
  109. };
  110. AddSubsectionTitle(content, tr::lng_media_auto_title());
  111. const auto downloadValues = Ui::CreateChild<base::flat_map<Type, int64>>(
  112. content);
  113. add(downloadValues, Type::Photo, tr::lng_media_photo_title());
  114. add(downloadValues, Type::File, tr::lng_media_file_title());
  115. const auto downloadLimit = AddSizeLimitSlider(
  116. content,
  117. *downloadValues,
  118. kDefaultDownloadLimit);
  119. AddSkip(content);
  120. AddSubsectionTitle(content, tr::lng_media_auto_play());
  121. const auto autoPlayValues = Ui::CreateChild<base::flat_map<Type, int64>>(
  122. content);
  123. add(
  124. autoPlayValues,
  125. Type::AutoPlayVideoMessage,
  126. tr::lng_media_video_messages_title());
  127. add(autoPlayValues, Type::AutoPlayVideo, tr::lng_media_video_title());
  128. add(autoPlayValues, Type::AutoPlayGIF, tr::lng_media_animation_title());
  129. const auto autoPlayLimit = AddSizeLimitSlider(
  130. content,
  131. *autoPlayValues,
  132. kDefaultAutoPlayLimit);
  133. const auto limitByType = [=](Type type) {
  134. return (ranges::find(kAutoPlayTypes, type) != end(kAutoPlayTypes))
  135. ? *autoPlayLimit
  136. : *downloadLimit;
  137. };
  138. addButton(tr::lng_connection_save(), [=] {
  139. auto &&values = ranges::views::concat(
  140. *downloadValues,
  141. *autoPlayValues);
  142. auto allowMore = values | ranges::views::filter([&](Pair pair) {
  143. const auto &[type, enabled] = pair;
  144. const auto value = enabled ? limitByType(type) : 0;
  145. const auto old = settings->bytesLimit(_source, type);
  146. return (old < value);
  147. }) | ranges::views::transform([](Pair pair) {
  148. return pair.first;
  149. });
  150. const auto less = ranges::any_of(*autoPlayValues, [&](Pair pair) {
  151. const auto &[type, enabled] = pair;
  152. const auto value = enabled ? limitByType(type) : 0;
  153. return value < settings->bytesLimit(_source, type);
  154. });
  155. const auto allowMoreTypes = base::flat_set<Type>(
  156. allowMore.begin(),
  157. allowMore.end());
  158. const auto changed = ranges::any_of(values, [&](Pair pair) {
  159. const auto &[type, enabled] = pair;
  160. const auto value = enabled ? limitByType(type) : 0;
  161. return value != settings->bytesLimit(_source, type);
  162. });
  163. const auto &kHidden = kStreamedTypes;
  164. const auto hiddenChanged = ranges::any_of(kHidden, [&](Type type) {
  165. const auto now = settings->bytesLimit(_source, type);
  166. return (now > 0) && (now != limitByType(type));
  167. });
  168. if (changed) {
  169. for (const auto &[type, enabled] : values) {
  170. const auto value = enabled ? limitByType(type) : 0;
  171. settings->setBytesLimit(_source, type, value);
  172. }
  173. }
  174. if (hiddenChanged) {
  175. for (const auto type : kHidden) {
  176. const auto now = settings->bytesLimit(_source, type);
  177. if (now > 0) {
  178. settings->setBytesLimit(
  179. _source,
  180. type,
  181. limitByType(type));
  182. }
  183. }
  184. }
  185. if (changed || hiddenChanged) {
  186. _session->saveSettingsDelayed();
  187. }
  188. if (allowMoreTypes.contains(Type::Photo)) {
  189. _session->data().photoLoadSettingsChanged();
  190. }
  191. if (ranges::any_of(allowMoreTypes, _1 != Type::Photo)) {
  192. _session->data().documentLoadSettingsChanged();
  193. }
  194. if (less) {
  195. _session->data().checkPlayingAnimations();
  196. }
  197. closeBox();
  198. });
  199. addButton(tr::lng_cancel(), [=] { closeBox(); });
  200. setDimensionsToContent(st::boxWidth, content);
  201. }