From 78a72b42b0a972a22985fd1776ef0d3462257e8c Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 5 Jul 2025 20:11:10 +0000 Subject: [PATCH 001/341] Don't stage unused boost-regex shared library in snap --- snap/snapcraft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 16da44ab9c..f7faf8e5ad 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -103,7 +103,6 @@ parts: - zlib1g-dev stage-packages: - libavif16 - - libboost-regex1.83.0 - libgeoclue-2-0 - libgeocode-glib-2-0 - libglib2.0-0t64 From 7cab32f71ba0f1dbe04d5887acdb57430ed584dd Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 25 Jan 2023 20:00:22 +0400 Subject: [PATCH 002/341] Switch snap to the gnome extension --- snap/snapcraft.yaml | 214 ++------------------------------------------ 1 file changed, 6 insertions(+), 208 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index f7faf8e5ad..ab34a7f2f6 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -9,73 +9,24 @@ compression: lzo apps: telegram-desktop: command: usr/bin/telegram-desktop - command-chain: - - bin/desktop-launch common-id: org.telegram.desktop desktop: usr/share/applications/org.telegram.desktop.desktop autostart: telegram-desktop_telegram-desktop.desktop + extensions: [gnome] plugs: - - alsa - audio-playback - audio-record - camera - - desktop - - desktop-legacy - - gsettings - hardware-observe - home - network - network-bind - network-status - - opengl - removable-media - unity7 - - wayland - - x11 slots: - mpris -hooks: - configure: - command-chain: - - bin/hooks-configure-desktop - plugs: - - desktop - -plugs: - desktop: - mount-host-font-cache: false - # Support for common GTK themes - # https://forum.snapcraft.io/t/how-to-use-the-system-gtk-theme-via-the-gtk-common-themes-snap/6235 - gtk-3-themes: - interface: content - target: $SNAP/data-dir/themes - default-provider: gtk-common-themes - icon-themes: - interface: content - target: $SNAP/data-dir/icons - default-provider: gtk-common-themes - sound-themes: - interface: content - target: $SNAP/data-dir/sounds - default-provider: gtk-common-themes - -layout: - /usr/share/alsa: - bind: $SNAP/usr/share/alsa - /usr/share/pipewire: - bind: $SNAP/usr/share/pipewire - /usr/share/X11: - bind: $SNAP/usr/share/X11 - /usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/gtk-3.0: - bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/gtk-3.0 - /usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pipewire-0.3: - bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pipewire-0.3 - /usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/spa-0.2: - bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/spa-0.2 - /usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.1: - bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.1 - parts: telegram: plugin: cmake @@ -87,40 +38,24 @@ parts: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s build-packages: - clang - - libtool-bin - - python3 - libavif-dev - libboost-regex-dev - - libgirepository1.0-dev - - libglib2.0-dev - libheif-dev - libopenal-dev - libssl-dev - - libxcb1-dev - libxcb-keysyms1-dev - libxcb-record0-dev - libxcb-screensaver0-dev - - zlib1g-dev stage-packages: - libavif16 - libgeoclue-2-0 - - libgeocode-glib-2-0 - - libglib2.0-0t64 - - libheif1 - libopenal1 - - libssl3t64 - - libwebkit2gtk-4.1-0 - - libxcb1 - - libxcb-keysyms1 - libxcb-record0 - libxcb-screensaver0 - - zlib1g - - glib-networking cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - - -DCMAKE_PREFIX_PATH=$CRAFT_STAGE/usr - -DTDESKTOP_API_ID=611335 - -DTDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c override-pull: | @@ -172,41 +107,6 @@ parts: rm -rf patches stage: [-./*] - desktop-qt: - source: https://github.com/desktop-app/snapcraft-desktop-helpers.git - source-depth: 1 - source-subdir: qt - plugin: make - make-parameters: ["FLAVOR=qt5"] - build-environment: - - LD_LIBRARY_PATH: $CRAFT_STAGE/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} - build-packages: - - build-essential - - dpkg-dev - - gtk-update-icon-cache - - libglib2.0-bin - - libgtk-3-0t64 - stage-packages: - - libc-bin - - libgdk-pixbuf-2.0-0 - - libnvidia-egl-wayland1 - - libxkbcommon0 - - locales-all - - shared-mime-info - - xdg-user-dirs - override-prime: | - craftctl default - update-mime-database usr/share/mime - glib-compile-schemas usr/share/glib-2.0/schemas - for theme in usr/share/icons/*; do - if [ -f "$theme/index.theme" ] && [ ! -f "$theme/icon-theme.cache" ]; then - update-icon-caches "$theme" - fi - done - GTK_PATH=$PWD/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/gtk-3.0 /usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libgtk-3-0t64/gtk-query-immodules-3.0 > usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/gtk-3.0/3.0.0/immodules/immodules.cache - after: - - telegram - ada: source: https://github.com/ada-url/ada.git source-depth: 1 @@ -242,8 +142,6 @@ parts: - libavutil58 - libswresample4 - libswscale7 - - va-driver-all - - vdpau-driver-all override-build: | craftctl default mv "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/blas/"* "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR" @@ -258,6 +156,8 @@ parts: plugin: cmake build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s + build-packages: + - libhwy-dev cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -274,9 +174,9 @@ parts: - -DJPEGXL_ENABLE_SJPEG=OFF - -DJPEGXL_ENABLE_OPENEXR=OFF - -DJPEGXL_ENABLE_SKCMS=OFF - stage: - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libbrotli* - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libhwy* + - -DJPEGXL_FORCE_SYSTEM_BROTLI=ON + - -DJPEGXL_FORCE_SYSTEM_LCMS2=ON + - -DJPEGXL_FORCE_SYSTEM_HWY=ON prime: - -./usr/bin - -./usr/include @@ -293,10 +193,6 @@ parts: plugin: cmake build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s - build-packages: - - zlib1g-dev - stage-packages: - - zlib1g cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -325,93 +221,30 @@ parts: build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s build-packages: - - libdbus-1-dev - - libegl-dev - - libfontconfig1-dev - - libfreetype-dev - - libglib2.0-dev - - libglx-dev - - libgtk-3-dev - - libharfbuzz-dev - - libice-dev - - libicu-dev - - liblcms2-dev - - libopengl-dev - - libpcre2-dev - - libpng-dev - - libsm-dev - libssl-dev - - libvulkan-dev - - libwayland-dev - - libx11-dev - - libx11-xcb-dev - - libxcb1-dev - libxcb-cursor-dev - libxcb-glx0-dev - libxcb-icccm4-dev - libxcb-image0-dev - libxcb-keysyms1-dev - libxcb-randr0-dev - - libxcb-render0-dev - libxcb-render-util0-dev - libxcb-shape0-dev - - libxcb-shm0-dev - libxcb-sync-dev - libxcb-util-dev - libxcb-xfixes0-dev - libxcb-xkb-dev - - libxkbcommon-dev - libxkbcommon-x11-dev - - zlib1g-dev stage-packages: - - libdbus-1-3 - - libegl1 - - libfontconfig1 - - libfreetype6 - - libglib2.0-0t64 - - libglx0 - - libgtk-3-0t64 - - libharfbuzz0b - - libice6 - - libicu74 - - liblcms2-2 - - libopengl0 - - libpcre2-16-0 - - libpng16-16t64 - - libsm6 - - libssl3t64 - - libvulkan1 - - libwayland-client0 - - libwayland-cursor0 - - libwayland-egl1 - - libwayland-server0 - - libx11-6 - - libx11-xcb1 - - libxcb1 - libxcb-cursor0 - libxcb-glx0 - - libxcb-icccm4 - - libxcb-image0 - - libxcb-keysyms1 - libxcb-randr0 - - libxcb-render0 - - libxcb-render-util0 - - libxcb-shape0 - - libxcb-shm0 - libxcb-sync1 - - libxcb-util1 - libxcb-xfixes0 - - libxcb-xkb1 - - libxkbcommon0 - - libxkbcommon-x11-0 - - zlib1g - - mesa-vulkan-drivers - - xkb-data cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - - -DCMAKE_PREFIX_PATH=$CRAFT_STAGE/usr - -DINSTALL_LIBDIR=/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR - -DINPUT_openssl=linked override-pull: | @@ -479,10 +312,6 @@ parts: build-packages: - gperf - libssl-dev - - zlib1g-dev - stage-packages: - - libssl3t64 - - zlib1g cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -503,48 +332,17 @@ parts: build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s build-packages: - - libdrm-dev - - libegl-dev - - libgbm-dev - - libgl-dev - - libglib2.0-dev - libopenh264-dev - libopus-dev - libpipewire-0.3-dev - libssl-dev - libvpx-dev - - libx11-dev - - libxcomposite-dev - - libxdamage-dev - - libxext-dev - - libxfixes-dev - - libxrender-dev - - libxrandr-dev - - libxtst-dev stage-packages: - - libdrm2 - - libegl1 - - libgbm1 - - libgl1 - - libglib2.0-0t64 - libopenh264-7 - - libopus0 - - libssl3t64 - - libvpx9 - - libx11-6 - - libxcomposite1 - - libxdamage1 - - libxext6 - - libxfixes3 - - libxrender1 - - libxrandr2 - - libxtst6 - - pipewire cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - - -DCMAKE_PREFIX_PATH=$CRAFT_STAGE/usr prime: - -./usr/include - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake From 3d6783597fdfc2f7a13045a026d550275cf133af Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 20 Feb 2025 05:24:42 +0400 Subject: [PATCH 003/341] Optimize geoclue dependency in snap It depends on entire daemon and brings unneeded dependencies that make the package way bigger --- snap/snapcraft.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index ab34a7f2f6..374ea77a75 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -48,7 +48,6 @@ parts: - libxcb-screensaver0-dev stage-packages: - libavif16 - - libgeoclue-2-0 - libopenal1 - libxcb-record0 - libxcb-screensaver0 @@ -88,6 +87,7 @@ parts: after: - ada - ffmpeg + - geoclue - libjxl - protobuf - qt @@ -149,6 +149,13 @@ parts: mv "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/lapack/"* "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR" rmdir "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/lapack" + geoclue: + plugin: nil + stage-packages: + - libgeoclue-2-0 + stage: + - ./usr/lib/x86_64-linux-gnu/libgeoclue-2.so* + libjxl: source: https://github.com/libjxl/libjxl.git source-depth: 1 From ef2e9406c74a7d509f10371de680d4da8633b872 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 4 Jul 2025 12:10:33 +0000 Subject: [PATCH 004/341] Move packages to a separate snap part --- snap/snapcraft.yaml | 97 ++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 374ea77a75..292c175cd5 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -36,21 +36,6 @@ parts: build-environment: - LD_LIBRARY_PATH: $CRAFT_STAGE/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s - build-packages: - - clang - - libavif-dev - - libboost-regex-dev - - libheif-dev - - libopenal-dev - - libssl-dev - - libxcb-keysyms1-dev - - libxcb-record0-dev - - libxcb-screensaver0-dev - stage-packages: - - libavif16 - - libopenal1 - - libxcb-record0 - - libxcb-screensaver0 cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -95,6 +80,48 @@ parts: - tde2e - webrtc + pkgs: + plugin: nil + build-packages: + - clang + - gperf + - libavif-dev + - libboost-regex-dev + - libheif-dev + - libhwy-dev + - libopenal-dev + - libopenh264-dev + - libopus-dev + - libpipewire-0.3-dev + - libssl-dev + - libvpx-dev + - libxcb-cursor-dev + - libxcb-glx0-dev + - libxcb-icccm4-dev + - libxcb-image0-dev + - libxcb-keysyms1-dev + - libxcb-randr0-dev + - libxcb-record0-dev + - libxcb-render-util0-dev + - libxcb-screensaver0-dev + - libxcb-shape0-dev + - libxcb-sync-dev + - libxcb-util-dev + - libxcb-xfixes0-dev + - libxcb-xkb-dev + - libxkbcommon-x11-dev + stage-packages: + - libavif16 + - libopenal1 + - libopenh264-7 + - libxcb-cursor0 + - libxcb-glx0 + - libxcb-randr0 + - libxcb-record0 + - libxcb-screensaver0 + - libxcb-sync1 + - libxcb-xfixes0 + patches: source: https://github.com/desktop-app/patches.git source-depth: 1 @@ -163,8 +190,6 @@ parts: plugin: cmake build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s - build-packages: - - libhwy-dev cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -212,6 +237,8 @@ parts: - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.so + after: + - pkgs qt: source: https://github.com/qt/qt5.git @@ -227,27 +254,6 @@ parts: plugin: cmake build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s - build-packages: - - libssl-dev - - libxcb-cursor-dev - - libxcb-glx0-dev - - libxcb-icccm4-dev - - libxcb-image0-dev - - libxcb-keysyms1-dev - - libxcb-randr0-dev - - libxcb-render-util0-dev - - libxcb-shape0-dev - - libxcb-sync-dev - - libxcb-util-dev - - libxcb-xfixes0-dev - - libxcb-xkb-dev - - libxkbcommon-x11-dev - stage-packages: - - libxcb-cursor0 - - libxcb-glx0 - - libxcb-randr0 - - libxcb-sync1 - - libxcb-xfixes0 cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -281,6 +287,7 @@ parts: after: - libjxl - patches + - pkgs rnnoise: source: https://gitlab.xiph.org/xiph/rnnoise.git @@ -316,9 +323,6 @@ parts: plugin: cmake build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s - build-packages: - - gperf - - libssl-dev cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -330,6 +334,8 @@ parts: - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.a + after: + - pkgs webrtc: source: https://github.com/desktop-app/tg_owt.git @@ -338,14 +344,6 @@ parts: plugin: cmake build-environment: - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s - build-packages: - - libopenh264-dev - - libopus-dev - - libpipewire-0.3-dev - - libssl-dev - - libvpx-dev - stage-packages: - - libopenh264-7 cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -357,3 +355,4 @@ parts: after: - ffmpeg - libjxl + - pkgs From 60f91bff505b21e0b77d0adfe2671d7efb698aa3 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 4 Jul 2025 12:12:47 +0000 Subject: [PATCH 005/341] Stop priming static libs completely in snap --- snap/snapcraft.yaml | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 292c175cd5..7d71a90f63 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -148,10 +148,7 @@ parts: - -DADA_TESTING=OFF - -DADA_TOOLS=OFF - -DADA_INCLUDE_URL_PATTERN=OFF - prime: - - -./usr/include - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.a + prime: [-./*] ffmpeg: plugin: nil @@ -329,11 +326,7 @@ parts: - -DCMAKE_INSTALL_PREFIX=/usr - -DCMAKE_INSTALL_LIBDIR=lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR - -DTD_E2E_ONLY=ON - prime: - - -./usr/include - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.a + prime: [-./*] after: - pkgs @@ -348,10 +341,7 @@ parts: cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - prime: - - -./usr/include - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.a + prime: [-./*] after: - ffmpeg - libjxl From ba1274ff3ada908b257fce61c697baffa040a1af Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 4 Jul 2025 12:21:42 +0000 Subject: [PATCH 006/341] Build all deps statically in snap for lesser package size --- snap/snapcraft.yaml | 57 ++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 7d71a90f63..9132fb7eec 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -35,7 +35,7 @@ parts: parse-info: [usr/share/metainfo/org.telegram.desktop.metainfo.xml] build-environment: - LD_LIBRARY_PATH: $CRAFT_STAGE/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s + - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -Wl,-push-state,-no-as-needed,-lhwy,-pop-state -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -191,6 +191,7 @@ parts: cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr + - -DBUILD_SHARED_LIBS=OFF - -DBUILD_TESTING=OFF - -DJPEGXL_ENABLE_DEVTOOLS=OFF - -DJPEGXL_ENABLE_TOOLS=OFF @@ -206,14 +207,13 @@ parts: - -DJPEGXL_FORCE_SYSTEM_BROTLI=ON - -DJPEGXL_FORCE_SYSTEM_LCMS2=ON - -DJPEGXL_FORCE_SYSTEM_HWY=ON - prime: - - -./usr/bin - - -./usr/include - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.a - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.so - - -./usr/share + override-build: | + craftctl default + cp lib/libjpegli-static.a "$CRAFT_PART_INSTALL"/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.a + ar rcs "$CRAFT_PART_INSTALL"/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.a lib/CMakeFiles/jpegli-libjpeg-obj.dir/jpegli/libjpeg_wrapper.cc.o + stage: + - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.so* + prime: [-./*] protobuf: source: https://github.com/protocolbuffers/protobuf.git @@ -226,14 +226,8 @@ parts: cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - - -DBUILD_SHARED_LIBS=ON - -Dprotobuf_BUILD_TESTS=OFF - prime: - - -./usr/bin - - -./usr/include - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.so + prime: [-./*] after: - pkgs @@ -250,12 +244,15 @@ parts: - qtwayland plugin: cmake build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s + - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -Wl,-push-state,-no-as-needed,-lhwy,-pop-state -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr - -DINSTALL_LIBDIR=/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR + - -DBUILD_SHARED_LIBS=OFF + - -DQT_QPA_PLATFORMS="wayland;xcb" + - -DFEATURE_eglfs=OFF - -DINPUT_openssl=linked override-pull: | craftctl default @@ -265,22 +262,7 @@ parts: cd ../qtwayland find $CRAFT_STAGE/patches/qtwayland_${QT} -type f -print0 | sort -z | xargs -r0 git apply cd .. - prime: - - -./usr/bin - - -./usr/doc - - -./usr/include - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/cmake - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.a - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.la - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.prl - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.so - - -./usr/libexec - - -./usr/metatypes - - -./usr/mkspecs - - -./usr/modules - - -./usr/sbom - - -./**/objects-* + prime: [-./*] after: - libjxl - patches @@ -296,15 +278,10 @@ parts: autotools-configure-parameters: - --prefix=/usr - --libdir=\${exec_prefix}/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR - - --disable-static + - --disable-shared - --disable-examples - --disable-doc - prime: - - -./usr/include - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/pkgconfig - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.la - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/*.so - - -./usr/share + prime: [-./*] systemd: plugin: nil From 90edb0903d9944827ec7f71071cebcc465073f83 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sun, 6 Jul 2025 00:54:00 +0000 Subject: [PATCH 007/341] Use only jpegli from self-built libjxl in snap --- snap/snapcraft.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 9132fb7eec..90ac781f16 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -73,7 +73,7 @@ parts: - ada - ffmpeg - geoclue - - libjxl + - jpegli - protobuf - qt - rnnoise @@ -89,6 +89,7 @@ parts: - libboost-regex-dev - libheif-dev - libhwy-dev + - libjxl-dev - libopenal-dev - libopenh264-dev - libopus-dev @@ -180,7 +181,7 @@ parts: stage: - ./usr/lib/x86_64-linux-gnu/libgeoclue-2.so* - libjxl: + jpegli: source: https://github.com/libjxl/libjxl.git source-depth: 1 source-tag: v0.11.1 @@ -212,7 +213,10 @@ parts: cp lib/libjpegli-static.a "$CRAFT_PART_INSTALL"/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.a ar rcs "$CRAFT_PART_INSTALL"/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.a lib/CMakeFiles/jpegli-libjpeg-obj.dir/jpegli/libjpeg_wrapper.cc.o stage: - - -./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.so* + - ./usr/include/jconfig.h + - ./usr/include/jmorecfg.h + - ./usr/include/jpeglib.h + - ./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.a prime: [-./*] protobuf: @@ -264,7 +268,7 @@ parts: cd .. prime: [-./*] after: - - libjxl + - jpegli - patches - pkgs @@ -321,5 +325,5 @@ parts: prime: [-./*] after: - ffmpeg - - libjxl + - jpegli - pkgs From a6a8363527d5853612e56b18841aed71f9ddb44a Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 20 Feb 2025 03:15:54 +0400 Subject: [PATCH 008/341] Self-build ffmpeg in snap for lesser package size --- snap/snapcraft.yaml | 184 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 162 insertions(+), 22 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 90ac781f16..8073f1adf5 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -39,7 +39,7 @@ parts: cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release - - -DCMAKE_INSTALL_PREFIX=/usr + - -DCMAKE_INSTALL_PREFIX=/ - -DTDESKTOP_API_ID=611335 - -DTDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c override-pull: | @@ -85,8 +85,10 @@ parts: build-packages: - clang - gperf + - nasm - libavif-dev - libboost-regex-dev + - libdav1d-dev - libheif-dev - libhwy-dev - libjxl-dev @@ -95,6 +97,7 @@ parts: - libopus-dev - libpipewire-0.3-dev - libssl-dev + - libvdpau-dev - libvpx-dev - libxcb-cursor-dev - libxcb-glx0-dev @@ -111,6 +114,7 @@ parts: - libxcb-xfixes0-dev - libxcb-xkb-dev - libxkbcommon-x11-dev + - libxv-dev stage-packages: - libavif16 - libopenal1 @@ -152,27 +156,153 @@ parts: prime: [-./*] ffmpeg: - plugin: nil - build-packages: - - libavcodec-dev - - libavfilter-dev - - libavformat-dev - - libavutil-dev - - libswresample-dev - - libswscale-dev - stage-packages: - - libavcodec60 - - libavfilter9 - - libavformat60 - - libavutil58 - - libswresample4 - - libswscale7 - override-build: | - craftctl default - mv "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/blas/"* "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR" - rmdir "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/blas" - mv "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/lapack/"* "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR" - rmdir "$CRAFT_PART_INSTALL/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/lapack" + source: https://github.com/FFmpeg/FFmpeg.git + source-depth: 1 + source-branch: n6.1.1 + plugin: autotools + build-environment: + - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s + autotools-configure-parameters: + - --prefix=/usr + - --libdir=/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR + - --extra-cflags="-DCONFIG_SAFE_BITSTREAM_READER=1" + - --extra-cxxflags="-DCONFIG_SAFE_BITSTREAM_READER=1" + - --disable-debug + - --disable-programs + - --disable-doc + - --disable-network + - --disable-autodetect + - --disable-everything + - --enable-libdav1d + - --enable-libopenh264 + - --enable-libopus + - --enable-libvpx + - --enable-vaapi + - --enable-vdpau + - --enable-xlib + - --enable-libdrm + - --enable-ffnvcodec + - --enable-nvdec + - --enable-cuvid + - --enable-protocol=file + - --enable-hwaccel=av1_vaapi + - --enable-hwaccel=av1_nvdec + - --enable-hwaccel=h264_vaapi + - --enable-hwaccel=h264_vdpau + - --enable-hwaccel=h264_nvdec + - --enable-hwaccel=hevc_vaapi + - --enable-hwaccel=hevc_vdpau + - --enable-hwaccel=hevc_nvdec + - --enable-hwaccel=mpeg2_vaapi + - --enable-hwaccel=mpeg2_vdpau + - --enable-hwaccel=mpeg2_nvdec + - --enable-hwaccel=mpeg4_vaapi + - --enable-hwaccel=mpeg4_vdpau + - --enable-hwaccel=mpeg4_nvdec + - --enable-hwaccel=vp8_vaapi + - --enable-hwaccel=vp8_nvdec + - --enable-decoder=aac + - --enable-decoder=aac_fixed + - --enable-decoder=aac_latm + - --enable-decoder=aasc + - --enable-decoder=ac3 + - --enable-decoder=alac + - --enable-decoder=av1 + - --enable-decoder=av1_cuvid + - --enable-decoder=eac3 + - --enable-decoder=flac + - --enable-decoder=gif + - --enable-decoder=h264 + - --enable-decoder=hevc + - --enable-decoder=libdav1d + - --enable-decoder=libvpx_vp8 + - --enable-decoder=libvpx_vp9 + - --enable-decoder=mp1 + - --enable-decoder=mp1float + - --enable-decoder=mp2 + - --enable-decoder=mp2float + - --enable-decoder=mp3 + - --enable-decoder=mp3adu + - --enable-decoder=mp3adufloat + - --enable-decoder=mp3float + - --enable-decoder=mp3on4 + - --enable-decoder=mp3on4float + - --enable-decoder=mpeg4 + - --enable-decoder=msmpeg4v2 + - --enable-decoder=msmpeg4v3 + - --enable-decoder=opus + - --enable-decoder=pcm_alaw + - --enable-decoder=pcm_f32be + - --enable-decoder=pcm_f32le + - --enable-decoder=pcm_f64be + - --enable-decoder=pcm_f64le + - --enable-decoder=pcm_lxf + - --enable-decoder=pcm_mulaw + - --enable-decoder=pcm_s16be + - --enable-decoder=pcm_s16be_planar + - --enable-decoder=pcm_s16le + - --enable-decoder=pcm_s16le_planar + - --enable-decoder=pcm_s24be + - --enable-decoder=pcm_s24daud + - --enable-decoder=pcm_s24le + - --enable-decoder=pcm_s24le_planar + - --enable-decoder=pcm_s32be + - --enable-decoder=pcm_s32le + - --enable-decoder=pcm_s32le_planar + - --enable-decoder=pcm_s64be + - --enable-decoder=pcm_s64le + - --enable-decoder=pcm_s8 + - --enable-decoder=pcm_s8_planar + - --enable-decoder=pcm_u16be + - --enable-decoder=pcm_u16le + - --enable-decoder=pcm_u24be + - --enable-decoder=pcm_u24le + - --enable-decoder=pcm_u32be + - --enable-decoder=pcm_u32le + - --enable-decoder=pcm_u8 + - --enable-decoder=pcm_zork + - --enable-decoder=vorbis + - --enable-decoder=vp8 + - --enable-decoder=wavpack + - --enable-decoder=wmalossless + - --enable-decoder=wmapro + - --enable-decoder=wmav1 + - --enable-decoder=wmav2 + - --enable-decoder=wmavoice + - --enable-encoder=aac + - --enable-encoder=libopenh264 + - --enable-encoder=libopus + - --enable-encoder=pcm_s16le + - --enable-filter=atempo + - --enable-parser=aac + - --enable-parser=aac_latm + - --enable-parser=flac + - --enable-parser=gif + - --enable-parser=h264 + - --enable-parser=hevc + - --enable-parser=mpeg4video + - --enable-parser=mpegaudio + - --enable-parser=opus + - --enable-parser=vorbis + - --enable-demuxer=aac + - --enable-demuxer=flac + - --enable-demuxer=gif + - --enable-demuxer=h264 + - --enable-demuxer=hevc + - --enable-demuxer=matroska + - --enable-demuxer=m4v + - --enable-demuxer=mov + - --enable-demuxer=mp3 + - --enable-demuxer=ogg + - --enable-demuxer=wav + - --enable-muxer=mp4 + - --enable-muxer=ogg + - --enable-muxer=opus + - --enable-muxer=wav + prime: [-./*] + after: + - nv-codec-headers + - pkgs geoclue: plugin: nil @@ -219,6 +349,16 @@ parts: - ./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.a prime: [-./*] + nv-codec-headers: + source: https://github.com/FFmpeg/nv-codec-headers.git + source-depth: 1 + source-branch: n12.1.14.0 + plugin: make + make-parameters: + - PREFIX=/usr + - LIBDIR=lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR + prime: [-./*] + protobuf: source: https://github.com/protocolbuffers/protobuf.git source-depth: 1 From 18ab93a9f6e6ce2cde3127106af6baff6db02224 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 5 Jul 2025 13:26:21 +0000 Subject: [PATCH 009/341] Self-build openal in snap for lesser package size --- snap/snapcraft.yaml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 8073f1adf5..d7117127a1 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -74,6 +74,7 @@ parts: - ffmpeg - geoclue - jpegli + - openal - protobuf - qt - rnnoise @@ -92,7 +93,6 @@ parts: - libheif-dev - libhwy-dev - libjxl-dev - - libopenal-dev - libopenh264-dev - libopus-dev - libpipewire-0.3-dev @@ -117,7 +117,6 @@ parts: - libxv-dev stage-packages: - libavif16 - - libopenal1 - libopenh264-7 - libxcb-cursor0 - libxcb-glx0 @@ -348,6 +347,29 @@ parts: - ./usr/include/jpeglib.h - ./usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjpeg.a prime: [-./*] + after: + - pkgs + + openal: + source: https://github.com/kcat/openal-soft.git + source-depth: 1 + source-tag: 1.24.3 + plugin: cmake + build-environment: + - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s + cmake-generator: Ninja + cmake-parameters: + - -DCMAKE_BUILD_TYPE=Release + - -DCMAKE_INSTALL_PREFIX=/usr + - -DLIBTYPE=STATIC + - -DALSOFT_DLOPEN=OFF + - -DALSOFT_EXAMPLES=OFF + - -DALSOFT_UTILS=OFF + - -DALSOFT_INSTALL_CONFIG=OFF + - -DALSOFT_BACKEND_PIPEWIRE=OFF + prime: [-./*] + after: + - pkgs nv-codec-headers: source: https://github.com/FFmpeg/nv-codec-headers.git From 918985449bd396fb87a560f90312d665dc457df0 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 5 Jul 2025 13:41:07 +0000 Subject: [PATCH 010/341] Self-build avif in snap for lesser package size --- snap/snapcraft.yaml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index d7117127a1..e978294f39 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -35,7 +35,7 @@ parts: parse-info: [usr/share/metainfo/org.telegram.desktop.metainfo.xml] build-environment: - LD_LIBRARY_PATH: $CRAFT_STAGE/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -Wl,-push-state,-no-as-needed,-lhwy,-pop-state -s + - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -Wl,-push-state,-no-as-needed,-ldav1d,-lhwy,-pop-state -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -71,6 +71,7 @@ parts: done after: - ada + - avif - ffmpeg - geoclue - jpegli @@ -87,7 +88,6 @@ parts: - clang - gperf - nasm - - libavif-dev - libboost-regex-dev - libdav1d-dev - libheif-dev @@ -116,7 +116,6 @@ parts: - libxkbcommon-x11-dev - libxv-dev stage-packages: - - libavif16 - libopenh264-7 - libxcb-cursor0 - libxcb-glx0 @@ -154,6 +153,24 @@ parts: - -DADA_INCLUDE_URL_PATTERN=OFF prime: [-./*] + avif: + source: https://github.com/AOMediaCodec/libavif.git + source-depth: 1 + source-tag: v1.3.0 + plugin: cmake + build-environment: + - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s + cmake-generator: Ninja + cmake-parameters: + - -DCMAKE_BUILD_TYPE=Release + - -DCMAKE_INSTALL_PREFIX=/usr + - -DBUILD_SHARED_LIBS=OFF + - -DAVIF_CODEC_DAV1D=SYSTEM + - -DAVIF_LIBYUV=OFF + prime: [-./*] + after: + - pkgs + ffmpeg: source: https://github.com/FFmpeg/FFmpeg.git source-depth: 1 From ea89a9f70608a5e205cf6558734674b54273db48 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 15 Jul 2025 21:07:09 +0000 Subject: [PATCH 011/341] Free more disk space in snap action --- .github/workflows/snap.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml index 6e70726588..ffdc0eabba 100644 --- a/.github/workflows/snap.yml +++ b/.github/workflows/snap.yml @@ -61,7 +61,16 @@ jobs: sudo lxd waitready - name: Free up some disk space. - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be + uses: endersonmenezes/free-disk-space@4cae28d0d8e716a770938d92630f23db5184f61f + with: + remove_android: true + remove_dotnet: true + remove_haskell: true + remove_tool_cache: true + remove_swap: true + remove_packages: "azure-cli google-cloud-cli microsoft-edge-stable google-chrome-stable firefox postgresql* temurin-* *llvm* mysql* dotnet-sdk-*" + remove_packages_one_command: true + remove_folders: "/usr/share/swift /usr/share/miniconda /usr/share/az* /usr/share/glade* /usr/local/lib/node_modules /usr/local/share/chromium /usr/local/share/powershell" - name: Telegram Desktop snap build. run: sudo -u $USER snap run snapcraft --verbosity=debug From 669f46d6a152e97379798621d2e1df4d850d7a5f Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 17 Jul 2025 18:03:12 +0000 Subject: [PATCH 012/341] Try to fix snap build on armhf --- snap/snapcraft.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index e978294f39..847eaf956d 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -315,6 +315,9 @@ parts: - --enable-muxer=ogg - --enable-muxer=opus - --enable-muxer=wav + override-pull: | + craftctl default + sed -i 's/disable ffnvcodec cuvid nvdec nvenc/:/g' configure prime: [-./*] after: - nv-codec-headers From 4c20e79d1fb70349bce5f40e75e103e5503062c6 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 17 Jul 2025 18:37:41 +0000 Subject: [PATCH 013/341] Update rnnoise to 0.2 in snap --- snap/snapcraft.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 847eaf956d..81829a95e0 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -88,6 +88,7 @@ parts: - clang - gperf - nasm + - wget - libboost-regex-dev - libdav1d-dev - libheif-dev @@ -455,9 +456,9 @@ parts: - pkgs rnnoise: - source: https://gitlab.xiph.org/xiph/rnnoise.git + source: https://github.com/xiph/rnnoise.git source-depth: 1 - source-commit: 7f449bf8bd3b933891d12c30112268c4090e4d59 + source-tag: v0.2 plugin: autotools build-environment: - CFLAGS: -O2 -s @@ -467,7 +468,12 @@ parts: - --disable-shared - --disable-examples - --disable-doc + override-pull: | + craftctl default + sed -i 's/os_support.h/common.h/g;s/OPUS_CLEAR/RNN_CLEAR/g' src/vec{,_neon}.h prime: [-./*] + after: + - pkgs systemd: plugin: nil From 1c35a91d13b8097e654b35dd4ac23768ef715bcf Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 17 Jul 2025 23:04:12 +0000 Subject: [PATCH 014/341] Remove -s where unneeded in snap This has no sense with static libraries --- snap/snapcraft.yaml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 81829a95e0..afc1a67576 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -143,8 +143,6 @@ parts: source-depth: 1 source-tag: v3.2.4 plugin: cmake - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -159,8 +157,6 @@ parts: source-depth: 1 source-tag: v1.3.0 plugin: cmake - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -177,8 +173,6 @@ parts: source-depth: 1 source-branch: n6.1.1 plugin: autotools - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s autotools-configure-parameters: - --prefix=/usr - --libdir=/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR @@ -336,8 +330,6 @@ parts: source-depth: 1 source-tag: v0.11.1 plugin: cmake - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -376,8 +368,6 @@ parts: source-depth: 1 source-tag: 1.24.3 plugin: cmake - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -407,8 +397,6 @@ parts: source-depth: 1 source-tag: v30.2 plugin: cmake - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -431,7 +419,7 @@ parts: - qtwayland plugin: cmake build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -Wl,-push-state,-no-as-needed,-lhwy,-pop-state -s + - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -Wl,-push-state,-no-as-needed,-lhwy,-pop-state cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -460,8 +448,6 @@ parts: source-depth: 1 source-tag: v0.2 plugin: autotools - build-environment: - - CFLAGS: -O2 -s autotools-configure-parameters: - --prefix=/usr - --libdir=\${exec_prefix}/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR @@ -487,8 +473,6 @@ parts: source-depth: 1 source-commit: 51743dfd01dff6179e2d8f7095729caa4e2222e9 plugin: cmake - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release @@ -504,8 +488,6 @@ parts: source-depth: 1 source-commit: 62321fd7128ab2650b459d4195781af8185e46b5 plugin: cmake - build-environment: - - LDFLAGS: ${LDFLAGS:+$LDFLAGS} -s cmake-generator: Ninja cmake-parameters: - -DCMAKE_BUILD_TYPE=Release From e070af31638acf77ac651cc56a5fd98eecf4d572 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sun, 20 Jul 2025 14:24:32 +0000 Subject: [PATCH 015/341] Limit malloc_trim to once per second --- .../platform/linux/integration_linux.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/platform/linux/integration_linux.cpp b/Telegram/SourceFiles/platform/linux/integration_linux.cpp index f36bfb6326..1a5e3b6903 100644 --- a/Telegram/SourceFiles/platform/linux/integration_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/integration_linux.cpp @@ -176,7 +176,18 @@ LinuxIntegration::LinuxIntegration() QObject::connect( QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, - [] { malloc_trim(0); }); + [] { + static auto timer = [] { + QElapsedTimer timer; + timer.start(); + return timer; + }(); + + if (timer.hasExpired(1000)) { + malloc_trim(0); + timer.start(); + } + }); #endif // __GLIBC__ } From 4c049d0d756585d7f5ce994f18cc1275fad130c3 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 22 Jul 2025 07:57:10 +0000 Subject: [PATCH 016/341] Use Windows SDK version specified in build instruction --- .github/workflows/win.yml | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index 8964ebac77..8d7a603b71 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -4,6 +4,7 @@ on: push: paths-ignore: - 'docs/**' + - '!docs/building-win*.md' - '**.md' - 'changelog.txt' - 'LEGAL' @@ -22,6 +23,7 @@ on: pull_request: paths-ignore: - 'docs/**' + - '!docs/building-win*.md' - '**.md' - 'changelog.txt' - 'LEGAL' @@ -69,26 +71,34 @@ jobs: shell: bash run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV - - uses: ilammy/msvc-dev-cmd@v1.13.0 - name: Native Tools Command Prompt. - with: - arch: ${{ matrix.arch }} - - name: Clone. uses: actions/checkout@v4 with: submodules: recursive path: ${{ env.TBUILD }}\${{ env.REPO_NAME }} - - name: Set up environment paths. + - name: First set up. shell: bash run: | - echo "CACHE_KEY=$(sha256sum $TBUILD/$REPO_NAME/$PREPARE_PATH | awk '{ print $1 }')" >> $GITHUB_ENV + DOCPATH=$TBUILD/$REPO_NAME/docs/building-win.md + [ "${{ matrix.arch }}" != Win32 ] && DOCPATH=$TBUILD/$REPO_NAME/docs/building-win-${{ matrix.arch }}.md + SDK="$(grep "SDK version" $DOCPATH | sed -r 's/.*\*\*(.*)\*\* SDK version.*/\1/')" + echo "SDK=$SDK" >> $GITHUB_ENV + + echo "$(sha256sum $TBUILD/$REPO_NAME/$PREPARE_PATH | awk '{ print $1 }')" >> CACHE_KEY.txt + echo "$SDK" >> CACHE_KEY.txt + echo "CACHE_KEY=$(sha256sum CACHE_KEY.txt | awk '{ print $1 }')" >> $GITHUB_ENV echo "Configurate git for cherry-picks." git config --global user.email "you@example.com" git config --global user.name "Sample" + - uses: ilammy/msvc-dev-cmd@v1.13.0 + name: Native Tools Command Prompt. + with: + arch: ${{ matrix.arch }} + sdk: ${{ env.SDK }} + - name: NuGet sources. run: | nuget sources Disable -Name "Microsoft Visual Studio Offline Packages" From 3882690ee1d528655919286516245a2961a0c6a8 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 22 Jul 2025 10:54:06 +0300 Subject: [PATCH 017/341] Removed transcribe button from voice and round messages in admin log. --- .../SourceFiles/history/view/media/history_view_document.cpp | 1 + Telegram/SourceFiles/history/view/media/history_view_gif.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index bfaddd394a..2f0030cdec 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -420,6 +420,7 @@ QSize Document::countOptimalSize() { const auto transcribes = &session->api().transcribes(); if (_parent->data()->media()->ttlSeconds() || _realParent->isScheduled() + || _realParent->isAdminLogEntry() || (!session->premium() && !transcribes->freeFor(_realParent) && !transcribes->trialsSupport()) diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index ad561899ef..9e45c231da 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -2200,6 +2200,7 @@ void Gif::ensureTranscribeButton() const { if (_data->isVideoMessage() && !_parent->data()->media()->ttlSeconds() && !_parent->data()->isScheduled() + && !_parent->data()->isAdminLogEntry() && (_data->session().premium() || _data->session().api().transcribes().trialsSupport())) { if (!_transcribe) { From e6387738ce6f8b91938e59c1f6c2254f80838637 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 22 Jul 2025 13:00:07 +0300 Subject: [PATCH 018/341] Slightly improved style of top bar suggestions. --- Telegram/SourceFiles/dialogs/dialogs.style | 1 + .../dialogs/dialogs_top_bar_suggestion.cpp | 56 ++++++++++++------- .../ui/dialogs_top_bar_suggestion_content.cpp | 17 ++++-- .../ui/dialogs_top_bar_suggestion_content.h | 2 +- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index b3e2eceea0..219e7a14c9 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -825,6 +825,7 @@ dialogsSponsoredButton: DialogRightButton(dialogRowOpenBot) { margin: margins(0px, 9px, 10px, 0px); } +dialogsTopBarLeftPadding: 18px; dialogsTopBarSuggestionTitleStyle: TextStyle(defaultTextStyle) { font: font(semibold 12px); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp b/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp index b4f028eb12..90b31e5d67 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp @@ -80,6 +80,7 @@ rpl::producer*> TopBarSuggestionValue( struct State { TopBarSuggestionContent *content = nullptr; Ui::SlideWrap *wrap = nullptr; + rpl::variable leftPadding; rpl::variable desiredWrapToggle; rpl::variable outerWrapToggle; rpl::lifetime birthdayLifetime; @@ -92,6 +93,8 @@ rpl::producer*> TopBarSuggestionValue( const auto state = lifetime.make_state(); state->outerWrapToggle = rpl::duplicate(outerWrapToggleValue); + state->leftPadding = rpl::variable( + rpl::single(st::dialogsTopBarLeftPadding)); const auto ensureWrap = [=] { if (!state->content) { state->content = Ui::CreateChild( @@ -112,6 +115,15 @@ rpl::producer*> TopBarSuggestionValue( } }; + const auto setLeftPaddingRelativeTo = [=]( + not_null content, + not_null relativeTo) { + content->setLeftPadding(state->leftPadding.value( + ) | rpl::map([w = relativeTo->width()](int padding) { + return w + padding * 2; + })); + }; + const auto processCurrentSuggestion = [=](auto repeat) -> void { state->birthdayLifetime.destroy(); state->premiumLifetime.destroy(); @@ -126,7 +138,7 @@ rpl::producer*> TopBarSuggestionValue( const auto promo = &session->promoSuggestions(); if (const auto custom = promo->custom()) { content->setRightIcon(RightIcon::Close); - content->setLeftPadding(0); + content->setLeftPadding(state->leftPadding.value()); content->setClickedCallback([=] { const auto controller = FindSessionController(parent); UrlClickHandler::Open( @@ -150,7 +162,7 @@ rpl::producer*> TopBarSuggestionValue( } else if (session->premiumCanBuy() && promo->current(kSugPremiumGrace.utf8())) { content->setRightIcon(RightIcon::Close); - content->setLeftPadding(0); + content->setLeftPadding(state->leftPadding.value()); content->setClickedCallback([=] { const auto controller = FindSessionController(parent); UrlClickHandler::Open( @@ -187,7 +199,7 @@ rpl::producer*> TopBarSuggestionValue( return; } content->setRightIcon(RightIcon::Close); - content->setLeftPadding(0); + content->setLeftPadding(state->leftPadding.value()); content->setClickedCallback([=] { const auto controller = FindSessionController(parent); controller->uiShow()->show(Box( @@ -298,8 +310,6 @@ rpl::producer*> TopBarSuggestionValue( tr::now, TextWithEntities::Simple); content->setContent(std::move(title), std::move(text)); - const auto leftPadding - = st::defaultDialogRow.padding.left(); state->giftsLifetime.destroy(); if (!isSingle) { struct UserViews { @@ -348,11 +358,16 @@ rpl::producer*> TopBarSuggestionValue( s->inRow, st, 3); - content->setLeftPadding(leftPadding - + (users.size() * st.size - st.shift)); + const auto v = int(users.size() * st.size + - st.shift); + content->setLeftPadding( + state->leftPadding.value( + ) | rpl::map([v](int padding) { + return padding * 2 + v; + })); } p.drawImage( - leftPadding, + state->leftPadding.current(), (widget->height() - (s->userpics.height() / style::DevicePixelRatio())) / 2, @@ -368,15 +383,17 @@ rpl::producer*> TopBarSuggestionValue( st::uploadUserpicButton)); const auto fake = ptr->get(); fake->setAttribute(Qt::WA_TransparentForMouseEvents); - content->sizeValue() | rpl::filter_size( - ) | rpl::start_with_next([=](const QSize &s) { + rpl::combine( + state->leftPadding.value(), + content->sizeValue() | rpl::filter_size() + ) | rpl::start_with_next([=](int p, const QSize &s) { fake->raise(); fake->show(); fake->moveToLeft( - leftPadding, + p, (s.height() - fake->height()) / 2); }, fake->lifetime()); - content->setLeftPadding(fake->width() + leftPadding); + setLeftPaddingRelativeTo(content, fake); } state->desiredWrapToggle.force_assign( @@ -386,7 +403,7 @@ rpl::producer*> TopBarSuggestionValue( } else if (promo->current(kSugSetBirthday.utf8()) && !Data::IsBirthdayToday(session->user()->birthday())) { content->setRightIcon(RightIcon::Close); - content->setLeftPadding(0); + content->setLeftPadding(state->leftPadding.value()); content->setClickedCallback([=] { const auto controller = FindSessionController(parent); Core::App().openInternalUrl( @@ -461,7 +478,7 @@ rpl::producer*> TopBarSuggestionValue( }; if (isPremiumAnnual || isPremiumRestore || isPremiumUpgrade) { content->setRightIcon(RightIcon::Arrow); - content->setLeftPadding(0); + content->setLeftPadding(state->leftPadding.value()); const auto api = &session->api().premium(); api->statusTextValue() | rpl::start_with_next([=] { for (const auto &o : api->subscriptionOptions()) { @@ -485,16 +502,17 @@ rpl::producer*> TopBarSuggestionValue( &controller->window(), Ui::UserpicButton::Role::ChoosePhoto, st::uploadUserpicButton); - const auto leftPadding = st::defaultDialogRow.padding.left(); - content->sizeValue() | rpl::filter_size( - ) | rpl::start_with_next([=](const QSize &s) { + rpl::combine( + state->leftPadding.value(), + content->sizeValue() | rpl::filter_size() + ) | rpl::start_with_next([=](int padding, const QSize &s) { upload->raise(); upload->show(); upload->moveToLeft( - leftPadding, + padding, (s.height() - upload->height()) / 2); }, content->lifetime()); - content->setLeftPadding(upload->width() + leftPadding); + setLeftPaddingRelativeTo(content, upload); upload->chosenImages() | rpl::start_with_next([=]( Ui::UserpicButton::ChosenImage &&chosen) { if (chosen.type == Ui::UserpicButton::ChosenType::Set) { diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.cpp index 40d70b2bc2..d6db29a927 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.cpp @@ -66,9 +66,14 @@ void TopBarSuggestionContent::draw(QPainter &p) { const auto r = Ui::RpWidget::rect(); p.fillRect(r, st::historyPinnedBg); + p.fillRect( + r.x(), + r.y() + r.height() - st::lineWidth, + r.width(), + st::lineWidth, + st::shadowFg); Ui::RippleButton::paintRipple(p, 0, 0); - const auto leftPadding = st::defaultDialogRow.padding.left() - + _leftPadding; + const auto leftPadding = _leftPadding; const auto rightPadding = 0; const auto topPadding = st::msgReplyPadding.top(); const auto availableWidthNoPhoto = r.width() @@ -189,9 +194,11 @@ void TopBarSuggestionContent::setHideCallback(Fn hideCallback) { _rightHide->setClickedCallback(std::move(hideCallback)); } -void TopBarSuggestionContent::setLeftPadding(int value) { - _leftPadding = value; - update(); +void TopBarSuggestionContent::setLeftPadding(rpl::producer value) { + std::move(value) | rpl::start_with_next([=](int padding) { + _leftPadding = padding; + update(); + }, lifetime()); } const style::TextStyle & TopBarSuggestionContent::contentTitleSt() const { diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.h b/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.h index 8297e37074..50923025e3 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_top_bar_suggestion_content.h @@ -39,7 +39,7 @@ public: void setHideCallback(Fn); void setRightIcon(RightIcon); - void setLeftPadding(int); + void setLeftPadding(rpl::producer); [[nodiscard]] const style::TextStyle &contentTitleSt() const; From c90c53c878d4b3e8b2188b1e668d43747c409cba Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 22 Jul 2025 12:43:24 +0300 Subject: [PATCH 019/341] Aligned first tab of slider in dialogs widget to main menu button. --- Telegram/SourceFiles/dialogs/dialogs.style | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index 219e7a14c9..40af906830 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -731,7 +731,7 @@ dialogsTabsScroll: ScrollArea(defaultScrollArea) { barHidden: true; } dialogsSearchTabs: SettingsSlider(defaultSettingsSlider) { - padding: 8px; + padding: 9px; height: 33px; barTop: 30px; barSkip: 0px; From 9149792846be18fd3658403bebf92673716440a7 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 22 Jul 2025 13:00:56 +0300 Subject: [PATCH 020/341] Aligned collapsed rows for folders to main menu button. --- Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index 924b7c0f4d..81b5a20269 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -1245,7 +1245,8 @@ void PaintCollapsedRow( + st::dialogsUnreadFont->ascent; const auto left = context.narrow ? ((context.width - st::semiboldFont->width(text)) / 2) - : context.st->padding.left(); + : st::dialogsTopBarLeftPadding; + // : context.st->padding.left(); p.drawText(left, textBaseline, text); } else { folder->paintUserpic( From 2a15faf12e9b2affac2a284c56c47da9596d27a0 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 22 Jul 2025 15:55:01 +0300 Subject: [PATCH 021/341] Fixed incorrect display of no-chats label in dialogs while search mode. --- Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 0961fe2850..2cbe2d23f0 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -4083,7 +4083,7 @@ void InnerWidget::refreshEmpty() { _empty->setVisible(_state == WidgetState::Default); if (_emptyList) { _emptyList->setVisible(_state == WidgetState::Default); - _empty->setVisible(!_emptyList->isVisible()); + _empty->setVisible(false); } if (_emptyButton) { _emptyButton->setVisible(_state == WidgetState::Default); From 15706a7af825aa85b3eb499dc9667418f6b67a8e Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 22 Jul 2025 16:02:36 +0300 Subject: [PATCH 022/341] Fixed ability to use PageDown/PageUp in section for pinned messages. --- .../SourceFiles/history/view/history_view_pinned_section.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index 446d957617..3330001bc7 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -176,6 +176,11 @@ PinnedWidget::PinnedWidget( onScroll(); }, lifetime()); + _inner->scrollKeyEvents( + ) | rpl::start_with_next([=](not_null e) { + _scroll->keyPressEvent(e); + }, lifetime()); + setupClearButton(); setupTranslateBar(); Window::SetupSwipeBackSection(this, _scroll.get(), _inner); From 133effef0e9fa11d4e72b95dd2bd95ffc932d0ca Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 22 Jul 2025 16:36:35 +0300 Subject: [PATCH 023/341] Added sound notification when recording of group call is started. --- Telegram/Resources/qrc/telegram/sounds.qrc | 1 + .../sounds/group_call_recording_start.mp3 | Bin 0 -> 17616 bytes Telegram/SourceFiles/calls/calls_instance.cpp | 2 ++ .../calls/group/calls_group_call.cpp | 4 ++++ .../SourceFiles/calls/group/calls_group_call.h | 2 ++ .../calls/group/calls_group_panel.cpp | 1 + 6 files changed, 10 insertions(+) create mode 100644 Telegram/Resources/sounds/group_call_recording_start.mp3 diff --git a/Telegram/Resources/qrc/telegram/sounds.qrc b/Telegram/Resources/qrc/telegram/sounds.qrc index d9f7cf8b5a..1ffc48b052 100644 --- a/Telegram/Resources/qrc/telegram/sounds.qrc +++ b/Telegram/Resources/qrc/telegram/sounds.qrc @@ -10,5 +10,6 @@ ../../sounds/group_call_connect.mp3 ../../sounds/group_call_end.mp3 ../../sounds/group_call_allowed.mp3 + ../../sounds/group_call_recording_start.mp3 diff --git a/Telegram/Resources/sounds/group_call_recording_start.mp3 b/Telegram/Resources/sounds/group_call_recording_start.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0060e82c3737b9fefb3d3cc59a240cfdcf458f54 GIT binary patch literal 17616 zcmdS>WmuF^*9Ht<6AVL2cRRG;(1;*Iw{&-RNeUuEN(xev(%s$N0*cZpB8`9w2!b## zKKFM&&(H7I`{UimF~@aH?6uZj`&{RaYp=mvr$B-KKgGb&&HnBu_wHT~06=ycz{Vyg zXJlk&XXoP+6O)lqQ&ZE`H8*!~@bK_>{yZckDk>^5F+Dvux45{ts;Z%(y}hrmZ)9X* zVtRUdZfSZpI=;DUS3^YUtizc+}>g^ce*T9rPSmE zcpr&AgAD%HLO~`392Eh8&i>gUMmNau-!J~Zdc|B9-T5CZ0awx(M*=GOj?{<&4x&GS z4|UGaT=qyd;q*QzfQCbt-T1*DBY}B4S0ZMr01p)G1re`9I+_T3BP_O;sc|E$Y8#e& zBcuK{@HTIV=sn~_bKs*FKkoN7XlCLT;1$L zhrJTbAAU8ak}Ib$xXmh|0D=dON72=Ju-ps#mJt0h9`c6|)OXvsOLeb|FH%Hy6QIU? zj6}hD-4EHX{1?wFP=S#B~CRu%2g{;o^Vz&wk7#aOm|-{GR+~ndw2pF^vkq4 z$t2lW6e#rMPu>Z`1N&5I<};1f-WWH?b^r#nr|RK{>xv#qkyuaRa% zKFx6D0K8QE&B(R;#Bk==N59gCqJLbvT7re2!?ds(et4?;9JzJq)C6XZRu{7^DmD3I}S$8S(bni2~Rxi8|Hco3PHp4%_iL> zHh|8<^4t+|fSNT#KBx)};V3H|ZO#Kc|12F}WLXPs#_bWjVO47=oX#Wf*Q-&imu8hA z2Cw09ZEmC@3s_pFM;_ug;l1!N!V&ukJCD#?kv({0Vj=#RsA1&geJtj)kBppO`f~F5 zK&kRoLsh#pq!e@sb-{I#{vq=o*`2V4x~+KUnB%I>&;-dP@`z`izHjv8ZN)waE0$pg z&itOetuHAYba5K3qqTeaGXt(AT=D6r52>-+yN??};=U_1_=+tdjO(8p$hH6mt79(9wpLq-mj194}Vj=UnG8mPr1Uj|G8T>}9PizsYtAe?_Ca;8>ENUfzT=`7 zBSF>ALfKWW4);bf_U{cxD>3w}+qnld-d%5IABYY!jkXk9+pj9sJ}S(`ToeHS)|&Dc z{WzRFhVu;0hI_oX<|HKCFO(o;-0ZSiGAG2g?@@AOv{Jn7Y+Sr;EW%@NPp>U2`E!)_ z#AKqWna4iCYc#{}&f70ijnjTLzf-PO9pt{xsV2OCS9^_@+))fPBXF&VBT^KxmtOyV zsAN+mS(H9J+%inuGPQD$P(y>pO+E(9v`6)sJAK0n**6Wmi7n^R(4|k>e^G)P&;3^E zt*F4qy*&_}my@VY(j$C`G*mBEAZ_lAM3pk{)>qzIyV;=1-UfRov$OGBM;B!t;+Pqu z^wDR`&{kiTblV+wRlr) zdzE-+q1w4oL-!-=1pXs4JrI_(!t2PeyfSYw8e$S_$^HLQKQF)T|N8|D0H|fJ#TiaV z2>4WQOBKcXuu#s=BwcwXi4Ai-1SN#Z?pkQfM5UoCE3XJVx0i_wL&V)2D+eC2@5HY) z`|Dsct8ASj+Z6qOBuwGd^cXBv@>Dw=WiI($T+DSq+<g~%MSrh^P<@IGk^^$w|8BwyjC*U@wqsXzX#bQ+p`Ua(hD8sw_nq#;Z|jIGn} z!}6S6KFP8cX``v#!BNoCyHFh-6>h42@Lm;;1^~Dm`<2e1CZMBd%kU^xri27e5wwP0 zsvKzgsQi?X_2Q$<#$u=jz?$pYM#nnnq`N7(nb9o&;B!!&dP0j%b8e@}4}K z#b%#>aj}cpu#lQmJd2PhvI;D#v%5~QZM18i^SdzM(=D&m$|r68-F7#cJ z|LL3ZM0u+B63I-S7sjY`C8ewymr%l;4av4TA~Tz6u$%v0=f1wE+7|I}D8$2`pjD1B z7Qx=0LTD<9sX8k*=?5^2P}E{>sYX8AZ(FdEW@1K9f-zU|L!JlQ6@AmgH zk6vqfd#Q5cOY=JFQp|M|lo61%w$ON-ne-zDPwB!-&5S(Sk>CB9%79AMuG)NVy031; z(xLxWlZH?Ep_NW|4n+zEvza+|R3Za{rZcIm*J|YHbYs@L1L?#bNjrQW6G}^(Jwgc~ z_VQ<&bd7RSwJK3PIO(~%ifc~G4Z0Q~Ktb@qF?cW(`ii`OI*Kmx`2K~N9jk1&Vn}~w zc^BRsh0}$Kt+wCxuU7%B76*@17e08Id$pM=Sq%Pc3-IDz_`b}WxmLcqD1)`e`6*j3 z`$^L5ZSUJ~jjy#OdMwmAx#ywdSF@S3@12xt4s~+?kNBz>T(_DCpf5hBtlW35+u8^TNBQdDwH)xU!Y=aY@WhzUEvnp6`{4OQfiewxwpWDnzI%W0$}2a2FjX zS4)2Mc2aFm!}QZ~(;!oV1A^5g157HJa2gr@75%qQNoSxhrA-6>`{Yw@H>!u)Nb>`f zO^BRm*foith>@c-@_jKqPqq8?`JZ3;8c@-I3C^h0zaH-egm33ZGoG!L!kO3emo=3H zPUhw(Tuc}S$158XLbQc#_U{|zu+-Tse|HLXq(_Q~zgYZvN=~ZY2u+zDX*~YEqsMg* zCtlvCy(a$rDnfg`8DIe&{o^+?2*GHt7yp#a$w!y*nTA%`V;BhwX$rN<)w|-zuCU}7Lj`}V zCmJ@ILJ{g|WU!PkMu97GF-pP|5IPlhfu(F?JZ z0K2c`q$?&;O_PJwm=w`W3So%JUOjZL4q)LEq)Abyzx2ETz)}(oDJ^th>CLaPhRiWm z9tPN&djuE0_7>Z^Cd9JE_9awpc)adR4nD>Doyq6UzR%NW1_}Lwih_o)A|E`RUb!-4 ztvMA?@Uvgnk(p=PJlDaTRH@0v>{r?X^a&-eu3|Bm+isAqSBp=6HQUp?B%02LH93Bm zG9CRnfQaSoPoS_KPDn<9Pu~+KOA?x=Tp{_xWlO3}M4x#~Zc)*~=)s%TI8qY&!748{kkRExp;Cj`pEljzt1odQhX(9pbKgg$P#l+lgnNfALxFOF|0QoxGhKMrb~YOJjX zRo|YkHpgF%>HOn2`lul>Bekr^Nc1bt_D0XjEsZ&Q;p39TQ1_A&wWDr-x(5@^)ndM^ ze)P5xv zDBNQ!sa7qbJo#H?#1Q=J%^C0E{u|yw64Vd4>gEE;^>$weIUK zK#dd%5HPupyjAkPcZ6$B;b4CA?eE6ZH!)vs`LLd`uS|Y1=xGh?G{j+VnpP zh-GcTP{s3^8!zWxSwH#nLva#;kE(;8EHDYW{`4(M6a^tC$wb@5g^NfisFZ;c_?g%b z8=E?k&fK3wAfiYA@I#6}6lXp~+nMy^l~Q}5&(XlWZF^yNH`@Wn5<9isLc_>8P#4|v z_f0cY?9C7VJOf7bgD7AhYoV5%O6!I#IK z7%jXN(qs))ypx`8WvW)QRxZ@q<~35107nAtBhAfStLZ{{V?{|qx^7=QKkMJkcFC}{ zZYjuF&}h!^{Q7pSpB0vQR1(s=n}RnZMKy^(7%n(i)Iyc}kmEAMtuWho79r~h_g-~- zdJJ-IX`qaTo!lp2W#Lh3hq&(?*Oc~vD!lZUTS-uvDZ6tUZ3tLA<7qtjQrFMk)USYz zK$oqtGus9~ZNlE>r-fK%$yE0ztp(2mr?alUXkx>elFf5CN~aG_kB^*A9Q3D&L#Vdl z67F}u39u=qfJY@lwZT!*!}>S8&&->{%HK`uYO!nDkmhOPw}CtrdrGxUNg>6B_x0o( zXaqH$zi2wtZti`_DreU!K#7WQU{a!OcGT9Ih>`k?!R*KMv-+vI%5=LZ&~{wiEq@66 z(t^V_-$eozTo$7Dfx@7G0vIR8Eqa-49@g*1EK z2@Po?^Bw*r*^cv*U4f(573D~pZO(0DQQKUH$Y0Cx4`y%{X*BnXAOGcLaWhfFHmteG zc1i?o9`fs7RP^77uZ)~JtgL56F&s+JtR(B$5)fM{8k8>*M#ZKqS8#n1M69>NTyy~d zCuD!6SQQGW;s9~Tf8!%|)DW$q+Dz5!#Pt1guRu>;qH=*d{K$pcu-Q%>b+r+x-BeG# zyN8mltHV8QZZBgKdK%fGU@M3e^uwmB(K~Vr;AS*wO5-eX9d8)yz6lo0kUL#tXr6Na z*7YP1>+Q7;Yj-By{M3S20OloYjQUOCHz71^vWTJCGLN=AFMk*X0c6;;0v zIdeODE-u>B}W#4yz4TQNJms-V668k(-&tYiL_X3hIFdlSW>PO zYB$W%q`1C)ixmXX+sZ{huP3`V}o23Z8_Z6Z^$ERI4bU z@8j6i6cdNo(0d$R`433k6Dwp5k~`PFk#3 zksZTFnLShIYU(BmAAcUcQ1JNh(hu_y<9}4b%`ykY=VtiJ#u*$322Vbuj6YZ-XeN() z0G0vlekABn-_=J1ruW;r#Rsw>QP1lkS3#*zBHIQDWgQG>~aid=}A%((ZuL7@Ngjyl8SWykhJhMPqa;S z9joo(%$&>gO}n?=-xhOi@-125@(}l>^}3L@8~!ozrWs#0(S@+syXD5Vi^!cHyAj5L zhkd``+i40XE@Xk+x0L&wx`uK$nmJsMVq?KrF}WIv^s@NPt$r6 z)-3@ZH+Ial{5AJt_M@|Y6enL?3r|ahs5?U)m(Ex=szn|E2rWpUFzkLYo0jq&DJeD! zH%Olaj%&`sKYk;^A4-%{&02}Md^euq6{v1TY)LHW*6lgKbARU!KaU)@-&6q{a^XZ_ zZEQ?73}iDFPI4MqYpG5pBWEId3QkR?#RK;r@{oiHcz8T8dpFhf;53pzc9_4sy}~9x ziv*@Hn)cA}jpEU9H$u5@ay%tQ^?6+AcC{l@!MP%g27~oCSl@1yh=*ian8E%vWsRrWX3lf~T7qt@P{zumQpmqpUvz4y zdU-e^AFaQA(ERZC>PHv-(e1JOEW|?k!8O)%LJ$5#^0l)G>V!Tw8Yb&)l8whH9+(Zz z>5ZU1X&%yftX}&VGWS-YfR<43Z1s7U%kenj_1Bde)1l=#l4s9b`<{?m(HOqZ_CKq~l=IbMqKKWtLLh`P0&iFw zy=A-z&`f=%+@zWlZ;fpsvUoqT&hh|_sF)X7F83;YnWiU3B;+EO#2%$S899bH*g+}i zT$Zn|(2cD^(#xR`)~BDO^o?p-AN=rfGFQHm4SLnN1aRig+e)yGfOk_YXR_kGVIPMc zc6xkI{q*+Bun!*OEf0)~c;(#lM$u5R4-N*AAz2zZC;57u!l-|=@Pnrv?t6x$9n?$H zEP9ej5<)_Ug^8^6Ihx{HI9R?@%oi_?+jGA>{*tQFaNr&ZG3Zve_IFQ;H!i3)d$%K2 z>Hd%3xZ;M|WG87~E~2wJ{)FA(Q&WPJ*X?Lqnzw*8ej&4L+a%-NoU3zc?cBn*E|Exs zR4MJzd(|qh>-!xKny>Zidb=w9;Le>RrO!H*K3ue!e|&E5h4KGcH}=WdtT56XN9?|L zVDLs~-ZUW*=n-1coXUW&KJrqR3IsCP1M>?i_|Wen-bjU$e4sM2PQMpIU2fv!ndsqD zM!@B9Ij^^Yvu~{CyOV`@%|Aa5A|pvOx(PnnE09QXos4ll_e2pGlAS&@e%3Q`qIx*N zs9FAJH8lC?xVl1gf!sN|eLF$2;+5{JglJFU#;w?Dt+Z47V`IDd)kUWIP`Q-ifeEZo zgt`d`G8br!6w7_DlGj<2n9=NEar*27|z%XlcZFc#WyxWcI6peQ14 zBwf@tb)ruvGxf83Wx?>3%gG7#!hGiEV@3;K5W~ZuF{rt32qYTaZz(#8M%;R;nxeU> zhr`fldWWVlm?8llAh$fP6^@-qjrBd$e7|8&ee%6RC`b1t{h{m&O+Sd<%RcH2cCqL< z3@m0@BFrEm>wY6~zCgTiV$;m;mPr5OB`TlT{>TIO3?iT7m7cl*->&)7n(0goFV_yq zso3qN@QZmoN!BPuN_UNFB7>ehE&zLZGC|_VJZ3S9Gd3Ffd$ptp zsQ$=5{E*=f8Oo_-tvuIA9Lw-}zLP-gO3wR_-+1YYr;fzS#8jV_&8=4xoWnk0LE@Bz zGhzb=c%SM|BI>MRae-IX!4Gp+NXOdZE3{a%UU008@G*3ZJaO#3m5=%I=i@B7po12+J=dp*ud}ME*O**Ud_^~H;n0E11m#Up>n(aA9y~^w$ z?pbn*r#x}s<*T zN%SSMgrMWI@rlsN%EA3rtAJ%XV}-0?QYABAUikuWxONh6`Y@BBtZ8rl3>gghX-2w& zf7fV``X7GaaYMzj6Ipls6QaNw=BLiB{*@f*{)D)Ih<=A)cR-LSPT|+j;AR~Mbm}G3qzJ6nv4Tym+i#XzXj~^mxNnvhb=MvW6z@>^{@%HGf8pXT zejRCGSpT70f9hV_AAgLYRV&RsejO@8Al-wV{(dCQA~Vg8jjvG<1L1noDEw-CTUyN$ zDl6Z};*b(wo~LI6@a_Z1cP+?S^aan7RhjDNclR;49Ut%lN>t1`&O(zpSvrpN)|?%y zRfDdcKkSaNGTuGeaYaf`Om4QMy=&;}VIcBBeG@mM8ASA6VQSwVU4=EsO9hAa!7RW~ zd5DyeHAT}769{I(0>PRJ$kV6c7Dqu?Q2oW+5BrGt`uiEFG9SEx?RlAH==RlEKd(Li zj*_|@$xI^1_m4^c;puRUC)`vuJE=s!x$-9=gUg6*r$XL?kw(>!-6)#%v+?|R!G%|u z&-clgr;+Ei{NlaSZyFQ_yqNdO2*6<3zPTrplp#aX;OM8H+48lMhf#cNK$+NsbTBf5 z2fzJ0X!=ug-|A%Q>UF2{uIkYnXC{qdZaxvC6$6bym)N!g2mdCpvz+#!x&K>(Ipj`M z!EqrulsJh@OKrwbKvxH^Le4vb%(49GizQtq)iI;lRF!msElM&DS<{ywHH|WVYHU)4 z9Gw1a(H}n^{KF3}{@`oTN!m&mtAJgcfB3ogVi)PoT3{xogE zq#KHj((SOAjuDS&vEEfkuX^O?#-}-|wJk!b&1EqLLpH!mSs9#GDFS=WIQ@m zv{2_{FWoV+H}}#Fg#0bUUO5NTEnwdY{}uG9Wx))8ld|j)s87O^^`2Q+5X^$< z(&C@Pz#IG)2;z~)`%#uiLV1t{mr(@7`H25s0X^8eIx+?g?wW*zSRkKd&3sSDerCxN z2$$m*%OZI5DCr;#%a1si+PEG$(ic_RCYn)DG0RS#YpBafuMe@1aWn``-&y;&?luP^gU+n#%!#-E4&br3+s)w%{h zruvmYL4ZlVmN}p2tOzvfZxZ6!nrAxfzFx0)U7@+nCH|0qMKb@+pnB(mxz()WZa1N` zG7c+Jb{bA((bwSkI?{pZnMFE~!{^{;%DE3W`)ll>UB#gYiDWNJlaYi~0T?Jwj3Ysm`bnz(yunbM^9pEM}-tu}F5% zz}Qg!?^1Bz7!C(+m1YpbBrMb)pLOC~C!cWGEgDUNFEAWLc=@8tP|{*BnkWwb{&L}P zeENR38jq~wVO(@r=|~9G2v=^iL$(z%y$qX*9|%F;J;Cf;Rov4Ef>Scix?n>$bUg-{ z_;ULhMX1V6p9Hrmma3Ci)O=krd0?X9N|qe(LB-zwp{bsPc;=TcZSz4onFjdcmz; zVNX@_L_%UH-tL9f+pDHo8oCu2bBKUKrto{P((mBA6A^R3K^DLPC}y|F0&*T1CrgPXErS>vuKzv2vmKzCjOoo0kvMu%kw)i%MD zcy**4VBn84NjT&%I0hnrO_%>h)+2QKNkULKU&6<2T4c09|4#CC4qk+hm~4cZ_bgfH zPpg~vfpfDR8!tKaeZH48Rv)*1@2TwgqHUOJvmlm>!QA9@s4*G>W-LTtGEfo_jODcIioT_$Am(6 zlk}fdKW_bb>u1B~D(=rtS^9sfW+4BW|)kU%=v&+@3i_!Db1E{sL`fh?L#cy@2+N` zXgkwqHo#GTDH3oj*gA6l%6shu%s4MYmXN%5)cn_Nv`pvS zsfTPYO*W80tI94l+y6iOA14#Tt4zD{+{hnm>3*O(FVPJ# zi(3z0NJ5$|{ktw7tXSVXT&dj<)@`X2%LXwZF_Kcx9rd7HhDP`t9-ZZ#MCX5Aq!6s5 zNeZHm`RIDkI~cdIjhk5h?de3E6%Xfm#SGQe<>*B||2^8tP^a-@gP9#MmA@FZ_2b)t zr;HBME{dT{pfDgY75VOIGXCAJTqGz@ibce163l3A(Bkd(*O*^B{SHL5;?&;~_hvp6wQS8jR9Bw)!uK;M)jl<-1h4yp zgue-3b3~vkT|IblhkpC3HS@)36r2i%G$7}*agreY{K&d zhJiytsrUm-5}#e)MC3Xq`CdO&CECLfIz_K~-wfUF7pzApAN=4G_mBDW0`}<3(khjw zQ5x^C0rB@Q-qeESJZyAzHr`LgW-GW&*_^~a&mgN+=4LU*oFA~8Rsv1+F$-5hVA9Wd z5MrGXpi~lesXp>95^ae^^KP8Xj>o$UJ03`>;*5gGP50XgRm!j7|DgKfwES-Ix+(zE zAj?y;HdJ*r{O#ozf*pYUD)F)gYulH7*?q@?RBhzxSDlI36w&ns*-+N$?U@>c_Z@$nZC)Ji&8gG>&+& zyI2W(6Xj83)!r9G+@B>>OvPQHcr5r!WD0vC*VO&+A3yNo52o{u->qK^tnD5N_^ETL zA%{8K9gFinr`Zr3iMRRoxL3vVY4@^w=9Sw3lhs3%K5pN1SagEQ!1Bcak@!G=-&$|f zLWsv~0t7DSA2bxQj}3|k)nk|TW4BOp1UI|!J_F&Jt0;V#dQjQ(Y>PeY!yQF*{fR|< zsy$6U6b%V*`*C;?^ks9dCuk(&qU%ryGi8#JlYEvOUund|`qNDn=+o%SqgVCSgbt%< z)u_SWd(}Jt-VP2y6jNlv^OhYGwG^tSnypOdx$fOVeM@<&!AS3u8a759BZSmNloz?V z<&b?6wQ{rju9(qG>cgy^zg{L7m18c!Y)RB+bMfTL+em312_OJ8n$3a%`)(hr#g^sU zjv(l@t3DOe_wvL#d-8QA8sk4&bTfSe!32_IAHMbT7P-mUm-E+rIsRF>dJ;EVNa-w# zIqpvA3J&bb!RMiC!i4cWuR*U%(tYJ&vu9%|Pgn zEq@mAqPj=8Z-c|SE^zt$10#R-aQ|WbvgT!O&USNpR9A??1e+X=Hev40-||Jxi1H~v z?s#rsVLLA4_mEpnu#wI6&$oQvG+VXrT~$_TwvHOk8lW}xIwB6s#ZXW04!29QK!B(N zms92yzRFx`r|XLmt*w&%6(18*mZ2{%|E#Lxl7iiMzt29ABj}ODjDsooROVmsJuYdE zbuzz*aTaU#BD~!HRBMj)xqLgrSfSU^)B>RNrXjKz+EFpEw&;U#T54E`L-VG=E6p=28sr)!%|*rTq`Oe z%XM%G@1JElq-y<(FDm?jD;}jRQ-@3E;S5qgbzVZ7UWB{jwq-MgEy11tMQLNJXEnW3 z>10nKgDH*#EQ#oLHNFOQY1iozN-0V>fL#>^!l*i?aIlUFSQup1+ zJ95A68m4}C-EV-ryWpM>>RG)U778}ceev; z2vP_}9rC3HXp{AQ5pV+!%*$p3KdNcy!-2QFj_DfNqHJ4QvZQgaO`lp0SlzKs5N^0a zIB`a%%P^tz^c;{v*c9$BZ`(1W)_&W`!TOVdQ-zu+OiMpk%4O z@7w%2^eRrhKm7d!Tj}KU-@nscVja(aZHyZQSyPA5OgHxiIXze&Kcb_y(w3yl)H{j0 z3&Fc-icreF2B=vD*=I3?OxeNq{`w<@{0DLw_kjW-fSz?6&(|zx4q*`%maERHxN#Wi zuGPNm9_^fmnzHL7`#D`zcK^i}6MT^6!TYSc__D$JbKj3!oWP=)?Zh$SYY>HP{P()< z8EW@Qy;e?SW1Q2`be2ePrn%%g`F_R8`Zq)^DHFB)K`dDSfrtZIf!M+zU4n!EqZaO< zg{L)<=wmohd;A9=Oo^FET6uuU0w?^Jx=sZ@q40NXtXy-X-3T2ckUdV~sU*tN&}+~7 zYUd-D`7$1Z<4pG>3g*Kyr#;#0nz8%xc9V@Uoug7Tp;@VkASYQSGA8gTpfQF_bRNV{ z>;ZUKiHejOb>h{B=Le`ib=xF<;RHtZGW_1c z+m|?ATP%G_YkKv%zMkXS{L1WE@=*eF?}IEiUa{}5roEhIJLUlk&J<;^HLzh(5hjOr zBA4T#3Va-b@XJ*EL#9ENr^C6xFO{So%w8z#>%p@*^s4QbT}S-7`J~Z} z8PzXgmI(SaRIeiF!HNdR2N8u59g*_7`JirqP3w>ssou6V#m5X3Ta)a0_?+>)&s9+# zwQ{9=n62FE-w>yG%9)MhI)J$;FxW0i#jIyEVrCnyvHhjjSR1u@kB?k+h+hWbI$Hv4 zi5t*FkOq`z5=nX1r^6|Q17+6wxoCId!r4&oSRyZ4D1;8b>Wf9kA_yAuOX}u3oea5} z0Gw3=;0F^e71=ACM6beh|H$VB4wedOo-fM-qpp+6AYpHtd>xc*#g2m-`r2XNqbXV| zr77Q>mzi4$DxZJ@fW@aV;iIOV{pw^(FQhM~afOJ$X0(uYW1xC#Y(mfnYg z_SXXoN`0R+>d2jfq!~CSowOh$;#2yK~ z<4?}Gf!(|DarwEC{&ogwASW*&Q6r7J%S68~h0WCL>+Fv6tZ$@W5nq2q*<3M!Gw=bb zG9nN-ynk48k}l*s*8p!rl;cifhipSW`5qxHR7Y5_RiaMKHzmsXaw7Z1URv|?x+is3 z8UdW#Pa;dTN%JBk%~M;SmZ6 zae+eMa5bSf4i!(R`IwDBp;nAxVqou0jl)Bw@aL+$%bj|yH-4c8n9(ogD|Iu{J1>q; zcTGxAJksJSU5!)gfnO5T&Dp7kVfq-1z}>X(Y^s{(Xu)t8 z1)iO|^5hg7KmXPw&14UgvfG)u}sj?KN%`j~hV>f~iP_Xm-M(4fRb01(8Ugn`kcLAr6AA(wsPuzmnYJaR3O z^a^KEEc;wmNQwLr`Op6p@MQW2V_C~wm&y?t3O+2wxMPiM$J@4+)@g|N)x54r#eMhX z=&wO@6aM<0A4d#M^}1C~bsmHUJYyJ@Op&L4`t5+`%vP4GqJ!Ul;VATKjt&)#+lln*k$)0`+g(&i;E8Y*e+{ggJ1x0{#>g#XLY6|SeX2Ulw&s{ z)0vW75P*{k;tO1!l~x9y~i^LbPk^rwGXc>b37!A zCKO$su)o?q>Kq>fjHWfAoxFWk90dz0RZ>01pt2(`*vf%1Mv;=cY4}} zd4RkovYs|YpP6@BASfHvt;xYx>WR7bhLRH`y`xdm?yxkF{`N@33!fYNhcm)$Kf>ac z0HL;8*A=w2L6)=pHr{!*xRS%uQ}EBo>CI+8dhGx#@l`JL!+Ga_6fa=%fO2mO5V?EW zo=5s2HtKMRobtMzsaAmzy!76(yRkZ>#cjS3oP<}%5i^RRNluB7bzV-a8n$d{Qt z+RkvAGs#|Vl?$Q(G^J1<13mgZF2iY&zMIdS#EM{AR%fnBM8=jE!q1kdsEdx10>5hY zlxb<77E%th zOQqPEVQ8Rg4gcn)#0xKSWUjHX?WZ8H;T$hs1T^i^tIV)7i^nV)EN$bbCZPesFSd8B zbsj#SPt?`jCQy_(cn~boM~OhVDvHO{{+p|mYfT! zai-m6d4Ns#Ql9LOS!h107PfOI4Mm$C%cw?fznzm)T($N%c#wR~+#HYj4ir`e4M|PVMA50GJJvXPh32pB-|O0SSU-~TNTk;Y_$U@T zMcp?B@1)cB#1C2{02sV1H|8*yrT?_)CXnT|&M<()T?PTzw$b;;(ZjHz1)3CbBJz>q z+_=Gicq70f5vLfP$t3nbg~6{poC~qxrYtU=GWpoCMUL&v*>k#TQ{x?-7Gq$;;&$tg z*DjOMp^{_gX|zL66rK{ywZEc%5fef0ez*bf^_}^e@fmKP90Rlr80lrgB=6$_>G~c1*nK zQ2n9j*Vtm-khhPhDCW}}b1;}*ov#gGd0bAL z8>c@*9j?s!!?CZCC7DLNfzivE+uRtExV`T!sm#qFT+ z#QH@>1i143V?MipiP%q#Rxj9D9&~frAdTJ}85vkL%D{qPn*TKwgP8`H=$dexcN+1z zKw?@i2u>*8D77UNJ+x$9%n5+N zS_JNJR7eEa6fm*1klp(q|KN}aQjBW18yfIPKbP=4dW4;5%3S@m*kTD6ao!r8jho*% zx-J4%td-SsL+bRI^8K{0Owf6HVs~O0amor$NS^&)4FR7uRUETF>On4Mi2NyO z#?sdsQ&RUZ{Aoltc+X}=EnHbT(w=90kT^u8diXm3ufAL2XDC24{H+G-=Y_p4b_kfd zqAXwdXj(Tjs`C9nK7`xP*xb;9)$q*E6uWExf2(0`V*p?g*A)eTxDx6^rpKcm?vUeG zW3OvkVW%1Ad6lPv37GD-g%yo4*EUenXuf$$CFdkkQQpmc3D0;=`66TX>MpsBj90eA zErP3VA2u%$pAt=j|4)7y0FHXpa+fIRkmXGdOaJxM>W2fE%5dcG~sL%v!s5+CN54NvaVzG(e_Yf~NgU(8QNbWHX)LfUW7M;xjz#g6{8UX2u zejEYIKdz*5K#0u5xz7>0Vb>=|J4M3NTJ^7T(5))AcF<4%+Dj4r=88heIf2t(e3O&M zI*t?$H)d3I4MXSQ*)+FsZ2kQv|9_EtcoVDcga%~fvNQm|G)06D99K)jH_d0=8|j*S zZ;w4f<-L93*!s&*lGrN9%C!V(xV7cM|9R@_IQDC>1#_v74>h4*SE&bBkZkAUu>@z5 zgzA@rnM5dJUU(+A1>fEbUF1A_GqOuR>Uu|6|0%84Y+N7Er~=qdpK>9uh5`PZN8du_ zGB;xmPlHCt?DuT^V&;PnaN`tLevvF5A6x*$eD6B|fKpZgE?j$KJ2n{n?s>g86c_ZS zidgB;#Zgoiw0M_cNCFqsr?26MZA?dPHMf>ERpq;muHaX>VSjVe`L4(2q*bD_E~@=s zD=_CT>i{V7unqtynOgvyj8d*0L)<%_m!YO!H&s+JlX=M*DcnOez86c>ruC86l#AJw z@&8x(_Ugo|#yAs%$g9r-aL|W|@QJ2DRNgmP83G!ptN}F{Hg{5V(UGMAJI?(E#2=m2 zK11~Yh53s0Q)2qr;Qv}sz}?LiNOR8Sx&X4%xyp+g=Lne`Q8_YdsZi`*8GTTFDwAo8 zBzkv2?KqJ7-r=3b+F>~Dncna~D5XUAOY zK#4%aRTSgSE}9M^Qe#)Hhun}VKF(_7)<*m*R`DC8>^4NNe9Ub2WsJ%HQq*0#4In&+ z0)P*Lw~3J}a9kI}!K+`N&)VbL?KPMu)(&e zPvOXpxTox&O{Is#6Zvy>FV_|TiYD%00zBfy0Yg8!F#GhKQl(N#oF-#JU7~=ryte@z zi}-Y-Q6^@M(^k&`p(_Vt4S-@<8@SQ;$H!#!bv&N?nrLld^EM-IMi*e?ZnfnEru5=7 z{+duY-96tyK;aN%0j_c$l?D~H<@ieo9t0f6`2a0pVWIqrRRcQ(A3^GA)CU6Smo@-E zh@b0iO7@paqLG|4vfLB(^(c@;@l|3U!#jJ1sqd3;vuCLHhWk(s*0)ZgvU$UF@dKl} z;WE$L8UPdz$_=ec@|En0aF)X#b4>=t4nz9<)5}3c)ITl@!G?gwIN8t=C<`Gh*2Fy4 za4;~O>jyAv>^bel6pi%2NnTOa&m^DCz*^wiUmOks6Q;(;o<+H_HK3* z#GA(l6arMwLadIinj`;%g>H)4k5Om<#f_2zPra16`|x(`@ak1T_~U#yfCk7!w!-c@ z2f0B6KmePQf9=8v+Yp1Opa3F#EDIb101Ub#JT^3liAg`Ca11~|7XbX-f3o*5w<%Y_ zcQ;qRDtDsF@6vby01CUy@%dM(kW47u|G7KCjIF$kc}oNNpLciiNg_Ay{t5vAh~R{M zII2*vI~WRKM*%3N$AHZw0Ec2^Zkk)da{r&b4q{-8hG=>(EueF%K4VwAhx4)k2Brh- zV54sSdbx_hh9Atn^yQkY_<|cTAool5e^}3OQUYi`&jZO~ko$qv60r5Dz`&pi+^Eaq z0nz^R=d^P6s+1`w7l|@3LS1*o@YnpQ5y$^8RA6)joBLn&(~hY}WADs?IAjgTd^Nrg zbqps3faU|27XY1;&t$@^l>jl{fq`>RAO*XpLFOCteVEMPA;BPAA)p}f3Fv-C4yH>E w90@@8iyvUbx}O(lC@6e@oA4QcOp^v+6jEY70BO8~lK=n! literal 0 HcmV?d00001 diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index d79a317018..a04db8bdb7 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -164,6 +164,8 @@ void Instance::Delegate::groupCallPlaySound(GroupCallSound sound) { case GroupCallSound::Ended: return "group_call_end"; case GroupCallSound::AllowedToSpeak: return "group_call_allowed"; case GroupCallSound::Connecting: return "group_call_connect"; + case GroupCallSound::RecordingStarted: + return "group_call_recording_start"; } Unexpected("GroupCallSound in Instance::groupCallPlaySound."); }()); diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index 8663c534c3..6714d32fac 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -2685,6 +2685,10 @@ void GroupCall::emitShareScreenError(Error error) { _errors.fire_copy(error); } +void GroupCall::playSoundRecordingStarted() const { + _delegate->groupCallPlaySound(Delegate::GroupCallSound::RecordingStarted); +} + void GroupCall::setupOutgoingVideo() { using Webrtc::VideoState; diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index e727173cd3..a78d3ab258 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -205,6 +205,7 @@ public: Connecting, AllowedToSpeak, Ended, + RecordingStarted, }; virtual void groupCallPlaySound(GroupCallSound sound) = 0; virtual auto groupCallGetVideoCapture(const QString &deviceId) @@ -283,6 +284,7 @@ public: const QString &title, bool video, bool videoPortrait); + void playSoundRecordingStarted() const; [[nodiscard]] bool recordingStoppedByMe() const { return _recordingStoppedByMe; } diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index 3a40c36f49..f3d2c524ed 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -1175,6 +1175,7 @@ void Panel::subscribeToChanges(not_null real) { const auto isVideo = real->recordVideo(); if (recorded) { *startedAsVideo = isVideo; + _call->playSoundRecordingStarted(); } validateRecordingMark(recorded); uiShow()->showToast((recorded From 9b490c95525968105ce2827f0a3e930cd5d84481 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 17 Jul 2025 12:30:20 +0400 Subject: [PATCH 024/341] Fix unrelated stories on top. --- Telegram/SourceFiles/data/data_stories.cpp | 36 +++++++++++++++++----- Telegram/SourceFiles/data/data_stories.h | 6 +++- Telegram/SourceFiles/data/data_user.cpp | 12 ++++++++ Telegram/SourceFiles/data/data_user.h | 4 +++ 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 4c9f11d787..03732644eb 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -234,7 +234,7 @@ void Stories::apply(not_null peer, const MTPPeerStories *data) { _sourceChanged.fire_copy(peer->id); updatePeerStoriesState(peer); } else { - parseAndApply(*data); + parseAndApply(*data, ParseSource::DirectRequest); } } @@ -272,7 +272,7 @@ void Stories::requestPeerStories( const auto &data = result.data(); _owner->processUsers(data.vusers()); _owner->processChats(data.vchats()); - parseAndApply(data.vstories()); + parseAndApply(data.vstories(), ParseSource::DirectRequest); finish(); }).fail([=] { applyDeletedFromSources(peer->id, StorySourcesList::NotHidden); @@ -366,7 +366,9 @@ void Stories::clearArchive(not_null peer) { _archiveChanged.fire_copy(peerId); } -void Stories::parseAndApply(const MTPPeerStories &stories) { +void Stories::parseAndApply( + const MTPPeerStories &stories, + ParseSource source) { const auto &data = stories.data(); const auto peerId = peerFromMTP(data.vpeer()); const auto already = _readTill.find(peerId); @@ -420,9 +422,25 @@ void Stories::parseAndApply(const MTPPeerStories &stories) { } sort(list); }; - if (result.peer->isSelf() - || (result.peer->isChannel() && result.peer->asChannel()->amIn()) - || result.peer->isUser()) { + const auto appendToStrip = [](not_null peer, ParseSource source) { + if (peer->isSelf()) { + return true; + } else if (const auto channel = peer->asChannel()) { + return channel->amIn(); + } else if (const auto user = peer->asUser()) { + return (source == ParseSource::MyStrip) + || user->storiesCorrespondent() + || user->isServiceUser() + || user->isContact() + || user->isBot(); + } + return false; + }; + if (appendToStrip(result.peer, source)) { + if (source == ParseSource::MyStrip + && !appendToStrip(result.peer, ParseSource::DirectRequest)) { + result.peer->asUser()->setStoriesCorrespondent(true); + } const auto hidden = result.peer->hasStoriesHidden(); using List = StorySourcesList; add(hidden ? List::Hidden : List::NotHidden); @@ -617,7 +635,7 @@ void Stories::loadMore(StorySourcesList list) { _sourcesStates[index] = qs(data.vstate()); _sourcesLoaded[index] = !data.is_has_more(); for (const auto &single : data.vpeer_stories().v) { - parseAndApply(single); + parseAndApply(single, ParseSource::MyStrip); } }, [](const MTPDstories_allStoriesNotModified &) { }); @@ -1191,7 +1209,9 @@ void Stories::toggleHidden( && !peer->asUser()->isServiceUser(); const auto justRemove = (byHints || peer->isServiceUser()) && hidden; if (peer->hasStoriesHidden() != hidden) { - if (!justRemove) { + if (byHints && hidden) { + peer->asUser()->setStoriesCorrespondent(false); + } else if (!justRemove) { peer->setStoriesHidden(hidden); } session().api().request(MTPstories_TogglePeerStoriesHidden( diff --git a/Telegram/SourceFiles/data/data_stories.h b/Telegram/SourceFiles/data/data_stories.h index 4e6b0ce88d..2c0da0750c 100644 --- a/Telegram/SourceFiles/data/data_stories.h +++ b/Telegram/SourceFiles/data/data_stories.h @@ -267,8 +267,12 @@ private: int chat = 0; int viewer = 0; }; + enum class ParseSource : uchar { + MyStrip, + DirectRequest, + }; - void parseAndApply(const MTPPeerStories &stories); + void parseAndApply(const MTPPeerStories &stories, ParseSource source); [[nodiscard]] Story *parseAndApply( not_null peer, const MTPDstoryItem &data, diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index b3e979708c..308b1bb609 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -543,6 +543,18 @@ int UserData::starsPerMessage() const { return _starsPerMessage; } +void UserData::setStoriesCorrespondent(bool is) { + if (is) { + _flags.add(UserDataFlag::StoriesCorrespondent); + } else { + _flags.remove(UserDataFlag::StoriesCorrespondent); + } +} + +bool UserData::storiesCorrespondent() const { + return (_flags.current() & UserDataFlag::StoriesCorrespondent); +} + void UserData::setStarsPerMessage(int stars) { if (_starsPerMessage != stars) { _starsPerMessage = stars; diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index a47340132f..b8c87b67b3 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -121,6 +121,7 @@ enum class UserDataFlag : uint32 { HasStarsPerMessage = (1 << 23), MessageMoneyRestrictionsKnown = (1 << 24), ReadDatesPrivate = (1 << 25), + StoriesCorrespondent = (1 << 26), }; inline constexpr bool is_flag_type(UserDataFlag) { return true; }; using UserDataFlags = base::flags; @@ -188,6 +189,9 @@ public: [[nodiscard]] bool canSendIgnoreMoneyRestrictions() const; [[nodiscard]] bool readDatesPrivate() const; + void setStoriesCorrespondent(bool is); + [[nodiscard]] bool storiesCorrespondent() const; + void setStarsPerMessage(int stars); [[nodiscard]] int starsPerMessage() const; From 9b990728f64f142f7ca3ce8e45c147c1680f0733 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 15 Jul 2025 10:04:13 +0400 Subject: [PATCH 025/341] Update API scheme to layer 210. --- Telegram/SourceFiles/boxes/star_gift_box.cpp | 1 + .../components/recent_shared_media_gifts.cpp | 1 + .../peer_gifts/info_peer_gifts_widget.cpp | 2 ++ Telegram/SourceFiles/mtproto/scheme/api.tl | 24 ++++++++++++++----- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index 5ba5079c4f..0398ffbc91 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -1114,6 +1114,7 @@ void PreviewWrap::paintEvent(QPaintEvent *e) { MTPpayments_GetSavedStarGifts( MTP_flags(Flag::f_exclude_limited | Flag::f_exclude_unlimited), user->input, + MTP_int(0), // collection_id MTP_string(offset), MTP_int(kMyGiftsPerPage) )).done([=](const MTPpayments_SavedStarGifts &result) { diff --git a/Telegram/SourceFiles/data/components/recent_shared_media_gifts.cpp b/Telegram/SourceFiles/data/components/recent_shared_media_gifts.cpp index 87bccbd272..3d2442b2d4 100644 --- a/Telegram/SourceFiles/data/components/recent_shared_media_gifts.cpp +++ b/Telegram/SourceFiles/data/components/recent_shared_media_gifts.cpp @@ -49,6 +49,7 @@ void RecentSharedMediaGifts::request( MTPpayments_GetSavedStarGifts( MTP_flags(0), peer->input, + MTP_int(0), // collection_id MTP_string(QString()), MTP_int(kMaxGifts) )).done([=](const MTPpayments_SavedStarGifts &result) { diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp index 8fd731a9e5..68a79563f6 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp @@ -348,6 +348,7 @@ void InnerWidget::loadMore() { } using Flag = MTPpayments_GetSavedStarGifts::Flag; const auto filter = _filter.current(); + const auto collectionId = 0; _loadMoreRequestId = _api.request(MTPpayments_GetSavedStarGifts( MTP_flags((filter.sortByValue ? Flag::f_sort_by_value : Flag()) | (filter.skipLimited ? Flag::f_exclude_limited : Flag()) @@ -356,6 +357,7 @@ void InnerWidget::loadMore() { | (filter.skipSaved ? Flag::f_exclude_saved : Flag()) | (filter.skipUnsaved ? Flag::f_exclude_unsaved : Flag())), _peer->input, + MTP_int(collectionId), MTP_string(_reloading ? QString() : _offset), MTP_int(kPerPage) )).done([=](const MTPpayments_SavedStarGifts &result) { diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index c6e4c22b2c..6f84162365 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -248,7 +248,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason; inputReportReasonIllegalDrugs#a8eb2be = ReportReason; inputReportReasonPersonalDetails#9ec7863d = ReportReason; -userFull#99e78045 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings = UserFull; +userFull#29de80be flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings stars_rating:flags2.17?StarsRating = UserFull; contact#145ade0b user_id:long mutual:Bool = Contact; @@ -1890,8 +1890,8 @@ starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption; -starGift#7f853c12 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string released_by:flags.6?Peer = StarGift; -starGiftUnique#f63778ae flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector availability_issued:int availability_total:int gift_address:flags.3?string resell_stars:flags.4?long released_by:flags.5?Peer = StarGift; +starGift#bcff5b flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true require_premium:flags.7?true limited_per_user:flags.8?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string released_by:flags.6?Peer per_user_total:flags.8?int per_user_remains:flags.8?int = StarGift; +starGiftUnique#f63778ae flags:# require_premium:flags.6?true id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector availability_issued:int availability_total:int gift_address:flags.3?string resell_stars:flags.4?long released_by:flags.5?Peer = StarGift; payments.starGiftsNotModified#a388a368 = payments.StarGifts; payments.starGifts#2ed82995 hash:int gifts:Vector chats:Vector users:Vector = payments.StarGifts; @@ -1940,7 +1940,7 @@ payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector = payments.Uni messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector = messages.WebPagePreview; -savedStarGift#dfda0499 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long can_transfer_at:flags.13?int can_resell_at:flags.14?int = SavedStarGift; +savedStarGift#1ea646df flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long can_transfer_at:flags.13?int can_resell_at:flags.14?int collection_id:flags.15?Vector = SavedStarGift; payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector next_offset:flags.0?string chats:Vector users:Vector = payments.SavedStarGifts; @@ -1989,6 +1989,13 @@ todoCompletion#4cc120b7 id:int completed_by:long date:int = TodoCompletion; suggestedPost#e8e37e5 flags:# accepted:flags.1?true rejected:flags.2?true price:flags.3?StarsAmount schedule_date:flags.0?int = SuggestedPost; +starsRating#1b0e4f07 flags:# level:int current_level_stars:long stars:long next_level_stars:flags.0?long = StarsRating; + +starGiftCollection#9d6b13b0 flags:# collection_id:int title:string icon:flags.0?Document gifts_count:int hash:long = StarGiftCollection; + +payments.starGiftCollectionsNotModified#a0ba4f17 = payments.StarGiftCollections; +payments.starGiftCollections#8a2932f3 collections:Vector = payments.StarGiftCollections; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -2590,7 +2597,7 @@ payments.getStarGiftUpgradePreview#9c9abcb1 gift_id:long = payments.StarGiftUpgr payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = Updates; payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates; payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift; -payments.getSavedStarGifts#23830de9 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer offset:string limit:int = payments.SavedStarGifts; +payments.getSavedStarGifts#a319e569 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer collection_id:flags.6?int offset:string limit:int = payments.SavedStarGifts; payments.getSavedStarGift#b455a106 stargift:Vector = payments.SavedStarGifts; payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl; payments.toggleChatStarGiftNotifications#60eaefa1 flags:# enabled:flags.0?true peer:InputPeer = Bool; @@ -2598,6 +2605,11 @@ payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector offset:string limit:int = payments.ResaleStarGifts; payments.updateStarGiftPrice#3baea4e1 stargift:InputSavedStarGift resell_stars:long = Updates; +payments.createStarGiftCollection#1f4a0e87 peer:InputPeer title:string stargift:Vector = StarGiftCollection; +payments.updateStarGiftCollection#4fddbee7 flags:# peer:InputPeer collection_id:int title:flags.0?string delete_stargift:flags.1?Vector add_stargift:flags.2?Vector order:flags.3?Vector = StarGiftCollection; +payments.reorderStarGiftCollections#c32af4cc peer:InputPeer order:Vector = Bool; +payments.deleteStarGiftCollection#ad5648e8 peer:InputPeer collection_id:int = Bool; +payments.getStarGiftCollections#981b91dd peer:InputPeer hash:long = payments.StarGiftCollections; stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector software:flags.3?string = messages.StickerSet; stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet; @@ -2720,4 +2732,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool; fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo; -// LAYER 209 +// LAYER 210 From fee892f9a239c254a88158610a259ff41c0e4e7f Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 21 Jul 2025 10:49:42 +0400 Subject: [PATCH 026/341] Call completionHandler if open panel was cancelled. --- Telegram/lib_webview | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_webview b/Telegram/lib_webview index 04c45d069f..f0fddc6f74 160000 --- a/Telegram/lib_webview +++ b/Telegram/lib_webview @@ -1 +1 @@ -Subproject commit 04c45d069fc0088740b9637bc5da414ee82be198 +Subproject commit f0fddc6f7486a16c9941347817704fa520c82471 From ccb8c43961cfecbf69c439ae89af656a4be682b3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 21 Jul 2025 16:47:41 +0400 Subject: [PATCH 027/341] Support age verification for sensitive media. --- .../icons/settings/filled_verify_age.svg | 12 + Telegram/Resources/langs/cloud_lang.strings | 3 + Telegram/Resources/langs/lang.strings | 7 + .../SourceFiles/api/api_sensitive_content.cpp | 24 +- .../SourceFiles/api/api_sensitive_content.h | 4 + Telegram/SourceFiles/data/data_session.cpp | 3 + .../view/media/history_view_media_common.cpp | 336 +++++++++++++++--- .../inline_bots/bot_attach_web_view.cpp | 8 + .../inline_bots/bot_attach_web_view.h | 14 +- Telegram/SourceFiles/lang/lang_tag.cpp | 13 +- Telegram/SourceFiles/lang/lang_tag.h | 1 + Telegram/SourceFiles/main/main_app_config.cpp | 16 + Telegram/SourceFiles/main/main_app_config.h | 5 + Telegram/SourceFiles/settings/settings.style | 15 + .../ui/chat/attach/attach_bot_webview.cpp | 10 + .../ui/chat/attach/attach_bot_webview.h | 1 + 16 files changed, 416 insertions(+), 56 deletions(-) create mode 100644 Telegram/Resources/icons/settings/filled_verify_age.svg diff --git a/Telegram/Resources/icons/settings/filled_verify_age.svg b/Telegram/Resources/icons/settings/filled_verify_age.svg new file mode 100644 index 0000000000..2b13be56ca --- /dev/null +++ b/Telegram/Resources/icons/settings/filled_verify_age.svg @@ -0,0 +1,12 @@ + + + Filled / filled_verify_age + + + + + + + + + \ No newline at end of file diff --git a/Telegram/Resources/langs/cloud_lang.strings b/Telegram/Resources/langs/cloud_lang.strings index c7e33531c0..3776c023a4 100644 --- a/Telegram/Resources/langs/cloud_lang.strings +++ b/Telegram/Resources/langs/cloud_lang.strings @@ -13,6 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "cloud_lng_topup_purpose_subs" = "Buy **Stars** to keep your channel subscriptions."; +"cloud_lng_age_verify_about_gb#one" = "To access such content, you must confirm that you are at least **{count}** year old as required by UK law."; +"cloud_lng_age_verify_about_gb#other" = "To access such content, you must confirm that you are at least **{count}** years old as required by UK law."; + "cloud_lng_passport_in_ar" = "Arabic"; "cloud_lng_passport_in_az" = "Azerbaijani"; "cloud_lng_passport_in_bg" = "Bulgarian"; diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index cfeb51a1eb..0b988fb211 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -6756,6 +6756,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_frozen_text3" = "Appeal via {link} before {date}, or your account will be deleted."; "lng_frozen_appeal_button" = "Submit an Appeal"; +"lng_age_verify_title" = "Age Verification"; +"lng_age_verify_mobile" = "Please open this media in the official Telegram app for Android or iOS to verify your age."; +"lng_age_verify_here" = "This is a one-time process using your phone's camera. Your selfie will not be stored by Telegram."; +"lng_age_verify_button" = "Verify My Age"; +"lng_age_verify_sorry_title" = "Age Check Failed"; +"lng_age_verify_sorry_text" = "Sorry, you can't view 18+ content."; + "lng_context_bank_card_copy" = "Copy Card Number"; "lng_context_bank_card_copied" = "Card number copied to clipboard."; diff --git a/Telegram/SourceFiles/api/api_sensitive_content.cpp b/Telegram/SourceFiles/api/api_sensitive_content.cpp index 31f83f5eba..e1e25950e8 100644 --- a/Telegram/SourceFiles/api/api_sensitive_content.cpp +++ b/Telegram/SourceFiles/api/api_sensitive_content.cpp @@ -25,7 +25,7 @@ SensitiveContent::SensitiveContent(not_null api) } void SensitiveContent::preload() { - if (!_loaded) { + if (!_loaded && !_loadRequestId) { reload(); } } @@ -37,7 +37,6 @@ void SensitiveContent::reload(bool force) { } return; } - _loaded = true; _loadRequestId = _api.request(MTPaccount_GetContentSettings( )).done([=](const MTPaccount_ContentSettings &result) { _loadRequestId = 0; @@ -50,6 +49,10 @@ void SensitiveContent::reload(bool force) { _enabled = enabled; _canChange = canChange; } + if (!_loaded) { + _loaded = true; + _loadedChanged.fire({}); + } if (base::take(_appConfigReloadForce) || changed) { _appConfigReloadTimer.callOnce(kRefreshAppConfigTimeout); } @@ -61,6 +64,19 @@ void SensitiveContent::reload(bool force) { }).send(); } +bool SensitiveContent::loaded() const { + return _loaded; +} + +rpl::producer SensitiveContent::loadedValue() const { + if (_loaded) { + return rpl::single(true); + } + return rpl::single(false) | rpl::then( + _loadedChanged.events() | rpl::map_to(true) + ); +} + bool SensitiveContent::enabledCurrent() const { return _enabled.current(); } @@ -69,6 +85,10 @@ rpl::producer SensitiveContent::enabled() const { return _enabled.value(); } +bool SensitiveContent::canChangeCurrent() const { + return _canChange.current(); +} + rpl::producer SensitiveContent::canChange() const { return _canChange.value(); } diff --git a/Telegram/SourceFiles/api/api_sensitive_content.h b/Telegram/SourceFiles/api/api_sensitive_content.h index 576bf275f3..e35f8cbf46 100644 --- a/Telegram/SourceFiles/api/api_sensitive_content.h +++ b/Telegram/SourceFiles/api/api_sensitive_content.h @@ -26,12 +26,16 @@ public: void reload(bool force = false); void update(bool enabled); + [[nodiscard]] bool loaded() const; + [[nodiscard]] rpl::producer loadedValue() const; [[nodiscard]] bool enabledCurrent() const; [[nodiscard]] rpl::producer enabled() const; + [[nodiscard]] bool canChangeCurrent() const; [[nodiscard]] rpl::producer canChange() const; private: const not_null _session; + rpl::event_stream<> _loadedChanged; MTP::Sender _api; mtpRequestId _loadRequestId = 0; mtpRequestId _saveRequestId = 0; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index ec2569bf55..f3c306a350 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1399,6 +1399,9 @@ UserData *Session::userByPhone(const QString &phone) const { PeerData *Session::peerByUsername(const QString &username) const { const auto uname = username.trimmed(); + if (uname.isEmpty()) { + return nullptr; + } for (const auto &[peerId, peer] : _peers) { if (peer->isLoaded() && !peer->username().compare(uname, Qt::CaseInsensitive)) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp index b899d9fc98..b1e9eeb3ad 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_sensitive_content.h" #include "api/api_views.h" #include "apiwrap.h" +#include "inline_bots/bot_attach_web_view.h" #include "ui/boxes/confirm_box.h" #include "ui/layers/generic_box.h" #include "ui/text/format_values.h" @@ -18,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/checkbox.h" #include "ui/wrap/slide_wrap.h" #include "ui/painter.h" +#include "core/application.h" #include "core/click_handler_types.h" #include "data/data_document.h" #include "data/data_session.h" @@ -34,18 +36,77 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "history/history.h" #include "lang/lang_keys.h" +#include "lottie/lottie_icon.h" +#include "main/main_app_config.h" #include "main/main_session.h" #include "mainwindow.h" #include "media/streaming/media_streaming_utility.h" #include "payments/payments_checkout_process.h" #include "payments/payments_non_panel_process.h" +#include "settings/settings_common.h" +#include "webrtc/webrtc_environment.h" +#include "webview/webview_interface.h" #include "window/window_session_controller.h" #include "styles/style_chat.h" +#include "styles/style_layers.h" +#include "styles/style_settings.h" namespace HistoryView { namespace { constexpr auto kMediaUnlockedTooltipDuration = 5 * crl::time(1000); +const auto kVerifyAgeAboutPrefix = "cloud_lng_age_verify_about_"; + +rpl::producer AgeVerifyAbout( + not_null session) { + const auto appConfig = &session->appConfig(); + return rpl::single( + rpl::empty + ) | rpl::then( + Lang::Updated() + ) | rpl::map([=] { + const auto country = appConfig->ageVerifyCountry().toLower(); + const auto age = appConfig->ageVerifyMinAge(); + const auto [shift, string] = Lang::Plural( + Lang::kPluralKeyBaseForCloudValue, + age, + lt_count); + const auto postfixes = { + "#zero", + "#one", + "#two", + "#few", + "#many", + "#other" + }; + Assert(shift >= 0 && shift < postfixes.size()); + const auto postfix = *(begin(postfixes) + shift); + return Ui::Text::RichLangValue(u"To access such content, you must confirm that you are at least **{count}** years old as required by UK law."_q.replace(u"{count}"_q, string)); + return Ui::Text::RichLangValue(Lang::GetNonDefaultValue( + kVerifyAgeAboutPrefix + country.toUtf8() + postfix AssertIsDebug(test_this) + ).replace(u"{count}"_q, string)); + }); +} + +[[nodiscard]] object_ptr AgeVerifyIcon( + not_null parent) { + const auto padding = st::settingsAgeVerifyIconPadding; + const auto full = st::settingsAgeVerifyIcon.size().grownBy(padding); + auto result = object_ptr(parent); + const auto raw = result.data(); + raw->resize(full); + raw->paintRequest() | rpl::start_with_next([=] { + auto p = QPainter(raw); + const auto x = (raw->width() - full.width()) / 2; + auto hq = PainterHighQualityEnabler(p); + p.setBrush(st::windowBgActive); + p.setPen(Qt::NoPen); + const auto inner = QRect(QPoint(x, 0), full); + p.drawEllipse(inner); + st::settingsAgeVerifyIcon.paintInCenter(p, inner); + }, raw->lifetime()); + return result; +} } // namespace @@ -278,61 +339,246 @@ ClickHandlerPtr MakePaidMediaLink(not_null item) { }); } +void ShowAgeVerification( + std::shared_ptr show, + not_null bot, + Fn reveal) { + show->show(Box([=](not_null box) { + box->setNoContentMargin(true); + box->setStyle(st::settingsAgeVerifyBox); + box->setWidth(st::boxWideWidth); + + box->addRow(AgeVerifyIcon(box), st::settingsAgeVerifyIconMargin); + + box->addRow( + object_ptr( + box, + tr::lng_age_verify_title(), + st::settingsAgeVerifyTitle), + st::boxRowPadding + st::settingsAgeVerifyMargin); + box->addRow( + object_ptr( + box, + AgeVerifyAbout(&bot->session()), + st::settingsAgeVerifyText), + st::boxRowPadding + st::settingsAgeVerifyMargin); + box->addRow( + object_ptr( + box, + tr::lng_age_verify_here(Ui::Text::RichLangValue), + st::settingsAgeVerifyText), + st::boxRowPadding + st::settingsAgeVerifyMargin); + + const auto weak = QPointer(box); + const auto done = crl::guard(&bot->session(), [=](int age) { + const auto min = bot->session().appConfig().ageVerifyMinAge(); + if (age >= min) { + reveal(); + bot->session().api().sensitiveContent().update(true); + } else { + show->showToast({ + .title = tr::lng_age_verify_sorry_title(tr::now), + .text = tr::lng_age_verify_sorry_text(tr::now), + .duration = Ui::Toast::kDefaultDuration * 3, + }); + } + if (const auto strong = weak.data()) { + strong->closeBox(); + } + }); + const auto button = box->addButton(tr::lng_age_verify_button(), [=] { + bot->session().attachWebView().open({ + .bot = bot, + .context = { .maySkipConfirmation = true }, + .source = InlineBots::WebViewSourceAgeVerification{ + .done = done, + }, + }); + }); + box->widthValue( + ) | rpl::start_with_next([=](int width) { + const auto &padding = st::settingsAgeVerifyBox.buttonPadding; + button->resizeToWidth(width + - padding.left() + - padding.right()); + button->moveToLeft(padding.left(), padding.top()); + }, button->lifetime()); + })); +} + +void ShowAgeVerificationMobile( + std::shared_ptr show, + not_null session) { + show->show(Box([=](not_null box) { + box->setTitle(tr::lng_age_verify_title()); + box->setWidth(st::boxWideWidth); + + const auto size = st::settingsCloudPasswordIconSize; + auto icon = Settings::CreateLottieIcon( + box->verticalLayout(), + { + .name = u"phone"_q, + .sizeOverride = { size, size }, + }, + st::peerAppearanceIconPadding); + + box->showFinishes( + ) | rpl::start_with_next([animate = std::move(icon.animate)] { + animate(anim::repeat::once); + }, box->lifetime()); + + box->addRow(std::move(icon.widget)); + + box->addRow( + object_ptr( + box, + AgeVerifyAbout(session), + st::settingsAgeVerifyText), + st::boxRowPadding + st::settingsAgeVerifyMargin); + box->addRow( + object_ptr( + box, + tr::lng_age_verify_mobile(Ui::Text::RichLangValue), + st::settingsAgeVerifyText), + st::boxRowPadding + st::settingsAgeVerifyMargin); + + box->addButton(tr::lng_box_ok(), [=] { + box->closeBox(); + }); + })); +} + +void ShowAgeVerificationRequired( + std::shared_ptr show, + not_null session, + Fn reveal) { + struct State { + Fn check; + rpl::lifetime lifetime; + std::optional bot; + }; + const auto state = std::make_shared(); + const auto username = session->appConfig().ageVerifyBotUsername(); + const auto bot = session->data().peerByUsername(username); + if (username.isEmpty() || bot) { + state->bot = bot; + } else { + session->api().request(MTPcontacts_ResolveUsername( + MTP_flags(0), + MTP_string(username), + MTPstring() + )).done([=](const MTPcontacts_ResolvedPeer &result) { + const auto &data = result.data(); + session->data().processUsers(data.vusers()); + session->data().processChats(data.vchats()); + const auto botId = peerFromMTP(data.vpeer()); + state->bot = session->data().peerLoaded(botId); + state->check(); + }).fail([=] { + state->bot = nullptr; + state->check(); + }).send(); + } + state->check = [=] { + const auto sensitive = &session->api().sensitiveContent(); + const auto ready = sensitive->loaded(); + if (!ready) { + state->lifetime = sensitive->loadedValue( + ) | rpl::filter( + rpl::mappers::_1 + ) | rpl::take(1) | rpl::start_with_next(state->check); + return; + } else if (!state->bot.has_value()) { + return; + } + const auto has = Core::App().mediaDevices().recordAvailability(); + const auto available = Webview::Availability(); + const auto bot = (*state->bot)->asUser(); + if (available.error == Webview::Available::Error::None + && has == Webrtc::RecordAvailability::VideoAndAudio + && sensitive->canChangeCurrent() + && bot + && bot->isBot() + && bot->botInfo->hasMainApp) { + ShowAgeVerification(show, bot, reveal); + } else { + ShowAgeVerificationMobile(show, session); + } + state->lifetime.destroy(); + state->check = nullptr; + }; + state->check(); +} + +void ShowSensitiveConfirm( + std::shared_ptr show, + not_null session, + Fn reveal) { + show->show(Box([=](not_null box) { + struct State { + rpl::variable canChange; + Ui::Checkbox *checkbox = nullptr; + }; + const auto state = box->lifetime().make_state(); + const auto sensitive = &session->api().sensitiveContent(); + state->canChange = sensitive->canChange(); + const auto done = [=](Fn close) { + if (state->canChange.current() + && state->checkbox->checked()) { + show->showToast({ + .text = tr::lng_sensitive_toast( + tr::now, + Ui::Text::RichLangValue), + .adaptive = true, + .duration = 5 * crl::time(1000), + }); + sensitive->update(true); + } else { + reveal(); + } + close(); + }; + Ui::ConfirmBox(box, { + .text = tr::lng_sensitive_text(Ui::Text::RichLangValue), + .confirmed = done, + .confirmText = tr::lng_sensitive_view(), + .title = tr::lng_sensitive_title(), + }); + const auto skip = st::defaultCheckbox.margin.bottom(); + const auto wrap = box->addRow( + object_ptr>( + box, + object_ptr( + box, + tr::lng_sensitive_always(tr::now), + false)), + st::boxRowPadding + QMargins(0, 0, 0, skip)); + wrap->toggleOn(state->canChange.value()); + wrap->finishAnimating(); + state->checkbox = wrap->entity(); + })); +} + ClickHandlerPtr MakeSensitiveMediaLink( ClickHandlerPtr reveal, not_null item) { const auto session = &item->history()->session(); + session->api().sensitiveContent().preload(); + return std::make_shared([=](ClickContext context) { + const auto plain = [reveal, context] { + reveal->onClick(context); + }; const auto my = context.other.value(); const auto controller = my.sessionWindow.get(); const auto show = controller ? controller->uiShow() : my.show; if (!show) { - reveal->onClick(context); - return; + plain(); + } else if (session->appConfig().ageVerifyNeeded()) { + ShowAgeVerificationRequired(show, session, plain); + } else { + ShowSensitiveConfirm(show, session, plain); } - show->show(Box([=](not_null box) { - struct State { - rpl::variable canChange; - Ui::Checkbox *checkbox = nullptr; - }; - const auto state = box->lifetime().make_state(); - const auto sensitive = &session->api().sensitiveContent(); - state->canChange = sensitive->canChange(); - const auto done = [=](Fn close) { - if (state->canChange.current() - && state->checkbox->checked()) { - show->showToast({ - .text = tr::lng_sensitive_toast( - tr::now, - Ui::Text::RichLangValue), - .adaptive = true, - .duration = 5 * crl::time(1000), - }); - sensitive->update(true); - } else { - reveal->onClick(context); - } - close(); - }; - Ui::ConfirmBox(box, { - .text = tr::lng_sensitive_text(Ui::Text::RichLangValue), - .confirmed = done, - .confirmText = tr::lng_sensitive_view(), - .title = tr::lng_sensitive_title(), - }); - const auto skip = st::defaultCheckbox.margin.bottom(); - const auto wrap = box->addRow( - object_ptr>( - box, - object_ptr( - box, - tr::lng_sensitive_always(tr::now), - false)), - st::boxRowPadding + QMargins(0, 0, 0, skip)); - wrap->toggleOn(state->canChange.value()); - wrap->finishAnimating(); - state->checkbox = wrap->entity(); - })); }); } diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 70901ecd7f..36e907923f 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -931,6 +931,8 @@ void WebViewInstance::resolve() { requestMain(); }); } + }, [&](WebViewSourceAgeVerification) { + requestMain(); }); } @@ -1997,6 +1999,12 @@ void WebViewInstance::botDownloadFile( }).send(); } +void WebViewInstance::botVerifyAge(int age) { + if (v::is(_source)) { + v::get(_source).done(age); + } +} + void WebViewInstance::botOpenPrivacyPolicy() { const auto bot = _bot; const auto weak = _context.controller; diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h index 442cc3fc78..e7fe7f281e 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h @@ -163,6 +163,16 @@ struct WebViewSourceBotProfile { WebViewSourceBotProfile) = default; }; +struct WebViewSourceAgeVerification { + Fn done; + + friend inline bool operator==( + WebViewSourceAgeVerification, + WebViewSourceAgeVerification) { + return true; + } +}; + struct WebViewSource : std::variant< WebViewSourceButton, WebViewSourceSwitch, @@ -173,7 +183,8 @@ struct WebViewSource : std::variant< WebViewSourceAttachMenu, WebViewSourceBotMenu, WebViewSourceGame, - WebViewSourceBotProfile> { + WebViewSourceBotProfile, + WebViewSourceAgeVerification> { using variant::variant; }; @@ -291,6 +302,7 @@ private: Ui::BotWebView::SetEmojiStatusRequest request) override; void botDownloadFile( Ui::BotWebView::DownloadFileRequest request) override; + void botVerifyAge(int age) override; void botOpenPrivacyPolicy() override; void botClose() override; diff --git a/Telegram/SourceFiles/lang/lang_tag.cpp b/Telegram/SourceFiles/lang/lang_tag.cpp index 02620f2e1d..5136a67a5e 100644 --- a/Telegram/SourceFiles/lang/lang_tag.cpp +++ b/Telegram/SourceFiles/lang/lang_tag.cpp @@ -1004,14 +1004,11 @@ PluralResult Plural( const auto t = f; const auto useNonDefaultPlural = (ChoosePlural != ChoosePluralDefault) - && Lang::details::IsNonDefaultPlural(keyBase); - const auto shift = (useNonDefaultPlural ? ChoosePlural : ChoosePluralDefault)( - (integer ? i : -1), - i, - v, - w, - f, - t); + && (keyBase == kPluralKeyBaseForCloudValue + || Lang::details::IsNonDefaultPlural(keyBase)); + const auto shift = (useNonDefaultPlural + ? ChoosePlural + : ChoosePluralDefault)((integer ? i : -1), i, v, w, f, t); if (integer) { const auto round = qRound(value); if (type == lt_count_short) { diff --git a/Telegram/SourceFiles/lang/lang_tag.h b/Telegram/SourceFiles/lang/lang_tag.h index 40f3ef9972..3d0f231186 100644 --- a/Telegram/SourceFiles/lang/lang_tag.h +++ b/Telegram/SourceFiles/lang/lang_tag.h @@ -38,6 +38,7 @@ struct PluralResult { int keyShift = 0; QString replacement; }; +inline constexpr auto kPluralKeyBaseForCloudValue = ushort(-1); PluralResult Plural( ushort keyBase, float64 value, diff --git a/Telegram/SourceFiles/main/main_app_config.cpp b/Telegram/SourceFiles/main/main_app_config.cpp index b65c104555..ea8561669e 100644 --- a/Telegram/SourceFiles/main/main_app_config.cpp +++ b/Telegram/SourceFiles/main/main_app_config.cpp @@ -208,6 +208,22 @@ TimeId AppConfig::suggestedPostAgeMin() const { return get(u"stars_suggested_post_age_min"_q, 86400); } +bool AppConfig::ageVerifyNeeded() const { + return get(u"need_age_video_verification"_q, false); +} + +QString AppConfig::ageVerifyCountry() const { + return get(u"verify_age_country"_q, QString()); +} + +int AppConfig::ageVerifyMinAge() const { + return get(u"verify_age_min"_q, 18); +} + +QString AppConfig::ageVerifyBotUsername() const { + return get(u"verify_age_bot_username"_q, QString()); +} + void AppConfig::refresh(bool force) { if (_requestId || !_api) { if (force) { diff --git a/Telegram/SourceFiles/main/main_app_config.h b/Telegram/SourceFiles/main/main_app_config.h index a2ea65f426..c5ba22ee40 100644 --- a/Telegram/SourceFiles/main/main_app_config.h +++ b/Telegram/SourceFiles/main/main_app_config.h @@ -102,6 +102,11 @@ public: [[nodiscard]] int suggestedPostDelayMax() const; [[nodiscard]] TimeId suggestedPostAgeMin() const; + [[nodiscard]] bool ageVerifyNeeded() const; + [[nodiscard]] QString ageVerifyCountry() const; + [[nodiscard]] int ageVerifyMinAge() const; + [[nodiscard]] QString ageVerifyBotUsername() const; + void refresh(bool force = false); private: diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index b153dbe371..70dded5edc 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -705,3 +705,18 @@ settingsCreditsButton: SettingsButton(settingsButton) { } settingsButtonIconGift: icon {{ "settings/gift", menuIconColor }}; settingsButtonIconEarn: icon {{ "settings/earn", menuIconColor }}; + +settingsAgeVerifyBox: Box(filterInviteBox) { + buttonPadding: margins(24px, 24px, 24px, 24px); +} +settingsAgeVerifyText: FlatLabel(defaultFlatLabel) { + minWidth: 200px; + align: align(top); +} +settingsAgeVerifyMargin: margins(0px, 6px, 0px, 6px); +settingsAgeVerifyTitle: FlatLabel(boxTitle) { + align: align(top); +} +settingsAgeVerifyIcon: icon {{ "settings/filled_verify_age-48x48", windowFgActive }}; +settingsAgeVerifyIconPadding: margins(16px, 16px, 16px, 16px); +settingsAgeVerifyIconMargin: margins(0px, 24px, 0px, 14px); diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index 526dceceed..525bc4eb05 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -1011,6 +1011,16 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) { secureStorageFailed(arguments); } else if (command == "web_app_secure_storage_clear") { secureStorageFailed(arguments); + } else if (command == "web_app_verify_age") { + const auto passed = arguments["passed"]; + const auto detected = arguments["age"]; + const auto valid = passed.isBool() + && passed.toBool() + && detected.isDouble(); + const auto age = valid + ? int(std::floor(detected.toDouble())) + : 0; + _delegate->botVerifyAge(age); } else if (command == "share_score") { _delegate->botHandleMenuButton(MenuButton::ShareGame); } diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h index 72edb0b391..63b11fc624 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h @@ -105,6 +105,7 @@ public: virtual void botDownloadFile(DownloadFileRequest request) = 0; virtual void botSendPreparedMessage( SendPreparedMessageRequest request) = 0; + virtual void botVerifyAge(int age) = 0; virtual void botOpenPrivacyPolicy() = 0; virtual void botClose() = 0; }; From 427487c5988f4726de6e5720f5dc19ec47efe61e Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 21 Jul 2025 17:03:36 +0400 Subject: [PATCH 028/341] Verify age in sensitive toggle settings. --- .../view/media/history_view_media_common.cpp | 12 +++++++++++ .../view/media/history_view_media_common.h | 13 ++++++++++++ .../settings/settings_privacy_security.cpp | 21 +++++++++++++++---- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp index b1e9eeb3ad..ef939886d6 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp @@ -403,6 +403,18 @@ void ShowAgeVerification( - padding.right()); button->moveToLeft(padding.left(), padding.top()); }, button->lifetime()); + + const auto close = Ui::CreateChild( + box.get(), + st::boxTitleClose); + close->setClickedCallback([=] { + box->closeBox(); + }); + box->widthValue( + ) | rpl::start_with_next([=](int width) { + close->moveToRight(0, 0); + }, box->lifetime()); + crl::on_main(close, [=] { close->raise(); }); })); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_common.h b/Telegram/SourceFiles/history/view/media/history_view_media_common.h index 03646372f5..be8fdba808 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_common.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media_common.h @@ -19,10 +19,18 @@ namespace Data { class Media; } // namespace Data +namespace Main { +class Session; +} // namespace Main + namespace Media::Streaming { struct ExpandDecision; } // namespace Media::Streaming +namespace Ui { +class Show; +} // namespace Ui + namespace HistoryView { class Media; @@ -75,6 +83,11 @@ void PaintInterpolatedIcon( int newWidth, int maxWidth); +void ShowAgeVerificationRequired( + std::shared_ptr show, + not_null session, + Fn reveal); + [[nodiscard]] ClickHandlerPtr MakePaidMediaLink( not_null item); [[nodiscard]] ClickHandlerPtr MakeSensitiveMediaLink( diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index 4c1910297e..fcc1d3fd5c 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/self_destruction_box.h" #include "core/application.h" #include "core/core_settings.h" +#include "history/view/media/history_view_media_common.h" #include "ui/chat/chat_style.h" #include "ui/effects/premium_graphics.h" #include "ui/effects/premium_top_bar.h" @@ -971,7 +972,9 @@ void SetupSensitiveContent( Ui::AddSkip(inner); Ui::AddSubsectionTitle(inner, tr::lng_settings_sensitive_title()); + const auto show = controller->uiShow(); const auto session = &controller->session(); + const auto disable = inner->lifetime().make_state>(); std::move( updateTrigger @@ -982,13 +985,23 @@ void SetupSensitiveContent( inner, tr::lng_settings_sensitive_disable_filtering(), st::settingsButtonNoIcon - ))->toggleOn( - session->api().sensitiveContent().enabled() - )->toggledChanges( + ))->toggleOn(rpl::merge( + session->api().sensitiveContent().enabled(), + disable->events() | rpl::map_to(false) + ))->toggledChanges( ) | rpl::filter([=](bool toggled) { return toggled != session->api().sensitiveContent().enabledCurrent(); }) | rpl::start_with_next([=](bool toggled) { - session->api().sensitiveContent().update(toggled); + if (toggled && session->appConfig().ageVerifyNeeded()) { + disable->fire({}); + + HistoryView::ShowAgeVerificationRequired( + show, + session, + [] {}); + } else { + session->api().sensitiveContent().update(toggled); + } }, container->lifetime()); Ui::AddSkip(inner); From 62aec345071565bd37db0c2f62caf8a93e9990b5 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 22 Jul 2025 12:05:44 +0400 Subject: [PATCH 029/341] Fix crash in official verify age bot open. --- .../SourceFiles/history/view/media/history_view_media_common.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp index ef939886d6..0e6ead19c7 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp @@ -389,6 +389,7 @@ void ShowAgeVerification( const auto button = box->addButton(tr::lng_age_verify_button(), [=] { bot->session().attachWebView().open({ .bot = bot, + .parentShow = box->uiShow(), .context = { .maySkipConfirmation = true }, .source = InlineBots::WebViewSourceAgeVerification{ .done = done, From 4b85c9e2df4bdcf0f40534c2eddb3e6ad8a2133d Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 22 Jul 2025 12:06:00 +0400 Subject: [PATCH 030/341] Add spoilers to shared GIFs. --- .../info/media/info_media_provider.cpp | 11 ++ .../SourceFiles/overview/overview_layout.cpp | 154 ++++++++++++++++-- .../SourceFiles/overview/overview_layout.h | 18 +- 3 files changed, 164 insertions(+), 19 deletions(-) diff --git a/Telegram/SourceFiles/info/media/info_media_provider.cpp b/Telegram/SourceFiles/info/media/info_media_provider.cpp index 88f47bc755..14553f7958 100644 --- a/Telegram/SourceFiles/info/media/info_media_provider.cpp +++ b/Telegram/SourceFiles/info/media/info_media_provider.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/media/info_media_list_section.h" #include "info/info_controller.h" #include "layout/layout_selection.h" +#include "main/main_app_config.h" #include "main/main_session.h" #include "lang/lang_keys.h" #include "history/history.h" @@ -59,6 +60,16 @@ Provider::Provider(not_null controller) layout.second.item->invalidateCache(); } }, _lifetime); + + _controller->session().appConfig().ignoredRestrictionReasonsChanges( + ) | rpl::start_with_next([=](std::vector &&changed) { + const auto sensitive = Data::UnavailableReason::Sensitive(); + if (ranges::contains(changed, sensitive.reason)) { + for (auto &[id, layout] : _layouts) { + layout.item->maybeClearSensitiveSpoiler(); + } + } + }, _lifetime); } Type Provider::type() { diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index af3317ca02..c80ffec3e5 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_components.h" #include "history/history_item_helpers.h" #include "history/view/history_view_cursor_state.h" +#include "history/view/media/history_view_media_common.h" #include "history/view/media/history_view_document.h" // DrawThumbnailAsSongCover #include "base/unixtime.h" #include "ui/effects/round_checkbox.h" @@ -98,6 +99,27 @@ constexpr auto kStoryRatio = 1.46; } } +void PaintSensitiveTag(Painter &p, QRect r) { + auto text = Ui::Text::String(); + text.setText( + st::semiboldTextStyle, + tr::lng_sensitive_tag(tr::now)); + const auto width = text.maxWidth(); + const auto inner = QRect(0, 0, width, text.minHeight()); + const auto outer = style::centerrect(r, inner.marginsAdded(st::paidTagPadding)); + const auto size = outer.size(); + const auto radius = std::min(size.width(), size.height()) / 2; + auto hq = PainterHighQualityEnabler(p); + + p.setPen(Qt::NoPen); + p.setBrush(st::radialBg); + p.drawRoundedRect(outer, radius, radius); + p.setPen(st::radialFg); + text.draw(p, { + .position = outer.marginsRemoved(st::paidTagPadding).topLeft(), + }); +} + } // namespace class Checkbox { @@ -327,18 +349,21 @@ Photo::Photo( MediaOptions options) : ItemBase(delegate, parent) , _data(photo) -, _link(std::make_shared( - photo, - crl::guard(this, [=](FullMsgId id) { - clearSpoiler(); - delegate->openPhoto(photo, id); - }), - parent->fullId())) -, _spoiler(options.spoiler ? std::make_unique([=] { - delegate->repaintItem(this); -}) : nullptr) +, _spoiler((options.spoiler || parent->isMediaSensitive()) + ? std::make_unique([=] { + delegate->repaintItem(this); + }) + : nullptr) +, _sensitiveSpoiler(parent->isMediaSensitive() ? 1 : 0) , _pinned(options.pinned) -, _story(options.story) { +, _story(options.story) +, _link(_sensitiveSpoiler + ? HistoryView::MakeSensitiveMediaLink( + std::make_shared(crl::guard(this, [=] { + maybeClearSensitiveSpoiler(); + })), + parent) + : makeOpenPhotoHandler()) { if (_data->inlineThumbnailBytes().isEmpty() && (_data->hasExact(Data::PhotoSize::Small) || _data->hasExact(Data::PhotoSize::Thumbnail))) { @@ -348,6 +373,16 @@ Photo::Photo( Photo::~Photo() = default; +ClickHandlerPtr Photo::makeOpenPhotoHandler() { + return std::make_shared( + _data, + crl::guard(this, [=](FullMsgId id) { + clearSpoiler(); + delegate()->openPhoto(_data, id); + }), + parent()->fullId()); +} + void Photo::initDimensions() { _maxw = 2 * st::overviewPhotoMinSize; _minh = _story ? qRound(_maxw * kStoryRatio) : _maxw; @@ -401,6 +436,10 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const QRect(0, 0, _width, _height), Ui::DefaultImageSpoiler().frame( _spoiler->index(context->ms, paused))); + + if (_sensitiveSpoiler) { + PaintSensitiveTag(p, QRect(0, 0, _width, _height)); + } } if (selected) { @@ -453,11 +492,19 @@ void Photo::ensureDataMediaCreated() const { void Photo::clearSpoiler() { if (_spoiler) { _spoiler = nullptr; + _sensitiveSpoiler = false; _pix = QPixmap(); delegate()->repaintItem(this); } } +void Photo::maybeClearSensitiveSpoiler() { + if (_sensitiveSpoiler) { + clearSpoiler(); + _link = makeOpenPhotoHandler(); + } +} + void Photo::itemDataChanged() { const auto pinned = parent()->isPinned(); if (_pinned != pinned) { @@ -488,12 +535,23 @@ Video::Video( , _data(video) , _videoCover(LookupVideoCover(video, parent)) , _duration(Ui::FormatDurationText(_data->duration() / 1000)) -, _spoiler(options.spoiler ? std::make_unique([=] { - delegate->repaintItem(this); -}) : nullptr) +, _spoiler((options.spoiler || parent->isMediaSensitive()) + ? std::make_unique([=] { + delegate->repaintItem(this); + }) + : nullptr) +, _sensitiveSpoiler(parent->isMediaSensitive() ? 1 : 0) , _pinned(options.pinned) , _story(options.story) { setDocumentLinks(_data); + if (_sensitiveSpoiler) { + _openl = HistoryView::MakeSensitiveMediaLink( + std::make_shared(crl::guard(this, [=] { + clearSpoiler(); + setDocumentLinks(_data); + })), + parent); + } if (!_videoCover) { _data->loadThumbnail(parent->fullId()); } else if (_videoCover->inlineThumbnailBytes().isEmpty() @@ -574,6 +632,10 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const QRect(0, 0, _width, _height), Ui::DefaultImageSpoiler().frame( _spoiler->index(context->ms, paused))); + + if (_sensitiveSpoiler) { + PaintSensitiveTag(p, QRect(0, 0, _width, _height)); + } } if (selected) { @@ -660,11 +722,19 @@ void Video::ensureDataMediaCreated() const { void Video::clearSpoiler() { if (_spoiler) { _spoiler = nullptr; + _sensitiveSpoiler = false; _pix = QPixmap(); delegate()->repaintItem(this); } } +void Video::maybeClearSensitiveSpoiler() { + if (_sensitiveSpoiler) { + clearSpoiler(); + setDocumentLinks(_data); + } +} + void Video::itemDataChanged() { const auto pinned = parent()->isPinned(); if (_pinned != pinned) { @@ -700,7 +770,9 @@ TextState Video::getState( StateRequest request) const { if (hasPoint(point)) { ensureDataMediaCreated(); - const auto link = (_data->loading() || _data->uploading()) + const auto link = _sensitiveSpoiler + ? _openl + : (_data->loading() || _data->uploading()) ? _cancell : (dataLoaded() || _dataMedia->canBePlayed(parent())) ? _openl @@ -2036,8 +2108,22 @@ Gif::Gif( not_null parent, not_null gif) : RadialProgressItem(delegate, parent) -, _data(gif) { +, _data(gif) +, _spoiler(parent->isMediaSensitive() + ? std::make_unique([=] { + delegate->repaintItem(this); + }) + : nullptr) +, _sensitiveSpoiler(parent->isMediaSensitive() ? 1 : 0) { setDocumentLinks(_data, true); + if (_sensitiveSpoiler) { + _openl = HistoryView::MakeSensitiveMediaLink( + std::make_shared(crl::guard(this, [=] { + clearSpoiler(); + setDocumentLinks(_data, true); + })), + parent); + } _data->loadThumbnail(parent->fullId()); } @@ -2140,6 +2226,23 @@ void Gif::clipCallback(Media::Clip::Notification notification) { } } +void Gif::clearSpoiler() { + if (_spoiler) { + _spoiler = nullptr; + _sensitiveSpoiler = false; + _thumb = QImage(); + _thumbGood = false; + delegate()->repaintItem(this); + } +} + +void Gif::maybeClearSensitiveSpoiler() { + if (_sensitiveSpoiler) { + clearSpoiler(); + setDocumentLinks(_data); + } +} + void Gif::validateThumbnail( Image *image, QSize size, @@ -2165,7 +2268,9 @@ void Gif::prepareThumbnail(QSize size, QSize frame) { Assert(document != nullptr); ensureDataMediaCreated(); - validateThumbnail(_dataMedia->thumbnail(), size, frame, true); + if (!_spoiler) { + validateThumbnail(_dataMedia->thumbnail(), size, frame, true); + } validateThumbnail(_dataMedia->thumbnailInline(), size, frame, false); } @@ -2194,7 +2299,7 @@ void Gif::paint( }); } - const auto animating = (_gif && _gif->started()); + const auto animating = !_spoiler && (_gif && _gif->started()); if (displayLoading) { ensureRadial(); if (!_radial->animating()) { @@ -2224,6 +2329,19 @@ void Gif::paint( } } + if (_spoiler) { + const auto paused = context->paused || On(PowerSaving::kChatSpoiler); + Ui::FillSpoilerRect( + p, + r, + Ui::DefaultImageSpoiler().frame( + _spoiler->index(context->ms, paused))); + + if (_sensitiveSpoiler) { + PaintSensitiveTag(p, r); + } + } + const auto selected = (selection == FullSelection); if (radial diff --git a/Telegram/SourceFiles/overview/overview_layout.h b/Telegram/SourceFiles/overview/overview_layout.h index ff0273d1d6..5edf2a6ac4 100644 --- a/Telegram/SourceFiles/overview/overview_layout.h +++ b/Telegram/SourceFiles/overview/overview_layout.h @@ -76,6 +76,9 @@ public: virtual void clearHeavyPart() { } + virtual void maybeClearSensitiveSpoiler() { + } + protected: [[nodiscard]] not_null parent() const { return _parent; @@ -210,21 +213,26 @@ public: void itemDataChanged() override; void clearHeavyPart() override; + void maybeClearSensitiveSpoiler() override; + private: void ensureDataMediaCreated() const; void setPixFrom(not_null image); + [[nodiscard]] ClickHandlerPtr makeOpenPhotoHandler(); void clearSpoiler(); const not_null _data; mutable std::shared_ptr _dataMedia; - ClickHandlerPtr _link; std::unique_ptr _spoiler; QPixmap _pix; bool _goodLoaded = false; + bool _sensitiveSpoiler = false; bool _pinned = false; bool _story = false; + ClickHandlerPtr _link; + }; class Gif final : public RadialProgressItem { @@ -249,6 +257,9 @@ public: void clearHeavyPart() override; void setPosition(int32 position) override; + void clearSpoiler() override; + void maybeClearSensitiveSpoiler() override; + protected: float64 dataProgress() const override; bool dataFinished() const override; @@ -279,9 +290,11 @@ private: const not_null _data; mutable std::shared_ptr _dataMedia; StatusText _status; + std::unique_ptr _spoiler; QImage _thumb; bool _thumbGood = false; + bool _sensitiveSpoiler = false; }; @@ -305,6 +318,8 @@ public: void clearHeavyPart() override; void clearSpoiler() override; + void maybeClearSensitiveSpoiler() override; + protected: float64 dataProgress() const override; bool dataFinished() const override; @@ -326,6 +341,7 @@ private: QPixmap _pix; bool _pixBlurred = true; + bool _sensitiveSpoiler = false; bool _pinned = false; bool _story = false; From 321c7120dfd1cb88ff5f959618d8157a10023a8f Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 22 Jul 2025 15:33:41 +0400 Subject: [PATCH 031/341] Censor 18+ marked stickers as well. --- .../view/media/history_view_media_common.cpp | 4 +- .../view/media/history_view_sticker.cpp | 58 +++++++++++++++++-- .../history/view/media/history_view_sticker.h | 5 ++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp index 0e6ead19c7..431a45e7a3 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp @@ -580,7 +580,9 @@ ClickHandlerPtr MakeSensitiveMediaLink( return std::make_shared([=](ClickContext context) { const auto plain = [reveal, context] { - reveal->onClick(context); + if (const auto raw = reveal.get()) { + raw->onClick(context); + } }; const auto my = context.other.value(); const auto controller = my.sessionWindow.get(); diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp index 3299a8735b..90bfe44ecf 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_cursor_state.h" #include "history/view/media/history_view_media_common.h" #include "history/view/media/history_view_sticker_player.h" +#include "lang/lang_keys.h" #include "ui/image/image.h" #include "ui/chat/chat_style.h" #include "ui/effects/path_shift_gradient.h" @@ -33,6 +34,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "chat_helpers/stickers_lottie.h" #include "styles/style_chat.h" +#include "styles/style_chat_helpers.h" +#include "styles/style_menu_icons.h" namespace HistoryView { namespace { @@ -86,7 +89,8 @@ Sticker::Sticker( , _data(data) , _replacements(replacements) , _cachingTag(ChatHelpers::StickerLottieSize::MessageHistory) -, _skipPremiumEffect(skipPremiumEffect) { +, _skipPremiumEffect(skipPremiumEffect) +, _sensitiveBlurred(parent->data()->isMediaSensitive()) { if ((_dataMedia = _data->activeMediaView())) { dataMediaCreated(); } else { @@ -172,7 +176,7 @@ bool Sticker::readyToDrawAnimationFrame() { return true; } const auto sticker = _data->sticker(); - if (!sticker) { + if (!sticker || _sensitiveBlurred) { return false; } @@ -234,6 +238,43 @@ void Sticker::draw( || !paintPixmap(p, context, r)) { paintPath(p, context, r); } + if (_sensitiveBlurred) { + paintSensitiveTag(p, context, r); + } +} + +void Sticker::paintSensitiveTag( + Painter &p, + const PaintContext &context, + const QRect &r) { + auto text = Ui::Text::String(); + auto iconSkip = 0; + text.setText( + st::semiboldTextStyle, + tr::lng_sensitive_tag(tr::now)); + iconSkip = st::mediaMenuIconStealth.width() * 1.4; + const auto width = iconSkip + text.maxWidth(); + const auto inner = QRect(0, 0, width, text.minHeight()); + const auto outer = style::centerrect( + r, + inner.marginsAdded(st::paidTagPadding)); + const auto size = outer.size(); + const auto real = outer.marginsRemoved(st::paidTagPadding); + const auto radius = std::min(size.width(), size.height()) / 2; + p.setPen(Qt::NoPen); + p.setBrush(context.st->msgServiceBg()); + p.drawRoundedRect(outer, radius, radius); + p.setPen(context.st->msgServiceFg()); + if (iconSkip) { + st::mediaMenuIconStealth.paint( + p, + real.x(), + (outer.y() + + (size.height() - st::mediaMenuIconStealth.height()) / 2), + outer.width(), + context.st->msgServiceFg()->c); + } + text.draw(p, real.x() + iconSkip, real.y(), width); } ClickHandlerPtr Sticker::link() { @@ -403,8 +444,13 @@ QPixmap Sticker::paintedPixmap(const PaintContext &context) const { : context.selected() ? &context.st->msgStickerOverlay() : nullptr; - const auto good = _dataMedia->goodThumbnail(); - if (const auto image = _dataMedia->getStickerLarge()) { + const auto good = _sensitiveBlurred + ? nullptr + : _dataMedia->goodThumbnail(); + const auto image = _sensitiveBlurred + ? nullptr + : _dataMedia->getStickerLarge(); + if (image) { return image->pix(useSize, { .colored = colored }); // // Inline thumbnails can't have alpha channel. @@ -445,7 +491,9 @@ void Sticker::refreshLink() { return; } const auto sticker = _data->sticker(); - if (emojiSticker()) { + if (_sensitiveBlurred) { + _link = MakeSensitiveMediaLink(nullptr, _parent->data()); + } else if (emojiSticker()) { const auto weak = base::make_weak(this); _link = std::make_shared([weak] { if (const auto that = weak.get()) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.h b/Telegram/SourceFiles/history/view/media/history_view_sticker.h index 629d330311..c975a5c1d0 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.h +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.h @@ -111,6 +111,10 @@ private: void paintPath(Painter &p, const PaintContext &context, const QRect &r); [[nodiscard]] QPixmap paintedPixmap(const PaintContext &context) const; [[nodiscard]] bool mirrorHorizontal() const; + void paintSensitiveTag( + Painter &p, + const PaintContext &context, + const QRect &r); void ensureDataMediaCreated() const; void dataMediaCreated() const; @@ -145,6 +149,7 @@ private: bool _webpagePart : 1 = false; bool _playingOnce : 1 = false; bool _stopOnLastFrame : 1 = false; + bool _sensitiveBlurred : 1 = false; }; From b754ad52482a56904962e9cd13eff8dd8a3e5715 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 18 Jul 2025 10:07:39 +0400 Subject: [PATCH 032/341] Use base::weak_qptr / base::make_weak. --- Telegram/SourceFiles/api/api_bot.cpp | 2 +- .../api/api_chat_filters_remove_manager.cpp | 2 +- .../api/api_chat_filters_remove_manager.h | 2 +- Telegram/SourceFiles/api/api_chat_invite.cpp | 6 +- .../SourceFiles/api/api_confirm_phone.cpp | 2 +- Telegram/SourceFiles/api/api_earn.cpp | 2 +- Telegram/SourceFiles/api/api_suggest_post.cpp | 20 +++---- Telegram/SourceFiles/api/api_who_reacted.cpp | 8 +-- Telegram/SourceFiles/boxes/abstract_box.h | 4 +- .../SourceFiles/boxes/add_contact_box.cpp | 18 +++--- Telegram/SourceFiles/boxes/add_contact_box.h | 2 +- Telegram/SourceFiles/boxes/background_box.cpp | 4 +- .../boxes/background_preview_box.cpp | 6 +- .../SourceFiles/boxes/delete_messages_box.cpp | 8 +-- .../boxes/dictionaries_manager.cpp | 2 +- .../SourceFiles/boxes/edit_caption_box.cpp | 2 +- .../SourceFiles/boxes/edit_privacy_box.cpp | 4 +- .../boxes/filters/edit_filter_links.cpp | 2 +- Telegram/SourceFiles/boxes/passcode_box.cpp | 28 +++++----- Telegram/SourceFiles/boxes/passcode_box.h | 4 +- .../boxes/peer_list_controllers.cpp | 4 +- .../boxes/peers/add_participants_box.cpp | 10 ++-- .../boxes/peers/add_participants_box.h | 6 +- .../boxes/peers/choose_peer_box.cpp | 8 +-- .../boxes/peers/edit_contact_box.cpp | 4 +- .../boxes/peers/edit_forum_topic_box.cpp | 6 +- .../boxes/peers/edit_participant_box.cpp | 12 ++-- .../boxes/peers/edit_participant_box.h | 4 +- .../boxes/peers/edit_participants_box.cpp | 4 +- .../boxes/peers/edit_participants_box.h | 4 +- .../boxes/peers/edit_peer_info_box.cpp | 6 +- .../boxes/peers/edit_peer_invite_link.cpp | 12 ++-- .../boxes/peers/verify_peers_box.cpp | 8 +-- .../SourceFiles/boxes/phone_banned_box.cpp | 2 +- .../SourceFiles/boxes/pin_messages_box.cpp | 8 +-- .../boxes/self_destruction_box.cpp | 2 +- .../SourceFiles/boxes/send_credits_box.cpp | 4 +- Telegram/SourceFiles/boxes/send_files_box.cpp | 8 +-- Telegram/SourceFiles/boxes/share_box.cpp | 12 ++-- Telegram/SourceFiles/boxes/star_gift_box.cpp | 12 ++-- .../SourceFiles/boxes/sticker_set_box.cpp | 16 +++--- Telegram/SourceFiles/boxes/sticker_set_box.h | 2 +- Telegram/SourceFiles/boxes/stickers_box.cpp | 2 +- .../SourceFiles/boxes/transfer_gift_box.cpp | 18 +++--- Telegram/SourceFiles/boxes/translate_box.cpp | 4 +- Telegram/SourceFiles/boxes/url_auth_box.cpp | 4 +- .../calls/calls_box_controller.cpp | 4 +- .../calls/calls_emoji_fingerprint.cpp | 4 +- .../calls/group/calls_choose_join_as.cpp | 2 +- .../calls/group/calls_choose_join_as.h | 2 +- .../calls/group/calls_group_common.cpp | 8 +-- .../group/calls_group_invite_controller.cpp | 8 +-- .../calls/group/calls_group_members.cpp | 6 +- .../calls/group/calls_group_panel.cpp | 12 ++-- .../calls/group/calls_group_rtmp.cpp | 4 +- .../calls/group/calls_group_rtmp.h | 2 +- .../calls/group/calls_group_settings.cpp | 4 +- .../ui/desktop_capture_choose_source.cpp | 8 +-- .../chat_helpers/emoji_sets_manager.cpp | 2 +- .../chat_helpers/emoji_suggestions_widget.cpp | 2 +- .../chat_helpers/message_field.cpp | 20 +++---- .../chat_helpers/stickers_list_widget.cpp | 4 +- .../chat_helpers/tabbed_selector.cpp | 4 +- Telegram/SourceFiles/core/application.cpp | 4 +- Telegram/SourceFiles/core/application.h | 2 +- .../SourceFiles/core/phone_click_handler.cpp | 2 +- .../data/data_document_resolver.cpp | 2 +- Telegram/SourceFiles/data/data_session.h | 2 +- .../dialogs/dialogs_inner_widget.cpp | 4 +- .../SourceFiles/dialogs/dialogs_widget.cpp | 2 +- .../dialogs/ui/dialogs_suggestions.cpp | 2 +- .../editor/editor_layer_widget.cpp | 4 +- Telegram/SourceFiles/editor/photo_editor.cpp | 4 +- .../SourceFiles/export/export_api_wrap.cpp | 4 +- Telegram/SourceFiles/export/export_api_wrap.h | 4 +- .../view/export_view_panel_controller.cpp | 6 +- .../view/export_view_panel_controller.h | 4 +- .../export/view/export_view_progress.cpp | 15 ++--- .../export/view/export_view_settings.cpp | 16 +++--- .../admin_log/history_admin_log_inner.cpp | 10 ++-- .../history/history_inner_widget.cpp | 2 +- .../history/history_item_helpers.cpp | 2 +- .../SourceFiles/history/history_widget.cpp | 10 ++-- .../controls/history_view_compose_search.cpp | 8 +-- .../controls/history_view_draft_options.cpp | 12 ++-- .../controls/history_view_forward_panel.cpp | 4 +- .../controls/history_view_suggest_options.cpp | 10 ++-- .../history_view_voice_record_bar.cpp | 2 +- .../view/history_view_chat_preview.cpp | 4 +- .../view/history_view_chat_section.cpp | 6 +- .../view/history_view_contact_status.cpp | 4 +- .../view/history_view_context_menu.cpp | 22 ++++---- .../history/view/history_view_list_widget.cpp | 16 +++--- .../view/history_view_scheduled_section.cpp | 4 +- .../view/history_view_top_bar_widget.cpp | 4 +- .../view/history_view_translate_bar.cpp | 6 +- .../bot/starref/info_bot_starref_common.cpp | 4 +- .../starref/info_bot_starref_join_widget.cpp | 4 +- .../starref/info_bot_starref_setup_widget.cpp | 6 +- .../boosts/create_giveaway_box.cpp | 4 +- .../boosts/info_boosts_inner_widget.cpp | 2 +- .../earn/info_channel_earn_list.cpp | 4 +- Telegram/SourceFiles/info/info_top_bar.cpp | 6 +- .../SourceFiles/info/info_wrap_widget.cpp | 2 +- .../info/media/info_media_list_widget.cpp | 10 ++-- .../info/media/info_media_list_widget.h | 4 +- .../peer_gifts/info_peer_gifts_common.cpp | 4 +- .../info/profile/info_profile_actions.cpp | 4 +- .../info_profile_emoji_status_panel.cpp | 2 +- .../info/settings/info_settings_widget.h | 4 +- .../inline_bots/bot_attach_web_view.cpp | 14 ++--- .../intro/intro_password_check.cpp | 2 +- Telegram/SourceFiles/intro/intro_widget.cpp | 4 +- Telegram/SourceFiles/iv/iv_controller.cpp | 2 +- Telegram/SourceFiles/iv/iv_instance.cpp | 4 +- Telegram/SourceFiles/iv/iv_pch.h | 2 +- Telegram/SourceFiles/mainwindow.cpp | 4 +- .../media/stories/media_stories_header.cpp | 4 +- .../media/view/media_view_overlay_widget.cpp | 6 +- .../SourceFiles/media/view/media_view_pip.cpp | 6 +- .../menu/menu_item_download_files.cpp | 8 +-- Telegram/SourceFiles/menu/menu_send.cpp | 16 +++--- .../mtproto/mtproto_concurrent_sender.cpp | 4 +- .../mtproto/mtproto_concurrent_sender.h | 5 +- .../passport/passport_form_view_controller.h | 4 +- .../passport/passport_panel_controller.cpp | 8 +-- .../passport/passport_panel_controller.h | 2 +- .../passport/ui/passport_details_row.cpp | 2 +- .../payments/payments_checkout_process.cpp | 8 +-- .../payments/payments_checkout_process.h | 2 +- .../payments/payments_reaction_process.cpp | 6 +- .../payments/ui/payments_reaction_box.cpp | 4 +- .../business/settings_away_message.cpp | 4 +- .../settings/business/settings_greeting.cpp | 4 +- .../business/settings_quick_replies.cpp | 4 +- .../business/settings_shortcut_messages.cpp | 4 +- .../business/settings_working_hours.cpp | 12 ++-- .../settings_cloud_password_common.cpp | 2 +- .../settings_cloud_password_common.h | 2 +- .../settings_cloud_password_input.cpp | 4 +- ...ngs_cloud_password_login_email_confirm.cpp | 4 +- .../settings_cloud_password_manage.cpp | 4 +- .../settings/settings_active_sessions.cpp | 10 ++-- .../settings/settings_blocked_peers.cpp | 4 +- .../settings/settings_blocked_peers.h | 2 +- .../settings/settings_business.cpp | 12 ++-- .../SourceFiles/settings/settings_calls.cpp | 2 +- .../SourceFiles/settings/settings_common.h | 4 +- .../SourceFiles/settings/settings_credits.cpp | 10 ++-- .../settings/settings_credits_graphics.cpp | 24 ++++---- .../SourceFiles/settings/settings_folders.cpp | 6 +- .../settings/settings_local_passcode.cpp | 4 +- .../SourceFiles/settings/settings_main.cpp | 2 +- .../settings/settings_notifications_type.cpp | 2 +- .../SourceFiles/settings/settings_premium.cpp | 12 ++-- .../settings/settings_shortcuts.cpp | 2 +- .../settings/settings_websites.cpp | 12 ++-- Telegram/SourceFiles/stdafx.h | 1 - .../support/support_autocomplete.cpp | 2 +- .../SourceFiles/ui/boxes/choose_date_time.cpp | 2 +- .../SourceFiles/ui/boxes/choose_font_box.cpp | 4 +- Telegram/SourceFiles/ui/boxes/choose_time.cpp | 20 +++---- Telegram/SourceFiles/ui/boxes/confirm_box.cpp | 2 +- .../SourceFiles/ui/boxes/edit_invite_link.cpp | 2 +- Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp | 2 +- .../ui/boxes/single_choice_box.cpp | 2 +- .../SourceFiles/ui/chat/choose_send_as.cpp | 2 +- .../ui/controls/subsection_tabs_slider.cpp | 2 +- Telegram/SourceFiles/ui/countryinput.cpp | 2 +- .../ui/effects/scroll_content_shadow.cpp | 6 +- Telegram/SourceFiles/ui/ui_pch.h | 2 +- .../ui/widgets/chat_filters_tabs_strip.cpp | 2 +- .../SourceFiles/window/section_widget.cpp | 2 +- .../window/themes/window_theme_editor.cpp | 2 +- .../window/themes/window_theme_editor_block.h | 4 +- .../window/window_chat_preview.cpp | 4 +- .../SourceFiles/window/window_controller.cpp | 2 +- .../SourceFiles/window/window_controller.h | 6 +- .../window/window_filters_menu.cpp | 2 +- .../window/window_lock_widgets.cpp | 4 +- .../SourceFiles/window/window_main_menu.cpp | 4 +- .../window/window_main_menu_helpers.cpp | 2 +- .../SourceFiles/window/window_peer_menu.cpp | 56 +++++++++---------- .../SourceFiles/window/window_peer_menu.h | 18 +++--- .../window/window_session_controller.cpp | 6 +- .../window/window_session_controller.h | 2 +- Telegram/lib_base | 2 +- Telegram/lib_spellcheck | 2 +- Telegram/lib_ui | 2 +- 189 files changed, 556 insertions(+), 555 deletions(-) diff --git a/Telegram/SourceFiles/api/api_bot.cpp b/Telegram/SourceFiles/api/api_bot.cpp index b86ce1a70c..05c0d46928 100644 --- a/Telegram/SourceFiles/api/api_bot.cpp +++ b/Telegram/SourceFiles/api/api_bot.cpp @@ -245,7 +245,7 @@ void SendBotCallbackDataWithPassword( fields.customSubmitButton = tr::lng_passcode_submit(); fields.customCheckCallback = [=]( const Core::CloudPasswordResult &result, - QPointer box) { + base::weak_qptr box) { if (const auto button = getButton()) { if (button->requestId) { return; diff --git a/Telegram/SourceFiles/api/api_chat_filters_remove_manager.cpp b/Telegram/SourceFiles/api/api_chat_filters_remove_manager.cpp index fe96accd61..ffd3fb0f79 100644 --- a/Telegram/SourceFiles/api/api_chat_filters_remove_manager.cpp +++ b/Telegram/SourceFiles/api/api_chat_filters_remove_manager.cpp @@ -57,7 +57,7 @@ void RemoveChatFilter( RemoveComplexChatFilter::RemoveComplexChatFilter() = default; void RemoveComplexChatFilter::request( - QPointer widget, + base::weak_qptr widget, base::weak_ptr weak, FilterId id) { const auto session = &weak->session(); diff --git a/Telegram/SourceFiles/api/api_chat_filters_remove_manager.h b/Telegram/SourceFiles/api/api_chat_filters_remove_manager.h index ce92b2df3c..6bd6ce7fa3 100644 --- a/Telegram/SourceFiles/api/api_chat_filters_remove_manager.h +++ b/Telegram/SourceFiles/api/api_chat_filters_remove_manager.h @@ -22,7 +22,7 @@ public: RemoveComplexChatFilter(); void request( - QPointer widget, + base::weak_qptr widget, base::weak_ptr weak, FilterId id); diff --git a/Telegram/SourceFiles/api/api_chat_invite.cpp b/Telegram/SourceFiles/api/api_chat_invite.cpp index b67e148677..0d5880fcb5 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.cpp +++ b/Telegram/SourceFiles/api/api_chat_invite.cpp @@ -272,7 +272,7 @@ void ConfirmSubscriptionBox( }, balance->lifetime()); } - const auto sendCredits = [=, weak = Ui::MakeWeak(box)] { + const auto sendCredits = [=, weak = base::make_weak(box)] { const auto show = box->uiShow(); const auto buttonWidth = state->saveButton ? state->saveButton->width() @@ -280,7 +280,7 @@ void ConfirmSubscriptionBox( const auto finish = [=] { state->api = std::nullopt; state->loading.force_assign(false); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; @@ -294,7 +294,7 @@ void ConfirmSubscriptionBox( }, [](const MTPDpayments_paymentVerificationNeeded &data) { }); const auto refill = session->data().activeCreditsSubsRebuilder(); - const auto strong = weak.data(); + const auto strong = weak.get(); if (!strong) { return; } diff --git a/Telegram/SourceFiles/api/api_confirm_phone.cpp b/Telegram/SourceFiles/api/api_confirm_phone.cpp index a3b41fefc9..7379681138 100644 --- a/Telegram/SourceFiles/api/api_confirm_phone.cpp +++ b/Telegram/SourceFiles/api/api_confirm_phone.cpp @@ -87,7 +87,7 @@ void ConfirmPhone::resolve( sentCodeLength, fragmentUrl, timeout); - const auto boxWeak = Ui::MakeWeak(box.data()); + const auto boxWeak = base::make_weak(box.data()); using LoginCode = rpl::event_stream; const auto codeHandles = box->lifetime().make_state(); controller->session().account().setHandleLoginCode([=]( diff --git a/Telegram/SourceFiles/api/api_earn.cpp b/Telegram/SourceFiles/api/api_earn.cpp index 9df407aad2..3b8272fc4e 100644 --- a/Telegram/SourceFiles/api/api_earn.cpp +++ b/Telegram/SourceFiles/api/api_earn.cpp @@ -82,7 +82,7 @@ void HandleWithdrawalButton( fields.customSubmitButton = tr::lng_passcode_submit(); fields.customCheckCallback = crl::guard(button, [=]( const Core::CloudPasswordResult &result, - QPointer box) { + base::weak_qptr box) { const auto done = [=](const QString &result) { if (!result.isEmpty()) { UrlClickHandler::Open(result); diff --git a/Telegram/SourceFiles/api/api_suggest_post.cpp b/Telegram/SourceFiles/api/api_suggest_post.cpp index 7af4fbc84d..05d0304452 100644 --- a/Telegram/SourceFiles/api/api_suggest_post.cpp +++ b/Telegram/SourceFiles/api/api_suggest_post.cpp @@ -223,7 +223,7 @@ void ConfirmApproval( .confirmText = tr::lng_suggest_accept_send(), .title = tr::lng_suggest_accept_title(), }); - *callback = [=, weak = Ui::MakeWeak(box)] { + *callback = [=, weak = base::make_weak(box)] { if (const auto onstack = accepted) { onstack(); } @@ -232,7 +232,7 @@ void ConfirmApproval( return; } SendApproval(show, item, scheduleDate); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; @@ -283,9 +283,9 @@ void RequestApprovalDate( std::shared_ptr show, not_null item) { const auto id = item->fullId(); - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto close = [=] { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; @@ -339,13 +339,13 @@ void RequestDeclineComment( box->setFocusCallback([=] { reason->setFocusFast(); }); - *callback = [=, weak = Ui::MakeWeak(box)] { + *callback = [=, weak = base::make_weak(box)] { const auto item = show->session().data().message(id); if (!item) { return; } SendDecline(show, item, reason->getLastText().trimmed()); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; @@ -422,14 +422,14 @@ void SuggestApprovalDate( } const auto id = item->fullId(); const auto state = std::make_shared(); - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto done = [=](TimeId result) { const auto item = show->session().data().message(id); if (!item) { return; } const auto close = [=] { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; @@ -458,14 +458,14 @@ void SuggestOfferForMessage( HistoryView::SuggestMode mode) { const auto id = item->fullId(); const auto state = std::make_shared(); - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto done = [=](SuggestPostOptions result) { const auto item = show->session().data().message(id); if (!item) { return; } const auto close = [=] { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; diff --git a/Telegram/SourceFiles/api/api_who_reacted.cpp b/Telegram/SourceFiles/api/api_who_reacted.cpp index 84ab9b0c2c..b3070fba0d 100644 --- a/Telegram/SourceFiles/api/api_who_reacted.cpp +++ b/Telegram/SourceFiles/api/api_who_reacted.cpp @@ -240,13 +240,13 @@ struct State { [[nodiscard]] rpl::producer WhoReadIds( not_null item, not_null context) { - auto weak = QPointer(context.get()); + auto weak = base::make_weak(context); const auto session = &item->history()->session(); return [=](auto consumer) { if (!weak) { return rpl::lifetime(); } - const auto context = PreparedContextAt(weak.data(), session); + const auto context = PreparedContextAt(weak.get(), session); auto &entry = context->cacheRead(item); if (entry.requestId) { } else if (const auto user = item->history()->peer->asUser()) { @@ -325,13 +325,13 @@ struct State { not_null item, const ReactionId &reaction, not_null context) { - auto weak = QPointer(context.get()); + auto weak = base::make_weak(context); const auto session = &item->history()->session(); return [=](auto consumer) { if (!weak) { return rpl::lifetime(); } - const auto context = PreparedContextAt(weak.data(), session); + const auto context = PreparedContextAt(weak.get(), session); auto &entry = context->cacheReacted(item, reaction); if (!entry.requestId) { using Flag = MTPmessages_GetMessageReactionsList::Flag; diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h index d48e93108f..119875a293 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.h +++ b/Telegram/SourceFiles/boxes/abstract_box.h @@ -37,11 +37,11 @@ void showBox( } // namespace internal template -QPointer show( +base::weak_qptr show( object_ptr content, Ui::LayerOptions options = Ui::LayerOption::CloseOther, anim::type animated = anim::type::normal) { - auto result = QPointer(content.data()); + auto result = base::weak_qptr(content.data()); internal::showBox(std::move(content), options, animated); return result; } diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp index 792eff79b4..6e9bc23955 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp @@ -194,16 +194,16 @@ void ShowAddParticipantsError( && channel->canAddAdmins()) { const auto makeAdmin = [=](Fn close) { const auto user = forbidden.users.front(); - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto done = [=](auto&&...) { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->uiShow()->showToast( tr::lng_box_done(tr::now)); strong->closeBox(); } }; const auto fail = [=] { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; @@ -446,7 +446,7 @@ void AddContactBox::save() { firstName = lastName; lastName = QString(); } - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto session = _session; _sentName = firstName; _contactId = base::RandomValue(); @@ -716,7 +716,7 @@ TimeId GroupInfoBox::ttlPeriod() const { } void GroupInfoBox::createGroup( - QPointer selectUsersBox, + base::weak_qptr selectUsersBox, const QString &title, const std::vector> &users) { if (_creationRequestId) { @@ -750,8 +750,8 @@ void GroupInfoBox::createGroup( _creationRequestId = 0; const auto controller = _navigation->parentController(); if (type == u"NO_CHAT_TITLE"_q) { - const auto weak = Ui::MakeWeak(this); - if (const auto strong = selectUsersBox.data()) { + const auto weak = base::make_weak(this); + if (const auto strong = selectUsersBox.get()) { strong->closeBox(); } if (weak) { @@ -792,10 +792,10 @@ void GroupInfoBox::submit() { } else if (_canAddBot) { createGroup(nullptr, title, { not_null(_canAddBot) }); } else { - auto initBox = [title, weak = Ui::MakeWeak(this)]( + auto initBox = [title, weak = base::make_weak(this)]( not_null box) { auto create = [box, title, weak] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->createGroup( box.get(), title, diff --git a/Telegram/SourceFiles/boxes/add_contact_box.h b/Telegram/SourceFiles/boxes/add_contact_box.h index 9bc7de6520..4032653564 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.h +++ b/Telegram/SourceFiles/boxes/add_contact_box.h @@ -129,7 +129,7 @@ protected: private: void createChannel(const QString &title, const QString &description); void createGroup( - QPointer selectUsersBox, + base::weak_qptr selectUsersBox, const QString &title, const std::vector> &users); void submitName(); diff --git a/Telegram/SourceFiles/boxes/background_box.cpp b/Telegram/SourceFiles/boxes/background_box.cpp index 59729b7fed..f2e2f647b3 100644 --- a/Telegram/SourceFiles/boxes/background_box.cpp +++ b/Telegram/SourceFiles/boxes/background_box.cpp @@ -345,7 +345,7 @@ void BackgroundBox::resetForPeer() { api->applyUpdates(result); }).send(); - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); _forPeer->setWallPaper({}); if (weak) { _controller->finishChatThemeEdit(_forPeer); @@ -358,7 +358,7 @@ bool BackgroundBox::forChannel() const { void BackgroundBox::removePaper(const Data::WallPaper &paper) { const auto session = &_controller->session(); - const auto remove = [=, weak = Ui::MakeWeak(this)](Fn &&close) { + const auto remove = [=, weak = base::make_weak(this)](Fn &&close) { close(); if (weak) { weak->_inner->removePaper(paper); diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index 0faa677720..0fc02e2efc 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -241,12 +241,12 @@ BackgroundPreviewBox::BackgroundPreviewBox( }, lifetime()); const auto prepare = [=](bool dark, auto pointer) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); crl::async([=] { auto result = std::make_unique(); Window::Theme::PreparePaletteCallback(dark, {})(*result); crl::on_main([=, result = std::move(result)]() mutable { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->*pointer = std::move(result); strong->paletteReady(); } @@ -685,7 +685,7 @@ void BackgroundPreviewBox::checkLevelForChannel() { const auto show = _controller->uiShow(); _forPeerLevelCheck = true; - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); CheckBoostLevel(show, _forPeer, [=](int level) { if (!weak) { return std::optional(); diff --git a/Telegram/SourceFiles/boxes/delete_messages_box.cpp b/Telegram/SourceFiles/boxes/delete_messages_box.cpp index 5c4b266cd4..503720fc27 100644 --- a/Telegram/SourceFiles/boxes/delete_messages_box.cpp +++ b/Telegram/SourceFiles/boxes/delete_messages_box.cpp @@ -522,10 +522,10 @@ void DeleteMessagesBox::deleteAndClear() { ? PaidPostType::None : paidPostType(); if (warnPaidType != PaidPostType::None) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto callback = [=](Fn close) { close(); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->_confirmedDeletePaidSuggestedPosts = true; strong->deleteAndClear(); } @@ -559,11 +559,11 @@ void DeleteMessagesBox::deleteAndClear() { const auto invokeCallbackAndClose = [&] { // deleteMessages can initiate closing of the current section, // which will cause this box to be destroyed. - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); if (const auto callback = _deleteConfirmedCallback) { callback(); } - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; diff --git a/Telegram/SourceFiles/boxes/dictionaries_manager.cpp b/Telegram/SourceFiles/boxes/dictionaries_manager.cpp index 72cfd29c0d..8881449fcb 100644 --- a/Telegram/SourceFiles/boxes/dictionaries_manager.cpp +++ b/Telegram/SourceFiles/boxes/dictionaries_manager.cpp @@ -282,7 +282,7 @@ auto AddButtonWithLoader( ) | rpl::start_with_next([=](bool toggled) { const auto &state = buttonState->current(); if (toggled && (v::is(state) || v::is(state))) { - const auto weak = Ui::MakeWeak(button); + const auto weak = base::make_weak(button); setLocalLoader(base::make_unique_q( QCoreApplication::instance(), session, diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index cb27997d66..3e48724b7f 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -1075,7 +1075,7 @@ void EditCaptionBox::save() { } void EditCaptionBox::closeAfterSave() { - const auto weak = MakeWeak(this); + const auto weak = base::make_weak(this); if (_saved) { _saved(); } diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index 86816ba15b..2d6f1e2448 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -1313,9 +1313,9 @@ void EditDirectMessagesPriceBox( }, box->lifetime()); box->addButton(tr::lng_settings_save(), [=] { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); callback(toggle->toggled() ? *result : std::optional()); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp index 90dd083bd1..acd6da5641 100644 --- a/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp +++ b/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp @@ -582,7 +582,7 @@ void LinkController::addLinkBlock(not_null container) { using namespace Settings; const auto link = _data.url; - const auto weak = Ui::MakeWeak(container); + const auto weak = base::make_weak(container); const auto copyLink = crl::guard(weak, [=] { CopyInviteLink(delegate()->peerListUiShow(), link); }); diff --git a/Telegram/SourceFiles/boxes/passcode_box.cpp b/Telegram/SourceFiles/boxes/passcode_box.cpp index 96d5f2d332..a235dc2d7a 100644 --- a/Telegram/SourceFiles/boxes/passcode_box.cpp +++ b/Telegram/SourceFiles/boxes/passcode_box.cpp @@ -49,7 +49,7 @@ void SetCloudPassword( session->api().cloudPassword().state( ) | rpl::start_with_next([=] { using namespace Settings; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); if (CheckEditCloudPassword(session)) { box->getDelegate()->show( EditCloudPasswordBox(session)); @@ -103,11 +103,11 @@ void StartPendingReset( not_null session, not_null context, Fn close) { - const auto weak = Ui::MakeWeak(context.get()); + const auto weak = base::make_weak(context.get()); auto lifetime = std::make_shared(); auto finish = [=](const QString &message) mutable { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { if (!message.isEmpty()) { strong->getDelegate()->show(Ui::MakeInformBox(message)); } @@ -136,7 +136,7 @@ void StartPendingReset( : hours ? tr::lng_hours(tr::now, lt_count, hours) : tr::lng_minutes(tr::now, lt_count, minutes); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->getDelegate()->show(Ui::MakeInformBox( tr::lng_cloud_password_reset_later( tr::now, @@ -447,7 +447,7 @@ void PasscodeBox::recoverPasswordDone( _replacedBy->closeBox(); } _setRequest = 0; - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); _newAuthorization.fire_copy(result); if (weak) { _newPasswordSet.fire_copy(newPasswordBytes); @@ -466,7 +466,7 @@ void PasscodeBox::setPasswordDone(const QByteArray &newPasswordBytes) { _replacedBy->closeBox(); } _setRequest = 0; - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); _newPasswordSet.fire_copy(newPasswordBytes); if (weak) { auto text = _reenterPasscode->isHidden() @@ -567,9 +567,9 @@ void PasscodeBox::validateEmail( } else if (error.type() == u"CODE_INVALID"_q) { errors->fire(tr::lng_signin_wrong_code(tr::now)); } else if (error.type() == u"EMAIL_HASH_EXPIRED"_q) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); _clearUnconfirmedPassword.fire({}); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->getDelegate()->show( Ui::MakeInformBox( Lang::Hard::EmailConfirmationExpired()), @@ -607,7 +607,7 @@ void PasscodeBox::validateEmail( box->boxClosing( ) | rpl::filter([=] { return !*set; - }) | start_with_next([=, weak = Ui::MakeWeak(this)] { + }) | start_with_next([=, weak = base::make_weak(this)] { if (weak) { weak->_clearUnconfirmedPassword.fire({}); } @@ -710,7 +710,7 @@ void PasscodeBox::save(bool force) { } } else { closeReplacedBy(); - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); cSetPasscodeBadTries(0); _session->domain().local().setPasscode(pwd.toUtf8()); Core::App().localPasscodeChanged(); @@ -742,7 +742,7 @@ void PasscodeBox::submitOnlyCheckCloudPassword(const QString &oldPassword) { void PasscodeBox::sendOnlyCheckCloudPassword(const QString &oldPassword) { checkPassword(oldPassword, [=](const Core::CloudPasswordResult &check) { if (const auto onstack = _cloudFields.customCheckCallback) { - onstack(check, Ui::MakeWeak(this)); + onstack(check, base::make_weak(this)); } else { Assert(_cloudFields.turningOff); sendClearCloudPassword(check); @@ -1105,7 +1105,7 @@ void PasscodeBox::recover() { return; } - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto box = getDelegate()->show(Box( &_api.instance(), _session, @@ -1343,7 +1343,7 @@ void RecoverBox::proceedToChange(const QString &code) { box->boxClosing( ) | rpl::start_with_next([=] { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); if (const auto onstack = _closeParent) { onstack(); } @@ -1399,7 +1399,7 @@ RecoveryEmailValidation ConfirmRecoveryEmail( const auto errors = std::make_shared>(); const auto resent = std::make_shared>(); const auto requestId = std::make_shared(0); - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto reloads = std::make_shared>(); const auto cancels = std::make_shared>(); diff --git a/Telegram/SourceFiles/boxes/passcode_box.h b/Telegram/SourceFiles/boxes/passcode_box.h index 09f3335617..5ab6413fc2 100644 --- a/Telegram/SourceFiles/boxes/passcode_box.h +++ b/Telegram/SourceFiles/boxes/passcode_box.h @@ -53,7 +53,7 @@ public: // Check cloud password for some action. using CustomCheck = Fn)>; + base::weak_qptr)>; CustomCheck customCheckCallback; rpl::producer customTitle; std::optional customDescription; @@ -158,7 +158,7 @@ private: QString _pattern; - QPointer _replacedBy; + base::weak_qptr _replacedBy; bool _turningOff = false; bool _cloudPwd = false; CloudFields _cloudFields; diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 37ab361a8f..0f0a8e0da3 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -831,7 +831,7 @@ void ChooseRecipientBoxController::rowClicked(not_null row) { auto guard = base::make_weak(this); const auto peer = row->peer(); if (const auto forum = peer->forum()) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto callback = [=](not_null topic) { const auto exists = guard.get(); if (!exists) { @@ -870,7 +870,7 @@ void ChooseRecipientBoxController::rowClicked(not_null row) { delegate()->peerListUiShow()->showBox(std::move(owned)); return; } else if (const auto monoforum = peer->monoforum()) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto callback = [=](not_null sublist) { const auto exists = guard.get(); if (!exists) { diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp index ab05d9bccb..75ccf927d9 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp @@ -898,9 +898,9 @@ bool AddParticipantsBoxController::needsInviteLinkButton() { return _peer->asChat()->canHaveInviteLink(); } -QPointer AddParticipantsBoxController::showBox( +base::weak_qptr AddParticipantsBoxController::showBox( object_ptr box) const { - const auto weak = Ui::MakeWeak(box.data()); + const auto weak = base::make_weak(box.data()); delegate()->peerListUiShow()->showBox(std::move(box)); return weak; } @@ -976,7 +976,7 @@ void AddParticipantsBoxController::inviteSelectedUsers( tr::lng_participant_invite_history(), true, st::defaultBoxCheckbox); - const auto weak = Ui::MakeWeak(checkbox.data()); + const auto weak = base::make_weak(checkbox.data()); auto text = (users.size() == 1) ? tr::lng_participant_invite_sure( @@ -1205,9 +1205,9 @@ void AddSpecialBoxController::migrate( _additional.migrate(chat, channel); } -QPointer AddSpecialBoxController::showBox( +base::weak_qptr AddSpecialBoxController::showBox( object_ptr box) const { - const auto weak = Ui::MakeWeak(box.data()); + const auto weak = base::make_weak(box.data()); delegate()->peerListUiShow()->showBox(std::move(box)); return weak; } diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.h b/Telegram/SourceFiles/boxes/peers/add_participants_box.h index 24d5e1031d..dc06e8040f 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.h @@ -56,7 +56,7 @@ private: base::flat_set> &&alreadyIn, bool justCreated); - QPointer showBox(object_ptr box) const; + base::weak_qptr showBox(object_ptr box) const; void addInviteLinkButton(); void inviteSelectedUsers( @@ -147,7 +147,7 @@ private: void subscribeToMigration(); void migrate(not_null chat, not_null channel); - QPointer showBox(object_ptr box) const; + base::weak_qptr showBox(object_ptr box) const; not_null _peer; MTP::Sender _api; @@ -158,7 +158,7 @@ private: ParticipantsAdditionalData _additional; std::unique_ptr _onlineSorter; Ui::BoxPointer _editBox; - QPointer _editParticipantBox; + base::weak_qptr _editParticipantBox; AdminDoneCallback _adminDoneCallback; BannedDoneCallback _bannedDoneCallback; diff --git a/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp b/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp index 7257a3c3f8..ca10840712 100644 --- a/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/choose_peer_box.cpp @@ -246,10 +246,10 @@ object_ptr CreatePeerByQueryBox( not_null bot, RequestPeerQuery query, Fn>)> done) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto callback = [=](not_null peer) { done({ peer }); - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; @@ -506,11 +506,11 @@ void ShowChoosePeerBox( }); return; } - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto callback = [=, done = std::move(chosen)]( std::vector> peers) { done(std::move(peers)); - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; diff --git a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp index 4bc2848c78..cc378e6095 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp @@ -37,7 +37,7 @@ QString UserPhone(not_null user) { } void SendRequest( - QPointer box, + base::weak_qptr box, not_null user, bool sharePhone, const QString &first, @@ -219,7 +219,7 @@ void Controller::initNameFields( } }; SendRequest( - Ui::MakeWeak(_box), + base::make_weak(_box), user, _sharePhone && _sharePhone->checked(), firstValue, diff --git a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp index 45ad6b1931..f1de1444ad 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp @@ -554,7 +554,7 @@ void EditForumTopicBox( } else { using Flag = MTPchannels_EditForumTopic::Flag; const auto api = &forum->session().api(); - const auto weak = Ui::MakeWeak(box.get()); + const auto weak = base::make_weak(box); state->requestId = api->request(MTPchannels_EditForumTopic( MTP_flags(Flag::f_title | (topic->isGeneral() ? Flag() : Flag::f_icon_emoji_id)), @@ -566,11 +566,11 @@ void EditForumTopicBox( MTPBool() // hidden )).done([=](const MTPUpdates &result) { api->applyUpdates(result); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }).fail([=](const MTP::Error &error) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { if (error.type() == u"TOPIC_NOT_MODIFIED") { strong->closeBox(); } else { diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp index 50c3254a37..84c47cd928 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp @@ -450,9 +450,9 @@ void EditAdminBox::prepare() { if (!_saveCallback) { return; } else if (_addAsAdmin && !_addAsAdmin->checked()) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); AddBotToGroup(show, user(), peer(), _addingBot->token); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } return; @@ -661,7 +661,7 @@ void EditAdminBox::requestTransferPassword(not_null channel) { fields.customSubmitButton = tr::lng_passcode_submit(); fields.customCheckCallback = crl::guard(this, [=]( const Core::CloudPasswordResult &result, - QPointer box) { + base::weak_qptr box) { sendTransferRequestFrom(box, channel, result); }); getDelegate()->show(Box(&channel->session(), fields)); @@ -669,13 +669,13 @@ void EditAdminBox::requestTransferPassword(not_null channel) { } void EditAdminBox::sendTransferRequestFrom( - QPointer box, + base::weak_qptr box, not_null channel, const Core::CloudPasswordResult &result) { if (_transferRequestId) { return; } - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto user = this->user(); const auto api = &channel->session().api(); _transferRequestId = api->request(MTPchannels_EditCreator( @@ -726,7 +726,7 @@ void EditAdminBox::sendTransferRequestFrom( || type.startsWith(u"PASSWORD_TOO_FRESH_"_q) || type.startsWith(u"SESSION_TOO_FRESH_"_q); }(); - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); getDelegate()->show(Ui::MakeInformBox(problem)); if (box) { box->closeBox(); diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h index 1e5c9fd8ae..b67efcd140 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h @@ -104,7 +104,7 @@ private: bool handleTransferPasswordError(const QString &error); void requestTransferPassword(not_null channel); void sendTransferRequestFrom( - QPointer box, + base::weak_qptr box, not_null channel, const Core::CloudPasswordResult &result); bool canSave() const { @@ -124,7 +124,7 @@ private: ChatAdminRightsInfo, const QString &rank)> _saveCallback; - QPointer _confirmBox; + base::weak_qptr _confirmBox; Ui::Checkbox *_addAsAdmin = nullptr; Ui::SlideWrap *_adminControlsWrap = nullptr; Ui::InputField *_rank = nullptr; diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp index 03fbc87c68..15a5f1aee1 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp @@ -1324,9 +1324,9 @@ void ParticipantsBoxController::rebuild() { refreshRows(); } -QPointer ParticipantsBoxController::showBox( +base::weak_qptr ParticipantsBoxController::showBox( object_ptr box) const { - const auto weak = Ui::MakeWeak(box.data()); + const auto weak = base::make_weak(box.data()); delegate()->peerListUiShow()->showBox(std::move(box)); return weak; } diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h index b993c740c5..6e14120302 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h @@ -240,7 +240,7 @@ private: Role role, not_null additional); - QPointer showBox(object_ptr box) const; + base::weak_qptr showBox(object_ptr box) const; void prepareChatRows(not_null chat); void rebuildChatRows(not_null chat); @@ -304,7 +304,7 @@ private: rpl::variable _fullCountValue; Ui::BoxPointer _editBox; Ui::BoxPointer _addBox; - QPointer _editParticipantBox; + base::weak_qptr _editParticipantBox; std::unique_ptr _stories; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 9d01c2560a..8f5f4221dd 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -906,7 +906,7 @@ void Controller::showEditDiscussionLinkBox() { return; } - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto channel = _peer->asChannel(); const auto callback = [=](ChannelData *result) { if (*box) { @@ -1252,12 +1252,12 @@ void Controller::fillAutoTranslateButton() { _autotranslateSavedValue = value; } else if (value) { state->toggled.fire(false); - auto weak = Ui::MakeWeak(autotranslate); + auto weak = base::make_weak(autotranslate); CheckBoostLevel( _navigation->uiShow(), _peer, [=](int level) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { state->isLocked = (level < requiredLevel); } return (level < requiredLevel) diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp index aba3714395..17fb1537fb 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp @@ -424,7 +424,7 @@ void Controller::addHeaderBlock(not_null container) { const auto revoked = current.revoked; const auto link = current.link; const auto admin = current.admin; - const auto weak = Ui::MakeWeak(container); + const auto weak = base::make_weak(container); const auto copyLink = crl::guard(weak, [=] { CopyInviteLink(delegate()->peerListUiShow(), link); }); @@ -1290,7 +1290,7 @@ void AddPermanentLinkBlock( return LinkData{ link.link, link.usage }; }); } - const auto weak = Ui::MakeWeak(container); + const auto weak = base::make_weak(container); const auto copyLink = crl::guard(weak, [=] { if (const auto current = value->current(); !current.link.isEmpty()) { CopyInviteLink(show, current.link); @@ -1471,7 +1471,7 @@ object_ptr ShareInviteLinkBox( const QString &link, const QString &copied) { const auto sending = std::make_shared(); - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto showToast = [=](const QString &text) { if (*box) { @@ -1551,7 +1551,7 @@ object_ptr ShareInviteLinkBox( .filterCallback = std::move(filterCallback), .moneyRestrictionError = ShareMessageMoneyRestrictionError(), }); - *box = Ui::MakeWeak(object.data()); + *box = base::make_weak(object.data()); return object; } @@ -1573,7 +1573,7 @@ object_ptr EditLinkBox( constexpr auto kPeriod = 3600 * 24 * 30; constexpr auto kTestModePeriod = 300; const auto creating = data.link.isEmpty(); - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); using Fields = Ui::InviteLinkFields; const auto done = [=](Fields result) { const auto finish = [=](Api::InviteLink finished) { @@ -1645,7 +1645,7 @@ object_ptr EditLinkBox( done); } }); - *box = Ui::MakeWeak(object.data()); + *box = base::make_weak(object.data()); return object; } diff --git a/Telegram/SourceFiles/boxes/peers/verify_peers_box.cpp b/Telegram/SourceFiles/boxes/peers/verify_peers_box.cpp index b368f5dc39..f3e71b6f5e 100644 --- a/Telegram/SourceFiles/boxes/peers/verify_peers_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/verify_peers_box.cpp @@ -127,11 +127,11 @@ void Controller::confirmAdd(not_null peer) { return; } state->sent = true; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); const auto description = modify ? state->description : QString(); Setup(bot, peer, description, [=](QString error) { if (error.isEmpty()) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } show->showToast({ @@ -204,10 +204,10 @@ void Controller::confirmRemove(not_null peer) { return; } *sent = true; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); Remove(bot, peer, [=](QString error) { if (error.isEmpty()) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } show->showToast(tr::lng_bot_verify_remove_done(tr::now)); diff --git a/Telegram/SourceFiles/boxes/phone_banned_box.cpp b/Telegram/SourceFiles/boxes/phone_banned_box.cpp index b29388e96c..c1e9fb512d 100644 --- a/Telegram/SourceFiles/boxes/phone_banned_box.cpp +++ b/Telegram/SourceFiles/boxes/phone_banned_box.cpp @@ -49,7 +49,7 @@ Locale: ") + ::Platform::SystemLanguage(); void ShowPhoneBannedError( not_null controller, const QString &phone) { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto close = [=] { if (*box) { (*box)->closeBox(); diff --git a/Telegram/SourceFiles/boxes/pin_messages_box.cpp b/Telegram/SourceFiles/boxes/pin_messages_box.cpp index 9ba027e20c..9f0a84fccb 100644 --- a/Telegram/SourceFiles/boxes/pin_messages_box.cpp +++ b/Telegram/SourceFiles/boxes/pin_messages_box.cpp @@ -50,8 +50,8 @@ void PinMessageBox( not_null box, not_null item) { struct State { - QPointer pinForPeer; - QPointer notify; + base::weak_qptr pinForPeer; + base::weak_qptr notify; mtpRequestId requestId = 0; }; @@ -81,7 +81,7 @@ void PinMessageBox( false, st::urlAuthCheckbox); object->setAllowTextLines(); - state->pinForPeer = Ui::MakeWeak(object.data()); + state->pinForPeer = base::make_weak(object.data()); return object; } else if (!pinningOld && (peer->isChat() || peer->isMegagroup()) @@ -92,7 +92,7 @@ void PinMessageBox( true, st::urlAuthCheckbox); object->setAllowTextLines(); - state->notify = Ui::MakeWeak(object.data()); + state->notify = base::make_weak(object.data()); return object; } return { nullptr }; diff --git a/Telegram/SourceFiles/boxes/self_destruction_box.cpp b/Telegram/SourceFiles/boxes/self_destruction_box.cpp index c4a070c16e..f65cd54b17 100644 --- a/Telegram/SourceFiles/boxes/self_destruction_box.cpp +++ b/Telegram/SourceFiles/boxes/self_destruction_box.cpp @@ -56,7 +56,7 @@ void AddDeleteAccount( fields.customSubmitButton = tr::lng_theme_delete(); fields.customCheckCallback = [=]( const Core::CloudPasswordResult &result, - QPointer box) { + base::weak_qptr box) { session->api().request(MTPaccount_DeleteAccount( MTP_flags(MTPaccount_DeleteAccount::Flag::f_password), MTP_string("Manual"), diff --git a/Telegram/SourceFiles/boxes/send_credits_box.cpp b/Telegram/SourceFiles/boxes/send_credits_box.cpp index 9e33609715..8f355b1aa6 100644 --- a/Telegram/SourceFiles/boxes/send_credits_box.cpp +++ b/Telegram/SourceFiles/boxes/send_credits_box.cpp @@ -397,7 +397,7 @@ void SendCreditsBox( return; } const auto show = box->uiShow(); - const auto weak = MakeWeak(box.get()); + const auto weak = base::make_weak(box.get()); state->confirmButtonBusy = true; session->api().request( MTPpayments_SendStarsForm( @@ -422,7 +422,7 @@ void SendCreditsBox( auto error = ::Ui::MakeInformBox( tr::lng_payments_precheckout_stars_failed(tr::now)); error->boxClosing() | rpl::start_with_next([=] { - if (const auto paybox = weak.data()) { + if (const auto paybox = weak.get()) { paybox->closeBox(); } }, error->lifetime()); diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 1ef95d7c89..b16040eeae 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -175,9 +175,9 @@ void EditPriceBox( field->showError(); return; } - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); apply(now); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; @@ -597,7 +597,7 @@ void SendFilesBox::enqueueNextPrepare() { } auto file = std::move(_list.filesToProcess.front()); _list.filesToProcess.pop_front(); - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); _preparing = true; const auto sideLimit = PhotoSideLimit(); // Get on main thread. crl::async([weak, sideLimit, file = std::move(file)]() mutable { @@ -803,7 +803,7 @@ void SendFilesBox::toggleSpoilers(bool enabled) { } void SendFilesBox::changePrice() { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto session = &_show->session(); const auto now = _price.current(); _show->show(Box(EditPriceBox, session, now, [=](uint64 price) { diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index dac3fe5d97..5f9e018a28 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -677,7 +677,7 @@ void ShareBox::submit(Api::SendOptions options) { _submitLifetime.destroy(); auto threads = _inner->selected(); - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto field = _comment->entity(); auto comment = field->getTextWithAppliedMarkdown(); const auto checkPaid = [=] { @@ -1371,8 +1371,8 @@ void ShareBox::Inner::changeCheckState(Chat *chat) { } void ShareBox::Inner::chooseForumTopic(not_null forum) { - const auto guard = Ui::MakeWeak(this); - const auto weak = std::make_shared>(); + const auto guard = base::make_weak(this); + const auto weak = std::make_shared>(); auto chosen = [=](not_null topic) { if (const auto strong = *weak) { strong->closeBox(); @@ -1419,8 +1419,8 @@ void ShareBox::Inner::chooseForumTopic(not_null forum) { void ShareBox::Inner::chooseMonoforumSublist( not_null monoforum) { - const auto guard = Ui::MakeWeak(this); - const auto weak = std::make_shared>(); + const auto guard = base::make_weak(this); + const auto weak = std::make_shared>(); auto chosen = [=](not_null sublist) { if (const auto strong = *weak) { strong->closeBox(); @@ -1953,7 +1953,7 @@ void FastShareLink( std::shared_ptr show, const QString &url, ShareBoxStyleOverrides st) { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto sending = std::make_shared(); auto copyCallback = [=] { QGuiApplication::clipboard()->setText(url); diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index 0398ffbc91..c63319b912 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -2516,7 +2516,7 @@ void SendGiftBox( if (!state->messageAllowed.current()) { details.text = {}; } - const auto weak = MakeWeak(box); + const auto weak = base::make_weak(box); const auto done = [=](Payments::CheckoutResult result) { if (result == Payments::CheckoutResult::Paid) { if (details.byStars @@ -2527,7 +2527,7 @@ void SendGiftBox( window->showPeerHistory(peer); ShowSentToast(window, details.descriptor, details); } - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; @@ -4337,12 +4337,12 @@ void ShowUniqueGiftWearBox( return; } *checking = true; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); CheckBoostLevel(show, peer, [=](int level) { const auto limits = Data::LevelLimits(&peer->session()); const auto wanted = limits.channelEmojiStatusLevelMin(); if (level >= wanted) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } emojiStatuses->set(peer, id); @@ -4835,13 +4835,13 @@ void UpgradeBox( } state->sent = true; const auto keepDetails = state->preserveDetails; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); const auto done = [=](Payments::CheckoutResult result) { if (result != Payments::CheckoutResult::Paid) { state->sent = false; } else { controller->showPeerHistory(args.peer); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } } diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index 3c7380f914..2079fc7108 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -494,7 +494,7 @@ StickerSetBox::StickerSetBox( : StickerSetBox(parent, std::move(show), set->identifier(), set->type()) { } -QPointer StickerSetBox::Show( +base::weak_qptr StickerSetBox::Show( std::shared_ptr show, not_null document) { if (const auto sticker = document->sticker()) { @@ -503,7 +503,7 @@ QPointer StickerSetBox::Show( show, sticker->set, sticker->setType); - const auto result = QPointer(box.data()); + const auto result = base::make_weak(box.data()); show->showBox(std::move(box)); return result; } @@ -1485,7 +1485,7 @@ void StickerSetBox::Inner::fillDeleteStickerBox( int index) { Expects(index >= 0 || index < _pack.size()); const auto document = _pack[index]; - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto show = _show; const auto container = box->verticalLayout(); @@ -1510,7 +1510,7 @@ void StickerSetBox::Inner::fillDeleteStickerBox( sticker->paintRequest( ) | rpl::start_with_next([=] { auto p = Painter(sticker); - if ([[maybe_unused]] const auto strong = weak.data()) { + if ([[maybe_unused]] const auto strong = weak.get()) { const auto paused = On(PowerSaving::kStickersPanel) || show->paused(ChatHelpers::PauseReason::Layer); paintSticker(p, index, QPoint(), paused, crl::now()); @@ -1551,7 +1551,7 @@ void StickerSetBox::Inner::fillDeleteStickerBox( if (state->requestId.current()) { return; } - const auto weakBox = Ui::MakeWeak(box); + const auto weakBox = base::make_weak(box); const auto buttonWidth = state->saveButton ? state->saveButton->width() : 0; @@ -1564,14 +1564,14 @@ void StickerSetBox::Inner::fillDeleteStickerBox( Data::StickersType::Stickers); }, [](const auto &) { }); - if ([[maybe_unused]] const auto strong = weak.data()) { + if ([[maybe_unused]] const auto strong = weak.get()) { applySet(result); } - if (const auto strongBox = weakBox.data()) { + if (const auto strongBox = weakBox.get()) { strongBox->closeBox(); } }).fail([=](const MTP::Error &error) { - if (const auto strongBox = weakBox.data()) { + if (const auto strongBox = weakBox.get()) { strongBox->uiShow()->showToast(error.type()); } }).send(); diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.h b/Telegram/SourceFiles/boxes/sticker_set_box.h index 07e0168e2b..85fbc2a404 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.h +++ b/Telegram/SourceFiles/boxes/sticker_set_box.h @@ -70,7 +70,7 @@ public: std::shared_ptr show, not_null set); - static QPointer Show( + static base::weak_qptr Show( std::shared_ptr show, not_null document); diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index 778db60af9..65d3c400bb 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -2058,7 +2058,7 @@ void StickersBox::Inner::checkGroupLevel(Fn done) { } _checkingGroupLevel = true; - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); CheckBoostLevel(_show, peer, [=](int level) { if (!weak) { return std::optional(); diff --git a/Telegram/SourceFiles/boxes/transfer_gift_box.cpp b/Telegram/SourceFiles/boxes/transfer_gift_box.cpp index d94c9d01e7..438beff1e0 100644 --- a/Telegram/SourceFiles/boxes/transfer_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/transfer_gift_box.cpp @@ -90,8 +90,8 @@ void ConfirmExportBox( Ui::Text::WithEntities), st::boxLabel)); box->addButton(tr::lng_gift_transfer_confirm_button(), [=] { - confirmed([weak = Ui::MakeWeak(box)] { - if (const auto strong = weak.data()) { + confirmed([weak = base::make_weak(box)] { + if (const auto strong = weak.get()) { strong->closeBox(); } }); @@ -143,7 +143,7 @@ void ExportOnBlockchain( fields.customSubmitButton = tr::lng_passcode_submit(); fields.customCheckCallback = crl::guard(parent, [=]( const Core::CloudPasswordResult &result, - QPointer box) { + base::weak_qptr box) { using ExportUrl = MTPpayments_StarGiftWithdrawalUrl; session->api().request( MTPpayments_GetStarGiftWithdrawalUrl( @@ -180,7 +180,7 @@ void ExportOnBlockchain( const auto state = std::make_shared(); const auto activate = [=] { const auto now = base::unixtime::now(); - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); const auto left = (when > now) ? (when - now) : 0; const auto hours = left ? std::max((left + 1800) / 3600, 1) : 0; if (!hours) { @@ -193,7 +193,7 @@ void ExportOnBlockchain( state->exporting = false; close(); }, [=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } close(); @@ -572,11 +572,11 @@ void ShowTransferToBox( return; } state->sent = true; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); const auto done = [=](Payments::CheckoutResult result) { if (result == Payments::CheckoutResult::Cancelled) { closeParentBox(); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } } else if (result != Payments::CheckoutResult::Paid) { @@ -586,7 +586,7 @@ void ShowTransferToBox( controller->showPeerHistory(peer); } closeParentBox(); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } } @@ -674,7 +674,7 @@ void ShowBuyResaleGiftBox( return; } state->sent = true; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); const auto done = [=](Payments::CheckoutResult result) { if (result == Payments::CheckoutResult::Cancelled) { closeParentBox(); diff --git a/Telegram/SourceFiles/boxes/translate_box.cpp b/Telegram/SourceFiles/boxes/translate_box.cpp index b79a417eec..8e29782b5b 100644 --- a/Telegram/SourceFiles/boxes/translate_box.cpp +++ b/Telegram/SourceFiles/boxes/translate_box.cpp @@ -307,7 +307,7 @@ object_ptr EditSkipTranslationLanguages() { auto title = tr::lng_translate_settings_choose(); const auto selected = std::make_shared>( Core::App().settings().skipTranslationLanguages()); - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto check = [=](LanguageId id) { const auto already = ranges::contains(*selected, id); if (already) { @@ -316,7 +316,7 @@ object_ptr EditSkipTranslationLanguages() { selected->push_back(id); } if (already && selected->empty()) { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->showToast( tr::lng_translate_settings_one(tr::now), kSkipAtLeastOneDuration); diff --git a/Telegram/SourceFiles/boxes/url_auth_box.cpp b/Telegram/SourceFiles/boxes/url_auth_box.cpp index 3dc29d9222..3047bbb771 100644 --- a/Telegram/SourceFiles/boxes/url_auth_box.cpp +++ b/Telegram/SourceFiles/boxes/url_auth_box.cpp @@ -134,7 +134,7 @@ void UrlAuthBox::Request( const auto bot = request.is_request_write_access() ? session->data().processUser(request.vbot()).get() : nullptr; - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto finishWithUrl = [=](const QString &url) { if (*box) { (*box)->closeBox(); @@ -185,7 +185,7 @@ void UrlAuthBox::Request( const auto bot = request.is_request_write_access() ? session->data().processUser(request.vbot()).get() : nullptr; - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto finishWithUrl = [=](const QString &url) { if (*box) { (*box)->closeBox(); diff --git a/Telegram/SourceFiles/calls/calls_box_controller.cpp b/Telegram/SourceFiles/calls/calls_box_controller.cpp index 372aa37c53..a68484c217 100644 --- a/Telegram/SourceFiles/calls/calls_box_controller.cpp +++ b/Telegram/SourceFiles/calls/calls_box_controller.cpp @@ -711,7 +711,7 @@ std::unique_ptr BoxController::createRow( void ClearCallsBox( not_null box, not_null<::Window::SessionController*> window) { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); box->addRow( object_ptr( box, @@ -754,7 +754,7 @@ void ClearCallsBox( self(revoke, self); } else { api->session().data().destroyAllCallItems(); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } } diff --git a/Telegram/SourceFiles/calls/calls_emoji_fingerprint.cpp b/Telegram/SourceFiles/calls/calls_emoji_fingerprint.cpp index 164f754c3d..7432c4a6b3 100644 --- a/Telegram/SourceFiles/calls/calls_emoji_fingerprint.cpp +++ b/Telegram/SourceFiles/calls/calls_emoji_fingerprint.cpp @@ -604,9 +604,9 @@ void SetupFingerprintTooltip(not_null widget) { st::confcallFingerprintTooltipLabel), st::confcallFingerprintTooltip); const auto raw = state->tooltip.get(); - const auto weak = QPointer(raw); + const auto weak = base::make_weak(raw); const auto destroy = [=] { - delete weak.data(); + delete weak.get(); }; raw->setAttribute(Qt::WA_TransparentForMouseEvents); raw->setHiddenCallback(destroy); diff --git a/Telegram/SourceFiles/calls/group/calls_choose_join_as.cpp b/Telegram/SourceFiles/calls/group/calls_choose_join_as.cpp index a3f57de101..137417a9e0 100644 --- a/Telegram/SourceFiles/calls/group/calls_choose_join_as.cpp +++ b/Telegram/SourceFiles/calls/group/calls_choose_join_as.cpp @@ -393,7 +393,7 @@ void ChooseJoinAsProcess::finish(JoinInfo info) { const auto box = _request->box; _request = nullptr; done(std::move(info)); - if (const auto strong = box.data()) { + if (const auto strong = box.get()) { strong->closeBox(); } } diff --git a/Telegram/SourceFiles/calls/group/calls_choose_join_as.h b/Telegram/SourceFiles/calls/group/calls_choose_join_as.h index eb899b5568..673546ffa1 100644 --- a/Telegram/SourceFiles/calls/group/calls_choose_join_as.h +++ b/Telegram/SourceFiles/calls/group/calls_choose_join_as.h @@ -51,7 +51,7 @@ private: std::shared_ptr show; Fn done; base::has_weak_ptr guard; - QPointer box; + base::weak_qptr box; rpl::lifetime lifetime; Context context = Context(); mtpRequestId id = 0; diff --git a/Telegram/SourceFiles/calls/group/calls_group_common.cpp b/Telegram/SourceFiles/calls/group/calls_group_common.cpp index fab26cc837..066d140861 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_common.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_common.cpp @@ -213,8 +213,8 @@ void ConferenceCallJoinConfirm( )->setTryMakeSimilarLines(true); } const auto joinAndClose = [=] { - join([weak = Ui::MakeWeak(box)] { - if (const auto strong = weak.data()) { + join([weak = base::make_weak(box)] { + if (const auto strong = weak.get()) { strong->closeBox(); } }); @@ -275,7 +275,7 @@ void ShowConferenceCallLinkBox( } state->resetting = true; using Flag = MTPphone_ToggleGroupCallSettings::Flag; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); call->session().api().request( MTPphone_ToggleGroupCallSettings( MTP_flags(Flag::f_reset_invite_hash), @@ -284,7 +284,7 @@ void ShowConferenceCallLinkBox( ).done([=](const MTPUpdates &result) { call->session().api().applyUpdates(result); ShowConferenceCallLinkBox(show, call, args); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } show->showToast({ diff --git a/Telegram/SourceFiles/calls/group/calls_group_invite_controller.cpp b/Telegram/SourceFiles/calls/group/calls_group_invite_controller.cpp index cd04eb32fa..6994aff627 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_invite_controller.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_invite_controller.cpp @@ -943,7 +943,7 @@ object_ptr PrepareInviteBox( : (nonMembers.size() < users.size()) ? tr::lng_group_call_add_to_group_some(tr::now, lt_group, name) : tr::lng_group_call_add_to_group_all(tr::now, lt_group, name); - const auto shared = std::make_shared>(); + const auto shared = std::make_shared>(); const auto finishWithConfirm = [=] { if (*shared) { (*shared)->closeBox(); @@ -983,7 +983,7 @@ object_ptr PrepareInviteBox( return !controller->hasRowFor(user); }) | ranges::to_vector; - const auto finish = [box = Ui::MakeWeak(box)]() { + const auto finish = [box = base::make_weak(box)]() { if (box) { box->closeBox(); } @@ -1098,14 +1098,14 @@ object_ptr PrepareInviteToEmptyBox( }, box->lifetime()); const auto join = [=] { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); auto selected = raw->requests(box->collectSelectedRows()); Core::App().calls().startOrJoinConferenceCall({ .call = call, .joinMessageId = inviteMsgId, .invite = std::move(selected), }); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index d5ce0e5791..67a82ccb7d 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -1346,16 +1346,16 @@ base::unique_qptr Members::Controller::createRowContextMenu( : addVolumeItem ? st::groupCallPopupMenuWithVolume : st::groupCallPopupMenu)); - const auto weakMenu = Ui::MakeWeak(result.get()); + const auto weakMenu = base::make_weak(result.get()); const auto withActiveWindow = [=](auto callback) { if (const auto window = Core::App().activePrimaryWindow()) { - if (const auto menu = weakMenu.data()) { + if (const auto menu = weakMenu.get()) { menu->discardParentReActivate(); // We must hide PopupMenu before we activate the MainWindow, // otherwise we set focus in field inside MainWindow and then // PopupMenu::hide activates back the group call panel :( - delete weakMenu; + delete weakMenu.get(); } window->invokeForSessionController( account, diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index f3d2c524ed..ce9c69b195 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -407,7 +407,7 @@ void Panel::startScheduledNow() { } else if (now + kStartNoConfirmation >= date) { _call->startScheduledNow(); } else { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto done = [=] { if (*box) { (*box)->closeBox(); @@ -1377,7 +1377,7 @@ void Panel::chooseShareScreenSource() { tr::now, lt_user, screencastFromPeer->shortName()); - const auto shared = std::make_shared>(); + const auto shared = std::make_shared>(); const auto done = [=] { if (*shared) { base::take(*shared)->closeBox(); @@ -2072,9 +2072,9 @@ void Panel::showNiceTooltip( ? st::groupCallStickedTooltip : st::groupCallNiceTooltip)); const auto tooltip = _niceTooltip.data(); - const auto weak = QPointer(tooltip); + const auto weak = base::make_weak(tooltip); const auto destroy = [=] { - delete weak.data(); + delete weak.get(); }; if (type != NiceTooltipType::Sticked) { tooltip->setAttribute(Qt::WA_TransparentForMouseEvents); @@ -2098,9 +2098,9 @@ void Panel::updateTooltipGeometry() { return; } const auto geometry = _niceTooltipControl->geometry(); - const auto weak = QPointer(_niceTooltip); + const auto weak = base::make_weak(_niceTooltip); const auto countPosition = [=](QSize size) { - const auto strong = weak.data(); + const auto strong = weak.get(); const auto wide = (_mode.current() == PanelMode::Wide); const auto top = geometry.y() - (wide ? st::groupCallNiceTooltipTop : 0) diff --git a/Telegram/SourceFiles/calls/group/calls_group_rtmp.cpp b/Telegram/SourceFiles/calls/group/calls_group_rtmp.cpp index db94f72cb0..9c35ed529d 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_rtmp.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_rtmp.cpp @@ -133,7 +133,7 @@ void StartRtmpProcess::start( void StartRtmpProcess::close() { if (_request) { _request->peer->session().api().request(_request->id).cancel(); - if (const auto strong = _request->box.data()) { + if (const auto strong = _request->box.get()) { strong->closeBox(); } _request = nullptr; @@ -199,7 +199,7 @@ void StartRtmpProcess::createBox() { ) | rpl::start_with_next([=] { _request = nullptr; }, _request->lifetime); - _request->box = Ui::MakeWeak(object.data()); + _request->box = base::make_weak(object.data()); _request->show->showBox(std::move(object)); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_rtmp.h b/Telegram/SourceFiles/calls/group/calls_group_rtmp.h index eb5d4b5fa6..c3cadab12d 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_rtmp.h +++ b/Telegram/SourceFiles/calls/group/calls_group_rtmp.h @@ -64,7 +64,7 @@ private: std::shared_ptr show; Fn done; base::has_weak_ptr guard; - QPointer box; + base::weak_qptr box; rpl::lifetime lifetime; mtpRequestId id = 0; }; diff --git a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp index 0adbb8e3e9..cb70c06e6d 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp @@ -110,7 +110,7 @@ object_ptr ShareInviteLinkBox( const QString &linkListener, std::shared_ptr show) { const auto sending = std::make_shared(); - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); auto bottom = linkSpeaker.isEmpty() ? nullptr @@ -220,7 +220,7 @@ void SettingsBox( using namespace Settings; const auto weakCall = base::make_weak(call); - const auto weakBox = Ui::MakeWeak(box); + const auto weakBox = base::make_weak(box); struct State { std::unique_ptr deviceId; diff --git a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp index a122f09a24..40712391b8 100644 --- a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp +++ b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp @@ -351,18 +351,18 @@ void ChooseSourceProcess::setupPanel() { if (_selectedId.isEmpty()) { return; } - const auto weak = MakeWeak(_window.get()); + const auto weak = base::make_weak(_window.get()); _delegate->chooseSourceAccepted( _selectedId, !_withAudio->isHidden() && _withAudio->checked()); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->close(); } }); _finish->setClickedCallback([=] { - const auto weak = MakeWeak(_window.get()); + const auto weak = base::make_weak(_window.get()); _delegate->chooseSourceStop(); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->close(); } }); diff --git a/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp b/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp index 2f88f8202d..38b54e3518 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp @@ -173,7 +173,7 @@ Loader::Loader( void Loader::unpack(const QString &path) { const auto folder = internal::SetDataPath(id()); - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); crl::async([=] { if (UnpackSet(path, folder)) { QFile(path).remove(); diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index 87fd388861..16f3a8f73a 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -984,7 +984,7 @@ void SuggestionsController::replaceCurrent( const auto position = cursor.position(); const auto suggestion = getEmojiQuery(); if (v::is(suggestion)) { - const auto weak = Ui::MakeWeak(_container.get()); + const auto weak = base::make_weak(_container.get()); const auto count = std::max(_emojiQueryLength, 1); for (auto i = 0; i != count; ++i) { const auto start = position - count + i; diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index 200ad997e8..8f5172c567 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -202,7 +202,7 @@ void EditLinkBox( url->showError(); return; } - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); callback(linkText, linkUrl); if (weak) { box->closeBox(); @@ -304,9 +304,9 @@ void EditCodeLanguageBox( const auto name = field->getLastText().trimmed(); const auto check = QRegularExpression("^[a-zA-Z0-9\\+\\-]*$"); if (check.match(name).hasMatch()) { - auto weak = Ui::MakeWeak(box); + auto weak = base::make_weak(box); save(name); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } } else { @@ -401,7 +401,7 @@ Fn show, not_null field, const style::InputField *fieldStyle) { - const auto weak = Ui::MakeWeak(field); + const auto weak = base::make_weak(field); return [=]( EditLinkSelection selection, TextWithTags text, @@ -412,7 +412,7 @@ FncommitMarkdownLinkEdit(selection, text, link); } }; @@ -484,7 +484,7 @@ void InitMessageFieldHandlers(MessageFieldHandlersArgs &&args) { EditLinkAction action)> FactcheckEditLinkCallback( std::shared_ptr show, not_null field) { - const auto weak = Ui::MakeWeak(field); + const auto weak = base::make_weak(field); return [=]( EditLinkSelection selection, TextWithTags text, @@ -503,7 +503,7 @@ void InitMessageFieldHandlers(MessageFieldHandlersArgs &&args) { return IsGoodFactcheckUrl(link); } auto callback = [=](const TextWithTags &text, const QString &link) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->commitMarkdownLinkEdit(selection, text, link); } }; @@ -696,9 +696,9 @@ void InitMessageFieldFade( bottomFade->move( 0, size.height() - st::historyComposeFieldFadeHeight); - }, [t = Ui::MakeWeak(topFade), b = Ui::MakeWeak(bottomFade)] { - Ui::DestroyChild(t.data()); - Ui::DestroyChild(b.data()); + }, [t = base::make_weak(topFade), b = base::make_weak(bottomFade)] { + Ui::DestroyChild(t.get()); + Ui::DestroyChild(b.get()); }, topFade->lifetime()); const auto descent = field->st().style.font->descent; diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index fed2bbd128..ecf20568ee 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -1736,8 +1736,8 @@ void StickersListWidget::showStickerSetBox( base::timer_once(kTimeout), document->owner().stickers().updated( Data::StickersType::Stickers) - ) | rpl::start_with_next([=, weak = Ui::MakeWeak(this)] { - if (weak.data()) { + ) | rpl::start_with_next([=, weak = base::make_weak(this)] { + if (weak.get()) { showStickerSetBox(document, setId); } lifetime->destroy(); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 04d49849d2..68437e450e 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -1471,13 +1471,13 @@ void TabbedSelector::Inner::disableScroll(bool disabled) { void TabbedSelector::Inner::checkHideWithBox( object_ptr box) { - const auto raw = QPointer(box.data()); + const auto raw = base::make_weak(box.data()); _show->showBox(std::move(box)); if (!raw) { return; } _preventHideWithBox = true; - connect(raw, &QObject::destroyed, this, [=] { + connect(raw.get(), &QObject::destroyed, this, [=] { _preventHideWithBox = false; _checkForHide.fire({}); }); diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index 53e01dd106..51fa20fcc6 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -902,7 +902,7 @@ void Application::forceLogOut( box->setCloseByEscape(false); box->setCloseByOutsideClick(false); const auto weak = base::make_weak(account); - connect(box, &QObject::destroyed, [=] { + connect(box.get(), &QObject::destroyed, [=] { crl::on_main(weak, [=] { account->forcedLogOut(); }); @@ -1669,7 +1669,7 @@ void Application::registerLeaveSubscription(not_null widget) { if (e->type() == QEvent::Leave) { if (const auto taken = _leaveFilters.take(window)) { for (const auto &weak : taken->registered) { - if (const auto widget = weak.data()) { + if (const auto widget = weak.get()) { QEvent ev(QEvent::Leave); QCoreApplication::sendEvent(widget, &ev); } diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index bfb330d351..24bec04def 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -437,7 +437,7 @@ private: const std::unique_ptr _langCloudManager; const std::unique_ptr _emojiKeywords; std::unique_ptr _translator; - QPointer _badProxyDisableBox; + base::weak_qptr _badProxyDisableBox; const std::unique_ptr _tray; diff --git a/Telegram/SourceFiles/core/phone_click_handler.cpp b/Telegram/SourceFiles/core/phone_click_handler.cpp index ec34b8f8be..167aec1653 100644 --- a/Telegram/SourceFiles/core/phone_click_handler.cpp +++ b/Telegram/SourceFiles/core/phone_click_handler.cpp @@ -340,7 +340,7 @@ void PhoneClickHandler::onClick(ClickContext context) const { if (Trim(phone) != Trim(controller->session().user()->phone())) { menu->addAction( tr::lng_info_add_as_contact(tr::now), - [=, raw = Ui::MakeWeak(resolvePhoneAction.get())] { + [=, raw = base::make_weak(resolvePhoneAction.get())] { controller->show( Box( &controller->session(), diff --git a/Telegram/SourceFiles/data/data_document_resolver.cpp b/Telegram/SourceFiles/data/data_document_resolver.cpp index 13b30f0bd2..eea69ed577 100644 --- a/Telegram/SourceFiles/data/data_document_resolver.cpp +++ b/Telegram/SourceFiles/data/data_document_resolver.cpp @@ -57,7 +57,7 @@ void ConfirmDontWarnBox( std::move(check), false, st::defaultBoxCheckbox); - const auto weak = Ui::MakeWeak(checkbox.data()); + const auto weak = base::make_weak(checkbox.data()); auto confirmed = crl::guard(weak, [=, callback = std::move(callback)] { const auto checked = weak->checked(); box->closeBox(); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 701eaf08db..cfcf028718 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -1008,7 +1008,7 @@ private: Storage::DatabasePointer _bigFileCache; TimeId _exportAvailableAt = 0; - QPointer _exportSuggestion; + base::weak_qptr _exportSuggestion; rpl::variable _contactsLoaded = false; rpl::variable _groupFreeTranscribeLevel; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 2cbe2d23f0..4ec8f4455c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1966,9 +1966,9 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) { }); } else if (_pressed) { auto row = _pressed; - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto updateCallback = [weak, row] { - const auto strong = weak.data(); + const auto strong = weak.get(); if (!strong || !strong->_pinnedShiftAnimation.animating()) { row->entry()->updateChatListEntry(); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index ffcd9dce43..c45a82a2b6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -1010,7 +1010,7 @@ void Widget::setGeometryWithTopMoved( _topDelta = topDelta; bool willBeResized = (size() != newGeometry.size()); if (geometry() != newGeometry) { - auto weak = Ui::MakeWeak(this); + auto weak = base::make_weak(this); setGeometry(newGeometry); if (!weak) { return; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp index ae4a4768cd..a66fe7488b 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp @@ -1452,7 +1452,7 @@ void Suggestions::setupChats() { _topPeers->showMenuRequests( ) | rpl::start_with_next([=](const ShowTopPeerMenuRequest &request) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto owner = &_controller->session().data(); const auto peer = owner->peer(PeerId(request.id)); const auto removeOne = [=] { diff --git a/Telegram/SourceFiles/editor/editor_layer_widget.cpp b/Telegram/SourceFiles/editor/editor_layer_widget.cpp index baa149d5a1..fc2096fa37 100644 --- a/Telegram/SourceFiles/editor/editor_layer_widget.cpp +++ b/Telegram/SourceFiles/editor/editor_layer_widget.cpp @@ -157,12 +157,12 @@ void LayerWidget::checkCacheBackground() { void LayerWidget::cacheBackground() { _backgroundCaching = true; - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto night = IsNightMode(); crl::async([weak, night, image = renderBackground()]() mutable { auto result = ProcessBackground(image, night); crl::on_main([weak, night, result = std::move(result)]() mutable { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->backgroundReady(std::move(result), night); } }); diff --git a/Telegram/SourceFiles/editor/photo_editor.cpp b/Telegram/SourceFiles/editor/photo_editor.cpp index 801e122582..0ec6de90b4 100644 --- a/Telegram/SourceFiles/editor/photo_editor.cpp +++ b/Telegram/SourceFiles/editor/photo_editor.cpp @@ -228,12 +228,12 @@ void InitEditorLayer( layer->closeLayer(); }, editor->lifetime()); - const auto weak = Ui::MakeWeak(layer.get()); + const auto weak = base::make_weak(layer.get()); editor->doneRequests( ) | rpl::start_with_next([=, done = std::move(doneCallback)]( const PhotoModifications &mods) { done(mods); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeLayer(); } }, editor->lifetime()); diff --git a/Telegram/SourceFiles/export/export_api_wrap.cpp b/Telegram/SourceFiles/export/export_api_wrap.cpp index bbc19fb5ea..fbb5b258eb 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.cpp +++ b/Telegram/SourceFiles/export/export_api_wrap.cpp @@ -404,7 +404,9 @@ auto ApiWrap::fileRequest(const Data::FileLocation &location, int64 offset) { }).toDC(MTP::ShiftDcId(location.dcId, MTP::kExportMediaDcShift))); } -ApiWrap::ApiWrap(QPointer weak, Fn)> runner) +ApiWrap::ApiWrap( + base::weak_qptr weak, + Fn)> runner) : _mtp(weak, std::move(runner)) , _fileCache(std::make_unique(kLocationCacheSize)) { } diff --git a/Telegram/SourceFiles/export/export_api_wrap.h b/Telegram/SourceFiles/export/export_api_wrap.h index 6073243152..de76417bc7 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.h +++ b/Telegram/SourceFiles/export/export_api_wrap.h @@ -40,7 +40,9 @@ struct Settings; class ApiWrap { public: - ApiWrap(QPointer weak, Fn)> runner); + ApiWrap( + base::weak_qptr weak, + Fn)> runner); rpl::producer errors() const; rpl::producer ioErrors() const; diff --git a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp index 4aef9c36e6..d65be8f077 100644 --- a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp +++ b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp @@ -96,11 +96,11 @@ Environment PrepareEnvironment(not_null session) { return result; } -QPointer SuggestStart(not_null session) { +base::weak_qptr SuggestStart(not_null session) { ClearSuggestStart(session); return Ui::show( Box(session), - Ui::LayerOption::KeepOther).data(); + Ui::LayerOption::KeepOther).get(); } void ClearSuggestStart(not_null session) { @@ -277,7 +277,7 @@ void PanelController::showCriticalError(const QString &text) { void PanelController::showError(const QString &text) { auto box = Ui::MakeInformBox(text); - const auto weak = Ui::MakeWeak(box.data()); + const auto weak = base::make_weak(box.data()); const auto hidden = _panel->isHidden(); _panel->showBox( std::move(box), diff --git a/Telegram/SourceFiles/export/view/export_view_panel_controller.h b/Telegram/SourceFiles/export/view/export_view_panel_controller.h index 70c72f8a69..b820202c3d 100644 --- a/Telegram/SourceFiles/export/view/export_view_panel_controller.h +++ b/Telegram/SourceFiles/export/view/export_view_panel_controller.h @@ -24,7 +24,7 @@ class Session; namespace Export { namespace View { -QPointer SuggestStart(not_null session); +base::weak_qptr SuggestStart(not_null session); void ClearSuggestStart(not_null session); bool IsDefaultPath(not_null session, const QString &path); void ResolveSettings(not_null session, Settings &settings); @@ -79,7 +79,7 @@ private: base::unique_qptr _panel; State _state; - QPointer _confirmStopBox; + base::weak_qptr _confirmStopBox; rpl::event_stream> _panelCloseEvents; bool _stopRequested = false; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/export/view/export_view_progress.cpp b/Telegram/SourceFiles/export/view/export_view_progress.cpp index dabda8280d..c7d28c7d47 100644 --- a/Telegram/SourceFiles/export/view/export_view_progress.cpp +++ b/Telegram/SourceFiles/export/view/export_view_progress.cpp @@ -51,8 +51,8 @@ private: void hideCurrentInstance(); void setInstanceProgress(Instance &instance, float64 progress); void toggleInstance(Instance &data, bool shown); - void instanceOpacityCallback(QPointer label); - void removeOldInstance(QPointer label); + void instanceOpacityCallback(base::weak_qptr label); + void removeOldInstance(base::weak_qptr label); void paintInstance(QPainter &p, const Instance &data); void updateControlsGeometry(int newWidth); @@ -146,7 +146,7 @@ void ProgressWidget::Row::toggleInstance(Instance &instance, bool shown) { if (instance.hiding != shown) { return; } - const auto label = Ui::MakeWeak(instance.label->entity()); + const auto label = base::make_weak(instance.label->entity()); instance.opacity.start( [=] { instanceOpacityCallback(label); }, shown ? 0. : 1., @@ -158,10 +158,10 @@ void ProgressWidget::Row::toggleInstance(Instance &instance, bool shown) { } void ProgressWidget::Row::instanceOpacityCallback( - QPointer label) { + base::weak_qptr label) { update(); const auto i = ranges::find(_old, label, [](const Instance &instance) { - return Ui::MakeWeak(instance.label->entity()); + return base::make_weak(instance.label->entity()); }); if (i != end(_old) && i->hiding && !i->opacity.animating()) { crl::on_main(this, [=] { @@ -170,9 +170,10 @@ void ProgressWidget::Row::instanceOpacityCallback( } } -void ProgressWidget::Row::removeOldInstance(QPointer label) { +void ProgressWidget::Row::removeOldInstance( + base::weak_qptr label) { const auto i = ranges::find(_old, label, [](const Instance &instance) { - return Ui::MakeWeak(instance.label->entity()); + return base::make_weak(instance.label->entity()); }); if (i != end(_old)) { _old.erase(i); diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp index bc25b60394..e610471279 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.cpp +++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp @@ -320,20 +320,20 @@ void SettingsWidget::addLocationLabel( } void SettingsWidget::chooseFormat() { - const auto shared = std::make_shared>(); + const auto shared = std::make_shared>(); const auto callback = [=](Format format) { changeData([&](Settings &data) { data.format = format; }); - if (const auto weak = shared->data()) { - weak->closeBox(); + if (const auto strong = shared->get()) { + strong->closeBox(); } }; auto box = Box( ChooseFormatBox, readData().format, callback); - *shared = Ui::MakeWeak(box.data()); + *shared = base::make_weak(box.data()); _showBoxCallback(std::move(box)); } @@ -602,18 +602,18 @@ void SettingsWidget::editDateLimit( ? base::unixtime::parse(min).date() : QDate::currentDate(); const auto month = highlighted; - const auto shared = std::make_shared>(); + const auto shared = std::make_shared>(); const auto finalize = [=](not_null box) { box->addLeftButton(std::move(resetLabel), crl::guard(this, [=] { done(0); - if (const auto weak = shared->data()) { + if (const auto weak = shared->get()) { weak->closeBox(); } })); }; const auto callback = crl::guard(this, [=](const QDate &date) { done(base::unixtime::serialize(date.startOfDay())); - if (const auto weak = shared->data()) { + if (const auto weak = shared->get()) { weak->closeBox(); } }); @@ -630,7 +630,7 @@ void SettingsWidget::editDateLimit( ? base::unixtime::parse(max).date() : QDate::currentDate()), }); - *shared = Ui::MakeWeak(box.data()); + *shared = base::make_weak(box.data()); _showBoxCallback(std::move(box)); } 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 0d917654d4..c47e562fae 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -1530,7 +1530,7 @@ void InnerWidget::suggestRestrictParticipant( UserData *by, TimeId since) { auto weak = QPointer(this); - auto weakBox = std::make_shared>(); + auto weakBox = std::make_shared>(); auto box = Box( _channel, user, @@ -1560,7 +1560,7 @@ void InnerWidget::suggestRestrictParticipant( tr::now, lt_user, participant->name()); - auto weakBox = std::make_shared>(); + auto weakBox = std::make_shared>(); const auto sure = crl::guard(this, [=] { restrictParticipant( participant, @@ -1810,10 +1810,8 @@ void InnerWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton but ActivateClickHandler(window(), activated, { button, QVariant::fromValue(ClickHandlerContext{ - .elementDelegate = [weak = Ui::MakeWeak(this)] { - return weak - ? (ElementDelegate*)weak - : nullptr; + .elementDelegate = [weak = base::make_weak(this)] { + return (ElementDelegate*)weak.get(); }, .sessionWindow = base::make_weak(_controller), }) diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index e897e65f26..bdfe45ca02 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1671,7 +1671,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) { _touchInProgress = false; const auto notMoved = (_touchPos - _touchStart).manhattanLength() < QApplication::startDragDistance(); - auto weak = Ui::MakeWeak(this); + auto weak = base::make_weak(this); if (_touchSelect) { if (notMoved || _touchMaybeSelecting.current()) { mouseActionFinish(_touchPos, Qt::RightButton); diff --git a/Telegram/SourceFiles/history/history_item_helpers.cpp b/Telegram/SourceFiles/history/history_item_helpers.cpp index 57bddb387e..762419f53a 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.cpp +++ b/Telegram/SourceFiles/history/history_item_helpers.cpp @@ -356,7 +356,7 @@ void ShowSendPaidConfirm( const auto messages = details.messages; const auto stars = details.stars; show->showBox(Box([=](not_null box) { - const auto trust = std::make_shared>(); + const auto trust = std::make_shared>(); const auto proceed = [=](Fn close) { if (singlePeer && (*trust)->checked()) { const auto session = &singlePeer->session(); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 9ab254a5e5..7d9f5765a4 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1024,7 +1024,7 @@ void HistoryWidget::setGeometryWithTopMoved( _topDelta = topDelta; bool willBeResized = (size() != newGeometry.size()); if (geometry() != newGeometry) { - auto weak = Ui::MakeWeak(this); + auto weak = base::make_weak(this); setGeometry(newGeometry); if (!weak) { return; @@ -4494,7 +4494,7 @@ void HistoryWidget::saveEditMessage(Api::SendOptions options) { } } - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto history = _history; const auto done = [=](mtpRequestId requestId) { @@ -5603,7 +5603,7 @@ bool HistoryWidget::searchInChatEmbedded( if (!peer || Window::SeparateId(peer) != controller()->windowId()) { return false; } else if (_peer != peer) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); controller()->showPeerHistory(peer); if (!weak) { return false; @@ -9054,9 +9054,9 @@ void HistoryWidget::forwardSelected() { if (!_list) { return; } - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); Window::ShowForwardMessagesBox(controller(), getSelectedItems(), [=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->clearSelected(); } }); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_search.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_search.cpp index 98064d0204..478ccdba89 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_search.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_search.cpp @@ -256,9 +256,9 @@ List CreateList( }, list.container->lifetime()); list.container->paintRequest( - ) | rpl::start_with_next([weak = Ui::MakeWeak(list.container.get())]( + ) | rpl::start_with_next([weak = base::make_weak(list.container.get())]( const QRect &r) { - auto p = QPainter(weak); + auto p = QPainter(weak.get()); p.fillRect(r, st::dialogsBg); }, list.container->lifetime()); @@ -937,7 +937,7 @@ ComposeSearch::Inner::Inner( _apiSearch.newFounds( ) | rpl::start_with_next([=] { const auto &apiData = _apiSearch.messages(); - const auto weak = Ui::MakeWeak(_bottomBar.get()); + const auto weak = base::make_weak(_bottomBar.get()); _bottomBar->setTotal(apiData.total); if (weak) { // Activating the first search result may switch the chat. @@ -970,7 +970,7 @@ ComposeSearch::Inner::Inner( _pendingJump.data = {}; const auto item = _history->owner().message(messages[index]); if (item) { - const auto weak = Ui::MakeWeak(_topBar.get()); + const auto weak = base::make_weak(_topBar.get()); _activations.fire_copy({ item, _apiSearch.request().query }); if (weak) { hideList(); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp index 15125a480b..253073f8dc 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp @@ -819,7 +819,7 @@ void DraftOptionsBox( FullReplyTo result, Data::WebPageDraft webpage, std::optional options) { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); auto forward = Data::ForwardDraft(); if (options) { forward.options = *options; @@ -828,7 +828,7 @@ void DraftOptionsBox( } } done(std::move(result), std::move(webpage), std::move(forward)); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; @@ -847,7 +847,7 @@ void DraftOptionsBox( }); } - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); Settings::AddButtonWithIcon( bottom, tr::lng_reply_show_in_chat(), @@ -855,7 +855,7 @@ void DraftOptionsBox( { &st::menuIconShowInChat } )->setClickedCallback([=] { highlight(resolveReply()); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); @@ -1402,10 +1402,10 @@ void ShowReplyToChatBox( }; auto callback = [=, chosen = std::move(chosen)]( Controller::Chosen thread) mutable { - const auto weak = Ui::MakeWeak(state->box); + const auto weak = base::make_weak(state->box); if (!chosen(thread)) { return; - } else if (const auto strong = weak.data()) { + } else if (const auto strong = weak.get()) { strong->closeBox(); } }; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp index de53aeb673..8a8b30fff8 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp @@ -434,11 +434,11 @@ void EditWebPageOptions( }); box->addButton(tr::lng_settings_save(), [=] { - const auto weak = Ui::MakeWeak(box.get()); + const auto weak = base::make_weak(box.get()); auto result = state->result.current(); result.manual = true; done(result); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp b/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp index f599f8a63b..0784d82782 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp @@ -484,13 +484,13 @@ void ChooseSuggestPriceBox( st::settingsButtonNoIcon); time->setClickedCallback([=] { - const auto weak = std::make_shared>(); - const auto parentWeak = Ui::MakeWeak(box); + const auto weak = std::make_shared>(); + const auto parentWeak = base::make_weak(box); const auto done = [=](TimeId result) { if (parentWeak) { state->date = result; } - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; @@ -793,12 +793,12 @@ void SuggestOptions::paintLines(QPainter &p, int x, int y, int outerWidth) { } void SuggestOptions::edit() { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto apply = [=](SuggestPostOptions values) { _values = values; updateTexts(); _updates.fire({}); - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp index 2f4cc7192c..8df2628252 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp @@ -2082,7 +2082,7 @@ void VoiceRecordBar::stopRecording(StopType type, bool ttlBeforeHide) { } } else if (type == StopType::Send) { if (_videoRecorder) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); _videoRecorder->hide([=](Ui::RoundVideoResult data) { crl::on_main([=, data = std::move(data)]() mutable { if (weak) { diff --git a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp index 5e9d3eecdd..353a9acec4 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp +++ b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp @@ -941,9 +941,9 @@ ChatPreview MakeChatPreview( result.actions = action->actions(); menu->addAction(std::move(action)); if (const auto topic = thread->asTopic()) { - const auto weak = Ui::MakeWeak(menu); + const auto weak = base::make_weak(menu); topic->destroyed() | rpl::start_with_next([weak] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { LOG(("Preview hidden for a destroyed topic.")); strong->hideMenu(true); } diff --git a/Telegram/SourceFiles/history/view/history_view_chat_section.cpp b/Telegram/SourceFiles/history/view/history_view_chat_section.cpp index 4f8595266a..fc4cf0fc3c 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_chat_section.cpp @@ -2315,9 +2315,9 @@ bool ChatWidget::preventsClose(Fn &&continueCallback) const { } else if (!_newTopicDiscarded && _topic && _topic->creating()) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); auto sure = [=](Fn &&close) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->_newTopicDiscarded = true; } close(); @@ -2602,7 +2602,7 @@ void ChatWidget::subscribeToSublist() { void ChatWidget::unreadCountUpdated() { if (_sublist && _sublist->unreadMark()) { crl::on_main(this, [=] { - const auto guard = Ui::MakeWeak(this); + const auto guard = base::make_weak(this); controller()->showPeerHistory(_sublist->owningHistory()); if (guard) { closeCurrent(); diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp index 99c135f6f3..b0a48e1bdb 100644 --- a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp +++ b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp @@ -947,8 +947,8 @@ void BusinessBotStatus::Bar::showMenu() { this, st::popupMenuExpandedSeparator); _menu->setDestroyedCallback([ - weak = Ui::MakeWeak(this), - weakButton = Ui::MakeWeak(_settings.data()), + weak = base::make_weak(this), + weakButton = base::make_weak(_settings.data()), menu = _menu.get()] { if (weak && weak->_menu == menu) { if (weakButton) { diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 3acc55e811..84e258e2fb 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -287,9 +287,9 @@ void AddDocumentActions( item->history()->peer, document); if (notAutoplayedGif) { - const auto weak = Ui::MakeWeak(list.get()); + const auto weak = base::make_weak(list.get()); menu->addAction(tr::lng_context_open_gif(tr::now), [=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { OpenGif(strong, contextId); } }, &st::menuIconShowInChat); @@ -390,9 +390,9 @@ bool AddForwardSelectedAction( } menu->addAction(tr::lng_context_forward_selected(tr::now), [=] { - const auto weak = Ui::MakeWeak(list); + const auto weak = base::make_weak(list); const auto callback = [=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->cancelSelection(); } }; @@ -471,7 +471,7 @@ bool AddSendNowSelectedAction( const auto history = *histories.begin(); menu->addAction(tr::lng_context_send_now_selected(tr::now), [=] { - const auto weak = Ui::MakeWeak(list); + const auto weak = base::make_weak(list); const auto callback = [=] { request.navigation->showBackFromStack(); }; @@ -1149,9 +1149,9 @@ void EditTagBox( field->showError(); return; } - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); controller->session().data().reactions().renameTag(id, text); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }; @@ -1629,10 +1629,10 @@ void AddWhoReactedAction( not_null item, not_null controller) { const auto whoReadIds = std::make_shared(); - const auto weak = Ui::MakeWeak(menu.get()); + const auto weak = base::make_weak(menu.get()); const auto user = item->history()->peer; const auto showOrPremium = [=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->hideMenu(); } const auto type = Ui::ShowOrPremium::ReadTime; @@ -1647,14 +1647,14 @@ void AddWhoReactedAction( }; const auto itemId = item->fullId(); const auto participantChosen = [=](Ui::WhoReadParticipant who) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->hideMenu(); } ShowWhoReadInfo(controller, itemId, who); }; const auto showAllChosen = [=, itemId = item->fullId()]{ // Pressing on an item that has a submenu doesn't hide it :( - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->hideMenu(); } if (const auto item = controller->session().data().message(itemId)) { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 6077d1a1f6..6a46231354 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -3123,7 +3123,7 @@ void ListWidget::touchEvent(QTouchEvent *e) { return; } _touchInProgress = false; - auto weak = Ui::MakeWeak(this); + auto weak = base::make_weak(this); const auto notMoved = (_touchPos - _touchStart).manhattanLength() < QApplication::startDragDistance(); if (_touchSelect) { @@ -3625,10 +3625,8 @@ void ListWidget::mouseActionFinish( ClickHandlerContext ListWidget::prepareClickHandlerContext(FullMsgId id) { return { .itemId = id, - .elementDelegate = [weak = Ui::MakeWeak(this)] { - return weak - ? (ElementDelegate*)weak - : nullptr; + .elementDelegate = [weak = base::make_weak(this)] { + return (ElementDelegate*)weak.get(); }, .sessionWindow = base::make_weak(controller()), }; @@ -4347,9 +4345,9 @@ void ConfirmForwardSelectedItems(not_null widget) { } } auto ids = widget->getSelectedIds(); - const auto weak = Ui::MakeWeak(widget); + const auto weak = base::make_weak(widget); Window::ShowForwardMessagesBox(widget->controller(), std::move(ids), [=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->cancelSelection(); } }); @@ -4378,8 +4376,8 @@ void ConfirmSendNowSelectedItems(not_null widget) { if (!history) { return; } - const auto clearSelection = [weak = Ui::MakeWeak(widget)] { - if (const auto strong = weak.data()) { + const auto clearSelection = [weak = base::make_weak(widget)] { + if (const auto strong = weak.get()) { strong->cancelSelection(); } }; diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index a6ac266d36..27c8d2f975 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -1340,9 +1340,9 @@ void ScheduledWidget::showProcessingVideoTooltip() { st::defaultImportantTooltipLabel), st::defaultImportantTooltip); const auto tooltip = _processingVideoTooltip.get(); - const auto weak = QPointer(tooltip); + const auto weak = base::make_weak(tooltip); const auto destroy = [=] { - delete weak.data(); + delete weak.get(); }; tooltip->setAttribute(Qt::WA_TransparentForMouseEvents); tooltip->setHiddenCallback([=] { diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 97edfbdc52..a5ed7ee279 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -336,8 +336,8 @@ bool TopBarWidget::createMenu(not_null button) { this, st::popupMenuExpandedSeparator); _menu->setDestroyedCallback([ - weak = Ui::MakeWeak(this), - weakButton = Ui::MakeWeak(button), + weak = base::make_weak(this), + weakButton = base::make_weak(button), menu = _menu.get()] { if (weak && weak->_menu == menu) { if (weakButton) { diff --git a/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp b/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp index 11e9cc8d7a..c263c5f9ee 100644 --- a/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp +++ b/Telegram/SourceFiles/history/view/history_view_translate_bar.cpp @@ -409,8 +409,8 @@ base::unique_qptr TranslateBar::createMenu( st::popupMenuExpandedSeparator); result->setDestroyedCallback([ this, - weak = Ui::MakeWeak(&_wrap), - weakButton = Ui::MakeWeak(button), + weak = base::make_weak(&_wrap), + weakButton = base::make_weak(button), menu = result.get() ] { if (weak && _menu == menu) { @@ -430,7 +430,7 @@ void TranslateBar::showMenu(base::unique_qptr menu) { _menu = std::move(menu); _menu->setForcedOrigin(Ui::PanelAnimation::Origin::TopRight); - const auto guard = Ui::MakeWeak(&_wrap); + const auto guard = base::make_weak(&_wrap); const auto now = _history->translatedTo(); const auto to = now ? now : Ui::ChooseTranslateTo(_history); const auto weak = base::make_weak(_controller); diff --git a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_common.cpp b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_common.cpp index 89dcda70a3..5e3b7d5ece 100644 --- a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_common.cpp +++ b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_common.cpp @@ -549,7 +549,7 @@ object_ptr JoinStarRefBox( struct State { rpl::variable> recipient; - QPointer weak; + base::weak_qptr weak; bool sent = false; }; const auto state = std::make_shared(State{ @@ -709,7 +709,7 @@ object_ptr JoinStarRefBox( } } show->show(StarRefLinkBox(info, recipient)); - if (const auto strong = state->weak.data()) { + if (const auto strong = state->weak.get()) { strong->closeBox(); } }, [=](const QString &error) { diff --git a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_join_widget.cpp b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_join_widget.cpp index 515b275923..0343af54bf 100644 --- a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_join_widget.cpp +++ b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_join_widget.cpp @@ -1105,7 +1105,7 @@ std::shared_ptr Make(not_null peer) { object_ptr ProgramsListBox( not_null window, not_null peer) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto initBox = [=](not_null box) { *weak = box; box->addButton(tr::lng_close(), [=] { @@ -1118,7 +1118,7 @@ object_ptr ProgramsListBox( peer, JoinType::Existing); controller->addForBotRequests() | rpl::start_with_next([=] { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } }, controller->lifetime()); diff --git a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp index 5d1772c93a..46183eb688 100644 --- a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp +++ b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp @@ -738,7 +738,7 @@ void InnerWidget::setupEnd() { tr::lng_star_ref_end(), st::settingsAttentionButton)); end->setClickedCallback([=] { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto window = _controller->parentController(); const auto sent = std::make_shared(); window->show(ConfirmEndBox([=] { @@ -751,7 +751,7 @@ void InnerWidget::setupEnd() { *sent = false; if (!success) { return; - } else if ([[maybe_unused]] const auto strong = weak.data()) { + } else if ([[maybe_unused]] const auto strong = weak.get()) { _controller->showBackFromStack(); window->showToast({ .title = tr::lng_star_ref_ended_title(tr::now), @@ -1013,7 +1013,7 @@ std::unique_ptr Widget::setupBottom() { st::boxDividerLabel), QMargins(margins.left(), 0, margins.right(), 0)); save->setClickedCallback([=] { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto user = _state->user; const auto program = _state->program; const auto show = controller()->uiShow(); diff --git a/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp b/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp index 09f5cdeb60..cc1c092bc3 100644 --- a/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp @@ -1459,11 +1459,11 @@ void CreateGiveawayBox( } state->confirmButtonBusy = true; const auto show = box->uiShow(); - const auto weak = Ui::MakeWeak(box.get()); + const auto weak = base::make_weak(box.get()); const auto done = [=](Payments::CheckoutResult result) { const auto isPaid = result == Payments::CheckoutResult::Paid; if (result == Payments::CheckoutResult::Pending || isPaid) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->window()->setFocus(); strong->closeBox(); } diff --git a/Telegram/SourceFiles/info/channel_statistics/boosts/info_boosts_inner_widget.cpp b/Telegram/SourceFiles/info/channel_statistics/boosts/info_boosts_inner_widget.cpp index 0f35e31de0..de6862e8bc 100644 --- a/Telegram/SourceFiles/info/channel_statistics/boosts/info_boosts_inner_widget.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/boosts/info_boosts_inner_widget.cpp @@ -174,7 +174,7 @@ void FillShareLink( std::shared_ptr show, const QString &link, not_null peer) { - const auto weak = Ui::MakeWeak(content); + const auto weak = base::make_weak(content); const auto copyLink = crl::guard(weak, [=] { QGuiApplication::clipboard()->setText(link); show->showToast(tr::lng_channel_public_link_copied(tr::now)); diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp index 1563bef9dd..4e6ef02378 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp @@ -1470,10 +1470,10 @@ void InnerWidget::fill() { [] {}); } if (!isLocked) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto show = _controller->uiShow(); const auto failed = [=](const QString &e) { - if (weak.data()) { + if (weak.get()) { toggled->fire(false); show->showToast(e); } diff --git a/Telegram/SourceFiles/info/info_top_bar.cpp b/Telegram/SourceFiles/info/info_top_bar.cpp index a6dd089a25..8e731fc914 100644 --- a/Telegram/SourceFiles/info/info_top_bar.cpp +++ b/Telegram/SourceFiles/info/info_top_bar.cpp @@ -53,7 +53,7 @@ void TopBar::registerUpdateControlCallback( QObject *guard, Callback &&callback) { _updateControlCallbacks[guard] =[ - weak = Ui::MakeWeak(guard), + weak = base::make_weak(guard), callback = std::forward(callback) ](anim::type animated) { if (!weak) { @@ -579,8 +579,8 @@ void TopBar::setStories(rpl::producer content) { } }, _storiesLifetime); - _storiesLifetime.add([weak = QPointer(label)] { - delete weak.data(); + _storiesLifetime.add([weak = base::make_weak(label)] { + delete weak.get(); }); } else { _storiesCount = 0; diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 56bc9bf193..20a99a2c58 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -979,7 +979,7 @@ object_ptr WrapWidget::createTopBarSurrogate( Assert(_topBar != nullptr); auto result = object_ptr(parent); - result->addClickHandler([weak = Ui::MakeWeak(this)]{ + result->addClickHandler([weak = base::make_weak(this)]{ if (weak) { weak->_controller->showBackFromStack(); } diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index d4d99d138a..f6b382b1e4 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -1224,8 +1224,8 @@ void ListWidget::forwardItems(MessageIdsList &&items) { { id.peer, StoryIdFromMsgId(id.msg) })); } } else { - auto callback = [weak = Ui::MakeWeak(this)] { - if (const auto strong = weak.data()) { + auto callback = [weak = base::make_weak(this)] { + if (const auto strong = weak.get()) { strong->clearSelected(); } }; @@ -1373,7 +1373,7 @@ void ListWidget::deleteItems(SelectedItems &&items, Fn confirmed) { : tr::lng_downloads_delete_in_cloud(tr::now)); const auto deleteSure = [=] { Ui::PostponeCall(this, [=] { - if (const auto box = _actionBoxWeak.data()) { + if (const auto box = _actionBoxWeak.get()) { box->closeBox(); } }); @@ -1433,10 +1433,10 @@ void ListWidget::deleteItems(SelectedItems &&items, Fn confirmed) { } } -void ListWidget::setActionBoxWeak(QPointer box) { +void ListWidget::setActionBoxWeak(base::weak_qptr box) { if ((_actionBoxWeak = box)) { _actionBoxWeakLifetime = _actionBoxWeak->alive( - ) | rpl::start_with_done([weak = Ui::MakeWeak(this)]{ + ) | rpl::start_with_done([weak = base::make_weak(this)]{ if (weak) { weak->_checkForHide.fire({}); } diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.h b/Telegram/SourceFiles/info/media/info_media_list_widget.h index 4f4a78e966..fa40321c47 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.h @@ -272,7 +272,7 @@ private: void checkMoveToOtherViewer(); void clearHeavyItems(); - void setActionBoxWeak(QPointer box); + void setActionBoxWeak(base::weak_qptr box); const not_null _controller; const std::unique_ptr _provider; @@ -307,7 +307,7 @@ private: base::unique_qptr _contextMenu; rpl::event_stream<> _checkForHide; - QPointer _actionBoxWeak; + base::weak_qptr _actionBoxWeak; rpl::lifetime _actionBoxWeakLifetime; QPoint _trippleClickPoint; diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp index 51c83a2f77..33e28a9227 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp @@ -1015,9 +1015,9 @@ void SelectGiftToUnpin( } Assert(index < int(pinned.size())); const auto &entry = pinned[index]; - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); chosen(::Settings::EntryToSavedStarGiftId(session, entry)); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index e07ba2d1c2..26823bb83b 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -885,13 +885,13 @@ rpl::producer AddCurrencyAction( state->balance = balance; } { - const auto weak = Ui::MakeWeak(wrap); + const auto weak = base::make_weak(wrap); const auto currencyLoadLifetime = std::make_shared(); const auto currencyLoad = currencyLoadLifetime->make_state(user); const auto done = [=](CreditsAmount balance) { - if ([[maybe_unused]] const auto strong = weak.data()) { + if ([[maybe_unused]] const auto strong = weak.get()) { state->balance = balance; currencyLoadLifetime->destroy(); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_emoji_status_panel.cpp b/Telegram/SourceFiles/info/profile/info_profile_emoji_status_panel.cpp index ecf24b2796..de39c8ed1b 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_emoji_status_panel.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_emoji_status_panel.cpp @@ -269,7 +269,7 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) { _panel->hideAnimated(); }, _panel->lifetime()); } else { - const auto weak = Ui::MakeWeak(_panel.get()); + const auto weak = base::make_weak(_panel.get()); const auto accept = [=](Chosen chosen) { Expects(chosen.until != Selector::kPickCustomTimeId); diff --git a/Telegram/SourceFiles/info/settings/info_settings_widget.h b/Telegram/SourceFiles/info/settings/info_settings_widget.h index e1aef6b78e..b08a4281f8 100644 --- a/Telegram/SourceFiles/info/settings/info_settings_widget.h +++ b/Telegram/SourceFiles/info/settings/info_settings_widget.h @@ -104,8 +104,8 @@ private: rpl::event_stream<> backButtonEnables; } _flexibleScroll; not_null<::Settings::AbstractSection*> _inner; - QPointer _pinnedToTop; - QPointer _pinnedToBottom; + base::weak_qptr _pinnedToTop; + base::weak_qptr _pinnedToBottom; rpl::event_stream> _removesFromStack; diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 36e907923f..8e1af089b1 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -219,7 +219,7 @@ void ShowChooseBox( PeerTypes types, Fn)> callback, rpl::producer titleOverride = nullptr) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto done = [=](not_null thread) mutable { if (const auto strong = *weak) { strong->closeBox(); @@ -1816,8 +1816,8 @@ void WebViewInstance::botSendPreparedMessage( .viaBotId = peerToUser(bot->id), }); struct State { - QPointer preview; - QPointer choose; + base::weak_qptr preview; + base::weak_qptr choose; rpl::event_stream> recipient; Fn send; SendPaymentHelper sendPayment; @@ -1837,10 +1837,10 @@ void WebViewInstance::botSendPreparedMessage( const auto weak1 = state->preview; const auto weak2 = state->choose; const auto close = [=] { - if (const auto strong = weak1.data()) { + if (const auto strong = weak1.get()) { strong->closeBox(); } - if (const auto strong = weak2.data()) { + if (const auto strong = weak2.get()) { strong->closeBox(); } }; @@ -1850,9 +1850,9 @@ void WebViewInstance::botSendPreparedMessage( } if (success) { *failed = -1; - if (const auto strong2 = weak2.data()) { + if (const auto strong2 = weak2.get()) { strong2->showToast({ tr::lng_share_done(tr::now) }); - } else if (const auto strong1 = weak1.data()) { + } else if (const auto strong1 = weak1.get()) { strong1->showToast({ tr::lng_share_done(tr::now) }); } base::call_delayed(Ui::Toast::kDefaultDuration, close); diff --git a/Telegram/SourceFiles/intro/intro_password_check.cpp b/Telegram/SourceFiles/intro/intro_password_check.cpp index 3555c95ef8..748e304fe1 100644 --- a/Telegram/SourceFiles/intro/intro_password_check.cpp +++ b/Telegram/SourceFiles/intro/intro_password_check.cpp @@ -230,7 +230,7 @@ void PasswordCheckWidget::codeSubmitDone( fields.mtp.curRequest = {}; fields.hasPassword = false; auto box = Box(&api().instance(), nullptr, fields); - const auto boxShared = std::make_shared>(); + const auto boxShared = std::make_shared>(); box->newAuthorization( ) | rpl::start_with_next([=](const MTPauth_Authorization &result) { diff --git a/Telegram/SourceFiles/intro/intro_widget.cpp b/Telegram/SourceFiles/intro/intro_widget.cpp index ca65b02214..296991f514 100644 --- a/Telegram/SourceFiles/intro/intro_widget.cpp +++ b/Telegram/SourceFiles/intro/intro_widget.cpp @@ -403,7 +403,7 @@ void Widget::historyMove(StackAction action, Animate animate) { } void Widget::hideAndDestroy(object_ptr> widget) { - const auto weak = Ui::MakeWeak(widget.data()); + const auto weak = base::make_weak(widget.data()); widget->hide(anim::type::normal); widget->shownValue( ) | rpl::start_with_next([=](bool shown) { @@ -625,7 +625,7 @@ void Widget::showTerms(Fn callback) { if (getData()->termsLock.text.text.isEmpty()) { return; } - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto box = Ui::show(callback ? Box( getData()->termsLock, diff --git a/Telegram/SourceFiles/iv/iv_controller.cpp b/Telegram/SourceFiles/iv/iv_controller.cpp index 87befe5bfd..2b436d842c 100644 --- a/Telegram/SourceFiles/iv/iv_controller.cpp +++ b/Telegram/SourceFiles/iv/iv_controller.cpp @@ -1096,7 +1096,7 @@ void Controller::showMenu() { } _menu->setDestroyedCallback(crl::guard(_window.get(), [ this, - weakButton = Ui::MakeWeak(_menuToggle.data()), + weakButton = base::make_weak(_menuToggle.data()), menu = _menu.get()] { if (_menu == menu && weakButton) { weakButton->setForceRippled(false); diff --git a/Telegram/SourceFiles/iv/iv_instance.cpp b/Telegram/SourceFiles/iv/iv_instance.cpp index 09a7e2e383..dec3f36cf9 100644 --- a/Telegram/SourceFiles/iv/iv_instance.cpp +++ b/Telegram/SourceFiles/iv/iv_instance.cpp @@ -315,11 +315,11 @@ ShareBoxResult Shown::shareBox(ShareBoxDescriptor &&descriptor) { }; const auto state = wrap->lifetime().make_state(); - const auto weak = QPointer(wrap); + const auto weak = base::make_weak(wrap); const auto lookup = crl::guard(weak, [state] { return state->stack; }); const auto layer = Ui::CreateChild( wrap.get(), - [=] { return std::make_shared(weak.data(), lookup); }); + [=] { return std::make_shared(weak.get(), lookup); }); state->stack = layer; const auto show = layer->showFactory()(); diff --git a/Telegram/SourceFiles/iv/iv_pch.h b/Telegram/SourceFiles/iv/iv_pch.h index 4ad8da65a9..15ad9d2fe7 100644 --- a/Telegram/SourceFiles/iv/iv_pch.h +++ b/Telegram/SourceFiles/iv/iv_pch.h @@ -22,9 +22,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/flat_map.h" #include "base/flat_set.h" +#include "base/weak_qptr.h" #include "ui/qt_object_factory.h" -#include "ui/qt_weak_factory.h" #include "scheme.h" #include "logs.h" diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index e7ed0c618d..773c4fb3a6 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -259,7 +259,7 @@ void MainWindow::setupMain( const auto animated = _intro || (_passcodeLock && !Core::App().passcodeLocked()); const auto weakAnimatedLayer = (_main && _layer && !_passcodeLock) - ? Ui::MakeWeak(_layer.get()) + ? base::make_weak(_layer.get()) : nullptr; if (weakAnimatedLayer) { Assert(!animated); @@ -288,7 +288,7 @@ void MainWindow::setupMain( Core::App().checkStartUrl(); } fixOrder(); - if (const auto strong = weakAnimatedLayer.data()) { + if (const auto strong = weakAnimatedLayer.get()) { strong->hideAllAnimatedRun(); } } diff --git a/Telegram/SourceFiles/media/stories/media_stories_header.cpp b/Telegram/SourceFiles/media/stories/media_stories_header.cpp index a77c700b25..316000a4fb 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_header.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_header.cpp @@ -741,9 +741,9 @@ void Header::toggleTooltip(Tooltip type, bool show) { st::storiesInfoTooltipLabel), st::storiesInfoTooltip); const auto tooltip = _tooltip.get(); - const auto weak = QPointer(tooltip); + const auto weak = base::make_weak(tooltip); const auto destroy = [=] { - delete weak.data(); + delete weak.get(); }; tooltip->setAttribute(Qt::WA_TransparentForMouseEvents); tooltip->setHiddenCallback(destroy); diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 9333efdc91..5ff6a060a3 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -3381,7 +3381,7 @@ void OverlayWidget::refreshCaption() { : Ui::ItemTextDefaultOptions()), context); if (_caption.hasSpoilers()) { - const auto weak = Ui::MakeWeak(widget()); + const auto weak = base::make_weak(widget()); _caption.setSpoilerLinkFilter([=](const ClickContext &context) { return (weak != nullptr); }); @@ -4286,7 +4286,7 @@ void OverlayWidget::initThemePreview() { const auto weakSession = base::make_weak(&_document->session()); const auto path = _document->location().name(); const auto id = _themePreviewId = base::RandomValue(); - const auto weak = Ui::MakeWeak(_widget); + const auto weak = base::make_weak(_widget); crl::async([=, data = std::move(current)]() mutable { auto preview = GeneratePreview( bytes, @@ -6448,7 +6448,7 @@ bool OverlayWidget::handleTouchEvent(not_null e) { if (!_touchPress) { break; } - auto weak = Ui::MakeWeak(_widget); + auto weak = base::make_weak(_widget); if (!_touchMove) { const auto button = _touchRightButton ? Qt::RightButton diff --git a/Telegram/SourceFiles/media/view/media_view_pip.cpp b/Telegram/SourceFiles/media/view/media_view_pip.cpp index 7c8f958889..42600dbb3e 100644 --- a/Telegram/SourceFiles/media/view/media_view_pip.cpp +++ b/Telegram/SourceFiles/media/view/media_view_pip.cpp @@ -1009,7 +1009,7 @@ void Pip::handleLeave() { } void Pip::handleMouseMove(QPoint position) { - const auto weak = Ui::MakeWeak(_panel.widget()); + const auto weak = base::make_weak(_panel.widget()); const auto guard = gsl::finally([&] { if (weak) { _panel.handleMouseMove(position); @@ -1087,7 +1087,7 @@ Pip::OverState Pip::ResolveShownOver(OverState state) { } void Pip::handleMousePress(QPoint position, Qt::MouseButton button) { - const auto weak = Ui::MakeWeak(_panel.widget()); + const auto weak = base::make_weak(_panel.widget()); const auto guard = gsl::finally([&] { if (weak) { _panel.handleMousePress(position, button); @@ -1105,7 +1105,7 @@ void Pip::handleMousePress(QPoint position, Qt::MouseButton button) { } void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) { - const auto weak = Ui::MakeWeak(_panel.widget()); + const auto weak = base::make_weak(_panel.widget()); const auto guard = gsl::finally([&] { if (weak) { _panel.handleMouseRelease(position, button); diff --git a/Telegram/SourceFiles/menu/menu_item_download_files.cpp b/Telegram/SourceFiles/menu/menu_item_download_files.cpp index 01a990b11b..540f2ebb71 100644 --- a/Telegram/SourceFiles/menu/menu_item_download_files.cpp +++ b/Telegram/SourceFiles/menu/menu_item_download_files.cpp @@ -226,8 +226,8 @@ void AddDownloadFilesAction( return; } } - const auto done = [weak = Ui::MakeWeak(list)] { - if (const auto strong = weak.data()) { + const auto done = [weak = base::make_weak(list)] { + if (const auto strong = weak.get()) { strong->cancelSelection(); } }; @@ -253,8 +253,8 @@ void AddDownloadFilesAction( return; } } - const auto done = [weak = Ui::MakeWeak(list)] { - if (const auto strong = weak.data()) { + const auto done = [weak = base::make_weak(list)] { + if (const auto strong = weak.get()) { strong->clearSelected(); } }; diff --git a/Telegram/SourceFiles/menu/menu_send.cpp b/Telegram/SourceFiles/menu/menu_send.cpp index 4125ac0891..86518f725f 100644 --- a/Telegram/SourceFiles/menu/menu_send.cpp +++ b/Telegram/SourceFiles/menu/menu_send.cpp @@ -589,7 +589,7 @@ void EffectPreview::toggle(bool shown) { Fn DefaultCallback( std::shared_ptr show, Fn send) { - const auto guard = Ui::MakeWeak(show->toastParent()); + const auto guard = base::make_weak(show->toastParent()); return [=](Action action, Details details) { if (action.type == ActionType::Send) { send(action.options); @@ -601,9 +601,9 @@ Fn DefaultCallback( details, send, action.options); - const auto weak = Ui::MakeWeak(box.data()); + const auto weak = base::make_weak(box.data()); show->showBox(std::move(box)); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->setCloseByOutsideClick(false); } }; @@ -618,7 +618,7 @@ FillMenuResult AttachSendMenuEffect( Expects(show != nullptr); using namespace HistoryView::Reactions; - const auto effect = std::make_shared>(); + const auto effect = std::make_shared>(); const auto position = desiredPositionOverride.value_or(QCursor::pos()); const auto selector = (show && details.effectAllowed) ? AttachSelectorToMenu( @@ -645,13 +645,13 @@ FillMenuResult AttachSendMenuEffect( const auto &effects = reactions.list(Data::Reactions::Type::Effects); const auto i = ranges::find(effects, chosen.id, &Data::Reaction::id); if (i != end(effects)) { - if (const auto strong = effect->data()) { + if (const auto strong = effect->get()) { strong->hideAnimated(); } - const auto weak = Ui::MakeWeak(menu); + const auto weak = base::make_weak(menu); const auto done = [=] { - delete effect->data(); - if (const auto strong = weak.data()) { + delete effect->get(); + if (const auto strong = weak.get()) { strong->hideMenu(true); } }; diff --git a/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.cpp b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.cpp index 5bb4d5d205..89ad7d9625 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.cpp +++ b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.cpp @@ -76,7 +76,7 @@ auto ConcurrentSender::with_instance(Method &&method) weak = _weak, method = std::forward(method) ]() mutable { - if (const auto instance = weak.data()) { + if (const auto instance = weak.get()) { std::move(method)(instance); } }); @@ -136,7 +136,7 @@ mtpRequestId ConcurrentSender::RequestBuilder::send() { } ConcurrentSender::ConcurrentSender( - QPointer weak, + base::weak_qptr weak, Fn)> runner) : _weak(weak) , _runner(runner) { diff --git a/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.h b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.h index 47daaf7a6c..f96d0fe3ac 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.h +++ b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/bytes.h" #include "base/weak_ptr.h" +#include "base/weak_qptr.h" #include "base/flat_map.h" #include "mtproto/core_types.h" #include "mtproto/details/mtproto_serialized_request.h" @@ -83,7 +84,7 @@ class ConcurrentSender : public base::has_weak_ptr { public: ConcurrentSender( - QPointer weak, + base::weak_qptr weak, Fn)> runner); template @@ -184,7 +185,7 @@ private: void senderRequestCancelAll(); void senderRequestDetach(mtpRequestId requestId); - const QPointer _weak; + const base::weak_qptr _weak; const Fn)> _runner; base::flat_map _requests; diff --git a/Telegram/SourceFiles/passport/passport_form_view_controller.h b/Telegram/SourceFiles/passport/passport_form_view_controller.h index b2a22fbdbc..590d7c2109 100644 --- a/Telegram/SourceFiles/passport/passport_form_view_controller.h +++ b/Telegram/SourceFiles/passport/passport_form_view_controller.h @@ -63,11 +63,11 @@ public: } template - QPointer show( + base::weak_qptr show( object_ptr box, Ui::LayerOptions options = Ui::LayerOption::KeepOther, anim::type animated = anim::type::normal) { - auto result = QPointer(box.data()); + auto result = base::weak_qptr(box.data()); showBox(std::move(box), options, animated); return result; } diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.cpp b/Telegram/SourceFiles/passport/passport_panel_controller.cpp index e4979bf3b2..1abfa686be 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_controller.cpp @@ -910,7 +910,7 @@ void PanelController::suggestReset(Fn callback) { .confirmed = [=] { resetPassport(callback); }, .cancelled = [=] { cancelReset(); }, .confirmText = Lang::Hard::PassportCorruptedReset(), - })).data()); + })).get()); } void PanelController::resetPassport(Fn callback) { @@ -921,7 +921,7 @@ void PanelController::resetPassport(Fn callback) { .confirmText = Lang::Hard::PassportCorruptedReset(), .confirmStyle = &st::attentionBoxButton, })); - _resetBox = Ui::BoxPointer(box.data()); + _resetBox = Ui::BoxPointer(box.get()); } void PanelController::cancelReset() { @@ -1210,7 +1210,7 @@ void PanelController::startScopeEdit( std::move(scans), std::move(translations), PrepareSpecialFiles(*_editDocument)); - const auto weak = Ui::MakeWeak(result.data()); + const auto weak = base::make_weak(result.data()); _panelHasUnsavedChanges = [=] { return weak ? weak->hasUnsavedChanges() : false; }; @@ -1229,7 +1229,7 @@ void PanelController::startScopeEdit( std::move(preferredLanguage)), _editValue->error, _editValue->data.parsedInEdit); - const auto weak = Ui::MakeWeak(result.data()); + const auto weak = base::make_weak(result.data()); _panelHasUnsavedChanges = [=] { return weak ? weak->hasUnsavedChanges() : false; }; diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.h b/Telegram/SourceFiles/passport/passport_panel_controller.h index 5c3d296b47..c08645056e 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.h +++ b/Telegram/SourceFiles/passport/passport_panel_controller.h @@ -174,7 +174,7 @@ private: std::unique_ptr _panel; Fn _panelHasUnsavedChanges; - QPointer _confirmForgetChangesBox; + base::weak_qptr _confirmForgetChangesBox; std::vector _editScopeBoxes; Scope *_editScope = nullptr; const Value *_editValue = nullptr; diff --git a/Telegram/SourceFiles/passport/ui/passport_details_row.cpp b/Telegram/SourceFiles/passport/ui/passport_details_row.cpp index 55739b7dbb..0fa946fd96 100644 --- a/Telegram/SourceFiles/passport/ui/passport_details_row.cpp +++ b/Telegram/SourceFiles/passport/ui/passport_details_row.cpp @@ -571,7 +571,7 @@ DateRow::DateRow( GetYear(value)) , _value(valueCurrent()) { const auto focused = [=](const object_ptr &field) { - return [this, pointer = MakeWeak(field.data())]{ + return [this, pointer = base::make_weak(field.data())]{ _borderAnimationStart = pointer->borderAnimationStart() + pointer->x() - _day->x(); diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.cpp b/Telegram/SourceFiles/payments/payments_checkout_process.cpp index 379036e6e9..d27161660e 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.cpp +++ b/Telegram/SourceFiles/payments/payments_checkout_process.cpp @@ -410,7 +410,7 @@ void CheckoutProcess::handleFormUpdate(const FormUpdate &update) { UnregisterPaymentStart(this); _submitState = SubmitState::Validated; _panel->showWarning(data.bot->name(), data.provider->name()); - if (const auto box = _enterPasswordBox.data()) { + if (const auto box = _enterPasswordBox.get()) { box->closeBox(); } }, [&](const VerificationNeeded &data) { @@ -534,7 +534,7 @@ void CheckoutProcess::handleError(const Error &error) { showToast({ "SmartGlocal Error: " + id }); } break; case Error::Type::TmpPassword: - if (const auto box = _enterPasswordBox.data()) { + if (const auto box = _enterPasswordBox.get()) { if (!box->handleCustomCheckError(id)) { showToast({ "Error: Could not generate tmp password." }); } @@ -542,7 +542,7 @@ void CheckoutProcess::handleError(const Error &error) { break; case Error::Type::Send: _sendFormFailed = true; - if (const auto box = _enterPasswordBox.data()) { + if (const auto box = _enterPasswordBox.get()) { box->closeBox(); } if (_submitState == SubmitState::Finishing) { @@ -857,7 +857,7 @@ void CheckoutProcess::requestPassword() { fields.customSubmitButton = tr::lng_payments_password_submit(); fields.customCheckCallback = [=]( const Core::CloudPasswordResult &result, - QPointer box) { + base::weak_qptr box) { _enterPasswordBox = box; _form->submit(result); }; diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.h b/Telegram/SourceFiles/payments/payments_checkout_process.h index 2f52caf23f..ad6648c500 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.h +++ b/Telegram/SourceFiles/payments/payments_checkout_process.h @@ -189,7 +189,7 @@ private: const not_null _session; const std::unique_ptr
_form; const std::unique_ptr _panel; - QPointer _enterPasswordBox; + base::weak_qptr _enterPasswordBox; Fn _reactivate; Fn _nonPanelPaymentFormProcess; SubmitState _submitState = SubmitState::None; diff --git a/Telegram/SourceFiles/payments/payments_reaction_process.cpp b/Telegram/SourceFiles/payments/payments_reaction_process.cpp index 3e5236fda1..3bea078d30 100644 --- a/Telegram/SourceFiles/payments/payments_reaction_process.cpp +++ b/Telegram/SourceFiles/payments/payments_reaction_process.cpp @@ -140,7 +140,7 @@ void ShowPaidReactionDetails( const auto chosen = std::clamp(kDefaultPerReaction, 1, max); struct State { - QPointer selectBox; + base::weak_qptr selectBox; bool ignoreShownPeerSwitch = false; bool sending = false; }; @@ -155,7 +155,7 @@ void ShowPaidReactionDetails( state->sending = false; if (success && count > 0) { state->ignoreShownPeerSwitch = true; - if (const auto strong = state->selectBox.data()) { + if (const auto strong = state->selectBox.get()) { strong->closeBox(); } } @@ -260,7 +260,7 @@ void ShowPaidReactionDetails( }, })); - if (const auto strong = state->selectBox.data()) { + if (const auto strong = state->selectBox.get()) { session->data().itemRemoved( ) | rpl::start_with_next([=](not_null removed) { if (removed == item) { diff --git a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp index 67ad2c7cc0..9a0011234e 100644 --- a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp @@ -236,7 +236,7 @@ void AddArrowDown(not_null widget) { } void SelectShownPeer( - std::shared_ptr> menu, + std::shared_ptr> menu, not_null parent, const std::vector &mine, uint64 selected, @@ -311,7 +311,7 @@ void FillTopReactors( bool chosenChanged = false; }; const auto state = wrap->lifetime().make_state(); - const auto menu = std::make_shared>(); + const auto menu = std::make_shared>(); rpl::combine( std::move(chosen), diff --git a/Telegram/SourceFiles/settings/business/settings_away_message.cpp b/Telegram/SourceFiles/settings/business/settings_away_message.cpp index 58f3a61656..181582fa3f 100644 --- a/Telegram/SourceFiles/settings/business/settings_away_message.cpp +++ b/Telegram/SourceFiles/settings/business/settings_away_message.cpp @@ -119,10 +119,10 @@ void AddAwayScheduleSelector( Fn max, Fn done) { using namespace Ui; - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto save = [=](TimeId time) { done(time); - if (const auto strong = box->data()) { + if (const auto strong = box->get()) { strong->closeBox(); } }; diff --git a/Telegram/SourceFiles/settings/business/settings_greeting.cpp b/Telegram/SourceFiles/settings/business/settings_greeting.cpp index 8437acc7c0..a65d6946dd 100644 --- a/Telegram/SourceFiles/settings/business/settings_greeting.cpp +++ b/Telegram/SourceFiles/settings/business/settings_greeting.cpp @@ -89,9 +89,9 @@ void EditPeriodBox( const auto take = TimePickerBox(box, values, phrases, days); box->addButton(tr::lng_settings_save(), [=] { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); save(take()); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); diff --git a/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp b/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp index e59ef7061d..9c4bcf11bb 100644 --- a/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp +++ b/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp @@ -220,8 +220,8 @@ void EditShortcutNameBox( if (!ValidShortcutName(name)) { field->showError(); } else { - submit(name, [weak = Ui::MakeWeak(box)] { - if (const auto strong = weak.data()) { + submit(name, [weak = base::make_weak(box)] { + if (const auto strong = weak.get()) { strong->closeBox(); } }); diff --git a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp index 135f7df7e3..eb3dc498ed 100644 --- a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp +++ b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp @@ -178,7 +178,7 @@ private: bool cornerButtonsUnreadMayBeShown() override; bool cornerButtonsHas(CornerButtonType type) override; - QPointer createPinnedToBottom( + base::weak_qptr createPinnedToBottom( not_null parent) override; void setupComposeControls(); void processScroll(); @@ -773,7 +773,7 @@ void ShortcutMessages::setupComposeControls() { }, lifetime()); } -QPointer ShortcutMessages::createPinnedToBottom( +base::weak_qptr ShortcutMessages::createPinnedToBottom( not_null parent) { auto placeholder = rpl::deferred([=] { return _shortcutId.value(); diff --git a/Telegram/SourceFiles/settings/business/settings_working_hours.cpp b/Telegram/SourceFiles/settings/business/settings_working_hours.cpp index 6e0bf6f504..00e4c291c0 100644 --- a/Telegram/SourceFiles/settings/business/settings_working_hours.cpp +++ b/Telegram/SourceFiles/settings/business/settings_working_hours.cpp @@ -255,12 +255,12 @@ void EditTimeBox( }); box->addButton(tr::lng_settings_save(), [=] { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); save(std::clamp( ((*minutesStart) / 60 + minutes->current()->index()) * 60, low, high)); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); @@ -398,9 +398,9 @@ void EditDayBox( AddDividerText(container, tr::lng_hours_about_day()); box->addButton(tr::lng_settings_save(), [=] { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); save(state->data.current()); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); @@ -457,9 +457,9 @@ void ChooseTimezoneBox( }); } group->setChangedCallback([=](int index) { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); save(list[index].id); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp index e8bb2607ab..cdc53eb748 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.cpp @@ -80,7 +80,7 @@ BottomButton CreateBottomDisableButton( divider->show(); return { - .content = Ui::MakeWeak(not_null{ content }), + .content = base::make_weak(content), .isBottomFillerShown = divider->geometryValue( ) | rpl::map([](const QRect &r) { return r.height() > 0; diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h index a87c1aaed5..cd6a53b85d 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_common.h @@ -82,7 +82,7 @@ void AddSkipInsteadOfField(not_null content); void AddSkipInsteadOfError(not_null content); struct BottomButton { - QPointer content; + base::weak_qptr content; rpl::producer isBottomFillerShown; }; diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp index 7719fc2ddd..a7dd669b4f 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_input.cpp @@ -126,7 +126,7 @@ public: using TypedAbstractStep::TypedAbstractStep; [[nodiscard]] rpl::producer title() override; - [[nodiscard]] QPointer createPinnedToTop( + [[nodiscard]] base::weak_qptr createPinnedToTop( not_null parent) override; void setupContent(); void setupValidateGood(); @@ -156,7 +156,7 @@ rpl::producer Input::title() { return tr::lng_settings_cloud_password_password_title(); } -QPointer Input::createPinnedToTop( +base::weak_qptr Input::createPinnedToTop( not_null parent) { _parent = parent; return nullptr; diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_login_email_confirm.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_login_email_confirm.cpp index 211c6dff48..31c4c2aeb6 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_login_email_confirm.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_login_email_confirm.cpp @@ -124,14 +124,14 @@ void LoginEmailConfirm::setupContent() { newInput->setFocus(); newInput->showError(); } else { - const auto weak = Ui::MakeWeak(controller()->content()); + const auto weak = base::make_weak(controller()->content()); const auto done = [=] { _api.reset(); _processFinishes.fire({}); cloudPassword().reload(); setStepData(StepData()); showBack(); - if (const auto strong = weak) { + if (const auto strong = weak.get()) { Ui::StartFireworks(strong); } }; diff --git a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_manage.cpp b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_manage.cpp index 1f7a876738..1c6c484ef6 100644 --- a/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_manage.cpp +++ b/Telegram/SourceFiles/settings/cloud_password/settings_cloud_password_manage.cpp @@ -53,7 +53,7 @@ public: [[nodiscard]] rpl::producer title() override; void setupContent(); - [[nodiscard]] QPointer createPinnedToBottom( + [[nodiscard]] base::weak_qptr createPinnedToBottom( not_null parent) override; protected: @@ -184,7 +184,7 @@ void Manage::setupContent() { Ui::ResizeFitChild(this, content); } -QPointer Manage::createPinnedToBottom( +base::weak_qptr Manage::createPinnedToBottom( not_null parent) { const auto disable = [=](Fn close) { diff --git a/Telegram/SourceFiles/settings/settings_active_sessions.cpp b/Telegram/SourceFiles/settings/settings_active_sessions.cpp index 2b8368b4df..48150fdeb6 100644 --- a/Telegram/SourceFiles/settings/settings_active_sessions.cpp +++ b/Telegram/SourceFiles/settings/settings_active_sessions.cpp @@ -496,7 +496,7 @@ void SessionInfoBox( box->addButton(tr::lng_about_done(), [=] { box->closeBox(); }); if (const auto hash = data.hash) { box->addLeftButton(tr::lng_sessions_terminate(), [=] { - const auto weak = Ui::MakeWeak(box.get()); + const auto weak = base::make_weak(box.get()); terminate(hash); if (weak) { box->closeBox(); @@ -652,7 +652,7 @@ private: Full _data; object_ptr _inner; - QPointer _terminateBox; + base::weak_qptr _terminateBox; base::Timer _shortPollTimer; @@ -843,12 +843,12 @@ void SessionsContent::terminate(Fn terminateRequest, QString message) { .confirmText = tr::lng_settings_reset_button(), .confirmStyle = &st::attentionBoxButton, }); - _terminateBox = Ui::MakeWeak(box.data()); + _terminateBox = base::make_weak(box.data()); _controller->show(std::move(box)); } void SessionsContent::terminateOne(uint64 hash) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); auto callback = [=] { auto done = crl::guard(weak, [=](const MTPBool &result) { if (mtpIsFalse(result)) { @@ -877,7 +877,7 @@ void SessionsContent::terminateOne(uint64 hash) { } void SessionsContent::terminateAll() { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); auto callback = [=] { const auto reset = crl::guard(weak, [=] { _authorizations->cancelCurrentRequest(); diff --git a/Telegram/SourceFiles/settings/settings_blocked_peers.cpp b/Telegram/SourceFiles/settings/settings_blocked_peers.cpp index c0b2a47463..fbb8a065ee 100644 --- a/Telegram/SourceFiles/settings/settings_blocked_peers.cpp +++ b/Telegram/SourceFiles/settings/settings_blocked_peers.cpp @@ -73,7 +73,7 @@ rpl::producer Blocked::title() { return tr::lng_settings_blocked_users(); } -QPointer Blocked::createPinnedToTop(not_null parent) { +base::weak_qptr Blocked::createPinnedToTop(not_null parent) { const auto content = Ui::CreateChild(parent.get()); Ui::AddSkip(content); @@ -118,7 +118,7 @@ QPointer Blocked::createPinnedToTop(not_null parent) { }, subtitle->lifetime()); } - return Ui::MakeWeak(not_null{ content }); + return base::make_weak(not_null{ content }); } void Blocked::setupContent() { diff --git a/Telegram/SourceFiles/settings/settings_blocked_peers.h b/Telegram/SourceFiles/settings/settings_blocked_peers.h index b534cd87ec..e8a8e7c2da 100644 --- a/Telegram/SourceFiles/settings/settings_blocked_peers.h +++ b/Telegram/SourceFiles/settings/settings_blocked_peers.h @@ -29,7 +29,7 @@ public: [[nodiscard]] rpl::producer title() override; - [[nodiscard]] QPointer createPinnedToTop( + [[nodiscard]] base::weak_qptr createPinnedToTop( not_null parent) override; private: diff --git a/Telegram/SourceFiles/settings/settings_business.cpp b/Telegram/SourceFiles/settings/settings_business.cpp index a59c30b63f..a619971545 100644 --- a/Telegram/SourceFiles/settings/settings_business.cpp +++ b/Telegram/SourceFiles/settings/settings_business.cpp @@ -332,9 +332,9 @@ public: [[nodiscard]] rpl::producer title() override; - [[nodiscard]] QPointer createPinnedToTop( + [[nodiscard]] base::weak_qptr createPinnedToTop( not_null parent) override; - [[nodiscard]] QPointer createPinnedToBottom( + [[nodiscard]] base::weak_qptr createPinnedToBottom( not_null parent) override; void showFinished() override; @@ -582,7 +582,7 @@ void Business::setupContent() { Ui::ResizeFitChild(this, content); } -QPointer Business::createPinnedToTop( +base::weak_qptr Business::createPinnedToTop( not_null parent) { auto title = tr::lng_business_title(); auto about = [&]() -> rpl::producer { @@ -671,14 +671,14 @@ QPointer Business::createPinnedToTop( } }, content->lifetime()); - return Ui::MakeWeak(not_null{ content }); + return base::make_weak(not_null{ content }); } void Business::showFinished() { _showFinished.fire({}); } -QPointer Business::createPinnedToBottom( +base::weak_qptr Business::createPinnedToBottom( not_null parent) { const auto content = Ui::CreateChild(parent.get()); @@ -747,7 +747,7 @@ QPointer Business::createPinnedToBottom( _subscribe->setVisible(!premium && premiumPossible); }, _subscribe->lifetime()); - return Ui::MakeWeak(not_null{ content }); + return base::make_weak(not_null{ content }); } } // namespace diff --git a/Telegram/SourceFiles/settings/settings_calls.cpp b/Telegram/SourceFiles/settings/settings_calls.cpp index 16d3f3a249..d80f394a24 100644 --- a/Telegram/SourceFiles/settings/settings_calls.cpp +++ b/Telegram/SourceFiles/settings/settings_calls.cpp @@ -483,7 +483,7 @@ void ChooseMediaDeviceBox( state->currentId = std::move(currentId); const auto choose = [=](const QString &id) { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); chosen(id); if (weak) { box->closeBox(); diff --git a/Telegram/SourceFiles/settings/settings_common.h b/Telegram/SourceFiles/settings/settings_common.h index 6a9e214951..bf4102f391 100644 --- a/Telegram/SourceFiles/settings/settings_common.h +++ b/Telegram/SourceFiles/settings/settings_common.h @@ -88,11 +88,11 @@ public: [[nodiscard]] virtual const Ui::RoundRect *bottomSkipRounding() const { return nullptr; } - [[nodiscard]] virtual QPointer createPinnedToTop( + [[nodiscard]] virtual base::weak_qptr createPinnedToTop( not_null parent) { return nullptr; } - [[nodiscard]] virtual QPointer createPinnedToBottom( + [[nodiscard]] virtual base::weak_qptr createPinnedToBottom( not_null parent) { return nullptr; } diff --git a/Telegram/SourceFiles/settings/settings_credits.cpp b/Telegram/SourceFiles/settings/settings_credits.cpp index 1ed8c28c51..b893508a66 100644 --- a/Telegram/SourceFiles/settings/settings_credits.cpp +++ b/Telegram/SourceFiles/settings/settings_credits.cpp @@ -73,7 +73,7 @@ public: [[nodiscard]] rpl::producer title() override; - [[nodiscard]] QPointer createPinnedToTop( + [[nodiscard]] base::weak_qptr createPinnedToTop( not_null parent) override; void showFinished() override; @@ -603,7 +603,7 @@ void Credits::setupContent() { Ui::ResizeFitChild(this, content); } -QPointer Credits::createPinnedToTop( +base::weak_qptr Credits::createPinnedToTop( not_null parent) { _parent = parent; const auto isCurrency = _creditsType == CreditsType::Ton; @@ -722,7 +722,7 @@ QPointer Credits::createPinnedToTop( } }, content->lifetime()); - return Ui::MakeWeak(not_null{ content }); + return base::make_weak(not_null{ content }); } void Credits::showFinished() { @@ -799,9 +799,9 @@ Fn BuyStarsHandler::handler( ? _api->options() : Data::CreditTopupOptions(); const auto amount = CreditsAmount(); - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); FillCreditOptions(show, inner, self, amount, [=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } if (const auto onstack = paid) { diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index 2850e85a01..decb554373 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -625,9 +625,9 @@ void FillCreditOptions( .giftPeerId = PeerId(option.giftBarePeerId), }; - const auto weak = Ui::MakeWeak(button); + const auto weak = base::make_weak(button); const auto done = [=](Payments::CheckoutResult result) { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->window()->setFocus(); if (result == Payments::CheckoutResult::Paid) { if (const auto onstack = paid) { @@ -889,10 +889,10 @@ void BoostCreditsBox( } void ProcessReceivedSubscriptions( - QPointer weak, + base::weak_qptr weak, not_null session) { const auto rebuilder = session->data().activeCreditsSubsRebuilder(); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { if (!rebuilder) { return strong->closeBox(); } @@ -903,7 +903,7 @@ void ProcessReceivedSubscriptions( true); api->requestSubscriptions({}, [=](Data::CreditsStatusSlice first) { rebuilder->fire(std::move(first)); - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->closeBox(); } }); @@ -1759,7 +1759,7 @@ void GenericCreditsEntryBox( && !e.giftTransferred && !e.giftRefunded && !e.converted; - const auto toggleVisibility = [=, weak = Ui::MakeWeak(box)](bool save) { + const auto toggleVisibility = [=, weak = base::make_weak(box)](bool save) { const auto showSection = !e.fromGiftsList; const auto savedId = EntryToSavedStarGiftId(&show->session(), e); const auto done = [=](bool ok) { @@ -1771,7 +1771,7 @@ void GenericCreditsEntryBox( Info::Section::Type::PeerGifts)); } } - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { if (ok) { strong->closeBox(); } else { @@ -1817,7 +1817,7 @@ void GenericCreditsEntryBox( const auto canUpgradeFree = canUpgrade && (e.starsUpgradedBySender > 0); if (isStarGift && e.id.isEmpty()) { - const auto convert = [=, weak = Ui::MakeWeak(box)] { + const auto convert = [=, weak = base::make_weak(box)] { const auto stars = e.starsConverted; const auto days = canConvert ? ((timeLeft + 86399) / 86400) : 0; auto text = giftToChannelCanManage @@ -1851,7 +1851,7 @@ void GenericCreditsEntryBox( .action = GiftAction::Convert, }); } - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { if (ok) { strong->closeBox(); } else { @@ -1973,7 +1973,7 @@ void GenericCreditsEntryBox( if (button != Qt::LeftButton) { return false; } - const auto done = [=, weak = Ui::MakeWeak(box)] { + const auto done = [=, weak = base::make_weak(box)] { ProcessReceivedSubscriptions(weak, session); }; const auto fail = [=, s = box->uiShow()](const QString &e) { @@ -2024,7 +2024,7 @@ void GenericCreditsEntryBox( ? tr::lng_gift_show_on_channel : tr::lng_gift_show_on_page)() : tr::lng_box_ok())); - const auto send = [=, weak = Ui::MakeWeak(box)] { + const auto send = [=, weak = base::make_weak(box)] { if (toRejoin && !toRenew) { if (const auto window = show->resolveWindow()) { const auto finish = [=](Payments::CheckoutResult&&) { @@ -2049,7 +2049,7 @@ void GenericCreditsEntryBox( ProcessReceivedSubscriptions(weak, session); }; const auto fail = [=, show = box->uiShow()](const QString &e) { - if ([[maybe_unused]] const auto strong = weak.data()) { + if ([[maybe_unused]] const auto strong = weak.get()) { state->confirmButtonBusy = false; } show->showToast(e); diff --git a/Telegram/SourceFiles/settings/settings_folders.cpp b/Telegram/SourceFiles/settings/settings_folders.cpp index bd5d8be137..1c5129e2f2 100644 --- a/Telegram/SourceFiles/settings/settings_folders.cpp +++ b/Telegram/SourceFiles/settings/settings_folders.cpp @@ -353,7 +353,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) { not_null*> tagsButtonEnabled) { auto &lifetime = container->lifetime(); - const auto weak = Ui::MakeWeak(container); + const auto weak = base::make_weak(container); const auto session = &controller->session(); const auto limit = [=] { return Data::PremiumLimits(session).dialogFiltersCurrent(); @@ -909,9 +909,9 @@ void SetupTagContent( tagsButton->setToggleLocked(!value); }, tagsButton->lifetime()); - const auto send = [=, weak = Ui::MakeWeak(tagsButton)](bool checked) { + const auto send = [=, weak = base::make_weak(tagsButton)](bool checked) { session->data().chatsFilters().requestToggleTags(checked, [=] { - if ([[maybe_unused]] const auto strong = weak.data()) { + if ([[maybe_unused]] const auto strong = weak.get()) { state->tagsTurnOff.fire(!checked); } }); diff --git a/Telegram/SourceFiles/settings/settings_local_passcode.cpp b/Telegram/SourceFiles/settings/settings_local_passcode.cpp index 8f639c30a6..75943bcaef 100644 --- a/Telegram/SourceFiles/settings/settings_local_passcode.cpp +++ b/Telegram/SourceFiles/settings/settings_local_passcode.cpp @@ -404,7 +404,7 @@ public: [[nodiscard]] rpl::producer> removeFromStack() override; - [[nodiscard]] QPointer createPinnedToBottom( + [[nodiscard]] base::weak_qptr createPinnedToBottom( not_null parent) override; private: @@ -606,7 +606,7 @@ void LocalPasscodeManage::setupContent() { Ui::ResizeFitChild(this, content); } -QPointer LocalPasscodeManage::createPinnedToBottom( +base::weak_qptr LocalPasscodeManage::createPinnedToBottom( not_null parent) { auto callback = [=] { _controller->show( diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index f7098544c6..e212d2c457 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -478,7 +478,7 @@ void SetupValidatePhoneNumberSuggestion( st::inviteLinkButton); no->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); no->setClickedCallback([=] { - const auto sharedLabel = std::make_shared>(); + const auto sharedLabel = std::make_shared>(); const auto height = st::boxLabel.style.font->height; const auto customEmojiFactory = [=]( QStringView data, diff --git a/Telegram/SourceFiles/settings/settings_notifications_type.cpp b/Telegram/SourceFiles/settings/settings_notifications_type.cpp index df18b65ee1..391f63babb 100644 --- a/Telegram/SourceFiles/settings/settings_notifications_type.cpp +++ b/Telegram/SourceFiles/settings/settings_notifications_type.cpp @@ -530,7 +530,7 @@ void SetupExceptions( state->controller->setDelegate(state->delegate.get()); add->setClickedCallback([=] { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto done = [=](not_null peer) { state->controller->bringToTop(peer); if (*box) { diff --git a/Telegram/SourceFiles/settings/settings_premium.cpp b/Telegram/SourceFiles/settings/settings_premium.cpp index 76d93b9d5d..2b04f6db57 100644 --- a/Telegram/SourceFiles/settings/settings_premium.cpp +++ b/Telegram/SourceFiles/settings/settings_premium.cpp @@ -863,9 +863,9 @@ public: [[nodiscard]] rpl::producer title() override; - [[nodiscard]] QPointer createPinnedToTop( + [[nodiscard]] base::weak_qptr createPinnedToTop( not_null parent) override; - [[nodiscard]] QPointer createPinnedToBottom( + [[nodiscard]] base::weak_qptr createPinnedToBottom( not_null parent) override; void showFinished() override; @@ -1023,7 +1023,7 @@ void Premium::setupContent() { } -QPointer Premium::createPinnedToTop( +base::weak_qptr Premium::createPinnedToTop( not_null parent) { auto title = _controller->session().premium() ? tr::lng_premium_summary_title() @@ -1168,14 +1168,14 @@ QPointer Premium::createPinnedToTop( } }, content->lifetime()); - return Ui::MakeWeak(not_null{ content }); + return base::make_weak(not_null{ content }); } void Premium::showFinished() { _showFinished.fire({}); } -QPointer Premium::createPinnedToBottom( +base::weak_qptr Premium::createPinnedToBottom( not_null parent) { const auto content = Ui::CreateChild(parent.get()); @@ -1278,7 +1278,7 @@ QPointer Premium::createPinnedToBottom( _subscribe->setVisible(!premium && premiumPossible); }, _subscribe->lifetime()); - return Ui::MakeWeak(not_null{ content }); + return base::make_weak(not_null{ content }); } } // namespace diff --git a/Telegram/SourceFiles/settings/settings_shortcuts.cpp b/Telegram/SourceFiles/settings/settings_shortcuts.cpp index 9d5135f614..ecd2f7914c 100644 --- a/Telegram/SourceFiles/settings/settings_shortcuts.cpp +++ b/Telegram/SourceFiles/settings/settings_shortcuts.cpp @@ -194,7 +194,7 @@ struct Labeled { }; checkModified(); - const auto menu = std::make_shared>(); + const auto menu = std::make_shared>(); const auto fill = [=](Entry &entry) { auto index = 0; if (entry.original.empty()) { diff --git a/Telegram/SourceFiles/settings/settings_websites.cpp b/Telegram/SourceFiles/settings/settings_websites.cpp index 7f495998f0..f74ae4c800 100644 --- a/Telegram/SourceFiles/settings/settings_websites.cpp +++ b/Telegram/SourceFiles/settings/settings_websites.cpp @@ -182,7 +182,7 @@ void InfoBox( box->addButton(tr::lng_about_done(), [=] { box->closeBox(); }); if (const auto hash = data.hash) { box->addLeftButton(tr::lng_settings_disconnect(), [=] { - const auto weak = Ui::MakeWeak(box.get()); + const auto weak = base::make_weak(box.get()); terminate(hash); if (weak) { box->closeBox(); @@ -334,7 +334,7 @@ private: Api::Websites::List _data; object_ptr _inner; - QPointer _terminateBox; + base::weak_qptr _terminateBox; base::Timer _shortPollTimer; @@ -492,7 +492,7 @@ void Content::terminate( rpl::producer title, rpl::producer text, QString blockText) { - if (const auto strong = _terminateBox.data()) { + if (const auto strong = _terminateBox.get()) { strong->deleteLater(); } auto box = Box([=](not_null box) { @@ -517,12 +517,12 @@ void Content::terminate( *block = box->addRow(object_ptr(box, blockText)); } }); - _terminateBox = Ui::MakeWeak(box.data()); + _terminateBox = base::make_weak(box.data()); _controller->show(std::move(box)); } void Content::terminateOne(uint64 hash) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto i = ranges::find(_data, hash, &EntryData::hash); if (i == end(_data)) { return; @@ -552,7 +552,7 @@ void Content::terminateOne(uint64 hash) { } void Content::terminateAll() { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); auto callback = [=](bool block) { const auto reset = crl::guard(weak, [=] { _websites->cancelCurrentRequest(); diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index 6647362881..b111130433 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -128,7 +128,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/arc_angles.h" #include "ui/emoji_config.h" #include "ui/qt_object_factory.h" -#include "ui/qt_weak_factory.h" #include "ui/ui_rpl_filter.h" #include "styles/palette.h" diff --git a/Telegram/SourceFiles/support/support_autocomplete.cpp b/Telegram/SourceFiles/support/support_autocomplete.cpp index 45ad83edde..8122a476a2 100644 --- a/Telegram/SourceFiles/support/support_autocomplete.cpp +++ b/Telegram/SourceFiles/support/support_autocomplete.cpp @@ -520,7 +520,7 @@ void ConfirmContactBox::prepare() { _contact->initDimensions(); _submit = [=, original = std::move(_submit)](Qt::KeyboardModifiers m) { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); original(m); if (weak) { closeBox(); diff --git a/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp b/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp index 8651b5b010..0dfc516056 100644 --- a/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp +++ b/Telegram/SourceFiles/ui/boxes/choose_date_time.cpp @@ -147,7 +147,7 @@ ChooseDateTimeBoxDescriptor ChooseDateTimeBox( }, content->lifetime()); const auto calendar - = content->lifetime().make_state>(); + = content->lifetime().make_state>(); const auto calendarStyle = args.style.calendarStyle; state->day->focusedChanges( ) | rpl::start_with_next([=](bool focused) { diff --git a/Telegram/SourceFiles/ui/boxes/choose_font_box.cpp b/Telegram/SourceFiles/ui/boxes/choose_font_box.cpp index 97f65b65d9..a891c422f1 100644 --- a/Telegram/SourceFiles/ui/boxes/choose_font_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/choose_font_box.cpp @@ -819,7 +819,7 @@ void PreviewPainter::layout() { const auto ratio = state->preview.devicePixelRatio(); raw->resize(state->preview.size() / int(ratio)); } else { - const auto weak = Ui::MakeWeak(raw); + const auto weak = base::make_weak(raw); const auto request = PrepareRequest(family); crl::async([=, bg = state->bg] { crl::on_main([ @@ -827,7 +827,7 @@ void PreviewPainter::layout() { state, preview = GeneratePreview(bg, request) ]() mutable { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { state->preview = std::move(preview); const auto ratio = state->preview.devicePixelRatio(); strong->resize( diff --git a/Telegram/SourceFiles/ui/boxes/choose_time.cpp b/Telegram/SourceFiles/ui/boxes/choose_time.cpp index aa7f2836e2..ba2bdba9a7 100644 --- a/Telegram/SourceFiles/ui/boxes/choose_time.cpp +++ b/Telegram/SourceFiles/ui/boxes/choose_time.cpp @@ -76,9 +76,9 @@ ChooseTimeResult ChooseTimeWidget( QString::number(startMinutes)), }); - const auto day = Ui::MakeWeak(state->day); - const auto hour = Ui::MakeWeak(state->hour); - const auto minute = Ui::MakeWeak(state->minute); + const auto day = base::make_weak(state->day); + const auto hour = base::make_weak(state->hour); + const auto minute = base::make_weak(state->minute); if (hiddenDaysInput) { day->setVisible(false); @@ -88,24 +88,24 @@ ChooseTimeResult ChooseTimeWidget( day->setMaxValue(31); day->setWheelStep(1); day->putNext() | rpl::start_with_next([=](QChar ch) { - putNext(hour, ch); + putNext(hour.get(), ch); }, content->lifetime()); hour->setPhrase(tr::lng_hours); hour->setMaxValue(23); hour->setWheelStep(1); hour->putNext() | rpl::start_with_next([=](QChar ch) { - putNext(minute, ch); + putNext(minute.get(), ch); }, content->lifetime()); hour->erasePrevious() | rpl::start_with_next([=] { - erasePrevious(day); + erasePrevious(day.get()); }, content->lifetime()); minute->setPhrase(tr::lng_minutes); minute->setMaxValue(59); minute->setWheelStep(10); minute->erasePrevious() | rpl::start_with_next([=] { - erasePrevious(hour); + erasePrevious(hour.get()); }, content->lifetime()); content->sizeValue( @@ -127,9 +127,9 @@ ChooseTimeResult ChooseTimeWidget( rpl::merge( rpl::single(rpl::empty), - base::qt_signal_producer(day.data(), &MaskedInputField::changed), - base::qt_signal_producer(hour.data(), &MaskedInputField::changed), - base::qt_signal_producer(minute.data(), &MaskedInputField::changed) + base::qt_signal_producer(day.get(), &MaskedInputField::changed), + base::qt_signal_producer(hour.get(), &MaskedInputField::changed), + base::qt_signal_producer(minute.get(), &MaskedInputField::changed) ) | rpl::start_with_next([=] { state->valueInSeconds = 0 + day->getLastText().toUInt() * 3600 * 24 diff --git a/Telegram/SourceFiles/ui/boxes/confirm_box.cpp b/Telegram/SourceFiles/ui/boxes/confirm_box.cpp index 0c06fb5262..6d9f25c984 100644 --- a/Telegram/SourceFiles/ui/boxes/confirm_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/confirm_box.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui { void ConfirmBox(not_null box, ConfirmBoxArgs &&args) { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); const auto lifetime = box->lifetime().make_state(); const auto withTitle = !v::is_null(args.title); diff --git a/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp b/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp index 49905b87e2..4b0bf0c136 100644 --- a/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp +++ b/Telegram/SourceFiles/ui/boxes/edit_invite_link.cpp @@ -286,7 +286,7 @@ void EditInviteLinkBox( } }; - const auto guard = MakeWeak(box); + const auto guard = base::make_weak(box); expireGroup->setChangedCallback([=](int value) { if (value) { state->expireValue = value; diff --git a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp index e49e457454..0585a18f21 100644 --- a/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/peer_qr_box.cpp @@ -897,7 +897,7 @@ void FillPeerQrBox( const auto top = photoSize ? userpicMedia->image(photoSize) : QImage(); - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); crl::async([=] { const auto qrImage = TelegramQr( diff --git a/Telegram/SourceFiles/ui/boxes/single_choice_box.cpp b/Telegram/SourceFiles/ui/boxes/single_choice_box.cpp index 2083a0f483..10303d64a9 100644 --- a/Telegram/SourceFiles/ui/boxes/single_choice_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/single_choice_box.cpp @@ -46,7 +46,7 @@ void SingleChoiceBox( } const auto callback = args.callback.value(); group->setChangedCallback([=](int value) { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); callback(value); if (weak) { box->closeBox(); diff --git a/Telegram/SourceFiles/ui/chat/choose_send_as.cpp b/Telegram/SourceFiles/ui/chat/choose_send_as.cpp index d7c7f08ab3..be0fa5601b 100644 --- a/Telegram/SourceFiles/ui/chat/choose_send_as.cpp +++ b/Telegram/SourceFiles/ui/chat/choose_send_as.cpp @@ -198,7 +198,7 @@ void ChooseSendAsBox( controller->clicked( ) | rpl::start_with_next([=](not_null peer) { - const auto weak = MakeWeak(box); + const auto weak = base::make_weak(box); if (done(peer) && weak) { box->closeBox(); } diff --git a/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp b/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp index 68c64708d7..42b0830749 100644 --- a/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp +++ b/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp @@ -384,7 +384,7 @@ void SubsectionSlider::activate(int index) { } } }; - const auto weak = MakeWeak(_bar); + const auto weak = base::make_weak(_bar); _sectionActivated.fire_copy(index); if (weak) { const auto duration = st::chatTabsSlider.duration; diff --git a/Telegram/SourceFiles/ui/countryinput.cpp b/Telegram/SourceFiles/ui/countryinput.cpp index bdf77d1c18..3cb78ae180 100644 --- a/Telegram/SourceFiles/ui/countryinput.cpp +++ b/Telegram/SourceFiles/ui/countryinput.cpp @@ -72,7 +72,7 @@ void CountryInput::mousePressEvent(QMouseEvent *e) { mouseMoveEvent(e); if (_active) { auto object = Box(); - const auto box = Ui::MakeWeak(object.data()); + const auto box = base::make_weak(object.data()); _show->showBox(std::move(object), Ui::LayerOption::CloseOther); box->entryChosen( ) | rpl::start_with_next([=]( diff --git a/Telegram/SourceFiles/ui/effects/scroll_content_shadow.cpp b/Telegram/SourceFiles/ui/effects/scroll_content_shadow.cpp index 5bc42cb8df..392caf2602 100644 --- a/Telegram/SourceFiles/ui/effects/scroll_content_shadow.cpp +++ b/Telegram/SourceFiles/ui/effects/scroll_content_shadow.cpp @@ -32,9 +32,9 @@ void SetupShadowsToScrollContent( bottomShadow->move( geometry.x(), geometry.y() + geometry.height() - st::lineWidth); - }, [t = Ui::MakeWeak(topShadow), b = Ui::MakeWeak(bottomShadow)] { - Ui::DestroyChild(t.data()); - Ui::DestroyChild(b.data()); + }, [t = base::make_weak(topShadow), b = base::make_weak(bottomShadow)] { + Ui::DestroyChild(t.get()); + Ui::DestroyChild(b.get()); }, topShadow->lifetime()); topShadow->toggleOn(scroll->scrollTopValue() | rpl::map(_1 > 0)); diff --git a/Telegram/SourceFiles/ui/ui_pch.h b/Telegram/SourceFiles/ui/ui_pch.h index eb9a86a713..f00ef0bf92 100644 --- a/Telegram/SourceFiles/ui/ui_pch.h +++ b/Telegram/SourceFiles/ui/ui_pch.h @@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/basic_types.h" #include "base/flat_map.h" #include "base/flat_set.h" +#include "base/weak_qptr.h" #include "core/credits_amount.h" @@ -40,5 +41,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text.h" #include "ui/effects/animations.h" #include "ui/qt_object_factory.h" -#include "ui/qt_weak_factory.h" #include "styles/palette.h" diff --git a/Telegram/SourceFiles/ui/widgets/chat_filters_tabs_strip.cpp b/Telegram/SourceFiles/ui/widgets/chat_filters_tabs_strip.cpp index 176b5644c4..96a66687bb 100644 --- a/Telegram/SourceFiles/ui/widgets/chat_filters_tabs_strip.cpp +++ b/Telegram/SourceFiles/ui/widgets/chat_filters_tabs_strip.cpp @@ -88,7 +88,7 @@ void ShowMenu( addAction); auto showRemoveBox = [=] { - state->removeApi.request(Ui::MakeWeak(parent), controller, id); + state->removeApi.request(base::make_weak(parent), controller, id); }; addAction({ .text = tr::lng_filters_context_remove(tr::now), diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index 95944d2f90..29da7f47ad 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -264,7 +264,7 @@ void SectionWidget::setGeometryWithTopMoved( _topDelta = topDelta; bool willBeResized = (size() != newGeometry.size()); if (geometry() != newGeometry) { - auto weak = Ui::MakeWeak(this); + auto weak = base::make_weak(this); setGeometry(newGeometry); if (!weak) { return; diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp index e7baf9c612..deba4892ad 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp @@ -725,7 +725,7 @@ void Editor::showMenu() { _menu = base::make_unique_q( this, st::dropdownMenuWithIcons); - _menu->setHiddenCallback([weak = Ui::MakeWeak(this), menu = _menu.get()]{ + _menu->setHiddenCallback([weak = base::make_weak(this), menu = _menu.get()]{ menu->deleteLater(); if (weak && weak->_menu == menu) { weak->_menu = nullptr; diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_block.h b/Telegram/SourceFiles/window/themes/window_theme_editor_block.h index 3b3f256afe..b41e479c50 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_block.h +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_block.h @@ -26,8 +26,8 @@ public: }; struct Context { struct { - QPointer box; - QPointer editor; + base::weak_qptr box; + base::weak_qptr editor; } colorEditor; QString name; QString possibleCopyOf; diff --git a/Telegram/SourceFiles/window/window_chat_preview.cpp b/Telegram/SourceFiles/window/window_chat_preview.cpp index 2a9607accb..68498ec087 100644 --- a/Telegram/SourceFiles/window/window_chat_preview.cpp +++ b/Telegram/SourceFiles/window/window_chat_preview.cpp @@ -54,7 +54,7 @@ bool ChatPreviewManager::show( return false; } _menu = std::move(preview.menu); - const auto weakMenu = Ui::MakeWeak(_menu.get()); + const auto weakMenu = base::make_weak(_menu.get()); const auto weakThread = base::make_weak(row.key.entry()->asThread()); const auto weakController = base::make_weak(_controller); std::move( @@ -82,7 +82,7 @@ bool ChatPreviewManager::show( } } } - if (const auto strong = weakMenu.data()) { + if (const auto strong = weakMenu.get()) { strong->hideMenu(); } }, _menu->lifetime()); diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index fb47a4050e..437e75f0d5 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -276,7 +276,7 @@ void Controller::checkLockByTerms() { showTermsDecline(); }, box->lifetime()); - QObject::connect(box, &QObject::destroyed, [=] { + QObject::connect(box.get(), &QObject::destroyed, [=] { crl::on_main(widget(), [=] { checkLockByTerms(); }); }); diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index 3eb6184e9d..a1a2d23b4e 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -98,11 +98,11 @@ public: typename BoxType, typename = std::enable_if_t< std::is_base_of_v>> - QPointer show( + base::weak_qptr show( object_ptr content, Ui::LayerOptions options = Ui::LayerOption::KeepOther, anim::type animated = anim::type()) { - auto result = QPointer(content.data()); + auto result = base::weak_qptr(content.data()); showBox(std::move(content), options, animated); return result; } @@ -168,7 +168,7 @@ private: const std::unique_ptr _adaptive; std::unique_ptr _sessionController; rpl::variable _sessionControllerValue; - QPointer _termsBox; + base::weak_qptr _termsBox; rpl::event_stream _openInMediaViewRequests; diff --git a/Telegram/SourceFiles/window/window_filters_menu.cpp b/Telegram/SourceFiles/window/window_filters_menu.cpp index 1e71a84b78..b23efa32f9 100644 --- a/Telegram/SourceFiles/window/window_filters_menu.cpp +++ b/Telegram/SourceFiles/window/window_filters_menu.cpp @@ -389,7 +389,7 @@ void FiltersMenu::showMenu(QPoint position, FilterId id) { addAction({ .text = tr::lng_filters_context_remove(tr::now), .handler = crl::guard(&_outer, [=, this] { - _removeApi.request(Ui::MakeWeak(&_outer), _session, id); + _removeApi.request(base::make_weak(&_outer), _session, id); }), .icon = &st::menuIconDeleteAttention, .isAttention = true, diff --git a/Telegram/SourceFiles/window/window_lock_widgets.cpp b/Telegram/SourceFiles/window/window_lock_widgets.cpp index b674458d11..3e2f6cb0ce 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -212,10 +212,10 @@ void PasscodeLockWidget::suggestSystemUnlock() { ) | rpl::filter( rpl::mappers::_1 != SystemUnlockType::None ) | rpl::take(1) | rpl::start_with_next([=] { - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); const auto done = [weak](SystemUnlockResult result) { crl::on_main([=] { - if (const auto strong = weak.data()) { + if (const auto strong = weak.get()) { strong->systemUnlockDone(result); } }); diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 7c0deede45..9c52ca45d6 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -751,7 +751,7 @@ void MainMenu::setupMenu() { tr::lng_theme_editor_cant_change_theme())); return; } - const auto weak = MakeWeak(this); + const auto weak = base::make_weak(this); const auto toggle = [=] { if (!weak) { Window::Theme::ToggleNightMode(); @@ -941,7 +941,7 @@ base::EventFilterResult MainMenu::redirectToInnerChecked(not_null e) { if (_insideEventRedirect) { return base::EventFilterResult::Continue; } - const auto weak = Ui::MakeWeak(this); + const auto weak = base::make_weak(this); _insideEventRedirect = true; QGuiApplication::sendEvent(_inner, e); if (weak) { diff --git a/Telegram/SourceFiles/window/window_main_menu_helpers.cpp b/Telegram/SourceFiles/window/window_main_menu_helpers.cpp index baf22753d5..0a05a3371e 100644 --- a/Telegram/SourceFiles/window/window_main_menu_helpers.cpp +++ b/Telegram/SourceFiles/window/window_main_menu_helpers.cpp @@ -353,7 +353,7 @@ void SetupMenuBots( st::mainMenuButton.iconLeft, (height - icon->height()) / 2); }, button->lifetime()); - const auto weak = Ui::MakeWeak(container); + const auto weak = base::make_weak(container); const auto show = controller->uiShow(); button->setAcceptBoth(true); button->clicks( diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index d16067c79f..58775ff4cb 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1832,7 +1832,7 @@ void PeerMenuShareContactBox( return; } // There is no async to make weak from controller. - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto callback = [=](not_null thread) { const auto peer = thread->peer(); if (!Data::CanSend(thread, ChatRestriction::SendOther)) { @@ -1956,7 +1956,7 @@ void PeerMenuCreatePoll( SendPaymentHelper sendPayment; bool lock = false; }; - const auto weak = QPointer(box); + const auto weak = base::make_weak(box); const auto state = box->lifetime().make_state(); state->create = [=](const CreatePollBox::Result &result) { auto action = Api::SendAction( @@ -2066,7 +2066,7 @@ void PeerMenuCreateTodoList( SendPaymentHelper sendPayment; bool lock = false; }; - const auto weak = QPointer(box); + const auto weak = base::make_weak(box); const auto state = box->lifetime().make_state(); state->create = [=](const EditTodoListBox::Result &result) { const auto withPaymentApproved = crl::guard(weak, [=](int stars) { @@ -2126,7 +2126,7 @@ void PeerMenuEditTodoList( return; } auto box = Box(controller, item); - const auto weak = QPointer(box); + const auto weak = base::make_weak(box); box->submitRequests( ) | rpl::start_with_next([=](const EditTodoListBox::Result &result) { const auto api = &item->history()->session().api(); @@ -2328,7 +2328,7 @@ object_ptr PrepareChooseRecipientBox( Fn>, Api::SendOptions)> sendMany) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto selectable = (sendMany != nullptr); class Controller final : public ChooseRecipientBoxController { public: @@ -2463,7 +2463,7 @@ object_ptr PrepareChooseRecipientBox( state->refreshStarsToSend(); const auto shown = raw->hasSelected(); if (shown) { - const auto weak = Ui::MakeWeak(box); + const auto weak = base::make_weak(box); state->submit = [=](Api::SendOptions options) { state->submitLifetime.destroy(); const auto show = box->peerListUiShow(); @@ -2551,7 +2551,7 @@ object_ptr PrepareChooseRecipientBox( return result; } -QPointer ShowChooseRecipientBox( +base::weak_qptr ShowChooseRecipientBox( not_null navigation, FnMut)> &&chosen, rpl::producer titleOverride, @@ -2565,7 +2565,7 @@ QPointer ShowChooseRecipientBox( typesRestriction)); } -QPointer ShowForwardMessagesBox( +base::weak_qptr ShowForwardMessagesBox( std::shared_ptr show, Data::ForwardDraft &&draft, Fn &&successCallback) { @@ -2825,10 +2825,10 @@ QPointer ShowForwardMessagesBox( }; auto callback = [=, chosen = std::move(chosen)]( Controller::Chosen thread) mutable { - const auto weak = Ui::MakeWeak(state->box); + const auto weak = base::make_weak(state->box); if (!chosen(thread)) { return; - } else if (const auto strong = weak.data()) { + } else if (const auto strong = weak.get()) { strong->closeBox(); } if (successCallback) { @@ -2857,7 +2857,7 @@ QPointer ShowForwardMessagesBox( history, msgIds); - const auto weak = Ui::MakeWeak(state->box); + const auto weak = base::make_weak(state->box); const auto field = comment->entity(); state->submit = [=](Api::SendOptions options) { const auto peers = state->box->collectSelectedRows(); @@ -3090,10 +3090,10 @@ QPointer ShowForwardMessagesBox( }); }, state->box->lifetime()); - return QPointer(state->box); + return base::make_weak(state->box); } -QPointer ShowForwardMessagesBox( +base::weak_qptr ShowForwardMessagesBox( not_null navigation, Data::ForwardDraft &&draft, Fn &&successCallback) { @@ -3103,7 +3103,7 @@ QPointer ShowForwardMessagesBox( std::move(successCallback)); } -QPointer ShowForwardMessagesBox( +base::weak_qptr ShowForwardMessagesBox( not_null navigation, MessageIdsList &&items, Fn &&successCallback) { @@ -3113,13 +3113,13 @@ QPointer ShowForwardMessagesBox( std::move(successCallback)); } -QPointer ShowShareGameBox( +base::weak_qptr ShowShareGameBox( not_null navigation, not_null bot, QString shortName) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto chosen = [=](not_null thread) mutable { - const auto confirm = std::make_shared>(); + const auto confirm = std::make_shared>(); auto send = crl::guard(thread, [=] { ShareBotGame(bot, thread, shortName); if (const auto strong = *weak) { @@ -3166,15 +3166,15 @@ QPointer ShowShareGameBox( .moneyRestrictionError = WriteMoneyRestrictionError, }), std::move(initBox))); - return weak->data(); + return weak->get(); } -QPointer ShowDropMediaBox( +base::weak_qptr ShowDropMediaBox( not_null navigation, std::shared_ptr data, not_null forum, FnMut &&successCallback) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto chosen = [ data = std::move(data), callback = std::move(successCallback), @@ -3206,15 +3206,15 @@ QPointer ShowDropMediaBox( forum, std::move(chosen)), std::move(initBox))); - return weak->data(); + return weak->get(); } -QPointer ShowDropMediaBox( +base::weak_qptr ShowDropMediaBox( not_null navigation, std::shared_ptr data, not_null monoforum, FnMut &&successCallback) { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); auto chosen = [ data = std::move(data), callback = std::move(successCallback), @@ -3246,10 +3246,10 @@ QPointer ShowDropMediaBox( monoforum, std::move(chosen)), std::move(initBox))); - return weak->data(); + return weak->get(); } -QPointer ShowSendNowMessagesBox( +base::weak_qptr ShowSendNowMessagesBox( not_null navigation, not_null history, MessageIdsList &&items, @@ -3298,7 +3298,7 @@ QPointer ShowSendNowMessagesBox( .text = text, .confirmed = std::move(done), .confirmText = tr::lng_send_button(), - })).data(); + })); } void PeerMenuAddChannelMembers( @@ -3826,7 +3826,7 @@ void PeerMenuConfirmToggleFee( return; } navigation->uiShow()->show(Box([=](not_null box) { - const auto refund = std::make_shared>(); + const auto refund = std::make_shared>(); Ui::ConfirmBox(box, { .text = tr::lng_payment_refund_text( tr::now, @@ -3846,7 +3846,7 @@ void PeerMenuConfirmToggleFee( *paid = paidAmount->value(); paid->value() | rpl::start_with_next([=](int already) { if (!already) { - delete base::take(*refund); + delete base::take(*refund).get(); } else if (!*refund) { const auto skip = st::defaultCheckbox.margin.top(); *refund = box->addRow( diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index 56c4a6baec..a39b2ba3ac 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -182,45 +182,45 @@ object_ptr PrepareChooseRecipientBox( Fn>, Api::SendOptions)> sendMany = nullptr); -QPointer ShowChooseRecipientBox( +base::weak_qptr ShowChooseRecipientBox( not_null navigation, FnMut)> &&chosen, rpl::producer titleOverride = nullptr, FnMut &&successCallback = nullptr, InlineBots::PeerTypes typesRestriction = 0); -QPointer ShowForwardMessagesBox( +base::weak_qptr ShowForwardMessagesBox( std::shared_ptr show, Data::ForwardDraft &&draft, Fn &&successCallback = nullptr); -QPointer ShowForwardMessagesBox( +base::weak_qptr ShowForwardMessagesBox( not_null navigation, Data::ForwardDraft &&draft, Fn &&successCallback = nullptr); -QPointer ShowForwardMessagesBox( +base::weak_qptr ShowForwardMessagesBox( not_null navigation, MessageIdsList &&items, Fn &&successCallback = nullptr); -QPointer ShowShareUrlBox( +base::weak_qptr ShowShareUrlBox( not_null navigation, const QString &url, const QString &text, FnMut &&successCallback = nullptr); -QPointer ShowShareGameBox( +base::weak_qptr ShowShareGameBox( not_null navigation, not_null bot, QString shortName); -QPointer ShowDropMediaBox( +base::weak_qptr ShowDropMediaBox( not_null navigation, std::shared_ptr data, not_null forum, FnMut &&successCallback = nullptr); -QPointer ShowDropMediaBox( +base::weak_qptr ShowDropMediaBox( not_null navigation, std::shared_ptr data, not_null monoforum, FnMut &&successCallback = nullptr); -QPointer ShowSendNowMessagesBox( +base::weak_qptr ShowSendNowMessagesBox( not_null navigation, not_null history, MessageIdsList &&items, diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index e58806b515..76f4ed2732 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -1022,14 +1022,14 @@ void SessionNavigation::applyBoost( } done({}); } else { - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto reassign = [=]( std::vector slots, int groups, int channels) { const auto count = int(slots.size()); const auto callback = [=](Ui::BoostCounters counters) { - if (const auto strong = weak->data()) { + if (const auto strong = weak->get()) { strong->closeBox(); } done(counters); @@ -2934,7 +2934,7 @@ auto SessionController::stickerOrEmojiChosen() const return _stickerOrEmojiChosen.events(); } -QPointer SessionController::show( +base::weak_qptr SessionController::show( object_ptr content, Ui::LayerOptions options, anim::type animated) { diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 7bde45c28d..8ca4819def 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -390,7 +390,7 @@ public: void stickerOrEmojiChosen(FileChosen chosen); [[nodiscard]] rpl::producer stickerOrEmojiChosen() const; - QPointer show( + base::weak_qptr show( object_ptr content, Ui::LayerOptions options = Ui::LayerOption::KeepOther, anim::type animated = anim::type::normal); diff --git a/Telegram/lib_base b/Telegram/lib_base index 402034cba6..bed6d0be44 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 402034cba675220647c5e2041f38cf9d977d496e +Subproject commit bed6d0be4422b8733d3c7e691eac6adf8439597f diff --git a/Telegram/lib_spellcheck b/Telegram/lib_spellcheck index c8ded8b758..81297706b3 160000 --- a/Telegram/lib_spellcheck +++ b/Telegram/lib_spellcheck @@ -1 +1 @@ -Subproject commit c8ded8b7585f8819780ea22a40c237625aec0c75 +Subproject commit 81297706b32a6ec829a7dff5461ff458f82fb602 diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 15bed2e494..1cb389224f 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 15bed2e494c4fa52c93681e7e03c4a83f1e15a6a +Subproject commit 1cb389224f285e619f2fbc3f9395516d17d62682 From dcac27e0729bc3975965a0497154d54b18def49d Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 23 Jul 2025 11:33:49 +0400 Subject: [PATCH 033/341] Make sure colors are ready for webview. --- .../inline_bots/bot_attach_web_view.cpp | 29 +++++++++++++++++++ .../inline_bots/bot_attach_web_view.h | 3 ++ 2 files changed, 32 insertions(+) diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 8e1af089b1..02304eb965 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -885,7 +885,28 @@ void WebViewInstance::activate() { } } +void WebViewInstance::requestFullBot() { + if (_bot->isFullLoaded()) { + return; + } + _bot->updateFull(); + _bot->session().changes().peerUpdates( + _bot, + Data::PeerUpdate::Flag::FullInfo + ) | rpl::start_with_next([=] { + if (_botFullWaitingArgs.has_value()) { + auto args = *base::take(_botFullWaitingArgs); + if (args.url.isEmpty()) { + showGame(); + } else { + show(std::move(args)); + } + } + }, _lifetime); +} + void WebViewInstance::resolve() { + requestFullBot(); v::match(_source, [&](WebViewSourceButton data) { confirmOpen([=] { if (data.simple) { @@ -1307,6 +1328,10 @@ void WebViewInstance::maybeChooseAndRequestButton(PeerTypes supported) { } void WebViewInstance::show(ShowArgs &&args) { + if (!_bot->isFullLoaded()) { + _botFullWaitingArgs.emplace(std::move(args)); + return; + } auto title = args.title.isEmpty() ? Info::Profile::NameValue(_bot) : rpl::single(args.title); @@ -1373,6 +1398,10 @@ void WebViewInstance::show(ShowArgs &&args) { void WebViewInstance::showGame() { Expects(v::is(_source)); + if (!_bot->isFullLoaded()) { + _botFullWaitingArgs.emplace(); + return; + } const auto game = v::get(_source); _panelUrl = QString::fromUtf8(_button.url); _panel = Ui::BotWebView::Show({ diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h index e7fe7f281e..7487de27e1 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h @@ -231,6 +231,7 @@ public: private: void resolve(); + void requestFullBot(); bool openAppFromBotMenuLink(); @@ -313,6 +314,8 @@ private: const WebViewButton _button; const WebViewSource _source; + std::optional _botFullWaitingArgs; + BotAppData *_app = nullptr; QString _appStartParam; bool _dataSent = false; From 048d995922d5ba1cf9cd35262329b2d24ff79355 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 23 Jul 2025 12:27:22 +0400 Subject: [PATCH 034/341] Add weak_qptr to stdafx.h --- Telegram/SourceFiles/stdafx.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index b111130433..1bc3da35d3 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -118,6 +118,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/optional.h" #include "base/variant.h" #include "base/weak_ptr.h" +#include "base/weak_qptr.h" #include "scheme.h" #include "mtproto/type_utils.h" From 65e3111e3555cea9920d63289f425a1605a3e5f6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 23 Jul 2025 13:06:58 +0400 Subject: [PATCH 035/341] Use real cloud lang. --- .../history/view/media/history_view_media_common.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp index 431a45e7a3..56079194d1 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_common.cpp @@ -81,9 +81,8 @@ rpl::producer AgeVerifyAbout( }; Assert(shift >= 0 && shift < postfixes.size()); const auto postfix = *(begin(postfixes) + shift); - return Ui::Text::RichLangValue(u"To access such content, you must confirm that you are at least **{count}** years old as required by UK law."_q.replace(u"{count}"_q, string)); return Ui::Text::RichLangValue(Lang::GetNonDefaultValue( - kVerifyAgeAboutPrefix + country.toUtf8() + postfix AssertIsDebug(test_this) + kVerifyAgeAboutPrefix + country.toUtf8() + postfix ).replace(u"{count}"_q, string)); }); } @@ -378,7 +377,7 @@ void ShowAgeVerification( } else { show->showToast({ .title = tr::lng_age_verify_sorry_title(tr::now), - .text = tr::lng_age_verify_sorry_text(tr::now), + .text = { tr::lng_age_verify_sorry_text(tr::now) }, .duration = Ui::Toast::kDefaultDuration * 3, }); } From 25d4a9c7a662b191e06742882061f080d2c8a83e Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 15 Jul 2025 10:28:13 +0400 Subject: [PATCH 036/341] Parse current stars rating values. --- Telegram/SourceFiles/data/data_changes.h | 33 ++++++++++++------------ Telegram/SourceFiles/data/data_peer.cpp | 7 +++++ Telegram/SourceFiles/data/data_peer.h | 14 ++++++++++ Telegram/SourceFiles/data/data_user.cpp | 26 +++++++++++++++++++ Telegram/SourceFiles/data/data_user.h | 4 +++ 5 files changed, 68 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h index 190f3f554c..86dc7f2bf4 100644 --- a/Telegram/SourceFiles/data/data_changes.h +++ b/Telegram/SourceFiles/data/data_changes.h @@ -99,28 +99,29 @@ struct PeerUpdate { StarRefProgram = (1ULL << 35), PaysPerMessage = (1ULL << 36), GiftSettings = (1ULL << 37), + StarsRating = (1ULL << 38), // For chats and channels - InviteLinks = (1ULL << 38), - Members = (1ULL << 39), - Admins = (1ULL << 40), - BannedUsers = (1ULL << 41), - Rights = (1ULL << 42), - PendingRequests = (1ULL << 43), - Reactions = (1ULL << 44), + InviteLinks = (1ULL << 39), + Members = (1ULL << 40), + Admins = (1ULL << 41), + BannedUsers = (1ULL << 42), + Rights = (1ULL << 43), + PendingRequests = (1ULL << 44), + Reactions = (1ULL << 45), // For channels - ChannelAmIn = (1ULL << 45), - StickersSet = (1ULL << 46), - EmojiSet = (1ULL << 47), - DiscussionLink = (1ULL << 48), - MonoforumLink = (1ULL << 49), - ChannelLocation = (1ULL << 50), - Slowmode = (1ULL << 51), - GroupCall = (1ULL << 52), + ChannelAmIn = (1ULL << 46), + StickersSet = (1ULL << 47), + EmojiSet = (1ULL << 48), + DiscussionLink = (1ULL << 49), + MonoforumLink = (1ULL << 50), + ChannelLocation = (1ULL << 51), + Slowmode = (1ULL << 52), + GroupCall = (1ULL << 53), // For iteration - LastUsedBit = (1ULL << 52), + LastUsedBit = (1ULL << 53), }; using Flags = base::flags; friend inline constexpr auto is_flag_type(Flag) { return true; } diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index cbc27b596a..fe0cbdf698 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1690,6 +1690,13 @@ int PeerData::starsPerMessageChecked() const { return starsPerMessage(); } +Data::StarsRating PeerData::starsRating() const { + if (const auto user = asUser()) { + return user->starsRating(); + } + return {}; +} + Data::GroupCall *PeerData::groupCall() const { if (const auto chat = asChat()) { return chat->groupCall(); diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 66f9d91ef9..96774bf5f7 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -109,6 +109,19 @@ struct UnavailableReason { const MTPvector *list); }; +struct StarsRating { + int level = 0; + int levelStars = 0; + int currentStars = 0; + int nextLevelStars = 0; + + explicit operator bool() const { + return level != 0 || levelStars != 0; + } + + friend inline bool operator==(StarsRating, StarsRating) = default; +}; + bool ApplyBotMenuButton( not_null info, const MTPBotMenuButton *button); @@ -290,6 +303,7 @@ public: [[nodiscard]] int starsPerMessage() const; [[nodiscard]] int starsPerMessageChecked() const; + [[nodiscard]] Data::StarsRating starsRating() const; [[nodiscard]] UserData *asBot(); [[nodiscard]] const UserData *asBot() const; diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 308b1bb609..dd4aa9b6bf 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -64,6 +64,20 @@ bool ApplyBotVerifierSettings( return false; } +[[nodiscard]] Data::StarsRating ParseStarsRating( + const MTPStarsRating *rating) { + if (!rating) { + return {}; + } + const auto &data = rating->data(); + return { + .level = data.vlevel().v, + .levelStars = int(data.vcurrent_level_stars().v), + .currentStars = int(data.vstars().v), + .nextLevelStars = int(data.vnext_level_stars().value_or_empty()), + }; +} + } // namespace BotInfo::BotInfo() = default; @@ -563,6 +577,17 @@ void UserData::setStarsPerMessage(int stars) { checkTrustedPayForMessage(); } +void UserData::setStarsRating(Data::StarsRating value) { + if (_starsRating != value) { + _starsRating = value; + session().changes().peerUpdated(this, UpdateFlag::StarsRating); + } +} + +Data::StarsRating UserData::starsRating() const { + return _starsRating; +} + bool UserData::canAddContact() const { return canShareThisContact() && !isContact(); } @@ -848,6 +873,7 @@ void ApplyUserUpdate(not_null user, const MTPDuserFull &update) { } user->setBotVerifyDetails( ParseBotVerifyDetails(update.vbot_verification())); + user->setStarsRating(ParseStarsRating(update.vstars_rating())); if (const auto gifts = update.vdisallowed_gifts()) { const auto &data = gifts->data(); diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index b8c87b67b3..435692cda6 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -195,6 +195,9 @@ public: void setStarsPerMessage(int stars); [[nodiscard]] int starsPerMessage() const; + void setStarsRating(Data::StarsRating value); + [[nodiscard]] Data::StarsRating starsRating() const; + [[nodiscard]] bool canShareThisContact() const; [[nodiscard]] bool canAddContact() const; @@ -300,6 +303,7 @@ private: QString _phone; QString _privateForwardName; std::unique_ptr _botVerifyDetails; + Data::StarsRating _starsRating; ChannelId _personalChannelId = 0; MsgId _personalChannelMessageId = 0; From 232c797507b0340c7149d123d0961a642fc86383 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 15 Jul 2025 14:07:09 +0400 Subject: [PATCH 037/341] Show stars rating bar. --- Telegram/CMakeLists.txt | 1 + Telegram/SourceFiles/data/data_peer.h | 16 +- Telegram/SourceFiles/data/data_peer_common.h | 25 ++ .../SourceFiles/data/data_peer_values.cpp | 13 ++ Telegram/SourceFiles/data/data_peer_values.h | 4 + Telegram/SourceFiles/info/info.style | 29 +++ .../info/profile/info_profile_cover.cpp | 27 ++- .../info/profile/info_profile_cover.h | 3 + .../SourceFiles/ui/controls/stars_rating.cpp | 215 ++++++++++++++++++ .../SourceFiles/ui/controls/stars_rating.h | 64 ++++++ Telegram/cmake/td_ui.cmake | 2 + 11 files changed, 382 insertions(+), 17 deletions(-) create mode 100644 Telegram/SourceFiles/data/data_peer_common.h create mode 100644 Telegram/SourceFiles/ui/controls/stars_rating.cpp create mode 100644 Telegram/SourceFiles/ui/controls/stars_rating.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index c0d00a6dbd..6e285ca175 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -612,6 +612,7 @@ PRIVATE data/data_peer_bot_command.h data/data_peer_bot_commands.cpp data/data_peer_bot_commands.h + data/data_peer_common.h data/data_peer_id.cpp data/data_peer_id.h data/data_peer_values.cpp diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 96774bf5f7..2e17161d75 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -7,10 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "data/notify/data_peer_notify_settings.h" #include "data/data_types.h" #include "data/data_flags.h" -#include "data/notify/data_peer_notify_settings.h" #include "data/data_cloud_file.h" +#include "data/data_peer_common.h" #include "ui/userpic_view.h" struct BotInfo; @@ -109,19 +110,6 @@ struct UnavailableReason { const MTPvector *list); }; -struct StarsRating { - int level = 0; - int levelStars = 0; - int currentStars = 0; - int nextLevelStars = 0; - - explicit operator bool() const { - return level != 0 || levelStars != 0; - } - - friend inline bool operator==(StarsRating, StarsRating) = default; -}; - bool ApplyBotMenuButton( not_null info, const MTPBotMenuButton *button); diff --git a/Telegram/SourceFiles/data/data_peer_common.h b/Telegram/SourceFiles/data/data_peer_common.h new file mode 100644 index 0000000000..87d1722ab1 --- /dev/null +++ b/Telegram/SourceFiles/data/data_peer_common.h @@ -0,0 +1,25 @@ +/* +This file is part of Telegram Desktop, +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 +*/ +#pragma once + +namespace Data { + +struct StarsRating { + int level = 0; + int levelStars = 0; + int currentStars = 0; + int nextLevelStars = 0; + + explicit operator bool() const { + return level != 0 || levelStars != 0; + } + + friend inline bool operator==(StarsRating, StarsRating) = default; +}; + +} // namespace Data diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp index 5739124d45..0da1a8137f 100644 --- a/Telegram/SourceFiles/data/data_peer_values.cpp +++ b/Telegram/SourceFiles/data/data_peer_values.cpp @@ -518,6 +518,19 @@ bool ChannelHasSubscriptionUntilDate(ChannelData *channel) { return channel && channel->subscriptionUntilDate() > 0; } +rpl::producer StarsRatingValue( + not_null peer) { + if (const auto user = peer->asUser()) { + return user->session().changes().peerFlagsValue( + user, + Data::PeerUpdate::Flag::StarsRating + ) | rpl::map([=] { + return user->starsRating(); + }); + } + return rpl::single(Data::StarsRating()); +} + rpl::producer PeerUserpicImageValue( not_null peer, int size, diff --git a/Telegram/SourceFiles/data/data_peer_values.h b/Telegram/SourceFiles/data/data_peer_values.h index b726746be0..322e1dda39 100644 --- a/Telegram/SourceFiles/data/data_peer_values.h +++ b/Telegram/SourceFiles/data/data_peer_values.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "data/data_peer.h" +#include "data/data_peer_values.h" #include "data/data_chat_participant_status.h" enum class ImageRoundRadius; @@ -166,6 +167,9 @@ inline auto PeerFullFlagValue( [[nodiscard]] bool ChannelHasActiveCall(not_null channel); [[nodiscard]] bool ChannelHasSubscriptionUntilDate(ChannelData *channel); +[[nodiscard]] rpl::producer StarsRatingValue( + not_null peer); + [[nodiscard]] rpl::producer PeerUserpicImageValue( not_null peer, int size, diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 5c9efd10c3..310387abb9 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -351,6 +351,8 @@ InfoProfileCover { status: FlatLabel; statusLeft: pixels; statusTop: pixels; + starsRatingLeft: pixels; + starsRatingTop: pixels; showLastSeen: RoundButton; showLastSeenPosition: point; showLastSeenVisible: bool; @@ -384,6 +386,8 @@ infoProfileCover: InfoProfileCover { status: infoProfileStatus; statusLeft: 109px; statusTop: 58px; + starsRatingLeft: 107px; + starsRatingTop: 57px; showLastSeen: RoundButton(defaultActiveButton) { textFg: windowSubTextFg; textFgOver: windowSubTextFg; @@ -1187,3 +1191,28 @@ topicsLayoutButtonIconPadding: margins(4px, 0px, 4px, 0px); topicsLayoutButtonIconSize: 140px; topicsLayoutButtonPadding: margins(4px, 0px, 4px, 12px); topicsLayoutButtonSkip: 0px; + +StarsRating { + margin: margins; + padding: margins; + style: TextStyle; + minSkip: pixels; + border: pixels; + activeBg: color; + inactiveBg: color; + activeFg: color; + inactiveFg: color; +} +infoStarsRating: StarsRating { + margin: margins(6px, 6px, 6px, 6px); + padding: margins(4px, 1px, 4px, 1px); + style: TextStyle(defaultTextStyle) { + font: font(11px semibold); + } + minSkip: 32px; + border: 2px; + activeBg: windowBgActive; + inactiveBg: windowBgRipple; + activeFg: windowFgActive; + inactiveFg: windowBoldFg; +} diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp index f6798194c3..906a7385d7 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp @@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/media/history_view_sticker_player.h" #include "lang/lang_keys.h" #include "ui/boxes/show_or_premium_box.h" +#include "ui/controls/stars_rating.h" #include "ui/controls/userpic_button.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" @@ -644,6 +645,12 @@ Cover::Cover( ? object_ptr(this, controller, topic) : nullptr) , _name(this, _st.name) +, _starsRating(_peer->isUser() + ? std::make_unique( + this, + st::infoStarsRating, + Data::StarsRatingValue(_peer)) + : nullptr) , _status(this, _st.status) , _showLastSeen(this, tr::lng_status_lastseen_when(), _st.showLastSeen) , _refreshStatusTimer([this] { refreshStatusText(); }) { @@ -657,6 +664,16 @@ Cover::Cover( if (!_peer->isMegagroup()) { _status->setAttribute(Qt::WA_TransparentForMouseEvents); + if (const auto rating = _starsRating.get()) { + _status->widthValue() | rpl::start_with_next([=](int width) { + rating->setMinimalAddedWidth(width); + }, rating->lifetime()); + _statusShift = rating->collapsedWidthValue(); + _statusShift.changes() | rpl::start_with_next([=] { + refreshStatusGeometry(width()); + }, _status->lifetime()); + rating->raise(); + } } setupShowLastSeen(); @@ -1053,9 +1070,13 @@ void Cover::refreshNameGeometry(int newWidth) { } void Cover::refreshStatusGeometry(int newWidth) { - auto statusWidth = newWidth - _st.statusLeft - _st.rightSkip; - _status->resizeToWidth(statusWidth); - _status->moveToLeft(_st.statusLeft, _st.statusTop, newWidth); + if (const auto rating = _starsRating.get()) { + rating->moveTo(_st.starsRatingLeft, _st.starsRatingTop); + } + const auto statusLeft = _st.statusLeft + _statusShift.current(); + auto statusWidth = newWidth - statusLeft - _st.rightSkip; + _status->resizeToNaturalWidth(statusWidth); + _status->moveToLeft(statusLeft, _st.statusTop, newWidth); const auto left = _st.statusLeft + _status->textMaxWidth(); _showLastSeen->moveToLeft( left + _st.showLastSeenPosition.x(), diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.h b/Telegram/SourceFiles/info/profile/info_profile_cover.h index 5add87fc71..7e45160788 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.h +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.h @@ -22,6 +22,7 @@ class FlatLabel; template class SlideWrap; class RoundButton; +class StarsRating; } // namespace Ui namespace HistoryView { @@ -171,7 +172,9 @@ private: std::optional _personalChosen; object_ptr _iconButton; object_ptr _name = { nullptr }; + std::unique_ptr _starsRating; object_ptr _status = { nullptr }; + rpl::variable _statusShift = 0; object_ptr _showLastSeen = { nullptr }; //object_ptr _dropArea = { nullptr }; base::Timer _refreshStatusTimer; diff --git a/Telegram/SourceFiles/ui/controls/stars_rating.cpp b/Telegram/SourceFiles/ui/controls/stars_rating.cpp new file mode 100644 index 0000000000..431eb1f328 --- /dev/null +++ b/Telegram/SourceFiles/ui/controls/stars_rating.cpp @@ -0,0 +1,215 @@ +/* +This file is part of Telegram Desktop, +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 "ui/controls/stars_rating.h" + +#include "lang/lang_keys.h" +#include "ui/widgets/buttons.h" +#include "ui/widgets/labels.h" +#include "ui/painter.h" +#include "ui/rp_widget.h" +#include "styles/style_info.h" + +namespace Ui { +namespace { + +constexpr auto kAutoCollapseTimeout = 4 * crl::time(1000); + +} // namespace + +StarsRating::StarsRating( + QWidget *parent, + const style::StarsRating &st, + rpl::producer value) +: _widget(std::make_unique(parent)) +, _st(st) +, _value(std::move(value)) +, _collapseTimer([=] { _expanded = false; }) { + init(); +} + +StarsRating::~StarsRating() = default; + +void StarsRating::init() { + _expanded.value() | rpl::start_with_next([=](bool expanded) { + _widget->setPointerCursor(!expanded); + const auto from = expanded ? 0. : 1.; + const auto till = expanded ? 1. : 0.; + _expandedAnimation.start([=] { + updateWidth(); + }, from, till, st::slideDuration); + }, lifetime()); + + _widget->paintRequest() | rpl::start_with_next([=] { + auto p = QPainter(_widget.get()); + paint(p); + }, lifetime()); + + _widget->setClickedCallback([=] { + if (!_value.current()) { + return; + } + _expanded = true; + _collapseTimer.callOnce(kAutoCollapseTimeout); + }); + + const auto added = _st.margin + _st.padding; + const auto border = 2 * _st.border; + const auto fontHeight = _st.style.font->height; + const auto height = added.top() + fontHeight + added.bottom() + border; + _widget->resize(_widget->width(), height); + + _value.value() | rpl::start_with_next([=](Data::StarsRating rating) { + if (!rating) { + _widget->resize(0, _widget->height()); + _collapsedWidthValue = 0; + _expanded = false; + updateExpandedWidth(); + _expandedAnimation.stop(); + return; + } + updateTexts(rating); + }, lifetime()); +} + +void StarsRating::updateTexts(Data::StarsRating rating) { + _collapsedText.setText( + _st.style, + Lang::FormatCountDecimal(rating.level)); + _expandedText.setText( + _st.style, + tr::lng_boost_level(tr::now, lt_count_decimal, rating.level)); + _nextText.setText( + _st.style, + (rating.nextLevelStars + ? Lang::FormatCountDecimal(rating.level + 1) + : QString())); + + const auto added = _st.padding; + const auto border = 2 * _st.border; + const auto add = added.left() + added.right() + border; + const auto min = _expandedText.maxWidth() + _nextText.maxWidth(); + const auto height = _widget->height(); + _minimalContentWidth = add + min + _st.minSkip; + _collapsedWidthValue = _st.margin.right() + + std::max( + add + _collapsedText.maxWidth(), + height - _st.margin.top() - _st.margin.bottom()); + updateExpandedWidth(); + updateWidth(); +} + +void StarsRating::updateExpandedWidth() { + _expandedWidthValue = _st.margin.right() + std::max( + _collapsedWidthValue.current() + _minimalAddedWidth.current(), + _minimalContentWidth.current()); +} + +void StarsRating::updateWidth() { + const auto widthToRight = anim::interpolate( + _collapsedWidthValue.current(), + _expandedWidthValue.current(), + _expandedAnimation.value(_expanded.current() ? 1. : 0.)); + _widget->resize(_st.margin.left() + widthToRight, _widget->height()); + _widget->update(); +} + +void StarsRating::raise() { + _widget->raise(); +} + +void StarsRating::moveTo(int x, int y) { + _widget->move(x - _st.margin.left(), y - _st.margin.top()); +} + +void StarsRating::paint(QPainter &p) { + const auto outer = _widget->rect().marginsRemoved(_st.margin); + if (outer.isEmpty()) { + return; + } + const auto border = _st.border; + const auto middle = outer.marginsRemoved( + { border, border, border, border }); + const auto mradius = middle.height() / 2.; + const auto inner = middle.marginsRemoved(_st.padding); + + const auto expanded = _expandedAnimation.value( + _expanded.current() ? 1. : 0.); + + auto hq = PainterHighQualityEnabler(p); + p.setPen(Qt::NoPen); + p.setBrush(_st.inactiveBg); + const auto oradius = outer.height() / 2.; + p.drawRoundedRect(outer, oradius, oradius); + p.setBrush(_st.activeBg); + + const auto value = _value.current(); + const auto expandedRatio = (value.nextLevelStars > value.levelStars) + ? ((value.nextLevelStars - value.currentStars) + / float64(value.nextLevelStars - value.levelStars)) + : 1.; + const auto skip = _st.style.font->spacew; + const auto expandedFilled = _st.padding.left() + + _expandedText.maxWidth() + + skip + + expandedRatio * (middle.width() + - _expandedText.maxWidth() + - _nextText.maxWidth() + - _st.padding.right() + - 2 * skip); + const auto collapsedFilled = middle.width(); + const auto filled = anim::interpolate( + collapsedFilled, + expandedFilled, + expanded); + p.drawRoundedRect( + middle.x(), + middle.y(), + filled, + middle.height(), + mradius, + mradius); + p.setPen(_st.activeFg); + if (expanded < 1.) { + p.setOpacity(1. - expanded); + const auto skip = (inner.width() - _collapsedText.maxWidth()) / 2; + _collapsedText.draw(p, { + .position = inner.topLeft() + QPoint(skip, 0), + .availableWidth = _collapsedText.maxWidth(), + }); + } + if (expanded > 0.) { + p.setOpacity(expanded); + _expandedText.draw(p, { + .position = inner.topLeft(), + .availableWidth = _expandedText.maxWidth(), + }); + + p.setPen(_st.inactiveFg); + _nextText.draw(p, { + .position = (inner.topLeft() + + QPoint(inner.width() - _nextText.maxWidth(), 0)), + .availableWidth = _nextText.maxWidth(), + }); + } +} + +void StarsRating::setMinimalAddedWidth(int addedWidth) { + _minimalAddedWidth = addedWidth + (_st.style.font->spacew * 2); + updateExpandedWidth(); + updateWidth(); +} + +rpl::producer StarsRating::collapsedWidthValue() const { + return _collapsedWidthValue.value(); +} + +rpl::lifetime &StarsRating::lifetime() { + return _widget->lifetime(); +} + +} // namespace Ui diff --git a/Telegram/SourceFiles/ui/controls/stars_rating.h b/Telegram/SourceFiles/ui/controls/stars_rating.h new file mode 100644 index 0000000000..43d079e0e6 --- /dev/null +++ b/Telegram/SourceFiles/ui/controls/stars_rating.h @@ -0,0 +1,64 @@ +/* +This file is part of Telegram Desktop, +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 +*/ +#pragma once + +#include "base/timer.h" +#include "data/data_peer_common.h" + +namespace style { +struct StarsRating; +} // namespace style + +namespace Ui { + +class AbstractButton; +class FlatLabel; + +class StarsRating final { +public: + StarsRating( + QWidget *parent, + const style::StarsRating &st, + rpl::producer value); + ~StarsRating(); + + void raise(); + void moveTo(int x, int y); + void setMinimalAddedWidth(int addedWidth); + + [[nodiscard]] rpl::producer collapsedWidthValue() const; + + [[nodiscard]] rpl::lifetime &lifetime(); + +private: + void init(); + void paint(QPainter &p); + void updateTexts(Data::StarsRating rating); + void updateExpandedWidth(); + void updateWidth(); + + const std::unique_ptr _widget; + const style::StarsRating &_st; + + Ui::Text::String _collapsedText; + Ui::Text::String _expandedText; + Ui::Text::String _nextText; + + rpl::variable _value; + rpl::variable _collapsedWidthValue; + rpl::variable _expandedWidthValue; + rpl::variable _minimalContentWidth; + rpl::variable _minimalAddedWidth; + rpl::variable _expanded = false; + Ui::Animations::Simple _expandedAnimation; + + base::Timer _collapseTimer; + +}; + +} // namespace Ui diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 813c5bf02d..b625012c04 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -388,6 +388,8 @@ PRIVATE ui/controls/send_as_button.h ui/controls/send_button.cpp ui/controls/send_button.h + ui/controls/stars_rating.cpp + ui/controls/stars_rating.h ui/controls/subsection_tabs_slider.cpp ui/controls/subsection_tabs_slider.h ui/controls/swipe_handler.cpp From f655297052d5379421fd4e10d6f8d8bed29ff13a Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 15 Jul 2025 16:32:29 +0400 Subject: [PATCH 038/341] Show stars rating tooltips. --- Telegram/SourceFiles/info/info.style | 13 +- .../info/profile/info_profile_cover.cpp | 3 +- .../SourceFiles/ui/controls/stars_rating.cpp | 152 ++++++++++++++++-- .../SourceFiles/ui/controls/stars_rating.h | 18 ++- 4 files changed, 174 insertions(+), 12 deletions(-) diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 310387abb9..283fa1df9a 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -1205,7 +1205,7 @@ StarsRating { } infoStarsRating: StarsRating { margin: margins(6px, 6px, 6px, 6px); - padding: margins(4px, 1px, 4px, 1px); + padding: margins(6px, 1px, 6px, 1px); style: TextStyle(defaultTextStyle) { font: font(11px semibold); } @@ -1216,3 +1216,14 @@ infoStarsRating: StarsRating { activeFg: windowFgActive; inactiveFg: windowBoldFg; } +infoStarsRatingLearn: RoundButton(defaultActiveButton) { + width: -24px; + height: 44px; + textTop: 13px; + textFg: mediaviewTextLinkFg; + textFgOver: mediaviewTextLinkFg; + textBg: transparent; + textBgOver: transparent; + ripple: emptyRippleAnimation; +} +infoStarsRatingTooltip: defaultImportantTooltip; diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp index 906a7385d7..de499e71ed 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp @@ -649,7 +649,8 @@ Cover::Cover( ? std::make_unique( this, st::infoStarsRating, - Data::StarsRatingValue(_peer)) + Data::StarsRatingValue(_peer), + _parentForTooltip) : nullptr) , _status(this, _st.status) , _showLastSeen(this, tr::lng_status_lastseen_when(), _st.showLastSeen) diff --git a/Telegram/SourceFiles/ui/controls/stars_rating.cpp b/Telegram/SourceFiles/ui/controls/stars_rating.cpp index 431eb1f328..2fa02a2269 100644 --- a/Telegram/SourceFiles/ui/controls/stars_rating.cpp +++ b/Telegram/SourceFiles/ui/controls/stars_rating.cpp @@ -8,11 +8,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/controls/stars_rating.h" #include "lang/lang_keys.h" +#include "ui/toast/toast.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/widgets/tooltip.h" +#include "ui/basic_click_handlers.h" #include "ui/painter.h" #include "ui/rp_widget.h" +#include "ui/ui_utility.h" #include "styles/style_info.h" +#include "styles/style_media_view.h" namespace Ui { namespace { @@ -24,9 +29,11 @@ constexpr auto kAutoCollapseTimeout = 4 * crl::time(1000); StarsRating::StarsRating( QWidget *parent, const style::StarsRating &st, - rpl::producer value) + rpl::producer value, + Fn()> parentForTooltip) : _widget(std::make_unique(parent)) , _st(st) +, _parentForTooltip(std::move(parentForTooltip)) , _value(std::move(value)) , _collapseTimer([=] { _expanded = false; }) { init(); @@ -41,7 +48,11 @@ void StarsRating::init() { const auto till = expanded ? 1. : 0.; _expandedAnimation.start([=] { updateWidth(); + if (!_expandedAnimation.animating()) { + updateStarsTooltipGeometry(); + } }, from, till, st::slideDuration); + toggleTooltips(expanded); }, lifetime()); _widget->paintRequest() | rpl::start_with_next([=] { @@ -116,6 +127,126 @@ void StarsRating::updateWidth() { _expandedAnimation.value(_expanded.current() ? 1. : 0.)); _widget->resize(_st.margin.left() + widthToRight, _widget->height()); _widget->update(); + updateStarsTooltipGeometry(); +} + +void StarsRating::toggleTooltips(bool shown) { + if (!shown) { + if (const auto strong = _about.get()) { + strong->hideAnimated(); + } + if (const auto strong = _stars.release()) { + strong->toggleAnimated(false); + } + return; + } + const auto value = _value.current(); + const auto parent = _parentForTooltip + ? _parentForTooltip().get() + : _widget->window(); + const auto text = value.nextLevelStars + ? (Lang::FormatCountDecimal(value.currentStars) + + u" / "_q + + Lang::FormatCountDecimal(value.nextLevelStars)) + : Lang::FormatCountDecimal(value.currentStars); + _stars = std::make_unique( + parent, + Ui::MakeNiceTooltipLabel( + _widget.get(), + rpl::single(TextWithEntities{ text }), + st::storiesInfoTooltipMaxWidth, + st::storiesInfoTooltipLabel), + st::infoStarsRatingTooltip); + const auto stars = _stars.get(); + const auto weak = QPointer(stars); + const auto destroy = [=] { + delete weak.data(); + }; + stars->setAttribute(Qt::WA_TransparentForMouseEvents); + stars->setHiddenCallback(destroy); + updateStarsTooltipGeometry(); + stars->toggleAnimated(true); + + _aboutSt = std::make_unique(st::defaultMultilineToast); + const auto learn = u"Learn More"_q; + _aboutSt->padding.setRight( + (st::infoStarsRatingLearn.style.font->width(learn) + - st::infoStarsRatingLearn.width)); + + _about = Ui::Toast::Show(parent, { + .text = TextWithEntities{ + u"Profile level reflects the user's payment reliability."_q, + }, + .st = _aboutSt.get(), + .attach = RectPart::Top, + .dark = true, + .adaptive = true, + .acceptinput = true, + .duration = kAutoCollapseTimeout, + }); + const auto strong = _about.get(); + if (!strong) { + return; + } + const auto widget = strong->widget(); + const auto hideToast = [weak = _about] { + if (const auto strong = weak.get()) { + strong->hideAnimated(); + } + }; + + const auto button = Ui::CreateChild( + widget.get(), + rpl::single(learn), + st::infoStarsRatingLearn); + button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); + button->show(); + rpl::combine( + widget->sizeValue(), + button->sizeValue() + ) | rpl::start_with_next([=](QSize outer, QSize inner) { + button->moveToRight( + 0, + (outer.height() - inner.height()) / 2, + outer.width()); + }, widget->lifetime()); + button->setClickedCallback([=] { + UrlClickHandler::Open(u"https://telegram.org/"_q); + }); +} + +void StarsRating::updateStarsTooltipGeometry() { + if (!_stars) { + return; + } + const auto weakParent = base::make_weak(_stars->parentWidget()); + const auto weak = base::make_weak(_widget.get()); + const auto point = _st.margin.left() + + _st.border + + (_activeWidth / (_value.current().nextLevelStars ? 1 : 2)); + const auto countPosition = [=](QSize size) { + const auto strong = weak.get(); + const auto parent = weakParent.get(); + if (!strong || !parent) { + return QPoint(); + } + const auto geometry = Ui::MapFrom(parent, strong, strong->rect()); + const auto shift = size.width() / 2; + const auto left = geometry.x() + point - shift; + const auto margin = st::defaultImportantTooltip.margin; + return QPoint( + std::min( + std::max(left, margin.left()), + parent->width() - size.width() - margin.right()), + geometry.y() + geometry.height()); + }; + _stars->pointAt( + Ui::MapFrom( + _stars->parentWidget(), + _widget.get(), + QRect(point, 0, st::lineWidth, _widget->height())), + RectPart::Bottom, + countPosition); } void StarsRating::raise() { @@ -149,27 +280,30 @@ void StarsRating::paint(QPainter &p) { const auto value = _value.current(); const auto expandedRatio = (value.nextLevelStars > value.levelStars) - ? ((value.nextLevelStars - value.currentStars) + ? ((value.currentStars - value.levelStars) / float64(value.nextLevelStars - value.levelStars)) : 1.; - const auto skip = _st.style.font->spacew; const auto expandedFilled = _st.padding.left() + _expandedText.maxWidth() - + skip + + _st.padding.right() + expandedRatio * (middle.width() + - _st.padding.left() - _expandedText.maxWidth() - - _nextText.maxWidth() - _st.padding.right() - - 2 * skip); - const auto collapsedFilled = middle.width(); - const auto filled = anim::interpolate( + - _st.padding.left() + - _nextText.maxWidth() + - _st.padding.right()); + const auto collapsedFilled = _collapsedWidthValue.current() + - _st.margin.right() + - 2 * _st.border; + _activeWidth = anim::interpolate( collapsedFilled, expandedFilled, expanded); p.drawRoundedRect( middle.x(), middle.y(), - filled, + _activeWidth, middle.height(), mradius, mradius); diff --git a/Telegram/SourceFiles/ui/controls/stars_rating.h b/Telegram/SourceFiles/ui/controls/stars_rating.h index 43d079e0e6..6e94480b72 100644 --- a/Telegram/SourceFiles/ui/controls/stars_rating.h +++ b/Telegram/SourceFiles/ui/controls/stars_rating.h @@ -8,14 +8,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "base/timer.h" +#include "base/weak_ptr.h" #include "data/data_peer_common.h" namespace style { +struct Toast; struct StarsRating; } // namespace style +namespace Ui::Toast { +class Instance; +} // namespace Ui::Toast + namespace Ui { +class ImportantTooltip; class AbstractButton; class FlatLabel; @@ -24,7 +31,8 @@ public: StarsRating( QWidget *parent, const style::StarsRating &st, - rpl::producer value); + rpl::producer value, + Fn()> parentForTooltip); ~StarsRating(); void raise(); @@ -41,9 +49,16 @@ private: void updateTexts(Data::StarsRating rating); void updateExpandedWidth(); void updateWidth(); + void toggleTooltips(bool shown); + void updateStarsTooltipGeometry(); const std::unique_ptr _widget; const style::StarsRating &_st; + const Fn()> _parentForTooltip; + + std::unique_ptr _aboutSt; + base::weak_ptr _about; + std::unique_ptr _stars; Ui::Text::String _collapsedText; Ui::Text::String _expandedText; @@ -56,6 +71,7 @@ private: rpl::variable _minimalAddedWidth; rpl::variable _expanded = false; Ui::Animations::Simple _expandedAnimation; + mutable int _activeWidth = 0; base::Timer _collapseTimer; From be6dbefe7cac4e89cd14d9ec99a200cd53271fdc Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 15 Jul 2025 18:18:58 +0400 Subject: [PATCH 039/341] Show premium badge on gifts. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/api/api_premium.cpp | 4 ++++ Telegram/SourceFiles/data/data_star_gift.h | 3 +++ .../peer_gifts/info_peer_gifts_common.cpp | 19 ++++++++++++++++++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 0b988fb211..7ba789dab5 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3521,6 +3521,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_stars_sold_out" = "sold out"; "lng_gift_stars_resale" = "resale"; "lng_gift_stars_on_sale" = "on sale"; +"lng_gift_stars_premium" = "premium"; "lng_gift_stars_tabs_all" = "All Gifts"; "lng_gift_stars_tabs_my" = "My Gifts"; "lng_gift_stars_tabs_limited" = "Limited"; diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp index 5065541e27..835f3a1c70 100644 --- a/Telegram/SourceFiles/api/api_premium.cpp +++ b/Telegram/SourceFiles/api/api_premium.cpp @@ -825,8 +825,11 @@ std::optional FromTL( .resellCount = int(data.vavailability_resale().value_or_empty()), .limitedLeft = remaining.value_or_empty(), .limitedCount = total.value_or_empty(), + .perUserTotal = data.vper_user_total().value_or_empty(), + .perUserRemains = data.vper_user_remains().value_or_empty(), .firstSaleDate = data.vfirst_sale_date().value_or_empty(), .lastSaleDate = data.vlast_sale_date().value_or_empty(), + .requirePremium = data.is_require_premium(), .upgradable = data.vupgrade_stars().has_value(), .birthday = data.is_birthday(), .soldOut = data.is_sold_out(), @@ -877,6 +880,7 @@ std::optional FromTL( .releasedBy = releasedBy, .limitedLeft = (total - data.vavailability_issued().v), .limitedCount = total, + .requirePremium = data.is_require_premium(), }; const auto unique = result.unique.get(); for (const auto &attribute : data.vattributes().v) { diff --git a/Telegram/SourceFiles/data/data_star_gift.h b/Telegram/SourceFiles/data/data_star_gift.h index df0aacc953..8b53bd5581 100644 --- a/Telegram/SourceFiles/data/data_star_gift.h +++ b/Telegram/SourceFiles/data/data_star_gift.h @@ -74,8 +74,11 @@ struct StarGift { int resellCount = 0; int limitedLeft = 0; int limitedCount = 0; + int perUserTotal = 0; + int perUserRemains = 0; TimeId firstSaleDate = 0; TimeId lastSaleDate = 0; + bool requirePremium = false; bool upgradable = false; bool birthday = false; bool soldOut = false; diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp index 33e28a9227..da39de9903 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp @@ -419,8 +419,11 @@ void GiftButton::paintEvent(QPaintEvent *e) { ? v::get(_descriptor).info.unique.get() : nullptr; const auto onsale = (unique && unique->starsForResale && _small); + const auto requirePremium = v::is(_descriptor) + && !v::get(_descriptor).userpic + && v::get(_descriptor).info.requirePremium; const auto hidden = v::is(_descriptor) - && v::get(_descriptor).hidden;; + && v::get(_descriptor).hidden; const auto extend = currentExtend(); const auto position = QPoint(extend.left(), extend.top()); const auto background = _delegate->background(); @@ -430,6 +433,16 @@ void GiftButton::paintEvent(QPaintEvent *e) { if (unique) { cacheUniqueBackground(unique, width, background.height() / dpr); p.drawImage(extend.left(), extend.top(), _uniqueBackgroundCache); + } else if (requirePremium) { + auto hq = PainterHighQualityEnabler(p); + auto pen = st::creditsFg->p; + pen.setWidth(style::ConvertScaleExact(2.)); + p.setPen(pen); + p.setBrush(Qt::NoBrush); + const auto outer = QRect(0, 0, width, background.height() / dpr); + const auto extend = currentExtend(); + const auto radius = st::giftBoxGiftRadius; + p.drawRoundedRect(outer.marginsRemoved(extend), radius, radius); } if (_userpic) { @@ -526,6 +539,8 @@ void GiftButton::paintEvent(QPaintEvent *e) { ? tr::lng_gift_stars_resale(tr::now) : soldOut ? tr::lng_gift_stars_sold_out(tr::now) + : (!data.userpic && data.info.requirePremium) + ? tr::lng_gift_stars_premium(tr::now) : (!data.userpic && !data.info.unique) ? tr::lng_gift_stars_limited(tr::now) : (count == 1) @@ -544,6 +559,8 @@ void GiftButton::paintEvent(QPaintEvent *e) { ? st::boxTextFgGood->c : soldOut ? st::attentionButtonFg->c + : data.info.requirePremium + ? st::creditsFg->c : st::windowActiveTextFg->c), .bg2 = (onsale ? QColor(0, 0, 0, 0) From 1cb4413869c3065db6eeb2ff64df323e3e42236d Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 17 Jul 2025 11:33:06 +0400 Subject: [PATCH 040/341] Lang pack rating / premium gift features. --- Telegram/Resources/langs/lang.strings | 12 ++ Telegram/SourceFiles/boxes/star_gift_box.cpp | 20 +- .../peer_gifts/info_peer_gifts_common.cpp | 7 +- .../SourceFiles/settings/settings_premium.cpp | 193 ++++++++++++++---- .../SourceFiles/settings/settings_premium.h | 7 + .../SourceFiles/ui/controls/stars_rating.cpp | 36 ++-- 6 files changed, 217 insertions(+), 58 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 7ba789dab5..06857aae47 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1876,6 +1876,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_star_ref_revoked_title" = "Link removed"; "lng_star_ref_revoked_text" = "It will no longer work."; +"lng_stars_rating_tooltip" = "Profile level reflects the user's payment reliability."; +"lng_stars_rating_learn_more" = "Learn More"; +"lng_stars_rating_about_url" = "https://telegram.org/"; + "lng_manage_discussion_group" = "Discussion"; "lng_manage_discussion_group_add" = "Add a group"; "lng_manage_linked_channel" = "Linked channel"; @@ -2589,6 +2593,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_premium_unlock_emoji" = "Unlock Animated Emoji"; "lng_premium_unlock_status" = "Unlock Emoji Status"; +"lng_premium_subscribe_months_24" = "2-Year"; "lng_premium_subscribe_months_12" = "Annual"; "lng_premium_subscribe_months_6" = "Semiannual"; "lng_premium_subscribe_months_1" = "Monthly"; @@ -3508,6 +3513,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_ton_amount#one" = "{count} TON"; "lng_gift_ton_amount#other" = "{count} TON"; +"lng_gift_premium_title" = "Premium Gift"; +"lng_gift_premium_text#one" = "Subscribe to **Telegram Premium** to send up to **{count}** of these gifts and unlock access to multiple additional features."; +"lng_gift_premium_text#other" = "Subscribe to **Telegram Premium** to send up to **{count}** of these gifts and unlock access to multiple additional features."; "lng_gift_premium_or_stars" = "Gift Premium or Stars"; "lng_gift_premium_subtitle" = "Gift Premium"; "lng_gift_premium_about" = "Give {name} access to exclusive features with Telegram Premium. {features}"; @@ -3559,6 +3567,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_sent_resale_done_self" = "{gift} is now yours."; "lng_gift_sent_about#one" = "You spent **{count}** Star from your balance."; "lng_gift_sent_about#other" = "You spent **{count}** Stars from your balance."; +"lng_gift_sent_finished#one" = "You've already sent **{count}** of these gifts, and it's the limit."; +"lng_gift_sent_finished#other" = "You've already sent **{count}** of these gifts, and it's the limit."; +"lng_gift_sent_remains#one" = "You can send **{count}** more."; +"lng_gift_sent_remains#other" = "You can send **{count}** more."; "lng_gift_limited_of_one" = "unique"; "lng_gift_limited_of_count" = "1 of {amount}"; "lng_gift_collectible_tag" = "gift"; diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index c63319b912..b3cf7bf156 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -777,6 +777,19 @@ void ShowSentToast( tr::now, Text::RichLangValue); }, [&](const GiftTypeStars &gift) { + if (gift.info.perUserTotal && gift.info.perUserRemains < 2) { + return tr::lng_gift_sent_finished( + tr::now, + lt_count, + gift.info.perUserTotal, + Text::RichLangValue); + } else if (gift.info.perUserTotal) { + return tr::lng_gift_sent_remains( + tr::now, + lt_count, + gift.info.perUserRemains - 1, + Text::RichLangValue); + } const auto amount = gift.info.stars + (details.upgraded ? gift.info.starsToUpgrade : 0); return tr::lng_gift_sent_about( @@ -2749,7 +2762,12 @@ void SendGiftBox( button->setClickedCallback([=] { const auto star = std::get_if(&descriptor); const auto unique = star ? star->info.unique : nullptr; - if (unique && star->mine && !peer->isSelf()) { + if (star + && star->info.requirePremium + && !peer->session().premium()) { + Settings::ShowPremiumGiftPremium(window, star->info); + return; + } else if (unique && star->mine && !peer->isSelf()) { if (ShowTransferGiftLater(window->uiShow(), unique)) { return; } diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp index da39de9903..5ae749173b 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp @@ -421,6 +421,7 @@ void GiftButton::paintEvent(QPaintEvent *e) { const auto onsale = (unique && unique->starsForResale && _small); const auto requirePremium = v::is(_descriptor) && !v::get(_descriptor).userpic + && !v::get(_descriptor).info.unique && v::get(_descriptor).info.requirePremium; const auto hidden = v::is(_descriptor) && v::get(_descriptor).hidden; @@ -539,7 +540,9 @@ void GiftButton::paintEvent(QPaintEvent *e) { ? tr::lng_gift_stars_resale(tr::now) : soldOut ? tr::lng_gift_stars_sold_out(tr::now) - : (!data.userpic && data.info.requirePremium) + : (!data.userpic + && !data.info.unique + && data.info.requirePremium) ? tr::lng_gift_stars_premium(tr::now) : (!data.userpic && !data.info.unique) ? tr::lng_gift_stars_limited(tr::now) @@ -559,7 +562,7 @@ void GiftButton::paintEvent(QPaintEvent *e) { ? st::boxTextFgGood->c : soldOut ? st::attentionButtonFg->c - : data.info.requirePremium + : (!data.userpic && data.info.requirePremium) ? st::creditsFg->c : st::windowActiveTextFg->c), .bg2 = (onsale diff --git a/Telegram/SourceFiles/settings/settings_premium.cpp b/Telegram/SourceFiles/settings/settings_premium.cpp index 2b04f6db57..5ca2783923 100644 --- a/Telegram/SourceFiles/settings/settings_premium.cpp +++ b/Telegram/SourceFiles/settings/settings_premium.cpp @@ -91,6 +91,8 @@ using SectionCustomTopBarData = Info::Settings::SectionCustomTopBarData; option.duration = tr::lng_premium_subscribe_months_6(tr::now); } else if (option.duration == tr::lng_years(tr::now, lt_count, 1)) { option.duration = tr::lng_premium_subscribe_months_12(tr::now); + } else if (option.duration == tr::lng_years(tr::now, lt_count, 2)) { + option.duration = tr::lng_premium_subscribe_months_24(tr::now); } } return result; @@ -164,6 +166,45 @@ struct Data { } } // namespace EmojiStatus + +namespace PremiumGift { + +struct Data { + DocumentId documentId = 0; + int perUserTotal = 0; + + explicit operator bool() const { + return documentId != 0; + } +}; + +[[nodiscard]] QString Serialize(const Data &gift) { + return u"premiumgift_:%1,peruser_:%2"_q + .arg(gift.documentId) + .arg(gift.perUserTotal); +} + +[[nodiscard]] Data Parse(QStringView data) { + if (data.startsWith(u"premiumgift_:"_q)) { + const auto components = data.split(','); + if (components.size() != 2) { + return {}; + } + const auto first = components[0].split(':'); + const auto second = components[1].split(':'); + if (first.size() != 2 || second.size() != 2) { + return {}; + } + return { + .documentId = DocumentId(first[1].toULongLong()), + .perUserTotal = second[1].toInt(), + }; + } + return {}; +} + +} // namespace PremiumGift + } // namespace Ref struct Entry { @@ -374,7 +415,6 @@ using Order = std::vector; tr::lng_premium_summary_subtitle_business(), tr::lng_premium_summary_about_business(), PremiumFeature::Business, - true, }, }, { @@ -393,6 +433,7 @@ using Order = std::vector; tr::lng_premium_summary_subtitle_todo_lists(), tr::lng_premium_summary_about_todo_lists(), PremiumFeature::TodoLists, + true, }, }, }; @@ -542,13 +583,30 @@ void EmojiStatusTopBar::paint(QPainter &p) { } } -class TopBarUser final : public Ui::Premium::TopBarAbstract { +enum class TopBarWithStickerType { + EmojiStatus, + PremiumGift, +}; + +struct TopBarWithStickerArgs { + rpl::producer stickerValue; + rpl::producer nameValue; + rpl::producer aboutValue; + TopBarWithStickerType type = TopBarWithStickerType::EmojiStatus; +}; + +class TopBarWithSticker final : public Ui::Premium::TopBarAbstract { public: - TopBarUser( + TopBarWithSticker( not_null parent, not_null controller, not_null peer, rpl::producer<> showFinished); + TopBarWithSticker( + not_null parent, + not_null controller, + TopBarWithStickerArgs args, + rpl::producer<> showFinished); void setPaused(bool paused) override; void setTextPosition(int x, int y) override; @@ -562,10 +620,13 @@ protected: private: void updateTitle( DocumentData *document, - TextWithEntities name, + const TextWithEntities &name, not_null controller); - void updateAbout(DocumentData *document) const; + void updateAbout( + DocumentData *document, + const TextWithEntities &about) const; + TopBarWithStickerType _type = TopBarWithStickerType::EmojiStatus; object_ptr _content; object_ptr _title; object_ptr _about; @@ -586,12 +647,35 @@ private: }; -TopBarUser::TopBarUser( +TopBarWithSticker::TopBarWithSticker( not_null parent, not_null controller, not_null peer, rpl::producer<> showFinished) +: TopBarWithSticker(parent, controller, { + .stickerValue = Info::Profile::EmojiStatusIdValue( + peer + ) | rpl::map([=](EmojiStatusId id) -> DocumentData* { + const auto documentId = id.collectible + ? id.collectible->documentId + : id.documentId; + const auto document = documentId + ? controller->session().data().document(documentId).get() + : nullptr; + return (document && document->sticker()) ? document : nullptr; + }), + .nameValue = Info::Profile::NameValue(peer), + .type = TopBarWithStickerType::EmojiStatus, +}, std::move(showFinished)) { +} + +TopBarWithSticker:: TopBarWithSticker( + not_null parent, + not_null controller, + TopBarWithStickerArgs args, + rpl::producer<> showFinished) : TopBarAbstract(parent, st::userPremiumCover) +, _type(args.type) , _content(this) , _title(_content, st::settingsPremiumUserTitle) , _about(_content, st::userPremiumCover.about) @@ -604,6 +688,10 @@ TopBarUser::TopBarUser( }) { _starRect = TopBarAbstract::starRect(1., 1.); + if (_type == TopBarWithStickerType::PremiumGift) { + _ministars.setColorOverride(Ui::Premium::CreditsIconGradientStops()); + } + rpl::single() | rpl::then( style::PaletteChanged() ) | rpl::start_with_next([=] { @@ -611,24 +699,14 @@ TopBarUser::TopBarUser( update(); }, lifetime()); - auto documentValue = Info::Profile::EmojiStatusIdValue( - peer - ) | rpl::map([=](EmojiStatusId id) -> DocumentData* { - const auto documentId = id.collectible - ? id.collectible->documentId - : id.documentId; - const auto document = documentId - ? controller->session().data().document(documentId).get() - : nullptr; - return (document && document->sticker()) ? document : nullptr; - }); - rpl::combine( - std::move(documentValue), - Info::Profile::NameValue(peer) + std::move(args.stickerValue), + std::move(args.nameValue), + std::move(args.aboutValue) ) | rpl::start_with_next([=]( DocumentData *document, - const QString &name) { + const QString &name, + const TextWithEntities &about) { if (document) { _emojiStatus = std::make_unique( document, @@ -641,7 +719,7 @@ TopBarUser::TopBarUser( } updateTitle(document, { name }, controller); - updateAbout(document); + updateAbout(document, about); auto event = QResizeEvent(size(), size()); resizeEvent(&event); @@ -746,14 +824,15 @@ TopBarUser::TopBarUser( p.drawImage(_starRect.topLeft(), _imageStar); } }, lifetime()); - } -void TopBarUser::updateTitle( +void TopBarWithSticker::updateTitle( DocumentData *document, - TextWithEntities name, + const TextWithEntities &name, not_null controller) { - if (!document) { + if (_type == TopBarWithStickerType::PremiumGift) { + return _title->setMarkedText(name); + } else if (!document) { return _title->setMarkedText( tr::lng_premium_summary_user_title( tr::now, @@ -816,36 +895,40 @@ void TopBarUser::updateTitle( _title->setLink(linkIndex, std::move(link)); } -void TopBarUser::updateAbout(DocumentData *document) const { - _about->setMarkedText((document - ? tr::lng_premium_emoji_status_about - : tr::lng_premium_summary_user_about)( - tr::now, - Ui::Text::RichLangValue)); +void TopBarWithSticker::updateAbout( + DocumentData *document, + const TextWithEntities &about) const { + _about->setMarkedText((_type == TopBarWithStickerType::PremiumGift) + ? about + : (document + ? tr::lng_premium_emoji_status_about + : tr::lng_premium_summary_user_about)( + tr::now, + Ui::Text::RichLangValue)); } -void TopBarUser::setPaused(bool paused) { +void TopBarWithSticker::setPaused(bool paused) { _ministars.setPaused(paused); if (_emojiStatus) { _emojiStatus->setPaused(paused); } } -void TopBarUser::setTextPosition(int x, int y) { +void TopBarWithSticker::setTextPosition(int x, int y) { _smallTop.position = { x, y }; } -rpl::producer TopBarUser::additionalHeight() const { +rpl::producer TopBarWithSticker::additionalHeight() const { return rpl::never(); } -void TopBarUser::paintEvent(QPaintEvent *e) { +void TopBarWithSticker::paintEvent(QPaintEvent *e) { auto p = QPainter(this); TopBarAbstract::paintEdges(p); } -void TopBarUser::resizeEvent(QResizeEvent *e) { +void TopBarWithSticker::resizeEvent(QResizeEvent *e) { _starRect = TopBarAbstract::starRect(1., 1.); _ministars.setCenter(_starRect.toRect()); @@ -1053,7 +1136,9 @@ base::weak_qptr Premium::createPinnedToTop( }(); const auto emojiStatusData = Ref::EmojiStatus::Parse(_ref); + const auto premiumGiftData = Ref::PremiumGift::Parse(_ref); const auto isEmojiStatus = (!!emojiStatusData); + const auto isPremiumGift = (!!premiumGiftData); auto peerWithPremium = [&]() -> PeerData* { if (isEmojiStatus) { @@ -1064,14 +1149,35 @@ base::weak_qptr Premium::createPinnedToTop( } return nullptr; }(); + auto premiumGift = [&]() -> DocumentData* { + if (isPremiumGift) { + auto &data = _controller->session().data(); + return data.document(premiumGiftData.documentId); + } + return nullptr; + }(); const auto content = [&]() -> Ui::Premium::TopBarAbstract* { if (peerWithPremium) { - return Ui::CreateChild( + return Ui::CreateChild( parent.get(), _controller, peerWithPremium, _showFinished.events()); + } else if (premiumGift) { + return Ui::CreateChild( + parent.get(), + _controller, + TopBarWithStickerArgs{ + .stickerValue = rpl::single(premiumGift), + .nameValue = tr::lng_gift_premium_title(), + .aboutValue = tr::lng_gift_premium_text( + lt_count, + rpl::single(premiumGiftData.perUserTotal * 1.), + Ui::Text::RichLangValue), + .type = TopBarWithStickerType::PremiumGift, + }, + _showFinished.events()); } const auto weak = base::make_weak(_controller); const auto clickContextOther = [=] { @@ -1102,7 +1208,7 @@ base::weak_qptr Premium::createPinnedToTop( }, content->lifetime()); const auto calculateMaximumHeight = [=] { - return isEmojiStatus + return (isEmojiStatus || isPremiumGift) ? st::settingsPremiumUserHeight + TopTransitionSkip() : st::settingsPremiumTopHeight; }; @@ -1352,6 +1458,15 @@ void ShowEmojiStatusPremium( } } +void ShowPremiumGiftPremium( + not_null controller, + const Data::StarGift &gift) { + ShowPremium(controller, Ref::PremiumGift::Serialize({ + .documentId = gift.document->id, + .perUserTotal = gift.perUserTotal, + })); +} + void StartPremiumPayment( not_null controller, const QString &ref) { diff --git a/Telegram/SourceFiles/settings/settings_premium.h b/Telegram/SourceFiles/settings/settings_premium.h index 2effb1e1a4..19333ddee2 100644 --- a/Telegram/SourceFiles/settings/settings_premium.h +++ b/Telegram/SourceFiles/settings/settings_premium.h @@ -20,6 +20,10 @@ namespace ChatHelpers { class Show; } // namespace ChatHelpers +namespace Data { +struct StarGift; +} // namespace Data + namespace Ui { class RpWidget; class RoundButton; @@ -52,6 +56,9 @@ void ShowGiftPremium( void ShowEmojiStatusPremium( not_null controller, not_null peer); +void ShowPremiumGiftPremium( + not_null controller, + const Data::StarGift &gift); void StartPremiumPayment( not_null controller, diff --git a/Telegram/SourceFiles/ui/controls/stars_rating.cpp b/Telegram/SourceFiles/ui/controls/stars_rating.cpp index 2fa02a2269..fb047ded9e 100644 --- a/Telegram/SourceFiles/ui/controls/stars_rating.cpp +++ b/Telegram/SourceFiles/ui/controls/stars_rating.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/controls/stars_rating.h" #include "lang/lang_keys.h" +#include "ui/text/text_utilities.h" #include "ui/toast/toast.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" @@ -42,7 +43,8 @@ StarsRating::StarsRating( StarsRating::~StarsRating() = default; void StarsRating::init() { - _expanded.value() | rpl::start_with_next([=](bool expanded) { + _widget->setPointerCursor(true); + _expanded.changes() | rpl::start_with_next([=](bool expanded) { _widget->setPointerCursor(!expanded); const auto from = expanded ? 0. : 1.; const auto till = expanded ? 1. : 0.; @@ -168,15 +170,15 @@ void StarsRating::toggleTooltips(bool shown) { stars->toggleAnimated(true); _aboutSt = std::make_unique(st::defaultMultilineToast); - const auto learn = u"Learn More"_q; + const auto learn = tr::lng_stars_rating_learn_more(tr::now); _aboutSt->padding.setRight( (st::infoStarsRatingLearn.style.font->width(learn) - st::infoStarsRatingLearn.width)); _about = Ui::Toast::Show(parent, { - .text = TextWithEntities{ - u"Profile level reflects the user's payment reliability."_q, - }, + .text = tr::lng_stars_rating_tooltip( + tr::now, + Ui::Text::WithEntities), .st = _aboutSt.get(), .attach = RectPart::Top, .dark = true, @@ -211,7 +213,7 @@ void StarsRating::toggleTooltips(bool shown) { outer.width()); }, widget->lifetime()); button->setClickedCallback([=] { - UrlClickHandler::Open(u"https://telegram.org/"_q); + UrlClickHandler::Open(tr::lng_stars_rating_about_url(tr::now)); }); } @@ -283,16 +285,18 @@ void StarsRating::paint(QPainter &p) { ? ((value.currentStars - value.levelStars) / float64(value.nextLevelStars - value.levelStars)) : 1.; - const auto expandedFilled = _st.padding.left() - + _expandedText.maxWidth() - + _st.padding.right() - + expandedRatio * (middle.width() - - _st.padding.left() - - _expandedText.maxWidth() - - _st.padding.right() - - _st.padding.left() - - _nextText.maxWidth() - - _st.padding.right()); + const auto expandedFilled = (expandedRatio < 1.) + ? (_st.padding.left() + + _expandedText.maxWidth() + + _st.padding.right() + + expandedRatio * (middle.width() + - _st.padding.left() + - _expandedText.maxWidth() + - _st.padding.right() + - _st.padding.left() + - _nextText.maxWidth() + - _st.padding.right())) + : middle.width(); const auto collapsedFilled = _collapsedWidthValue.current() - _st.margin.right() - 2 * _st.border; From 66e8f9865abc73d55874be6b14fd057d2870b2a3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 17 Jul 2025 17:31:38 +0400 Subject: [PATCH 041/341] Started gift collections. --- Telegram/CMakeLists.txt | 2 + Telegram/Resources/langs/lang.strings | 17 +++ .../chat_helpers/chat_helpers.style | 3 - Telegram/SourceFiles/info/info.style | 16 +++ .../info_peer_gifts_collections.cpp | 107 ++++++++++++++++++ .../peer_gifts/info_peer_gifts_collections.h | 30 +++++ .../peer_gifts/info_peer_gifts_widget.cpp | 19 +++- Telegram/SourceFiles/main/main_app_config.cpp | 8 ++ Telegram/SourceFiles/main/main_app_config.h | 2 + 9 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp create mode 100644 Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 6e285ca175..a1f99fb31d 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1007,6 +1007,8 @@ PRIVATE info/media/info_media_widget.h info/members/info_members_widget.cpp info/members/info_members_widget.h + info/peer_gifts/info_peer_gifts_collections.cpp + info/peer_gifts/info_peer_gifts_collections.h info/peer_gifts/info_peer_gifts_common.cpp info/peer_gifts/info_peer_gifts_common.h info/peer_gifts/info_peer_gifts_widget.cpp diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 06857aae47..2e049a9692 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3751,6 +3751,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_resale_early" = "You will be able to resell this gift in {duration}."; "lng_gift_transfer_early" = "You will be able to transfer this gift in {duration}."; "lng_gift_resale_transfer_early_title" = "Try Later"; +"lng_gift_collection_add" = "Add Collection"; +"lng_gift_collection_new_title" = "Create a New Collection"; +"lng_gift_collection_new_button" = "New Collection"; +"lng_gift_collection_new_text" = "Choose a name for your collection and start adding your gifts there."; +"lng_gift_collection_new_ph" = "Title"; +"lng_gift_collection_new_create" = "Create"; +"lng_gift_collection_empty_title" = "Organize Your Gifts"; +"lng_gift_collection_empty_text" = "Add some of your gifts to this collection."; +"lng_gift_collection_empty_button" = "Add to Collection"; +"lng_gift_collection_all" = "All Gifts"; +"lng_gift_collection_add_title" = "Add Gifts"; +"lng_gift_collection_edit" = "Edit Name"; +"lng_gift_collection_limit_title" = "Limit Reached"; +"lng_gift_collection_limit_text" = "Please remove one of the existing collections to add a new one."; +"lng_gift_collection_delete" = "Delete Collection"; +"lng_gift_collection_add_to" = "Add to Collection"; +"lng_gift_collection_reorder" = "Reorder"; "lng_accounts_limit_title" = "Limit Reached"; "lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account."; diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style index a2158bbe20..252a7dbc94 100644 --- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style +++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style @@ -1487,9 +1487,6 @@ editTagField: InputField(defaultInputField) { heightMin: 36px; } -editTagLimit: FlatLabel(defaultFlatLabel) { - textFg: windowSubTextFg; -} editStickerSetNameField: InputField(defaultInputField) { textMargins: margins(0px, 8px, 26px, 4px); diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 283fa1df9a..5e05950c2c 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -1227,3 +1227,19 @@ infoStarsRatingLearn: RoundButton(defaultActiveButton) { ripple: emptyRippleAnimation; } infoStarsRatingTooltip: defaultImportantTooltip; + +collectionAbout: FlatLabel(defaultFlatLabel) { + minWidth: 256px; +} +collectionNameField: InputField(defaultInputField) { + textBg: transparent; + textMargins: margins(2px, 10px, 32px, 2px); + + placeholderFg: placeholderFg; + placeholderFgActive: placeholderFgActive; + placeholderFgError: placeholderFgActive; + placeholderMargins: margins(2px, 0px, 2px, 0px); + placeholderScale: 0.; + + heightMin: 36px; +} diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp new file mode 100644 index 0000000000..2b66c8a78b --- /dev/null +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp @@ -0,0 +1,107 @@ +/* +This file is part of Telegram Desktop, +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 "info/peer_gifts/info_peer_gifts_collections.h" + +#include "api/api_credits.h" // +#include "apiwrap.h" +#include "data/data_peer.h" +#include "data/data_star_gift.h" +#include "lang/lang_keys.h" +#include "main/main_session.h" +#include "ui/boxes/confirm_box.h" +#include "ui/layers/generic_box.h" +#include "ui/widgets/fields/input_field.h" +#include "window/window_session_controller.h" +#include "styles/style_layers.h" +#include "styles/style_info.h" + +namespace Info::PeerGifts { +namespace { + +constexpr auto kCollectionNameLimit = 12; + +} // namespace + +void NewCollectionBox( + not_null box, + not_null navigation, + not_null peer, + Data::SavedStarGiftId addId) { + box->setTitle(tr::lng_gift_collection_new_title()); + + box->addRow( + object_ptr( + box, + tr::lng_gift_collection_new_text(), + st::collectionAbout)); + const auto title = box->addRow( + object_ptr( + box, + st::collectionNameField, + tr::lng_gift_collection_new_ph())); + title->setMaxLength(kCollectionNameLimit * 2); + box->setFocusCallback([=] { + title->setFocusFast(); + }); + + Ui::AddLengthLimitLabel(title, kCollectionNameLimit); + + const auto show = navigation->uiShow(); + const auto session = &peer->session(); + + const auto creating = std::make_shared(false); + box->addButton(tr::lng_gift_collection_new_create(), [=] { + if (*creating) { + return; + } + const auto text = title->getLastText().trimmed(); + if (text.isEmpty()) { + title->showError(); + return; + } + + *creating = true; + auto ids = QVector(); + if (addId) { + ids.push_back(Api::InputSavedStarGiftId(addId)); + } + const auto weak = base::make_weak(box); + session->api().request(MTPpayments_CreateStarGiftCollection( + peer->input, + MTP_string(text), + MTP_vector(ids) + )).done([=](const MTPStarGiftCollection &result) { + *creating = false; + if (const auto strong = weak.get()) { + strong->closeBox(); + } + }).fail([=](const MTP::Error &error) { + *creating = false; + const auto &type = error.type(); + if (type == u""_q) { + show->show(Ui::MakeInformBox({ + .text = tr::lng_gift_collection_limit_text(), + .confirmText = tr::lng_box_ok(), + .title = tr::lng_gift_collection_limit_title(), + })); + if (const auto strong = weak.get()) { + strong->closeBox(); + } + } else { + show->showToast(error.type()); + } + }).send(); + }); + + box->addButton(tr::lng_cancel(), [=] { + box->closeBox(); + }); + +} + +} // namespace Info::PeerGifts diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.h b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.h new file mode 100644 index 0000000000..cbb18a28a8 --- /dev/null +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.h @@ -0,0 +1,30 @@ +/* +This file is part of Telegram Desktop, +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 +*/ +#pragma once + +namespace Data { +class SavedStarGiftId; +} // namespace Data + +namespace Ui { +class GenericBox; +} // namespace Ui + +namespace Window { +class SessionNavigation; +} // namespace Window + +namespace Info::PeerGifts { + +void NewCollectionBox( + not_null box, + not_null navigation, + not_null peer, + Data::SavedStarGiftId addId); + +} // namespace Info::PeerGifts diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp index 68a79563f6..73bd98c99a 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_credits.h" #include "data/data_session.h" #include "data/data_user.h" +#include "info/peer_gifts/info_peer_gifts_collections.h" #include "info/peer_gifts/info_peer_gifts_common.h" #include "info/info_controller.h" #include "ui/layers/generic_box.h" @@ -807,6 +808,8 @@ void Widget::setupNotifyCheckbox(bool enabled) { } void Widget::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { + const auto peer = _inner->peer(); + const auto canManage = peer->canManageGifts(); const auto filter = _filter.current(); const auto change = [=](Fn update) { auto now = _filter.current(); @@ -824,6 +827,20 @@ void Widget::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { }, &st::menuIconEarn); } + if (canManage) { + const auto weak = base::make_weak( + (Window::SessionNavigation*)controller()); + addAction(tr::lng_gift_collection_add(tr::now), [=] { + if (const auto strong = weak.get()) { + strong->uiShow()->show(Box( + NewCollectionBox, + strong, + peer, + Data::SavedStarGiftId())); + } + }, &st::menuIconAddToFolder); + } + addAction({ .isSeparator = true }); addAction(tr::lng_peer_gifts_filter_unlimited(tr::now), [=] { @@ -857,7 +874,7 @@ void Widget::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { }); }, filter.skipUnique ? nullptr : &st::mediaPlayerMenuCheck); - if (_inner->peer()->canManageGifts()) { + if (canManage) { addAction({ .isSeparator = true }); addAction(tr::lng_peer_gifts_filter_saved(tr::now), [=] { diff --git a/Telegram/SourceFiles/main/main_app_config.cpp b/Telegram/SourceFiles/main/main_app_config.cpp index ea8561669e..32b1ae53d8 100644 --- a/Telegram/SourceFiles/main/main_app_config.cpp +++ b/Telegram/SourceFiles/main/main_app_config.cpp @@ -121,6 +121,14 @@ int AppConfig::pinnedGiftsLimit() const { return get(u"stargifts_pinned_to_top_limit"_q, 6); } +int AppConfig::giftCollectionsLimit() const { + return get(u"stargifts_collections_limit"_q, 10); +} + +int AppConfig::giftCollectionGiftsLimit() const { + return get(u"stargifts_collection_gifts_limit"_q, 500); +} + bool AppConfig::callsDisabledForSession() const { const auto authorizations = _account->sessionExists() ? &_account->session().api().authorizations() diff --git a/Telegram/SourceFiles/main/main_app_config.h b/Telegram/SourceFiles/main/main_app_config.h index c5ba22ee40..7dc2205d1a 100644 --- a/Telegram/SourceFiles/main/main_app_config.h +++ b/Telegram/SourceFiles/main/main_app_config.h @@ -78,6 +78,8 @@ public: [[nodiscard]] int paidMessageChannelStarsDefault() const; [[nodiscard]] int pinnedGiftsLimit() const; + [[nodiscard]] int giftCollectionsLimit() const; + [[nodiscard]] int giftCollectionGiftsLimit() const; [[nodiscard]] bool callsDisabledForSession() const; [[nodiscard]] int confcallSizeLimit() const; From a7fe004344244da59a673b8b43927b84245781fb Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 18 Jul 2025 14:03:52 +0400 Subject: [PATCH 042/341] Load collections, request gifts in them. --- Telegram/Resources/langs/lang.strings | 1 - Telegram/SourceFiles/data/data_star_gift.h | 8 + .../data/stickers/data_custom_emoji.cpp | 5 +- .../info_peer_gifts_collections.cpp | 2 +- .../peer_gifts/info_peer_gifts_widget.cpp | 323 +++++++++++++----- Telegram/SourceFiles/ui/controls/sub_tabs.cpp | 239 +++++++++++++ Telegram/SourceFiles/ui/controls/sub_tabs.h | 77 +++++ Telegram/cmake/td_ui.cmake | 2 + 8 files changed, 577 insertions(+), 80 deletions(-) create mode 100644 Telegram/SourceFiles/ui/controls/sub_tabs.cpp create mode 100644 Telegram/SourceFiles/ui/controls/sub_tabs.h diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 2e049a9692..ba03b8f6c4 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3767,7 +3767,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_collection_limit_text" = "Please remove one of the existing collections to add a new one."; "lng_gift_collection_delete" = "Delete Collection"; "lng_gift_collection_add_to" = "Add to Collection"; -"lng_gift_collection_reorder" = "Reorder"; "lng_accounts_limit_title" = "Limit Reached"; "lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account."; diff --git a/Telegram/SourceFiles/data/data_star_gift.h b/Telegram/SourceFiles/data/data_star_gift.h index 8b53bd5581..89650f31f6 100644 --- a/Telegram/SourceFiles/data/data_star_gift.h +++ b/Telegram/SourceFiles/data/data_star_gift.h @@ -150,4 +150,12 @@ struct SavedStarGift { bool mine = false; }; +struct GiftCollection { + int id = 0; + int count = 0; + QString title; + DocumentData *icon = nullptr; + uint64 hash = 0; +}; + } // namespace Data diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index eb34f30dfb..ff551f225e 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -1108,7 +1108,10 @@ TextWithEntities SingleCustomEmoji(DocumentId id) { } TextWithEntities SingleCustomEmoji(not_null document) { - return SingleCustomEmoji(document->id); + const auto sticker = document->sticker(); + return Ui::Text::SingleCustomEmoji( + SerializeCustomEmojiId(document), + sticker ? sticker->alt : QString()); } bool AllowEmojiWithoutPremium( diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp index 2b66c8a78b..d1b49aa49b 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_collections.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/peer_gifts/info_peer_gifts_collections.h" -#include "api/api_credits.h" // +#include "api/api_credits.h" #include "apiwrap.h" #include "data/data_peer.h" #include "data/data_star_gift.h" diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp index 73bd98c99a..773d51ef5b 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp @@ -7,9 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/peer_gifts/info_peer_gifts_widget.h" +#include "api/api_hash.h" #include "api/api_premium.h" #include "apiwrap.h" #include "boxes/star_gift_box.h" +#include "core/ui_integration.h" +#include "data/stickers/data_custom_emoji.h" #include "data/data_channel.h" #include "data/data_credits.h" #include "data/data_session.h" @@ -17,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/peer_gifts/info_peer_gifts_collections.h" #include "info/peer_gifts/info_peer_gifts_common.h" #include "info/info_controller.h" +#include "ui/controls/sub_tabs.h" #include "ui/layers/generic_box.h" #include "ui/text/text_utilities.h" #include "ui/widgets/menu/menu_add_action_callback.h" @@ -61,6 +65,28 @@ constexpr auto kPerPage = 50; }; } +[[nodiscard]] std::vector FromTL( + not_null session, + const MTPDpayments_starGiftCollections &data) { + auto result = std::vector(); + + const auto &list = data.vcollections().v; + result.reserve(list.size()); + for (const auto &collection : list) { + const auto &data = collection.data(); + result.push_back({ + .id = data.vcollection_id().v, + .count = data.vgifts_count().v, + .title = qs(data.vtitle()), + .icon = (data.vicon() + ? session->data().processDocument(*data.vicon()).get() + : nullptr), + .hash = data.vhash().v, + }); + } + return result; +} + } // namespace class InnerWidget final : public Ui::BoxContentDivider { @@ -92,6 +118,11 @@ private: Data::SavedStarGift gift; GiftDescriptor descriptor; }; + struct Entries { + std::vector list; + int total = 0; + bool allLoaded = false; + }; struct View { std::unique_ptr button; Data::SavedStarGiftId manageId; @@ -105,12 +136,15 @@ private: void paintEvent(QPaintEvent *e) override; void subscribeToUpdates(); + void loadCollections(); void loadMore(); + void loaded(const MTPpayments_SavedStarGifts &result); void refreshButtons(); void validateButtons(); void showGift(int index); void showMenuFor(not_null button, QPoint point); void refreshAbout(); + void refreshCollectionsTabs(); void markPinned(std::vector::iterator i); void markUnpinned(std::vector::iterator i); @@ -122,20 +156,28 @@ private: const not_null _window; rpl::variable _filter; + rpl::variable _collectionId; Delegate _delegate; - not_null _controller; + const not_null _controller; + std::unique_ptr _collectionsTabs; std::unique_ptr _about; const not_null _peer; - std::vector _entries; - int _totalCount = 0; rpl::event_stream<> _scrollToTop; + std::vector _collections; + + Entries _all; + base::flat_map _perCollection; + not_null _entries; + not_null*> _list; + MTP::Sender _api; mtpRequestId _loadMoreRequestId = 0; + Fn _collectionsLoadedCallback; QString _offset; - bool _allLoaded = false; bool _reloading = false; bool _aboutFiltered = false; + bool _collectionsLoaded = false; rpl::event_stream<> _resetFilterRequests; rpl::event_stream _notifyEnabled; @@ -165,7 +207,9 @@ InnerWidget::InnerWidget( , _delegate(&_window->session(), GiftButtonMode::Minimal) , _controller(controller) , _peer(peer) -, _totalCount(_peer->peerGiftsCount()) +, _all({ .total = _peer->peerGiftsCount() }) +, _entries(&_all) +, _list(&_entries->list) , _api(&_peer->session().mtp()) { _singleMin = _delegate.buttonSize(); @@ -173,13 +217,54 @@ InnerWidget::InnerWidget( subscribeToUpdates(); } + loadCollections(); + _filter.value() | rpl::start_with_next([=] { _reloading = true; _api.request(base::take(_loadMoreRequestId)).cancel(); - _allLoaded = false; + _collectionsLoadedCallback = nullptr; + _entries->allLoaded = false; refreshAbout(); loadMore(); }, lifetime()); + + _collectionId.changes() | rpl::start_with_next([=](int now) { + _reloading = true; + _api.request(base::take(_loadMoreRequestId)).cancel(); + _collectionsLoadedCallback = nullptr; + _entries = now ? &_perCollection[now] : &_all; + _list = &_entries->list; + refreshAbout(); + if (_entries->allLoaded) { + refreshButtons(); + } else { + loadMore(); + } + }, lifetime()); +} + +void InnerWidget::loadCollections() { + _api.request(MTPpayments_GetStarGiftCollections( + _peer->input, + MTP_long(Api::CountHash(_collections + | ranges::views::transform(&Data::GiftCollection::hash))) + )).done([=](const MTPpayments_StarGiftCollections &result) { + result.match([&](const MTPDpayments_starGiftCollections &data) { + _collections = FromTL(&_window->session(), data); + + refreshCollectionsTabs(); + }, [&](const MTPDpayments_starGiftCollectionsNotModified &) { + }); + _collectionsLoaded = true; + if (const auto onstack = base::take(_collectionsLoadedCallback)) { + onstack(); + } + }).fail([=] { + _collectionsLoaded = true; + if (const auto onstack = base::take(_collectionsLoadedCallback)) { + onstack(); + } + }).send(); } void InnerWidget::subscribeToUpdates() { @@ -194,19 +279,19 @@ void InnerWidget::subscribeToUpdates() { : QString(); }; const auto i = update.id - ? ranges::find(_entries, update.id, savedId) - : ranges::find(_entries, update.slug, bySlug); - if (i == end(_entries)) { + ? ranges::find(*_list, update.id, savedId) + : ranges::find(*_list, update.slug, bySlug); + if (i == end(*_list)) { return; } - const auto index = int(i - begin(_entries)); + const auto index = int(i - begin(*_list)); using Action = Data::GiftUpdate::Action; if (update.action == Action::Convert || update.action == Action::Transfer || update.action == Action::Delete) { - _entries.erase(i); - if (_totalCount > 0) { - --_totalCount; + _list->erase(i); + if (_entries->total > 0) { + --_entries->total; } for (auto &view : _views) { if (view.index >= index) { @@ -256,7 +341,7 @@ void InnerWidget::subscribeToUpdates() { } void InnerWidget::markPinned(std::vector::iterator i) { - const auto index = int(i - begin(_entries)); + const auto index = int(i - begin(*_list)); i->gift.pinned = true; v::match(i->descriptor, [](const GiftTypePremium &) { @@ -264,13 +349,13 @@ void InnerWidget::markPinned(std::vector::iterator i) { data.pinned = true; }); if (index) { - std::rotate(begin(_entries), i, i + 1); + std::rotate(begin(*_list), i, i + 1); } - auto unpin = end(_entries); + auto unpin = end(*_list); const auto session = &_window->session(); const auto limit = session->appConfig().pinnedGiftsLimit(); - if (limit < _entries.size()) { - const auto j = begin(_entries) + limit; + if (limit < _list->size()) { + const auto j = begin(*_list) + limit; if (j->gift.pinned) { unpin = j; } @@ -281,13 +366,13 @@ void InnerWidget::markPinned(std::vector::iterator i) { view.manageId = {}; } } - if (unpin != end(_entries)) { + if (unpin != end(_entries->list)) { markUnpinned(unpin); } } void InnerWidget::markUnpinned(std::vector::iterator i) { - const auto index = int(i - begin(_entries)); + const auto index = int(i - begin(*_list)); i->gift.pinned = false; v::match(i->descriptor, [](const GiftTypePremium &) { @@ -295,19 +380,19 @@ void InnerWidget::markUnpinned(std::vector::iterator i) { data.pinned = false; }); auto after = index + 1; - for (auto j = i + 1; j != end(_entries); ++j) { + for (auto j = i + 1; j != end(*_list); ++j) { if (!j->gift.pinned && j->gift.date <= i->gift.date) { break; } ++after; } - if (after == _entries.size() && !_allLoaded) { + if (after == _list->size() && !_entries->allLoaded) { // We don't know if the correct position is exactly in the end // of the loaded part or later, so we hide it for now, let it // be loaded later while scrolling. - _entries.erase(i); + _list->erase(i); } else if (after > index + 1) { - std::rotate(i, i + 1, begin(_entries) + after); + std::rotate(i, i + 1, begin(*_list) + after); } for (auto &view : _views) { if (view.index >= index) { @@ -344,69 +429,85 @@ void InnerWidget::paintEvent(QPaintEvent *e) { } void InnerWidget::loadMore() { - if (_allLoaded || _loadMoreRequestId) { + if (_entries->allLoaded || _loadMoreRequestId) { return; } using Flag = MTPpayments_GetSavedStarGifts::Flag; const auto filter = _filter.current(); - const auto collectionId = 0; + const auto collectionId = _collectionId.current(); _loadMoreRequestId = _api.request(MTPpayments_GetSavedStarGifts( MTP_flags((filter.sortByValue ? Flag::f_sort_by_value : Flag()) | (filter.skipLimited ? Flag::f_exclude_limited : Flag()) | (filter.skipUnlimited ? Flag::f_exclude_unlimited : Flag()) | (filter.skipUnique ? Flag::f_exclude_unique : Flag()) | (filter.skipSaved ? Flag::f_exclude_saved : Flag()) - | (filter.skipUnsaved ? Flag::f_exclude_unsaved : Flag())), + | (filter.skipUnsaved ? Flag::f_exclude_unsaved : Flag()) + | (collectionId ? Flag::f_collection_id : Flag())), _peer->input, MTP_int(collectionId), MTP_string(_reloading ? QString() : _offset), MTP_int(kPerPage) )).done([=](const MTPpayments_SavedStarGifts &result) { - _loadMoreRequestId = 0; const auto &data = result.data(); - if (const auto enabled = data.vchat_notifications_enabled()) { - _notifyEnabled.fire(mtpIsTrue(*enabled)); - } - if (const auto next = data.vnext_offset()) { - _offset = qs(*next); - } else { - _allLoaded = true; - } - if (!filter.skipsSomething()) { - _totalCount = data.vcount().v; - } const auto owner = &_peer->owner(); owner->processUsers(data.vusers()); owner->processChats(data.vchats()); - if (base::take(_reloading)) { - _entries.clear(); - } - _entries.reserve(_entries.size() + data.vgifts().v.size()); - auto hasUnique = false; - for (const auto &gift : data.vgifts().v) { - if (auto parsed = Api::FromTL(_peer, gift)) { - auto descriptor = DescriptorForGift(_peer, *parsed); - _entries.push_back({ - .gift = std::move(*parsed), - .descriptor = std::move(descriptor), - }); - hasUnique = (parsed->info.unique != nullptr); - } - } - refreshButtons(); - refreshAbout(); - - if (hasUnique) { - Ui::PreloadUniqueGiftResellPrices(&_peer->session()); + if (_collectionsLoaded) { + loaded(result); + } else { + _collectionsLoadedCallback = [=] { + loaded(result); + }; } }).fail([=] { _loadMoreRequestId = 0; - _allLoaded = true; + _collectionsLoadedCallback = nullptr; + _entries->allLoaded = true; }).send(); } +void InnerWidget::loaded(const MTPpayments_SavedStarGifts &result) { + const auto &data = result.data(); + + _loadMoreRequestId = 0; + _collectionsLoadedCallback = nullptr; + if (const auto enabled = data.vchat_notifications_enabled()) { + _notifyEnabled.fire(mtpIsTrue(*enabled)); + } + if (const auto next = data.vnext_offset()) { + _offset = qs(*next); + } else { + _entries->allLoaded = true; + } + if (!_filter.current().skipsSomething()) { + _entries->total = data.vcount().v; + } + + if (base::take(_reloading)) { + _list->clear(); + } + _list->reserve(_list->size() + data.vgifts().v.size()); + auto hasUnique = false; + for (const auto &gift : data.vgifts().v) { + if (auto parsed = Api::FromTL(_peer, gift)) { + auto descriptor = DescriptorForGift(_peer, *parsed); + _list->push_back({ + .gift = std::move(*parsed), + .descriptor = std::move(descriptor), + }); + hasUnique = (parsed->info.unique != nullptr); + } + } + refreshButtons(); + refreshAbout(); + + if (hasUnique) { + Ui::PreloadUniqueGiftResellPrices(&_peer->session()); + } +} + void InnerWidget::refreshButtons() { _viewsForWidth = 0; _viewsFromRow = 0; @@ -420,7 +521,9 @@ void InnerWidget::validateButtons() { return; } const auto padding = st::giftBoxPadding; - const auto vskip = padding.bottom(); + const auto vskip = _collectionsTabs + ? (padding.top() + _collectionsTabs->height() + padding.top()) + : padding.bottom(); const auto row = _single.height() + st::giftBoxGiftSkip.y(); const auto fromRow = std::max(_visibleFrom - vskip, 0) / row; const auto tillRow = (_visibleTill - vskip + row - 1) / row; @@ -448,9 +551,9 @@ void InnerWidget::validateButtons() { for (auto j = row; j != tillRow; ++j) { for (auto i = column; i != _perRow; ++i) { const auto index = j * _perRow + i; - if (index >= _entries.size()) { + if (index >= _list->size()) { return false; - } else if (_entries[index].gift.info.id == giftId) { + } else if ((*_list)[index].gift.info.id == giftId) { return true; } } @@ -460,12 +563,12 @@ void InnerWidget::validateButtons() { }; const auto add = [&](int column, int row) { const auto index = row * _perRow + column; - if (index >= _entries.size()) { + if (index >= _list->size()) { return false; } - const auto giftId = _entries[index].gift.info.id; - const auto manageId = _entries[index].gift.manageId; - const auto &descriptor = _entries[index].descriptor; + const auto giftId = (*_list)[index].gift.info.id; + const auto manageId = (*_list)[index].gift.manageId; + const auto &descriptor = (*_list)[index].descriptor; const auto already = ranges::find(_views, giftId, &View::giftId); if (already != end(_views)) { views.push_back(base::take(*already)); @@ -520,7 +623,7 @@ auto InnerWidget::pinnedSavedGifts() std::shared_ptr unique; }; auto entries = std::vector(); - for (const auto &entry : _entries) { + for (const auto &entry : *_list) { if (entry.gift.pinned) { Assert(entry.gift.info.unique != nullptr); entries.push_back({ @@ -566,7 +669,7 @@ void InnerWidget::showMenuFor(not_null button, QPoint point) { auto entry = ::Settings::SavedStarGiftEntry( _peer, - _entries[index].gift); + (*_list)[index].gift); entry.pinnedSavedGifts = pinnedSavedGifts(); _menu = base::make_unique_q(this, st::popupMenuWithIcons); ::Settings::FillSavedStarGiftMenu( @@ -581,27 +684,27 @@ void InnerWidget::showMenuFor(not_null button, QPoint point) { } void InnerWidget::showGift(int index) { - Expects(index >= 0 && index < _entries.size()); + Expects(index >= 0 && index < _list->size()); _window->show(Box( ::Settings::SavedStarGiftBox, _window, _peer, - _entries[index].gift, + (*_list)[index].gift, pinnedSavedGifts())); } void InnerWidget::refreshAbout() { const auto filter = _filter.current(); - const auto filteredEmpty = _allLoaded - && _entries.empty() + const auto filteredEmpty = _entries->allLoaded + && _list->empty() && filter.skipsSomething(); if (filteredEmpty) { auto text = tr::lng_peer_gifts_empty_search( tr::now, Ui::Text::RichLangValue); - if (_totalCount > 0) { + if (_entries->total > 0) { text.append("\n\n").append(Ui::Text::Link( tr::lng_peer_gifts_view_all(tr::now))); } @@ -621,7 +724,7 @@ void InnerWidget::refreshAbout() { _aboutFiltered = false; } - if (!_peer->isSelf() && _peer->canManageGifts() && !_entries.empty()) { + if (!_peer->isSelf() && _peer->canManageGifts() && !_list->empty()) { if (_about) { _about = nullptr; resizeToWidth(width()); @@ -641,16 +744,82 @@ void InnerWidget::refreshAbout() { } } +void InnerWidget::refreshCollectionsTabs() { + if (_collections.empty()) { + if (base::take(_collectionsTabs)) { + resizeToWidth(width()); + } + return; + } + auto tabs = std::vector(); + tabs.push_back({ + .id = u"all"_q, + .text = tr::lng_gift_stars_tabs_all(tr::now, Ui::Text::WithEntities), + }); + for (const auto &collection : _collections) { + auto title = TextWithEntities(); + if (collection.icon) { + title.append( + Data::SingleCustomEmoji(collection.icon) + ).append(' '); + } + title.append(collection.title); + tabs.push_back({ + .id = QString::number(collection.id), + .text = std::move(title), + }); + } + tabs.push_back({ + .id = u"add"_q, + .text = { '+' + tr::lng_gift_collection_add(tr::now) }, + }); + const auto context = Core::TextContext({ + .session = &_controller->session(), + }); + if (!_collectionsTabs) { + _collectionsTabs = std::make_unique( + this, + Ui::SubTabs::Options{ .selected = u"all"_q, .centered = true}, + std::move(tabs), + context); + _collectionsTabs->show(); + + _collectionsTabs->activated( + ) | rpl::start_with_next([=](const QString &id) { + if (id == u"add"_q) { + _controller->uiShow()->show(Box( + NewCollectionBox, + _controller, + peer(), + Data::SavedStarGiftId())); + } else { + _collectionsTabs->setActiveTab(id); + _collectionId = (id == u"all"_q) ? 0 : id.toInt(); + } + }, _collectionsTabs->lifetime()); + } else { + _collectionsTabs->setTabs(std::move(tabs), context); + } + resizeToWidth(width()); +} + int InnerWidget::resizeGetHeight(int width) { - const auto count = int(_entries.size()); const auto padding = st::giftBoxPadding; + auto top = padding.top(); + if (_collectionsTabs) { + _collectionsTabs->resizeToWidth(width); + _collectionsTabs->move(0, top); + top += _collectionsTabs->height() + padding.top(); + } + + const auto count = int(_list->size()); const auto available = width - padding.left() - padding.right(); const auto skipw = st::giftBoxGiftSkip.x(); _perRow = std::min( (available + skipw) / (_singleMin.width() + skipw), std::max(count, 1)); if (!_perRow) { - return 0; + return (top == padding.top()) ? 0 : top; } const auto singlew = std::min( ((available + skipw) / _perRow) - skipw, diff --git a/Telegram/SourceFiles/ui/controls/sub_tabs.cpp b/Telegram/SourceFiles/ui/controls/sub_tabs.cpp new file mode 100644 index 0000000000..88d5c4b2fd --- /dev/null +++ b/Telegram/SourceFiles/ui/controls/sub_tabs.cpp @@ -0,0 +1,239 @@ +/* +This file is part of Telegram Desktop, +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 "ui/controls/sub_tabs.h" + +#include "ui/painter.h" +#include "ui/ui_utility.h" +#include "styles/style_basic.h" +#include "styles/style_chat_helpers.h" +#include "styles/style_credits.h" + +#include + +namespace Ui { + +SubTabs::SubTabs( + QWidget *parent, + Options options, + std::vector tabs, + Text::MarkedContext context) +: RpWidget(parent) +, _centered(options.centered) { + setMouseTracking(true); + setTabs(std::move(tabs), context); + if (!options.selected.isEmpty()) { + setActiveTab(options.selected); + } +} + +void SubTabs::setTabs( + std::vector tabs, + Text::MarkedContext context) { + auto x = st::giftBoxTabsMargin.left(); + auto y = st::giftBoxTabsMargin.top(); + + setSelected(-1); + _buttons.resize(tabs.size()); + const auto padding = st::giftBoxTabPadding; + auto activeId = (_active >= 0 + && ranges::contains(tabs, _buttons[_active].tab.id, &Tab::id)) + ? _buttons[_active].tab.id + : QString(); + _active = -1; + context.repaint = [=] { update(); }; + for (auto i = 0, count = int(tabs.size()); i != count; ++i) { + auto &tab = tabs[i]; + Assert(!tab.id.isEmpty()); + + auto &button = _buttons[i]; + button.active = (tab.id == activeId); + if (button.tab != tab) { + button.text = Text::String(); + button.text.setMarkedText( + st::semiboldTextStyle, + tab.text, + kMarkupTextOptions, + context); + button.tab = std::move(tab); + } + if (button.active) { + _active = i; + } + const auto width = button.text.maxWidth(); + const auto height = st::giftBoxTabStyle.font->height; + const auto r = QRect(0, 0, width, height).marginsAdded(padding); + button.geometry = QRect(QPoint(x, y), r.size()); + x += r.width() + st::giftBoxTabSkip; + } + const auto width = x + - st::giftBoxTabSkip + + st::giftBoxTabsMargin.right(); + _fullWidth = width; + resizeToWidth(this->width()); + update(); +} + +void SubTabs::setActiveTab(const QString &id) { + if (id.isEmpty()) { + setActive(-1); + return; + } + const auto i = ranges::find( + _buttons, + id, + [](const Button &button) { return button.tab.id; }); + Assert(i != end(_buttons)); + setActive(i - begin(_buttons)); +} + +rpl::producer SubTabs::activated() const { + return _activated.events(); +} + +void SubTabs::setSelected(int index) { + const auto was = (_selected >= 0); + const auto now = (index >= 0); + _selected = index; + if (was != now) { + setCursor(now ? style::cur_pointer : style::cur_default); + } +} + +void SubTabs::setActive(int index) { + const auto was = _active; + if (was == index) { + return; + } + if (was >= 0 && was < _buttons.size()) { + _buttons[was].active = false; + } + _active = index; + _buttons[index].active = true; + update(); +} + +int SubTabs::resizeGetHeight(int newWidth) { + if (_centered) { + update(); + const auto fullWidth = _fullWidth; + _fullShift = (fullWidth < newWidth) ? (newWidth - fullWidth) / 2 : 0; + } + _scrollMax = (_fullWidth > newWidth) ? (_fullWidth - newWidth) : 0; + return _buttons.empty() + ? 0 + : (st::giftBoxTabsMargin.top() + + _buttons.back().geometry.height() + + st::giftBoxTabsMargin.bottom()); +} + +bool SubTabs::eventHook(QEvent *e) { + if (e->type() == QEvent::Leave) { + setSelected(-1); + } + return RpWidget::eventHook(e); +} + +void SubTabs::mouseMoveEvent(QMouseEvent *e) { + const auto mousex = e->pos().x(); + const auto drag = QApplication::startDragDistance(); + if (_dragx > 0) { + _scroll = std::clamp( + _dragscroll + _dragx - mousex, + 0., + _scrollMax * 1.); + update(); + return; + } else if (_pressx > 0 && std::abs(_pressx - mousex) > drag) { + _dragx = _pressx; + _dragscroll = _scroll; + } + auto selected = -1; + const auto position = e->pos() + scroll(); + for (auto i = 0, c = int(_buttons.size()); i != c; ++i) { + if (_buttons[i].geometry.contains(position)) { + selected = i; + break; + } + } + setSelected(selected); +} + +void SubTabs::wheelEvent(QWheelEvent *e) { + _scroll = std::clamp(_scroll - ScrollDeltaF(e).x(), 0., _scrollMax * 1.); + update(); +} + +void SubTabs::mousePressEvent(QMouseEvent *e) { + if (e->button() != Qt::LeftButton) { + return; + } + _pressed = _selected; + _pressx = e->pos().x(); +} + +void SubTabs::mouseReleaseEvent(QMouseEvent *e) { + if (e->button() != Qt::LeftButton) { + return; + } + const auto dragx = std::exchange(_dragx, 0); + const auto pressed = std::exchange(_pressed, -1); + _pressx = 0; + if (!dragx + && pressed >= 0 + && _selected == pressed + && pressed < _buttons.size()) { + _activated.fire_copy(_buttons[pressed].tab.id); + } +} + +void SubTabs::paintEvent(QPaintEvent *e) { + auto p = QPainter(this); + auto hq = PainterHighQualityEnabler(p); + const auto padding = st::giftBoxTabPadding; + const auto shift = -scroll(); + for (const auto &button : _buttons) { + const auto geometry = button.geometry.translated(shift); + if (button.active) { + p.setBrush(st::giftBoxTabBgActive); + p.setPen(Qt::NoPen); + const auto radius = geometry.height() / 2.; + p.drawRoundedRect(geometry, radius, radius); + p.setPen(st::giftBoxTabFgActive); + } else { + p.setPen(st::giftBoxTabFg); + } + button.text.draw(p, { + .position = geometry.marginsRemoved(padding).topLeft(), + .availableWidth = button.text.maxWidth(), + }); + } + if (_fullWidth > width()) { + const auto &icon = st::defaultEmojiSuggestions; + const auto w = icon.fadeRight.width(); + const auto &c = st::boxDividerBg->c; + const auto r = QRect(0, 0, w, height()); + const auto s = std::abs(float64(shift.x())); + constexpr auto kF = 0.5; + const auto opacityRight = (_scrollMax - s) + / (icon.fadeRight.width() * kF); + p.setOpacity(std::clamp(std::abs(opacityRight), 0., 1.)); + icon.fadeRight.fill(p, r.translated(width() - w, 0), c); + + const auto opacityLeft = s / (icon.fadeLeft.width() * kF); + p.setOpacity(std::clamp(std::abs(opacityLeft), 0., 1.)); + icon.fadeLeft.fill(p, r, c); + } + +} + +QPoint SubTabs::scroll() const { + return QPoint(int(base::SafeRound(_scroll)) - _fullShift, 0); +} + +} // namespace Ui + diff --git a/Telegram/SourceFiles/ui/controls/sub_tabs.h b/Telegram/SourceFiles/ui/controls/sub_tabs.h new file mode 100644 index 0000000000..d5403c3547 --- /dev/null +++ b/Telegram/SourceFiles/ui/controls/sub_tabs.h @@ -0,0 +1,77 @@ +/* +This file is part of Telegram Desktop, +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 +*/ +#pragma once + +#include "ui/rp_widget.h" + +namespace Ui { + +class SubTabs : public RpWidget { +public: + struct Options { + QString selected; + bool centered = false; + }; + struct Tab { + QString id; + TextWithEntities text; + + friend inline bool operator==(const Tab &, const Tab &) = default; + }; + + explicit SubTabs( + QWidget *parent, + Options options = {}, + std::vector tabs = {}, + Text::MarkedContext context = {}); + + void setTabs( + std::vector tabs, + Text::MarkedContext context = {}); + + void setActiveTab(const QString &id); + + [[nodiscard]] rpl::producer activated() const; + +private: + struct Button { + Tab tab; + QRect geometry; + Text::String text; + bool active = false; + }; + + int resizeGetHeight(int newWidth) override; + void wheelEvent(QWheelEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void paintEvent(QPaintEvent *e) override; + bool eventHook(QEvent *e) override; + + void setSelected(int index); + void setActive(int index); + [[nodiscard]] QPoint scroll() const; + + std::vector