Compare commits
324 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5434ea491 | ||
|
|
ce4338fae4 | ||
|
|
5a1a8af222 | ||
|
|
152b49c65c | ||
|
|
5c5414b680 | ||
|
|
f99960e1f6 | ||
|
|
e363b254f6 | ||
|
|
3aea9cb3ca | ||
|
|
060fe6a928 | ||
|
|
8c45b5e0f8 | ||
|
|
0126578dbd | ||
|
|
1a9c241b96 | ||
|
|
638d4d63c5 | ||
|
|
9370e87c54 | ||
|
|
59c38df5cc | ||
|
|
5655ad25b0 | ||
|
|
c86ced8a1e | ||
|
|
511067981d | ||
|
|
9a186cd8ce | ||
|
|
385aa3eef7 | ||
|
|
e065d32d28 | ||
|
|
d4feb16378 | ||
|
|
79e6369e27 | ||
|
|
e4bd89d33e | ||
|
|
2b89700f66 | ||
|
|
ab95751a66 | ||
|
|
841908fe31 | ||
|
|
9e0b046213 | ||
|
|
d46b9d024e | ||
|
|
52cd9f8cbf | ||
|
|
25d69434ec | ||
|
|
8c4e8212cd | ||
|
|
c24da4c3df | ||
|
|
47a237c924 | ||
|
|
fc3a9d98c0 | ||
|
|
acce671eb0 | ||
|
|
67b6023b32 | ||
|
|
5a46bb1770 | ||
|
|
01fd8aded1 | ||
|
|
e0750f7b87 | ||
|
|
4eaba39a7c | ||
|
|
6ac9ef34eb | ||
|
|
42a2286230 | ||
|
|
24d02d5461 | ||
|
|
9bf2940375 | ||
|
|
d98212e8b3 | ||
|
|
3fe9c36d90 | ||
|
|
22f16caa89 | ||
|
|
46cce57f6b | ||
|
|
456244cdec | ||
|
|
69b2030c71 | ||
|
|
11018d76f1 | ||
|
|
e862215efb | ||
|
|
129de6d87f | ||
|
|
3c3ce24675 | ||
|
|
d98ac33425 | ||
|
|
76842792b8 | ||
|
|
4b01043b27 | ||
|
|
0a4f3f310c | ||
|
|
8320feea10 | ||
|
|
58281023bc | ||
|
|
0b655450bb | ||
|
|
61292557bf | ||
|
|
12ad1190ff | ||
|
|
42e0994581 | ||
|
|
69bc595e31 | ||
|
|
5c097887ef | ||
|
|
b02b690747 | ||
|
|
c52da743fd | ||
|
|
63dff9ff91 | ||
|
|
1c41808042 | ||
|
|
2ebf44c166 | ||
|
|
c46b96f252 | ||
|
|
6c89f60679 | ||
|
|
bb73687fc5 | ||
|
|
31fa2d9355 | ||
|
|
c350e33dd8 | ||
|
|
7dd9adb934 | ||
|
|
01dc3b9382 | ||
|
|
c62b39e287 | ||
|
|
04f95e905e | ||
|
|
9463bbd266 | ||
|
|
f64f1ea62e | ||
|
|
55bd469b2d | ||
|
|
ba50393e86 | ||
|
|
df155f6cb5 | ||
|
|
8aafe6ba0e | ||
|
|
9cf15da2b1 | ||
|
|
d9c566ac44 | ||
|
|
780b5555d7 | ||
|
|
87aa8a249f | ||
|
|
8de6d0b63b | ||
|
|
8dceec5a9f | ||
|
|
da690d2741 | ||
|
|
b95f5071a4 | ||
|
|
7cc55e24c0 | ||
|
|
199c746216 | ||
|
|
2b9cce2f23 | ||
|
|
ed4b90717a | ||
|
|
c50df6a6bc | ||
|
|
54149fb156 | ||
|
|
2f964d0415 | ||
|
|
0970728273 | ||
|
|
b02dd889e0 | ||
|
|
f68e4d9d59 | ||
|
|
9445ce4b09 | ||
|
|
515d8e78da | ||
|
|
f316d951ae | ||
|
|
52e780b065 | ||
|
|
900f7e1304 | ||
|
|
2f5cb33bf2 | ||
|
|
000a7ae28b | ||
|
|
00460506b2 | ||
|
|
0852e717c3 | ||
|
|
a7f9b260de | ||
|
|
7d81159ccf | ||
|
|
556aa28df6 | ||
|
|
c61cabb075 | ||
|
|
a6fe5c08ad | ||
|
|
256e976167 | ||
|
|
e081ed4b4a | ||
|
|
4623804123 | ||
|
|
93e78f1565 | ||
|
|
b587328fed | ||
|
|
2fd5771c3d | ||
|
|
59b521d666 | ||
|
|
c3f5de30be | ||
|
|
2df5972f68 | ||
|
|
c9ebe28fc1 | ||
|
|
9997af1e8b | ||
|
|
b13b4a6b5c | ||
|
|
f10b2194e6 | ||
|
|
d1050e6041 | ||
|
|
326574ab7e | ||
|
|
3822845f86 | ||
|
|
f887bf3b6a | ||
|
|
dfa4a9990d | ||
|
|
7f55fd2cad | ||
|
|
822c0434e8 | ||
|
|
76596f42c7 | ||
|
|
f2577265ee | ||
|
|
895c65d518 | ||
|
|
d8cc7a9b50 | ||
|
|
212944d89c | ||
|
|
2b5df331bd | ||
|
|
7ebebc2bc3 | ||
|
|
120ce27894 | ||
|
|
17312a1eec | ||
|
|
f1b4a82015 | ||
|
|
a6c76382e3 | ||
|
|
370ad0aa44 | ||
|
|
b1554782fb | ||
|
|
90c6ff3e41 | ||
|
|
432ce4caa4 | ||
|
|
eb1845e33b | ||
|
|
0981335ca7 | ||
|
|
1a69627102 | ||
|
|
3c0694280f | ||
|
|
e050055c1e | ||
|
|
e7c598e533 | ||
|
|
dd76d54aeb | ||
|
|
1dc31c7f2f | ||
|
|
5cc7c2b6c6 | ||
|
|
dd0e0a10cd | ||
|
|
9fb12b6093 | ||
|
|
5ea5d3c60d | ||
|
|
20ea3af2f0 | ||
|
|
41f2cc6d81 | ||
|
|
d529c60081 | ||
|
|
7d0eb3ba8e | ||
|
|
3c028590b1 | ||
|
|
47c8b852b8 | ||
|
|
c15019dee6 | ||
|
|
09aff23ac9 | ||
|
|
b7707a8a89 | ||
|
|
10ced19841 | ||
|
|
2ef47222f4 | ||
|
|
a95b756111 | ||
|
|
d2615dda63 | ||
|
|
e6f3cd1d56 | ||
|
|
5d32ba5867 | ||
|
|
4b1e9e3b9d | ||
|
|
06c9e55c26 | ||
|
|
613a2f358a | ||
|
|
c3fa300b5c | ||
|
|
0db6fc4ffb | ||
|
|
9211b4d421 | ||
|
|
ab33af3f73 | ||
|
|
dfc1712043 | ||
|
|
87eaab15b5 | ||
|
|
90af3d295b | ||
|
|
107dea085c | ||
|
|
a9eedf0024 | ||
|
|
db435aa9b1 | ||
|
|
711fcc2e11 | ||
|
|
90f7f482ee | ||
|
|
eff340deaf | ||
|
|
a8d0b80baa | ||
|
|
c777f51427 | ||
|
|
1a07a388d0 | ||
|
|
cbad993bba | ||
|
|
40971d6da6 | ||
|
|
52eef22273 | ||
|
|
44e81269a3 | ||
|
|
0ede4bba72 | ||
|
|
5e8e654324 | ||
|
|
916601a52c | ||
|
|
a726c6411b | ||
|
|
a33c9479a5 | ||
|
|
73b0153a66 | ||
|
|
bb8f9a1b7f | ||
|
|
4922768086 | ||
|
|
806f2e0b50 | ||
|
|
d319c85c57 | ||
|
|
f697abe9a1 | ||
|
|
ae31bdcd1b | ||
|
|
aaf71b34b5 | ||
|
|
5f9dae1b72 | ||
|
|
1757dd856b | ||
|
|
5689154ec5 | ||
|
|
57249c6ea0 | ||
|
|
1bd0b03e8e | ||
|
|
0227b5f2fa | ||
|
|
b629e0c43a | ||
|
|
6507007086 | ||
|
|
a389a1e468 | ||
|
|
4e57ce8dbb | ||
|
|
b6ac4a0233 | ||
|
|
f8dca0ae88 | ||
|
|
ef6fab7f2a | ||
|
|
c8c7497d75 | ||
|
|
4f062788d2 | ||
|
|
25ab88d87a | ||
|
|
e5732cba97 | ||
|
|
0e794d53cd | ||
|
|
68badc6682 | ||
|
|
27c799ce3d | ||
|
|
044c281cf7 | ||
|
|
3f0078cfbf | ||
|
|
6068dc418d | ||
|
|
6960e4808a | ||
|
|
793e8c102e | ||
|
|
31c745cb07 | ||
|
|
c8efb77520 | ||
|
|
76593b0f3d | ||
|
|
9703f7460a | ||
|
|
325840703e | ||
|
|
70fdc4eb39 | ||
|
|
79a361ba43 | ||
|
|
8c4d3a86e7 | ||
|
|
2b5d3b022d | ||
|
|
bf7aae5fc6 | ||
|
|
8171ed6c12 | ||
|
|
5d6a494934 | ||
|
|
90a9cb4f8d | ||
|
|
c60b9cfa4d | ||
|
|
8fec04ba7a | ||
|
|
c19c0afe60 | ||
|
|
8ad1e8aed9 | ||
|
|
65050bf9dd | ||
|
|
28cafb129e | ||
|
|
0bc2bfe630 | ||
|
|
d8a2b391a3 | ||
|
|
e38d39656d | ||
|
|
99bf61ac8c | ||
|
|
e7b8a52278 | ||
|
|
30c82bb2e0 | ||
|
|
4d65df6ca2 | ||
|
|
4add6234b6 | ||
|
|
55ec4ebf86 | ||
|
|
c92c15883d | ||
|
|
7b0a32b607 | ||
|
|
34ef54e40b | ||
|
|
51c2bc7349 | ||
|
|
2e7a89d9c4 | ||
|
|
1248cef86b | ||
|
|
0696a2d5c0 | ||
|
|
e318a7d65f | ||
|
|
5f238a71f9 | ||
|
|
f129b6b90d | ||
|
|
bc3719038f | ||
|
|
1705a1aa4a | ||
|
|
a45d088ee4 | ||
|
|
28570b45e3 | ||
|
|
4a8d297df3 | ||
|
|
3bb352e0e5 | ||
|
|
b49a8e6dc1 | ||
|
|
0824d2da20 | ||
|
|
2635ca33f8 | ||
|
|
5433c16244 | ||
|
|
997913be25 | ||
|
|
83538675ce | ||
|
|
4d6cc58f0d | ||
|
|
3a5ede534e | ||
|
|
357caf8007 | ||
|
|
63cdda2df7 | ||
|
|
3ef45f5431 | ||
|
|
c83659f0c7 | ||
|
|
ba103fdd40 | ||
|
|
bc144377c0 | ||
|
|
5e045ec02c | ||
|
|
ab5796c117 | ||
|
|
6fc5e22882 | ||
|
|
815e26eea5 | ||
|
|
9faf15943a | ||
|
|
dddd355f6c | ||
|
|
f450f81215 | ||
|
|
3c4e959468 | ||
|
|
b0f9ad71dd | ||
|
|
0ad7dcaef9 | ||
|
|
7f09da9e32 | ||
|
|
0b028b959b | ||
|
|
ee43027bea | ||
|
|
ea86433be5 | ||
|
|
598fb67cdf | ||
|
|
5f8d22f1f2 | ||
|
|
7892ba97e6 | ||
|
|
ad4afe9293 | ||
|
|
739a3ebe97 | ||
|
|
03dec15e8e | ||
|
|
fc174f742a | ||
|
|
27af83267e | ||
|
|
4b354b0928 | ||
|
|
3878a1b212 |
14
.github/workflows/linux.yml
vendored
@@ -95,7 +95,7 @@ jobs:
|
||||
libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \
|
||||
autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \
|
||||
libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \
|
||||
libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \
|
||||
libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-screensaver0-dev \
|
||||
libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \
|
||||
libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \
|
||||
libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \
|
||||
@@ -157,7 +157,7 @@ jobs:
|
||||
|
||||
- name: Opus cache.
|
||||
id: cache-opus
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/opus
|
||||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
|
||||
- name: FFmpeg cache.
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/ffmpeg-cache
|
||||
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}
|
||||
@@ -356,7 +356,7 @@ jobs:
|
||||
|
||||
- name: OpenSSL cache.
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openssl-cache
|
||||
key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }}
|
||||
@@ -369,7 +369,7 @@ jobs:
|
||||
git clone -b OpenSSL_${OPENSSL_VER}-stable --depth=1 \
|
||||
$GIT/openssl/openssl $opensslDir
|
||||
cd $opensslDir
|
||||
./config --prefix="$OPENSSL_PREFIX"
|
||||
./config --prefix="$OPENSSL_PREFIX" no-tests
|
||||
make -j$(nproc)
|
||||
sudo make DESTDIR="$LibrariesPath/openssl-cache" install_sw
|
||||
cd ..
|
||||
@@ -412,7 +412,7 @@ jobs:
|
||||
|
||||
- name: Qt 5.12.8 cache.
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/qt-cache
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qt*_5_12_8/*') }}
|
||||
@@ -461,7 +461,7 @@ jobs:
|
||||
|
||||
- name: Breakpad cache.
|
||||
id: cache-breakpad
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/breakpad-cache
|
||||
key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }}
|
||||
|
||||
13
.github/workflows/mac.yml
vendored
@@ -133,7 +133,7 @@ jobs:
|
||||
|
||||
- name: OpenSSL cache.
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.OS }}-${{ env.OPENSSL_VER }}-${{ env.CACHE_KEY }}
|
||||
@@ -147,6 +147,7 @@ jobs:
|
||||
git checkout OpenSSL_"$OPENSSL_VER"-stable
|
||||
./Configure \
|
||||
--prefix=$PREFIX \
|
||||
no-tests \
|
||||
darwin64-x86_64-cc \
|
||||
-static \
|
||||
$MIN_MAC
|
||||
@@ -163,7 +164,7 @@ jobs:
|
||||
|
||||
- name: Opus cache.
|
||||
id: cache-opus
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/opus
|
||||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
@@ -185,7 +186,7 @@ jobs:
|
||||
|
||||
- name: Libiconv cache.
|
||||
id: cache-libiconv
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/${{ env.LIBICONV_VER }}
|
||||
key: ${{ runner.OS }}-${{ env.LIBICONV_VER }}-${{ env.CACHE_KEY }}
|
||||
@@ -206,7 +207,7 @@ jobs:
|
||||
|
||||
- name: FFmpeg cache.
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/ffmpeg-cache
|
||||
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}
|
||||
@@ -362,7 +363,7 @@ jobs:
|
||||
|
||||
- name: Crashpad cache.
|
||||
id: cache-crashpad
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/crashpad
|
||||
key: ${{ runner.OS }}-crashpad-${{ env.CACHE_KEY }}-${{ hashFiles('**/crashpad.diff') }}-${{ hashFiles('**/mini_chromium.diff') }}
|
||||
@@ -401,7 +402,7 @@ jobs:
|
||||
|
||||
- name: Qt 5.12.8 cache.
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/qt-cache
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}
|
||||
|
||||
14
.github/workflows/win.yml
vendored
@@ -133,7 +133,7 @@ jobs:
|
||||
|
||||
- name: OpenSSL cache.
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openssl_${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.OS }}-${{ env.CACHE_KEY }}-${{ env.OPENSSL_VER }}
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
git clone %GIT%/openssl/openssl.git openssl_%OPENSSL_VER%
|
||||
cd openssl_%OPENSSL_VER%
|
||||
git checkout OpenSSL_%OPENSSL_VER%-stable
|
||||
perl Configure no-shared debug-VC-WIN32
|
||||
perl Configure no-shared no-tests debug-VC-WIN32
|
||||
nmake
|
||||
mkdir out32.dbg
|
||||
move libcrypto.lib out32.dbg
|
||||
@@ -177,7 +177,7 @@ jobs:
|
||||
|
||||
- name: OpenAL Soft cache.
|
||||
id: cache-openal
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/openal-soft
|
||||
key: ${{ runner.OS }}-openal-soft-${{ env.CACHE_KEY }}
|
||||
@@ -201,7 +201,7 @@ jobs:
|
||||
|
||||
- name: Breakpad cache.
|
||||
id: cache-breakpad
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/breakpad
|
||||
key: ${{ runner.OS }}-breakpad-${{ env.CACHE_KEY }}-${{ hashFiles('**/breakpad.diff') }}
|
||||
@@ -250,7 +250,7 @@ jobs:
|
||||
|
||||
- name: Opus cache.
|
||||
id: cache-opus
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/opus
|
||||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
@@ -269,7 +269,7 @@ jobs:
|
||||
|
||||
- name: FFmpeg cache.
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/ffmpeg
|
||||
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}-2-${{ hashFiles('**/build_ffmpeg_win.sh') }}
|
||||
@@ -291,7 +291,7 @@ jobs:
|
||||
|
||||
- name: Qt 5.12.8 cache.
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/Qt-5.12.8
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}
|
||||
|
||||
@@ -72,9 +72,7 @@ if (LINUX)
|
||||
PRIVATE
|
||||
desktop-app::external_materialdecoration
|
||||
desktop-app::external_nimf_qt5
|
||||
desktop-app::external_qt5ct
|
||||
desktop-app::external_qt5ct_style
|
||||
desktop-app::external_qt5ct_qtplugin
|
||||
desktop-app::external_qt5ct_support
|
||||
)
|
||||
|
||||
if (NOT DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
|
||||
@@ -106,6 +104,7 @@ PRIVATE
|
||||
tdesktop::lib_mtproto
|
||||
tdesktop::lib_scheme
|
||||
tdesktop::lib_export
|
||||
tdesktop::lib_tgvoip
|
||||
desktop-app::lib_base
|
||||
desktop-app::lib_crl
|
||||
desktop-app::lib_ui
|
||||
@@ -122,29 +121,64 @@ PRIVATE
|
||||
desktop-app::external_qr_code_generator
|
||||
desktop-app::external_crash_reports
|
||||
desktop-app::external_auto_updates
|
||||
tdesktop::lib_tgvoip
|
||||
desktop-app::external_openssl
|
||||
desktop-app::external_openal
|
||||
)
|
||||
|
||||
# Telegram uses long atomic types, so on some architectures libatomic is needed.
|
||||
check_cxx_source_compiles("
|
||||
#include <atomic>
|
||||
std::atomic_int64_t foo;
|
||||
int main() {return foo;}
|
||||
" HAVE_LONG_ATOMIC_WITHOUT_LIB)
|
||||
if (NOT HAVE_LONG_ATOMIC_WITHOUT_LIB)
|
||||
target_link_libraries(Telegram PRIVATE atomic)
|
||||
if (LINUX AND DESKTOP_APP_USE_PACKAGED AND Qt5WaylandClient_VERSION VERSION_LESS 5.13.0)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
|
||||
|
||||
target_include_directories(Telegram
|
||||
PRIVATE
|
||||
${WAYLAND_CLIENT_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
if (LINUX)
|
||||
if (DESKTOP_APP_USE_PACKAGED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(XCB_SCREENSAVER REQUIRED IMPORTED_TARGET xcb-screensaver)
|
||||
pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb)
|
||||
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
)
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
PkgConfig::XCB_SCREENSAVER
|
||||
PkgConfig::XCB
|
||||
)
|
||||
else()
|
||||
target_link_static_libraries(Telegram PRIVATE xcb-screensaver)
|
||||
target_link_libraries(Telegram PRIVATE xcb)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LINUX AND NOT TDESKTOP_DISABLE_GTK_INTEGRATION)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
target_compile_options(Telegram PRIVATE -Wno-register)
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED AND NOT DESKTOP_APP_USE_PACKAGED_LAZY)
|
||||
pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11)
|
||||
pkg_check_modules(GOBJECT2 REQUIRED IMPORTED_TARGET gobject-2.0)
|
||||
pkg_check_modules(GLIB2 REQUIRED IMPORTED_TARGET glib-2.0)
|
||||
pkg_check_modules(GTK3 REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
PkgConfig::X11
|
||||
PkgConfig::GOBJECT2
|
||||
PkgConfig::GLIB2
|
||||
PkgConfig::GTK3
|
||||
)
|
||||
else()
|
||||
pkg_search_module(GTK REQUIRED gtk+-2.0 gtk+-3.0)
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
X11
|
||||
gobject-2.0
|
||||
glib-2.0
|
||||
)
|
||||
target_include_directories(Telegram PRIVATE ${GTK_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_precompile_headers(Telegram PRIVATE ${src_loc}/stdafx.h)
|
||||
@@ -152,12 +186,25 @@ nice_target_sources(Telegram ${src_loc}
|
||||
PRIVATE
|
||||
${style_files}
|
||||
|
||||
api/api_bot.cpp
|
||||
api/api_bot.h
|
||||
api/api_chat_filters.cpp
|
||||
api/api_chat_filters.h
|
||||
api/api_chat_invite.cpp
|
||||
api/api_chat_invite.h
|
||||
api/api_common.h
|
||||
api/api_editing.cpp
|
||||
api/api_editing.h
|
||||
api/api_global_privacy.cpp
|
||||
api/api_global_privacy.h
|
||||
api/api_hash.cpp
|
||||
api/api_hash.h
|
||||
api/api_media.cpp
|
||||
api/api_media.h
|
||||
api/api_self_destruct.cpp
|
||||
api/api_self_destruct.h
|
||||
api/api_send_progress.cpp
|
||||
api/api_send_progress.h
|
||||
api/api_sending.cpp
|
||||
api/api_sending.h
|
||||
api/api_sensitive_content.cpp
|
||||
@@ -166,6 +213,8 @@ PRIVATE
|
||||
api/api_single_message_search.h
|
||||
api/api_text_entities.cpp
|
||||
api/api_text_entities.h
|
||||
api/api_updates.cpp
|
||||
api/api_updates.h
|
||||
boxes/filters/edit_filter_box.cpp
|
||||
boxes/filters/edit_filter_box.h
|
||||
boxes/filters/edit_filter_chats_list.cpp
|
||||
@@ -293,16 +342,16 @@ PRIVATE
|
||||
chat_helpers/message_field.h
|
||||
chat_helpers/spellchecker_common.cpp
|
||||
chat_helpers/spellchecker_common.h
|
||||
chat_helpers/stickers.cpp
|
||||
chat_helpers/stickers.h
|
||||
chat_helpers/stickers_emoji_image_loader.cpp
|
||||
chat_helpers/stickers_emoji_image_loader.h
|
||||
chat_helpers/stickers_emoji_pack.cpp
|
||||
chat_helpers/stickers_emoji_pack.h
|
||||
chat_helpers/stickers_dice_pack.cpp
|
||||
chat_helpers/stickers_dice_pack.h
|
||||
chat_helpers/stickers_list_widget.cpp
|
||||
chat_helpers/stickers_list_widget.h
|
||||
chat_helpers/stickers_set.cpp
|
||||
chat_helpers/stickers_set.h
|
||||
chat_helpers/stickers_lottie.cpp
|
||||
chat_helpers/stickers_lottie.h
|
||||
chat_helpers/tabbed_panel.cpp
|
||||
chat_helpers/tabbed_panel.h
|
||||
chat_helpers/tabbed_section.cpp
|
||||
@@ -344,6 +393,10 @@ PRIVATE
|
||||
core/utils.cpp
|
||||
core/utils.h
|
||||
core/version.h
|
||||
data/stickers/data_stickers_set.cpp
|
||||
data/stickers/data_stickers_set.h
|
||||
data/stickers/data_stickers.cpp
|
||||
data/stickers/data_stickers.h
|
||||
data/data_abstract_structure.cpp
|
||||
data/data_abstract_structure.h
|
||||
data/data_auto_download.cpp
|
||||
@@ -352,6 +405,8 @@ PRIVATE
|
||||
data/data_chat.h
|
||||
data/data_chat_filters.cpp
|
||||
data/data_chat_filters.h
|
||||
data/data_changes.cpp
|
||||
data/data_changes.h
|
||||
data/data_channel.cpp
|
||||
data/data_channel.h
|
||||
data/data_channel_admins.cpp
|
||||
@@ -448,6 +503,8 @@ PRIVATE
|
||||
dialogs/dialogs_search_from_controllers.h
|
||||
dialogs/dialogs_widget.cpp
|
||||
dialogs/dialogs_widget.h
|
||||
export/export_manager.cpp
|
||||
export/export_manager.h
|
||||
export/view/export_view_content.cpp
|
||||
export/view/export_view_content.h
|
||||
export/view/export_view_panel_controller.cpp
|
||||
@@ -529,6 +586,8 @@ PRIVATE
|
||||
history/view/history_view_service_message.h
|
||||
history/view/history_view_top_bar_widget.cpp
|
||||
history/view/history_view_top_bar_widget.h
|
||||
history/view/history_view_webpage_preview.cpp
|
||||
history/view/history_view_webpage_preview.h
|
||||
history/history.cpp
|
||||
history/history.h
|
||||
history/history_drag_area.cpp
|
||||
@@ -663,10 +722,12 @@ PRIVATE
|
||||
main/main_account.h
|
||||
main/main_app_config.cpp
|
||||
main/main_app_config.h
|
||||
main/main_domain.cpp
|
||||
main/main_domain.h
|
||||
main/main_session.cpp
|
||||
main/main_session.h
|
||||
main/main_settings.cpp
|
||||
main/main_settings.h
|
||||
main/main_session_settings.cpp
|
||||
main/main_session_settings.h
|
||||
media/audio/media_audio.cpp
|
||||
media/audio/media_audio.h
|
||||
media/audio/media_audio_capture.cpp
|
||||
@@ -681,6 +742,8 @@ PRIVATE
|
||||
media/audio/media_audio_track.h
|
||||
media/audio/media_child_ffmpeg_loader.cpp
|
||||
media/audio/media_child_ffmpeg_loader.h
|
||||
media/audio/media_openal_functions.cpp
|
||||
media/audio/media_openal_functions.h
|
||||
media/clip/media_clip_check_streaming.cpp
|
||||
media/clip/media_clip_check_streaming.h
|
||||
media/clip/media_clip_ffmpeg.cpp
|
||||
@@ -746,8 +809,6 @@ PRIVATE
|
||||
mtproto/connection_tcp.cpp
|
||||
mtproto/connection_tcp.h
|
||||
mtproto/core_types.h
|
||||
mtproto/dc_options.cpp
|
||||
mtproto/dc_options.h
|
||||
mtproto/dedicated_file_loader.cpp
|
||||
mtproto/dedicated_file_loader.h
|
||||
mtproto/facade.cpp
|
||||
@@ -793,6 +854,8 @@ PRIVATE
|
||||
platform/linux/linux_gdk_helper.h
|
||||
platform/linux/linux_libs.cpp
|
||||
platform/linux/linux_libs.h
|
||||
platform/linux/linux_xlib_helper.cpp
|
||||
platform/linux/linux_xlib_helper.h
|
||||
platform/linux/file_utilities_linux.cpp
|
||||
platform/linux/file_utilities_linux.h
|
||||
platform/linux/launcher_linux.cpp
|
||||
@@ -803,6 +866,7 @@ PRIVATE
|
||||
platform/linux/notifications_manager_linux.h
|
||||
platform/linux/specific_linux.cpp
|
||||
platform/linux/specific_linux.h
|
||||
platform/linux/window_title_linux.h
|
||||
platform/mac/file_utilities_mac.mm
|
||||
platform/mac/file_utilities_mac.h
|
||||
platform/mac/launcher_mac.mm
|
||||
@@ -817,8 +881,24 @@ PRIVATE
|
||||
platform/mac/specific_mac_p.h
|
||||
platform/mac/window_title_mac.mm
|
||||
platform/mac/window_title_mac.h
|
||||
platform/mac/mac_touchbar.h
|
||||
platform/mac/mac_touchbar.mm
|
||||
platform/mac/touchbar/items/mac_formatter_item.h
|
||||
platform/mac/touchbar/items/mac_formatter_item.mm
|
||||
platform/mac/touchbar/items/mac_pinned_chats_item.h
|
||||
platform/mac/touchbar/items/mac_pinned_chats_item.mm
|
||||
platform/mac/touchbar/items/mac_scrubber_item.h
|
||||
platform/mac/touchbar/items/mac_scrubber_item.mm
|
||||
platform/mac/touchbar/mac_touchbar_audio.h
|
||||
platform/mac/touchbar/mac_touchbar_audio.mm
|
||||
platform/mac/touchbar/mac_touchbar_common.h
|
||||
platform/mac/touchbar/mac_touchbar_common.mm
|
||||
platform/mac/touchbar/mac_touchbar_controls.h
|
||||
platform/mac/touchbar/mac_touchbar_controls.mm
|
||||
platform/mac/touchbar/mac_touchbar_main.h
|
||||
platform/mac/touchbar/mac_touchbar_main.mm
|
||||
platform/mac/touchbar/mac_touchbar_manager.h
|
||||
platform/mac/touchbar/mac_touchbar_manager.mm
|
||||
platform/mac/touchbar/mac_touchbar_media_view.h
|
||||
platform/mac/touchbar/mac_touchbar_media_view.mm
|
||||
platform/win/audio_win.cpp
|
||||
platform/win/audio_win.h
|
||||
platform/win/file_utilities_win.cpp
|
||||
@@ -881,6 +961,10 @@ PRIVATE
|
||||
settings/settings_privacy_controllers.h
|
||||
settings/settings_privacy_security.cpp
|
||||
settings/settings_privacy_security.h
|
||||
storage/details/storage_file_utilities.cpp
|
||||
storage/details/storage_file_utilities.h
|
||||
storage/details/storage_settings_scheme.cpp
|
||||
storage/details/storage_settings_scheme.h
|
||||
storage/download_manager_mtproto.cpp
|
||||
storage/download_manager_mtproto.h
|
||||
storage/file_download.cpp
|
||||
@@ -899,8 +983,14 @@ PRIVATE
|
||||
storage/serialize_common.h
|
||||
storage/serialize_document.cpp
|
||||
storage/serialize_document.h
|
||||
storage/serialize_peer.cpp
|
||||
storage/serialize_peer.h
|
||||
storage/storage_account.cpp
|
||||
storage/storage_account.h
|
||||
storage/storage_cloud_blob.cpp
|
||||
storage/storage_cloud_blob.h
|
||||
storage/storage_domain.cpp
|
||||
storage/storage_domain.h
|
||||
storage/storage_facade.cpp
|
||||
storage/storage_facade.h
|
||||
# storage/storage_feed_messages.cpp
|
||||
@@ -981,6 +1071,7 @@ PRIVATE
|
||||
window/window_connecting_widget.h
|
||||
window/window_controller.cpp
|
||||
window/window_controller.h
|
||||
window/window_controls_layout.h
|
||||
window/window_filters_menu.cpp
|
||||
window/window_filters_menu.h
|
||||
window/window_history_hider.cpp
|
||||
@@ -999,6 +1090,8 @@ PRIVATE
|
||||
window/window_session_controller.h
|
||||
window/window_slide_animation.cpp
|
||||
window/window_slide_animation.h
|
||||
window/window_title_qt.cpp
|
||||
window/window_title_qt.h
|
||||
window/window_title.h
|
||||
window/window_top_bar_wrap.h
|
||||
window/themes/window_theme.cpp
|
||||
@@ -1035,16 +1128,19 @@ PRIVATE
|
||||
mainwidget.h
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
observer_peer.cpp
|
||||
observer_peer.h
|
||||
qt_static_plugins.cpp
|
||||
settings.cpp
|
||||
settings.h
|
||||
)
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED)
|
||||
nice_target_sources(Telegram ${src_loc} PRIVATE qt_functions.cpp)
|
||||
else()
|
||||
if (NOT LINUX)
|
||||
remove_target_sources(Telegram ${src_loc}
|
||||
window/window_title_qt.cpp
|
||||
window/window_title_qt.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT DESKTOP_APP_USE_PACKAGED)
|
||||
nice_target_sources(Telegram ${src_loc} PRIVATE platform/mac/mac_iconv_helper.c)
|
||||
endif()
|
||||
|
||||
@@ -1124,19 +1220,6 @@ elseif (APPLE)
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
elseif (LINUX)
|
||||
if (NOT TDESKTOP_DISABLE_GTK_INTEGRATION)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_search_module(GTK REQUIRED gtk+-2.0 gtk+-3.0)
|
||||
target_include_directories(Telegram PRIVATE ${GTK_INCLUDE_DIRS})
|
||||
target_compile_options(Telegram PRIVATE -Wno-register)
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED)
|
||||
find_library(X11_LIBRARY X11)
|
||||
target_link_libraries(Telegram PRIVATE ${X11_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (build_macstore)
|
||||
@@ -1199,7 +1282,7 @@ PRIVATE
|
||||
TDESKTOP_API_HASH=${TDESKTOP_API_HASH}
|
||||
)
|
||||
|
||||
if (${CMAKE_GENERATOR} MATCHES "(Visual Studio|Xcode)")
|
||||
if (APPLE OR NOT CMAKE_EXECUTABLE_SUFFIX STREQUAL "" OR NOT "${output_name}" STREQUAL "Telegram")
|
||||
set(output_folder ${CMAKE_BINARY_DIR})
|
||||
elseif (DESKTOP_APP_SPECIAL_TARGET STREQUAL "")
|
||||
set(output_folder ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
BIN
Telegram/Resources/icons/account_check.png
Normal file
|
After Width: | Height: | Size: 263 B |
BIN
Telegram/Resources/icons/account_check@2x.png
Normal file
|
After Width: | Height: | Size: 363 B |
BIN
Telegram/Resources/icons/account_check@3x.png
Normal file
|
After Width: | Height: | Size: 525 B |
|
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 247 B |
|
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 350 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread.png
Normal file
|
After Width: | Height: | Size: 146 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread@2x.png
Normal file
|
After Width: | Height: | Size: 289 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread@3x.png
Normal file
|
After Width: | Height: | Size: 386 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread_dot.png
Normal file
|
After Width: | Height: | Size: 170 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread_dot@2x.png
Normal file
|
After Width: | Height: | Size: 362 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread_dot@3x.png
Normal file
|
After Width: | Height: | Size: 488 B |
BIN
Telegram/Resources/icons/menu_add_account.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
Telegram/Resources/icons/menu_add_account@2x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Telegram/Resources/icons/menu_add_account@3x.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
@@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_menu_update" = "Update";
|
||||
"lng_menu_back" = "Back";
|
||||
"lng_menu_night_mode" = "Night Mode";
|
||||
"lng_menu_add_account" = "Add Account";
|
||||
"lng_menu_activate" = "Activate";
|
||||
|
||||
"lng_disable_notifications_from_tray" = "Disable notifications";
|
||||
"lng_enable_notifications_from_tray" = "Enable notifications";
|
||||
@@ -290,6 +292,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_empty_bio" = "None";
|
||||
|
||||
"lng_settings_section_notify" = "Notifications";
|
||||
"lng_settings_show_from" = "Show notifications from";
|
||||
"lng_settings_notify_all" = "All accounts";
|
||||
"lng_settings_notify_all_about" = "Turn this off if you want to receive notifications only from the account you are currently using.";
|
||||
"lng_settings_notify_title" = "Notifications for chats";
|
||||
"lng_settings_desktop_notify" = "Desktop notifications";
|
||||
"lng_settings_show_name" = "Show sender's name";
|
||||
@@ -333,6 +338,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_update_fail" = "Update check failed :(";
|
||||
"lng_settings_workmode_tray" = "Show tray icon";
|
||||
"lng_settings_workmode_window" = "Show taskbar icon";
|
||||
"lng_settings_native_frame" = "Use system window frame";
|
||||
"lng_settings_auto_start" = "Launch Telegram when system starts";
|
||||
"lng_settings_start_min" = "Launch minimized";
|
||||
"lng_settings_add_sendto" = "Place Telegram in \"Send to\" menu";
|
||||
@@ -418,6 +424,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_passcode_title" = "Local passcode";
|
||||
"lng_settings_password_title" = "Two-step verification";
|
||||
"lng_settings_sessions_title" = "Active sessions";
|
||||
"lng_settings_new_unknown" = "New chats from unknown users";
|
||||
"lng_settings_auto_archive" = "Archive and Mute";
|
||||
"lng_settings_auto_archive_about" = "Automatically archive and mute new chats, groups and channels from non-contacts.";
|
||||
"lng_settings_destroy_title" = "Delete my account";
|
||||
"lng_settings_network_proxy" = "Network and proxy";
|
||||
"lng_settings_version_info" = "Version and updates";
|
||||
@@ -428,6 +437,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_sensitive_disable_filtering" = "Disable filtering";
|
||||
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
|
||||
|
||||
"lng_settings_auto_night_mode" = "Auto-Night mode";
|
||||
"lng_settings_auto_night_enabled" = "Match the system settings";
|
||||
"lng_settings_auto_night_warning" = "You have enabled auto-night mode. If you want to change the dark mode settings, you'll need to disable it first.";
|
||||
"lng_settings_auto_night_disable" = "Disable";
|
||||
|
||||
"lng_suggest_hide_new_title" = "Hide new chats?";
|
||||
"lng_suggest_hide_new_about" = "You are receiving lots of new chats from users who are not in your Contact List.\n\nDo you want to have such chats **automatically muted** and **archived**?";
|
||||
"lng_suggest_hide_new_to_settings" = "Go to Settings";
|
||||
|
||||
"lng_settings_spellchecker" = "Spell checker";
|
||||
"lng_settings_system_spellchecker" = "Use system spell checker";
|
||||
"lng_settings_custom_spellchecker" = "Use spell checker";
|
||||
@@ -1121,6 +1139,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
"lng_group_invite_members#one" = "{count} member, among them:";
|
||||
"lng_group_invite_members#other" = "{count} members, among them:";
|
||||
"lng_channel_invite_private" = "This channel is private.\nPlease join it to continue viewing its content.";
|
||||
|
||||
"lng_group_invite_create" = "Create an invite link";
|
||||
"lng_group_invite_about" = "Telegram users will be able to join\nyour group by following this link.";
|
||||
@@ -1275,6 +1294,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_new_contact_share_done" = "{user} can now see your phone number.";
|
||||
"lng_new_contact_add_name" = "Add {user} to contacts";
|
||||
"lng_new_contact_add_done" = "{user} is now in your contact list.";
|
||||
"lng_new_contact_unarchive" = "Unarchive";
|
||||
"lng_cant_send_to_not_contact" = "Sorry, you can only send messages to\nmutual contacts at the moment.\n{more_info}";
|
||||
"lng_cant_invite_not_contact" = "Sorry, you can only add mutual contacts\nto groups at the moment.\n{more_info}";
|
||||
"lng_cant_more_info" = "More info »";
|
||||
|
||||
@@ -62,10 +62,9 @@ inputMediaUploadedPhoto#1e287d04 flags:# file:InputFile stickers:flags.0?Vector<
|
||||
inputMediaPhoto#b3ba0635 flags:# id:InputPhoto ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
|
||||
inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia;
|
||||
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
|
||||
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
|
||||
inputMediaDocument#23ab23d2 flags:# id:InputDocument ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
|
||||
inputMediaGifExternal#4843b0fd url:string q:string = InputMedia;
|
||||
inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
|
||||
@@ -75,7 +74,7 @@ inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> s
|
||||
inputMediaDice#e66fbf7b emoticon:string = InputMedia;
|
||||
|
||||
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
|
||||
inputChatUploadedPhoto#927c55b4 file:InputFile = InputChatPhoto;
|
||||
inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = InputChatPhoto;
|
||||
inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto;
|
||||
|
||||
inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
|
||||
@@ -113,7 +112,7 @@ userEmpty#200250ba id:int = User;
|
||||
user#938458c1 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
|
||||
|
||||
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
||||
userProfilePhoto#ecd75d8c photo_id:long photo_small:FileLocation photo_big:FileLocation dc_id:int = UserProfilePhoto;
|
||||
userProfilePhoto#69d3ab26 flags:# has_video:flags.0?true photo_id:long photo_small:FileLocation photo_big:FileLocation dc_id:int = UserProfilePhoto;
|
||||
|
||||
userStatusEmpty#9d05049 = UserStatus;
|
||||
userStatusOnline#edb93949 expires:int = UserStatus;
|
||||
@@ -139,7 +138,7 @@ chatParticipantsForbidden#fc900c2b flags:# chat_id:int self_participant:flags.0?
|
||||
chatParticipants#3f460fed chat_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
|
||||
|
||||
chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||
chatPhoto#475cdbd5 photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
|
||||
chatPhoto#d20b9f3c flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
|
||||
|
||||
messageEmpty#83e5de54 id:int = Message;
|
||||
message#452c0e65 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> = Message;
|
||||
@@ -187,7 +186,7 @@ dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer t
|
||||
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
||||
|
||||
photoEmpty#2331b22d id:long = Photo;
|
||||
photo#d07504a5 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> dc_id:int = Photo;
|
||||
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
|
||||
|
||||
photoSizeEmpty#e17e23c type:string = PhotoSize;
|
||||
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
|
||||
@@ -213,7 +212,7 @@ inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags
|
||||
|
||||
peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings;
|
||||
|
||||
peerSettings#818426cd flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true = PeerSettings;
|
||||
peerSettings#733f2961 flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true autoarchived:flags.7?true geo_distance:flags.6?int = PeerSettings;
|
||||
|
||||
wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
|
||||
wallPaperNoFile#8af40b25 flags:# default:flags.1?true dark:flags.4?true settings:flags.2?WallPaperSettings = WallPaper;
|
||||
@@ -358,6 +357,7 @@ updateDialogFilter#26ffde7d flags:# id:int filter:flags.0?DialogFilter = Update;
|
||||
updateDialogFilterOrder#a5d72105 order:Vector<int> = Update;
|
||||
updateDialogFilters#3504914f = Update;
|
||||
updatePhoneCallSignalingData#2661bf09 phone_call_id:long data:bytes = Update;
|
||||
updateChannelParticipant#65d2b464 flags:# channel_id:int date:int user_id:int prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant qts:int = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@@ -395,7 +395,7 @@ help.inviteText#18cb9f78 message:string = help.InviteText;
|
||||
|
||||
encryptedChatEmpty#ab7ec0a0 id:int = EncryptedChat;
|
||||
encryptedChatWaiting#3bf703dc id:int access_hash:long date:int admin_id:int participant_id:int = EncryptedChat;
|
||||
encryptedChatRequested#c878527e id:int access_hash:long date:int admin_id:int participant_id:int g_a:bytes = EncryptedChat;
|
||||
encryptedChatRequested#62718a82 flags:# folder_id:flags.0?int id:int access_hash:long date:int admin_id:int participant_id:int g_a:bytes = EncryptedChat;
|
||||
encryptedChat#fa56ce36 id:int access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long = EncryptedChat;
|
||||
encryptedChatDiscarded#13d6dd27 id:int = EncryptedChat;
|
||||
|
||||
@@ -529,6 +529,7 @@ chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
|
||||
|
||||
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
|
||||
chatInvite#dfc2f58e flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:Photo participants_count:int participants:flags.4?Vector<User> = ChatInvite;
|
||||
chatInvitePeek#61695cb0 chat:Chat expires:int = ChatInvite;
|
||||
|
||||
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
|
||||
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
||||
@@ -619,11 +620,6 @@ channels.channelParticipant#d0d9b163 participant:ChannelParticipant users:Vector
|
||||
|
||||
help.termsOfService#780a0310 flags:# popup:flags.0?true id:DataJSON text:string entities:Vector<MessageEntity> min_age_confirm:flags.1?int = help.TermsOfService;
|
||||
|
||||
foundGif#162ecc1f url:string thumb_url:string content_url:string content_type:string w:int h:int = FoundGif;
|
||||
foundGifCached#9c750409 url:string photo:Photo document:Document = FoundGif;
|
||||
|
||||
messages.foundGifs#450a1c0a next_offset:int results:Vector<FoundGif> = messages.FoundGifs;
|
||||
|
||||
messages.savedGifsNotModified#e8025ca2 = messages.SavedGifs;
|
||||
messages.savedGifs#2e0709a5 hash:int gifs:Vector<Document> = messages.SavedGifs;
|
||||
|
||||
@@ -1141,7 +1137,17 @@ stats.broadcastStats#bdf78394 period:StatsDateRangeDays followers:StatsAbsValueA
|
||||
help.promoDataEmpty#98f6ac75 expires:int = help.PromoData;
|
||||
help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector<Chat> users:Vector<User> psa_type:flags.1?string psa_message:flags.2?string = help.PromoData;
|
||||
|
||||
videoSize#435bb987 type:string location:FileLocation w:int h:int size:int = VideoSize;
|
||||
videoSize#e831c556 flags:# type:string location:FileLocation w:int h:int size:int video_start_ts:flags.0?double = VideoSize;
|
||||
|
||||
statsGroupTopPoster#18f3d0f7 user_id:int messages:int avg_chars:int = StatsGroupTopPoster;
|
||||
|
||||
statsGroupTopAdmin#6014f412 user_id:int deleted:int kicked:int banned:int = StatsGroupTopAdmin;
|
||||
|
||||
statsGroupTopInviter#31962a4c user_id:int invitations:int = StatsGroupTopInviter;
|
||||
|
||||
stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats;
|
||||
|
||||
globalPrivacySettings#bea2f424 flags:# archive_and_mute_new_noncontact_peers:flags.0?Bool = GlobalPrivacySettings;
|
||||
|
||||
---functions---
|
||||
|
||||
@@ -1237,6 +1243,8 @@ account.getThemes#285946f8 format:string hash:int = account.Themes;
|
||||
account.setContentSettings#b574b16b flags:# sensitive_enabled:flags.0?true = Bool;
|
||||
account.getContentSettings#8b9b4dae = account.ContentSettings;
|
||||
account.getMultiWallPapers#65ad71dc wallpapers:Vector<InputWallPaper> = Vector<WallPaper>;
|
||||
account.getGlobalPrivacySettings#eb2b4cf6 = GlobalPrivacySettings;
|
||||
account.setGlobalPrivacySettings#1edaaac2 settings:GlobalPrivacySettings = GlobalPrivacySettings;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||
@@ -1312,7 +1320,6 @@ messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
||||
messages.searchGlobal#bf7225a4 flags:# folder_id:flags.0?int q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
|
||||
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
||||
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
|
||||
messages.getSavedGifs#83bf3d52 hash:int = messages.SavedGifs;
|
||||
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
|
||||
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
|
||||
@@ -1392,7 +1399,7 @@ updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:
|
||||
updates.getChannelDifference#3173d78 flags:# force:flags.0?true channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference;
|
||||
|
||||
photos.updateProfilePhoto#f0bb5152 id:InputPhoto = UserProfilePhoto;
|
||||
photos.uploadProfilePhoto#4f32c098 file:InputFile = photos.Photo;
|
||||
photos.uploadProfilePhoto#89f30f69 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
|
||||
photos.deletePhotos#87cf7f2f id:Vector<InputPhoto> = Vector<long>;
|
||||
photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;
|
||||
|
||||
@@ -1425,6 +1432,7 @@ help.getUserInfo#38a08d3 user_id:InputUser = help.UserInfo;
|
||||
help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector<MessageEntity> = help.UserInfo;
|
||||
help.getPromoData#c0977421 = help.PromoData;
|
||||
help.hidePromoData#1e251c95 peer:InputPeer = Bool;
|
||||
help.dismissSuggestion#77fa99f suggestion:string = Bool;
|
||||
|
||||
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
|
||||
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
|
||||
@@ -1501,5 +1509,6 @@ folders.deleteFolder#1c295881 folder_id:int = Updates;
|
||||
|
||||
stats.getBroadcastStats#ab42441a flags:# dark:flags.0?true channel:InputChannel = stats.BroadcastStats;
|
||||
stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph;
|
||||
stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel = stats.MegagroupStats;
|
||||
|
||||
// LAYER 114
|
||||
// LAYER 116
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="2.1.13.0" />
|
||||
Version="2.2.0.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||
|
||||
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,13,0
|
||||
PRODUCTVERSION 2,1,13,0
|
||||
FILEVERSION 2,2,0,0
|
||||
PRODUCTVERSION 2,2,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -62,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "2.1.13.0"
|
||||
VALUE "FileVersion", "2.2.0.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.13.0"
|
||||
VALUE "ProductVersion", "2.2.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,13,0
|
||||
PRODUCTVERSION 2,1,13,0
|
||||
FILEVERSION 2,2,0,0
|
||||
PRODUCTVERSION 2,2,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -53,10 +53,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "2.1.13.0"
|
||||
VALUE "FileVersion", "2.2.0.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.13.0"
|
||||
VALUE "ProductVersion", "2.2.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
117
Telegram/SourceFiles/api/api_bot.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
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 "api/api_bot.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_send_progress.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/share_box.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/toast/toast.h"
|
||||
|
||||
namespace Api {
|
||||
|
||||
void SendBotCallbackData(
|
||||
not_null<HistoryItem*> item,
|
||||
int row,
|
||||
int column) {
|
||||
if (!IsServerMsgId(item->id)) {
|
||||
return;
|
||||
}
|
||||
const auto history = item->history();
|
||||
const auto session = &history->session();
|
||||
const auto owner = &history->owner();
|
||||
const auto api = &session->api();
|
||||
const auto bot = item->getMessageBot();
|
||||
const auto fullId = item->fullId();
|
||||
const auto getButton = [=] {
|
||||
return HistoryMessageMarkupButton::Get(
|
||||
owner,
|
||||
fullId,
|
||||
row,
|
||||
column);
|
||||
};
|
||||
const auto button = getButton();
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
using ButtonType = HistoryMessageMarkupButton::Type;
|
||||
const auto isGame = (button->type == ButtonType::Game);
|
||||
|
||||
auto flags = MTPmessages_GetBotCallbackAnswer::Flags(0);
|
||||
QByteArray sendData;
|
||||
if (isGame) {
|
||||
flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_game;
|
||||
} else if (button->type == ButtonType::Callback) {
|
||||
flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_data;
|
||||
sendData = button->data;
|
||||
}
|
||||
button->requestId = api->request(MTPmessages_GetBotCallbackAnswer(
|
||||
MTP_flags(flags),
|
||||
history->peer->input,
|
||||
MTP_int(item->id),
|
||||
MTP_bytes(sendData)
|
||||
)).done([=](const MTPmessages_BotCallbackAnswer &result) {
|
||||
const auto item = owner->message(fullId);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
if (const auto button = getButton()) {
|
||||
button->requestId = 0;
|
||||
owner->requestItemRepaint(item);
|
||||
}
|
||||
result.match([&](const MTPDmessages_botCallbackAnswer &data) {
|
||||
if (const auto message = data.vmessage()) {
|
||||
if (data.is_alert()) {
|
||||
Ui::show(Box<InformBox>(qs(*message)));
|
||||
} else {
|
||||
Ui::Toast::Show(qs(*message));
|
||||
}
|
||||
} else if (const auto url = data.vurl()) {
|
||||
const auto link = qs(*url);
|
||||
if (!isGame) {
|
||||
UrlClickHandler::Open(link);
|
||||
return;
|
||||
}
|
||||
const auto scoreLink = AppendShareGameScoreUrl(
|
||||
session,
|
||||
link,
|
||||
item->fullId());
|
||||
BotGameUrlClickHandler(bot, scoreLink).onClick({});
|
||||
session->sendProgressManager().update(
|
||||
history,
|
||||
Api::SendProgressType::PlayGame);
|
||||
}
|
||||
});
|
||||
}).fail([=](const RPCError &error) {
|
||||
const auto item = owner->message(fullId);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
// Show error?
|
||||
if (const auto button = getButton()) {
|
||||
button->requestId = 0;
|
||||
owner->requestItemRepaint(item);
|
||||
}
|
||||
}).send();
|
||||
|
||||
session->changes().messageUpdated(
|
||||
item,
|
||||
Data::MessageUpdate::Flag::BotCallbackSent
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
19
Telegram/SourceFiles/api/api_bot.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
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
|
||||
|
||||
class HistoryItem;
|
||||
|
||||
namespace Api {
|
||||
|
||||
void SendBotCallbackData(
|
||||
not_null<HistoryItem*> item,
|
||||
int row,
|
||||
int column);
|
||||
|
||||
} // namespace Api
|
||||
230
Telegram/SourceFiles/api/api_chat_invite.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
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 "api/api_chat_invite.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "data/data_photo_media.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
namespace Api {
|
||||
|
||||
void CheckChatInvite(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &hash,
|
||||
ChannelData *invitePeekChannel) {
|
||||
const auto session = &controller->session();
|
||||
const auto weak = base::make_weak(controller.get());
|
||||
session->api().checkChatInvite(hash, [=](const MTPChatInvite &result) {
|
||||
Core::App().hideMediaView();
|
||||
result.match([=](const MTPDchatInvite &data) {
|
||||
const auto box = Ui::show(Box<ConfirmInviteBox>(
|
||||
session,
|
||||
data,
|
||||
invitePeekChannel,
|
||||
[=] { session->api().importChatInvite(hash); }));
|
||||
if (invitePeekChannel) {
|
||||
box->boxClosing(
|
||||
) | rpl::filter([=] {
|
||||
return !invitePeekChannel->amIn();
|
||||
}) | rpl::start_with_next([=] {
|
||||
if (const auto strong = weak.get()) {
|
||||
strong->clearSectionStack(Window::SectionShow(
|
||||
Window::SectionShow::Way::ClearStack,
|
||||
anim::type::normal,
|
||||
anim::activation::background));
|
||||
}
|
||||
}, box->lifetime());
|
||||
}
|
||||
}, [=](const MTPDchatInviteAlready &data) {
|
||||
if (const auto chat = session->data().processChat(data.vchat())) {
|
||||
if (const auto channel = chat->asChannel()) {
|
||||
channel->clearInvitePeek();
|
||||
}
|
||||
if (const auto strong = weak.get()) {
|
||||
strong->showPeerHistory(
|
||||
chat,
|
||||
Window::SectionShow::Way::Forward);
|
||||
}
|
||||
}
|
||||
}, [=](const MTPDchatInvitePeek &data) {
|
||||
if (const auto chat = session->data().processChat(data.vchat())) {
|
||||
if (const auto channel = chat->asChannel()) {
|
||||
channel->setInvitePeek(hash, data.vexpires().v);
|
||||
if (const auto strong = weak.get()) {
|
||||
strong->showPeerHistory(
|
||||
chat,
|
||||
Window::SectionShow::Way::Forward);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [=](const RPCError &error) {
|
||||
if (error.code() != 400) {
|
||||
return;
|
||||
}
|
||||
Core::App().hideMediaView();
|
||||
Ui::show(Box<InformBox>(tr::lng_group_invite_bad_link(tr::now)));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data,
|
||||
ChannelData *invitePeekChannel,
|
||||
Fn<void()> submit)
|
||||
: _session(session)
|
||||
, _submit(std::move(submit))
|
||||
, _title(this, st::confirmInviteTitle)
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _participants(GetParticipants(_session, data))
|
||||
, _isChannel(data.is_channel() && !data.is_megagroup()) {
|
||||
const auto title = qs(data.vtitle());
|
||||
const auto count = data.vparticipants_count().v;
|
||||
const auto status = [&] {
|
||||
return invitePeekChannel
|
||||
? tr::lng_channel_invite_private(tr::now)
|
||||
: (!_participants.empty() && _participants.size() < count)
|
||||
? tr::lng_group_invite_members(tr::now, lt_count, count)
|
||||
: (count > 0)
|
||||
? tr::lng_chat_status_members(tr::now, lt_count_decimal, count)
|
||||
: _isChannel
|
||||
? tr::lng_channel_status(tr::now)
|
||||
: tr::lng_group_status(tr::now);
|
||||
}();
|
||||
_title->setText(title);
|
||||
_status->setText(status);
|
||||
|
||||
const auto photo = _session->data().processPhoto(data.vphoto());
|
||||
if (!photo->isNull()) {
|
||||
_photo = photo->createMediaView();
|
||||
_photo->wanted(Data::PhotoSize::Small, Data::FileOrigin());
|
||||
if (!_photo->image(Data::PhotoSize::Small)) {
|
||||
_session->downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
}
|
||||
} else {
|
||||
_photoEmpty = std::make_unique<Ui::EmptyUserpic>(
|
||||
Data::PeerUserpicColor(0),
|
||||
title);
|
||||
}
|
||||
}
|
||||
|
||||
ConfirmInviteBox::~ConfirmInviteBox() = default;
|
||||
|
||||
auto ConfirmInviteBox::GetParticipants(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data)
|
||||
-> std::vector<Participant> {
|
||||
const auto participants = data.vparticipants();
|
||||
if (!participants) {
|
||||
return {};
|
||||
}
|
||||
const auto &v = participants->v;
|
||||
auto result = std::vector<Participant>();
|
||||
result.reserve(v.size());
|
||||
for (const auto &participant : v) {
|
||||
if (const auto user = session->data().processUser(participant)) {
|
||||
result.push_back(Participant{ user });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::prepare() {
|
||||
addButton(
|
||||
(_isChannel
|
||||
? tr::lng_profile_join_channel()
|
||||
: tr::lng_profile_join_group()),
|
||||
_submit);
|
||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||
|
||||
while (_participants.size() > 4) {
|
||||
_participants.pop_back();
|
||||
}
|
||||
|
||||
auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom();
|
||||
if (!_participants.empty()) {
|
||||
int skip = (st::boxWideWidth - 4 * st::confirmInviteUserPhotoSize) / 5;
|
||||
int padding = skip / 2;
|
||||
_userWidth = (st::confirmInviteUserPhotoSize + 2 * padding);
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (st::boxWideWidth - sumWidth) / 2;
|
||||
for (const auto &participant : _participants) {
|
||||
auto name = new Ui::FlatLabel(this, st::confirmInviteUserName);
|
||||
name->resizeToWidth(st::confirmInviteUserPhotoSize + padding);
|
||||
name->setText(participant.user->firstName.isEmpty()
|
||||
? participant.user->name
|
||||
: participant.user->firstName);
|
||||
name->moveToLeft(left + (padding / 2), st::confirmInviteUserNameTop);
|
||||
left += _userWidth;
|
||||
}
|
||||
|
||||
newHeight += st::confirmInviteUserHeight;
|
||||
}
|
||||
setDimensions(st::boxWideWidth, newHeight);
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
_title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop);
|
||||
_status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop);
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
||||
BoxContent::paintEvent(e);
|
||||
|
||||
Painter p(this);
|
||||
|
||||
if (_photo) {
|
||||
if (const auto image = _photo->image(Data::PhotoSize::Small)) {
|
||||
p.drawPixmap(
|
||||
(width() - st::confirmInvitePhotoSize) / 2,
|
||||
st::confirmInvitePhotoTop,
|
||||
image->pixCircled(
|
||||
st::confirmInvitePhotoSize,
|
||||
st::confirmInvitePhotoSize));
|
||||
}
|
||||
} else if (_photoEmpty) {
|
||||
_photoEmpty->paint(
|
||||
p,
|
||||
(width() - st::confirmInvitePhotoSize) / 2,
|
||||
st::confirmInvitePhotoTop,
|
||||
width(),
|
||||
st::confirmInvitePhotoSize);
|
||||
}
|
||||
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (width() - sumWidth) / 2;
|
||||
for (auto &participant : _participants) {
|
||||
participant.user->paintUserpicLeft(
|
||||
p,
|
||||
participant.userpic,
|
||||
left + (_userWidth - st::confirmInviteUserPhotoSize) / 2,
|
||||
st::confirmInviteUserPhotoTop,
|
||||
width(),
|
||||
st::confirmInviteUserPhotoSize);
|
||||
left += _userWidth;
|
||||
}
|
||||
}
|
||||
74
Telegram/SourceFiles/api/api_chat_invite.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
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/layers/box_content.h"
|
||||
|
||||
class UserData;
|
||||
class ChannelData;
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Data {
|
||||
class CloudImageView;
|
||||
class PhotoMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
class EmptyUserpic;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Api {
|
||||
|
||||
void CheckChatInvite(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &hash,
|
||||
ChannelData *invitePeekChannel = nullptr);
|
||||
|
||||
} // namespace Api
|
||||
|
||||
class ConfirmInviteBox final : public Ui::BoxContent {
|
||||
public:
|
||||
ConfirmInviteBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data,
|
||||
ChannelData *invitePeekChannel,
|
||||
Fn<void()> submit);
|
||||
~ConfirmInviteBox();
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
struct Participant {
|
||||
not_null<UserData*> user;
|
||||
std::shared_ptr<Data::CloudImageView> userpic;
|
||||
};
|
||||
static std::vector<Participant> GetParticipants(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
|
||||
Fn<void()> _submit;
|
||||
object_ptr<Ui::FlatLabel> _title;
|
||||
object_ptr<Ui::FlatLabel> _status;
|
||||
std::shared_ptr<Data::PhotoMedia> _photo;
|
||||
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
|
||||
std::vector<Participant> _participants;
|
||||
bool _isChannel = false;
|
||||
|
||||
int _userWidth = 0;
|
||||
|
||||
};
|
||||
213
Telegram/SourceFiles/api/api_editing.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
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 "api/api_editing.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_media.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_session.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
using namespace rpl::details;
|
||||
|
||||
template <typename T>
|
||||
constexpr auto WithId =
|
||||
is_callable_plain_v<T, const MTPUpdates &, Fn<void()>, mtpRequestId>;
|
||||
template <typename T>
|
||||
constexpr auto WithoutId =
|
||||
is_callable_plain_v<T, const MTPUpdates &, Fn<void()>>;
|
||||
template <typename T>
|
||||
constexpr auto WithoutCallback =
|
||||
is_callable_plain_v<T, const MTPUpdates &>;
|
||||
|
||||
template <typename DoneCallback, typename FailCallback>
|
||||
mtpRequestId EditMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &textWithEntities,
|
||||
SendOptions options,
|
||||
DoneCallback &&done,
|
||||
FailCallback &&fail,
|
||||
std::optional<MTPInputMedia> inputMedia = std::nullopt) {
|
||||
const auto session = &item->history()->session();
|
||||
const auto api = &session->api();
|
||||
|
||||
const auto text = textWithEntities.text;
|
||||
const auto sentEntities = EntitiesToMTP(
|
||||
session,
|
||||
textWithEntities.entities,
|
||||
ConvertOption::SkipLocal);
|
||||
const auto media = item->media();
|
||||
|
||||
const auto emptyFlag = MTPmessages_EditMessage::Flag(0);
|
||||
const auto flags = emptyFlag
|
||||
| (!text.isEmpty() || media
|
||||
? MTPmessages_EditMessage::Flag::f_message
|
||||
: emptyFlag)
|
||||
| ((media && inputMedia.has_value())
|
||||
? MTPmessages_EditMessage::Flag::f_media
|
||||
: emptyFlag)
|
||||
| (options.removeWebPageId
|
||||
? MTPmessages_EditMessage::Flag::f_no_webpage
|
||||
: emptyFlag)
|
||||
| (!sentEntities.v.isEmpty()
|
||||
? MTPmessages_EditMessage::Flag::f_entities
|
||||
: emptyFlag)
|
||||
| (options.scheduled
|
||||
? MTPmessages_EditMessage::Flag::f_schedule_date
|
||||
: emptyFlag);
|
||||
|
||||
const auto id = item->isScheduled()
|
||||
? session->data().scheduledMessages().lookupId(item)
|
||||
: item->id;
|
||||
return api->request(MTPmessages_EditMessage(
|
||||
MTP_flags(flags),
|
||||
item->history()->peer->input,
|
||||
MTP_int(id),
|
||||
MTP_string(text),
|
||||
inputMedia.value_or(MTPInputMedia()),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(options.scheduled)
|
||||
)).done([=](
|
||||
const MTPUpdates &result,
|
||||
[[maybe_unused]] mtpRequestId requestId) {
|
||||
const auto apply = [=] { api->applyUpdates(result); };
|
||||
|
||||
if constexpr (WithId<DoneCallback>) {
|
||||
done(result, apply, requestId);
|
||||
} else if constexpr (WithoutId<DoneCallback>) {
|
||||
done(result, apply);
|
||||
} else if constexpr (WithoutCallback<DoneCallback>) {
|
||||
done(result);
|
||||
apply();
|
||||
} else {
|
||||
apply();
|
||||
}
|
||||
}).fail(
|
||||
fail
|
||||
).send();
|
||||
}
|
||||
|
||||
template <typename DoneCallback, typename FailCallback>
|
||||
mtpRequestId EditMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
SendOptions options,
|
||||
DoneCallback &&done,
|
||||
FailCallback &&fail,
|
||||
std::optional<MTPInputMedia> inputMedia = std::nullopt) {
|
||||
const auto &text = item->originalText();
|
||||
return EditMessage(
|
||||
item,
|
||||
text,
|
||||
options,
|
||||
std::forward<DoneCallback>(done),
|
||||
std::forward<FailCallback>(fail),
|
||||
inputMedia);
|
||||
}
|
||||
|
||||
void EditMessageWithUploadedMedia(
|
||||
not_null<HistoryItem*> item,
|
||||
SendOptions options,
|
||||
MTPInputMedia media) {
|
||||
const auto done = [=](const auto &result, Fn<void()> applyUpdates) {
|
||||
if (item) {
|
||||
item->clearSavedMedia();
|
||||
item->setIsLocalUpdateMedia(true);
|
||||
applyUpdates();
|
||||
item->setIsLocalUpdateMedia(false);
|
||||
}
|
||||
};
|
||||
const auto fail = [=](const RPCError &error) {
|
||||
const auto err = error.type();
|
||||
const auto session = &item->history()->session();
|
||||
const auto notModified = (err == u"MESSAGE_NOT_MODIFIED"_q);
|
||||
const auto mediaInvalid = (err == u"MEDIA_NEW_INVALID"_q);
|
||||
if (notModified || mediaInvalid) {
|
||||
item->returnSavedMedia();
|
||||
session->data().sendHistoryChangeNotifications();
|
||||
if (mediaInvalid) {
|
||||
Ui::show(
|
||||
Box<InformBox>(tr::lng_edit_media_invalid_file(tr::now)),
|
||||
Ui::LayerOption::KeepOther);
|
||||
}
|
||||
} else {
|
||||
session->api().sendMessageFail(error, item->history()->peer);
|
||||
}
|
||||
};
|
||||
|
||||
EditMessage(item, options, done, fail, media);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void RescheduleMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
SendOptions options) {
|
||||
const auto empty = [](const auto &r) {};
|
||||
EditMessage(item, options, empty, empty);
|
||||
}
|
||||
|
||||
void EditMessageWithUploadedDocument(
|
||||
HistoryItem *item,
|
||||
const MTPInputFile &file,
|
||||
const std::optional<MTPInputFile> &thumb,
|
||||
SendOptions options) {
|
||||
if (!item || !item->media() || !item->media()->document()) {
|
||||
return;
|
||||
}
|
||||
const auto media = PrepareUploadedDocument(item, file, thumb);
|
||||
EditMessageWithUploadedMedia(item, options, media);
|
||||
}
|
||||
|
||||
void EditMessageWithUploadedPhoto(
|
||||
HistoryItem *item,
|
||||
const MTPInputFile &file,
|
||||
SendOptions options) {
|
||||
if (!item || !item->media() || !item->media()->photo()) {
|
||||
return;
|
||||
}
|
||||
const auto media = PrepareUploadedPhoto(file);
|
||||
EditMessageWithUploadedMedia(item, options, media);
|
||||
}
|
||||
|
||||
mtpRequestId EditCaption(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &caption,
|
||||
SendOptions options,
|
||||
Fn<void(const MTPUpdates &)> done,
|
||||
Fn<void(const RPCError &)> fail) {
|
||||
return EditMessage(item, caption, options, done, fail);
|
||||
}
|
||||
|
||||
mtpRequestId EditTextMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &caption,
|
||||
SendOptions options,
|
||||
Fn<void(const MTPUpdates &, mtpRequestId requestId)> done,
|
||||
Fn<void(const RPCError &, mtpRequestId requestId)> fail) {
|
||||
const auto callback = [=](
|
||||
const auto &result,
|
||||
Fn<void()> applyUpdates,
|
||||
auto id) {
|
||||
applyUpdates();
|
||||
done(result, id);
|
||||
};
|
||||
return EditMessage(item, caption, options, callback, fail);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Api
|
||||
52
Telegram/SourceFiles/api/api_editing.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
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
|
||||
|
||||
class HistoryItem;
|
||||
class RPCError;
|
||||
|
||||
namespace Api {
|
||||
|
||||
struct SendOptions;
|
||||
|
||||
const auto kDefaultEditMessagesErrors = {
|
||||
u"MESSAGE_ID_INVALID"_q,
|
||||
u"CHAT_ADMIN_REQUIRED"_q,
|
||||
u"MESSAGE_EDIT_TIME_EXPIRED"_q,
|
||||
};
|
||||
|
||||
void RescheduleMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
SendOptions options);
|
||||
|
||||
void EditMessageWithUploadedDocument(
|
||||
HistoryItem *item,
|
||||
const MTPInputFile &file,
|
||||
const std::optional<MTPInputFile> &thumb,
|
||||
SendOptions options);
|
||||
|
||||
void EditMessageWithUploadedPhoto(
|
||||
HistoryItem *item,
|
||||
const MTPInputFile &file,
|
||||
SendOptions options);
|
||||
|
||||
mtpRequestId EditCaption(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &caption,
|
||||
SendOptions options,
|
||||
Fn<void(const MTPUpdates &)> done,
|
||||
Fn<void(const RPCError &)> fail);
|
||||
|
||||
mtpRequestId EditTextMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &caption,
|
||||
SendOptions options,
|
||||
Fn<void(const MTPUpdates &, mtpRequestId requestId)> done,
|
||||
Fn<void(const RPCError &, mtpRequestId requestId)> fail);
|
||||
|
||||
} // namespace Api
|
||||
103
Telegram/SourceFiles/api/api_global_privacy.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
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 "api/api_global_privacy.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
|
||||
namespace Api {
|
||||
|
||||
GlobalPrivacy::GlobalPrivacy(not_null<ApiWrap*> api)
|
||||
: _session(&api->session())
|
||||
, _api(&api->instance()) {
|
||||
}
|
||||
|
||||
void GlobalPrivacy::reload(Fn<void()> callback) {
|
||||
if (callback) {
|
||||
_callbacks.push_back(std::move(callback));
|
||||
}
|
||||
if (_requestId) {
|
||||
return;
|
||||
}
|
||||
_requestId = _api.request(MTPaccount_GetGlobalPrivacySettings(
|
||||
)).done([=](const MTPGlobalPrivacySettings &result) {
|
||||
_requestId = 0;
|
||||
apply(result);
|
||||
for (const auto &callback : base::take(_callbacks)) {
|
||||
callback();
|
||||
}
|
||||
}).fail([=](const RPCError &error) {
|
||||
_requestId = 0;
|
||||
for (const auto &callback : base::take(_callbacks)) {
|
||||
callback();
|
||||
}
|
||||
}).send();
|
||||
|
||||
_session->account().appConfig().value(
|
||||
) | rpl::start_with_next([=] {
|
||||
_showArchiveAndMute = _session->account().appConfig().get<bool>(
|
||||
u"autoarchive_setting_available"_q,
|
||||
false);
|
||||
}, _session->lifetime());
|
||||
}
|
||||
|
||||
bool GlobalPrivacy::archiveAndMuteCurrent() const {
|
||||
return _archiveAndMute.current();
|
||||
}
|
||||
|
||||
rpl::producer<bool> GlobalPrivacy::archiveAndMute() const {
|
||||
return _archiveAndMute.value();
|
||||
}
|
||||
|
||||
rpl::producer<bool> GlobalPrivacy::showArchiveAndMute() const {
|
||||
using namespace rpl::mappers;
|
||||
|
||||
return rpl::combine(
|
||||
archiveAndMute(),
|
||||
_showArchiveAndMute.value(),
|
||||
_1 || _2);
|
||||
}
|
||||
|
||||
rpl::producer<> GlobalPrivacy::suggestArchiveAndMute() const {
|
||||
return _session->account().appConfig().suggestionRequested(
|
||||
u"AUTOARCHIVE_POPULAR"_q);
|
||||
}
|
||||
|
||||
void GlobalPrivacy::dismissArchiveAndMuteSuggestion() {
|
||||
_session->account().appConfig().dismissSuggestion(
|
||||
u"AUTOARCHIVE_POPULAR"_q);
|
||||
}
|
||||
|
||||
void GlobalPrivacy::update(bool archiveAndMute) {
|
||||
using Flag = MTPDglobalPrivacySettings::Flag;
|
||||
|
||||
_api.request(_requestId).cancel();
|
||||
_requestId = _api.request(MTPaccount_SetGlobalPrivacySettings(
|
||||
MTP_globalPrivacySettings(
|
||||
MTP_flags(Flag::f_archive_and_mute_new_noncontact_peers),
|
||||
MTP_bool(archiveAndMute))
|
||||
)).done([=](const MTPGlobalPrivacySettings &result) {
|
||||
_requestId = 0;
|
||||
apply(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
_requestId = 0;
|
||||
}).send();
|
||||
_archiveAndMute = archiveAndMute;
|
||||
}
|
||||
|
||||
void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &data) {
|
||||
data.match([&](const MTPDglobalPrivacySettings &data) {
|
||||
_archiveAndMute = data.varchive_and_mute_new_noncontact_peers()
|
||||
? mtpIsTrue(*data.varchive_and_mute_new_noncontact_peers())
|
||||
: false;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
45
Telegram/SourceFiles/api/api_global_privacy.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
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 "mtproto/sender.h"
|
||||
|
||||
class ApiWrap;
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Api {
|
||||
|
||||
class GlobalPrivacy final {
|
||||
public:
|
||||
explicit GlobalPrivacy(not_null<ApiWrap*> api);
|
||||
|
||||
void reload(Fn<void()> callback = nullptr);
|
||||
void update(bool archiveAndMute);
|
||||
|
||||
[[nodiscard]] bool archiveAndMuteCurrent() const;
|
||||
[[nodiscard]] rpl::producer<bool> archiveAndMute() const;
|
||||
[[nodiscard]] rpl::producer<bool> showArchiveAndMute() const;
|
||||
[[nodiscard]] rpl::producer<> suggestArchiveAndMute() const;
|
||||
void dismissArchiveAndMuteSuggestion();
|
||||
|
||||
private:
|
||||
void apply(const MTPGlobalPrivacySettings &data);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _requestId = 0;
|
||||
rpl::variable<bool> _archiveAndMute = false;
|
||||
rpl::variable<bool> _showArchiveAndMute = false;
|
||||
std::vector<Fn<void()>> _callbacks;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
||||
94
Telegram/SourceFiles/api/api_hash.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
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 "api/api_hash.h"
|
||||
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "main/main_session.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] int32 CountDocumentVectorHash(
|
||||
const QVector<DocumentData*> vector) {
|
||||
auto result = HashInit();
|
||||
for (const auto document : vector) {
|
||||
HashUpdate(result, document->id);
|
||||
}
|
||||
return HashFinalize(result);
|
||||
}
|
||||
|
||||
[[nodiscard]] int32 CountSpecialStickerSetHash(
|
||||
not_null<Main::Session*> session,
|
||||
uint64 setId) {
|
||||
const auto &sets = session->data().stickers().sets();
|
||||
const auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
return CountDocumentVectorHash(it->second->stickers);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int32 CountStickersHash(
|
||||
not_null<Main::Session*> session,
|
||||
bool checkOutdatedInfo) {
|
||||
auto result = HashInit();
|
||||
bool foundOutdated = false;
|
||||
const auto &sets = session->data().stickers().sets();
|
||||
const auto &order = session->data().stickers().setsOrder();
|
||||
for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) {
|
||||
auto it = sets.find(*i);
|
||||
if (it != sets.cend()) {
|
||||
const auto set = it->second.get();
|
||||
if (set->id == Data::Stickers::DefaultSetId) {
|
||||
foundOutdated = true;
|
||||
} else if (!(set->flags & MTPDstickerSet_ClientFlag::f_special)
|
||||
&& !(set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
HashUpdate(result, set->hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (!checkOutdatedInfo || !foundOutdated)
|
||||
? HashFinalize(result)
|
||||
: 0;
|
||||
}
|
||||
|
||||
int32 CountRecentStickersHash(not_null<Main::Session*> session) {
|
||||
return CountSpecialStickerSetHash(
|
||||
session,
|
||||
Data::Stickers::CloudRecentSetId);
|
||||
}
|
||||
|
||||
int32 CountFavedStickersHash(not_null<Main::Session*> session) {
|
||||
return CountSpecialStickerSetHash(session, Data::Stickers::FavedSetId);
|
||||
}
|
||||
|
||||
int32 CountFeaturedStickersHash(not_null<Main::Session*> session) {
|
||||
auto result = HashInit();
|
||||
const auto &sets = session->data().stickers().sets();
|
||||
const auto &featured = session->data().stickers().featuredSetsOrder();
|
||||
for (const auto setId : featured) {
|
||||
HashUpdate(result, setId);
|
||||
|
||||
const auto it = sets.find(setId);
|
||||
if (it != sets.cend()
|
||||
&& (it->second->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
HashUpdate(result, 1);
|
||||
}
|
||||
}
|
||||
return HashFinalize(result);
|
||||
}
|
||||
|
||||
int32 CountSavedGifsHash(not_null<Main::Session*> session) {
|
||||
return CountDocumentVectorHash(session->data().stickers().savedGifs());
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
@@ -7,8 +7,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Api {
|
||||
|
||||
[[nodiscard]] int32 CountStickersHash(
|
||||
not_null<Main::Session*> session,
|
||||
bool checkOutdatedInfo = false);
|
||||
[[nodiscard]] int32 CountRecentStickersHash(
|
||||
not_null<Main::Session*> session);
|
||||
[[nodiscard]] int32 CountFavedStickersHash(not_null<Main::Session*> session);
|
||||
[[nodiscard]] int32 CountFeaturedStickersHash(
|
||||
not_null<Main::Session*> session);
|
||||
[[nodiscard]] int32 CountSavedGifsHash(not_null<Main::Session*> session);
|
||||
|
||||
[[nodiscard]] inline uint32 HashInit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
107
Telegram/SourceFiles/api/api_media.cpp
Normal file
@@ -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 "api/api_media.h"
|
||||
|
||||
#include "data/data_document.h"
|
||||
#include "history/history_item.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
MTPVector<MTPDocumentAttribute> ComposeSendingDocumentAttributes(
|
||||
not_null<DocumentData*> document) {
|
||||
const auto filenameAttribute = MTP_documentAttributeFilename(
|
||||
MTP_string(document->filename()));
|
||||
const auto dimensions = document->dimensions;
|
||||
auto attributes = QVector<MTPDocumentAttribute>(1, filenameAttribute);
|
||||
if (dimensions.width() > 0 && dimensions.height() > 0) {
|
||||
const auto duration = document->getDuration();
|
||||
if (duration >= 0 && !document->hasMimeType(qstr("image/gif"))) {
|
||||
auto flags = MTPDdocumentAttributeVideo::Flags(0);
|
||||
using VideoFlag = MTPDdocumentAttributeVideo::Flag;
|
||||
if (document->isVideoMessage()) {
|
||||
flags |= VideoFlag::f_round_message;
|
||||
}
|
||||
if (document->supportsStreaming()) {
|
||||
flags |= VideoFlag::f_supports_streaming;
|
||||
}
|
||||
attributes.push_back(MTP_documentAttributeVideo(
|
||||
MTP_flags(flags),
|
||||
MTP_int(duration),
|
||||
MTP_int(dimensions.width()),
|
||||
MTP_int(dimensions.height())));
|
||||
} else {
|
||||
attributes.push_back(MTP_documentAttributeImageSize(
|
||||
MTP_int(dimensions.width()),
|
||||
MTP_int(dimensions.height())));
|
||||
}
|
||||
}
|
||||
if (document->type == AnimatedDocument) {
|
||||
attributes.push_back(MTP_documentAttributeAnimated());
|
||||
} else if (document->type == StickerDocument && document->sticker()) {
|
||||
attributes.push_back(MTP_documentAttributeSticker(
|
||||
MTP_flags(0),
|
||||
MTP_string(document->sticker()->alt),
|
||||
document->sticker()->set,
|
||||
MTPMaskCoords()));
|
||||
} else if (const auto song = document->song()) {
|
||||
const auto flags = MTPDdocumentAttributeAudio::Flag::f_title
|
||||
| MTPDdocumentAttributeAudio::Flag::f_performer;
|
||||
attributes.push_back(MTP_documentAttributeAudio(
|
||||
MTP_flags(flags),
|
||||
MTP_int(song->duration),
|
||||
MTP_string(song->title),
|
||||
MTP_string(song->performer),
|
||||
MTPstring()));
|
||||
} else if (const auto voice = document->voice()) {
|
||||
const auto flags = MTPDdocumentAttributeAudio::Flag::f_voice
|
||||
| MTPDdocumentAttributeAudio::Flag::f_waveform;
|
||||
attributes.push_back(MTP_documentAttributeAudio(
|
||||
MTP_flags(flags),
|
||||
MTP_int(voice->duration),
|
||||
MTPstring(),
|
||||
MTPstring(),
|
||||
MTP_bytes(documentWaveformEncode5bit(voice->waveform))));
|
||||
}
|
||||
return MTP_vector<MTPDocumentAttribute>(attributes);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MTPInputMedia PrepareUploadedPhoto(const MTPInputFile &file) {
|
||||
return MTP_inputMediaUploadedPhoto(
|
||||
MTP_flags(0),
|
||||
file,
|
||||
MTPVector<MTPInputDocument>(),
|
||||
MTP_int(0));
|
||||
}
|
||||
|
||||
MTPInputMedia PrepareUploadedDocument(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPInputFile &file,
|
||||
const std::optional<MTPInputFile> &thumb) {
|
||||
if (!item || !item->media() || !item->media()->document()) {
|
||||
return MTP_inputMediaEmpty();
|
||||
}
|
||||
const auto emptyFlag = MTPDinputMediaUploadedDocument::Flags(0);
|
||||
using DocFlags = MTPDinputMediaUploadedDocument::Flag;
|
||||
const auto flags = emptyFlag
|
||||
| (thumb ? DocFlags::f_thumb : emptyFlag)
|
||||
| (item->groupId() ? DocFlags::f_nosound_video : emptyFlag);
|
||||
const auto document = item->media()->document();
|
||||
return MTP_inputMediaUploadedDocument(
|
||||
MTP_flags(flags),
|
||||
file,
|
||||
thumb.value_or(MTPInputFile()),
|
||||
MTP_string(document->mimeString()),
|
||||
ComposeSendingDocumentAttributes(document),
|
||||
MTPVector<MTPInputDocument>(),
|
||||
MTP_int(0));
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
21
Telegram/SourceFiles/api/api_media.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
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
|
||||
|
||||
class HistoryItem;
|
||||
|
||||
namespace Api {
|
||||
|
||||
MTPInputMedia PrepareUploadedPhoto(const MTPInputFile &file);
|
||||
|
||||
MTPInputMedia PrepareUploadedDocument(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPInputFile &file,
|
||||
const std::optional<MTPInputFile> &thumb);
|
||||
|
||||
} // namespace Api
|
||||
@@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace Api {
|
||||
|
||||
SelfDestruct::SelfDestruct(not_null<ApiWrap*> api)
|
||||
: _api(api->instance()) {
|
||||
: _api(&api->instance()) {
|
||||
}
|
||||
|
||||
void SelfDestruct::reload() {
|
||||
|
||||
108
Telegram/SourceFiles/api/api_send_progress.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
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 "api/api_send_progress.h"
|
||||
|
||||
#include "main/main_session.h"
|
||||
#include "history/history.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
constexpr auto kCancelTypingActionTimeout = crl::time(5000);
|
||||
|
||||
} // namespace
|
||||
|
||||
SendProgressManager::SendProgressManager(not_null<Main::Session*> session)
|
||||
: _session(session)
|
||||
, _stopTypingTimer([=] { cancelTyping(base::take(_stopTypingHistory)); }) {
|
||||
}
|
||||
|
||||
void SendProgressManager::cancel(
|
||||
not_null<History*> history,
|
||||
SendProgressType type) {
|
||||
const auto i = _requests.find({ history, type });
|
||||
if (i != _requests.end()) {
|
||||
_session->api().request(i->second).cancel();
|
||||
_requests.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void SendProgressManager::cancelTyping(not_null<History*> history) {
|
||||
_stopTypingTimer.cancel();
|
||||
cancel(history, SendProgressType::Typing);
|
||||
}
|
||||
|
||||
void SendProgressManager::update(
|
||||
not_null<History*> history,
|
||||
SendProgressType type,
|
||||
int32 progress) {
|
||||
const auto peer = history->peer;
|
||||
if (peer->isSelf() || (peer->isChannel() && !peer->isMegagroup())) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto doing = (progress >= 0);
|
||||
if (history->mySendActionUpdated(type, doing)) {
|
||||
cancel(history, type);
|
||||
if (doing) {
|
||||
send(history, type, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendProgressManager::send(
|
||||
not_null<History*> history,
|
||||
SendProgressType type,
|
||||
int32 progress) {
|
||||
using Type = SendProgressType;
|
||||
const auto action = [&]() -> MTPsendMessageAction {
|
||||
const auto p = MTP_int(progress);
|
||||
switch (type) {
|
||||
case Type::Typing: return MTP_sendMessageTypingAction();
|
||||
case Type::RecordVideo: return MTP_sendMessageRecordVideoAction();
|
||||
case Type::UploadVideo: return MTP_sendMessageUploadVideoAction(p);
|
||||
case Type::RecordVoice: return MTP_sendMessageRecordAudioAction();
|
||||
case Type::UploadVoice: return MTP_sendMessageUploadAudioAction(p);
|
||||
case Type::RecordRound: return MTP_sendMessageRecordRoundAction();
|
||||
case Type::UploadRound: return MTP_sendMessageUploadRoundAction(p);
|
||||
case Type::UploadPhoto: return MTP_sendMessageUploadPhotoAction(p);
|
||||
case Type::UploadFile: return MTP_sendMessageUploadDocumentAction(p);
|
||||
case Type::ChooseLocation: return MTP_sendMessageGeoLocationAction();
|
||||
case Type::ChooseContact: return MTP_sendMessageChooseContactAction();
|
||||
case Type::PlayGame: return MTP_sendMessageGamePlayAction();
|
||||
default: return MTP_sendMessageTypingAction();
|
||||
}
|
||||
}();
|
||||
const auto requestId = _session->api().request(MTPmessages_SetTyping(
|
||||
history->peer->input,
|
||||
action
|
||||
)).done([=](const MTPBool &result, mtpRequestId requestId) {
|
||||
done(result, requestId);
|
||||
}).send();
|
||||
_requests.emplace(Key{ history, type }, requestId);
|
||||
|
||||
if (type == Type::Typing) {
|
||||
_stopTypingHistory = history;
|
||||
_stopTypingTimer.callOnce(kCancelTypingActionTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void SendProgressManager::done(
|
||||
const MTPBool &result,
|
||||
mtpRequestId requestId) {
|
||||
for (auto i = _requests.begin(), e = _requests.end(); i != e; ++i) {
|
||||
if (i->second == requestId) {
|
||||
_requests.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
88
Telegram/SourceFiles/api/api_send_progress.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
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 "api/api_common.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
class History;
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Api {
|
||||
|
||||
enum class SendProgressType {
|
||||
Typing,
|
||||
RecordVideo,
|
||||
UploadVideo,
|
||||
RecordVoice,
|
||||
UploadVoice,
|
||||
RecordRound,
|
||||
UploadRound,
|
||||
UploadPhoto,
|
||||
UploadFile,
|
||||
ChooseLocation,
|
||||
ChooseContact,
|
||||
PlayGame,
|
||||
};
|
||||
|
||||
struct SendProgress {
|
||||
SendProgress(
|
||||
SendProgressType type,
|
||||
crl::time until,
|
||||
int progress = 0)
|
||||
: type(type)
|
||||
, until(until)
|
||||
, progress(progress) {
|
||||
}
|
||||
SendProgressType type = SendProgressType::Typing;
|
||||
crl::time until = 0;
|
||||
int progress = 0;
|
||||
|
||||
};
|
||||
|
||||
class SendProgressManager final {
|
||||
public:
|
||||
SendProgressManager(not_null<Main::Session*> session);
|
||||
|
||||
void update(
|
||||
not_null<History*> history,
|
||||
SendProgressType type,
|
||||
int32 progress = 0);
|
||||
void cancel(
|
||||
not_null<History*> history,
|
||||
SendProgressType type);
|
||||
void cancelTyping(not_null<History*> history);
|
||||
|
||||
private:
|
||||
struct Key {
|
||||
not_null<History*> history;
|
||||
SendProgressType type = SendProgressType();
|
||||
|
||||
inline bool operator<(const Key &other) const {
|
||||
return (history < other.history)
|
||||
|| (history == other.history && type < other.type);
|
||||
}
|
||||
};
|
||||
|
||||
void send(
|
||||
not_null<History*> history,
|
||||
SendProgressType type,
|
||||
int32 progress);
|
||||
void done(const MTPBool &result, mtpRequestId requestId);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
base::flat_map<Key, mtpRequestId> _requests;
|
||||
base::Timer _stopTypingTimer;
|
||||
History *_stopTypingHistory = nullptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
||||
@@ -16,13 +16,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_message.h" // NewMessageFlags.
|
||||
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
|
||||
#include "ui/text/text_entity.h" // TextWithEntities.
|
||||
#include "ui/text_options.h" // Ui::ItemTextOptions.
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "mainwidget.h"
|
||||
#include "apiwrap.h"
|
||||
#include "app.h"
|
||||
@@ -124,8 +129,7 @@ void SendExistingMedia(
|
||||
caption,
|
||||
MTPReplyMarkup());
|
||||
|
||||
auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
|
||||
auto performRequest = [=] {
|
||||
auto performRequest = [=](const auto &repeatRequest) -> void {
|
||||
auto &histories = history->owner().histories();
|
||||
const auto requestType = Data::Histories::RequestType::Send;
|
||||
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||
@@ -144,32 +148,27 @@ void SendExistingMedia(
|
||||
api->applyUpdates(result, randomId);
|
||||
finish();
|
||||
}).fail([=](const RPCError &error) {
|
||||
(*failHandler)(error, usedFileReference);
|
||||
if (error.code() == 400
|
||||
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
|
||||
api->refreshFileReference(origin, [=](const auto &result) {
|
||||
if (media->fileReference() != usedFileReference) {
|
||||
repeatRequest(repeatRequest);
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
finish();
|
||||
}).afterRequest(history->sendRequestId
|
||||
).send();
|
||||
return history->sendRequestId;
|
||||
});
|
||||
};
|
||||
*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
|
||||
if (error.code() == 400
|
||||
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
|
||||
api->refreshFileReference(origin, [=](const auto &result) {
|
||||
if (media->fileReference() != usedFileReference) {
|
||||
performRequest();
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
}
|
||||
};
|
||||
performRequest();
|
||||
performRequest(performRequest);
|
||||
|
||||
if (const auto main = App::main()) {
|
||||
main->finishForwarding(message.action);
|
||||
}
|
||||
api->finishForwarding(message.action);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -190,10 +189,7 @@ void SendExistingDocument(
|
||||
document->stickerOrGifOrigin());
|
||||
|
||||
if (document->sticker()) {
|
||||
if (const auto main = App::main()) {
|
||||
main->incrementSticker(document);
|
||||
document->owner().notifyRecentStickersUpdated();
|
||||
}
|
||||
document->owner().stickers().incrementSticker(document);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +318,7 @@ bool SendDice(Api::MessageToSend &message) {
|
||||
).send();
|
||||
return history->sendRequestId;
|
||||
});
|
||||
api->finishForwarding(message.action);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -332,4 +329,209 @@ void FillMessagePostFlags(
|
||||
InnerFillMessagePostFlags(action.options, peer, flags);
|
||||
}
|
||||
|
||||
void SendConfirmedFile(
|
||||
not_null<Main::Session*> session,
|
||||
const std::shared_ptr<FileLoadResult> &file,
|
||||
const std::optional<FullMsgId> &oldId) {
|
||||
const auto isEditing = oldId.has_value();
|
||||
const auto channelId = peerToChannel(file->to.peer);
|
||||
|
||||
const auto newId = oldId.value_or(
|
||||
FullMsgId(channelId, session->data().nextLocalMessageId()));
|
||||
auto groupId = file->album ? file->album->groupId : uint64(0);
|
||||
if (file->album) {
|
||||
const auto proj = [](const SendingAlbum::Item &item) {
|
||||
return item.taskId;
|
||||
};
|
||||
const auto it = ranges::find(file->album->items, file->taskId, proj);
|
||||
Assert(it != file->album->items.end());
|
||||
|
||||
it->msgId = newId;
|
||||
}
|
||||
file->edit = isEditing;
|
||||
session->uploader().upload(newId, file);
|
||||
|
||||
const auto itemToEdit = isEditing
|
||||
? session->data().message(newId)
|
||||
: nullptr;
|
||||
|
||||
const auto history = session->data().history(file->to.peer);
|
||||
const auto peer = history->peer;
|
||||
|
||||
auto action = Api::SendAction(history);
|
||||
action.options = file->to.options;
|
||||
action.clearDraft = false;
|
||||
action.replyTo = file->to.replyTo;
|
||||
action.generateLocal = true;
|
||||
session->api().sendAction(action);
|
||||
|
||||
auto caption = TextWithEntities{
|
||||
file->caption.text,
|
||||
TextUtilities::ConvertTextTagsToEntities(file->caption.tags)
|
||||
};
|
||||
const auto prepareFlags = Ui::ItemTextOptions(
|
||||
history,
|
||||
session->user()).flags;
|
||||
TextUtilities::PrepareForSending(caption, prepareFlags);
|
||||
TextUtilities::Trim(caption);
|
||||
auto localEntities = Api::EntitiesToMTP(session, caption.entities);
|
||||
|
||||
if (itemToEdit) {
|
||||
if (const auto id = itemToEdit->groupId()) {
|
||||
groupId = id.value;
|
||||
}
|
||||
}
|
||||
|
||||
auto flags = (isEditing ? MTPDmessage::Flags() : NewMessageFlags(peer))
|
||||
| MTPDmessage::Flag::f_entities
|
||||
| MTPDmessage::Flag::f_media;
|
||||
auto clientFlags = NewMessageClientFlags();
|
||||
if (file->to.replyTo) {
|
||||
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
|
||||
}
|
||||
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
|
||||
const auto silentPost = file->to.options.silent;
|
||||
Api::FillMessagePostFlags(action, peer, flags);
|
||||
if (silentPost) {
|
||||
flags |= MTPDmessage::Flag::f_silent;
|
||||
}
|
||||
if (groupId) {
|
||||
flags |= MTPDmessage::Flag::f_grouped_id;
|
||||
}
|
||||
if (file->to.options.scheduled) {
|
||||
flags |= MTPDmessage::Flag::f_from_scheduled;
|
||||
// Scheduled messages have no the 'edited' badge.
|
||||
flags |= MTPDmessage::Flag::f_edit_hide;
|
||||
} else {
|
||||
clientFlags |= MTPDmessage_ClientFlag::f_local_history_entry;
|
||||
}
|
||||
|
||||
const auto messageFromId = channelPost ? 0 : session->userId();
|
||||
const auto messagePostAuthor = channelPost
|
||||
? session->user()->name
|
||||
: QString();
|
||||
|
||||
if (file->type == SendMediaType::Photo) {
|
||||
const auto photoFlags = MTPDmessageMediaPhoto::Flag::f_photo | 0;
|
||||
const auto photo = MTP_messageMediaPhoto(
|
||||
MTP_flags(photoFlags),
|
||||
file->photo,
|
||||
MTPint());
|
||||
|
||||
const auto mtpMessage = MTP_message(
|
||||
MTP_flags(flags),
|
||||
MTP_int(newId.msg),
|
||||
MTP_int(messageFromId),
|
||||
peerToMTP(file->to.peer),
|
||||
MTPMessageFwdHeader(),
|
||||
MTPint(),
|
||||
MTP_int(file->to.replyTo),
|
||||
MTP_int(HistoryItem::NewMessageDate(file->to.options.scheduled)),
|
||||
MTP_string(caption.text),
|
||||
photo,
|
||||
MTPReplyMarkup(),
|
||||
localEntities,
|
||||
MTP_int(1),
|
||||
MTPint(),
|
||||
MTP_string(messagePostAuthor),
|
||||
MTP_long(groupId),
|
||||
//MTPMessageReactions(),
|
||||
MTPVector<MTPRestrictionReason>());
|
||||
|
||||
if (itemToEdit) {
|
||||
itemToEdit->savePreviousMedia();
|
||||
itemToEdit->applyEdition(mtpMessage.c_message());
|
||||
} else {
|
||||
history->addNewMessage(
|
||||
mtpMessage,
|
||||
clientFlags,
|
||||
NewMessageType::Unread);
|
||||
}
|
||||
} else if (file->type == SendMediaType::File) {
|
||||
const auto documentFlags = MTPDmessageMediaDocument::Flag::f_document | 0;
|
||||
const auto document = MTP_messageMediaDocument(
|
||||
MTP_flags(documentFlags),
|
||||
file->document,
|
||||
MTPint());
|
||||
|
||||
const auto mtpMessage = MTP_message(
|
||||
MTP_flags(flags),
|
||||
MTP_int(newId.msg),
|
||||
MTP_int(messageFromId),
|
||||
peerToMTP(file->to.peer),
|
||||
MTPMessageFwdHeader(),
|
||||
MTPint(),
|
||||
MTP_int(file->to.replyTo),
|
||||
MTP_int(HistoryItem::NewMessageDate(file->to.options.scheduled)),
|
||||
MTP_string(caption.text),
|
||||
document,
|
||||
MTPReplyMarkup(),
|
||||
localEntities,
|
||||
MTP_int(1),
|
||||
MTPint(),
|
||||
MTP_string(messagePostAuthor),
|
||||
MTP_long(groupId),
|
||||
//MTPMessageReactions(),
|
||||
MTPVector<MTPRestrictionReason>());
|
||||
|
||||
if (itemToEdit) {
|
||||
itemToEdit->savePreviousMedia();
|
||||
itemToEdit->applyEdition(mtpMessage.c_message());
|
||||
} else {
|
||||
history->addNewMessage(
|
||||
mtpMessage,
|
||||
clientFlags,
|
||||
NewMessageType::Unread);
|
||||
}
|
||||
} else if (file->type == SendMediaType::Audio) {
|
||||
if (!peer->isChannel() || peer->isMegagroup()) {
|
||||
flags |= MTPDmessage::Flag::f_media_unread;
|
||||
}
|
||||
const auto documentFlags = MTPDmessageMediaDocument::Flag::f_document | 0;
|
||||
const auto document = MTP_messageMediaDocument(
|
||||
MTP_flags(documentFlags),
|
||||
file->document,
|
||||
MTPint());
|
||||
history->addNewMessage(
|
||||
MTP_message(
|
||||
MTP_flags(flags),
|
||||
MTP_int(newId.msg),
|
||||
MTP_int(messageFromId),
|
||||
peerToMTP(file->to.peer),
|
||||
MTPMessageFwdHeader(),
|
||||
MTPint(),
|
||||
MTP_int(file->to.replyTo),
|
||||
MTP_int(
|
||||
HistoryItem::NewMessageDate(file->to.options.scheduled)),
|
||||
MTP_string(caption.text),
|
||||
document,
|
||||
MTPReplyMarkup(),
|
||||
localEntities,
|
||||
MTP_int(1),
|
||||
MTPint(),
|
||||
MTP_string(messagePostAuthor),
|
||||
MTP_long(groupId),
|
||||
//MTPMessageReactions(),
|
||||
MTPVector<MTPRestrictionReason>()),
|
||||
clientFlags,
|
||||
NewMessageType::Unread);
|
||||
// Voices can't be edited.
|
||||
} else {
|
||||
Unexpected("Type in sendFilesConfirmed.");
|
||||
}
|
||||
|
||||
if (isEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
session->data().sendHistoryChangeNotifications();
|
||||
if (!itemToEdit) {
|
||||
session->changes().historyUpdated(
|
||||
history,
|
||||
(action.options.scheduled
|
||||
? Data::HistoryUpdate::Flag::ScheduledSent
|
||||
: Data::HistoryUpdate::Flag::MessageSent));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -10,10 +10,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
class History;
|
||||
class PhotoData;
|
||||
class DocumentData;
|
||||
struct FileLoadResult;
|
||||
|
||||
namespace Api {
|
||||
|
||||
struct MessageToSend;
|
||||
struct SendAction;
|
||||
|
||||
void SendExistingDocument(
|
||||
Api::MessageToSend &&message,
|
||||
@@ -30,4 +32,9 @@ void FillMessagePostFlags(
|
||||
not_null<PeerData*> peer,
|
||||
MTPDmessage::Flags &flags);
|
||||
|
||||
void SendConfirmedFile(
|
||||
not_null<Main::Session*> session,
|
||||
const std::shared_ptr<FileLoadResult> &file,
|
||||
const std::optional<FullMsgId> &oldId);
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -21,7 +21,7 @@ constexpr auto kRefreshAppConfigTimeout = 3 * crl::time(1000);
|
||||
|
||||
SensitiveContent::SensitiveContent(not_null<ApiWrap*> api)
|
||||
: _session(&api->session())
|
||||
, _api(api->instance())
|
||||
, _api(&api->instance())
|
||||
, _appConfigReloadTimer([=] { _session->account().appConfig().refresh(); }) {
|
||||
}
|
||||
|
||||
|
||||
2051
Telegram/SourceFiles/api/api_updates.cpp
Normal file
172
Telegram/SourceFiles/api/api_updates.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
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 "data/data_pts_waiter.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
class RPCError;
|
||||
class ApiWrap;
|
||||
class History;
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Api {
|
||||
|
||||
class Updates final {
|
||||
public:
|
||||
explicit Updates(not_null<Main::Session*> session);
|
||||
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
[[nodiscard]] ApiWrap &api() const;
|
||||
|
||||
void applyUpdates(
|
||||
const MTPUpdates &updates,
|
||||
uint64 sentMessageRandomId = 0);
|
||||
void applyUpdatesNoPtsCheck(const MTPUpdates &updates);
|
||||
void applyUpdateNoPtsCheck(const MTPUpdate &update);
|
||||
|
||||
void updateOnline();
|
||||
[[nodiscard]] bool isIdle() const;
|
||||
void checkIdleFinish();
|
||||
bool lastWasOnline() const;
|
||||
crl::time lastSetOnline() const;
|
||||
bool isQuitPrevent();
|
||||
|
||||
bool updateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates);
|
||||
bool updateAndApply(int32 pts, int32 ptsCount, const MTPUpdate &update);
|
||||
bool updateAndApply(int32 pts, int32 ptsCount);
|
||||
|
||||
void checkLastUpdate(bool afterSleep);
|
||||
|
||||
// ms <= 0 - stop timer
|
||||
void ptsWaiterStartTimerFor(ChannelData *channel, crl::time ms);
|
||||
|
||||
void getDifference();
|
||||
void requestChannelRangeDifference(not_null<History*> history);
|
||||
|
||||
void addActiveChat(rpl::producer<PeerData*> chat);
|
||||
|
||||
private:
|
||||
enum class ChannelDifferenceRequest {
|
||||
Unknown,
|
||||
PtsGapOrShortPoll,
|
||||
AfterFail,
|
||||
};
|
||||
|
||||
struct ActiveChatTracker {
|
||||
PeerData *peer = nullptr;
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
void channelRangeDifferenceSend(
|
||||
not_null<ChannelData*> channel,
|
||||
MsgRange range,
|
||||
int32 pts);
|
||||
void channelRangeDifferenceDone(
|
||||
not_null<ChannelData*> channel,
|
||||
MsgRange range,
|
||||
const MTPupdates_ChannelDifference &result);
|
||||
|
||||
void updateOnline(bool gotOtherOffline);
|
||||
void sendPing();
|
||||
void getDifferenceByPts();
|
||||
void getDifferenceAfterFail();
|
||||
|
||||
[[nodiscard]] bool requestingDifference() const {
|
||||
return _ptsWaiter.requesting();
|
||||
}
|
||||
void getChannelDifference(
|
||||
not_null<ChannelData*> channel,
|
||||
ChannelDifferenceRequest from = ChannelDifferenceRequest::Unknown);
|
||||
void differenceDone(const MTPupdates_Difference &result);
|
||||
void differenceFail(const RPCError &error);
|
||||
void feedDifference(
|
||||
const MTPVector<MTPUser> &users,
|
||||
const MTPVector<MTPChat> &chats,
|
||||
const MTPVector<MTPMessage> &msgs,
|
||||
const MTPVector<MTPUpdate> &other);
|
||||
void stateDone(const MTPupdates_State &state);
|
||||
void setState(int32 pts, int32 date, int32 qts, int32 seq);
|
||||
void channelDifferenceDone(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPupdates_ChannelDifference &diff);
|
||||
void channelDifferenceFail(
|
||||
not_null<ChannelData*> channel,
|
||||
const RPCError &error);
|
||||
void failDifferenceStartTimerFor(ChannelData *channel);
|
||||
void feedChannelDifference(const MTPDupdates_channelDifference &data);
|
||||
|
||||
void mtpUpdateReceived(const MTPUpdates &updates);
|
||||
void mtpNewSessionCreated();
|
||||
void feedUpdateVector(
|
||||
const MTPVector<MTPUpdate> &updates,
|
||||
bool skipMessageIds = false);
|
||||
// Doesn't call sendHistoryChangeNotifications itself.
|
||||
void feedMessageIds(const MTPVector<MTPUpdate> &updates);
|
||||
// Doesn't call sendHistoryChangeNotifications itself.
|
||||
void feedUpdate(const MTPUpdate &update);
|
||||
|
||||
bool whenGetDiffChanged(
|
||||
ChannelData *channel,
|
||||
int32 ms,
|
||||
base::flat_map<not_null<ChannelData*>, crl::time> &whenMap,
|
||||
crl::time &curTime);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
|
||||
int32 _updatesDate = 0;
|
||||
int32 _updatesQts = -1;
|
||||
int32 _updatesSeq = 0;
|
||||
base::Timer _noUpdatesTimer;
|
||||
base::Timer _onlineTimer;
|
||||
|
||||
PtsWaiter _ptsWaiter;
|
||||
|
||||
base::flat_map<not_null<ChannelData*>, crl::time> _whenGetDiffByPts;
|
||||
base::flat_map<not_null<ChannelData*>, crl::time> _whenGetDiffAfterFail;
|
||||
crl::time _getDifferenceTimeByPts = 0;
|
||||
crl::time _getDifferenceTimeAfterFail = 0;
|
||||
|
||||
base::Timer _byPtsTimer;
|
||||
|
||||
base::flat_map<int32, MTPUpdates> _bySeqUpdates;
|
||||
base::Timer _bySeqTimer;
|
||||
|
||||
base::Timer _byMinChannelTimer;
|
||||
|
||||
// growing timeout for getDifference calls, if it fails
|
||||
crl::time _failDifferenceTimeout = 1;
|
||||
// growing timeout for getChannelDifference calls, if it fails
|
||||
base::flat_map<
|
||||
not_null<ChannelData*>,
|
||||
crl::time> _channelFailDifferenceTimeout;
|
||||
base::Timer _failDifferenceTimer;
|
||||
|
||||
base::flat_map<
|
||||
not_null<ChannelData*>,
|
||||
mtpRequestId> _rangeDifferenceRequests;
|
||||
|
||||
crl::time _lastUpdateTime = 0;
|
||||
bool _handlingChannelDifference = false;
|
||||
|
||||
base::flat_map<int, ActiveChatTracker> _activeChats;
|
||||
|
||||
mtpRequestId _onlineRequest = 0;
|
||||
base::Timer _idleFinishTimer;
|
||||
crl::time _lastSetOnline = 0;
|
||||
bool _lastWasOnline = false;
|
||||
bool _isIdle = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
||||
@@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/flat_map.h"
|
||||
#include "base/flat_set.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "chat_helpers/stickers_set.h"
|
||||
#include "data/stickers/data_stickers_set.h"
|
||||
#include "data/data_messages.h"
|
||||
|
||||
class TaskQueue;
|
||||
@@ -38,6 +38,7 @@ namespace Storage {
|
||||
enum class SharedMediaType : signed char;
|
||||
struct PreparedList;
|
||||
class DownloadMtprotoTask;
|
||||
class Account;
|
||||
} // namespace Storage
|
||||
|
||||
namespace Dialogs {
|
||||
@@ -49,6 +50,12 @@ struct CloudPasswordState;
|
||||
} // namespace Core
|
||||
|
||||
namespace Api {
|
||||
|
||||
class Updates;
|
||||
class SelfDestruct;
|
||||
class SensitiveContent;
|
||||
class GlobalPrivacy;
|
||||
|
||||
namespace details {
|
||||
|
||||
inline QString ToString(const QString &value) {
|
||||
@@ -83,9 +90,6 @@ QString RequestKey(Types &&...values) {
|
||||
return result;
|
||||
}
|
||||
|
||||
class SelfDestruct;
|
||||
class SensitiveContent;
|
||||
|
||||
} // namespace Api
|
||||
|
||||
class ApiWrap : public MTP::Sender, private base::Subscriber {
|
||||
@@ -136,7 +140,9 @@ public:
|
||||
explicit ApiWrap(not_null<Main::Session*> session);
|
||||
~ApiWrap();
|
||||
|
||||
Main::Session &session() const;
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
[[nodiscard]] Storage::Account &local() const;
|
||||
[[nodiscard]] Api::Updates &updates() const;
|
||||
|
||||
void applyUpdates(
|
||||
const MTPUpdates &updates,
|
||||
@@ -152,6 +158,8 @@ public:
|
||||
MTPInputNotifyPeer peer,
|
||||
const MTPPeerNotifySettings &settings);
|
||||
|
||||
void saveCurrentDraftToCloud();
|
||||
|
||||
void savePinnedOrder(Data::Folder *folder);
|
||||
void toggleHistoryArchived(
|
||||
not_null<History*> history,
|
||||
@@ -192,7 +200,6 @@ public:
|
||||
void requestBots(not_null<ChannelData*> channel);
|
||||
void requestAdmins(not_null<ChannelData*> channel);
|
||||
void requestParticipantsCountDelayed(not_null<ChannelData*> channel);
|
||||
void requestChannelRangeDifference(not_null<History*> history);
|
||||
|
||||
using UpdatedFileReferences = Data::UpdatedFileReferences;
|
||||
using FileReferencesHandler = FnMut<void(const UpdatedFileReferences&)>;
|
||||
@@ -256,12 +263,11 @@ public:
|
||||
void clearWebPageRequest(WebPageData *page);
|
||||
void clearWebPageRequests();
|
||||
|
||||
void requestAttachedStickerSets(not_null<PhotoData*> photo);
|
||||
void scheduleStickerSetRequest(uint64 setId, uint64 access);
|
||||
void requestStickerSets();
|
||||
void saveStickerSets(
|
||||
const Stickers::Order &localOrder,
|
||||
const Stickers::Order &localRemoved);
|
||||
const Data::StickersSetsOrder &localOrder,
|
||||
const Data::StickersSetsOrder &localRemoved);
|
||||
void updateStickers();
|
||||
void requestRecentStickersForce();
|
||||
void setGroupStickerSet(
|
||||
@@ -308,9 +314,6 @@ public:
|
||||
|
||||
bool isQuitPrevent();
|
||||
|
||||
void applyUpdatesNoPtsCheck(const MTPUpdates &updates);
|
||||
void applyUpdateNoPtsCheck(const MTPUpdate &update);
|
||||
|
||||
void jumpToDate(Dialogs::Key chat, const QDate &date);
|
||||
|
||||
void preloadEnoughUnreadMentions(not_null<History*> history);
|
||||
@@ -366,11 +369,11 @@ public:
|
||||
not_null<PeerData*> peer,
|
||||
const std::vector<not_null<UserData*>> &users);
|
||||
|
||||
|
||||
rpl::producer<SendAction> sendActions() const {
|
||||
return _sendActions.events();
|
||||
}
|
||||
void sendAction(const SendAction &action);
|
||||
void finishForwarding(const SendAction &action);
|
||||
void forwardMessages(
|
||||
HistoryItemsList &&items,
|
||||
const SendAction &action,
|
||||
@@ -420,12 +423,6 @@ public:
|
||||
const MTPInputFile &file,
|
||||
const std::optional<MTPInputFile> &thumb,
|
||||
Api::SendOptions options);
|
||||
void editUploadedFile(
|
||||
FullMsgId localId,
|
||||
const MTPInputFile &file,
|
||||
const std::optional<MTPInputFile> &thumb,
|
||||
Api::SendOptions options,
|
||||
bool isDocument);
|
||||
|
||||
void cancelLocalItem(not_null<HistoryItem*> item);
|
||||
|
||||
@@ -464,6 +461,7 @@ public:
|
||||
|
||||
[[nodiscard]] Api::SelfDestruct &selfDestruct();
|
||||
[[nodiscard]] Api::SensitiveContent &sensitiveContent();
|
||||
[[nodiscard]] Api::GlobalPrivacy &globalPrivacy();
|
||||
|
||||
void createPoll(
|
||||
const PollData &data,
|
||||
@@ -476,10 +474,6 @@ public:
|
||||
void closePoll(not_null<HistoryItem*> item);
|
||||
void reloadPollResults(not_null<HistoryItem*> item);
|
||||
|
||||
void rescheduleMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
Api::SendOptions options);
|
||||
|
||||
private:
|
||||
struct MessageDataRequest {
|
||||
using Callbacks = QList<RequestMessageDataCallback>;
|
||||
@@ -552,15 +546,6 @@ private:
|
||||
mtpRequestId req);
|
||||
void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result);
|
||||
|
||||
void channelRangeDifferenceSend(
|
||||
not_null<ChannelData*> channel,
|
||||
MsgRange range,
|
||||
int32 pts);
|
||||
void channelRangeDifferenceDone(
|
||||
not_null<ChannelData*> channel,
|
||||
MsgRange range,
|
||||
const MTPupdates_ChannelDifference &result);
|
||||
|
||||
void stickerSetDisenabled(mtpRequestId requestId);
|
||||
void stickersSaveOrder();
|
||||
|
||||
@@ -707,10 +692,6 @@ private:
|
||||
|
||||
base::flat_set<not_null<ChannelData*>> _selfParticipantRequests;
|
||||
|
||||
base::flat_map<
|
||||
not_null<ChannelData*>,
|
||||
mtpRequestId> _rangeDifferenceRequests;
|
||||
|
||||
QMap<WebPageData*, mtpRequestId> _webPagesPending;
|
||||
base::Timer _webPagesTimer;
|
||||
|
||||
@@ -724,7 +705,7 @@ private:
|
||||
base::Timer _draftsSaveTimer;
|
||||
|
||||
base::flat_set<mtpRequestId> _stickerSetDisenableRequests;
|
||||
Stickers::Order _stickersOrder;
|
||||
Data::StickersSetsOrder _stickersOrder;
|
||||
mtpRequestId _stickersReorderRequestId = 0;
|
||||
mtpRequestId _stickersClearRecentRequestId = 0;
|
||||
|
||||
@@ -842,6 +823,7 @@ private:
|
||||
|
||||
const std::unique_ptr<Api::SelfDestruct> _selfDestruct;
|
||||
const std::unique_ptr<Api::SensitiveContent> _sensitiveContent;
|
||||
const std::unique_ptr<Api::GlobalPrivacy> _globalPrivacy;
|
||||
|
||||
base::flat_map<FullMsgId, mtpRequestId> _pollVotesRequestIds;
|
||||
base::flat_map<FullMsgId, mtpRequestId> _pollCloseRequestIds;
|
||||
@@ -856,8 +838,6 @@ private:
|
||||
std::optional<bool> _contactSignupSilent;
|
||||
rpl::event_stream<bool> _contactSignupSilentChanges;
|
||||
|
||||
mtpRequestId _attachedStickerSetsRequestId = 0;
|
||||
|
||||
base::flat_map<FullMsgId, QString> _unlikelyMessageLinks;
|
||||
|
||||
};
|
||||
|
||||
@@ -39,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "mainwidget.h"
|
||||
#include "apiwrap.h"
|
||||
#include "numbers.h"
|
||||
#include "observer_peer.h"
|
||||
#include "main/main_session.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_overview.h"
|
||||
@@ -75,8 +74,6 @@ using CornersMap = QMap<uint32, CornersPixmaps>;
|
||||
CornersMap cornersMap;
|
||||
QImage cornersMaskLarge[4], cornersMaskSmall[4];
|
||||
|
||||
int32 serviceImageCacheSize = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace App {
|
||||
@@ -207,16 +204,16 @@ namespace App {
|
||||
if (update.paletteChanged()) {
|
||||
createPaletteCorners();
|
||||
|
||||
if (App::main()) {
|
||||
App::main()->updateScrollColors();
|
||||
if (const auto m = App::main()) { // multi good
|
||||
m->updateScrollColors();
|
||||
}
|
||||
HistoryView::serviceColorsUpdated();
|
||||
} else if (update.type == Update::Type::New) {
|
||||
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
|
||||
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
|
||||
|
||||
if (App::main()) {
|
||||
App::main()->updateScrollColors();
|
||||
if (const auto m = App::main()) { // multi good
|
||||
m->updateScrollColors();
|
||||
}
|
||||
HistoryView::serviceColorsUpdated();
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ namespace App {
|
||||
void setLaunchState(LaunchState state);
|
||||
void restart();
|
||||
|
||||
constexpr auto kFileSizeLimit = 1500 * 1024 * 1024; // Load files up to 1500mb
|
||||
constexpr auto kImageSizeLimit = 64 * 1024 * 1024; // Open images up to 64mb jpg/png/gif
|
||||
QImage readImage(QByteArray data, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr);
|
||||
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0);
|
||||
|
||||
@@ -34,11 +34,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_cloud_file.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
#include "observer_peer.h"
|
||||
#include "main/main_session.h"
|
||||
#include "facades.h"
|
||||
#include "styles/style_layers.h"
|
||||
@@ -118,9 +118,11 @@ style::InputField CreateBioFieldStyle() {
|
||||
return result;
|
||||
}
|
||||
|
||||
QString PeerFloodErrorText(PeerFloodType type) {
|
||||
auto link = textcmdLink(
|
||||
Core::App().createInternalLinkFull(qsl("spambot")),
|
||||
QString PeerFloodErrorText(
|
||||
not_null<Main::Session*> session,
|
||||
PeerFloodType type) {
|
||||
const auto link = textcmdLink(
|
||||
session->createInternalLinkFull(qsl("spambot")),
|
||||
tr::lng_cant_more_info(tr::now));
|
||||
if (type == PeerFloodType::InviteGroup) {
|
||||
return tr::lng_cant_invite_not_contact(tr::now, lt_more_info, link);
|
||||
@@ -170,8 +172,7 @@ void ShowAddParticipantsError(
|
||||
return;
|
||||
}
|
||||
}
|
||||
const auto bot = ranges::find_if(users, &UserData::isBot);
|
||||
const auto hasBot = (bot != end(users));
|
||||
const auto hasBot = ranges::any_of(users, &UserData::isBot);
|
||||
const auto text = [&] {
|
||||
if (error == qstr("USER_BOT")) {
|
||||
return tr::lng_cant_invite_bot_to_channel(tr::now);
|
||||
@@ -190,10 +191,10 @@ void ShowAddParticipantsError(
|
||||
} else if (error == qstr("BOT_GROUPS_BLOCKED")) {
|
||||
return tr::lng_error_cant_add_bot(tr::now);
|
||||
} else if (error == qstr("PEER_FLOOD")) {
|
||||
const auto isGroup = (chat->isChat() || chat->isMegagroup());
|
||||
return PeerFloodErrorText(isGroup
|
||||
const auto type = (chat->isChat() || chat->isMegagroup())
|
||||
? PeerFloodType::InviteGroup
|
||||
: PeerFloodType::InviteChannel);
|
||||
: PeerFloodType::InviteChannel;
|
||||
return PeerFloodErrorText(&chat->session(), type);
|
||||
} else if (error == qstr("ADMINS_TOO_MUCH")) {
|
||||
return ((chat->isChat() || chat->isMegagroup())
|
||||
? tr::lng_error_admin_limit
|
||||
@@ -453,7 +454,7 @@ GroupInfoBox::GroupInfoBox(
|
||||
const QString &title,
|
||||
Fn<void(not_null<ChannelData*>)> channelDone)
|
||||
: _navigation(navigation)
|
||||
, _api(_navigation->session().api().instance())
|
||||
, _api(&_navigation->session().mtp())
|
||||
, _type(type)
|
||||
, _initialTitle(title)
|
||||
, _channelDone(std::move(channelDone)) {
|
||||
@@ -479,7 +480,7 @@ void GroupInfoBox::prepare() {
|
||||
_title->setMaxLength(kMaxGroupChannelTitle);
|
||||
_title->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
_title->setInstantReplacesEnabled(
|
||||
_navigation->session().settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
Ui::Emoji::SuggestionsController::Init(
|
||||
getDelegate()->outerContainer(),
|
||||
_title,
|
||||
@@ -495,8 +496,9 @@ void GroupInfoBox::prepare() {
|
||||
_description->setMaxLength(kMaxChannelDescription);
|
||||
_description->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
_description->setInstantReplacesEnabled(
|
||||
_navigation->session().settings().replaceEmojiValue());
|
||||
_description->setSubmitSettings(_navigation->session().settings().sendSubmitWay());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
_description->setSubmitSettings(
|
||||
Core::App().settings().sendSubmitWay());
|
||||
|
||||
connect(_description, &Ui::InputField::resized, [=] { descriptionResized(); });
|
||||
connect(_description, &Ui::InputField::submitted, [=] { submit(); });
|
||||
@@ -598,7 +600,9 @@ void GroupInfoBox::createGroup(
|
||||
} else if (error.type() == qstr("PEER_FLOOD")) {
|
||||
Ui::show(
|
||||
Box<InformBox>(
|
||||
PeerFloodErrorText(PeerFloodType::InviteGroup)),
|
||||
PeerFloodErrorText(
|
||||
&_navigation->session(),
|
||||
PeerFloodType::InviteGroup)),
|
||||
Ui::LayerOption::KeepOther);
|
||||
} else if (error.type() == qstr("USER_RESTRICTED")) {
|
||||
Ui::show(
|
||||
@@ -750,6 +754,7 @@ SetupChannelBox::SetupChannelBox(
|
||||
bool existing)
|
||||
: _navigation(navigation)
|
||||
, _channel(channel)
|
||||
, _api(&_channel->session().mtp())
|
||||
, _existing(existing)
|
||||
, _privacyGroup(
|
||||
std::make_shared<Ui::RadioenumGroup<Privacy>>(Privacy::Public))
|
||||
@@ -789,7 +794,12 @@ SetupChannelBox::SetupChannelBox(
|
||||
: tr::lng_create_private_channel_about)(tr::now),
|
||||
_defaultOptions,
|
||||
_aboutPublicWidth)
|
||||
, _link(this, st::setupChannelLink, nullptr, channel->username, true) {
|
||||
, _link(
|
||||
this,
|
||||
st::setupChannelLink,
|
||||
nullptr,
|
||||
channel->username,
|
||||
channel->session().createInternalLink(QString())) {
|
||||
}
|
||||
|
||||
void SetupChannelBox::prepare() {
|
||||
@@ -797,12 +807,12 @@ void SetupChannelBox::prepare() {
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
_checkRequestId = MTP::send(
|
||||
MTPchannels_CheckUsername(
|
||||
_channel->inputChannel,
|
||||
MTP_string("preston")),
|
||||
RPCDoneHandlerPtr(),
|
||||
rpcFail(&SetupChannelBox::onFirstCheckFail));
|
||||
_checkRequestId = _api.request(MTPchannels_CheckUsername(
|
||||
_channel->inputChannel,
|
||||
MTP_string("preston")
|
||||
)).fail([=](const RPCError &error) {
|
||||
firstCheckFail(error);
|
||||
}).send();
|
||||
|
||||
addButton(tr::lng_settings_save(), [=] { save(); });
|
||||
addButton(
|
||||
@@ -816,11 +826,13 @@ void SetupChannelBox::prepare() {
|
||||
connect(&_checkTimer, &QTimer::timeout, [=] { check(); });
|
||||
|
||||
_privacyGroup->setChangedCallback([this](Privacy value) { privacyChanged(value); });
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::InviteLinkChanged, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _channel) {
|
||||
rtlupdate(_invitationLink);
|
||||
}
|
||||
}));
|
||||
|
||||
_channel->session().changes().peerUpdates(
|
||||
_channel,
|
||||
Data::PeerUpdate::Flag::InviteLink
|
||||
) | rpl::start_with_next([=] {
|
||||
rtlupdate(_invitationLink);
|
||||
}, lifetime());
|
||||
|
||||
boxClosing() | rpl::start_with_next([=] {
|
||||
if (!_existing) {
|
||||
@@ -950,12 +962,22 @@ void SetupChannelBox::updateSelected(const QPoint &cursorGlobalPosition) {
|
||||
}
|
||||
|
||||
void SetupChannelBox::save() {
|
||||
const auto saveUsername = [&](const QString &link) {
|
||||
_sentUsername = link;
|
||||
_saveRequestId = _api.request(MTPchannels_UpdateUsername(
|
||||
_channel->inputChannel,
|
||||
MTP_string(_sentUsername)
|
||||
)).done([=](const MTPBool &result) {
|
||||
updateDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
updateFail(error);
|
||||
}).send();
|
||||
};
|
||||
if (_saveRequestId) {
|
||||
return;
|
||||
} else if (_privacyGroup->value() == Privacy::Private) {
|
||||
if (_existing) {
|
||||
_sentUsername = QString();
|
||||
_saveRequestId = MTP::send(MTPchannels_UpdateUsername(_channel->inputChannel, MTP_string(_sentUsername)), rpcDone(&SetupChannelBox::onUpdateDone), rpcFail(&SetupChannelBox::onUpdateFail));
|
||||
saveUsername(QString());
|
||||
} else {
|
||||
closeBox();
|
||||
}
|
||||
@@ -966,8 +988,7 @@ void SetupChannelBox::save() {
|
||||
_link->showError();
|
||||
return;
|
||||
}
|
||||
_sentUsername = link;
|
||||
_saveRequestId = MTP::send(MTPchannels_UpdateUsername(_channel->inputChannel, MTP_string(_sentUsername)), rpcDone(&SetupChannelBox::onUpdateDone), rpcFail(&SetupChannelBox::onUpdateFail));
|
||||
saveUsername(link);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1010,17 +1031,19 @@ void SetupChannelBox::handleChange() {
|
||||
|
||||
void SetupChannelBox::check() {
|
||||
if (_checkRequestId) {
|
||||
MTP::cancel(_checkRequestId);
|
||||
_channel->session().api().request(_checkRequestId).cancel();
|
||||
}
|
||||
QString link = _link->text().trimmed();
|
||||
if (link.size() >= kMinUsernameLength) {
|
||||
_checkUsername = link;
|
||||
_checkRequestId = MTP::send(
|
||||
MTPchannels_CheckUsername(
|
||||
_channel->inputChannel,
|
||||
MTP_string(link)),
|
||||
rpcDone(&SetupChannelBox::onCheckDone),
|
||||
rpcFail(&SetupChannelBox::onCheckFail));
|
||||
_checkRequestId = _api.request(MTPchannels_CheckUsername(
|
||||
_channel->inputChannel,
|
||||
MTP_string(link)
|
||||
)).done([=](const MTPBool &result) {
|
||||
checkDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
checkFail(error);
|
||||
}).send();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1053,38 +1076,36 @@ void SetupChannelBox::privacyChanged(Privacy value) {
|
||||
update();
|
||||
}
|
||||
|
||||
void SetupChannelBox::onUpdateDone(const MTPBool &result) {
|
||||
void SetupChannelBox::updateDone(const MTPBool &result) {
|
||||
_channel->setName(TextUtilities::SingleLine(_channel->name), _sentUsername);
|
||||
closeBox();
|
||||
}
|
||||
|
||||
bool SetupChannelBox::onUpdateFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
void SetupChannelBox::updateFail(const RPCError &error) {
|
||||
_saveRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == "USERNAME_NOT_MODIFIED" || _sentUsername == _channel->username) {
|
||||
_channel->setName(TextUtilities::SingleLine(_channel->name), TextUtilities::SingleLine(_sentUsername));
|
||||
if (err == "USERNAME_NOT_MODIFIED"
|
||||
|| _sentUsername == _channel->username) {
|
||||
_channel->setName(
|
||||
TextUtilities::SingleLine(_channel->name),
|
||||
TextUtilities::SingleLine(_sentUsername));
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == "USERNAME_INVALID") {
|
||||
_link->setFocus();
|
||||
_link->showError();
|
||||
_errorText = tr::lng_create_channel_link_invalid(tr::now);
|
||||
update();
|
||||
return true;
|
||||
} else if (err == "USERNAME_OCCUPIED" || err == "USERNAMES_UNAVAILABLE") {
|
||||
_link->setFocus();
|
||||
_link->showError();
|
||||
_errorText = tr::lng_create_channel_link_occupied(tr::now);
|
||||
update();
|
||||
return true;
|
||||
} else {
|
||||
_link->setFocus();
|
||||
}
|
||||
_link->setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetupChannelBox::onCheckDone(const MTPBool &result) {
|
||||
void SetupChannelBox::checkDone(const MTPBool &result) {
|
||||
_checkRequestId = 0;
|
||||
QString newError = (mtpIsTrue(result) || _checkUsername == _channel->username) ? QString() : tr::lng_create_channel_link_occupied(tr::now);
|
||||
QString newGood = newError.isEmpty() ? tr::lng_create_channel_link_available(tr::now) : QString();
|
||||
@@ -1095,14 +1116,11 @@ void SetupChannelBox::onCheckDone(const MTPBool &result) {
|
||||
}
|
||||
}
|
||||
|
||||
bool SetupChannelBox::onCheckFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
void SetupChannelBox::checkFail(const RPCError &error) {
|
||||
_checkRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == qstr("CHANNEL_PUBLIC_GROUP_NA")) {
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
} else if (err == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
|
||||
if (_existing) {
|
||||
showRevokePublicLinkBoxForEdit();
|
||||
@@ -1110,19 +1128,16 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
|
||||
_tooMuchUsernames = true;
|
||||
_privacyGroup->setValue(Privacy::Private);
|
||||
}
|
||||
return true;
|
||||
} else if (err == qstr("USERNAME_INVALID")) {
|
||||
_errorText = tr::lng_create_channel_link_invalid(tr::now);
|
||||
update();
|
||||
return true;
|
||||
} else if (err == qstr("USERNAME_OCCUPIED") && _checkUsername != _channel->username) {
|
||||
_errorText = tr::lng_create_channel_link_occupied(tr::now);
|
||||
update();
|
||||
return true;
|
||||
} else {
|
||||
_goodText = QString();
|
||||
_link->setFocus();
|
||||
}
|
||||
_goodText = QString();
|
||||
_link->setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetupChannelBox::showRevokePublicLinkBoxForEdit() {
|
||||
@@ -1142,14 +1157,11 @@ void SetupChannelBox::showRevokePublicLinkBoxForEdit() {
|
||||
Ui::LayerOption::KeepOther);
|
||||
}
|
||||
|
||||
bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
void SetupChannelBox::firstCheckFail(const RPCError &error) {
|
||||
_checkRequestId = 0;
|
||||
const auto &type = error.type();
|
||||
if (type == qstr("CHANNEL_PUBLIC_GROUP_NA")) {
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
} else if (type == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
|
||||
if (_existing) {
|
||||
showRevokePublicLinkBoxForEdit();
|
||||
@@ -1157,15 +1169,15 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
|
||||
_tooMuchUsernames = true;
|
||||
_privacyGroup->setValue(Privacy::Private);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
_goodText = QString();
|
||||
_link->setFocus();
|
||||
}
|
||||
_goodText = QString();
|
||||
_link->setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
EditNameBox::EditNameBox(QWidget*, not_null<UserData*> user)
|
||||
: _user(user)
|
||||
, _api(&_user->session().mtp())
|
||||
, _first(this, st::defaultInputField, tr::lng_signup_firstname(), _user->firstName)
|
||||
, _last(this, st::defaultInputField, tr::lng_signup_lastname(), _user->lastName)
|
||||
, _invertOrder(langFirstNameGoesSecond()) {
|
||||
@@ -1248,14 +1260,16 @@ void EditNameBox::save() {
|
||||
_sentName = first;
|
||||
auto flags = MTPaccount_UpdateProfile::Flag::f_first_name
|
||||
| MTPaccount_UpdateProfile::Flag::f_last_name;
|
||||
_requestId = MTP::send(
|
||||
MTPaccount_UpdateProfile(
|
||||
MTP_flags(flags),
|
||||
MTP_string(first),
|
||||
MTP_string(last),
|
||||
MTPstring()),
|
||||
rpcDone(&EditNameBox::saveSelfDone),
|
||||
rpcFail(&EditNameBox::saveSelfFail));
|
||||
_requestId = _api.request(MTPaccount_UpdateProfile(
|
||||
MTP_flags(flags),
|
||||
MTP_string(first),
|
||||
MTP_string(last),
|
||||
MTPstring()
|
||||
)).done([=](const MTPUser &result) {
|
||||
saveSelfDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
saveSelfFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void EditNameBox::saveSelfDone(const MTPUser &user) {
|
||||
@@ -1263,27 +1277,22 @@ void EditNameBox::saveSelfDone(const MTPUser &user) {
|
||||
closeBox();
|
||||
}
|
||||
|
||||
bool EditNameBox::saveSelfFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
void EditNameBox::saveSelfFail(const RPCError &error) {
|
||||
auto err = error.type();
|
||||
auto first = TextUtilities::SingleLine(_first->getLastText().trimmed());
|
||||
auto last = TextUtilities::SingleLine(_last->getLastText().trimmed());
|
||||
if (err == "NAME_NOT_MODIFIED") {
|
||||
_user->setName(first, last, QString(), TextUtilities::SingleLine(_user->username));
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == "FIRSTNAME_INVALID") {
|
||||
_first->setFocus();
|
||||
_first->showError();
|
||||
return true;
|
||||
} else if (err == "LASTNAME_INVALID") {
|
||||
_last->setFocus();
|
||||
_last->showError();
|
||||
return true;
|
||||
} else {
|
||||
_first->setFocus();
|
||||
}
|
||||
_first->setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
RevokePublicLinkBox::Inner::Inner(
|
||||
@@ -1292,7 +1301,7 @@ RevokePublicLinkBox::Inner::Inner(
|
||||
Fn<void()> revokeCallback)
|
||||
: TWidget(parent)
|
||||
, _session(session)
|
||||
, _api(_session->api().instance())
|
||||
, _api(&_session->mtp())
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _revokeWidth(st::normalFont->width(tr::lng_channels_too_much_public_revoke(tr::now)))
|
||||
, _revokeCallback(std::move(revokeCallback)) {
|
||||
@@ -1320,7 +1329,7 @@ RevokePublicLinkBox::Inner::Inner(
|
||||
Ui::NameTextOptions());
|
||||
row.status.setText(
|
||||
st::defaultTextStyle,
|
||||
Core::App().createInternalLink(
|
||||
_session->createInternalLink(
|
||||
textcmdLink(1, peer->userName())),
|
||||
Ui::DialogTextOptions());
|
||||
_rows.push_back(std::move(row));
|
||||
@@ -1355,7 +1364,10 @@ void RevokePublicLinkBox::prepare() {
|
||||
|
||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||
|
||||
subscribe(_session->downloaderTaskFinished(), [=] { update(); });
|
||||
_session->downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
|
||||
_inner->resizeToWidth(st::boxWideWidth);
|
||||
setDimensions(st::boxWideWidth, _innerTop + _inner->height());
|
||||
@@ -1401,7 +1413,7 @@ void RevokePublicLinkBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
auto text = text_method(
|
||||
tr::now,
|
||||
lt_link,
|
||||
Core::App().createInternalLink(pressed->userName()),
|
||||
_session->createInternalLink(pressed->userName()),
|
||||
lt_group,
|
||||
pressed->name);
|
||||
auto confirmText = tr::lng_channels_too_much_public_revoke(tr::now);
|
||||
|
||||
@@ -46,9 +46,11 @@ enum class PeerFloodType {
|
||||
InviteChannel,
|
||||
};
|
||||
|
||||
style::InputField CreateBioFieldStyle();
|
||||
[[nodiscard]] style::InputField CreateBioFieldStyle();
|
||||
|
||||
QString PeerFloodErrorText(PeerFloodType type);
|
||||
[[nodiscard]] QString PeerFloodErrorText(
|
||||
not_null<Main::Session*> session,
|
||||
PeerFloodType type);
|
||||
void ShowAddParticipantsError(
|
||||
const QString &error,
|
||||
not_null<PeerData*> chat,
|
||||
@@ -140,9 +142,8 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class SetupChannelBox
|
||||
class SetupChannelBox final
|
||||
: public Ui::BoxContent
|
||||
, public RPCSender
|
||||
, private base::Subscriber {
|
||||
public:
|
||||
SetupChannelBox(
|
||||
@@ -174,12 +175,12 @@ private:
|
||||
void check();
|
||||
void save();
|
||||
|
||||
void onUpdateDone(const MTPBool &result);
|
||||
bool onUpdateFail(const RPCError &error);
|
||||
void updateDone(const MTPBool &result);
|
||||
void updateFail(const RPCError &error);
|
||||
|
||||
void onCheckDone(const MTPBool &result);
|
||||
bool onCheckFail(const RPCError &error);
|
||||
bool onFirstCheckFail(const RPCError &error);
|
||||
void checkDone(const MTPBool &result);
|
||||
void checkFail(const RPCError &error);
|
||||
void firstCheckFail(const RPCError &error);
|
||||
|
||||
void updateMaxHeight();
|
||||
|
||||
@@ -187,6 +188,7 @@ private:
|
||||
|
||||
const not_null<Window::SessionNavigation*> _navigation;
|
||||
const not_null<ChannelData*> _channel;
|
||||
MTP::Sender _api;
|
||||
|
||||
bool _existing = false;
|
||||
|
||||
@@ -210,7 +212,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class EditNameBox : public Ui::BoxContent, public RPCSender {
|
||||
class EditNameBox : public Ui::BoxContent {
|
||||
public:
|
||||
EditNameBox(QWidget*, not_null<UserData*> user);
|
||||
|
||||
@@ -224,9 +226,10 @@ private:
|
||||
void submit();
|
||||
void save();
|
||||
void saveSelfDone(const MTPUser &user);
|
||||
bool saveSelfFail(const RPCError &error);
|
||||
void saveSelfFail(const RPCError &error);
|
||||
|
||||
not_null<UserData*> _user;
|
||||
const not_null<UserData*> _user;
|
||||
MTP::Sender _api;
|
||||
|
||||
object_ptr<Ui::InputField> _first;
|
||||
object_ptr<Ui::InputField> _last;
|
||||
@@ -238,9 +241,8 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class RevokePublicLinkBox
|
||||
class RevokePublicLinkBox final
|
||||
: public Ui::BoxContent
|
||||
, public RPCSender
|
||||
, private base::Subscriber {
|
||||
public:
|
||||
RevokePublicLinkBox(
|
||||
|
||||
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_session_settings.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_auto_download.h"
|
||||
#include "ui/widgets/continuous_sliders.h"
|
||||
@@ -96,9 +97,6 @@ void AutoDownloadBox::setupContent() {
|
||||
setTitle(tr::lng_profile_settings_section());
|
||||
|
||||
const auto settings = &_session->settings().autoDownload();
|
||||
const auto checked = [=](Source source, Type type) {
|
||||
return (settings->bytesLimit(source, type) > 0);
|
||||
};
|
||||
|
||||
auto wrap = object_ptr<Ui::VerticalLayout>(this);
|
||||
const auto content = wrap.data();
|
||||
@@ -171,26 +169,26 @@ void AutoDownloadBox::setupContent() {
|
||||
}) | ranges::view::transform([](Pair pair) {
|
||||
return pair.first;
|
||||
});
|
||||
const auto less = ranges::find_if(*autoPlayValues, [&](Pair pair) {
|
||||
const auto less = ranges::any_of(*autoPlayValues, [&](Pair pair) {
|
||||
const auto [type, enabled] = pair;
|
||||
const auto value = enabled ? limitByType(type) : 0;
|
||||
return value < settings->bytesLimit(_source, type);
|
||||
}) != end(*autoPlayValues);
|
||||
});
|
||||
const auto allowMoreTypes = base::flat_set<Type>(
|
||||
allowMore.begin(),
|
||||
allowMore.end());
|
||||
|
||||
const auto changed = ranges::find_if(values, [&](Pair pair) {
|
||||
const auto changed = ranges::any_of(values, [&](Pair pair) {
|
||||
const auto [type, enabled] = pair;
|
||||
const auto value = enabled ? limitByType(type) : 0;
|
||||
return value != settings->bytesLimit(_source, type);
|
||||
}) != end(values);
|
||||
});
|
||||
|
||||
const auto &kHidden = kStreamedTypes;
|
||||
const auto hiddenChanged = ranges::find_if(kHidden, [&](Type type) {
|
||||
const auto hiddenChanged = ranges::any_of(kHidden, [&](Type type) {
|
||||
const auto now = settings->bytesLimit(_source, type);
|
||||
return (now > 0) && (now != limitByType(type));
|
||||
}) != end(kHidden);
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
for (const auto [type, enabled] : values) {
|
||||
@@ -210,13 +208,12 @@ void AutoDownloadBox::setupContent() {
|
||||
}
|
||||
}
|
||||
if (changed || hiddenChanged) {
|
||||
Local::writeUserSettings();
|
||||
_session->saveSettingsDelayed();
|
||||
}
|
||||
if (allowMoreTypes.contains(Type::Photo)) {
|
||||
_session->data().photoLoadSettingsChanged();
|
||||
}
|
||||
if (ranges::find_if(allowMoreTypes, _1 != Type::Photo)
|
||||
!= allowMoreTypes.end()) {
|
||||
if (ranges::any_of(allowMoreTypes, _1 != Type::Photo)) {
|
||||
_session->data().documentLoadSettingsChanged();
|
||||
}
|
||||
if (less) {
|
||||
|
||||
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "core/application.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "facades.h"
|
||||
@@ -26,7 +27,8 @@ void AutoLockBox::prepare() {
|
||||
|
||||
auto options = { 60, 300, 3600, 18000 };
|
||||
|
||||
auto group = std::make_shared<Ui::RadiobuttonGroup>(Global::AutoLock());
|
||||
auto group = std::make_shared<Ui::RadiobuttonGroup>(
|
||||
Core::App().settings().autoLock());
|
||||
auto y = st::boxOptionListPadding.top() + st::autolockButton.margin.top();
|
||||
auto count = int(options.size());
|
||||
_options.reserve(count);
|
||||
@@ -41,10 +43,10 @@ void AutoLockBox::prepare() {
|
||||
}
|
||||
|
||||
void AutoLockBox::durationChanged(int seconds) {
|
||||
Global::SetAutoLock(seconds);
|
||||
Local::writeUserSettings();
|
||||
Core::App().settings().setAutoLock(seconds);
|
||||
Core::App().saveSettingsDelayed();
|
||||
Global::RefLocalPasscodeChanged().notify();
|
||||
|
||||
_session->checkAutoLock();
|
||||
Core::App().checkAutoLock();
|
||||
closeBox();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_document_media.h"
|
||||
#include "boxes/background_preview_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_overview.h"
|
||||
#include "styles/style_layers.h"
|
||||
@@ -131,8 +132,10 @@ private:
|
||||
|
||||
};
|
||||
|
||||
BackgroundBox::BackgroundBox(QWidget*, not_null<Main::Session*> session)
|
||||
: _session(session) {
|
||||
BackgroundBox::BackgroundBox(
|
||||
QWidget*,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: _controller(controller) {
|
||||
}
|
||||
|
||||
void BackgroundBox::prepare() {
|
||||
@@ -143,13 +146,13 @@ void BackgroundBox::prepare() {
|
||||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||
|
||||
_inner = setInnerWidget(
|
||||
object_ptr<Inner>(this, _session),
|
||||
object_ptr<Inner>(this, &_controller->session()),
|
||||
st::backgroundScroll);
|
||||
|
||||
_inner->chooseEvents(
|
||||
) | rpl::start_with_next([=](const Data::WallPaper &paper) {
|
||||
Ui::show(
|
||||
Box<BackgroundPreviewBox>(_session, paper),
|
||||
Box<BackgroundPreviewBox>(_controller, paper),
|
||||
Ui::LayerOption::KeepOther);
|
||||
}, _inner->lifetime());
|
||||
|
||||
@@ -161,7 +164,7 @@ void BackgroundBox::prepare() {
|
||||
|
||||
void BackgroundBox::removePaper(const Data::WallPaper &paper) {
|
||||
const auto box = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||
const auto session = _session;
|
||||
const auto session = &_controller->session();
|
||||
const auto remove = [=, weak = Ui::MakeWeak(this)]{
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
@@ -171,7 +174,7 @@ void BackgroundBox::removePaper(const Data::WallPaper &paper) {
|
||||
}
|
||||
session->data().removeWallpaper(paper);
|
||||
session->api().request(MTPaccount_SaveWallPaper(
|
||||
paper.mtpInput(),
|
||||
paper.mtpInput(session),
|
||||
MTP_bool(true),
|
||||
paper.mtpSettings()
|
||||
)).send();
|
||||
@@ -190,7 +193,7 @@ BackgroundBox::Inner::Inner(
|
||||
not_null<Main::Session*> session)
|
||||
: RpWidget(parent)
|
||||
, _session(session)
|
||||
, _api(_session->api().instance())
|
||||
, _api(&_session->mtp())
|
||||
, _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [=] { update(); })) {
|
||||
_check->setChecked(true, anim::type::instant);
|
||||
if (_session->data().wallpapers().empty()) {
|
||||
@@ -200,7 +203,10 @@ BackgroundBox::Inner::Inner(
|
||||
}
|
||||
requestPapers();
|
||||
|
||||
subscribe(_session->downloaderTaskFinished(), [=] { update(); });
|
||||
_session->downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
using Update = Window::Theme::BackgroundUpdate;
|
||||
subscribe(Window::Theme::Background(), [=](const Update &update) {
|
||||
if (update.paletteChanged()) {
|
||||
|
||||
@@ -9,9 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Data {
|
||||
class WallPaper;
|
||||
@@ -19,7 +19,7 @@ class WallPaper;
|
||||
|
||||
class BackgroundBox : public Ui::BoxContent {
|
||||
public:
|
||||
BackgroundBox(QWidget*, not_null<Main::Session*> session);
|
||||
BackgroundBox(QWidget*, not_null<Window::SessionController*> controller);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
@@ -29,7 +29,7 @@ private:
|
||||
|
||||
void removePaper(const Data::WallPaper &paper);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
|
||||
QPointer<Inner> _inner;
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/unixtime.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/background_preview_box.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_layers.h"
|
||||
@@ -270,14 +271,14 @@ bool ServiceCheck::checkRippleStartPosition(QPoint position) const {
|
||||
if (slug.isEmpty() || slug.size() > kMaxWallPaperSlugLength) {
|
||||
return false;
|
||||
}
|
||||
return ranges::find_if(slug, [](QChar ch) {
|
||||
return ranges::none_of(slug, [](QChar ch) {
|
||||
return (ch != '.')
|
||||
&& (ch != '_')
|
||||
&& (ch != '-')
|
||||
&& (ch < '0' || ch > '9')
|
||||
&& (ch < 'a' || ch > 'z')
|
||||
&& (ch < 'A' || ch > 'Z');
|
||||
}) == slug.end();
|
||||
});
|
||||
}
|
||||
|
||||
AdminLog::OwnedItem GenerateTextItem(
|
||||
@@ -347,7 +348,6 @@ QImage ColorizePattern(QImage image, QColor color) {
|
||||
const auto height = image.height();
|
||||
const auto pattern = anim::shifted(color);
|
||||
|
||||
const auto resultBytesPerPixel = (image.depth() >> 3);
|
||||
constexpr auto resultIntsPerPixel = 1;
|
||||
const auto resultIntsPerLine = (image.bytesPerLine() >> 2);
|
||||
const auto resultIntsAdded = resultIntsPerLine - width * resultIntsPerPixel;
|
||||
@@ -396,18 +396,19 @@ QImage PrepareScaledFromFull(
|
||||
|
||||
BackgroundPreviewBox::BackgroundPreviewBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const Data::WallPaper &paper)
|
||||
: _session(session)
|
||||
: SimpleElementDelegate(controller)
|
||||
, _controller(controller)
|
||||
, _text1(GenerateTextItem(
|
||||
delegate(),
|
||||
_session->data().history(
|
||||
_controller->session().data().history(
|
||||
peerFromUser(PeerData::kServiceNotificationsId)),
|
||||
tr::lng_background_text1(tr::now),
|
||||
false))
|
||||
, _text2(GenerateTextItem(
|
||||
delegate(),
|
||||
_session->data().history(
|
||||
_controller->session().data().history(
|
||||
peerFromUser(PeerData::kServiceNotificationsId)),
|
||||
tr::lng_background_text2(tr::now),
|
||||
true))
|
||||
@@ -417,7 +418,10 @@ BackgroundPreviewBox::BackgroundPreviewBox(
|
||||
if (_media) {
|
||||
_media->thumbnailWanted(_paper.fileOrigin());
|
||||
}
|
||||
subscribe(_session->downloaderTaskFinished(), [=] { update(); });
|
||||
_controller->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
not_null<HistoryView::ElementDelegate*> BackgroundPreviewBox::delegate() {
|
||||
@@ -500,10 +504,10 @@ void BackgroundPreviewBox::createBlurCheckbox() {
|
||||
void BackgroundPreviewBox::apply() {
|
||||
const auto install = (_paper.id() != Window::Theme::Background()->id())
|
||||
&& Data::IsCloudWallPaper(_paper);
|
||||
App::main()->setChatBackground(_paper, std::move(_full));
|
||||
_controller->content()->setChatBackground(_paper, std::move(_full));
|
||||
if (install) {
|
||||
_session->api().request(MTPaccount_InstallWallPaper(
|
||||
_paper.mtpInput(),
|
||||
_controller->session().api().request(MTPaccount_InstallWallPaper(
|
||||
_paper.mtpInput(&_controller->session()),
|
||||
_paper.mtpSettings()
|
||||
)).send();
|
||||
}
|
||||
@@ -511,7 +515,8 @@ void BackgroundPreviewBox::apply() {
|
||||
}
|
||||
|
||||
void BackgroundPreviewBox::share() {
|
||||
QGuiApplication::clipboard()->setText(_paper.shareUrl());
|
||||
QGuiApplication::clipboard()->setText(
|
||||
_paper.shareUrl(&_controller->session()));
|
||||
Ui::Toast::Show(tr::lng_background_link_copied(tr::now));
|
||||
}
|
||||
|
||||
@@ -738,7 +743,6 @@ void BackgroundPreviewBox::checkLoadedDocument() {
|
||||
guard = _generating.make_guard()
|
||||
]() mutable {
|
||||
auto scaled = PrepareScaledFromFull(image, patternBackground);
|
||||
const auto ms = crl::now();
|
||||
auto blurred = patternBackground
|
||||
? QImage()
|
||||
: PrepareScaledNonPattern(
|
||||
@@ -763,12 +767,12 @@ void BackgroundPreviewBox::checkLoadedDocument() {
|
||||
}
|
||||
|
||||
bool BackgroundPreviewBox::Start(
|
||||
not_null<Main::Session*> session,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &slug,
|
||||
const QMap<QString, QString> ¶ms) {
|
||||
if (const auto paper = Data::WallPaper::FromColorSlug(slug)) {
|
||||
Ui::show(Box<BackgroundPreviewBox>(
|
||||
session,
|
||||
controller,
|
||||
paper->withUrlParams(params)));
|
||||
return true;
|
||||
}
|
||||
@@ -776,11 +780,12 @@ bool BackgroundPreviewBox::Start(
|
||||
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
|
||||
return false;
|
||||
}
|
||||
session->api().requestWallPaper(slug, [=](const Data::WallPaper &result) {
|
||||
controller->session().api().requestWallPaper(slug, crl::guard(controller, [=](
|
||||
const Data::WallPaper &result) {
|
||||
Ui::show(Box<BackgroundPreviewBox>(
|
||||
session,
|
||||
controller,
|
||||
result.withUrlParams(params)));
|
||||
}, [](const RPCError &error) {
|
||||
}), [](const RPCError &error) {
|
||||
Ui::show(Box<InformBox>(tr::lng_background_bad_link(tr::now)));
|
||||
});
|
||||
return true;
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Data {
|
||||
class DocumentMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Ui {
|
||||
class Checkbox;
|
||||
@@ -34,11 +34,11 @@ class BackgroundPreviewBox
|
||||
public:
|
||||
BackgroundPreviewBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const Data::WallPaper &paper);
|
||||
|
||||
static bool Start(
|
||||
not_null<Main::Session*> session,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const QString &slug,
|
||||
const QMap<QString, QString> ¶ms);
|
||||
|
||||
@@ -71,7 +71,7 @@ private:
|
||||
void startFadeInFrom(QPixmap previous);
|
||||
void checkBlurAnimationStart();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
AdminLog::OwnedItem _text1;
|
||||
AdminLog::OwnedItem _text2;
|
||||
Data::WallPaper _paper;
|
||||
|
||||
@@ -94,7 +94,6 @@ confirmInviteTitle: FlatLabel(defaultFlatLabel) {
|
||||
confirmInviteStatus: FlatLabel(boxLabel) {
|
||||
align: align(center);
|
||||
minWidth: 320px;
|
||||
maxHeight: 20px;
|
||||
textFg: windowSubTextFg;
|
||||
}
|
||||
confirmInviteTitleTop: 106px;
|
||||
|
||||
@@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "boxes/calendar_box.h"
|
||||
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
@@ -123,8 +122,6 @@ void CalendarBox::Context::applyMonth(const QDate &month, bool forced) {
|
||||
_daysCount = month.daysInMonth();
|
||||
_daysShift = daysShiftForMonth(month);
|
||||
_rowsCount = rowsCountForMonth(month);
|
||||
auto yearIndex = month.year();
|
||||
auto monthIndex = month.month();
|
||||
_highlightedIndex = month.daysTo(_highlighted);
|
||||
_minDayIndex = _min.isNull() ? INT_MIN : month.daysTo(_min);
|
||||
_maxDayIndex = _max.isNull() ? INT_MAX : month.daysTo(_max);
|
||||
@@ -199,7 +196,7 @@ QString CalendarBox::Context::labelFromIndex(int index) const {
|
||||
return QString::number(day());
|
||||
}
|
||||
|
||||
class CalendarBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
||||
class CalendarBox::Inner : public TWidget, private base::Subscriber {
|
||||
public:
|
||||
Inner(
|
||||
QWidget *parent,
|
||||
@@ -303,7 +300,6 @@ int CalendarBox::Inner::rowsTop() const {
|
||||
|
||||
void CalendarBox::Inner::paintRows(Painter &p, QRect clip) {
|
||||
p.setFont(st::calendarDaysFont);
|
||||
auto ms = crl::now();
|
||||
auto y = rowsTop();
|
||||
auto index = -_context->daysShift();
|
||||
auto highlightedIndex = _context->highlightedIndex();
|
||||
|
||||
@@ -19,7 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "mtproto/facade.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "apiwrap.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
@@ -76,14 +77,15 @@ protected:
|
||||
|
||||
private:
|
||||
void submit();
|
||||
void sendPhoneDone(const QString &phoneNumber, const MTPauth_SentCode &result);
|
||||
bool sendPhoneFail(const QString &phoneNumber, const RPCError &error);
|
||||
void sendPhoneDone(const MTPauth_SentCode &result, const QString &phoneNumber);
|
||||
void sendPhoneFail(const RPCError &error, const QString &phoneNumber);
|
||||
void showError(const QString &text);
|
||||
void hideError() {
|
||||
showError(QString());
|
||||
}
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
|
||||
object_ptr<Ui::PhoneInput> _phone = { nullptr };
|
||||
object_ptr<Ui::FadeWrap<Ui::FlatLabel>> _error = { nullptr };
|
||||
@@ -112,7 +114,7 @@ private:
|
||||
void submit();
|
||||
void sendCall();
|
||||
void updateCall();
|
||||
bool sendCodeFail(const RPCError &error);
|
||||
void sendCodeFail(const RPCError &error);
|
||||
void showError(const QString &text);
|
||||
void hideError() {
|
||||
showError(QString());
|
||||
@@ -120,6 +122,7 @@ private:
|
||||
int countHeight();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
|
||||
QString _phone;
|
||||
QString _hash;
|
||||
@@ -136,7 +139,8 @@ private:
|
||||
ChangePhoneBox::EnterPhone::EnterPhone(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session)
|
||||
: _session(session) {
|
||||
: _session(session)
|
||||
, _api(&session->mtp()) {
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterPhone::prepare() {
|
||||
@@ -171,20 +175,19 @@ void ChangePhoneBox::EnterPhone::submit() {
|
||||
hideError();
|
||||
|
||||
auto phoneNumber = _phone->getLastText().trimmed();
|
||||
_requestId = MTP::send(
|
||||
MTPaccount_SendChangePhoneCode(
|
||||
MTP_string(phoneNumber),
|
||||
MTP_codeSettings(MTP_flags(0))),
|
||||
rpcDone(crl::guard(this, [=](
|
||||
const MTPauth_SentCode &result) {
|
||||
return sendPhoneDone(phoneNumber, result);
|
||||
})), rpcFail(crl::guard(this, [=](
|
||||
const RPCError &error) {
|
||||
return sendPhoneFail(phoneNumber, error);
|
||||
})));
|
||||
_requestId = _api.request(MTPaccount_SendChangePhoneCode(
|
||||
MTP_string(phoneNumber),
|
||||
MTP_codeSettings(MTP_flags(0))
|
||||
)).done([=](const MTPauth_SentCode &result) {
|
||||
sendPhoneDone(result, phoneNumber);
|
||||
}).fail([=](const RPCError &error) {
|
||||
sendPhoneFail(error, phoneNumber);
|
||||
}).handleFloodErrors().send();
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterPhone::sendPhoneDone(const QString &phoneNumber, const MTPauth_SentCode &result) {
|
||||
void ChangePhoneBox::EnterPhone::sendPhoneDone(
|
||||
const MTPauth_SentCode &result,
|
||||
const QString &phoneNumber) {
|
||||
Expects(result.type() == mtpc_auth_sentCode);
|
||||
_requestId = 0;
|
||||
|
||||
@@ -219,18 +222,14 @@ void ChangePhoneBox::EnterPhone::sendPhoneDone(const QString &phoneNumber, const
|
||||
Ui::LayerOption::KeepOther);
|
||||
}
|
||||
|
||||
bool ChangePhoneBox::EnterPhone::sendPhoneFail(const QString &phoneNumber, const RPCError &error) {
|
||||
auto errorText = Lang::Hard::ServerError();
|
||||
void ChangePhoneBox::EnterPhone::sendPhoneFail(const RPCError &error, const QString &phoneNumber) {
|
||||
_requestId = 0;
|
||||
if (MTP::isFloodError(error)) {
|
||||
errorText = tr::lng_flood_error(tr::now);
|
||||
} else if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
showError(tr::lng_flood_error(tr::now));
|
||||
} else if (error.type() == qstr("PHONE_NUMBER_INVALID")) {
|
||||
errorText = tr::lng_bad_phone(tr::now);
|
||||
showError(tr::lng_bad_phone(tr::now));
|
||||
} else if (error.type() == qstr("PHONE_NUMBER_BANNED")) {
|
||||
ShowPhoneBannedError(phoneNumber);
|
||||
_requestId = 0;
|
||||
return true;
|
||||
} else if (error.type() == qstr("PHONE_NUMBER_OCCUPIED")) {
|
||||
Ui::show(Box<InformBox>(
|
||||
tr::lng_change_phone_occupied(
|
||||
@@ -238,12 +237,9 @@ bool ChangePhoneBox::EnterPhone::sendPhoneFail(const QString &phoneNumber, const
|
||||
lt_phone,
|
||||
App::formatPhone(phoneNumber)),
|
||||
tr::lng_box_ok(tr::now)));
|
||||
_requestId = 0;
|
||||
return true;
|
||||
} else {
|
||||
showError(Lang::Hard::ServerError());
|
||||
}
|
||||
showError(errorText);
|
||||
_requestId = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterPhone::showError(const QString &text) {
|
||||
@@ -261,6 +257,7 @@ ChangePhoneBox::EnterCode::EnterCode(
|
||||
int codeLength,
|
||||
int callTimeout)
|
||||
: _session(session)
|
||||
, _api(&session->mtp())
|
||||
, _phone(phone)
|
||||
, _hash(hash)
|
||||
, _codeLength(codeLength)
|
||||
@@ -313,25 +310,28 @@ void ChangePhoneBox::EnterCode::submit() {
|
||||
const auto session = _session;
|
||||
const auto code = _code->getDigitsOnly();
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
_requestId = MTP::send(MTPaccount_ChangePhone(
|
||||
_requestId = session->api().request(MTPaccount_ChangePhone(
|
||||
MTP_string(_phone),
|
||||
MTP_string(_hash),
|
||||
MTP_string(code)
|
||||
), rpcDone([=](const MTPUser &result) {
|
||||
)).done([=](const MTPUser &result) {
|
||||
session->data().processUser(result);
|
||||
if (weak) {
|
||||
Ui::hideLayer();
|
||||
}
|
||||
Ui::Toast::Show(tr::lng_change_phone_success(tr::now));
|
||||
}), rpcFail(crl::guard(this, [this](const RPCError &error) {
|
||||
return sendCodeFail(error);
|
||||
})));
|
||||
}).fail(crl::guard(this, [=](const RPCError &error) {
|
||||
sendCodeFail(error);
|
||||
})).handleFloodErrors().send();
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterCode::sendCall() {
|
||||
MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_hash)), rpcDone(crl::guard(this, [this] {
|
||||
_api.request(MTPauth_ResendCode(
|
||||
MTP_string(_phone),
|
||||
MTP_string(_hash)
|
||||
)).done([=](const MTPauth_SentCode &result) {
|
||||
_call.callDone();
|
||||
})));
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ChangePhoneBox::EnterCode::updateCall() {
|
||||
@@ -354,25 +354,20 @@ void ChangePhoneBox::EnterCode::showError(const QString &text) {
|
||||
}
|
||||
}
|
||||
|
||||
bool ChangePhoneBox::EnterCode::sendCodeFail(const RPCError &error) {
|
||||
auto errorText = Lang::Hard::ServerError();
|
||||
void ChangePhoneBox::EnterCode::sendCodeFail(const RPCError &error) {
|
||||
_requestId = 0;
|
||||
if (MTP::isFloodError(error)) {
|
||||
errorText = tr::lng_flood_error(tr::now);
|
||||
} else if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
showError(tr::lng_flood_error(tr::now));
|
||||
} else if (error.type() == qstr("PHONE_CODE_EMPTY") || error.type() == qstr("PHONE_CODE_INVALID")) {
|
||||
errorText = tr::lng_bad_code(tr::now);
|
||||
showError(tr::lng_bad_code(tr::now));
|
||||
} else if (error.type() == qstr("PHONE_CODE_EXPIRED")
|
||||
|| error.type() == qstr("PHONE_NUMBER_BANNED")) {
|
||||
closeBox(); // Go back to phone input.
|
||||
_requestId = 0;
|
||||
return true;
|
||||
} else if (error.type() == qstr("PHONE_NUMBER_INVALID")) {
|
||||
errorText = tr::lng_bad_phone(tr::now);
|
||||
showError(tr::lng_bad_phone(tr::now));
|
||||
} else {
|
||||
showError(Lang::Hard::ServerError());
|
||||
}
|
||||
_requestId = 0;
|
||||
showError(errorText);
|
||||
return true;
|
||||
}
|
||||
|
||||
ChangePhoneBox::ChangePhoneBox(QWidget*, not_null<Main::Session*> session)
|
||||
|
||||
@@ -33,10 +33,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_photo_media.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "main/main_session.h"
|
||||
#include "observer_peer.h"
|
||||
#include "facades.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
#include "facades.h" // Ui::showChatsList
|
||||
#include "app.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
@@ -351,7 +352,7 @@ MaxInviteBox::MaxInviteBox(QWidget*, not_null<ChannelData*> channel) : BoxConten
|
||||
tr::lng_participant_invite_sorry(
|
||||
tr::now,
|
||||
lt_count,
|
||||
Global::ChatSizeMax()),
|
||||
channel->session().serverConfig().chatSizeMax),
|
||||
kInformBoxTextOptions,
|
||||
(st::boxWidth
|
||||
- st::boxPadding.left()
|
||||
@@ -367,11 +368,12 @@ void MaxInviteBox::prepare() {
|
||||
_textHeight = qMin(_text.countHeight(_textWidth), 16 * st::boxLabelStyle.lineHeight);
|
||||
setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom());
|
||||
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::InviteLinkChanged, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == _channel) {
|
||||
rtlupdate(_invitationLink);
|
||||
}
|
||||
}));
|
||||
_channel->session().changes().peerUpdates(
|
||||
_channel,
|
||||
Data::PeerUpdate::Flag::InviteLink
|
||||
) | rpl::start_with_next([=] {
|
||||
rtlupdate(_invitationLink);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) {
|
||||
@@ -432,6 +434,7 @@ PinMessageBox::PinMessageBox(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId msgId)
|
||||
: _peer(peer)
|
||||
, _api(&peer->session().mtp())
|
||||
, _msgId(msgId)
|
||||
, _text(this, tr::lng_pinned_pin_sure(tr::now), st::boxLabel) {
|
||||
}
|
||||
@@ -474,24 +477,16 @@ void PinMessageBox::pinMessage() {
|
||||
if (_notify && !_notify->checked()) {
|
||||
flags |= MTPmessages_UpdatePinnedMessage::Flag::f_silent;
|
||||
}
|
||||
_requestId = MTP::send(
|
||||
MTPmessages_UpdatePinnedMessage(
|
||||
MTP_flags(flags),
|
||||
_peer->input,
|
||||
MTP_int(_msgId)),
|
||||
rpcDone(&PinMessageBox::pinDone),
|
||||
rpcFail(&PinMessageBox::pinFail));
|
||||
}
|
||||
|
||||
void PinMessageBox::pinDone(const MTPUpdates &updates) {
|
||||
_peer->session().api().applyUpdates(updates);
|
||||
Ui::hideLayer();
|
||||
}
|
||||
|
||||
bool PinMessageBox::pinFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
_requestId = _api.request(MTPmessages_UpdatePinnedMessage(
|
||||
MTP_flags(flags),
|
||||
_peer->input,
|
||||
MTP_int(_msgId)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_peer->session().api().applyUpdates(result);
|
||||
Ui::hideLayer();
|
||||
}).fail([=](const RPCError &error) {
|
||||
Ui::hideLayer();
|
||||
}).send();
|
||||
}
|
||||
|
||||
DeleteMessagesBox::DeleteMessagesBox(
|
||||
@@ -683,10 +678,7 @@ auto DeleteMessagesBox::revokeText(not_null<PeerData*> peer) const
|
||||
const auto cannotRevoke = [&](HistoryItem *item) {
|
||||
return !item->canDeleteForEveryone(now);
|
||||
};
|
||||
const auto canRevokeAll = ranges::find_if(
|
||||
items,
|
||||
cannotRevoke
|
||||
) == end(items);
|
||||
const auto canRevokeAll = ranges::none_of(items, cannotRevoke);
|
||||
auto outgoing = items | ranges::view::filter(&HistoryItem::out);
|
||||
const auto canRevokeOutgoingCount = canRevokeAll
|
||||
? -1
|
||||
@@ -775,9 +767,10 @@ void DeleteMessagesBox::deleteAndClear() {
|
||||
if (justClear) {
|
||||
peer->session().api().clearHistory(peer, revoke);
|
||||
} else {
|
||||
const auto controller = App::wnd()->sessionController();
|
||||
if (controller->activeChatCurrent().peer() == peer) {
|
||||
Ui::showChatsList();
|
||||
for (const auto controller : peer->session().windows()) {
|
||||
if (controller->activeChatCurrent().peer() == peer) {
|
||||
Ui::showChatsList(&peer->session());
|
||||
}
|
||||
}
|
||||
// Don't delete old history by default,
|
||||
// because Android app doesn't.
|
||||
@@ -847,8 +840,8 @@ void DeleteMessagesBox::deleteAndClear() {
|
||||
peer->session().api().request(MTPmessages_DeleteScheduledMessages(
|
||||
peer->input,
|
||||
MTP_vector<MTPint>(ids)
|
||||
)).done([=, peer=peer](const MTPUpdates &updates) {
|
||||
peer->session().api().applyUpdates(updates);
|
||||
)).done([peer=peer](const MTPUpdates &result) {
|
||||
peer->session().api().applyUpdates(result);
|
||||
}).send();
|
||||
}
|
||||
|
||||
@@ -868,145 +861,6 @@ void DeleteMessagesBox::deleteAndClear() {
|
||||
session->data().sendHistoryChangeNotifications();
|
||||
}
|
||||
|
||||
ConfirmInviteBox::ConfirmInviteBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data,
|
||||
Fn<void()> submit)
|
||||
: _session(session)
|
||||
, _submit(std::move(submit))
|
||||
, _title(this, st::confirmInviteTitle)
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _participants(GetParticipants(_session, data))
|
||||
, _isChannel(data.is_channel() && !data.is_megagroup()) {
|
||||
const auto title = qs(data.vtitle());
|
||||
const auto count = data.vparticipants_count().v;
|
||||
const auto status = [&] {
|
||||
return (!_participants.empty() && _participants.size() < count)
|
||||
? tr::lng_group_invite_members(tr::now, lt_count, count)
|
||||
: (count > 0)
|
||||
? tr::lng_chat_status_members(tr::now, lt_count_decimal, count)
|
||||
: _isChannel
|
||||
? tr::lng_channel_status(tr::now)
|
||||
: tr::lng_group_status(tr::now);
|
||||
}();
|
||||
_title->setText(title);
|
||||
_status->setText(status);
|
||||
|
||||
const auto photo = _session->data().processPhoto(data.vphoto());
|
||||
if (!photo->isNull()) {
|
||||
_photo = photo->createMediaView();
|
||||
_photo->wanted(Data::PhotoSize::Small, Data::FileOrigin());
|
||||
if (!_photo->image(Data::PhotoSize::Small)) {
|
||||
subscribe(_session->downloaderTaskFinished(), [=] {
|
||||
update();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
_photoEmpty = std::make_unique<Ui::EmptyUserpic>(
|
||||
Data::PeerUserpicColor(0),
|
||||
title);
|
||||
}
|
||||
}
|
||||
|
||||
auto ConfirmInviteBox::GetParticipants(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data)
|
||||
-> std::vector<Participant> {
|
||||
const auto participants = data.vparticipants();
|
||||
if (!participants) {
|
||||
return {};
|
||||
}
|
||||
const auto &v = participants->v;
|
||||
auto result = std::vector<Participant>();
|
||||
result.reserve(v.size());
|
||||
for (const auto &participant : v) {
|
||||
if (const auto user = session->data().processUser(participant)) {
|
||||
result.push_back(Participant{ user });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::prepare() {
|
||||
addButton(
|
||||
(_isChannel
|
||||
? tr::lng_profile_join_channel()
|
||||
: tr::lng_profile_join_group()),
|
||||
_submit);
|
||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||
|
||||
while (_participants.size() > 4) {
|
||||
_participants.pop_back();
|
||||
}
|
||||
|
||||
auto newHeight = st::confirmInviteStatusTop + _status->height() + st::boxPadding.bottom();
|
||||
if (!_participants.empty()) {
|
||||
int skip = (st::boxWideWidth - 4 * st::confirmInviteUserPhotoSize) / 5;
|
||||
int padding = skip / 2;
|
||||
_userWidth = (st::confirmInviteUserPhotoSize + 2 * padding);
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (st::boxWideWidth - sumWidth) / 2;
|
||||
for (const auto &participant : _participants) {
|
||||
auto name = new Ui::FlatLabel(this, st::confirmInviteUserName);
|
||||
name->resizeToWidth(st::confirmInviteUserPhotoSize + padding);
|
||||
name->setText(participant.user->firstName.isEmpty()
|
||||
? participant.user->name
|
||||
: participant.user->firstName);
|
||||
name->moveToLeft(left + (padding / 2), st::confirmInviteUserNameTop);
|
||||
left += _userWidth;
|
||||
}
|
||||
|
||||
newHeight += st::confirmInviteUserHeight;
|
||||
}
|
||||
setDimensions(st::boxWideWidth, newHeight);
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
_title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop);
|
||||
_status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop);
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
||||
BoxContent::paintEvent(e);
|
||||
|
||||
Painter p(this);
|
||||
|
||||
if (_photo) {
|
||||
if (const auto image = _photo->image(Data::PhotoSize::Small)) {
|
||||
p.drawPixmap(
|
||||
(width() - st::confirmInvitePhotoSize) / 2,
|
||||
st::confirmInvitePhotoTop,
|
||||
image->pixCircled(
|
||||
st::confirmInvitePhotoSize,
|
||||
st::confirmInvitePhotoSize));
|
||||
}
|
||||
} else if (_photoEmpty) {
|
||||
_photoEmpty->paint(
|
||||
p,
|
||||
(width() - st::confirmInvitePhotoSize) / 2,
|
||||
st::confirmInvitePhotoTop,
|
||||
width(),
|
||||
st::confirmInvitePhotoSize);
|
||||
}
|
||||
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (width() - sumWidth) / 2;
|
||||
for (auto &participant : _participants) {
|
||||
participant.user->paintUserpicLeft(
|
||||
p,
|
||||
participant.userpic,
|
||||
left + (_userWidth - st::confirmInviteUserPhotoSize) / 2,
|
||||
st::confirmInviteUserPhotoTop,
|
||||
width(),
|
||||
st::confirmInviteUserPhotoSize);
|
||||
left += _userWidth;
|
||||
}
|
||||
}
|
||||
|
||||
ConfirmInviteBox::~ConfirmInviteBox() = default;
|
||||
|
||||
ConfirmDontWarnBox::ConfirmDontWarnBox(
|
||||
QWidget*,
|
||||
rpl::producer<TextWithEntities> text,
|
||||
|
||||
@@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
namespace Data {
|
||||
class PhotoMedia;
|
||||
@@ -129,7 +129,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class PinMessageBox : public Ui::BoxContent, public RPCSender {
|
||||
class PinMessageBox final : public Ui::BoxContent {
|
||||
public:
|
||||
PinMessageBox(QWidget*, not_null<PeerData*> peer, MsgId msgId);
|
||||
|
||||
@@ -141,10 +141,9 @@ protected:
|
||||
|
||||
private:
|
||||
void pinMessage();
|
||||
void pinDone(const MTPUpdates &updates);
|
||||
bool pinFail(const RPCError &error);
|
||||
|
||||
not_null<PeerData*> _peer;
|
||||
const not_null<PeerData*> _peer;
|
||||
MTP::Sender _api;
|
||||
MsgId _msgId;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _text;
|
||||
@@ -154,7 +153,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class DeleteMessagesBox : public Ui::BoxContent, public RPCSender {
|
||||
class DeleteMessagesBox final : public Ui::BoxContent {
|
||||
public:
|
||||
DeleteMessagesBox(
|
||||
QWidget*,
|
||||
@@ -207,47 +206,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class ConfirmInviteBox
|
||||
: public Ui::BoxContent
|
||||
, public RPCSender
|
||||
, private base::Subscriber {
|
||||
public:
|
||||
ConfirmInviteBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data,
|
||||
Fn<void()> submit);
|
||||
~ConfirmInviteBox();
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
struct Participant {
|
||||
not_null<UserData*> user;
|
||||
std::shared_ptr<Data::CloudImageView> userpic;
|
||||
};
|
||||
static std::vector<Participant> GetParticipants(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDchatInvite &data);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
|
||||
Fn<void()> _submit;
|
||||
object_ptr<Ui::FlatLabel> _title;
|
||||
object_ptr<Ui::FlatLabel> _status;
|
||||
std::shared_ptr<Data::PhotoMedia> _photo;
|
||||
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
|
||||
std::vector<Participant> _participants;
|
||||
bool _isChannel = false;
|
||||
|
||||
int _userWidth = 0;
|
||||
|
||||
};
|
||||
|
||||
class ConfirmDontWarnBox : public Ui::BoxContent {
|
||||
public:
|
||||
ConfirmDontWarnBox(
|
||||
|
||||
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "core/click_handler_types.h" // UrlClickHandler
|
||||
#include "base/qthelp_url.h" // qthelp::url_encode
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "numbers.h"
|
||||
#include "app.h"
|
||||
@@ -203,36 +204,54 @@ QString SentCodeCall::getText() const {
|
||||
return QString();
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::start(const QString &phone, const QString &hash) {
|
||||
if (CurrentConfirmPhoneBox && CurrentConfirmPhoneBox->getPhone() != phone) {
|
||||
void ConfirmPhoneBox::Start(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &phone,
|
||||
const QString &hash) {
|
||||
if (CurrentConfirmPhoneBox
|
||||
&& (CurrentConfirmPhoneBox->getPhone() != phone
|
||||
|| &CurrentConfirmPhoneBox->session() != session)) {
|
||||
CurrentConfirmPhoneBox.destroyDelayed();
|
||||
}
|
||||
if (!CurrentConfirmPhoneBox) {
|
||||
CurrentConfirmPhoneBox = Box<ConfirmPhoneBox>(phone, hash);
|
||||
CurrentConfirmPhoneBox = Box<ConfirmPhoneBox>(session, phone, hash);
|
||||
}
|
||||
CurrentConfirmPhoneBox->checkPhoneAndHash();
|
||||
}
|
||||
|
||||
ConfirmPhoneBox::ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash)
|
||||
: _phone(phone)
|
||||
ConfirmPhoneBox::ConfirmPhoneBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const QString &phone,
|
||||
const QString &hash)
|
||||
: _session(session)
|
||||
, _api(&session->mtp())
|
||||
, _phone(phone)
|
||||
, _hash(hash)
|
||||
, _call([this] { sendCall(); }, [this] { update(); }) {
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::sendCall() {
|
||||
MTP::send(MTPauth_ResendCode(MTP_string(_phone), MTP_string(_phoneHash)), rpcDone(&ConfirmPhoneBox::callDone));
|
||||
_api.request(MTPauth_ResendCode(
|
||||
MTP_string(_phone),
|
||||
MTP_string(_phoneHash)
|
||||
)).done([=](const MTPauth_SentCode &result) {
|
||||
callDone(result);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::checkPhoneAndHash() {
|
||||
if (_sendCodeRequestId) {
|
||||
return;
|
||||
}
|
||||
_sendCodeRequestId = MTP::send(
|
||||
MTPaccount_SendConfirmPhoneCode(
|
||||
MTP_string(_hash),
|
||||
MTP_codeSettings(MTP_flags(0))),
|
||||
rpcDone(&ConfirmPhoneBox::sendCodeDone),
|
||||
rpcFail(&ConfirmPhoneBox::sendCodeFail));
|
||||
_sendCodeRequestId = _api.request(MTPaccount_SendConfirmPhoneCode(
|
||||
MTP_string(_hash),
|
||||
MTP_codeSettings(MTP_flags(0))
|
||||
)).done([=](const MTPauth_SentCode &result) {
|
||||
sendCodeDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
sendCodeFail(error);
|
||||
}).handleFloodErrors().send();
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::sendCodeDone(const MTPauth_SentCode &result) {
|
||||
@@ -259,12 +278,10 @@ void ConfirmPhoneBox::sendCodeDone(const MTPauth_SentCode &result) {
|
||||
});
|
||||
}
|
||||
|
||||
bool ConfirmPhoneBox::sendCodeFail(const RPCError &error) {
|
||||
void ConfirmPhoneBox::sendCodeFail(const RPCError &error) {
|
||||
auto errorText = Lang::Hard::ServerError();
|
||||
if (MTP::isFloodError(error)) {
|
||||
errorText = tr::lng_flood_error(tr::now);
|
||||
} else if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
} else if (error.code() == 400) {
|
||||
errorText = tr::lng_confirm_phone_link_invalid(tr::now);
|
||||
}
|
||||
@@ -275,7 +292,6 @@ bool ConfirmPhoneBox::sendCodeFail(const RPCError &error) {
|
||||
} else {
|
||||
deleteLater();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::launch() {
|
||||
@@ -327,10 +343,14 @@ void ConfirmPhoneBox::sendCode() {
|
||||
|
||||
showError(QString());
|
||||
|
||||
_sendCodeRequestId = MTP::send(
|
||||
MTPaccount_ConfirmPhone(MTP_string(_phoneHash), MTP_string(code)),
|
||||
rpcDone(&ConfirmPhoneBox::confirmDone),
|
||||
rpcFail(&ConfirmPhoneBox::confirmFail));
|
||||
_sendCodeRequestId = _api.request(MTPaccount_ConfirmPhone(
|
||||
MTP_string(_phoneHash),
|
||||
MTP_string(code)
|
||||
)).done([=](const MTPBool &result) {
|
||||
confirmDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
confirmFail(error);
|
||||
}).handleFloodErrors().send();
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::confirmDone(const MTPBool &result) {
|
||||
@@ -338,12 +358,10 @@ void ConfirmPhoneBox::confirmDone(const MTPBool &result) {
|
||||
Ui::show(Box<InformBox>(tr::lng_confirm_phone_success(tr::now, lt_phone, App::formatPhone(_phone))));
|
||||
}
|
||||
|
||||
bool ConfirmPhoneBox::confirmFail(const RPCError &error) {
|
||||
void ConfirmPhoneBox::confirmFail(const RPCError &error) {
|
||||
auto errorText = Lang::Hard::ServerError();
|
||||
if (MTP::isFloodError(error)) {
|
||||
errorText = tr::lng_flood_error(tr::now);
|
||||
} else if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
} else {
|
||||
auto &errorType = error.type();
|
||||
if (errorType == qstr("PHONE_CODE_EMPTY") || errorType == qstr("PHONE_CODE_INVALID")) {
|
||||
@@ -354,7 +372,6 @@ bool ConfirmPhoneBox::confirmFail(const RPCError &error) {
|
||||
_code->setDisabled(false);
|
||||
_code->setFocus();
|
||||
showError(errorText);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfirmPhoneBox::showError(const QString &error) {
|
||||
@@ -406,9 +423,3 @@ void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) {
|
||||
void ConfirmPhoneBox::setInnerFocus() {
|
||||
_code->setFocusFast();
|
||||
}
|
||||
|
||||
ConfirmPhoneBox::~ConfirmPhoneBox() {
|
||||
if (_sendCodeRequestId) {
|
||||
MTP::cancel(_sendCodeRequestId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "base/timer.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
namespace Ui {
|
||||
class InputField;
|
||||
class FlatLabel;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
void ShowPhoneBannedError(const QString &phone);
|
||||
[[nodiscard]] QString ExtractPhonePrefix(const QString &phone);
|
||||
|
||||
@@ -86,11 +90,16 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class ConfirmPhoneBox : public Ui::BoxContent, public RPCSender {
|
||||
class ConfirmPhoneBox final : public Ui::BoxContent {
|
||||
public:
|
||||
static void start(const QString &phone, const QString &hash);
|
||||
static void Start(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &phone,
|
||||
const QString &hash);
|
||||
|
||||
~ConfirmPhoneBox();
|
||||
[[nodiscard]] Main::Session &session() const {
|
||||
return *_session;
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
@@ -100,7 +109,11 @@ protected:
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
ConfirmPhoneBox(QWidget*, const QString &phone, const QString &hash);
|
||||
ConfirmPhoneBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const QString &phone,
|
||||
const QString &hash);
|
||||
friend class object_ptr<ConfirmPhoneBox>;
|
||||
|
||||
void sendCode();
|
||||
@@ -108,12 +121,12 @@ private:
|
||||
void checkPhoneAndHash();
|
||||
|
||||
void sendCodeDone(const MTPauth_SentCode &result);
|
||||
bool sendCodeFail(const RPCError &error);
|
||||
void sendCodeFail(const RPCError &error);
|
||||
|
||||
void callDone(const MTPauth_SentCode &result);
|
||||
|
||||
void confirmDone(const MTPBool &result);
|
||||
bool confirmFail(const RPCError &error);
|
||||
void confirmFail(const RPCError &error);
|
||||
|
||||
QString getPhone() const {
|
||||
return _phone;
|
||||
@@ -122,6 +135,8 @@ private:
|
||||
|
||||
void showError(const QString &error);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _sendCodeRequestId = 0;
|
||||
|
||||
// _hash from the link for account.sendConfirmPhoneCode call.
|
||||
|
||||
@@ -171,7 +171,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class ProxyBox : public Ui::BoxContent {
|
||||
class ProxyBox final : public Ui::BoxContent {
|
||||
public:
|
||||
ProxyBox(
|
||||
QWidget*,
|
||||
@@ -179,12 +179,14 @@ public:
|
||||
Fn<void(ProxyData)> callback,
|
||||
Fn<void(ProxyData)> shareCallback);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
using Type = ProxyData::Type;
|
||||
|
||||
void prepare() override;
|
||||
void setInnerFocus() override {
|
||||
_host->setFocusFast();
|
||||
}
|
||||
|
||||
void refreshButtons();
|
||||
ProxyData collectData();
|
||||
void save();
|
||||
@@ -693,8 +695,8 @@ void ProxiesBox::applyView(View &&view) {
|
||||
setupButtons(id, i->second.get());
|
||||
if (_noRows) {
|
||||
_noRows.reset();
|
||||
wrap->resizeToWidth(width());
|
||||
}
|
||||
wrap->resizeToWidth(width());
|
||||
} else if (view.host.isEmpty()) {
|
||||
_rows.erase(i);
|
||||
} else {
|
||||
@@ -765,6 +767,31 @@ ProxyBox::ProxyBox(
|
||||
void ProxyBox::prepare() {
|
||||
setTitle(tr::lng_proxy_edit());
|
||||
|
||||
connect(_host.data(), &Ui::InputField::changed, [=] {
|
||||
Ui::PostponeCall(_host, [=] {
|
||||
const auto host = _host->getLastText().trimmed();
|
||||
static const auto mask = u"^\\d+\\.\\d+\\.\\d+\\.\\d+:(\\d*)$"_q;
|
||||
const auto match = QRegularExpression(mask).match(host);
|
||||
if (_host->textCursor().position() == host.size()
|
||||
&& match.hasMatch()) {
|
||||
const auto port = match.captured(1);
|
||||
_port->setText(port);
|
||||
_port->setCursorPosition(port.size());
|
||||
_port->setFocus();
|
||||
_host->setText(host.mid(0, host.size() - port.size() - 1));
|
||||
}
|
||||
});
|
||||
});
|
||||
_port.data()->events(
|
||||
) | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::KeyPress
|
||||
&& (static_cast<QKeyEvent*>(e.get())->key() == Qt::Key_Backspace)
|
||||
&& _port->cursorPosition() == 0) {
|
||||
_host->setCursorPosition(_host->getLastText().size());
|
||||
_host->setFocus();
|
||||
}
|
||||
}, _port->lifetime());
|
||||
|
||||
refreshButtons();
|
||||
setDimensionsToContent(st::boxWideWidth, _content);
|
||||
}
|
||||
@@ -978,8 +1005,9 @@ void ProxyBox::addLabel(
|
||||
|
||||
} // namespace
|
||||
|
||||
ProxiesBoxController::ProxiesBoxController()
|
||||
: _saveTimer([] { Local::writeSettings(); }) {
|
||||
ProxiesBoxController::ProxiesBoxController(not_null<Main::Account*> account)
|
||||
: _account(account)
|
||||
, _saveTimer([] { Local::writeSettings(); }) {
|
||||
_list = ranges::view::all(
|
||||
Global::ProxiesList()
|
||||
) | ranges::view::transform([&](const ProxyData &proxy) {
|
||||
@@ -1027,7 +1055,7 @@ void ProxiesBoxController::ShowApplyConfirmation(
|
||||
: QString());
|
||||
*box = Ui::show(Box<ConfirmBox>(text, tr::lng_sure_enable(tr::now), [=] {
|
||||
auto &proxies = Global::RefProxiesList();
|
||||
if (ranges::find(proxies, proxy) == end(proxies)) {
|
||||
if (!ranges::contains(proxies, proxy)) {
|
||||
proxies.push_back(proxy);
|
||||
}
|
||||
Core::App().setCurrentProxy(
|
||||
@@ -1058,7 +1086,7 @@ void ProxiesBoxController::refreshChecker(Item &item) {
|
||||
const auto type = (item.data.type == Type::Http)
|
||||
? Variants::Http
|
||||
: Variants::Tcp;
|
||||
const auto mtproto = Core::App().activeAccount().mtp();
|
||||
const auto mtproto = &_account->mtp();
|
||||
const auto dcId = mtproto->mainDcId();
|
||||
|
||||
item.state = ItemState::Checking;
|
||||
@@ -1081,7 +1109,7 @@ void ProxiesBoxController::refreshChecker(Item &item) {
|
||||
dcId);
|
||||
item.checkerv6 = nullptr;
|
||||
} else {
|
||||
const auto options = mtproto->dcOptions()->lookup(
|
||||
const auto options = mtproto->dcOptions().lookup(
|
||||
dcId,
|
||||
MTP::DcType::Regular,
|
||||
true);
|
||||
@@ -1142,8 +1170,9 @@ void ProxiesBoxController::setupChecker(int id, const Checker &checker) {
|
||||
pointer->connect(pointer, &Connection::error, failed);
|
||||
}
|
||||
|
||||
object_ptr<Ui::BoxContent> ProxiesBoxController::CreateOwningBox() {
|
||||
auto controller = std::make_unique<ProxiesBoxController>();
|
||||
object_ptr<Ui::BoxContent> ProxiesBoxController::CreateOwningBox(
|
||||
not_null<Main::Account*> account) {
|
||||
auto controller = std::make_unique<ProxiesBoxController>(account);
|
||||
auto box = controller->create();
|
||||
Ui::AttachAsChild(box, std::move(controller));
|
||||
return box;
|
||||
@@ -1372,7 +1401,7 @@ void ProxiesBoxController::setTryIPv6(bool enabled) {
|
||||
return;
|
||||
}
|
||||
Global::SetTryIPv6(enabled);
|
||||
MTP::restart();
|
||||
_account->mtp().restart();
|
||||
Global::RefConnectionTypeChanged().notify();
|
||||
saveDelayed();
|
||||
}
|
||||
@@ -1386,7 +1415,6 @@ auto ProxiesBoxController::views() const -> rpl::producer<ItemView> {
|
||||
}
|
||||
|
||||
void ProxiesBoxController::updateView(const Item &item) {
|
||||
const auto ping = 0;
|
||||
const auto selected = (Global::SelectedProxy() == item.data);
|
||||
const auto deleted = item.deleted;
|
||||
const auto type = [&] {
|
||||
@@ -1404,7 +1432,7 @@ void ProxiesBoxController::updateView(const Item &item) {
|
||||
if (!selected
|
||||
|| (Global::ProxySettings() != ProxyData::Settings::Enabled)) {
|
||||
return item.state;
|
||||
} else if (MTP::dcstate() == MTP::ConnectedState) {
|
||||
} else if (_account->mtp().dcstate() == MTP::ConnectedState) {
|
||||
return ItemState::Online;
|
||||
}
|
||||
return ItemState::Connecting;
|
||||
|
||||
@@ -24,18 +24,23 @@ template <typename Enum>
|
||||
class Radioenum;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Main {
|
||||
class Account;
|
||||
} // namespace Main
|
||||
|
||||
class ProxiesBoxController : public base::Subscriber {
|
||||
public:
|
||||
using ProxyData = MTP::ProxyData;
|
||||
using Type = ProxyData::Type;
|
||||
|
||||
ProxiesBoxController();
|
||||
explicit ProxiesBoxController(not_null<Main::Account*> account);
|
||||
|
||||
static void ShowApplyConfirmation(
|
||||
Type type,
|
||||
const QMap<QString, QString> &fields);
|
||||
|
||||
static object_ptr<Ui::BoxContent> CreateOwningBox();
|
||||
static object_ptr<Ui::BoxContent> CreateOwningBox(
|
||||
not_null<Main::Account*> account);
|
||||
object_ptr<Ui::BoxContent> create();
|
||||
|
||||
enum class ItemState {
|
||||
@@ -104,6 +109,7 @@ private:
|
||||
const ProxyData &proxy);
|
||||
void addNewItem(const ProxyData &proxy);
|
||||
|
||||
const not_null<Main::Account*> _account;
|
||||
int _idCounter = 0;
|
||||
std::vector<Item> _list;
|
||||
rpl::event_stream<ItemView> _views;
|
||||
|
||||
@@ -20,6 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "main/main_session.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "chat_helpers/message_field.h"
|
||||
#include "history/view/history_view_schedule_box.h"
|
||||
@@ -27,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/unique_qptr.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/call_delayed.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_settings.h"
|
||||
@@ -159,7 +162,7 @@ void InitField(
|
||||
not_null<Main::Session*> session) {
|
||||
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
field->setInstantReplacesEnabled(
|
||||
session->settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
auto options = Ui::Emoji::SuggestionsController::Options();
|
||||
options.suggestExactFirstWord = false;
|
||||
Ui::Emoji::SuggestionsController::Init(
|
||||
@@ -721,9 +724,8 @@ void Options::removeDestroyed(not_null<Option*> option) {
|
||||
void Options::validateState() {
|
||||
checkLastOption();
|
||||
_hasOptions = (ranges::count_if(_list, &Option::isGood) > 1);
|
||||
_isValid = _hasOptions
|
||||
&& (ranges::find_if(_list, &Option::isTooLong) == end(_list));
|
||||
_hasCorrect = ranges::find_if(_list, &Option::isCorrect) != end(_list);
|
||||
_isValid = _hasOptions && ranges::none_of(_list, &Option::isTooLong);
|
||||
_hasCorrect = ranges::any_of(_list, &Option::isCorrect);
|
||||
|
||||
const auto lastEmpty = !_list.empty() && _list.back()->isEmpty();
|
||||
_usedCount = _list.size() - (lastEmpty ? 1 : 0);
|
||||
@@ -748,11 +750,11 @@ void Options::checkLastOption() {
|
||||
|
||||
CreatePollBox::CreatePollBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<Window::SessionController*> controller,
|
||||
PollData::Flags chosen,
|
||||
PollData::Flags disabled,
|
||||
Api::SendType sendType)
|
||||
: _session(session)
|
||||
: _controller(controller)
|
||||
, _chosen(chosen)
|
||||
, _disabled(disabled)
|
||||
, _sendType(sendType) {
|
||||
@@ -774,6 +776,7 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
|
||||
not_null<Ui::VerticalLayout*> container) {
|
||||
using namespace Settings;
|
||||
|
||||
const auto session = &_controller->session();
|
||||
AddSubsectionTitle(container, tr::lng_polls_create_question());
|
||||
const auto question = container->add(
|
||||
object_ptr<Ui::InputField>(
|
||||
@@ -782,7 +785,7 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
|
||||
Ui::InputField::Mode::MultiLine,
|
||||
tr::lng_polls_create_question_placeholder()),
|
||||
st::createPollFieldPadding);
|
||||
InitField(getDelegate()->outerContainer(), question, _session);
|
||||
InitField(getDelegate()->outerContainer(), question, session);
|
||||
question->setMaxLength(kQuestionLimit + kErrorLimit);
|
||||
question->setSubmitSettings(Ui::InputField::SubmitSettings::Both);
|
||||
question->customTab(true);
|
||||
@@ -824,6 +827,7 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
|
||||
)->setDuration(0)->toggleOn(std::move(shown));
|
||||
const auto inner = outer->entity();
|
||||
|
||||
const auto session = &_controller->session();
|
||||
AddSkip(inner);
|
||||
AddSubsectionTitle(inner, tr::lng_polls_solution_title());
|
||||
const auto solution = inner->add(
|
||||
@@ -833,14 +837,14 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
|
||||
Ui::InputField::Mode::MultiLine,
|
||||
tr::lng_polls_solution_placeholder()),
|
||||
st::createPollFieldPadding);
|
||||
InitField(getDelegate()->outerContainer(), solution, _session);
|
||||
InitField(getDelegate()->outerContainer(), solution, session);
|
||||
solution->setMaxLength(kSolutionLimit + kErrorLimit);
|
||||
solution->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
solution->setInstantReplacesEnabled(
|
||||
_session->settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
solution->setMarkdownReplacesEnabled(rpl::single(true));
|
||||
solution->setEditLinkCallback(
|
||||
DefaultEditLinkCallback(_session, solution));
|
||||
DefaultEditLinkCallback(_controller, solution));
|
||||
solution->customTab(true);
|
||||
|
||||
const auto warning = CreateWarningLabel(
|
||||
@@ -896,7 +900,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
const auto options = lifetime().make_state<Options>(
|
||||
getDelegate()->outerContainer(),
|
||||
container,
|
||||
_session,
|
||||
&_controller->session(),
|
||||
(_chosen & PollData::Flag::Quiz));
|
||||
auto limit = options->usedCount() | rpl::after_next([=](int count) {
|
||||
setCloseByEscape(!count);
|
||||
@@ -1011,7 +1015,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
|
||||
const auto collectResult = [=] {
|
||||
using Flag = PollData::Flag;
|
||||
auto result = PollData(&_session->data(), id);
|
||||
auto result = PollData(&_controller->session().data(), id);
|
||||
result.question = question->getLastText().trimmed();
|
||||
result.answers = options->toPollAnswers();
|
||||
const auto solutionWithTags = quiz->checked()
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace Ui {
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
class CreatePollBox : public Ui::BoxContent {
|
||||
public:
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
|
||||
CreatePollBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<Window::SessionController*> controller,
|
||||
PollData::Flags chosen,
|
||||
PollData::Flags disabled,
|
||||
Api::SendType sendType);
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<bool> shown);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const PollData::Flags _chosen = PollData::Flags();
|
||||
const PollData::Flags _disabled = PollData::Flags();
|
||||
const Api::SendType _sendType = Api::SendType();
|
||||
|
||||
@@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "chat_helpers/spellchecker_common.h"
|
||||
#include "core/application.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mtproto/dedicated_file_loader.h"
|
||||
#include "spellcheck/spellcheck_utils.h"
|
||||
@@ -27,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
||||
namespace Ui {
|
||||
namespace {
|
||||
@@ -46,13 +46,18 @@ using QStringView = QString;
|
||||
|
||||
class Inner : public Ui::RpWidget {
|
||||
public:
|
||||
Inner(QWidget *parent, Dictionaries enabledDictionaries);
|
||||
Inner(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
Dictionaries enabledDictionaries);
|
||||
|
||||
Dictionaries enabledRows() const;
|
||||
QueryCallback queryCallback() const;
|
||||
|
||||
private:
|
||||
void setupContent(Dictionaries enabledDictionaries);
|
||||
void setupContent(
|
||||
not_null<Window::SessionController*> controller,
|
||||
Dictionaries enabledDictionaries);
|
||||
|
||||
Dictionaries _enabledRows;
|
||||
QueryCallback _queryCallback;
|
||||
@@ -96,8 +101,10 @@ auto CreateMultiSelect(QWidget *parent) {
|
||||
|
||||
Inner::Inner(
|
||||
QWidget *parent,
|
||||
Dictionaries enabledDictionaries) : RpWidget(parent) {
|
||||
setupContent(std::move(enabledDictionaries));
|
||||
not_null<Window::SessionController*> controller,
|
||||
Dictionaries enabledDictionaries)
|
||||
: RpWidget(parent) {
|
||||
setupContent(controller, std::move(enabledDictionaries));
|
||||
}
|
||||
|
||||
QueryCallback Inner::queryCallback() const {
|
||||
@@ -110,6 +117,7 @@ Dictionaries Inner::enabledRows() const {
|
||||
|
||||
auto AddButtonWithLoader(
|
||||
not_null<Ui::VerticalLayout*> content,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const Spellchecker::Dict &dict,
|
||||
bool buttonEnabled,
|
||||
rpl::producer<QStringView> query) {
|
||||
@@ -238,39 +246,29 @@ auto AddButtonWithLoader(
|
||||
) | rpl::then(
|
||||
rpl::merge(
|
||||
// Events to toggle on.
|
||||
dictionaryFromGlobalLoader->events(
|
||||
) | rpl::map([] {
|
||||
return true;
|
||||
}),
|
||||
dictionaryFromGlobalLoader->events() | rpl::map_to(true),
|
||||
// Events to toggle off.
|
||||
rpl::merge(
|
||||
dictionaryRemoved->events(),
|
||||
buttonState->value(
|
||||
) | rpl::filter([](const DictState &state) {
|
||||
return state.is<Failed>();
|
||||
}) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
})
|
||||
) | rpl::map([] {
|
||||
return false;
|
||||
})
|
||||
}) | rpl::to_empty
|
||||
) | rpl::map_to(false)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
*buttonState = localLoaderValues->events_starting_with(
|
||||
rawGlobalLoaderPtr() ? rawGlobalLoaderPtr() : localLoader->get()
|
||||
) | rpl::map([=](Loader *loader) {
|
||||
*buttonState = localLoaderValues->events_starting_with(
|
||||
rawGlobalLoaderPtr() ? rawGlobalLoaderPtr() : localLoader->get()
|
||||
) | rpl::map([=](Loader *loader) {
|
||||
return (loader && loader->id() == id)
|
||||
? loader->state()
|
||||
: rpl::single(
|
||||
buttonEnabled
|
||||
) | rpl::then(
|
||||
rpl::merge(
|
||||
dictionaryRemoved->events(
|
||||
) | rpl::map([] {
|
||||
return false;
|
||||
}),
|
||||
dictionaryRemoved->events() | rpl::map_to(false),
|
||||
button->toggledValue()
|
||||
)
|
||||
) | rpl::map([=](auto enabled) {
|
||||
@@ -287,7 +285,8 @@ auto AddButtonWithLoader(
|
||||
if (toggled && (state.is<Available>() || state.is<Failed>())) {
|
||||
const auto weak = Ui::MakeWeak(button);
|
||||
setLocalLoader(base::make_unique_q<Loader>(
|
||||
App::main(),
|
||||
QCoreApplication::instance(),
|
||||
&controller->session(),
|
||||
id,
|
||||
Spellchecker::GetDownloadLocation(id),
|
||||
Spellchecker::DictPathByLangId(id),
|
||||
@@ -336,7 +335,9 @@ auto AddButtonWithLoader(
|
||||
return button;
|
||||
}
|
||||
|
||||
void Inner::setupContent(Dictionaries enabledDictionaries) {
|
||||
void Inner::setupContent(
|
||||
not_null<Window::SessionController*> controller,
|
||||
Dictionaries enabledDictionaries) {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
const auto queryStream = content->lifetime()
|
||||
@@ -346,6 +347,7 @@ void Inner::setupContent(Dictionaries enabledDictionaries) {
|
||||
const auto id = dict.id;
|
||||
const auto row = AddButtonWithLoader(
|
||||
content,
|
||||
controller,
|
||||
dict,
|
||||
ranges::contains(enabledDictionaries, id),
|
||||
queryStream->events());
|
||||
@@ -375,8 +377,8 @@ void Inner::setupContent(Dictionaries enabledDictionaries) {
|
||||
|
||||
ManageDictionariesBox::ManageDictionariesBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session)
|
||||
: _session(session) {
|
||||
not_null<Window::SessionController*> controller)
|
||||
: _controller(controller) {
|
||||
}
|
||||
|
||||
void ManageDictionariesBox::setInnerFocus() {
|
||||
@@ -389,7 +391,8 @@ void ManageDictionariesBox::prepare() {
|
||||
const auto inner = setInnerWidget(
|
||||
object_ptr<Inner>(
|
||||
this,
|
||||
_session->settings().dictionariesEnabled()),
|
||||
_controller,
|
||||
Core::App().settings().dictionariesEnabled()),
|
||||
st::boxScroll,
|
||||
multiSelect->height()
|
||||
);
|
||||
@@ -407,9 +410,9 @@ void ManageDictionariesBox::prepare() {
|
||||
setTitle(tr::lng_settings_manage_dictionaries());
|
||||
|
||||
addButton(tr::lng_settings_save(), [=] {
|
||||
_session->settings().setDictionariesEnabled(
|
||||
Core::App().settings().setDictionariesEnabled(
|
||||
FilterEnabledDict(inner->enabledRows()));
|
||||
_session->saveSettingsDelayed();
|
||||
Core::App().saveSettingsDelayed();
|
||||
// Ignore boxClosing() when the Save button was pressed.
|
||||
lifetime().destroy();
|
||||
closeBox();
|
||||
@@ -417,9 +420,9 @@ void ManageDictionariesBox::prepare() {
|
||||
addButton(tr::lng_close(), [=] { closeBox(); });
|
||||
|
||||
boxClosing() | rpl::start_with_next([=] {
|
||||
_session->settings().setDictionariesEnabled(
|
||||
Core::App().settings().setDictionariesEnabled(
|
||||
FilterEnabledDict(initialEnabledRows));
|
||||
_session->saveSettingsDelayed();
|
||||
Core::App().saveSettingsDelayed();
|
||||
}, lifetime());
|
||||
|
||||
setDimensionsToContent(st::boxWidth, inner);
|
||||
|
||||
@@ -11,9 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Ui {
|
||||
|
||||
@@ -21,14 +21,14 @@ class ManageDictionariesBox : public Ui::BoxContent {
|
||||
public:
|
||||
ManageDictionariesBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session);
|
||||
not_null<Window::SessionController*> controller);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
void setInnerFocus() override;
|
||||
|
||||
private:
|
||||
const not_null<Main::Session*> _session;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
Fn<void()> _setInnerFocus;
|
||||
|
||||
};
|
||||
|
||||
@@ -8,18 +8,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/download_path_box.h"
|
||||
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "facades.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
DownloadPathBox::DownloadPathBox(QWidget *parent)
|
||||
: _path(Global::DownloadPath())
|
||||
, _pathBookmark(Global::DownloadPathBookmark())
|
||||
DownloadPathBox::DownloadPathBox(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: _controller(controller)
|
||||
, _path(Core::App().settings().downloadPath())
|
||||
, _pathBookmark(Core::App().settings().downloadPathBookmark())
|
||||
, _group(std::make_shared<Ui::RadioenumGroup<Directory>>(typeFromPath(_path)))
|
||||
, _default(this, _group, Directory::Downloads, tr::lng_download_path_default_radio(tr::now), st::defaultBoxCheckbox)
|
||||
, _temp(this, _group, Directory::Temp, tr::lng_download_path_temp_radio(tr::now), st::defaultBoxCheckbox)
|
||||
@@ -86,8 +90,9 @@ void DownloadPathBox::radioChanged(Directory value) {
|
||||
|
||||
void DownloadPathBox::editPath() {
|
||||
const auto initialPath = [] {
|
||||
if (!Global::DownloadPath().isEmpty() && Global::DownloadPath() != qstr("tmp")) {
|
||||
return Global::DownloadPath().left(Global::DownloadPath().size() - (Global::DownloadPath().endsWith('/') ? 1 : 0));
|
||||
const auto path = Core::App().settings().downloadPath();
|
||||
if (!path.isEmpty() && path != qstr("tmp")) {
|
||||
return path.left(path.size() - (path.endsWith('/') ? 1 : 0));
|
||||
}
|
||||
return QString();
|
||||
}();
|
||||
@@ -117,10 +122,10 @@ void DownloadPathBox::save() {
|
||||
}
|
||||
return QString();
|
||||
};
|
||||
Global::SetDownloadPath(computePath());
|
||||
Global::SetDownloadPathBookmark((value == Directory::Custom) ? _pathBookmark : QByteArray());
|
||||
Local::writeUserSettings();
|
||||
Global::RefDownloadPathChanged().notify();
|
||||
Core::App().settings().setDownloadPathBookmark(
|
||||
(value == Directory::Custom) ? _pathBookmark : QByteArray());
|
||||
Core::App().settings().setDownloadPath(computePath());
|
||||
Core::App().saveSettings();
|
||||
closeBox();
|
||||
#endif // OS_WIN_STORE
|
||||
}
|
||||
|
||||
@@ -18,9 +18,15 @@ class Radioenum;
|
||||
class LinkButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
class DownloadPathBox : public Ui::BoxContent {
|
||||
public:
|
||||
DownloadPathBox(QWidget *parent);
|
||||
DownloadPathBox(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
@@ -48,6 +54,7 @@ private:
|
||||
void setPathText(const QString &text);
|
||||
void editPath();
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
QString _path;
|
||||
QByteArray _pathBookmark;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/edit_caption_box.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_editing.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "main/main_session.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
@@ -15,6 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "chat_helpers/tabbed_panel.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/mime_type.h"
|
||||
#include "data/data_document.h"
|
||||
@@ -27,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_photo_media.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_drag_area.h"
|
||||
#include "history/history_item.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "lang/lang_keys.h"
|
||||
@@ -35,8 +39,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "media/streaming/media_streaming_player.h"
|
||||
#include "media/streaming/media_streaming_document.h"
|
||||
#include "media/streaming/media_streaming_loader_local.h"
|
||||
#include "platform/platform_file_utilities.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
@@ -45,7 +51,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/text_options.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "confirm_box.h"
|
||||
#include "facades.h"
|
||||
#include "apiwrap.h"
|
||||
#include "facades.h" // App::LambdaDelayed.
|
||||
#include "app.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
@@ -59,6 +66,50 @@ namespace {
|
||||
using namespace ::Media::Streaming;
|
||||
using Data::PhotoSize;
|
||||
|
||||
auto ListFromMimeData(not_null<const QMimeData*> data) {
|
||||
using Error = Storage::PreparedList::Error;
|
||||
auto result = data->hasUrls()
|
||||
? Storage::PrepareMediaList(
|
||||
// When we edit media, we need only 1 file.
|
||||
data->urls().mid(0, 1),
|
||||
st::sendMediaPreviewSize)
|
||||
: Storage::PreparedList(Error::EmptyFile, QString());
|
||||
if (result.error == Error::None) {
|
||||
return result;
|
||||
} else if (data->hasImage()) {
|
||||
auto image = Platform::GetImageFromClipboard();
|
||||
if (image.isNull()) {
|
||||
image = qvariant_cast<QImage>(data->imageData());
|
||||
}
|
||||
if (!image.isNull()) {
|
||||
return Storage::PrepareMediaFromImage(
|
||||
std::move(image),
|
||||
QByteArray(),
|
||||
st::sendMediaPreviewSize);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
auto CheckMimeData(not_null<const QMimeData*> data, bool isAlbum) {
|
||||
if (data->urls().size() > 1) {
|
||||
return false;
|
||||
} else if (data->hasImage()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isAlbum && data->hasUrls()) {
|
||||
const auto url = data->urls().front();
|
||||
if (url.isLocalFile()) {
|
||||
using namespace Core;
|
||||
const auto info = QFileInfo(Platform::File::UrlToLocal(url));
|
||||
return IsMimeAcceptedForAlbum(MimeTypeForFile(info).name());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EditCaptionBox::EditCaptionBox(
|
||||
@@ -286,7 +337,8 @@ EditCaptionBox::EditCaptionBox(
|
||||
Assert(_thumbnailImageLoaded || _refreshThumbnail);
|
||||
|
||||
if (!_thumbnailImageLoaded) {
|
||||
subscribe(_controller->session().downloaderTaskFinished(), [=] {
|
||||
_controller->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (_thumbnailImageLoaded
|
||||
|| (_photoMedia && !_photoMedia->image(PhotoSize::Large))
|
||||
|| (_documentMedia && !_documentMedia->thumbnail())) {
|
||||
@@ -294,7 +346,7 @@ EditCaptionBox::EditCaptionBox(
|
||||
}
|
||||
_refreshThumbnail();
|
||||
update();
|
||||
});
|
||||
}, lifetime());
|
||||
}
|
||||
_field.create(
|
||||
this,
|
||||
@@ -302,16 +354,18 @@ EditCaptionBox::EditCaptionBox(
|
||||
Ui::InputField::Mode::MultiLine,
|
||||
tr::lng_photo_caption(),
|
||||
editData);
|
||||
_field->setMaxLength(Global::CaptionLengthMax());
|
||||
_field->setSubmitSettings(_controller->session().settings().sendSubmitWay());
|
||||
_field->setMaxLength(
|
||||
_controller->session().serverConfig().captionLengthMax);
|
||||
_field->setSubmitSettings(
|
||||
Core::App().settings().sendSubmitWay());
|
||||
_field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
_field->setInstantReplacesEnabled(
|
||||
_controller->session().settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
_field->setMarkdownReplacesEnabled(rpl::single(true));
|
||||
_field->setEditLinkCallback(
|
||||
DefaultEditLinkCallback(&_controller->session(), _field));
|
||||
DefaultEditLinkCallback(_controller, _field));
|
||||
|
||||
InitSpellchecker(&_controller->session(), _field);
|
||||
InitSpellchecker(_controller, _field);
|
||||
|
||||
auto r = object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
|
||||
this,
|
||||
@@ -609,12 +663,8 @@ void EditCaptionBox::prepare() {
|
||||
if (action == Ui::InputField::MimeAction::Check) {
|
||||
if (!data->hasText() && !_isAllowedEditMedia) {
|
||||
return false;
|
||||
} else if (data->hasImage()) {
|
||||
} else if (CheckMimeData(data, _isAlbum)) {
|
||||
return true;
|
||||
} else if (const auto urls = data->urls(); !urls.empty()) {
|
||||
if (ranges::all_of(urls, &QUrl::isLocalFile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return data->hasText();
|
||||
} else if (action == Ui::InputField::MimeAction::Insert) {
|
||||
@@ -632,6 +682,8 @@ void EditCaptionBox::prepare() {
|
||||
auto cursor = _field->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
_field->setTextCursor(cursor);
|
||||
|
||||
setupDragArea();
|
||||
}
|
||||
|
||||
bool EditCaptionBox::fileFromClipboard(not_null<const QMimeData*> data) {
|
||||
@@ -639,50 +691,34 @@ bool EditCaptionBox::fileFromClipboard(not_null<const QMimeData*> data) {
|
||||
return false;
|
||||
}
|
||||
using Error = Storage::PreparedList::Error;
|
||||
using AlbumType = Storage::PreparedFile::AlbumType;
|
||||
auto list = ListFromMimeData(data);
|
||||
|
||||
auto list = [&] {
|
||||
auto url = QList<QUrl>();
|
||||
auto canAddUrl = false;
|
||||
// When we edit media, we need only 1 file.
|
||||
if (data->hasUrls()) {
|
||||
const auto first = data->urls().front();
|
||||
url.push_front(first);
|
||||
canAddUrl = first.isLocalFile();
|
||||
}
|
||||
auto result = canAddUrl
|
||||
? Storage::PrepareMediaList(url, st::sendMediaPreviewSize)
|
||||
: Storage::PreparedList(
|
||||
Error::EmptyFile,
|
||||
QString());
|
||||
if (result.error == Error::None) {
|
||||
return result;
|
||||
} else if (data->hasImage()) {
|
||||
auto image = Platform::GetImageFromClipboard();
|
||||
if (image.isNull()) {
|
||||
image = qvariant_cast<QImage>(data->imageData());
|
||||
}
|
||||
if (!image.isNull()) {
|
||||
_isImage = true;
|
||||
_photo = true;
|
||||
return Storage::PrepareMediaFromImage(
|
||||
std::move(image),
|
||||
QByteArray(),
|
||||
st::sendMediaPreviewSize);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}();
|
||||
if (list.error != Error::None || list.files.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (list.files.front().type == Storage::PreparedFile::AlbumType::None
|
||||
&& _isAlbum) {
|
||||
Ui::show(
|
||||
Box<InformBox>(tr::lng_edit_media_album_error(tr::now)),
|
||||
Ui::LayerOption::KeepOther);
|
||||
|
||||
const auto file = &list.files.front();
|
||||
if (_isAlbum && (file->type == AlbumType::None)) {
|
||||
const auto imageAsDoc = [&] {
|
||||
using Info = FileMediaInformation;
|
||||
const auto fileMedia = &file->information->media;
|
||||
if (const auto image = base::get_if<Info::Image>(fileMedia)) {
|
||||
return !Storage::ValidateThumbDimensions(
|
||||
image->data.width(),
|
||||
image->data.height());
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (!data->hasText() || imageAsDoc) {
|
||||
Ui::show(
|
||||
Box<InformBox>(tr::lng_edit_media_album_error(tr::now)),
|
||||
Ui::LayerOption::KeepOther);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_photo = _isImage = (file->type == AlbumType::Photo);
|
||||
_preparedList = std::move(list);
|
||||
updateEditPreview();
|
||||
return true;
|
||||
@@ -727,6 +763,35 @@ void EditCaptionBox::setupEmojiPanel() {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void EditCaptionBox::setupDragArea() {
|
||||
auto enterFilter = [=](not_null<const QMimeData*> data) {
|
||||
return !_isAllowedEditMedia ? false : CheckMimeData(data, _isAlbum);
|
||||
};
|
||||
// Avoid both drag areas appearing at one time.
|
||||
auto computeState = [=](const QMimeData *data) {
|
||||
const auto state = Storage::ComputeMimeDataState(data);
|
||||
return (state == Storage::MimeDataState::PhotoFiles)
|
||||
? Storage::MimeDataState::Image
|
||||
: state;
|
||||
};
|
||||
const auto areas = DragArea::SetupDragAreaToContainer(
|
||||
this,
|
||||
std::move(enterFilter),
|
||||
[=](bool f) { _field->setAcceptDrops(f); },
|
||||
nullptr,
|
||||
std::move(computeState));
|
||||
|
||||
const auto droppedCallback = [=](bool compress) {
|
||||
return [=](const QMimeData *data) {
|
||||
fileFromClipboard(data);
|
||||
Window::ActivateWindow(_controller);
|
||||
};
|
||||
};
|
||||
areas.document->setDroppedCallback(droppedCallback(false));
|
||||
areas.photo->setDroppedCallback(droppedCallback(true));
|
||||
}
|
||||
|
||||
void EditCaptionBox::updateBoxSize() {
|
||||
auto newHeight = st::boxPhotoPadding.top() + st::boxPhotoCaptionSkip + _field->height() + errorTopSkip() + st::normalFont->height;
|
||||
if (_photo) {
|
||||
@@ -751,8 +816,7 @@ int EditCaptionBox::errorTopSkip() const {
|
||||
void EditCaptionBox::checkStreamedIsStarted() {
|
||||
if (!_streamed) {
|
||||
return;
|
||||
}
|
||||
if (_streamed->paused()) {
|
||||
} else if (_streamed->paused()) {
|
||||
_streamed->resume();
|
||||
}
|
||||
if (!_streamed->active() && !_streamed->failed()) {
|
||||
@@ -922,88 +986,60 @@ void EditCaptionBox::save() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto flags = MTPmessages_EditMessage::Flag::f_message | 0;
|
||||
if (_previewCancelled) {
|
||||
flags |= MTPmessages_EditMessage::Flag::f_no_webpage;
|
||||
}
|
||||
const auto textWithTags = _field->getTextWithAppliedMarkdown();
|
||||
auto sending = TextWithEntities{
|
||||
const auto sending = TextWithEntities{
|
||||
textWithTags.text,
|
||||
TextUtilities::ConvertTextTagsToEntities(textWithTags.tags)
|
||||
};
|
||||
const auto prepareFlags = Ui::ItemTextOptions(
|
||||
item->history(),
|
||||
_controller->session().user()).flags;
|
||||
TextUtilities::PrepareForSending(sending, prepareFlags);
|
||||
TextUtilities::Trim(sending);
|
||||
|
||||
const auto sentEntities = Api::EntitiesToMTP(
|
||||
&item->history()->session(),
|
||||
sending.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
if (!sentEntities.v.isEmpty()) {
|
||||
flags |= MTPmessages_EditMessage::Flag::f_entities;
|
||||
}
|
||||
auto options = Api::SendOptions();
|
||||
options.scheduled = item->isScheduled() ? item->date() : 0;
|
||||
|
||||
if (!_preparedList.files.empty()) {
|
||||
const auto textWithTags = _field->getTextWithAppliedMarkdown();
|
||||
auto sending = TextWithEntities{
|
||||
textWithTags.text,
|
||||
TextUtilities::ConvertTextTagsToEntities(textWithTags.tags)
|
||||
};
|
||||
item->setText(sending);
|
||||
auto action = Api::SendAction(item->history());
|
||||
action.options = options;
|
||||
|
||||
_controller->session().api().editMedia(
|
||||
std::move(_preparedList),
|
||||
(!_asFile && _photo) ? SendMediaType::Photo : SendMediaType::File,
|
||||
_field->getTextWithAppliedMarkdown(),
|
||||
Api::SendAction(item->history()),
|
||||
action,
|
||||
item->fullId().msg);
|
||||
closeBox();
|
||||
return;
|
||||
}
|
||||
|
||||
_saveRequestId = MTP::send(
|
||||
MTPmessages_EditMessage(
|
||||
MTP_flags(flags),
|
||||
item->history()->peer->input,
|
||||
MTP_int(item->id),
|
||||
MTP_string(sending.text),
|
||||
MTPInputMedia(),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(0)), // schedule_date
|
||||
rpcDone(&EditCaptionBox::saveDone),
|
||||
rpcFail(&EditCaptionBox::saveFail));
|
||||
}
|
||||
|
||||
void EditCaptionBox::saveDone(const MTPUpdates &updates) {
|
||||
_saveRequestId = 0;
|
||||
const auto controller = _controller;
|
||||
closeBox();
|
||||
controller->session().api().applyUpdates(updates);
|
||||
}
|
||||
|
||||
bool EditCaptionBox::saveFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
_saveRequestId = 0;
|
||||
const auto &type = error.type();
|
||||
if (type == qstr("MESSAGE_ID_INVALID")
|
||||
|| type == qstr("CHAT_ADMIN_REQUIRED")
|
||||
|| type == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
|
||||
_error = tr::lng_edit_error(tr::now);
|
||||
} else if (type == qstr("MESSAGE_NOT_MODIFIED")) {
|
||||
const auto done = crl::guard(this, [=](const MTPUpdates &updates) {
|
||||
_saveRequestId = 0;
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (type == qstr("MESSAGE_EMPTY")) {
|
||||
_field->setFocus();
|
||||
_field->showError();
|
||||
} else {
|
||||
_error = tr::lng_edit_error(tr::now);
|
||||
}
|
||||
update();
|
||||
return true;
|
||||
});
|
||||
|
||||
const auto fail = crl::guard(this, [=](const RPCError &error) {
|
||||
_saveRequestId = 0;
|
||||
const auto &type = error.type();
|
||||
if (ranges::contains(Api::kDefaultEditMessagesErrors, type)) {
|
||||
_error = tr::lng_edit_error(tr::now);
|
||||
update();
|
||||
} else if (type == u"MESSAGE_NOT_MODIFIED"_q) {
|
||||
closeBox();
|
||||
} else if (type == u"MESSAGE_EMPTY"_q) {
|
||||
_field->setFocus();
|
||||
_field->showError();
|
||||
update();
|
||||
} else {
|
||||
_error = tr::lng_edit_error(tr::now);
|
||||
update();
|
||||
}
|
||||
});
|
||||
|
||||
lifetime().add([=] {
|
||||
if (_saveRequestId) {
|
||||
auto &session = _controller->session();
|
||||
session.api().request(base::take(_saveRequestId)).cancel();
|
||||
}
|
||||
});
|
||||
|
||||
_saveRequestId = Api::EditCaption(item, sending, options, done, fail);
|
||||
}
|
||||
|
||||
void EditCaptionBox::setName(QString nameString, qint64 size) {
|
||||
|
||||
@@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
|
||||
class Image;
|
||||
|
||||
@@ -49,10 +48,7 @@ struct Information;
|
||||
} // namespace Streaming
|
||||
} // namespace Media
|
||||
|
||||
class EditCaptionBox
|
||||
: public Ui::BoxContent
|
||||
, public RPCSender
|
||||
, private base::Subscriber {
|
||||
class EditCaptionBox final : public Ui::BoxContent, private base::Subscriber {
|
||||
public:
|
||||
EditCaptionBox(
|
||||
QWidget*,
|
||||
@@ -83,12 +79,11 @@ private:
|
||||
void updateEmojiPanelGeometry();
|
||||
void emojiFilterForGeometry(not_null<QEvent*> event);
|
||||
|
||||
void setupDragArea();
|
||||
|
||||
void save();
|
||||
void captionResized();
|
||||
|
||||
void saveDone(const MTPUpdates &updates);
|
||||
bool saveFail(const RPCError &error);
|
||||
|
||||
void setName(QString nameString, qint64 size);
|
||||
bool fileFromClipboard(not_null<const QMimeData*> data);
|
||||
void updateEditPreview();
|
||||
@@ -104,7 +99,8 @@ private:
|
||||
: _preparedList.files.front().path;
|
||||
}
|
||||
|
||||
not_null<Window::SessionController*> _controller;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
|
||||
FullMsgId _msgId;
|
||||
std::shared_ptr<Data::PhotoMedia> _photoMedia;
|
||||
std::shared_ptr<Data::DocumentMedia> _documentMedia;
|
||||
@@ -136,7 +132,6 @@ private:
|
||||
|
||||
Storage::PreparedList _preparedList;
|
||||
|
||||
bool _previewCancelled = false;
|
||||
mtpRequestId _saveRequestId = 0;
|
||||
|
||||
object_ptr<Ui::IconButton> _editMedia = nullptr;
|
||||
|
||||
@@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "lang/lang_keys.h"
|
||||
@@ -500,7 +502,7 @@ void EditFilterBox(
|
||||
name->setMaxLength(kMaxFilterTitleLength);
|
||||
name->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
name->setInstantReplacesEnabled(
|
||||
window->session().settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
Ui::Emoji::SuggestionsController::Init(
|
||||
box->getDelegate()->outerContainer(),
|
||||
name,
|
||||
|
||||
@@ -1100,10 +1100,13 @@ void LanguageBox::prepare() {
|
||||
) | rpl::start_with_next([=](const Language &language) {
|
||||
// "#custom" is applied each time it's passed to switchToLanguage().
|
||||
// So we check that the language really has changed.
|
||||
if (language.id != Lang::Current().id()) {
|
||||
const auto currentId = [] {
|
||||
return Lang::LanguageIdOrDefault(Lang::Current().id());
|
||||
};
|
||||
if (language.id != currentId()) {
|
||||
Lang::CurrentCloudManager().switchToLanguage(language);
|
||||
if (inner) {
|
||||
inner->changeChosen(Lang::Current().id());
|
||||
inner->changeChosen(currentId());
|
||||
}
|
||||
}
|
||||
}, inner->lifetime());
|
||||
|
||||
@@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/continuous_sliders.h"
|
||||
#include "ui/effects/radial_animation.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "storage/cache/storage_cache_database.h"
|
||||
#include "data/data_session.h"
|
||||
#include "lang/lang_keys.h"
|
||||
@@ -206,7 +206,7 @@ void LocalStorageBox::Row::radialAnimationCallback() {
|
||||
}
|
||||
|
||||
rpl::producer<> LocalStorageBox::Row::clearRequests() const {
|
||||
return _clear->clicks() | rpl::map([] { return rpl::empty_value(); });
|
||||
return _clear->clicks() | rpl::to_empty;
|
||||
}
|
||||
|
||||
int LocalStorageBox::Row::resizeGetHeight(int newWidth) {
|
||||
@@ -271,8 +271,8 @@ LocalStorageBox::LocalStorageBox(
|
||||
: _session(session)
|
||||
, _db(&session->data().cache())
|
||||
, _dbBig(&session->data().cacheBigFile()) {
|
||||
const auto &settings = Local::cacheSettings();
|
||||
const auto &settingsBig = Local::cacheBigFileSettings();
|
||||
const auto &settings = session->local().cacheSettings();
|
||||
const auto &settingsBig = session->local().cacheBigFileSettings();
|
||||
_totalSizeLimit = settings.totalSizeLimit + settingsBig.totalSizeLimit;
|
||||
_mediaSizeLimit = settingsBig.totalSizeLimit;
|
||||
_timeLimit = settings.totalTimeLimit;
|
||||
@@ -560,8 +560,8 @@ void LocalStorageBox::setupLimits(not_null<Ui::VerticalLayout*> container) {
|
||||
}
|
||||
|
||||
void LocalStorageBox::limitsChanged() {
|
||||
const auto &settings = Local::cacheSettings();
|
||||
const auto &settingsBig = Local::cacheBigFileSettings();
|
||||
const auto &settings = _session->local().cacheSettings();
|
||||
const auto &settingsBig = _session->local().cacheBigFileSettings();
|
||||
const auto sizeLimit = _totalSizeLimit - _mediaSizeLimit;
|
||||
const auto changed = (settings.totalSizeLimit != sizeLimit)
|
||||
|| (settingsBig.totalSizeLimit != _mediaSizeLimit)
|
||||
@@ -590,7 +590,7 @@ void LocalStorageBox::save() {
|
||||
auto updateBig = Storage::Cache::Database::SettingsUpdate();
|
||||
updateBig.totalSizeLimit = _mediaSizeLimit;
|
||||
updateBig.totalTimeLimit = _timeLimit;
|
||||
Local::updateCacheSettings(update, updateBig);
|
||||
_session->local().updateCacheSettings(update, updateBig);
|
||||
_session->data().cache().updateSettings(update);
|
||||
closeBox();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
#include "main/main_session.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "main/main_domain.h"
|
||||
#include "core/application.h"
|
||||
#include "storage/storage_domain.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
@@ -48,7 +50,7 @@ PasscodeBox::PasscodeBox(
|
||||
not_null<Main::Session*> session,
|
||||
bool turningOff)
|
||||
: _session(session)
|
||||
, _api(_session->api().instance())
|
||||
, _api(&_session->mtp())
|
||||
, _turningOff(turningOff)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, tr::lng_passcode_enter_old())
|
||||
@@ -64,7 +66,7 @@ PasscodeBox::PasscodeBox(
|
||||
not_null<Main::Session*> session,
|
||||
const CloudFields &fields)
|
||||
: _session(session)
|
||||
, _api(_session->api().instance())
|
||||
, _api(&_session->mtp())
|
||||
, _turningOff(fields.turningOff)
|
||||
, _cloudPwd(true)
|
||||
, _cloudFields(fields)
|
||||
@@ -450,7 +452,7 @@ void PasscodeBox::save(bool force) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Local::checkPasscode(old.toUtf8())) {
|
||||
if (Core::App().domain().local().checkPasscode(old.toUtf8())) {
|
||||
cSetPasscodeBadTries(0);
|
||||
if (_turningOff) pwd = conf = QString();
|
||||
} else {
|
||||
@@ -518,8 +520,8 @@ void PasscodeBox::save(bool force) {
|
||||
closeReplacedBy();
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
cSetPasscodeBadTries(0);
|
||||
Local::setPasscode(pwd.toUtf8());
|
||||
_session->localPasscodeChanged();
|
||||
Core::App().domain().local().setPasscode(pwd.toUtf8());
|
||||
Core::App().localPasscodeChanged();
|
||||
if (weak) {
|
||||
closeBox();
|
||||
}
|
||||
@@ -683,7 +685,7 @@ void PasscodeBox::setNewCloudPassword(const QString &newPassword) {
|
||||
setPasswordDone(newPasswordBytes);
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(newPasswordBytes, email, error);
|
||||
}).send();
|
||||
}).handleFloodErrors().send();
|
||||
}
|
||||
|
||||
void PasscodeBox::changeCloudPassword(
|
||||
@@ -736,9 +738,9 @@ void PasscodeBox::changeCloudPassword(
|
||||
sendChangeCloudPassword(check, newPassword, secureSecret);
|
||||
});
|
||||
}
|
||||
}).handleFloodErrors().fail([=](const RPCError &error) {
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(error);
|
||||
}).send();
|
||||
}).handleFloodErrors().send();
|
||||
}
|
||||
|
||||
void PasscodeBox::suggestSecretReset(const QString &newPassword) {
|
||||
@@ -831,9 +833,9 @@ void PasscodeBox::sendChangeCloudPassword(
|
||||
MTP_long(newSecureSecretId)))
|
||||
)).done([=](const MTPBool &result) {
|
||||
setPasswordDone(newPasswordBytes);
|
||||
}).handleFloodErrors().fail([=](const RPCError &error) {
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(newPasswordBytes, QString(), error);
|
||||
}).send();
|
||||
}).handleFloodErrors().send();
|
||||
}
|
||||
|
||||
void PasscodeBox::badOldPasscode() {
|
||||
@@ -895,13 +897,14 @@ void PasscodeBox::recover() {
|
||||
if (_pattern == "-") return;
|
||||
|
||||
const auto box = getDelegate()->show(Box<RecoverBox>(
|
||||
_session,
|
||||
_pattern,
|
||||
_cloudFields.notEmptyPassport));
|
||||
|
||||
box->passwordCleared(
|
||||
) | rpl::map([] {
|
||||
return QByteArray();
|
||||
}) | rpl::start_to_stream(_newPasswordSet, lifetime());
|
||||
) | rpl::map_to(
|
||||
QByteArray()
|
||||
) | rpl::start_to_stream(_newPasswordSet, lifetime());
|
||||
|
||||
box->recoveryExpired(
|
||||
) | rpl::start_with_next([=] {
|
||||
@@ -923,9 +926,11 @@ void PasscodeBox::recoverStartFail(const RPCError &error) {
|
||||
|
||||
RecoverBox::RecoverBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const QString &pattern,
|
||||
bool notEmptyPassport)
|
||||
: _pattern(st::normalFont->elided(tr::lng_signin_recover_hint(tr::now, lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
|
||||
: _api(&session->mtp())
|
||||
, _pattern(st::normalFont->elided(tr::lng_signin_recover_hint(tr::now, lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
|
||||
, _notEmptyPassport(notEmptyPassport)
|
||||
, _recoverCode(this, st::defaultInputField, tr::lng_signin_code()) {
|
||||
}
|
||||
@@ -988,10 +993,13 @@ void RecoverBox::submit() {
|
||||
}
|
||||
|
||||
const auto send = crl::guard(this, [=] {
|
||||
_submitRequest = MTP::send(
|
||||
MTPauth_RecoverPassword(MTP_string(code)),
|
||||
rpcDone(&RecoverBox::codeSubmitDone, true),
|
||||
rpcFail(&RecoverBox::codeSubmitFail));
|
||||
_submitRequest = _api.request(MTPauth_RecoverPassword(
|
||||
MTP_string(code)
|
||||
)).done([=](const MTPauth_Authorization &result) {
|
||||
codeSubmitDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
codeSubmitFail(error);
|
||||
}).handleFloodErrors().send();
|
||||
});
|
||||
if (_notEmptyPassport) {
|
||||
const auto box = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||
@@ -1015,9 +1023,7 @@ void RecoverBox::codeChanged() {
|
||||
update();
|
||||
}
|
||||
|
||||
void RecoverBox::codeSubmitDone(
|
||||
bool recover,
|
||||
const MTPauth_Authorization &result) {
|
||||
void RecoverBox::codeSubmitDone(const MTPauth_Authorization &result) {
|
||||
_submitRequest = 0;
|
||||
|
||||
_passwordCleared.fire({});
|
||||
@@ -1026,16 +1032,14 @@ void RecoverBox::codeSubmitDone(
|
||||
Ui::LayerOption::CloseOther);
|
||||
}
|
||||
|
||||
bool RecoverBox::codeSubmitFail(const RPCError &error) {
|
||||
void RecoverBox::codeSubmitFail(const RPCError &error) {
|
||||
if (MTP::isFloodError(error)) {
|
||||
_submitRequest = 0;
|
||||
_error = tr::lng_flood_error(tr::now);
|
||||
update();
|
||||
_recoverCode->showError();
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
_submitRequest = 0;
|
||||
|
||||
const QString &err = error.type();
|
||||
@@ -1044,33 +1048,31 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) {
|
||||
getDelegate()->show(
|
||||
Box<InformBox>(tr::lng_cloud_password_removed(tr::now)),
|
||||
Ui::LayerOption::CloseOther);
|
||||
return true;
|
||||
} else if (err == qstr("PASSWORD_RECOVERY_NA")) {
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == qstr("PASSWORD_RECOVERY_EXPIRED")) {
|
||||
_recoveryExpired.fire({});
|
||||
closeBox();
|
||||
return true;
|
||||
} else if (err == qstr("CODE_INVALID")) {
|
||||
_error = tr::lng_signin_wrong_code(tr::now);
|
||||
update();
|
||||
_recoverCode->selectAll();
|
||||
_recoverCode->setFocus();
|
||||
_recoverCode->showError();
|
||||
return true;
|
||||
}
|
||||
if (Logs::DebugEnabled()) { // internal server error
|
||||
_error = err + ": " + error.description();
|
||||
} else {
|
||||
_error = Lang::Hard::ServerError();
|
||||
if (Logs::DebugEnabled()) { // internal server error
|
||||
_error = err + ": " + error.description();
|
||||
} else {
|
||||
_error = Lang::Hard::ServerError();
|
||||
}
|
||||
update();
|
||||
_recoverCode->setFocus();
|
||||
}
|
||||
update();
|
||||
_recoverCode->setFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern) {
|
||||
RecoveryEmailValidation ConfirmRecoveryEmail(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &pattern) {
|
||||
const auto errors = std::make_shared<rpl::event_stream<QString>>();
|
||||
const auto resent = std::make_shared<rpl::event_stream<QString>>();
|
||||
const auto requestId = std::make_shared<mtpRequestId>(0);
|
||||
@@ -1082,7 +1084,9 @@ RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern) {
|
||||
if (*requestId) {
|
||||
return;
|
||||
}
|
||||
const auto done = [=](const MTPBool &result) {
|
||||
*requestId = session->api().request(MTPaccount_ConfirmPasswordEmail(
|
||||
MTP_string(code)
|
||||
)).done([=](const MTPBool &result) {
|
||||
*requestId = 0;
|
||||
reloads->fire({});
|
||||
if (*weak) {
|
||||
@@ -1090,13 +1094,7 @@ RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern) {
|
||||
Box<InformBox>(tr::lng_cloud_password_was_set(tr::now)),
|
||||
Ui::LayerOption::CloseOther);
|
||||
}
|
||||
};
|
||||
const auto fail = [=](const RPCError &error) {
|
||||
const auto skip = MTP::isDefaultHandledError(error)
|
||||
&& !MTP::isFloodError(error);
|
||||
if (skip) {
|
||||
return false;
|
||||
}
|
||||
}).fail([=](const RPCError &error) {
|
||||
*requestId = 0;
|
||||
if (MTP::isFloodError(error)) {
|
||||
errors->fire(tr::lng_flood_error(tr::now));
|
||||
@@ -1114,26 +1112,20 @@ RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern) {
|
||||
} else {
|
||||
errors->fire(Lang::Hard::ServerError());
|
||||
}
|
||||
return true;
|
||||
};
|
||||
*requestId = MTP::send(
|
||||
MTPaccount_ConfirmPasswordEmail(MTP_string(code)),
|
||||
rpcDone(done),
|
||||
rpcFail(fail));
|
||||
}).handleFloodErrors().send();
|
||||
};
|
||||
const auto resend = [=] {
|
||||
if (*requestId) {
|
||||
return;
|
||||
}
|
||||
*requestId = MTP::send(MTPaccount_ResendPasswordEmail(
|
||||
), rpcDone([=](const MTPBool &result) {
|
||||
*requestId = session->api().request(MTPaccount_ResendPasswordEmail(
|
||||
)).done([=](const MTPBool &result) {
|
||||
*requestId = 0;
|
||||
resent->fire(tr::lng_cloud_password_resent(tr::now));
|
||||
}), rpcFail([=](const RPCError &error) {
|
||||
}).fail([=](const RPCError &error) {
|
||||
*requestId = 0;
|
||||
errors->fire(Lang::Hard::ServerError());
|
||||
return true;
|
||||
}));
|
||||
}).send();
|
||||
};
|
||||
|
||||
auto box = Passport::VerifyEmailBox(
|
||||
|
||||
@@ -164,9 +164,13 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class RecoverBox : public Ui::BoxContent, public RPCSender {
|
||||
class RecoverBox final : public Ui::BoxContent {
|
||||
public:
|
||||
RecoverBox(QWidget*, const QString &pattern, bool notEmptyPassport);
|
||||
RecoverBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const QString &pattern,
|
||||
bool notEmptyPassport);
|
||||
|
||||
rpl::producer<> passwordCleared() const;
|
||||
rpl::producer<> recoveryExpired() const;
|
||||
@@ -184,9 +188,10 @@ protected:
|
||||
private:
|
||||
void submit();
|
||||
void codeChanged();
|
||||
void codeSubmitDone(bool recover, const MTPauth_Authorization &result);
|
||||
bool codeSubmitFail(const RPCError &error);
|
||||
void codeSubmitDone(const MTPauth_Authorization &result);
|
||||
void codeSubmitFail(const RPCError &error);
|
||||
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _submitRequest = 0;
|
||||
|
||||
QString _pattern;
|
||||
@@ -206,4 +211,6 @@ struct RecoveryEmailValidation {
|
||||
rpl::producer<> reloadRequests;
|
||||
rpl::producer<> cancelRequests;
|
||||
};
|
||||
RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern);
|
||||
[[nodiscard]] RecoveryEmailValidation ConfirmRecoveryEmail(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &pattern);
|
||||
|
||||
@@ -19,11 +19,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "observer_peer.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "styles/style_layers.h"
|
||||
@@ -662,19 +662,23 @@ PeerListContent::PeerListContent(
|
||||
, _st(st)
|
||||
, _controller(controller)
|
||||
, _rowHeight(_st.item.height) {
|
||||
subscribe(_controller->session().downloaderTaskFinished(), [=] {
|
||||
_controller->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
});
|
||||
}, lifetime());
|
||||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
auto changes = UpdateFlag::NameChanged | UpdateFlag::PhotoChanged;
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(changes, [this](const Notify::PeerUpdate &update) {
|
||||
if (update.flags & UpdateFlag::PhotoChanged) {
|
||||
this->update();
|
||||
} else if (update.flags & UpdateFlag::NameChanged) {
|
||||
handleNameChanged(update);
|
||||
using UpdateFlag = Data::PeerUpdate::Flag;
|
||||
_controller->session().changes().peerUpdates(
|
||||
UpdateFlag::Name | UpdateFlag::Photo
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
if (update.flags & UpdateFlag::Name) {
|
||||
handleNameChanged(update.peer);
|
||||
}
|
||||
}));
|
||||
if (update.flags & UpdateFlag::Photo) {
|
||||
this->update();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
||||
if (update.paletteChanged()) {
|
||||
invalidatePixmapsCache();
|
||||
@@ -1295,7 +1299,6 @@ crl::time PeerListContent::paintRow(
|
||||
p.drawTextLeft(_st.item.statusPosition.x(), _st.item.statusPosition.y(), width(), highlightedPart);
|
||||
} else {
|
||||
grayedPart = st::contactsStatusFont->elided(grayedPart, availableWidth - highlightedWidth);
|
||||
auto grayedWidth = st::contactsStatusFont->width(grayedPart);
|
||||
p.setPen(_st.item.statusFgActive);
|
||||
p.drawTextLeft(_st.item.statusPosition.x(), _st.item.statusPosition.y(), width(), highlightedPart);
|
||||
p.setPen(selected ? _st.item.statusFgOver : _st.item.statusFg);
|
||||
@@ -1717,8 +1720,8 @@ PeerListContent::RowIndex PeerListContent::findRowIndex(
|
||||
return result;
|
||||
}
|
||||
|
||||
void PeerListContent::handleNameChanged(const Notify::PeerUpdate &update) {
|
||||
auto byPeer = _rowsByPeer.find(update.peer);
|
||||
void PeerListContent::handleNameChanged(not_null<PeerData*> peer) {
|
||||
auto byPeer = _rowsByPeer.find(peer);
|
||||
if (byPeer != _rowsByPeer.cend()) {
|
||||
for (auto row : byPeer->second) {
|
||||
if (addingToSearchIndex()) {
|
||||
|
||||
@@ -34,10 +34,6 @@ struct ScrollToRequest;
|
||||
class PopupMenu;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Notify {
|
||||
struct PeerUpdate;
|
||||
} // namespace Notify
|
||||
|
||||
using PaintRoundImageCallback = Fn<void(
|
||||
Painter &p,
|
||||
int x,
|
||||
@@ -551,7 +547,7 @@ protected:
|
||||
private:
|
||||
void refreshIndices();
|
||||
void removeRowAtIndex(std::vector<std::unique_ptr<PeerListRow>> &from, int index);
|
||||
void handleNameChanged(const Notify::PeerUpdate &update);
|
||||
void handleNameChanged(not_null<PeerData*> peer);
|
||||
|
||||
void invalidatePixmapsCache();
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "observer_peer.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "main/main_session.h"
|
||||
@@ -147,7 +146,7 @@ void PeerListRowWithLink::paintAction(
|
||||
PeerListGlobalSearchController::PeerListGlobalSearchController(
|
||||
not_null<Window::SessionNavigation*> navigation)
|
||||
: _navigation(navigation)
|
||||
, _api(_navigation->session().api().instance()) {
|
||||
, _api(&_navigation->session().mtp()) {
|
||||
_timer.setCallback([this] { searchOnServer(); });
|
||||
}
|
||||
|
||||
|
||||
@@ -15,16 +15,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "history/history.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "apiwrap.h"
|
||||
#include "observer_peer.h"
|
||||
#include "facades.h"
|
||||
#include "facades.h" // Ui::showPeerHistory
|
||||
#include "app.h"
|
||||
|
||||
namespace {
|
||||
@@ -87,10 +88,11 @@ void AddParticipantsBoxController::subscribeToMigration() {
|
||||
}
|
||||
|
||||
void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
const auto &serverConfig = session().serverConfig();
|
||||
auto count = fullCount();
|
||||
auto limit = _peer && (_peer->isChat() || _peer->isMegagroup())
|
||||
? Global::MegagroupSizeMax()
|
||||
: Global::ChatSizeMax();
|
||||
? serverConfig.megagroupSizeMax
|
||||
: serverConfig.chatSizeMax;
|
||||
if (count < limit || row->checked()) {
|
||||
delegate()->peerListSetRowChecked(row, !row->checked());
|
||||
updateTitle();
|
||||
@@ -100,8 +102,8 @@ void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
Box<MaxInviteBox>(_peer->asChannel()),
|
||||
Ui::LayerOption::KeepOther);
|
||||
}
|
||||
} else if (count >= Global::ChatSizeMax()
|
||||
&& count < Global::MegagroupSizeMax()) {
|
||||
} else if (count >= serverConfig.chatSizeMax
|
||||
&& count < serverConfig.megagroupSizeMax) {
|
||||
Ui::show(
|
||||
Box<InformBox>(tr::lng_profile_add_more_after_create(tr::now)),
|
||||
Ui::LayerOption::KeepOther);
|
||||
@@ -166,7 +168,9 @@ void AddParticipantsBoxController::updateTitle() {
|
||||
&& _peer->isChannel()
|
||||
&& !_peer->isMegagroup())
|
||||
? QString()
|
||||
: qsl("%1 / %2").arg(fullCount()).arg(Global::MegagroupSizeMax());
|
||||
: qsl("%1 / %2"
|
||||
).arg(fullCount()
|
||||
).arg(session().serverConfig().megagroupSizeMax);
|
||||
delegate()->peerListSetTitle(tr::lng_profile_add_participant());
|
||||
delegate()->peerListSetAdditionalTitle(rpl::single(additional));
|
||||
}
|
||||
@@ -240,7 +244,7 @@ void AddParticipantsBoxController::Start(
|
||||
box->boxClosing() | rpl::start_with_next([=] {
|
||||
auto params = Window::SectionShow();
|
||||
params.activation = anim::activation::background;
|
||||
App::wnd()->sessionController()->showPeerHistory(
|
||||
navigation->parentController()->showPeerHistory(
|
||||
channel,
|
||||
params,
|
||||
ShowAtTheEndMsgId);
|
||||
@@ -276,7 +280,7 @@ AddSpecialBoxController::AddSpecialBoxController(
|
||||
peer,
|
||||
&_additional))
|
||||
, _peer(peer)
|
||||
, _api(_peer->session().api().instance())
|
||||
, _api(&_peer->session().mtp())
|
||||
, _role(role)
|
||||
, _additional(peer, Role::Members)
|
||||
, _adminDoneCallback(std::move(adminDoneCallback))
|
||||
@@ -348,17 +352,16 @@ void AddSpecialBoxController::prepareChatRows(not_null<ChatData*> chat) {
|
||||
chat->updateFullForced();
|
||||
}
|
||||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
|
||||
UpdateFlag::MembersChanged | UpdateFlag::AdminsChanged,
|
||||
[=](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == chat) {
|
||||
_additional.fillFromPeer();
|
||||
if (update.flags & UpdateFlag::MembersChanged) {
|
||||
rebuildChatRows(chat);
|
||||
}
|
||||
}
|
||||
}));
|
||||
using UpdateFlag = Data::PeerUpdate::Flag;
|
||||
chat->session().changes().peerUpdates(
|
||||
chat,
|
||||
UpdateFlag::Members | UpdateFlag::Admins
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
_additional.fillFromPeer();
|
||||
if (update.flags & UpdateFlag::Members) {
|
||||
rebuildChatRows(chat);
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void AddSpecialBoxController::rebuildChatRows(not_null<ChatData*> chat) {
|
||||
@@ -651,8 +654,6 @@ void AddSpecialBoxController::showRestricted(
|
||||
_editParticipantBox->closeBox();
|
||||
}
|
||||
|
||||
const auto chat = _peer->asChat();
|
||||
const auto channel = _peer->asChannel();
|
||||
const auto showRestrictedSure = crl::guard(this, [=] {
|
||||
showRestricted(user, true);
|
||||
});
|
||||
@@ -830,7 +831,7 @@ AddSpecialBoxSearchController::AddSpecialBoxSearchController(
|
||||
not_null<ParticipantsAdditionalData*> additional)
|
||||
: _peer(peer)
|
||||
, _additional(additional)
|
||||
, _api(_peer->session().api().instance())
|
||||
, _api(&_peer->session().mtp())
|
||||
, _timer([=] { searchOnServer(); }) {
|
||||
subscribeToMigration();
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class Controller {
|
||||
public:
|
||||
Controller(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::Controller*> window,
|
||||
not_null<Window::SessionController*> window,
|
||||
not_null<UserData*> user);
|
||||
|
||||
void prepare();
|
||||
@@ -100,7 +100,7 @@ private:
|
||||
bool inverted);
|
||||
|
||||
not_null<Ui::GenericBox*> _box;
|
||||
not_null<Window::Controller*> _window;
|
||||
not_null<Window::SessionController*> _window;
|
||||
not_null<UserData*> _user;
|
||||
Ui::Checkbox *_sharePhone = nullptr;
|
||||
QString _phone;
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
|
||||
Controller::Controller(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::Controller*> window,
|
||||
not_null<Window::SessionController*> window,
|
||||
not_null<UserData*> user)
|
||||
: _box(box)
|
||||
, _window(window)
|
||||
@@ -143,7 +143,7 @@ void Controller::setupCover() {
|
||||
object_ptr<Info::Profile::Cover>(
|
||||
_box,
|
||||
_user,
|
||||
_window->sessionController(),
|
||||
_window,
|
||||
(_phone.isEmpty()
|
||||
? tr::lng_contact_mobile_hidden()
|
||||
: rpl::single(App::formatPhone(_phone)))),
|
||||
@@ -266,7 +266,7 @@ void Controller::setupSharePhoneNumber() {
|
||||
|
||||
void EditContactBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::Controller*> window,
|
||||
not_null<Window::SessionController*> window,
|
||||
not_null<UserData*> user) {
|
||||
box->lifetime().make_state<Controller>(box, window, user)->prepare();
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
class UserData;
|
||||
|
||||
namespace Window {
|
||||
class Controller;
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
void EditContactBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::Controller*> window,
|
||||
not_null<Window::SessionController*> window,
|
||||
not_null<UserData*> user);
|
||||
|
||||
@@ -35,7 +35,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "core/core_cloud_password.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "apiwrap.h"
|
||||
#include "facades.h"
|
||||
#include "main/main_session.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
@@ -13,22 +13,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/add_contact_box.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
#include "apiwrap.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "observer_peer.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "history/history.h"
|
||||
#include "facades.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -286,20 +286,19 @@ void SubscribeToMigration(
|
||||
if (const auto channel = peer->migrateTo()) {
|
||||
migrate(channel);
|
||||
} else if (!chat->isDeactivated()) {
|
||||
const auto alive = lifetime.make_state<base::Subscription>();
|
||||
const auto handler = [=](const Notify::PeerUpdate &update) {
|
||||
if (update.peer == peer) {
|
||||
if (const auto channel = peer->migrateTo()) {
|
||||
const auto onstack = base::duplicate(migrate);
|
||||
*alive = base::Subscription();
|
||||
onstack(channel);
|
||||
}
|
||||
}
|
||||
};
|
||||
*alive = Notify::PeerUpdated().add_subscription(
|
||||
Notify::PeerUpdatedHandler(
|
||||
Notify::PeerUpdate::Flag::MigrationChanged,
|
||||
handler));
|
||||
chat->session().changes().peerUpdates(
|
||||
peer,
|
||||
Data::PeerUpdate::Flag::Migration
|
||||
) | rpl::map([](const Data::PeerUpdate &update) {
|
||||
return update.peer->migrateTo();
|
||||
}) | rpl::filter([](ChannelData *channel) {
|
||||
return (channel != nullptr);
|
||||
}) | rpl::take(
|
||||
1
|
||||
) | rpl::start_with_next([=](not_null<ChannelData*> channel) {
|
||||
const auto onstack = base::duplicate(migrate);
|
||||
onstack(channel);
|
||||
}, lifetime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -686,17 +685,15 @@ ParticipantsOnlineSorter::ParticipantsOnlineSorter(
|
||||
: _peer(peer)
|
||||
, _delegate(delegate)
|
||||
, _sortByOnlineTimer([=] { sort(); }) {
|
||||
const auto handleUpdate = [=](const Notify::PeerUpdate &update) {
|
||||
peer->session().changes().peerUpdates(
|
||||
Data::PeerUpdate::Flag::OnlineStatus
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
const auto peerId = update.peer->id;
|
||||
if (const auto row = _delegate->peerListFindRow(peerId)) {
|
||||
row->refreshStatus();
|
||||
sortDelayed();
|
||||
}
|
||||
};
|
||||
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
|
||||
Notify::PeerUpdate::Flag::UserOnlineChanged,
|
||||
handleUpdate));
|
||||
}, _lifetime);
|
||||
sort();
|
||||
}
|
||||
|
||||
@@ -710,7 +707,8 @@ void ParticipantsOnlineSorter::sort() {
|
||||
const auto channel = _peer->asChannel();
|
||||
if (channel
|
||||
&& (!channel->isMegagroup()
|
||||
|| channel->membersCount() > Global::ChatSizeMax())) {
|
||||
|| (channel->membersCount()
|
||||
> channel->session().serverConfig().chatSizeMax))) {
|
||||
_onlineCount = 0;
|
||||
return;
|
||||
}
|
||||
@@ -755,7 +753,7 @@ ParticipantsBoxController::ParticipantsBoxController(
|
||||
: PeerListController(CreateSearchController(peer, role, &_additional))
|
||||
, _navigation(navigation)
|
||||
, _peer(peer)
|
||||
, _api(_peer->session().api().instance())
|
||||
, _api(&_peer->session().mtp())
|
||||
, _role(role)
|
||||
, _additional(peer, _role) {
|
||||
subscribeToMigration();
|
||||
@@ -847,8 +845,9 @@ void ParticipantsBoxController::Start(
|
||||
return chat
|
||||
? chat->canAddMembers()
|
||||
: (channel->canAddMembers()
|
||||
&& (channel->membersCount() < Global::ChatSizeMax()
|
||||
|| channel->isMegagroup()));
|
||||
&& (channel->isMegagroup()
|
||||
|| (channel->membersCount()
|
||||
< channel->session().serverConfig().chatSizeMax)));
|
||||
case Role::Admins:
|
||||
return chat
|
||||
? chat->canAddAdmins()
|
||||
@@ -927,7 +926,8 @@ void ParticipantsBoxController::addNewParticipants() {
|
||||
if (chat) {
|
||||
AddParticipantsBoxController::Start(_navigation, chat);
|
||||
} else if (channel->isMegagroup()
|
||||
|| channel->membersCount() < Global::ChatSizeMax()) {
|
||||
|| (channel->membersCount()
|
||||
< channel->session().serverConfig().chatSizeMax)) {
|
||||
const auto count = delegate()->peerListFullRowsCount();
|
||||
auto already = std::vector<not_null<UserData*>>();
|
||||
already.reserve(count);
|
||||
@@ -985,10 +985,10 @@ auto ParticipantsBoxController::saveState() const
|
||||
|
||||
const auto weak = result.get();
|
||||
if (const auto chat = _peer->asChat()) {
|
||||
Notify::PeerUpdateViewer(
|
||||
chat->session().changes().peerUpdates(
|
||||
chat,
|
||||
Notify::PeerUpdate::Flag::MembersChanged
|
||||
) | rpl::start_with_next([=](const Notify::PeerUpdate &) {
|
||||
Data::PeerUpdate::Flag::Members
|
||||
) | rpl::start_with_next([=] {
|
||||
weak->controllerState = nullptr;
|
||||
}, my->lifetime);
|
||||
} else if (const auto channel = _peer->asMegagroup()) {
|
||||
@@ -1104,23 +1104,20 @@ void ParticipantsBoxController::prepareChatRows(not_null<ChatData*> chat) {
|
||||
chat->updateFullForced();
|
||||
}
|
||||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
|
||||
UpdateFlag::MembersChanged
|
||||
| UpdateFlag::AdminsChanged,
|
||||
[=](const Notify::PeerUpdate &update) {
|
||||
if (update.peer != chat) {
|
||||
return;
|
||||
}
|
||||
_additional.fillFromPeer();
|
||||
if ((update.flags & UpdateFlag::MembersChanged)
|
||||
|| (_role == Role::Admins)) {
|
||||
rebuildChatRows(chat);
|
||||
}
|
||||
if (update.flags & UpdateFlag::AdminsChanged) {
|
||||
rebuildRowTypes();
|
||||
}
|
||||
}));
|
||||
using UpdateFlag = Data::PeerUpdate::Flag;
|
||||
chat->session().changes().peerUpdates(
|
||||
chat,
|
||||
UpdateFlag::Members | UpdateFlag::Admins
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
_additional.fillFromPeer();
|
||||
if ((update.flags & UpdateFlag::Members)
|
||||
|| (_role == Role::Admins)) {
|
||||
rebuildChatRows(chat);
|
||||
}
|
||||
if (update.flags & UpdateFlag::Admins) {
|
||||
rebuildRowTypes();
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void ParticipantsBoxController::rebuildChatRows(not_null<ChatData*> chat) {
|
||||
@@ -1893,7 +1890,7 @@ void ParticipantsBoxController::subscribeToCreatorChange(
|
||||
channel->inputChannel,
|
||||
MTP_channelParticipantsRecent(),
|
||||
MTP_int(0),
|
||||
MTP_int(Global::ChatSizeMax()),
|
||||
MTP_int(channel->session().serverConfig().chatSizeMax),
|
||||
MTP_int(0)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
if (channel->amCreator()) {
|
||||
@@ -1928,7 +1925,7 @@ ParticipantsBoxSearchController::ParticipantsBoxSearchController(
|
||||
: _channel(channel)
|
||||
, _role(role)
|
||||
, _additional(additional)
|
||||
, _api(_channel->session().api().instance()) {
|
||||
, _api(&_channel->session().mtp()) {
|
||||
_timer.setCallback([=] { searchOnServer(); });
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ enum class ParticipantsRole {
|
||||
Kicked,
|
||||
};
|
||||
|
||||
class ParticipantsOnlineSorter : private base::Subscriber {
|
||||
class ParticipantsOnlineSorter {
|
||||
public:
|
||||
ParticipantsOnlineSorter(
|
||||
not_null<PeerData*> peer,
|
||||
@@ -63,10 +63,11 @@ private:
|
||||
void sortDelayed();
|
||||
void refreshOnlineCount();
|
||||
|
||||
not_null<PeerData*> _peer;
|
||||
not_null<PeerListDelegate*> _delegate;
|
||||
const not_null<PeerData*> _peer;
|
||||
const not_null<PeerListDelegate*> _delegate;
|
||||
base::Timer _sortByOnlineTimer;
|
||||
rpl::variable<int> _onlineCount = 0;
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/peers/edit_linked_chat_box.h"
|
||||
#include "boxes/stickers_box.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_peer.h"
|
||||
@@ -29,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "observer_peer.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "ui/toast/toast.h"
|
||||
@@ -192,9 +193,11 @@ void SaveSlowmodeSeconds(
|
||||
api->registerModifyRequest(key, requestId);
|
||||
}
|
||||
|
||||
void ShowEditPermissions(not_null<PeerData*> peer) {
|
||||
void ShowEditPermissions(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> peer) {
|
||||
const auto box = Ui::show(
|
||||
Box<EditPeerPermissionsBox>(peer),
|
||||
Box<EditPeerPermissionsBox>(navigation, peer),
|
||||
Ui::LayerOption::KeepOther);
|
||||
const auto saving = box->lifetime().make_state<int>(0);
|
||||
const auto save = [=](
|
||||
@@ -356,7 +359,7 @@ Controller::Controller(
|
||||
: _navigation(navigation)
|
||||
, _box(box)
|
||||
, _peer(peer)
|
||||
, _api(_peer->session().api().instance())
|
||||
, _api(&_peer->session().mtp())
|
||||
, _isGroup(_peer->isChat() || _peer->isMegagroup()) {
|
||||
_box->setTitle(_isGroup
|
||||
? tr::lng_edit_group()
|
||||
@@ -465,7 +468,7 @@ object_ptr<Ui::RpWidget> Controller::createTitleEdit() {
|
||||
result->entity()->setMaxLength(kMaxGroupChannelTitle);
|
||||
result->entity()->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
result->entity()->setInstantReplacesEnabled(
|
||||
_peer->session().settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
Ui::Emoji::SuggestionsController::Init(
|
||||
_wrap->window(),
|
||||
result->entity(),
|
||||
@@ -499,8 +502,8 @@ object_ptr<Ui::RpWidget> Controller::createDescriptionEdit() {
|
||||
result->entity()->setMaxLength(kMaxChannelDescription);
|
||||
result->entity()->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
result->entity()->setInstantReplacesEnabled(
|
||||
_peer->session().settings().replaceEmojiValue());
|
||||
result->entity()->setSubmitSettings(_peer->session().settings().sendSubmitWay());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
result->entity()->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
||||
Ui::Emoji::SuggestionsController::Init(
|
||||
_wrap->window(),
|
||||
result->entity(),
|
||||
@@ -561,7 +564,9 @@ object_ptr<Ui::RpWidget> Controller::createStickersEdit() {
|
||||
tr::lng_group_stickers_add(tr::now),
|
||||
st::editPeerInviteLinkButton)
|
||||
)->addClickHandler([=] {
|
||||
Ui::show(Box<StickersBox>(channel), Ui::LayerOption::KeepOther);
|
||||
Ui::show(
|
||||
Box<StickersBox>(_navigation->parentController(), channel),
|
||||
Ui::LayerOption::KeepOther);
|
||||
});
|
||||
|
||||
return result;
|
||||
@@ -830,8 +835,6 @@ void Controller::fillHistoryVisibilityButton() {
|
||||
void Controller::fillManageSection() {
|
||||
Expects(_controls.buttonsLayout != nullptr);
|
||||
|
||||
const auto navigation = App::wnd()->sessionController();
|
||||
|
||||
const auto chat = _peer->asChat();
|
||||
const auto channel = _peer->asChannel();
|
||||
const auto isChannel = (!chat);
|
||||
@@ -943,7 +946,7 @@ void Controller::fillManageSection() {
|
||||
Info::Profile::RestrictionsCountValue
|
||||
) | rpl::flatten_latest(
|
||||
) | ToPositiveNumberStringRestrictions(),
|
||||
[=] { ShowEditPermissions(_peer); },
|
||||
[=] { ShowEditPermissions(_navigation, _peer); },
|
||||
st::infoIconPermissions);
|
||||
}
|
||||
if (canViewAdmins) {
|
||||
@@ -958,7 +961,7 @@ void Controller::fillManageSection() {
|
||||
) | ToPositiveNumberString(),
|
||||
[=] {
|
||||
ParticipantsBoxController::Start(
|
||||
navigation,
|
||||
_navigation,
|
||||
_peer,
|
||||
ParticipantsBoxController::Role::Admins);
|
||||
},
|
||||
@@ -976,7 +979,7 @@ void Controller::fillManageSection() {
|
||||
) | ToPositiveNumberString(),
|
||||
[=] {
|
||||
ParticipantsBoxController::Start(
|
||||
navigation,
|
||||
_navigation,
|
||||
_peer,
|
||||
ParticipantsBoxController::Role::Members);
|
||||
},
|
||||
@@ -990,7 +993,7 @@ void Controller::fillManageSection() {
|
||||
| ToPositiveNumberString(),
|
||||
[=] {
|
||||
ParticipantsBoxController::Start(
|
||||
navigation,
|
||||
_navigation,
|
||||
_peer,
|
||||
ParticipantsBoxController::Role::Kicked);
|
||||
},
|
||||
@@ -1002,7 +1005,7 @@ void Controller::fillManageSection() {
|
||||
tr::lng_manage_peer_recent_actions(),
|
||||
rpl::single(QString()), //Empty count.
|
||||
[=] {
|
||||
navigation->showSection(AdminLog::SectionMemento(channel));
|
||||
_navigation->showSection(AdminLog::SectionMemento(channel));
|
||||
},
|
||||
st::infoIconRecentActions);
|
||||
}
|
||||
@@ -1440,15 +1443,22 @@ void Controller::deleteChannel() {
|
||||
const auto channel = _peer->asChannel();
|
||||
const auto chat = channel->migrateFrom();
|
||||
|
||||
const auto session = &_peer->session();
|
||||
|
||||
Ui::hideLayer();
|
||||
Ui::showChatsList();
|
||||
Ui::showChatsList(session);
|
||||
if (chat) {
|
||||
chat->session().api().deleteConversation(chat, false);
|
||||
session->api().deleteConversation(chat, false);
|
||||
}
|
||||
MTP::send(
|
||||
MTPchannels_DeleteChannel(channel->inputChannel),
|
||||
App::main()->rpcDone(&MainWidget::sentUpdatesReceived),
|
||||
App::main()->rpcFail(&MainWidget::deleteChannelFailed));
|
||||
session->api().request(MTPchannels_DeleteChannel(
|
||||
channel->inputChannel
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
session->api().applyUpdates(result);
|
||||
//}).fail([=](const RPCError &error) {
|
||||
// if (error.type() == qstr("CHANNEL_TOO_LARGE")) {
|
||||
// Ui::show(Box<InformBox>(tr::lng_cant_delete_channel(tr::now)));
|
||||
// }
|
||||
}).send();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -307,8 +307,10 @@ ChatAdminRights FullAdminRights(bool isGroup) {
|
||||
|
||||
EditPeerPermissionsBox::EditPeerPermissionsBox(
|
||||
QWidget*,
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> peer)
|
||||
: _peer(peer->migrateToOrMe()) {
|
||||
: _navigation(navigation)
|
||||
, _peer(peer->migrateToOrMe()) {
|
||||
}
|
||||
|
||||
auto EditPeerPermissionsBox::saveEvents() const -> rpl::producer<Result> {
|
||||
@@ -522,8 +524,6 @@ void EditPeerPermissionsBox::addBannedButtons(
|
||||
}
|
||||
}
|
||||
const auto channel = _peer->asChannel();
|
||||
|
||||
const auto navigation = App::wnd()->sessionController();
|
||||
container->add(EditPeerInfoBox::CreateButton(
|
||||
container,
|
||||
tr::lng_manage_peer_exceptions(),
|
||||
@@ -532,7 +532,7 @@ void EditPeerPermissionsBox::addBannedButtons(
|
||||
: rpl::single(0)) | ToPositiveNumberString(),
|
||||
[=] {
|
||||
ParticipantsBoxController::Start(
|
||||
navigation,
|
||||
_navigation,
|
||||
_peer,
|
||||
ParticipantsBoxController::Role::Restricted);
|
||||
},
|
||||
@@ -545,7 +545,7 @@ void EditPeerPermissionsBox::addBannedButtons(
|
||||
| ToPositiveNumberString(),
|
||||
[=] {
|
||||
ParticipantsBoxController::Start(
|
||||
navigation,
|
||||
_navigation,
|
||||
_peer,
|
||||
ParticipantsBoxController::Role::Kicked);
|
||||
},
|
||||
|
||||
@@ -15,9 +15,16 @@ class RoundButton;
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionNavigation;
|
||||
} // namespace Window
|
||||
|
||||
class EditPeerPermissionsBox : public Ui::BoxContent {
|
||||
public:
|
||||
EditPeerPermissionsBox(QWidget*, not_null<PeerData*> peer);
|
||||
EditPeerPermissionsBox(
|
||||
QWidget*,
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> peer);
|
||||
|
||||
struct Result {
|
||||
MTPDchatBannedRights::Flags rights;
|
||||
@@ -34,7 +41,8 @@ private:
|
||||
void addSlowmodeLabels(not_null<Ui::VerticalLayout*> container);
|
||||
void addBannedButtons(not_null<Ui::VerticalLayout*> container);
|
||||
|
||||
not_null<PeerData*> _peer;
|
||||
const not_null<Window::SessionNavigation*> _navigation;
|
||||
const not_null<PeerData*> _peer;
|
||||
Ui::RoundButton *_save = nullptr;
|
||||
Fn<Result()> _value;
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "info/profile/info_profile_values.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "observer_peer.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "ui/toast/toast.h"
|
||||
@@ -168,7 +168,7 @@ Controller::Controller(
|
||||
std::optional<Privacy> privacySavedValue,
|
||||
std::optional<QString> usernameSavedValue)
|
||||
: _peer(peer)
|
||||
, _api(_peer->session().api().instance())
|
||||
, _api(&_peer->session().mtp())
|
||||
, _privacySavedValue(privacySavedValue)
|
||||
, _usernameSavedValue(usernameSavedValue)
|
||||
, _useLocationPhrases(useLocationPhrases)
|
||||
@@ -335,7 +335,7 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
|
||||
st::setupChannelLink,
|
||||
nullptr,
|
||||
username,
|
||||
true));
|
||||
_peer->session().createInternalLink(QString())));
|
||||
_controls.usernameInput->heightValue(
|
||||
) | rpl::start_with_next([placeholder](int height) {
|
||||
placeholder->resize(placeholder->width(), height);
|
||||
@@ -485,12 +485,12 @@ void Controller::usernameChanged() {
|
||||
_checkUsernameTimer.cancel();
|
||||
return;
|
||||
}
|
||||
const auto bad = ranges::find_if(username, [](QChar ch) {
|
||||
const auto bad = ranges::any_of(username, [](QChar ch) {
|
||||
return (ch < 'A' || ch > 'Z')
|
||||
&& (ch < 'a' || ch > 'z')
|
||||
&& (ch < '0' || ch > '9')
|
||||
&& (ch != '_');
|
||||
}) != username.end();
|
||||
});
|
||||
if (bad) {
|
||||
showUsernameError(tr::lng_create_channel_link_bad_symbols());
|
||||
} else if (username.size() < kMinUsernameLength) {
|
||||
@@ -574,9 +574,9 @@ void Controller::observeInviteLink() {
|
||||
if (!_controls.editInviteLinkWrap) {
|
||||
return;
|
||||
}
|
||||
Notify::PeerUpdateValue(
|
||||
_peer->session().changes().peerFlagsValue(
|
||||
_peer,
|
||||
Notify::PeerUpdate::Flag::InviteLinkChanged
|
||||
Data::PeerUpdate::Flag::InviteLink
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshCreateInviteLink();
|
||||
refreshEditInviteLink();
|
||||
|
||||
@@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "mainwindow.h"
|
||||
#include "main/main_session.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "apiwrap.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_calls.h"
|
||||
@@ -31,7 +33,7 @@ RateCallBox::RateCallBox(
|
||||
uint64 callId,
|
||||
uint64 callAccessHash)
|
||||
: _session(session)
|
||||
, _api(_session->api().instance())
|
||||
, _api(&_session->mtp())
|
||||
, _callId(callId)
|
||||
, _callAccessHash(callAccessHash) {
|
||||
}
|
||||
@@ -85,7 +87,7 @@ void RateCallBox::ratingChanged(int value) {
|
||||
Ui::InputField::Mode::MultiLine,
|
||||
tr::lng_call_rate_comment());
|
||||
_comment->show();
|
||||
_comment->setSubmitSettings(_session->settings().sendSubmitWay());
|
||||
_comment->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
||||
_comment->setMaxLength(kRateCallCommentLengthMax);
|
||||
_comment->resize(width() - (st::callRatingPadding.left() + st::callRatingPadding.right()), _comment->height());
|
||||
|
||||
|
||||
@@ -15,8 +15,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "mtproto/facade.h"
|
||||
#include "mainwindow.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "core/application.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
@@ -28,11 +29,13 @@ constexpr auto kReportReasonLengthMax = 200;
|
||||
} // namespace
|
||||
|
||||
ReportBox::ReportBox(QWidget*, not_null<PeerData*> peer)
|
||||
: _peer(peer) {
|
||||
: _peer(peer)
|
||||
, _api(&_peer->session().mtp()) {
|
||||
}
|
||||
|
||||
ReportBox::ReportBox(QWidget*, not_null<PeerData*> peer, MessageIdsList ids)
|
||||
: _peer(peer)
|
||||
, _api(&_peer->session().mtp())
|
||||
, _ids(std::move(ids)) {
|
||||
}
|
||||
|
||||
@@ -107,7 +110,7 @@ void ReportBox::reasonChanged(Reason reason) {
|
||||
Ui::InputField::Mode::MultiLine,
|
||||
tr::lng_report_reason_description());
|
||||
_reasonOtherText->show();
|
||||
_reasonOtherText->setSubmitSettings(_peer->session().settings().sendSubmitWay());
|
||||
_reasonOtherText->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
||||
_reasonOtherText->setMaxLength(kReportReasonLengthMax);
|
||||
_reasonOtherText->resize(width() - (st::boxPadding.left() + st::boxOptionListPadding.left() + st::boxPadding.right()), _reasonOtherText->height());
|
||||
|
||||
@@ -137,7 +140,9 @@ void ReportBox::reasonResized() {
|
||||
}
|
||||
|
||||
void ReportBox::report() {
|
||||
if (_requestId) return;
|
||||
if (_requestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_reasonOtherText && _reasonOtherText->getLastText().trimmed().isEmpty()) {
|
||||
_reasonOtherText->showError();
|
||||
@@ -159,18 +164,24 @@ void ReportBox::report() {
|
||||
for (const auto &fullId : *_ids) {
|
||||
ids.push_back(MTP_int(fullId.msg));
|
||||
}
|
||||
_requestId = MTP::send(
|
||||
MTPmessages_Report(
|
||||
_peer->input,
|
||||
MTP_vector<MTPint>(ids),
|
||||
reason),
|
||||
rpcDone(&ReportBox::reportDone),
|
||||
rpcFail(&ReportBox::reportFail));
|
||||
_requestId = _api.request(MTPmessages_Report(
|
||||
_peer->input,
|
||||
MTP_vector<MTPint>(ids),
|
||||
reason
|
||||
)).done([=](const MTPBool &result) {
|
||||
reportDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
reportFail(error);
|
||||
}).send();
|
||||
} else {
|
||||
_requestId = MTP::send(
|
||||
MTPaccount_ReportPeer(_peer->input, reason),
|
||||
rpcDone(&ReportBox::reportDone),
|
||||
rpcFail(&ReportBox::reportFail));
|
||||
_requestId = _api.request(MTPaccount_ReportPeer(
|
||||
_peer->input,
|
||||
reason
|
||||
)).done([=](const MTPBool &result) {
|
||||
reportDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
reportFail(error);
|
||||
}).send();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,16 +191,11 @@ void ReportBox::reportDone(const MTPBool &result) {
|
||||
closeBox();
|
||||
}
|
||||
|
||||
bool ReportBox::reportFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReportBox::reportFail(const RPCError &error) {
|
||||
_requestId = 0;
|
||||
if (_reasonOtherText) {
|
||||
_reasonOtherText->showError();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReportBox::updateMaxHeight() {
|
||||
|
||||
@@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#pragma once
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
namespace Ui {
|
||||
template <typename Enum>
|
||||
@@ -18,7 +18,7 @@ class Radioenum;
|
||||
class InputField;
|
||||
} // namespace Ui
|
||||
|
||||
class ReportBox : public Ui::BoxContent, public RPCSender {
|
||||
class ReportBox final : public Ui::BoxContent {
|
||||
public:
|
||||
ReportBox(QWidget*, not_null<PeerData*> peer);
|
||||
ReportBox(QWidget*, not_null<PeerData*> peer, MessageIdsList ids);
|
||||
@@ -43,9 +43,10 @@ private:
|
||||
void report();
|
||||
|
||||
void reportDone(const MTPBool &result);
|
||||
bool reportFail(const RPCError &error);
|
||||
void reportFail(const RPCError &error);
|
||||
|
||||
not_null<PeerData*> _peer;
|
||||
const not_null<PeerData*> _peer;
|
||||
MTP::Sender _api;
|
||||
std::optional<MessageIdsList> _ids;
|
||||
|
||||
std::shared_ptr<Ui::RadioenumGroup<Reason>> _reasonGroup;
|
||||
|
||||
@@ -62,7 +62,6 @@ void SelfDestructionBox::showContent() {
|
||||
_description->moveToLeft(st::boxPadding.left(), y);
|
||||
y += _description->height() + st::boxMediumSkip;
|
||||
|
||||
const auto count = int(_ttlValues.size());
|
||||
for (const auto value : _ttlValues) {
|
||||
const auto button = Ui::CreateChild<Ui::Radiobutton>(
|
||||
this,
|
||||
|
||||
@@ -12,11 +12,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "storage/localstorage.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "mainwidget.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mtproto/mtproto_config.h"
|
||||
#include "chat_helpers/message_field.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "chat_helpers/tabbed_panel.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "confirm_box.h"
|
||||
#include "history/history_drag_area.h"
|
||||
#include "history/view/history_view_schedule_box.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/mime_type.h"
|
||||
@@ -35,8 +38,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "api/api_common.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "layout.h"
|
||||
#include "facades.h"
|
||||
#include "facades.h" // App::LambdaDelayed.
|
||||
#include "app.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_layers.h"
|
||||
@@ -58,10 +63,7 @@ enum class ButtonType {
|
||||
};
|
||||
|
||||
inline bool CanAddUrls(const QList<QUrl> &urls) {
|
||||
return !urls.isEmpty() && ranges::find_if(
|
||||
urls,
|
||||
[](const QUrl &url) { return !url.isLocalFile(); }
|
||||
) == urls.end();
|
||||
return !urls.isEmpty() && ranges::all_of(urls, &QUrl::isLocalFile);
|
||||
}
|
||||
|
||||
inline bool IsFirstAlbumItem(const Storage::PreparedList &list) {
|
||||
@@ -332,7 +334,7 @@ AlbumThumb::AlbumThumb(
|
||||
- st::sendMediaFileThumbSize
|
||||
// Right buttons.
|
||||
- st::sendBoxAlbumGroupButtonFile.width * 2
|
||||
- st::sendBoxAlbumGroupEditInternalSkip
|
||||
- st::sendBoxAlbumGroupEditInternalSkip * 2
|
||||
- st::sendBoxAlbumGroupSkipRight;
|
||||
const auto filepath = file.path;
|
||||
if (filepath.isEmpty()) {
|
||||
@@ -1857,6 +1859,40 @@ void SendFilesBox::prepare() {
|
||||
}));
|
||||
|
||||
updateLeftButtonVisibility();
|
||||
setupDragArea();
|
||||
}
|
||||
|
||||
void SendFilesBox::setupDragArea() {
|
||||
// Avoid both drag areas appearing at one time.
|
||||
auto computeState = [=](const QMimeData *data) {
|
||||
const auto state = Storage::ComputeMimeDataState(data);
|
||||
return (state == Storage::MimeDataState::PhotoFiles)
|
||||
? Storage::MimeDataState::Image
|
||||
: (state == Storage::MimeDataState::Files)
|
||||
// Temporary enable drag'n'drop only for images. TODO.
|
||||
? Storage::MimeDataState::None
|
||||
: state;
|
||||
};
|
||||
const auto areas = DragArea::SetupDragAreaToContainer(
|
||||
this,
|
||||
[=](not_null<const QMimeData*> d) { return canAddFiles(d); },
|
||||
[=](bool f) { _caption->setAcceptDrops(f); },
|
||||
[=] { updateControlsGeometry(); },
|
||||
std::move(computeState));
|
||||
|
||||
const auto droppedCallback = [=](bool compress) {
|
||||
return [=](const QMimeData *data) {
|
||||
addFiles(data);
|
||||
Window::ActivateWindow(_controller);
|
||||
};
|
||||
};
|
||||
areas.document->setDroppedCallback(droppedCallback(false));
|
||||
areas.photo->setDroppedCallback(droppedCallback(true));
|
||||
_albumChanged.events(
|
||||
) | rpl::start_with_next([=] {
|
||||
areas.document->raise();
|
||||
areas.photo->raise();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void SendFilesBox::updateLeftButtonVisibility() {
|
||||
@@ -1874,6 +1910,7 @@ void SendFilesBox::refreshAllAfterAlbumChanges() {
|
||||
preparePreview();
|
||||
captionResized();
|
||||
updateLeftButtonVisibility();
|
||||
_albumChanged.fire({});
|
||||
}
|
||||
|
||||
void SendFilesBox::openDialogToAddFileToAlbum() {
|
||||
@@ -1910,7 +1947,7 @@ void SendFilesBox::initSendWay() {
|
||||
? SendFilesWay::Album
|
||||
: SendFilesWay::Photos;
|
||||
}
|
||||
const auto way = _controller->session().settings().sendFilesWay();
|
||||
const auto way = Core::App().settings().sendFilesWay();
|
||||
if (way == SendFilesWay::Files) {
|
||||
return way;
|
||||
} else if (way == SendFilesWay::Album) {
|
||||
@@ -2041,8 +2078,10 @@ void SendFilesBox::applyAlbumOrder() {
|
||||
}
|
||||
|
||||
void SendFilesBox::setupCaption() {
|
||||
_caption->setMaxLength(Global::CaptionLengthMax());
|
||||
_caption->setSubmitSettings(_controller->session().settings().sendSubmitWay());
|
||||
_caption->setMaxLength(
|
||||
_controller->session().serverConfig().captionLengthMax);
|
||||
_caption->setSubmitSettings(
|
||||
Core::App().settings().sendSubmitWay());
|
||||
connect(_caption, &Ui::InputField::resized, [=] {
|
||||
captionResized();
|
||||
});
|
||||
@@ -2066,16 +2105,16 @@ void SendFilesBox::setupCaption() {
|
||||
});
|
||||
_caption->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
_caption->setInstantReplacesEnabled(
|
||||
_controller->session().settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
_caption->setMarkdownReplacesEnabled(rpl::single(true));
|
||||
_caption->setEditLinkCallback(
|
||||
DefaultEditLinkCallback(&_controller->session(), _caption));
|
||||
DefaultEditLinkCallback(_controller, _caption));
|
||||
Ui::Emoji::SuggestionsController::Init(
|
||||
getDelegate()->outerContainer(),
|
||||
_caption,
|
||||
&_controller->session());
|
||||
|
||||
InitSpellchecker(&_controller->session(), _caption);
|
||||
InitSpellchecker(_controller, _caption);
|
||||
|
||||
updateCaptionPlaceholder();
|
||||
setupEmojiPanel();
|
||||
@@ -2339,7 +2378,7 @@ void SendFilesBox::send(
|
||||
const auto way = _sendWay ? _sendWay->value() : Way::Files;
|
||||
|
||||
if (_compressConfirm == CompressConfirm::Auto) {
|
||||
const auto oldWay = _controller->session().settings().sendFilesWay();
|
||||
const auto oldWay = Core::App().settings().sendFilesWay();
|
||||
if (way != oldWay) {
|
||||
// Check if the user _could_ use the old value, but didn't.
|
||||
if ((oldWay == Way::Album && _sendAlbum)
|
||||
@@ -2347,8 +2386,8 @@ void SendFilesBox::send(
|
||||
|| (oldWay == Way::Files && _sendFiles)
|
||||
|| (way == Way::Files && (_sendAlbum || _sendPhotos))) {
|
||||
// And in that case save it to settings.
|
||||
_controller->session().settings().setSendFilesWay(way);
|
||||
_controller->session().saveSettingsDelayed();
|
||||
Core::App().settings().setSendFilesWay(way);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ private:
|
||||
void sendScheduled();
|
||||
void captionResized();
|
||||
|
||||
void setupDragArea();
|
||||
void setupTitleText();
|
||||
void updateBoxSize();
|
||||
void updateControlsGeometry();
|
||||
@@ -163,6 +164,7 @@ private:
|
||||
std::shared_ptr<Ui::RadioenumGroup<SendFilesWay>> _sendWay;
|
||||
|
||||
rpl::variable<int> _footerHeight = 0;
|
||||
rpl::event_stream<> _albumChanged;
|
||||
|
||||
QWidget *_preview = nullptr;
|
||||
AlbumPreview *_albumPreview = nullptr;
|
||||
|
||||
@@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "storage/localstorage.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_session.h"
|
||||
#include "base/unixtime.h"
|
||||
@@ -78,7 +77,7 @@ private:
|
||||
|
||||
SessionsBox::SessionsBox(QWidget*, not_null<Main::Session*> session)
|
||||
: _session(session)
|
||||
, _api(_session->api().instance())
|
||||
, _api(&_session->mtp())
|
||||
, _shortPollTimer([=] { shortPollSessions(); }) {
|
||||
}
|
||||
|
||||
@@ -426,9 +425,7 @@ void SessionsBox::Inner::showData(const Full &data) {
|
||||
}
|
||||
|
||||
rpl::producer<> SessionsBox::Inner::terminateAll() const {
|
||||
return _terminateAll->clicks() | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
});
|
||||
return _terminateAll->clicks() | rpl::to_empty;
|
||||
}
|
||||
|
||||
rpl::producer<uint64> SessionsBox::Inner::terminateOne() const {
|
||||
|
||||
@@ -8,12 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/share_box.h"
|
||||
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "observer_peer.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mainwidget.h"
|
||||
#include "base/qthelp_url.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "apiwrap.h"
|
||||
#include "ui/toast/toast.h"
|
||||
@@ -35,16 +34,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "main/main_session.h"
|
||||
#include "core/application.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
|
||||
class ShareBox::Inner
|
||||
: public Ui::RpWidget
|
||||
, public RPCSender
|
||||
, private base::Subscriber {
|
||||
class ShareBox::Inner final : public Ui::RpWidget, private base::Subscriber {
|
||||
public:
|
||||
Inner(
|
||||
QWidget *parent,
|
||||
@@ -94,7 +91,6 @@ private:
|
||||
Ui::Animations::Simple nameActive;
|
||||
};
|
||||
|
||||
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
||||
void invalidateCache();
|
||||
|
||||
int displayedChatsCount() const;
|
||||
@@ -163,6 +159,7 @@ ShareBox::ShareBox(
|
||||
SubmitCallback &&submitCallback,
|
||||
FilterCallback &&filterCallback)
|
||||
: _navigation(navigation)
|
||||
, _api(&_navigation->session().mtp())
|
||||
, _copyCallback(std::move(copyCallback))
|
||||
, _submitCallback(std::move(submitCallback))
|
||||
, _filterCallback(std::move(filterCallback))
|
||||
@@ -202,13 +199,13 @@ void ShareBox::prepareCommentField() {
|
||||
|
||||
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
field->setInstantReplacesEnabled(
|
||||
_navigation->session().settings().replaceEmojiValue());
|
||||
Core::App().settings().replaceEmojiValue());
|
||||
field->setMarkdownReplacesEnabled(rpl::single(true));
|
||||
field->setEditLinkCallback(
|
||||
DefaultEditLinkCallback(&_navigation->session(), field));
|
||||
field->setSubmitSettings(_navigation->session().settings().sendSubmitWay());
|
||||
DefaultEditLinkCallback(_navigation->parentController(), field));
|
||||
field->setSubmitSettings(Core::App().settings().sendSubmitWay());
|
||||
|
||||
InitSpellchecker(&_navigation->session(), field);
|
||||
InitSpellchecker(_navigation->parentController(), field);
|
||||
Ui::SendPendingMoveResizeEvents(_comment);
|
||||
}
|
||||
|
||||
@@ -309,18 +306,20 @@ bool ShareBox::searchByUsername(bool searchCache) {
|
||||
if (i != _peopleCache.cend()) {
|
||||
_peopleQuery = query;
|
||||
_peopleRequest = 0;
|
||||
peopleReceived(i.value(), 0);
|
||||
peopleDone(i.value(), 0);
|
||||
return true;
|
||||
}
|
||||
} else if (_peopleQuery != query) {
|
||||
_peopleQuery = query;
|
||||
_peopleFull = false;
|
||||
_peopleRequest = MTP::send(
|
||||
MTPcontacts_Search(
|
||||
MTP_string(_peopleQuery),
|
||||
MTP_int(SearchPeopleLimit)),
|
||||
rpcDone(&ShareBox::peopleReceived),
|
||||
rpcFail(&ShareBox::peopleFailed));
|
||||
_peopleRequest = _api.request(MTPcontacts_Search(
|
||||
MTP_string(_peopleQuery),
|
||||
MTP_int(SearchPeopleLimit)
|
||||
)).done([=](const MTPcontacts_Found &result, mtpRequestId requestId) {
|
||||
peopleDone(result, requestId);
|
||||
}).fail([=](const RPCError &error, mtpRequestId requestId) {
|
||||
peopleFail(error, requestId);
|
||||
}).send();
|
||||
_peopleQueries.insert(_peopleRequest, _peopleQuery);
|
||||
}
|
||||
}
|
||||
@@ -333,7 +332,7 @@ void ShareBox::needSearchByUsername() {
|
||||
}
|
||||
}
|
||||
|
||||
void ShareBox::peopleReceived(
|
||||
void ShareBox::peopleDone(
|
||||
const MTPcontacts_Found &result,
|
||||
mtpRequestId requestId) {
|
||||
Expects(result.type() == mtpc_contacts_found);
|
||||
@@ -364,14 +363,11 @@ void ShareBox::peopleReceived(
|
||||
}
|
||||
}
|
||||
|
||||
bool ShareBox::peopleFailed(const RPCError &error, mtpRequestId requestId) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
void ShareBox::peopleFail(const RPCError &error, mtpRequestId requestId) {
|
||||
if (_peopleRequest == requestId) {
|
||||
_peopleRequest = 0;
|
||||
_peopleFull = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShareBox::setInnerFocus() {
|
||||
@@ -561,14 +557,23 @@ ShareBox::Inner::Inner(
|
||||
_filter = qsl("a");
|
||||
updateFilter();
|
||||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
auto observeEvents = UpdateFlag::NameChanged | UpdateFlag::PhotoChanged;
|
||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
||||
notifyPeerUpdated(update);
|
||||
}));
|
||||
subscribe(_navigation->session().downloaderTaskFinished(), [=] {
|
||||
_navigation->session().changes().peerUpdates(
|
||||
Data::PeerUpdate::Flag::Photo
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
updateChat(update.peer);
|
||||
}, lifetime());
|
||||
|
||||
_navigation->session().changes().realtimeNameUpdates(
|
||||
) | rpl::start_with_next([=](const Data::NameUpdate &update) {
|
||||
_chatsIndexed->peerNameChanged(
|
||||
update.peer,
|
||||
update.oldFirstLetters);
|
||||
}, lifetime());
|
||||
|
||||
_navigation->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
});
|
||||
}, lifetime());
|
||||
|
||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
||||
if (update.paletteChanged()) {
|
||||
@@ -619,16 +624,6 @@ void ShareBox::Inner::activateSkipPage(int pageHeight, int direction) {
|
||||
activateSkipRow(direction * (pageHeight / _rowHeight));
|
||||
}
|
||||
|
||||
void ShareBox::Inner::notifyPeerUpdated(const Notify::PeerUpdate &update) {
|
||||
if (update.flags & Notify::PeerUpdate::Flag::NameChanged) {
|
||||
_chatsIndexed->peerNameChanged(
|
||||
update.peer,
|
||||
update.oldNameFirstLetters);
|
||||
}
|
||||
|
||||
updateChat(update.peer);
|
||||
}
|
||||
|
||||
void ShareBox::Inner::updateChat(not_null<PeerData*> peer) {
|
||||
if (const auto i = _dataMap.find(peer); i != end(_dataMap)) {
|
||||
updateChatName(i->second.get(), peer);
|
||||
@@ -1101,7 +1096,7 @@ QString AppendShareGameScoreUrl(
|
||||
*reinterpret_cast<uint64*>(shareHashEncrypted.data()) ^= *reinterpret_cast<uint64*>(channelAccessHashInts);
|
||||
|
||||
// Encrypt data.
|
||||
if (!Local::encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(), shareHashEncrypted.constData())) {
|
||||
if (!session->local().encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(), shareHashEncrypted.constData())) {
|
||||
return url;
|
||||
}
|
||||
|
||||
@@ -1137,7 +1132,7 @@ void ShareGameScoreByHash(
|
||||
|
||||
// Decrypt data.
|
||||
auto hashData = QByteArray(hashEncrypted.size() - key128Size, Qt::Uninitialized);
|
||||
if (!Local::decrypt(hashEncrypted.constData() + key128Size, hashData.data(), hashEncrypted.size() - key128Size, hashEncrypted.constData())) {
|
||||
if (!session->local().decrypt(hashEncrypted.constData() + key128Size, hashData.data(), hashEncrypted.size() - key128Size, hashEncrypted.constData())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/timer.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
enum class SendMenuType;
|
||||
|
||||
@@ -33,10 +33,6 @@ class Row;
|
||||
class IndexedList;
|
||||
} // namespace Dialogs
|
||||
|
||||
namespace Notify {
|
||||
struct PeerUpdate;
|
||||
} // namespace Notify
|
||||
|
||||
namespace Ui {
|
||||
class MultiSelect;
|
||||
class InputField;
|
||||
@@ -53,7 +49,7 @@ void ShareGameScoreByHash(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &hash);
|
||||
|
||||
class ShareBox : public Ui::BoxContent, public RPCSender {
|
||||
class ShareBox final : public Ui::BoxContent {
|
||||
public:
|
||||
using CopyCallback = Fn<void()>;
|
||||
using SubmitCallback = Fn<void(
|
||||
@@ -101,12 +97,13 @@ private:
|
||||
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
|
||||
void innerSelectedChanged(PeerData *peer, bool checked);
|
||||
|
||||
void peopleReceived(
|
||||
void peopleDone(
|
||||
const MTPcontacts_Found &result,
|
||||
mtpRequestId requestId);
|
||||
bool peopleFailed(const RPCError &error, mtpRequestId requestId);
|
||||
void peopleFail(const RPCError &error, mtpRequestId requestId);
|
||||
|
||||
const not_null<Window::SessionNavigation*> _navigation;
|
||||
MTP::Sender _api;
|
||||
|
||||
CopyCallback _copyCallback;
|
||||
SubmitCallback _submitCallback;
|
||||
|
||||