Compare commits
217 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5bc567eb8 | ||
|
|
5f91a97778 | ||
|
|
63aa3576d8 | ||
|
|
7749794d6b | ||
|
|
368468447f | ||
|
|
54fa16424d | ||
|
|
fc7f1991dd | ||
|
|
910d0a7e47 | ||
|
|
6e8fb2ec06 | ||
|
|
94d943f3af | ||
|
|
41e6e32962 | ||
|
|
2f58a7d3c4 | ||
|
|
e364b80d0a | ||
|
|
f3efa85206 | ||
|
|
42f2f3c99f | ||
|
|
a6d0367d71 | ||
|
|
bcbf009a62 | ||
|
|
fedd8bece3 | ||
|
|
031525e7e3 | ||
|
|
4d5cb6398e | ||
|
|
3ef352b63c | ||
|
|
9809c12fb8 | ||
|
|
3e4ac35913 | ||
|
|
a72953411b | ||
|
|
3967e58627 | ||
|
|
db46f84f2c | ||
|
|
9a57347973 | ||
|
|
c9c988e5f4 | ||
|
|
5e2acdeaa3 | ||
|
|
5a4d1a1e85 | ||
|
|
fbd9437775 | ||
|
|
2eaa17b938 | ||
|
|
01eacadca5 | ||
|
|
9f155e0053 | ||
|
|
2f9dc6ca2a | ||
|
|
3d6f6cdd8f | ||
|
|
7e3c54f8d0 | ||
|
|
540ee0bc44 | ||
|
|
627170520a | ||
|
|
77d50d9177 | ||
|
|
c47140c62d | ||
|
|
546dfb08ef | ||
|
|
376b592e5a | ||
|
|
c27db754a7 | ||
|
|
5fb71cb165 | ||
|
|
972666440e | ||
|
|
549d7c77e5 | ||
|
|
de3b30ed7d | ||
|
|
a4f5e3f411 | ||
|
|
df19b62e92 | ||
|
|
caf2be13b3 | ||
|
|
e206f42e4e | ||
|
|
3f60410190 | ||
|
|
3cdd8558db | ||
|
|
f2b89445ae | ||
|
|
3ff4bf77e7 | ||
|
|
d16ccf0d9e | ||
|
|
fc7d9b264f | ||
|
|
b28d5a63d1 | ||
|
|
043ba4ff04 | ||
|
|
d6c3bf4168 | ||
|
|
7bf7a8feff | ||
|
|
3413ad1d22 | ||
|
|
84af084a3b | ||
|
|
cd50008429 | ||
|
|
767459ab57 | ||
|
|
3b45a120e6 | ||
|
|
b04aaba8d0 | ||
|
|
bfa3655c7b | ||
|
|
8642eb23a7 | ||
|
|
ef8ecc546b | ||
|
|
fafbbb4996 | ||
|
|
3a021f4e49 | ||
|
|
2788c19c85 | ||
|
|
300cc3dbca | ||
|
|
62516e264d | ||
|
|
8b89cfc4cb | ||
|
|
e3f65d2346 | ||
|
|
2b383a4236 | ||
|
|
a8426bd6da | ||
|
|
39a02e649d | ||
|
|
276fe2169a | ||
|
|
8fae56bee8 | ||
|
|
0e16a50bbc | ||
|
|
9de372d715 | ||
|
|
fbae5bdbcf | ||
|
|
aee1ef78da | ||
|
|
27c5c4b8f2 | ||
|
|
94e06c6846 | ||
|
|
7948d971e8 | ||
|
|
70acc7a0e3 | ||
|
|
56fdc7d39a | ||
|
|
f67c3bbf65 | ||
|
|
de194c4aa2 | ||
|
|
511805199f | ||
|
|
aa241a1f62 | ||
|
|
4125a45503 | ||
|
|
1349989494 | ||
|
|
639ed8b973 | ||
|
|
2f5db08c9b | ||
|
|
4c6814def6 | ||
|
|
387914be31 | ||
|
|
2f2003c89b | ||
|
|
48589b721d | ||
|
|
3bdf1634a9 | ||
|
|
1878061c9a | ||
|
|
774c3b5ba0 | ||
|
|
a64b8d4181 | ||
|
|
e3e380124d | ||
|
|
823fc25fa8 | ||
|
|
4062912a98 | ||
|
|
62b5192f24 | ||
|
|
058717532a | ||
|
|
d117a72e6e | ||
|
|
3ba5b825e5 | ||
|
|
075ab20e5b | ||
|
|
deeea0aaed | ||
|
|
8113117cc4 | ||
|
|
7bfe096f3b | ||
|
|
c37b08ac8b | ||
|
|
c52a5927e5 | ||
|
|
edcfac8da3 | ||
|
|
a994c9f017 | ||
|
|
66e6bf8217 | ||
|
|
4a4cc766c2 | ||
|
|
31cd841b75 | ||
|
|
1710890886 | ||
|
|
16f616c5e0 | ||
|
|
7600c9bb2f | ||
|
|
100a44daef | ||
|
|
54305fafde | ||
|
|
d172d3d7db | ||
|
|
cee593c423 | ||
|
|
43adbb1cb1 | ||
|
|
e96731be11 | ||
|
|
6ea062462f | ||
|
|
1bc8d6fb18 | ||
|
|
73d00a4caf | ||
|
|
a23561c380 | ||
|
|
bb75a6a31b | ||
|
|
ce79c1f0c4 | ||
|
|
3cdb82a0bf | ||
|
|
d2f928f0c3 | ||
|
|
3cc0110464 | ||
|
|
df533f2efe | ||
|
|
2529bd3f44 | ||
|
|
a5c12065af | ||
|
|
101e795af8 | ||
|
|
8faa65fdf3 | ||
|
|
644881bd3e | ||
|
|
efa1b2dcbc | ||
|
|
92a9832337 | ||
|
|
8f3456cd6c | ||
|
|
e67192cdf0 | ||
|
|
9f2683a35b | ||
|
|
0a7e25e45a | ||
|
|
643a034aae | ||
|
|
1c5a3aef54 | ||
|
|
bfe47a1ba2 | ||
|
|
acd76fc97b | ||
|
|
78fedce2d5 | ||
|
|
5261e962e2 | ||
|
|
e4bfd562b5 | ||
|
|
d289bbdc5e | ||
|
|
2e9e3b3751 | ||
|
|
af0a2f182c | ||
|
|
e3ac84a849 | ||
|
|
6dce8dfa20 | ||
|
|
eef1da56c8 | ||
|
|
e37866d0b9 | ||
|
|
1ed7d482ab | ||
|
|
f1a7db780e | ||
|
|
8591fae031 | ||
|
|
18b9bba21c | ||
|
|
580e15dc21 | ||
|
|
bf4fc2596a | ||
|
|
9a4d2bc8f9 | ||
|
|
62a2277f43 | ||
|
|
d11885d48c | ||
|
|
c8cec18ad3 | ||
|
|
86105403bf | ||
|
|
41288f5ddb | ||
|
|
9cc1a020f3 | ||
|
|
68f35e98e0 | ||
|
|
b6c9a1d655 | ||
|
|
9b35fa29b8 | ||
|
|
53272d951b | ||
|
|
e3dc4ae088 | ||
|
|
000d9d8b52 | ||
|
|
3d8742fa7c | ||
|
|
ae43e78a86 | ||
|
|
7c72393361 | ||
|
|
fa95ca4289 | ||
|
|
e6e90e99da | ||
|
|
6a3c1f2fd9 | ||
|
|
90f99ebfbe | ||
|
|
59fb61e3e6 | ||
|
|
261740967d | ||
|
|
e99e35a12a | ||
|
|
fd6d09caaa | ||
|
|
47ec5b18b8 | ||
|
|
aac21e1f71 | ||
|
|
21c647147a | ||
|
|
07a022bfb6 | ||
|
|
0427f90649 | ||
|
|
64627c9093 | ||
|
|
148a173474 | ||
|
|
acb6e5dbc3 | ||
|
|
9bd9f17a6c | ||
|
|
d59ed7b14c | ||
|
|
3600055424 | ||
|
|
949caecb75 | ||
|
|
87df42f8c1 | ||
|
|
2996cbc518 | ||
|
|
205cd3b751 | ||
|
|
d25bd2f481 | ||
|
|
072974216b |
11
.github/workflows/docker.yml
vendored
@@ -15,6 +15,9 @@ jobs:
|
||||
name: Ubuntu
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
IMAGE_TAG: ghcr.io/${{ github.repository }}/centos_env:latest
|
||||
|
||||
steps:
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v2
|
||||
@@ -22,4 +25,10 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Docker image build.
|
||||
run: docker build -t telegram_desktop Telegram/build/docker/centos_env
|
||||
run: docker build -t $IMAGE_TAG --build-arg DEBUG= Telegram/build/docker/centos_env
|
||||
|
||||
- name: Push the Docker image.
|
||||
if: ${{ github.ref_name == github.event.repository.default_branch }}
|
||||
run: |
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
|
||||
docker push $IMAGE_TAG
|
||||
|
||||
2
.github/workflows/linux.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
||||
name: CentOS 7
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: docker.pkg.github.com/telegramdesktop/tdesktop/centos_env
|
||||
image: ghcr.io/${{ github.repository }}/centos_env
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
10
.github/workflows/mac.yml
vendored
@@ -51,6 +51,7 @@ jobs:
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
ONLY_CACHE: "false"
|
||||
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
|
||||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
@@ -65,8 +66,7 @@ jobs:
|
||||
- name: First set up.
|
||||
run: |
|
||||
sudo chown -R `whoami`:admin /usr/local/share
|
||||
brew install automake fdk-aac lame libass libtool libvorbis libvpx \
|
||||
ninja opus sdl shtool texi2html theora x264 xvid yasm pkg-config
|
||||
brew install automake
|
||||
|
||||
# Disable spotlight.
|
||||
sudo mdutil -a -i off
|
||||
@@ -78,14 +78,16 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ThirdParty
|
||||
key: ${{ runner.OS }}-third-party
|
||||
key: ${{ runner.OS }}-third-party-${{ hashFiles(format('{0}/{1}', env.REPO_NAME, env.PREPARE_PATH)) }}
|
||||
restore-keys: ${{ runner.OS }}-third-party-
|
||||
|
||||
- name: Libraries cache.
|
||||
id: cache-libs
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: Libraries
|
||||
key: ${{ runner.OS }}-libs
|
||||
key: ${{ runner.OS }}-libs-${{ hashFiles(format('{0}/{1}', env.REPO_NAME, env.PREPARE_PATH)) }}
|
||||
restore-keys: ${{ runner.OS }}-libs-
|
||||
|
||||
- name: Libraries.
|
||||
run: |
|
||||
|
||||
22
.github/workflows/win.yml
vendored
@@ -13,7 +13,7 @@ on:
|
||||
- '!.github/workflows/win.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/build/docker/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
@@ -32,7 +32,7 @@ on:
|
||||
- '!.github/workflows/win.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/build/docker/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
@@ -58,12 +58,12 @@ jobs:
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
working-directory: ${{ github.workspace }}
|
||||
|
||||
steps:
|
||||
- name: Prepare directories.
|
||||
run: |
|
||||
mkdir %userprofile%\TBuild\Libraries
|
||||
mkdir %userprofile%\TBuild Libraries
|
||||
mklink /d %userprofile%\TBuild\Libraries %GITHUB_WORKSPACE%\Libraries
|
||||
echo TBUILD=%userprofile%\TBuild>>%GITHUB_ENV%
|
||||
|
||||
- name: Get repository name.
|
||||
@@ -98,6 +98,8 @@ jobs:
|
||||
echo "C:\\Program Files\\NASM\\" >> $GITHUB_PATH
|
||||
echo "C:\\ProgramData\\chocolatey\\lib\\ninja\\tools\\" >> $GITHUB_PATH
|
||||
|
||||
echo "CACHE_KEY=$(sha256sum $TBUILD/$REPO_NAME/$PREPARE_PATH | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||
|
||||
echo "Configurate git for cherry-picks."
|
||||
git config --global user.email "you@example.com"
|
||||
git config --global user.name "Sample"
|
||||
@@ -111,17 +113,15 @@ jobs:
|
||||
id: cache-libs
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.TBUILD }}/Libraries
|
||||
key: ${{ runner.OS }}-libs
|
||||
path: Libraries
|
||||
key: ${{ runner.OS }}-${{ matrix.arch }}-libs-${{ env.CACHE_KEY }}
|
||||
restore-keys: ${{ runner.OS }}-${{ matrix.arch }}-libs-
|
||||
|
||||
- name: Libraries.
|
||||
env:
|
||||
GYP_MSVS_OVERRIDE_PATH: 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\'
|
||||
GYP_MSVS_VERSION: 2022
|
||||
run: |
|
||||
C:
|
||||
cd %TBUILD%
|
||||
%REPO_NAME%/Telegram/build/prepare/win.bat skip-release silent
|
||||
run: '%TBUILD%\%REPO_NAME%\Telegram\build\prepare\win.bat skip-release silent'
|
||||
|
||||
- name: Read defines.
|
||||
shell: bash
|
||||
@@ -138,8 +138,6 @@ jobs:
|
||||
|
||||
- name: Free up some disk space.
|
||||
run: |
|
||||
C:
|
||||
cd %TBUILD%
|
||||
del /S Libraries\*.pdb
|
||||
del /S Libraries\*.pch
|
||||
del /S Libraries\*.obj
|
||||
|
||||
@@ -137,6 +137,8 @@ PRIVATE
|
||||
api/api_peer_photo.h
|
||||
api/api_polls.cpp
|
||||
api/api_polls.h
|
||||
api/api_report.cpp
|
||||
api/api_report.h
|
||||
api/api_ringtones.cpp
|
||||
api/api_ringtones.h
|
||||
api/api_self_destruct.cpp
|
||||
@@ -186,8 +188,6 @@ PRIVATE
|
||||
boxes/peers/edit_peer_invite_link.h
|
||||
boxes/peers/edit_peer_invite_links.cpp
|
||||
boxes/peers/edit_peer_invite_links.h
|
||||
boxes/peers/edit_peer_history_visibility_box.cpp
|
||||
boxes/peers/edit_peer_history_visibility_box.h
|
||||
boxes/peers/edit_peer_permissions_box.cpp
|
||||
boxes/peers/edit_peer_permissions_box.h
|
||||
boxes/peers/edit_peer_reactions.cpp
|
||||
@@ -258,6 +258,8 @@ PRIVATE
|
||||
boxes/pin_messages_box.h
|
||||
boxes/reactions_settings_box.cpp
|
||||
boxes/reactions_settings_box.h
|
||||
boxes/report_messages_box.cpp
|
||||
boxes/report_messages_box.h
|
||||
boxes/ringtones_box.cpp
|
||||
boxes/ringtones_box.h
|
||||
boxes/self_destruction_box.cpp
|
||||
@@ -988,6 +990,8 @@ PRIVATE
|
||||
platform/linux/notifications_manager_linux.h
|
||||
platform/linux/specific_linux.cpp
|
||||
platform/linux/specific_linux.h
|
||||
platform/linux/tray_linux.cpp
|
||||
platform/linux/tray_linux.h
|
||||
platform/mac/file_utilities_mac.mm
|
||||
platform/mac/file_utilities_mac.h
|
||||
platform/mac/launcher_mac.mm
|
||||
@@ -1003,6 +1007,8 @@ PRIVATE
|
||||
platform/mac/specific_mac.h
|
||||
platform/mac/specific_mac_p.mm
|
||||
platform/mac/specific_mac_p.h
|
||||
platform/mac/tray_mac.mm
|
||||
platform/mac/tray_mac.h
|
||||
platform/mac/window_title_mac.mm
|
||||
platform/mac/touchbar/items/mac_formatter_item.h
|
||||
platform/mac/touchbar/items/mac_formatter_item.mm
|
||||
@@ -1036,6 +1042,8 @@ PRIVATE
|
||||
platform/win/notifications_manager_win.h
|
||||
platform/win/specific_win.cpp
|
||||
platform/win/specific_win.h
|
||||
platform/win/tray_win.cpp
|
||||
platform/win/tray_win.h
|
||||
platform/win/windows_app_user_model_id.cpp
|
||||
platform/win/windows_app_user_model_id.h
|
||||
platform/win/windows_dlls.cpp
|
||||
@@ -1052,6 +1060,7 @@ PRIVATE
|
||||
platform/platform_main_window.h
|
||||
platform/platform_notifications_manager.h
|
||||
platform/platform_specific.h
|
||||
platform/platform_tray.h
|
||||
platform/platform_window_title.h
|
||||
profile/profile_back_button.cpp
|
||||
profile/profile_back_button.h
|
||||
@@ -1063,8 +1072,24 @@ PRIVATE
|
||||
profile/profile_block_widget.h
|
||||
profile/profile_cover_drop_area.cpp
|
||||
profile/profile_cover_drop_area.h
|
||||
settings/cloud_password/settings_cloud_password_common.cpp
|
||||
settings/cloud_password/settings_cloud_password_common.h
|
||||
settings/cloud_password/settings_cloud_password_email.cpp
|
||||
settings/cloud_password/settings_cloud_password_email.h
|
||||
settings/cloud_password/settings_cloud_password_email_confirm.cpp
|
||||
settings/cloud_password/settings_cloud_password_email_confirm.h
|
||||
settings/cloud_password/settings_cloud_password_hint.cpp
|
||||
settings/cloud_password/settings_cloud_password_hint.h
|
||||
settings/cloud_password/settings_cloud_password_input.cpp
|
||||
settings/cloud_password/settings_cloud_password_input.h
|
||||
settings/cloud_password/settings_cloud_password_manage.cpp
|
||||
settings/cloud_password/settings_cloud_password_manage.h
|
||||
settings/cloud_password/settings_cloud_password_start.cpp
|
||||
settings/cloud_password/settings_cloud_password_start.h
|
||||
settings/settings_advanced.cpp
|
||||
settings/settings_advanced.h
|
||||
settings/settings_blocked_peers.cpp
|
||||
settings/settings_blocked_peers.h
|
||||
settings/settings_chat.cpp
|
||||
settings/settings_chat.h
|
||||
settings/settings_calls.cpp
|
||||
@@ -1081,6 +1106,8 @@ PRIVATE
|
||||
settings/settings_information.h
|
||||
settings/settings_intro.cpp
|
||||
settings/settings_intro.h
|
||||
settings/settings_local_passcode.cpp
|
||||
settings/settings_local_passcode.h
|
||||
settings/settings_main.cpp
|
||||
settings/settings_main.h
|
||||
settings/settings_notifications.cpp
|
||||
@@ -1256,6 +1283,8 @@ PRIVATE
|
||||
settings.cpp
|
||||
settings.h
|
||||
stdafx.h
|
||||
tray.cpp
|
||||
tray.h
|
||||
)
|
||||
|
||||
if (NOT build_winstore)
|
||||
|
||||
BIN
Telegram/Resources/animations/blocked_peers_empty.tgs
Normal file
BIN
Telegram/Resources/animations/cloud_password/email.tgs
Normal file
BIN
Telegram/Resources/animations/cloud_password/hint.tgs
Normal file
BIN
Telegram/Resources/animations/cloud_password/intro.tgs
Normal file
BIN
Telegram/Resources/animations/cloud_password/password_input.tgs
Normal file
BIN
Telegram/Resources/animations/filters.tgs
Normal file
BIN
Telegram/Resources/animations/local_passcode_enter.tgs
Normal file
BIN
Telegram/Resources/icons/folders/folders_airplane.png
Normal file
|
After Width: | Height: | Size: 635 B |
BIN
Telegram/Resources/icons/folders/folders_airplane@2x.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/folders/folders_airplane@3x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
Telegram/Resources/icons/folders/folders_book.png
Normal file
|
After Width: | Height: | Size: 456 B |
BIN
Telegram/Resources/icons/folders/folders_book@2x.png
Normal file
|
After Width: | Height: | Size: 837 B |
BIN
Telegram/Resources/icons/folders/folders_book@3x.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/folders/folders_light.png
Normal file
|
After Width: | Height: | Size: 691 B |
BIN
Telegram/Resources/icons/folders/folders_light@2x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Telegram/Resources/icons/folders/folders_light@3x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
Telegram/Resources/icons/folders/folders_like.png
Normal file
|
After Width: | Height: | Size: 797 B |
BIN
Telegram/Resources/icons/folders/folders_like@2x.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/folders/folders_like@3x.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
Telegram/Resources/icons/folders/folders_money.png
Normal file
|
After Width: | Height: | Size: 774 B |
BIN
Telegram/Resources/icons/folders/folders_money@2x.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Telegram/Resources/icons/folders/folders_money@3x.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Telegram/Resources/icons/folders/folders_note.png
Normal file
|
After Width: | Height: | Size: 495 B |
BIN
Telegram/Resources/icons/folders/folders_note@2x.png
Normal file
|
After Width: | Height: | Size: 823 B |
BIN
Telegram/Resources/icons/folders/folders_note@3x.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/folders/folders_palette.png
Normal file
|
After Width: | Height: | Size: 689 B |
BIN
Telegram/Resources/icons/folders/folders_palette@2x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Telegram/Resources/icons/folders/folders_palette@3x.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
Telegram/Resources/icons/folders/folders_poo.png
Normal file
|
After Width: | Height: | Size: 828 B |
BIN
Telegram/Resources/icons/folders/folders_poo@2x.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/folders/folders_poo@3x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
Telegram/Resources/icons/info/edit/channel_manage_signature.png
Normal file
|
After Width: | Height: | Size: 503 B |
|
After Width: | Height: | Size: 901 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 432 B |
|
Before Width: | Height: | Size: 768 B After Width: | Height: | Size: 757 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 957 B After Width: | Height: | Size: 515 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 989 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 469 B |
|
After Width: | Height: | Size: 745 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 583 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1023 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 665 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 734 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 989 B After Width: | Height: | Size: 509 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 891 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
Telegram/Resources/icons/info/edit/group_manage_type.png
Normal file
|
After Width: | Height: | Size: 494 B |
BIN
Telegram/Resources/icons/info/edit/group_manage_type@2x.png
Normal file
|
After Width: | Height: | Size: 925 B |
BIN
Telegram/Resources/icons/info/edit/group_manage_type@3x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 650 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
Telegram/Resources/icons/settings/blocked.png
Normal file
|
After Width: | Height: | Size: 476 B |
BIN
Telegram/Resources/icons/settings/blocked@2x.png
Normal file
|
After Width: | Height: | Size: 789 B |
BIN
Telegram/Resources/icons/settings/blocked@3x.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Telegram/Resources/icons/settings/remove.png
Normal file
|
After Width: | Height: | Size: 193 B |
BIN
Telegram/Resources/icons/settings/remove@2x.png
Normal file
|
After Width: | Height: | Size: 233 B |
BIN
Telegram/Resources/icons/settings/remove@3x.png
Normal file
|
After Width: | Height: | Size: 294 B |
@@ -490,8 +490,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_forwards_privacy" = "Forwarded messages";
|
||||
"lng_settings_profile_photo_privacy" = "Profile photo";
|
||||
"lng_settings_sessions_about" = "Control your sessions on other devices.";
|
||||
"lng_settings_passcode_disable" = "Disable passcode";
|
||||
"lng_settings_password_disable" = "Disable cloud password";
|
||||
"lng_settings_passcode_disable" = "Disable Passcode";
|
||||
"lng_settings_passcode_disable_sure" = "Are you sure you want to disable passcode?";
|
||||
"lng_settings_password_disable" = "Disable Cloud Password";
|
||||
"lng_settings_password_abort" = "Abort two-step verification setup";
|
||||
"lng_settings_password_reenter_email" = "Re-enter recovery email";
|
||||
"lng_settings_about_bio" = "Any details such as age, occupation or city.\nExample: 23 y.o. designer from San Francisco";
|
||||
@@ -540,6 +541,31 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_security_bots" = "Bots and websites";
|
||||
"lng_settings_clear_payment_info" = "Clear Payment and Shipping Info";
|
||||
|
||||
"lng_settings_cloud_password_on" = "On";
|
||||
"lng_settings_cloud_password_off" = "Off";
|
||||
"lng_settings_cloud_password_start_title" = "Two-Step Verification";
|
||||
"lng_settings_cloud_password_password_title" = "Password";
|
||||
"lng_settings_cloud_password_hint_title" = "Password Hint";
|
||||
"lng_settings_cloud_password_email_title" = "Recovery Email";
|
||||
"lng_settings_cloud_password_start_about" = "Protect your Telegram account with an additional password.";
|
||||
"lng_settings_cloud_password_hint_about" = "You can create a hint for your password.";
|
||||
"lng_settings_cloud_password_email_about" = "Please enter your new recovery email. It is the only way to recover a forgotten password.";
|
||||
"lng_settings_cloud_password_password_subtitle" = "Create Password";
|
||||
"lng_settings_cloud_password_check_subtitle" = "Your Password";
|
||||
"lng_settings_cloud_password_hint_subtitle" = "Add Password Hint";
|
||||
"lng_settings_cloud_password_email_subtitle" = "Add Recovery Email";
|
||||
"lng_settings_cloud_password_email_recovery_subtitle" = "Password Recovery";
|
||||
"lng_settings_cloud_password_manage_about1" = "You have Two-Step Verification enabled, so your account is protected with an additional password.";
|
||||
"lng_settings_cloud_password_manage_about2" = "This email is the only way to recover a forgotten password.";
|
||||
"lng_settings_cloud_password_manage_disable_sure" = "Are you sure you want to disable your password?";
|
||||
"lng_settings_cloud_password_manage_email_new" = "Set Recovery Email";
|
||||
"lng_settings_cloud_password_manage_email_change" = "Change Recovery Email";
|
||||
"lng_settings_cloud_password_manage_password_change" = "Change Password";
|
||||
"lng_settings_cloud_password_skip_hint" = "Skip hint";
|
||||
"lng_settings_cloud_password_save" = "Save and Finish";
|
||||
"lng_settings_cloud_password_email_confirm" = "Confirm and Finish";
|
||||
"lng_settings_cloud_password_reset_in" = "You can reset your password in {duration}.";
|
||||
|
||||
"lng_clear_payment_info_title" = "Clear payment info";
|
||||
"lng_clear_payment_info_sure" = "Are you sure you want to clear your payment and shipping info?";
|
||||
"lng_clear_payment_info_shipping" = "Shipping info";
|
||||
@@ -634,7 +660,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_passcode_remove_button" = "Remove";
|
||||
|
||||
"lng_passcode_turn_on" = "Turn on local passcode";
|
||||
"lng_passcode_change" = "Change local passcode";
|
||||
"lng_passcode_change" = "Change Passcode";
|
||||
"lng_passcode_create" = "Local passcode";
|
||||
"lng_passcode_remove" = "Remove local passcode";
|
||||
"lng_passcode_turn_off" = "Turn off";
|
||||
@@ -647,6 +673,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_passcode_enter_new" = "Enter new passcode";
|
||||
"lng_passcode_confirm_new" = "Re-enter new passcode";
|
||||
"lng_passcode_about" = "When a local passcode is set, a lock icon appears at the top of your chats list. Click it to lock the app.\n\nNote: if you forget your local passcode, you'll need to relogin in Telegram Desktop.";
|
||||
"lng_passcode_about1" = "When a local passcode is set, a lock icon appears at the top of your chats list.";
|
||||
"lng_passcode_about2" = "Click it to lock Telegram Desktop.";
|
||||
"lng_passcode_about3" = "Note: if you forget your passcode, you'll need to log out of Telegram Desktop and log in again.";
|
||||
"lng_passcode_differ" = "Passcodes are different";
|
||||
"lng_passcode_wrong" = "Wrong passcode";
|
||||
"lng_passcode_is_same" = "Passcode was not changed";
|
||||
@@ -655,6 +684,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_passcode_submit" = "Submit";
|
||||
"lng_passcode_logout" = "Log out";
|
||||
"lng_passcode_need_unblock" = "You need to unlock me first.";
|
||||
"lng_passcode_create_button" = "Save Passcode";
|
||||
"lng_passcode_check_button" = "Submit";
|
||||
"lng_passcode_change_button" = "Save Passcode";
|
||||
"lng_passcode_create_title" = "Create Local Passcode";
|
||||
"lng_passcode_check_title" = "Enter Passcode";
|
||||
"lng_passcode_change_title" = "Enter Passcode";
|
||||
|
||||
"lng_cloud_password_waiting_code" = "Confirmation code sent to {email}...";
|
||||
"lng_cloud_password_confirm" = "Confirm recovery email";
|
||||
@@ -668,12 +703,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_cloud_password_reset_cancel" = "Cancel password reset";
|
||||
"lng_cloud_password_enter_old" = "Enter current password";
|
||||
"lng_cloud_password_enter_first" = "Enter a password";
|
||||
"lng_cloud_password_enter_new" = "Enter new password";
|
||||
"lng_cloud_password_confirm_new" = "Re-enter new password";
|
||||
"lng_cloud_password_hint" = "Enter password hint";
|
||||
"lng_cloud_password_enter_new" = "Enter password";
|
||||
"lng_cloud_password_confirm_new" = "Re-enter password";
|
||||
"lng_cloud_password_hint" = "Enter Password Hint";
|
||||
"lng_cloud_password_change_hint" = "Enter new password hint";
|
||||
"lng_cloud_password_bad" = "Password and hint cannot be the same.";
|
||||
"lng_cloud_password_email" = "Enter recovery email";
|
||||
"lng_cloud_password_email" = "Enter Email";
|
||||
"lng_cloud_password_bad_email" = "Incorrect email, please try other.";
|
||||
"lng_cloud_password_about" = "This password will be asked when you log in on a new device in addition to the SMS code.";
|
||||
"lng_cloud_password_about_recover" = "Warning! Are you sure you don't want to\nadd a password recovery email?\n\nIf you forget your password, you will\nlose access to your Telegram account.";
|
||||
@@ -695,6 +730,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_cloud_password_reset_cancel_title" = "Cancel reset";
|
||||
"lng_cloud_password_reset_cancel_sure" = "Cancel the password reset process? If you request a new reset later, it will take another 7 days.";
|
||||
"lng_cloud_password_reset_later" = "You recently requested a password reset that was cancelled. Please wait {duration} before making a new request.";
|
||||
"lng_cloud_password_expired" = "Please re-enter your password.";
|
||||
|
||||
"lng_connection_auto_connecting" = "Default (connecting...)";
|
||||
"lng_connection_auto" = "Default ({transport} used)";
|
||||
@@ -799,6 +835,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_blocked_list_confirm_text" = "Do you want to block {name} from messaging and calling you on Telegram?";
|
||||
"lng_blocked_list_confirm_clear" = "Delete this chat";
|
||||
"lng_blocked_list_confirm_ok" = "Block";
|
||||
"lng_blocked_list_empty_title" = "No blocked users";
|
||||
"lng_blocked_list_empty_description" = "You haven't blocked anyone yet.";
|
||||
"lng_blocked_list_subtitle#one" = "{count} blocked user";
|
||||
"lng_blocked_list_subtitle#other" = "{count} blocked users";
|
||||
|
||||
"lng_edit_privacy_everyone" = "Everybody";
|
||||
"lng_edit_privacy_contacts" = "My contacts";
|
||||
@@ -1141,6 +1181,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_report_group_title" = "Report group";
|
||||
"lng_report_bot_title" = "Report bot";
|
||||
"lng_report_message_title" = "Report message";
|
||||
"lng_report_profile_photo_title" = "Report profile photo";
|
||||
"lng_report_profile_video_title" = "Report profile video";
|
||||
"lng_report_please_select_messages" = "Please select messages to report.";
|
||||
"lng_report_select_messages" = "Select messages";
|
||||
"lng_report_messages_none" = "Select Messages";
|
||||
@@ -1974,7 +2016,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_try_other_contact" = "Try someone else";
|
||||
"lng_create_group_link" = "Link";
|
||||
"lng_create_group_invite_link" = "Invite link";
|
||||
"lng_create_group_description" = "Description (optional)";
|
||||
"lng_create_group_description" = "Add description...";
|
||||
|
||||
"lng_drag_images_here" = "Drop images here";
|
||||
"lng_drag_photos_here" = "Drop photos here";
|
||||
@@ -2053,6 +2095,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_mediaview_yesterday" = "yesterday at {time}";
|
||||
"lng_mediaview_date_time" = "{date} at {time}";
|
||||
"lng_mediaview_set_userpic" = "Set as Main";
|
||||
"lng_mediaview_report_profile_photo" = "Report";
|
||||
|
||||
"lng_mediaview_saved_to" = "Image was saved to your {downloads} folder";
|
||||
"lng_mediaview_downloads" = "Downloads";
|
||||
@@ -2145,6 +2188,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_payments_webview_install_webkit" = "Please install WebKitGTK (webkit2gtk-5.0/webkit2gtk-4.1/webkit2gtk-4.0) using your package manager.";
|
||||
"lng_payments_webview_switch_mutter" = "Qt's window embedding doesn't work well with Mutter window manager. Please switch to another window manager or desktop environment.";
|
||||
"lng_payments_webview_switch_wayland" = "There is no way to embed WebView window on Wayland. Please switch to X11.";
|
||||
"lng_payments_webview_update_windows" = "Please update your system to Windows 8.1 or later.";
|
||||
"lng_payments_sure_close" = "Are you sure you want to close this payment form? The changes you made will be lost.";
|
||||
"lng_payments_receipt_label" = "Receipt";
|
||||
"lng_payments_receipt_label_test" = "Test receipt";
|
||||
@@ -2657,7 +2701,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_admin_log_pinned_message" = "{from} pinned this message:";
|
||||
"lng_admin_log_unpinned_message" = "{from} unpinned this message";
|
||||
"lng_admin_log_edited_caption" = "{from} edited caption:";
|
||||
"lng_admin_log_removed_caption" = "{from} removed caption";
|
||||
"lng_admin_log_edited_media" = "{from} edited media:";
|
||||
"lng_admin_log_edited_media_and_caption" = "{from} edited media and caption:";
|
||||
"lng_admin_log_edited_media_and_removed_caption" = "{from} edited media and removed caption:";
|
||||
"lng_admin_log_removed_caption" = "{from} removed caption:";
|
||||
"lng_admin_log_previous_caption" = "Original caption";
|
||||
"lng_admin_log_edited_message" = "{from} edited this message:";
|
||||
"lng_admin_log_previous_message" = "Original message";
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<RCC>
|
||||
<qresource prefix="/animations">
|
||||
<file alias="change_number.tgs">../../animations/change_number.tgs</file>
|
||||
<file alias="blocked_peers_empty.tgs">../../animations/blocked_peers_empty.tgs</file>
|
||||
<file alias="filters.tgs">../../animations/filters.tgs</file>
|
||||
<file alias="local_passcode_enter.tgs">../../animations/local_passcode_enter.tgs</file>
|
||||
<file alias="cloud_password/intro.tgs">../../animations/cloud_password/intro.tgs</file>
|
||||
<file alias="cloud_password/password_input.tgs">../../animations/cloud_password/password_input.tgs</file>
|
||||
<file alias="cloud_password/hint.tgs">../../animations/cloud_password/hint.tgs</file>
|
||||
<file alias="cloud_password/email.tgs">../../animations/cloud_password/email.tgs</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -125,7 +125,7 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
||||
chatEmpty#29562865 id:long = Chat;
|
||||
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
|
||||
chatForbidden#6592a1a7 id:long title:string = Chat;
|
||||
channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||
channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
|
||||
chatFull#d18ee226 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?Vector<string> = ChatFull;
|
||||
@@ -414,9 +414,9 @@ photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
|
||||
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
|
||||
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector<FileHash> = upload.File;
|
||||
|
||||
dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
|
||||
dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true this_port_only:flags.5?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
|
||||
|
||||
config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
|
||||
config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true force_try_ipv6:flags.14?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
|
||||
|
||||
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
|
||||
|
||||
@@ -874,7 +874,7 @@ phoneCallAccepted#3660c311 flags:# video:flags.6?true id:long access_hash:long d
|
||||
phoneCall#967f7c67 flags:# p2p_allowed:flags.5?true video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connections:Vector<PhoneConnection> start_date:int = PhoneCall;
|
||||
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.6?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall;
|
||||
|
||||
phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
|
||||
phoneConnection#9cc123c7 flags:# tcp:flags.0?true id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
|
||||
phoneConnectionWebrtc#635fe375 flags:# turn:flags.0?true stun:flags.1?true id:long ip:string ipv6:string port:int username:string password:string = PhoneConnection;
|
||||
|
||||
phoneCallProtocol#fc878fc8 flags:# udp_p2p:flags.0?true udp_reflector:flags.1?true min_layer:int max_layer:int library_versions:Vector<string> = PhoneCallProtocol;
|
||||
@@ -1227,7 +1227,7 @@ messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> use
|
||||
|
||||
messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
||||
|
||||
messageReplyHeader#a6d57763 flags:# reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
|
||||
messageReplyHeader#a6d57763 flags:# reply_to_scheduled:flags.2?true reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
|
||||
|
||||
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
|
||||
|
||||
@@ -1295,7 +1295,7 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR
|
||||
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
|
||||
|
||||
sponsoredMessage#3a836df8 flags:# random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector<MessageEntity> = SponsoredMessage;
|
||||
sponsoredMessage#3a836df8 flags:# recommended:flags.5?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector<MessageEntity> = SponsoredMessage;
|
||||
|
||||
messages.sponsoredMessages#65a4c7d5 messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
|
||||
|
||||
@@ -1807,6 +1807,7 @@ phone.joinGroupCallPresentation#cbea6bc4 call:InputGroupCall params:DataJSON = U
|
||||
phone.leaveGroupCallPresentation#1c50d144 call:InputGroupCall = Updates;
|
||||
phone.getGroupCallStreamChannels#1ab21940 call:InputGroupCall = phone.GroupCallStreamChannels;
|
||||
phone.getGroupCallStreamRtmpUrl#deb3abbf peer:InputPeer revoke:Bool = phone.GroupCallStreamRtmpUrl;
|
||||
phone.saveCallLog#41248786 peer:InputPhoneCall file:InputFile = Bool;
|
||||
|
||||
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
|
||||
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
||||
@@ -1823,4 +1824,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel
|
||||
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
|
||||
|
||||
// LAYER 140
|
||||
// LAYER 142
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="3.6.3.0" />
|
||||
Version="3.7.5.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
||||
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,6,3,0
|
||||
PRODUCTVERSION 3,6,3,0
|
||||
FILEVERSION 3,7,5,0
|
||||
PRODUCTVERSION 3,7,5,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -62,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "3.6.3.0"
|
||||
VALUE "FileVersion", "3.7.5.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "3.6.3.0"
|
||||
VALUE "ProductVersion", "3.7.5.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,6,3,0
|
||||
PRODUCTVERSION 3,6,3,0
|
||||
FILEVERSION 3,7,5,0
|
||||
PRODUCTVERSION 3,7,5,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", "3.6.3.0"
|
||||
VALUE "FileVersion", "3.7.5.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "3.6.3.0"
|
||||
VALUE "ProductVersion", "3.7.5.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -7,18 +7,37 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "api/api_cloud_password.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "base/random.h"
|
||||
#include "core/core_cloud_password.h"
|
||||
#include "apiwrap.h"
|
||||
#include "passport/passport_encryption.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
// #TODO Add ability to set recovery email separately.
|
||||
[[nodiscard]] Core::CloudPasswordState ProcessMtpState(
|
||||
const MTPaccount_password &state) {
|
||||
return state.match([&](const MTPDaccount_password &data) {
|
||||
base::RandomAddSeed(bytes::make_span(data.vsecure_random().v));
|
||||
return Core::ParseCloudPasswordState(data);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CloudPassword::CloudPassword(not_null<ApiWrap*> api)
|
||||
: _api(&api->instance()) {
|
||||
}
|
||||
|
||||
void CloudPassword::apply(Core::CloudPasswordState state) {
|
||||
if (_state) {
|
||||
*_state = std::move(state);
|
||||
} else {
|
||||
_state = std::make_unique<Core::CloudPasswordState>(std::move(state));
|
||||
}
|
||||
_stateChanges.fire_copy(*_state);
|
||||
}
|
||||
|
||||
void CloudPassword::reload() {
|
||||
if (_requestId) {
|
||||
return;
|
||||
@@ -26,16 +45,7 @@ void CloudPassword::reload() {
|
||||
_requestId = _api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
_requestId = 0;
|
||||
result.match([&](const MTPDaccount_password &data) {
|
||||
base::RandomAddSeed(bytes::make_span(data.vsecure_random().v));
|
||||
if (_state) {
|
||||
*_state = Core::ParseCloudPasswordState(data);
|
||||
} else {
|
||||
_state = std::make_unique<Core::CloudPasswordState>(
|
||||
Core::ParseCloudPasswordState(data));
|
||||
}
|
||||
_stateChanges.fire_copy(*_state);
|
||||
});
|
||||
apply(ProcessMtpState(result));
|
||||
}).fail([=] {
|
||||
_requestId = 0;
|
||||
}).send();
|
||||
@@ -109,4 +119,426 @@ auto CloudPassword::cancelResetPassword()
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<CloudPassword::SetOk, QString> CloudPassword::set(
|
||||
const QString &oldPassword,
|
||||
const QString &newPassword,
|
||||
const QString &hint,
|
||||
bool hasRecoveryEmail,
|
||||
const QString &recoveryEmail) {
|
||||
|
||||
const auto generatePasswordCheck = [=](
|
||||
const Core::CloudPasswordState &latestState) {
|
||||
if (oldPassword.isEmpty() || !latestState.hasPassword) {
|
||||
return Core::CloudPasswordResult{
|
||||
MTP_inputCheckPasswordEmpty()
|
||||
};
|
||||
}
|
||||
const auto hash = Core::ComputeCloudPasswordHash(
|
||||
latestState.mtp.request.algo,
|
||||
bytes::make_span(oldPassword.toUtf8()));
|
||||
return Core::ComputeCloudPasswordCheck(
|
||||
latestState.mtp.request,
|
||||
hash);
|
||||
};
|
||||
|
||||
const auto finish = [=](auto consumer, int unconfirmedEmailLengthCode) {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
apply(ProcessMtpState(result));
|
||||
if (unconfirmedEmailLengthCode) {
|
||||
consumer.put_next(SetOk{ unconfirmedEmailLengthCode });
|
||||
} else {
|
||||
consumer.put_done();
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).handleFloodErrors().send();
|
||||
};
|
||||
|
||||
const auto sendMTPaccountUpdatePasswordSettings = [=](
|
||||
const Core::CloudPasswordState &latestState,
|
||||
const QByteArray &secureSecret,
|
||||
auto consumer) {
|
||||
const auto newPasswordBytes = newPassword.toUtf8();
|
||||
const auto newPasswordHash = Core::ComputeCloudPasswordDigest(
|
||||
latestState.mtp.newPassword,
|
||||
bytes::make_span(newPasswordBytes));
|
||||
if (!newPassword.isEmpty() && newPasswordHash.modpow.empty()) {
|
||||
consumer.put_error("INTERNAL_SERVER_ERROR");
|
||||
return;
|
||||
}
|
||||
using Flag = MTPDaccount_passwordInputSettings::Flag;
|
||||
const auto flags = Flag::f_new_algo
|
||||
| Flag::f_new_password_hash
|
||||
| Flag::f_hint
|
||||
| (secureSecret.isEmpty() ? Flag(0) : Flag::f_new_secure_settings)
|
||||
| ((!hasRecoveryEmail) ? Flag(0) : Flag::f_email);
|
||||
|
||||
auto newSecureSecret = bytes::vector();
|
||||
auto newSecureSecretId = 0ULL;
|
||||
if (!secureSecret.isEmpty()) {
|
||||
newSecureSecretId = Passport::CountSecureSecretId(
|
||||
bytes::make_span(secureSecret));
|
||||
newSecureSecret = Passport::EncryptSecureSecret(
|
||||
bytes::make_span(secureSecret),
|
||||
Core::ComputeSecureSecretHash(
|
||||
latestState.mtp.newSecureSecret,
|
||||
bytes::make_span(newPasswordBytes)));
|
||||
}
|
||||
const auto settings = MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
Core::PrepareCloudPasswordAlgo(newPassword.isEmpty()
|
||||
? v::null
|
||||
: latestState.mtp.newPassword),
|
||||
newPassword.isEmpty()
|
||||
? MTP_bytes()
|
||||
: MTP_bytes(newPasswordHash.modpow),
|
||||
MTP_string(hint),
|
||||
MTP_string(recoveryEmail),
|
||||
MTP_secureSecretSettings(
|
||||
Core::PrepareSecureSecretAlgo(
|
||||
latestState.mtp.newSecureSecret),
|
||||
MTP_bytes(newSecureSecret),
|
||||
MTP_long(newSecureSecretId)));
|
||||
_api.request(MTPaccount_UpdatePasswordSettings(
|
||||
generatePasswordCheck(latestState).result,
|
||||
settings
|
||||
)).done([=] {
|
||||
finish(consumer, 0);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
const auto &type = error.type();
|
||||
const auto prefix = u"EMAIL_UNCONFIRMED_"_q;
|
||||
if (type.startsWith(prefix)) {
|
||||
const auto codeLength = base::StringViewMid(
|
||||
type,
|
||||
prefix.size()).toInt();
|
||||
|
||||
finish(consumer, codeLength);
|
||||
} else {
|
||||
consumer.put_error_copy(type);
|
||||
}
|
||||
}).handleFloodErrors().send();
|
||||
};
|
||||
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
const auto latestState = ProcessMtpState(result);
|
||||
|
||||
if (latestState.hasPassword
|
||||
&& !oldPassword.isEmpty()
|
||||
&& !newPassword.isEmpty()) {
|
||||
|
||||
_api.request(MTPaccount_GetPasswordSettings(
|
||||
generatePasswordCheck(latestState).result
|
||||
)).done([=](const MTPaccount_PasswordSettings &result) {
|
||||
using Settings = MTPDaccount_passwordSettings;
|
||||
const auto &data = result.match([&](
|
||||
const Settings &data) -> const Settings & {
|
||||
return data;
|
||||
});
|
||||
auto secureSecret = QByteArray();
|
||||
if (const auto wrapped = data.vsecure_settings()) {
|
||||
using Secure = MTPDsecureSecretSettings;
|
||||
const auto &settings = wrapped->match([](
|
||||
const Secure &data) -> const Secure & {
|
||||
return data;
|
||||
});
|
||||
const auto passwordUtf = oldPassword.toUtf8();
|
||||
const auto secret = Passport::DecryptSecureSecret(
|
||||
bytes::make_span(settings.vsecure_secret().v),
|
||||
Core::ComputeSecureSecretHash(
|
||||
Core::ParseSecureSecretAlgo(
|
||||
settings.vsecure_algo()),
|
||||
bytes::make_span(passwordUtf)));
|
||||
if (secret.empty()) {
|
||||
LOG(("API Error: "
|
||||
"Failed to decrypt secure secret."));
|
||||
consumer.put_error("SUGGEST_SECRET_RESET");
|
||||
return;
|
||||
} else if (Passport::CountSecureSecretId(secret)
|
||||
!= settings.vsecure_secret_id().v) {
|
||||
LOG(("API Error: Wrong secure secret id."));
|
||||
consumer.put_error("SUGGEST_SECRET_RESET");
|
||||
return;
|
||||
} else {
|
||||
secureSecret = QByteArray(
|
||||
reinterpret_cast<const char*>(secret.data()),
|
||||
secret.size());
|
||||
}
|
||||
}
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
const auto latestState = ProcessMtpState(result);
|
||||
sendMTPaccountUpdatePasswordSettings(
|
||||
latestState,
|
||||
secureSecret,
|
||||
consumer);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
} else {
|
||||
sendMTPaccountUpdatePasswordSettings(
|
||||
latestState,
|
||||
QByteArray(),
|
||||
consumer);
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> CloudPassword::check(
|
||||
const QString &password) {
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
const auto latestState = ProcessMtpState(result);
|
||||
const auto input = [&] {
|
||||
if (password.isEmpty()) {
|
||||
return Core::CloudPasswordResult{
|
||||
MTP_inputCheckPasswordEmpty()
|
||||
};
|
||||
}
|
||||
const auto hash = Core::ComputeCloudPasswordHash(
|
||||
latestState.mtp.request.algo,
|
||||
bytes::make_span(password.toUtf8()));
|
||||
return Core::ComputeCloudPasswordCheck(
|
||||
latestState.mtp.request,
|
||||
hash);
|
||||
}();
|
||||
|
||||
_api.request(MTPaccount_GetPasswordSettings(
|
||||
input.result
|
||||
)).done([=](const MTPaccount_PasswordSettings &result) {
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> CloudPassword::confirmEmail(
|
||||
const QString &code) {
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPaccount_ConfirmPasswordEmail(
|
||||
MTP_string(code)
|
||||
)).done([=] {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
apply(ProcessMtpState(result));
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).handleFloodErrors().send();
|
||||
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> CloudPassword::resendEmailCode() {
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPaccount_ResendPasswordEmail(
|
||||
)).done([=] {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
apply(ProcessMtpState(result));
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).handleFloodErrors().send();
|
||||
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<CloudPassword::SetOk, QString> CloudPassword::setEmail(
|
||||
const QString &oldPassword,
|
||||
const QString &recoveryEmail) {
|
||||
const auto generatePasswordCheck = [=](
|
||||
const Core::CloudPasswordState &latestState) {
|
||||
if (oldPassword.isEmpty() || !latestState.hasPassword) {
|
||||
return Core::CloudPasswordResult{
|
||||
MTP_inputCheckPasswordEmpty()
|
||||
};
|
||||
}
|
||||
const auto hash = Core::ComputeCloudPasswordHash(
|
||||
latestState.mtp.request.algo,
|
||||
bytes::make_span(oldPassword.toUtf8()));
|
||||
return Core::ComputeCloudPasswordCheck(
|
||||
latestState.mtp.request,
|
||||
hash);
|
||||
};
|
||||
|
||||
const auto finish = [=](auto consumer, int unconfirmedEmailLengthCode) {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
apply(ProcessMtpState(result));
|
||||
if (unconfirmedEmailLengthCode) {
|
||||
consumer.put_next(SetOk{ unconfirmedEmailLengthCode });
|
||||
} else {
|
||||
consumer.put_done();
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).handleFloodErrors().send();
|
||||
};
|
||||
|
||||
const auto sendMTPaccountUpdatePasswordSettings = [=](
|
||||
const Core::CloudPasswordState &latestState,
|
||||
auto consumer) {
|
||||
const auto settings = MTP_account_passwordInputSettings(
|
||||
MTP_flags(MTPDaccount_passwordInputSettings::Flag::f_email),
|
||||
MTP_passwordKdfAlgoUnknown(),
|
||||
MTP_bytes(),
|
||||
MTP_string(),
|
||||
MTP_string(recoveryEmail),
|
||||
MTPSecureSecretSettings());
|
||||
_api.request(MTPaccount_UpdatePasswordSettings(
|
||||
generatePasswordCheck(latestState).result,
|
||||
settings
|
||||
)).done([=] {
|
||||
finish(consumer, 0);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
const auto &type = error.type();
|
||||
const auto prefix = u"EMAIL_UNCONFIRMED_"_q;
|
||||
if (type.startsWith(prefix)) {
|
||||
const auto codeLength = base::StringViewMid(
|
||||
type,
|
||||
prefix.size()).toInt();
|
||||
|
||||
finish(consumer, codeLength);
|
||||
} else {
|
||||
consumer.put_error_copy(type);
|
||||
}
|
||||
}).handleFloodErrors().send();
|
||||
};
|
||||
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
const auto latestState = ProcessMtpState(result);
|
||||
sendMTPaccountUpdatePasswordSettings(latestState, consumer);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> CloudPassword::recoverPassword(
|
||||
const QString &code,
|
||||
const QString &newPassword,
|
||||
const QString &newHint) {
|
||||
|
||||
const auto finish = [=](auto consumer) {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
apply(ProcessMtpState(result));
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).handleFloodErrors().send();
|
||||
};
|
||||
|
||||
const auto sendMTPaccountUpdatePasswordSettings = [=](
|
||||
const Core::CloudPasswordState &latestState,
|
||||
auto consumer) {
|
||||
const auto newPasswordBytes = newPassword.toUtf8();
|
||||
const auto newPasswordHash = Core::ComputeCloudPasswordDigest(
|
||||
latestState.mtp.newPassword,
|
||||
bytes::make_span(newPasswordBytes));
|
||||
if (!newPassword.isEmpty() && newPasswordHash.modpow.empty()) {
|
||||
consumer.put_error("INTERNAL_SERVER_ERROR");
|
||||
return;
|
||||
}
|
||||
using Flag = MTPDaccount_passwordInputSettings::Flag;
|
||||
const auto flags = Flag::f_new_algo
|
||||
| Flag::f_new_password_hash
|
||||
| Flag::f_hint;
|
||||
|
||||
const auto settings = MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
Core::PrepareCloudPasswordAlgo(newPassword.isEmpty()
|
||||
? v::null
|
||||
: latestState.mtp.newPassword),
|
||||
newPassword.isEmpty()
|
||||
? MTP_bytes()
|
||||
: MTP_bytes(newPasswordHash.modpow),
|
||||
MTP_string(newHint),
|
||||
MTP_string(),
|
||||
MTPSecureSecretSettings());
|
||||
|
||||
_api.request(MTPauth_RecoverPassword(
|
||||
MTP_flags(newPassword.isEmpty()
|
||||
? MTPauth_RecoverPassword::Flags(0)
|
||||
: MTPauth_RecoverPassword::Flag::f_new_settings),
|
||||
MTP_string(code),
|
||||
settings
|
||||
)).done([=](const MTPauth_Authorization &result) {
|
||||
finish(consumer);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
const auto &type = error.type();
|
||||
consumer.put_error_copy(type);
|
||||
}).handleFloodErrors().send();
|
||||
};
|
||||
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
const auto latestState = ProcessMtpState(result);
|
||||
sendMTPaccountUpdatePasswordSettings(latestState, consumer);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<QString, QString> CloudPassword::requestPasswordRecovery() {
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPauth_RequestPasswordRecovery(
|
||||
)).done([=](const MTPauth_PasswordRecovery &result) {
|
||||
result.match([&](const MTPDauth_passwordRecovery &data) {
|
||||
consumer.put_next(qs(data.vemail_pattern().v));
|
||||
});
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
auto CloudPassword::checkRecoveryEmailAddressCode(const QString &code)
|
||||
-> rpl::producer<rpl::no_value, QString> {
|
||||
return [=](auto consumer) {
|
||||
_api.request(MTPauth_CheckRecoveryPassword(
|
||||
MTP_string(code)
|
||||
)).done([=] {
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).handleFloodErrors().send();
|
||||
|
||||
return rpl::lifetime();
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -23,6 +23,10 @@ namespace Api {
|
||||
|
||||
class CloudPassword final {
|
||||
public:
|
||||
struct SetOk {
|
||||
int unconfirmedEmailLengthCode = 0;
|
||||
};
|
||||
|
||||
using ResetRetryDate = int;
|
||||
explicit CloudPassword(not_null<ApiWrap*> api);
|
||||
|
||||
@@ -34,7 +38,31 @@ public:
|
||||
rpl::producer<ResetRetryDate, QString> resetPassword();
|
||||
rpl::producer<rpl::no_value, QString> cancelResetPassword();
|
||||
|
||||
rpl::producer<SetOk, QString> set(
|
||||
const QString &oldPassword,
|
||||
const QString &newPassword,
|
||||
const QString &hint,
|
||||
bool hasRecoveryEmail,
|
||||
const QString &recoveryEmail);
|
||||
rpl::producer<rpl::no_value, QString> check(const QString &password);
|
||||
|
||||
rpl::producer<rpl::no_value, QString> confirmEmail(const QString &code);
|
||||
rpl::producer<rpl::no_value, QString> resendEmailCode();
|
||||
rpl::producer<SetOk, QString> setEmail(
|
||||
const QString &oldPassword,
|
||||
const QString &recoveryEmail);
|
||||
|
||||
rpl::producer<rpl::no_value, QString> recoverPassword(
|
||||
const QString &code,
|
||||
const QString &newPassword,
|
||||
const QString &newHint);
|
||||
rpl::producer<QString, QString> requestPasswordRecovery();
|
||||
rpl::producer<rpl::no_value, QString> checkRecoveryEmailAddressCode(
|
||||
const QString &code);
|
||||
|
||||
private:
|
||||
void apply(Core::CloudPasswordState state);
|
||||
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _requestId = 0;
|
||||
std::unique_ptr<Core::CloudPasswordState> _state;
|
||||
|
||||
@@ -83,7 +83,7 @@ MTPInputMedia PrepareUploadedPhoto(RemoteFileInfo info) {
|
||||
MTP_flags(flags),
|
||||
info.file,
|
||||
MTP_vector<MTPInputDocument>(
|
||||
ranges::to<QVector>(info.attachedStickers)),
|
||||
ranges::to<QVector<MTPInputDocument>>(info.attachedStickers)),
|
||||
MTP_int(0));
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ MTPInputMedia PrepareUploadedDocument(
|
||||
MTP_string(document->mimeString()),
|
||||
ComposeSendingDocumentAttributes(document),
|
||||
MTP_vector<MTPInputDocument>(
|
||||
ranges::to<QVector>(info.attachedStickers)),
|
||||
ranges::to<QVector<MTPInputDocument>>(info.attachedStickers)),
|
||||
MTP_int(0));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "main/main_session.h"
|
||||
|
||||
namespace Api {
|
||||
|
||||
namespace {
|
||||
|
||||
MessageIdsList HistoryItemsFromTL(
|
||||
[[nodiscard]] MessageIdsList HistoryItemsFromTL(
|
||||
not_null<Data::Session*> data,
|
||||
const QVector<MTPMessage> &messages) {
|
||||
auto result = MessageIdsList();
|
||||
@@ -45,8 +44,12 @@ MessageIdsList HistoryItemsFromTL(
|
||||
} // namespace
|
||||
|
||||
MessagesSearch::MessagesSearch(not_null<History*> history)
|
||||
: _history(history)
|
||||
, _api(&history->session().mtp()) {
|
||||
: _history(history) {
|
||||
}
|
||||
|
||||
MessagesSearch::~MessagesSearch() {
|
||||
_history->owner().histories().cancelRequest(
|
||||
base::take(_searchInHistoryRequest));
|
||||
}
|
||||
|
||||
void MessagesSearch::searchMessages(const QString &query, PeerData *from) {
|
||||
@@ -78,7 +81,7 @@ void MessagesSearch::searchRequest() {
|
||||
const auto flags = _from
|
||||
? MTP_flags(MTPmessages_Search::Flag::f_from_id)
|
||||
: MTP_flags(0);
|
||||
_requestId = _api.request(MTPmessages_Search(
|
||||
_requestId = _history->session().api().request(MTPmessages_Search(
|
||||
flags,
|
||||
_history->peer->input,
|
||||
MTP_string(_query),
|
||||
@@ -102,10 +105,11 @@ void MessagesSearch::searchRequest() {
|
||||
}).fail([=](const MTP::Error &error, mtpRequestId id) {
|
||||
_searchInHistoryRequest = 0;
|
||||
|
||||
if (_requestId == id) {
|
||||
_requestId = 0;
|
||||
}
|
||||
if (error.type() == u"SEARCH_QUERY_EMPTY"_q) {
|
||||
_messagesFounds.fire({ 0, MessageIdsList(), nextToken });
|
||||
} else if (_requestId == id) {
|
||||
_requestId = 0;
|
||||
}
|
||||
|
||||
finish();
|
||||
@@ -159,7 +163,7 @@ void MessagesSearch::searchReceived(
|
||||
owner.processChats(data.vchats());
|
||||
}
|
||||
auto items = HistoryItemsFromTL(&owner, data.vmessages().v);
|
||||
const auto total = int(data.vmessages().v.size());
|
||||
const auto total = int(data.vcount().v);
|
||||
return FoundMessages{ total, std::move(items), nextToken };
|
||||
}, [](const MTPDmessages_messagesNotModified &data) {
|
||||
return FoundMessages{};
|
||||
|
||||
@@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class HistoryItem;
|
||||
class History;
|
||||
class PeerData;
|
||||
@@ -24,6 +22,7 @@ struct FoundMessages {
|
||||
class MessagesSearch final {
|
||||
public:
|
||||
explicit MessagesSearch(not_null<History*> history);
|
||||
~MessagesSearch();
|
||||
|
||||
void searchMessages(const QString &query, PeerData *from);
|
||||
void searchMore();
|
||||
@@ -39,7 +38,6 @@ private:
|
||||
const QString &nextToken);
|
||||
|
||||
const not_null<History*> _history;
|
||||
MTP::Sender _api;
|
||||
|
||||
base::flat_map<QString, TLMessages> _cacheOfStartByToken;
|
||||
|
||||
|
||||
@@ -18,11 +18,10 @@ bool MessagesSearchMerged::RequestCompare::operator()(
|
||||
}
|
||||
|
||||
MessagesSearchMerged::MessagesSearchMerged(not_null<History*> history)
|
||||
: _apiSearch(history)
|
||||
, _migratedSearch(history->migrateFrom()
|
||||
? std::make_optional<MessagesSearch>(history->migrateFrom())
|
||||
: std::nullopt) {
|
||||
|
||||
: _apiSearch(history) {
|
||||
if (const auto migrated = history->migrateFrom()) {
|
||||
_migratedSearch.emplace(migrated);
|
||||
}
|
||||
const auto checkWaitingForTotal = [=] {
|
||||
if (_waitingForTotal) {
|
||||
if (_concatedFound.total >= 0 && _migratedFirstFound.total >= 0) {
|
||||
|
||||
78
Telegram/SourceFiles/api/api_report.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
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_report.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/boxes/report_box.h"
|
||||
#include "ui/toast/toast.h"
|
||||
|
||||
namespace Api {
|
||||
|
||||
namespace {
|
||||
|
||||
MTPreportReason ReasonToTL(const Ui::ReportReason &reason) {
|
||||
using Reason = Ui::ReportReason;
|
||||
switch (reason) {
|
||||
case Reason::Spam: return MTP_inputReportReasonSpam();
|
||||
case Reason::Fake: return MTP_inputReportReasonFake();
|
||||
case Reason::Violence: return MTP_inputReportReasonViolence();
|
||||
case Reason::ChildAbuse: return MTP_inputReportReasonChildAbuse();
|
||||
case Reason::Pornography: return MTP_inputReportReasonPornography();
|
||||
case Reason::Copyright: return MTP_inputReportReasonCopyright();
|
||||
case Reason::IllegalDrugs: return MTP_inputReportReasonIllegalDrugs();
|
||||
case Reason::PersonalDetails:
|
||||
return MTP_inputReportReasonPersonalDetails();
|
||||
case Reason::Other: return MTP_inputReportReasonOther();
|
||||
}
|
||||
Unexpected("Bad reason group value.");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SendReport(
|
||||
not_null<QWidget*> toastParent,
|
||||
not_null<PeerData*> peer,
|
||||
Ui::ReportReason reason,
|
||||
const QString &comment,
|
||||
std::variant<v::null_t, MessageIdsList, not_null<PhotoData*>> data) {
|
||||
auto done = [=] {
|
||||
Ui::Toast::Show(toastParent, tr::lng_report_thanks(tr::now));
|
||||
};
|
||||
v::match(data, [&](v::null_t) {
|
||||
peer->session().api().request(MTPaccount_ReportPeer(
|
||||
peer->input,
|
||||
ReasonToTL(reason),
|
||||
MTP_string(comment)
|
||||
)).done(std::move(done)).send();
|
||||
}, [&](const MessageIdsList &ids) {
|
||||
auto apiIds = QVector<MTPint>();
|
||||
apiIds.reserve(ids.size());
|
||||
for (const auto &fullId : ids) {
|
||||
apiIds.push_back(MTP_int(fullId.msg));
|
||||
}
|
||||
peer->session().api().request(MTPmessages_Report(
|
||||
peer->input,
|
||||
MTP_vector<MTPint>(apiIds),
|
||||
ReasonToTL(reason),
|
||||
MTP_string(comment)
|
||||
)).done(std::move(done)).send();
|
||||
}, [&](not_null<PhotoData*> photo) {
|
||||
peer->session().api().request(MTPaccount_ReportProfilePhoto(
|
||||
peer->input,
|
||||
photo->mtpInput(),
|
||||
ReasonToTL(reason),
|
||||
MTP_string(comment)
|
||||
)).done(std::move(done)).send();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
26
Telegram/SourceFiles/api/api_report.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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 PeerData;
|
||||
class PhotoData;
|
||||
|
||||
namespace Ui {
|
||||
enum class ReportReason;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Api {
|
||||
|
||||
void SendReport(
|
||||
not_null<QWidget*> toastParent,
|
||||
not_null<PeerData*> peer,
|
||||
Ui::ReportReason reason,
|
||||
const QString &comment,
|
||||
std::variant<v::null_t, MessageIdsList, not_null<PhotoData*>> data);
|
||||
|
||||
} // namespace Api
|
||||
@@ -146,7 +146,6 @@ void Ringtones::requestList() {
|
||||
document->forceToCache(true);
|
||||
_list.documents.emplace_back(document->id);
|
||||
}
|
||||
requestList();
|
||||
_list.updates.fire({});
|
||||
}, [&](const MTPDaccount_savedRingtonesNotModified &) {
|
||||
});
|
||||
|
||||
@@ -3570,7 +3570,7 @@ void ApiWrap::sendBotStart(
|
||||
}
|
||||
|
||||
auto &info = bot->botInfo;
|
||||
auto &token = chat ? startTokenForChat : info->startToken;
|
||||
const auto token = chat ? startTokenForChat : info->startToken;
|
||||
if (token.isEmpty()) {
|
||||
auto message = MessageToSend(
|
||||
Api::SendAction(_session->data().history(chat
|
||||
|
||||
@@ -1393,6 +1393,18 @@ void EditNameBox::prepare() {
|
||||
|
||||
connect(_first, &Ui::InputField::submitted, [=] { submit(); });
|
||||
connect(_last, &Ui::InputField::submitted, [=] { submit(); });
|
||||
|
||||
_first->customTab(true);
|
||||
_last->customTab(true);
|
||||
|
||||
QObject::connect(
|
||||
_first,
|
||||
&Ui::InputField::tabbed,
|
||||
[=] { _last->setFocus(); });
|
||||
QObject::connect(
|
||||
_last,
|
||||
&Ui::InputField::tabbed,
|
||||
[=] { _first->setFocus(); });
|
||||
}
|
||||
|
||||
void EditNameBox::setInnerFocus() {
|
||||
|
||||
@@ -602,6 +602,9 @@ changePhoneError: FlatLabel(changePhoneLabel) {
|
||||
textFg: boxTextFgError;
|
||||
}
|
||||
|
||||
blockedUsersListSubtitleAddPadding: margins(0px, 1px, 0px, -14px);
|
||||
blockedUsersListIconPadding: margins(0px, 34px, 0px, 5px);
|
||||
|
||||
adminLogFilterUserpicLeft: 15px;
|
||||
adminLogFilterLittleSkip: 16px;
|
||||
adminLogFilterCheckbox: Checkbox(defaultBoxCheckbox) {
|
||||
|
||||
@@ -510,7 +510,7 @@ void ChangePhone::setupContent() {
|
||||
}
|
||||
|
||||
void ChangePhone::showFinished() {
|
||||
_animate();
|
||||
_animate(anim::repeat::loop);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
|
||||
@@ -36,7 +36,7 @@ private:
|
||||
void setupContent();
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
Fn<void()> _animate;
|
||||
Fn<void(anim::repeat)> _animate;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/filter_icons.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h" // Ui::Text::Bold
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
@@ -27,46 +26,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
namespace {
|
||||
|
||||
class FolderButton : public Ui::SettingsButton {
|
||||
public:
|
||||
FolderButton(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
const Data::ChatFilter &filter);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
const Ui::FilterIcon _icon;
|
||||
|
||||
};
|
||||
|
||||
FolderButton::FolderButton(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
const Data::ChatFilter &filter)
|
||||
: SettingsButton(
|
||||
parent,
|
||||
rpl::single(filter.title()),
|
||||
st::paymentsSectionButton)
|
||||
, _icon(Ui::ComputeFilterIcon(filter)) {
|
||||
}
|
||||
|
||||
void FolderButton::paintEvent(QPaintEvent *e) {
|
||||
SettingsButton::paintEvent(e);
|
||||
|
||||
Painter p(this);
|
||||
const auto over = isOver() || isDown();
|
||||
const auto icon = Ui::LookupFilterIcon(_icon).normal;
|
||||
icon->paint(
|
||||
p,
|
||||
st::settingsFilterIconLeft,
|
||||
(height() - icon->height()) / 2,
|
||||
width(),
|
||||
(over
|
||||
? st::dialogsUnreadBgMutedOver
|
||||
: st::dialogsUnreadBgMuted)->c);
|
||||
}
|
||||
|
||||
Data::ChatFilter ChangedFilter(
|
||||
const Data::ChatFilter &filter,
|
||||
not_null<History*> history,
|
||||
@@ -165,47 +124,6 @@ void ChooseFilterValidator::remove(FilterId filterId) const {
|
||||
ChangeFilterById(filterId, _history, false);
|
||||
}
|
||||
|
||||
void ChooseFilterBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<History*> history) {
|
||||
box->setTitle(tr::lng_filters_add_box_title());
|
||||
|
||||
const auto validator = ChooseFilterValidator(history);
|
||||
|
||||
const auto container = box->verticalLayout()->add(
|
||||
object_ptr<Ui::VerticalLayout>(box->verticalLayout()));
|
||||
|
||||
const auto rebuild = [=] {
|
||||
while (container->count()) {
|
||||
delete container->widgetAt(0);
|
||||
}
|
||||
for (const auto &filter : history->owner().chatsFilters().list()) {
|
||||
if (filter.contains(history)) {
|
||||
continue;
|
||||
}
|
||||
container->add(
|
||||
object_ptr<FolderButton>(box, filter),
|
||||
style::margins()
|
||||
)->setClickedCallback([=, id = filter.id()] {
|
||||
validator.add(id);
|
||||
box->closeBox();
|
||||
});
|
||||
}
|
||||
container->resizeToWidth(box->verticalLayout()->width());
|
||||
if (!container->count()) {
|
||||
box->closeBox();
|
||||
}
|
||||
};
|
||||
|
||||
history->owner().chatsFilters().changed(
|
||||
) | rpl::start_with_next([=] {
|
||||
rebuild();
|
||||
}, box->lifetime());
|
||||
rebuild();
|
||||
|
||||
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
void FillChooseFilterMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
not_null<History*> history) {
|
||||
|
||||
@@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#pragma once
|
||||
|
||||
namespace Ui {
|
||||
class GenericBox;
|
||||
class PopupMenu;
|
||||
} // namespace Ui
|
||||
|
||||
@@ -29,10 +28,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
void ChooseFilterBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<History*> history);
|
||||
|
||||
void FillChooseFilterMenu(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
not_null<History*> history);
|
||||
|
||||
@@ -500,6 +500,7 @@ void EditFilterBox(
|
||||
const Data::ChatFilter &filter,
|
||||
Fn<void(const Data::ChatFilter &)> doneCallback) {
|
||||
const auto creating = filter.title().isEmpty();
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->setTitle(creating ? tr::lng_filters_new() : tr::lng_filters_edit());
|
||||
box->setCloseByOutsideClick(false);
|
||||
|
||||
@@ -571,8 +572,9 @@ void EditFilterBox(
|
||||
|
||||
const auto includeAdd = AddButton(
|
||||
content,
|
||||
tr::lng_filters_add_chats() | Ui::Text::ToUpper(),
|
||||
st::settingsUpdate);
|
||||
tr::lng_filters_add_chats(),
|
||||
st::settingsButtonActive,
|
||||
{ &st::settingsIconAdd, 0, IconType::Round, &st::windowBgActive });
|
||||
|
||||
const auto include = SetupChatsPreview(
|
||||
content,
|
||||
@@ -582,21 +584,16 @@ void EditFilterBox(
|
||||
&Data::ChatFilter::always);
|
||||
|
||||
AddSkip(content);
|
||||
content->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
content,
|
||||
tr::lng_filters_include_about(),
|
||||
st::boxDividerLabel),
|
||||
st::windowFilterAboutPadding);
|
||||
AddDivider(content);
|
||||
AddDividerText(content, tr::lng_filters_include_about());
|
||||
AddSkip(content);
|
||||
|
||||
AddSubsectionTitle(content, tr::lng_filters_exclude());
|
||||
|
||||
const auto excludeAdd = AddButton(
|
||||
content,
|
||||
tr::lng_filters_remove_chats() | Ui::Text::ToUpper(),
|
||||
st::settingsUpdate);
|
||||
tr::lng_filters_remove_chats(),
|
||||
st::settingsButtonActive,
|
||||
{ &st::settingsIconRemove, 0, IconType::Round, &st::windowBgActive });
|
||||
|
||||
const auto exclude = SetupChatsPreview(
|
||||
content,
|
||||
@@ -606,12 +603,7 @@ void EditFilterBox(
|
||||
&Data::ChatFilter::never);
|
||||
|
||||
AddSkip(content);
|
||||
content->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
content,
|
||||
tr::lng_filters_exclude_about(),
|
||||
st::boxDividerLabel),
|
||||
st::windowFilterAboutPadding);
|
||||
AddDividerText(content, tr::lng_filters_exclude_about());
|
||||
|
||||
const auto refreshPreviews = [=] {
|
||||
include->updateData(
|
||||
|
||||
@@ -154,9 +154,10 @@ void StartPendingReset(
|
||||
PasscodeBox::CloudFields PasscodeBox::CloudFields::From(
|
||||
const Core::CloudPasswordState ¤t) {
|
||||
auto result = CloudFields();
|
||||
result.curRequest = current.request;
|
||||
result.newAlgo = current.newPassword;
|
||||
result.newSecureSecretAlgo = current.newSecureSecret;
|
||||
result.hasPassword = current.hasPassword;
|
||||
result.mtp.curRequest = current.mtp.request;
|
||||
result.mtp.newAlgo = current.mtp.newPassword;
|
||||
result.mtp.newSecureSecretAlgo = current.mtp.newSecureSecret;
|
||||
result.hasRecovery = current.hasRecovery;
|
||||
result.notEmptyPassport = current.notEmptyPassport;
|
||||
result.hint = current.hint;
|
||||
@@ -200,21 +201,21 @@ PasscodeBox::PasscodeBox(
|
||||
, _newPasscode(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
(fields.curRequest
|
||||
(fields.hasPassword
|
||||
? tr::lng_cloud_password_enter_new()
|
||||
: tr::lng_cloud_password_enter_first()))
|
||||
, _reenterPasscode(this, st::defaultInputField, tr::lng_cloud_password_confirm_new())
|
||||
, _passwordHint(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
(fields.curRequest
|
||||
(fields.hasPassword
|
||||
? tr::lng_cloud_password_change_hint()
|
||||
: tr::lng_cloud_password_hint()))
|
||||
, _recoverEmail(this, st::defaultInputField, tr::lng_cloud_password_email())
|
||||
, _recover(this, tr::lng_signin_recover(tr::now))
|
||||
, _showRecoverLink(_cloudFields.hasRecovery || !_cloudFields.pendingResetDate) {
|
||||
Expects(session != nullptr || !fields.fromRecoveryCode.isEmpty());
|
||||
Expects(!_turningOff || _cloudFields.curRequest);
|
||||
Expects(!_turningOff || _cloudFields.hasPassword);
|
||||
|
||||
if (!_cloudFields.hint.isEmpty()) {
|
||||
_hintText.setText(
|
||||
@@ -248,7 +249,7 @@ rpl::producer<MTPauth_Authorization> PasscodeBox::newAuthorization() const {
|
||||
|
||||
bool PasscodeBox::currentlyHave() const {
|
||||
return _cloudPwd
|
||||
? (!!_cloudFields.curRequest)
|
||||
? _cloudFields.hasPassword
|
||||
: _session->domain().local().hasLocalPasscode();
|
||||
}
|
||||
|
||||
@@ -609,7 +610,7 @@ void PasscodeBox::handleSrpIdInvalid() {
|
||||
const auto now = crl::now();
|
||||
if (_lastSrpIdInvalidTime > 0
|
||||
&& now - _lastSrpIdInvalidTime < Core::kHandleSrpIdInvalidTimeout) {
|
||||
_cloudFields.curRequest.id = 0;
|
||||
_cloudFields.mtp.curRequest.id = 0;
|
||||
_oldError = Lang::Hard::ServerError();
|
||||
update();
|
||||
} else {
|
||||
@@ -743,14 +744,14 @@ void PasscodeBox::checkPassword(
|
||||
CheckPasswordCallback callback) {
|
||||
const auto passwordUtf = oldPassword.toUtf8();
|
||||
_checkPasswordHash = Core::ComputeCloudPasswordHash(
|
||||
_cloudFields.curRequest.algo,
|
||||
_cloudFields.mtp.curRequest.algo,
|
||||
bytes::make_span(passwordUtf));
|
||||
checkPasswordHash(std::move(callback));
|
||||
}
|
||||
|
||||
void PasscodeBox::checkPasswordHash(CheckPasswordCallback callback) {
|
||||
_checkPasswordCallback = std::move(callback);
|
||||
if (_cloudFields.curRequest.id) {
|
||||
if (_cloudFields.mtp.curRequest.id) {
|
||||
passwordChecked();
|
||||
} else {
|
||||
requestPasswordData();
|
||||
@@ -758,16 +759,16 @@ void PasscodeBox::checkPasswordHash(CheckPasswordCallback callback) {
|
||||
}
|
||||
|
||||
void PasscodeBox::passwordChecked() {
|
||||
if (!_cloudFields.curRequest || !_cloudFields.curRequest.id || !_checkPasswordCallback) {
|
||||
if (!_cloudFields.mtp.curRequest || !_cloudFields.mtp.curRequest.id || !_checkPasswordCallback) {
|
||||
return serverError();
|
||||
}
|
||||
const auto check = Core::ComputeCloudPasswordCheck(
|
||||
_cloudFields.curRequest,
|
||||
_cloudFields.mtp.curRequest,
|
||||
_checkPasswordHash);
|
||||
if (!check) {
|
||||
return serverError();
|
||||
}
|
||||
_cloudFields.curRequest.id = 0;
|
||||
_cloudFields.mtp.curRequest.id = 0;
|
||||
_checkPasswordCallback(check);
|
||||
}
|
||||
|
||||
@@ -782,7 +783,7 @@ void PasscodeBox::requestPasswordData() {
|
||||
).done([=](const MTPaccount_Password &result) {
|
||||
_setRequest = 0;
|
||||
result.match([&](const MTPDaccount_password &data) {
|
||||
_cloudFields.curRequest = Core::ParseCloudPasswordCheckRequest(data);
|
||||
_cloudFields.mtp.curRequest = Core::ParseCloudPasswordCheckRequest(data);
|
||||
passwordChecked();
|
||||
});
|
||||
}).send();
|
||||
@@ -820,7 +821,7 @@ void PasscodeBox::sendClearCloudPassword(
|
||||
check.result,
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.newAlgo),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.mtp.newAlgo),
|
||||
MTP_bytes(), // new_password_hash
|
||||
MTP_string(hint),
|
||||
MTP_string(email),
|
||||
@@ -835,7 +836,7 @@ void PasscodeBox::sendClearCloudPassword(
|
||||
void PasscodeBox::setNewCloudPassword(const QString &newPassword) {
|
||||
const auto newPasswordBytes = newPassword.toUtf8();
|
||||
const auto newPasswordHash = Core::ComputeCloudPasswordDigest(
|
||||
_cloudFields.newAlgo,
|
||||
_cloudFields.mtp.newAlgo,
|
||||
bytes::make_span(newPasswordBytes));
|
||||
if (newPasswordHash.modpow.empty()) {
|
||||
return serverError();
|
||||
@@ -851,7 +852,7 @@ void PasscodeBox::setNewCloudPassword(const QString &newPassword) {
|
||||
|
||||
const auto settings = MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.newAlgo),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.mtp.newAlgo),
|
||||
MTP_bytes(newPasswordHash.modpow),
|
||||
MTP_string(hint),
|
||||
MTP_string(email),
|
||||
@@ -989,7 +990,7 @@ void PasscodeBox::sendChangeCloudPassword(
|
||||
const QByteArray &secureSecret) {
|
||||
const auto newPasswordBytes = newPassword.toUtf8();
|
||||
const auto newPasswordHash = Core::ComputeCloudPasswordDigest(
|
||||
_cloudFields.newAlgo,
|
||||
_cloudFields.mtp.newAlgo,
|
||||
bytes::make_span(newPasswordBytes));
|
||||
if (newPasswordHash.modpow.empty()) {
|
||||
return serverError();
|
||||
@@ -1007,19 +1008,19 @@ void PasscodeBox::sendChangeCloudPassword(
|
||||
newSecureSecret = Passport::EncryptSecureSecret(
|
||||
bytes::make_span(secureSecret),
|
||||
Core::ComputeSecureSecretHash(
|
||||
_cloudFields.newSecureSecretAlgo,
|
||||
_cloudFields.mtp.newSecureSecretAlgo,
|
||||
bytes::make_span(newPasswordBytes)));
|
||||
}
|
||||
_setRequest = _api.request(MTPaccount_UpdatePasswordSettings(
|
||||
check.result,
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.newAlgo),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.mtp.newAlgo),
|
||||
MTP_bytes(newPasswordHash.modpow),
|
||||
MTP_string(hint),
|
||||
MTPstring(), // email is not changing
|
||||
MTP_secureSecretSettings(
|
||||
Core::PrepareSecureSecretAlgo(_cloudFields.newSecureSecretAlgo),
|
||||
Core::PrepareSecureSecretAlgo(_cloudFields.mtp.newSecureSecretAlgo),
|
||||
MTP_bytes(newSecureSecret),
|
||||
MTP_long(newSecureSecretId)))
|
||||
)).done([=] {
|
||||
@@ -1294,7 +1295,8 @@ void RecoverBox::proceedToChange(const QString &code) {
|
||||
fields.hasRecovery = false;
|
||||
// we could've been turning off, no need to force new password then
|
||||
// like if (_cloudFields.turningOff) { just RecoverPassword else Check }
|
||||
fields.curRequest = {};
|
||||
fields.mtp.curRequest = {};
|
||||
fields.hasPassword = false;
|
||||
auto box = Box<PasscodeBox>(_session, fields);
|
||||
|
||||
box->boxClosing(
|
||||
|
||||
@@ -36,13 +36,17 @@ public:
|
||||
struct CloudFields {
|
||||
static CloudFields From(const Core::CloudPasswordState ¤t);
|
||||
|
||||
Core::CloudPasswordCheckRequest curRequest;
|
||||
Core::CloudPasswordAlgo newAlgo;
|
||||
struct Mtp {
|
||||
Core::CloudPasswordCheckRequest curRequest;
|
||||
Core::CloudPasswordAlgo newAlgo;
|
||||
Core::SecureSecretAlgo newSecureSecretAlgo;
|
||||
};
|
||||
Mtp mtp;
|
||||
bool hasPassword = false;
|
||||
bool hasRecovery = false;
|
||||
QString fromRecoveryCode;
|
||||
bool notEmptyPassport = false;
|
||||
QString hint;
|
||||
Core::SecureSecretAlgo newSecureSecretAlgo;
|
||||
bool turningOff = false;
|
||||
TimeId pendingResetDate = 0;
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/boxes/calendar_box.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "settings/settings_privacy_security.h"
|
||||
#include "ui/boxes/choose_date_time.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "boxes/passcode_box.h"
|
||||
#include "boxes/peers/add_bot_to_chat_box.h"
|
||||
@@ -510,7 +510,8 @@ not_null<Ui::SlideWrap<Ui::RpWidget>*> EditAdminBox::setupTransferButton(
|
||||
: tr::lng_rights_transfer_channel)(),
|
||||
rpl::single(QString()),
|
||||
[=] { transferOwnership(); },
|
||||
st::peerPermissionsButton));
|
||||
st::peerPermissionsButton,
|
||||
{}));
|
||||
|
||||
return wrap;
|
||||
}
|
||||
@@ -783,35 +784,33 @@ ChatRestrictionsInfo EditRestrictedBox::defaultRights() const {
|
||||
}
|
||||
|
||||
void EditRestrictedBox::showRestrictUntil() {
|
||||
auto tomorrow = QDate::currentDate().addDays(1);
|
||||
auto highlighted = isUntilForever()
|
||||
? tomorrow
|
||||
: base::unixtime::parse(getRealUntilValue()).date();
|
||||
auto month = highlighted;
|
||||
auto box = Box<Ui::CalendarBox>(Ui::CalendarBoxArgs{
|
||||
.month = month,
|
||||
.highlighted = highlighted,
|
||||
.callback = [=](const QDate &date) {
|
||||
setRestrictUntil(
|
||||
static_cast<int>(date.startOfDay().toSecsSinceEpoch()));
|
||||
},
|
||||
.finalize = [=](not_null<Ui::CalendarBox*> box) {
|
||||
box->addLeftButton(
|
||||
tr::lng_rights_chat_banned_forever(),
|
||||
[=] { setRestrictUntil(0); });
|
||||
},
|
||||
.minDate = tomorrow,
|
||||
.maxDate = QDate::currentDate().addDays(kMaxRestrictDelayDays),
|
||||
});
|
||||
_restrictUntilBox = Ui::MakeWeak(box.data());
|
||||
_show.showBox(std::move(box));
|
||||
_show.showBox(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
const auto save = [=](TimeId result) {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
setRestrictUntil(result);
|
||||
box->closeBox();
|
||||
};
|
||||
const auto now = base::unixtime::now();
|
||||
const auto time = isUntilForever()
|
||||
? (now + kSecondsInDay)
|
||||
: getRealUntilValue();
|
||||
ChooseDateTimeBox(box, {
|
||||
.title = tr::lng_rights_chat_banned_until_header(),
|
||||
.submit = tr::lng_settings_save(),
|
||||
.done = save,
|
||||
.min = [=] { return now; },
|
||||
.time = time,
|
||||
.max = [=] {
|
||||
return now + kSecondsInDay * kMaxRestrictDelayDays;
|
||||
},
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
void EditRestrictedBox::setRestrictUntil(TimeId until) {
|
||||
_until = until;
|
||||
if (_restrictUntilBox) {
|
||||
_restrictUntilBox->closeBox();
|
||||
}
|
||||
_untilVariants.clear();
|
||||
createUntilGroup();
|
||||
createUntilVariants();
|
||||
@@ -861,8 +860,7 @@ void EditRestrictedBox::createUntilVariants() {
|
||||
tr::lng_rights_chat_banned_custom_date(
|
||||
tr::now,
|
||||
lt_date,
|
||||
langDayOfMonthFull(
|
||||
base::unixtime::parse(until).date())));
|
||||
langDateTime(base::unixtime::parse(until))));
|
||||
}
|
||||
};
|
||||
auto addCurrentVariant = [&](TimeId from, TimeId to) {
|
||||
|
||||
@@ -17,7 +17,6 @@ class LinkButton;
|
||||
class Checkbox;
|
||||
class Radiobutton;
|
||||
class RadiobuttonGroup;
|
||||
class CalendarBox;
|
||||
class VerticalLayout;
|
||||
template <typename Widget>
|
||||
class SlideWrap;
|
||||
@@ -176,7 +175,6 @@ private:
|
||||
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> _untilGroup;
|
||||
std::vector<base::unique_qptr<Ui::Radiobutton>> _untilVariants;
|
||||
QPointer<Ui::CalendarBox> _restrictUntilBox;
|
||||
|
||||
static constexpr auto kUntilOneDay = -1;
|
||||
static constexpr auto kUntilOneWeek = -2;
|
||||
|
||||
@@ -7,125 +7,56 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "boxes/peers/edit_peer_history_visibility_box.h"
|
||||
|
||||
#include "boxes/peers/edit_peer_permissions_box.h"
|
||||
#include "boxes/peers/edit_participants_box.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_info.h"
|
||||
|
||||
namespace {
|
||||
void EditPeerHistoryVisibilityBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
bool isLegacy,
|
||||
Fn<void(HistoryVisibility)> savedCallback,
|
||||
HistoryVisibility historyVisibilitySavedValue) {
|
||||
const auto historyVisibility = std::make_shared<
|
||||
Ui::RadioenumGroup<HistoryVisibility>
|
||||
>(historyVisibilitySavedValue);
|
||||
|
||||
void AddRadioButton(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
HistoryVisibility value,
|
||||
const QString &groupText,
|
||||
rpl::producer<QString> groupAbout,
|
||||
std::shared_ptr<Ui::RadioenumGroup<HistoryVisibility>> historyVisibility) {
|
||||
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||
container,
|
||||
st::editPeerHistoryVisibilityTopSkip));
|
||||
container->add(object_ptr<Ui::Radioenum<HistoryVisibility>>(
|
||||
container,
|
||||
box->setTitle(tr::lng_manage_history_visibility_title());
|
||||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
savedCallback(historyVisibility->value());
|
||||
box->closeBox();
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
|
||||
box->addSkip(st::editPeerHistoryVisibilityTopSkip);
|
||||
box->addRow(object_ptr<Ui::Radioenum<HistoryVisibility>>(
|
||||
box,
|
||||
historyVisibility,
|
||||
value,
|
||||
groupText,
|
||||
st::defaultBoxCheckbox));
|
||||
container->add(object_ptr<Ui::PaddingWrap<Ui::FlatLabel>>(
|
||||
container,
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
container,
|
||||
std::move(groupAbout),
|
||||
st::editPeerPrivacyLabel),
|
||||
st::editPeerPreHistoryLabelMargins));
|
||||
}
|
||||
|
||||
void FillContent(
|
||||
not_null<Ui::VerticalLayout*> parent,
|
||||
not_null<PeerData*> peer,
|
||||
std::shared_ptr<Ui::RadioenumGroup<HistoryVisibility>> historyVisibility,
|
||||
HistoryVisibility savedValue) {
|
||||
const auto canEdit = [&] {
|
||||
if (const auto chat = peer->asChat()) {
|
||||
return chat->canEditPreHistoryHidden();
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
return channel->canEditPreHistoryHidden();
|
||||
}
|
||||
Unexpected("User in HistoryVisibilityEdit.");
|
||||
}();
|
||||
if (!canEdit) {
|
||||
return;
|
||||
}
|
||||
|
||||
historyVisibility->setValue(savedValue);
|
||||
|
||||
const auto result = parent->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
parent,
|
||||
object_ptr<Ui::VerticalLayout>(parent),
|
||||
st::editPeerHistoryVisibilityMargins));
|
||||
const auto container = result->entity();
|
||||
|
||||
Assert(historyVisibility != nullptr);
|
||||
|
||||
AddRadioButton(
|
||||
container,
|
||||
HistoryVisibility::Visible,
|
||||
tr::lng_manage_history_visibility_shown(tr::now),
|
||||
tr::lng_manage_history_visibility_shown_about(),
|
||||
historyVisibility);
|
||||
AddRadioButton(
|
||||
container,
|
||||
st::defaultBoxCheckbox));
|
||||
box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
tr::lng_manage_history_visibility_shown_about(),
|
||||
st::editPeerPrivacyLabel),
|
||||
st::editPeerPreHistoryLabelMargins + st::boxRowPadding);
|
||||
|
||||
box->addSkip(st::editPeerHistoryVisibilityTopSkip);
|
||||
box->addRow(object_ptr<Ui::Radioenum<HistoryVisibility>>(
|
||||
box,
|
||||
historyVisibility,
|
||||
HistoryVisibility::Hidden,
|
||||
tr::lng_manage_history_visibility_hidden(tr::now),
|
||||
(peer->isChat()
|
||||
? tr::lng_manage_history_visibility_hidden_legacy
|
||||
: tr::lng_manage_history_visibility_hidden_about)(),
|
||||
historyVisibility);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EditPeerHistoryVisibilityBox::EditPeerHistoryVisibilityBox(
|
||||
QWidget*,
|
||||
not_null<PeerData*> peer,
|
||||
FnMut<void(HistoryVisibility)> savedCallback,
|
||||
HistoryVisibility historyVisibilitySavedValue)
|
||||
: _peer(peer)
|
||||
, _savedCallback(std::move(savedCallback))
|
||||
, _historyVisibilitySavedValue(historyVisibilitySavedValue)
|
||||
, _historyVisibility(
|
||||
std::make_shared<Ui::RadioenumGroup<HistoryVisibility>>(
|
||||
_historyVisibilitySavedValue)) {
|
||||
}
|
||||
|
||||
void EditPeerHistoryVisibilityBox::prepare() {
|
||||
_peer->updateFull();
|
||||
|
||||
setTitle(tr::lng_manage_history_visibility_title());
|
||||
addButton(tr::lng_settings_save(), [=] {
|
||||
auto local = std::move(_savedCallback);
|
||||
local(_historyVisibility->value());
|
||||
closeBox();
|
||||
});
|
||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||
|
||||
setupContent();
|
||||
}
|
||||
|
||||
void EditPeerHistoryVisibilityBox::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
FillContent(
|
||||
content,
|
||||
_peer,
|
||||
_historyVisibility,
|
||||
_historyVisibilitySavedValue);
|
||||
setDimensionsToContent(st::boxWidth, content);
|
||||
st::defaultBoxCheckbox));
|
||||
box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
(isLegacy
|
||||
? tr::lng_manage_history_visibility_hidden_legacy
|
||||
: tr::lng_manage_history_visibility_hidden_about)(),
|
||||
st::editPeerPrivacyLabel),
|
||||
st::editPeerPreHistoryLabelMargins + st::boxRowPadding);
|
||||
}
|
||||
|
||||