window_theme.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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. #pragma once
  8. #include "data/data_wall_paper.h"
  9. #include "data/data_cloud_themes.h"
  10. #include "ui/style/style_core_palette.h"
  11. class QFileSystemWatcher;
  12. struct FilePrepareResult;
  13. namespace style {
  14. struct colorizer;
  15. } // namespace style
  16. namespace Main {
  17. class Session;
  18. } // namespace Main
  19. namespace Window {
  20. class Controller;
  21. } // namespace Window
  22. namespace Ui {
  23. struct ChatThemeBackground;
  24. class ChatTheme;
  25. } // namespace Ui
  26. namespace Webview {
  27. struct ThemeParams;
  28. } // namespace Webview
  29. namespace Window {
  30. namespace Theme {
  31. inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
  32. inline constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024;
  33. struct ParsedTheme;
  34. [[nodiscard]] bool IsEmbeddedTheme(const QString &path);
  35. struct Object {
  36. QString pathRelative;
  37. QString pathAbsolute;
  38. QByteArray content;
  39. Data::CloudTheme cloud;
  40. };
  41. struct Cached {
  42. QByteArray colors;
  43. QByteArray background;
  44. bool tiled = false;
  45. int32 paletteChecksum = 0;
  46. int32 contentChecksum = 0;
  47. };
  48. struct Saved {
  49. Object object;
  50. Cached cache;
  51. };
  52. bool Initialize(Saved &&saved);
  53. void Uninitialize();
  54. struct Instance {
  55. style::palette palette;
  56. QImage background;
  57. Cached cached;
  58. bool tiled = false;
  59. };
  60. struct Preview {
  61. Object object;
  62. Instance instance;
  63. QImage preview;
  64. };
  65. bool Apply(
  66. const QString &filepath,
  67. const Data::CloudTheme &cloud = Data::CloudTheme());
  68. bool Apply(std::unique_ptr<Preview> preview);
  69. void ApplyDefaultWithPath(const QString &themePath);
  70. bool ApplyEditedPalette(const QByteArray &content);
  71. void KeepApplied();
  72. void KeepFromEditor(
  73. const QByteArray &originalContent,
  74. const ParsedTheme &originalParsed,
  75. const Data::CloudTheme &cloud,
  76. const QByteArray &themeContent,
  77. const ParsedTheme &themeParsed,
  78. const QImage &background);
  79. QString NightThemePath();
  80. [[nodiscard]] bool IsNightMode();
  81. void SetNightModeValue(bool nightMode);
  82. [[nodiscard]] rpl::producer<bool> IsNightModeValue();
  83. void ToggleNightMode();
  84. void ToggleNightMode(const QString &themePath);
  85. void ToggleNightModeWithConfirmation(
  86. not_null<Controller*> window,
  87. Fn<void()> toggle);
  88. void ResetToSomeDefault();
  89. [[nodiscard]] bool IsNonDefaultBackground();
  90. void Revert();
  91. [[nodiscard]] rpl::producer<bool> IsThemeDarkValue();
  92. [[nodiscard]] QString EditingPalettePath();
  93. // NB! This method looks to Core::App().settings() to get colorizer by 'file'.
  94. bool LoadFromFile(
  95. const QString &path,
  96. not_null<Instance*> out,
  97. Cached *outCache,
  98. QByteArray *outContent);
  99. bool LoadFromFile(
  100. const QString &path,
  101. not_null<Instance*> out,
  102. Cached *outCache,
  103. QByteArray *outContent,
  104. const style::colorizer &colorizer);
  105. bool LoadFromContent(
  106. const QByteArray &content,
  107. not_null<Instance*> out,
  108. Cached *outCache);
  109. struct BackgroundUpdate {
  110. enum class Type {
  111. New,
  112. Changed,
  113. Start,
  114. TestingTheme,
  115. RevertingTheme,
  116. ApplyingTheme,
  117. ApplyingEdit,
  118. };
  119. BackgroundUpdate(Type type, bool tiled) : type(type), tiled(tiled) {
  120. }
  121. [[nodiscard]] bool paletteChanged() const {
  122. return (type == Type::TestingTheme)
  123. || (type == Type::RevertingTheme)
  124. || (type == Type::ApplyingEdit)
  125. || (type == Type::New);
  126. }
  127. Type type;
  128. bool tiled;
  129. };
  130. enum class ClearEditing {
  131. Temporary,
  132. RevertChanges,
  133. KeepChanges,
  134. };
  135. class ChatBackground final {
  136. public:
  137. ChatBackground();
  138. ~ChatBackground();
  139. [[nodiscard]] rpl::producer<BackgroundUpdate> updates() const {
  140. return _updates.events();
  141. }
  142. void start();
  143. // This method is allowed to (and should) be called before start().
  144. void setThemeData(QImage &&themeImage, bool themeTile);
  145. // This method is setting the default (themed) image if none was set yet.
  146. void set(const Data::WallPaper &paper, QImage image = QImage());
  147. void setTile(bool tile);
  148. void setTileDayValue(bool tile);
  149. void setTileNightValue(bool tile);
  150. void setThemeObject(const Object &object);
  151. [[nodiscard]] const Object &themeObject() const;
  152. [[nodiscard]] std::optional<Data::CloudTheme> editingTheme() const;
  153. void setEditingTheme(const Data::CloudTheme &editing);
  154. void clearEditingTheme(ClearEditing clear = ClearEditing::Temporary);
  155. void reset();
  156. void setTestingTheme(Instance &&theme);
  157. void saveAdjustableColors();
  158. void setTestingDefaultTheme();
  159. void revert();
  160. void appliedEditedPalette();
  161. void downloadingStarted(bool tile);
  162. [[nodiscard]] const Data::WallPaper &paper() const {
  163. return _paper;
  164. }
  165. [[nodiscard]] WallPaperId id() const {
  166. return _paper.id();
  167. }
  168. [[nodiscard]] const QImage &prepared() const {
  169. return _prepared;
  170. }
  171. [[nodiscard]] const QImage &preparedForTiled() const {
  172. return _preparedForTiled;
  173. }
  174. [[nodiscard]] std::optional<QColor> colorForFill() const;
  175. [[nodiscard]] QImage gradientForFill() const;
  176. void recacheGradientForFill(QImage gradient);
  177. [[nodiscard]] QImage createCurrentImage() const;
  178. [[nodiscard]] bool tile() const;
  179. [[nodiscard]] bool tileDay() const;
  180. [[nodiscard]] bool tileNight() const;
  181. [[nodiscard]] std::optional<QColor> imageMonoColor() const;
  182. [[nodiscard]] bool nightModeChangeAllowed() const;
  183. private:
  184. struct AdjustableColor {
  185. AdjustableColor(style::color data);
  186. style::color item;
  187. QColor original;
  188. };
  189. [[nodiscard]] bool started() const;
  190. void initialRead();
  191. void saveForRevert();
  192. void setPreparedAfterPaper(QImage image);
  193. void setPrepared(QImage original, QImage prepared, QImage gradient);
  194. void prepareImageForTiled();
  195. void writeNewBackgroundSettings();
  196. void setPaper(const Data::WallPaper &paper);
  197. [[nodiscard]] bool adjustPaletteRequired();
  198. void adjustPaletteUsingBackground(const QImage &image);
  199. void adjustPaletteUsingColors(const std::vector<QColor> &colors);
  200. void adjustPaletteUsingColor(QColor color);
  201. void restoreAdjustableColors();
  202. void setNightModeValue(bool nightMode);
  203. [[nodiscard]] bool nightMode() const;
  204. void toggleNightMode(std::optional<QString> themePath);
  205. void reapplyWithNightMode(
  206. std::optional<QString> themePath,
  207. bool newNightMode);
  208. void keepApplied(const Object &object, bool write);
  209. [[nodiscard]] bool isNonDefaultThemeOrBackground();
  210. [[nodiscard]] bool isNonDefaultBackground();
  211. void checkUploadWallPaper();
  212. [[nodiscard]] QImage postprocessBackgroundImage(QImage image);
  213. void refreshThemeWatcher();
  214. friend bool IsNightMode();
  215. friend void SetNightModeValue(bool nightMode);
  216. friend void ToggleNightMode();
  217. friend void ToggleNightMode(const QString &themePath);
  218. friend void ResetToSomeDefault();
  219. friend void KeepApplied();
  220. friend void KeepFromEditor(
  221. const QByteArray &originalContent,
  222. const ParsedTheme &originalParsed,
  223. const Data::CloudTheme &cloud,
  224. const QByteArray &themeContent,
  225. const ParsedTheme &themeParsed,
  226. const QImage &background);
  227. friend bool IsNonDefaultBackground();
  228. Main::Session *_session = nullptr;
  229. rpl::event_stream<BackgroundUpdate> _updates;
  230. Data::WallPaper _paper = Data::details::UninitializedWallPaper();
  231. std::optional<QColor> _paperColor;
  232. QImage _gradient;
  233. QImage _original;
  234. QImage _prepared;
  235. QImage _preparedForTiled;
  236. bool _nightMode = false;
  237. bool _tileDayValue = false;
  238. bool _tileNightValue = true;
  239. std::optional<bool> _localStoredTileDayValue;
  240. std::optional<bool> _localStoredTileNightValue;
  241. std::optional<QColor> _imageMonoColor;
  242. Object _themeObject;
  243. QImage _themeImage;
  244. bool _themeTile = false;
  245. std::optional<Data::CloudTheme> _editingTheme;
  246. std::unique_ptr<QFileSystemWatcher> _themeWatcher;
  247. Data::WallPaper _paperForRevert
  248. = Data::details::UninitializedWallPaper();
  249. QImage _originalForRevert;
  250. bool _tileForRevert = false;
  251. std::vector<AdjustableColor> _adjustableColors;
  252. FullMsgId _wallPaperUploadId;
  253. mtpRequestId _wallPaperRequestId = 0;
  254. rpl::lifetime _wallPaperUploadLifetime;
  255. rpl::lifetime _lifetime;
  256. };
  257. [[nodiscard]] std::shared_ptr<FilePrepareResult> PrepareWallPaper(
  258. MTP::DcId dcId,
  259. const QImage &image);
  260. [[nodiscard]] ChatBackground *Background();
  261. bool ReadPaletteValues(
  262. const QByteArray &content,
  263. Fn<bool(QLatin1String name, QLatin1String value)> callback);
  264. [[nodiscard]] Webview::ThemeParams WebViewParams();
  265. [[nodiscard]] std::unique_ptr<Ui::ChatTheme> DefaultChatThemeOn(
  266. rpl::lifetime &lifetime);
  267. } // namespace Theme
  268. } // namespace Window