Updated TDesktop sources to 2.4.7
This commit is contained in:
commit
e5123d56df
390 changed files with 13355 additions and 7386 deletions
21
.github/stale.yml
vendored
Normal file
21
.github/stale.yml
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 180
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 30
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels: []
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: |
|
||||
Hey there!
|
||||
|
||||
This issue was inactive for a long time and will be automatically closed in 30 days if there isn't any further activity. We therefore assume that the user has lost interest or resolved the problem on their own.
|
||||
|
||||
Don't worry though; if this is an error, let us know with a comment and we'll be happy to reopen the issue.
|
||||
|
||||
Thanks!
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
# Process only issues
|
||||
only: issues
|
||||
25
.github/workflows/docker.yml
vendored
Normal file
25
.github/workflows/docker.yml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
name: Docker.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/docker.yml'
|
||||
- 'Telegram/build/docker/centos_env/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/docker.yml'
|
||||
- 'Telegram/build/docker/centos_env/**'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
name: Ubuntu
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Docker image build.
|
||||
run: docker build -t telegram_desktop Telegram/build/docker/centos_env
|
||||
4
.github/workflows/issue_closer.yml
vendored
4
.github/workflows/issue_closer.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
run: |
|
||||
tag=$(git ls-remote --tags git://github.com/$GITHUB_REPOSITORY | cut -f 2 | tail -n1)
|
||||
echo $tag
|
||||
echo ::set-env name=LATEST_TAG::$tag
|
||||
echo "LATEST_TAG=$tag" >> $GITHUB_ENV
|
||||
|
||||
- name: Get the latest macOS version.
|
||||
shell: python
|
||||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
ver = itemlist[0].attributes['sparkle:shortVersionString'].value;
|
||||
print(ver);
|
||||
|
||||
subprocess.check_call("echo ::set-env name=%s::%s" % ("LATEST_MACOS", ver), shell=True);
|
||||
open(os.environ['GITHUB_ENV'], "a").write("LATEST_MACOS=" + ver);
|
||||
|
||||
- name: Check a version from an issue.
|
||||
uses: actions/github-script@0.4.0
|
||||
|
|
|
|||
31
.github/workflows/linux.yml
vendored
31
.github/workflows/linux.yml
vendored
|
|
@ -78,7 +78,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
run: echo ::set-env name=REPO_NAME::${GITHUB_REPOSITORY##*/}
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Disable man for further package installs.
|
||||
run: |
|
||||
|
|
@ -136,11 +136,11 @@ jobs:
|
|||
echo `md5sum $thisFile | cut -c -32` >> CACHE_KEY.txt
|
||||
fi
|
||||
md5cache=$(md5sum CACHE_KEY.txt | cut -c -32)
|
||||
echo ::set-env name=CACHE_KEY::$md5cache
|
||||
echo "CACHE_KEY=$md5cache" >> $GITHUB_ENV
|
||||
|
||||
mkdir -p Libraries
|
||||
cd Libraries
|
||||
echo ::set-env name=LibrariesPath::`pwd`
|
||||
echo "LibrariesPath=`pwd`" >> $GITHUB_ENV
|
||||
|
||||
- name: Patches.
|
||||
run: |
|
||||
|
|
@ -164,6 +164,22 @@ jobs:
|
|||
|
||||
cmake --version
|
||||
|
||||
- name: MozJPEG.
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone -b v4.0.1-rc2 $GIT/mozilla/mozjpeg.git
|
||||
cd mozjpeg
|
||||
cmake -B build . \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DWITH_JPEG8=ON \
|
||||
-DPNG_SUPPORTED=OFF
|
||||
cmake --build build -j$(nproc)
|
||||
sudo cmake --install build
|
||||
cd ..
|
||||
rm -rf mozjpeg
|
||||
|
||||
- name: Opus cache.
|
||||
id: cache-opus
|
||||
uses: actions/cache@v2
|
||||
|
|
@ -189,7 +205,7 @@ jobs:
|
|||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone $GIT/01org/libva.git
|
||||
git clone $GIT/intel/libva.git
|
||||
cd libva
|
||||
./autogen.sh --enable-static
|
||||
make -j$(nproc)
|
||||
|
|
@ -446,7 +462,6 @@ jobs:
|
|||
-confirm-license \
|
||||
-qt-zlib \
|
||||
-qt-libpng \
|
||||
-qt-libjpeg \
|
||||
-qt-harfbuzz \
|
||||
-qt-pcre \
|
||||
-qt-xcb \
|
||||
|
|
@ -538,7 +553,7 @@ jobs:
|
|||
cmake -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DTG_OWT_SPECIAL_TARGET=linux \
|
||||
-DTG_OWT_LIBJPEG_INCLUDE_PATH=`pwd`/../../../qt_$QT/qtbase/src/3rdparty/libjpeg \
|
||||
-DTG_OWT_LIBJPEG_INCLUDE_PATH=/usr/local/include \
|
||||
-DTG_OWT_OPENSSL_INCLUDE_PATH=$OPENSSL_PREFIX/include \
|
||||
-DTG_OWT_OPUS_INCLUDE_PATH=/usr/local/include/opus \
|
||||
-DTG_OWT_FFMPEG_INCLUDE_PATH=/usr/local/include \
|
||||
|
|
@ -563,9 +578,9 @@ jobs:
|
|||
if [ -n "${{ matrix.defines }}" ]; then
|
||||
DEFINE="-D ${{ matrix.defines }}=ON"
|
||||
echo Define from matrix: $DEFINE
|
||||
echo ::set-env name=ARTIFACT_NAME::Kotatogram_${{ matrix.defines }}
|
||||
echo "ARTIFACT_NAME=Kotatogram_${{ matrix.defines }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo ::set-env name=ARTIFACT_NAME::Kotatogram
|
||||
echo "ARTIFACT_NAME=Kotatogram" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
./configure.sh \
|
||||
|
|
|
|||
42
.github/workflows/mac.yml
vendored
42
.github/workflows/mac.yml
vendored
|
|
@ -76,7 +76,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
run: echo ::set-env name=REPO_NAME::${GITHUB_REPOSITORY##*/}
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v2
|
||||
|
|
@ -101,13 +101,13 @@ jobs:
|
|||
thisFile=$REPO_NAME/.github/workflows/mac.yml
|
||||
echo `md5 -q $thisFile` >> CACHE_KEY.txt
|
||||
fi
|
||||
echo ::set-env name=CACHE_KEY::`md5 -q CACHE_KEY.txt`
|
||||
echo "CACHE_KEY=`md5 -q CACHE_KEY.txt`" >> $GITHUB_ENV
|
||||
|
||||
echo ::add-path::$PWD/Libraries/depot_tools
|
||||
echo "$PWD/Libraries/depot_tools" >> $GITHUB_PATH
|
||||
|
||||
mkdir -p Libraries/macos
|
||||
cd Libraries/macos
|
||||
echo ::set-env name=LibrariesPath::`pwd`
|
||||
echo "LibrariesPath=`pwd`" >> $GITHUB_ENV
|
||||
|
||||
- name: Patches.
|
||||
run: |
|
||||
|
|
@ -139,6 +139,20 @@ jobs:
|
|||
make -j$(nproc)
|
||||
sudo make install
|
||||
|
||||
- name: MozJPEG.
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone -b v4.0.1-rc2 $GIT/mozilla/mozjpeg.git
|
||||
cd mozjpeg
|
||||
cmake -B build . \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/local/macos \
|
||||
-DWITH_JPEG8=ON \
|
||||
-DPNG_SUPPORTED=OFF
|
||||
cmake --build build -j$(nproc)
|
||||
sudo cmake --install build
|
||||
|
||||
- name: OpenSSL cache.
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v2
|
||||
|
|
@ -176,17 +190,14 @@ jobs:
|
|||
with:
|
||||
path: ${{ env.LibrariesPath }}/opus-cache
|
||||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
- name: Opus clone.
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone -b v1.3 --depth=1 $GIT/xiph/opus
|
||||
- name: Opus build.
|
||||
- name: Opus.
|
||||
if: steps.cache-opus.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone $GIT/xiph/opus
|
||||
cd opus
|
||||
git checkout v1.3
|
||||
./autogen.sh
|
||||
CFLAGS="$MIN_MAC $UNGUARDED" CPPFLAGS="$MIN_MAC $UNGUARDED" LDFLAGS="$MIN_MAC" ./configure --prefix=$PREFIX
|
||||
make -j$(nproc)
|
||||
|
|
@ -453,7 +464,10 @@ jobs:
|
|||
-securetransport \
|
||||
-nomake examples \
|
||||
-nomake tests \
|
||||
-platform macx-clang
|
||||
-platform macx-clang \
|
||||
-I "/usr/local/macos/include" \
|
||||
LIBJPEG_LIBS="/usr/local/macos/lib/libjpeg.a" \
|
||||
ZLIB_LIBS="/usr/local/macos/lib/libz.a"
|
||||
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
|
|
@ -477,7 +491,7 @@ jobs:
|
|||
cd tg_owt/out/Debug
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DTG_OWT_SPECIAL_TARGET=mac \
|
||||
-DTG_OWT_LIBJPEG_INCLUDE_PATH=`pwd`/../../../qt_$QT/qtbase/src/3rdparty/libjpeg \
|
||||
-DTG_OWT_LIBJPEG_INCLUDE_PATH=/usr/local/macos/include \
|
||||
-DTG_OWT_OPENSSL_INCLUDE_PATH=`pwd`/../../../openssl_$OPENSSL_VER/include \
|
||||
-DTG_OWT_OPUS_INCLUDE_PATH=$PREFIX/include/opus \
|
||||
-DTG_OWT_FFMPEG_INCLUDE_PATH=/usr/local/include \
|
||||
|
|
@ -500,9 +514,9 @@ jobs:
|
|||
if [ -n "${{ matrix.defines }}" ]; then
|
||||
DEFINE="-D ${{ matrix.defines }}=ON"
|
||||
echo Define from matrix: $DEFINE
|
||||
echo ::set-env name=ARTIFACT_NAME::Kotatogram_${{ matrix.defines }}
|
||||
echo "ARTIFACT_NAME=Kotatogram_${{ matrix.defines }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo ::set-env name=ARTIFACT_NAME::Kotatogram
|
||||
echo "ARTIFACT_NAME=Kotatogram" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
./configure.sh \
|
||||
|
|
|
|||
2
.github/workflows/snap.yml
vendored
2
.github/workflows/snap.yml
vendored
|
|
@ -83,7 +83,7 @@ jobs:
|
|||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
artifact_name=$(echo kotatogram-desktop_*.snap)
|
||||
echo ::set-env name=ARTIFACT_NAME::$artifact_name
|
||||
echo "ARTIFACT_NAME=$artifact_name" >> $GITHUB_ENV
|
||||
|
||||
mkdir artifact
|
||||
mv $artifact_name artifact
|
||||
|
|
|
|||
154
.github/workflows/user_agent_updater.yml
vendored
Normal file
154
.github/workflows/user_agent_updater.yml
vendored
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
name: User-agent updater.
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: ["Restart user_agent_updater workflow."]
|
||||
schedule:
|
||||
# At 00:00 on day-of-month 1.
|
||||
- cron: '0 0 1 * *'
|
||||
pull_request_target:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
User-agent:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
codeFile: "Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp"
|
||||
headBranchPrefix: "chrome_"
|
||||
baseBranch: "dev"
|
||||
isPull: "0"
|
||||
|
||||
steps:
|
||||
- name: Set env.
|
||||
if: startsWith(github.event_name, 'pull_request')
|
||||
run: |
|
||||
echo "isPull=1" >> $GITHUB_ENV
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up git.
|
||||
run: |
|
||||
token=${{ secrets.TOKEN_FOR_MASTER_UPDATER }}
|
||||
if [ -z "${token}" ]; then
|
||||
echo "Token is unset. Nothing to do."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
url=https://x-access-token:$token@github.com/$GITHUB_REPOSITORY
|
||||
|
||||
git config --global user.email "action@github.com"
|
||||
git config --global user.name "GitHub Action"
|
||||
|
||||
git remote set-url origin $url
|
||||
|
||||
- name: Delete branch.
|
||||
if: |
|
||||
env.isPull == '1'
|
||||
&& github.event.action == 'closed'
|
||||
&& startsWith(github.head_ref, env.headBranchPrefix)
|
||||
run: |
|
||||
git push origin --delete ${{ github.head_ref }}
|
||||
|
||||
- name: Write a new version of Google Chrome to the user-agent for DNS.
|
||||
if: env.isPull == '0'
|
||||
shell: python
|
||||
run: |
|
||||
import subprocess, os, re;
|
||||
|
||||
regExpVersion = "[0-9]+.[0-9]+.[0-9]+.[0-9]+";
|
||||
chrome = "Chrome/";
|
||||
|
||||
def newVersion():
|
||||
output = subprocess.check_output(["google-chrome", "--version"]);
|
||||
version = re.search(regExpVersion, output);
|
||||
if not version:
|
||||
print("Can't find a Chrome version.");
|
||||
exit();
|
||||
return version.group(0);
|
||||
|
||||
newChromeVersion = newVersion();
|
||||
print(newChromeVersion);
|
||||
|
||||
def setEnv(value):
|
||||
open(os.environ['GITHUB_ENV'], "a").write(value);
|
||||
|
||||
def writeUserAgent():
|
||||
p = os.environ['codeFile'];
|
||||
w = open(p, "r");
|
||||
content = w.read();
|
||||
w.close();
|
||||
|
||||
regExpChrome = chrome + regExpVersion;
|
||||
|
||||
version = re.search(regExpChrome, content);
|
||||
if not version:
|
||||
print("Can't find an user-agent in the code.");
|
||||
exit();
|
||||
content = re.sub(regExpChrome, chrome + newChromeVersion, content);
|
||||
|
||||
w = open(p, "w");
|
||||
w.write(content);
|
||||
|
||||
setEnv("ChromeVersion=" + newChromeVersion);
|
||||
|
||||
writeUserAgent();
|
||||
|
||||
- name: Push to a new branch.
|
||||
if: env.isPull == '0' && env.ChromeVersion != ''
|
||||
run: |
|
||||
git diff > git_diff.txt
|
||||
if [[ ! -s git_diff.txt ]]; then
|
||||
echo "Nothing to commit."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git checkout -b $headBranchPrefix$ChromeVersion
|
||||
git add $codeFile
|
||||
git commit -m "Update User-Agent for DNS to Chrome $ChromeVersion."
|
||||
|
||||
git push origin $headBranchPrefix$ChromeVersion
|
||||
echo "Done!"
|
||||
|
||||
- name: Close previous pull requests.
|
||||
if: env.isPull == '0' && env.ChromeVersion != ''
|
||||
uses: actions/github-script@0.4.0
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const common = {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
};
|
||||
|
||||
github.pulls.list(common).then(response => {
|
||||
response.data.forEach((item, _) => {
|
||||
if (item.head.ref.startsWith(process.env.headBranchPrefix)) {
|
||||
console.log(`Close ${item.title} #${item.number}.`);
|
||||
github.pulls.update({
|
||||
pull_number: item.number,
|
||||
state: "closed",
|
||||
...common
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
- name: Create a new pull request.
|
||||
if: env.isPull == '0' && env.ChromeVersion != ''
|
||||
uses: actions/github-script@0.4.0
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const version = process.env.ChromeVersion;
|
||||
const title = `Update User-Agent for DNS to Chrome ${version}.`;
|
||||
|
||||
github.pulls.create({
|
||||
title: title,
|
||||
body: "",
|
||||
head: `${process.env.headBranchPrefix}${version}`,
|
||||
base: process.env.baseBranch,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
});
|
||||
125
.github/workflows/win.yml
vendored
125
.github/workflows/win.yml
vendored
|
|
@ -75,10 +75,31 @@ jobs:
|
|||
DOC_PATH: "docs/building-msvc.md"
|
||||
AUTO_CACHING: "1"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
shell: bash
|
||||
run: echo ::set-env name=REPO_NAME::${GITHUB_REPOSITORY##*/}
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up environment paths.
|
||||
shell: bash
|
||||
run: |
|
||||
echo "C:\\Strawberry\\perl\\bin\\" >> $GITHUB_PATH
|
||||
echo "C:\\Program Files\\NASM\\" >> $GITHUB_PATH
|
||||
echo "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Auxiliary\\Build\\" >> $GITHUB_PATH
|
||||
|
||||
mkdir Libraries && cd Libraries
|
||||
echo "Convert unix path to win path."
|
||||
p=`pwd | sed 's#^/[d]#d:#g' |sed 's#/#\\\\#g'`
|
||||
echo "LibrariesPath=$p" >> $GITHUB_ENV
|
||||
|
||||
- name: Save msbuild version.
|
||||
run: |
|
||||
call vcvars32.bat
|
||||
msbuild -version > CACHE_KEY.txt
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v2
|
||||
|
|
@ -86,38 +107,18 @@ jobs:
|
|||
submodules: recursive
|
||||
path: ${{ env.REPO_NAME }}
|
||||
|
||||
- name: Set up environment variables.
|
||||
shell: cmd
|
||||
run: |
|
||||
echo ::add-path::C:\Strawberry\perl\bin\
|
||||
echo ::add-path::"%programfiles%\NASM"
|
||||
|
||||
C:
|
||||
cd "%programfiles(x86)%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\"
|
||||
echo ::add-path::%cd%
|
||||
|
||||
call vcvars32.bat
|
||||
D:
|
||||
cd %GITHUB_WORKSPACE%
|
||||
msbuild -version > CACHE_KEY.txt
|
||||
echo %MANUAL_CACHING% >> CACHE_KEY.txt
|
||||
|
||||
mkdir Libraries
|
||||
cd Libraries
|
||||
echo ::set-env name=LibrariesPath::%cd%
|
||||
|
||||
- name: Generate cache key.
|
||||
shell: bash
|
||||
run: |
|
||||
echo $MANUAL_CACHING >> CACHE_KEY.txt
|
||||
if [ "$AUTO_CACHING" == "1" ]; then
|
||||
thisFile=$REPO_NAME/.github/workflows/win.yml
|
||||
echo `md5sum $thisFile | awk '{ print $1 }'` >> CACHE_KEY.txt
|
||||
fi
|
||||
echo ::set-env name=CACHE_KEY::`md5sum CACHE_KEY.txt | awk '{ print $1 }'`
|
||||
echo "CACHE_KEY=`md5sum CACHE_KEY.txt | awk '{ print $1 }'`" >> $GITHUB_ENV
|
||||
|
||||
- name: Choco installs.
|
||||
run: |
|
||||
choco install --no-progress -y nasm yasm jom ninja
|
||||
run: choco install --no-progress -y nasm yasm jom ninja
|
||||
|
||||
- name: Patches.
|
||||
shell: bash
|
||||
|
|
@ -130,21 +131,18 @@ jobs:
|
|||
eval $checkoutCommit
|
||||
|
||||
- name: Find any version of Python 2.
|
||||
shell: cmd
|
||||
shell: bash
|
||||
run: |
|
||||
echo Find any version of Python 2.
|
||||
for /D %%a in (C:\hostedtoolcache\windows\Python\2.*) do (
|
||||
SET PY2=%%a\x64
|
||||
)
|
||||
if [%PY2%] == [] (
|
||||
echo Python 2 is not found.
|
||||
echo "Find any version of Python 2."
|
||||
p=`ls /c/hostedtoolcache/windows/python | grep 2 | tail -1`
|
||||
if [ -z "$p" ]; then
|
||||
echo "Python 2 is not found."
|
||||
exit 1
|
||||
)
|
||||
echo Found %PY2%.
|
||||
echo ::set-env name=PY2::%PY2%
|
||||
fi
|
||||
echo "PY2=C:\\hostedtoolcache\\windows\\Python\\$p\\x64" >> $GITHUB_ENV
|
||||
echo "Found $p."
|
||||
|
||||
- name: LZMA.
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
|
||||
|
|
@ -161,7 +159,6 @@ jobs:
|
|||
key: ${{ runner.OS }}-${{ env.CACHE_KEY }}-${{ env.OPENSSL_VER }}
|
||||
- name: OpenSSL.
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
|
||||
|
|
@ -187,7 +184,6 @@ jobs:
|
|||
rmdir /S /Q .git
|
||||
|
||||
- name: Zlib.
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
|
||||
|
|
@ -197,6 +193,20 @@ jobs:
|
|||
cd contrib\vstudio\vc14
|
||||
msbuild -m zlibstat.vcxproj /property:Configuration=Debug
|
||||
|
||||
- name: MozJPEG.
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
|
||||
git clone -b v4.0.1-rc2 %GIT%/mozilla/mozjpeg.git
|
||||
cd mozjpeg
|
||||
cmake . ^
|
||||
-G "Visual Studio 16 2019" ^
|
||||
-A Win32 ^
|
||||
-DWITH_JPEG8=ON ^
|
||||
-DPNG_SUPPORTED=OFF
|
||||
cmake --build . --config Debug
|
||||
|
||||
- name: OpenAL Soft cache.
|
||||
id: cache-openal
|
||||
uses: actions/cache@v2
|
||||
|
|
@ -204,7 +214,6 @@ jobs:
|
|||
path: ${{ env.LibrariesPath }}/openal-soft
|
||||
key: ${{ runner.OS }}-openal-soft-${{ env.CACHE_KEY }}
|
||||
- name: OpenAL Soft.
|
||||
shell: cmd
|
||||
if: steps.cache-openal.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
%VC%
|
||||
|
|
@ -232,7 +241,6 @@ jobs:
|
|||
env:
|
||||
GYP_MSVS_OVERRIDE_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\'
|
||||
GYP_MSVS_VERSION: 2019
|
||||
shell: cmd
|
||||
if: steps.cache-breakpad.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd %LibrariesPath%
|
||||
|
|
@ -269,7 +277,6 @@ jobs:
|
|||
key: ${{ runner.OS }}-opus-${{ env.CACHE_KEY }}
|
||||
- name: Opus.
|
||||
if: steps.cache-opus.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
|
||||
|
|
@ -288,7 +295,6 @@ jobs:
|
|||
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}-2-${{ hashFiles('**/build_ffmpeg_win.sh') }}
|
||||
- name: FFmpeg.
|
||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
choco install --no-progress -y msys2
|
||||
|
|
@ -310,7 +316,6 @@ jobs:
|
|||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}
|
||||
- name: Configure Qt 5.12.8.
|
||||
if: steps.cache-qt.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
|
||||
|
|
@ -342,10 +347,12 @@ jobs:
|
|||
-mp ^
|
||||
-nomake examples ^
|
||||
-nomake tests ^
|
||||
-platform win32-msvc
|
||||
-platform win32-msvc ^
|
||||
-I "%LibrariesPath%\mozjpeg" ^
|
||||
LIBJPEG_LIBS_DEBUG="%LibrariesPath%\mozjpeg\Debug\jpeg-static.lib" ^
|
||||
LIBJPEG_LIBS_RELEASE="%LibrariesPath%\mozjpeg\Release\jpeg-static.lib"
|
||||
- name: Qt 5.12.8 build.
|
||||
if: steps.cache-qt.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
cd qt_%QT%
|
||||
|
|
@ -364,32 +371,16 @@ jobs:
|
|||
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}
|
||||
- name: WebRTC.
|
||||
if: steps.cache-webrtc.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
%VC%
|
||||
|
||||
:: Qt libjpeg.
|
||||
mkdir qt_%QT%
|
||||
cd qt_%QT%
|
||||
git clone -b %QT_VER% https://github.com/qt/qtbase
|
||||
|
||||
move qtbase\src\3rdparty\libjpeg ..
|
||||
cd ..
|
||||
dir
|
||||
rmdir /S /Q qt_%QT%
|
||||
mkdir qt_%QT%\qtbase\src\3rdparty\
|
||||
move libjpeg qt_%QT%\qtbase\src\3rdparty\
|
||||
|
||||
:: WebRTC.
|
||||
cd %LibrariesPath%
|
||||
|
||||
git clone %GIT%/desktop-app/tg_owt.git
|
||||
mkdir tg_owt\out\Debug
|
||||
cd tg_owt\out\Debug
|
||||
cmake -G Ninja ^
|
||||
-DCMAKE_BUILD_TYPE=Debug ^
|
||||
-DTG_OWT_SPECIAL_TARGET=win ^
|
||||
-DTG_OWT_LIBJPEG_INCLUDE_PATH=%cd%/../../../qt_%QT%/qtbase/src/3rdparty/libjpeg ^
|
||||
-DTG_OWT_LIBJPEG_INCLUDE_PATH=%cd%/../../../mozjpeg ^
|
||||
-DTG_OWT_OPENSSL_INCLUDE_PATH=%cd%/../../../openssl_%OPENSSL_VER%/include ^
|
||||
-DTG_OWT_OPUS_INCLUDE_PATH=%cd%/../../../opus/include ^
|
||||
-DTG_OWT_FFMPEG_INCLUDE_PATH=%cd%/../../../ffmpeg ^
|
||||
|
|
@ -404,9 +395,6 @@ jobs:
|
|||
mkdir out\Debug
|
||||
move tg_owt.lib out\Debug\tg_owt.lib
|
||||
|
||||
cd %LibrariesPath%
|
||||
rmdir /S /Q qt_%QT%
|
||||
|
||||
- name: Read defines.
|
||||
shell: bash
|
||||
run: |
|
||||
|
|
@ -414,16 +402,14 @@ jobs:
|
|||
if [ -n "${{ matrix.defines }}" ]; then
|
||||
DEFINE="-D ${{ matrix.defines }}=ON"
|
||||
echo Define from matrix: $DEFINE
|
||||
echo ::set-env name=ARTIFACT_NAME::Kotatogram_${{ matrix.defines }}
|
||||
echo "ARTIFACT_NAME=Kotatogram_${{ matrix.defines }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo ::set-env name=ARTIFACT_NAME::Kotatogram
|
||||
echo "ARTIFACT_NAME=Kotatogram" >> $GITHUB_ENV
|
||||
fi
|
||||
echo "::set-env name=TDESKTOP_BUILD_DEFINE::$DEFINE"
|
||||
echo "TDESKTOP_BUILD_DEFINE=$DEFINE" >> $GITHUB_ENV
|
||||
|
||||
- name: Kotatogram Desktop build.
|
||||
if: env.ONLY_CACHE == 'false'
|
||||
shell: cmd
|
||||
timeout-minutes: 120
|
||||
run: |
|
||||
cd %REPO_NAME%\Telegram
|
||||
|
||||
|
|
@ -441,7 +427,6 @@ jobs:
|
|||
|
||||
- name: Move artifact.
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
cd %REPO_NAME%\out\Debug
|
||||
mkdir artifact
|
||||
|
|
|
|||
6
.gitmodules
vendored
6
.gitmodules
vendored
|
|
@ -82,12 +82,6 @@
|
|||
[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
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@ add_subdirectory(lib_qr)
|
|||
add_subdirectory(lib_webrtc)
|
||||
add_subdirectory(codegen)
|
||||
|
||||
include(lib_ui/cmake/generate_styles.cmake)
|
||||
include(cmake/generate_numbers.cmake)
|
||||
|
||||
get_filename_component(src_loc SourceFiles REALPATH)
|
||||
get_filename_component(res_loc Resources REALPATH)
|
||||
|
||||
|
|
@ -37,36 +34,6 @@ include(cmake/td_lang.cmake)
|
|||
include(cmake/td_scheme.cmake)
|
||||
include(cmake/td_ui.cmake)
|
||||
|
||||
set(style_files
|
||||
boxes/boxes.style
|
||||
calls/calls.style
|
||||
chat_helpers/chat_helpers.style
|
||||
dialogs/dialogs.style
|
||||
export/view/export.style
|
||||
history/history.style
|
||||
info/info.style
|
||||
intro/intro.style
|
||||
media/view/media_view.style
|
||||
media/player/media_player.style
|
||||
overview/overview.style
|
||||
passport/passport.style
|
||||
profile/profile.style
|
||||
settings/settings.style
|
||||
ui/filter_icons.style
|
||||
window/window.style
|
||||
)
|
||||
|
||||
set(dependent_style_files
|
||||
${submodules_loc}/lib_ui/ui/colors.palette
|
||||
${submodules_loc}/lib_ui/ui/basic.style
|
||||
${submodules_loc}/lib_ui/ui/layers/layers.style
|
||||
${submodules_loc}/lib_ui/ui/widgets/widgets.style
|
||||
${src_loc}/ui/td_common.style
|
||||
)
|
||||
|
||||
generate_styles(Telegram ${src_loc} "${style_files}" "${dependent_style_files}")
|
||||
generate_numbers(Telegram ${res_loc}/numbers.txt)
|
||||
|
||||
set_target_properties(Telegram PROPERTIES AUTOMOC ON AUTORCC ON)
|
||||
|
||||
target_link_libraries(Telegram
|
||||
|
|
@ -106,17 +73,12 @@ if (LINUX)
|
|||
desktop-app::external_materialdecoration
|
||||
desktop-app::external_nimf_qt5
|
||||
desktop-app::external_qt5ct_support
|
||||
desktop-app::external_xcb_screensaver
|
||||
desktop-app::external_xcb
|
||||
desktop-app::external_glib
|
||||
)
|
||||
|
||||
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
|
||||
|
|
@ -137,35 +99,6 @@ if (LINUX)
|
|||
)
|
||||
endif()
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(XCB_SCREENSAVER REQUIRED IMPORTED_TARGET xcb-screensaver)
|
||||
pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb)
|
||||
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
PkgConfig::XCB_SCREENSAVER
|
||||
PkgConfig::XCB
|
||||
)
|
||||
else()
|
||||
target_link_static_libraries(Telegram PRIVATE xcb-screensaver)
|
||||
target_link_libraries(Telegram PRIVATE xcb)
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GLIB2 REQUIRED IMPORTED_TARGET glib-2.0)
|
||||
pkg_check_modules(GOBJECT REQUIRED IMPORTED_TARGET gobject-2.0)
|
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
PkgConfig::GLIB2
|
||||
PkgConfig::GOBJECT
|
||||
PkgConfig::GIO
|
||||
)
|
||||
|
||||
target_compile_definitions(Telegram PRIVATE G_LOG_DOMAIN="Kotatogram")
|
||||
|
||||
if (NOT TDESKTOP_DISABLE_GTK_INTEGRATION)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
|
|
@ -191,6 +124,8 @@ nice_target_sources(Telegram ${src_loc}
|
|||
PRIVATE
|
||||
${style_files}
|
||||
|
||||
api/api_attached_stickers.cpp
|
||||
api/api_attached_stickers.h
|
||||
api/api_authorizations.cpp
|
||||
api/api_authorizations.h
|
||||
api/api_bot.cpp
|
||||
|
|
@ -394,8 +329,6 @@ PRIVATE
|
|||
core/launcher.h
|
||||
core/local_url_handlers.cpp
|
||||
core/local_url_handlers.h
|
||||
core/mime_type.cpp
|
||||
core/mime_type.h
|
||||
core/sandbox.cpp
|
||||
core/sandbox.h
|
||||
core/shortcuts.cpp
|
||||
|
|
@ -573,6 +506,8 @@ PRIVATE
|
|||
history/view/media/history_view_photo.cpp
|
||||
history/view/media/history_view_poll.h
|
||||
history/view/media/history_view_poll.cpp
|
||||
history/view/media/history_view_slot_machine.h
|
||||
history/view/media/history_view_slot_machine.cpp
|
||||
history/view/media/history_view_sticker.h
|
||||
history/view/media/history_view_sticker.cpp
|
||||
history/view/media/history_view_theme_document.h
|
||||
|
|
@ -594,6 +529,12 @@ PRIVATE
|
|||
history/view/history_view_message.cpp
|
||||
history/view/history_view_message.h
|
||||
history/view/history_view_object.h
|
||||
history/view/history_view_pinned_bar.cpp
|
||||
history/view/history_view_pinned_bar.h
|
||||
history/view/history_view_pinned_section.cpp
|
||||
history/view/history_view_pinned_section.h
|
||||
history/view/history_view_pinned_tracker.cpp
|
||||
history/view/history_view_pinned_tracker.h
|
||||
history/view/history_view_replies_section.cpp
|
||||
history/view/history_view_replies_section.h
|
||||
history/view/history_view_schedule_box.cpp
|
||||
|
|
@ -768,14 +709,6 @@ PRIVATE
|
|||
media/audio/media_child_ffmpeg_loader.h
|
||||
media/audio/media_openal_functions.cpp
|
||||
media/audio/media_openal_functions.h
|
||||
media/clip/media_clip_check_streaming.cpp
|
||||
media/clip/media_clip_check_streaming.h
|
||||
media/clip/media_clip_ffmpeg.cpp
|
||||
media/clip/media_clip_ffmpeg.h
|
||||
media/clip/media_clip_implementation.cpp
|
||||
media/clip/media_clip_implementation.h
|
||||
media/clip/media_clip_reader.cpp
|
||||
media/clip/media_clip_reader.h
|
||||
media/player/media_player_button.cpp
|
||||
media/player/media_player_button.h
|
||||
media/player/media_player_float.cpp
|
||||
|
|
@ -1067,8 +1000,8 @@ PRIVATE
|
|||
ui/filter_icons.h
|
||||
ui/filter_icon_panel.cpp
|
||||
ui/filter_icon_panel.h
|
||||
ui/grouped_layout.cpp
|
||||
ui/grouped_layout.h
|
||||
ui/item_text_options.cpp
|
||||
ui/item_text_options.h
|
||||
ui/resize_area.h
|
||||
ui/search_field_controller.cpp
|
||||
ui/search_field_controller.h
|
||||
|
|
@ -1076,8 +1009,6 @@ PRIVATE
|
|||
ui/special_buttons.h
|
||||
ui/special_fields.cpp
|
||||
ui/special_fields.h
|
||||
ui/text_options.cpp
|
||||
ui/text_options.h
|
||||
ui/unread_badge.cpp
|
||||
ui/unread_badge.h
|
||||
window/main_window.cpp
|
||||
|
|
@ -1305,6 +1236,7 @@ target_compile_definitions(Telegram
|
|||
PRIVATE
|
||||
TDESKTOP_API_ID=${TDESKTOP_API_ID}
|
||||
TDESKTOP_API_HASH=${TDESKTOP_API_HASH}
|
||||
G_LOG_DOMAIN="Kotatogram"
|
||||
)
|
||||
|
||||
if (APPLE OR NOT CMAKE_EXECUTABLE_SUFFIX STREQUAL "" OR NOT "${output_name}" STREQUAL "Kotatogram")
|
||||
|
|
|
|||
BIN
Telegram/Resources/art/bball_idle.tgs
Normal file
BIN
Telegram/Resources/art/bball_idle.tgs
Normal file
Binary file not shown.
BIN
Telegram/Resources/art/fball_idle.tgs
Normal file
BIN
Telegram/Resources/art/fball_idle.tgs
Normal file
Binary file not shown.
BIN
Telegram/Resources/art/slot_0_idle.tgs
Normal file
BIN
Telegram/Resources/art/slot_0_idle.tgs
Normal file
Binary file not shown.
BIN
Telegram/Resources/art/slot_1_idle.tgs
Normal file
BIN
Telegram/Resources/art/slot_1_idle.tgs
Normal file
Binary file not shown.
BIN
Telegram/Resources/art/slot_2_idle.tgs
Normal file
BIN
Telegram/Resources/art/slot_2_idle.tgs
Normal file
Binary file not shown.
BIN
Telegram/Resources/art/slot_back.tgs
Normal file
BIN
Telegram/Resources/art/slot_back.tgs
Normal file
Binary file not shown.
BIN
Telegram/Resources/art/slot_pull.tgs
Normal file
BIN
Telegram/Resources/art/slot_pull.tgs
Normal file
Binary file not shown.
BIN
Telegram/Resources/icons/history_pin.png
Normal file
BIN
Telegram/Resources/icons/history_pin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 438 B |
BIN
Telegram/Resources/icons/history_pin@2x.png
Normal file
BIN
Telegram/Resources/icons/history_pin@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 720 B |
BIN
Telegram/Resources/icons/history_pin@3x.png
Normal file
BIN
Telegram/Resources/icons/history_pin@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1 KiB |
BIN
Telegram/Resources/icons/pinned_show_all.png
Normal file
BIN
Telegram/Resources/icons/pinned_show_all.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 642 B |
BIN
Telegram/Resources/icons/pinned_show_all@2x.png
Normal file
BIN
Telegram/Resources/icons/pinned_show_all@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Telegram/Resources/icons/pinned_show_all@3x.png
Normal file
BIN
Telegram/Resources/icons/pinned_show_all@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -161,13 +161,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_deleted" = "Deleted Account";
|
||||
"lng_deleted_message" = "Deleted message";
|
||||
"lng_pinned_message" = "Pinned message";
|
||||
"lng_pinned_previous" = "Previous message";
|
||||
"lng_pinned_poll" = "Pinned poll";
|
||||
"lng_pinned_quiz" = "Pinned quiz";
|
||||
"lng_pinned_unpin_sure" = "Would you like to unpin this message?";
|
||||
"lng_pinned_pin_sure" = "Would you like to pin this message?";
|
||||
"lng_pinned_pin_sure_group" = "Do you want to pin this message for all members in the group?";
|
||||
"lng_pinned_pin_old_sure" = "Do you want to pin an older message while leaving a more recent one pinned?";
|
||||
"lng_pinned_pin" = "Pin";
|
||||
"lng_pinned_unpin" = "Unpin";
|
||||
"lng_pinned_notify" = "Notify all members";
|
||||
"lng_pinned_also_for_other" = "Also pin for {user}";
|
||||
"lng_pinned_messages_title#one" = "{count} pinned message";
|
||||
"lng_pinned_messages_title#other" = "{count} pinned messages";
|
||||
"lng_pinned_hide_all" = "Don't show pinned messages";
|
||||
"lng_pinned_unpin_all#one" = "Unpin {count} message";
|
||||
"lng_pinned_unpin_all#other" = "Unpin all {count} messages";
|
||||
"lng_pinned_unpin_all_sure" = "Do you want to unpin all messages?";
|
||||
"lng_pinned_hide_all_sure" = "Do you want to hide the pinned messages bar? It will stay hidden until a new message is pinned.";
|
||||
"lng_pinned_hide_all_hide" = "Hide";
|
||||
|
||||
"lng_edit_media_album_error" = "This file cannot be saved as a part of an album.";
|
||||
"lng_edit_media_invalid_file" = "Sorry, no way to use this file.";
|
||||
|
|
@ -1103,6 +1115,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_action_secure_proof_of_address" = "proof of address";
|
||||
"lng_action_secure_phone" = "phone number";
|
||||
"lng_action_secure_email" = "email address";
|
||||
"lng_action_proximity_reached" = "{from} is now within {distance} from {user}";
|
||||
"lng_action_proximity_reached_you" = "{from} is now within {distance} from you";
|
||||
"lng_action_you_proximity_reached" = "You are now within {distance} from {user}";
|
||||
"lng_action_proximity_distance_m#one" = "{count} meter";
|
||||
"lng_action_proximity_distance_m#other" = "{count} metres";
|
||||
"lng_action_proximity_distance_km#one" = "{count} km";
|
||||
"lng_action_proximity_distance_km#other" = "{count} km";
|
||||
|
||||
"lng_ttl_photo_received" = "{from} sent you a self-destructing photo. Please view it on your mobile.";
|
||||
"lng_ttl_photo_sent" = "You sent a self-destructing photo.";
|
||||
|
|
@ -1524,9 +1543,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_send_files_selected#other" = "{count} files selected";
|
||||
"lng_send_files#one" = "Send {count} file";
|
||||
"lng_send_files#other" = "Send {count} files";
|
||||
"lng_send_album" = "Send as an album";
|
||||
"lng_send_photo" = "Send as a photo";
|
||||
"lng_send_file" = "Send as a file";
|
||||
"lng_send_grouped" = "Group items";
|
||||
"lng_send_compressed" = "Compress images";
|
||||
"lng_send_media_invalid_files" = "Sorry, no valid files found.";
|
||||
|
||||
"lng_forward_choose" = "Choose recipient...";
|
||||
|
|
@ -2272,6 +2290,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_language_not_ready_link" = "translations platform";
|
||||
|
||||
"lng_launch_exe_warning" = "This file has a {extension} extension.\nAre you sure you want to run it?";
|
||||
"lng_launch_svg_warning" = "Opening this file can potentially expose your IP address to its sender. Continue?";
|
||||
"lng_launch_exe_sure" = "Run";
|
||||
"lng_launch_exe_dont_ask" = "Don't ask me again";
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,13 @@
|
|||
<file alias="art/sunrise.jpg">../../art/sunrise.jpg</file>
|
||||
<file alias="art/dice_idle.tgs">../../art/dice_idle.tgs</file>
|
||||
<file alias="art/dart_idle.tgs">../../art/dart_idle.tgs</file>
|
||||
<file alias="art/bball_idle.tgs">../../art/bball_idle.tgs</file>
|
||||
<file alias="art/fball_idle.tgs">../../art/fball_idle.tgs</file>
|
||||
<file alias="art/slot_0_idle.tgs">../../art/slot_0_idle.tgs</file>
|
||||
<file alias="art/slot_1_idle.tgs">../../art/slot_1_idle.tgs</file>
|
||||
<file alias="art/slot_2_idle.tgs">../../art/slot_2_idle.tgs</file>
|
||||
<file alias="art/slot_back.tgs">../../art/slot_back.tgs</file>
|
||||
<file alias="art/slot_pull.tgs">../../art/slot_pull.tgs</file>
|
||||
<file alias="day-blue.tdesktop-theme">../../day-blue.tdesktop-theme</file>
|
||||
<file alias="night.tdesktop-theme">../../night.tdesktop-theme</file>
|
||||
<file alias="night-green.tdesktop-theme">../../night-green.tdesktop-theme</file>
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = In
|
|||
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
|
||||
inputMediaInvoice#f4e096c3 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:string = InputMedia;
|
||||
inputMediaGeoLive#ce4e82fd flags:# stopped:flags.0?true geo_point:InputGeoPoint period:flags.1?int = InputMedia;
|
||||
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
|
||||
inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> solution:flags.1?string solution_entities:flags.1?Vector<MessageEntity> = InputMedia;
|
||||
inputMediaDice#e66fbf7b emoticon:string = InputMedia;
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?Inp
|
|||
inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto;
|
||||
|
||||
inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
|
||||
inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint;
|
||||
inputGeoPoint#48222faf flags:# lat:double long:double accuracy_radius:flags.0?int = InputGeoPoint;
|
||||
|
||||
inputPhotoEmpty#1cd7bf0d = InputPhoto;
|
||||
inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
|
||||
|
|
@ -141,7 +141,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
|
|||
chatPhoto#d20b9f3c flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
|
||||
|
||||
messageEmpty#83e5de54 id:int = Message;
|
||||
message#58ae39c9 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> = Message;
|
||||
message#58ae39c9 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> = Message;
|
||||
messageService#286fa604 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction = Message;
|
||||
|
||||
messageMediaEmpty#3ded6320 = MessageMedia;
|
||||
|
|
@ -154,7 +154,7 @@ messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia;
|
|||
messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
|
||||
messageMediaGame#fdb19008 game:Game = MessageMedia;
|
||||
messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
|
||||
messageMediaGeoLive#7c3c2609 geo:GeoPoint period:int = MessageMedia;
|
||||
messageMediaGeoLive#b940c666 flags:# geo:GeoPoint heading:flags.0?int period:int proximity_notification_radius:flags.1?int = MessageMedia;
|
||||
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
|
||||
messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia;
|
||||
|
||||
|
|
@ -181,6 +181,7 @@ messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
|||
messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:SecureCredentialsEncrypted = MessageAction;
|
||||
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
|
||||
messageActionContactSignUp#f3f25f76 = MessageAction;
|
||||
messageActionGeoProximityReached#98e0d697 from_id:Peer to_id:Peer distance:int = MessageAction;
|
||||
|
||||
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
|
||||
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
||||
|
|
@ -195,7 +196,7 @@ photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
|
|||
photoSizeProgressive#5aa86a51 type:string location:FileLocation w:int h:int sizes:Vector<int> = PhotoSize;
|
||||
|
||||
geoPointEmpty#1117dd5f = GeoPoint;
|
||||
geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint;
|
||||
geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;
|
||||
|
||||
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
|
||||
|
||||
|
|
@ -247,8 +248,8 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
|
|||
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
||||
|
||||
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesSlice#c8edce1e flags:# inexact:flags.1?true count:int next_rate:flags.0?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesSlice#3a54685e flags:# inexact:flags.1?true count:int next_rate:flags.0?int offset_id_offset:flags.2?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.channelMessages#64479808 flags:# inexact:flags.1?true pts:int count:int offset_id_offset:flags.2?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesNotModified#74535f21 count:int = messages.Messages;
|
||||
|
||||
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
|
||||
|
|
@ -274,6 +275,7 @@ inputMessagesFilterRoundVideo#b549da53 = MessagesFilter;
|
|||
inputMessagesFilterMyMentions#c1f8e69a = MessagesFilter;
|
||||
inputMessagesFilterGeo#e7026d0d = MessagesFilter;
|
||||
inputMessagesFilterContacts#e062db83 = MessagesFilter;
|
||||
inputMessagesFilterPinned#1bb00451 = MessagesFilter;
|
||||
|
||||
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
|
||||
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
||||
|
|
@ -313,7 +315,6 @@ updateSavedGifs#9375341e = Update;
|
|||
updateBotInlineQuery#54826690 flags:# query_id:long user_id:int query:string geo:flags.0?GeoPoint offset:string = Update;
|
||||
updateBotInlineSend#e48f964 flags:# user_id:int query:string geo:flags.0?GeoPoint id:string msg_id:flags.1?InputBotInlineMessageID = Update;
|
||||
updateEditChannelMessage#1b3f4df7 message:Message pts:int pts_count:int = Update;
|
||||
updateChannelPinnedMessage#98592475 channel_id:int id:int = Update;
|
||||
updateBotCallbackQuery#e73547e1 flags:# query_id:long user_id:int peer:Peer msg_id:int chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
|
||||
updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
|
||||
updateInlineBotCallbackQuery#f9d27a5a flags:# query_id:long user_id:int msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
|
||||
|
|
@ -338,8 +339,6 @@ updateChannelReadMessagesContents#89893b45 channel_id:int messages:Vector<int> =
|
|||
updateContactsReset#7084a7be = Update;
|
||||
updateChannelAvailableMessages#70db6837 channel_id:int available_min_id:int = Update;
|
||||
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
|
||||
updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
|
||||
updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update;
|
||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
||||
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
||||
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
|
||||
|
|
@ -361,6 +360,8 @@ updateReadChannelDiscussionInbox#1cc7de54 flags:# channel_id:int top_msg_id:int
|
|||
updateReadChannelDiscussionOutbox#4638a26c channel_id:int top_msg_id:int read_max_id:int = Update;
|
||||
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
|
||||
updateChannelUserTyping#ff2abe9f flags:# channel_id:int top_msg_id:flags.0?int user_id:int action:SendMessageAction = Update;
|
||||
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
|
||||
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
|
|
@ -607,6 +608,7 @@ channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelPar
|
|||
channelParticipantCreator#447dca4b flags:# user_id:int admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
|
||||
channelParticipantAdmin#ccbebbaf flags:# can_edit:flags.0?true self:flags.1?true user_id:int inviter_id:flags.1?int promoted_by:int date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
|
||||
channelParticipantBanned#1c0facaf flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant;
|
||||
channelParticipantLeft#c3c6796b user_id:int = ChannelParticipant;
|
||||
|
||||
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
|
||||
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
|
||||
|
|
@ -615,6 +617,7 @@ channelParticipantsBots#b0d1865b = ChannelParticipantsFilter;
|
|||
channelParticipantsBanned#1427a5e1 q:string = ChannelParticipantsFilter;
|
||||
channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter;
|
||||
channelParticipantsContacts#bb6ae88d q:string = ChannelParticipantsFilter;
|
||||
channelParticipantsMentions#e04b5ceb flags:# q:flags.0?string top_msg_id:flags.1?int = ChannelParticipantsFilter;
|
||||
|
||||
channels.channelParticipants#f56ee2a8 count:int participants:Vector<ChannelParticipant> users:Vector<User> = channels.ChannelParticipants;
|
||||
channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;
|
||||
|
|
@ -628,7 +631,7 @@ messages.savedGifs#2e0709a5 hash:int gifs:Vector<Document> = messages.SavedGifs;
|
|||
|
||||
inputBotInlineMessageMediaAuto#3380c786 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||
inputBotInlineMessageText#3dcd7a87 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||
inputBotInlineMessageMediaGeo#c1b15d65 flags:# geo_point:InputGeoPoint period:int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||
inputBotInlineMessageMediaGeo#96929a85 flags:# geo_point:InputGeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||
inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||
inputBotInlineMessageMediaContact#a6edbffd flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||
|
|
@ -640,7 +643,7 @@ inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:Input
|
|||
|
||||
botInlineMessageMediaAuto#764cf810 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||
botInlineMessageText#8c7f65e2 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||
botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||
botInlineMessageMediaGeo#51846fd flags:# geo:GeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||
botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||
botInlineMessageMediaContact#18d1cdc2 flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||
|
||||
|
|
@ -1164,8 +1167,6 @@ messageViews#455b853d flags:# views:flags.0?int forwards:flags.1?int replies:fla
|
|||
|
||||
messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> users:Vector<User> = messages.MessageViews;
|
||||
|
||||
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
|
||||
|
||||
messages.discussionMessage#f5dd8f9d flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
||||
|
||||
messageReplyHeader#a6d57763 flags:# reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
|
||||
|
|
@ -1174,6 +1175,8 @@ messageReplies#4128faac flags:# comments:flags.0?true replies:int replies_pts:in
|
|||
|
||||
peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
|
||||
|
||||
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
|
|
@ -1299,7 +1302,7 @@ contacts.blockFromReplies#29a8962c flags:# delete_message:flags.0?true delete_hi
|
|||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
||||
messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
|
||||
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||
messages.search#4e17810b flags:# peer:InputPeer q:string from_id:flags.0?InputUser top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||
messages.search#c352eec flags:# peer:InputPeer q:string from_id:flags.0?InputPeer top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
||||
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int = messages.AffectedHistory;
|
||||
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
|
||||
|
|
@ -1393,7 +1396,7 @@ messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
|
|||
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.getDialogUnreadMarks#22e24e22 = Vector<DialogPeer>;
|
||||
messages.clearAllDrafts#7e58ee9c = Bool;
|
||||
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true peer:InputPeer id:int = Updates;
|
||||
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true unpin:flags.1?true pm_oneside:flags.2?true peer:InputPeer id:int = Updates;
|
||||
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
|
||||
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
|
||||
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
|
||||
|
|
@ -1422,6 +1425,7 @@ messages.getOldFeaturedStickers#5fe7025b offset:int limit:int hash:int = message
|
|||
messages.getReplies#24b581ba peer:InputPeer msg_id:int offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
|
||||
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
|
||||
messages.unpinAllMessages#f025bc8b peer:InputPeer = messages.AffectedHistory;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||
|
|
@ -1543,4 +1547,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel
|
|||
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
|
||||
|
||||
// LAYER 119
|
||||
// LAYER 120
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="2.4.3.0" />
|
||||
Version="2.4.7.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,4,3,0
|
||||
PRODUCTVERSION 2,4,3,0
|
||||
FILEVERSION 2,4,7,0
|
||||
PRODUCTVERSION 2,4,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
|
@ -62,10 +62,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "2.4.3.0"
|
||||
VALUE "FileVersion", "2.4.7.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.4.3.0"
|
||||
VALUE "ProductVersion", "2.4.7.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,4,3,0
|
||||
PRODUCTVERSION 2,4,3,0
|
||||
FILEVERSION 2,4,7,0
|
||||
PRODUCTVERSION 2,4,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
|
@ -53,10 +53,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop Updater"
|
||||
VALUE "FileVersion", "2.4.3.0"
|
||||
VALUE "FileVersion", "2.4.7.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.4.3.0"
|
||||
VALUE "ProductVersion", "2.4.7.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
|||
82
Telegram/SourceFiles/api/api_attached_stickers.cpp
Normal file
82
Telegram/SourceFiles/api/api_attached_stickers.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "api/api_attached_stickers.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/sticker_set_box.h"
|
||||
#include "boxes/stickers_box.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_photo.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
||||
namespace Api {
|
||||
|
||||
AttachedStickers::AttachedStickers(not_null<ApiWrap*> api)
|
||||
: _api(&api->instance()) {
|
||||
}
|
||||
|
||||
void AttachedStickers::request(
|
||||
not_null<Window::SessionController*> controller,
|
||||
MTPmessages_GetAttachedStickers &&mtpRequest) {
|
||||
const auto weak = base::make_weak(controller.get());
|
||||
_api.request(_requestId).cancel();
|
||||
_requestId = _api.request(
|
||||
std::move(mtpRequest)
|
||||
).done([=](const MTPVector<MTPStickerSetCovered> &result) {
|
||||
_requestId = 0;
|
||||
const auto strongController = weak.get();
|
||||
if (!strongController) {
|
||||
return;
|
||||
}
|
||||
if (result.v.isEmpty()) {
|
||||
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
|
||||
return;
|
||||
} else if (result.v.size() > 1) {
|
||||
Ui::show(Box<StickersBox>(strongController, result));
|
||||
return;
|
||||
}
|
||||
// Single attached sticker pack.
|
||||
const auto setData = result.v.front().match([&](const auto &data) {
|
||||
return data.vset().match([&](const MTPDstickerSet &data) {
|
||||
return &data;
|
||||
});
|
||||
});
|
||||
|
||||
const auto setId = (setData->vid().v && setData->vaccess_hash().v)
|
||||
? MTP_inputStickerSetID(setData->vid(), setData->vaccess_hash())
|
||||
: MTP_inputStickerSetShortName(setData->vshort_name());
|
||||
Ui::show(
|
||||
Box<StickerSetBox>(strongController, setId),
|
||||
Ui::LayerOption::KeepOther);
|
||||
}).fail([=](const RPCError &error) {
|
||||
_requestId = 0;
|
||||
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
|
||||
}).send();
|
||||
}
|
||||
|
||||
void AttachedStickers::requestAttachedStickerSets(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PhotoData*> photo) {
|
||||
request(
|
||||
controller,
|
||||
MTPmessages_GetAttachedStickers(
|
||||
MTP_inputStickeredMediaPhoto(photo->mtpInput())));
|
||||
}
|
||||
|
||||
void AttachedStickers::requestAttachedStickerSets(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<DocumentData*> document) {
|
||||
request(
|
||||
controller,
|
||||
MTPmessages_GetAttachedStickers(
|
||||
MTP_inputStickeredMediaDocument(document->mtpInput())));
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
44
Telegram/SourceFiles/api/api_attached_stickers.h
Normal file
44
Telegram/SourceFiles/api/api_attached_stickers.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class ApiWrap;
|
||||
class DocumentData;
|
||||
class PhotoData;
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Api {
|
||||
|
||||
class AttachedStickers final {
|
||||
public:
|
||||
explicit AttachedStickers(not_null<ApiWrap*> api);
|
||||
|
||||
void requestAttachedStickerSets(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PhotoData*> photo);
|
||||
|
||||
void requestAttachedStickerSets(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<DocumentData*> document);
|
||||
|
||||
private:
|
||||
void request(
|
||||
not_null<Window::SessionController*> controller,
|
||||
MTPmessages_GetAttachedStickers &&mtpRequest);
|
||||
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _requestId = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
||||
|
|
@ -10,6 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "history/history.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_user.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
namespace Api {
|
||||
|
|
@ -17,6 +20,7 @@ namespace {
|
|||
|
||||
constexpr auto kCancelTypingActionTimeout = crl::time(5000);
|
||||
constexpr auto kSetMyActionForMs = 10 * crl::time(1000);
|
||||
constexpr auto kSendTypingsToOfflineFor = TimeId(30);
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
@ -98,6 +102,9 @@ bool SendProgressManager::updated(const Key &key, bool doing) {
|
|||
}
|
||||
|
||||
void SendProgressManager::send(const Key &key, int progress) {
|
||||
if (skipRequest(key)) {
|
||||
return;
|
||||
}
|
||||
using Type = SendProgressType;
|
||||
const auto action = [&]() -> MTPsendMessageAction {
|
||||
const auto p = MTP_int(progress);
|
||||
|
|
@ -135,6 +142,26 @@ void SendProgressManager::send(const Key &key, int progress) {
|
|||
}
|
||||
}
|
||||
|
||||
bool SendProgressManager::skipRequest(const Key &key) const {
|
||||
const auto user = key.history->peer->asUser();
|
||||
if (!user) {
|
||||
return false;
|
||||
} else if (user->isSelf()) {
|
||||
return true;
|
||||
} else if (user->isBot() && !user->isSupport()) {
|
||||
return true;
|
||||
}
|
||||
const auto recently = base::unixtime::now() - kSendTypingsToOfflineFor;
|
||||
const auto online = user->onlineTill;
|
||||
if (online == -2) { // last seen recently
|
||||
return false;
|
||||
} else if (online < 0) {
|
||||
return (-online < recently);
|
||||
} else {
|
||||
return (online < recently);
|
||||
}
|
||||
}
|
||||
|
||||
void SendProgressManager::done(
|
||||
const MTPBool &result,
|
||||
mtpRequestId requestId) {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ private:
|
|||
void send(const Key &key, int progress);
|
||||
void done(const MTPBool &result, mtpRequestId requestId);
|
||||
|
||||
[[nodiscard]] bool skipRequest(const Key &key) const;
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
base::flat_map<Key, mtpRequestId> _requests;
|
||||
base::flat_map<Key, crl::time> _updated;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history.h"
|
||||
#include "history/history_message.h" // NewMessageFlags.
|
||||
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
|
||||
#include "chat_helpers/stickers_dice_pack.h" // DicePacks::kDiceString.
|
||||
#include "ui/text/text_entity.h" // TextWithEntities.
|
||||
#include "ui/text_options.h" // Ui::ItemTextOptions.
|
||||
#include "ui/item_text_options.h" // Ui::ItemTextOptions.
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
|
|
@ -237,8 +238,12 @@ bool SendDice(Api::MessageToSend &message) {
|
|||
auto &account = message.action.history->session().account();
|
||||
auto &config = account.appConfig();
|
||||
static const auto hardcoded = std::vector<QString>{
|
||||
QString::fromUtf8("\xF0\x9F\x8E\xB2"),
|
||||
QString::fromUtf8("\xF0\x9F\x8E\xAF")
|
||||
Stickers::DicePacks::kDiceString,
|
||||
Stickers::DicePacks::kDartString,
|
||||
Stickers::DicePacks::kSlotString,
|
||||
Stickers::DicePacks::kFballString,
|
||||
Stickers::DicePacks::kFballString + QChar(0xFE0F),
|
||||
Stickers::DicePacks::kBballString,
|
||||
};
|
||||
const auto list = config.get<std::vector<QString>>(
|
||||
"emojies_send_dice",
|
||||
|
|
@ -604,8 +609,10 @@ void SendLocationPoint(
|
|||
MTP_int(replyTo),
|
||||
MTP_inputMediaGeoPoint(
|
||||
MTP_inputGeoPoint(
|
||||
MTP_flags(0),
|
||||
MTP_double(data.lat()),
|
||||
MTP_double(data.lon()))),
|
||||
MTP_double(data.lon()),
|
||||
MTP_int(0))),
|
||||
MTP_string(),
|
||||
MTP_long(rand_value<uint64>()),
|
||||
MTPReplyMarkup(),
|
||||
|
|
|
|||
|
|
@ -63,6 +63,22 @@ enum class DataIsLoadedResult {
|
|||
Ok = 3,
|
||||
};
|
||||
|
||||
void ProcessScheduledMessageWithElapsedTime(
|
||||
not_null<Main::Session*> session,
|
||||
bool needToAdd,
|
||||
const MTPDmessage &data) {
|
||||
if (needToAdd && !data.is_from_scheduled()) {
|
||||
// If we still need to add a new message,
|
||||
// we should first check if this message is in
|
||||
// the list of scheduled messages.
|
||||
// This is necessary to correctly update the file reference.
|
||||
// Note that when a message is scheduled until online
|
||||
// while the recipient is already online, the server sends
|
||||
// an ordinary new message with skipped "from_scheduled" flag.
|
||||
session->data().scheduledMessages().checkEntitiesAndUpdate(data);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsForceLogoutNotification(const MTPDupdateServiceNotification &data) {
|
||||
return qs(data.vtype()).startsWith(qstr("AUTH_KEY_DROP_"));
|
||||
}
|
||||
|
|
@ -958,17 +974,7 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
|||
LOG(("Skipping message, because it is already in blocks!"));
|
||||
needToAdd = false;
|
||||
}
|
||||
if (needToAdd && !data.is_from_scheduled()) {
|
||||
// If we still need to add a new message,
|
||||
// we should first check if this message is in
|
||||
// the list of scheduled messages.
|
||||
// This is necessary to correctly update the file reference.
|
||||
// Note that when a message is scheduled until online
|
||||
// while the recipient is already online, the server sends
|
||||
// an ordinary new message with skipped "from_scheduled" flag.
|
||||
_session->data().scheduledMessages().checkEntitiesAndUpdate(
|
||||
data);
|
||||
}
|
||||
ProcessScheduledMessageWithElapsedTime(_session, needToAdd, data);
|
||||
}
|
||||
if (needToAdd) {
|
||||
_session->data().addNewMessage(
|
||||
|
|
@ -1057,10 +1063,12 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
|||
auto &d = update.c_updateNewChannelMessage();
|
||||
auto needToAdd = true;
|
||||
if (d.vmessage().type() == mtpc_message) { // index forwarded messages to links _overview
|
||||
if (_session->data().checkEntitiesAndViewsUpdate(d.vmessage().c_message())) { // already in blocks
|
||||
const auto &data = d.vmessage().c_message();
|
||||
if (_session->data().checkEntitiesAndViewsUpdate(data)) { // already in blocks
|
||||
LOG(("Skipping message, because it is already in blocks!"));
|
||||
needToAdd = false;
|
||||
}
|
||||
ProcessScheduledMessageWithElapsedTime(_session, needToAdd, data);
|
||||
}
|
||||
if (needToAdd) {
|
||||
_session->data().addNewMessage(
|
||||
|
|
@ -1075,6 +1083,17 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
|||
_session->data().updateEditedMessage(d.vmessage());
|
||||
} break;
|
||||
|
||||
case mtpc_updatePinnedChannelMessages: {
|
||||
const auto &d = update.c_updatePinnedChannelMessages();
|
||||
const auto channelId = d.vchannel_id().v;
|
||||
for (const auto &msgId : d.vmessages().v) {
|
||||
const auto item = session().data().message(channelId, msgId.v);
|
||||
if (item) {
|
||||
item->setIsPinned(d.is_pinned());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateEditMessage: {
|
||||
auto &d = update.c_updateEditMessage();
|
||||
_session->data().updateEditedMessage(d.vmessage());
|
||||
|
|
@ -1090,6 +1109,17 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
|||
_session->data().processMessagesDeleted(d.vchannel_id().v, d.vmessages().v);
|
||||
} break;
|
||||
|
||||
case mtpc_updatePinnedMessages: {
|
||||
const auto &d = update.c_updatePinnedMessages();
|
||||
const auto peerId = peerFromMTP(d.vpeer());
|
||||
for (const auto &msgId : d.vmessages().v) {
|
||||
const auto item = session().data().message(0, msgId.v);
|
||||
if (item) {
|
||||
item->setIsPinned(d.is_pinned());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
default: Unexpected("Type in applyUpdateNoPtsCheck()");
|
||||
}
|
||||
}
|
||||
|
|
@ -1385,6 +1415,21 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updatePinnedChannelMessages: {
|
||||
auto &d = update.c_updatePinnedChannelMessages();
|
||||
auto channel = session().data().channelLoaded(d.vchannel_id().v);
|
||||
|
||||
if (channel && !_handlingChannelDifference) {
|
||||
if (channel->ptsRequesting()) { // skip global updates while getting channel difference
|
||||
return;
|
||||
} else {
|
||||
channel->ptsUpdateAndApply(d.vpts().v, d.vpts_count().v, update);
|
||||
}
|
||||
} else {
|
||||
applyUpdateNoPtsCheck(update);
|
||||
}
|
||||
} break;
|
||||
|
||||
// Messages being read.
|
||||
case mtpc_updateReadHistoryInbox: {
|
||||
auto &d = update.c_updateReadHistoryInbox();
|
||||
|
|
@ -1991,28 +2036,9 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
} break;
|
||||
|
||||
// Pinned message.
|
||||
case mtpc_updateUserPinnedMessage: {
|
||||
const auto &d = update.c_updateUserPinnedMessage();
|
||||
if (const auto user = session().data().userLoaded(d.vuser_id().v)) {
|
||||
user->setPinnedMessageId(d.vid().v);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateChatPinnedMessage: {
|
||||
const auto &d = update.c_updateChatPinnedMessage();
|
||||
if (const auto chat = session().data().chatLoaded(d.vchat_id().v)) {
|
||||
const auto status = chat->applyUpdateVersion(d.vversion().v);
|
||||
if (status == ChatData::UpdateStatus::Good) {
|
||||
chat->setPinnedMessageId(d.vid().v);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateChannelPinnedMessage: {
|
||||
const auto &d = update.c_updateChannelPinnedMessage();
|
||||
if (const auto channel = session().data().channelLoaded(d.vchannel_id().v)) {
|
||||
channel->setPinnedMessageId(d.vid().v);
|
||||
}
|
||||
case mtpc_updatePinnedMessages: {
|
||||
const auto &d = update.c_updatePinnedMessages();
|
||||
updateAndApply(d.vpts().v, d.vpts_count().v, update);
|
||||
} break;
|
||||
|
||||
////// Cloud sticker sets
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "apiwrap.h"
|
||||
|
||||
#include "api/api_authorizations.h"
|
||||
#include "api/api_attached_stickers.h"
|
||||
#include "api/api_hash.h"
|
||||
#include "api/api_media.h"
|
||||
#include "api/api_sending.h"
|
||||
|
|
@ -63,8 +64,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "window/themes/window_theme.h"
|
||||
#include "inline_bots/inline_bot_result.h"
|
||||
#include "chat_helpers/message_field.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/item_text_options.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "ui/chat/attach/attach_prepare.h"
|
||||
#include "support/support_helper.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "storage/download_manager_mtproto.h"
|
||||
|
|
@ -188,6 +190,7 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
|
|||
, _topPromotionTimer([=] { refreshTopPromotion(); })
|
||||
, _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); })
|
||||
, _authorizations(std::make_unique<Api::Authorizations>(this))
|
||||
, _attachedStickers(std::make_unique<Api::AttachedStickers>(this))
|
||||
, _selfDestruct(std::make_unique<Api::SelfDestruct>(this))
|
||||
, _sensitiveContent(std::make_unique<Api::SensitiveContent>(this))
|
||||
, _globalPrivacy(std::make_unique<Api::GlobalPrivacy>(this)) {
|
||||
|
|
@ -1690,6 +1693,9 @@ void ApiWrap::requestSelfParticipant(not_null<ChannelData*> channel) {
|
|||
}, [&](const MTPDchannelParticipant &data) {
|
||||
LOG(("API Error: Got self regular participant."));
|
||||
finalize(-1, 0);
|
||||
}, [&](const MTPDchannelParticipantLeft &data) {
|
||||
LOG(("API Error: Got self left participant."));
|
||||
finalize(-1, 0);
|
||||
});
|
||||
});
|
||||
}).fail([=](const RPCError &error) {
|
||||
|
|
@ -3564,6 +3570,9 @@ void ApiWrap::sharedMediaDone(
|
|||
parsed.noSkipRange,
|
||||
parsed.fullCount
|
||||
));
|
||||
if (type == SharedMediaType::Pinned && !parsed.messageIds.empty()) {
|
||||
peer->setHasPinnedMessages(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::requestUserPhotos(
|
||||
|
|
@ -4496,7 +4505,7 @@ void ApiWrap::sendVoiceMessage(
|
|||
}
|
||||
|
||||
void ApiWrap::editMedia(
|
||||
Storage::PreparedList &&list,
|
||||
Ui::PreparedList &&list,
|
||||
SendMediaType type,
|
||||
TextWithTags &&caption,
|
||||
const SendAction &action,
|
||||
|
|
@ -4518,21 +4527,18 @@ void ApiWrap::editMedia(
|
|||
}
|
||||
|
||||
void ApiWrap::sendFiles(
|
||||
Storage::PreparedList &&list,
|
||||
Ui::PreparedList &&list,
|
||||
SendMediaType type,
|
||||
TextWithTags &&caption,
|
||||
std::shared_ptr<SendingAlbum> album,
|
||||
const SendAction &action) {
|
||||
const auto haveCaption = !caption.text.isEmpty();
|
||||
const auto isAlbum = (album != nullptr);
|
||||
const auto compressImages = (type == SendMediaType::Photo);
|
||||
if (haveCaption && !list.canAddCaption(isAlbum, compressImages)) {
|
||||
if (haveCaption && !list.canAddCaption(album != nullptr)) {
|
||||
auto message = MessageToSend(action.history);
|
||||
message.textWithTags = std::move(caption);
|
||||
message.textWithTags = base::take(caption);
|
||||
message.action = action;
|
||||
message.action.clearDraft = false;
|
||||
sendMessage(std::move(message));
|
||||
caption = TextWithTags();
|
||||
}
|
||||
|
||||
const auto to = fileLoadTaskOptions(action);
|
||||
|
|
@ -4542,23 +4548,18 @@ void ApiWrap::sendFiles(
|
|||
auto tasks = std::vector<std::unique_ptr<Task>>();
|
||||
tasks.reserve(list.files.size());
|
||||
for (auto &file : list.files) {
|
||||
if (album) {
|
||||
switch (file.type) {
|
||||
case Storage::PreparedFile::AlbumType::Photo:
|
||||
type = SendMediaType::Photo;
|
||||
break;
|
||||
case Storage::PreparedFile::AlbumType::Video:
|
||||
type = SendMediaType::File;
|
||||
break;
|
||||
default: Unexpected("AlbumType in uploadFilesAfterConfirmation");
|
||||
}
|
||||
}
|
||||
const auto uploadWithType = !album
|
||||
? type
|
||||
: (file.type == Ui::PreparedFile::Type::Photo
|
||||
&& type != SendMediaType::File)
|
||||
? SendMediaType::Photo
|
||||
: SendMediaType::File;
|
||||
tasks.push_back(std::make_unique<FileLoadTask>(
|
||||
&session(),
|
||||
file.path,
|
||||
file.content,
|
||||
std::move(file.information),
|
||||
type,
|
||||
uploadWithType,
|
||||
to,
|
||||
caption,
|
||||
album));
|
||||
|
|
@ -5553,6 +5554,10 @@ Api::Authorizations &ApiWrap::authorizations() {
|
|||
return *_authorizations;
|
||||
}
|
||||
|
||||
Api::AttachedStickers &ApiWrap::attachedStickers() {
|
||||
return *_attachedStickers;
|
||||
}
|
||||
|
||||
Api::SelfDestruct &ApiWrap::selfDestruct() {
|
||||
return *_selfDestruct;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ class Result;
|
|||
|
||||
namespace Storage {
|
||||
enum class SharedMediaType : signed char;
|
||||
struct PreparedList;
|
||||
class DownloadMtprotoTask;
|
||||
class Account;
|
||||
} // namespace Storage
|
||||
|
|
@ -49,10 +48,15 @@ namespace Core {
|
|||
struct CloudPasswordState;
|
||||
} // namespace Core
|
||||
|
||||
namespace Ui {
|
||||
struct PreparedList;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Api {
|
||||
|
||||
class Updates;
|
||||
class Authorizations;
|
||||
class AttachedStickers;
|
||||
class SelfDestruct;
|
||||
class SensitiveContent;
|
||||
class GlobalPrivacy;
|
||||
|
|
@ -392,7 +396,7 @@ public:
|
|||
int duration,
|
||||
const SendAction &action);
|
||||
void sendFiles(
|
||||
Storage::PreparedList &&list,
|
||||
Ui::PreparedList &&list,
|
||||
SendMediaType type,
|
||||
TextWithTags &&caption,
|
||||
std::shared_ptr<SendingAlbum> album,
|
||||
|
|
@ -403,7 +407,7 @@ public:
|
|||
const SendAction &action);
|
||||
|
||||
void editMedia(
|
||||
Storage::PreparedList &&list,
|
||||
Ui::PreparedList &&list,
|
||||
SendMediaType type,
|
||||
TextWithTags &&caption,
|
||||
const SendAction &action,
|
||||
|
|
@ -458,6 +462,7 @@ public:
|
|||
rpl::producer<BlockedPeersSlice> blockedPeersSlice();
|
||||
|
||||
[[nodiscard]] Api::Authorizations &authorizations();
|
||||
[[nodiscard]] Api::AttachedStickers &attachedStickers();
|
||||
[[nodiscard]] Api::SelfDestruct &selfDestruct();
|
||||
[[nodiscard]] Api::SensitiveContent &sensitiveContent();
|
||||
[[nodiscard]] Api::GlobalPrivacy &globalPrivacy();
|
||||
|
|
@ -821,6 +826,7 @@ private:
|
|||
rpl::event_stream<BlockedPeersSlice> _blockedPeersChanges;
|
||||
|
||||
const std::unique_ptr<Api::Authorizations> _authorizations;
|
||||
const std::unique_ptr<Api::AttachedStickers> _attachedStickers;
|
||||
const std::unique_ptr<Api::SelfDestruct> _selfDestruct;
|
||||
const std::unique_ptr<Api::SensitiveContent> _sensitiveContent;
|
||||
const std::unique_ptr<Api::GlobalPrivacy> _globalPrivacy;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/history_view_service_message.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
#include "core/crash_reports.h"
|
||||
#include "core/update_checker.h"
|
||||
|
|
@ -44,7 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "styles/style_overview.h"
|
||||
#include "styles/style_media_view.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
#include <QtCore/QBuffer>
|
||||
|
|
@ -66,14 +67,6 @@ HistoryView::Element *hoveredItem = nullptr,
|
|||
*pressedLinkItem = nullptr,
|
||||
*mousedItem = nullptr;
|
||||
|
||||
struct CornersPixmaps {
|
||||
QPixmap p[4];
|
||||
};
|
||||
QVector<CornersPixmaps> corners;
|
||||
using CornersMap = QMap<uint32, CornersPixmaps>;
|
||||
CornersMap cornersMap;
|
||||
QImage cornersMaskLarge[4], cornersMaskSmall[4];
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace App {
|
||||
|
|
@ -104,114 +97,12 @@ namespace App {
|
|||
return result;
|
||||
}
|
||||
|
||||
void prepareCorners(RoundCorners index, int32 radius, const QBrush &brush, const style::color *shadow = nullptr, QImage *cors = nullptr) {
|
||||
Expects(::corners.size() > index);
|
||||
|
||||
int32 r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor();
|
||||
QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4];
|
||||
{
|
||||
Painter p(&rect);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
p.fillRect(QRect(0, 0, rect.width(), rect.height()), Qt::transparent);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
p.setPen(Qt::NoPen);
|
||||
if (shadow) {
|
||||
p.setBrush((*shadow)->b);
|
||||
p.drawRoundedRect(0, s, r * 3, r * 3, r, r);
|
||||
}
|
||||
p.setBrush(brush);
|
||||
p.drawRoundedRect(0, 0, r * 3, r * 3, r, r);
|
||||
}
|
||||
if (!cors) cors = localCors;
|
||||
cors[0] = rect.copy(0, 0, r, r);
|
||||
cors[1] = rect.copy(r * 2, 0, r, r);
|
||||
cors[2] = rect.copy(0, r * 2, r, r + (shadow ? s : 0));
|
||||
cors[3] = rect.copy(r * 2, r * 2, r, r + (shadow ? s : 0));
|
||||
if (index != SmallMaskCorners && index != LargeMaskCorners) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
::corners[index].p[i] = pixmapFromImageInPlace(std::move(cors[i]));
|
||||
::corners[index].p[i].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createMaskCorners() {
|
||||
QImage mask[4];
|
||||
prepareCorners(SmallMaskCorners, st::buttonRadius, QColor(255, 255, 255), nullptr, mask);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
::cornersMaskSmall[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
::cornersMaskSmall[i].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
prepareCorners(LargeMaskCorners, st::historyMessageRadius, QColor(255, 255, 255), nullptr, mask);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
::cornersMaskLarge[i] = mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
::cornersMaskLarge[i].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
}
|
||||
|
||||
void createPaletteCorners() {
|
||||
prepareCorners(MenuCorners, st::buttonRadius, st::menuBg);
|
||||
prepareCorners(BoxCorners, st::boxRadius, st::boxBg);
|
||||
prepareCorners(BotKbOverCorners, st::dateRadius, st::msgBotKbOverBgAdd);
|
||||
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
|
||||
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
|
||||
prepareCorners(SelectedOverlaySmallCorners, st::buttonRadius, st::msgSelectOverlay);
|
||||
prepareCorners(SelectedOverlayLargeCorners, st::historyMessageRadius, st::msgSelectOverlay);
|
||||
prepareCorners(DateCorners, st::dateRadius, st::msgDateImgBg);
|
||||
prepareCorners(DateSelectedCorners, st::dateRadius, st::msgDateImgBgSelected);
|
||||
prepareCorners(OverviewVideoCorners, st::overviewVideoStatusRadius, st::msgDateImgBg);
|
||||
prepareCorners(OverviewVideoSelectedCorners, st::overviewVideoStatusRadius, st::msgDateImgBgSelected);
|
||||
prepareCorners(InShadowCorners, st::historyMessageRadius, st::msgInShadow);
|
||||
prepareCorners(InSelectedShadowCorners, st::historyMessageRadius, st::msgInShadowSelected);
|
||||
prepareCorners(ForwardCorners, st::historyMessageRadius, st::historyForwardChooseBg);
|
||||
prepareCorners(MediaviewSaveCorners, st::mediaviewControllerRadius, st::mediaviewSaveMsgBg);
|
||||
prepareCorners(EmojiHoverCorners, st::buttonRadius, st::emojiPanHover);
|
||||
prepareCorners(StickerHoverCorners, st::buttonRadius, st::emojiPanHover);
|
||||
prepareCorners(BotKeyboardCorners, st::buttonRadius, st::botKbBg);
|
||||
prepareCorners(PhotoSelectOverlayCorners, st::buttonRadius, st::overviewPhotoSelectOverlay);
|
||||
|
||||
prepareCorners(Doc1Corners, st::buttonRadius, st::msgFile1Bg);
|
||||
prepareCorners(Doc2Corners, st::buttonRadius, st::msgFile2Bg);
|
||||
prepareCorners(Doc3Corners, st::buttonRadius, st::msgFile3Bg);
|
||||
prepareCorners(Doc4Corners, st::buttonRadius, st::msgFile4Bg);
|
||||
|
||||
prepareCorners(MessageInCorners, st::historyMessageRadius, st::msgInBg, &st::msgInShadow);
|
||||
prepareCorners(MessageInSelectedCorners, st::historyMessageRadius, st::msgInBgSelected, &st::msgInShadowSelected);
|
||||
prepareCorners(MessageOutCorners, st::historyMessageRadius, st::msgOutBg, &st::msgOutShadow);
|
||||
prepareCorners(MessageOutSelectedCorners, st::historyMessageRadius, st::msgOutBgSelected, &st::msgOutShadowSelected);
|
||||
|
||||
prepareCorners(SendFilesBoxAlbumGroupCorners, st::sendBoxAlbumGroupRadius, st::callFingerprintBg);
|
||||
}
|
||||
|
||||
void createCorners() {
|
||||
::corners.resize(RoundCornersCount);
|
||||
createMaskCorners();
|
||||
createPaletteCorners();
|
||||
}
|
||||
|
||||
void clearCorners() {
|
||||
::corners.clear();
|
||||
::cornersMap.clear();
|
||||
}
|
||||
|
||||
void initMedia() {
|
||||
createCorners();
|
||||
Ui::StartCachedCorners();
|
||||
|
||||
using Update = Window::Theme::BackgroundUpdate;
|
||||
static auto subscription = Window::Theme::Background()->add_subscription([](const Update &update) {
|
||||
if (update.paletteChanged()) {
|
||||
createPaletteCorners();
|
||||
|
||||
if (const auto m = App::main()) { // multi good
|
||||
m->updateScrollColors();
|
||||
}
|
||||
HistoryView::serviceColorsUpdated();
|
||||
} else if (update.type == Update::Type::New) {
|
||||
prepareCorners(StickerCorners, st::dateRadius, st::msgServiceBg);
|
||||
prepareCorners(StickerSelectedCorners, st::dateRadius, st::msgServiceBgSelected);
|
||||
|
||||
if (const auto m = App::main()) { // multi good
|
||||
m->updateScrollColors();
|
||||
}
|
||||
|
|
@ -221,8 +112,7 @@ namespace App {
|
|||
}
|
||||
|
||||
void deinitMedia() {
|
||||
clearCorners();
|
||||
|
||||
Ui::FinishCachedCorners();
|
||||
Data::clearGlobalStructures();
|
||||
}
|
||||
|
||||
|
|
@ -396,132 +286,4 @@ namespace App {
|
|||
return QPixmap::fromImage(std::move(image), Qt::ColorOnly);
|
||||
}
|
||||
|
||||
void rectWithCorners(Painter &p, QRect rect, const style::color &bg, RoundCorners index, RectParts corners) {
|
||||
auto parts = RectPart::Top
|
||||
| RectPart::NoTopBottom
|
||||
| RectPart::Bottom
|
||||
| corners;
|
||||
roundRect(p, rect, bg, index, nullptr, parts);
|
||||
if ((corners & RectPart::AllCorners) != RectPart::AllCorners) {
|
||||
const auto size = ::corners[index].p[0].width() / cIntRetinaFactor();
|
||||
if (!(corners & RectPart::TopLeft)) {
|
||||
p.fillRect(rect.x(), rect.y(), size, size, bg);
|
||||
}
|
||||
if (!(corners & RectPart::TopRight)) {
|
||||
p.fillRect(rect.x() + rect.width() - size, rect.y(), size, size, bg);
|
||||
}
|
||||
if (!(corners & RectPart::BottomLeft)) {
|
||||
p.fillRect(rect.x(), rect.y() + rect.height() - size, size, size, bg);
|
||||
}
|
||||
if (!(corners & RectPart::BottomRight)) {
|
||||
p.fillRect(rect.x() + rect.width() - size, rect.y() + rect.height() - size, size, size, bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
|
||||
if (radius == ImageRoundRadius::Ellipse) {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(p.textPalette().selectOverlay);
|
||||
p.drawEllipse(rect);
|
||||
} else {
|
||||
auto overlayCorners = (radius == ImageRoundRadius::Small)
|
||||
? SelectedOverlaySmallCorners
|
||||
: SelectedOverlayLargeCorners;
|
||||
const auto bg = p.textPalette().selectOverlay;
|
||||
rectWithCorners(p, rect, bg, overlayCorners, corners);
|
||||
}
|
||||
}
|
||||
|
||||
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
|
||||
rectWithCorners(p, rect, st::msgInBg, MessageInCorners, corners);
|
||||
}
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) {
|
||||
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
|
||||
if (w < 2 * cornerWidth || h < 2 * cornerHeight) return;
|
||||
if (w > 2 * cornerWidth) {
|
||||
if (parts & RectPart::Top) {
|
||||
p.fillRect(x + cornerWidth, y, w - 2 * cornerWidth, cornerHeight, bg);
|
||||
}
|
||||
if (parts & RectPart::Bottom) {
|
||||
p.fillRect(x + cornerWidth, y + h - cornerHeight, w - 2 * cornerWidth, cornerHeight, bg);
|
||||
if (shadow) {
|
||||
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, *shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (h > 2 * cornerHeight) {
|
||||
if ((parts & RectPart::NoTopBottom) == RectPart::NoTopBottom) {
|
||||
p.fillRect(x, y + cornerHeight, w, h - 2 * cornerHeight, bg);
|
||||
} else {
|
||||
if (parts & RectPart::Left) {
|
||||
p.fillRect(x, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg);
|
||||
}
|
||||
if ((parts & RectPart::Center) && w > 2 * cornerWidth) {
|
||||
p.fillRect(x + cornerWidth, y + cornerHeight, w - 2 * cornerWidth, h - 2 * cornerHeight, bg);
|
||||
}
|
||||
if (parts & RectPart::Right) {
|
||||
p.fillRect(x + w - cornerWidth, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parts & RectPart::TopLeft) {
|
||||
p.drawPixmap(x, y, corner.p[0]);
|
||||
}
|
||||
if (parts & RectPart::TopRight) {
|
||||
p.drawPixmap(x + w - cornerWidth, y, corner.p[1]);
|
||||
}
|
||||
if (parts & RectPart::BottomLeft) {
|
||||
p.drawPixmap(x, y + h - cornerHeight, corner.p[2]);
|
||||
}
|
||||
if (parts & RectPart::BottomRight) {
|
||||
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, corner.p[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, RoundCorners index, const style::color *shadow, RectParts parts) {
|
||||
roundRect(p, x, y, w, h, bg, ::corners[index], shadow, parts);
|
||||
}
|
||||
|
||||
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts) {
|
||||
auto &corner = ::corners[index];
|
||||
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
|
||||
if (parts & RectPart::Bottom) {
|
||||
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, shadow);
|
||||
}
|
||||
if (parts & RectPart::BottomLeft) {
|
||||
p.fillRect(x, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
|
||||
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, corner.p[2]);
|
||||
}
|
||||
if (parts & RectPart::BottomRight) {
|
||||
p.fillRect(x + w - cornerWidth, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
|
||||
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, corner.p[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts) {
|
||||
auto colorKey = ((uint32(bg->c.alpha()) & 0xFF) << 24) | ((uint32(bg->c.red()) & 0xFF) << 16) | ((uint32(bg->c.green()) & 0xFF) << 8) | ((uint32(bg->c.blue()) & 0xFF) << 24);
|
||||
auto i = cornersMap.find(colorKey);
|
||||
if (i == cornersMap.cend()) {
|
||||
QImage images[4];
|
||||
switch (radius) {
|
||||
case ImageRoundRadius::Small: prepareCorners(SmallMaskCorners, st::buttonRadius, bg, nullptr, images); break;
|
||||
case ImageRoundRadius::Large: prepareCorners(LargeMaskCorners, st::historyMessageRadius, bg, nullptr, images); break;
|
||||
default: p.fillRect(x, y, w, h, bg); return;
|
||||
}
|
||||
|
||||
CornersPixmaps pixmaps;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
pixmaps.p[j] = pixmapFromImageInPlace(std::move(images[j]));
|
||||
pixmaps.p[j].setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
i = cornersMap.insert(colorKey, pixmaps);
|
||||
}
|
||||
roundRect(p, x, y, w, h, bg, i.value(), nullptr, parts);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,54 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "data/data_types.h"
|
||||
#include "ui/rect_part.h"
|
||||
|
||||
enum class ImageRoundRadius;
|
||||
|
||||
namespace HistoryView {
|
||||
class Element;
|
||||
} // namespace HistoryView
|
||||
|
||||
enum RoundCorners : int {
|
||||
SmallMaskCorners = 0x00, // for images
|
||||
LargeMaskCorners,
|
||||
|
||||
BoxCorners,
|
||||
MenuCorners,
|
||||
BotKbOverCorners,
|
||||
StickerCorners,
|
||||
StickerSelectedCorners,
|
||||
SelectedOverlaySmallCorners,
|
||||
SelectedOverlayLargeCorners,
|
||||
DateCorners,
|
||||
DateSelectedCorners,
|
||||
OverviewVideoCorners,
|
||||
OverviewVideoSelectedCorners,
|
||||
ForwardCorners,
|
||||
MediaviewSaveCorners,
|
||||
EmojiHoverCorners,
|
||||
StickerHoverCorners,
|
||||
BotKeyboardCorners,
|
||||
PhotoSelectOverlayCorners,
|
||||
|
||||
Doc1Corners,
|
||||
Doc2Corners,
|
||||
Doc3Corners,
|
||||
Doc4Corners,
|
||||
|
||||
InShadowCorners, // for photos without bg
|
||||
InSelectedShadowCorners,
|
||||
|
||||
MessageInCorners, // with shadow
|
||||
MessageInSelectedCorners,
|
||||
MessageOutCorners,
|
||||
MessageOutSelectedCorners,
|
||||
|
||||
SendFilesBoxAlbumGroupCorners,
|
||||
|
||||
RoundCornersCount
|
||||
};
|
||||
|
||||
namespace App {
|
||||
QString formatPhone(QString phone);
|
||||
|
||||
|
|
@ -90,20 +47,4 @@ namespace App {
|
|||
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0);
|
||||
QPixmap pixmapFromImageInPlace(QImage &&image);
|
||||
|
||||
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);
|
||||
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
|
||||
}
|
||||
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full);
|
||||
inline void roundShadow(Painter &p, const QRect &rect, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full) {
|
||||
return roundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts);
|
||||
}
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ 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 "core/file_utilities.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "core/update_checker.h"
|
||||
|
|
@ -126,7 +125,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 {
|
||||
File::OpenUrl(qsl("https://desktop.telegram.org/changelog"));
|
||||
UrlClickHandler::Open(qsl("https://desktop.telegram.org/changelog"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/toast/toast.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "ui/special_fields.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/unread_badge.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "data/data_channel.h"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/background_preview_box.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ backgroundScroll: ScrollArea(boxScroll) {
|
|||
deltab: 10px;
|
||||
}
|
||||
|
||||
editMediaButtonSize: 29px;
|
||||
editMediaButtonSize: 28px;
|
||||
editMediaButtonSkip: 8px;
|
||||
editMediaButtonFileSkipRight: 1px;
|
||||
editMediaButtonFileSkipTop: 7px;
|
||||
|
|
@ -508,25 +508,33 @@ editMediaButton: IconButton {
|
|||
|
||||
// SendFilesBox
|
||||
|
||||
sendBoxAlbumGroupEditInternalSkip: 9px;
|
||||
sendBoxAlbumGroupEditInternalSkip: 8px;
|
||||
sendBoxAlbumGroupSkipRight: 6px;
|
||||
sendBoxAlbumGroupSkipTop: 6px;
|
||||
sendBoxAlbumGroupRadius: 12px;
|
||||
sendBoxAlbumGroupHeight: 25px;
|
||||
sendBoxAlbumGroupRadius: 13px;
|
||||
sendBoxAlbumGroupHeight: 26px;
|
||||
|
||||
sendBoxAlbumGroupEditButtonIcon: editMediaButtonIconPhoto;
|
||||
sendBoxAlbumGroupEditButtonIconPosition: point(4px, -1px);
|
||||
sendBoxFileGroupSkipTop: 2px;
|
||||
sendBoxFileGroupSkipRight: 8px;
|
||||
sendBoxFileGroupEditInternalSkip: -1px;
|
||||
|
||||
sendBoxAlbumGroupButtonFile: IconButton(editMediaButton) {
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgRipple;
|
||||
}
|
||||
}
|
||||
|
||||
sendBoxAlbumGroupDeleteButtonIconPosition: point(-3px, 0px);
|
||||
sendBoxAlbumGroupDeleteButtonIcon: icon {{ "history_file_cancel", msgServiceFg}};
|
||||
sendBoxAlbumGroupEditButtonIconFile: editMediaButtonIconFile;
|
||||
sendBoxAlbumGroupDeleteButtonIconFile: icon {{ "history_file_cancel", menuIconFg, point(6px, 6px) }};
|
||||
|
||||
sendBoxAlbumGroupButtonMediaEdit: icon {{ "settings_edit", msgServiceFg, point(3px, -2px) }};
|
||||
sendBoxAlbumGroupButtonMediaDelete: icon {{ "history_file_cancel", msgServiceFg, point(2px, 5px) }};
|
||||
sendBoxAlbumGroupButtonMedia: IconButton {
|
||||
width: sendBoxAlbumGroupHeight;
|
||||
height: sendBoxAlbumGroupHeight;
|
||||
|
||||
icon: sendBoxAlbumGroupButtonMediaEdit;
|
||||
}
|
||||
|
||||
// End of SendFilesBox
|
||||
|
||||
calendarTitleHeight: boxTitleHeight;
|
||||
|
|
@ -705,11 +713,7 @@ groupStickersSubTitleHeight: 36px;
|
|||
|
||||
sendMediaPreviewSize: 308px;
|
||||
sendMediaPreviewHeightMax: 1280;
|
||||
sendMediaPreviewPhotoSkip: 10px;
|
||||
sendMediaFileThumbSize: 64px;
|
||||
sendMediaFileThumbSkip: 10px;
|
||||
sendMediaFileNameTop: 7px;
|
||||
sendMediaFileStatusTop: 37px;
|
||||
sendMediaRowSkip: 10px;
|
||||
|
||||
proxyUsePadding: margins(22px, 6px, 22px, 5px);
|
||||
proxyTryIPv6Padding: margins(22px, 8px, 22px, 5px);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,21 @@ TextParseOptions kMarkedTextBoxOptions = {
|
|||
Qt::LayoutDirectionAuto, // dir
|
||||
};
|
||||
|
||||
[[nodiscard]] bool IsOldForPin(MsgId id, not_null<PeerData*> peer) {
|
||||
const auto normal = peer->migrateToOrMe();
|
||||
const auto migrated = normal->migrateFrom();
|
||||
const auto top = Data::ResolveTopPinnedId(normal, migrated);
|
||||
if (!top) {
|
||||
return false;
|
||||
} else if (peer == migrated) {
|
||||
return top.channel || (id < top.msg);
|
||||
} else if (migrated) {
|
||||
return top.channel && (id < top.msg);
|
||||
} else {
|
||||
return (id < top.msg);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ConfirmBox::ConfirmBox(
|
||||
|
|
@ -444,20 +459,43 @@ PinMessageBox::PinMessageBox(
|
|||
: _peer(peer)
|
||||
, _api(&peer->session().mtp())
|
||||
, _msgId(msgId)
|
||||
, _text(this, tr::lng_pinned_pin_sure(tr::now), st::boxLabel) {
|
||||
, _pinningOld(IsOldForPin(msgId, peer))
|
||||
, _text(
|
||||
this,
|
||||
(_pinningOld
|
||||
? tr::lng_pinned_pin_old_sure(tr::now)
|
||||
: (peer->isChat() || peer->isMegagroup())
|
||||
? tr::lng_pinned_pin_sure_group(tr::now)
|
||||
: tr::lng_pinned_pin_sure(tr::now)),
|
||||
st::boxLabel) {
|
||||
}
|
||||
|
||||
void PinMessageBox::prepare() {
|
||||
addButton(tr::lng_pinned_pin(), [this] { pinMessage(); });
|
||||
addButton(tr::lng_cancel(), [this] { closeBox(); });
|
||||
|
||||
if (_peer->isChat() || _peer->isMegagroup()) {
|
||||
_notify.create(this, tr::lng_pinned_notify(tr::now), false, st::defaultBoxCheckbox);
|
||||
if (_peer->isUser() && !_peer->isSelf()) {
|
||||
_pinForPeer.create(
|
||||
this,
|
||||
tr::lng_pinned_also_for_other(
|
||||
tr::now,
|
||||
lt_user,
|
||||
_peer->shortName()),
|
||||
false,
|
||||
st::defaultBoxCheckbox);
|
||||
_checkbox = _pinForPeer;
|
||||
} else if (!_pinningOld && (_peer->isChat() || _peer->isMegagroup())) {
|
||||
_notify.create(
|
||||
this,
|
||||
tr::lng_pinned_notify(tr::now),
|
||||
false,
|
||||
st::defaultBoxCheckbox);
|
||||
_checkbox = _notify;
|
||||
}
|
||||
|
||||
auto height = st::boxPadding.top() + _text->height() + st::boxPadding.bottom();
|
||||
if (_notify) {
|
||||
height += st::boxMediumSkip + _notify->heightNoMargins();
|
||||
if (_checkbox) {
|
||||
height += st::boxMediumSkip + _checkbox->heightNoMargins();
|
||||
}
|
||||
setDimensions(st::boxWidth, height);
|
||||
}
|
||||
|
|
@ -465,8 +503,8 @@ void PinMessageBox::prepare() {
|
|||
void PinMessageBox::resizeEvent(QResizeEvent *e) {
|
||||
BoxContent::resizeEvent(e);
|
||||
_text->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
|
||||
if (_notify) {
|
||||
_notify->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip);
|
||||
if (_checkbox) {
|
||||
_checkbox->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,6 +523,9 @@ void PinMessageBox::pinMessage() {
|
|||
if (_notify && !_notify->checked()) {
|
||||
flags |= MTPmessages_UpdatePinnedMessage::Flag::f_silent;
|
||||
}
|
||||
if (_pinForPeer && !_pinForPeer->checked()) {
|
||||
flags |= MTPmessages_UpdatePinnedMessage::Flag::f_pm_oneside;
|
||||
}
|
||||
_requestId = _api.request(MTPmessages_UpdatePinnedMessage(
|
||||
MTP_flags(flags),
|
||||
_peer->input,
|
||||
|
|
|
|||
|
|
@ -183,10 +183,13 @@ private:
|
|||
|
||||
const not_null<PeerData*> _peer;
|
||||
MTP::Sender _api;
|
||||
MsgId _msgId;
|
||||
MsgId _msgId = 0;
|
||||
bool _pinningOld = false;
|
||||
|
||||
object_ptr<Ui::FlatLabel> _text;
|
||||
object_ptr<Ui::Checkbox> _notify = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _pinForPeer = { nullptr };
|
||||
QPointer<Ui::Checkbox> _checkbox;
|
||||
|
||||
mtpRequestId _requestId = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/toast/toast.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/radial_animation.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "facades.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
|
|
|||
|
|
@ -47,17 +47,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/text/format_values.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/chat/attach/attach_prepare.h"
|
||||
#include "ui/controls/emoji_button.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "confirm_box.h"
|
||||
#include "apiwrap.h"
|
||||
#include "app.h" // App::pixmapFromImageInPlace.
|
||||
#include "facades.h" // App::LambdaDelayed.
|
||||
#include "app.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
#include <QtCore/QMimeData>
|
||||
|
||||
|
|
@ -67,13 +70,13 @@ using namespace ::Media::Streaming;
|
|||
using Data::PhotoSize;
|
||||
|
||||
auto ListFromMimeData(not_null<const QMimeData*> data) {
|
||||
using Error = Storage::PreparedList::Error;
|
||||
using Error = Ui::PreparedList::Error;
|
||||
auto result = data->hasUrls()
|
||||
? Storage::PrepareMediaList(
|
||||
// When we edit media, we need only 1 file.
|
||||
data->urls().mid(0, 1),
|
||||
st::sendMediaPreviewSize)
|
||||
: Storage::PreparedList(Error::EmptyFile, QString());
|
||||
: Ui::PreparedList(Error::EmptyFile, QString());
|
||||
if (result.error == Error::None) {
|
||||
return result;
|
||||
} else if (data->hasImage()) {
|
||||
|
|
@ -103,10 +106,23 @@ EditCaptionBox::EditCaptionBox(
|
|||
Expects(item->media()->allowsEditCaption());
|
||||
|
||||
_isAllowedEditMedia = item->media()->allowsEditMedia();
|
||||
_isAlbum = !item->groupId().empty();
|
||||
|
||||
auto dimensions = QSize();
|
||||
const auto media = item->media();
|
||||
|
||||
if (!item->groupId().empty()) {
|
||||
if (media->photo()) {
|
||||
_albumType = Ui::AlbumType::PhotoVideo;
|
||||
} else if (const auto document = media->document()) {
|
||||
if (document->isVideoFile()) {
|
||||
_albumType = Ui::AlbumType::PhotoVideo;
|
||||
} else if (document->isSong()) {
|
||||
_albumType = Ui::AlbumType::Music;
|
||||
} else {
|
||||
_albumType = Ui::AlbumType::File;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto photo = media->photo()) {
|
||||
_photoMedia = photo->createMediaView();
|
||||
_photoMedia->wanted(PhotoSize::Large, _msgId);
|
||||
|
|
@ -155,11 +171,12 @@ EditCaptionBox::EditCaptionBox(
|
|||
_thumbw = 0;
|
||||
_thumbnailImageLoaded = true;
|
||||
} else {
|
||||
const auto thumbSize = st::msgFileThumbLayout.thumbSize;
|
||||
const auto tw = dimensions.width(), th = dimensions.height();
|
||||
if (tw > th) {
|
||||
_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||
_thumbw = (tw * thumbSize) / th;
|
||||
} else {
|
||||
_thumbw = st::msgFileThumbSize;
|
||||
_thumbw = thumbSize;
|
||||
}
|
||||
_refreshThumbnail = [=] {
|
||||
const auto image = computeImage();
|
||||
|
|
@ -177,8 +194,8 @@ EditCaptionBox::EditCaptionBox(
|
|||
_thumbw * cIntRetinaFactor(),
|
||||
0,
|
||||
options,
|
||||
st::msgFileThumbSize,
|
||||
st::msgFileThumbSize));
|
||||
thumbSize,
|
||||
thumbSize));
|
||||
_thumbnailImageLoaded = true;
|
||||
};
|
||||
_refreshThumbnail();
|
||||
|
|
@ -352,8 +369,8 @@ EditCaptionBox::EditCaptionBox(
|
|||
this,
|
||||
object_ptr<Ui::Checkbox>(
|
||||
this,
|
||||
tr::lng_send_file(tr::now),
|
||||
false,
|
||||
tr::lng_send_compressed(tr::now),
|
||||
true,
|
||||
st::defaultBoxCheckbox),
|
||||
st::editMediaCheckboxMargins);
|
||||
_wayWrap = r.data();
|
||||
|
|
@ -361,8 +378,14 @@ EditCaptionBox::EditCaptionBox(
|
|||
|
||||
r->entity()->checkedChanges(
|
||||
) | rpl::start_with_next([&](bool checked) {
|
||||
_asFile = checked;
|
||||
_asFile = !checked;
|
||||
}, _wayWrap->lifetime());
|
||||
|
||||
_controller->session().data().itemRemoved(
|
||||
_msgId
|
||||
) | rpl::start_with_next([=] {
|
||||
closeBox();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
EditCaptionBox::~EditCaptionBox() = default;
|
||||
|
|
@ -469,7 +492,7 @@ void EditCaptionBox::streamingReady(Information &&info) {
|
|||
}
|
||||
|
||||
void EditCaptionBox::updateEditPreview() {
|
||||
using Info = FileMediaInformation;
|
||||
using Info = Ui::PreparedFileInformation;
|
||||
|
||||
const auto file = &_preparedList.files.front();
|
||||
const auto fileMedia = &file->information->media;
|
||||
|
|
@ -477,7 +500,8 @@ void EditCaptionBox::updateEditPreview() {
|
|||
const auto fileinfo = QFileInfo(file->path);
|
||||
const auto filename = fileinfo.fileName();
|
||||
|
||||
_isImage = fileIsImage(filename, file->mime);
|
||||
const auto mime = file->information->filemime;
|
||||
_isImage = Core::FileIsImage(filename, mime);
|
||||
_isAudio = false;
|
||||
_animated = false;
|
||||
_photo = false;
|
||||
|
|
@ -490,9 +514,10 @@ void EditCaptionBox::updateEditPreview() {
|
|||
auto shouldAsDoc = true;
|
||||
auto docPhotoSize = QSize();
|
||||
if (const auto image = std::get_if<Info::Image>(fileMedia)) {
|
||||
shouldAsDoc = !Storage::ValidateThumbDimensions(
|
||||
shouldAsDoc = !Ui::ValidateThumbDimensions(
|
||||
image->data.width(),
|
||||
image->data.height());
|
||||
image->data.height()
|
||||
) || (_albumType == Ui::AlbumType::File);
|
||||
if (shouldAsDoc) {
|
||||
docPhotoSize.setWidth(image->data.width());
|
||||
docPhotoSize.setHeight(image->data.height());
|
||||
|
|
@ -509,7 +534,7 @@ void EditCaptionBox::updateEditPreview() {
|
|||
if (shouldAsDoc) {
|
||||
auto nameString = filename;
|
||||
if (const auto song = std::get_if<Info::Song>(fileMedia)) {
|
||||
nameString = DocumentData::ComposeNameString(
|
||||
nameString = Ui::ComposeNameString(
|
||||
filename,
|
||||
song->title,
|
||||
song->performer);
|
||||
|
|
@ -517,7 +542,7 @@ void EditCaptionBox::updateEditPreview() {
|
|||
}
|
||||
|
||||
const auto getExt = [&] {
|
||||
auto patterns = Core::MimeTypeForName(file->mime).globPatterns();
|
||||
auto patterns = Core::MimeTypeForName(mime).globPatterns();
|
||||
if (!patterns.isEmpty()) {
|
||||
return patterns.front().replace('*', QString());
|
||||
}
|
||||
|
|
@ -543,7 +568,7 @@ void EditCaptionBox::updateEditPreview() {
|
|||
_doc = true;
|
||||
}
|
||||
|
||||
const auto showCheckbox = _photo && !_isAlbum;
|
||||
const auto showCheckbox = _photo && (_albumType == Ui::AlbumType::None);
|
||||
_wayWrap->toggle(showCheckbox, anim::type::instant);
|
||||
|
||||
if (!_doc) {
|
||||
|
|
@ -580,25 +605,40 @@ void EditCaptionBox::updateEditMediaButton() {
|
|||
|
||||
void EditCaptionBox::createEditMediaButton() {
|
||||
const auto callback = [=](FileDialog::OpenResult &&result) {
|
||||
auto showBoxErrorCallback = [](tr::phrase<> t) {
|
||||
Ui::show(Box<InformBox>(t(tr::now)), Ui::LayerOption::KeepOther);
|
||||
auto showError = [](tr::phrase<> t) {
|
||||
Ui::Toast::Show(t(tr::now));
|
||||
};
|
||||
|
||||
auto list = Storage::PreparedList::PreparedFileFromFilesDialog(
|
||||
const auto checkResult = [=](const Ui::PreparedList &list) {
|
||||
if (list.files.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
const auto &file = list.files.front();
|
||||
const auto mime = file.information->filemime;
|
||||
if (Core::IsMimeSticker(mime)) {
|
||||
showError(tr::lng_edit_media_invalid_file);
|
||||
return false;
|
||||
} else if (_albumType != Ui::AlbumType::None
|
||||
&& !file.canBeInAlbumType(_albumType)) {
|
||||
showError(tr::lng_edit_media_album_error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
auto list = Storage::PreparedFileFromFilesDialog(
|
||||
std::move(result),
|
||||
_isAlbum,
|
||||
std::move(showBoxErrorCallback),
|
||||
checkResult,
|
||||
showError,
|
||||
st::sendMediaPreviewSize);
|
||||
|
||||
if (list) {
|
||||
_preparedList = std::move(*list);
|
||||
updateEditPreview();
|
||||
setPreparedList(std::move(*list));
|
||||
}
|
||||
};
|
||||
|
||||
const auto buttonCallback = [=] {
|
||||
const auto filters = _isAlbum
|
||||
? FileDialog::AlbumFilesFilter()
|
||||
const auto filters = (_albumType == Ui::AlbumType::PhotoVideo)
|
||||
? FileDialog::PhotoVideoFilesFilter()
|
||||
: FileDialog::AllFilesFilter();
|
||||
FileDialog::GetOpenPath(
|
||||
this,
|
||||
|
|
@ -616,9 +656,10 @@ void EditCaptionBox::createEditMediaButton() {
|
|||
_editMedia.create(this, st::editMediaButton);
|
||||
updateEditMediaButton();
|
||||
_editMedia->setClickedCallback(
|
||||
App::LambdaDelayed(st::historyAttach.ripple.hideDuration, this, [=] {
|
||||
buttonCallback();
|
||||
}));
|
||||
App::LambdaDelayed(
|
||||
st::historyAttach.ripple.hideDuration,
|
||||
this,
|
||||
buttonCallback));
|
||||
}
|
||||
|
||||
void EditCaptionBox::prepare() {
|
||||
|
|
@ -644,7 +685,7 @@ void EditCaptionBox::prepare() {
|
|||
if (action == Ui::InputField::MimeAction::Check) {
|
||||
if (!data->hasText() && !_isAllowedEditMedia) {
|
||||
return false;
|
||||
} else if (Storage::ValidateDragData(data, _isAlbum)) {
|
||||
} else if (Storage::ValidateEditMediaDragData(data, _albumType)) {
|
||||
return true;
|
||||
}
|
||||
return data->hasText();
|
||||
|
|
@ -668,38 +709,32 @@ void EditCaptionBox::prepare() {
|
|||
}
|
||||
|
||||
bool EditCaptionBox::fileFromClipboard(not_null<const QMimeData*> data) {
|
||||
return setPreparedList(ListFromMimeData(data));
|
||||
}
|
||||
|
||||
bool EditCaptionBox::setPreparedList(Ui::PreparedList &&list) {
|
||||
if (!_isAllowedEditMedia) {
|
||||
return false;
|
||||
}
|
||||
using Error = Storage::PreparedList::Error;
|
||||
using AlbumType = Storage::PreparedFile::AlbumType;
|
||||
auto list = ListFromMimeData(data);
|
||||
|
||||
using Error = Ui::PreparedList::Error;
|
||||
using Type = Ui::PreparedFile::Type;
|
||||
if (list.error != Error::None || list.files.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto file = &list.files.front();
|
||||
if (_isAlbum && (file->type == AlbumType::None)) {
|
||||
const auto imageAsDoc = [&] {
|
||||
using Info = FileMediaInformation;
|
||||
const auto fileMedia = &file->information->media;
|
||||
if (const auto image = std::get_if<Info::Image>(fileMedia)) {
|
||||
return !Storage::ValidateThumbDimensions(
|
||||
image->data.width(),
|
||||
image->data.height());
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (!data->hasText() || imageAsDoc) {
|
||||
Ui::show(
|
||||
Box<InformBox>(tr::lng_edit_media_album_error(tr::now)),
|
||||
Ui::LayerOption::KeepOther);
|
||||
auto file = &list.files.front();
|
||||
const auto invalidForAlbum = (_albumType != Ui::AlbumType::None)
|
||||
&& !file->canBeInAlbumType(_albumType);
|
||||
if (_albumType == Ui::AlbumType::PhotoVideo) {
|
||||
using Video = Ui::PreparedFileInformation::Video;
|
||||
if (const auto video = std::get_if<Video>(&file->information->media)) {
|
||||
video->isGifv = false;
|
||||
}
|
||||
}
|
||||
if (invalidForAlbum) {
|
||||
Ui::Toast::Show(tr::lng_edit_media_album_error(tr::now));
|
||||
return false;
|
||||
}
|
||||
_photo = _isImage = (file->type == AlbumType::Photo);
|
||||
_photo = _isImage = (file->type == Type::Photo);
|
||||
_preparedList = std::move(list);
|
||||
updateEditPreview();
|
||||
return true;
|
||||
|
|
@ -749,7 +784,7 @@ void EditCaptionBox::setupDragArea() {
|
|||
auto enterFilter = [=](not_null<const QMimeData*> data) {
|
||||
return !_isAllowedEditMedia
|
||||
? false
|
||||
: Storage::ValidateDragData(data, _isAlbum);
|
||||
: Storage::ValidateEditMediaDragData(data, _albumType);
|
||||
};
|
||||
// Avoid both drag areas appearing at one time.
|
||||
auto computeState = [=](const QMimeData *data) {
|
||||
|
|
@ -780,12 +815,11 @@ void EditCaptionBox::updateBoxSize() {
|
|||
if (_photo) {
|
||||
newHeight += _wayWrap->height() / 2;
|
||||
}
|
||||
const auto &st = _thumbw ? st::msgFileThumbLayout : st::msgFileLayout;
|
||||
if (_photo || _animated) {
|
||||
newHeight += std::max(_thumbh, _gifh);
|
||||
} else if (_thumbw) {
|
||||
newHeight += 0 + st::msgFileThumbSize + 0;
|
||||
} else if (_doc) {
|
||||
newHeight += 0 + st::msgFileSize + 0;
|
||||
} else if (_thumbw || _doc) {
|
||||
newHeight += 0 + st.thumbSize + 0;
|
||||
} else {
|
||||
newHeight += st::boxTitleFont->height;
|
||||
}
|
||||
|
|
@ -854,7 +888,8 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
p.drawPixmap(_thumbx, st::boxPhotoPadding.top() + offset, _thumb);
|
||||
}
|
||||
if (_animated && !_streamed) {
|
||||
QRect inner(_thumbx + (_thumbw - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (th - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
const auto &st = st::msgFileLayout;
|
||||
QRect inner(_thumbx + (_thumbw - st.thumbSize) / 2, st::boxPhotoPadding.top() + (th - st.thumbSize) / 2, st.thumbSize, st.thumbSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgDateImgBg);
|
||||
|
||||
|
|
@ -867,43 +902,35 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
icon->paintInCenter(p, inner);
|
||||
}
|
||||
} else if (_doc) {
|
||||
const auto &st = _thumbw ? st::msgFileThumbLayout : st::msgFileLayout;
|
||||
const auto w = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
const auto h = _thumbw ? (0 + st::msgFileThumbSize + 0) : (0 + st::msgFileSize + 0);
|
||||
auto nameleft = 0, nametop = 0, nameright = 0, statustop = 0;
|
||||
if (_thumbw) {
|
||||
nameleft = 0 + st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
nametop = st::msgFileThumbNameTop - st::msgFileThumbPadding.top();
|
||||
nameright = 0;
|
||||
statustop = st::msgFileThumbStatusTop - st::msgFileThumbPadding.top();
|
||||
} else {
|
||||
nameleft = 0 + st::msgFileSize + st::msgFilePadding.right();
|
||||
nametop = st::msgFileNameTop - st::msgFilePadding.top();
|
||||
nameright = 0;
|
||||
statustop = st::msgFileStatusTop - st::msgFilePadding.top();
|
||||
}
|
||||
const auto h = 0 + st.thumbSize + 0;
|
||||
const auto nameleft = 0 + st.thumbSize + st.padding.right();
|
||||
const auto nametop = st.nameTop - st.padding.top();
|
||||
const auto nameright = 0;
|
||||
const auto statustop = st.statusTop - st.padding.top();
|
||||
const auto editButton = _isAllowedEditMedia
|
||||
? _editMedia->width() + st::editMediaButtonSkip
|
||||
: 0;
|
||||
const auto namewidth = w - nameleft - editButton;
|
||||
const auto x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
|
||||
// App::roundRect(p, x, y, w, h, st::msgInBg, MessageInCorners, &st::msgInShadow);
|
||||
// Ui::FillRoundCorner(p, x, y, w, h, st::msgInBg, Ui::MessageInCorners, &st::msgInShadow);
|
||||
|
||||
const auto rthumb = style::rtlrect(x + 0, y + 0, st.thumbSize, st.thumbSize, width());
|
||||
if (_thumbw) {
|
||||
QRect rthumb(style::rtlrect(x + 0, y + 0, st::msgFileThumbSize, st::msgFileThumbSize, width()));
|
||||
p.drawPixmap(rthumb.topLeft(), _thumb);
|
||||
} else {
|
||||
const QRect inner(style::rtlrect(x + 0, y + 0, st::msgFileSize, st::msgFileSize, width()));
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgFileInBg);
|
||||
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.drawEllipse(inner);
|
||||
p.drawEllipse(rthumb);
|
||||
}
|
||||
|
||||
const auto icon = &(_isAudio ? st::historyFileInPlay : _isImage ? st::historyFileInImage : st::historyFileInDocument);
|
||||
icon->paintInCenter(p, inner);
|
||||
icon->paintInCenter(p, rthumb);
|
||||
}
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::historyFileNameInFg);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/abstract_box.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/chat/attach/attach_prepare.h"
|
||||
|
||||
class Image;
|
||||
|
||||
|
|
@ -32,6 +33,7 @@ class InputField;
|
|||
class EmojiButton;
|
||||
class IconButton;
|
||||
class Checkbox;
|
||||
enum class AlbumType;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
|
@ -92,6 +94,7 @@ private:
|
|||
int errorTopSkip() const;
|
||||
|
||||
void createEditMediaButton();
|
||||
bool setPreparedList(Ui::PreparedList &&list);
|
||||
|
||||
inline QString getNewMediaPath() {
|
||||
return _preparedList.files.empty()
|
||||
|
|
@ -130,15 +133,15 @@ private:
|
|||
int _gifh = 0;
|
||||
int _gifx = 0;
|
||||
|
||||
Storage::PreparedList _preparedList;
|
||||
Ui::PreparedList _preparedList;
|
||||
|
||||
mtpRequestId _saveRequestId = 0;
|
||||
|
||||
object_ptr<Ui::IconButton> _editMedia = nullptr;
|
||||
Ui::SlideWrap<Ui::RpWidget> *_wayWrap = nullptr;
|
||||
QString _newMediaPath;
|
||||
Ui::AlbumType _albumType = Ui::AlbumType();
|
||||
bool _isAllowedEditMedia = false;
|
||||
bool _isAlbum = false;
|
||||
bool _asFile = false;
|
||||
rpl::event_stream<> _editMediaClicks;
|
||||
|
||||
|
|
|
|||
|
|
@ -77,8 +77,12 @@ std::vector<not_null<PeerData*>> PrivacyExceptionsBoxController::getResult() con
|
|||
}
|
||||
|
||||
void PrivacyExceptionsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
const auto peer = row->peer();
|
||||
|
||||
// This call may delete row, if it was a search result row.
|
||||
delegate()->peerListSetRowChecked(row, !row->checked());
|
||||
if (const auto channel = row->peer()->asChannel()) {
|
||||
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
if (!channel->membersCountKnown()) {
|
||||
channel->updateFull();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/filters/edit_filter_chats_list.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "mainwidget.h"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "data/data_peer_values.h"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_histories.h"
|
||||
#include "apiwrap.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "history/history.h"
|
||||
#include "dialogs/dialogs_main_list.h"
|
||||
|
|
@ -104,6 +105,20 @@ void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
|
|||
// return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||
//}
|
||||
|
||||
object_ptr<Ui::BoxContent> PrepareContactsBox(
|
||||
not_null<Window::SessionController*> sessionController) {
|
||||
const auto controller = sessionController;
|
||||
auto delegate = [=](not_null<PeerListBox*> box) {
|
||||
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
|
||||
box->addLeftButton(
|
||||
tr::lng_profile_add_contact(),
|
||||
[=] { controller->widget()->onShowAddContact(); });
|
||||
};
|
||||
return Box<PeerListBox>(
|
||||
std::make_unique<ContactsBoxController>(controller),
|
||||
std::move(delegate));
|
||||
}
|
||||
|
||||
void PeerListRowWithLink::setActionLink(const QString &action) {
|
||||
_action = action;
|
||||
refreshActionLink();
|
||||
|
|
|
|||
|
|
@ -31,9 +31,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
class History;
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
class SessionNavigation;
|
||||
} // namespace Window
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareContactsBox(
|
||||
not_null<Window::SessionController*> sessionController);
|
||||
|
||||
class PeerListRowWithLink : public PeerListRow {
|
||||
public:
|
||||
using PeerListRow::PeerListRow;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@ public:
|
|||
AdminDoneCallback adminDoneCallback,
|
||||
BannedDoneCallback bannedDoneCallback);
|
||||
|
||||
[[nodiscard]] not_null<PeerData*> peer() const {
|
||||
return _peer;
|
||||
}
|
||||
[[nodiscard]] Main::Session &session() const override;
|
||||
void prepare() override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "chat_helpers/emoji_suggestions_widget.h"
|
||||
#include "settings/settings_privacy_security.h"
|
||||
|
|
@ -326,7 +326,7 @@ void EditAdminBox::prepare() {
|
|||
}, lifetime());
|
||||
|
||||
if (canTransferOwnership()) {
|
||||
const auto allFlags = FullAdminRights(isGroup);
|
||||
const auto allFlags = AdminRightsForOwnershipTransfer(isGroup);
|
||||
setupTransferButton(
|
||||
isGroup
|
||||
)->toggleOn(rpl::duplicate(
|
||||
|
|
|
|||
|
|
@ -559,6 +559,8 @@ UserData *ParticipantsAdditionalData::applyParticipant(
|
|||
return logBad();
|
||||
}
|
||||
return applyBanned(data);
|
||||
}, [&](const MTPDchannelParticipantLeft &data) {
|
||||
return logBad();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -305,10 +305,12 @@ ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions) {
|
|||
return restrictions;
|
||||
}
|
||||
|
||||
ChatAdminRights FullAdminRights(bool isGroup) {
|
||||
ChatAdminRights AdminRightsForOwnershipTransfer(bool isGroup) {
|
||||
auto result = ChatAdminRights();
|
||||
for (const auto &[flag, label] : AdminRightLabels(isGroup, true)) {
|
||||
result |= flag;
|
||||
if (!(flag & ChatAdminRight::f_anonymous)) {
|
||||
result |= flag;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,4 +71,4 @@ EditFlagsControl<MTPDchatAdminRights::Flags> CreateEditAdminRights(
|
|||
|
||||
ChatAdminRights DisabledByDefaultRestrictions(not_null<PeerData*> peer);
|
||||
ChatRestrictions FixDependentRestrictions(ChatRestrictions restrictions);
|
||||
ChatAdminRights FullAdminRights(bool isGroup);
|
||||
ChatAdminRights AdminRightsForOwnershipTransfer(bool isGroup);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <rpl/variable.h>
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "ui/chat/attach/attach_prepare.h"
|
||||
#include "ui/chat/attach/attach_send_files_way.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
|
||||
|
|
@ -26,14 +28,13 @@ class TabbedPanel;
|
|||
} // namespace ChatHelpers
|
||||
|
||||
namespace Ui {
|
||||
template <typename Enum>
|
||||
class Radioenum;
|
||||
template <typename Enum>
|
||||
class RadioenumGroup;
|
||||
class Checkbox;
|
||||
class RoundButton;
|
||||
class InputField;
|
||||
struct GroupMediaLayout;
|
||||
class EmojiButton;
|
||||
class AlbumPreview;
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
|
@ -44,12 +45,6 @@ namespace SendMenu {
|
|||
enum class Type;
|
||||
} // namespace SendMenu
|
||||
|
||||
enum class SendFilesWay {
|
||||
Album,
|
||||
Photos,
|
||||
Files,
|
||||
};
|
||||
|
||||
class SendFilesBox : public Ui::BoxContent {
|
||||
public:
|
||||
enum class SendLimit {
|
||||
|
|
@ -59,17 +54,16 @@ public:
|
|||
SendFilesBox(
|
||||
QWidget*,
|
||||
not_null<Window::SessionController*> controller,
|
||||
Storage::PreparedList &&list,
|
||||
Ui::PreparedList &&list,
|
||||
const TextWithTags &caption,
|
||||
CompressConfirm compressed,
|
||||
SendLimit limit,
|
||||
Api::SendType sendType,
|
||||
SendMenu::Type sendMenuType);
|
||||
|
||||
void setConfirmedCallback(
|
||||
Fn<void(
|
||||
Storage::PreparedList &&list,
|
||||
SendFilesWay way,
|
||||
Ui::PreparedList &&list,
|
||||
Ui::SendFilesWay way,
|
||||
TextWithTags &&caption,
|
||||
Api::SendOptions options,
|
||||
bool ctrlShiftEnter)> callback) {
|
||||
|
|
@ -90,65 +84,92 @@ protected:
|
|||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
class AlbumPreview;
|
||||
class Block final {
|
||||
public:
|
||||
Block(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<std::vector<Ui::PreparedFile>*> items,
|
||||
int from,
|
||||
int till,
|
||||
Fn<bool()> gifPaused,
|
||||
Ui::SendFilesWay way);
|
||||
Block(Block &&other) = default;
|
||||
Block &operator=(Block &&other) = default;
|
||||
|
||||
[[nodiscard]] int fromIndex() const;
|
||||
[[nodiscard]] int tillIndex() const;
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> takeWidget();
|
||||
|
||||
[[nodiscard]] rpl::producer<int> itemDeleteRequest() const;
|
||||
[[nodiscard]] rpl::producer<int> itemReplaceRequest() const;
|
||||
|
||||
void setSendWay(Ui::SendFilesWay way);
|
||||
void applyAlbumOrder();
|
||||
|
||||
private:
|
||||
base::unique_qptr<Ui::RpWidget> _preview;
|
||||
not_null<std::vector<Ui::PreparedFile>*> _items;
|
||||
int _from = 0;
|
||||
int _till = 0;
|
||||
bool _isAlbum = false;
|
||||
bool _isSingleMedia = false;
|
||||
|
||||
};
|
||||
void initSendWay();
|
||||
void initPreview(rpl::producer<int> desiredPreviewHeight);
|
||||
void initPreview();
|
||||
|
||||
void setupControls();
|
||||
void refreshControls();
|
||||
void setupSendWayControls();
|
||||
void setupCaption();
|
||||
void setupShadows(
|
||||
not_null<Ui::ScrollArea*> wrap,
|
||||
not_null<AlbumPreview*> content);
|
||||
void setupShadows();
|
||||
|
||||
void setupEmojiPanel();
|
||||
void updateSendWayControlsVisibility();
|
||||
void updateEmojiPanelGeometry();
|
||||
void emojiFilterForGeometry(not_null<QEvent*> event);
|
||||
|
||||
void refreshAlbumMediaCount();
|
||||
void preparePreview();
|
||||
void prepareSingleFilePreview();
|
||||
void prepareAlbumPreview();
|
||||
void applyAlbumOrder();
|
||||
void generatePreviewFrom(int fromBlock);
|
||||
|
||||
void send(Api::SendOptions options, bool ctrlShiftEnter = false);
|
||||
void sendSilent();
|
||||
void sendScheduled();
|
||||
void captionResized();
|
||||
void saveSendWaySettings();
|
||||
|
||||
void setupDragArea();
|
||||
void setupTitleText();
|
||||
void refreshTitleText();
|
||||
void updateBoxSize();
|
||||
void updateControlsGeometry();
|
||||
void updateCaptionPlaceholder();
|
||||
|
||||
void addThumbButtonHandlers(not_null<Ui::ScrollArea*> wrap);
|
||||
|
||||
bool canAddFiles(not_null<const QMimeData*> data) const;
|
||||
bool addFiles(not_null<const QMimeData*> data);
|
||||
bool addFiles(Storage::PreparedList list);
|
||||
bool addFiles(Ui::PreparedList list);
|
||||
void addFile(Ui::PreparedFile &&file);
|
||||
void pushBlock(int from, int till);
|
||||
|
||||
void openDialogToAddFileToAlbum();
|
||||
void updateLeftButtonVisibility();
|
||||
void refreshAllAfterAlbumChanges();
|
||||
void refreshAllAfterChanges(int fromItem);
|
||||
|
||||
void enqueueNextPrepare();
|
||||
void addPreparedAsyncFile(Ui::PreparedFile &&file);
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const Api::SendType _sendType = Api::SendType();
|
||||
|
||||
QString _titleText;
|
||||
int _titleHeight = 0;
|
||||
rpl::variable<int> _titleHeight = 0;
|
||||
|
||||
Storage::PreparedList _list;
|
||||
Ui::PreparedList _list;
|
||||
std::optional<int> _removingIndex;
|
||||
|
||||
CompressConfirm _compressConfirmInitial = CompressConfirm::None;
|
||||
CompressConfirm _compressConfirm = CompressConfirm::None;
|
||||
SendLimit _sendLimit = SendLimit::Many;
|
||||
SendMenu::Type _sendMenuType = SendMenu::Type();
|
||||
|
||||
Fn<void(
|
||||
Storage::PreparedList &&list,
|
||||
SendFilesWay way,
|
||||
Ui::PreparedList &&list,
|
||||
Ui::SendFilesWay way,
|
||||
TextWithTags &&caption,
|
||||
Api::SendOptions options,
|
||||
bool ctrlShiftEnter)> _confirmedCallback;
|
||||
|
|
@ -160,22 +181,20 @@ private:
|
|||
base::unique_qptr<ChatHelpers::TabbedPanel> _emojiPanel;
|
||||
base::unique_qptr<QObject> _emojiFilter;
|
||||
|
||||
object_ptr<Ui::Radioenum<SendFilesWay>> _sendAlbum = { nullptr };
|
||||
object_ptr<Ui::Radioenum<SendFilesWay>> _sendPhotos = { nullptr };
|
||||
object_ptr<Ui::Radioenum<SendFilesWay>> _sendFiles = { nullptr };
|
||||
std::shared_ptr<Ui::RadioenumGroup<SendFilesWay>> _sendWay;
|
||||
object_ptr<Ui::Checkbox> _groupFiles = { nullptr };
|
||||
object_ptr<Ui::Checkbox> _sendImagesAsPhotos = { nullptr };
|
||||
rpl::variable<Ui::SendFilesWay> _sendWay = Ui::SendFilesWay();
|
||||
|
||||
rpl::variable<int> _footerHeight = 0;
|
||||
rpl::event_stream<> _albumChanged;
|
||||
rpl::lifetime _dimensionsLifetime;
|
||||
|
||||
QWidget *_preview = nullptr;
|
||||
AlbumPreview *_albumPreview = nullptr;
|
||||
int _albumVideosCount = 0;
|
||||
int _albumPhotosCount = 0;
|
||||
|
||||
int _lastScrollTop = 0;
|
||||
object_ptr<Ui::ScrollArea> _scroll;
|
||||
QPointer<Ui::VerticalLayout> _inner;
|
||||
std::vector<Block> _blocks;
|
||||
Fn<void()> _whenReadySend;
|
||||
bool _preparing = false;
|
||||
|
||||
QPointer<Ui::RoundButton> _send;
|
||||
QPointer<Ui::RoundButton> _addFileToAlbum;
|
||||
QPointer<Ui::RoundButton> _addFile;
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "chat_helpers/message_field.h"
|
||||
#include "chat_helpers/send_context_menu.h"
|
||||
#include "history/history.h"
|
||||
|
|
@ -41,7 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/application.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_info.h"
|
||||
|
||||
class ShareBox::Inner final : public Ui::RpWidget, private base::Subscriber {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/emoji_config.h"
|
||||
#include "ui/toast/toast.h"
|
||||
//#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "lottie/lottie_multi_player.h"
|
||||
#include "lottie/lottie_animation.h"
|
||||
#include "chat_helpers/stickers_lottie.h"
|
||||
|
|
@ -36,7 +37,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "apiwrap.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_info.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
|
@ -720,7 +720,7 @@ void StickerSetBox::Inner::paintSticker(
|
|||
p.setOpacity(over);
|
||||
auto tl = position;
|
||||
if (rtl()) tl.setX(width() - tl.x() - st::stickersSize.width());
|
||||
App::roundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, StickerHoverCorners);
|
||||
Ui::FillRoundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, Ui::StickerHoverCorners);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "main/main_session.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
|
@ -1129,7 +1129,7 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
|
|||
Ui::Shadow::paint(p, rect, width(), st::boxRoundShadow);
|
||||
p.setOpacity(1);
|
||||
|
||||
App::roundRect(p, rect, st::boxBg, BoxCorners);
|
||||
Ui::FillRoundRect(p, rect, st::boxBg, Ui::BoxCorners);
|
||||
|
||||
p.setOpacity(1. - current);
|
||||
paintFakeButton(p, row, index);
|
||||
|
|
@ -1318,7 +1318,7 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int ind
|
|||
auto textWidth = (_section == Section::Installed) ? _undoWidth : _addWidth;
|
||||
auto &text = (_section == Section::Installed) ? _undoText : _addText;
|
||||
auto &textBg = selected ? st.textBgOver : st.textBg;
|
||||
App::roundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small);
|
||||
Ui::FillRoundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small);
|
||||
if (row->ripple) {
|
||||
row->ripple->paint(p, rect.x(), rect.y(), width());
|
||||
if (row->ripple->empty()) {
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ void BoxController::loadMoreRows() {
|
|||
MTP_flags(0),
|
||||
MTP_inputPeerEmpty(),
|
||||
MTP_string(),
|
||||
MTP_inputUserEmpty(),
|
||||
MTP_inputPeerEmpty(),
|
||||
MTPint(), // top_msg_id
|
||||
MTP_inputMessagesFilterPhoneCalls(MTP_flags(0)),
|
||||
MTP_int(0),
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "app.h"
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "ui/platform/win/ui_window_title_win.h"
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ void Style::paintButtonBg(
|
|||
Painter &p,
|
||||
const QRect &rect,
|
||||
float64 howMuchOver) const {
|
||||
App::roundRect(p, rect, st::botKbBg, BotKeyboardCorners);
|
||||
Ui::FillRoundRect(p, rect, st::botKbBg, Ui::BotKeyboardCorners);
|
||||
}
|
||||
|
||||
void Style::paintButtonIcon(
|
||||
|
|
|
|||
|
|
@ -278,3 +278,6 @@ manageEmojiPreviewPadding: margins(22px, 9px, 19px, 9px);
|
|||
manageEmojiMarginRight: 21px;
|
||||
manageEmojiNameTop: 3px;
|
||||
manageEmojiStatusTop: 25px;
|
||||
|
||||
inlineRadialSize: 44px;
|
||||
inlineFileSize: 44px;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "emoji_suggestions_data.h"
|
||||
#include "emoji_suggestions_helper.h"
|
||||
|
|
@ -20,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/application.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
||||
namespace ChatHelpers {
|
||||
|
|
@ -211,7 +211,7 @@ void EmojiColorPicker::paintEvent(QPaintEvent *e) {
|
|||
return;
|
||||
}
|
||||
Ui::Shadow::paint(p, inner, width(), st::defaultRoundShadow);
|
||||
App::roundRect(p, inner, st::boxBg, BoxCorners);
|
||||
Ui::FillRoundRect(p, inner, st::boxBg, Ui::BoxCorners);
|
||||
|
||||
auto x = st::emojiPanMargins.left() + 2 * st::emojiColorsPadding + _singleSize.width();
|
||||
if (rtl()) x = width() - x - st::emojiColorsSep;
|
||||
|
|
@ -372,7 +372,7 @@ void EmojiColorPicker::drawVariant(Painter &p, int variant) {
|
|||
if (variant == _selected) {
|
||||
QPoint tl(w);
|
||||
if (rtl()) tl.setX(width() - tl.x() - _singleSize.width());
|
||||
App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
|
||||
Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners);
|
||||
}
|
||||
const auto esize = Ui::Emoji::GetSizeLarge();
|
||||
Ui::Emoji::Draw(
|
||||
|
|
@ -558,7 +558,7 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) {
|
|||
if (selected) {
|
||||
auto tl = w;
|
||||
if (rtl()) tl.setX(width() - tl.x() - _singleSize.width());
|
||||
App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
|
||||
Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners);
|
||||
}
|
||||
Ui::Emoji::Draw(
|
||||
p,
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "core/application.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "main/main_session.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
|
|
@ -218,11 +218,11 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) {
|
|||
? _pressed
|
||||
: _selectedAnimation.value(_selected);
|
||||
if (selected > -1.) {
|
||||
App::roundRect(
|
||||
Ui::FillRoundRect(
|
||||
p,
|
||||
QRect(selected * _oneWidth, 0, _oneWidth, _oneWidth),
|
||||
st::emojiPanHover,
|
||||
StickerHoverCorners);
|
||||
Ui::StickerHoverCorners);
|
||||
}
|
||||
|
||||
for (auto i = from; i != till; ++i) {
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ 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 "ui/cached_round_corners.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
||||
|
|
@ -690,7 +690,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
if (_sel == index) {
|
||||
QPoint tl(pos);
|
||||
if (rtl()) tl.setX(width() - tl.x() - st::stickerPanSize.width());
|
||||
App::roundRect(p, QRect(tl, st::stickerPanSize), st::emojiPanHover, StickerHoverCorners);
|
||||
Ui::FillRoundRect(p, QRect(tl, st::stickerPanSize), st::emojiPanHover, Ui::StickerHoverCorners);
|
||||
}
|
||||
|
||||
media->checkStickerSmall();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtCore/QStack>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Stickers {
|
||||
|
||||
const QString DicePacks::kDiceString = QString::fromUtf8("\xF0\x9F\x8E\xB2");
|
||||
const QString DicePacks::kDartString = QString::fromUtf8("\xF0\x9F\x8E\xAF");
|
||||
const QString DicePacks::kSlotString = QString::fromUtf8("\xF0\x9F\x8E\xB0");
|
||||
const QString DicePacks::kFballString = QString::fromUtf8("\xE2\x9A\xBD");
|
||||
const QString DicePacks::kBballString = QString::fromUtf8("\xF0\x9F\x8F\x80");
|
||||
|
||||
DicePack::DicePack(not_null<Main::Session*> session, const QString &emoji)
|
||||
: _session(session)
|
||||
, _emoji(emoji) {
|
||||
|
|
@ -52,15 +58,23 @@ void DicePack::load() {
|
|||
}
|
||||
|
||||
void DicePack::applySet(const MTPDmessages_stickerSet &data) {
|
||||
_map.clear();
|
||||
const auto isSlotMachine = DicePacks::IsSlot(_emoji);
|
||||
auto index = 0;
|
||||
auto documents = base::flat_map<DocumentId, not_null<DocumentData*>>();
|
||||
for (const auto &sticker : data.vdocuments().v) {
|
||||
const auto document = _session->data().processDocument(
|
||||
sticker);
|
||||
if (document->sticker()) {
|
||||
documents.emplace(document->id, document);
|
||||
if (isSlotMachine) {
|
||||
_map.emplace(index++, document);
|
||||
} else {
|
||||
documents.emplace(document->id, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSlotMachine) {
|
||||
return;
|
||||
}
|
||||
for (const auto pack : data.vpacks().v) {
|
||||
pack.match([&](const MTPDstickerPack &data) {
|
||||
const auto emoji = qs(data.vemoticon());
|
||||
|
|
@ -86,16 +100,25 @@ void DicePack::tryGenerateLocalZero() {
|
|||
return;
|
||||
}
|
||||
|
||||
static const auto kDiceString = QString::fromUtf8("\xF0\x9F\x8E\xB2");
|
||||
static const auto kDartString = QString::fromUtf8("\xF0\x9F\x8E\xAF");
|
||||
const auto path = (_emoji == kDiceString)
|
||||
? qsl(":/gui/art/dice_idle.tgs")
|
||||
: (_emoji == kDartString)
|
||||
? qsl(":/gui/art/dart_idle.tgs")
|
||||
: QString();
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
if (_emoji == DicePacks::kDiceString) {
|
||||
generateLocal(0, u"dice_idle"_q);
|
||||
} else if (_emoji == DicePacks::kDartString) {
|
||||
generateLocal(0, u"dart_idle"_q);
|
||||
} else if (_emoji == DicePacks::kBballString) {
|
||||
generateLocal(0, u"bball_idle"_q);
|
||||
} else if (_emoji == DicePacks::kFballString) {
|
||||
generateLocal(0, u"fball_idle"_q);
|
||||
} else if (_emoji == DicePacks::kSlotString) {
|
||||
generateLocal(0, u"slot_back"_q);
|
||||
generateLocal(2, u"slot_pull"_q);
|
||||
generateLocal(8, u"slot_0_idle"_q);
|
||||
generateLocal(14, u"slot_1_idle"_q);
|
||||
generateLocal(20, u"slot_2_idle"_q);
|
||||
}
|
||||
}
|
||||
|
||||
void DicePack::generateLocal(int index, const QString &name) {
|
||||
const auto path = u":/gui/art/"_q + name + u".tgs"_q;
|
||||
auto task = FileLoadTask(
|
||||
_session,
|
||||
path,
|
||||
|
|
@ -104,15 +127,15 @@ void DicePack::tryGenerateLocalZero() {
|
|||
SendMediaType::File,
|
||||
FileLoadTo(0, {}, 0),
|
||||
{});
|
||||
task.process();
|
||||
task.process({ .generateGoodThumbnail = false });
|
||||
const auto result = task.peekResult();
|
||||
Assert(result != nullptr);
|
||||
const auto document = _session->data().processDocument(
|
||||
result->document,
|
||||
Images::FromImageInMemory(result->thumb, "PNG"));
|
||||
document->setLocation(FileLocation(path));
|
||||
Images::FromImageInMemory(result->thumb, "WEBP", result->thumbbytes));
|
||||
document->setLocation(Core::FileLocation(path));
|
||||
|
||||
_map.emplace(0, document);
|
||||
_map.emplace(index, document);
|
||||
|
||||
Ensures(document->sticker());
|
||||
Ensures(document->sticker()->animated);
|
||||
|
|
@ -122,13 +145,16 @@ DicePacks::DicePacks(not_null<Main::Session*> session) : _session(session) {
|
|||
}
|
||||
|
||||
DocumentData *DicePacks::lookup(const QString &emoji, int value) {
|
||||
const auto i = _packs.find(emoji);
|
||||
const auto key = emoji.endsWith(QChar(0xFE0F))
|
||||
? emoji.mid(0, emoji.size() - 1)
|
||||
: emoji;
|
||||
const auto i = _packs.find(key);
|
||||
if (i != end(_packs)) {
|
||||
return i->second->lookup(value);
|
||||
}
|
||||
return _packs.emplace(
|
||||
emoji,
|
||||
std::make_unique<DicePack>(_session, emoji)
|
||||
key,
|
||||
std::make_unique<DicePack>(_session, key)
|
||||
).first->second->lookup(value);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,13 @@ public:
|
|||
DicePack(not_null<Main::Session*> session, const QString &emoji);
|
||||
~DicePack();
|
||||
|
||||
DocumentData *lookup(int value);
|
||||
[[nodiscard]] DocumentData *lookup(int value);
|
||||
|
||||
private:
|
||||
void load();
|
||||
void applySet(const MTPDmessages_stickerSet &data);
|
||||
void tryGenerateLocalZero();
|
||||
void generateLocal(int index, const QString &name);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
QString _emoji;
|
||||
|
|
@ -39,7 +40,17 @@ class DicePacks final {
|
|||
public:
|
||||
explicit DicePacks(not_null<Main::Session*> session);
|
||||
|
||||
DocumentData *lookup(const QString &emoji, int value);
|
||||
static const QString kDiceString;
|
||||
static const QString kDartString;
|
||||
static const QString kSlotString;
|
||||
static const QString kFballString;
|
||||
static const QString kBballString;
|
||||
|
||||
[[nodiscard]] static bool IsSlot(const QString &emoji) {
|
||||
return (emoji == kSlotString);
|
||||
}
|
||||
|
||||
[[nodiscard]] DocumentData *lookup(const QString &emoji, int value);
|
||||
|
||||
private:
|
||||
const not_null<Main::Session*> _session;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "chat_helpers/stickers_emoji_image_loader.h"
|
||||
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
namespace Stickers {
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/call_delayed.h"
|
||||
#include "apiwrap.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_history.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
#include <QtCore/QBuffer>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "lottie/lottie_multi_player.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "lottie/lottie_animation.h"
|
||||
|
|
@ -38,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session_settings.h"
|
||||
#include "apiwrap.h"
|
||||
#include "api/api_toggling_media.h" // Api::ToggleFavedSticker
|
||||
#include "app.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
|
|
@ -1541,7 +1541,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
auto selected = selectedButton ? (selectedButton->section == info.section) : false;
|
||||
auto &textBg = selected ? st::stickersTrendingAdd.textBgOver : st::stickersTrendingAdd.textBg;
|
||||
|
||||
App::roundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small);
|
||||
Ui::FillRoundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small);
|
||||
if (set.ripple) {
|
||||
set.ripple->paint(p, add.x(), add.y(), width());
|
||||
if (set.ripple->empty()) {
|
||||
|
|
@ -1771,7 +1771,7 @@ void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSe
|
|||
: st::stickerGroupCategoryAdd.textBg;
|
||||
|
||||
auto button = _megagroupSetButtonRect.translated(0, y);
|
||||
App::roundRect(p, myrtlrect(button), textBg, ImageRoundRadius::Small);
|
||||
Ui::FillRoundRect(p, myrtlrect(button), textBg, ImageRoundRadius::Small);
|
||||
if (_megagroupSetButtonRipple) {
|
||||
_megagroupSetButtonRipple->paint(p, button.x(), button.y(), width());
|
||||
if (_megagroupSetButtonRipple->empty()) {
|
||||
|
|
@ -1851,7 +1851,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
|
|||
if (selected) {
|
||||
auto tl = pos;
|
||||
if (rtl()) tl.setX(width() - tl.x() - _singleSize.width());
|
||||
App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
|
||||
Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners);
|
||||
}
|
||||
|
||||
media->checkStickerSmall();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_session_settings.h"
|
||||
|
|
@ -521,10 +522,10 @@ void TabbedSelector::paintSlideFrame(Painter &p) {
|
|||
if (_roundRadius > 0) {
|
||||
if (full()) {
|
||||
auto topPart = QRect(0, 0, width(), _tabsSlider->height() + _roundRadius);
|
||||
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
|
||||
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
|
||||
} else {
|
||||
auto topPart = QRect(0, 0, width(), 3 * _roundRadius);
|
||||
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
|
||||
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
|
||||
}
|
||||
} else if (full()) {
|
||||
p.fillRect(0, 0, width(), _tabsSlider->height(), st::emojiPanBg);
|
||||
|
|
@ -538,15 +539,15 @@ void TabbedSelector::paintContent(Painter &p) {
|
|||
if (_roundRadius > 0) {
|
||||
if (full()) {
|
||||
auto topPart = QRect(0, 0, width(), _tabsSlider->height() + _roundRadius);
|
||||
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
|
||||
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::NoTopBottom);
|
||||
} else {
|
||||
auto topPart = QRect(0, 0, width(), 3 * _roundRadius);
|
||||
App::roundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
|
||||
Ui::FillRoundRect(p, topPart, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop);
|
||||
}
|
||||
|
||||
auto bottomPart = QRect(0, _footerTop - _roundRadius, width(), st::emojiFooterHeight + _roundRadius);
|
||||
auto bottomParts = RectPart::NoTopBottom | RectPart::FullBottom;
|
||||
App::roundRect(p, bottomPart, bottomBg, ImageRoundRadius::Small, bottomParts);
|
||||
Ui::FillRoundRect(p, bottomPart, bottomBg, ImageRoundRadius::Small, bottomParts);
|
||||
} else {
|
||||
if (full()) {
|
||||
p.fillRect(0, 0, width(), _tabsSlider->height(), st::emojiPanBg);
|
||||
|
|
|
|||
|
|
@ -22,13 +22,8 @@ enum {
|
|||
LocalEncryptSaltSize = 32, // 256 bit
|
||||
|
||||
AnimationTimerDelta = 7,
|
||||
ClipThreadsCount = 8,
|
||||
AverageGifSize = 320 * 240,
|
||||
WaitBeforeGifPause = 200, // wait 200ms for gif draw before pausing it
|
||||
RecentInlineBotsLimit = 10,
|
||||
|
||||
AVBlockSize = 4096, // 4Kb for ffmpeg blocksize
|
||||
|
||||
AutoSearchTimeout = 900, // 0.9 secs
|
||||
SearchPerPage = 50,
|
||||
SearchManyPerPage = 100,
|
||||
|
|
@ -105,25 +100,3 @@ inline const QRegularExpression &cRussianLetters() {
|
|||
static QRegularExpression regexp(QString::fromUtf8("[а-яА-ЯёЁ]"));
|
||||
return regexp;
|
||||
}
|
||||
|
||||
inline const QStringList &cImgExtensions() {
|
||||
static QStringList result;
|
||||
if (result.isEmpty()) {
|
||||
result.reserve(4);
|
||||
result.push_back(qsl(".jpg"));
|
||||
result.push_back(qsl(".jpeg"));
|
||||
result.push_back(qsl(".png"));
|
||||
result.push_back(qsl(".gif"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const QStringList &cExtensionsForCompress() {
|
||||
static QStringList result;
|
||||
if (result.isEmpty()) {
|
||||
result.push_back(qsl(".jpg"));
|
||||
result.push_back(qsl(".jpeg"));
|
||||
result.push_back(qsl(".png"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "chat_helpers/emoji_keywords.h"
|
||||
#include "chat_helpers/stickers_emoji_image_loader.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/base_platform_last_input.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "mainwindow.h"
|
||||
#include "dialogs/dialogs_entry.h"
|
||||
|
|
@ -57,7 +58,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_location_manager.h"
|
||||
#include "ui/widgets/tooltip.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "storage/serialize_common.h"
|
||||
|
|
@ -79,7 +80,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <QtCore/QMimeDatabase>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QDesktopServices>
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
|
|
@ -832,7 +832,7 @@ void Application::updateNonIdle() {
|
|||
|
||||
crl::time Application::lastNonIdleTime() const {
|
||||
return std::max(
|
||||
Platform::LastUserInputTime().value_or(0),
|
||||
base::Platform::LastUserInputTime().value_or(0),
|
||||
_lastNonIdleTime);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,26 +23,6 @@ namespace {
|
|||
|
||||
std::map<int, const char*> BetaLogs() {
|
||||
return {
|
||||
{
|
||||
1009020,
|
||||
"- Fix crash in shared links search.\n"
|
||||
|
||||
"- Fix blurred thumbnails in albums with video files.\n"
|
||||
|
||||
"- Fix a possible crash in animated stickers rendering."
|
||||
},
|
||||
{
|
||||
1009022,
|
||||
"- Organize chats into Chat Folders if you have too many chats.\n"
|
||||
},
|
||||
{
|
||||
2000001,
|
||||
"- Switch between folders using Ctrl+1, ..., Ctrl+8.\n"
|
||||
|
||||
"- Fix crash when a pinned in folder chat was added to archive.\n"
|
||||
|
||||
"- Fix font issues in Linux version."
|
||||
},
|
||||
{
|
||||
2001008,
|
||||
"- Add support for full group message history export.\n"
|
||||
|
|
@ -97,6 +77,16 @@ std::map<int, const char*> BetaLogs() {
|
|||
|
||||
"- Enjoy dark native window frame for Telegram night mode on Windows.\n"
|
||||
},
|
||||
{
|
||||
2004006,
|
||||
"- Fix image compression option when sending files with drag-n-drop.\n"
|
||||
|
||||
"- Fix caption text selection in media albums.\n"
|
||||
|
||||
"- Fix drafts display in personal chats in the chats list.\n"
|
||||
|
||||
"- Bug fixes and other minor improvements.\n"
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
namespace {
|
||||
|
||||
bool UrlRequiresConfirmation(const QUrl &url) {
|
||||
using namespace qthelp;
|
||||
return !regex_match(qsl("(^|\\.)(telegram\\.org|telegra\\.ph|telesco\\.pe)$"), url.host(), RegExOption::CaseInsensitive);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
return !regex_match(
|
||||
"(^|\\.)(telegram\\.(org|me|dog)|t\\.me|telegra\\.ph|telesco\\.pe)$",
|
||||
url.host(),
|
||||
RegExOption::CaseInsensitive);
|
||||
}
|
||||
|
||||
void HiddenUrlClickHandler::Open(QString url, QVariant context) {
|
||||
url = Core::TryConvertUrlToLocal(url);
|
||||
|
|
@ -49,7 +49,7 @@ void HiddenUrlClickHandler::Open(QString url, QVariant context) {
|
|||
open();
|
||||
} else {
|
||||
const auto parsedUrl = QUrl::fromUserInput(url);
|
||||
if (UrlRequiresConfirmation(url)
|
||||
if (UrlRequiresConfirmation(parsedUrl)
|
||||
&& QGuiApplication::keyboardModifiers() != Qt::ControlModifier) {
|
||||
Core::App().hideMediaView();
|
||||
const auto displayed = parsedUrl.isValid()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ namespace Main {
|
|||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
[[nodiscard]] bool UrlRequiresConfirmation(const QUrl &url);
|
||||
|
||||
class HiddenUrlClickHandler : public UrlClickHandler {
|
||||
public:
|
||||
HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Core {
|
||||
|
||||
Settings::Settings()
|
||||
: _sendFilesWay(SendFilesWay::Album)
|
||||
, _sendSubmitWay(Ui::InputSubmitSettings::Enter)
|
||||
: _sendSubmitWay(Ui::InputSubmitSettings::Enter)
|
||||
, _floatPlayerColumn(Window::Column::Second)
|
||||
, _floatPlayerCorner(RectPart::TopRight)
|
||||
, _dialogsWidthRatio(DefaultDialogsWidthRatio()) {
|
||||
|
|
@ -75,7 +74,7 @@ QByteArray Settings::serialize() const {
|
|||
stream << key << value;
|
||||
}
|
||||
stream
|
||||
<< qint32(_sendFilesWay)
|
||||
<< qint32(_sendFilesWay.serialize())
|
||||
<< qint32(_sendSubmitWay)
|
||||
<< qint32(_includeMutedCounter ? 1 : 0)
|
||||
<< qint32(_countUnreadMessages ? 1 : 0)
|
||||
|
|
@ -109,7 +108,8 @@ QByteArray Settings::serialize() const {
|
|||
<< qint32(_notifyFromAll ? 1 : 0)
|
||||
<< qint32(_nativeWindowFrame.current() ? 1 : 0)
|
||||
<< qint32(_systemDarkModeEnabled.current() ? 1 : 0)
|
||||
<< _callVideoInputDeviceId;
|
||||
<< _callVideoInputDeviceId
|
||||
<< qint32(_ipRevealWarning ? 1 : 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
qint32 lastSeenWarningSeen = _lastSeenWarningSeen ? 1 : 0;
|
||||
qint32 soundOverridesCount = 0;
|
||||
base::flat_map<QString, QString> soundOverrides;
|
||||
qint32 sendFilesWay = static_cast<qint32>(_sendFilesWay);
|
||||
qint32 sendFilesWay = _sendFilesWay.serialize();
|
||||
qint32 sendSubmitWay = static_cast<qint32>(_sendSubmitWay);
|
||||
qint32 includeMutedCounter = _includeMutedCounter ? 1 : 0;
|
||||
qint32 countUnreadMessages = _countUnreadMessages ? 1 : 0;
|
||||
|
|
@ -176,6 +176,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
qint32 notifyFromAll = _notifyFromAll ? 1 : 0;
|
||||
qint32 nativeWindowFrame = _nativeWindowFrame.current() ? 1 : 0;
|
||||
qint32 systemDarkModeEnabled = _systemDarkModeEnabled.current() ? 1 : 0;
|
||||
qint32 ipRevealWarning = _ipRevealWarning ? 1 : 0;
|
||||
|
||||
stream >> themesAccentColors;
|
||||
if (!stream.atEnd()) {
|
||||
|
|
@ -259,6 +260,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
if (!stream.atEnd()) {
|
||||
stream >> callVideoInputDeviceId;
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
stream >> ipRevealWarning;
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("App Error: "
|
||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||
|
|
@ -304,12 +308,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
_callAudioDuckingEnabled = (callAudioDuckingEnabled == 1);
|
||||
_lastSeenWarningSeen = (lastSeenWarningSeen == 1);
|
||||
_soundOverrides = std::move(soundOverrides);
|
||||
auto uncheckedSendFilesWay = static_cast<SendFilesWay>(sendFilesWay);
|
||||
switch (uncheckedSendFilesWay) {
|
||||
case SendFilesWay::Album:
|
||||
case SendFilesWay::Photos:
|
||||
case SendFilesWay::Files: _sendFilesWay = uncheckedSendFilesWay; break;
|
||||
}
|
||||
_sendFilesWay = Ui::SendFilesWay::FromSerialized(sendFilesWay).value_or(_sendFilesWay);
|
||||
auto uncheckedSendSubmitWay = static_cast<Ui::InputSubmitSettings>(sendSubmitWay);
|
||||
switch (uncheckedSendSubmitWay) {
|
||||
case Ui::InputSubmitSettings::Enter:
|
||||
|
|
@ -318,6 +317,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
_includeMutedCounter = (includeMutedCounter == 1);
|
||||
_countUnreadMessages = (countUnreadMessages == 1);
|
||||
_exeLaunchWarning = (exeLaunchWarning == 1);
|
||||
_ipRevealWarning = (ipRevealWarning == 1);
|
||||
_notifyAboutPinned = (notifyAboutPinned == 1);
|
||||
_loopAnimatedStickers = (loopAnimatedStickers == 1);
|
||||
_largeEmoji = (largeEmoji == 1);
|
||||
|
|
@ -463,11 +463,12 @@ void Settings::resetOnLastLogout() {
|
|||
//_themesAccentColors = Window::Theme::AccentColors();
|
||||
|
||||
_lastSeenWarningSeen = false;
|
||||
_sendFilesWay = SendFilesWay::Album;
|
||||
_sendFilesWay = Ui::SendFilesWay();
|
||||
//_sendSubmitWay = Ui::InputSubmitSettings::Enter;
|
||||
_soundOverrides = {};
|
||||
|
||||
_exeLaunchWarning = true;
|
||||
_ipRevealWarning = true;
|
||||
_loopAnimatedStickers = true;
|
||||
_largeEmoji = true;
|
||||
_replaceEmoji = true;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "window/themes/window_themes_embedded.h"
|
||||
#include "window/window_controls_layout.h"
|
||||
#include "ui/chat/attach/attach_send_files_way.h"
|
||||
|
||||
enum class SendFilesWay;
|
||||
enum class RectPart;
|
||||
|
||||
namespace Ui {
|
||||
|
|
@ -229,10 +229,10 @@ public:
|
|||
[[nodiscard]] bool lastSeenWarningSeen() const {
|
||||
return _lastSeenWarningSeen;
|
||||
}
|
||||
void setSendFilesWay(SendFilesWay way) {
|
||||
void setSendFilesWay(Ui::SendFilesWay way) {
|
||||
_sendFilesWay = way;
|
||||
}
|
||||
[[nodiscard]] SendFilesWay sendFilesWay() const {
|
||||
[[nodiscard]] Ui::SendFilesWay sendFilesWay() const {
|
||||
return _sendFilesWay;
|
||||
}
|
||||
void setSendSubmitWay(Ui::InputSubmitSettings value) {
|
||||
|
|
@ -255,6 +255,12 @@ public:
|
|||
void setExeLaunchWarning(bool warning) {
|
||||
_exeLaunchWarning = warning;
|
||||
}
|
||||
[[nodiscard]] bool ipRevealWarning() const {
|
||||
return _ipRevealWarning;
|
||||
}
|
||||
void setIpRevealWarning(bool warning) {
|
||||
_ipRevealWarning = warning;
|
||||
}
|
||||
[[nodiscard]] bool loopAnimatedStickers() const {
|
||||
return _loopAnimatedStickers;
|
||||
}
|
||||
|
|
@ -509,10 +515,11 @@ private:
|
|||
bool _callAudioDuckingEnabled = true;
|
||||
Window::Theme::AccentColors _themesAccentColors;
|
||||
bool _lastSeenWarningSeen = false;
|
||||
SendFilesWay _sendFilesWay;
|
||||
Ui::SendFilesWay _sendFilesWay;
|
||||
Ui::InputSubmitSettings _sendSubmitWay;
|
||||
base::flat_map<QString, QString> _soundOverrides;
|
||||
bool _exeLaunchWarning = true;
|
||||
bool _ipRevealWarning = true;
|
||||
bool _loopAnimatedStickers = true;
|
||||
rpl::variable<bool> _largeEmoji = true;
|
||||
rpl::variable<bool> _replaceEmoji = true;
|
||||
|
|
|
|||
121
Telegram/SourceFiles/core/file_location.cpp
Normal file
121
Telegram/SourceFiles/core/file_location.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "core/file_location.h"
|
||||
|
||||
#include "platform/platform_file_bookmark.h"
|
||||
#include "logs.h"
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
|
||||
const auto kInMediaCacheLocation = u"*media_cache*"_q;
|
||||
|
||||
} // namespace
|
||||
|
||||
ReadAccessEnabler::ReadAccessEnabler(const Platform::FileBookmark *bookmark)
|
||||
: _bookmark(bookmark)
|
||||
, _failed(_bookmark ? !_bookmark->enable() : false) {
|
||||
}
|
||||
|
||||
ReadAccessEnabler::ReadAccessEnabler(
|
||||
const std::shared_ptr<Platform::FileBookmark> &bookmark)
|
||||
: _bookmark(bookmark.get())
|
||||
, _failed(_bookmark ? !_bookmark->enable() : false) {
|
||||
}
|
||||
|
||||
ReadAccessEnabler::~ReadAccessEnabler() {
|
||||
if (_bookmark && !_failed) _bookmark->disable();
|
||||
}
|
||||
|
||||
FileLocation::FileLocation(const QString &name) : fname(name) {
|
||||
if (fname.isEmpty() || fname == kInMediaCacheLocation) {
|
||||
size = 0;
|
||||
} else {
|
||||
setBookmark(Platform::PathBookmark(name));
|
||||
|
||||
QFileInfo f(name);
|
||||
if (f.exists()) {
|
||||
qint64 s = f.size();
|
||||
if (s > INT_MAX) {
|
||||
fname = QString();
|
||||
_bookmark = nullptr;
|
||||
size = 0;
|
||||
} else {
|
||||
modified = f.lastModified();
|
||||
size = qint32(s);
|
||||
}
|
||||
} else {
|
||||
fname = QString();
|
||||
_bookmark = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileLocation FileLocation::InMediaCacheLocation() {
|
||||
return FileLocation(kInMediaCacheLocation);
|
||||
}
|
||||
|
||||
bool FileLocation::check() const {
|
||||
if (fname.isEmpty() || fname == kInMediaCacheLocation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadAccessEnabler enabler(_bookmark);
|
||||
if (enabler.failed()) {
|
||||
const_cast<FileLocation*>(this)->_bookmark = nullptr;
|
||||
}
|
||||
|
||||
QFileInfo f(name());
|
||||
if (!f.isReadable()) return false;
|
||||
|
||||
quint64 s = f.size();
|
||||
if (s > INT_MAX) {
|
||||
DEBUG_LOG(("File location check: Wrong size %1").arg(s));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qint32(s) != size) {
|
||||
DEBUG_LOG(("File location check: Wrong size %1 when should be %2").arg(s).arg(size));
|
||||
return false;
|
||||
}
|
||||
auto realModified = f.lastModified();
|
||||
if (realModified != modified) {
|
||||
DEBUG_LOG(("File location check: Wrong last modified time %1 when should be %2").arg(realModified.toMSecsSinceEpoch()).arg(modified.toMSecsSinceEpoch()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString &FileLocation::name() const {
|
||||
return _bookmark ? _bookmark->name(fname) : fname;
|
||||
}
|
||||
|
||||
QByteArray FileLocation::bookmark() const {
|
||||
return _bookmark ? _bookmark->bookmark() : QByteArray();
|
||||
}
|
||||
|
||||
bool FileLocation::inMediaCache() const {
|
||||
return (fname == kInMediaCacheLocation);
|
||||
}
|
||||
|
||||
void FileLocation::setBookmark(const QByteArray &bm) {
|
||||
_bookmark.reset(bm.isEmpty() ? nullptr : new Platform::FileBookmark(bm));
|
||||
}
|
||||
|
||||
bool FileLocation::accessEnable() const {
|
||||
return isEmpty() ? false : (_bookmark ? _bookmark->enable() : true);
|
||||
}
|
||||
|
||||
void FileLocation::accessDisable() const {
|
||||
return _bookmark ? _bookmark->disable() : (void)0;
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
72
Telegram/SourceFiles/core/file_location.h
Normal file
72
Telegram/SourceFiles/core/file_location.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
namespace Platform {
|
||||
class FileBookmark;
|
||||
} // namespace Platform
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ReadAccessEnabler {
|
||||
public:
|
||||
ReadAccessEnabler(const Platform::FileBookmark *bookmark);
|
||||
ReadAccessEnabler(
|
||||
const std::shared_ptr<Platform::FileBookmark> &bookmark);
|
||||
bool failed() const {
|
||||
return _failed;
|
||||
}
|
||||
~ReadAccessEnabler();
|
||||
|
||||
private:
|
||||
const Platform::FileBookmark *_bookmark = nullptr;
|
||||
bool _failed;
|
||||
|
||||
};
|
||||
|
||||
class FileLocation {
|
||||
public:
|
||||
FileLocation() = default;
|
||||
explicit FileLocation(const QString &name);
|
||||
|
||||
static FileLocation InMediaCacheLocation();
|
||||
|
||||
[[nodiscard]] bool check() const;
|
||||
[[nodiscard]] const QString &name() const;
|
||||
void setBookmark(const QByteArray &bookmark);
|
||||
QByteArray bookmark() const;
|
||||
[[nodiscard]] bool isEmpty() const {
|
||||
return name().isEmpty();
|
||||
}
|
||||
[[nodiscard]] bool inMediaCache() const;
|
||||
|
||||
bool accessEnable() const;
|
||||
void accessDisable() const;
|
||||
|
||||
QString fname;
|
||||
QDateTime modified;
|
||||
qint32 size;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Platform::FileBookmark> _bookmark;
|
||||
|
||||
};
|
||||
|
||||
inline bool operator==(const FileLocation &a, const FileLocation &b) {
|
||||
return (a.name() == b.name())
|
||||
&& (a.modified == b.modified)
|
||||
&& (a.size == b.size);
|
||||
}
|
||||
|
||||
inline bool operator!=(const FileLocation &a, const FileLocation &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
@ -7,11 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "core/file_utilities.h"
|
||||
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/base_platform_file_utilities.h"
|
||||
#include "platform/platform_file_utilities.h"
|
||||
#include "core/application.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "ui/delayed_activation.h"
|
||||
#include "ui/chat/attach/attach_extensions.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
|
|
@ -154,7 +158,11 @@ void Launch(const QString &filepath) {
|
|||
void ShowInFolder(const QString &filepath) {
|
||||
crl::on_main([=] {
|
||||
Ui::PreventDelayedActivation();
|
||||
Platform::File::UnsafeShowInFolder(filepath);
|
||||
if (Platform::IsLinux()) {
|
||||
// Hide mediaview to make other apps visible.
|
||||
Ui::hideLayer(anim::type::instant);
|
||||
}
|
||||
base::Platform::ShowInFolder(filepath);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -309,8 +317,21 @@ QString AllFilesFilter() {
|
|||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
QString AlbumFilesFilter() {
|
||||
return qsl("Image and Video Files (*.png *.jpg *.jpeg *.mp4 *.mov)");
|
||||
QString ImagesFilter() {
|
||||
return u"Image files (*"_q + Ui::ImageExtensions().join(u" *"_q) + u")"_q;
|
||||
}
|
||||
|
||||
QString AllOrImagesFilter() {
|
||||
return AllFilesFilter() + u";;"_q + ImagesFilter();
|
||||
}
|
||||
|
||||
QString ImagesOrAllFilter() {
|
||||
return ImagesFilter() + u";;"_q + AllFilesFilter();
|
||||
}
|
||||
|
||||
QString PhotoVideoFilesFilter() {
|
||||
return u"Image and Video Files (*.png *.jpg *.jpeg *.mp4 *.mov);;"_q
|
||||
+ AllFilesFilter();
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
|
|
|||
|
|
@ -89,8 +89,11 @@ void GetFolder(
|
|||
Fn<void(QString &&result)> callback,
|
||||
Fn<void()> failed = Fn<void()>());
|
||||
|
||||
QString AllFilesFilter();
|
||||
QString AlbumFilesFilter();
|
||||
[[nodiscard]] QString AllFilesFilter();
|
||||
[[nodiscard]] QString ImagesFilter();
|
||||
[[nodiscard]] QString AllOrImagesFilter();
|
||||
[[nodiscard]] QString ImagesOrAllFilter();
|
||||
[[nodiscard]] QString PhotoVideoFilesFilter();
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "platform/platform_launcher.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/base_platform_file_utilities.h"
|
||||
#include "ui/main_queue_processor.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "core/crash_reports.h"
|
||||
|
|
@ -303,10 +304,6 @@ void Launcher::init() {
|
|||
|
||||
QApplication::setApplicationName(qsl("KotatogramDesktop"));
|
||||
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
|
||||
QApplication::setDesktopFileName(Platform::GetLauncherFilename());
|
||||
#endif
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true);
|
||||
#endif // OS_MAC_OLD
|
||||
|
|
@ -353,7 +350,7 @@ int Launcher::exec() {
|
|||
if (!UpdaterDisabled() && cRestartingUpdate()) {
|
||||
DEBUG_LOG(("Sandbox Info: executing updater to install update."));
|
||||
if (!launchUpdater(UpdaterLaunch::PerformUpdate)) {
|
||||
psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
|
||||
base::Platform::DeleteDirectory(cWorkingDir() + qsl("tupdates/temp"));
|
||||
}
|
||||
} else if (cRestarting()) {
|
||||
DEBUG_LOG(("Sandbox Info: executing Kotatogram because of restart."));
|
||||
|
|
@ -413,7 +410,7 @@ bool Launcher::customWorkingDir() const {
|
|||
}
|
||||
|
||||
void Launcher::prepareSettings() {
|
||||
auto path = Platform::CurrentExecutablePath(_argc, _argv);
|
||||
auto path = base::Platform::CurrentExecutablePath(_argc, _argv);
|
||||
LOG(("Executable path before check: %1").arg(path));
|
||||
if (!path.isEmpty()) {
|
||||
auto info = QFileInfo(path);
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ MimeType::MimeType(Known type) : _type(type) {
|
|||
|
||||
QStringList MimeType::globPatterns() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return QStringList(qsl("*.webp"));
|
||||
case Known::Tgs: return QStringList(qsl("*.tgs"));
|
||||
case Known::TDesktopTheme: return QStringList(qsl("*.tdesktop-theme"));
|
||||
case Known::TDesktopPalette: return QStringList(qsl("*.tdesktop-palette"));
|
||||
case Known::WebP: return QStringList(u"*.webp"_q);
|
||||
case Known::Tgs: return QStringList(u"*.tgs"_q);
|
||||
case Known::TDesktopTheme: return QStringList(u"*.tdesktop-theme"_q);
|
||||
case Known::TDesktopPalette: return QStringList(u"*.tdesktop-palette"_q);
|
||||
default: break;
|
||||
}
|
||||
return _typeStruct.globPatterns();
|
||||
|
|
@ -30,10 +30,10 @@ QStringList MimeType::globPatterns() const {
|
|||
|
||||
QString MimeType::filterString() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return qsl("WebP image (*.webp)");
|
||||
case Known::Tgs: return qsl("Telegram sticker (*.tgs)");
|
||||
case Known::TDesktopTheme: return qsl("Theme files (*.tdesktop-theme)");
|
||||
case Known::TDesktopPalette: return qsl("Palette files (*.tdesktop-palette)");
|
||||
case Known::WebP: return u"WebP image (*.webp)"_q;
|
||||
case Known::Tgs: return u"Telegram sticker (*.tgs)"_q;
|
||||
case Known::TDesktopTheme: return u"Theme files (*.tdesktop-theme)"_q;
|
||||
case Known::TDesktopPalette: return u"Palette files (*.tdesktop-palette)"_q;
|
||||
default: break;
|
||||
}
|
||||
return _typeStruct.filterString();
|
||||
|
|
@ -41,10 +41,10 @@ QString MimeType::filterString() const {
|
|||
|
||||
QString MimeType::name() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return qsl("image/webp");
|
||||
case Known::Tgs: return qsl("application/x-tgsticker");
|
||||
case Known::TDesktopTheme: return qsl("application/x-tdesktop-theme");
|
||||
case Known::TDesktopPalette: return qsl("application/x-tdesktop-palette");
|
||||
case Known::WebP: return u"image/webp"_q;
|
||||
case Known::Tgs: return u"application/x-tgsticker"_q;
|
||||
case Known::TDesktopTheme: return u"application/x-tdesktop-theme"_q;
|
||||
case Known::TDesktopPalette: return u"application/x-tdesktop-palette"_q;
|
||||
default: break;
|
||||
}
|
||||
return _typeStruct.name();
|
||||
|
|
@ -103,19 +103,38 @@ MimeType MimeTypeForData(const QByteArray &data) {
|
|||
}
|
||||
|
||||
bool IsMimeStickerAnimated(const QString &mime) {
|
||||
return mime == qsl("application/x-tgsticker");
|
||||
return (mime == u"application/x-tgsticker"_q);
|
||||
}
|
||||
|
||||
bool IsMimeSticker(const QString &mime) {
|
||||
return mime == qsl("image/webp")
|
||||
return (mime == u"image/webp"_q)
|
||||
|| IsMimeStickerAnimated(mime);
|
||||
}
|
||||
|
||||
bool IsMimeAcceptedForAlbum(const QString &mime) {
|
||||
bool IsMimeAcceptedForPhotoVideoAlbum(const QString &mime) {
|
||||
return (mime == u"image/jpeg"_q)
|
||||
|| (mime == u"image/png"_q)
|
||||
|| (mime == u"video/mp4"_q)
|
||||
|| (mime == u"video/quicktime"_q);
|
||||
}
|
||||
|
||||
bool FileIsImage(const QString &name, const QString &mime) {
|
||||
QString lowermime = mime.toLower(), namelower = name.toLower();
|
||||
if (lowermime.startsWith(qstr("image/"))) {
|
||||
return true;
|
||||
} else if (namelower.endsWith(qstr(".bmp"))
|
||||
|| namelower.endsWith(qstr(".jpg"))
|
||||
|| namelower.endsWith(qstr(".jpeg"))
|
||||
|| namelower.endsWith(qstr(".gif"))
|
||||
|| namelower.endsWith(qstr(".webp"))
|
||||
|| namelower.endsWith(qstr(".tga"))
|
||||
|| namelower.endsWith(qstr(".tiff"))
|
||||
|| namelower.endsWith(qstr(".tif"))
|
||||
|| namelower.endsWith(qstr(".psd"))
|
||||
|| namelower.endsWith(qstr(".png"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QMimeType>
|
||||
|
|
@ -35,12 +36,14 @@ private:
|
|||
|
||||
};
|
||||
|
||||
MimeType MimeTypeForName(const QString &mime);
|
||||
MimeType MimeTypeForFile(const QFileInfo &file);
|
||||
MimeType MimeTypeForData(const QByteArray &data);
|
||||
[[nodiscard]] MimeType MimeTypeForName(const QString &mime);
|
||||
[[nodiscard]] MimeType MimeTypeForFile(const QFileInfo &file);
|
||||
[[nodiscard]] MimeType MimeTypeForData(const QByteArray &data);
|
||||
|
||||
bool IsMimeStickerAnimated(const QString &mime);
|
||||
bool IsMimeSticker(const QString &mime);
|
||||
bool IsMimeAcceptedForAlbum(const QString &mime);
|
||||
[[nodiscard]] bool IsMimeStickerAnimated(const QString &mime);
|
||||
[[nodiscard]] bool IsMimeSticker(const QString &mime);
|
||||
[[nodiscard]] bool IsMimeAcceptedForPhotoVideoAlbum(const QString &mime);
|
||||
|
||||
[[nodiscard]] bool FileIsImage(const QString &name, const QString &mime);
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ Sandbox::Sandbox(
|
|||
}
|
||||
})
|
||||
, _launcher(launcher) {
|
||||
setQuitOnLastWindowClosed(false);
|
||||
}
|
||||
|
||||
int Sandbox::start() {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ const auto CommandByName = base::flat_map<QString, Command>{
|
|||
{ qsl("last_folder") , Command::ShowFolderLast },
|
||||
|
||||
{ qsl("show_archive") , Command::ShowArchive },
|
||||
{ qsl("show_contacts") , Command::ShowContacts },
|
||||
|
||||
{ qsl("read_chat") , Command::ReadChat },
|
||||
|
||||
|
|
@ -154,6 +155,7 @@ const auto CommandNames = base::flat_map<Command, QString>{
|
|||
{ Command::ShowFolderLast , qsl("last_folder") },
|
||||
|
||||
{ Command::ShowArchive , qsl("show_archive") },
|
||||
{ Command::ShowContacts , qsl("show_contacts") },
|
||||
|
||||
{ Command::ReadChat , qsl("read_chat") },
|
||||
|
||||
|
|
@ -414,6 +416,7 @@ void Manager::fillDefaults() {
|
|||
set(qsl("ctrl+0"), Command::ChatSelf);
|
||||
|
||||
set(qsl("ctrl+9"), Command::ShowArchive);
|
||||
set(qsl("ctrl+j"), Command::ShowContacts);
|
||||
|
||||
set(qsl("ctrl+r"), Command::ReadChat);
|
||||
set(qsl("ctrl+s"), Command::SaveDraft);
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ enum class Command {
|
|||
FolderPrevious,
|
||||
|
||||
ShowArchive,
|
||||
ShowContacts,
|
||||
|
||||
JustSendMessage,
|
||||
SendSilentMessage,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "core/update_checker.h"
|
||||
|
||||
#include "platform/platform_specific.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/base_platform_file_utilities.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/bytes.h"
|
||||
#include "base/unixtime.h"
|
||||
|
|
@ -211,7 +213,7 @@ QString UpdatesFolder() {
|
|||
}
|
||||
|
||||
void ClearAll() {
|
||||
psDeleteDir(UpdatesFolder());
|
||||
base::Platform::DeleteDirectory(UpdatesFolder());
|
||||
}
|
||||
|
||||
QString FindUpdateFile() {
|
||||
|
|
@ -270,7 +272,7 @@ bool UnpackUpdate(const QString &filepath) {
|
|||
input.close();
|
||||
|
||||
QString tempDirPath = cWorkingDir() + qsl("tupdates/temp"), readyFilePath = cWorkingDir() + qsl("tupdates/temp/ready");
|
||||
psDeleteDir(tempDirPath);
|
||||
base::Platform::DeleteDirectory(tempDirPath);
|
||||
|
||||
QDir tempDir(tempDirPath);
|
||||
if (tempDir.exists() || QFile(readyFilePath).exists()) {
|
||||
|
|
@ -1556,8 +1558,8 @@ bool checkReadyUpdate() {
|
|||
#endif // Q_OS_UNIX
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
Platform::RemoveQuarantine(QFileInfo(curUpdater).absolutePath());
|
||||
Platform::RemoveQuarantine(updater.absolutePath());
|
||||
base::Platform::RemoveQuarantine(QFileInfo(curUpdater).absolutePath());
|
||||
base::Platform::RemoveQuarantine(updater.absolutePath());
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
return true;
|
||||
|
|
@ -1570,9 +1572,16 @@ void UpdateApplication() {
|
|||
return "https://www.microsoft.com/en-us/store/p/telegram-desktop/9nztwsqntd0s";
|
||||
#elif defined OS_MAC_STORE // OS_WIN_STORE
|
||||
return "https://itunes.apple.com/ae/app/telegram-desktop/id946399090";
|
||||
#else // OS_WIN_STORE || OS_MAC_STORE
|
||||
#elif defined Q_OS_UNIX && !defined Q_OS_MAC // OS_WIN_STORE || OS_MAC_STORE
|
||||
if (Platform::InFlatpak()) {
|
||||
return "https://flathub.org/apps/details/io.github.kotatogram";
|
||||
//} else if (Platform::InSnap()) {
|
||||
// return "https://snapcraft.io/telegram-desktop";
|
||||
}
|
||||
return "https://github.com/kotatogram/kotatogram-desktop";
|
||||
#endif // OS_WIN_STORE || OS_MAC_STORE
|
||||
#else // OS_WIN_STORE || OS_MAC_STORE || (defined Q_OS_UNIX && !defined Q_OS_MAC)
|
||||
return "https://github.com/kotatogram/kotatogram-desktop";
|
||||
#endif // OS_WIN_STORE || OS_MAC_STORE || (defined Q_OS_UNIX && !defined Q_OS_MAC)
|
||||
}();
|
||||
UrlClickHandler::Open(url);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
|
|||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||
constexpr auto AppName = "Kotatogram Desktop"_cs;
|
||||
constexpr auto AppFile = "Kotatogram"_cs;
|
||||
constexpr auto AppVersion = 2004003;
|
||||
constexpr auto AppVersionStr = "2.4.3";
|
||||
constexpr auto AppVersion = 2004007;
|
||||
constexpr auto AppVersionStr = "2.4.7";
|
||||
constexpr auto AppBetaVersion = true;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ struct PeerUpdate {
|
|||
Notifications = (1 << 4),
|
||||
Migration = (1 << 5),
|
||||
UnavailableReason = (1 << 6),
|
||||
PinnedMessage = (1 << 7),
|
||||
PinnedMessages = (1 << 7),
|
||||
IsBlocked = (1 << 8),
|
||||
|
||||
// For users
|
||||
|
|
|
|||
|
|
@ -404,9 +404,6 @@ void ChannelData::setUnavailableReasons(
|
|||
void ChannelData::setAvailableMinId(MsgId availableMinId) {
|
||||
if (_availableMinId != availableMinId) {
|
||||
_availableMinId = availableMinId;
|
||||
if (pinnedMessageId() <= _availableMinId) {
|
||||
clearPinnedMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -793,9 +790,7 @@ void ApplyChannelUpdate(
|
|||
}
|
||||
}
|
||||
if (const auto pinned = update.vpinned_msg_id()) {
|
||||
channel->setPinnedMessageId(pinned->v);
|
||||
} else {
|
||||
channel->clearPinnedMessage();
|
||||
SetTopPinnedMessageId(channel, pinned->v);
|
||||
}
|
||||
if (channel->isMegagroup()) {
|
||||
const auto stickerSet = update.vstickerset();
|
||||
|
|
|
|||
|
|
@ -333,9 +333,7 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
|
|||
return QString();
|
||||
}));
|
||||
if (const auto pinned = update.vpinned_msg_id()) {
|
||||
chat->setPinnedMessageId(pinned->v);
|
||||
} else {
|
||||
chat->clearPinnedMessage();
|
||||
SetTopPinnedMessageId(chat, pinned->v);
|
||||
}
|
||||
chat->checkFolder(update.vfolder_id().value_or_empty());
|
||||
chat->fullUpdated();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue