diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 5eab26160..936f3002b 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1100,8 +1100,6 @@ PRIVATE window/window_slide_animation.cpp window/window_slide_animation.h window/window_top_bar_wrap.h - window/themes/window_chat_theme.cpp - window/themes/window_chat_theme.h window/themes/window_theme.cpp window/themes/window_theme.h window/themes/window_theme_editor.cpp diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index 4c4ff770f..e56ff46ab 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "mainwidget.h" #include "window/themes/window_theme.h" +#include "ui/chat/chat_theme.h" #include "ui/toast/toast.h" #include "ui/image/image.h" #include "ui/widgets/checkbox.h" diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 6940ca7a5..fa7ae0eaa 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "main/main_session.h" #include "main/main_session_settings.h" +#include "ui/chat/chat_theme.h" #include "ui/widgets/popup_menu.h" #include "ui/image/image.h" #include "ui/text/text_utilities.h" diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index a7461a572..354ddf333 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_service_message.h" #include "history/view/history_view_cursor_state.h" #include "history/view/history_view_context_menu.h" +#include "ui/chat/chat_theme.h" #include "ui/widgets/popup_menu.h" #include "ui/image/image.h" #include "ui/toast/toast.h" diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 32aedd932..c0bb6717f 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -105,6 +105,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/boxes/report_box.h" #include "ui/chat/pinned_bar.h" #include "ui/chat/group_call_bar.h" +#include "ui/chat/chat_theme.h" #include "ui/widgets/popup_menu.h" #include "ui/item_text_options.h" #include "ui/unread_badge.h" @@ -116,7 +117,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "window/window_slide_animation.h" #include "window/window_peer_menu.h" -#include "window/themes/window_chat_theme.h" #include "inline_bots/inline_results_widget.h" #include "info/profile/info_profile_values.h" // SharedMediaCountValue. #include "chat_helpers/emoji_suggestions_widget.h" diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 6e848bd84..ddd6086ba 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -25,6 +25,7 @@ class SessionController; namespace Ui { class PathShiftGradient; struct BubblePattern; +struct ChatPaintContext; } // namespace Ui namespace HistoryView { @@ -192,30 +193,7 @@ struct DateBadge : public RuntimeComponent { }; -struct PaintContext { - not_null st; - const Ui::BubblePattern *bubblesPattern = nullptr; - QRect viewport; - QRect clip; - TextSelection selection; - crl::time now = 0; - - void translate(int x, int y) { - viewport.translate(x, y); - clip.translate(x, y); - } - void translate(QPoint point) { - translate(point.x(), point.y()); - } - [[nodiscard]] PaintContext translated(int x, int y) const { - auto result = *this; - result.translate(x, y); - return result; - } - [[nodiscard]] PaintContext translated(QPoint point) const { - return translated(point.x(), point.y()); - } -}; +using PaintContext = Ui::ChatPaintContext; class Element : public Object diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index c3f7b487a..913f1a42c 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -27,13 +27,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_adaptive.h" #include "window/window_session_controller.h" #include "window/window_peer_menu.h" -#include "window/themes/window_chat_theme.h" #include "main/main_session.h" #include "boxes/confirm_box.h" #include "ui/widgets/popup_menu.h" #include "ui/toast/toast.h" #include "ui/inactive_press.h" #include "ui/effects/path_shift_gradient.h" +#include "ui/chat/chat_theme.h" #include "lang/lang_keys.h" #include "boxes/peers/edit_participant_box.h" #include "data/data_session.h" diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 42651ae65..e48226673 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/media/history_view_web_page.h" #include "history/view/history_view_group_call_tracker.h" // UserpicInRow. #include "history/history.h" +#include "ui/chat/chat_theme.h" #include "ui/effects/ripple_animation.h" #include "base/unixtime.h" #include "ui/chat/message_bubble.h" diff --git a/Telegram/SourceFiles/history/view/history_view_service_message.cpp b/Telegram/SourceFiles/history/view/history_view_service_message.cpp index 351a7a1e4..332f4e830 100644 --- a/Telegram/SourceFiles/history/view/history_view_service_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_service_message.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_abstract_structure.h" #include "data/data_chat.h" #include "data/data_channel.h" +#include "ui/chat/chat_theme.h" #include "ui/text/text_options.h" #include "ui/ui_utility.h" #include "mainwidget.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_call.cpp b/Telegram/SourceFiles/history/view/media/history_view_call.cpp index aefa5bcd7..569349cc5 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_call.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_call.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/media/history_view_call.h" #include "lang/lang_keys.h" +#include "ui/chat/chat_theme.h" #include "ui/text/format_values.h" #include "layout/layout_selection.h" // FullSelection #include "history/history.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_contact.cpp b/Telegram/SourceFiles/history/view/media/history_view_contact.cpp index 03b941224..6b786ee3d 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_contact.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_contact.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_cursor_state.h" #include "window/window_session_controller.h" #include "ui/empty_userpic.h" +#include "ui/chat/chat_theme.h" #include "ui/text/format_values.h" // Ui::FormatPhone #include "ui/text/text_options.h" #include "data/data_session.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index bf133b6ee..bdcda1d03 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/format_values.h" #include "ui/text/format_song_document_name.h" #include "ui/chat/message_bubble.h" +#include "ui/chat/chat_theme.h" #include "ui/cached_round_corners.h" #include "ui/ui_utility.h" #include "layout/layout_selection.h" // FullSelection diff --git a/Telegram/SourceFiles/history/view/media/history_view_game.cpp b/Telegram/SourceFiles/history/view/media/history_view_game.cpp index 4702b0dd3..d524a565a 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_game.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_game.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/media/history_view_media_common.h" #include "ui/item_text_options.h" #include "ui/cached_round_corners.h" +#include "ui/chat/chat_theme.h" #include "core/ui_integration.h" #include "data/data_session.h" #include "data/data_game.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 6f45f3602..13788c539 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/media/history_view_media_common.h" #include "window/window_session_controller.h" #include "core/application.h" // Application::showDocument. +#include "ui/chat/chat_theme.h" #include "ui/image/image.h" #include "ui/text/format_values.h" #include "ui/grouped_layout.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_invoice.cpp b/Telegram/SourceFiles/history/view/media/history_view_invoice.cpp index 991c66409..41ebcef1f 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_invoice.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_invoice.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/media/history_view_photo.h" #include "history/view/media/history_view_media_common.h" #include "ui/item_text_options.h" +#include "ui/chat/chat_theme.h" #include "ui/text/format_values.h" #include "ui/cached_round_corners.h" #include "data/data_media_types.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_location.cpp b/Telegram/SourceFiles/history/view/media/history_view_location.cpp index fdf15b6e6..2637e8da6 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_location.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_location.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_location_manager.h" #include "history/view/history_view_element.h" #include "history/view/history_view_cursor_state.h" +#include "ui/chat/chat_theme.h" #include "ui/image/image.h" #include "ui/text/text_options.h" #include "ui/cached_round_corners.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.cpp b/Telegram/SourceFiles/history/view/media/history_view_media.cpp index 5b27a2689..728e05d44 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "layout/layout_selection.h" #include "data/data_document.h" #include "ui/item_text_options.h" +#include "ui/chat/chat_theme.h" #include "ui/chat/message_bubble.h" #include "core/ui_integration.h" #include "styles/style_chat.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.h b/Telegram/SourceFiles/history/view/media/history_view_media.h index 74454e752..9d5d1738e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media.h @@ -31,6 +31,7 @@ struct ColorReplacements; namespace Ui { struct BubbleSelectionInterval; +struct ChatPaintContext; } // namespace Ui namespace HistoryView { @@ -40,9 +41,10 @@ enum class CursorState : char; enum class InfoDisplayType : char; struct TextState; struct StateRequest; -struct PaintContext; class Element; +using PaintContext = Ui::ChatPaintContext; + enum class MediaInBubbleState { None, Top, diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp index 6f10b5448..3b86bfbea 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_shared_media.h" #include "lang/lang_keys.h" #include "ui/grouped_layout.h" +#include "ui/chat/chat_theme.h" #include "ui/chat/message_bubble.h" #include "ui/text/text_options.h" #include "layout/layout_selection.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp index f252d793d..a16f451e7 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_components.h" #include "lottie/lottie_single_player.h" #include "ui/cached_round_corners.h" +#include "ui/chat/chat_theme.h" #include "layout/layout_selection.h" #include "styles/style_chat.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index 9862fa125..5640ec232 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "main/main_session_settings.h" #include "ui/image/image.h" +#include "ui/chat/chat_theme.h" #include "ui/grouped_layout.h" #include "ui/cached_round_corners.h" #include "data/data_session.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp index d9ad0d85f..77ad5a6c9 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_cursor_state.h" #include "calls/calls_instance.h" #include "ui/chat/message_bubble.h" +#include "ui/chat/chat_theme.h" #include "ui/text/text_options.h" #include "ui/text/text_utilities.h" #include "ui/text/format_values.h" diff --git a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp index 67ae487bd..5cb50e5a9 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/qthelp_url.h" #include "core/local_url_handlers.h" #include "ui/text/format_values.h" +#include "ui/chat/chat_theme.h" #include "ui/cached_round_corners.h" #include "ui/ui_utility.h" #include "layout/layout_selection.h" // FullSelection diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index e96eb1264..44b5c9c90 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "ui/text/text_options.h" #include "ui/text/format_values.h" +#include "ui/chat/chat_theme.h" #include "ui/cached_round_corners.h" #include "layout/layout_selection.h" // FullSelection #include "data/data_session.h" diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index 881c48289..cc58ce4d3 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "calls/calls_instance.h" #include "base/unixtime.h" +#include "ui/chat/chat_theme.h" #include "ui/widgets/checkbox.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/vertical_layout.h" diff --git a/Telegram/SourceFiles/support/support_autocomplete.cpp b/Telegram/SourceFiles/support/support_autocomplete.cpp index 46b157146..f8a5a8bad 100644 --- a/Telegram/SourceFiles/support/support_autocomplete.cpp +++ b/Telegram/SourceFiles/support/support_autocomplete.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "support/support_autocomplete.h" +#include "ui/chat/chat_theme.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/buttons.h" diff --git a/Telegram/SourceFiles/window/themes/window_chat_theme.cpp b/Telegram/SourceFiles/ui/chat/chat_theme.cpp similarity index 64% rename from Telegram/SourceFiles/window/themes/window_chat_theme.cpp rename to Telegram/SourceFiles/ui/chat/chat_theme.cpp index 92ac29ef4..170fd817f 100644 --- a/Telegram/SourceFiles/window/themes/window_chat_theme.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_theme.cpp @@ -5,17 +5,16 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "window/themes/window_chat_theme.h" +#include "ui/chat/chat_theme.h" -#include "window/themes/window_theme.h" #include "ui/image/image_prepare.h" #include "ui/ui_utility.h" #include "ui/chat/message_bubble.h" -#include "history/view/history_view_element.h" +#include #include -namespace Window::Theme { +namespace Ui { namespace { constexpr auto kMaxChatEntryHistorySize = 50; @@ -25,49 +24,52 @@ constexpr auto kBackgroundFadeDuration = crl::time(200); [[nodiscard]] CacheBackgroundResult CacheBackground( const CacheBackgroundRequest &request) { - const auto gradient = request.gradient.isNull() + const auto gradient = request.background.gradientForFill.isNull() ? QImage() - : request.recreateGradient + : (request.gradientRotationAdd != 0) ? Images::GenerateGradient( - request.gradient.size(), - request.gradientColors, - request.gradientRotation) - : request.gradient; - if (request.isPattern || request.tile || request.prepared.isNull()) { + request.background.gradientForFill.size(), + request.background.colors, + (request.background.gradientRotation + + request.gradientRotationAdd) % 360) + : request.background.gradientForFill; + if (request.background.isPattern + || request.background.tile + || request.background.prepared.isNull()) { auto result = gradient.isNull() ? QImage( - request.area * cIntRetinaFactor(), + request.area * style::DevicePixelRatio(), QImage::Format_ARGB32_Premultiplied) : gradient.scaled( - request.area * cIntRetinaFactor(), + request.area * style::DevicePixelRatio(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - result.setDevicePixelRatio(cRetinaFactor()); - if (!request.prepared.isNull()) { + result.setDevicePixelRatio(style::DevicePixelRatio()); + if (!request.background.prepared.isNull()) { QPainter p(&result); if (!gradient.isNull()) { - if (request.patternOpacity >= 0.) { + if (request.background.patternOpacity >= 0.) { p.setCompositionMode(QPainter::CompositionMode_SoftLight); - p.setOpacity(request.patternOpacity); + p.setOpacity(request.background.patternOpacity); } else { p.setCompositionMode( QPainter::CompositionMode_DestinationIn); } } - const auto tiled = request.isPattern - ? request.prepared.scaled( - request.area.height() * cIntRetinaFactor(), - request.area.height() * cIntRetinaFactor(), + const auto tiled = request.background.isPattern + ? request.background.prepared.scaled( + request.area.height() * style::DevicePixelRatio(), + request.area.height() * style::DevicePixelRatio(), Qt::KeepAspectRatio, Qt::SmoothTransformation) - : request.preparedForTiled; - const auto w = tiled.width() / cRetinaFactor(); - const auto h = tiled.height() / cRetinaFactor(); - const auto cx = qCeil(request.area.width() / w); - const auto cy = qCeil(request.area.height() / h); + : request.background.preparedForTiled; + const auto w = tiled.width() / style::DevicePixelRatio(); + const auto h = tiled.height() / style::DevicePixelRatio(); + const auto cx = int(std::ceil(request.area.width() / w)); + const auto cy = int(std::ceil(request.area.height() / h)); const auto rows = cy; - const auto cols = request.isPattern ? (((cx / 2) * 2) + 1) : cx; - const auto xshift = request.isPattern + const auto cols = request.background.isPattern ? (((cx / 2) * 2) + 1) : cx; + const auto xshift = request.background.isPattern ? (request.area.width() - cols * w) / 2 : 0; for (auto y = 0; y != rows; ++y) { @@ -76,10 +78,10 @@ constexpr auto kBackgroundFadeDuration = crl::time(200); } } if (!gradient.isNull() - && request.patternOpacity < 0. - && request.patternOpacity > -1.) { + && request.background.patternOpacity < 0. + && request.background.patternOpacity > -1.) { p.setCompositionMode(QPainter::CompositionMode_SourceOver); - p.setOpacity(1. + request.patternOpacity); + p.setOpacity(1. + request.background.patternOpacity); p.fillRect(QRect(QPoint(), request.area), Qt::black); } } @@ -90,15 +92,15 @@ constexpr auto kBackgroundFadeDuration = crl::time(200); .area = request.area, }; } else { - const auto rects = ComputeBackgroundRects( + const auto rects = ComputeChatBackgroundRects( request.area, - request.prepared.size()); - auto result = request.prepared.copy(rects.from).scaled( - rects.to.width() * cIntRetinaFactor(), - rects.to.height() * cIntRetinaFactor(), + request.background.prepared.size()); + auto result = request.background.prepared.copy(rects.from).scaled( + rects.to.width() * style::DevicePixelRatio(), + rects.to.height() * style::DevicePixelRatio(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - result.setDevicePixelRatio(cRetinaFactor()); + result.setDevicePixelRatio(style::DevicePixelRatio()); return { .image = std::move(result).convertToFormat( QImage::Format_ARGB32_Premultiplied), @@ -112,17 +114,24 @@ constexpr auto kBackgroundFadeDuration = crl::time(200); } // namespace +bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b) { + return (a.prepared.cacheKey() == b.prepared.cacheKey()) + && (a.gradientForFill.cacheKey() == b.gradientForFill.cacheKey()) + && (a.tile == b.tile) + && (a.patternOpacity == b.patternOpacity); +} + +bool operator!=(const ChatThemeBackground &a, const ChatThemeBackground &b) { + return !(a == b); +} + bool operator==( const CacheBackgroundRequest &a, const CacheBackgroundRequest &b) { - return (a.prepared.cacheKey() == b.prepared.cacheKey()) + return (a.background == b.background) && (a.area == b.area) - && (a.gradientRotation == b.gradientRotation) - && (a.tile == b.tile) - && (a.recreateGradient == b.recreateGradient) - && (a.gradient.cacheKey() == b.gradient.cacheKey()) - && (a.gradientProgress == b.gradientProgress) - && (a.patternOpacity == b.patternOpacity); + && (a.gradientRotationAdd == b.gradientRotationAdd) + && (a.gradientProgress == b.gradientProgress); } bool operator!=( @@ -139,19 +148,25 @@ CachedBackground::CachedBackground(CacheBackgroundResult &&result) } ChatTheme::ChatTheme() { - Background()->updates( - ) | rpl::start_with_next([=](const BackgroundUpdate &update) { - if (update.type == BackgroundUpdate::Type::New - || update.type == BackgroundUpdate::Type::Changed) { - clearCachedBackground(); - } - }, _lifetime); } // Runs from background thread. -ChatTheme::ChatTheme(const Data::CloudTheme &theme) -: _id(theme.id) +ChatTheme::ChatTheme(ChatThemeDescriptor &&descriptor) +: _id(descriptor.id) , _palette(std::make_unique()) { + descriptor.preparePalette(*_palette); + setBackground(descriptor.prepareBackground()); +} + +void ChatTheme::setBackground(ChatThemeBackground &&background) { + _mutableBackground = std::move(background); + _backgroundState = {}; + _backgroundNext = {}; + _backgroundFade.stop(); + if (_cacheBackgroundTimer) { + _cacheBackgroundTimer->cancel(); + } + _repaintBackgroundRequests.fire({}); } uint64 ChatTheme::key() const { @@ -162,7 +177,9 @@ void ChatTheme::setBubblesBackground(QImage image) { _bubblesBackgroundPrepared = std::move(image); if (!_bubblesBackground.area.isEmpty()) { _bubblesBackground = CacheBackground({ - .prepared = _bubblesBackgroundPrepared, + .background = { + .prepared = _bubblesBackgroundPrepared, + }, .area = _bubblesBackground.area, }); } @@ -173,7 +190,7 @@ void ChatTheme::setBubblesBackground(QImage image) { _repaintBackgroundRequests.fire({}); } -HistoryView::PaintContext ChatTheme::preparePaintContext( +ChatPaintContext ChatTheme::preparePaintContext( QRect viewport, QRect clip) { _bubblesBackground.area = viewport.size(); @@ -202,7 +219,7 @@ const BackgroundState &ChatTheme::backgroundState(QSize area) { } _backgroundState.shown = _backgroundFade.value(1.); if (_backgroundState.now.pixmap.isNull() - && !Background()->gradientForFill().isNull()) { + && !background().gradientForFill.isNull()) { // We don't support direct painting of patterned gradients. // So we need to sync-generate cache image here. setCachedBackground(CacheBackground(currentCacheRequest(area))); @@ -235,8 +252,7 @@ void ChatTheme::generateNextBackgroundRotation() { || !readyForBackgroundRotation()) { return; } - const auto background = Background(); - if (background->paper().backgroundColors().size() < 3) { + if (background().colors.size() < 3) { return; } constexpr auto kAddRotation = 315; @@ -255,8 +271,8 @@ void ChatTheme::generateNextBackgroundRotation() { _backgroundState.now.area, kAddRotation); if (forRequest == request) { - _backgroundAddRotation - = (_backgroundAddRotation + kAddRotation) % 360; + _mutableBackground.gradientRotation + = (_mutableBackground.gradientRotation + kAddRotation) % 360; _backgroundNext = std::move(result); } }); @@ -264,28 +280,14 @@ void ChatTheme::generateNextBackgroundRotation() { auto ChatTheme::currentCacheRequest(QSize area, int addRotation) const -> CacheBackgroundRequest { - const auto background = Background(); - if (background->colorForFill()) { + if (background().colorForFill) { return {}; } - const auto rotation = background->paper().gradientRotation(); - const auto gradient = background->gradientForFill(); return { - .prepared = background->prepared(), - .preparedForTiled = background->preparedForTiled(), + .background = background(), .area = area, - .gradientRotation = (rotation - + _backgroundAddRotation - + addRotation) % 360, - .tile = background->tile(), - .isPattern = background->paper().isPattern(), - .recreateGradient = (addRotation != 0), - .gradient = gradient, - .gradientColors = (gradient.isNull() - ? std::vector() - : background->paper().backgroundColors()), - .gradientProgress = 1., - .patternOpacity = background->paper().patternOpacity(), + .gradientRotationAdd = addRotation, +// .recreateGradient = (addRotation != 0), }; } @@ -337,8 +339,7 @@ void ChatTheme::cacheBackgroundAsync( void ChatTheme::setCachedBackground(CacheBackgroundResult &&cached) { _backgroundNext = {}; - const auto background = Background(); - if (background->gradientForFill().isNull() + if (background().gradientForFill.isNull() || _backgroundState.now.pixmap.isNull() || anim::Disabled()) { _backgroundFade.stop(); @@ -364,27 +365,66 @@ void ChatTheme::setCachedBackground(CacheBackgroundResult &&cached) { kBackgroundFadeDuration); } -void ChatTheme::clearCachedBackground() { - _backgroundState = {}; - _backgroundAddRotation = 0; - _backgroundNext = {}; - _backgroundFade.stop(); - if (_cacheBackgroundTimer) { - _cacheBackgroundTimer->cancel(); - } - _repaintBackgroundRequests.fire({}); -} - rpl::producer<> ChatTheme::repaintBackgroundRequests() const { return _repaintBackgroundRequests.events(); } void ChatTheme::rotateComplexGradientBackground() { if (!_backgroundFade.animating() && !_backgroundNext.image.isNull()) { - Background()->recacheGradientForFill( - std::move(_backgroundNext.gradient)); + if (_mutableBackground.gradientForFill.size() + == _backgroundNext.gradient.size()) { + _mutableBackground.gradientForFill + = std::move(_backgroundNext.gradient); + } setCachedBackground(base::take(_backgroundNext)); } } +ChatBackgroundRects ComputeChatBackgroundRects( + QSize fillSize, + QSize imageSize) { + if (uint64(imageSize.width()) * fillSize.height() + > uint64(imageSize.height()) * fillSize.width()) { + const auto pxsize = fillSize.height() / float64(imageSize.height()); + auto takewidth = int(std::ceil(fillSize.width() / pxsize)); + if (takewidth > imageSize.width()) { + takewidth = imageSize.width(); + } else if ((imageSize.width() % 2) != (takewidth % 2)) { + ++takewidth; + } + return { + .from = QRect( + (imageSize.width() - takewidth) / 2, + 0, + takewidth, + imageSize.height()), + .to = QRect( + int((fillSize.width() - takewidth * pxsize) / 2.), + 0, + int(std::ceil(takewidth * pxsize)), + fillSize.height()), + }; + } else { + const auto pxsize = fillSize.width() / float64(imageSize.width()); + auto takeheight = int(std::ceil(fillSize.height() / pxsize)); + if (takeheight > imageSize.height()) { + takeheight = imageSize.height(); + } else if ((imageSize.height() % 2) != (takeheight % 2)) { + ++takeheight; + } + return { + .from = QRect( + 0, + (imageSize.height() - takeheight) / 2, + imageSize.width(), + takeheight), + .to = QRect( + 0, + int((fillSize.height() - takeheight * pxsize) / 2.), + fillSize.width(), + int(std::ceil(takeheight * pxsize))), + }; + } +} + } // namespace Window::Theme diff --git a/Telegram/SourceFiles/window/themes/window_chat_theme.h b/Telegram/SourceFiles/ui/chat/chat_theme.h similarity index 64% rename from Telegram/SourceFiles/window/themes/window_chat_theme.h rename to Telegram/SourceFiles/ui/chat/chat_theme.h index b427d6626..22c0e88ff 100644 --- a/Telegram/SourceFiles/window/themes/window_chat_theme.h +++ b/Telegram/SourceFiles/ui/chat/chat_theme.h @@ -11,35 +11,59 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" #include "base/weak_ptr.h" -namespace Data { -struct CloudTheme; -} // namespace Data - -namespace HistoryView { -struct PaintContext; -} // namespace HistoryView - namespace Ui { + struct BubblePattern; -} // namespace Ui -namespace Window::Theme { +struct ChatPaintContext { + not_null st; + const BubblePattern *bubblesPattern = nullptr; + QRect viewport; + QRect clip; + TextSelection selection; + crl::time now = 0; -struct CacheBackgroundRequest { + void translate(int x, int y) { + viewport.translate(x, y); + clip.translate(x, y); + } + void translate(QPoint point) { + translate(point.x(), point.y()); + } + [[nodiscard]] ChatPaintContext translated(int x, int y) const { + auto result = *this; + result.translate(x, y); + return result; + } + [[nodiscard]] ChatPaintContext translated(QPoint point) const { + return translated(point.x(), point.y()); + } +}; + +struct ChatThemeBackground { QImage prepared; QImage preparedForTiled; - QSize area; - int gradientRotation = 0; - bool tile = false; - bool isPattern = false; - bool recreateGradient = false; - QImage gradient; - std::vector gradientColors; - float64 gradientProgress = 1.; + QImage gradientForFill; + std::optional colorForFill; + std::vector colors; float64 patternOpacity = 1.; + int gradientRotation = 0; + bool isPattern = false; + bool tile = false; +}; + +bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b); +bool operator!=(const ChatThemeBackground &a, const ChatThemeBackground &b); + +struct CacheBackgroundRequest { + ChatThemeBackground background; + QSize area; + int gradientRotationAdd = 0; + float64 gradientProgress = 1.; explicit operator bool() const { - return !prepared.isNull() || !gradient.isNull(); + return !background.prepared.isNull() + || !background.gradientForFill.isNull(); } }; @@ -74,38 +98,35 @@ struct BackgroundState { float64 shown = 1.; }; -struct ChatThemeBackground { - QImage prepared; - QImage gradientForFill; - std::optional colorForFill; -}; - struct ChatThemeDescriptor { + uint64 id = 0; Fn preparePalette; Fn prepareBackground; - std::vector backgroundColors; }; class ChatTheme final : public base::has_weak_ptr { public: ChatTheme(); - // Runs from background thread. - ChatTheme(const Data::CloudTheme &theme); + // Expected to be invoked on a background thread. Invokes callbacks there. + ChatTheme(ChatThemeDescriptor &&descriptor); [[nodiscard]] uint64 key() const; [[nodiscard]] not_null palette() const { return _palette.get(); } - void setBackground(ChatThemeBackground); + void setBackground(ChatThemeBackground &&background); + const ChatThemeBackground &background() const { + return _mutableBackground; + } void setBubblesBackground(QImage image); - const Ui::BubblePattern *bubblesBackgroundPattern() const { + const BubblePattern *bubblesBackgroundPattern() const { return _bubblesBackgroundPattern.get(); } - [[nodiscard]] HistoryView::PaintContext preparePaintContext( + [[nodiscard]] ChatPaintContext preparePaintContext( QRect viewport, QRect clip); [[nodiscard]] const BackgroundState &backgroundState(QSize area); @@ -118,7 +139,6 @@ private: void cacheBackgroundAsync( const CacheBackgroundRequest &request, Fn done = nullptr); - void clearCachedBackground(); void setCachedBackground(CacheBackgroundResult &&cached); [[nodiscard]] CacheBackgroundRequest currentCacheRequest( QSize area, @@ -128,8 +148,9 @@ private: uint64 _id = 0; std::unique_ptr _palette; + ChatThemeBackground _mutableBackground; BackgroundState _backgroundState; - Ui::Animations::Simple _backgroundFade; + Animations::Simple _backgroundFade; CacheBackgroundRequest _backgroundCachingRequest; CacheBackgroundResult _backgroundNext; int _backgroundAddRotation = 0; @@ -138,7 +159,7 @@ private: std::optional _cacheBackgroundTimer; CachedBackground _bubblesBackground; QImage _bubblesBackgroundPrepared; - std::unique_ptr _bubblesBackgroundPattern; + std::unique_ptr _bubblesBackgroundPattern; rpl::event_stream<> _repaintBackgroundRequests; @@ -146,4 +167,12 @@ private: }; -} // namespace Window::Theme +struct ChatBackgroundRects { + QRect from; + QRect to; +}; +[[nodiscard]] ChatBackgroundRects ComputeChatBackgroundRects( + QSize fillSize, + QSize imageSize); + +} // namespace Ui diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index 0c26c857d..9046a0bcf 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwidget.h" #include "ui/ui_utility.h" +#include "ui/chat/chat_theme.h" #include "data/data_peer.h" #include "data/data_changes.h" #include "data/data_session.h" @@ -18,7 +19,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_slide_animation.h" #include "window/window_session_controller.h" #include "window/themes/window_theme.h" -#include "window/themes/window_chat_theme.h" #include @@ -64,11 +64,11 @@ namespace { [[nodiscard]] auto ChatThemeValueFromPeer( not_null controller, not_null peer) --> rpl::producer> { +-> rpl::producer> { return MaybeCloudThemeValueFromPeer( peer ) | rpl::map([=](std::optional theme) - -> rpl::producer> { + -> rpl::producer> { if (!theme) { return rpl::single(controller->defaultChatTheme()); } @@ -94,7 +94,7 @@ AbstractSectionWidget::AbstractSectionWidget( return ChatThemeValueFromPeer( controller, peer - ) | rpl::map([](const std::shared_ptr &theme) { + ) | rpl::map([](const std::shared_ptr &theme) { return rpl::single( rpl::empty_value() ) | rpl::then( @@ -185,21 +185,21 @@ QPixmap SectionWidget::grabForShowAnimation( void SectionWidget::PaintBackground( not_null controller, - not_null theme, + not_null theme, not_null widget, QRect clip) { Painter p(widget); - const auto background = Window::Theme::Background(); - if (const auto color = background->colorForFill()) { - p.fillRect(clip, *color); + const auto &background = theme->background(); + if (background.colorForFill) { + p.fillRect(clip, *background.colorForFill); return; } - const auto gradient = background->gradientForFill(); + const auto &gradient = background.gradientForFill; const auto fill = QSize(widget->width(), controller->content()->height()); auto fromy = controller->content()->backgroundFromY(); auto state = theme->backgroundState(fill); - const auto paintCache = [&](const Theme::CachedBackground &cache) { + const auto paintCache = [&](const Ui::CachedBackground &cache) { const auto to = QRect( QPoint(cache.x, fromy + cache.y), cache.pixmap.size() / cIntRetinaFactor()); @@ -233,10 +233,10 @@ void SectionWidget::PaintBackground( paintCache(state.now); return; } - const auto &prepared = background->prepared(); + const auto &prepared = background.prepared; if (prepared.isNull()) { return; - } else if (background->paper().isPattern()) { + } else if (background.isPattern) { const auto w = prepared.width() * fill.height() / prepared.height(); const auto cx = qCeil(fill.width() / float64(w)); const auto cols = (cx / 2) * 2 + 1; @@ -247,8 +247,8 @@ void SectionWidget::PaintBackground( prepared, QRect(QPoint(), prepared.size())); } - } else if (background->tile()) { - const auto &tiled = background->preparedForTiled(); + } else if (background.tile) { + const auto &tiled = background.preparedForTiled; const auto left = clip.left(); const auto top = clip.top(); const auto right = clip.left() + clip.width(); @@ -266,7 +266,7 @@ void SectionWidget::PaintBackground( } } else { const auto hq = PainterHighQualityEnabler(p); - const auto rects = Window::Theme::ComputeBackgroundRects( + const auto rects = Ui::ComputeChatBackgroundRects( fill, prepared.size()); auto to = rects.to; diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index f24dfb5f3..6bcbb5411 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -22,11 +22,8 @@ class Session; namespace Ui { class LayerWidget; -} // namespace Ui - -namespace Window::Theme { class ChatTheme; -} // namespace Window::Theme +} // namespace Ui namespace Window { @@ -164,7 +161,7 @@ public: static void PaintBackground( not_null controller, - not_null theme, + not_null theme, not_null widget, QRect clip); diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index d1877a84b..32dc2c081 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -1448,10 +1448,22 @@ bool LoadFromFile( const QString &path, not_null out, Cached *outCache, - not_null outContent) { - *outContent = readThemeContent(path); + QByteArray *outContent) { const auto colorizer = ColorizerForTheme(path); - return LoadTheme(*outContent, colorizer, std::nullopt, outCache, out); + return LoadFromFile(path, out, outCache, outContent, colorizer); +} + +bool LoadFromFile( + const QString &path, + not_null out, + Cached *outCache, + QByteArray *outContent, + const Colorizer &colorizer) { + const auto content = readThemeContent(path); + if (outContent) { + *outContent = content; + } + return LoadTheme(content, colorizer, std::nullopt, outCache, out); } bool LoadFromContent( @@ -1523,34 +1535,6 @@ QImage PreprocessBackgroundImage(QImage image) { return image; } -BackgroundRects ComputeBackgroundRects(QSize fillSize, QSize imageSize) { - if (uint64(imageSize.width()) * fillSize.height() > uint64(imageSize.height()) * fillSize.width()) { - float64 pxsize = fillSize.height() / float64(imageSize.height()); - int takewidth = qCeil(fillSize.width() / pxsize); - if (takewidth > imageSize.width()) { - takewidth = imageSize.width(); - } else if ((imageSize.width() % 2) != (takewidth % 2)) { - ++takewidth; - } - return { - .from = QRect((imageSize.width() - takewidth) / 2, 0, takewidth, imageSize.height()), - .to = QRect(int((fillSize.width() - takewidth * pxsize) / 2.), 0, qCeil(takewidth * pxsize), fillSize.height()), - }; - } else { - float64 pxsize = fillSize.width() / float64(imageSize.width()); - int takeheight = qCeil(fillSize.height() / pxsize); - if (takeheight > imageSize.height()) { - takeheight = imageSize.height(); - } else if ((imageSize.height() % 2) != (takeheight % 2)) { - ++takeheight; - } - return { - .from = QRect(0, (imageSize.height() - takeheight) / 2, imageSize.width(), takeheight), - .to = QRect(0, int((fillSize.height() - takeheight * pxsize) / 2.), fillSize.width(), qCeil(takeheight * pxsize)), - }; - } -} - bool ReadPaletteValues(const QByteArray &content, Fn callback) { if (content.size() > kThemeSchemeSizeLimit) { LOG(("Theme Error: color scheme file too large (should be less than 1 MB, got %2)").arg(content.size())); diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index 895ecb27b..40dfaa650 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -25,6 +25,7 @@ inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024; inline constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024; struct ParsedTheme; +struct Colorizer; [[nodiscard]] bool IsEmbeddedTheme(const QString &path); @@ -90,11 +91,18 @@ void Revert(); [[nodiscard]] QString EditingPalettePath(); +// NB! This method looks to Core::App().settings() to get colorizer by 'file'. bool LoadFromFile( - const QString &file, + const QString &path, not_null out, Cached *outCache, - not_null outContent); + QByteArray *outContent); +bool LoadFromFile( + const QString &path, + not_null out, + Cached *outCache, + QByteArray *outContent, + const Colorizer &colorizer); bool LoadFromContent( const QByteArray &content, not_null out, @@ -272,14 +280,6 @@ private: [[nodiscard]] ChatBackground *Background(); -struct BackgroundRects { - QRect from; - QRect to; -}; -[[nodiscard]] BackgroundRects ComputeBackgroundRects( - QSize fillSize, - QSize imageSize); - bool ReadPaletteValues(const QByteArray &content, Fn callback); } // namespace Theme diff --git a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp index 44193beb9..cae3ae0c3 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_options.h" #include "ui/image/image_prepare.h" #include "ui/emoji_config.h" +#include "ui/chat/chat_theme.h" #include "styles/style_widgets.h" #include "styles/style_window.h" #include "styles/style_media_view.h" @@ -456,7 +457,9 @@ void Generator::paintHistoryBackground() { PainterHighQualityEnabler hq(*_p); auto fill = QSize(_topBar.width(), _body.height()); - const auto rects = ComputeBackgroundRects(fill, background.size()); + const auto rects = Ui::ComputeChatBackgroundRects( + fill, + background.size()); auto to = rects.to; to.moveTop(to.top() + fromy); to.moveTopLeft(to.topLeft() + _history.topLeft()); diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index ff663ba04..ee5daedce 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/themes/window_theme.h" #include "window/window_peer_menu.h" #include "window/window_session_controller.h" +#include "ui/chat/chat_theme.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/widgets/menu/menu.h" @@ -990,7 +991,7 @@ void MainMenu::refreshBackground() { const auto &paper = background->paper(); const auto &prepared = background->prepared(); - const auto rects = Window::Theme::ComputeBackgroundRects( + const auto rects = Ui::ComputeChatBackgroundRects( fill, prepared.size()); diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index d7ffba729..d3ab9406d 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -14,7 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_controller.h" #include "window/main_window.h" #include "window/window_filters_menu.h" -#include "window/themes/window_chat_theme.h" #include "info/info_memento.h" #include "info/info_controller.h" #include "history/history.h" @@ -43,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/delayed_activation.h" #include "ui/chat/message_bubble.h" +#include "ui/chat/chat_theme.h" #include "ui/toast/toast.h" #include "ui/toasts/common_toasts.h" #include "calls/calls_instance.h" // Core::App().calls().inCall(). @@ -468,9 +468,18 @@ SessionController::SessionController( _window->widget(), this)) , _invitePeekTimer([=] { checkInvitePeek(); }) -, _defaultChatTheme(std::make_shared()) { +, _defaultChatTheme(std::make_shared()) { init(); + pushDefaultChatBackground(); + Theme::Background()->updates( + ) | rpl::start_with_next([=](const Theme::BackgroundUpdate &update) { + if (update.type == Theme::BackgroundUpdate::Type::New + || update.type == Theme::BackgroundUpdate::Type::Changed) { + pushDefaultChatBackground(); + } + }, _lifetime); + if (Media::Player::instance()->pauseGifByRoundVideo()) { enableGifPauseReason(GifPauseReason::RoundPlaying); } @@ -1310,7 +1319,7 @@ void SessionController::openDocument( auto SessionController::cachedChatThemeValue( const Data::CloudTheme &data) --> rpl::producer> { +-> rpl::producer> { const auto key = data.id; if (!key || !data.paper || data.paper->backgroundColors().empty()) { return rpl::single(_defaultChatTheme); @@ -1326,23 +1335,75 @@ auto SessionController::cachedChatThemeValue( return rpl::single( _defaultChatTheme ) | rpl::then(_cachedThemesStream.events( - ) | rpl::filter([=](const std::shared_ptr &theme) { + ) | rpl::filter([=](const std::shared_ptr &theme) { return (theme->key() == key); }) | rpl::take(1)); } +void SessionController::pushDefaultChatBackground() { + const auto background = Theme::Background(); + const auto &paper = background->paper(); + _defaultChatTheme->setBackground({ + .prepared = background->prepared(), + .preparedForTiled = background->preparedForTiled(), + .gradientForFill = background->gradientForFill(), + .colorForFill = background->colorForFill(), + .colors = paper.backgroundColors(), + .patternOpacity = paper.patternOpacity(), + .gradientRotation = paper.gradientRotation(), + .isPattern = paper.isPattern(), + .tile = background->tile(), + }); +} + void SessionController::cacheChatTheme(const Data::CloudTheme &data) { Expects(data.id != 0); + using namespace Theme; + const auto key = data.id; + const auto dark = data.basedOnDark; + const auto accent = data.accentColor; if (data.paper) { const auto document = data.paper->document(); } - crl::async([this, data, weak = base::make_weak(this)] { + const auto preparePalette = [=](style::palette &palette) { + if (dark) { + const auto &embedded = Theme::EmbeddedThemes(); + const auto i = ranges::find( + embedded, + EmbeddedType::Night, + &EmbeddedScheme::type); + Assert(i != end(embedded)); + + auto instance = Instance(); + const auto loaded = LoadFromFile( + i->path, + &instance, + nullptr, + nullptr, + accent ? ColorizerFrom(*i, *accent) : Colorizer()); + Assert(loaded); + palette = instance.palette; + } else { + // #TODO themes apply accent color to classic theme + } + }; + const auto prepareBackground = [] { + return Ui::ChatThemeBackground{ + + }; + }; + auto descriptor = Ui::ChatThemeDescriptor{ + .id = key, + .preparePalette = preparePalette, + .prepareBackground = prepareBackground, + }; + crl::async([this, descriptor = std::move(descriptor), weak = base::make_weak(this)] { crl::on_main(weak, [ this, - result = std::make_shared(data) + result = std::make_shared(std::move(descriptor)) ]() mutable { _customChatThemes.emplace(result->key(), result); _cachedThemesStream.fire(std::move(result)); diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index b5ae93b9e..abb598e60 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -25,10 +25,6 @@ namespace Adaptive { enum class WindowLayout; } // namespace Adaptive -namespace HistoryView { -struct PaintContext; -} // namespace HistoryView - namespace ChatHelpers { class TabbedSelector; } // namespace ChatHelpers @@ -49,11 +45,9 @@ class FormController; namespace Ui { class LayerWidget; enum class ReportReason; -} // namespace Ui - -namespace Window::Theme { class ChatTheme; -} // namespace Window::Theme +struct ChatPaintContext; +} // namespace Ui namespace Data { struct CloudTheme; @@ -403,21 +397,21 @@ public: [[nodiscard]] rpl::producer<> filtersMenuChanged() const; [[nodiscard]] auto defaultChatTheme() const - -> const std::shared_ptr & { + -> const std::shared_ptr & { return _defaultChatTheme; } [[nodiscard]] auto cachedChatThemeValue( const Data::CloudTheme &data) - -> rpl::producer>; + -> rpl::producer>; struct PaintContextArgs { - not_null theme; + not_null theme; int visibleAreaTop = 0; int visibleAreaTopGlobal = 0; int visibleAreaWidth = 0; QRect clip; }; - [[nodiscard]] HistoryView::PaintContext preparePaintContext( + [[nodiscard]] Ui::ChatPaintContext preparePaintContext( PaintContextArgs &&args); rpl::lifetime &lifetime() { @@ -449,6 +443,7 @@ private: void checkInvitePeek(); + void pushDefaultChatBackground(); void cacheChatTheme(const Data::CloudTheme &data); const not_null _window; @@ -478,11 +473,9 @@ private: rpl::event_stream<> _filtersMenuChanged; - std::shared_ptr _defaultChatTheme; - base::flat_map< - uint64, - std::shared_ptr> _customChatThemes; - rpl::event_stream> _cachedThemesStream; + std::shared_ptr _defaultChatTheme; + base::flat_map> _customChatThemes; + rpl::event_stream> _cachedThemesStream; rpl::lifetime _lifetime; diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 151650052..35a5f2c7d 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -135,6 +135,8 @@ PRIVATE ui/chat/attach/attach_single_file_preview.h ui/chat/attach/attach_single_media_preview.cpp ui/chat/attach/attach_single_media_preview.h + ui/chat/chat_theme.cpp + ui/chat/chat_theme.h ui/chat/group_call_bar.cpp ui/chat/group_call_bar.h ui/chat/group_call_userpics.cpp