Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7351641034 | ||
|
|
e0669e222d | ||
|
|
4c1f83daca | ||
|
|
ced2652deb | ||
|
|
8d1db85a28 | ||
|
|
97305c8cb5 | ||
|
|
1ef5d81270 | ||
|
|
9ff427afad | ||
|
|
1c5eadcd79 | ||
|
|
bc6c01de7f | ||
|
|
41255cab44 | ||
|
|
ccbc63cd6e | ||
|
|
97446ae783 | ||
|
|
5a75dd2b6f | ||
|
|
6559e83e83 | ||
|
|
d679703bbf | ||
|
|
66a3e36024 | ||
|
|
31e38e1690 | ||
|
|
da10059f45 | ||
|
|
cb5863177f | ||
|
|
84399286c1 | ||
|
|
2e92441b3a | ||
|
|
7883f97c94 | ||
|
|
297b5d6a76 | ||
|
|
492dc2568c | ||
|
|
547c657b1a | ||
|
|
c478d96385 | ||
|
|
2ede53e0ee | ||
|
|
6f760d513e | ||
|
|
f4f6550d66 | ||
|
|
c7878f9d21 | ||
|
|
cd75a45673 | ||
|
|
07e3671ca8 | ||
|
|
295aa644bf | ||
|
|
b5b78c0ade | ||
|
|
f5c0e5d31d | ||
|
|
246ed43046 | ||
|
|
701e1d7b4d | ||
|
|
9cbe899688 | ||
|
|
7409d615a3 | ||
|
|
c9553c2d4c | ||
|
|
bedefaee4d | ||
|
|
5d3b8f02fc | ||
|
|
5120d3ef2c | ||
|
|
82a372873f | ||
|
|
d1d1f83881 | ||
|
|
78c3c86fe6 | ||
|
|
447d4e6c47 | ||
|
|
d0e3d15e8e | ||
|
|
0251f58bf2 | ||
|
|
36997f084a | ||
|
|
942fcb9aae | ||
|
|
6232dce1a3 | ||
|
|
0c0fc46b90 | ||
|
|
dcf737bebe | ||
|
|
919834093e | ||
|
|
99ccd49e13 | ||
|
|
29896b2efd | ||
|
|
1b7f3db43a | ||
|
|
1fa22398a9 | ||
|
|
0e16b3fe69 | ||
|
|
462020d54c | ||
|
|
9c17147f60 | ||
|
|
0bf933b009 | ||
|
|
27f6c8ce62 | ||
|
|
3135463017 | ||
|
|
89950de93e | ||
|
|
13c2d6ff72 | ||
|
|
5e70bf64c6 | ||
|
|
3260e9e752 | ||
|
|
1f16ac59ca | ||
|
|
87bf0654a2 | ||
|
|
6adcf660f1 | ||
|
|
038d8f1781 | ||
|
|
a5977f5f7a | ||
|
|
2143864fd5 | ||
|
|
73691e795b | ||
|
|
c0246a9373 | ||
|
|
1af394a485 | ||
|
|
5180d31b40 | ||
|
|
07c8aae225 | ||
|
|
3c1c17ef80 | ||
|
|
b79ecb5909 | ||
|
|
b98f0933af | ||
|
|
05dcd6fc9c | ||
|
|
19bcc145ad | ||
|
|
4ae760dd7e | ||
|
|
cad4d19272 | ||
|
|
ae64747489 | ||
|
|
db5d599052 | ||
|
|
cc463b07b1 | ||
|
|
d8e55081b0 | ||
|
|
9c66bd553a | ||
|
|
a6bb180e22 | ||
|
|
38ca3ba341 | ||
|
|
8ef00dc4ff | ||
|
|
1630ad0804 | ||
|
|
c3c482aa50 | ||
|
|
f4a63e1e9d | ||
|
|
161e51757c | ||
|
|
46d4b03d49 | ||
|
|
48743a7973 | ||
|
|
6709147560 | ||
|
|
0b2d4326e7 | ||
|
|
ca49e74b6f | ||
|
|
95b4f56b86 | ||
|
|
9828262a03 | ||
|
|
f76e094e98 | ||
|
|
067e52f5d1 | ||
|
|
4efd649c27 | ||
|
|
ff25f1d5c9 | ||
|
|
dd78052f92 | ||
|
|
8a4c7e3994 | ||
|
|
44e71dfa03 | ||
|
|
b6e184d0c8 | ||
|
|
042ed8f54a | ||
|
|
aabc8173c3 | ||
|
|
c14e20b33f | ||
|
|
266c1531ce | ||
|
|
8d632bd2be | ||
|
|
c70a1f03de | ||
|
|
17de6c1ff3 | ||
|
|
4e210e40a2 | ||
|
|
e13593b095 | ||
|
|
e149f10d40 | ||
|
|
7f890122e6 | ||
|
|
422831fa79 | ||
|
|
7494468f1f | ||
|
|
7bc86cc9af |
30
.github/workflows/issue_closer.yml
vendored
@@ -14,6 +14,22 @@ jobs:
|
||||
echo $tag
|
||||
echo ::set-env name=LATEST_TAG::$tag
|
||||
|
||||
- name: Get the latest macOS version.
|
||||
shell: python
|
||||
run: |
|
||||
import subprocess;
|
||||
from xml.dom import minidom;
|
||||
|
||||
url = "https://osx.telegram.org/updates/versions.xml";
|
||||
subprocess.check_call("wget %s" % url, shell=True);
|
||||
|
||||
xmldoc = minidom.parse('versions.xml');
|
||||
itemlist = xmldoc.getElementsByTagName('enclosure');
|
||||
ver = itemlist[0].attributes['sparkle:shortVersionString'].value;
|
||||
print(ver);
|
||||
|
||||
subprocess.check_call("echo ::set-env name=%s::%s" % ("LATEST_MACOS", ver), shell=True);
|
||||
|
||||
- name: Check a version from an issue.
|
||||
uses: actions/github-script@0.4.0
|
||||
with:
|
||||
@@ -75,10 +91,20 @@ jobs:
|
||||
let issueNum = firstNum(issueVer);
|
||||
let latestNum = firstNum(latestVer);
|
||||
|
||||
if (issueNum <= latestNum && issueNum < 5) {
|
||||
let macos_ver = process.env.LATEST_MACOS;
|
||||
console.log("Telegram for MacOS version from website: " + macos_ver);
|
||||
|
||||
if (issueNum <= latestNum && issueNum < macos_ver) {
|
||||
console.log("Seems the version of this issue is fine!");
|
||||
return;
|
||||
}
|
||||
if (issueNum > macos_ver) {
|
||||
let message = `Seems like it's neither the Telegram Desktop\
|
||||
nor the Telegram for macOS version.
|
||||
`;
|
||||
console.log(message);
|
||||
return;
|
||||
}
|
||||
|
||||
let message = `
|
||||
Sorry, but according to the version you specify in this issue, \
|
||||
@@ -87,7 +113,7 @@ jobs:
|
||||
You can report your issue to [the group](https://t.me/macswift) \
|
||||
or to [the repository of Telegram for macOS](https://github.com/overtake/TelegramSwift).
|
||||
|
||||
If I made a mistake and closed your issue wrongly, please reopen it. Thanks!
|
||||
**If I made a mistake and closed your issue wrongly, please reopen it. Thanks!**
|
||||
`;
|
||||
|
||||
let params = {
|
||||
|
||||
63
.github/workflows/linux.yml
vendored
@@ -5,10 +5,42 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-cmake.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/linux.yml'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
- 'Telegram/Telegram/**'
|
||||
- 'Telegram/configure.bat'
|
||||
- 'Telegram/Telegram.plist'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-cmake.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/linux.yml'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
- 'Telegram/Telegram/**'
|
||||
- 'Telegram/configure.bat'
|
||||
- 'Telegram/Telegram.plist'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -101,14 +133,6 @@ jobs:
|
||||
cd Libraries
|
||||
echo ::set-env name=LibrariesPath::`pwd`
|
||||
|
||||
- name: Range-v3.
|
||||
run: |
|
||||
echo "Find necessary branch from doc."
|
||||
cloneRange=$(grep -A 1 "range-v3" $REPO_NAME/$DOC_PATH | sed -n 1p)
|
||||
cd $LibrariesPath
|
||||
echo $cloneRange
|
||||
eval $cloneRange
|
||||
|
||||
- name: Patches.
|
||||
run: |
|
||||
echo "Find necessary commit from doc."
|
||||
@@ -311,19 +335,6 @@ jobs:
|
||||
|
||||
sudo cp -R ffmpeg-cache/. /
|
||||
|
||||
- name: PortAudio.
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone https://git.assembla.com/portaudio.git
|
||||
cd portaudio
|
||||
git checkout 396fe4b669
|
||||
./configure
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
cd ..
|
||||
rm -rf portaudio
|
||||
|
||||
- name: OpenAL Soft.
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
@@ -404,15 +415,11 @@ jobs:
|
||||
|
||||
git clone -b v5.12.8 --depth=1 git://code.qt.io/qt/qt5.git qt_${QT}
|
||||
cd qt_${QT}
|
||||
perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg
|
||||
git submodule update qtbase qtwayland qtimageformats qtsvg
|
||||
perl init-repository --module-subset=qtbase,qtwayland,qtimageformats,qtsvg,qtx11extras
|
||||
git submodule update qtbase qtwayland qtimageformats qtsvg qtx11extras
|
||||
cd qtbase
|
||||
git apply ../../patches/qtbase_${QT}.diff
|
||||
cd src/plugins/platforminputcontexts
|
||||
git clone $GIT/desktop-app/fcitx.git
|
||||
git clone $GIT/desktop-app/hime.git
|
||||
git clone $GIT/desktop-app/nimf.git
|
||||
cd ../../../..
|
||||
cd ../
|
||||
|
||||
./configure -prefix "$QT_PREFIX" \
|
||||
-release \
|
||||
|
||||
38
.github/workflows/mac.yml
vendored
@@ -5,10 +5,40 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-xcode.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/mac.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/configure.bat'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-xcode.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/mac.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/configure.bat'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -70,14 +100,6 @@ jobs:
|
||||
cd Libraries/macos
|
||||
echo ::set-env name=LibrariesPath::`pwd`
|
||||
|
||||
- name: Range-v3.
|
||||
run: |
|
||||
echo "Find necessary branch from doc."
|
||||
cloneRange=$(grep -A 1 "range-v3" $REPO_NAME/$DOC_PATH | sed -n 1p)
|
||||
cd $LibrariesPath
|
||||
echo $cloneRange
|
||||
eval $cloneRange
|
||||
|
||||
- name: Patches.
|
||||
run: |
|
||||
echo "Find necessary commit from doc."
|
||||
|
||||
35
.github/workflows/master_updater.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Master branch updater.
|
||||
|
||||
on:
|
||||
release:
|
||||
types: released
|
||||
|
||||
jobs:
|
||||
updater:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
SKIP: "0"
|
||||
to_branch: "master"
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
if: env.SKIP == '0'
|
||||
- name: Push the code to the master branch.
|
||||
if: env.SKIP == '0'
|
||||
run: |
|
||||
token=${{ secrets.TOKEN_FOR_MASTER_UPDATER }}
|
||||
if [ -z "${token}" ]; then
|
||||
echo "Token is unset. Nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
url=https://x-access-token:$token@github.com/$GITHUB_REPOSITORY
|
||||
latest_tag=$(git describe --tags --abbrev=0)
|
||||
echo "Latest tag: $latest_tag"
|
||||
|
||||
git remote set-url origin $url
|
||||
git remote -v
|
||||
git checkout master
|
||||
git merge $latest_tag
|
||||
|
||||
git push origin HEAD:refs/heads/$to_branch
|
||||
echo "Done!"
|
||||
32
.github/workflows/snap.yml
vendored
@@ -5,10 +5,40 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/snap.yml'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- '!Telegram/Patches/ffmpeg.diff'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
- 'Telegram/Telegram/**'
|
||||
- 'Telegram/configure.bat'
|
||||
- 'Telegram/Telegram.plist'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/snap.yml'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- '!Telegram/Patches/ffmpeg.diff'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
- 'Telegram/Telegram/**'
|
||||
- 'Telegram/configure.bat'
|
||||
- 'Telegram/Telegram.plist'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -19,7 +49,7 @@ jobs:
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
ONLY_CACHE: "false"
|
||||
MANUAL_CACHING: "4"
|
||||
MANUAL_CACHING: "5"
|
||||
|
||||
steps:
|
||||
- name: Clone.
|
||||
|
||||
44
.github/workflows/win.yml
vendored
@@ -5,10 +5,45 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-msvc.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/win.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- '!Telegram/Patches/build_ffmpeg_win.sh'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
- 'Telegram/Telegram/**'
|
||||
- 'Telegram/configure.sh'
|
||||
- 'Telegram/Telegram.plist'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- '!docs/building-msvc.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/win.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- '!Telegram/Patches/build_ffmpeg_win.sh'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/SourceFiles/platform/mac/**'
|
||||
- '!Telegram/Patches/breakpad.diff'
|
||||
- 'Telegram/Telegram/**'
|
||||
- 'Telegram/configure.sh'
|
||||
- 'Telegram/Telegram.plist'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -76,15 +111,6 @@ jobs:
|
||||
run: |
|
||||
choco install --no-progress -y nasm yasm jom ninja
|
||||
|
||||
- name: Range-v3.
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Find necessary branch from doc."
|
||||
cloneRange=$(grep -A 1 "range-v3" $REPO_NAME/$DOC_PATH | sed -n 1p)
|
||||
cd $LibrariesPath
|
||||
echo $cloneRange
|
||||
eval $cloneRange
|
||||
|
||||
- name: Patches.
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
27
.gitmodules
vendored
@@ -67,3 +67,30 @@
|
||||
[submodule "Telegram/ThirdParty/hunspell"]
|
||||
path = Telegram/ThirdParty/hunspell
|
||||
url = https://github.com/hunspell/hunspell
|
||||
[submodule "Telegram/ThirdParty/materialdecoration"]
|
||||
path = Telegram/ThirdParty/materialdecoration
|
||||
url = https://github.com/desktop-app/materialdecoration.git
|
||||
[submodule "Telegram/ThirdParty/range-v3"]
|
||||
path = Telegram/ThirdParty/range-v3
|
||||
url = https://github.com/ericniebler/range-v3.git
|
||||
[submodule "Telegram/ThirdParty/fcitx-qt5"]
|
||||
path = Telegram/ThirdParty/fcitx-qt5
|
||||
url = https://github.com/fcitx/fcitx-qt5.git
|
||||
[submodule "Telegram/ThirdParty/nimf"]
|
||||
path = Telegram/ThirdParty/nimf
|
||||
url = https://github.com/hamonikr/nimf.git
|
||||
[submodule "Telegram/ThirdParty/hime"]
|
||||
path = Telegram/ThirdParty/hime
|
||||
url = https://github.com/hime-ime/hime.git
|
||||
[submodule "Telegram/ThirdParty/qt5ct"]
|
||||
path = Telegram/ThirdParty/qt5ct
|
||||
url = https://github.com/desktop-app/qt5ct.git
|
||||
[submodule "Telegram/ThirdParty/lxqt-qtplugin"]
|
||||
path = Telegram/ThirdParty/lxqt-qtplugin
|
||||
url = https://github.com/lxqt/lxqt-qtplugin.git
|
||||
[submodule "Telegram/ThirdParty/libqtxdg"]
|
||||
path = Telegram/ThirdParty/libqtxdg
|
||||
url = https://github.com/lxqt/libqtxdg.git
|
||||
[submodule "Telegram/ThirdParty/fcitx5-qt"]
|
||||
path = Telegram/ThirdParty/fcitx5-qt
|
||||
url = https://github.com/fcitx/fcitx5-qt.git
|
||||
|
||||
28
README.md
@@ -13,18 +13,27 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
||||
|
||||
## Supported systems
|
||||
|
||||
* Windows XP - Windows 10 (**not** RT)
|
||||
* Mac OS X 10.8 - Mac OS X 10.15
|
||||
* Mac OS X 10.6 - Mac OS X 10.7 (separate build)
|
||||
* Ubuntu 12.04 - Ubuntu 19.10
|
||||
* Fedora 22 - Fedora 31
|
||||
* [Snappy](https://snapcraft.io/telegram-desktop)
|
||||
* [Flathub](https://flathub.org/apps/details/org.telegram.desktop)
|
||||
The latest version is available for
|
||||
|
||||
* [Windows 7 and above](https://telegram.org/dl/desktop/win) ([portable](https://telegram.org/dl/desktop/win_portable))
|
||||
* [macOS 10.12 and above](https://telegram.org/dl/desktop/mac)
|
||||
* [OS X 10.10 and 10.11](https://telegram.org/dl/desktop/osx)
|
||||
* [Linux static build for 64 bit](https://telegram.org/dl/desktop/linux) ([32 bit](https://telegram.org/dl/desktop/linux32))
|
||||
* [Snap](https://snapcraft.io/telegram-desktop)
|
||||
* [Flatpak](https://flathub.org/apps/details/org.telegram.desktop)
|
||||
|
||||
## Old system versions
|
||||
|
||||
Version **1.8.15** was the last that supports older systems
|
||||
|
||||
* [Windows XP and Vista](https://updates.tdesktop.com/tsetup/tsetup.1.8.15.exe) ([portable](https://updates.tdesktop.com/tsetup/tportable.1.8.15.zip))
|
||||
* [OS X 10.8 and 10.9](https://updates.tdesktop.com/tmac/tsetup.1.8.15.dmg)
|
||||
* [OS X 10.6 and 10.7](https://updates.tdesktop.com/tmac32/tsetup32.1.8.15.dmg)
|
||||
|
||||
## Third-party
|
||||
|
||||
* Qt 5.12.8 and 5.6.2, slightly patched ([LGPL](http://doc.qt.io/qt-5/lgpl.html))
|
||||
* OpenSSL 1.1.1 ([OpenSSL License](https://www.openssl.org/source/license.html))
|
||||
* Qt 5.12.8, 5.6.2 and 5.3.2 slightly patched ([LGPL](http://doc.qt.io/qt-5/lgpl.html))
|
||||
* OpenSSL 1.1.1 and 1.0.1 ([OpenSSL License](https://www.openssl.org/source/license.html))
|
||||
* zlib 1.2.11 ([zlib License](http://www.zlib.net/zlib_license.html))
|
||||
* LZMA SDK 9.20 ([public domain](http://www.7-zip.org/sdk.html))
|
||||
* liblzma ([public domain](http://tukaani.org/xz/))
|
||||
@@ -39,6 +48,7 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
||||
* Mapbox Variant ([BSD License](https://github.com/mapbox/variant/blob/master/LICENSE))
|
||||
* Range-v3 ([Boost License](https://github.com/ericniebler/range-v3/blob/master/LICENSE.txt))
|
||||
* Open Sans font ([Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html))
|
||||
* Vazir font ([License](https://github.com/rastikerdar/vazir-font/blob/master/LICENSE))
|
||||
* Emoji alpha codes ([MIT License](https://github.com/emojione/emojione/blob/master/extras/alpha-codes/LICENSE.md))
|
||||
* Catch test framework ([Boost License](https://github.com/philsquared/Catch/blob/master/LICENSE.txt))
|
||||
* xxHash ([BSD License](https://github.com/Cyan4973/xxHash/blob/dev/LICENSE))
|
||||
|
||||
@@ -67,12 +67,34 @@ generate_numbers(Telegram ${res_loc}/numbers.txt)
|
||||
|
||||
set_target_properties(Telegram PROPERTIES AUTOMOC ON AUTORCC ON)
|
||||
|
||||
if (LINUX AND NOT DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
|
||||
if (LINUX)
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
desktop-app::external_statusnotifieritem
|
||||
desktop-app::external_dbusmenu_qt
|
||||
desktop-app::external_materialdecoration
|
||||
desktop-app::external_nimf_qt5
|
||||
desktop-app::external_qt5ct
|
||||
desktop-app::external_qt5ct_style
|
||||
desktop-app::external_qt5ct_qtplugin
|
||||
)
|
||||
|
||||
if (NOT DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
|
||||
# conflicts with Qt static link
|
||||
if (DESKTOP_APP_USE_PACKAGED_LAZY_PLATFORMTHEMES)
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
desktop-app::external_lxqt_qtplugin
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
desktop-app::external_statusnotifieritem
|
||||
desktop-app::external_dbusmenu_qt
|
||||
desktop-app::external_fcitx_qt5
|
||||
desktop-app::external_fcitx5_qt5
|
||||
desktop-app::external_hime_qt
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (add_hunspell_library)
|
||||
@@ -105,10 +127,6 @@ PRIVATE
|
||||
desktop-app::external_openal
|
||||
)
|
||||
|
||||
if (NOT DESKTOP_APP_USE_PACKAGED)
|
||||
target_link_libraries(Telegram PRIVATE desktop-app::external_opus)
|
||||
endif()
|
||||
|
||||
# Telegram uses long atomic types, so on some architectures libatomic is needed.
|
||||
check_cxx_source_compiles("
|
||||
#include <atomic>
|
||||
@@ -121,11 +139,10 @@ endif()
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
${CMAKE_DL_LIBS}
|
||||
Threads::Threads
|
||||
)
|
||||
endif()
|
||||
@@ -1010,14 +1027,13 @@ PRIVATE
|
||||
mainwindow.h
|
||||
observer_peer.cpp
|
||||
observer_peer.h
|
||||
qt_static_plugins.cpp
|
||||
settings.cpp
|
||||
settings.h
|
||||
)
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED)
|
||||
nice_target_sources(Telegram ${src_loc} PRIVATE qt_functions.cpp)
|
||||
else()
|
||||
nice_target_sources(Telegram ${src_loc} PRIVATE qt_static_plugins.cpp)
|
||||
endif()
|
||||
|
||||
nice_target_sources(Telegram ${res_loc}
|
||||
@@ -1027,12 +1043,15 @@ PRIVATE
|
||||
qrc/emoji_3.qrc
|
||||
qrc/emoji_4.qrc
|
||||
qrc/emoji_5.qrc
|
||||
qrc/emoji_6.qrc
|
||||
qrc/emoji_7.qrc
|
||||
qrc/emoji_preview.qrc
|
||||
qrc/telegram/telegram.qrc
|
||||
qrc/telegram/sounds.qrc
|
||||
winrc/Telegram.rc
|
||||
winrc/Telegram.manifest
|
||||
langs/lang.strings
|
||||
langs/cloud_lang.strings
|
||||
numbers.txt
|
||||
)
|
||||
|
||||
@@ -1162,21 +1181,12 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/Telegram PREFIX Resources FILES ${
|
||||
|
||||
target_include_directories(Telegram PRIVATE ${src_loc})
|
||||
|
||||
if (NOT DESKTOP_APP_USE_PACKAGED)
|
||||
target_include_directories(Telegram PRIVATE ${third_party_loc}/minizip)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(Telegram
|
||||
PRIVATE
|
||||
TDESKTOP_API_ID=${TDESKTOP_API_ID}
|
||||
TDESKTOP_API_HASH=${TDESKTOP_API_HASH}
|
||||
AL_ALEXT_PROTOTYPES
|
||||
)
|
||||
|
||||
if (NOT DESKTOP_APP_USE_PACKAGED)
|
||||
target_compile_definitions(Telegram PRIVATE AL_LIBTYPE_STATIC)
|
||||
endif()
|
||||
|
||||
if (${CMAKE_GENERATOR} MATCHES "(Visual Studio|Xcode)")
|
||||
set(output_folder ${CMAKE_BINARY_DIR})
|
||||
elseif (DESKTOP_APP_SPECIAL_TARGET STREQUAL "")
|
||||
@@ -1203,6 +1213,10 @@ if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR NOT LINUX) AND NOT build_macstore AND
|
||||
|
||||
set_target_properties(Updater PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
|
||||
|
||||
if (WIN32 AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
target_link_options(Updater PRIVATE -municode)
|
||||
endif()
|
||||
|
||||
if (LINUX)
|
||||
target_link_options(Updater PRIVATE -static-libstdc++)
|
||||
endif()
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 894 KiB After Width: | Height: | Size: 1.4 MiB |
BIN
Telegram/Resources/emoji/emoji_6.webp
Normal file
|
After Width: | Height: | Size: 862 KiB |
BIN
Telegram/Resources/emoji/emoji_7.webp
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
Telegram/Resources/icons/message_psa_tooltip.png
Normal file
|
After Width: | Height: | Size: 549 B |
BIN
Telegram/Resources/icons/message_psa_tooltip@2x.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/message_psa_tooltip@3x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
Telegram/Resources/icons/toast_info.png
Normal file
|
After Width: | Height: | Size: 504 B |
BIN
Telegram/Resources/icons/toast_info@2x.png
Normal file
|
After Width: | Height: | Size: 992 B |
BIN
Telegram/Resources/icons/toast_info@3x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
@@ -6,6 +6,11 @@ For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
|
||||
"cloud_lng_badge_psa_covid" = "COVID-19";
|
||||
"cloud_lng_about_psa_covid" = "This message provides you with a public service announcement in relation to the ongoing COVID-19 pandemic. To remove it from your chats list, right click it and select **Hide**.";
|
||||
"cloud_lng_forwarded_psa_covid" = "COVID-19 Notification from {channel}";
|
||||
"cloud_lng_tooltip_psa_covid" = "This message provides you with a public service announcement in relation to the ongoing COVID-19 pandemic. Learn more about this initiative at https://telegram.org/blog/coronavirus";
|
||||
|
||||
"cloud_lng_passport_in_ar" = "Arabic";
|
||||
"cloud_lng_passport_in_az" = "Azerbaijani";
|
||||
"cloud_lng_passport_in_bg" = "Bulgarian";
|
||||
|
||||
@@ -118,6 +118,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_chat_status_online#one" = "{count} online";
|
||||
"lng_chat_status_online#other" = "{count} online";
|
||||
"lng_chat_status_members_online" = "{members_count}, {online_count}";
|
||||
"lng_chat_status_subscribers#one" = "{count} subscriber";
|
||||
"lng_chat_status_subscribers#other" = "{count} subscribers";
|
||||
|
||||
"lng_channel_status" = "channel";
|
||||
"lng_group_status" = "group";
|
||||
@@ -298,6 +300,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_notifications_position" = "Location on the screen";
|
||||
"lng_settings_notifications_count" = "Notifications count";
|
||||
"lng_settings_sound_notify" = "Play sound";
|
||||
"lng_settings_alert_windows" = "Flash the taskbar icon";
|
||||
"lng_settings_alert_mac" = "Bounce the dock icon";
|
||||
"lng_settings_alert_linux" = "Draw attention to the window";
|
||||
"lng_settings_badge_title" = "Badge counter";
|
||||
"lng_settings_include_muted" = "Include muted chats in unread count";
|
||||
"lng_settings_count_unread" = "Count unread messages";
|
||||
@@ -600,6 +605,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_proxy_sponsor" = "Proxy sponsor";
|
||||
"lng_proxy_sponsor_about" = "This channel is shown by your proxy server.\nTo remove this channel from your chats list,\ndisable the proxy in Telegram Settings.";
|
||||
"lng_proxy_sponsor_warning" = "This proxy may display a sponsored channel in your chat list. This doesn't reveal any of your Telegram traffic.";
|
||||
"lng_badge_psa_default" = "PSA";
|
||||
"lng_about_psa_default" = "This message provides you with a public service announcement. To remove it from your chats list, right click it and select **Hide**.";
|
||||
"lng_tooltip_psa_default" = "This message provides you with a public service announcement.";
|
||||
|
||||
"lng_settings_blocked_users" = "Blocked users";
|
||||
"lng_settings_no_blocked_users" = "None";
|
||||
@@ -764,6 +772,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_profile_common_groups#one" = "{count} group in common";
|
||||
"lng_profile_common_groups#other" = "{count} groups in common";
|
||||
"lng_profile_participants_section" = "Members";
|
||||
"lng_profile_subscribers_section" = "Subscribers";
|
||||
"lng_profile_mobile_number" = "Mobile:";
|
||||
"lng_profile_username" = "Username:";
|
||||
"lng_profile_link" = "Link:";
|
||||
@@ -885,6 +894,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_manage_channel_info" = "Channel Info";
|
||||
"lng_manage_peer_recent_actions" = "Recent Actions";
|
||||
"lng_manage_peer_members" = "Members";
|
||||
"lng_manage_peer_subscribers" = "Subscribers";
|
||||
"lng_manage_peer_administrators" = "Administrators";
|
||||
"lng_manage_peer_exceptions" = "Exceptions";
|
||||
"lng_manage_peer_removed_users" = "Removed users";
|
||||
@@ -1126,6 +1136,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_forwarded" = "Forwarded from {user}";
|
||||
"lng_forwarded_date" = "Original: {date}";
|
||||
"lng_forwarded_channel" = "Forwarded from {channel}";
|
||||
"lng_forwarded_psa_default" = "Forwarded from {channel}";
|
||||
"lng_forwarded_via" = "Forwarded from {user} via {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Forwarded from {channel} via {inline_bot}";
|
||||
"lng_forwarded_signed" = "{channel} ({user})";
|
||||
@@ -1401,6 +1412,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_context_view_group" = "View group info";
|
||||
"lng_context_view_channel" = "View channel info";
|
||||
//"lng_context_view_feed_info" = "View feed info";
|
||||
"lng_context_hide_psa" = "Hide this announcement";
|
||||
"lng_context_pin_to_top" = "Pin to top";
|
||||
"lng_context_unpin_from_top" = "Unpin from top";
|
||||
"lng_context_mark_unread" = "Mark as unread";
|
||||
@@ -1442,6 +1454,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_context_edit_msg" = "Edit";
|
||||
"lng_context_forward_msg" = "Forward Message";
|
||||
"lng_context_send_now_msg" = "Send now";
|
||||
"lng_context_reschedule" = "Reschedule";
|
||||
"lng_context_delete_msg" = "Delete Message";
|
||||
"lng_context_select_msg" = "Select Message";
|
||||
"lng_context_report_msg" = "Report Message";
|
||||
@@ -1851,6 +1864,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_admin_log_no_results_search_text" = "No recent actions that contain '{query}' have been found.";
|
||||
"lng_admin_log_no_events_title" = "No actions yet";
|
||||
"lng_admin_log_no_events_text" = "There were no service actions\ntaken by the group's members\nand admins in the last 48 hours.";
|
||||
"lng_admin_log_no_events_text_channel" = "There were no service actions\ntaken by the channels's admins\nin the last 48 hours.";
|
||||
|
||||
"lng_admin_log_empty_text" = "Empty";
|
||||
"lng_admin_log_changed_title_group" = "{from} changed group name to «{title}»";
|
||||
|
||||
5
Telegram/Resources/qrc/emoji_6.qrc
Normal file
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/gui">
|
||||
<file alias="emoji/emoji_6.webp">../emoji/emoji_6.webp</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
5
Telegram/Resources/qrc/emoji_7.qrc
Normal file
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/gui">
|
||||
<file alias="emoji/emoji_7.webp">../emoji/emoji_7.webp</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -651,7 +651,7 @@ messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_off
|
||||
|
||||
exportedMessageLink#5dab1af4 link:string html:string = ExportedMessageLink;
|
||||
|
||||
messageFwdHeader#ec338270 flags:# from_id:flags.0?int from_name:flags.5?string date:int channel_id:flags.1?int channel_post:flags.2?int post_author:flags.3?string saved_from_peer:flags.4?Peer saved_from_msg_id:flags.4?int = MessageFwdHeader;
|
||||
messageFwdHeader#353a686b flags:# from_id:flags.0?int from_name:flags.5?string date:int channel_id:flags.1?int channel_post:flags.2?int post_author:flags.3?string saved_from_peer:flags.4?Peer saved_from_msg_id:flags.4?int psa_type:flags.6?string = MessageFwdHeader;
|
||||
|
||||
auth.codeTypeSms#72a3158c = auth.CodeType;
|
||||
auth.codeTypeCall#741cd3e3 = auth.CodeType;
|
||||
@@ -912,9 +912,6 @@ fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;
|
||||
|
||||
inputClientProxy#75588b3f address:string port:int = InputClientProxy;
|
||||
|
||||
help.proxyDataEmpty#e09e1fb8 expires:int = help.ProxyData;
|
||||
help.proxyDataPromo#2bf7ee23 expires:int peer:Peer chats:Vector<Chat> users:Vector<User> = help.ProxyData;
|
||||
|
||||
help.termsOfServiceUpdateEmpty#e3309f7f expires:int = help.TermsOfServiceUpdate;
|
||||
help.termsOfServiceUpdate#28ecf961 expires:int terms_of_service:help.TermsOfService = help.TermsOfServiceUpdate;
|
||||
|
||||
@@ -1140,6 +1137,9 @@ messageInteractionCounters#ad4fc9bd msg_id:int views:int forwards:int = MessageI
|
||||
|
||||
stats.broadcastStats#bdf78394 period:StatsDateRangeDays followers:StatsAbsValueAndPrev views_per_post:StatsAbsValueAndPrev shares_per_post:StatsAbsValueAndPrev enabled_notifications:StatsPercentValue growth_graph:StatsGraph followers_graph:StatsGraph mute_graph:StatsGraph top_hours_graph:StatsGraph interactions_graph:StatsGraph iv_interactions_graph:StatsGraph views_by_source_graph:StatsGraph new_followers_by_source_graph:StatsGraph languages_graph:StatsGraph recent_message_interactions:Vector<MessageInteractionCounters> = stats.BroadcastStats;
|
||||
|
||||
help.promoDataEmpty#98f6ac75 expires:int = help.PromoData;
|
||||
help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector<Chat> users:Vector<User> psa_type:flags.1?string psa_message:flags.2?string = help.PromoData;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@@ -1411,7 +1411,6 @@ help.getAppChangelog#9010ef6f prev_app_version:string = Updates;
|
||||
help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool;
|
||||
help.getCdnConfig#52029342 = CdnConfig;
|
||||
help.getRecentMeUrls#3dc0f114 referer:string = help.RecentMeUrls;
|
||||
help.getProxyData#3d7758e1 = help.ProxyData;
|
||||
help.getTermsOfServiceUpdate#2ca51fd1 = help.TermsOfServiceUpdate;
|
||||
help.acceptTermsOfService#ee72f79a id:DataJSON = Bool;
|
||||
help.getDeepLinkInfo#3fedc75f path:string = help.DeepLinkInfo;
|
||||
@@ -1421,6 +1420,8 @@ help.getPassportConfig#c661ad08 hash:int = help.PassportConfig;
|
||||
help.getSupportName#d360e72c = help.SupportName;
|
||||
help.getUserInfo#38a08d3 user_id:InputUser = help.UserInfo;
|
||||
help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector<MessageEntity> = help.UserInfo;
|
||||
help.getPromoData#c0977421 = help.PromoData;
|
||||
help.hidePromoData#1e251c95 peer:InputPeer = Bool;
|
||||
|
||||
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
|
||||
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
|
||||
@@ -1494,7 +1495,7 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua
|
||||
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
|
||||
folders.deleteFolder#1c295881 folder_id:int = Updates;
|
||||
|
||||
stats.getBroadcastStats#e6300dba flags:# dark:flags.0?true channel:InputChannel tz_offset:int = stats.BroadcastStats;
|
||||
stats.getBroadcastStats#ab42441a flags:# dark:flags.0?true channel:InputChannel = stats.BroadcastStats;
|
||||
stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph;
|
||||
|
||||
// LAYER 112
|
||||
// LAYER 113
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="2.1.0.0" />
|
||||
Version="2.1.7.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||
|
||||
@@ -6,7 +6,18 @@
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
#if defined(__MINGW64__) || defined(__MINGW32__)
|
||||
// MinGW-w64, MinGW
|
||||
#if defined(__has_include) && __has_include(<winres.h>)
|
||||
#include <winres.h>
|
||||
#else
|
||||
#include <afxres.h>
|
||||
#include <winresrc.h>
|
||||
#endif
|
||||
#else
|
||||
// MSVC, Windows SDK
|
||||
#include <winres.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
@@ -33,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,0,0
|
||||
PRODUCTVERSION 2,1,0,0
|
||||
FILEVERSION 2,1,7,0
|
||||
PRODUCTVERSION 2,1,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -51,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "2.1.0.0"
|
||||
VALUE "FileVersion", "2.1.7.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.0.0"
|
||||
VALUE "ProductVersion", "2.1.7.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -6,7 +6,18 @@
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
#if defined(__MINGW64__) || defined(__MINGW32__)
|
||||
// MinGW-w64, MinGW
|
||||
#if defined(__has_include) && __has_include(<winres.h>)
|
||||
#include <winres.h>
|
||||
#else
|
||||
#include <afxres.h>
|
||||
#include <winresrc.h>
|
||||
#endif
|
||||
#else
|
||||
// MSVC, Windows SDK
|
||||
#include <winres.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
@@ -24,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,0,0
|
||||
PRODUCTVERSION 2,1,0,0
|
||||
FILEVERSION 2,1,7,0
|
||||
PRODUCTVERSION 2,1,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -42,10 +53,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "2.1.0.0"
|
||||
VALUE "FileVersion", "2.1.7.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.0.0"
|
||||
VALUE "ProductVersion", "2.1.7.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -268,7 +268,7 @@ int main(int argc, char *argv[])
|
||||
cout << "Compression start, size: " << resultSize << "\n";
|
||||
|
||||
QByteArray compressed, resultCheck;
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
|
||||
|
||||
compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size
|
||||
|
||||
@@ -27,7 +27,7 @@ extern "C" {
|
||||
#include <openssl/evp.h>
|
||||
} // extern "C"
|
||||
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
#include <LzmaLib.h>
|
||||
#else
|
||||
#include <lzma.h>
|
||||
|
||||
@@ -30,6 +30,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
void InnerFillMessagePostFlags(
|
||||
const Api::SendOptions &options,
|
||||
not_null<PeerData*> peer,
|
||||
MTPDmessage::Flags &flags) {
|
||||
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
|
||||
if (!channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_from_id;
|
||||
return;
|
||||
}
|
||||
flags |= MTPDmessage::Flag::f_post;
|
||||
// Don't display views and author of a new post when it's scheduled.
|
||||
if (options.scheduled) {
|
||||
return;
|
||||
}
|
||||
flags |= MTPDmessage::Flag::f_views;
|
||||
if (peer->asChannel()->addsSignature()) {
|
||||
flags |= MTPDmessage::Flag::f_post_author;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MediaData>
|
||||
void SendExistingMedia(
|
||||
Api::MessageToSend &&message,
|
||||
@@ -60,15 +80,7 @@ void SendExistingMedia(
|
||||
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
|
||||
const auto silentPost = message.action.options.silent
|
||||
|| (channelPost && session->data().notifySilentPosts(peer));
|
||||
if (channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_views;
|
||||
flags |= MTPDmessage::Flag::f_post;
|
||||
}
|
||||
if (!channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_from_id;
|
||||
} else if (peer->asChannel()->addsSignature()) {
|
||||
flags |= MTPDmessage::Flag::f_post_author;
|
||||
}
|
||||
InnerFillMessagePostFlags(message.action.options, peer, flags);
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
||||
}
|
||||
@@ -246,15 +258,7 @@ bool SendDice(Api::MessageToSend &message) {
|
||||
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
|
||||
const auto silentPost = message.action.options.silent
|
||||
|| (channelPost && session->data().notifySilentPosts(peer));
|
||||
if (channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_views;
|
||||
flags |= MTPDmessage::Flag::f_post;
|
||||
}
|
||||
if (!channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_from_id;
|
||||
} else if (peer->asChannel()->addsSignature()) {
|
||||
flags |= MTPDmessage::Flag::f_post_author;
|
||||
}
|
||||
InnerFillMessagePostFlags(message.action.options, peer, flags);
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
||||
}
|
||||
@@ -320,4 +324,11 @@ bool SendDice(Api::MessageToSend &message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FillMessagePostFlags(
|
||||
const Api::SendAction &action,
|
||||
not_null<PeerData*> peer,
|
||||
MTPDmessage::Flags &flags) {
|
||||
InnerFillMessagePostFlags(action.options, peer, flags);
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -25,4 +25,9 @@ void SendExistingPhoto(
|
||||
|
||||
bool SendDice(Api::MessageToSend &message);
|
||||
|
||||
void FillMessagePostFlags(
|
||||
const SendAction &action,
|
||||
not_null<PeerData*> peer,
|
||||
MTPDmessage::Flags &flags);
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -82,6 +82,7 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||
if (entity.length() <= 0) continue;
|
||||
if (option == ConvertOption::SkipLocal
|
||||
&& entity.type() != EntityType::Bold
|
||||
//&& entity.type() != EntityType::Semibold // Not in API.
|
||||
&& entity.type() != EntityType::Italic
|
||||
&& entity.type() != EntityType::Underline
|
||||
&& entity.type() != EntityType::StrikeOut
|
||||
|
||||
@@ -88,8 +88,8 @@ constexpr auto kMaxUsersPerInvite = 100;
|
||||
// that was added to this chat.
|
||||
constexpr auto kForwardMessagesOnAdd = 100;
|
||||
|
||||
constexpr auto kProxyPromotionInterval = TimeId(60 * 60);
|
||||
constexpr auto kProxyPromotionMinDelay = TimeId(10);
|
||||
constexpr auto kTopPromotionInterval = TimeId(60 * 60);
|
||||
constexpr auto kTopPromotionMinDelay = TimeId(10);
|
||||
constexpr auto kSmallDelayMs = 5;
|
||||
constexpr auto kUnreadMentionsPreloadIfLess = 5;
|
||||
constexpr auto kUnreadMentionsFirstRequestLimit = 10;
|
||||
@@ -237,7 +237,7 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
|
||||
, _dialogsLoadState(std::make_unique<DialogsLoadState>())
|
||||
, _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout))
|
||||
//, _feedReadTimer([=] { readFeeds(); }) // #feed
|
||||
, _proxyPromotionTimer([=] { refreshProxyPromotion(); })
|
||||
, _topPromotionTimer([=] { refreshTopPromotion(); })
|
||||
, _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); })
|
||||
, _selfDestruct(std::make_unique<Api::SelfDestruct>(this))
|
||||
, _sensitiveContent(std::make_unique<Api::SensitiveContent>(this)) {
|
||||
@@ -288,13 +288,13 @@ void ApiWrap::requestChangelog(
|
||||
).send();
|
||||
}
|
||||
|
||||
void ApiWrap::refreshProxyPromotion() {
|
||||
void ApiWrap::refreshTopPromotion() {
|
||||
const auto now = base::unixtime::now();
|
||||
const auto next = (_proxyPromotionNextRequestTime != 0)
|
||||
? _proxyPromotionNextRequestTime
|
||||
const auto next = (_topPromotionNextRequestTime != 0)
|
||||
? _topPromotionNextRequestTime
|
||||
: now;
|
||||
if (_proxyPromotionRequestId) {
|
||||
getProxyPromotionDelayed(now, next);
|
||||
if (_topPromotionRequestId) {
|
||||
getTopPromotionDelayed(now, next);
|
||||
return;
|
||||
}
|
||||
const auto key = [&]() -> std::pair<QString, uint32> {
|
||||
@@ -307,51 +307,51 @@ void ApiWrap::refreshProxyPromotion() {
|
||||
}
|
||||
return { proxy.host, proxy.port };
|
||||
}();
|
||||
if (_proxyPromotionKey == key && now < next) {
|
||||
getProxyPromotionDelayed(now, next);
|
||||
if (_topPromotionKey == key && now < next) {
|
||||
getTopPromotionDelayed(now, next);
|
||||
return;
|
||||
}
|
||||
_proxyPromotionKey = key;
|
||||
if (key.first.isEmpty() || !key.second) {
|
||||
proxyPromotionDone(MTP_help_proxyDataEmpty(
|
||||
MTP_int(base::unixtime::now() + kProxyPromotionInterval)));
|
||||
return;
|
||||
}
|
||||
_proxyPromotionRequestId = request(MTPhelp_GetProxyData(
|
||||
)).done([=](const MTPhelp_ProxyData &result) {
|
||||
_proxyPromotionRequestId = 0;
|
||||
proxyPromotionDone(result);
|
||||
_topPromotionKey = key;
|
||||
_topPromotionRequestId = request(MTPhelp_GetPromoData(
|
||||
)).done([=](const MTPhelp_PromoData &result) {
|
||||
_topPromotionRequestId = 0;
|
||||
topPromotionDone(result);
|
||||
}).fail([=](const RPCError &error) {
|
||||
_proxyPromotionRequestId = 0;
|
||||
_topPromotionRequestId = 0;
|
||||
const auto now = base::unixtime::now();
|
||||
const auto next = _proxyPromotionNextRequestTime = now
|
||||
+ kProxyPromotionInterval;
|
||||
if (!_proxyPromotionTimer.isActive()) {
|
||||
getProxyPromotionDelayed(now, next);
|
||||
const auto next = _topPromotionNextRequestTime = now
|
||||
+ kTopPromotionInterval;
|
||||
if (!_topPromotionTimer.isActive()) {
|
||||
getTopPromotionDelayed(now, next);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::getProxyPromotionDelayed(TimeId now, TimeId next) {
|
||||
_proxyPromotionTimer.callOnce(std::min(
|
||||
std::max(next - now, kProxyPromotionMinDelay),
|
||||
kProxyPromotionInterval) * crl::time(1000));
|
||||
void ApiWrap::getTopPromotionDelayed(TimeId now, TimeId next) {
|
||||
_topPromotionTimer.callOnce(std::min(
|
||||
std::max(next - now, kTopPromotionMinDelay),
|
||||
kTopPromotionInterval) * crl::time(1000));
|
||||
};
|
||||
|
||||
void ApiWrap::proxyPromotionDone(const MTPhelp_ProxyData &proxy) {
|
||||
_proxyPromotionNextRequestTime = proxy.match([&](const auto &data) {
|
||||
void ApiWrap::topPromotionDone(const MTPhelp_PromoData &proxy) {
|
||||
_topPromotionNextRequestTime = proxy.match([&](const auto &data) {
|
||||
return data.vexpires().v;
|
||||
});
|
||||
getProxyPromotionDelayed(base::unixtime::now(), _proxyPromotionNextRequestTime);
|
||||
getTopPromotionDelayed(
|
||||
base::unixtime::now(),
|
||||
_topPromotionNextRequestTime);
|
||||
|
||||
proxy.match([&](const MTPDhelp_proxyDataEmpty &data) {
|
||||
_session->data().setProxyPromoted(nullptr);
|
||||
}, [&](const MTPDhelp_proxyDataPromo &data) {
|
||||
proxy.match([&](const MTPDhelp_promoDataEmpty &data) {
|
||||
_session->data().setTopPromoted(nullptr, QString(), QString());
|
||||
}, [&](const MTPDhelp_promoData &data) {
|
||||
_session->data().processChats(data.vchats());
|
||||
_session->data().processUsers(data.vusers());
|
||||
const auto peerId = peerFromMTP(data.vpeer());
|
||||
const auto peer = _session->data().peer(peerId);
|
||||
_session->data().setProxyPromoted(peer);
|
||||
_session->data().setTopPromoted(
|
||||
peer,
|
||||
data.vpsa_type().value_or_empty(),
|
||||
data.vpsa_message().value_or_empty());
|
||||
if (const auto history = _session->data().historyLoaded(peer)) {
|
||||
history->owner().histories().requestDialogEntry(history);
|
||||
}
|
||||
@@ -4328,15 +4328,7 @@ void ApiWrap::forwardMessages(
|
||||
auto flags = MTPDmessage::Flags(0);
|
||||
auto clientFlags = MTPDmessage_ClientFlags();
|
||||
auto sendFlags = MTPmessages_ForwardMessages::Flags(0);
|
||||
if (channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_views;
|
||||
flags |= MTPDmessage::Flag::f_post;
|
||||
}
|
||||
if (!channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_from_id;
|
||||
} else if (peer->asChannel()->addsSignature()) {
|
||||
flags |= MTPDmessage::Flag::f_post_author;
|
||||
}
|
||||
FillMessagePostFlags(action, peer, flags);
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_ForwardMessages::Flag::f_silent;
|
||||
}
|
||||
@@ -4489,15 +4481,7 @@ void ApiWrap::sendSharedContact(
|
||||
if (action.replyTo) {
|
||||
flags |= MTPDmessage::Flag::f_reply_to_msg_id;
|
||||
}
|
||||
if (channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_views;
|
||||
flags |= MTPDmessage::Flag::f_post;
|
||||
if (peer->asChannel()->addsSignature()) {
|
||||
flags |= MTPDmessage::Flag::f_post_author;
|
||||
}
|
||||
} else {
|
||||
flags |= MTPDmessage::Flag::f_from_id;
|
||||
}
|
||||
FillMessagePostFlags(action, peer, flags);
|
||||
if (action.options.scheduled) {
|
||||
flags |= MTPDmessage::Flag::f_from_scheduled;
|
||||
} else {
|
||||
@@ -4874,15 +4858,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
|
||||
const auto silentPost = action.options.silent
|
||||
|| (channelPost && _session->data().notifySilentPosts(peer));
|
||||
if (channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_views;
|
||||
flags |= MTPDmessage::Flag::f_post;
|
||||
}
|
||||
if (!channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_from_id;
|
||||
} else if (peer->asChannel()->addsSignature()) {
|
||||
flags |= MTPDmessage::Flag::f_post_author;
|
||||
}
|
||||
FillMessagePostFlags(action, peer, flags);
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_silent;
|
||||
}
|
||||
@@ -5019,15 +4995,7 @@ void ApiWrap::sendInlineResult(
|
||||
bool channelPost = peer->isChannel() && !peer->isMegagroup();
|
||||
bool silentPost = action.options.silent
|
||||
|| (channelPost && _session->data().notifySilentPosts(peer));
|
||||
if (channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_views;
|
||||
flags |= MTPDmessage::Flag::f_post;
|
||||
}
|
||||
if (!channelPost) {
|
||||
flags |= MTPDmessage::Flag::f_from_id;
|
||||
} else if (peer->asChannel()->addsSignature()) {
|
||||
flags |= MTPDmessage::Flag::f_post_author;
|
||||
}
|
||||
FillMessagePostFlags(action, peer, flags);
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendInlineBotResult::Flag::f_silent;
|
||||
}
|
||||
@@ -5857,6 +5825,43 @@ void ApiWrap::closePoll(not_null<HistoryItem*> item) {
|
||||
_pollCloseRequestIds.emplace(itemId, requestId);
|
||||
}
|
||||
|
||||
void ApiWrap::rescheduleMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
Api::SendOptions options) {
|
||||
const auto text = item->originalText().text;
|
||||
const auto sentEntities = Api::EntitiesToMTP(
|
||||
item->originalText().entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
const auto media = item->media();
|
||||
|
||||
const auto emptyFlag = MTPmessages_EditMessage::Flag(0);
|
||||
const auto flags = MTPmessages_EditMessage::Flag::f_schedule_date
|
||||
| (!text.isEmpty()
|
||||
? MTPmessages_EditMessage::Flag::f_message
|
||||
: emptyFlag)
|
||||
| ((!media || !media->webpage())
|
||||
? MTPmessages_EditMessage::Flag::f_no_webpage
|
||||
: emptyFlag)
|
||||
| (!sentEntities.v.isEmpty()
|
||||
? MTPmessages_EditMessage::Flag::f_entities
|
||||
: emptyFlag);
|
||||
|
||||
const auto id = _session->data().scheduledMessages().lookupId(item);
|
||||
request(MTPmessages_EditMessage(
|
||||
MTP_flags(flags),
|
||||
item->history()->peer->input,
|
||||
MTP_int(id),
|
||||
MTP_string(text),
|
||||
MTPInputMedia(),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(options.scheduled)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
applyUpdates(result);
|
||||
}).fail([](const RPCError &error) {
|
||||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::reloadPollResults(not_null<HistoryItem*> item) {
|
||||
const auto itemId = item->fullId();
|
||||
if (!IsServerMsgId(item->id)
|
||||
|
||||
@@ -208,7 +208,7 @@ public:
|
||||
void requestChangelog(
|
||||
const QString &sinceVersion,
|
||||
Fn<void(const MTPUpdates &result)> callback);
|
||||
void refreshProxyPromotion();
|
||||
void refreshTopPromotion();
|
||||
void requestDeepLinkInfo(
|
||||
const QString &path,
|
||||
Fn<void(const MTPDhelp_deepLinkInfo &result)> callback);
|
||||
@@ -476,6 +476,10 @@ public:
|
||||
void closePoll(not_null<HistoryItem*> item);
|
||||
void reloadPollResults(not_null<HistoryItem*> item);
|
||||
|
||||
void rescheduleMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
Api::SendOptions options);
|
||||
|
||||
private:
|
||||
struct MessageDataRequest {
|
||||
using Callbacks = QList<RequestMessageDataCallback>;
|
||||
@@ -646,8 +650,8 @@ private:
|
||||
|
||||
//void readFeeds(); // #feed
|
||||
|
||||
void getProxyPromotionDelayed(TimeId now, TimeId next);
|
||||
void proxyPromotionDone(const MTPhelp_ProxyData &proxy);
|
||||
void getTopPromotionDelayed(TimeId now, TimeId next);
|
||||
void topPromotionDone(const MTPhelp_PromoData &proxy);
|
||||
|
||||
void sendNotifySettingsUpdates();
|
||||
|
||||
@@ -787,10 +791,10 @@ private:
|
||||
//base::flat_map<not_null<Data::Feed*>, mtpRequestId> _feedReadRequests;
|
||||
//base::Timer _feedReadTimer;
|
||||
|
||||
mtpRequestId _proxyPromotionRequestId = 0;
|
||||
std::pair<QString, uint32> _proxyPromotionKey;
|
||||
TimeId _proxyPromotionNextRequestTime = TimeId(0);
|
||||
base::Timer _proxyPromotionTimer;
|
||||
mtpRequestId _topPromotionRequestId = 0;
|
||||
std::pair<QString, uint32> _topPromotionKey;
|
||||
TimeId _topPromotionNextRequestTime = TimeId(0);
|
||||
base::Timer _topPromotionTimer;
|
||||
|
||||
base::flat_set<not_null<const PeerData*>> _updateNotifySettingsPeers;
|
||||
base::Timer _updateNotifySettingsTimer;
|
||||
|
||||
@@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "platform/platform_file_utilities.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "core/update_checker.h"
|
||||
@@ -23,7 +23,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QClipboard>
|
||||
#include <QtGui/QDesktopServices>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -109,7 +108,7 @@ void AboutBox::showVersionHistory() {
|
||||
|
||||
Ui::show(Box<InformBox>("The link to the current private alpha version of Telegram Desktop was copied to the clipboard."));
|
||||
} else {
|
||||
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/changelog"));
|
||||
File::OpenUrl(qsl("https://desktop.telegram.org/changelog"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ peerListBox: PeerList(defaultPeerList) {
|
||||
}
|
||||
|
||||
localStorageRowHeight: 50px;
|
||||
localStorageRowPadding: margins(23px, 5px, 20px, 5px);
|
||||
localStorageRowPadding: margins(22px, 5px, 20px, 5px);
|
||||
localStorageRowTitle: FlatLabel(defaultFlatLabel) {
|
||||
textFg: windowBoldFg;
|
||||
maxHeight: 20px;
|
||||
@@ -275,11 +275,11 @@ localStorageClear: defaultBoxButton;
|
||||
localStorageLimitLabel: LabelSimple(defaultLabelSimple) {
|
||||
font: boxTextFont;
|
||||
}
|
||||
localStorageLimitLabelMargin: margins(23px, 10px, 20px, 5px);
|
||||
localStorageLimitLabelMargin: margins(22px, 10px, 20px, 5px);
|
||||
localStorageLimitSlider: MediaSlider(defaultContinuousSlider) {
|
||||
seekSize: size(15px, 15px);
|
||||
}
|
||||
localStorageLimitMargin: margins(23px, 5px, 20px, 10px);
|
||||
localStorageLimitMargin: margins(22px, 5px, 20px, 10px);
|
||||
|
||||
shareRowsTop: 12px;
|
||||
shareRowHeight: 108px;
|
||||
@@ -340,7 +340,7 @@ sessionsHeight: 350px;
|
||||
sessionHeight: 70px;
|
||||
sessionCurrentPadding: margins(0px, 7px, 0px, 4px);
|
||||
sessionCurrentHeight: 118px;
|
||||
sessionPadding: margins(23px, 10px, 23px, 0px);
|
||||
sessionPadding: margins(22px, 10px, 22px, 0px);
|
||||
sessionNameFont: msgNameFont;
|
||||
sessionNameFg: boxTextFg;
|
||||
sessionWhenFont: msgDateFont;
|
||||
@@ -428,7 +428,7 @@ aboutLabel: FlatLabel(defaultFlatLabel) {
|
||||
}
|
||||
|
||||
autoDownloadTopDelta: 10px;
|
||||
autoDownloadTitlePosition: point(23px, 18px);
|
||||
autoDownloadTitlePosition: point(22px, 18px);
|
||||
autoDownloadTitleFont: font(15px semibold);
|
||||
autoDownloadLimitSlider: MediaSlider(defaultContinuousSlider) {
|
||||
seekSize: size(15px, 15px);
|
||||
@@ -562,7 +562,7 @@ passcodeTextStyle: TextStyle(defaultTextStyle) {
|
||||
lineHeight: 20px;
|
||||
}
|
||||
|
||||
usernamePadding: margins(23px, 6px, 21px, 12px);
|
||||
usernamePadding: margins(22px, 6px, 21px, 12px);
|
||||
usernameSkip: 49px;
|
||||
usernameTextStyle: TextStyle(boxTextStyle, passcodeTextStyle) {
|
||||
}
|
||||
@@ -642,9 +642,9 @@ rightsToggle: Toggle(defaultToggle) {
|
||||
}
|
||||
rightsDividerHeight: boxDividerHeight;
|
||||
rightsDividerMargin: margins(0px, 0px, 0px, 20px);
|
||||
rightsHeaderMargin: margins(23px, 0px, 23px, 8px);
|
||||
rightsToggleMargin: margins(23px, 8px, 23px, 8px);
|
||||
rightsAboutMargin: margins(23px, 8px, 23px, 8px);
|
||||
rightsHeaderMargin: margins(22px, 0px, 22px, 8px);
|
||||
rightsToggleMargin: margins(22px, 8px, 22px, 8px);
|
||||
rightsAboutMargin: margins(22px, 8px, 22px, 8px);
|
||||
rightsPhotoButton: UserpicButton(defaultUserpicButton) {
|
||||
size: size(60px, 60px);
|
||||
photoSize: 60px;
|
||||
@@ -773,8 +773,8 @@ markdownLinkFieldPadding: margins(22px, 0px, 22px, 10px);
|
||||
termsContent: FlatLabel(defaultFlatLabel) {
|
||||
minWidth: 285px;
|
||||
}
|
||||
termsPadding: margins(23px, 4px, 16px, 16px);
|
||||
termsAgePadding: margins(23px, 16px, 16px, 0px);
|
||||
termsPadding: margins(22px, 4px, 16px, 16px);
|
||||
termsAgePadding: margins(22px, 16px, 16px, 0px);
|
||||
|
||||
themesSmallSkip: 10px;
|
||||
themesBackgroundSize: 120px;
|
||||
@@ -860,7 +860,7 @@ createPollWarning: FlatLabel(defaultFlatLabel) {
|
||||
}
|
||||
}
|
||||
createPollWarningPosition: point(16px, 6px);
|
||||
createPollCheckboxMargin: margins(23px, 10px, 23px, 10px);
|
||||
createPollCheckboxMargin: margins(22px, 10px, 22px, 10px);
|
||||
createPollFieldTitlePadding: margins(22px, 7px, 10px, 6px);
|
||||
|
||||
callSettingsButton: IconButton {
|
||||
@@ -915,7 +915,7 @@ blockUserConfirmation: FlatLabel(boxLabel) {
|
||||
minWidth: 240px;
|
||||
}
|
||||
|
||||
transferCheckWidth: 300px;
|
||||
transferCheckWidth: 320px;
|
||||
|
||||
slowmodeLabelsMargin: margins(0px, 5px, 0px, 0px);
|
||||
slowmodeLabel: LabelSimple(defaultLabelSimple) {
|
||||
|
||||
@@ -599,4 +599,19 @@ void CalendarBox::keyPressEvent(QKeyEvent *e) {
|
||||
}
|
||||
}
|
||||
|
||||
void CalendarBox::wheelEvent(QWheelEvent *e) {
|
||||
// Only a mouse wheel is accepted.
|
||||
constexpr auto step = static_cast<int>(QWheelEvent::DefaultDeltasPerStep);
|
||||
const auto delta = e->angleDelta().y();
|
||||
if (std::abs(delta) != step) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (delta < 0) {
|
||||
goPreviousMonth();
|
||||
} else {
|
||||
goNextMonth();
|
||||
}
|
||||
}
|
||||
|
||||
CalendarBox::~CalendarBox() = default;
|
||||
|
||||
@@ -46,6 +46,7 @@ protected:
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void wheelEvent(QWheelEvent *e) override;
|
||||
|
||||
private:
|
||||
void monthChanged(QDate month);
|
||||
|
||||
@@ -83,7 +83,7 @@ private:
|
||||
void show(anim::type animated);
|
||||
void destroy(FnMut<void()> done);
|
||||
|
||||
[[nodisacrd]] bool hasShadow() const;
|
||||
[[nodiscard]] bool hasShadow() const;
|
||||
void createShadow();
|
||||
void destroyShadow();
|
||||
|
||||
|
||||
@@ -548,18 +548,10 @@ void EditCaptionBox::prepare() {
|
||||
if (action == Ui::InputField::MimeAction::Check) {
|
||||
if (!data->hasText() && !_isAllowedEditMedia) {
|
||||
return false;
|
||||
}
|
||||
if (data->hasImage()) {
|
||||
const auto image = qvariant_cast<QImage>(data->imageData());
|
||||
if (!image.isNull()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (const auto urls = data->urls(); !urls.empty()) {
|
||||
if (ranges::find_if(
|
||||
urls,
|
||||
[](const QUrl &url) { return !url.isLocalFile(); }
|
||||
) == urls.end()) {
|
||||
} else if (data->hasImage()) {
|
||||
return true;
|
||||
} else if (const auto urls = data->urls(); !urls.empty()) {
|
||||
if (ranges::all_of(urls, &QUrl::isLocalFile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
LastSeen,
|
||||
Custom,
|
||||
};
|
||||
void refreshStatus();
|
||||
virtual void refreshStatus();
|
||||
crl::time refreshStatusTime() const;
|
||||
|
||||
void setAbsoluteIndex(int index) {
|
||||
|
||||
@@ -584,5 +584,9 @@ void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
|
||||
auto ChooseRecipientBoxController::createRow(
|
||||
not_null<History*> history) -> std::unique_ptr<Row> {
|
||||
return std::make_unique<Row>(history);
|
||||
const auto peer = history->peer;
|
||||
const auto skip = peer->isChannel()
|
||||
&& !peer->isMegagroup()
|
||||
&& !peer->canWrite();
|
||||
return skip ? nullptr : std::make_unique<Row>(history);
|
||||
}
|
||||
|
||||
@@ -1056,7 +1056,9 @@ void ParticipantsBoxController::prepare() {
|
||||
switch (_role) {
|
||||
case Role::Admins: return tr::lng_channel_admins();
|
||||
case Role::Profile:
|
||||
case Role::Members: return tr::lng_profile_participants_section();
|
||||
case Role::Members: return (_peer->isChannel() && !_peer->isMegagroup()
|
||||
? tr::lng_profile_subscribers_section()
|
||||
: tr::lng_profile_participants_section());
|
||||
case Role::Restricted: return tr::lng_exceptions_list_title();
|
||||
case Role::Kicked: return tr::lng_removed_list_title();
|
||||
}
|
||||
@@ -1786,6 +1788,12 @@ std::unique_ptr<PeerListRow> ParticipantsBoxController::createRow(
|
||||
|| _additional.canEditAdmin(user))) {
|
||||
row->setActionLink(tr::lng_profile_kick(tr::now));
|
||||
}
|
||||
if (_role == Role::Members && user->isBot()) {
|
||||
auto seesAllMessages = (user->botInfo->readsAllHistory || _additional.adminRights(user).has_value());
|
||||
row->setCustomStatus(seesAllMessages
|
||||
? tr::lng_status_bot_reads_all(tr::now)
|
||||
: tr::lng_status_bot_not_reads_all(tr::now));
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
@@ -967,7 +967,7 @@ void Controller::fillManageSection() {
|
||||
if (canViewMembers) {
|
||||
AddButtonWithCount(
|
||||
_controls.buttonsLayout,
|
||||
tr::lng_manage_peer_members(),
|
||||
(_isGroup ? tr::lng_manage_peer_members() : tr::lng_manage_peer_subscribers()),
|
||||
Info::Profile::MigratedOrMeValue(
|
||||
_peer
|
||||
) | rpl::map(
|
||||
|
||||
@@ -1934,6 +1934,7 @@ void SendFilesBox::initSendWay() {
|
||||
if (_albumPreview) {
|
||||
_albumPreview->setSendWay(value);
|
||||
}
|
||||
updateEmojiPanelGeometry();
|
||||
setInnerFocus();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
bool actionSelected) override;
|
||||
|
||||
private:
|
||||
void refreshStatus();
|
||||
void refreshStatus() override;
|
||||
static Type ComputeType(not_null<const HistoryItem*> item);
|
||||
|
||||
std::vector<not_null<HistoryItem*>> _items;
|
||||
|
||||
@@ -463,6 +463,8 @@ void Panel::toggleOpacityAnimation(bool visible) {
|
||||
_visible ? 1. : 0.,
|
||||
st::callPanelDuration,
|
||||
_visible ? anim::easeOutCirc : anim::easeInCirc);
|
||||
} else if (!isHidden() && !_visible) {
|
||||
hide();
|
||||
}
|
||||
if (isHidden() && _visible) {
|
||||
show();
|
||||
|
||||
@@ -218,8 +218,11 @@ stickerGroupCategoryAbout: defaultTextStyle;
|
||||
stickerGroupCategoryAddMargin: margins(0px, 10px, 0px, 5px);
|
||||
stickerGroupCategoryAdd: stickersTrendingAdd;
|
||||
|
||||
stickersToastMaxWidth: 340px;
|
||||
stickersToastPadding: margins(16px, 13px, 16px, 12px);
|
||||
stickersToast: Toast(defaultToast) {
|
||||
minWidth: 340px;
|
||||
maxWidth: 340px;
|
||||
padding: margins(16px, 13px, 16px, 12px);
|
||||
}
|
||||
|
||||
stickersEmpty: icon {{ "stickers_empty", windowSubTextFg }};
|
||||
|
||||
@@ -271,7 +274,7 @@ autocompleteRowAnswer: defaultTextStyle;
|
||||
manageEmojiPreview: 22px;
|
||||
manageEmojiPreviewWidth: 48px;
|
||||
manageEmojiPreviewHeight: 48px;
|
||||
manageEmojiPreviewPadding: margins(23px, 9px, 19px, 9px);
|
||||
manageEmojiPreviewPadding: margins(22px, 9px, 19px, 9px);
|
||||
manageEmojiMarginRight: 21px;
|
||||
manageEmojiNameTop: 3px;
|
||||
manageEmojiStatusTop: 25px;
|
||||
|
||||
@@ -40,15 +40,15 @@ inline auto PreviewPath(int i) {
|
||||
|
||||
const auto kSets = {
|
||||
Set{ {0, 0, 0, "Mac"}, PreviewPath(0) },
|
||||
Set{ {1, 246, 7'336'383, "Android"}, PreviewPath(1) },
|
||||
Set{ {2, 206, 5'038'738, "Twemoji"}, PreviewPath(2) },
|
||||
Set{ {3, 238, 6'992'260, "JoyPixels"}, PreviewPath(3) },
|
||||
Set{ {1, 713, 7'313'166, "Android"}, PreviewPath(1) },
|
||||
Set{ {2, 714, 4'690'333, "Twemoji"}, PreviewPath(2) },
|
||||
Set{ {3, 716, 5'968'021, "JoyPixels"}, PreviewPath(3) },
|
||||
};
|
||||
|
||||
using Loading = MTP::DedicatedLoader::Progress;
|
||||
using SetState = BlobState;
|
||||
|
||||
class Loader : public BlobLoader {
|
||||
class Loader final : public BlobLoader {
|
||||
public:
|
||||
Loader(
|
||||
QObject *parent,
|
||||
@@ -60,6 +60,9 @@ public:
|
||||
void destroy() override;
|
||||
void unpack(const QString &path) override;
|
||||
|
||||
private:
|
||||
void fail() override;
|
||||
|
||||
};
|
||||
|
||||
class Inner : public Ui::RpWidget {
|
||||
@@ -155,12 +158,14 @@ bool UnpackSet(const QString &path, const QString &folder) {
|
||||
return UnpackBlob(path, folder, GoodSetPartName);
|
||||
}
|
||||
|
||||
|
||||
Loader::Loader(
|
||||
QObject *parent,
|
||||
int id,
|
||||
MTP::DedicatedLoader::Location location,
|
||||
const QString &folder,
|
||||
int size) : BlobLoader(parent, id, location, folder, size) {
|
||||
int size)
|
||||
: BlobLoader(parent, id, location, folder, size) {
|
||||
}
|
||||
|
||||
void Loader::unpack(const QString &path) {
|
||||
@@ -190,6 +195,11 @@ void Loader::destroy() {
|
||||
SetGlobalLoader(nullptr);
|
||||
}
|
||||
|
||||
void Loader::fail() {
|
||||
ClearNeedSwitchToId();
|
||||
BlobLoader::fail();
|
||||
}
|
||||
|
||||
Inner::Inner(QWidget *parent) : RpWidget(parent) {
|
||||
setupContent();
|
||||
}
|
||||
@@ -401,12 +411,7 @@ void Row::setupHandler() {
|
||||
}
|
||||
|
||||
void Row::load() {
|
||||
SetGlobalLoader(base::make_unique_q<Loader>(
|
||||
App::main(),
|
||||
_id,
|
||||
GetDownloadLocation(_id),
|
||||
internal::SetDataPath(_id),
|
||||
GetDownloadSize(_id)));
|
||||
LoadAndSwitchTo(_id);
|
||||
}
|
||||
|
||||
void Row::setupLabels(const Set &set) {
|
||||
@@ -538,5 +543,20 @@ void ManageSetsBox::prepare() {
|
||||
setDimensionsToContent(st::boxWidth, inner);
|
||||
}
|
||||
|
||||
void LoadAndSwitchTo(int id) {
|
||||
Expects(App::main() != nullptr);
|
||||
|
||||
if (!ranges::contains(kSets, id, &Set::id)) {
|
||||
ClearNeedSwitchToId();
|
||||
return;
|
||||
}
|
||||
SetGlobalLoader(base::make_unique_q<Loader>(
|
||||
App::main(),
|
||||
id,
|
||||
GetDownloadLocation(id),
|
||||
internal::SetDataPath(id),
|
||||
GetDownloadSize(id)));
|
||||
}
|
||||
|
||||
} // namespace Emoji
|
||||
} // namespace Ui
|
||||
|
||||
@@ -21,5 +21,7 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
void LoadAndSwitchTo(int id);
|
||||
|
||||
} // namespace Emoji
|
||||
} // namespace Ui
|
||||
|
||||
@@ -20,9 +20,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "main/main_session.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_history.h"
|
||||
@@ -33,14 +33,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
FieldAutocomplete::FieldAutocomplete(
|
||||
QWidget *parent,
|
||||
not_null<Main::Session*> session)
|
||||
not_null<Window::SessionController*> controller)
|
||||
: RpWidget(parent)
|
||||
, _session(session)
|
||||
, _controller(controller)
|
||||
, _scroll(this, st::mentionScroll) {
|
||||
_scroll->setGeometry(rect());
|
||||
|
||||
_inner = _scroll->setOwnedWidget(
|
||||
object_ptr<internal::FieldAutocompleteInner>(
|
||||
_controller,
|
||||
this,
|
||||
&_mrows,
|
||||
&_hrows,
|
||||
@@ -169,7 +170,7 @@ inline int indexOfInFirstN(const T &v, const U &elem, int last) {
|
||||
|
||||
internal::StickerRows FieldAutocomplete::getStickerSuggestions() {
|
||||
const auto list = Stickers::GetListByEmoji(
|
||||
_session,
|
||||
&_controller->session(),
|
||||
_emoji,
|
||||
_stickersSeed
|
||||
);
|
||||
@@ -584,12 +585,14 @@ bool FieldAutocomplete::eventFilter(QObject *obj, QEvent *e) {
|
||||
namespace internal {
|
||||
|
||||
FieldAutocompleteInner::FieldAutocompleteInner(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<FieldAutocomplete*> parent,
|
||||
not_null<MentionRows*> mrows,
|
||||
not_null<HashtagRows*> hrows,
|
||||
not_null<BotCommandRows*> brows,
|
||||
not_null<StickerRows*> srows)
|
||||
: _parent(parent)
|
||||
: _controller(controller)
|
||||
, _parent(parent)
|
||||
, _mrows(mrows)
|
||||
, _hrows(hrows)
|
||||
, _brows(brows)
|
||||
@@ -665,7 +668,6 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
||||
}
|
||||
if (sticker.animated && sticker.animated->ready()) {
|
||||
const auto frame = sticker.animated->frame();
|
||||
sticker.animated->markFrameShown();
|
||||
const auto size = frame.size() / cIntRetinaFactor();
|
||||
const auto ppos = pos + QPoint(
|
||||
(st::stickerPanSize.width() - size.width()) / 2,
|
||||
@@ -673,6 +675,11 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
||||
p.drawImage(
|
||||
QRect(ppos, size),
|
||||
frame);
|
||||
const auto paused = _controller->isGifPausedAtLeastFor(
|
||||
Window::GifPauseReason::SavedGifs);
|
||||
if (!paused) {
|
||||
sticker.animated->markFrameShown();
|
||||
}
|
||||
} else if (const auto image = document->getStickerSmall()) {
|
||||
QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2);
|
||||
p.drawPixmapLeft(ppos, width(), image->pix(document->stickerSetOrigin(), w, h));
|
||||
|
||||
@@ -22,9 +22,9 @@ class SinglePlayer;
|
||||
class FrameRenderer;
|
||||
} // namespace Lottie;
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -46,7 +46,9 @@ class FieldAutocomplete final : public Ui::RpWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FieldAutocomplete(QWidget *parent, not_null<Main::Session*> session);
|
||||
FieldAutocomplete(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
~FieldAutocomplete();
|
||||
|
||||
bool clearFilteredBotCommands();
|
||||
@@ -109,7 +111,7 @@ private:
|
||||
void recount(bool resetScroll = false);
|
||||
internal::StickerRows getStickerSuggestions();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
QPixmap _cache;
|
||||
internal::MentionRows _mrows;
|
||||
internal::HashtagRows _hrows;
|
||||
@@ -160,6 +162,7 @@ class FieldAutocompleteInner final
|
||||
|
||||
public:
|
||||
FieldAutocompleteInner(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<FieldAutocomplete*> parent,
|
||||
not_null<MentionRows*> mrows,
|
||||
not_null<HashtagRows*> hrows,
|
||||
@@ -204,11 +207,12 @@ private:
|
||||
void repaintSticker(not_null<DocumentData*> document);
|
||||
std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
|
||||
|
||||
not_null<FieldAutocomplete*> _parent;
|
||||
not_null<MentionRows*> _mrows;
|
||||
not_null<HashtagRows*> _hrows;
|
||||
not_null<BotCommandRows*> _brows;
|
||||
not_null<StickerRows*> _srows;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const not_null<FieldAutocomplete*> _parent;
|
||||
const not_null<MentionRows*> _mrows;
|
||||
const not_null<HashtagRows*> _hrows;
|
||||
const not_null<BotCommandRows*> _brows;
|
||||
const not_null<StickerRows*> _srows;
|
||||
rpl::lifetime _stickersLifetime;
|
||||
std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
|
||||
int _stickersPerRow = 1;
|
||||
|
||||
@@ -77,12 +77,11 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
|
||||
Local::writeInstalledStickers();
|
||||
Local::writeArchivedStickers();
|
||||
|
||||
auto toast = Ui::Toast::Config();
|
||||
toast.text = { tr::lng_stickers_packs_archived(tr::now) };
|
||||
toast.maxWidth = toast.minWidth = st::stickersToastMaxWidth;
|
||||
toast.multiline = true;
|
||||
toast.padding = st::stickersToastPadding;
|
||||
Ui::Toast::Show(toast);
|
||||
Ui::Toast::Show(Ui::Toast::Config{
|
||||
.text = { tr::lng_stickers_packs_archived(tr::now) },
|
||||
.st = &st::stickersToast,
|
||||
.multiline = true,
|
||||
});
|
||||
// Ui::show(Box<StickersBox>(archived, &Auth()), Ui::LayerOption::KeepOther);
|
||||
|
||||
Auth().data().notifyStickersUpdated();
|
||||
|
||||
@@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "observer_peer.h"
|
||||
#include "storage/storage_databases.h"
|
||||
#include "mainwidget.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "main/main_account.h"
|
||||
#include "media/view/media_view_overlay_widget.h"
|
||||
#include "mtproto/dc_options.h"
|
||||
@@ -300,7 +301,7 @@ void Application::showDocument(not_null<DocumentData*> document, HistoryItem *it
|
||||
if (cUseExternalVideoPlayer()
|
||||
&& document->isVideoFile()
|
||||
&& document->loaded()) {
|
||||
QDesktopServices::openUrl(QUrl("file:///" + document->location(false).fname));
|
||||
File::Launch(document->location(false).fname);
|
||||
} else {
|
||||
_mediaView->showDocument(document, item);
|
||||
_mediaView->activateWindow();
|
||||
@@ -517,6 +518,21 @@ void Application::switchTestMode() {
|
||||
App::restart();
|
||||
}
|
||||
|
||||
void Application::switchFreeType() {
|
||||
if (cUseFreeType()) {
|
||||
QFile(cWorkingDir() + qsl("tdata/withfreetype")).remove();
|
||||
cSetUseFreeType(false);
|
||||
} else {
|
||||
QFile f(cWorkingDir() + qsl("tdata/withfreetype"));
|
||||
if (f.open(QIODevice::WriteOnly)) {
|
||||
f.write("1");
|
||||
f.close();
|
||||
}
|
||||
cSetUseFreeType(true);
|
||||
}
|
||||
App::restart();
|
||||
}
|
||||
|
||||
void Application::writeInstallBetaVersionsSetting() {
|
||||
_launcher->writeInstallBetaVersionsSetting();
|
||||
}
|
||||
|
||||
@@ -215,6 +215,7 @@ public:
|
||||
|
||||
void switchDebugMode();
|
||||
void switchTestMode();
|
||||
void switchFreeType();
|
||||
void writeInstallBetaVersionsSetting();
|
||||
|
||||
void call_handleUnreadCounterUpdate();
|
||||
|
||||
@@ -22,7 +22,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
|
||||
#include <QtGui/QDesktopServices>
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -42,7 +42,9 @@ PreLaunchWindow::PreLaunchWindow(QString title) {
|
||||
p.setColor(QPalette::Background, QColor(255, 255, 255));
|
||||
setPalette(p);
|
||||
|
||||
_size = QFontInfo(QApplication::font()).pixelSize();
|
||||
QLabel tmp(this);
|
||||
tmp.setText(qsl("Tmp"));
|
||||
_size = tmp.sizeHint().height();
|
||||
|
||||
int paddingVertical = (_size / 2);
|
||||
int paddingHorizontal = _size;
|
||||
@@ -90,6 +92,7 @@ void PreLaunchLabel::setText(const QString &text) {
|
||||
|
||||
PreLaunchInput::PreLaunchInput(QWidget *parent, bool password) : QLineEdit(parent) {
|
||||
QFont logFont(font());
|
||||
logFont.setFamily(style::internal::GetFontOverride());
|
||||
logFont.setPixelSize(static_cast<PreLaunchWindow*>(parent)->basicSize());
|
||||
setFont(logFont);
|
||||
|
||||
@@ -107,6 +110,7 @@ PreLaunchInput::PreLaunchInput(QWidget *parent, bool password) : QLineEdit(paren
|
||||
|
||||
PreLaunchLog::PreLaunchLog(QWidget *parent) : QTextEdit(parent) {
|
||||
QFont logFont(font());
|
||||
logFont.setFamily(style::internal::GetFontOverride());
|
||||
logFont.setPixelSize(static_cast<PreLaunchWindow*>(parent)->basicSize());
|
||||
setFont(logFont);
|
||||
|
||||
|
||||
@@ -118,6 +118,13 @@ QString filedialogNextFilename(
|
||||
|
||||
namespace File {
|
||||
|
||||
void OpenUrl(const QString &url) {
|
||||
crl::on_main([=] {
|
||||
Ui::PreventDelayedActivation();
|
||||
Platform::File::UnsafeOpenUrl(url);
|
||||
});
|
||||
}
|
||||
|
||||
void OpenEmailLink(const QString &email) {
|
||||
crl::on_main([=] {
|
||||
Ui::PreventDelayedActivation();
|
||||
@@ -162,6 +169,10 @@ QString DefaultDownloadPath() {
|
||||
|
||||
namespace internal {
|
||||
|
||||
void UnsafeOpenUrlDefault(const QString &url) {
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
|
||||
void UnsafeOpenEmailLinkDefault(const QString &email) {
|
||||
auto url = QUrl(qstr("mailto:") + email);
|
||||
QDesktopServices::openUrl(url);
|
||||
|
||||
@@ -30,6 +30,7 @@ QString filedialogNextFilename(
|
||||
namespace File {
|
||||
|
||||
// Those functions are async wrappers to Platform::File::Unsafe* calls.
|
||||
void OpenUrl(const QString &url);
|
||||
void OpenEmailLink(const QString &email);
|
||||
void OpenWith(const QString &filepath, QPoint menuPosition);
|
||||
void Launch(const QString &filepath);
|
||||
@@ -43,6 +44,7 @@ inline QString UrlToLocalDefault(const QUrl &url) {
|
||||
return url.toLocalFile();
|
||||
}
|
||||
|
||||
void UnsafeOpenUrlDefault(const QString &url);
|
||||
void UnsafeOpenEmailLinkDefault(const QString &email);
|
||||
void UnsafeLaunchDefault(const QString &filepath);
|
||||
|
||||
|
||||
@@ -34,26 +34,47 @@ private:
|
||||
static constexpr auto kForwardArgumentCount = 1;
|
||||
|
||||
int _count = 0;
|
||||
char *_arguments[kForwardArgumentCount + 1] = { nullptr };
|
||||
std::vector<QByteArray> _owned;
|
||||
std::vector<char*> _arguments;
|
||||
|
||||
void pushArgument(const char *text);
|
||||
|
||||
};
|
||||
|
||||
FilteredCommandLineArguments::FilteredCommandLineArguments(
|
||||
int argc,
|
||||
char **argv)
|
||||
: _count(std::clamp(argc, 0, kForwardArgumentCount)) {
|
||||
char **argv) {
|
||||
// For now just pass only the first argument, the executable path.
|
||||
for (auto i = 0; i != _count; ++i) {
|
||||
_arguments[i] = argv[i];
|
||||
for (auto i = 0; i != kForwardArgumentCount; ++i) {
|
||||
pushArgument(argv[i]);
|
||||
}
|
||||
|
||||
#if defined Q_OS_WIN || defined Q_OS_MAC
|
||||
if (cUseFreeType()) {
|
||||
pushArgument("-platform");
|
||||
#ifdef Q_OS_WIN
|
||||
pushArgument("windows:fontengine=freetype");
|
||||
#else // Q_OS_WIN
|
||||
pushArgument("cocoa:fontengine=freetype");
|
||||
#endif // !Q_OS_WIN
|
||||
}
|
||||
#endif // Q_OS_WIN || Q_OS_MAC
|
||||
|
||||
pushArgument(nullptr);
|
||||
}
|
||||
|
||||
int &FilteredCommandLineArguments::count() {
|
||||
_count = _arguments.size() - 1;
|
||||
return _count;
|
||||
}
|
||||
|
||||
char **FilteredCommandLineArguments::values() {
|
||||
return _arguments;
|
||||
return _arguments.data();
|
||||
}
|
||||
|
||||
void FilteredCommandLineArguments::pushArgument(const char *text) {
|
||||
_owned.emplace_back(text);
|
||||
_arguments.push_back(_owned.back().data());
|
||||
}
|
||||
|
||||
QString DebugModeSettingPath() {
|
||||
@@ -82,6 +103,12 @@ void ComputeTestMode() {
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeFreeType() {
|
||||
if (QFile(cWorkingDir() + qsl("tdata/withfreetype")).exists()) {
|
||||
cSetUseFreeType(true);
|
||||
}
|
||||
}
|
||||
|
||||
QString InstallBetaVersionsSettingPath() {
|
||||
return cWorkingDir() + qsl("tdata/devversion");
|
||||
}
|
||||
@@ -301,6 +328,7 @@ void Launcher::workingFolderReady() {
|
||||
|
||||
ComputeTestMode();
|
||||
ComputeDebugMode();
|
||||
ComputeFreeType();
|
||||
ComputeInstallBetaVersions();
|
||||
ComputeInstallationTag();
|
||||
}
|
||||
@@ -382,6 +410,7 @@ void Launcher::processArguments() {
|
||||
auto parseMap = std::map<QByteArray, KeyFormat> {
|
||||
{ "-testmode" , KeyFormat::NoValues },
|
||||
{ "-debug" , KeyFormat::NoValues },
|
||||
{ "-freetype" , KeyFormat::NoValues },
|
||||
{ "-many" , KeyFormat::NoValues },
|
||||
{ "-key" , KeyFormat::OneValue },
|
||||
{ "-autostart" , KeyFormat::NoValues },
|
||||
@@ -423,6 +452,7 @@ void Launcher::processArguments() {
|
||||
SetUpdaterDisabledAtStartup();
|
||||
}
|
||||
gTestMode = parseResult.contains("-testmode");
|
||||
gUseFreeType = parseResult.contains("-freetype");
|
||||
Logs::SetDebugEnabled(parseResult.contains("-debug"));
|
||||
gManyInstance = parseResult.contains("-many");
|
||||
gKeyFile = parseResult.value("-key", {}).join(QString()).toLower();
|
||||
|
||||
@@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/connection_box.h"
|
||||
#include "boxes/sticker_set_box.h"
|
||||
#include "boxes/sessions_box.h"
|
||||
#include "boxes/language_box.h"
|
||||
#include "passport/passport_form_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "data/data_session.h"
|
||||
@@ -101,12 +102,21 @@ bool ShowTheme(
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShowLanguagesBox() {
|
||||
static auto Guard = base::binary_guard();
|
||||
Guard = LanguageBox::Show();
|
||||
}
|
||||
|
||||
bool SetLanguage(
|
||||
Main::Session *session,
|
||||
const Match &match,
|
||||
const QVariant &context) {
|
||||
const auto languageId = match->captured(1);
|
||||
Lang::CurrentCloudManager().switchWithWarning(languageId);
|
||||
if (match->capturedRef(1).isEmpty()) {
|
||||
ShowLanguagesBox();
|
||||
} else {
|
||||
const auto languageId = match->captured(2);
|
||||
Lang::CurrentCloudManager().switchWithWarning(languageId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -351,6 +361,9 @@ bool ResolveSettings(
|
||||
if (section == qstr("devices")) {
|
||||
Ui::show(Box<SessionsBox>(session));
|
||||
return true;
|
||||
} else if (section == qstr("language")) {
|
||||
ShowLanguagesBox();
|
||||
return true;
|
||||
}
|
||||
const auto type = (section == qstr("folders"))
|
||||
? ::Settings::Type::Folders
|
||||
@@ -441,7 +454,7 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
|
||||
ShowTheme
|
||||
},
|
||||
{
|
||||
qsl("^setlanguage/?\\?lang=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"),
|
||||
qsl("^setlanguage/?(\\?lang=([a-zA-Z0-9\\.\\_\\-]+))?(&|$)"),
|
||||
SetLanguage
|
||||
},
|
||||
{
|
||||
@@ -481,7 +494,7 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
|
||||
ResolvePrivatePost
|
||||
},
|
||||
{
|
||||
qsl("^settings(/folders|/devices)?$"),
|
||||
qsl("^settings(/folders|/devices|/language)?$"),
|
||||
ResolveSettings
|
||||
},
|
||||
{
|
||||
|
||||
@@ -373,11 +373,8 @@ void Sandbox::readClients() {
|
||||
toSend.append(_escapeFrom7bit(cmds.mid(from + 5, to - from - 5)));
|
||||
}
|
||||
} else if (cmd.startsWith(qsl("OPEN:"))) {
|
||||
auto activateRequired = true;
|
||||
if (cStartUrl().isEmpty()) {
|
||||
startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)).mid(0, 8192);
|
||||
activateRequired = StartUrlRequiresActivate(startUrl);
|
||||
}
|
||||
startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)).mid(0, 8192);
|
||||
auto activateRequired = StartUrlRequiresActivate(startUrl);
|
||||
if (activateRequired) {
|
||||
execExternal("show");
|
||||
}
|
||||
|
||||
@@ -55,57 +55,81 @@ const auto SupportCommands = base::flat_set<Command>{
|
||||
};
|
||||
|
||||
const auto CommandByName = base::flat_map<QString, Command>{
|
||||
{ qsl("close_telegram") , Command::Close },
|
||||
{ qsl("lock_telegram") , Command::Lock },
|
||||
{ qsl("minimize_telegram"), Command::Minimize },
|
||||
{ qsl("quit_telegram") , Command::Quit },
|
||||
{ qsl("close_telegram") , Command::Close },
|
||||
{ qsl("lock_telegram") , Command::Lock },
|
||||
{ qsl("minimize_telegram") , Command::Minimize },
|
||||
{ qsl("quit_telegram") , Command::Quit },
|
||||
|
||||
{ qsl("media_play") , Command::MediaPlay },
|
||||
{ qsl("media_pause") , Command::MediaPause },
|
||||
{ qsl("media_playpause") , Command::MediaPlayPause },
|
||||
{ qsl("media_stop") , Command::MediaStop },
|
||||
{ qsl("media_previous") , Command::MediaPrevious },
|
||||
{ qsl("media_next") , Command::MediaNext },
|
||||
{ qsl("media_play") , Command::MediaPlay },
|
||||
{ qsl("media_pause") , Command::MediaPause },
|
||||
{ qsl("media_playpause") , Command::MediaPlayPause },
|
||||
{ qsl("media_stop") , Command::MediaStop },
|
||||
{ qsl("media_previous") , Command::MediaPrevious },
|
||||
{ qsl("media_next") , Command::MediaNext },
|
||||
|
||||
{ qsl("search") , Command::Search },
|
||||
{ qsl("search") , Command::Search },
|
||||
|
||||
{ qsl("previous_chat") , Command::ChatPrevious },
|
||||
{ qsl("next_chat") , Command::ChatNext },
|
||||
{ qsl("first_chat") , Command::ChatFirst },
|
||||
{ qsl("last_chat") , Command::ChatLast },
|
||||
{ qsl("self_chat") , Command::ChatSelf },
|
||||
{ qsl("previous_chat") , Command::ChatPrevious },
|
||||
{ qsl("next_chat") , Command::ChatNext },
|
||||
{ qsl("first_chat") , Command::ChatFirst },
|
||||
{ qsl("last_chat") , Command::ChatLast },
|
||||
{ qsl("self_chat") , Command::ChatSelf },
|
||||
|
||||
{ qsl("previous_folder") , Command::FolderPrevious },
|
||||
{ qsl("next_folder") , Command::FolderNext },
|
||||
{ qsl("all_chats") , Command::ShowAllChats },
|
||||
|
||||
{ qsl("folder1") , Command::ShowFolder1 },
|
||||
{ qsl("folder2") , Command::ShowFolder2 },
|
||||
{ qsl("folder3") , Command::ShowFolder3 },
|
||||
{ qsl("folder4") , Command::ShowFolder4 },
|
||||
{ qsl("folder5") , Command::ShowFolder5 },
|
||||
{ qsl("folder6") , Command::ShowFolder6 },
|
||||
{ qsl("last_folder") , Command::ShowFolderLast },
|
||||
|
||||
{ qsl("show_archive") , Command::ShowArchive },
|
||||
{ qsl("show_archive") , Command::ShowArchive },
|
||||
|
||||
// Shortcuts that have no default values.
|
||||
{ qsl("message") , Command::JustSendMessage },
|
||||
{ qsl("message_silently") , Command::SendSilentMessage },
|
||||
{ qsl("message_scheduled"), Command::ScheduleMessage },
|
||||
{ qsl("message") , Command::JustSendMessage },
|
||||
{ qsl("message_silently") , Command::SendSilentMessage },
|
||||
{ qsl("message_scheduled") , Command::ScheduleMessage },
|
||||
//
|
||||
};
|
||||
|
||||
const auto CommandNames = base::flat_map<Command, QString>{
|
||||
{ Command::Close , qsl("close_telegram") },
|
||||
{ Command::Lock , qsl("lock_telegram") },
|
||||
{ Command::Minimize , qsl("minimize_telegram") },
|
||||
{ Command::Quit , qsl("quit_telegram") },
|
||||
{ Command::Close , qsl("close_telegram") },
|
||||
{ Command::Lock , qsl("lock_telegram") },
|
||||
{ Command::Minimize , qsl("minimize_telegram") },
|
||||
{ Command::Quit , qsl("quit_telegram") },
|
||||
|
||||
{ Command::MediaPlay , qsl("media_play") },
|
||||
{ Command::MediaPause , qsl("media_pause") },
|
||||
{ Command::MediaPlayPause, qsl("media_playpause") },
|
||||
{ Command::MediaStop , qsl("media_stop") },
|
||||
{ Command::MediaPrevious , qsl("media_previous") },
|
||||
{ Command::MediaNext , qsl("media_next") },
|
||||
{ Command::MediaPlay , qsl("media_play") },
|
||||
{ Command::MediaPause , qsl("media_pause") },
|
||||
{ Command::MediaPlayPause , qsl("media_playpause") },
|
||||
{ Command::MediaStop , qsl("media_stop") },
|
||||
{ Command::MediaPrevious , qsl("media_previous") },
|
||||
{ Command::MediaNext , qsl("media_next") },
|
||||
|
||||
{ Command::Search , qsl("search") },
|
||||
{ Command::Search , qsl("search") },
|
||||
|
||||
{ Command::ChatPrevious , qsl("previous_chat") },
|
||||
{ Command::ChatNext , qsl("next_chat") },
|
||||
{ Command::ChatFirst , qsl("first_chat") },
|
||||
{ Command::ChatLast , qsl("last_chat") },
|
||||
{ Command::ChatSelf , qsl("self_chat") },
|
||||
{ Command::ChatPrevious , qsl("previous_chat") },
|
||||
{ Command::ChatNext , qsl("next_chat") },
|
||||
{ Command::ChatFirst , qsl("first_chat") },
|
||||
{ Command::ChatLast , qsl("last_chat") },
|
||||
{ Command::ChatSelf , qsl("self_chat") },
|
||||
|
||||
{ Command::FolderPrevious , qsl("previous_folder") },
|
||||
{ Command::FolderNext , qsl("next_folder") },
|
||||
{ Command::ShowAllChats , qsl("all_chats") },
|
||||
|
||||
{ Command::ShowFolder1 , qsl("folder1") },
|
||||
{ Command::ShowFolder2 , qsl("folder2") },
|
||||
{ Command::ShowFolder3 , qsl("folder3") },
|
||||
{ Command::ShowFolder4 , qsl("folder4") },
|
||||
{ Command::ShowFolder5 , qsl("folder5") },
|
||||
{ Command::ShowFolder6 , qsl("folder6") },
|
||||
{ Command::ShowFolderLast , qsl("last_folder") },
|
||||
|
||||
{ Command::ShowArchive , qsl("show_archive") },
|
||||
{ Command::ShowArchive , qsl("show_archive") },
|
||||
};
|
||||
|
||||
class Manager {
|
||||
|
||||
@@ -143,7 +143,9 @@ bool UiIntegration::handleUrlClick(
|
||||
Core::App().openInternalUrl(local, context);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
File::OpenUrl(url);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ extern "C" {
|
||||
#include <openssl/err.h>
|
||||
} // extern "C"
|
||||
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
#include <LzmaLib.h>
|
||||
#else // Q_OS_WIN
|
||||
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
#include <lzma.h>
|
||||
#endif // else of Q_OS_WIN
|
||||
#endif // else of Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
@@ -252,11 +252,11 @@ bool UnpackUpdate(const QString &filepath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
|
||||
#else // Q_OS_WIN
|
||||
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header
|
||||
#endif // Q_OS_WIN
|
||||
#endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
|
||||
QByteArray compressed = input.readAll();
|
||||
int32 compressedLen = compressed.size() - hSize;
|
||||
@@ -311,14 +311,14 @@ bool UnpackUpdate(const QString &filepath) {
|
||||
uncompressed.resize(uncompressedLen);
|
||||
|
||||
size_t resultLen = uncompressed.size();
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
#if defined Q_OS_WIN && !defined DESKTOP_APP_USE_PACKAGED // use Lzma SDK for win
|
||||
SizeT srcLen = compressedLen;
|
||||
int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE);
|
||||
if (uncompressRes != SZ_OK) {
|
||||
LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes));
|
||||
return false;
|
||||
}
|
||||
#else // Q_OS_WIN
|
||||
#else // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
lzma_stream stream = LZMA_STREAM_INIT;
|
||||
|
||||
lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED);
|
||||
@@ -361,7 +361,7 @@ bool UnpackUpdate(const QString &filepath) {
|
||||
LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res));
|
||||
return false;
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
#endif // Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||
|
||||
tempDir.mkdir(tempDir.absolutePath());
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
|
||||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||
constexpr auto AppName = "Telegram Desktop"_cs;
|
||||
constexpr auto AppFile = "Telegram"_cs;
|
||||
constexpr auto AppVersion = 2001000;
|
||||
constexpr auto AppVersionStr = "2.1";
|
||||
constexpr auto AppVersion = 2001007;
|
||||
constexpr auto AppVersionStr = "2.1.7";
|
||||
constexpr auto AppBetaVersion = false;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
||||
@@ -393,11 +393,11 @@ bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
||||
});
|
||||
}
|
||||
}
|
||||
filter = std::move(updated);
|
||||
if (pinnedChanged) {
|
||||
const auto filterList = _owner->chatsFilters().chatsList(id);
|
||||
filterList->pinned()->applyList(updated.pinned());
|
||||
filterList->pinned()->applyList(filter.pinned());
|
||||
}
|
||||
filter = std::move(updated);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_document_good_thumbnail.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/media_active_cache.h"
|
||||
@@ -296,6 +297,14 @@ QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = fals
|
||||
return FileNameForSave(caption, filter, prefix, name, forceSavingAs, dir);
|
||||
}
|
||||
|
||||
DocumentClickHandler::DocumentClickHandler(
|
||||
not_null<DocumentData*> document,
|
||||
FullMsgId context)
|
||||
: FileClickHandler(context)
|
||||
, _session(&document->session())
|
||||
, _document(document) {
|
||||
}
|
||||
|
||||
void DocumentOpenClickHandler::Open(
|
||||
Data::FileOrigin origin,
|
||||
not_null<DocumentData*> data,
|
||||
@@ -345,7 +354,9 @@ void DocumentOpenClickHandler::Open(
|
||||
}
|
||||
|
||||
void DocumentOpenClickHandler::onClickImpl() const {
|
||||
Open(context(), document(), getActionItem());
|
||||
if (valid()) {
|
||||
Open(context(), document(), getActionItem());
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentSaveClickHandler::Save(
|
||||
@@ -385,14 +396,20 @@ void DocumentSaveClickHandler::Save(
|
||||
}
|
||||
|
||||
void DocumentSaveClickHandler::onClickImpl() const {
|
||||
Save(context(), document());
|
||||
if (valid()) {
|
||||
Save(context(), document());
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentCancelClickHandler::onClickImpl() const {
|
||||
const auto data = document();
|
||||
if (!data->date) return;
|
||||
if (!valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->uploading()) {
|
||||
const auto data = document();
|
||||
if (!data->date) {
|
||||
return;
|
||||
} else if (data->uploading()) {
|
||||
if (const auto item = data->owner().message(context())) {
|
||||
App::main()->cancelUploadLayer(item);
|
||||
}
|
||||
@@ -423,7 +440,9 @@ void DocumentOpenWithClickHandler::Open(
|
||||
}
|
||||
|
||||
void DocumentOpenWithClickHandler::onClickImpl() const {
|
||||
Open(context(), document());
|
||||
if (valid()) {
|
||||
Open(context(), document());
|
||||
}
|
||||
}
|
||||
|
||||
Data::FileOrigin StickerData::setOrigin() const {
|
||||
|
||||
@@ -315,16 +315,19 @@ class DocumentClickHandler : public FileClickHandler {
|
||||
public:
|
||||
DocumentClickHandler(
|
||||
not_null<DocumentData*> document,
|
||||
FullMsgId context = FullMsgId())
|
||||
: FileClickHandler(context)
|
||||
, _document(document) {
|
||||
FullMsgId context = FullMsgId());
|
||||
|
||||
[[nodiscard]] bool valid() const {
|
||||
return !_session.empty();
|
||||
}
|
||||
not_null<DocumentData*> document() const {
|
||||
|
||||
[[nodiscard]] not_null<DocumentData*> document() const {
|
||||
return _document;
|
||||
}
|
||||
|
||||
private:
|
||||
not_null<DocumentData*> _document;
|
||||
const base::weak_ptr<Main::Session> _session;
|
||||
const not_null<DocumentData*> _document;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -66,23 +66,32 @@ void Histories::clearAll() {
|
||||
}
|
||||
|
||||
void Histories::readInbox(not_null<History*> history) {
|
||||
DEBUG_LOG(("Reading: readInbox called."));
|
||||
if (history->lastServerMessageKnown()) {
|
||||
const auto last = history->lastServerMessage();
|
||||
DEBUG_LOG(("Reading: last known, reading till %1."
|
||||
).arg(last ? last->id : 0));
|
||||
readInboxTill(history, last ? last->id : 0);
|
||||
return;
|
||||
} else if (history->loadedAtBottom()) {
|
||||
if (const auto lastId = history->maxMsgId()) {
|
||||
DEBUG_LOG(("Reading: loaded at bottom, maxMsgId %1."
|
||||
).arg(lastId));
|
||||
readInboxTill(history, lastId);
|
||||
return;
|
||||
} else if (history->loadedAtTop()) {
|
||||
DEBUG_LOG(("Reading: loaded at bottom, loaded at top."));
|
||||
readInboxTill(history, 0);
|
||||
return;
|
||||
}
|
||||
DEBUG_LOG(("Reading: loaded at bottom, but requesting entry."));
|
||||
}
|
||||
requestDialogEntry(history, [=] {
|
||||
Expects(history->lastServerMessageKnown());
|
||||
|
||||
const auto last = history->lastServerMessage();
|
||||
DEBUG_LOG(("Reading: got entry, reading till %1."
|
||||
).arg(last ? last->id : 0));
|
||||
readInboxTill(history, last ? last->id : 0);
|
||||
});
|
||||
}
|
||||
@@ -135,10 +144,20 @@ void Histories::readInboxTill(
|
||||
bool force) {
|
||||
Expects(IsServerMsgId(tillId) || (!tillId && !force));
|
||||
|
||||
DEBUG_LOG(("Reading: readInboxTill %1, force %2."
|
||||
).arg(tillId
|
||||
).arg(Logs::b(force)));
|
||||
|
||||
const auto syncGuard = gsl::finally([&] {
|
||||
DEBUG_LOG(("Reading: in guard, unread %1."
|
||||
).arg(history->unreadCount()));
|
||||
if (history->unreadCount() > 0) {
|
||||
if (const auto last = history->lastServerMessage()) {
|
||||
DEBUG_LOG(("Reading: checking last %1 and %2."
|
||||
).arg(last->id
|
||||
).arg(tillId));
|
||||
if (last->id == tillId) {
|
||||
DEBUG_LOG(("Reading: locally marked as read."));
|
||||
history->setUnreadCount(0);
|
||||
history->updateChatListEntry();
|
||||
}
|
||||
@@ -150,14 +169,21 @@ void Histories::readInboxTill(
|
||||
|
||||
const auto needsRequest = history->readInboxTillNeedsRequest(tillId);
|
||||
if (!needsRequest && !force) {
|
||||
DEBUG_LOG(("Reading: readInboxTill finish 1."));
|
||||
return;
|
||||
} else if (!history->trackUnreadMessages()) {
|
||||
DEBUG_LOG(("Reading: readInboxTill finish 2."));
|
||||
return;
|
||||
}
|
||||
const auto maybeState = lookup(history);
|
||||
if (maybeState && maybeState->sentReadTill >= tillId) {
|
||||
DEBUG_LOG(("Reading: readInboxTill finish 3 with %1."
|
||||
).arg(maybeState->sentReadTill));
|
||||
return;
|
||||
} else if (maybeState && maybeState->willReadTill >= tillId) {
|
||||
DEBUG_LOG(("Reading: readInboxTill finish 4 with %1 and force %2."
|
||||
).arg(maybeState->sentReadTill
|
||||
).arg(Logs::b(force)));
|
||||
if (force) {
|
||||
sendPendingReadInbox(history);
|
||||
}
|
||||
@@ -171,23 +197,35 @@ void Histories::readInboxTill(
|
||||
&& stillUnread
|
||||
&& history->unreadCountKnown()
|
||||
&& *stillUnread == history->unreadCount()) {
|
||||
DEBUG_LOG(("Reading: count didn't change so just update till %1"
|
||||
).arg(tillId));
|
||||
history->setInboxReadTill(tillId);
|
||||
return;
|
||||
}
|
||||
auto &state = maybeState ? *maybeState : _states[history];
|
||||
state.willReadTill = tillId;
|
||||
if (force || !stillUnread || !*stillUnread) {
|
||||
DEBUG_LOG(("Reading: will read till %1 with still unread %2"
|
||||
).arg(tillId
|
||||
).arg(stillUnread.value_or(-666)));
|
||||
state.willReadWhen = 0;
|
||||
sendReadRequests();
|
||||
if (!stillUnread) {
|
||||
return;
|
||||
}
|
||||
} else if (!state.willReadWhen) {
|
||||
DEBUG_LOG(("Reading: will read till %1 with postponed").arg(tillId));
|
||||
state.willReadWhen = crl::now() + kReadRequestTimeout;
|
||||
if (!_readRequestsTimer.isActive()) {
|
||||
_readRequestsTimer.callOnce(kReadRequestTimeout);
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG(("Reading: will read till %1 postponed already"
|
||||
).arg(tillId));
|
||||
}
|
||||
DEBUG_LOG(("Reading: marking now with till %1 and still %2"
|
||||
).arg(tillId
|
||||
).arg(*stillUnread));
|
||||
history->setInboxReadTill(tillId);
|
||||
history->setUnreadCount(*stillUnread);
|
||||
history->updateChatListEntry();
|
||||
@@ -399,6 +437,9 @@ void Histories::requestFakeChatListMessage(
|
||||
|
||||
void Histories::sendPendingReadInbox(not_null<History*> history) {
|
||||
if (const auto state = lookup(history)) {
|
||||
DEBUG_LOG(("Reading: send pending now with till %1 and when %2"
|
||||
).arg(state->willReadTill
|
||||
).arg(state->willReadWhen));
|
||||
if (state->willReadTill && state->willReadWhen) {
|
||||
state->willReadWhen = 0;
|
||||
sendReadRequests();
|
||||
@@ -407,6 +448,7 @@ void Histories::sendPendingReadInbox(not_null<History*> history) {
|
||||
}
|
||||
|
||||
void Histories::sendReadRequests() {
|
||||
DEBUG_LOG(("Reading: send requests with count %1.").arg(_states.size()));
|
||||
if (_states.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -414,10 +456,14 @@ void Histories::sendReadRequests() {
|
||||
auto next = std::optional<crl::time>();
|
||||
for (auto &[history, state] : _states) {
|
||||
if (!state.willReadTill) {
|
||||
DEBUG_LOG(("Reading: skipping zero till."));
|
||||
continue;
|
||||
} else if (state.willReadWhen <= now) {
|
||||
DEBUG_LOG(("Reading: sending with till %1."
|
||||
).arg(state.willReadTill));
|
||||
sendReadRequest(history, state);
|
||||
} else if (!next || *next > state.willReadWhen) {
|
||||
DEBUG_LOG(("Reading: scheduling for later send."));
|
||||
next = state.willReadWhen;
|
||||
}
|
||||
}
|
||||
@@ -434,7 +480,11 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
|
||||
const auto tillId = state.sentReadTill = base::take(state.willReadTill);
|
||||
state.willReadWhen = 0;
|
||||
state.sentReadDone = false;
|
||||
DEBUG_LOG(("Reading: sending request now with till %1."
|
||||
).arg(tillId));
|
||||
sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> finish) {
|
||||
DEBUG_LOG(("Reading: sending request invoked with till %1."
|
||||
).arg(tillId));
|
||||
const auto finished = [=] {
|
||||
const auto state = lookup(history);
|
||||
Assert(state != nullptr);
|
||||
|
||||
@@ -46,7 +46,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace Data {
|
||||
namespace {
|
||||
|
||||
Call ComputeCallData(const MTPDmessageActionPhoneCall &call) {
|
||||
constexpr auto kFastRevokeRestriction = 24 * 60 * TimeId(60);
|
||||
|
||||
[[nodiscard]] Call ComputeCallData(const MTPDmessageActionPhoneCall &call) {
|
||||
auto result = Call();
|
||||
result.finishReason = [&] {
|
||||
if (const auto reason = call.vreason()) {
|
||||
@@ -68,7 +70,7 @@ Call ComputeCallData(const MTPDmessageActionPhoneCall &call) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Invoice ComputeInvoiceData(
|
||||
[[nodiscard]] Invoice ComputeInvoiceData(
|
||||
not_null<HistoryItem*> item,
|
||||
const MTPDmessageMediaInvoice &data) {
|
||||
auto result = Invoice();
|
||||
@@ -84,7 +86,7 @@ Invoice ComputeInvoiceData(
|
||||
return result;
|
||||
}
|
||||
|
||||
QString WithCaptionDialogsText(
|
||||
[[nodiscard]] QString WithCaptionDialogsText(
|
||||
const QString &attachType,
|
||||
const QString &caption) {
|
||||
if (caption.isEmpty()) {
|
||||
@@ -102,7 +104,7 @@ QString WithCaptionDialogsText(
|
||||
TextUtilities::Clean(caption));
|
||||
}
|
||||
|
||||
QString WithCaptionNotificationText(
|
||||
[[nodiscard]] QString WithCaptionNotificationText(
|
||||
const QString &attachType,
|
||||
const QString &caption) {
|
||||
if (caption.isEmpty()) {
|
||||
@@ -220,7 +222,7 @@ bool Media::allowsEditMedia() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Media::allowsRevoke() const {
|
||||
bool Media::allowsRevoke(TimeId now) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1344,6 +1346,14 @@ int MediaDice::value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
bool MediaDice::allowsRevoke(TimeId now) const {
|
||||
const auto peer = parent()->history()->peer;
|
||||
if (peer->isSelf() || !peer->isUser()) {
|
||||
return true;
|
||||
}
|
||||
return (now >= parent()->date() + kFastRevokeRestriction);
|
||||
}
|
||||
|
||||
QString MediaDice::notificationText() const {
|
||||
return _emoji;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
virtual bool allowsEdit() const;
|
||||
virtual bool allowsEditCaption() const;
|
||||
virtual bool allowsEditMedia() const;
|
||||
virtual bool allowsRevoke() const;
|
||||
virtual bool allowsRevoke(TimeId now) const;
|
||||
virtual bool forwardedBecomesUnread() const;
|
||||
virtual QString errorTextForForward(not_null<PeerData*> peer) const;
|
||||
|
||||
@@ -414,6 +414,7 @@ public:
|
||||
[[nodiscard]] QString emoji() const;
|
||||
[[nodiscard]] int value() const;
|
||||
|
||||
bool allowsRevoke(TimeId now) const override;
|
||||
QString notificationText() const override;
|
||||
QString pinnedTextSubstring() const override;
|
||||
TextForMimeData clipboardText() const override;
|
||||
|
||||
@@ -770,7 +770,7 @@ int PeerData::slowmodeSecondsLeft() const {
|
||||
|
||||
bool PeerData::canSendPolls() const {
|
||||
if (const auto user = asUser()) {
|
||||
return user->isBot();
|
||||
return user->isBot() && !user->isSupport();
|
||||
} else if (const auto chat = asChat()) {
|
||||
return chat->canSendPolls();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
|
||||
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_file_origin.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/image/image_source.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "core/application.h"
|
||||
#include "facades.h"
|
||||
@@ -250,22 +251,42 @@ int PhotoData::height() const {
|
||||
return _large->height();
|
||||
}
|
||||
|
||||
PhotoClickHandler::PhotoClickHandler(
|
||||
not_null<PhotoData*> photo,
|
||||
FullMsgId context,
|
||||
PeerData *peer)
|
||||
: FileClickHandler(context)
|
||||
, _session(&photo->session())
|
||||
, _photo(photo)
|
||||
, _peer(peer) {
|
||||
}
|
||||
|
||||
void PhotoOpenClickHandler::onClickImpl() const {
|
||||
Core::App().showPhoto(this);
|
||||
if (valid()) {
|
||||
Core::App().showPhoto(this);
|
||||
}
|
||||
}
|
||||
|
||||
void PhotoSaveClickHandler::onClickImpl() const {
|
||||
auto data = photo();
|
||||
if (!data->date) return;
|
||||
|
||||
data->download(context());
|
||||
if (!valid()) {
|
||||
return;
|
||||
}
|
||||
const auto data = photo();
|
||||
if (!data->date) {
|
||||
return;
|
||||
} else {
|
||||
data->download(context());
|
||||
}
|
||||
}
|
||||
|
||||
void PhotoCancelClickHandler::onClickImpl() const {
|
||||
auto data = photo();
|
||||
if (!data->date) return;
|
||||
|
||||
if (data->uploading()) {
|
||||
if (!valid()) {
|
||||
return;
|
||||
}
|
||||
const auto data = photo();
|
||||
if (!data->date) {
|
||||
return;
|
||||
} else if (data->uploading()) {
|
||||
if (const auto item = data->owner().message(context())) {
|
||||
App::main()->cancelUploadLayer(item);
|
||||
}
|
||||
|
||||
@@ -108,21 +108,23 @@ public:
|
||||
PhotoClickHandler(
|
||||
not_null<PhotoData*> photo,
|
||||
FullMsgId context = FullMsgId(),
|
||||
PeerData *peer = nullptr)
|
||||
: FileClickHandler(context)
|
||||
, _photo(photo)
|
||||
, _peer(peer) {
|
||||
PeerData *peer = nullptr);
|
||||
|
||||
[[nodiscard]] bool valid() const {
|
||||
return !_session.empty();
|
||||
}
|
||||
not_null<PhotoData*> photo() const {
|
||||
|
||||
[[nodiscard]] not_null<PhotoData*> photo() const {
|
||||
return _photo;
|
||||
}
|
||||
PeerData *peer() const {
|
||||
[[nodiscard]] PeerData *peer() const {
|
||||
return _peer;
|
||||
}
|
||||
|
||||
private:
|
||||
not_null<PhotoData*> _photo;
|
||||
PeerData *_peer = nullptr;
|
||||
const base::weak_ptr<Main::Session> _session;
|
||||
const not_null<PhotoData*> _photo;
|
||||
PeerData * const _peer = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -147,14 +147,16 @@ bool PollData::applyResults(const MTPPollResults &results) {
|
||||
}) | ranges::to_vector;
|
||||
}
|
||||
}
|
||||
auto newSolution = TextWithEntities{
|
||||
results.vsolution().value_or_empty(),
|
||||
Api::EntitiesFromMTP(
|
||||
results.vsolution_entities().value_or_empty())
|
||||
};
|
||||
if (solution != newSolution) {
|
||||
solution = std::move(newSolution);
|
||||
changed = true;
|
||||
if (results.vsolution()) {
|
||||
auto newSolution = TextWithEntities{
|
||||
results.vsolution().value_or_empty(),
|
||||
Api::EntitiesFromMTP(
|
||||
results.vsolution_entities().value_or_empty())
|
||||
};
|
||||
if (solution != newSolution) {
|
||||
solution = std::move(newSolution);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (!changed) {
|
||||
return false;
|
||||
@@ -205,11 +207,9 @@ bool PollData::applyResultToAnswers(
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (!isMinResults || closed()) {
|
||||
if (answer->correct != voters.is_correct()) {
|
||||
answer->correct = voters.is_correct();
|
||||
changed = true;
|
||||
}
|
||||
if (voters.is_correct() && !answer->correct) {
|
||||
answer->correct = voters.is_correct();
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
});
|
||||
|
||||
@@ -414,6 +414,7 @@ HistoryItem *ScheduledMessages::append(
|
||||
}, data.vmedia());
|
||||
existing->updateReplyMarkup(data.vreply_markup());
|
||||
existing->updateForwardedInfo(data.vfwd_from());
|
||||
existing->updateDate(data.vdate().v);
|
||||
history->owner().requestItemTextRefresh(existing);
|
||||
}, [&](const auto &data) {});
|
||||
return existing;
|
||||
|
||||
@@ -3713,30 +3713,37 @@ MessageIdsList Session::takeMimeForwardIds() {
|
||||
return std::move(_mimeForwardIds);
|
||||
}
|
||||
|
||||
void Session::setProxyPromoted(PeerData *promoted) {
|
||||
if (_proxyPromoted != promoted) {
|
||||
if (const auto history = historyLoaded(_proxyPromoted)) {
|
||||
history->cacheProxyPromoted(false);
|
||||
void Session::setTopPromoted(
|
||||
PeerData *promoted,
|
||||
const QString &type,
|
||||
const QString &message) {
|
||||
const auto changed = (_topPromoted != promoted);
|
||||
const auto history = promoted ? this->history(promoted).get() : nullptr;
|
||||
if (changed
|
||||
|| (history && history->topPromotionMessage() != message)) {
|
||||
if (changed) {
|
||||
if (const auto history = historyLoaded(_topPromoted)) {
|
||||
history->cacheTopPromotion(false, QString(), QString());
|
||||
}
|
||||
}
|
||||
const auto old = std::exchange(_proxyPromoted, promoted);
|
||||
if (_proxyPromoted) {
|
||||
const auto history = this->history(_proxyPromoted);
|
||||
history->cacheProxyPromoted(true);
|
||||
const auto old = std::exchange(_topPromoted, promoted);
|
||||
if (history) {
|
||||
history->cacheTopPromotion(true, type, message);
|
||||
history->requestChatListMessage();
|
||||
Notify::peerUpdatedDelayed(
|
||||
_proxyPromoted,
|
||||
Notify::PeerUpdate::Flag::ChannelPromotedChanged);
|
||||
_topPromoted,
|
||||
Notify::PeerUpdate::Flag::TopPromotedChanged);
|
||||
}
|
||||
if (old) {
|
||||
if (changed && old) {
|
||||
Notify::peerUpdatedDelayed(
|
||||
old,
|
||||
Notify::PeerUpdate::Flag::ChannelPromotedChanged);
|
||||
Notify::PeerUpdate::Flag::TopPromotedChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PeerData *Session::proxyPromoted() const {
|
||||
return _proxyPromoted;
|
||||
PeerData *Session::topPromoted() const {
|
||||
return _topPromoted;
|
||||
}
|
||||
|
||||
bool Session::updateWallpapers(const MTPaccount_WallPapers &data) {
|
||||
|
||||
@@ -678,8 +678,11 @@ public:
|
||||
void setMimeForwardIds(MessageIdsList &&list);
|
||||
MessageIdsList takeMimeForwardIds();
|
||||
|
||||
void setProxyPromoted(PeerData *promoted);
|
||||
PeerData *proxyPromoted() const;
|
||||
void setTopPromoted(
|
||||
PeerData *promoted,
|
||||
const QString &type,
|
||||
const QString &message);
|
||||
PeerData *topPromoted() const;
|
||||
|
||||
bool updateWallpapers(const MTPaccount_WallPapers &data);
|
||||
void removeWallpaper(const WallPaper &paper);
|
||||
@@ -957,7 +960,7 @@ private:
|
||||
|
||||
base::flat_set<not_null<ViewElement*>> _heavyViewParts;
|
||||
|
||||
PeerData *_proxyPromoted = nullptr;
|
||||
PeerData *_topPromoted = nullptr;
|
||||
|
||||
NotifySettings _defaultUserNotifySettings;
|
||||
NotifySettings _defaultChatNotifySettings;
|
||||
|
||||
@@ -483,7 +483,7 @@ public:
|
||||
_context = context;
|
||||
}
|
||||
|
||||
FullMsgId context() const {
|
||||
[[nodiscard]] FullMsgId context() const {
|
||||
return _context;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,15 +86,20 @@ void Entry::cachePinnedIndex(FilterId filterId, int index) {
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::cacheProxyPromoted(bool promoted) {
|
||||
if (_isProxyPromoted != promoted) {
|
||||
_isProxyPromoted = promoted;
|
||||
updateChatListSortPosition();
|
||||
updateChatListEntry();
|
||||
if (!_isProxyPromoted) {
|
||||
updateChatListExistence();
|
||||
}
|
||||
void Entry::cacheTopPromoted(bool promoted) {
|
||||
if (_isTopPromoted == promoted) {
|
||||
return;
|
||||
}
|
||||
_isTopPromoted = promoted;
|
||||
updateChatListSortPosition();
|
||||
updateChatListEntry();
|
||||
if (!_isTopPromoted) {
|
||||
updateChatListExistence();
|
||||
}
|
||||
}
|
||||
|
||||
bool Entry::isTopPromoted() const {
|
||||
return _isTopPromoted;
|
||||
}
|
||||
|
||||
bool Entry::needUpdateInChatList() const {
|
||||
|
||||
@@ -120,10 +120,7 @@ public:
|
||||
return lookupPinnedIndex(filterId) != 0;
|
||||
}
|
||||
void cachePinnedIndex(FilterId filterId, int index);
|
||||
bool isProxyPromoted() const {
|
||||
return _isProxyPromoted;
|
||||
}
|
||||
void cacheProxyPromoted(bool promoted);
|
||||
[[nodiscard]] bool isTopPromoted() const;
|
||||
[[nodiscard]] uint64 sortKeyInChatList(FilterId filterId) const {
|
||||
return filterId
|
||||
? computeSortPosition(filterId)
|
||||
@@ -137,7 +134,7 @@ public:
|
||||
|
||||
virtual int fixedOnTopIndex() const = 0;
|
||||
static constexpr auto kArchiveFixOnTopIndex = 1;
|
||||
static constexpr auto kProxyPromotionFixOnTopIndex = 2;
|
||||
static constexpr auto kTopPromotionFixOnTopIndex = 2;
|
||||
|
||||
virtual bool shouldBeInChatList() const = 0;
|
||||
virtual int chatListUnreadCount() const = 0;
|
||||
@@ -194,6 +191,8 @@ protected:
|
||||
|
||||
[[nodiscard]] int lookupPinnedIndex(FilterId filterId) const;
|
||||
|
||||
void cacheTopPromoted(bool promoted);
|
||||
|
||||
private:
|
||||
virtual void changedChatListPinHook();
|
||||
void pinnedIndexChanged(int was, int now);
|
||||
@@ -211,8 +210,8 @@ private:
|
||||
uint64 _sortKeyInChatList = 0;
|
||||
uint64 _sortKeyByDate = 0;
|
||||
base::flat_map<FilterId, int> _pinnedIndex;
|
||||
bool _isProxyPromoted = false;
|
||||
TimeId _timeId = 0;
|
||||
bool _isTopPromoted = false;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1549,6 +1549,17 @@ void InnerWidget::repaintDialogRow(RowDescriptor row) {
|
||||
updateDialogRow(row);
|
||||
}
|
||||
|
||||
void InnerWidget::refreshDialogRow(RowDescriptor row) {
|
||||
if (row.fullId) {
|
||||
for (const auto &result : _searchResults) {
|
||||
if (result->item()->fullId() == row.fullId) {
|
||||
result->invalidateCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
repaintDialogRow(row);
|
||||
}
|
||||
|
||||
void InnerWidget::updateSearchResult(not_null<PeerData*> peer) {
|
||||
if (_state == WidgetState::Filtered) {
|
||||
if (!_peerSearchResults.empty()) {
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
void removeDialog(Key key);
|
||||
void repaintDialogRow(FilterId filterId, not_null<Row*> row);
|
||||
void repaintDialogRow(RowDescriptor row);
|
||||
void refreshDialogRow(RowDescriptor row);
|
||||
|
||||
void dragLeft();
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace {
|
||||
|
||||
// Show all dates that are in the last 20 hours in time format.
|
||||
constexpr int kRecentlyInSeconds = 20 * 3600;
|
||||
const auto kPsaBadgePrefix = "cloud_lng_badge_psa_";
|
||||
|
||||
bool ShowUserBotIcon(not_null<UserData*> user) {
|
||||
return user->isBot() && !user->isSupport();
|
||||
@@ -296,10 +297,19 @@ void paintRow(
|
||||
namewidth,
|
||||
st::msgNameFont->height);
|
||||
|
||||
const auto promoted = (history && history->useProxyPromotion())
|
||||
const auto promoted = (history && history->useTopPromotion())
|
||||
&& !(flags & (Flag::SearchResult/* | Flag::FeedSearchResult*/)); // #feed
|
||||
if (promoted) {
|
||||
const auto text = tr::lng_proxy_sponsor(tr::now);
|
||||
const auto type = history->topPromotionType();
|
||||
const auto custom = type.isEmpty()
|
||||
? QString()
|
||||
: Lang::Current().getNonDefaultValue(
|
||||
kPsaBadgePrefix + type.toUtf8());
|
||||
const auto text = type.isEmpty()
|
||||
? tr::lng_proxy_sponsor(tr::now)
|
||||
: custom.isEmpty()
|
||||
? tr::lng_badge_psa_default(tr::now)
|
||||
: custom;
|
||||
PaintRowTopRight(p, text, rectForName, active, selected);
|
||||
} else if (from/* && !(flags & Flag::FeedSearchResult)*/) { // #feed
|
||||
if (const auto chatTypeIcon = ChatTypeIcon(from, active, selected)) {
|
||||
@@ -315,7 +325,18 @@ void paintRow(
|
||||
auto texttop = st::dialogsPadding.y()
|
||||
+ st::msgNameFont->height
|
||||
+ st::dialogsSkip;
|
||||
if (draft
|
||||
if (promoted && !history->topPromotionMessage().isEmpty()) {
|
||||
auto availableWidth = namewidth;
|
||||
p.setFont(st::dialogsTextFont);
|
||||
if (history->cloudDraftTextCache.isEmpty()) {
|
||||
history->cloudDraftTextCache.setText(
|
||||
st::dialogsTextStyle,
|
||||
history->topPromotionMessage(),
|
||||
Ui::DialogTextOptions());
|
||||
}
|
||||
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg));
|
||||
history->cloudDraftTextCache.drawElided(p, nameleft, texttop, availableWidth, 1);
|
||||
} else if (draft
|
||||
|| (supportMode
|
||||
&& Auth().supportHelper().isOccupiedBySomeone(history))) {
|
||||
if (!promoted) {
|
||||
|
||||
@@ -49,7 +49,7 @@ int PinnedList::addPinnedGetPosition(const Key &key) {
|
||||
}
|
||||
|
||||
void PinnedList::setPinned(const Key &key, bool pinned) {
|
||||
Expects(key.entry()->folderKnown());
|
||||
Expects(key.entry()->folderKnown() || _filterId != 0);
|
||||
|
||||
if (pinned) {
|
||||
const int position = addPinnedGetPosition(key);
|
||||
@@ -100,7 +100,8 @@ void PinnedList::applyList(
|
||||
void PinnedList::applyList(const std::vector<not_null<History*>> &list) {
|
||||
Expects(_filterId != 0);
|
||||
|
||||
clear();
|
||||
const auto old = base::take(_data);
|
||||
|
||||
const auto count = int(list.size());
|
||||
_data.reserve(count);
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
@@ -108,6 +109,13 @@ void PinnedList::applyList(const std::vector<not_null<History*>> &list) {
|
||||
_data.emplace_back(history);
|
||||
history->cachePinnedIndex(_filterId, i + 1);
|
||||
}
|
||||
|
||||
for (const auto &key : old) {
|
||||
const auto history = key.history();
|
||||
if (!history || !ranges::contains(_data, history, &Key::history)) {
|
||||
key.entry()->cachePinnedIndex(_filterId, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PinnedList::reorder(const Key &key1, const Key &key2) {
|
||||
|
||||
@@ -121,6 +121,11 @@ public:
|
||||
return _item;
|
||||
}
|
||||
|
||||
void invalidateCache() {
|
||||
_cacheFor = nullptr;
|
||||
_cache = Ui::Text::String();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Layout::RowPainter;
|
||||
|
||||
|
||||
@@ -549,6 +549,10 @@ void Widget::repaintDialogRow(RowDescriptor row) {
|
||||
_inner->repaintDialogRow(row);
|
||||
}
|
||||
|
||||
void Widget::refreshDialogRow(RowDescriptor row) {
|
||||
_inner->refreshDialogRow(row);
|
||||
}
|
||||
|
||||
void Widget::jumpToTop() {
|
||||
if (session().supportMode()) {
|
||||
return;
|
||||
@@ -674,7 +678,6 @@ void Widget::animationCallback() {
|
||||
|
||||
updateControlsVisibility(true);
|
||||
|
||||
applyFilterUpdate();
|
||||
if (!_filter->hasFocus()) {
|
||||
if (App::wnd()) App::wnd()->setInnerFocus();
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
void removeDialog(Key key);
|
||||
void repaintDialogRow(FilterId filterId, not_null<Row*> row);
|
||||
void repaintDialogRow(RowDescriptor row);
|
||||
void refreshDialogRow(RowDescriptor row);
|
||||
|
||||
void jumpToTop();
|
||||
|
||||
|
||||
@@ -381,7 +381,9 @@ struct Data {
|
||||
bool VoiceMsgPlaybackDoubled = false;
|
||||
bool SoundNotify = true;
|
||||
bool DesktopNotify = true;
|
||||
bool FlashBounceNotify = true;
|
||||
bool RestoreSoundNotifyFromTray = false;
|
||||
bool RestoreFlashBounceNotifyFromTray = false;
|
||||
DBINotifyView NotifyView = dbinvShowPreview;
|
||||
bool NativeNotifications = false;
|
||||
int NotificationsCount = 3;
|
||||
@@ -508,7 +510,9 @@ DefineRefVar(Global, base::Observable<void>, DownloadPathChanged);
|
||||
DefineVar(Global, bool, VoiceMsgPlaybackDoubled);
|
||||
DefineVar(Global, bool, SoundNotify);
|
||||
DefineVar(Global, bool, DesktopNotify);
|
||||
DefineVar(Global, bool, FlashBounceNotify);
|
||||
DefineVar(Global, bool, RestoreSoundNotifyFromTray);
|
||||
DefineVar(Global, bool, RestoreFlashBounceNotifyFromTray);
|
||||
DefineVar(Global, DBINotifyView, NotifyView);
|
||||
DefineVar(Global, bool, NativeNotifications);
|
||||
DefineVar(Global, int, NotificationsCount);
|
||||
|
||||
@@ -210,7 +210,9 @@ DeclareRefVar(base::Observable<void>, DownloadPathChanged);
|
||||
DeclareVar(bool, VoiceMsgPlaybackDoubled);
|
||||
DeclareVar(bool, SoundNotify);
|
||||
DeclareVar(bool, DesktopNotify);
|
||||
DeclareVar(bool, FlashBounceNotify);
|
||||
DeclareVar(bool, RestoreSoundNotifyFromTray);
|
||||
DeclareVar(bool, RestoreFlashBounceNotifyFromTray);
|
||||
DeclareVar(DBINotifyView, NotifyView);
|
||||
DeclareVar(bool, NativeNotifications);
|
||||
DeclareVar(int, NotificationsCount);
|
||||
|
||||
@@ -478,7 +478,7 @@ void InnerWidget::updateEmptyText() {
|
||||
options.flags |= TextParseMarkdown;
|
||||
auto hasSearch = !_searchQuery.isEmpty();
|
||||
auto hasFilter = (_filter.flags != 0) || !_filter.allUsers;
|
||||
auto text = Ui::Text::Bold((hasSearch || hasFilter)
|
||||
auto text = Ui::Text::Semibold((hasSearch || hasFilter)
|
||||
? tr::lng_admin_log_no_results_title(tr::now)
|
||||
: tr::lng_admin_log_no_events_title(tr::now));
|
||||
auto description = hasSearch
|
||||
@@ -488,7 +488,9 @@ void InnerWidget::updateEmptyText() {
|
||||
TextUtilities::Clean(_searchQuery))
|
||||
: hasFilter
|
||||
? tr::lng_admin_log_no_results_text(tr::now)
|
||||
: tr::lng_admin_log_no_events_text(tr::now);
|
||||
: _channel->isMegagroup()
|
||||
? tr::lng_admin_log_no_events_text(tr::now)
|
||||
: tr::lng_admin_log_no_events_text_channel(tr::now);
|
||||
text.text.append(qstr("\n\n") + description);
|
||||
_emptyText.setMarkedText(st::defaultTextStyle, text, options);
|
||||
}
|
||||
@@ -582,6 +584,11 @@ void InnerWidget::elementShowPollResults(
|
||||
FullMsgId context) {
|
||||
}
|
||||
|
||||
void InnerWidget::elementShowTooltip(
|
||||
const TextWithEntities &text,
|
||||
Fn<void()> hiddenCallback) {
|
||||
}
|
||||
|
||||
void InnerWidget::saveState(not_null<SectionMemento*> memento) {
|
||||
memento->setFilter(std::move(_filter));
|
||||
memento->setAdmins(std::move(_admins));
|
||||
|
||||
@@ -104,6 +104,9 @@ public:
|
||||
void elementShowPollResults(
|
||||
not_null<PollData*> poll,
|
||||
FullMsgId context) override;
|
||||
void elementShowTooltip(
|
||||
const TextWithEntities &text,
|
||||
Fn<void()> hiddenCallback) override;
|
||||
|
||||
~InnerWidget();
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ MTPMessage PrepareLogMessage(
|
||||
| MTPDmessage::Flag::f_reply_to_msg_id
|
||||
| MTPDmessage::Flag::f_edit_date
|
||||
| MTPDmessage::Flag::f_grouped_id
|
||||
| MTPDmessage::Flag::f_views
|
||||
//| MTPDmessage::Flag::f_reactions
|
||||
| MTPDmessage::Flag::f_restriction_reason;
|
||||
const auto flags = message.vflags().v & ~removeFlags;
|
||||
|
||||
@@ -1622,6 +1622,9 @@ bool History::readInboxTillNeedsRequest(MsgId tillId) {
|
||||
if (unreadMark()) {
|
||||
owner().histories().changeDialogUnreadMark(this, false);
|
||||
}
|
||||
DEBUG_LOG(("Reading: readInboxTillNeedsRequest is_server %1, before %2."
|
||||
).arg(Logs::b(IsServerMsgId(tillId))
|
||||
).arg(_inboxReadBefore.value_or(-666)));
|
||||
return IsServerMsgId(tillId) && (_inboxReadBefore.value_or(1) <= tillId);
|
||||
}
|
||||
|
||||
@@ -1639,10 +1642,17 @@ bool History::unreadCountRefreshNeeded(MsgId readTillId) const {
|
||||
|
||||
std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
|
||||
if (isEmpty() || !folderKnown()) {
|
||||
DEBUG_LOG(("Reading: countStillUnreadLocal unknown %1 and %2."
|
||||
).arg(Logs::b(isEmpty())
|
||||
).arg(Logs::b(folderKnown())));
|
||||
return std::nullopt;
|
||||
}
|
||||
if (_inboxReadBefore) {
|
||||
const auto before = *_inboxReadBefore;
|
||||
DEBUG_LOG(("Reading: check before %1 with min %2 and max %3."
|
||||
).arg(before
|
||||
).arg(minMsgId()
|
||||
).arg(maxMsgId()));
|
||||
if (minMsgId() <= before && maxMsgId() >= readTillId) {
|
||||
auto result = 0;
|
||||
for (const auto &block : blocks) {
|
||||
@@ -1658,12 +1668,19 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_LOG(("Reading: check before result %1 with existing %2"
|
||||
).arg(result
|
||||
).arg(_unreadCount.value_or(-666)));
|
||||
if (_unreadCount) {
|
||||
return std::max(*_unreadCount - result, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto minimalServerId = minMsgId();
|
||||
DEBUG_LOG(("Reading: check at end loaded from %1 loaded %2 - %3"
|
||||
).arg(minimalServerId
|
||||
).arg(Logs::b(loadedAtBottom())
|
||||
).arg(Logs::b(loadedAtTop())));
|
||||
if (!loadedAtBottom()
|
||||
|| (!loadedAtTop() && !minimalServerId)
|
||||
|| minimalServerId > readTillId) {
|
||||
@@ -1682,6 +1699,7 @@ std::optional<int> History::countStillUnreadLocal(MsgId readTillId) const {
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_LOG(("Reading: check at end counted %1").arg(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1965,6 +1983,9 @@ void History::setFolderPointer(Data::Folder *folder) {
|
||||
if (folder) {
|
||||
folder->registerOne(this);
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::FolderChanged);
|
||||
}
|
||||
|
||||
void History::applyPinnedUpdate(const MTPDupdateDialogPinned &data) {
|
||||
@@ -2580,17 +2601,19 @@ void History::updateChatListExistence() {
|
||||
//}
|
||||
}
|
||||
|
||||
bool History::useProxyPromotion() const {
|
||||
if (!isProxyPromoted()) {
|
||||
bool History::useTopPromotion() const {
|
||||
if (!isTopPromoted()) {
|
||||
return false;
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
return !isPinnedDialog(FilterId()) && !channel->amIn();
|
||||
} else if (const auto user = peer->asUser()) {
|
||||
return !isPinnedDialog(FilterId()) && user->isBot() && isEmpty();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int History::fixedOnTopIndex() const {
|
||||
return useProxyPromotion() ? kProxyPromotionFixOnTopIndex : 0;
|
||||
return useTopPromotion() ? kTopPromotionFixOnTopIndex : 0;
|
||||
}
|
||||
|
||||
bool History::trackUnreadMessages() const {
|
||||
@@ -2607,7 +2630,7 @@ bool History::shouldBeInChatList() const {
|
||||
return true;
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
if (!channel->amIn()) {
|
||||
return isProxyPromoted();
|
||||
return isTopPromoted();
|
||||
//} else if (const auto feed = channel->feed()) { // #feed
|
||||
// return !feed->needUpdateInChatList();
|
||||
}
|
||||
@@ -2615,6 +2638,10 @@ bool History::shouldBeInChatList() const {
|
||||
return chat->amIn()
|
||||
|| !lastMessageKnown()
|
||||
|| (lastMessage() != nullptr);
|
||||
} else if (const auto user = peer->asUser()) {
|
||||
if (user->isBot() && isTopPromoted()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return !lastMessageKnown()
|
||||
|| (lastMessage() != nullptr);
|
||||
@@ -2718,6 +2745,41 @@ void History::dialogEntryApplied() {
|
||||
}
|
||||
}
|
||||
|
||||
void History::cacheTopPromotion(
|
||||
bool promoted,
|
||||
const QString &type,
|
||||
const QString &message) {
|
||||
const auto changed = (isTopPromoted() != promoted);
|
||||
cacheTopPromoted(promoted);
|
||||
if (topPromotionType() != type || _topPromotedMessage != message) {
|
||||
_topPromotedType = type;
|
||||
_topPromotedMessage = message;
|
||||
cloudDraftTextCache.clear();
|
||||
} else if (changed) {
|
||||
cloudDraftTextCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
QStringRef History::topPromotionType() const {
|
||||
return topPromotionAboutShown()
|
||||
? _topPromotedType.midRef(5)
|
||||
: _topPromotedType.midRef(0);
|
||||
}
|
||||
|
||||
bool History::topPromotionAboutShown() const {
|
||||
return _topPromotedType.startsWith("seen^");
|
||||
}
|
||||
|
||||
void History::markTopPromotionAboutShown() {
|
||||
if (!topPromotionAboutShown()) {
|
||||
_topPromotedType = "seen^" + _topPromotedType;
|
||||
}
|
||||
}
|
||||
|
||||
QString History::topPromotionMessage() const {
|
||||
return _topPromotedMessage;
|
||||
}
|
||||
|
||||
bool History::clearUnreadOnClientSide() const {
|
||||
if (!session().supportMode()) {
|
||||
return false;
|
||||
|
||||
@@ -237,6 +237,15 @@ public:
|
||||
MsgId maxOutboxRead);
|
||||
void dialogEntryApplied();
|
||||
|
||||
void cacheTopPromotion(
|
||||
bool promoted,
|
||||
const QString &type,
|
||||
const QString &message);
|
||||
[[nodiscard]] QStringRef topPromotionType() const;
|
||||
[[nodiscard]] QString topPromotionMessage() const;
|
||||
[[nodiscard]] bool topPromotionAboutShown() const;
|
||||
void markTopPromotionAboutShown();
|
||||
|
||||
MsgId minMsgId() const;
|
||||
MsgId maxMsgId() const;
|
||||
MsgId msgIdForRead() const;
|
||||
@@ -330,7 +339,7 @@ public:
|
||||
void setForwardDraft(MessageIdsList &&items);
|
||||
|
||||
History *migrateSibling() const;
|
||||
bool useProxyPromotion() const;
|
||||
[[nodiscard]] bool useTopPromotion() const;
|
||||
int fixedOnTopIndex() const override;
|
||||
void updateChatListExistence() override;
|
||||
bool shouldBeInChatList() const override;
|
||||
@@ -559,6 +568,9 @@ private:
|
||||
TimeId _lastSentDraftTime = 0;
|
||||
MessageIdsList _forwardDraft;
|
||||
|
||||
QString _topPromotedMessage;
|
||||
QString _topPromotedType;
|
||||
|
||||
base::flat_map<not_null<UserData*>, crl::time> _typing;
|
||||
base::flat_map<not_null<UserData*>, SendAction> _sendActions;
|
||||
QString _sendActionString;
|
||||
|
||||
@@ -12,7 +12,7 @@ using "ui/widgets/widgets.style";
|
||||
minPhotoSize: 100px;
|
||||
minVideoSize: 160px;
|
||||
maxMediaSize: 430px;
|
||||
maxStickerSize: 256px;
|
||||
maxStickerSize: 228px;
|
||||
maxGifSize: 320px;
|
||||
maxVideoMessageSize: 240px;
|
||||
maxSignatureSize: 144px;
|
||||
@@ -379,6 +379,21 @@ botKbTinyButton: BotKeyboardButton {
|
||||
botKbScroll: defaultSolidScroll;
|
||||
|
||||
historyDateFadeDuration: 200;
|
||||
historyDiceToast: Toast(defaultToast) {
|
||||
minWidth: msgMinWidth;
|
||||
maxWidth: 640px;
|
||||
durationFadeOut: 200;
|
||||
}
|
||||
historyErrorToast: Toast(defaultToast) {
|
||||
minWidth: msgMinWidth;
|
||||
}
|
||||
historyInfoToast: Toast(defaultToast) {
|
||||
minWidth: msgMinWidth;
|
||||
maxWidth: 380px;
|
||||
padding: margins(54px, 13px, 19px, 12px);
|
||||
icon: icon {{ "toast_info", toastFg }};
|
||||
iconPosition: point(13px, 13px);
|
||||
}
|
||||
|
||||
historyPhotoLeft: 14px;
|
||||
historyPhotoBubbleMinWidth: 200px;
|
||||
@@ -394,6 +409,15 @@ historyBubbleTailOutRightSelected: icon {{ "bubble_tail-flip_horizontal", msgOut
|
||||
|
||||
historyPeerUserpicFont: semiboldFont;
|
||||
|
||||
historyPsaIconIn: icon {{ "message_psa_tooltip", msgFileThumbLinkInFg }};
|
||||
historyPsaIconInSelected: icon {{ "message_psa_tooltip", msgFileThumbLinkInFgSelected }};
|
||||
historyPsaIconOut: icon {{ "message_psa_tooltip", msgFileThumbLinkOutFg }};
|
||||
historyPsaIconOutSelected: icon {{ "message_psa_tooltip", msgFileThumbLinkOutFgSelected }};
|
||||
historyPsaIconSkip1: 23px;
|
||||
historyPsaIconSkip2: 23px;
|
||||
historyPsaIconPosition1: point(-5px, 0px);
|
||||
historyPsaIconPosition2: point(-5px, 0px);
|
||||
|
||||
historyStatusFg: windowSubTextFg;
|
||||
historyStatusFgActive: windowActiveTextFg;
|
||||
historyStatusFgTyping: historyStatusFgActive;
|
||||
@@ -506,15 +530,13 @@ historyGroupSkip: 4px;
|
||||
historyGroupRadialSize: 44px;
|
||||
historyGroupRadialLine: 3px;
|
||||
|
||||
historyAboutProxy: FlatLabel(defaultFlatLabel) {
|
||||
align: align(top);
|
||||
textFg: windowSubTextFg;
|
||||
}
|
||||
historyAboutProxyPadding: margins(20px, 10px, 20px, 10px);
|
||||
|
||||
historyMapPoint: icon {{ "map_point", mapPointDrop }};
|
||||
historyMapPointInner: icon {{ "map_point_inner", mapPointDot }};
|
||||
|
||||
historyPsaForwardPalette: TextPalette(defaultTextPalette) {
|
||||
linkFg: boxTextFgGood;
|
||||
}
|
||||
|
||||
webPageLeft: 10px;
|
||||
webPageBar: 2px;
|
||||
webPageTitleFont: semiboldFont;
|
||||
|
||||