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