update to 0.9.15
Signed-off-by: Олег Зонов <me.OZone@Gmail.com> (github: OZ1)
|
@ -1,123 +1,167 @@
|
|||
@echo OFF
|
||||
|
||||
FOR /F "tokens=1,2* delims= " %%i in (Version) do set "%%i=%%j"
|
||||
|
||||
if %DevChannel% neq 0 goto preparedev
|
||||
|
||||
set "DevParam="
|
||||
set "AppVersionStrFull=%AppVersionStr%"
|
||||
goto devprepared
|
||||
|
||||
:preparedev
|
||||
|
||||
set "DevParam=-dev"
|
||||
set "AppVersionStrFull=%AppVersionStr%.dev"
|
||||
|
||||
:devprepared
|
||||
set "VersionForPacker=%AppVersion%"
|
||||
if %BetaVersion% neq 0 (
|
||||
set "AppVersion=%BetaVersion%"
|
||||
set "AppVersionStrFull=%AppVersionStr%_%BetaVersion%"
|
||||
set "DevParam=-beta %BetaVersion%"
|
||||
set "BetaKeyFile=tbeta_%BetaVersion%_key"
|
||||
) else (
|
||||
if %DevChannel% neq 0 (
|
||||
set "DevParam=-dev"
|
||||
set "AppVersionStrFull=%AppVersionStr%.dev"
|
||||
) else (
|
||||
set "DevParam="
|
||||
set "AppVersionStrFull=%AppVersionStr%"
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Building version %AppVersionStrFull% for Windows..
|
||||
echo.
|
||||
|
||||
if exist ..\Win32\Deploy\deploy\%AppVersionStrMajor%\%AppVersionStr%\ goto error_exist1
|
||||
if exist ..\Win32\Deploy\deploy\%AppVersionStrMajor%\%AppVersionStr%.dev\ goto error_exist2
|
||||
if exist ..\Win32\Deploy\tupdate%AppVersion% goto error_exist3
|
||||
set "UpdateFile=tupdate%AppVersion%"
|
||||
set "SetupFile=tsetup.%AppVersionStrFull%.exe"
|
||||
set "PortableFile=tportable.%AppVersionStrFull%.zip"
|
||||
set "HomePath=..\..\Telegram"
|
||||
set "ReleasePath=..\Win32\Deploy"
|
||||
set "DeployPath=%ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStrFull%"
|
||||
set "SignPath=..\..\TelegramPrivate\Sign.bat"
|
||||
|
||||
if %BetaVersion% neq 0 (
|
||||
if exist %ReleasePath%\%BetaKeyFile% (
|
||||
echo Beta version key file for version %AppVersion% already exists!
|
||||
exit /b 1
|
||||
)
|
||||
) else (
|
||||
if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%.dev\ (
|
||||
echo Deploy folder for version %AppVersionStr%.dev already exists!
|
||||
exit /b 1
|
||||
)
|
||||
if exist %ReleasePath%\tupdate%AppVersion% (
|
||||
echo Update file for version %AppVersion% already exists!
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%\ (
|
||||
echo Deploy folder for version %AppVersionStr% already exists!
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
cd SourceFiles\
|
||||
copy telegram.qrc /B+,,/Y
|
||||
rem copy telegram.qrc /B+,,/Y
|
||||
cd ..\
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
cd ..\
|
||||
MSBuild Telegram.sln /property:Configuration=Deploy
|
||||
if %errorlevel% neq 0 goto error0
|
||||
cd Telegram\
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
echo .
|
||||
echo Version %AppVersionStrFull% build successfull! Preparing..
|
||||
echo Version %AppVersionStrFull% build successfull. Preparing..
|
||||
echo .
|
||||
|
||||
set "PATH=%PATH%;C:\Program Files\7-Zip;C:\Program Files (x86)\Inno Setup 5"
|
||||
cd Win32\Deploy\
|
||||
|
||||
call ..\..\..\TelegramPrivate\Sign.bat Telegram.exe
|
||||
if %errorlevel% neq 0 goto error1
|
||||
call %SignPath% %ReleasePath%\Telegram.exe
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
call ..\..\..\TelegramPrivate\Sign.bat Updater.exe
|
||||
if %errorlevel% neq 0 goto error1
|
||||
call %SignPath% %ReleasePath%\Updater.exe
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
iscc /dMyAppVersion=%AppVersionStrSmall% /dMyAppVersionZero=%AppVersionStr% /dMyAppVersionFull=%AppVersionStrFull% ..\..\Telegram\Setup.iss
|
||||
if %errorlevel% neq 0 goto error1
|
||||
if %BetaVersion% equ 0 (
|
||||
cd %ReleasePath%
|
||||
iscc /dMyAppVersion=%AppVersionStrSmall% /dMyAppVersionZero=%AppVersionStr% /dMyAppVersionFull=%AppVersionStrFull% %HomePath%\Setup.iss
|
||||
cd %HomePath%
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
call ..\..\..\TelegramPrivate\Sign.bat tsetup.%AppVersionStrFull%.exe
|
||||
if %errorlevel% neq 0 goto error1
|
||||
call %SignPath% %ReleasePath%\tsetup.%AppVersionStrFull%.exe
|
||||
if %errorlevel% neq 0 goto error
|
||||
)
|
||||
|
||||
call Packer.exe -version %AppVersion% -path Telegram.exe -path Updater.exe %DevParam%
|
||||
if %errorlevel% neq 0 goto error1
|
||||
cd %ReleasePath%
|
||||
call Packer.exe -version %VersionForPacker% -path Telegram.exe -path Updater.exe %DevParam%
|
||||
cd %HomePath%
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
if not exist deploy mkdir deploy
|
||||
if not exist deploy\%AppVersionStrMajor% mkdir deploy\%AppVersionStrMajor%
|
||||
mkdir deploy\%AppVersionStrMajor%\%AppVersionStrFull%
|
||||
mkdir deploy\%AppVersionStrMajor%\%AppVersionStrFull%\Telegram
|
||||
if %errorlevel% neq 0 goto error1
|
||||
if %BetaVersion% neq 0 (
|
||||
if not exist %ReleasePath%\%BetaKeyFile% (
|
||||
echo Beta version key file not found!
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
move Telegram.exe deploy\%AppVersionStrMajor%\%AppVersionStrFull%\Telegram\
|
||||
move Updater.exe deploy\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
move Telegram.pdb deploy\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
move Updater.pdb deploy\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
move tsetup.%AppVersionStrFull%.exe deploy\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
move tupdate%AppVersion% deploy\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
if %errorlevel% neq 0 goto error1
|
||||
FOR /F "tokens=1* delims= " %%i in (%ReleasePath%\%BetaKeyFile%) do set "BetaSignature=%%i"
|
||||
)
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
cd deploy\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
7z a -mx9 tportable.%AppVersionStrFull%.zip Telegram\
|
||||
if %errorlevel% neq 0 goto error2
|
||||
if %BetaVersion% neq 0 (
|
||||
set "UpdateFile=%UpdateFile%_%BetaSignature%"
|
||||
set "PortableFile=tbeta%BetaVersion%_%BetaSignature%.zip"
|
||||
)
|
||||
|
||||
if not exist %ReleasePath%\deploy mkdir %ReleasePath%\deploy
|
||||
if not exist %ReleasePath%\deploy\%AppVersionStrMajor% mkdir %ReleasePath%\deploy\%AppVersionStrMajor%
|
||||
mkdir %DeployPath%
|
||||
mkdir %DeployPath%\Telegram
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
move %ReleasePath%\Telegram.exe %DeployPath%\Telegram\
|
||||
move %ReleasePath%\Updater.exe %DeployPath%\
|
||||
move %ReleasePath%\Telegram.pdb %DeployPath%\
|
||||
move %ReleasePath%\Updater.pdb %DeployPath%\
|
||||
if %BetaVersion% equ 0 (
|
||||
move %ReleasePath%\%SetupFile% %DeployPath%\
|
||||
) else (
|
||||
move %ReleasePath%\%BetaKeyFile% %DeployPath%\
|
||||
)
|
||||
move %ReleasePath%\%UpdateFile% %DeployPath%\
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
cd %DeployPath%\
|
||||
7z a -mx9 %PortableFile% Telegram\
|
||||
cd ..\..\..\%HomePath%\
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
echo .
|
||||
echo Version %AppVersionStrFull% is ready for deploy!
|
||||
echo .
|
||||
|
||||
if not exist tupdate%AppVersion% goto error2
|
||||
if not exist tportable.%AppVersionStrFull%.zip goto error2
|
||||
if not exist tsetup.%AppVersionStrFull%.exe goto error2
|
||||
if not exist Telegram.pdb goto error2
|
||||
if not exist Updater.exe goto error2
|
||||
if not exist Updater.pdb goto error2
|
||||
if not exist Z:\TBuild\tother\tsetup\%AppVersionStrMajor% mkdir Z:\TBuild\tother\tsetup\%AppVersionStrMajor%
|
||||
if not exist Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull% mkdir Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull%
|
||||
set "FinalReleasePath=Z:\TBuild\tother\tsetup"
|
||||
set "FinalDeployPath=%FinalReleasePath%\%AppVersionStrMajor%\%AppVersionStrFull%"
|
||||
|
||||
xcopy tupdate%AppVersion% Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
xcopy tportable.%AppVersionStrFull%.zip Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
xcopy tsetup.%AppVersionStrFull%.exe Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
xcopy Telegram.pdb Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
xcopy Updater.exe Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
xcopy Updater.pdb Z:\TBuild\tother\tsetup\%AppVersionStrMajor%\%AppVersionStrFull%\
|
||||
if not exist %DeployPath%\%UpdateFile% goto error
|
||||
if not exist %DeployPath%\%PortableFile% goto error
|
||||
if %BetaVersion% equ 0 (
|
||||
if not exist %DeployPath%\%SetupFile% goto error
|
||||
)
|
||||
if not exist %DeployPath%\Telegram.pdb goto error
|
||||
if not exist %DeployPath%\Updater.exe goto error
|
||||
if not exist %DeployPath%\Updater.pdb goto error
|
||||
if not exist %FinalReleasePath%\%AppVersionStrMajor% mkdir %FinalReleasePath%\%AppVersionStrMajor%
|
||||
if not exist %FinalDeployPath% mkdir %FinalDeployPath%
|
||||
|
||||
xcopy %DeployPath%\%UpdateFile% %FinalDeployPath%\
|
||||
xcopy %DeployPath%\%PortableFile% %FinalDeployPath%\
|
||||
if %BetaVersion% equ 0 (
|
||||
xcopy %DeployPath%\%SetupFile% %FinalDeployPath%\
|
||||
) else (
|
||||
xcopy %DeployPath%\%BetaKeyFile% %FinalDeployPath%\
|
||||
)
|
||||
xcopy %DeployPath%\Telegram.pdb %FinalDeployPath%\
|
||||
xcopy %DeployPath%\Updater.exe %FinalDeployPath%\
|
||||
xcopy %DeployPath%\Updater.pdb %FinalDeployPath%\
|
||||
|
||||
echo Version %AppVersionStrFull% is ready!
|
||||
|
||||
cd ..\..\..\..\..\Telegram\
|
||||
goto eof
|
||||
|
||||
:error2
|
||||
cd ..\..\..\
|
||||
:error1
|
||||
cd ..\..\
|
||||
:error0
|
||||
cd Telegram\
|
||||
goto error
|
||||
|
||||
:error_exist1
|
||||
echo Deploy folder for version %AppVersionStr% already exists!
|
||||
exit /b 1
|
||||
|
||||
:error_exist2
|
||||
echo Deploy folder for version %AppVersionStr%.dev already exists!
|
||||
exit /b 1
|
||||
|
||||
:error_exist3
|
||||
echo Update file for version %AppVersion% already exists!
|
||||
exit /b 1
|
||||
|
||||
:error
|
||||
echo ERROR occured!
|
||||
exit /b %errorlevel%
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
exit /b 1
|
||||
|
||||
:eof
|
||||
|
|
|
@ -5,9 +5,16 @@ while IFS='' read -r line || [[ -n "$line" ]]; do
|
|||
eval $1="$2"
|
||||
done < Version
|
||||
|
||||
AppVersionStrFull="$AppVersionStr"
|
||||
DevParam=''
|
||||
if [ "$DevChannel" != "0" ]; then
|
||||
VersionForPacker="$AppVersion"
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
AppVersion="$BetaVersion"
|
||||
AppVersionStrFull="${AppVersionStr}_${BetaVersion}"
|
||||
DevParam="-beta $BetaVersion"
|
||||
BetaKeyFile="tbeta_${AppVersion}_key"
|
||||
elif [ "$DevChannel" == "0" ]; then
|
||||
AppVersionStrFull="$AppVersionStr"
|
||||
DevParam=''
|
||||
else
|
||||
AppVersionStrFull="$AppVersionStr.dev"
|
||||
DevParam='-dev'
|
||||
fi
|
||||
|
@ -22,12 +29,12 @@ while IFS='' read -r line || [[ -n "$line" ]]; do
|
|||
done < Target
|
||||
|
||||
echo ""
|
||||
HomePath="./../../Telegram"
|
||||
if [ "$BuildTarget" == "linux" ]; then
|
||||
echo "Building version $AppVersionStrFull for Linux 64bit.."
|
||||
UpdateFile="tlinuxupd$AppVersion"
|
||||
SetupFile="tsetup.$AppVersionStrFull.tar.xz"
|
||||
WorkPath="./../Linux"
|
||||
HomePath="./../../Telegram"
|
||||
FixScript="$HomePath/FixMake.sh"
|
||||
ReleasePath="./../Linux/Release"
|
||||
elif [ "$BuildTarget" == "linux32" ]; then
|
||||
|
@ -35,7 +42,6 @@ elif [ "$BuildTarget" == "linux32" ]; then
|
|||
UpdateFile="tlinux32upd$AppVersion"
|
||||
SetupFile="tsetup32.$AppVersionStrFull.tar.xz"
|
||||
WorkPath="./../Linux"
|
||||
HomePath="./../../Telegram"
|
||||
FixScript="$HomePath/FixMake32.sh"
|
||||
ReleasePath="./../Linux/Release"
|
||||
elif [ "$BuildTarget" == "mac" ]; then
|
||||
|
@ -51,6 +57,11 @@ elif [ "$BuildTarget" == "mac32" ]; then
|
|||
ReleasePath="./../Mac/Release"
|
||||
BinaryName="Telegram"
|
||||
elif [ "$BuildTarget" == "macstore" ]; then
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
echo "Can't build macstore beta version!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building version $AppVersionStrFull for Mac App Store.."
|
||||
ReleasePath="./../Mac/Release"
|
||||
BinaryName="Telegram Desktop"
|
||||
|
@ -62,19 +73,31 @@ else
|
|||
fi
|
||||
|
||||
#if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarget" == "macstore" ]; then
|
||||
if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStr.dev" ]; then
|
||||
echo "Deploy folder for version $AppVersionStr.dev already exists!"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
if [ -f "$ReleasePath/$BetaKeyFile" ]; then
|
||||
echo "Beta version key file for version $AppVersion already exists!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStr" ]; then
|
||||
echo "Deploy folder for version $AppVersionStr already exists!"
|
||||
exit 1
|
||||
fi
|
||||
if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStrFull" ]; then
|
||||
echo "Deploy folder for version $AppVersionStrFull already exists!"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStr.dev" ]; then
|
||||
echo "Deploy folder for version $AppVersionStr.dev already exists!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "$ReleasePath/$UpdateFile" ]; then
|
||||
echo "Update file for version $AppVersion already exists!"
|
||||
exit 1
|
||||
if [ -f "$ReleasePath/$UpdateFile" ]; then
|
||||
echo "Update file for version $AppVersion already exists!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStr" ]; then
|
||||
echo "Deploy folder for version $AppVersionStr already exists!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
DeployPath="$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStrFull"
|
||||
|
@ -87,14 +110,14 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
|||
make
|
||||
echo "Updater build complete!"
|
||||
cd "$HomePath"
|
||||
|
||||
|
||||
mkdir -p "$WorkPath/ReleaseIntermediate"
|
||||
cd "$WorkPath/ReleaseIntermediate"
|
||||
/usr/local/Qt-5.5.1/bin/qmake "$HomePath/Telegram.pro"
|
||||
eval "$FixScript"
|
||||
make
|
||||
echo "Telegram build complete!"
|
||||
cd "$HomePath"
|
||||
cd "$HomePath"
|
||||
if [ ! -f "$ReleasePath/Telegram" ]; then
|
||||
echo "Telegram not found!"
|
||||
exit 1
|
||||
|
@ -106,9 +129,23 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
|||
fi
|
||||
|
||||
echo "Preparing version $AppVersionStrFull, executing Packer.."
|
||||
cd $ReleasePath && ./Packer -path Telegram -path Updater -version $AppVersion $DevParam && cd ./../../Telegram
|
||||
cd "$ReleasePath" && "./Packer" -path Telegram -path Updater -version $VersionForPacker $DevParam && cd "$HomePath"
|
||||
echo "Packer done!"
|
||||
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
if [ ! -f "$ReleasePath/$BetaKeyFile" ]; then
|
||||
echo "Beta version key file not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||
BetaSignature="$line"
|
||||
done < "$ReleasePath/$BetaKeyFile"
|
||||
|
||||
UpdateFile="${UpdateFile}_${BetaSignature}"
|
||||
SetupFile="tbeta${BetaVersion}_${BetaSignature}.tar.xz"
|
||||
fi
|
||||
|
||||
if [ ! -d "$ReleasePath/deploy" ]; then
|
||||
mkdir "$ReleasePath/deploy"
|
||||
fi
|
||||
|
@ -120,15 +157,18 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
|||
echo "Copying Telegram, Updater and $UpdateFile to deploy/$AppVersionStrMajor/$AppVersionStrFull..";
|
||||
mkdir "$DeployPath"
|
||||
mkdir "$DeployPath/Telegram"
|
||||
mv $ReleasePath/Telegram $DeployPath/Telegram/
|
||||
mv $ReleasePath/Updater $DeployPath/Telegram/
|
||||
mv $ReleasePath/$UpdateFile $DeployPath/
|
||||
cd $DeployPath && tar -cJvf $SetupFile Telegram/ && cd ./../../../../../Telegram
|
||||
mv "$ReleasePath/Telegram" "$DeployPath/Telegram/"
|
||||
mv "$ReleasePath/Updater" "$DeployPath/Telegram/"
|
||||
mv "$ReleasePath/$UpdateFile" "$DeployPath/"
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
mv "$ReleasePath/$BetaKeyFile" "$DeployPath/"
|
||||
fi
|
||||
cd "$DeployPath" && tar -cJvf "$SetupFile" "Telegram/" && cd "./../../../$HomePath"
|
||||
fi
|
||||
|
||||
if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarget" == "macstore" ]; then
|
||||
|
||||
touch ./SourceFiles/telegram.qrc
|
||||
touch "./SourceFiles/telegram.qrc"
|
||||
xcodebuild -project Telegram.xcodeproj -alltargets -configuration Release build
|
||||
|
||||
if [ ! -d "$ReleasePath/$BinaryName.app" ]; then
|
||||
|
@ -176,14 +216,31 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
|
|||
fi
|
||||
|
||||
if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ]; then
|
||||
cd $ReleasePath
|
||||
temppath=`hdiutil attach -readwrite tsetup.dmg | awk -F "\t" 'END {print $3}'`
|
||||
cp -R "./$BinaryName.app" "$temppath/"
|
||||
bless --folder "$temppath/" --openfolder "$temppath/"
|
||||
hdiutil detach "$temppath"
|
||||
hdiutil convert tsetup.dmg -format UDZO -imagekey zlib-level=9 -ov -o $SetupFile
|
||||
cd ./../../Telegram
|
||||
cd $ReleasePath && ./Packer.app/Contents/MacOS/Packer -path "$BinaryName.app" -version $AppVersion $DevParam && cd ./../../Telegram
|
||||
if [ "$BetaVersion" == "0" ]; then
|
||||
cd "$ReleasePath"
|
||||
temppath=`hdiutil attach -readwrite tsetup.dmg | awk -F "\t" 'END {print $3}'`
|
||||
cp -R "./$BinaryName.app" "$temppath/"
|
||||
bless --folder "$temppath/" --openfolder "$temppath/"
|
||||
hdiutil detach "$temppath"
|
||||
hdiutil convert tsetup.dmg -format UDZO -imagekey zlib-level=9 -ov -o "$SetupFile"
|
||||
cd "./../../Telegram"
|
||||
fi
|
||||
cd "$ReleasePath" && "./Packer.app/Contents/MacOS/Packer" -path "$BinaryName.app" -version $VersionForPacker $DevParam && cd "$HomePath"
|
||||
echo "Packer done!"
|
||||
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
if [ ! -f "$ReleasePath/$BetaKeyFile" ]; then
|
||||
echo "Beta version key file not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||
BetaSignature="$line"
|
||||
done < "$ReleasePath/$BetaKeyFile"
|
||||
|
||||
UpdateFile="${UpdateFile}_${BetaSignature}"
|
||||
SetupFile="tbeta${BetaVersion}_${BetaSignature}.zip"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$ReleasePath/deploy" ]; then
|
||||
|
@ -198,13 +255,17 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
|
|||
echo "Copying $BinaryName.app and $UpdateFile to deploy/$AppVersionStrMajor/$AppVersionStr..";
|
||||
mkdir "$DeployPath"
|
||||
mkdir "$DeployPath/Telegram"
|
||||
cp -r "$ReleasePath/$BinaryName.app" $DeployPath/Telegram/
|
||||
mv "$ReleasePath/$BinaryName.app.dSYM" $DeployPath/
|
||||
cp -r "$ReleasePath/$BinaryName.app" "$DeployPath/Telegram/"
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
cd "$DeployPath" && zip -r "$SetupFile" "Telegram" && mv "$SetupFile" "./../../../" && cd "./../../../$HomePath"
|
||||
mv "$ReleasePath/$BetaKeyFile" "$DeployPath/"
|
||||
fi
|
||||
mv "$ReleasePath/$BinaryName.app.dSYM" "$DeployPath/"
|
||||
rm "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName"
|
||||
rm "$ReleasePath/$BinaryName.app/Contents/Frameworks/Updater"
|
||||
rm -rf "$ReleasePath/$BinaryName.app/Contents/_CodeSignature"
|
||||
mv $ReleasePath/$UpdateFile $DeployPath/
|
||||
mv $ReleasePath/$SetupFile $DeployPath/
|
||||
mv "$ReleasePath/$UpdateFile" "$DeployPath/"
|
||||
mv "$ReleasePath/$SetupFile" "$DeployPath/"
|
||||
|
||||
if [ "$BuildTarget" == "mac32" ]; then
|
||||
ReleaseToPath="./../../../TBuild/tother/tmac32"
|
||||
|
@ -217,16 +278,19 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
|
|||
mkdir "$DeployToPath"
|
||||
fi
|
||||
|
||||
cp -v $DeployPath/$UpdateFile $DeployToPath/
|
||||
cp -v $DeployPath/$SetupFile $DeployToPath/
|
||||
cp -rv $DeployPath/$BinaryName.app.dSYM $DeployToPath/
|
||||
cp -v "$DeployPath/$UpdateFile" "$DeployToPath/"
|
||||
cp -v "$DeployPath/$SetupFile" "$DeployToPath/"
|
||||
cp -rv "$DeployPath/$BinaryName.app.dSYM" "$DeployToPath/"
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
cp -v "$DeployPath/$BetaKeyFile" "$DeployToPath/"
|
||||
fi
|
||||
fi
|
||||
elif [ "$BuildTarget" == "macstore" ]; then
|
||||
echo "Copying $BinaryName.app to deploy/$AppVersionStrMajor/$AppVersionStr..";
|
||||
mkdir "$DeployPath"
|
||||
cp -r "$ReleasePath/$BinaryName.app" $DeployPath/
|
||||
mv "$ReleasePath/$BinaryName.pkg" $DeployPath/
|
||||
mv "$ReleasePath/$BinaryName.app.dSYM" $DeployPath/
|
||||
cp -r "$ReleasePath/$BinaryName.app" "$DeployPath/"
|
||||
mv "$ReleasePath/$BinaryName.pkg" "$DeployPath/"
|
||||
mv "$ReleasePath/$BinaryName.app.dSYM" "$DeployPath/"
|
||||
rm "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName"
|
||||
rm -rf "$ReleasePath/$BinaryName.app/Contents/_CodeSignature"
|
||||
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
set -e
|
||||
|
||||
DeployTarget="$1"
|
||||
|
||||
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||
set $line
|
||||
eval $1="$2"
|
||||
done < Version
|
||||
|
||||
AppVersionStrFull="$AppVersionStr"
|
||||
DevParam=''
|
||||
if [ "$DevChannel" != "0" ]; then
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
AppVersion="$BetaVersion"
|
||||
AppVersionStrFull="${AppVersionStr}_${BetaVersion}"
|
||||
DevParam="-beta $BetaVersion"
|
||||
BetaKeyFile="tbeta_${AppVersion}_key"
|
||||
elif [ "$DevChannel" == "0" ]; then
|
||||
AppVersionStrFull="$AppVersionStr"
|
||||
DevParam=''
|
||||
else
|
||||
AppVersionStrFull="$AppVersionStr.dev"
|
||||
DevParam='-dev'
|
||||
fi
|
||||
|
||||
if [ ! -f "Target" ]; then
|
||||
echo "Build target not found!"
|
||||
echo "Deploy target not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -35,7 +43,24 @@ elif [ "$BuildTarget" == "linux32" ]; then
|
|||
ReleasePath="./../Linux/Release"
|
||||
RemoteFolder="tlinux32"
|
||||
elif [ "$BuildTarget" == "mac" ]; then
|
||||
echo "Deploying three versions of $AppVersionStrFull: for Windows, OS X 10.6 and 10.7 and OS X 10.8+.."
|
||||
DeployMac="0"
|
||||
DeployMac32="0"
|
||||
DeployWin="0"
|
||||
if [ "$DeployTarget" == "mac" ]; then
|
||||
DeployMac="1"
|
||||
echo "Deploying version $AppVersionStrFull for OS X 10.8+.."
|
||||
elif [ "$DeployTarget" == "mac32" ]; then
|
||||
DeployMac32="1"
|
||||
echo "Deploying version $AppVersionStrFull for OS X 10.6 and 10.7.."
|
||||
elif [ "$DeployTarget" == "win" ]; then
|
||||
DeployWin="1"
|
||||
echo "Deploying version $AppVersionStrFull for Windows.."
|
||||
else
|
||||
DeployMac="1"
|
||||
DeployMac32="1"
|
||||
DeployWin="1"
|
||||
echo "Deploying three versions of $AppVersionStrFull: for Windows, OS X 10.6 and 10.7 and OS X 10.8+.."
|
||||
fi
|
||||
UpdateFile="tmacupd$AppVersion"
|
||||
SetupFile="tsetup.$AppVersionStrFull.dmg"
|
||||
ReleasePath="./../Mac/Release"
|
||||
|
@ -51,6 +76,8 @@ elif [ "$BuildTarget" == "mac" ]; then
|
|||
WinRemoteFolder="tsetup"
|
||||
DropboxPath="./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor"
|
||||
DropboxDeployPath="$DropboxPath/$AppVersionStrFull"
|
||||
DropboxSetupFile="$SetupFile"
|
||||
DropboxMac32SetupFile="$Mac32SetupFile"
|
||||
elif [ "$BuildTarget" == "mac32" ] || [ "$BuildTarget" = "macstore" ]; then
|
||||
echo "No need to deploy this target."
|
||||
exit
|
||||
|
@ -61,69 +88,137 @@ fi
|
|||
|
||||
DeployPath="$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStrFull"
|
||||
|
||||
#if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarget" == "macstore" ]; then
|
||||
|
||||
if [ ! -f "$DeployPath/$UpdateFile" ]; then
|
||||
echo "$UpdateFile not found!";
|
||||
exit 1
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
if [ "$DeployTarget" == "win" ]; then
|
||||
BetaFilePath="$WinDeployPath/$BetaKeyFile"
|
||||
elif [ "$DeployTarget" == "mac32" ]; then
|
||||
BetaFilePath="$Mac32DeployPath/$BetaKeyFile"
|
||||
else
|
||||
BetaFilePath="$DeployPath/$BetaKeyFile"
|
||||
fi
|
||||
if [ ! -f "$BetaFilePath" ]; then
|
||||
echo "Beta key file for $AppVersionStrFull not found :("
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$DeployPath/$SetupFile" ]; then
|
||||
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||
BetaSignature="$line"
|
||||
done < "$BetaFilePath"
|
||||
|
||||
UpdateFile="${UpdateFile}_${BetaSignature}"
|
||||
if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
||||
SetupFile="tbeta${BetaVersion}_${BetaSignature}.tar.xz"
|
||||
elif [ "$BuildTarget" == "mac" ]; then
|
||||
SetupFile="tbeta${BetaVersion}_${BetaSignature}.zip"
|
||||
DropboxSetupFile="tbeta${BetaVersion}_${BetaSignature}_mac.zip"
|
||||
Mac32UpdateFile="${Mac32UpdateFile}_${BetaSignature}"
|
||||
Mac32SetupFile="tbeta${BetaVersion}_${BetaSignature}.zip"
|
||||
DropboxMac32SetupFile="tbeta${BetaVersion}_${BetaSignature}_mac32.zip"
|
||||
WinUpdateFile="${WinUpdateFile}_${BetaSignature}"
|
||||
WinPortableFile="tbeta${BetaVersion}_${BetaSignature}.zip"
|
||||
fi
|
||||
fi
|
||||
|
||||
#if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarget" == "macstore" ]; then
|
||||
|
||||
if [ "$BuildTarget" != "mac" ] || [ "$DeployMac" == "1" ]; then
|
||||
if [ ! -f "$DeployPath/$UpdateFile" ]; then
|
||||
echo "$UpdateFile not found!";
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$DeployPath/$SetupFile" ]; then
|
||||
echo "$SetupFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$BuildTarget" == "mac" ]; then
|
||||
if [ ! -f "$Mac32DeployPath/$Mac32UpdateFile" ]; then
|
||||
echo "$Mac32UpdateFile not found!"
|
||||
exit 1
|
||||
if [ "$DeployMac32" == "1" ]; then
|
||||
if [ ! -f "$Mac32DeployPath/$Mac32UpdateFile" ]; then
|
||||
echo "$Mac32UpdateFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$Mac32DeployPath/$Mac32SetupFile" ]; then
|
||||
echo "$Mac32SetupFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$Mac32DeployPath/$Mac32SetupFile" ]; then
|
||||
echo "$Mac32SetupFile not found!"
|
||||
exit 1
|
||||
if [ "$DeployWin" == "1" ]; then
|
||||
if [ ! -f "$WinDeployPath/$WinUpdateFile" ]; then
|
||||
echo "$WinUpdateFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$BetaVersion" == "0" ]; then
|
||||
if [ ! -f "$WinDeployPath/$WinSetupFile" ]; then
|
||||
echo "$WinSetupFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$WinDeployPath/$WinPortableFile" ]; then
|
||||
echo "$WinPortableFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$WinDeployPath/$WinUpdateFile" ]; then
|
||||
echo "$WinUpdateFile not found!"
|
||||
exit 1
|
||||
if [ ! -d "$DropboxPath" ]; then
|
||||
mkdir "$DropboxPath"
|
||||
fi
|
||||
|
||||
if [ ! -f "$WinDeployPath/$WinSetupFile" ]; then
|
||||
echo "$WinSetupFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$WinDeployPath/$WinPortableFile" ]; then
|
||||
echo "$WinPortableFile not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor" ]; then
|
||||
mkdir "./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor"
|
||||
if [ ! -d "$DropboxDeployPath" ]; then
|
||||
mkdir "$DropboxDeployPath"
|
||||
fi
|
||||
fi
|
||||
#fi
|
||||
|
||||
if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$BuildTarget" == "mac" ]; then
|
||||
scp "$DeployPath/$UpdateFile" "tmaster:tdesktop/www/$RemoteFolder/"
|
||||
scp "$DeployPath/$SetupFile" "tmaster:tdesktop/www/$RemoteFolder/"
|
||||
|
||||
if [ "$BuildTarget" != "mac" ] || [ "$DeployMac" == "1" ]; then
|
||||
scp "$DeployPath/$UpdateFile" "tmaster:tdesktop/www/$RemoteFolder/"
|
||||
scp "$DeployPath/$SetupFile" "tmaster:tdesktop/www/$RemoteFolder/"
|
||||
fi
|
||||
if [ "$BuildTarget" == "mac" ]; then
|
||||
scp "$Mac32DeployPath/$Mac32UpdateFile" "tmaster:tdesktop/www/$Mac32RemoteFolder/"
|
||||
scp "$Mac32DeployPath/$Mac32SetupFile" "tmaster:tdesktop/www/$Mac32RemoteFolder/"
|
||||
scp "$WinDeployPath/$WinUpdateFile" "tmaster:tdesktop/www/$WinRemoteFolder/"
|
||||
scp "$WinDeployPath/$WinSetupFile" "tmaster:tdesktop/www/$WinRemoteFolder/"
|
||||
scp "$WinDeployPath/$WinPortableFile" "tmaster:tdesktop/www/$WinRemoteFolder/"
|
||||
if [ "$DeployMac32" == "1" ]; then
|
||||
scp "$Mac32DeployPath/$Mac32UpdateFile" "tmaster:tdesktop/www/$Mac32RemoteFolder/"
|
||||
scp "$Mac32DeployPath/$Mac32SetupFile" "tmaster:tdesktop/www/$Mac32RemoteFolder/"
|
||||
fi
|
||||
if [ "$DeployWin" == "1" ]; then
|
||||
scp "$WinDeployPath/$WinUpdateFile" "tmaster:tdesktop/www/$WinRemoteFolder/"
|
||||
if [ "$BetaVersion" == "0" ]; then
|
||||
scp "$WinDeployPath/$WinSetupFile" "tmaster:tdesktop/www/$WinRemoteFolder/"
|
||||
fi
|
||||
scp "$WinDeployPath/$WinPortableFile" "tmaster:tdesktop/www/$WinRemoteFolder/"
|
||||
fi
|
||||
|
||||
mv -v "$WinDeployPath" "$DropboxPath/"
|
||||
|
||||
cp -v "$DeployPath/$UpdateFile" "$DropboxDeployPath/"
|
||||
cp -v "$DeployPath/$SetupFile" "$DropboxDeployPath/"
|
||||
cp -rv "$DeployPath/Telegram.app.dSYM" "$DropboxDeployPath/"
|
||||
cp -v "$Mac32DeployPath/$Mac32UpdateFile" "$DropboxDeployPath/"
|
||||
cp -v "$Mac32DeployPath/$Mac32SetupFile" "$DropboxDeployPath/"
|
||||
cp -rv "$DeployPath/Telegram.app.dSYM" "$DropboxDeployPath/Telegram32.app.dSYM"
|
||||
if [ "$DeployMac" == "1" ]; then
|
||||
cp -v "$DeployPath/$UpdateFile" "$DropboxDeployPath/"
|
||||
cp -v "$DeployPath/$SetupFile" "$DropboxDeployPath/$DropboxSetupFile"
|
||||
if [ -d "$DropboxDeployPath/Telegram.app.dSYM" ]; then
|
||||
rm -rf "$DropboxDeployPath/Telegram.app.dSYM"
|
||||
fi
|
||||
cp -rv "$DeployPath/Telegram.app.dSYM" "$DropboxDeployPath/"
|
||||
fi
|
||||
if [ "$DeployMac32" == "1" ]; then
|
||||
mv -v "$Mac32DeployPath/$Mac32UpdateFile" "$DropboxDeployPath/"
|
||||
mv -v "$Mac32DeployPath/$Mac32SetupFile" "$DropboxDeployPath/$DropboxMac32SetupFile"
|
||||
if [ -d "$DropboxDeployPath/Telegram32.app.dSYM" ]; then
|
||||
rm -rf "$DropboxDeployPath/Telegram32.app.dSYM"
|
||||
fi
|
||||
mv -v "$Mac32DeployPath/Telegram.app.dSYM" "$DropboxDeployPath/Telegram32.app.dSYM"
|
||||
fi
|
||||
if [ "$DeployWin" == "1" ]; then
|
||||
mv -v "$WinDeployPath/Telegram.pdb" "$DropboxDeployPath/"
|
||||
mv -v "$WinDeployPath/Updater.exe" "$DropboxDeployPath/"
|
||||
mv -v "$WinDeployPath/Updater.pdb" "$DropboxDeployPath/"
|
||||
mv -v "$WinDeployPath/$WinUpdateFile" "$DropboxDeployPath/"
|
||||
if [ "$BetaVersion" == "0" ]; then
|
||||
mv -v "$WinDeployPath/$WinSetupFile" "$DropboxDeployPath/"
|
||||
fi
|
||||
mv -v "$WinDeployPath/$WinPortableFile" "$DropboxDeployPath/"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -431,6 +431,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_channel_add_admins" = "New administrator";
|
||||
"lng_channel_add_members" = "Add members";
|
||||
"lng_channel_members" = "Members";
|
||||
"lng_channel_only_last_shown" = "Only the last {count:_not_used_|# member is|# members are} shown here";
|
||||
"lng_channel_admins" = "Administrators";
|
||||
"lng_channel_add_admin" = "Add Administrator";
|
||||
"lng_channel_admin_sure" = "Add {user} to administrators?";
|
||||
|
@ -564,10 +565,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category1" = "People";
|
||||
"lng_emoji_category2" = "Nature";
|
||||
"lng_emoji_category3" = "Food & Drink";
|
||||
"lng_emoji_category4" = "Celebration";
|
||||
"lng_emoji_category5" = "Activity";
|
||||
"lng_emoji_category6" = "Travel & Places";
|
||||
"lng_emoji_category7" = "Objects & Symbols";
|
||||
"lng_emoji_category4" = "Activity";
|
||||
"lng_emoji_category5" = "Travel & Places";
|
||||
"lng_emoji_category6" = "Objects";
|
||||
"lng_emoji_category7" = "Symbols & Flags";
|
||||
|
||||
"lng_switch_stickers" = "Stickers";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
@ -581,6 +582,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_not_found" = "Sticker pack not found.";
|
||||
"lng_stickers_copied" = "Sticker pack link copied to clipboard.";
|
||||
"lng_stickers_default_set" = "Great Minds";
|
||||
"lng_stickers_you_have" = "Manage and reorder sticker packs";
|
||||
"lng_stickers_packs" = "Sticker Packs";
|
||||
"lng_stickers_reorder" = "Click and drag to reorder sticker packs";
|
||||
"lng_stickers_remove" = "Delete";
|
||||
"lng_stickers_return" = "Undo";
|
||||
"lng_stickers_restore" = "Restore";
|
||||
"lng_stickers_count" = "{count:Loading..|# sticker|# stickers}";
|
||||
|
||||
"lng_in_dlg_photo" = "Photo";
|
||||
"lng_in_dlg_video" = "Video";
|
||||
|
@ -658,6 +666,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
"lng_choose_images" = "Choose images";
|
||||
|
||||
"lng_context_view_profile" = "View profile";
|
||||
"lng_context_view_group" = "View group info";
|
||||
"lng_context_view_channel" = "View channel info";
|
||||
|
||||
"lng_context_open_link" = "Open Link";
|
||||
"lng_context_copy_link" = "Copy Link";
|
||||
"lng_context_open_email" = "Write to this address";
|
||||
|
@ -789,7 +801,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
||||
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
||||
"lng_new_version_text" = "— Groups can now have multiple administrators with the ability to edit the name and logo, and add and remove members\n— Groups that have reached their capacity of 200 users can be upgraded to supergroups of up to 1,000 members\n\nMore about admins and supergroups:\n{link}";
|
||||
"lng_new_version_text" = "— Sticker management: manually rearrange your sticker packs, pack order is now synced across all your devices\n— Click and hold on a sticker to preview it before sending\n— New context menu for chats in chats list\n— Support for all existing emoji";
|
||||
|
||||
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ titleBG: #6389a8;
|
|||
titleColor: #0f8dcc;//rgb(20, 136, 210);
|
||||
titleHeight: 39px;
|
||||
titleIconPos: point(7px, 7px);
|
||||
titleIconImg: sprite(160px, 100px, 26px, 26px);
|
||||
titleIconImg: sprite(161px, 100px, 26px, 26px);
|
||||
titleFont: font(17px);
|
||||
titlePos: point(44px, 29px);
|
||||
titleMenuOffset: 36px;
|
||||
|
@ -1424,12 +1424,13 @@ contactsNewItemIconPosition: point(29px, 19px);
|
|||
contactsNewItemTop: 18px;
|
||||
contactsNewItemFg: #4b82af;
|
||||
contactsAboutBg: #f7f7f7;
|
||||
contactsAboutShadow: #0000001F;
|
||||
contactsAdminCheckbox: Checkbox(defaultCheckbox) {
|
||||
font: semiboldFont;
|
||||
textBg: #f7f7f7;
|
||||
textPosition: point(34px, 1px);
|
||||
}
|
||||
contactsAboutHeight: 80px;
|
||||
contactsAboutHeight: 42px;
|
||||
contactsAboutTop: 9px;
|
||||
contactsScroll: flatScroll(boxScroll) {
|
||||
deltab: 0px;
|
||||
|
@ -1794,6 +1795,10 @@ stickersScroll: flatScroll(boxScroll) {
|
|||
deltat: 23px;
|
||||
deltab: 9px;
|
||||
}
|
||||
stickersReorderPadding: margins(0px, 12px, 0px, 12px);
|
||||
stickersReorderFg: #777;
|
||||
stickersRowDisabledOpacity: 0.4;
|
||||
stickersRowDuration: 200;
|
||||
|
||||
emojiScroll: flatScroll(solidScroll) {
|
||||
deltat: 48px;
|
||||
|
@ -1806,14 +1811,15 @@ emojiNatureOver: sprite(42px, 196px, 21px, 22px);
|
|||
emojiNatureActive: sprite(245px, 286px, 21px, 22px);
|
||||
emojiFoodOver: sprite(63px, 196px, 21px, 22px);
|
||||
emojiFoodActive: sprite(266px, 286px, 21px, 22px);
|
||||
emojiCelebrationOver: sprite(84px, 196px, 21px, 22px);
|
||||
emojiCelebrationActive: sprite(287px, 286px, 21px, 22px);
|
||||
emojiActivityOver: sprite(126px, 196px, 21px, 22px);
|
||||
emojiActivityActive: sprite(287px, 264px, 21px, 22px);
|
||||
emojiTravelOver: sprite(105px, 196px, 21px, 22px);
|
||||
emojiTravelActive: sprite(308px, 286px, 21px, 22px);
|
||||
emojiObjectsOver: sprite(147px, 196px, 21px, 22px);
|
||||
emojiObjectsActive: sprite(308px, 264px, 21px, 22px);
|
||||
emojiSymbolsOver: sprite(84px, 196px, 21px, 22px);
|
||||
emojiSymbolsActive: sprite(287px, 286px, 21px, 22px);
|
||||
stickersSettings: sprite(140px, 124px, 21px, 22px);
|
||||
|
||||
emojiPanCategories: #f7f7f7;
|
||||
|
||||
|
@ -1867,14 +1873,6 @@ rbEmojiFood: flatCheckbox(rbEmoji) {
|
|||
disImageRect: emojiFoodOver;
|
||||
chkDisImageRect: emojiFoodActive;
|
||||
}
|
||||
rbEmojiCelebration: flatCheckbox(rbEmoji) {
|
||||
imageRect: emojiCelebrationOver;
|
||||
chkImageRect: emojiCelebrationActive;
|
||||
overImageRect: emojiCelebrationOver;
|
||||
chkOverImageRect: emojiCelebrationActive;
|
||||
disImageRect: emojiCelebrationOver;
|
||||
chkDisImageRect: emojiCelebrationActive;
|
||||
}
|
||||
rbEmojiActivity: flatCheckbox(rbEmoji) {
|
||||
imageRect: emojiActivityOver;
|
||||
chkImageRect: emojiActivityActive;
|
||||
|
@ -1899,6 +1897,14 @@ rbEmojiObjects: flatCheckbox(rbEmoji) {
|
|||
disImageRect: emojiObjectsOver;
|
||||
chkDisImageRect: emojiObjectsActive;
|
||||
}
|
||||
rbEmojiSymbols: flatCheckbox(rbEmoji) {
|
||||
imageRect: emojiSymbolsOver;
|
||||
chkImageRect: emojiSymbolsActive;
|
||||
overImageRect: emojiSymbolsOver;
|
||||
chkOverImageRect: emojiSymbolsActive;
|
||||
disImageRect: emojiSymbolsOver;
|
||||
chkDisImageRect: emojiSymbolsActive;
|
||||
}
|
||||
emojiPanPadding: 12px;
|
||||
emojiPanSize: size(45px, 41px);
|
||||
emojiPanWidth: 345px;
|
||||
|
@ -1934,12 +1940,15 @@ stickerIconSelColor: #58b2ed;
|
|||
stickerIconLeft: sprite(342px, 72px, 40px, 1px);
|
||||
stickerIconRight: sprite(342px, 73px, 40px, 1px);
|
||||
stickerIconMove: 400;
|
||||
stickerPreviewDuration: 150;
|
||||
stickerPreviewBg: #FFFFFFB0;
|
||||
stickerPreviewMin: 0.1;
|
||||
|
||||
verifiedCheckProfile: sprite(285px, 240px, 22px, 22px);
|
||||
verifiedCheckProfilePos: point(9px, 4px);
|
||||
verifiedCheck: sprite(285px, 221px, 19px, 19px);
|
||||
verifiedCheckInv: sprite(304px, 221px, 19px, 19px);
|
||||
verifiedCheckPos: point(5px, 0px);
|
||||
verifiedCheckProfile: sprite(285px, 235px, 18px, 18px);
|
||||
verifiedCheckProfilePos: point(7px, 6px);
|
||||
verifiedCheck: sprite(285px, 221px, 14px, 14px);
|
||||
verifiedCheckInv: sprite(299px, 221px, 14px, 14px);
|
||||
verifiedCheckPos: point(4px, 2px);
|
||||
|
||||
botKbDuration: 200;
|
||||
botKbBg: #f7f7f7;
|
||||
|
|
|
@ -36,8 +36,9 @@ Q_IMPORT_PLUGIN(QWebpPlugin)
|
|||
#endif
|
||||
|
||||
bool DevChannel = false;
|
||||
quint64 BetaVersion = 0;
|
||||
|
||||
const char *publicKey = "\
|
||||
const char *PublicKey = "\
|
||||
-----BEGIN RSA PUBLIC KEY-----\n\
|
||||
MIGJAoGBAMA4ViQrjkPZ9xj0lrer3r23JvxOnrtE8nI69XLGSr+sRERz9YnUptnU\n\
|
||||
BZpkIfKaRcl6XzNJiN28cVwO1Ui5JSa814UAiDHzWUqCaXUiUEQ6NmNTneiGx2sQ\n\
|
||||
|
@ -45,7 +46,7 @@ BZpkIfKaRcl6XzNJiN28cVwO1Ui5JSa814UAiDHzWUqCaXUiUEQ6NmNTneiGx2sQ\n\
|
|||
-----END RSA PUBLIC KEY-----\
|
||||
";
|
||||
|
||||
const char *publicDevKey = "\
|
||||
const char *PublicDevKey = "\
|
||||
-----BEGIN RSA PUBLIC KEY-----\n\
|
||||
MIGJAoGBALWu9GGs0HED7KG7BM73CFZ6o0xufKBRQsdnq3lwA8nFQEvmdu+g/I1j\n\
|
||||
0LQ+0IQO7GW4jAgzF/4+soPDb6uHQeNFrlVx1JS9DZGhhjZ5rf65yg11nTCIHZCG\n\
|
||||
|
@ -53,9 +54,12 @@ w/CVnbwQOw0g5GBwwFV3r0uTTvy44xx8XXxk+Qknu4eBCsmrAFNnAgMBAAE=\n\
|
|||
-----END RSA PUBLIC KEY-----\
|
||||
";
|
||||
|
||||
extern const char *privateKey;
|
||||
extern const char *privateDevKey;
|
||||
extern const char *PrivateKey;
|
||||
extern const char *PrivateDevKey;
|
||||
#include "../../../../TelegramPrivate/packer_private.h" // RSA PRIVATE KEYS for update signing
|
||||
#include "../../../../TelegramPrivate/beta_private.h" // private key for beta version file generation
|
||||
|
||||
QString countBetaVersionSignature(quint64 version);
|
||||
|
||||
// sha1 hash
|
||||
typedef unsigned char uchar;
|
||||
|
@ -138,6 +142,8 @@ int32 *hashSha1(const void *data, uint32 len, void *dest) {
|
|||
return (int32*)sha1To;
|
||||
}
|
||||
|
||||
QString BetaSignature;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QString workDir;
|
||||
|
@ -167,14 +173,28 @@ int main(int argc, char *argv[])
|
|||
version = QString(argv[i + 1]).toInt();
|
||||
} else if (string("-dev") == argv[i]) {
|
||||
DevChannel = true;
|
||||
} else if (string("-beta") == argv[i] && i + 1 < argc) {
|
||||
BetaVersion = QString(argv[i + 1]).toULongLong();
|
||||
if (BetaVersion > version * 1000ULL && BetaVersion < (version + 1) * 1000ULL) {
|
||||
DevChannel = false;
|
||||
BetaSignature = countBetaVersionSignature(BetaVersion);
|
||||
if (BetaSignature.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
cout << "Bad -beta param value passed, should be for the same version: " << version << ", beta: " << BetaVersion << "\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (files.isEmpty() || remove.isEmpty() || version <= 1016 || version > 999999) { // not for release =)
|
||||
if (files.isEmpty() || remove.isEmpty() || version <= 1016 || version > 999999999) {
|
||||
#ifdef Q_OS_WIN
|
||||
cout << "Usage: Packer.exe -path {file} -version {version} OR Packer.exe -path {dir} -version {version}\n";
|
||||
#elif defined Q_OS_MAC
|
||||
cout << "Usage: Packer.app -path {file} -version {version} OR Packer.app -path {dir} -version {version}\n";
|
||||
#else
|
||||
cout << "Usage: Packer -path {file} -version {version} OR Packer -path {dir} -version {version}\n";
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
@ -218,7 +238,12 @@ int main(int argc, char *argv[])
|
|||
QDataStream stream(&buffer);
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
|
||||
stream << quint32(version);
|
||||
if (BetaVersion) {
|
||||
stream << quint32(0x7FFFFFFF);
|
||||
stream << quint64(BetaVersion);
|
||||
} else {
|
||||
stream << quint32(version);
|
||||
}
|
||||
|
||||
stream << quint32(files.size());
|
||||
cout << "Found " << files.size() << " file" << (files.size() == 1 ? "" : "s") << "..\n";
|
||||
|
@ -409,19 +434,19 @@ int main(int argc, char *argv[])
|
|||
uint32 siglen = 0;
|
||||
|
||||
cout << "Signing..\n";
|
||||
RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(DevChannel ? privateDevKey : privateKey), -1), 0, 0, 0);
|
||||
RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>((DevChannel || BetaVersion) ? PrivateDevKey : PrivateKey), -1), 0, 0, 0);
|
||||
if (!prKey) {
|
||||
cout << "Could not read RSA private key!\n";
|
||||
return -1;
|
||||
}
|
||||
if (RSA_size(prKey) != hSigLen) {
|
||||
RSA_free(prKey);
|
||||
cout << "Bad private key, size: " << RSA_size(prKey) << "\n";
|
||||
RSA_free(prKey);
|
||||
return -1;
|
||||
}
|
||||
if (RSA_sign(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (uchar*)(compressed.data()), &siglen, prKey) != 1) { // count signature
|
||||
RSA_free(prKey);
|
||||
cout << "Signing failed!\n";
|
||||
RSA_free(prKey);
|
||||
return -1;
|
||||
}
|
||||
RSA_free(prKey);
|
||||
|
@ -432,7 +457,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
cout << "Checking signature..\n";
|
||||
RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(DevChannel ? publicDevKey : publicKey), -1), 0, 0, 0);
|
||||
RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>((DevChannel || BetaVersion) ? PublicDevKey : PublicKey), -1), 0, 0, 0);
|
||||
if (!pbKey) {
|
||||
cout << "Could not read RSA public key!\n";
|
||||
return -1;
|
||||
|
@ -445,16 +470,19 @@ int main(int argc, char *argv[])
|
|||
cout << "Signature verified!\n";
|
||||
RSA_free(pbKey);
|
||||
#ifdef Q_OS_WIN
|
||||
QString outName(QString("tupdate%1").arg(version));
|
||||
QString outName(QString("tupdate%1").arg(BetaVersion ? BetaVersion : version));
|
||||
#elif defined Q_OS_MAC
|
||||
QString outName(QString("tmacupd%1").arg(version));
|
||||
QString outName(QString("tmacupd%1").arg(BetaVersion ? BetaVersion : version));
|
||||
#elif defined Q_OS_LINUX32
|
||||
QString outName(QString("tlinux32upd%1").arg(version));
|
||||
QString outName(QString("tlinux32upd%1").arg(BetaVersion ? BetaVersion : version));
|
||||
#elif defined Q_OS_LINUX64
|
||||
QString outName(QString("tlinuxupd%1").arg(version));
|
||||
QString outName(QString("tlinuxupd%1").arg(BetaVersion ? BetaVersion : version));
|
||||
#else
|
||||
#error Unknown platform!
|
||||
#endif
|
||||
if (BetaVersion) {
|
||||
outName += "_" + BetaSignature;
|
||||
}
|
||||
QFile out(outName);
|
||||
if (!out.open(QIODevice::WriteOnly)) {
|
||||
cout << "Can't open '" << outName.toUtf8().constData() << "' for write..\n";
|
||||
|
@ -463,7 +491,63 @@ int main(int argc, char *argv[])
|
|||
out.write(compressed);
|
||||
out.close();
|
||||
|
||||
if (BetaVersion) {
|
||||
QString keyName(QString("tbeta_%1_key").arg(BetaVersion));
|
||||
QFile key(keyName);
|
||||
if (!key.open(QIODevice::WriteOnly)) {
|
||||
cout << "Can't open '" << keyName.toUtf8().constData() << "' for write..\n";
|
||||
return -1;
|
||||
}
|
||||
key.write(BetaSignature.toUtf8());
|
||||
key.close();
|
||||
}
|
||||
|
||||
cout << "Update file '" << outName.toUtf8().constData() << "' written successfully!\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString countBetaVersionSignature(quint64 version) { // duplicated in autoupdate.cpp
|
||||
QByteArray cBetaPrivateKey(BetaPrivateKey);
|
||||
if (cBetaPrivateKey.isEmpty()) {
|
||||
cout << "Error: Trying to count beta version signature without beta private key!\n";
|
||||
return QString();
|
||||
}
|
||||
|
||||
QByteArray signedData = (QLatin1String("TelegramBeta_") + QString::number(version, 16).toLower()).toUtf8();
|
||||
|
||||
static const int32 shaSize = 20, keySize = 128;
|
||||
|
||||
uchar sha1Buffer[shaSize];
|
||||
hashSha1(signedData.constData(), signedData.size(), sha1Buffer); // count sha1
|
||||
|
||||
uint32 siglen = 0;
|
||||
|
||||
RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cBetaPrivateKey.constData()), -1), 0, 0, 0);
|
||||
if (!prKey) {
|
||||
cout << "Error: Could not read beta private key!\n";
|
||||
return QString();
|
||||
}
|
||||
if (RSA_size(prKey) != keySize) {
|
||||
cout << "Error: Bad beta private key size: " << RSA_size(prKey) << "\n";
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
QByteArray signature;
|
||||
signature.resize(keySize);
|
||||
if (RSA_sign(NID_sha1, (const uchar*)(sha1Buffer), shaSize, (uchar*)(signature.data()), &siglen, prKey) != 1) { // count signature
|
||||
cout << "Error: Counting beta version signature failed!\n";
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
RSA_free(prKey);
|
||||
|
||||
if (siglen != keySize) {
|
||||
cout << "Error: Bad beta version signature length: " << siglen << "\n";
|
||||
return QString();
|
||||
}
|
||||
|
||||
signature = signature.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
signature = signature.replace('-', '8').replace('_', 'B');
|
||||
return QString::fromUtf8(signature.mid(19, 32));
|
||||
}
|
||||
|
|
|
@ -148,10 +148,14 @@ bool update() {
|
|||
if (versionFile != INVALID_HANDLE_VALUE) {
|
||||
if (!ReadFile(versionFile, &versionNum, sizeof(DWORD), &readLen, NULL) || readLen != sizeof(DWORD)) {
|
||||
versionNum = 0;
|
||||
} else if (!ReadFile(versionFile, &versionLen, sizeof(DWORD), &readLen, NULL) || readLen != sizeof(DWORD) || versionLen > 63) {
|
||||
versionNum = 0;
|
||||
} else if (!ReadFile(versionFile, versionStr, versionLen, &readLen, NULL) || readLen != versionLen) {
|
||||
versionNum = 0;
|
||||
} else {
|
||||
if (versionNum == 0x7FFFFFFF) { // beta version
|
||||
|
||||
} else if (!ReadFile(versionFile, &versionLen, sizeof(DWORD), &readLen, NULL) || readLen != sizeof(DWORD) || versionLen > 63) {
|
||||
versionNum = 0;
|
||||
} else if (!ReadFile(versionFile, versionStr, versionLen, &readLen, NULL) || readLen != versionLen) {
|
||||
versionNum = 0;
|
||||
}
|
||||
}
|
||||
CloseHandle(versionFile);
|
||||
writeLog(L"Version file read.");
|
||||
|
@ -270,7 +274,7 @@ bool update() {
|
|||
}
|
||||
|
||||
void updateRegistry() {
|
||||
if (versionNum) {
|
||||
if (versionNum && versionNum != 0x7FFFFFFF) {
|
||||
writeLog(L"Updating registry..");
|
||||
versionStr[versionLen / 2] = 0;
|
||||
HKEY rkey;
|
||||
|
|
|
@ -726,29 +726,19 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
it->access = s.vaccess_hash.v;
|
||||
it->hash = s.vhash.v;
|
||||
it->shortName = qs(s.vshort_name);
|
||||
QString title = qs(s.vtitle);
|
||||
if ((it->flags & MTPDstickerSet::flag_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) {
|
||||
title = lang(lng_stickers_default_set);
|
||||
}
|
||||
it->title = title;
|
||||
it->title = stickerSetTitle(s);
|
||||
it->flags = s.vflags.v;
|
||||
|
||||
const QVector<MTPDocument> &d_docs(d.vdocuments.c_vector().v);
|
||||
StickerSets::iterator custom = sets.find(CustomStickerSetId);
|
||||
|
||||
QSet<DocumentData*> found;
|
||||
int32 wasCount = -1;
|
||||
StickerPack pack;
|
||||
pack.reserve(d_docs.size());
|
||||
for (int32 i = 0, l = d_docs.size(); i != l; ++i) {
|
||||
DocumentData *doc = App::feedDocument(d_docs.at(i));
|
||||
if (!doc || !doc->sticker()) continue;
|
||||
|
||||
if (wasCount < 0) wasCount = it->stickers.size();
|
||||
if (it->stickers.indexOf(doc) < 0) {
|
||||
it->stickers.push_back(doc);
|
||||
} else {
|
||||
found.insert(doc);
|
||||
}
|
||||
|
||||
pack.push_back(doc);
|
||||
if (custom != sets.cend()) {
|
||||
int32 index = custom->stickers.indexOf(doc);
|
||||
if (index >= 0) {
|
||||
|
@ -763,39 +753,20 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
|
||||
bool writeRecent = false;
|
||||
RecentStickerPack &recent(cGetRecentStickers());
|
||||
|
||||
if (wasCount < 0) { // no stickers received
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
cRefStickerSetsOrder().removeOne(setId);
|
||||
}
|
||||
if (pack.isEmpty()) {
|
||||
int32 removeIndex = cStickerSetsOrder().indexOf(setId);
|
||||
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
||||
sets.erase(it);
|
||||
} else {
|
||||
for (int32 j = 0, l = wasCount; j < l;) {
|
||||
if (found.contains(it->stickers.at(j))) {
|
||||
++j;
|
||||
} else {
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.at(j) == i->first) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
it->stickers.removeAt(j);
|
||||
--l;
|
||||
}
|
||||
}
|
||||
if (it->stickers.isEmpty()) {
|
||||
cRefStickerSetsOrder().removeOne(setId);
|
||||
sets.erase(it);
|
||||
}
|
||||
it->stickers = pack;
|
||||
}
|
||||
|
||||
if (writeRecent) {
|
||||
|
|
|
@ -1632,8 +1632,9 @@ namespace App {
|
|||
convert->sticker()->loc = thumbLocation;
|
||||
}
|
||||
|
||||
if (convert->location.check()) {
|
||||
Local::writeFileLocation(mediaKey(DocumentFileLocation, convert->dc, convert->id), convert->location);
|
||||
const FileLocation &loc(convert->location(true));
|
||||
if (!loc.isEmpty()) {
|
||||
Local::writeFileLocation(mediaKey(DocumentFileLocation, convert->dc, convert->id), loc);
|
||||
}
|
||||
}
|
||||
DocumentsData::const_iterator i = documentsData.constFind(document);
|
||||
|
@ -1984,7 +1985,7 @@ namespace App {
|
|||
webPagesData.clear();
|
||||
if (api()) api()->clearWebPageRequests();
|
||||
cSetRecentStickers(RecentStickerPack());
|
||||
cSetStickersHash(QByteArray());
|
||||
cSetStickersHash(0);
|
||||
cSetStickerSets(StickerSets());
|
||||
cSetStickerSetsOrder(StickerSetsOrder());
|
||||
cSetLastStickersUpdate(0);
|
||||
|
@ -2804,79 +2805,4 @@ namespace App {
|
|||
|
||||
WallPapers gServerBackgrounds;
|
||||
|
||||
void sendBotCommand(const QString &cmd, MsgId replyTo) {
|
||||
if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
|
||||
}
|
||||
|
||||
void insertBotCommand(const QString &cmd) {
|
||||
if (MainWidget *m = main()) m->insertBotCommand(cmd);
|
||||
}
|
||||
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer) {
|
||||
if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
|
||||
}
|
||||
|
||||
void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
|
||||
if (MainWidget *m = main()) m->openPeerByName(username, toProfile, startToken);
|
||||
}
|
||||
|
||||
void joinGroupByHash(const QString &hash) {
|
||||
if (MainWidget *m = main()) m->joinGroupByHash(hash);
|
||||
}
|
||||
|
||||
void stickersBox(const QString &name) {
|
||||
if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
|
||||
}
|
||||
|
||||
void openLocalUrl(const QString &url) {
|
||||
if (MainWidget *m = main()) m->openLocalUrl(url);
|
||||
}
|
||||
|
||||
bool forward(const PeerId &peer, ForwardWhatMessages what) {
|
||||
if (MainWidget *m = main()) return m->onForward(peer, what);
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeDialog(History *history) {
|
||||
if (MainWidget *m = main()) m->removeDialog(history);
|
||||
}
|
||||
|
||||
void showSettings() {
|
||||
if (Window *win = wnd()) win->showSettings();
|
||||
}
|
||||
|
||||
void showLayer(LayeredWidget *w, bool forceFast) {
|
||||
if (Window *win = wnd()) win->showLayer(w, forceFast);
|
||||
}
|
||||
|
||||
void replaceLayer(LayeredWidget *w) {
|
||||
if (Window *win = wnd()) win->replaceLayer(w);
|
||||
}
|
||||
|
||||
void showLayerLast(LayeredWidget *w) {
|
||||
if (Window *win = wnd()) win->showLayerLast(w);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Notify {
|
||||
|
||||
void userIsBotChanged(UserData *user) {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->notifyUserIsBotChanged(user);
|
||||
}
|
||||
}
|
||||
|
||||
void botCommandsChanged(UserData *user) {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->notifyBotCommandsChanged(user);
|
||||
}
|
||||
}
|
||||
|
||||
void migrateUpdated(PeerData *peer) {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->notifyMigrateUpdated(peer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,13 +80,6 @@ enum RoundCorners {
|
|||
RoundCornersCount
|
||||
};
|
||||
|
||||
enum ForwardWhatMessages {
|
||||
ForwardSelectedMessages,
|
||||
ForwardContextMessage,
|
||||
ForwardPressedMessage,
|
||||
ForwardPressedLinkMessage
|
||||
};
|
||||
|
||||
class LayeredWidget;
|
||||
|
||||
namespace App {
|
||||
|
@ -233,7 +226,7 @@ namespace App {
|
|||
bool quiting();
|
||||
void setQuiting();
|
||||
|
||||
QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
|
||||
QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
|
||||
QImage readImage(const QString &file, QByteArray *format = 0, bool opaque = true, bool *animated = 0, QByteArray *content = 0);
|
||||
|
||||
void regVideoItem(VideoData *data, HistoryItem *item);
|
||||
|
@ -300,26 +293,27 @@ namespace App {
|
|||
typedef QList<WallPaper> WallPapers;
|
||||
DeclareSetting(WallPapers, ServerBackgrounds);
|
||||
|
||||
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
|
||||
void insertBotCommand(const QString &cmd);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
|
||||
void joinGroupByHash(const QString &hash);
|
||||
void stickersBox(const QString &name);
|
||||
void openLocalUrl(const QString &url);
|
||||
bool forward(const PeerId &peer, ForwardWhatMessages what);
|
||||
void removeDialog(History *history);
|
||||
void showSettings();
|
||||
void showLayer(LayeredWidget *w, bool forceFast = false);
|
||||
void replaceLayer(LayeredWidget *w);
|
||||
void showLayerLast(LayeredWidget *w);
|
||||
|
||||
};
|
||||
|
||||
namespace Notify {
|
||||
inline int32 stickersCountHash(bool checkOfficial = false) {
|
||||
uint32 acc = 0;
|
||||
bool foundOfficial = false, foundBad = false;;
|
||||
const StickerSets &sets(cStickerSets());
|
||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||
for (StickerSetsOrder::const_iterator i = order.cbegin(), e = order.cend(); i != e; ++i) {
|
||||
StickerSets::const_iterator j = sets.constFind(*i);
|
||||
if (j != sets.cend()) {
|
||||
if (j->id == 0) {
|
||||
foundBad = true;
|
||||
} else if (j->flags & MTPDstickerSet::flag_official) {
|
||||
foundOfficial = true;
|
||||
}
|
||||
if (!(j->flags & MTPDstickerSet::flag_disabled)) {
|
||||
acc = (acc * 20261) + j->hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
|
||||
}
|
||||
|
||||
void userIsBotChanged(UserData *user);
|
||||
void botCommandsChanged(UserData *user);
|
||||
void migrateUpdated(PeerData *peer);
|
||||
|
||||
};
|
||||
#include "facades.h"
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace {
|
|||
bool eventFilter(QObject *o, QEvent *e) {
|
||||
if (e->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *ev = static_cast<QKeyEvent*>(e);
|
||||
if (cPlatform() == dbipMac) {
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
if (ev->key() == Qt::Key_W && (ev->modifiers() & Qt::ControlModifier)) {
|
||||
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
|
||||
App::wnd()->minimizeToTray();
|
||||
|
@ -210,11 +210,17 @@ void Application::updateGotCurrent() {
|
|||
cSetLastUpdateCheck(unixtime());
|
||||
QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromUtf8(updateReply->readAll()));
|
||||
if (m.hasMatch()) {
|
||||
int32 currentVersion = m.captured(1).toInt();
|
||||
if (currentVersion > AppVersion) {
|
||||
uint64 currentVersion = m.captured(1).toULongLong();
|
||||
QString url = m.captured(2);
|
||||
bool betaVersion = false;
|
||||
if (url.startsWith(qstr("beta_"))) {
|
||||
betaVersion = true;
|
||||
url = url.mid(5) + '_' + countBetaVersionSignature(currentVersion);
|
||||
}
|
||||
if ((!betaVersion || cBetaVersion()) && currentVersion > (betaVersion ? cBetaVersion() : uint64(AppVersion))) {
|
||||
updateThread = new QThread();
|
||||
connect(updateThread, SIGNAL(finished()), updateThread, SLOT(deleteLater()));
|
||||
updateDownloader = new UpdateDownloader(updateThread, m.captured(2));
|
||||
updateDownloader = new UpdateDownloader(updateThread, url);
|
||||
updateThread->start();
|
||||
}
|
||||
}
|
||||
|
@ -225,7 +231,7 @@ void Application::updateGotCurrent() {
|
|||
if (updates.exists()) {
|
||||
QFileInfoList list = updates.entryInfoList(QDir::Files);
|
||||
for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
|
||||
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
||||
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+(_[a-z\\d]+)?$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
||||
QFile(i->absoluteFilePath()).remove();
|
||||
}
|
||||
}
|
||||
|
@ -543,14 +549,15 @@ void Application::startUpdateCheck(bool forceWait) {
|
|||
updateCheckTimer.stop();
|
||||
if (updateRequestId || updateThread || updateReply || !cAutoUpdate()) return;
|
||||
|
||||
int32 updateInSecs = cLastUpdateCheck() + UpdateDelayConstPart + (rand() % UpdateDelayRandPart) - unixtime();
|
||||
bool sendRequest = (updateInSecs <= 0 || updateInSecs > (UpdateDelayConstPart + UpdateDelayRandPart));
|
||||
int32 constDelay = cBetaVersion() ? 600 : UpdateDelayConstPart, randDelay = cBetaVersion() ? 300 : UpdateDelayRandPart;
|
||||
int32 updateInSecs = cLastUpdateCheck() + constDelay + (rand() % randDelay) - unixtime();
|
||||
bool sendRequest = (updateInSecs <= 0 || updateInSecs > (constDelay + randDelay));
|
||||
if (!sendRequest && !forceWait) {
|
||||
QDir updates(cWorkingDir() + "tupdates");
|
||||
if (updates.exists()) {
|
||||
QFileInfoList list = updates.entryInfoList(QDir::Files);
|
||||
for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
|
||||
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
||||
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+(_[a-z\\d]+)?$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
||||
sendRequest = true;
|
||||
}
|
||||
}
|
||||
|
@ -560,7 +567,9 @@ void Application::startUpdateCheck(bool forceWait) {
|
|||
|
||||
if (sendRequest) {
|
||||
QUrl url(cUpdateURL());
|
||||
if (cDevVersion()) {
|
||||
if (cBetaVersion()) {
|
||||
url.setQuery(qsl("version=%1&beta=%2").arg(AppVersion).arg(cBetaVersion()));
|
||||
} else if (cDevVersion()) {
|
||||
url.setQuery(qsl("version=%1&dev=1").arg(AppVersion));
|
||||
} else {
|
||||
url.setQuery(qsl("version=%1").arg(AppVersion));
|
||||
|
@ -696,10 +705,10 @@ void Application::checkMapVersion() {
|
|||
if (Local::oldMapVersion() < AppVersion) {
|
||||
if (Local::oldMapVersion()) {
|
||||
QString versionFeatures;
|
||||
if (cDevVersion() && Local::oldMapVersion() < 9011) {
|
||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Groups can now have multiple administrators with the ability to edit the name and logo, and add and remove members.\n\xe2\x80\x94 Groups that have reached their capacity of 200 users can be upgraded to supergroups of up to 1,000 members.\n\nWARNING: Only updated Telegram apps will be able to open supergroups. DO NOT upgrade your groups before the stable version is out and updates for other apps are released.");// .replace('@', qsl("@") + QChar(0x200D));
|
||||
} else if (Local::oldMapVersion() < 9013) {
|
||||
versionFeatures = lng_new_version_text(lt_link, qsl("https://telegram.org/blog/supergroups")).trimmed();
|
||||
if (cDevVersion() && Local::oldMapVersion() < 9014) {
|
||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Sticker management: manually rearrange your sticker packs, pack order is now synced across all your devices\n\xe2\x80\x94 Click and hold on a sticker to preview it before sending\n\xe2\x80\x94 New context menu for chats in chats list\n\xe2\x80\x94 Support for all existing emoji");// .replace('@', qsl("@") + QChar(0x200D));
|
||||
} else if (Local::oldMapVersion() < 9015) {
|
||||
versionFeatures = lang(lng_new_version_text).trimmed();
|
||||
} else {
|
||||
versionFeatures = lang(lng_new_version_minor).trimmed();
|
||||
}
|
||||
|
@ -709,6 +718,9 @@ void Application::checkMapVersion() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (cNeedConfigResave()) {
|
||||
Local::writeUserSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::startApp() {
|
||||
|
|
Before Width: | Height: | Size: 586 KiB After Width: | Height: | Size: 762 KiB |
Before Width: | Height: | Size: 789 KiB After Width: | Height: | Size: 1 MiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 240 KiB |
|
@ -270,7 +270,7 @@ void audioFinish() {
|
|||
}
|
||||
|
||||
void AudioPlayer::Msg::clearData() {
|
||||
fname = QString();
|
||||
file = FileLocation();
|
||||
data = QByteArray();
|
||||
position = duration = 0;
|
||||
frequency = AudioVoiceMsgFrequency;
|
||||
|
@ -463,9 +463,9 @@ void AudioPlayer::play(const AudioMsgId &audio, int64 position) {
|
|||
current = &_audioData[_audioCurrent];
|
||||
}
|
||||
current->audio = audio;
|
||||
current->fname = audio.audio->already(true);
|
||||
current->file = audio.audio->location(true);
|
||||
current->data = audio.audio->data;
|
||||
if (current->fname.isEmpty() && current->data.isEmpty()) {
|
||||
if (current->file.isEmpty() && current->data.isEmpty()) {
|
||||
setStoppedState(current, AudioPlayerStoppedAtError);
|
||||
onError(audio);
|
||||
} else {
|
||||
|
@ -507,9 +507,9 @@ void AudioPlayer::play(const SongMsgId &song, int64 position) {
|
|||
current = &_songData[_songCurrent];
|
||||
}
|
||||
current->song = song;
|
||||
current->fname = song.song->already(true);
|
||||
current->file = song.song->location(true);
|
||||
current->data = song.song->data;
|
||||
if (current->fname.isEmpty() && current->data.isEmpty()) {
|
||||
if (current->file.isEmpty() && current->data.isEmpty()) {
|
||||
setStoppedState(current);
|
||||
if (!song.song->loader) {
|
||||
DocumentOpenLink::doOpen(song.song);
|
||||
|
@ -1076,13 +1076,17 @@ void AudioPlayerFader::resumeDevice() {
|
|||
|
||||
class AudioPlayerLoader {
|
||||
public:
|
||||
AudioPlayerLoader(const QString &fname, const QByteArray &data) : fname(fname), data(data), dataPos(0) {
|
||||
AudioPlayerLoader(const FileLocation &file, const QByteArray &data) : file(file), access(false), data(data), dataPos(0) {
|
||||
}
|
||||
virtual ~AudioPlayerLoader() {
|
||||
if (access) {
|
||||
file.accessDisable();
|
||||
access = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool check(const QString &fname, const QByteArray &data) {
|
||||
return this->fname == fname && this->data.size() == data.size();
|
||||
bool check(const FileLocation &file, const QByteArray &data) {
|
||||
return this->file == file && this->data.size() == data.size();
|
||||
}
|
||||
|
||||
virtual bool open(qint64 position = 0) = 0;
|
||||
|
@ -1093,7 +1097,8 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
QString fname;
|
||||
FileLocation file;
|
||||
bool access;
|
||||
QByteArray data;
|
||||
|
||||
QFile f;
|
||||
|
@ -1102,9 +1107,16 @@ protected:
|
|||
bool openFile() {
|
||||
if (data.isEmpty()) {
|
||||
if (f.isOpen()) f.close();
|
||||
f.setFileName(fname);
|
||||
if (!access) {
|
||||
if (!file.accessEnable()) {
|
||||
LOG(("Audio Error: could not open file access '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(f.error()).arg(f.errorString()));
|
||||
return false;
|
||||
}
|
||||
access = true;
|
||||
}
|
||||
f.setFileName(file.name());
|
||||
if (!f.open(QIODevice::ReadOnly)) {
|
||||
LOG(("Audio Error: could not open file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(f.error()).arg(f.errorString()));
|
||||
LOG(("Audio Error: could not open file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(f.error()).arg(f.errorString()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1121,7 +1133,7 @@ static const int32 _toChannels = 2;
|
|||
class FFMpegLoader : public AudioPlayerLoader {
|
||||
public:
|
||||
|
||||
FFMpegLoader(const QString &fname, const QByteArray &data) : AudioPlayerLoader(fname, data),
|
||||
FFMpegLoader(const FileLocation &file, const QByteArray &data) : AudioPlayerLoader(file, data),
|
||||
freq(AudioVoiceMsgFrequency), fmt(AL_FORMAT_STEREO16),
|
||||
sampleSize(2 * sizeof(short)), srcRate(AudioVoiceMsgFrequency), dstRate(AudioVoiceMsgFrequency),
|
||||
maxResampleSamples(1024), dstSamplesData(0), len(0),
|
||||
|
@ -1143,7 +1155,7 @@ public:
|
|||
}
|
||||
fmtContext = avformat_alloc_context();
|
||||
if (!fmtContext) {
|
||||
LOG(("Audio Error: Unable to avformat_alloc_context for file '%1', data size '%2'").arg(fname).arg(data.size()));
|
||||
LOG(("Audio Error: Unable to avformat_alloc_context for file '%1', data size '%2'").arg(file.name()).arg(data.size()));
|
||||
return false;
|
||||
}
|
||||
fmtContext->pb = ioContext;
|
||||
|
@ -1153,19 +1165,19 @@ public:
|
|||
if ((res = avformat_open_input(&fmtContext, 0, 0, 0)) < 0) {
|
||||
ioBuffer = 0;
|
||||
|
||||
LOG(("Audio Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
return false;
|
||||
}
|
||||
_opened = true;
|
||||
|
||||
if ((res = avformat_find_stream_info(fmtContext, 0)) < 0) {
|
||||
LOG(("Audio Error: Unable to avformat_find_stream_info for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to avformat_find_stream_info for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
return false;
|
||||
}
|
||||
|
||||
streamId = av_find_best_stream(fmtContext, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
|
||||
if (streamId < 0) {
|
||||
LOG(("Audio Error: Unable to av_find_best_stream for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(streamId).arg(av_make_error_string(err, sizeof(err), streamId)));
|
||||
LOG(("Audio Error: Unable to av_find_best_stream for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(streamId).arg(av_make_error_string(err, sizeof(err), streamId)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1173,7 +1185,7 @@ public:
|
|||
codecContext = fmtContext->streams[streamId]->codec;
|
||||
av_opt_set_int(codecContext, "refcounted_frames", 1, 0);
|
||||
if ((res = avcodec_open2(codecContext, codec, 0)) < 0) {
|
||||
LOG(("Audio Error: Unable to avcodec_open2 for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to avcodec_open2 for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1217,7 +1229,7 @@ public:
|
|||
if (sampleSize < 0) {
|
||||
swrContext = swr_alloc();
|
||||
if (!swrContext) {
|
||||
LOG(("Audio Error: Unable to swr_alloc for file '%1', data size '%2'").arg(fname).arg(data.size()));
|
||||
LOG(("Audio Error: Unable to swr_alloc for file '%1', data size '%2'").arg(file.name()).arg(data.size()));
|
||||
return false;
|
||||
}
|
||||
int64_t src_ch_layout = layout, dst_ch_layout = _toChannelLayout;
|
||||
|
@ -1233,7 +1245,7 @@ public:
|
|||
av_opt_set_sample_fmt(swrContext, "out_sample_fmt", dst_sample_fmt, 0);
|
||||
|
||||
if ((res = swr_init(swrContext)) < 0) {
|
||||
LOG(("Audio Error: Unable to swr_init for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to swr_init for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1244,7 +1256,7 @@ public:
|
|||
|
||||
maxResampleSamples = av_rescale_rnd(AVBlockSize / sampleSize, dstRate, srcRate, AV_ROUND_UP);
|
||||
if ((res = av_samples_alloc_array_and_samples(&dstSamplesData, 0, _toChannels, maxResampleSamples, _toFormat, 0)) < 0) {
|
||||
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1279,7 +1291,7 @@ public:
|
|||
if ((res = av_read_frame(fmtContext, &avpkt)) < 0) {
|
||||
if (res != AVERROR_EOF) {
|
||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||
LOG(("Audio Error: Unable to av_read_frame() file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to av_read_frame() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -1288,7 +1300,7 @@ public:
|
|||
int got_frame = 0;
|
||||
if ((res = avcodec_decode_audio4(codecContext, frame, &got_frame, &avpkt)) < 0) {
|
||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||
LOG(("Audio Error: Unable to avcodec_decode_audio4() file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to avcodec_decode_audio4() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
|
||||
av_free_packet(&avpkt);
|
||||
if (res == AVERROR_INVALIDDATA) return 0; // try to skip bad packet
|
||||
|
@ -1305,7 +1317,7 @@ public:
|
|||
if ((res = av_samples_alloc(dstSamplesData, 0, _toChannels, maxResampleSamples, _toFormat, 1)) < 0) {
|
||||
dstSamplesData[0] = 0;
|
||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
|
||||
av_free_packet(&avpkt);
|
||||
return -1;
|
||||
|
@ -1313,7 +1325,7 @@ public:
|
|||
}
|
||||
if ((res = swr_convert(swrContext, dstSamplesData, dstSamples, (const uint8_t**)frame->extended_data, frame->nb_samples)) < 0) {
|
||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||
LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
|
||||
|
||||
av_free_packet(&avpkt);
|
||||
return -1;
|
||||
|
@ -1678,7 +1690,7 @@ AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (*l && (!isGoodId || !(*l)->check(m->fname, m->data))) {
|
||||
if (*l && (!isGoodId || !(*l)->check(m->file, m->data))) {
|
||||
delete *l;
|
||||
*l = 0;
|
||||
switch (type) {
|
||||
|
@ -1693,23 +1705,23 @@ AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const
|
|||
case OverviewDocuments: _song = *static_cast<const SongMsgId*>(objId); break;
|
||||
}
|
||||
|
||||
QByteArray header = m->data.mid(0, 8);
|
||||
if (header.isEmpty()) {
|
||||
QFile f(m->fname);
|
||||
if (!f.open(QIODevice::ReadOnly)) {
|
||||
LOG(("Audio Error: could not open file '%1'").arg(m->fname));
|
||||
m->state = AudioPlayerStoppedAtStart;
|
||||
return 0;
|
||||
}
|
||||
header = f.read(8);
|
||||
}
|
||||
if (header.size() < 8) {
|
||||
LOG(("Audio Error: could not read header from file '%1', data size %2").arg(m->fname).arg(m->data.isEmpty() ? QFileInfo(m->fname).size() : m->data.size()));
|
||||
m->state = AudioPlayerStoppedAtStart;
|
||||
return 0;
|
||||
}
|
||||
// QByteArray header = m->data.mid(0, 8);
|
||||
// if (header.isEmpty()) {
|
||||
// QFile f(m->fname);
|
||||
// if (!f.open(QIODevice::ReadOnly)) {
|
||||
// LOG(("Audio Error: could not open file '%1'").arg(m->fname));
|
||||
// m->state = AudioPlayerStoppedAtStart;
|
||||
// return 0;
|
||||
// }
|
||||
// header = f.read(8);
|
||||
// }
|
||||
// if (header.size() < 8) {
|
||||
// LOG(("Audio Error: could not read header from file '%1', data size %2").arg(m->fname).arg(m->data.isEmpty() ? QFileInfo(m->fname).size() : m->data.size()));
|
||||
// m->state = AudioPlayerStoppedAtStart;
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
*l = new FFMpegLoader(m->fname, m->data);
|
||||
*l = new FFMpegLoader(m->file, m->data);
|
||||
|
||||
int ret;
|
||||
if (!(*l)->open(position)) {
|
||||
|
@ -1758,7 +1770,7 @@ AudioPlayer::Msg *AudioPlayerLoaders::checkLoader(MediaOverviewType type) {
|
|||
}
|
||||
if (!l || !m) return 0;
|
||||
|
||||
if (!isGoodId || !m->loading || !(*l)->check(m->fname, m->data)) {
|
||||
if (!isGoodId || !m->loading || !(*l)->check(m->file, m->data)) {
|
||||
LOG(("Audio Error: playing changed while loading"));
|
||||
return 0;
|
||||
}
|
||||
|
@ -2278,7 +2290,7 @@ void AudioCaptureInner::writeFrame(int32 offset, int32 framesize) {
|
|||
class FFMpegAttributesReader : public AudioPlayerLoader {
|
||||
public:
|
||||
|
||||
FFMpegAttributesReader(const QString &fname, const QByteArray &data) : AudioPlayerLoader(fname, data),
|
||||
FFMpegAttributesReader(const FileLocation &file, const QByteArray &data) : AudioPlayerLoader(file, data),
|
||||
ioBuffer(0), ioContext(0), fmtContext(0), codec(0), streamId(0),
|
||||
_opened(false) {
|
||||
}
|
||||
|
@ -2488,7 +2500,7 @@ private:
|
|||
};
|
||||
|
||||
MTPDocumentAttribute audioReadSongAttributes(const QString &fname, const QByteArray &data, QImage &cover, QByteArray &coverBytes, QByteArray &coverFormat) {
|
||||
FFMpegAttributesReader reader(fname, data);
|
||||
FFMpegAttributesReader reader(FileLocation(StorageFilePartial, fname), data);
|
||||
if (reader.open()) {
|
||||
int32 duration = reader.duration() / reader.frequency();
|
||||
if (reader.duration() > 0) {
|
||||
|
|
|
@ -127,7 +127,7 @@ private:
|
|||
|
||||
void clearData();
|
||||
|
||||
QString fname;
|
||||
FileLocation file;
|
||||
QByteArray data;
|
||||
int64 position, duration;
|
||||
int32 frequency;
|
||||
|
|
|
@ -269,7 +269,7 @@ void UpdateDownloader::unpackUpdate() {
|
|||
}
|
||||
if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature
|
||||
RSA_free(pbKey);
|
||||
if (cDevVersion()) { // try other public key, if we are in dev version
|
||||
if (cDevVersion() || cBetaVersion()) { // try other public key, if we are in dev or beta version
|
||||
pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(DevVersion ? UpdatesPublicKey : UpdatesPublicDevKey), -1), 0, 0, 0);
|
||||
if (!pbKey) {
|
||||
LOG(("Update Error: cant read public rsa key!"));
|
||||
|
@ -360,7 +360,19 @@ void UpdateDownloader::unpackUpdate() {
|
|||
LOG(("Update Error: cant read version from downloaded stream, status: %1").arg(stream.status()));
|
||||
return fatalFail();
|
||||
}
|
||||
if (int32(version) <= AppVersion) {
|
||||
|
||||
quint64 betaVersion = 0;
|
||||
if (version == 0x7FFFFFFF) { // beta version
|
||||
stream >> betaVersion;
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("Update Error: cant read beta version from downloaded stream, status: %1").arg(stream.status()));
|
||||
return fatalFail();
|
||||
}
|
||||
if (!cBetaVersion() || betaVersion <= cBetaVersion()) {
|
||||
LOG(("Update Error: downloaded beta version %1 is not greater, than mine %2").arg(betaVersion).arg(cBetaVersion()));
|
||||
return fatalFail();
|
||||
}
|
||||
} else if (int32(version) <= AppVersion) {
|
||||
LOG(("Update Error: downloaded version %1 is not greater, than mine %2").arg(version).arg(AppVersion));
|
||||
return fatalFail();
|
||||
}
|
||||
|
@ -430,8 +442,12 @@ void UpdateDownloader::unpackUpdate() {
|
|||
return fatalFail();
|
||||
}
|
||||
fVersion.write((const char*)&versionNum, sizeof(VerInt));
|
||||
fVersion.write((const char*)&versionLen, sizeof(VerInt));
|
||||
fVersion.write((const char*)&versionStr[0], versionLen);
|
||||
if (versionNum == 0x7FFFFFFF) { // beta version
|
||||
fVersion.write((const char*)&betaVersion, sizeof(quint64));
|
||||
} else {
|
||||
fVersion.write((const char*)&versionLen, sizeof(VerInt));
|
||||
fVersion.write((const char*)&versionStr[0], versionLen);
|
||||
}
|
||||
fVersion.close();
|
||||
}
|
||||
|
||||
|
@ -481,12 +497,24 @@ bool checkReadyUpdate() {
|
|||
UpdateDownloader::clearAll();
|
||||
return false;
|
||||
}
|
||||
fVersion.close();
|
||||
if (versionNum <= AppVersion) {
|
||||
if (versionNum == 0x7FFFFFFF) { // beta version
|
||||
quint64 betaVersion = 0;
|
||||
if (fVersion.read((char*)&betaVersion, sizeof(quint64)) != sizeof(quint64)) {
|
||||
LOG(("Update Error: cant read beta version from file '%1'").arg(versionPath));
|
||||
UpdateDownloader::clearAll();
|
||||
return false;
|
||||
}
|
||||
if (!cBetaVersion() || betaVersion <= cBetaVersion()) {
|
||||
LOG(("Update Error: cant install beta version %1 having beta version %2").arg(betaVersion).arg(cBetaVersion()));
|
||||
UpdateDownloader::clearAll();
|
||||
return false;
|
||||
}
|
||||
} else if (versionNum <= AppVersion) {
|
||||
LOG(("Update Error: cant install version %1 having version %2").arg(versionNum).arg(AppVersion));
|
||||
UpdateDownloader::clearAll();
|
||||
return false;
|
||||
}
|
||||
fVersion.close();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -542,3 +570,47 @@ bool checkReadyUpdate() {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
QString countBetaVersionSignature(uint64 version) { // duplicated in packer.cpp
|
||||
if (cBetaPrivateKey().isEmpty()) {
|
||||
LOG(("Error: Trying to count beta version signature without beta private key!"));
|
||||
return QString();
|
||||
}
|
||||
|
||||
QByteArray signedData = (qstr("TelegramBeta_") + QString::number(version, 16).toLower()).toUtf8();
|
||||
|
||||
static const int32 shaSize = 20, keySize = 128;
|
||||
|
||||
uchar sha1Buffer[shaSize];
|
||||
hashSha1(signedData.constData(), signedData.size(), sha1Buffer); // count sha1
|
||||
|
||||
uint32 siglen = 0;
|
||||
|
||||
RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cBetaPrivateKey().constData()), -1), 0, 0, 0);
|
||||
if (!prKey) {
|
||||
LOG(("Error: Could not read beta private key!"));
|
||||
return QString();
|
||||
}
|
||||
if (RSA_size(prKey) != keySize) {
|
||||
LOG(("Error: Bad beta private key size: %1").arg(RSA_size(prKey)));
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
QByteArray signature;
|
||||
signature.resize(keySize);
|
||||
if (RSA_sign(NID_sha1, (const uchar*)(sha1Buffer), shaSize, (uchar*)(signature.data()), &siglen, prKey) != 1) { // count signature
|
||||
LOG(("Error: Counting beta version signature failed!"));
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
RSA_free(prKey);
|
||||
|
||||
if (siglen != keySize) {
|
||||
LOG(("Error: Bad beta version signature length: %1").arg(siglen));
|
||||
return QString();
|
||||
}
|
||||
|
||||
signature = signature.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
signature = signature.replace('-', '8').replace('_', 'B');
|
||||
return QString::fromUtf8(signature.mid(19, 32));
|
||||
}
|
||||
|
|
|
@ -67,3 +67,5 @@ private:
|
|||
bool checkReadyUpdate();
|
||||
|
||||
#endif
|
||||
|
||||
QString countBetaVersionSignature(uint64 version);
|
||||
|
|
|
@ -25,8 +25,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "autoupdater.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
#include "application.h"
|
||||
|
||||
AboutBox::AboutBox() : AbstractBox(st::aboutWidth)
|
||||
, _version(this, lng_about_version(lt_version, QString::fromWCharArray(AppVersionStr) + (cDevVersion() ? " dev" : "")), st::aboutVersionLink)
|
||||
, _version(this, lng_about_version(lt_version, QString::fromWCharArray(AppVersionStr) + (cDevVersion() ? " dev" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink)
|
||||
, _text1(this, lang(lng_about_text_1), st::aboutLabel, st::aboutTextStyle)
|
||||
, _text2(this, lang(lng_about_text_2), st::aboutLabel, st::aboutTextStyle)
|
||||
, _text3(this, QString(), st::aboutLabel, st::aboutTextStyle)
|
||||
|
@ -66,7 +71,23 @@ void AboutBox::resizeEvent(QResizeEvent *e) {
|
|||
}
|
||||
|
||||
void AboutBox::onVersion() {
|
||||
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog"));
|
||||
if (cRealBetaVersion()) {
|
||||
QString url = qsl("https://tdesktop.com/");
|
||||
switch (cPlatform()) {
|
||||
case dbipWindows: url += qsl("win/%1.zip"); break;
|
||||
case dbipMac: url += qsl("mac/%1.zip"); break;
|
||||
case dbipMacOld: url += qsl("mac32/%1.zip"); break;
|
||||
case dbipLinux32: url += qsl("linux32/%1.tar.xz"); break;
|
||||
case dbipLinux64: url += qsl("linux/%1.tar.xz"); break;
|
||||
}
|
||||
url = url.arg(qsl("tbeta%1_%2").arg(cRealBetaVersion()).arg(countBetaVersionSignature(cRealBetaVersion())));
|
||||
|
||||
App::app()->clipboard()->setText(url);
|
||||
|
||||
App::showLayer(new InformBox("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
|
||||
} else {
|
||||
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/?_hash=changelog"));
|
||||
}
|
||||
}
|
||||
|
||||
void AboutBox::keyPressEvent(QKeyEvent *e) {
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace {
|
|||
|
||||
ContactsInner::ContactsInner(ChatData *chat, MembersFilter membersFilter) : TWidget()
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _newItemHeight((membersFilter == MembersFilterAdmins) ? (st::contactsNewItemHeight + st::contactsAboutHeight) : 0)
|
||||
, _newItemHeight(0)
|
||||
, _newItemSel(false)
|
||||
, _chat(chat)
|
||||
, _channel(0)
|
||||
|
@ -119,8 +119,11 @@ ContactsInner::ContactsInner(ChatData *chat, MembersFilter membersFilter) : TWid
|
|||
, _addContactLnk(this, lang(lng_add_contact_button))
|
||||
, _saving(false) {
|
||||
initList();
|
||||
if (membersFilter == MembersFilterAdmins && !_contacts->list.count) {
|
||||
App::api()->requestFullPeer(_chat);
|
||||
if (membersFilter == MembersFilterAdmins) {
|
||||
_newItemHeight = st::contactsNewItemHeight + qMax(_aboutAllAdmins.countHeight(_aboutWidth), _aboutAdmins.countHeight(_aboutWidth)) + st::contactsAboutHeight;
|
||||
if (!_contacts->list.count) {
|
||||
App::api()->requestFullPeer(_chat);
|
||||
}
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
@ -775,9 +778,9 @@ void ContactsInner::changeCheckState(ContactData *data, PeerData *peer) {
|
|||
int32 ContactsInner::selectedCount() const {
|
||||
int32 result = _selCount;
|
||||
if (_chat) {
|
||||
result += (_chat->count > 0) ? _chat->count : 1;
|
||||
result += qMax(_chat->count, 1);
|
||||
} else if (_channel) {
|
||||
result += _already.size();
|
||||
result += qMax(_channel->count, _already.size());
|
||||
} else if (_creating == CreatingGroupGroup) {
|
||||
result += 1;
|
||||
}
|
||||
|
@ -1379,6 +1382,7 @@ void ContactsBox::init() {
|
|||
connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(updateSel()));
|
||||
connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||
connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
|
||||
connect(&_filter, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
|
||||
connect(&_filterCancel, SIGNAL(clicked()), this, SLOT(onFilterCancel()));
|
||||
connect(&_inner, SIGNAL(mustScrollTo(int, int)), &_scroll, SLOT(scrollToY(int, int)));
|
||||
connect(&_inner, SIGNAL(selectAllQuery()), &_filter, SLOT(selectAll()));
|
||||
|
@ -1500,14 +1504,12 @@ void ContactsBox::showDone() {
|
|||
_filter.setFocus();
|
||||
}
|
||||
|
||||
void ContactsBox::onSubmit() {
|
||||
_inner.chooseParticipant();
|
||||
}
|
||||
|
||||
void ContactsBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
||||
if (_filter.hasFocus()) {
|
||||
_inner.chooseParticipant();
|
||||
} else {
|
||||
ItemListBox::keyPressEvent(e);
|
||||
}
|
||||
} else if (_filter.hasFocus()) {
|
||||
if (_filter.hasFocus()) {
|
||||
if (e->key() == Qt::Key_Down) {
|
||||
_inner.selectSkip(1);
|
||||
} else if (e->key() == Qt::Key_Up) {
|
||||
|
@ -1770,7 +1772,10 @@ MembersInner::MembersInner(ChannelData *channel, MembersFilter filter) : TWidget
|
|||
, _kickRequestId(0)
|
||||
, _kickBox(0)
|
||||
, _loading(true)
|
||||
, _loadingRequestId(0) {
|
||||
, _loadingRequestId(0)
|
||||
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
|
||||
, _about(_aboutWidth)
|
||||
, _aboutHeight(0) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
|
@ -1821,6 +1826,10 @@ void MembersInner::paintEvent(QPaintEvent *e) {
|
|||
paintDialog(p, _rows[from], data(from), sel, kickSel, kickDown);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
if (to == _rows.size() && _filter == MembersFilterRecent && (_rows.size() < _channel->count || _rows.size() >= cMaxGroupCount())) {
|
||||
p.setPen(st::stickersReorderFg);
|
||||
_about.draw(p, st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1909,7 +1918,7 @@ void MembersInner::paintDialog(Painter &p, PeerData *peer, MemberData *data, boo
|
|||
}
|
||||
|
||||
p.setFont(st::contactsStatusFont->f);
|
||||
p.setPen(sel ? st::contactsStatusFgOver : (data->onlineColor ? st::contactsStatusFgOnline : st::contactsStatusFg));
|
||||
p.setPen(data->onlineColor ? st::contactsStatusFgOnline : (sel ? st::contactsStatusFgOver : st::contactsStatusFg));
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), data->online);
|
||||
}
|
||||
|
||||
|
@ -1992,8 +2001,14 @@ void MembersInner::chooseParticipant() {
|
|||
void MembersInner::refresh() {
|
||||
if (_rows.isEmpty()) {
|
||||
resize(width(), st::membersPadding.top() + st::noContactsHeight + st::membersPadding.bottom());
|
||||
_aboutHeight = 0;
|
||||
} else {
|
||||
resize(width(), st::membersPadding.top() + _newItemHeight + _rows.size() * _rowHeight + st::membersPadding.bottom());
|
||||
_about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size()));
|
||||
_aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom();
|
||||
if (_filter != MembersFilterRecent || (_rows.size() >= _channel->count && _rows.size() < cMaxGroupCount())) {
|
||||
_aboutHeight = 0;
|
||||
}
|
||||
resize(width(), st::membersPadding.top() + _newItemHeight + _rows.size() * _rowHeight + st::membersPadding.bottom() + _aboutHeight);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
@ -2228,6 +2243,7 @@ void MembersInner::removeKicked() {
|
|||
--_channel->adminsCount;
|
||||
if (App::main()) emit App::main()->peerUpdated(_channel);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
_kickConfirm = 0;
|
||||
}
|
||||
|
|
|
@ -216,6 +216,8 @@ public slots:
|
|||
void onCreate();
|
||||
void onSaveAdmins();
|
||||
|
||||
void onSubmit();
|
||||
|
||||
bool onSearchByUsername(bool searchCache = false);
|
||||
void onNeedSearchByUsername();
|
||||
|
||||
|
@ -386,6 +388,10 @@ private:
|
|||
MemberRoles _roles;
|
||||
MemberDatas _datas;
|
||||
|
||||
int32 _aboutWidth;
|
||||
Text _about;
|
||||
int32 _aboutHeight;
|
||||
|
||||
QPoint _lastMousePos;
|
||||
|
||||
};
|
||||
|
|
|
@ -25,15 +25,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "downloadpathbox.h"
|
||||
#include "gui/filedialog.h"
|
||||
#include "pspecific.h"
|
||||
|
||||
DownloadPathBox::DownloadPathBox() :
|
||||
_path(cDownloadPath()),
|
||||
_default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty()),
|
||||
_temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), _path == qsl("tmp")),
|
||||
_dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), !_path.isEmpty() && _path != qsl("tmp")),
|
||||
_pathLink(this, QString(), st::defaultBoxLinkButton),
|
||||
_save(this, lang(lng_connection_save), st::defaultBoxButton),
|
||||
_cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||
DownloadPathBox::DownloadPathBox() : AbstractBox()
|
||||
, _path(cDownloadPath())
|
||||
, _pathBookmark(cDownloadPathBookmark())
|
||||
, _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty())
|
||||
, _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), _path == qsl("tmp"))
|
||||
, _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), !_path.isEmpty() && _path != qsl("tmp"))
|
||||
, _pathLink(this, QString(), st::defaultBoxLinkButton)
|
||||
, _save(this, lang(lng_connection_save), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||
|
||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
@ -124,12 +126,13 @@ void DownloadPathBox::onChange() {
|
|||
void DownloadPathBox::onEditPath() {
|
||||
filedialogInit();
|
||||
QString path, lastPath = cDialogLastPath();
|
||||
if (!cDownloadPath().isEmpty()) {
|
||||
cSetDialogLastPath(cDownloadPath());
|
||||
if (!cDownloadPath().isEmpty() && cDownloadPath() != qstr("tmp")) {
|
||||
cSetDialogLastPath(cDownloadPath().left(cDownloadPath().size() - (cDownloadPath().endsWith('/') ? 1 : 0)));
|
||||
}
|
||||
if (filedialogGetDir(path, lang(lng_download_path_choose))) {
|
||||
if (!path.isEmpty()) {
|
||||
_path = path + '/';
|
||||
_pathBookmark = psDownloadPathBookmark(_path);
|
||||
setPathText(QDir::toNativeSeparators(_path));
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +141,7 @@ void DownloadPathBox::onEditPath() {
|
|||
|
||||
void DownloadPathBox::onSave() {
|
||||
cSetDownloadPath(_default.checked() ? QString() : (_temp.checked() ? qsl("tmp") : _path));
|
||||
cSetDownloadPathBookmark((_default.checked() || _temp.checked()) ? QByteArray() : _pathBookmark);
|
||||
Local::writeUserSettings();
|
||||
emit closed();
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ private:
|
|||
void setPathText(const QString &text);
|
||||
|
||||
QString _path;
|
||||
QByteArray _pathBookmark;
|
||||
|
||||
Radiobutton _default, _temp, _dir;
|
||||
LinkButton _pathLink;
|
||||
|
|
|
@ -125,7 +125,11 @@ PhotoSendBox::PhotoSendBox(const QString &phone, const QString &fname, const QSt
|
|||
, _compressed(this, lang(lng_send_image_compressed), true)
|
||||
, _send(this, lang(lng_send_button), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _phone(phone), _fname(fname), _lname(lname), _replyTo(replyTo) {
|
||||
, _phone(phone)
|
||||
, _fname(fname)
|
||||
, _lname(lname)
|
||||
, _replyTo(replyTo)
|
||||
, _confirmed(false) {
|
||||
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ _input(set), _installRequest(0) {
|
|||
case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break;
|
||||
}
|
||||
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&StickerSetInner::gotSet), rpcFail(&StickerSetInner::failedSet));
|
||||
cSetLastStickersUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
}
|
||||
|
||||
|
@ -56,7 +55,7 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
|||
}
|
||||
if (d.vset.type() == mtpc_stickerSet) {
|
||||
const MTPDstickerSet &s(d.vset.c_stickerSet());
|
||||
_setTitle = qs(s.vtitle);
|
||||
_setTitle = stickerSetTitle(s);
|
||||
_title = st::boxTitleFont->elided(_setTitle, width() - st::boxTitlePosition.x() - st::boxTitleHeight);
|
||||
_setShortName = qs(s.vshort_name);
|
||||
_setId = s.vid.v;
|
||||
|
@ -91,23 +90,14 @@ bool StickerSetInner::failedSet(const RPCError &error) {
|
|||
void StickerSetInner::installDone(const MTPBool &result) {
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
|
||||
_setFlags &= ~MTPDstickerSet::flag_disabled;
|
||||
sets.insert(_setId, StickerSet(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags)).value().stickers = _pack;
|
||||
|
||||
int32 insertAtIndex = 0;
|
||||
StickerSetsOrder &order(cRefStickerSetsOrder());
|
||||
for (int32 s = order.size(); insertAtIndex < s; ++insertAtIndex) {
|
||||
StickerSets::const_iterator i = sets.constFind(order.at(insertAtIndex));
|
||||
if (i == sets.cend() || !(i->flags & MTPDstickerSet::flag_official)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int32 currentIndex = cStickerSetsOrder().indexOf(_setId);
|
||||
int32 insertAtIndex = 0, currentIndex = order.indexOf(_setId);
|
||||
if (currentIndex != insertAtIndex) {
|
||||
if (currentIndex > 0) {
|
||||
order.removeAt(currentIndex);
|
||||
if (currentIndex < insertAtIndex) {
|
||||
--insertAtIndex;
|
||||
}
|
||||
}
|
||||
order.insert(insertAtIndex, _setId);
|
||||
}
|
||||
|
@ -115,13 +105,14 @@ void StickerSetInner::installDone(const MTPBool &result) {
|
|||
StickerSets::iterator custom = sets.find(CustomStickerSetId);
|
||||
if (custom != sets.cend()) {
|
||||
for (int32 i = 0, l = _pack.size(); i < l; ++i) {
|
||||
custom->stickers.removeOne(_pack.at(i));
|
||||
int32 removeIndex = custom->stickers.indexOf(_pack.at(i));
|
||||
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
|
||||
}
|
||||
if (custom->stickers.isEmpty()) {
|
||||
sets.erase(custom);
|
||||
}
|
||||
}
|
||||
cSetStickersHash(QByteArray());
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
emit installed(_setId);
|
||||
App::wnd()->hideLayer();
|
||||
|
@ -195,7 +186,10 @@ bool StickerSetInner::loaded() const {
|
|||
}
|
||||
|
||||
int32 StickerSetInner::notInstalled() const {
|
||||
return (_loaded && (cStickerSets().constFind(_setId) == cStickerSets().cend())) ? _pack.size() : 0;
|
||||
if (!_loaded) return 0;
|
||||
StickerSets::const_iterator it = cStickerSets().constFind(_setId);
|
||||
if (it == cStickerSets().cend() || (it->flags & MTPDstickerSet::flag_disabled)) return _pack.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool StickerSetInner::official() const {
|
||||
|
@ -285,16 +279,16 @@ void StickerSetBox::showAll() {
|
|||
int32 cnt = _inner.notInstalled();
|
||||
if (_inner.loaded()) {
|
||||
_shadow.show();
|
||||
if (_inner.official()) {
|
||||
_add.hide();
|
||||
_share.hide();
|
||||
_cancel.hide();
|
||||
_done.show();
|
||||
} else if (_inner.notInstalled()) {
|
||||
if (_inner.notInstalled()) {
|
||||
_add.show();
|
||||
_cancel.show();
|
||||
_share.hide();
|
||||
_done.hide();
|
||||
} else if (_inner.official()) {
|
||||
_add.hide();
|
||||
_share.hide();
|
||||
_cancel.hide();
|
||||
_done.show();
|
||||
} else {
|
||||
_share.show();
|
||||
_cancel.show();
|
||||
|
@ -334,3 +328,625 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) {
|
|||
_cancel.moveToRight(st::boxButtonPadding.right() + _add.width() + st::boxButtonPadding.left(), _add.y());
|
||||
}
|
||||
}
|
||||
|
||||
StickersInner::StickersInner() : TWidget()
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _aboveShadowFadeStart(0)
|
||||
, _aboveShadowFadeOpacity(0, 0)
|
||||
, _a_shifting(animFunc(this, &StickersInner::animStep_shifting))
|
||||
, _itemsTop(st::membersPadding.top())
|
||||
, _saving(false)
|
||||
, _removeSel(-1)
|
||||
, _removeDown(-1)
|
||||
, _removeWidth(st::normalFont->width(lang(lng_stickers_remove)))
|
||||
, _returnWidth(st::normalFont->width(lang(lng_stickers_return)))
|
||||
, _restoreWidth(st::normalFont->width(lang(lng_stickers_restore)))
|
||||
, _selected(-1)
|
||||
, _started(-1)
|
||||
, _dragging(-1)
|
||||
, _above(-1)
|
||||
, _aboveShadow(st::boxShadow)
|
||||
, _scrollbar(0) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
void StickersInner::paintEvent(QPaintEvent *e) {
|
||||
QRect r(e->rect());
|
||||
Painter p(this);
|
||||
|
||||
updateAnimatedValues();
|
||||
|
||||
p.fillRect(r, st::white);
|
||||
p.setClipRect(r);
|
||||
if (_rows.isEmpty()) {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
p.setPen(st::noContactsColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
|
||||
} else {
|
||||
p.translate(0, _itemsTop);
|
||||
|
||||
int32 yFrom = r.y() - _itemsTop, yTo = r.y() + r.height() - _itemsTop;
|
||||
int32 from = floorclamp(yFrom - _rowHeight, _rowHeight, 0, _rows.size());
|
||||
int32 to = ceilclamp(yTo + _rowHeight, _rowHeight, 0, _rows.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (int32 i = from; i < to; ++i) {
|
||||
if (i != _above) {
|
||||
paintRow(p, i);
|
||||
}
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
if (from <= _above && _above < to) {
|
||||
p.translate(0, (_above - to) * _rowHeight);
|
||||
paintRow(p, _above);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StickersInner::paintRow(Painter &p, int32 index) {
|
||||
const StickerSetRow *s(_rows.at(index));
|
||||
|
||||
int32 xadd = 0, yadd = s->yadd.current();
|
||||
if (xadd || yadd) p.translate(xadd, yadd);
|
||||
|
||||
bool removeSel = (index == _removeSel && (_removeDown < 0 || index == _removeDown));
|
||||
bool removeDown = removeSel && (index == _removeDown);
|
||||
|
||||
p.setFont((removeSel ? st::linkOverFont : st::linkFont)->f);
|
||||
if (removeDown) {
|
||||
p.setPen(st::btnDefLink.downColor->p);
|
||||
} else {
|
||||
p.setPen(st::btnDefLink.color->p);
|
||||
}
|
||||
int32 remWidth = s->disabled ? (s->official ? _restoreWidth : _returnWidth) : _removeWidth;
|
||||
QString remText = lang(s->disabled ? (s->official ? lng_stickers_restore : lng_stickers_return) : lng_stickers_remove);
|
||||
p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), remText, remWidth);
|
||||
|
||||
if (index == _above) {
|
||||
float64 current = _aboveShadowFadeOpacity.current();
|
||||
if (_started >= 0) {
|
||||
float64 o = aboveShadowOpacity();
|
||||
if (o > current) {
|
||||
_aboveShadowFadeOpacity = anim::fvalue(o, o);
|
||||
current = o;
|
||||
}
|
||||
}
|
||||
p.setOpacity(current);
|
||||
QRect row(myrtlrect(_aboveShadow.getDimensions(st::boxShadowShift).left(), st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - _aboveShadow.getDimensions(st::boxShadowShift).right(), _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2)));
|
||||
_aboveShadow.paint(p, row, st::boxShadowShift);
|
||||
p.fillRect(row, st::white);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
|
||||
if (s->disabled) p.setOpacity(st::stickersRowDisabledOpacity);
|
||||
if (s->sticker) {
|
||||
s->sticker->thumb->load();
|
||||
QPixmap pix(s->sticker->thumb->pix(s->pixw, s->pixh));
|
||||
p.drawPixmapLeft(st::contactsPadding.left() + (st::contactsPhotoSize - s->pixw) / 2, st::contactsPadding.top() + (st::contactsPhotoSize - s->pixh) / 2, width(), pix);
|
||||
}
|
||||
p.setFont(st::contactsNameFont);
|
||||
p.setPen(st::black);
|
||||
|
||||
int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsNameTop, width(), s->title);
|
||||
|
||||
p.setFont(st::contactsStatusFont);
|
||||
p.setPen(st::contactsStatusFg);
|
||||
p.drawTextLeft(namex, st::contactsPadding.top() + st::contactsStatusTop, width(), lng_stickers_count(lt_count, s->count));
|
||||
|
||||
p.setOpacity(1);
|
||||
if (xadd || yadd) p.translate(-xadd, -yadd);
|
||||
}
|
||||
|
||||
void StickersInner::mousePressEvent(QMouseEvent *e) {
|
||||
if (_saving) return;
|
||||
if (_dragging >= 0) mouseReleaseEvent(e);
|
||||
_mouse = e->globalPos();
|
||||
onUpdateSelected();
|
||||
if (_removeSel >= 0) {
|
||||
_removeDown = _removeSel;
|
||||
update(0, _itemsTop + _removeSel * _rowHeight, width(), _rowHeight);
|
||||
} else if (_selected >= 0) {
|
||||
_above = _dragging = _started = _selected;
|
||||
_dragStart = mapFromGlobal(_mouse);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersInner::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_saving) return;
|
||||
_mouse = e->globalPos();
|
||||
onUpdateSelected();
|
||||
}
|
||||
|
||||
void StickersInner::onUpdateSelected() {
|
||||
if (_saving) return;
|
||||
QPoint local(mapFromGlobal(_mouse));
|
||||
if (_dragging >= 0) {
|
||||
int32 shift = 0;
|
||||
uint64 ms = getms();
|
||||
if (_dragStart.y() > local.y() && _dragging > 0) {
|
||||
shift = -floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging);
|
||||
for (int32 from = _dragging, to = _dragging + shift; from > to; --from) {
|
||||
qSwap(_rows[from], _rows[from - 1]);
|
||||
_rows.at(from)->yadd = anim::ivalue(_rows.at(from)->yadd.current() - _rowHeight, 0);
|
||||
_animStartTimes[from] = ms;
|
||||
}
|
||||
} else if (_dragStart.y() < local.y() && _dragging + 1 < _rows.size()) {
|
||||
shift = floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1);
|
||||
for (int32 from = _dragging, to = _dragging + shift; from < to; ++from) {
|
||||
qSwap(_rows[from], _rows[from + 1]);
|
||||
_rows.at(from)->yadd = anim::ivalue(_rows.at(from)->yadd.current() + _rowHeight, 0);
|
||||
_animStartTimes[from] = ms;
|
||||
}
|
||||
}
|
||||
if (shift) {
|
||||
_dragging += shift;
|
||||
_above = _dragging;
|
||||
_dragStart.setY(_dragStart.y() + shift * _rowHeight);
|
||||
if (!_a_shifting.animating()) {
|
||||
_a_shifting.start();
|
||||
}
|
||||
}
|
||||
_rows.at(_dragging)->yadd = anim::ivalue(local.y() - _dragStart.y(), local.y() - _dragStart.y());
|
||||
_animStartTimes[_dragging] = 0;
|
||||
updateAnimatedRegions();
|
||||
|
||||
emit checkDraggingScroll(local.y());
|
||||
} else {
|
||||
bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersPadding.bottom())).contains(local);
|
||||
_selected = in ? floorclamp(local.y() - _itemsTop, _rowHeight, 0, _rows.size() - 1) : -1;
|
||||
int32 removeSel = -1;
|
||||
|
||||
if (_selected >= 0) {
|
||||
int32 remw = _rows.at(_selected)->disabled ? (_rows.at(_selected)->official ? _restoreWidth : _returnWidth) : _removeWidth;
|
||||
QRect rem(myrtlrect(width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - remw, st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, remw, st::normalFont->height));
|
||||
removeSel = rem.contains(local.x(), local.y() - _itemsTop - _selected * _rowHeight) ? _selected : -1;
|
||||
}
|
||||
setRemoveSel(removeSel);
|
||||
emit noDraggingScroll();
|
||||
}
|
||||
}
|
||||
|
||||
float64 StickersInner::aboveShadowOpacity() const {
|
||||
if (_above < 0) return 0;
|
||||
|
||||
int32 dx = 0;
|
||||
int32 dy = qAbs(_above * _rowHeight + _rows.at(_above)->yadd.current() - _started * _rowHeight);
|
||||
return qMin((dx + dy) * 2. / _rowHeight, 1.);
|
||||
}
|
||||
|
||||
void StickersInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (_saving) return;
|
||||
_mouse = e->globalPos();
|
||||
onUpdateSelected();
|
||||
if (_removeDown == _removeSel && _removeSel >= 0) {
|
||||
_rows[_removeDown]->disabled = !_rows[_removeDown]->disabled;
|
||||
} else if (_dragging >= 0) {
|
||||
QPoint local(mapFromGlobal(_mouse));
|
||||
_rows[_dragging]->yadd.start(0);
|
||||
_aboveShadowFadeStart = _animStartTimes[_dragging] = getms();
|
||||
_aboveShadowFadeOpacity = anim::fvalue(aboveShadowOpacity(), 0);
|
||||
if (!_a_shifting.animating()) {
|
||||
_a_shifting.start();
|
||||
}
|
||||
|
||||
_dragging = _started = -1;
|
||||
}
|
||||
if (_removeDown >= 0) {
|
||||
update(0, _itemsTop + _removeDown * _rowHeight, width(), _rowHeight);
|
||||
_removeDown = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void StickersInner::updateAnimatedRegions() {
|
||||
int32 updateMin = -1, updateMax = 0;
|
||||
for (int32 i = 0, l = _animStartTimes.size(); i < l; ++i) {
|
||||
if (_animStartTimes.at(i)) {
|
||||
if (updateMin < 0) updateMin = i;
|
||||
updateMax = i;
|
||||
}
|
||||
}
|
||||
if (_aboveShadowFadeStart) {
|
||||
if (updateMin < 0 || updateMin > _above) updateMin = _above;
|
||||
if (updateMax < _above) updateMin = _above;
|
||||
}
|
||||
if (_dragging >= 0) {
|
||||
if (updateMin < 0 || updateMin > _dragging) updateMin = _dragging;
|
||||
if (updateMax < _dragging) updateMax = _dragging;
|
||||
}
|
||||
if (updateMin >= 0) {
|
||||
update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3));
|
||||
}
|
||||
}
|
||||
|
||||
bool StickersInner::updateAnimatedValues() {
|
||||
bool animating = false;
|
||||
uint64 ms = getms();
|
||||
for (int32 i = 0, l = _animStartTimes.size(); i < l; ++i) {
|
||||
uint64 start = _animStartTimes.at(i);
|
||||
if (start) {
|
||||
if (start + st::stickersRowDuration > ms && ms >= start) {
|
||||
_rows.at(i)->yadd.update((ms - start) / st::stickersRowDuration, anim::sineInOut);
|
||||
animating = true;
|
||||
} else {
|
||||
_rows.at(i)->yadd.finish();
|
||||
_animStartTimes[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_aboveShadowFadeStart) {
|
||||
if (_aboveShadowFadeStart + st::stickersRowDuration > ms && ms > _aboveShadowFadeStart) {
|
||||
_aboveShadowFadeOpacity.update((ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut);
|
||||
animating = true;
|
||||
} else {
|
||||
_aboveShadowFadeOpacity.finish();
|
||||
_aboveShadowFadeStart = 0;
|
||||
}
|
||||
}
|
||||
return animating;
|
||||
}
|
||||
|
||||
bool StickersInner::animStep_shifting(float64) {
|
||||
updateAnimatedRegions();
|
||||
|
||||
bool animating = updateAnimatedValues();
|
||||
if (!animating) {
|
||||
_above = _dragging;
|
||||
}
|
||||
return animating;
|
||||
}
|
||||
|
||||
void StickersInner::clear() {
|
||||
for (int32 i = 0, l = _rows.size(); i < l; ++i) {
|
||||
delete _rows.at(i);
|
||||
}
|
||||
_rows.clear();
|
||||
_animStartTimes.clear();
|
||||
_aboveShadowFadeStart = 0;
|
||||
_aboveShadowFadeOpacity = anim::fvalue(0, 0);
|
||||
_a_shifting.stop();
|
||||
_above = _dragging = _started = -1;
|
||||
_selected = -1;
|
||||
_removeDown = -1;
|
||||
setRemoveSel(-1);
|
||||
update();
|
||||
}
|
||||
|
||||
void StickersInner::setRemoveSel(int32 removeSel) {
|
||||
if (removeSel != _removeSel) {
|
||||
if (_removeSel >= 0) update(0, _itemsTop + _removeSel * _rowHeight, width(), _rowHeight);
|
||||
_removeSel = removeSel;
|
||||
if (_removeSel >= 0) update(0, _itemsTop + _removeSel * _rowHeight, width(), _rowHeight);
|
||||
setCursor((_removeSel >= 0 && (_removeDown < 0 || _removeDown == _removeSel)) ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersInner::rebuild() {
|
||||
QList<StickerSetRow*> rows, rowsDisabled;
|
||||
|
||||
int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
int32 namew = st::boxWideWidth - namex - st::contactsPadding.right() - st::contactsCheckPosition.x() - qMax(qMax(_returnWidth, _removeWidth), _restoreWidth);
|
||||
|
||||
clear();
|
||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||
_animStartTimes.reserve(order.size());
|
||||
|
||||
const StickerSets &sets(cStickerSets());
|
||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||
StickerSets::const_iterator it = sets.constFind(order.at(i));
|
||||
if (it != sets.cend()) {
|
||||
bool disabled = (it->flags & MTPDstickerSet::flag_disabled);
|
||||
|
||||
DocumentData *sticker = it->stickers.isEmpty() ? 0 : it->stickers.at(0);
|
||||
int32 pixw = 0, pixh = 0;
|
||||
if (sticker) {
|
||||
pixw = sticker->thumb->width();
|
||||
pixh = sticker->thumb->height();
|
||||
if (pixw > st::contactsPhotoSize) {
|
||||
if (pixw > pixh) {
|
||||
pixh = (pixh * st::contactsPhotoSize) / pixw;
|
||||
pixw = st::contactsPhotoSize;
|
||||
} else {
|
||||
pixw = (pixw * st::contactsPhotoSize) / pixh;
|
||||
pixh = st::contactsPhotoSize;
|
||||
}
|
||||
} else if (pixh > st::contactsPhotoSize) {
|
||||
pixw = (pixw * st::contactsPhotoSize) / pixh;
|
||||
pixh = st::contactsPhotoSize;
|
||||
}
|
||||
}
|
||||
QString title = it->title;
|
||||
int32 titleWidth = st::contactsNameFont->width(title);
|
||||
if (titleWidth > namew) {
|
||||
title = st::contactsNameFont->elided(title, namew);
|
||||
}
|
||||
bool official = (it->flags & MTPDstickerSet::flag_official);
|
||||
(disabled ? rowsDisabled : rows).push_back(new StickerSetRow(it->id, sticker, it->stickers.size(), title, official, disabled, pixw, pixh));
|
||||
_animStartTimes.push_back(0);
|
||||
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_flag_NOT_LOADED)) {
|
||||
App::api()->scheduleStickerSetRequest(it->id, it->access);
|
||||
}
|
||||
}
|
||||
}
|
||||
App::api()->requestStickerSets();
|
||||
_rows = rows + rowsDisabled;
|
||||
resize(width(), _itemsTop + _rows.size() * _rowHeight + st::membersPadding.bottom());
|
||||
}
|
||||
|
||||
QVector<uint64> StickersInner::getOrder() const {
|
||||
QVector<uint64> result;
|
||||
result.reserve(_rows.size());
|
||||
for (int32 i = 0, l = _rows.size(); i < l; ++i) {
|
||||
if (_rows.at(i)->disabled) {
|
||||
StickerSets::const_iterator it = cStickerSets().constFind(_rows.at(i)->id);
|
||||
if (it == cStickerSets().cend() || !(it->flags & MTPDstickerSet::flag_official)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.push_back(_rows.at(i)->id);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<uint64> StickersInner::getDisabledSets() const {
|
||||
QVector<uint64> result;
|
||||
result.reserve(_rows.size());
|
||||
for (int32 i = 0, l = _rows.size(); i < l; ++i) {
|
||||
if (_rows.at(i)->disabled) {
|
||||
result.push_back(_rows.at(i)->id);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void StickersInner::setVisibleScrollbar(int32 width) {
|
||||
_scrollbar = width;
|
||||
}
|
||||
|
||||
StickersInner::~StickersInner() {
|
||||
clear();
|
||||
}
|
||||
|
||||
StickersBox::StickersBox() : ItemListBox(st::boxScroll)
|
||||
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _reorderRequest(0)
|
||||
, _topShadow(this, st::contactsAboutShadow)
|
||||
, _bottomShadow(this)
|
||||
, _scrollDelta(0)
|
||||
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPhotoSize - st::contactsPadding.left() - st::contactsPadding.right())
|
||||
, _about(st::boxTextFont, lang(lng_stickers_reorder), _defaultOptions, _aboutWidth)
|
||||
, _aboutHeight(st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom()) {
|
||||
ItemListBox::init(&_inner, st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom(), st::boxTitleHeight + _aboutHeight);
|
||||
setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight)));
|
||||
|
||||
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
|
||||
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
|
||||
connect(&_inner, SIGNAL(checkDraggingScroll(int)), this, SLOT(onCheckDraggingScroll(int)));
|
||||
connect(&_inner, SIGNAL(noDraggingScroll()), this, SLOT(onNoDraggingScroll()));
|
||||
connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(onUpdateSelected()));
|
||||
connect(&_scrollTimer, SIGNAL(timeout()), this, SLOT(onScrollTimer()));
|
||||
_scrollTimer.setSingleShot(false);
|
||||
|
||||
onStickersUpdated();
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
int32 StickersBox::countHeight() const {
|
||||
return st::boxTitleHeight + _aboutHeight + _inner.height() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom();
|
||||
}
|
||||
|
||||
void StickersBox::disenableDone(const MTPBool & result, mtpRequestId req) {
|
||||
_disenableRequests.remove(req);
|
||||
if (_disenableRequests.isEmpty()) {
|
||||
saveOrder();
|
||||
}
|
||||
}
|
||||
|
||||
bool StickersBox::disenableFail(const RPCError &error, mtpRequestId req) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
_disenableRequests.remove(req);
|
||||
if (_disenableRequests.isEmpty()) {
|
||||
saveOrder();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void StickersBox::saveOrder() {
|
||||
QVector<uint64> order = _inner.getOrder();
|
||||
if (order.size() > 1) {
|
||||
QVector<MTPlong> mtpOrder;
|
||||
mtpOrder.reserve(order.size());
|
||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||
mtpOrder.push_back(MTP_long(order.at(i)));
|
||||
}
|
||||
_reorderRequest = MTP::send(MTPmessages_ReorderStickerSets(MTP_vector<MTPlong>(mtpOrder)), rpcDone(&StickersBox::reorderDone), rpcFail(&StickersBox::reorderFail));
|
||||
} else {
|
||||
reorderDone(MTP_boolTrue());
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::reorderDone(const MTPBool &result) {
|
||||
_reorderRequest = 0;
|
||||
onClose();
|
||||
}
|
||||
|
||||
bool StickersBox::reorderFail(const RPCError &result) {
|
||||
if (mtpIsFlood(result)) return false;
|
||||
_reorderRequest = 0;
|
||||
cSetLastStickersUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
onClose();
|
||||
return true;
|
||||
}
|
||||
|
||||
void StickersBox::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (paint(p)) return;
|
||||
|
||||
paintTitle(p, lang(lng_stickers_packs));
|
||||
p.translate(0, st::boxTitleHeight);
|
||||
|
||||
p.fillRect(0, 0, width(), _aboutHeight, st::contactsAboutBg);
|
||||
p.setPen(st::stickersReorderFg);
|
||||
_about.drawLeft(p, st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, width());
|
||||
}
|
||||
|
||||
void StickersBox::closePressed() {
|
||||
if (!_disenableRequests.isEmpty()) {
|
||||
for (QMap<mtpRequestId, NullType>::const_iterator i = _disenableRequests.cbegin(), e = _disenableRequests.cend(); i != e; ++i) {
|
||||
MTP::cancel(i.key());
|
||||
}
|
||||
_disenableRequests.clear();
|
||||
cSetLastStickersUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
} else if (_reorderRequest) {
|
||||
MTP::cancel(_reorderRequest);
|
||||
_reorderRequest = 0;
|
||||
cSetLastStickersUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::resizeEvent(QResizeEvent *e) {
|
||||
ItemListBox::resizeEvent(e);
|
||||
_save.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save.height());
|
||||
_cancel.moveToRight(st::boxButtonPadding.right() + _save.width() + st::boxButtonPadding.left(), _save.y());
|
||||
_inner.resize(width(), _inner.height());
|
||||
_topShadow.setGeometry(0, st::boxTitleHeight + _aboutHeight, width(), st::lineWidth);
|
||||
_bottomShadow.setGeometry(0, height() - st::boxButtonPadding.bottom() - _save.height() - st::boxButtonPadding.top() - st::lineWidth, width(), st::lineWidth);
|
||||
_inner.setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
|
||||
}
|
||||
|
||||
void StickersBox::onStickersUpdated() {
|
||||
_inner.rebuild();
|
||||
setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight)));
|
||||
_inner.setVisibleScrollbar((_scroll.scrollTopMax() > 0) ? (st::boxScroll.width - st::boxScroll.deltax) : 0);
|
||||
}
|
||||
|
||||
void StickersBox::onCheckDraggingScroll(int localY) {
|
||||
if (localY < _scroll.scrollTop()) {
|
||||
_scrollDelta = localY - _scroll.scrollTop();
|
||||
} else if (localY >= _scroll.scrollTop() + _scroll.height()) {
|
||||
_scrollDelta = localY - _scroll.scrollTop() - _scroll.height() + 1;
|
||||
} else {
|
||||
_scrollDelta = 0;
|
||||
}
|
||||
if (_scrollDelta) {
|
||||
_scrollTimer.start(15);
|
||||
} else {
|
||||
_scrollTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::onNoDraggingScroll() {
|
||||
_scrollTimer.stop();
|
||||
}
|
||||
|
||||
void StickersBox::onScrollTimer() {
|
||||
int32 d = (_scrollDelta > 0) ? qMin(_scrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_scrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed));
|
||||
_scroll.scrollToY(_scroll.scrollTop() + d);
|
||||
}
|
||||
|
||||
void StickersBox::onSave() {
|
||||
if (!_inner.savingStart()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool writeRecent = false;
|
||||
RecentStickerPack &recent(cGetRecentStickers());
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
|
||||
QVector<uint64> reorder = _inner.getOrder(), disabled = _inner.getDisabledSets();
|
||||
for (int32 i = 0, l = disabled.size(); i < l; ++i) {
|
||||
StickerSets::iterator it = sets.find(disabled.at(i));
|
||||
if (it != sets.cend()) {
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (!(it->flags & MTPDstickerSet::flag_disabled)) {
|
||||
MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName));
|
||||
if (it->flags & MTPDstickerSet::flag_official) {
|
||||
_disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolTrue()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType());
|
||||
it->flags |= MTPDstickerSet::flag_disabled;
|
||||
} else {
|
||||
_disenableRequests.insert(MTP::send(MTPmessages_UninstallStickerSet(setId), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType());
|
||||
int32 removeIndex = cStickerSetsOrder().indexOf(it->id);
|
||||
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
||||
sets.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StickerSetsOrder &order(cRefStickerSetsOrder());
|
||||
order.clear();
|
||||
for (int32 i = 0, l = reorder.size(); i < l; ++i) {
|
||||
StickerSets::iterator it = sets.find(reorder.at(i));
|
||||
if (it != sets.cend()) {
|
||||
if ((it->flags & MTPDstickerSet::flag_disabled) && !disabled.contains(it->id)) {
|
||||
MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName));
|
||||
_disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolFalse()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType());
|
||||
it->flags &= ~MTPDstickerSet::flag_disabled;
|
||||
}
|
||||
order.push_back(reorder.at(i));
|
||||
}
|
||||
}
|
||||
for (StickerSets::iterator it = sets.begin(); it != sets.cend();) {
|
||||
if (it->id == CustomStickerSetId || it->id == RecentStickerSetId || order.contains(it->id)) {
|
||||
++it;
|
||||
} else {
|
||||
it = sets.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
emit App::main()->stickersUpdated();
|
||||
|
||||
if (_disenableRequests.isEmpty()) {
|
||||
saveOrder();
|
||||
} else {
|
||||
MTP::sendAnything();
|
||||
}
|
||||
}
|
||||
|
||||
void StickersBox::hideAll() {
|
||||
_save.hide();
|
||||
_cancel.hide();
|
||||
_topShadow.hide();
|
||||
_bottomShadow.hide();
|
||||
ItemListBox::hideAll();
|
||||
}
|
||||
|
||||
void StickersBox::showAll() {
|
||||
_save.show();
|
||||
_cancel.show();
|
||||
_topShadow.show();
|
||||
_bottomShadow.show();
|
||||
ItemListBox::showAll();
|
||||
}
|
||||
|
||||
int32 stickerPacksCount(bool includeDisabledOfficial) {
|
||||
int32 result = 0;
|
||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||
const StickerSets &sets(cStickerSets());
|
||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||
StickerSets::const_iterator it = sets.constFind(order.at(i));
|
||||
if (it != sets.cend()) {
|
||||
if (!(it->flags & MTPDstickerSet::flag_disabled) || ((it->flags & MTPDstickerSet::flag_official) && includeDisabledOfficial)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -106,3 +106,145 @@ private:
|
|||
BoxButton _add, _share, _cancel, _done;
|
||||
QString _title;
|
||||
};
|
||||
|
||||
class StickersInner : public TWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
StickersInner();
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
|
||||
void rebuild();
|
||||
bool savingStart() {
|
||||
if (_saving) return false;
|
||||
_saving = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<uint64> getOrder() const;
|
||||
QVector<uint64> getDisabledSets() const;
|
||||
|
||||
void setVisibleScrollbar(int32 width);
|
||||
|
||||
~StickersInner();
|
||||
|
||||
signals:
|
||||
|
||||
void checkDraggingScroll(int localY);
|
||||
void noDraggingScroll();
|
||||
|
||||
public slots:
|
||||
|
||||
void onUpdateSelected();
|
||||
|
||||
private:
|
||||
|
||||
bool animStep_shifting(float64 ms);
|
||||
void paintRow(Painter &p, int32 index);
|
||||
void clear();
|
||||
void setRemoveSel(int32 removeSel);
|
||||
float64 aboveShadowOpacity() const;
|
||||
void updateAnimatedRegions();
|
||||
bool updateAnimatedValues();
|
||||
|
||||
int32 _rowHeight;
|
||||
struct StickerSetRow {
|
||||
StickerSetRow(uint64 id, DocumentData *sticker, int32 count, const QString &title, bool official, bool disabled, int32 pixw, int32 pixh) : id(id)
|
||||
, sticker(sticker)
|
||||
, count(count)
|
||||
, title(title)
|
||||
, official(official)
|
||||
, disabled(disabled)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh)
|
||||
, yadd(0, 0) {
|
||||
}
|
||||
uint64 id;
|
||||
DocumentData *sticker;
|
||||
int32 count;
|
||||
QString title;
|
||||
bool official, disabled;
|
||||
int32 pixw, pixh;
|
||||
anim::ivalue yadd;
|
||||
};
|
||||
typedef QList<StickerSetRow*> StickerSetRows;
|
||||
StickerSetRows _rows;
|
||||
QList<uint64> _animStartTimes;
|
||||
uint64 _aboveShadowFadeStart;
|
||||
anim::fvalue _aboveShadowFadeOpacity;
|
||||
Animation _a_shifting;
|
||||
|
||||
int32 _itemsTop;
|
||||
|
||||
bool _saving;
|
||||
|
||||
int32 _removeSel, _removeDown, _removeWidth, _returnWidth, _restoreWidth;
|
||||
|
||||
QPoint _mouse;
|
||||
int32 _selected;
|
||||
QPoint _dragStart;
|
||||
int32 _started, _dragging, _above;
|
||||
|
||||
BoxShadow _aboveShadow;
|
||||
|
||||
int32 _scrollbar;
|
||||
};
|
||||
|
||||
class StickersBox : public ItemListBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
StickersBox();
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
|
||||
void closePressed();
|
||||
|
||||
public slots:
|
||||
|
||||
void onStickersUpdated();
|
||||
|
||||
void onCheckDraggingScroll(int localY);
|
||||
void onNoDraggingScroll();
|
||||
void onScrollTimer();
|
||||
|
||||
void onSave();
|
||||
|
||||
protected:
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
|
||||
private:
|
||||
|
||||
int32 countHeight() const;
|
||||
|
||||
void disenableDone(const MTPBool &result, mtpRequestId req);
|
||||
bool disenableFail(const RPCError &error, mtpRequestId req);
|
||||
void reorderDone(const MTPBool &result);
|
||||
bool reorderFail(const RPCError &result);
|
||||
void saveOrder();
|
||||
|
||||
StickersInner _inner;
|
||||
BoxButton _save, _cancel;
|
||||
QMap<mtpRequestId, NullType> _disenableRequests;
|
||||
mtpRequestId _reorderRequest;
|
||||
PlainShadow _topShadow;
|
||||
ScrollableBoxShadow _bottomShadow;
|
||||
|
||||
QTimer _scrollTimer;
|
||||
int32 _scrollDelta;
|
||||
|
||||
int32 _aboutWidth;
|
||||
Text _about;
|
||||
int32 _aboutHeight;
|
||||
|
||||
};
|
||||
|
||||
int32 stickerPacksCount(bool includeDisabledOfficial = false);
|
||||
|
|
|
@ -20,9 +20,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
static const int32 AppVersion = 9013;
|
||||
static const wchar_t *AppVersionStr = L"0.9.13";
|
||||
static const int32 AppVersion = 9015;
|
||||
static const wchar_t *AppVersionStr = L"0.9.15";
|
||||
static const bool DevVersion = false;
|
||||
//#define BETA_VERSION (9014003ULL) // just comment this line to build public version
|
||||
|
||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||
static const wchar_t *AppName = L"Telegram Desktop";
|
||||
|
@ -58,6 +59,8 @@ enum {
|
|||
|
||||
MTPDebugBufferSize = 1024 * 1024, // 1 mb start size
|
||||
|
||||
MaxUsersPerInvite = 100, // max users in one super group invite request
|
||||
|
||||
MTPPingDelayDisconnect = 60, // 1 min
|
||||
MTPPingSendAfterAuto = 30, // send new ping starting from 30 seconds (add to existing container)
|
||||
MTPPingSendAfter = 45, // send new ping after 45 seconds without ping
|
||||
|
@ -67,7 +70,7 @@ enum {
|
|||
MaxSelectedItems = 100,
|
||||
|
||||
MaxPhoneCodeLength = 4, // max length of country phone code
|
||||
MaxPhoneTailLength = 18, // rest of the phone number, without country code (seen 12 at least)
|
||||
MaxPhoneTailLength = 32, // rest of the phone number, without country code (seen 12 at least), need more for service numbers
|
||||
|
||||
MaxScrollSpeed = 37, // 37px per 15ms while select-by-drag
|
||||
FingerAccuracyThreshold = 3, // touch flick ignore 3px
|
||||
|
@ -265,6 +268,18 @@ static const int32 ApiId = 17349;
|
|||
static const char *ApiHash = "344583e45741c457fe1862106095a5eb";
|
||||
#endif
|
||||
|
||||
#ifndef BETA_VERSION
|
||||
#define BETA_VERSION (0)
|
||||
#endif
|
||||
|
||||
#if (defined CUSTOM_API_ID) && (BETA_VERSION > 0)
|
||||
#include "../../../TelegramPrivate/beta_private.h" // private key for downloading closed betas
|
||||
#else
|
||||
static const char *BetaPrivateKey = "";
|
||||
#undef BETA_VERSION
|
||||
#define BETA_VERSION 0
|
||||
#endif
|
||||
|
||||
inline const char *cApiDeviceModel() {
|
||||
#ifdef Q_OS_WIN
|
||||
return "PC";
|
||||
|
|
|
@ -28,6 +28,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "mainwidget.h"
|
||||
#include "boxes/addcontactbox.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
#include "localstorage.h"
|
||||
|
||||
|
@ -53,7 +54,10 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
|
|||
, _cancelSearchInPeer(this, st::btnCancelSearch)
|
||||
, _overDelete(false)
|
||||
, _searchInPeer(0)
|
||||
, _searchInMigrated(0) {
|
||||
, _searchInMigrated(0)
|
||||
, _menuPeer(0)
|
||||
, _menuActionPeer(0)
|
||||
, _menu(0) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
||||
connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*)));
|
||||
|
@ -61,7 +65,7 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
|
|||
connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
|
||||
connect(&_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer()));
|
||||
_cancelSearchInPeer.hide();
|
||||
refresh(false);
|
||||
refresh();
|
||||
}
|
||||
|
||||
int32 DialogsInner::filteredOffset() const {
|
||||
|
@ -91,7 +95,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
|||
|
||||
if (_state == DefaultState) {
|
||||
int32 otherStart = dialogs.list.count * st::dlgHeight;
|
||||
PeerData *active = App::main()->activePeer(), *selected = sel ? sel->history->peer : 0;
|
||||
PeerData *active = App::main()->activePeer(), *selected = _menuPeer ? _menuPeer : (sel ? sel->history->peer : 0);
|
||||
if (otherStart) {
|
||||
dialogs.list.paint(p, fullWidth(), r.top(), r.top() + r.height(), active, selected, paintingOther);
|
||||
}
|
||||
|
@ -160,7 +164,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
|||
MsgId actId = App::main()->activeMsgId();
|
||||
for (; from < to; ++from) {
|
||||
bool active = ((_filterResults[from]->history->peer == act) || (_filterResults[from]->history->peer->migrateTo() && _filterResults[from]->history->peer->migrateTo() == act)) && !actId;
|
||||
bool selected = (from == _filteredSel);
|
||||
bool selected = (from == _filteredSel) || (_filterResults[from]->history->peer == _menuPeer);
|
||||
_filterResults[from]->paint(p, w, active, selected, paintingOther);
|
||||
p.translate(0, st::dlgHeight);
|
||||
}
|
||||
|
@ -461,6 +465,9 @@ void DialogsInner::createDialog(History *history) {
|
|||
|
||||
void DialogsInner::removeDialog(History *history) {
|
||||
if (!history) return;
|
||||
if (history->peer == _menuPeer && _menu) {
|
||||
_menu->deleteLater();
|
||||
}
|
||||
if (sel && sel->history == history) {
|
||||
sel = 0;
|
||||
}
|
||||
|
@ -549,13 +556,26 @@ void DialogsInner::enterEvent(QEvent *e) {
|
|||
onUpdateSelected(true);
|
||||
}
|
||||
|
||||
void DialogsInner::updateSelectedRow() {
|
||||
void DialogsInner::updateSelectedRow(PeerData *peer) {
|
||||
if (_state == DefaultState) {
|
||||
if (sel) {
|
||||
if (peer) {
|
||||
if (History *h = App::historyLoaded(peer->id)) {
|
||||
if (h->dialogs.contains(0)) {
|
||||
update(0, h->dialogs.value(0)->pos * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
}
|
||||
}
|
||||
} else if (sel) {
|
||||
update(0, sel->pos * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
}
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
if (_hashtagSel >= 0) {
|
||||
if (peer) {
|
||||
for (int32 i = 0, l = _filterResults.size(); i != l; ++i) {
|
||||
if (_filterResults.at(i)->history->peer == peer) {
|
||||
update(0, filteredOffset() + i * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_hashtagSel >= 0) {
|
||||
update(0, _hashtagSel * st::mentionHeight, fullWidth(), st::mentionHeight);
|
||||
} else if (_filteredSel >= 0) {
|
||||
update(0, filteredOffset() + _filteredSel * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
|
@ -579,6 +599,148 @@ void DialogsInner::leaveEvent(QEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
|
||||
if (_menu) {
|
||||
_menu->deleteLater();
|
||||
_menu = 0;
|
||||
}
|
||||
if (_menuPeer) {
|
||||
updateSelectedRow(_menuPeer);
|
||||
_menuPeer = 0;
|
||||
disconnect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
}
|
||||
|
||||
if (e->reason() == QContextMenuEvent::Mouse) {
|
||||
lastMousePos = e->globalPos();
|
||||
selByMouse = true;
|
||||
onUpdateSelected(true);
|
||||
}
|
||||
|
||||
History *history = 0;
|
||||
if (_state == DefaultState) {
|
||||
if (sel) history = sel->history;
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) {
|
||||
history = _filterResults[_filteredSel]->history;
|
||||
}
|
||||
}
|
||||
if (!history) return;
|
||||
_menuPeer = history->peer;
|
||||
|
||||
_menu = new PopupMenu();
|
||||
_menu->addAction(lang((_menuPeer->isChat() || _menuPeer->isMegagroup()) ? lng_context_view_group : (_menuPeer->isUser() ? lng_context_view_profile : lng_context_view_channel)), this, SLOT(onContextProfile()))->setEnabled(true);
|
||||
_menu->addAction(lang(menuPeerMuted() ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray), this, SLOT(onContextToggleNotifications()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_profile_search_messages), this, SLOT(onContextSearch()))->setEnabled(true);
|
||||
if (_menuPeer->isUser()) {
|
||||
_menu->addAction(lang(lng_profile_clear_history), this, SLOT(onContextClearHistory()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_profile_delete_conversation), this, SLOT(onContextDeleteAndLeave()))->setEnabled(true);
|
||||
if (_menuPeer->asUser()->access != UserNoAccess) {
|
||||
_menu->addAction(lang((_menuPeer->asUser()->blocked == UserIsBlocked) ? (_menuPeer->asUser()->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_menuPeer->asUser()->botInfo ? lng_profile_block_bot : lng_profile_block_user)), this, SLOT(onContextToggleBlock()))->setEnabled(true);
|
||||
connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
}
|
||||
} else if (_menuPeer->isChat()) {
|
||||
_menu->addAction(lang(lng_profile_clear_history), this, SLOT(onContextClearHistory()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_profile_clear_and_exit), this, SLOT(onContextDeleteAndLeave()))->setEnabled(true);
|
||||
} else if (_menuPeer->isChannel() && _menuPeer->asChannel()->amIn() && !_menuPeer->asChannel()->amCreator()) {
|
||||
_menu->addAction(lang(_menuPeer->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel), this, SLOT(onContextDeleteAndLeave()))->setEnabled(true);
|
||||
}
|
||||
|
||||
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroyed(QObject*)));
|
||||
_menu->popup(e->globalPos());
|
||||
e->accept();
|
||||
}
|
||||
|
||||
bool DialogsInner::menuPeerMuted() {
|
||||
return _menuPeer && _menuPeer->notify != EmptyNotifySettings && _menuPeer->notify != UnknownNotifySettings && _menuPeer->notify->mute >= unixtime();
|
||||
}
|
||||
|
||||
void DialogsInner::onContextProfile() {
|
||||
if (!_menuPeer) return;
|
||||
App::main()->showPeerProfile(_menuPeer);
|
||||
}
|
||||
|
||||
void DialogsInner::onContextToggleNotifications() {
|
||||
if (!_menuPeer) return;
|
||||
App::main()->updateNotifySetting(_menuPeer, menuPeerMuted());
|
||||
}
|
||||
|
||||
void DialogsInner::onContextSearch() {
|
||||
if (!_menuPeer) return;
|
||||
App::main()->searchInPeer(_menuPeer);
|
||||
}
|
||||
|
||||
void DialogsInner::onContextClearHistory() {
|
||||
if (!_menuPeer || _menuPeer->isChannel()) return;
|
||||
|
||||
_menuActionPeer = _menuPeer;
|
||||
ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : lng_sure_delete_group_history(lt_group, _menuPeer->name), lang(lng_box_delete), st::attentionBoxButton);
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onContextClearHistorySure()));
|
||||
App::showLayer(box);
|
||||
}
|
||||
|
||||
void DialogsInner::onContextClearHistorySure() {
|
||||
if (!_menuActionPeer || _menuActionPeer->isChannel()) return;
|
||||
App::wnd()->hideLayer();
|
||||
App::main()->clearHistory(_menuActionPeer);
|
||||
}
|
||||
|
||||
void DialogsInner::onContextDeleteAndLeave() {
|
||||
if (!_menuPeer) return;
|
||||
|
||||
_menuActionPeer = _menuPeer;
|
||||
ConfirmBox *box = new ConfirmBox(_menuPeer->isUser() ? lng_sure_delete_history(lt_contact, _menuPeer->name) : (_menuPeer->isChat() ? lng_sure_delete_and_exit(lt_group, _menuPeer->name) : lang(_menuPeer->isMegagroup() ? lng_sure_leave_group : lng_sure_leave_channel)), lang(_menuPeer->isUser() ? lng_box_delete : lng_box_leave), _menuPeer->isChannel() ? st::defaultBoxButton : st::attentionBoxButton);
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onContextDeleteAndLeaveSure()));
|
||||
App::wnd()->showLayer(box);
|
||||
}
|
||||
|
||||
void DialogsInner::onContextDeleteAndLeaveSure() {
|
||||
if (!_menuActionPeer) return;
|
||||
|
||||
App::wnd()->hideLayer();
|
||||
App::main()->showDialogs();
|
||||
if (_menuActionPeer->isUser()) {
|
||||
App::main()->deleteConversation(_menuActionPeer);
|
||||
} else if (_menuActionPeer->isChat()) {
|
||||
MTP::send(MTPmessages_DeleteChatUser(_menuActionPeer->asChat()->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _menuActionPeer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _menuActionPeer));
|
||||
} else if (_menuActionPeer->isChannel()) {
|
||||
if (_menuActionPeer->migrateFrom()) {
|
||||
App::main()->deleteConversation(_menuActionPeer->migrateFrom());
|
||||
}
|
||||
MTP::send(MTPchannels_LeaveChannel(_menuActionPeer->asChannel()->inputChannel), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::onContextToggleBlock() {
|
||||
if (!_menuPeer || !_menuPeer->isUser()) return;
|
||||
if (_menuPeer->asUser()->blocked == UserIsBlocked) {
|
||||
MTP::send(MTPcontacts_Unblock(_menuPeer->asUser()->inputUser), rpcDone(&DialogsInner::contextBlockDone, qMakePair(_menuPeer->asUser(), false)));
|
||||
} else {
|
||||
MTP::send(MTPcontacts_Block(_menuPeer->asUser()->inputUser), rpcDone(&DialogsInner::contextBlockDone, qMakePair(_menuPeer->asUser(), true)));
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::contextBlockDone(QPair<UserData*, bool> data, const MTPBool &result) {
|
||||
data.first->blocked = data.second ? UserIsBlocked : UserIsNotBlocked;
|
||||
emit App::main()->peerUpdated(data.first);
|
||||
}
|
||||
|
||||
void DialogsInner::onMenuDestroyed(QObject *obj) {
|
||||
if (_menu == obj) {
|
||||
_menu = 0;
|
||||
if (_menuPeer) {
|
||||
updateSelectedRow(_menuPeer);
|
||||
_menuPeer = 0;
|
||||
disconnect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
}
|
||||
lastMousePos = QCursor::pos();
|
||||
if (rect().contains(mapFromGlobal(lastMousePos))) {
|
||||
selByMouse = true;
|
||||
setMouseTracking(true);
|
||||
onUpdateSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::onParentGeometryChanged() {
|
||||
lastMousePos = QCursor::pos();
|
||||
if (rect().contains(mapFromGlobal(lastMousePos))) {
|
||||
|
@ -763,6 +925,18 @@ void DialogsInner::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) {
|
|||
}
|
||||
}
|
||||
|
||||
void DialogsInner::updateNotifySettings(PeerData *peer) {
|
||||
if (_menu && _menuPeer == peer && _menu->actions().size() > 1) {
|
||||
_menu->actions().at(1)->setText(lang(menuPeerMuted() ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray));
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::peerUpdated(PeerData *peer) {
|
||||
if (_menu && _menuPeer == peer && _menuPeer->isUser() && _menu->actions().size() > 5) {
|
||||
_menu->actions().at(5)->setText(lang((_menuPeer->asUser()->blocked == UserIsBlocked) ? (_menuPeer->asUser()->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_menuPeer->asUser()->botInfo ? lng_profile_block_bot : lng_profile_block_user)));
|
||||
}
|
||||
}
|
||||
|
||||
PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) {
|
||||
lastMousePos = globalPos;
|
||||
selByMouse = true;
|
||||
|
@ -1008,7 +1182,6 @@ void DialogsInner::setState(State newState) {
|
|||
_filteredSel = -1;
|
||||
}
|
||||
onFilterUpdate(_filter, true);
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
DialogsInner::State DialogsInner::state() const {
|
||||
|
@ -1681,7 +1854,9 @@ bool DialogsWidget::animStep_show(float64 ms) {
|
|||
|
||||
_scroll.show();
|
||||
_filter.show();
|
||||
onFilterUpdate(true);
|
||||
_a_show.stop();
|
||||
|
||||
onFilterUpdate();
|
||||
activate();
|
||||
|
||||
if (App::app()) App::app()->mtpUnpause();
|
||||
|
@ -1708,6 +1883,10 @@ void DialogsWidget::itemReplaced(HistoryItem *oldItem, HistoryItem *newItem) {
|
|||
_inner.itemReplaced(oldItem, newItem);
|
||||
}
|
||||
|
||||
void DialogsWidget::updateNotifySettings(PeerData *peer) {
|
||||
_inner.updateNotifySettings(peer);
|
||||
}
|
||||
|
||||
void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
|
||||
for (QVector<MTPDialog>::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) {
|
||||
switch (i->type()) {
|
||||
|
|
|
@ -31,7 +31,7 @@ enum DialogsSearchRequestType {
|
|||
DialogsSearchMigratedFromOffset,
|
||||
};
|
||||
|
||||
class DialogsInner : public SplittedWidget {
|
||||
class DialogsInner : public SplittedWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -59,6 +59,7 @@ public:
|
|||
void resizeEvent(QResizeEvent *e);
|
||||
void enterEvent(QEvent *e);
|
||||
void leaveEvent(QEvent *e);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
|
||||
void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool act, bool sel, bool onlyBackground) const;
|
||||
void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const;
|
||||
|
@ -120,6 +121,8 @@ public:
|
|||
|
||||
PeerData *updateFromParentDrag(QPoint globalPos);
|
||||
|
||||
void updateNotifySettings(PeerData *peer);
|
||||
|
||||
~DialogsInner();
|
||||
|
||||
public slots:
|
||||
|
@ -130,6 +133,19 @@ public slots:
|
|||
void onPeerPhotoChanged(PeerData *peer);
|
||||
void onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow);
|
||||
|
||||
void onContextProfile();
|
||||
void onContextToggleNotifications();
|
||||
void onContextSearch();
|
||||
void onContextClearHistory();
|
||||
void onContextClearHistorySure();
|
||||
void onContextDeleteAndLeave();
|
||||
void onContextDeleteAndLeaveSure();
|
||||
void onContextToggleBlock();
|
||||
|
||||
void onMenuDestroyed(QObject*);
|
||||
|
||||
void peerUpdated(PeerData *peer);
|
||||
|
||||
signals:
|
||||
|
||||
void mustScrollTo(int scrollToTop, int scrollToBottom);
|
||||
|
@ -147,7 +163,9 @@ protected:
|
|||
private:
|
||||
|
||||
void clearSearchResults(bool clearPeople = true);
|
||||
void updateSelectedRow();
|
||||
void updateSelectedRow(PeerData *peer = 0);
|
||||
bool menuPeerMuted();
|
||||
void contextBlockDone(QPair<UserData*, bool> data, const MTPBool &result);
|
||||
|
||||
DialogsIndexed dialogs;
|
||||
DialogsIndexed contactsNoDialogs;
|
||||
|
@ -186,7 +204,9 @@ private:
|
|||
|
||||
bool _overDelete;
|
||||
|
||||
PeerData *_searchInPeer, *_searchInMigrated;
|
||||
PeerData *_searchInPeer, *_searchInMigrated, *_menuPeer, *_menuActionPeer;
|
||||
|
||||
PopupMenu *_menu;
|
||||
|
||||
};
|
||||
|
||||
|
@ -242,6 +262,8 @@ public:
|
|||
void itemRemoved(HistoryItem *item);
|
||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
||||
|
||||
void updateNotifySettings(PeerData *peer);
|
||||
|
||||
signals:
|
||||
|
||||
void cancelled();
|
||||
|
|
|
@ -30,6 +30,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "apiwrap.h"
|
||||
|
||||
#include "boxes/confirmbox.h"
|
||||
#include "boxes/stickersetbox.h"
|
||||
|
||||
Dropdown::Dropdown(QWidget *parent, const style::dropdown &st) : TWidget(parent),
|
||||
_ignore(false), _selected(-1), _st(st), _width(_st.width), _hiding(false), a_opacity(0), _shadow(_st.shadow) {
|
||||
|
@ -38,7 +39,7 @@ _ignore(false), _selected(-1), _st(st), _width(_st.width), _hiding(false), a_opa
|
|||
_hideTimer.setSingleShot(true);
|
||||
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart()));
|
||||
|
||||
if (cPlatform() == dbipMac) {
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
|
||||
}
|
||||
}
|
||||
|
@ -1195,22 +1196,31 @@ void EmojiPanInner::showEmojiPack(DBIEmojiTab packIndex) {
|
|||
update();
|
||||
}
|
||||
|
||||
StickerPanInner::StickerPanInner() : _maxHeight(st::emojiPanMaxHeight),
|
||||
_top(0), _selected(-1), _pressedSel(-1) {
|
||||
resize(st::emojiPanWidth - st::emojiScroll.width, countHeight());
|
||||
StickerPanInner::StickerPanInner() : TWidget()
|
||||
, _top(0)
|
||||
, _selected(-1)
|
||||
, _pressedSel(-1)
|
||||
, _settings(this, lang(lng_stickers_you_have))
|
||||
, _previewShown(false) {
|
||||
setMaxHeight(st::emojiPanMaxHeight);
|
||||
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
connect(&_settings, SIGNAL(clicked()), this, SLOT(onSettings()));
|
||||
|
||||
_previewTimer.setSingleShot(true);
|
||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
||||
|
||||
refreshStickers();
|
||||
}
|
||||
|
||||
void StickerPanInner::setMaxHeight(int32 h) {
|
||||
_maxHeight = h;
|
||||
resize(st::emojiPanWidth - st::emojiScroll.width, countHeight());
|
||||
_settings.moveToLeft((st::emojiPanWidth - _settings.width()) / 2, height() / 3);
|
||||
}
|
||||
|
||||
void StickerPanInner::setScrollTop(int top) {
|
||||
|
@ -1228,7 +1238,7 @@ int StickerPanInner::countHeight() {
|
|||
if (i == _sets.size() - 1 && h < minLastH) h = minLastH;
|
||||
result += h;
|
||||
}
|
||||
return result + st::stickerPanPadding;
|
||||
return qMax(minLastH, result) + st::stickerPanPadding;
|
||||
}
|
||||
|
||||
QRect StickerPanInner::stickerRect(int tab, int sel) {
|
||||
|
@ -1343,15 +1353,23 @@ void StickerPanInner::mousePressEvent(QMouseEvent *e) {
|
|||
updateSelected();
|
||||
|
||||
_pressedSel = _selected;
|
||||
_previewTimer.start(QApplication::startDragTime());
|
||||
}
|
||||
|
||||
void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_previewTimer.stop();
|
||||
|
||||
int32 pressed = _pressedSel;
|
||||
_pressedSel = -1;
|
||||
|
||||
_lastMousePos = e->globalPos();
|
||||
updateSelected();
|
||||
|
||||
if (_previewShown) {
|
||||
_previewShown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selected < 0 || _selected != pressed) return;
|
||||
if (_selected >= MatrixRowShift * _sets.size()) {
|
||||
return;
|
||||
|
@ -1461,6 +1479,8 @@ void StickerPanInner::refreshStickers() {
|
|||
int32 h = countHeight();
|
||||
if (h != height()) resize(width(), h);
|
||||
|
||||
_settings.setVisible(_sets.isEmpty());
|
||||
|
||||
emit refreshIcons();
|
||||
|
||||
updateSelected();
|
||||
|
@ -1512,7 +1532,7 @@ uint64 StickerPanInner::currentSet(int yOffset) const {
|
|||
void StickerPanInner::appendSet(uint64 setId) {
|
||||
const StickerSets &sets(cStickerSets());
|
||||
StickerSets::const_iterator it = sets.constFind(setId);
|
||||
if (it == sets.cend() || it->stickers.isEmpty()) return;
|
||||
if (it == sets.cend() || (it->flags & MTPDstickerSet::flag_disabled) || it->stickers.isEmpty()) return;
|
||||
|
||||
StickerPack pack;
|
||||
pack.reserve(it->stickers.size());
|
||||
|
@ -1630,7 +1650,7 @@ void StickerPanInner::refreshPanels(QVector<EmojiPanel*> &panels) {
|
|||
}
|
||||
|
||||
void StickerPanInner::updateSelected() {
|
||||
if (_pressedSel >= 0) return;
|
||||
if (_pressedSel >= 0 && !_previewShown) return;
|
||||
|
||||
int32 selIndex = -1;
|
||||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
|
@ -1707,9 +1727,29 @@ void StickerPanInner::updateSelected() {
|
|||
}
|
||||
}
|
||||
_selected = selIndex;
|
||||
if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
|
||||
_pressedSel = _selected;
|
||||
if (newSel >= 0 && xNewSel < 0) {
|
||||
Ui::showStickerPreview(_sets.at(newSelTab).pack.at(newSel % MatrixRowShift));
|
||||
}
|
||||
}
|
||||
if (startanim) anim::start(this);
|
||||
}
|
||||
|
||||
void StickerPanInner::onSettings() {
|
||||
App::showLayer(new StickersBox());
|
||||
}
|
||||
|
||||
void StickerPanInner::onPreview() {
|
||||
if (_pressedSel >= 0 && _pressedSel < MatrixRowShift * _sets.size()) {
|
||||
int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
|
||||
if (sel < _sets.at(tab).pack.size()) {
|
||||
Ui::showStickerPreview(_sets.at(tab).pack.at(sel));
|
||||
_previewShown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool StickerPanInner::animStep(float64 ms) {
|
||||
uint64 now = getms();
|
||||
QRegion toUpdate;
|
||||
|
@ -1831,14 +1871,14 @@ void EmojiSwitchButton::paintEvent(QPaintEvent *e) {
|
|||
|
||||
EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent), _maxHeight(st::emojiPanMaxHeight),
|
||||
_horizontal(false), _noTabUpdate(false), _hiding(false), a_opacity(0), _shadow(st::dropdownDef.shadow),
|
||||
_recent(this , qsl("emoji_group"), dbietRecent , QString(), true , st::rbEmojiRecent),
|
||||
_people(this , qsl("emoji_group"), dbietPeople , QString(), false, st::rbEmojiPeople),
|
||||
_nature(this , qsl("emoji_group"), dbietNature , QString(), false, st::rbEmojiNature),
|
||||
_food(this , qsl("emoji_group"), dbietFood , QString(), false, st::rbEmojiFood),
|
||||
_celebration(this, qsl("emoji_group"), dbietCelebration, QString(), false, st::rbEmojiCelebration),
|
||||
_activity(this , qsl("emoji_group"), dbietActivity , QString(), false, st::rbEmojiActivity),
|
||||
_travel(this , qsl("emoji_group"), dbietTravel , QString(), false, st::rbEmojiTravel),
|
||||
_objects(this , qsl("emoji_group"), dbietObjects , QString(), false, st::rbEmojiObjects),
|
||||
_recent(this , qsl("emoji_group"), dbietRecent , QString(), true , st::rbEmojiRecent),
|
||||
_people(this , qsl("emoji_group"), dbietPeople , QString(), false, st::rbEmojiPeople),
|
||||
_nature(this , qsl("emoji_group"), dbietNature , QString(), false, st::rbEmojiNature),
|
||||
_food(this , qsl("emoji_group"), dbietFood , QString(), false, st::rbEmojiFood),
|
||||
_activity(this, qsl("emoji_group"), dbietActivity, QString(), false, st::rbEmojiActivity),
|
||||
_travel(this , qsl("emoji_group"), dbietTravel , QString(), false, st::rbEmojiTravel),
|
||||
_objects(this , qsl("emoji_group"), dbietObjects , QString(), false, st::rbEmojiObjects),
|
||||
_symbols(this , qsl("emoji_group"), dbietSymbols , QString(), false, st::rbEmojiSymbols),
|
||||
_iconOver(-1), _iconSel(0), _iconDown(-1), _iconsDragging(false),
|
||||
_iconAnim(animFunc(this, &EmojiPan::iconAnim)),
|
||||
_iconsLeft(0), _iconsTop(0), _iconsStartX(0), _iconsMax(0), _iconsX(0, 0), _iconSelX(0, 0), _iconsStartAnim(0),
|
||||
|
@ -1872,10 +1912,10 @@ s_scroll(this, st::emojiScroll), s_inner(), s_switch(&s_scroll, false), _removin
|
|||
prepareTab(left, top, _width, _people);
|
||||
prepareTab(left, top, _width, _nature);
|
||||
prepareTab(left, top, _width, _food);
|
||||
prepareTab(left, top, _width, _celebration);
|
||||
prepareTab(left, top, _width, _activity);
|
||||
prepareTab(left, top, _width, _travel);
|
||||
prepareTab(left, top, _width, _objects);
|
||||
prepareTab(left, top, _width, _symbols);
|
||||
e_inner.fillPanels(e_panels);
|
||||
updatePanelsPositions(e_panels, 0);
|
||||
|
||||
|
@ -1903,7 +1943,7 @@ s_scroll(this, st::emojiScroll), s_inner(), s_switch(&s_scroll, false), _removin
|
|||
connect(&e_inner, SIGNAL(needRefreshPanels()), this, SLOT(onRefreshPanels()));
|
||||
connect(&s_inner, SIGNAL(needRefreshPanels()), this, SLOT(onRefreshPanels()));
|
||||
|
||||
if (cPlatform() == dbipMac) {
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
|
||||
}
|
||||
|
||||
|
@ -1938,10 +1978,10 @@ void EmojiPan::setMaxHeight(int32 h) {
|
|||
_people.move(_people.x(), _iconsTop);
|
||||
_nature.move(_nature.x(), _iconsTop);
|
||||
_food.move(_food.x(), _iconsTop);
|
||||
_celebration.move(_celebration.x(), _iconsTop);
|
||||
_activity.move(_activity.x(), _iconsTop);
|
||||
_travel.move(_travel.x(), _iconsTop);
|
||||
_objects.move(_objects.x(), _iconsTop);
|
||||
_symbols.move(_symbols.x(), _iconsTop);
|
||||
|
||||
update();
|
||||
}
|
||||
|
@ -1976,6 +2016,8 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
|
|||
p.fillRect(myrtlrect(r.x() + r.width() - st::emojiScroll.width, r.y(), st::emojiScroll.width, e_scroll.height()), st::white->b);
|
||||
if (_stickersShown) {
|
||||
p.fillRect(r.left(), _iconsTop, r.width(), st::rbEmoji.height, st::emojiPanCategories->b);
|
||||
p.drawSpriteLeft(_iconsLeft + 7 * st::rbEmoji.width + st::rbEmojiRecent.imagePos.x(), _iconsTop + st::rbEmojiRecent.imagePos.y(), width(), st::stickersSettings);
|
||||
|
||||
if (!_icons.isEmpty()) {
|
||||
int32 x = _iconsLeft, i = 0, selxrel = _iconSelX.current(), selx = x + selxrel - _iconsX.current();
|
||||
if (!_icons.at(i).sticker) {
|
||||
|
@ -1996,13 +2038,13 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
|
|||
++i;
|
||||
}
|
||||
|
||||
QRect clip(x, _iconsTop, _iconsLeft + 8 * st::rbEmoji.width - x, st::rbEmoji.height);
|
||||
QRect clip(x, _iconsTop, _iconsLeft + 7 * st::rbEmoji.width - x, st::rbEmoji.height);
|
||||
if (rtl()) clip.moveLeft(width() - x - clip.width());
|
||||
p.setClipRect(clip);
|
||||
|
||||
i += _iconsX.current() / int(st::rbEmoji.width);
|
||||
x -= _iconsX.current() % int(st::rbEmoji.width);
|
||||
for (int32 l = qMin(_icons.size(), i + 8 + (_icons.at(0).sticker ? 1 : 0)); i < l; ++i) {
|
||||
for (int32 l = qMin(_icons.size(), i + 7 + (_icons.at(0).sticker ? 1 : 0)); i < l; ++i) {
|
||||
const StickerIcon &s(_icons.at(i));
|
||||
s.sticker->thumb->load();
|
||||
QPixmap pix(s.sticker->thumb->pix(s.pixw, s.pixh));
|
||||
|
@ -2028,7 +2070,7 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
|
|||
float64 o_right = snap(float64(_iconsMax - _iconsX.current()) / st::stickerIconRight.pxWidth(), 0., 1.);
|
||||
if (o_right > 0) {
|
||||
p.setOpacity(o_right);
|
||||
p.drawSpriteRight(QRect(width() - _iconsLeft - 8 * st::rbEmoji.width, _iconsTop, st::stickerIconRight.pxWidth(), st::rbEmoji.height), width(), st::stickerIconRight);
|
||||
p.drawSpriteRight(QRect(width() - _iconsLeft - 7 * st::rbEmoji.width, _iconsTop, st::stickerIconRight.pxWidth(), st::rbEmoji.height), width(), st::stickerIconRight);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2100,27 +2142,31 @@ void EmojiPan::otherLeave() {
|
|||
}
|
||||
|
||||
void EmojiPan::mousePressEvent(QMouseEvent *e) {
|
||||
if (!_stickersShown || _icons.isEmpty()) return;
|
||||
if (!_stickersShown) return;
|
||||
_iconsMousePos = e ? e->globalPos() : QCursor::pos();
|
||||
updateSelected();
|
||||
|
||||
_iconDown = _iconOver;
|
||||
_iconsMouseDown = _iconsMousePos;
|
||||
_iconsStartX = _iconsX.current();
|
||||
if (_iconOver == _icons.size()) {
|
||||
App::showLayer(new StickersBox());
|
||||
} else {
|
||||
_iconDown = _iconOver;
|
||||
_iconsMouseDown = _iconsMousePos;
|
||||
_iconsStartX = _iconsX.current();
|
||||
}
|
||||
}
|
||||
|
||||
void EmojiPan::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (!_stickersShown || _icons.isEmpty()) return;
|
||||
if (!_stickersShown) return;
|
||||
_iconsMousePos = e ? e->globalPos() : QCursor::pos();
|
||||
updateSelected();
|
||||
|
||||
if (!_iconsDragging && _iconDown >= (_icons.at(0).sticker ? 0 : 1)) {
|
||||
if (!_iconsDragging && !_icons.isEmpty() && _iconDown >= (_icons.at(0).sticker ? 0 : 1)) {
|
||||
if ((_iconsMousePos - _iconsMouseDown).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
_iconsDragging = true;
|
||||
}
|
||||
}
|
||||
if (_iconsDragging) {
|
||||
int32 newX = snap(_iconsStartX + _iconsMouseDown.x() - _iconsMousePos.x(), 0, _iconsMax);
|
||||
int32 newX = snap(_iconsStartX + (rtl() ? -1 : 1) * (_iconsMouseDown.x() - _iconsMousePos.x()), 0, _iconsMax);
|
||||
if (newX != _iconsX.current()) {
|
||||
_iconsX = anim::ivalue(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
|
@ -2150,7 +2196,7 @@ void EmojiPan::mouseReleaseEvent(QMouseEvent *e) {
|
|||
} else {
|
||||
updateSelected();
|
||||
|
||||
if (wasDown == _iconOver && _iconOver >= 0) {
|
||||
if (wasDown == _iconOver && _iconOver >= 0 && _iconOver < _icons.size()) {
|
||||
_iconSelX = anim::ivalue(_iconOver * st::rbEmoji.width, _iconOver * st::rbEmoji.width);
|
||||
s_inner.showStickerSet(_icons.at(_iconOver).setId);
|
||||
}
|
||||
|
@ -2160,7 +2206,7 @@ void EmojiPan::mouseReleaseEvent(QMouseEvent *e) {
|
|||
bool EmojiPan::event(QEvent *e) {
|
||||
if (e->type() == QEvent::TouchBegin) {
|
||||
int a = 0;
|
||||
} else if (e->type() == QEvent::Wheel && _iconOver >= ((_icons.isEmpty() || _icons.at(0).sticker) ? 0 : 1) && _iconDown < 0) {
|
||||
} else if (e->type() == QEvent::Wheel && !_icons.isEmpty() && _iconOver >= (_icons.at(0).sticker ? 0 : 1) && _iconOver < _icons.size() && _iconDown < 0) {
|
||||
QWheelEvent *ev = static_cast<QWheelEvent*>(e);
|
||||
bool hor = (ev->angleDelta().x() != 0 || ev->orientation() == Qt::Horizontal);
|
||||
bool ver = (ev->angleDelta().y() != 0 || ev->orientation() == Qt::Vertical);
|
||||
|
@ -2213,7 +2259,7 @@ void EmojiPan::onRefreshIcons() {
|
|||
_iconsMax = 0;
|
||||
} else {
|
||||
_iconHovers = QVector<float64>(_icons.size(), 0);
|
||||
_iconsMax = qMax(int((_icons.size() - 8) * st::rbEmoji.width), 0);
|
||||
_iconsMax = qMax(int((_icons.size() - 7) * st::rbEmoji.width), 0);
|
||||
}
|
||||
updatePanelsPositions(s_panels, s_scroll.scrollTop());
|
||||
updateSelected();
|
||||
|
@ -2237,23 +2283,29 @@ void EmojiPan::leaveToChildEvent(QEvent *e) {
|
|||
}
|
||||
|
||||
void EmojiPan::updateSelected() {
|
||||
if (_icons.isEmpty() || _iconDown >= 0) return;
|
||||
if (_iconDown >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPoint p(mapFromGlobal(_iconsMousePos));
|
||||
int32 x = p.x(), y = p.y(), newOver = -1;
|
||||
if (rtl()) x = width() - x;
|
||||
x -= _iconsLeft;
|
||||
if (y >= _iconsTop && y < _iconsTop + st::rbEmoji.height && x >= 0 && x < 8 * st::rbEmoji.width && x < _icons.size() * st::rbEmoji.width) {
|
||||
if (!_icons.at(0).sticker) {
|
||||
if (x < st::rbEmoji.width) {
|
||||
newOver = 0;
|
||||
} else {
|
||||
x -= st::rbEmoji.width;
|
||||
if (x >= st::rbEmoji.width * 7 && x < st::rbEmoji.width * 8 && y >= _iconsTop && y < _iconsTop + st::rbEmoji.height) {
|
||||
newOver = _icons.size();
|
||||
} else if (!_icons.isEmpty()) {
|
||||
if (y >= _iconsTop && y < _iconsTop + st::rbEmoji.height && x >= 0 && x < 7 * st::rbEmoji.width && x < _icons.size() * st::rbEmoji.width) {
|
||||
if (!_icons.at(0).sticker) {
|
||||
if (x < st::rbEmoji.width) {
|
||||
newOver = 0;
|
||||
} else {
|
||||
x -= st::rbEmoji.width;
|
||||
}
|
||||
}
|
||||
if (newOver < 0) {
|
||||
x += _iconsX.current();
|
||||
newOver = qFloor(x / st::rbEmoji.width) + (_icons.at(0).sticker ? 0 : 1);
|
||||
}
|
||||
}
|
||||
if (newOver < 0) {
|
||||
x += _iconsX.current();
|
||||
newOver = qFloor(x / st::rbEmoji.width) + (_icons.at(0).sticker ? 0 : 1);
|
||||
}
|
||||
}
|
||||
if (newOver != _iconOver) {
|
||||
|
@ -2263,7 +2315,7 @@ void EmojiPan::updateSelected() {
|
|||
setCursor(style::cur_pointer);
|
||||
}
|
||||
bool startanim = false;
|
||||
if (_iconOver >= 0) {
|
||||
if (_iconOver >= 0 && _iconOver < _icons.size()) {
|
||||
_iconAnimations.remove(_iconOver + 1);
|
||||
if (_iconAnimations.find(-_iconOver - 1) == _iconAnimations.end()) {
|
||||
if (_iconAnimations.isEmpty() && !_iconsStartAnim) startanim = true;
|
||||
|
@ -2271,7 +2323,7 @@ void EmojiPan::updateSelected() {
|
|||
}
|
||||
}
|
||||
_iconOver = newOver;
|
||||
if (_iconOver >= 0) {
|
||||
if (_iconOver >= 0 && _iconOver < _icons.size()) {
|
||||
_iconAnimations.remove(-_iconOver - 1);
|
||||
if (_iconAnimations.find(_iconOver + 1) == _iconAnimations.end()) {
|
||||
if (_iconAnimations.isEmpty() && !_iconsStartAnim) startanim = true;
|
||||
|
@ -2474,10 +2526,10 @@ void EmojiPan::showAll() {
|
|||
_people.hide();
|
||||
_nature.hide();
|
||||
_food.hide();
|
||||
_celebration.hide();
|
||||
_activity.hide();
|
||||
_travel.hide();
|
||||
_objects.hide();
|
||||
_symbols.hide();
|
||||
e_scroll.hide();
|
||||
} else {
|
||||
s_scroll.hide();
|
||||
|
@ -2485,10 +2537,10 @@ void EmojiPan::showAll() {
|
|||
_people.show();
|
||||
_nature.show();
|
||||
_food.show();
|
||||
_celebration.show();
|
||||
_activity.show();
|
||||
_travel.show();
|
||||
_objects.show();
|
||||
_symbols.show();
|
||||
e_scroll.show();
|
||||
}
|
||||
}
|
||||
|
@ -2498,10 +2550,10 @@ void EmojiPan::hideAll() {
|
|||
_people.hide();
|
||||
_nature.hide();
|
||||
_food.hide();
|
||||
_celebration.hide();
|
||||
_activity.hide();
|
||||
_travel.hide();
|
||||
_objects.hide();
|
||||
_symbols.hide();
|
||||
e_scroll.hide();
|
||||
s_scroll.hide();
|
||||
e_inner.clearSelection(true);
|
||||
|
@ -2514,10 +2566,10 @@ void EmojiPan::onTabChange() {
|
|||
if (_people.checked()) newTab = dbietPeople;
|
||||
else if (_nature.checked()) newTab = dbietNature;
|
||||
else if (_food.checked()) newTab = dbietFood;
|
||||
else if (_celebration.checked()) newTab = dbietCelebration;
|
||||
else if (_activity.checked()) newTab = dbietActivity;
|
||||
else if (_travel.checked()) newTab = dbietTravel;
|
||||
else if (_objects.checked()) newTab = dbietObjects;
|
||||
else if (_symbols.checked()) newTab = dbietSymbols;
|
||||
e_inner.showEmojiPack(newTab);
|
||||
}
|
||||
|
||||
|
@ -2540,14 +2592,14 @@ void EmojiPan::onScroll() {
|
|||
DBIEmojiTab tab = e_inner.currentTab(st);
|
||||
FlatRadiobutton *check = 0;
|
||||
switch (tab) {
|
||||
case dbietRecent : check = &_recent ; break;
|
||||
case dbietPeople : check = &_people ; break;
|
||||
case dbietNature : check = &_nature ; break;
|
||||
case dbietFood : check = &_food ; break;
|
||||
case dbietCelebration: check = &_celebration; break;
|
||||
case dbietActivity : check = &_activity ; break;
|
||||
case dbietTravel : check = &_travel ; break;
|
||||
case dbietObjects : check = &_objects ; break;
|
||||
case dbietRecent : check = &_recent ; break;
|
||||
case dbietPeople : check = &_people ; break;
|
||||
case dbietNature : check = &_nature ; break;
|
||||
case dbietFood : check = &_food ; break;
|
||||
case dbietActivity: check = &_activity; break;
|
||||
case dbietTravel : check = &_travel ; break;
|
||||
case dbietObjects : check = &_objects ; break;
|
||||
case dbietSymbols : check = &_symbols ; break;
|
||||
}
|
||||
if (check && !check->checked()) {
|
||||
_noTabUpdate = true;
|
||||
|
@ -2644,8 +2696,9 @@ void EmojiPan::onRemoveSetSure() {
|
|||
}
|
||||
}
|
||||
cRefStickerSets().erase(it);
|
||||
cRefStickerSetsOrder().removeOne(_removingSetId);
|
||||
cSetStickersHash(QByteArray());
|
||||
int32 removeIndex = cStickerSetsOrder().indexOf(_removingSetId);
|
||||
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
||||
cSetStickersHash(stickersCountHash());
|
||||
refreshStickers();
|
||||
Local::writeStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
|
@ -2920,6 +2973,8 @@ _scroll(this, st::mentionScroll), _inner(this, &_rows, &_hrows, &_crows), _chat(
|
|||
connect(&_inner, SIGNAL(chosen(QString)), this, SIGNAL(chosen(QString)));
|
||||
connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int)));
|
||||
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), &_inner, SLOT(update()));
|
||||
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
_scroll.setFocusPolicy(Qt::NoFocus);
|
||||
_scroll.viewport()->setFocusPolicy(Qt::NoFocus);
|
||||
|
@ -2934,7 +2989,7 @@ _scroll(this, st::mentionScroll), _inner(this, &_rows, &_hrows, &_crows), _chat(
|
|||
connect(&_scroll, SIGNAL(geometryChanged()), &_inner, SLOT(onParentGeometryChanged()));
|
||||
connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(onUpdateSelected()));
|
||||
|
||||
if (cPlatform() == dbipMac) {
|
||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -348,6 +348,8 @@ public:
|
|||
public slots:
|
||||
|
||||
void updateSelected();
|
||||
void onSettings();
|
||||
void onPreview();
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -391,6 +393,11 @@ private:
|
|||
|
||||
int32 _selected, _pressedSel;
|
||||
QPoint _lastMousePos;
|
||||
|
||||
LinkButton _settings;
|
||||
|
||||
QTimer _previewTimer;
|
||||
bool _previewShown;
|
||||
};
|
||||
|
||||
class EmojiPanel : public TWidget {
|
||||
|
@ -545,7 +552,7 @@ private:
|
|||
|
||||
BoxShadow _shadow;
|
||||
|
||||
FlatRadiobutton _recent, _people, _nature, _food, _celebration, _activity, _travel, _objects;
|
||||
FlatRadiobutton _recent, _people, _nature, _food, _activity, _travel, _objects, _symbols;
|
||||
QVector<StickerIcon> _icons;
|
||||
QVector<float64> _iconHovers;
|
||||
int32 _iconOver, _iconSel, _iconDown;
|
||||
|
|
109
Telegram/SourceFiles/facades.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mainwidget.h"
|
||||
|
||||
namespace App {
|
||||
|
||||
void sendBotCommand(const QString &cmd, MsgId replyTo) {
|
||||
if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
|
||||
}
|
||||
|
||||
void insertBotCommand(const QString &cmd) {
|
||||
if (MainWidget *m = main()) m->insertBotCommand(cmd);
|
||||
}
|
||||
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer) {
|
||||
if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
|
||||
}
|
||||
|
||||
void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
|
||||
if (MainWidget *m = main()) m->openPeerByName(username, toProfile, startToken);
|
||||
}
|
||||
|
||||
void joinGroupByHash(const QString &hash) {
|
||||
if (MainWidget *m = main()) m->joinGroupByHash(hash);
|
||||
}
|
||||
|
||||
void stickersBox(const QString &name) {
|
||||
if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
|
||||
}
|
||||
|
||||
void openLocalUrl(const QString &url) {
|
||||
if (MainWidget *m = main()) m->openLocalUrl(url);
|
||||
}
|
||||
|
||||
bool forward(const PeerId &peer, ForwardWhatMessages what) {
|
||||
if (MainWidget *m = main()) return m->onForward(peer, what);
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeDialog(History *history) {
|
||||
if (MainWidget *m = main()) m->removeDialog(history);
|
||||
}
|
||||
|
||||
void showSettings() {
|
||||
if (Window *win = wnd()) win->showSettings();
|
||||
}
|
||||
|
||||
void showLayer(LayeredWidget *widget, bool forceFast) {
|
||||
if (Window *w = wnd()) w->showLayer(widget, forceFast);
|
||||
}
|
||||
|
||||
void replaceLayer(LayeredWidget *widget) {
|
||||
if (Window *w = wnd()) w->replaceLayer(widget);
|
||||
}
|
||||
|
||||
void showLayerLast(LayeredWidget *widget) {
|
||||
if (Window *w = wnd()) w->showLayerLast(widget);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Ui {
|
||||
|
||||
void showStickerPreview(DocumentData *sticker) {
|
||||
if (MainWidget *m = App::main()) m->ui_showStickerPreview(sticker);
|
||||
}
|
||||
|
||||
void hideStickerPreview() {
|
||||
if (MainWidget *m = App::main()) m->ui_hideStickerPreview();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Notify {
|
||||
|
||||
void userIsBotChanged(UserData *user) {
|
||||
if (MainWidget *m = App::main()) m->notifyUserIsBotChanged(user);
|
||||
}
|
||||
|
||||
void botCommandsChanged(UserData *user) {
|
||||
if (MainWidget *m = App::main()) m->notifyBotCommandsChanged(user);
|
||||
}
|
||||
|
||||
void migrateUpdated(PeerData *peer) {
|
||||
if (MainWidget *m = App::main()) m->notifyMigrateUpdated(peer);
|
||||
}
|
||||
|
||||
}
|
56
Telegram/SourceFiles/facades.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class LayeredWidget;
|
||||
|
||||
namespace App {
|
||||
|
||||
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
|
||||
void insertBotCommand(const QString &cmd);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
|
||||
void joinGroupByHash(const QString &hash);
|
||||
void stickersBox(const QString &name);
|
||||
void openLocalUrl(const QString &url);
|
||||
bool forward(const PeerId &peer, ForwardWhatMessages what);
|
||||
void removeDialog(History *history);
|
||||
void showSettings();
|
||||
void showLayer(LayeredWidget *w, bool forceFast = false);
|
||||
void replaceLayer(LayeredWidget *w);
|
||||
void showLayerLast(LayeredWidget *w);
|
||||
|
||||
};
|
||||
|
||||
namespace Ui { // it doesn't allow me to use UI :(
|
||||
|
||||
void showStickerPreview(DocumentData *sticker);
|
||||
void hideStickerPreview();
|
||||
|
||||
};
|
||||
|
||||
namespace Notify {
|
||||
|
||||
void userIsBotChanged(UserData *user);
|
||||
void botCommandsChanged(UserData *user);
|
||||
void migrateUpdated(PeerData *peer);
|
||||
|
||||
};
|
|
@ -41,7 +41,7 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
|||
}
|
||||
document->status = FileUploading;
|
||||
if (!media.file.isEmpty()) {
|
||||
document->location = FileLocation(StorageFilePartial, media.file);
|
||||
document->setLocation(FileLocation(StorageFilePartial, media.file));
|
||||
}
|
||||
} else if (media.type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(media.audio);
|
||||
|
@ -64,7 +64,7 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
|
|||
}
|
||||
document->status = FileUploading;
|
||||
if (!file->filepath.isEmpty()) {
|
||||
document->location = FileLocation(StorageFilePartial, file->filepath);
|
||||
document->setLocation(FileLocation(StorageFilePartial, file->filepath));
|
||||
}
|
||||
} else if (file->type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(file->audio);
|
||||
|
|
|
@ -161,10 +161,17 @@ bool AnimatedGif::animStep(float64 ms) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void AnimatedGif::start(HistoryItem *row, const QString &file) {
|
||||
void AnimatedGif::start(HistoryItem *row, const FileLocation &f) {
|
||||
stop();
|
||||
|
||||
reader = new QImageReader(file);
|
||||
file = new FileLocation(f);
|
||||
if (!file->accessEnable()) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
access = true;
|
||||
|
||||
reader = new QImageReader(file->name());
|
||||
if (!reader->canRead() || !reader->supportsAnimation()) {
|
||||
stop();
|
||||
return;
|
||||
|
@ -206,6 +213,15 @@ void AnimatedGif::start(HistoryItem *row, const QString &file) {
|
|||
}
|
||||
|
||||
void AnimatedGif::stop(bool onItemRemoved) {
|
||||
if (file) {
|
||||
if (access) {
|
||||
file->accessDisable();
|
||||
}
|
||||
delete file;
|
||||
file = 0;
|
||||
}
|
||||
access = false;
|
||||
|
||||
if (isNull()) return;
|
||||
|
||||
delete reader;
|
||||
|
|
|
@ -387,17 +387,18 @@ private:
|
|||
};
|
||||
|
||||
class HistoryItem;
|
||||
class FileLocation;
|
||||
class AnimatedGif : public QObject, public Animated {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
AnimatedGif() : msg(0), reader(0), w(0), h(0), frame(0), framesCount(0), duration(0) {
|
||||
AnimatedGif() : msg(0), file(0), access(false), reader(0), w(0), h(0), frame(0), framesCount(0), duration(0) {
|
||||
}
|
||||
|
||||
bool animStep(float64 ms);
|
||||
|
||||
void start(HistoryItem *row, const QString &file);
|
||||
void start(HistoryItem *row, const FileLocation &file);
|
||||
void stop(bool onItemRemoved = false);
|
||||
|
||||
bool isNull() const {
|
||||
|
@ -418,6 +419,8 @@ public:
|
|||
|
||||
HistoryItem *msg;
|
||||
QImage img;
|
||||
FileLocation *file;
|
||||
bool access;
|
||||
QImageReader *reader;
|
||||
int32 w, h, frame;
|
||||
|
||||
|
|
|
@ -151,98 +151,3 @@ private:
|
|||
|
||||
ScrollableBoxShadow _topShadow;
|
||||
};
|
||||
|
||||
/** /
|
||||
class CountryList : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
CountryList(QWidget *parent, const style::countryList &st = st::countryList);
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void enterEvent(QEvent *e);
|
||||
void leaveEvent(QEvent *e);
|
||||
|
||||
void selectSkip(int delta);
|
||||
void selectSkipPage(int h, int delta);
|
||||
|
||||
void updateFiltered();
|
||||
|
||||
QString getSelectedCountry() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void onUpdateSelected(bool force = false);
|
||||
void onParentGeometryChanged();
|
||||
|
||||
signals:
|
||||
|
||||
void countrySelected();
|
||||
void mustScrollTo(int scrollToTop, int scrollToBottom);
|
||||
|
||||
private:
|
||||
|
||||
void resetList();
|
||||
void setSelected(int newSelected);
|
||||
|
||||
int _sel;
|
||||
style::countryList _st;
|
||||
QPoint _mousePos;
|
||||
|
||||
bool _mouseSel;
|
||||
|
||||
};
|
||||
|
||||
class CountrySelect : public QWidget, public Animated {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
CountrySelect();
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
bool animStep(float64 ms);
|
||||
|
||||
~CountrySelect();
|
||||
|
||||
signals:
|
||||
|
||||
void countryChosen(const QString &country = QString());
|
||||
void countryFinished();
|
||||
|
||||
public slots:
|
||||
|
||||
void onParentResize(const QSize &newSize);
|
||||
void onCountryChoose();
|
||||
void onCountryCancel();
|
||||
void onScrollFinished();
|
||||
void onFilterUpdate();
|
||||
|
||||
private:
|
||||
|
||||
void finish(const QString &res);
|
||||
void prepareAnimation(int to);
|
||||
|
||||
QString _result;
|
||||
FlatInput _filter;
|
||||
ScrollArea _scroll;
|
||||
CountryList _list;
|
||||
BoxButton _doneButton, _cancelButton;
|
||||
int32 _innerLeft, _innerTop, _innerWidth, _innerHeight;
|
||||
|
||||
anim::fvalue a_alpha, a_bgAlpha;
|
||||
anim::ivalue a_coord;
|
||||
anim::transition af_alpha, af_bgAlpha, af_coord;
|
||||
QPixmap _cache;
|
||||
|
||||
BoxShadow _shadow;
|
||||
|
||||
};
|
||||
*/
|
|
@ -85,7 +85,7 @@ inline EmojiPtr emojiFromUrl(const QString &url) {
|
|||
|
||||
inline EmojiPtr emojiFromText(const QChar *ch, const QChar *e, int &len) {
|
||||
EmojiPtr emoji = 0;
|
||||
if (ch + 1 < e && ((ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) || (((ch->unicode() >= 48 && ch->unicode() < 58) || ch->unicode() == 35) && (ch + 1)->unicode() == 0x20E3))) {
|
||||
if (ch + 1 < e && ((ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) || (((ch->unicode() >= 0x30 && ch->unicode() < 0x3A) || ch->unicode() == 0x23 || ch->unicode() == 0x2A) && (ch + 1)->unicode() == 0x20E3))) {
|
||||
uint32 code = (ch->unicode() << 16) | (ch + 1)->unicode();
|
||||
emoji = emojiGet(code);
|
||||
if (emoji) {
|
||||
|
@ -105,6 +105,11 @@ inline EmojiPtr emojiFromText(const QChar *ch, const QChar *e, int &len) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (ch + 2 < e && ((ch->unicode() >= 0x30 && ch->unicode() < 0x3A) || ch->unicode() == 0x23 || ch->unicode() == 0x2A) && (ch + 1)->unicode() == 0xFE0F && (ch + 2)->unicode() == 0x20E3) {
|
||||
uint32 code = (ch->unicode() << 16) | (ch + 2)->unicode();
|
||||
emoji = emojiGet(code);
|
||||
len = emoji->len + 1;
|
||||
return emoji;
|
||||
} else if (ch < e) {
|
||||
emoji = emojiGet(ch->unicode());
|
||||
Q_ASSERT(emoji != TwoSymbolEmoji);
|
||||
|
|
|
@ -89,7 +89,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
|||
}
|
||||
return !files.isEmpty();
|
||||
} else if (multipleFiles < -1) {
|
||||
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption);
|
||||
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile);
|
||||
} else if (multipleFiles < 0) {
|
||||
file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||
} else {
|
||||
|
|
|
@ -1180,7 +1180,7 @@ void InputArea::setCtrlEnterSubmit(CtrlEnterSubmit ctrlEnterSubmit) {
|
|||
|
||||
void InputArea::InputAreaInner::keyPressEvent(QKeyEvent *e) {
|
||||
bool shift = e->modifiers().testFlag(Qt::ShiftModifier), alt = e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool macmeta = (cPlatform() == dbipMac) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool macmeta = (cPlatform() == dbipMac || cPlatform() == dbipMacOld) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool ctrl = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier);
|
||||
bool ctrlGood = (ctrl && shift) ||
|
||||
(ctrl && (f()->_ctrlEnterSubmit == CtrlEnterSubmitCtrlEnter || f()->_ctrlEnterSubmit == CtrlEnterSubmitBoth)) ||
|
||||
|
@ -1904,7 +1904,7 @@ void InputField::customUpDown(bool custom) {
|
|||
|
||||
void InputField::InputFieldInner::keyPressEvent(QKeyEvent *e) {
|
||||
bool shift = e->modifiers().testFlag(Qt::ShiftModifier), alt = e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool macmeta = (cPlatform() == dbipMac) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool macmeta = (cPlatform() == dbipMac || cPlatform() == dbipMacOld) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool ctrl = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier), ctrlGood = true;
|
||||
bool enter = (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return);
|
||||
|
||||
|
|
|
@ -860,7 +860,7 @@ void FlatTextarea::setCtrlEnterSubmit(bool ctrlEnterSubmit) {
|
|||
|
||||
void FlatTextarea::keyPressEvent(QKeyEvent *e) {
|
||||
bool shift = e->modifiers().testFlag(Qt::ShiftModifier);
|
||||
bool macmeta = (cPlatform() == dbipMac) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool macmeta = (cPlatform() == dbipMac || cPlatform() == dbipMacOld) && e->modifiers().testFlag(Qt::ControlModifier) && !e->modifiers().testFlag(Qt::MetaModifier) && !e->modifiers().testFlag(Qt::AltModifier);
|
||||
bool ctrl = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::MetaModifier), ctrlGood = (ctrl && _ctrlEnterSubmit) || (!ctrl && !shift && !_ctrlEnterSubmit) || (ctrl && shift);
|
||||
bool enter = (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return);
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "mainwidget.h"
|
||||
#include "localstorage.h"
|
||||
|
||||
#include "pspecific.h"
|
||||
|
||||
namespace {
|
||||
typedef QMap<QString, LocalImage*> LocalImages;
|
||||
LocalImages localImages;
|
||||
|
@ -712,3 +714,82 @@ StorageImage *getImage(const StorageImageLocation &location, const QByteArray &b
|
|||
}
|
||||
return i.value();
|
||||
}
|
||||
|
||||
ReadAccessEnabler::ReadAccessEnabler(const PsFileBookmark *bookmark) : _bookmark(bookmark), _failed(_bookmark ? !_bookmark->enable() : false) {
|
||||
}
|
||||
|
||||
ReadAccessEnabler::ReadAccessEnabler(const QSharedPointer<PsFileBookmark> &bookmark) : _bookmark(bookmark.data()), _failed(_bookmark ? !_bookmark->enable() : false) {
|
||||
}
|
||||
|
||||
ReadAccessEnabler::~ReadAccessEnabler() {
|
||||
if (_bookmark && !_failed) _bookmark->disable();
|
||||
}
|
||||
|
||||
FileLocation::FileLocation(StorageFileType type, const QString &name) : type(type), fname(name) {
|
||||
if (fname.isEmpty()) {
|
||||
size = 0;
|
||||
type = StorageFileUnknown;
|
||||
} else {
|
||||
setBookmark(psPathBookmark(name));
|
||||
|
||||
QFileInfo f(name);
|
||||
if (f.exists()) {
|
||||
qint64 s = f.size();
|
||||
if (s > INT_MAX) {
|
||||
fname = QString();
|
||||
_bookmark.reset(0);
|
||||
size = 0;
|
||||
type = StorageFileUnknown;
|
||||
} else {
|
||||
modified = f.lastModified();
|
||||
size = qint32(s);
|
||||
}
|
||||
} else {
|
||||
fname = QString();
|
||||
_bookmark.reset(0);
|
||||
size = 0;
|
||||
type = StorageFileUnknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FileLocation::check() const {
|
||||
if (fname.isEmpty()) return false;
|
||||
|
||||
ReadAccessEnabler enabler(_bookmark);
|
||||
if (enabler.failed()) {
|
||||
const_cast<FileLocation*>(this)->_bookmark.reset(0);
|
||||
}
|
||||
|
||||
QFileInfo f(name());
|
||||
if (!f.isReadable()) return false;
|
||||
|
||||
quint64 s = f.size();
|
||||
if (s > INT_MAX) return false;
|
||||
|
||||
return (f.lastModified() == modified) && (qint32(s) == size);
|
||||
}
|
||||
|
||||
const QString &FileLocation::name() const {
|
||||
return _bookmark ? _bookmark->name(fname) : fname;
|
||||
}
|
||||
|
||||
QByteArray FileLocation::bookmark() const {
|
||||
return _bookmark ? _bookmark->bookmark() : QByteArray();
|
||||
}
|
||||
|
||||
void FileLocation::setBookmark(const QByteArray &bm) {
|
||||
if (bm.isEmpty()) {
|
||||
_bookmark.reset(0);
|
||||
} else {
|
||||
_bookmark.reset(new PsFileBookmark(bm));
|
||||
}
|
||||
}
|
||||
|
||||
bool FileLocation::accessEnable() const {
|
||||
return isEmpty() ? false : (_bookmark ? _bookmark->enable() : true);
|
||||
}
|
||||
|
||||
void FileLocation::accessDisable() const {
|
||||
return _bookmark ? _bookmark->disable() : (void)0;
|
||||
}
|
||||
|
|
|
@ -240,46 +240,50 @@ void clearStorageImages();
|
|||
void clearAllImages();
|
||||
int64 imageCacheSize();
|
||||
|
||||
struct FileLocation {
|
||||
FileLocation(StorageFileType type, const QString &name, const QDateTime &modified, qint32 size) : type(type), name(name), modified(modified), size(size) {
|
||||
}
|
||||
FileLocation(StorageFileType type, const QString &name) : type(type), name(name) {
|
||||
QFileInfo f(name);
|
||||
if (f.exists()) {
|
||||
qint64 s = f.size();
|
||||
if (s > INT_MAX) {
|
||||
this->name = QString();
|
||||
size = 0;
|
||||
type = StorageFileUnknown;
|
||||
} else {
|
||||
modified = f.lastModified();
|
||||
size = qint32(s);
|
||||
}
|
||||
} else {
|
||||
this->name = QString();
|
||||
size = 0;
|
||||
type = StorageFileUnknown;
|
||||
}
|
||||
class PsFileBookmark;
|
||||
class ReadAccessEnabler {
|
||||
public:
|
||||
ReadAccessEnabler(const PsFileBookmark *bookmark);
|
||||
ReadAccessEnabler(const QSharedPointer<PsFileBookmark> &bookmark);
|
||||
bool failed() const {
|
||||
return _failed;
|
||||
}
|
||||
~ReadAccessEnabler();
|
||||
|
||||
private:
|
||||
const PsFileBookmark *_bookmark;
|
||||
bool _failed;
|
||||
|
||||
};
|
||||
|
||||
class FileLocation {
|
||||
public:
|
||||
FileLocation(StorageFileType type, const QString &name);
|
||||
FileLocation() : size(0) {
|
||||
}
|
||||
bool check() const {
|
||||
if (name.isEmpty()) return false;
|
||||
QFileInfo f(name);
|
||||
if (!f.exists()) return false;
|
||||
|
||||
quint64 s = f.size();
|
||||
if (s > INT_MAX) return false;
|
||||
|
||||
return (f.lastModified() == modified) && (qint32(s) == size);
|
||||
bool check() const;
|
||||
const QString &name() const;
|
||||
void setBookmark(const QByteArray &bookmark);
|
||||
QByteArray bookmark() const;
|
||||
bool isEmpty() const {
|
||||
return name().isEmpty();
|
||||
}
|
||||
|
||||
bool accessEnable() const;
|
||||
void accessDisable() const;
|
||||
|
||||
StorageFileType type;
|
||||
QString name;
|
||||
QString fname;
|
||||
QDateTime modified;
|
||||
qint32 size;
|
||||
|
||||
private:
|
||||
QSharedPointer<PsFileBookmark> _bookmark;
|
||||
|
||||
};
|
||||
inline bool operator==(const FileLocation &a, const FileLocation &b) {
|
||||
return a.type == b.type && a.name == b.name && a.modified == b.modified && a.size == b.size;
|
||||
return a.type == b.type && a.name() == b.name() && a.modified == b.modified && a.size == b.size;
|
||||
}
|
||||
inline bool operator!=(const FileLocation &a, const FileLocation &b) {
|
||||
return !(a == b);
|
||||
|
|
|
@ -545,7 +545,7 @@ public:
|
|||
void parseCurrentChar() {
|
||||
int skipBack = 0;
|
||||
ch = ((ptr < end) ? *ptr : 0);
|
||||
chInt = ch.unicode();
|
||||
emojiLookback = 0;
|
||||
bool skip = false, isNewLine = multiline && chIsNewline(ch), isSpace = chIsSpace(ch), isDiac = chIsDiac(ch), isTilde = checkTilde && (ch == '~');
|
||||
if (chIsBad(ch) || ch.isLowSurrogate()) {
|
||||
skip = true;
|
||||
|
@ -561,15 +561,7 @@ public:
|
|||
skipBack = -1;
|
||||
++ptr;
|
||||
ch = *ptr;
|
||||
chInt = (chInt << 16) | ch.unicode();
|
||||
}
|
||||
} else if ((ch >= 48 && ch < 58) || ch == 35) { // check for digit emoji
|
||||
if (ptr + 1 < end && (ptr + 1)->unicode() == 0x20E3) {
|
||||
_t->_text.push_back(ch);
|
||||
skipBack = -1;
|
||||
++ptr;
|
||||
ch = *ptr;
|
||||
chInt = (chInt << 16) | 0x20E3;
|
||||
emojiLookback = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,11 +593,11 @@ public:
|
|||
}
|
||||
|
||||
void parseEmojiFromCurrent() {
|
||||
int len = 0, skipped = (chInt > 0xFFFFU) ? 1 : 0;
|
||||
EmojiPtr e = emojiFromText(ptr - skipped, end, len);
|
||||
int len = 0;
|
||||
EmojiPtr e = emojiFromText(ptr - emojiLookback, end, len);
|
||||
if (!e) return;
|
||||
|
||||
for (int l = len - skipped - 1; l > 0; --l) {
|
||||
for (int l = len - emojiLookback - 1; l > 0; --l) {
|
||||
_t->_text.push_back(*++ptr);
|
||||
}
|
||||
if (e->postfix && _t->_text.at(_t->_text.size() - 1).unicode() != e->postfix) {
|
||||
|
@ -688,7 +680,7 @@ public:
|
|||
blockStart = 0;
|
||||
emoji = 0;
|
||||
|
||||
ch = chInt = 0;
|
||||
ch = emojiLookback = 0;
|
||||
lastSkipped = false;
|
||||
checkTilde = !cRetina() && _t->_font->size() == 13 && _t->_font->flags() == 0; // tilde Open Sans fix
|
||||
entitiesEnd = entities.cend();
|
||||
|
@ -789,7 +781,7 @@ private:
|
|||
|
||||
// current char data
|
||||
QChar ch; // current char (low surrogate, if current char is surrogate pair)
|
||||
uint32 chInt; // full ch, could be surrogate pair
|
||||
int32 emojiLookback; // how far behind the current ptr to look for current emoji
|
||||
bool lastSkipped; // did we skip current char
|
||||
bool checkTilde; // do we need a special text block for tilde symbol
|
||||
};
|
||||
|
@ -1112,8 +1104,8 @@ public:
|
|||
|
||||
if (_btype == TextBlockTText) {
|
||||
TextBlock *t = static_cast<TextBlock*>(b);
|
||||
QFixed f_wLeft = _wLeft;
|
||||
int32 f_lineHeight = _lineHeight;
|
||||
QFixed f_wLeft = _wLeft; // vars for saving state of the last word start
|
||||
int32 f_lineHeight = _lineHeight; // f points to the last word-start element of t->_words
|
||||
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), en = t->_words.cend(), f = j; j != en; ++j) {
|
||||
bool wordEndsHere = (j->width >= 0);
|
||||
QFixed j_width = wordEndsHere ? j->width : -j->width;
|
||||
|
@ -1131,9 +1123,9 @@ public:
|
|||
longWordLine = false;
|
||||
}
|
||||
if (wordEndsHere || longWordLine) {
|
||||
f = j + 1;
|
||||
f_wLeft = _wLeft;
|
||||
f_lineHeight = _lineHeight;
|
||||
f = j + 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1143,6 +1135,7 @@ public:
|
|||
if (elidedLine) {
|
||||
_lineHeight = elidedLineHeight;
|
||||
} else if (f != j) {
|
||||
// word did not fit completely, so we roll back the state to the beginning of this long word
|
||||
j = f;
|
||||
_wLeft = f_wLeft;
|
||||
_lineHeight = f_lineHeight;
|
||||
|
@ -1166,6 +1159,28 @@ public:
|
|||
f_wLeft = _wLeft;
|
||||
f_lineHeight = _lineHeight;
|
||||
}
|
||||
if (lpadding > 0) { // no words in this block, spaces only
|
||||
int32 elidedLineHeight = qMax(_lineHeight, blockHeight);
|
||||
bool elidedLine = _elideLast && (_y + elidedLineHeight >= _yTo);
|
||||
if (elidedLine) {
|
||||
_lineHeight = elidedLineHeight;
|
||||
}
|
||||
ushort nextStart = _blockEnd(_t, i, e);
|
||||
if (!drawLine(nextStart, i + 1, e)) return;
|
||||
_y += _lineHeight;
|
||||
_lineHeight = qMax(0, blockHeight);
|
||||
_lineStart = nextStart;
|
||||
_lineStartBlock = blockIndex + 1;
|
||||
|
||||
last_rBearing = _rb;
|
||||
last_rPadding = b->rpadding();
|
||||
_wLeft = _w;
|
||||
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yTo)) {
|
||||
_wLeft -= _elideRemoveFromEnd;
|
||||
}
|
||||
|
||||
longWordLine = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2553,7 +2568,7 @@ void Text::setMarkedText(style::font font, const QString &text, const EntitiesIn
|
|||
_font = font;
|
||||
clean();
|
||||
{
|
||||
// QByteArray ba = text.toUtf8();
|
||||
// QByteArray ba = text.toUtf8(); // chars for OS X crash investigation
|
||||
// const char *ch = ba.constData();
|
||||
// LOG(("STR: %1").arg(text));
|
||||
// LOG(("BYTES: %1").arg(mb(ba.constData(), ba.size()).str()));
|
||||
|
@ -2562,6 +2577,36 @@ void Text::setMarkedText(style::font font, const QString &text, const EntitiesIn
|
|||
// }
|
||||
// int32 w = _font->width(text);
|
||||
|
||||
// QString newText; // utf16 of the text for emoji
|
||||
// newText.reserve(8 * text.size());
|
||||
// for (const QChar *ch = text.constData(), *e = ch + text.size(); ch != e; ++ch) {
|
||||
// if (chIsNewline(*ch)) {
|
||||
// newText.append(*ch);
|
||||
// } else {
|
||||
// if (ch->isHighSurrogate() || ch->isLowSurrogate()) {
|
||||
// if (ch->isHighSurrogate() && (ch + 1 != e) && ((ch + 1)->isLowSurrogate())) {
|
||||
// newText.append("0x").append(QString::number((uint32(ch->unicode()) << 16) | uint32((ch + 1)->unicode()), 16).toUpper()).append("LLU,");
|
||||
// ++ch;
|
||||
// } else {
|
||||
// newText.append("BADx").append(QString::number(ch->unicode(), 16).toUpper()).append("LLU,");
|
||||
// }
|
||||
// } else {
|
||||
// newText.append("0x").append(QString::number(ch->unicode(), 16).toUpper()).append("LLU,");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// newText.append("\n\n").append(text);
|
||||
// TextParser parser(this, newText, EntitiesInText(), options);
|
||||
|
||||
// QString newText; // utf8 of the text for emoji sequences
|
||||
// newText.reserve(8 * text.size());
|
||||
// QByteArray ba = text.toUtf8();
|
||||
// for (int32 i = 0, l = ba.size(); i < l; ++i) {
|
||||
// newText.append("\\x").append(QString::number(uchar(ba.at(i)), 16).toLower());
|
||||
// }
|
||||
// newText.append("\n\n").append(text);
|
||||
// TextParser parser(this, newText, EntitiesInText(), options);
|
||||
|
||||
TextParser parser(this, text, entities, options);
|
||||
}
|
||||
recountNaturalSize(true, options.dir);
|
||||
|
|
|
@ -698,7 +698,7 @@ inline bool chIsDiac(QChar ch) { // diac and variation selectors
|
|||
return (ch.category() == QChar::Mark_NonSpacing) || (ch.unicode() == 1652);
|
||||
}
|
||||
inline bool chIsBad(QChar ch) {
|
||||
return (ch == 0) || (ch >= 8232 && ch < 8237) || (ch >= 65024 && ch < 65040 && ch != 65039) || (ch >= 127 && ch < 160 && ch != 156) || (cPlatform() == dbipMac && ch >= 0x0B00 && ch <= 0x0B7F && chIsDiac(ch) && QSysInfo::macVersion() >= QSysInfo::MV_10_11); // tmp hack see https://bugreports.qt.io/browse/QTBUG-48910
|
||||
return (ch == 0) || (ch >= 8232 && ch < 8237) || (ch >= 65024 && ch < 65040 && ch != 65039) || (ch >= 127 && ch < 160 && ch != 156) || (cPlatform() == dbipMac && ch >= 0x0B00 && ch <= 0x0B7F && chIsDiac(ch) && cIsElCapitan()); // tmp hack see https://bugreports.qt.io/browse/QTBUG-48910
|
||||
}
|
||||
inline bool chIsTrimmed(QChar ch, bool rich = false) {
|
||||
return (!rich || ch != TextCommand) && (chIsSpace(ch) || chIsBad(ch));
|
||||
|
|
|
@ -150,7 +150,7 @@ void historyInit() {
|
|||
_initTextOptions();
|
||||
}
|
||||
|
||||
void startGif(HistoryItem *row, const QString &file) {
|
||||
void startGif(HistoryItem *row, const FileLocation &file) {
|
||||
if (row == animated.msg) {
|
||||
stopGif();
|
||||
} else {
|
||||
|
|
|
@ -24,7 +24,7 @@ void historyInit();
|
|||
|
||||
class HistoryItem;
|
||||
|
||||
void startGif(HistoryItem *row, const QString &file);
|
||||
void startGif(HistoryItem *row, const FileLocation &file);
|
||||
void itemRemovedGif(HistoryItem *item);
|
||||
void itemReplacedGif(HistoryItem *oldItem, HistoryItem *newItem);
|
||||
void stopGif();
|
||||
|
|
|
@ -874,6 +874,8 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
isUponSelected = hasSelected;
|
||||
}
|
||||
|
||||
_menu = new PopupMenu();
|
||||
|
||||
_contextMenuLnk = textlnkOver();
|
||||
HistoryItem *item = App::hoveredItem() ? App::hoveredItem() : App::hoveredLinkItem();
|
||||
PhotoLink *lnkPhoto = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
|
||||
|
@ -881,7 +883,6 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
|
||||
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
|
||||
if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument) {
|
||||
_menu = new PopupMenu();
|
||||
if (isUponSelected > 0) {
|
||||
_menu->addAction(lang(lng_context_copy_selected), this, SLOT(copySelectedText()))->setEnabled(true);
|
||||
}
|
||||
|
@ -897,7 +898,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
_menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true);
|
||||
} else {
|
||||
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
|
||||
_menu->addAction(lang(cPlatform() == dbipMac ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
|
||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
|
||||
}
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_open_video : (lnkAudio ? lng_context_open_audio : lng_context_open_file)), this, SLOT(openContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
|
@ -931,59 +932,49 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
HistoryServiceMsg *srv = dynamic_cast<HistoryServiceMsg*>(item);
|
||||
|
||||
if (isUponSelected > 0) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_copy_selected), this, SLOT(copySelectedText()))->setEnabled(true);
|
||||
if (item && item->id > 0 && isUponSelected != 2 && canSendMessages) {
|
||||
_menu->addAction(lang(lng_context_reply_msg), _widget, SLOT(onReplyToMessage()));
|
||||
}
|
||||
} else {
|
||||
if (item && item->id > 0 && isUponSelected != -2 && canSendMessages) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_reply_msg), _widget, SLOT(onReplyToMessage()));
|
||||
}
|
||||
if (item && !isUponSelected && !_contextMenuLnk) {
|
||||
if (HistorySticker *sticker = dynamic_cast<HistorySticker*>(msg ? msg->getMedia() : 0)) {
|
||||
DocumentData *doc = sticker->document();
|
||||
if (doc && doc->sticker() && doc->sticker()->set.type() != mtpc_inputStickerSetEmpty) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(doc->sticker()->setInstalled() ? lng_context_pack_info : lng_context_pack_add), _widget, SLOT(onStickerPackInfo()));
|
||||
}
|
||||
}
|
||||
QString contextMenuText = item->selectedText(FullItemSel);
|
||||
if (!contextMenuText.isEmpty() && (!msg || !msg->getMedia() || msg->getMedia()->type() != MediaTypeSticker)) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_copy_text), this, SLOT(copyContextText()))->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_contextMenuLnk && dynamic_cast<TextLink*>(_contextMenuLnk.data())) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_open_link), this, SLOT(openContextUrl()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_context_copy_link), this, SLOT(copyContextUrl()))->setEnabled(true);
|
||||
} else if (_contextMenuLnk && dynamic_cast<EmailLink*>(_contextMenuLnk.data())) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_open_email), this, SLOT(openContextUrl()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_context_copy_email), this, SLOT(copyContextUrl()))->setEnabled(true);
|
||||
} else if (_contextMenuLnk && dynamic_cast<MentionLink*>(_contextMenuLnk.data())) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_open_mention), this, SLOT(openContextUrl()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_context_copy_mention), this, SLOT(copyContextUrl()))->setEnabled(true);
|
||||
} else if (_contextMenuLnk && dynamic_cast<HashtagLink*>(_contextMenuLnk.data())) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_open_hashtag), this, SLOT(openContextUrl()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_context_copy_hashtag), this, SLOT(copyContextUrl()))->setEnabled(true);
|
||||
} else {
|
||||
}
|
||||
if (isUponSelected > 1) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_forward_selected), _widget, SLOT(onForwardSelected()));
|
||||
if (selectedForDelete == selectedForForward) {
|
||||
_menu->addAction(lang(lng_context_delete_selected), _widget, SLOT(onDeleteSelected()));
|
||||
}
|
||||
_menu->addAction(lang(lng_context_clear_selection), _widget, SLOT(onClearSelected()));
|
||||
} else if (item && ((isUponSelected != -2 && (canForward || canDelete)) || item->id > 0)) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
if (isUponSelected != -2) {
|
||||
if (canForward) {
|
||||
_menu->addAction(lang(lng_context_forward_msg), _widget, SLOT(forwardMessage()))->setEnabled(true);
|
||||
|
@ -998,7 +989,6 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
}
|
||||
} else {
|
||||
if (App::mousedItem() && !App::mousedItem()->serviceMsg() && App::mousedItem()->id > 0) {
|
||||
if (!_menu) _menu = new PopupMenu();
|
||||
_menu->addAction(lang(lng_context_select_msg), _widget, SLOT(selectMessage()))->setEnabled(true);
|
||||
item = App::mousedItem();
|
||||
}
|
||||
|
@ -1006,7 +996,10 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
App::contextItem(item);
|
||||
}
|
||||
|
||||
if (_menu) {
|
||||
if (_menu->actions().isEmpty()) {
|
||||
delete _menu;
|
||||
_menu = 0;
|
||||
} else {
|
||||
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
|
||||
_menu->popup(e->globalPos());
|
||||
e->accept();
|
||||
|
@ -2943,7 +2936,8 @@ void HistoryWidget::updateStickers() {
|
|||
if (cLastStickersUpdate() && getms(true) < cLastStickersUpdate() + StickersUpdateTimeout) return;
|
||||
if (_stickersUpdateRequest) return;
|
||||
|
||||
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_string(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
|
||||
cSetStickersHash(stickersCountHash(true));
|
||||
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(cStickersHash())), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
|
||||
}
|
||||
|
||||
void HistoryWidget::notifyBotCommandsChanged(UserData *user) {
|
||||
|
@ -2993,9 +2987,6 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
|
||||
const QVector<MTPStickerSet> &d_sets(d.vsets.c_vector().v);
|
||||
|
||||
QByteArray wasHash = cStickersHash();
|
||||
cSetStickersHash(qba(d.vhash));
|
||||
|
||||
StickerSetsOrder &setsOrder(cRefStickerSetsOrder());
|
||||
setsOrder.clear();
|
||||
|
||||
|
@ -3008,21 +2999,9 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
if (d_sets.at(i).type() == mtpc_stickerSet) {
|
||||
const MTPDstickerSet &set(d_sets.at(i).c_stickerSet());
|
||||
StickerSets::iterator i = sets.find(set.vid.v);
|
||||
QString title = qs(set.vtitle);
|
||||
if (set.vflags.v & MTPDstickerSet::flag_official) {
|
||||
if (!title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) {
|
||||
title = lang(lng_stickers_default_set);
|
||||
}
|
||||
setsOrder.push_front(set.vid.v);
|
||||
} else {
|
||||
setsOrder.push_back(set.vid.v);
|
||||
}
|
||||
|
||||
QString title = stickerSetTitle(set);
|
||||
if (i == sets.cend()) {
|
||||
i = sets.insert(set.vid.v, StickerSet(set.vid.v, set.vaccess_hash.v, title, qs(set.vshort_name), set.vcount.v, set.vhash.v, set.vflags.v | MTPDstickerSet_flag_NOT_LOADED));
|
||||
if (!(i->flags & MTPDstickerSet::flag_disabled)) {
|
||||
setsToRequest.insert(set.vid.v, set.vaccess_hash.v);
|
||||
}
|
||||
} else {
|
||||
i->access = set.vaccess_hash.v;
|
||||
i->title = title;
|
||||
|
@ -3032,21 +3011,40 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
i->count = set.vcount.v;
|
||||
i->hash = set.vhash.v;
|
||||
i->flags |= MTPDstickerSet_flag_NOT_LOADED; // need to request this set
|
||||
if (!(i->flags & MTPDstickerSet::flag_disabled)) {
|
||||
setsToRequest.insert(set.vid.v, set.vaccess_hash.v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(i->flags & MTPDstickerSet::flag_disabled) || (i->flags & MTPDstickerSet::flag_official)) {
|
||||
setsOrder.push_back(set.vid.v);
|
||||
if (i->stickers.isEmpty() || (i->flags & MTPDstickerSet_flag_NOT_LOADED)) {
|
||||
setsToRequest.insert(set.vid.v, set.vaccess_hash.v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (StickerSets::iterator i = sets.begin(), e = sets.end(); i != e;) {
|
||||
if (i->id == CustomStickerSetId || i->access != 0) {
|
||||
++i;
|
||||
bool writeRecent = false;
|
||||
RecentStickerPack &recent(cGetRecentStickers());
|
||||
for (StickerSets::iterator it = sets.begin(), e = sets.end(); it != e;) {
|
||||
if (it->id == CustomStickerSetId || it->access != 0) {
|
||||
++it;
|
||||
} else {
|
||||
i = sets.erase(i);
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
it = sets.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
int32 countedHash = stickersCountHash();
|
||||
cSetStickersHash(countedHash);
|
||||
if (countedHash != d.vhash.v) {
|
||||
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(countedHash));
|
||||
}
|
||||
|
||||
if (!setsToRequest.isEmpty() && App::api()) {
|
||||
for (QMap<uint64, uint64>::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
|
||||
App::api()->scheduleStickerSetRequest(i.key(), i.value());
|
||||
|
@ -3055,6 +3053,7 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
|
|||
}
|
||||
|
||||
Local::writeStickers();
|
||||
if (writeRecent) Local::writeUserSettings();
|
||||
|
||||
if (App::main()) emit App::main()->stickersUpdated();
|
||||
}
|
||||
|
@ -3217,6 +3216,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
|
||||
if (_history) {
|
||||
_history->draft = _field.getLastText();
|
||||
if (_migrated) _migrated->draft = QString(); // use migrated draft only once
|
||||
_history->draftCursor.fillFrom(_field);
|
||||
_history->draftToId = _replyToId;
|
||||
_history->draftPreviewCancelled = _previewCancelled;
|
||||
|
@ -3326,6 +3326,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
_history->draftCursor = _migrated->draftCursor;
|
||||
_history->draftPreviewCancelled = _migrated->draftPreviewCancelled;
|
||||
_history->draftToId = 0;
|
||||
_migrated->draft = QString(); // use migrated draft only once
|
||||
applyDraft(false);
|
||||
_replyToId = 0;
|
||||
} else {
|
||||
|
@ -4246,7 +4247,7 @@ void HistoryWidget::blockDone(PeerData *peer, const MTPBool &result) {
|
|||
}
|
||||
|
||||
void HistoryWidget::onBotStart() {
|
||||
if (!_peer || !_peer->isUser() || !_peer->asUser()->botInfo) {
|
||||
if (!_peer || !_peer->isUser() || !_peer->asUser()->botInfo || !_canSendMessages) {
|
||||
updateControlsVisibility();
|
||||
return;
|
||||
}
|
||||
|
@ -4813,7 +4814,7 @@ bool HistoryWidget::hasBroadcastToggle() const {
|
|||
}
|
||||
|
||||
bool HistoryWidget::isBotStart() const {
|
||||
if (!_peer || !_peer->isUser() || !_peer->asUser()->botInfo) return false;
|
||||
if (!_peer || !_peer->isUser() || !_peer->asUser()->botInfo || !_canSendMessages) return false;
|
||||
return !_peer->asUser()->botInfo->startToken.isEmpty() || (_history->isEmpty() && !_history->lastMsg);
|
||||
}
|
||||
|
||||
|
@ -5291,11 +5292,12 @@ void HistoryWidget::cancelSendFile(const FileLoadResultPtr &file) {
|
|||
void HistoryWidget::confirmShareContact(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, bool ctrlShiftEnter) {
|
||||
if (!_peer) return;
|
||||
|
||||
PeerId shareToId = _peer->id;
|
||||
if (_confirmWithTextId == 0xFFFFFFFFFFFFFFFFL) {
|
||||
onSend(ctrlShiftEnter, replyTo);
|
||||
_confirmWithTextId = 0;
|
||||
}
|
||||
shareContact(_peer->id, phone, fname, lname, replyTo);
|
||||
shareContact(shareToId, phone, fname, lname, replyTo);
|
||||
}
|
||||
|
||||
void HistoryWidget::cancelShareContact() {
|
||||
|
@ -5893,7 +5895,7 @@ void HistoryWidget::updateBotKeyboard(History *h) {
|
|||
if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == FullMsgId(_channel, _history->lastKeyboardId) && _history->lastKeyboardUsed) {
|
||||
_history->lastKeyboardHiddenId = _history->lastKeyboardId;
|
||||
}
|
||||
if (!isBotStart() && !isBlocked() && (wasVisible || _replyTo || (!_field.hasSendText() && !kbWasHidden()))) {
|
||||
if (!isBotStart() && !isBlocked() && _canSendMessages && (wasVisible || _replyTo || (!_field.hasSendText() && !kbWasHidden()))) {
|
||||
if (!_a_show.animating()) {
|
||||
if (hasMarkup) {
|
||||
_kbScroll.show();
|
||||
|
|
|
@ -85,8 +85,8 @@ QString Translator::translate(const char *context, const char *sourceText, const
|
|||
return QString();
|
||||
}
|
||||
if (qstr("QWidgetTextControl") == context || qstr("QLineEdit") == context) {
|
||||
if (qstr("&Undo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_undo : ((cPlatform() == dbipMac) ? lng_mac_menu_undo : lng_linux_menu_undo));
|
||||
if (qstr("&Redo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_redo : ((cPlatform() == dbipMac) ? lng_mac_menu_redo : lng_linux_menu_redo));
|
||||
if (qstr("&Undo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_undo : ((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_mac_menu_undo : lng_linux_menu_undo));
|
||||
if (qstr("&Redo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_redo : ((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_mac_menu_redo : lng_linux_menu_redo));
|
||||
if (qstr("Cu&t") == sourceText) return lang(lng_mac_menu_cut);
|
||||
if (qstr("&Copy") == sourceText) return lang(lng_mac_menu_copy);
|
||||
if (qstr("&Paste") == sourceText) return lang(lng_mac_menu_paste);
|
||||
|
|
|
@ -431,6 +431,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_channel_add_admins" = "Neuer Administrator";
|
||||
"lng_channel_add_members" = "Mitglieder hinzufügen";
|
||||
"lng_channel_members" = "Mitglieder";
|
||||
"lng_channel_only_last_shown" = "Nur {count:_not_used_|# letztes Mitglied wird angezeigt|letzte # Mitglieder werden angezeigt}";
|
||||
"lng_channel_admins" = "Administratoren";
|
||||
"lng_channel_add_admin" = "Administrator hinzufügen";
|
||||
"lng_channel_admin_sure" = "Soll {user} Administrator werden?";
|
||||
|
@ -564,10 +565,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category1" = "Personen";
|
||||
"lng_emoji_category2" = "Natur";
|
||||
"lng_emoji_category3" = "Essen & Trinken";
|
||||
"lng_emoji_category4" = "Feiern";
|
||||
"lng_emoji_category5" = "Aktivität";
|
||||
"lng_emoji_category6" = "Reisen & Orte";
|
||||
"lng_emoji_category7" = "Objekte & Symbole";
|
||||
"lng_emoji_category4" = "Aktivitäten";
|
||||
"lng_emoji_category5" = "Reisen & Orte";
|
||||
"lng_emoji_category6" = "Objekte";
|
||||
"lng_emoji_category7" = "Symbole & Flaggen";
|
||||
|
||||
"lng_switch_stickers" = "Sticker";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
@ -581,6 +582,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_not_found" = "Sticker-Paket nicht gefunden.";
|
||||
"lng_stickers_copied" = "Sticker-Paket Link in die Zwischenablage kopiert.";
|
||||
"lng_stickers_default_set" = "Große Denker";
|
||||
"lng_stickers_you_have" = "Sticker-Pakete verwalten";
|
||||
"lng_stickers_packs" = "Sticker-Pakete";
|
||||
"lng_stickers_reorder" = "Paket gedrückt halten und verschieben um die Anordnung zu ändern";
|
||||
"lng_stickers_remove" = "Löschen";
|
||||
"lng_stickers_return" = "Rückgängig";
|
||||
"lng_stickers_restore" = "Zeigen";
|
||||
"lng_stickers_count" = "{count:Lade..|# Sticker|# Sticker}";
|
||||
|
||||
"lng_in_dlg_photo" = "Bild";
|
||||
"lng_in_dlg_video" = "Video";
|
||||
|
@ -658,6 +666,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
"lng_choose_images" = "Bilder auswählen";
|
||||
|
||||
"lng_context_view_profile" = "Profil öffnen";
|
||||
"lng_context_view_group" = "Gruppeninfo zeigen";
|
||||
"lng_context_view_channel" = "Kanalinfo anzeigen";
|
||||
|
||||
"lng_context_open_link" = "Link öffnen";
|
||||
"lng_context_copy_link" = "Link kopieren";
|
||||
"lng_context_open_email" = "Email verfassen";
|
||||
|
@ -789,7 +801,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}";
|
||||
"lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen";
|
||||
"lng_new_version_text" = "— Gruppen erlauben ab sofort Administratoren: Diese können den Gruppennamen und das Bild ändern sowie Mitglieder hinzufügen und auch wieder entfernen\n— Gruppen, die das Limit von 200 Mitgliedern erreicht haben, können in eine Supergruppe (1000 Mitglieder) geändert werden\n\nAusführliche Informationen zu den neuen Supergruppen:\n{link}\n\nUnseren deutschsprachigen Infokanal findest du hier: https://telegram.me/TelegramDE";
|
||||
"lng_new_version_text" = "— Sticker-Verwaltung: Ändere die Sortierung deiner Sticker-Pakete, Sortierung wird auf all deinen Geräten synchronisiert \n— Sticker gedrückt halten vor dem Versand für eine Vorschau\n— Neues Kontextmenü für Chats in der Chatliste \n— Neue Emoji werden unterstützt\n\nUnseren deutschsprachigen Infokanal findest du hier: https://telegram.me/TelegramDE";
|
||||
|
||||
"lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen";
|
||||
|
||||
|
|
|
@ -407,10 +407,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_profile_set_group_photo" = "Poner foto";
|
||||
"lng_profile_add_participant" = "Añadir miembros";
|
||||
"lng_profile_delete_and_exit" = "Dejar grupo";
|
||||
"lng_profile_kick" = "Expulsar";
|
||||
"lng_profile_sure_kick" = "¿Expulsar a {user} del grupo?";
|
||||
"lng_profile_sure_kick_channel" = "¿Expulsar a {user} del canal?";
|
||||
"lng_profile_sure_kick_admin" = "¿Expulsar a {user} de los administradores?";
|
||||
"lng_profile_kick" = "Eliminar";
|
||||
"lng_profile_sure_kick" = "¿Eliminar a {user} del grupo?";
|
||||
"lng_profile_sure_kick_channel" = "¿Eliminar a {user} del canal?";
|
||||
"lng_profile_sure_kick_admin" = "¿Eliminar a {user} de los administradores?";
|
||||
"lng_profile_loading" = "Cargando...";
|
||||
"lng_profile_shared_media" = "Multimedia";
|
||||
"lng_profile_no_media" = "No hay multimedia en este chat.";
|
||||
|
@ -431,6 +431,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_channel_add_admins" = "Nuevo administrador";
|
||||
"lng_channel_add_members" = "Añadir miembros";
|
||||
"lng_channel_members" = "Miembros";
|
||||
"lng_channel_only_last_shown" = "Sólo {count:_not_used_|aparece el último miembro|aparecen los últimos # miembros}";
|
||||
"lng_channel_admins" = "Administradores";
|
||||
"lng_channel_add_admin" = "Añadir administrador";
|
||||
"lng_channel_admin_sure" = "¿Añadir a {user} como administrador?";
|
||||
|
@ -438,7 +439,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_chat_all_members_admins" = "Todos son administradores";
|
||||
"lng_chat_about_all_admins" = "Todos pueden añadir nuevos miembros, editar el nombre y la foto del grupo.";
|
||||
"lng_chat_about_admins" = "Sólo los administradores pueden añadir y quitar miembros, editar el nombre y la foto del grupo.";
|
||||
"lng_chat_about_admins" = "Sólo los administradores pueden añadir y eliminar miembros, editar el nombre y la foto del grupo.";
|
||||
|
||||
"lng_participant_filter" = "Buscar";
|
||||
"lng_participant_invite" = "Invitar";
|
||||
|
@ -447,7 +448,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_create_group_next" = "Siguiente";
|
||||
"lng_create_group_create" = "Crear";
|
||||
"lng_create_group_title" = "Nuevo grupo";
|
||||
"lng_create_group_about" = "Los grupos son ideales para las comunidades más pequeñas,\nde hasta {count:_not_used|# miembro|# miembros}";
|
||||
"lng_create_group_about" = "Los grupos son ideales para las comunidades\nmás pequeñas, de hasta {count:_not_used|# miembro|# miembros}";
|
||||
"lng_create_channel_title" = "Nuevo canal";
|
||||
"lng_create_channel_about" = "Los canales permiten difundir tus mensajes a audiencias ilimitadas";
|
||||
"lng_create_public_channel_title" = "Canal público";
|
||||
|
@ -477,9 +478,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_sure_delete_group_history" = "¿Quieres borrar todo el historial en «{group}»?\n\nEsta acción no se puede deshacer.";
|
||||
"lng_sure_delete_and_exit" = "¿Quieres eliminar todo el historial de mensajes y dejar el grupo «{group}»?\n\nEsta acción no se puede deshacer.";
|
||||
"lng_sure_leave_channel" = "¿Quieres dejar este canal?";
|
||||
"lng_sure_delete_channel" = "¿Quieres eliminar este canal? Todos los miembros y mensajes serán eliminados.";
|
||||
"lng_sure_delete_channel" = "¿Quieres eliminar este canal? Todos los miembros y mensajes se perderán.";
|
||||
"lng_sure_leave_group" = "¿Quieres salir del grupo?\nNo puedes deshacer esta acción.";
|
||||
"lng_sure_delete_group" = "¿Quieres eliminar este grupo? Todos los miembros y mensajes serán eliminados.";
|
||||
"lng_sure_delete_group" = "¿Quieres eliminar este grupo? Todos los miembros y mensajes se perderán.";
|
||||
|
||||
"lng_message_empty" = "Mensaje vacío";
|
||||
"lng_media_unsupported" = "Multimedia no soportada";
|
||||
|
@ -492,12 +493,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_action_you_joined" = "Te uniste a este canal";
|
||||
"lng_action_add_you_group" = "{from} te añadió al grupo";
|
||||
"lng_action_you_joined_group" = "Te uniste a este grupo";
|
||||
"lng_action_kick_user" = "{from} expulsó a {user}";
|
||||
"lng_action_kick_user" = "{from} eliminó a {user}";
|
||||
"lng_action_user_left" = "{from} dejó el grupo";
|
||||
"lng_action_user_joined" = "{from} se unió al grupo";
|
||||
"lng_action_user_joined_by_link" = "{from} se unió al grupo con un enlace de invitación";
|
||||
"lng_action_user_registered" = "{from} se acaba de unir a Telegram";
|
||||
"lng_action_removed_photo" = "{from} quitó la foto del grupo";
|
||||
"lng_action_removed_photo" = "{from} eliminó la foto del grupo";
|
||||
"lng_action_removed_photo_channel" = "Foto del canal eliminada";
|
||||
"lng_action_changed_photo" = "{from} actualizó la foto del grupo";
|
||||
"lng_action_changed_photo_channel" = "Foto del canal actualizada";
|
||||
|
@ -564,10 +565,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category1" = "Personas";
|
||||
"lng_emoji_category2" = "Naturaleza";
|
||||
"lng_emoji_category3" = "Comida y bebida";
|
||||
"lng_emoji_category4" = "Celebración";
|
||||
"lng_emoji_category5" = "Actividad";
|
||||
"lng_emoji_category6" = "Viajes y destinos";
|
||||
"lng_emoji_category7" = "Objetos y símbolos";
|
||||
"lng_emoji_category4" = "Actividad";
|
||||
"lng_emoji_category5" = "Viajes y destinos";
|
||||
"lng_emoji_category6" = "Objetos";
|
||||
"lng_emoji_category7" = "Símbolos y banderas";
|
||||
|
||||
"lng_switch_stickers" = "Stickers";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
@ -581,6 +582,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_not_found" = "Pack de stickers no encontrado.";
|
||||
"lng_stickers_copied" = "Enlace del pack de stickers copiado al portapapeles.";
|
||||
"lng_stickers_default_set" = "Grandes personajes";
|
||||
"lng_stickers_you_have" = "Administrar y ordenar los packs de stickers";
|
||||
"lng_stickers_packs" = "Packs de stickers";
|
||||
"lng_stickers_reorder" = "Haz clic y arrastra para ordenar los packs";
|
||||
"lng_stickers_remove" = "Eliminar";
|
||||
"lng_stickers_return" = "Deshacer";
|
||||
"lng_stickers_restore" = "Restaurar";
|
||||
"lng_stickers_count" = "{count:Cargando...|# sticker|# stickers}";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
"lng_in_dlg_video" = "Vídeo";
|
||||
|
@ -658,6 +666,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
"lng_choose_images" = "Elegir imágenes";
|
||||
|
||||
"lng_context_view_profile" = "Ver información";
|
||||
"lng_context_view_group" = "Ver información";
|
||||
"lng_context_view_channel" = "Ver información";
|
||||
|
||||
"lng_context_open_link" = "Abrir enlace";
|
||||
"lng_context_copy_link" = "Copiar enlace";
|
||||
"lng_context_open_email" = "Escribir a esta dirección";
|
||||
|
@ -789,7 +801,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram Desktop ha sido actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}";
|
||||
"lng_new_version_minor" = "— Corrección de errores y otras mejoras menores";
|
||||
"lng_new_version_text" = "– Los grupos ahora pueden tener múltiples administradores, con la habilidad de editar el nombre y foto de perfil, además de añadir y quitar miembros\n– Los grupos que alcanzan la capacidad de 200 usuarios pueden convertirse en supergrupos, que permiten hasta 1000 miembros\n\nMás sobre los administradores y supergrupos:\n{link}";
|
||||
"lng_new_version_text" = "— Administra los stickers: ordena manualmente tus packs de stickers. El orden de los packs se sincronizará en todos tus dispositivos \n— Haz clic y mantén en un sticker para ver una vista previa antes de enviar\n— Nuevo menú contextual para los chats en la lista de chats \n— Soporte de todos los emojis existentes";
|
||||
|
||||
"lng_menu_insert_unicode" = "Insertar caracteres de control Unicode";
|
||||
|
||||
|
|
|
@ -431,6 +431,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_channel_add_admins" = "Nuovo amministratore";
|
||||
"lng_channel_add_members" = "Aggiungi membri";
|
||||
"lng_channel_members" = "Membri";
|
||||
"lng_channel_only_last_shown" = "Solo {count:_not_used_|l'ultimo membro è mostrato|gli ultimi # membri sono mostrati} qui";
|
||||
"lng_channel_admins" = "Amministratori";
|
||||
"lng_channel_add_admin" = "Aggiungi amministratore";
|
||||
"lng_channel_admin_sure" = "Aggiungere {user} agli amministratori?";
|
||||
|
@ -564,10 +565,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category1" = "Persone";
|
||||
"lng_emoji_category2" = "Natura";
|
||||
"lng_emoji_category3" = "Cibo e bevande";
|
||||
"lng_emoji_category4" = "Festeggiamenti";
|
||||
"lng_emoji_category5" = "Attività";
|
||||
"lng_emoji_category6" = "Viaggi e luoghi";
|
||||
"lng_emoji_category7" = "Oggetti e simboli";
|
||||
"lng_emoji_category4" = "Attività";
|
||||
"lng_emoji_category5" = "Viaggi e luoghi";
|
||||
"lng_emoji_category6" = "Oggetti";
|
||||
"lng_emoji_category7" = "Simboli e bandiere";
|
||||
|
||||
"lng_switch_stickers" = "Sticker";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
@ -578,9 +579,16 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_remove_pack" = "Rimuovere «{sticker_pack}»?";
|
||||
"lng_stickers_add_pack" = "Aggiungi sticker";
|
||||
"lng_stickers_share_pack" = "Condividi sticker";
|
||||
"lng_stickers_not_found" = "Pacchetto di sticker non trovato.";
|
||||
"lng_stickers_not_found" = "Set di sticker non trovato.";
|
||||
"lng_stickers_copied" = "Link degli sticker copiato negli appunti.";
|
||||
"lng_stickers_default_set" = "Grandi menti";
|
||||
"lng_stickers_you_have" = "Organizza e riordina i set di sticker";
|
||||
"lng_stickers_packs" = "Set di sticker";
|
||||
"lng_stickers_reorder" = "Clicca e tieni premuto per riordinare i set di sticker";
|
||||
"lng_stickers_remove" = "Elimina";
|
||||
"lng_stickers_return" = "Annulla";
|
||||
"lng_stickers_restore" = "Ripristina";
|
||||
"lng_stickers_count" = "{count:Caricamento..|# sticker|# sticker}";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
"lng_in_dlg_video" = "Video";
|
||||
|
@ -658,6 +666,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
"lng_choose_images" = "Scegli immagini";
|
||||
|
||||
"lng_context_view_profile" = "Visualizza profilo";
|
||||
"lng_context_view_group" = "Visualizza info gruppo";
|
||||
"lng_context_view_channel" = "Visualizza info canale";
|
||||
|
||||
"lng_context_open_link" = "Apri link";
|
||||
"lng_context_copy_link" = "Copia link";
|
||||
"lng_context_open_email" = "Scrivi a questo indirizzo";
|
||||
|
@ -789,7 +801,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli aggiornamenti è disponibile qui:\n{link}";
|
||||
"lng_new_version_minor" = "— Bug fix e altri miglioramenti minori";
|
||||
"lng_new_version_text" = "— I gruppi ora possono avere più amministratori con la possibilità di cambiare il nome e l'immagine, e di aggiungere e rimuovere membri\n— I gruppi che hanno raggiunto i 200 membri possono essere aggiornati a supergruppi e avere fino a 1000 membri\n\nPiù info su amministratori e supergruppi:\n{link}";
|
||||
"lng_new_version_text" = "— Gestione degli sticker: Riordina manualmente i tuoi set di sticker, ora sono sincronizzati tra i tuoi dispositivi\n— Clicca e tieni premuto su uno sticker per visualizzare l'anteprima prima di inviarlo\n— Nuovo menu contestuale per le chat nella lista chat\n— Tutte le nuove emoji ora sono supportate";
|
||||
|
||||
"lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode";
|
||||
|
||||
|
|
|
@ -431,6 +431,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_channel_add_admins" = "새로운 관리자";
|
||||
"lng_channel_add_members" = "구성원 추가";
|
||||
"lng_channel_members" = "구성원";
|
||||
"lng_channel_only_last_shown" = "마지막 {count:_not_used_|# 구성원|# 구성원} 들이 표시가 됩니다.";
|
||||
"lng_channel_admins" = "관리자";
|
||||
"lng_channel_add_admin" = "관리자 추가";
|
||||
"lng_channel_admin_sure" = "{user}를 관리자로 추가하시겠습니까?";
|
||||
|
@ -564,10 +565,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category1" = "사람";
|
||||
"lng_emoji_category2" = "자연";
|
||||
"lng_emoji_category3" = "음식점";
|
||||
"lng_emoji_category4" = "기념일";
|
||||
"lng_emoji_category5" = "활동";
|
||||
"lng_emoji_category6" = "여행 및 장소";
|
||||
"lng_emoji_category7" = "오브제 & 상징";
|
||||
"lng_emoji_category4" = "활동";
|
||||
"lng_emoji_category5" = "여행 및 장소";
|
||||
"lng_emoji_category6" = "물건";
|
||||
"lng_emoji_category7" = "심볼 및 국기";
|
||||
|
||||
"lng_switch_stickers" = "스티커";
|
||||
"lng_switch_emoji" = "이모티콘";
|
||||
|
@ -581,6 +582,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_not_found" = "스티커 팩을 찾을 수 없습니다.";
|
||||
"lng_stickers_copied" = "클립보드에 스티커 팩 링크가 복사 되었습니다.";
|
||||
"lng_stickers_default_set" = "Great Minds";
|
||||
"lng_stickers_you_have" = "스티커팩 관리 및 변경";
|
||||
"lng_stickers_packs" = "스티커팩";
|
||||
"lng_stickers_reorder" = "클릭과 드래그를 통하여 스태커 팩을 변경하세요";
|
||||
"lng_stickers_remove" = "삭제";
|
||||
"lng_stickers_return" = "실행취소";
|
||||
"lng_stickers_restore" = "복구";
|
||||
"lng_stickers_count" = "{count:Loading..|# 스티커|# 스티커} ";
|
||||
|
||||
"lng_in_dlg_photo" = "사진";
|
||||
"lng_in_dlg_video" = "비디오";
|
||||
|
@ -658,6 +666,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
"lng_choose_images" = "이미지 선택";
|
||||
|
||||
"lng_context_view_profile" = "프로필 보기";
|
||||
"lng_context_view_group" = "그룹 정보 보기";
|
||||
"lng_context_view_channel" = "채널 정보 보기";
|
||||
|
||||
"lng_context_open_link" = "링크 열기";
|
||||
"lng_context_copy_link" = "링크 복사";
|
||||
"lng_context_open_email" = "이 주소로 메시지 보내기";
|
||||
|
@ -789,7 +801,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}";
|
||||
"lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상";
|
||||
"lng_new_version_text" = "— 그룹방은 이름,로고, 초대등이 가능한 여러 관리자 설정 가능\n— 기존 200명까지 허용 가능한 그룹방은 슈퍼그룹방으로 업그레이드를 하여 1,000명까지 허용 가능\n\n관리자 및 슈퍼그룹방에 대하여:\n{link}";
|
||||
"lng_new_version_text" = "— 스티커관리 : 스티커팩을 순서를 수동으로 변경하여, 연결된 모든 기기에 동기화 \n— 스티커를 지속하여 누를 경우 전송전 프리뷰 기능 추가\n— 채팅목록에 채팅관련 메뉴 추가\n— 기존 이모티콘 지원";
|
||||
|
||||
"lng_menu_insert_unicode" = "유니코드 문자를 입력하세요.";
|
||||
|
||||
|
|
|
@ -431,6 +431,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_channel_add_admins" = "Beheerder toevoegen";
|
||||
"lng_channel_add_members" = "Deelnemers toevoegen";
|
||||
"lng_channel_members" = "Deelnemers";
|
||||
"lng_channel_only_last_shown" = "De laatste {count:_not_used_|# deelnemer|# deelnemers} worden hier weergegeven";
|
||||
"lng_channel_admins" = "Beheerders";
|
||||
"lng_channel_add_admin" = "Beheerder toevoegen";
|
||||
"lng_channel_admin_sure" = "{user} aan beheerders toevoegen?";
|
||||
|
@ -564,10 +565,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category1" = "Mensen";
|
||||
"lng_emoji_category2" = "Natuur";
|
||||
"lng_emoji_category3" = "Eten & drinken";
|
||||
"lng_emoji_category4" = "Feestelijkheid";
|
||||
"lng_emoji_category5" = "Activiteit";
|
||||
"lng_emoji_category6" = "Reizen & plekken";
|
||||
"lng_emoji_category7" = "Objecten & symbolen";
|
||||
"lng_emoji_category4" = "Activiteit";
|
||||
"lng_emoji_category5" = "Reizen & plekken";
|
||||
"lng_emoji_category6" = "Objecten";
|
||||
"lng_emoji_category7" = "Symbolen en vlaggen";
|
||||
|
||||
"lng_switch_stickers" = "Stickers";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
@ -581,6 +582,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_not_found" = "Stickerbundel niet gevonden.";
|
||||
"lng_stickers_copied" = "Stickerbundel-link gekopieerd naar klembord";
|
||||
"lng_stickers_default_set" = "Grote geesten";
|
||||
"lng_stickers_you_have" = "Beheer en sorteer stickerbundels";
|
||||
"lng_stickers_packs" = "Stickerbundels";
|
||||
"lng_stickers_reorder" = "Klik en sleep om stickerbundels te herschikken";
|
||||
"lng_stickers_remove" = "Verwijder";
|
||||
"lng_stickers_return" = "Ongedaan maken";
|
||||
"lng_stickers_restore" = "Herstellen";
|
||||
"lng_stickers_count" = "{count:Laden..|# sticker|# stickers}";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
"lng_in_dlg_video" = "Video";
|
||||
|
@ -658,6 +666,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
"lng_choose_images" = "Afbeeldingen kiezen";
|
||||
|
||||
"lng_context_view_profile" = "Profiel weergeven";
|
||||
"lng_context_view_group" = "Groepsinformatie weergeven";
|
||||
"lng_context_view_channel" = "Kanaalinformatie weergeven";
|
||||
|
||||
"lng_context_open_link" = "Link openen";
|
||||
"lng_context_copy_link" = "Link kopiëren";
|
||||
"lng_context_open_email" = "Naar dit adres sturen";
|
||||
|
@ -789,7 +801,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
|
||||
"lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen";
|
||||
"lng_new_version_text" = "— Meerdere beheerders in groepen, naast het wijzigen van de groepsnaam en afbeelding kunnen beheerders ook leden toevoegen en verwijderen.\n— Groepen die de limiet van 200 deelnemers hebben bereikt kunnen worden opgewaardeerd naar supergroepen met maximaal 1000 deelnemers.\n\nMeer informatie over supergroepen en de andere nieuwe functies is hier te vinden: \n{link}";
|
||||
"lng_new_version_text" = "— Stickerbeheer: Je kunt nu handmatig je stickerbundels sorteren, de volgorde synchroniseren we voor je, over al je apparaten.\n— Klik en hou een sticker vast om een voorbeeld weer te geven voor het versturen.\n— Nieuw contextmenu voor chats in het chats-overzicht\n— Ondersteuning voor alle bestaande emoji";
|
||||
|
||||
"lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen";
|
||||
|
||||
|
|
|
@ -431,6 +431,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_channel_add_admins" = "Novo administrador";
|
||||
"lng_channel_add_members" = "Adicionar membros";
|
||||
"lng_channel_members" = "Membros";
|
||||
"lng_channel_only_last_shown" = "Somente os últimos {count:_not_used_|# membro é|# membros são} exibidos";
|
||||
"lng_channel_admins" = "Administradores";
|
||||
"lng_channel_add_admin" = "Adicionar Administrador";
|
||||
"lng_channel_admin_sure" = "Adicionar {user} aos administradores?";
|
||||
|
@ -510,7 +511,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_profile_migrate_reached" = "{count:_not_used_|# membro|# membros} limite alcançado";
|
||||
"lng_profile_migrate_about" = "Se você deseja ir além do limite, pode converter seu grupo em um supergrupo. Nos supergrupos:";
|
||||
"lng_profile_migrate_feature1" = "— O limite de membros são {count:_not_used_|# usuário|# usuários}";
|
||||
"lng_profile_migrate_feature2" = "— Novos membros podem ver o histórico completo do chat";
|
||||
"lng_profile_migrate_feature2" = "— Novos membros podem ver todo o histórico";
|
||||
"lng_profile_migrate_feature3" = "— Administradores podem apagar mensagens para todos";
|
||||
"lng_profile_migrate_feature4" = "— Notificações silenciadas por padrão";
|
||||
"lng_profile_migrate_button" = "Atualizar para supergrupo";
|
||||
|
@ -564,10 +565,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category1" = "Pessoas";
|
||||
"lng_emoji_category2" = "Natureza";
|
||||
"lng_emoji_category3" = "Comidas e Bebidas";
|
||||
"lng_emoji_category4" = "Celebração";
|
||||
"lng_emoji_category5" = "Atividade";
|
||||
"lng_emoji_category6" = "Viagens e Lugares";
|
||||
"lng_emoji_category7" = "Objetos e Símbolos";
|
||||
"lng_emoji_category4" = "Atividade";
|
||||
"lng_emoji_category5" = "Viagens e Lugares";
|
||||
"lng_emoji_category6" = "Objetos";
|
||||
"lng_emoji_category7" = "Símbolos e Bandeiras";
|
||||
|
||||
"lng_switch_stickers" = "Stickers";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
@ -581,6 +582,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_not_found" = "Pacote de sticker não encontrado.";
|
||||
"lng_stickers_copied" = "Link copiado para a área de transferência.";
|
||||
"lng_stickers_default_set" = "Grandes Mentes";
|
||||
"lng_stickers_you_have" = "Gerenciar e reordenar os pacotes de sticker";
|
||||
"lng_stickers_packs" = "Pacotes de Sticker";
|
||||
"lng_stickers_reorder" = "Clique e arraste para reordenar os pacotes";
|
||||
"lng_stickers_remove" = "Remover";
|
||||
"lng_stickers_return" = "Desfazer";
|
||||
"lng_stickers_restore" = "Restaurar";
|
||||
"lng_stickers_count" = "{count:Carregando..|# sticker|# stickers}";
|
||||
|
||||
"lng_in_dlg_photo" = "Foto";
|
||||
"lng_in_dlg_video" = "Vídeo";
|
||||
|
@ -658,6 +666,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
"lng_choose_images" = "Escolher imagens";
|
||||
|
||||
"lng_context_view_profile" = "Ver perfil";
|
||||
"lng_context_view_group" = "Ver info do grupo";
|
||||
"lng_context_view_channel" = "Ver info do canal";
|
||||
|
||||
"lng_context_open_link" = "Abrir Link";
|
||||
"lng_context_copy_link" = "Copiar Link";
|
||||
"lng_context_open_email" = "Escrever para este endereço";
|
||||
|
@ -789,7 +801,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}";
|
||||
"lng_new_version_minor" = "— Resolução de bugs e outras melhorias menores";
|
||||
"lng_new_version_text" = "— Grupos agora podem ter múltiplos administradores com a habilidade de editar o nome e o logo, além de adicionar e remover membros\n— Grupos que ultrapassarem o limite dos 200 usuários poderão atualizar para supergrupos e ter até 1.000 membros\n\nMais sobre administradores e supergrupos:\n{link}";
|
||||
"lng_new_version_text" = "— Gerenciamento de stickers: rearranje manualmente seus pacotes de sticker, a ordem dos pacotes agora é sincronizada entre todos os dispositivos\n— Clique e segure sobre um sticker para pré-visualizar antes de enviar\n— Novo menu de contexto para os chats na lista de chats \n— Suporte para todos os emojis existentes";
|
||||
|
||||
"lng_menu_insert_unicode" = "Inserir caractere de controle Unicode";
|
||||
|
||||
|
|
|
@ -27,8 +27,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "mainwidget.h"
|
||||
#include "gui/filedialog.h"
|
||||
|
||||
BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : QWidget(parent), w(w),
|
||||
aBackground(0), aBackgroundFunc(anim::easeOutCirc), hiding(false), shadow(st::boxShadow) {
|
||||
BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : TWidget(parent)
|
||||
, w(w)
|
||||
, aBackground(0)
|
||||
, aBackgroundFunc(anim::easeOutCirc)
|
||||
, hiding(false)
|
||||
, shadow(st::boxShadow) {
|
||||
w->setParent(this);
|
||||
if (App::app()) App::app()->mtpPause();
|
||||
setGeometry(0, 0, App::wnd()->width(), App::wnd()->height());
|
||||
|
@ -189,3 +193,115 @@ BackgroundWidget::~BackgroundWidget() {
|
|||
(*i)->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
StickerPreviewWidget::StickerPreviewWidget(QWidget *parent) : TWidget(parent)
|
||||
, a_shown(0, 0)
|
||||
, _a_shown(animFunc(this, &StickerPreviewWidget::animStep_shown))
|
||||
, _doc(0)
|
||||
, _cacheStatus(CacheNotLoaded) {
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
void StickerPreviewWidget::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
QRect r(e->rect());
|
||||
|
||||
const QPixmap &draw(currentImage());
|
||||
uint32 w = draw.width() / cIntRetinaFactor(), h = draw.height() / cIntRetinaFactor();
|
||||
if (_a_shown.animating()) {
|
||||
float64 shown = a_shown.current();
|
||||
p.setOpacity(shown);
|
||||
// w = qMax(qRound(w * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(w % 2), 1);
|
||||
// h = qMax(qRound(h * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(h % 2), 1);
|
||||
}
|
||||
p.fillRect(r, st::stickerPreviewBg);
|
||||
p.drawPixmap((width() - w) / 2, (height() - h) / 2, draw);
|
||||
}
|
||||
|
||||
void StickerPreviewWidget::resizeEvent(QResizeEvent *e) {
|
||||
update();
|
||||
}
|
||||
|
||||
bool StickerPreviewWidget::animStep_shown(float64 ms) {
|
||||
float64 dt = ms / st::stickerPreviewDuration;
|
||||
if (dt >= 1) {
|
||||
a_shown.finish();
|
||||
_a_shown.stop();
|
||||
if (a_shown.current() < 0.5) hide();
|
||||
} else {
|
||||
a_shown.update(dt, anim::linear);
|
||||
}
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
|
||||
void StickerPreviewWidget::showPreview(DocumentData *sticker) {
|
||||
if (sticker && !sticker->sticker()) sticker = 0;
|
||||
if (sticker) {
|
||||
_cache = QPixmap();
|
||||
if (isHidden() || _a_shown.animating()) {
|
||||
if (isHidden()) show();
|
||||
a_shown.start(1);
|
||||
_a_shown.start();
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
} else if (isHidden()) {
|
||||
return;
|
||||
} else {
|
||||
a_shown.start(0);
|
||||
_a_shown.start();
|
||||
}
|
||||
_doc = sticker;
|
||||
_cacheStatus = CacheNotLoaded;
|
||||
}
|
||||
|
||||
void StickerPreviewWidget::hidePreview() {
|
||||
showPreview(0);
|
||||
}
|
||||
|
||||
QSize StickerPreviewWidget::currentDimensions() const {
|
||||
if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
|
||||
|
||||
QSize result(qMax(_doc->dimensions.width(), 1), qMax(_doc->dimensions.height(), 1));
|
||||
if (result.width() > st::maxStickerSize) {
|
||||
result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
|
||||
result.setWidth(st::maxStickerSize);
|
||||
}
|
||||
if (result.height() > st::maxStickerSize) {
|
||||
result.setWidth(qMax(qRound((st::maxStickerSize * result.width()) / result.height()), 1));
|
||||
result.setHeight(st::maxStickerSize);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QPixmap StickerPreviewWidget::currentImage() const {
|
||||
if (_doc && _cacheStatus != CacheLoaded) {
|
||||
bool already = !_doc->already().isEmpty(), hasdata = !_doc->data.isEmpty();
|
||||
if (!_doc->loader && _doc->status != FileFailed && !already && !hasdata) {
|
||||
_doc->save(QString());
|
||||
}
|
||||
if (_doc->sticker()->img->isNull() && (already || hasdata)) {
|
||||
if (already) {
|
||||
_doc->sticker()->img = ImagePtr(_doc->already());
|
||||
} else {
|
||||
_doc->sticker()->img = ImagePtr(_doc->data);
|
||||
}
|
||||
}
|
||||
if (_doc->sticker()->img->isNull()) {
|
||||
if (_cacheStatus != CacheThumbLoaded) {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _doc->thumb->pixBlurred(s.width(), s.height());
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
}
|
||||
} else {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _doc->sticker()->img->pix(s.width(), s.height());
|
||||
_cacheStatus = CacheLoaded;
|
||||
}
|
||||
}
|
||||
return _cache;
|
||||
}
|
||||
|
||||
StickerPreviewWidget::~StickerPreviewWidget() {
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ signals:
|
|||
|
||||
};
|
||||
|
||||
class BackgroundWidget : public QWidget, public Animated {
|
||||
class BackgroundWidget : public TWidget, public Animated {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -104,3 +104,39 @@ private:
|
|||
|
||||
BoxShadow shadow;
|
||||
};
|
||||
|
||||
class StickerPreviewWidget : public TWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
StickerPreviewWidget(QWidget *parent);
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
bool animStep_shown(float64 ms);
|
||||
|
||||
void showPreview(DocumentData *sticker);
|
||||
void hidePreview();
|
||||
|
||||
~StickerPreviewWidget();
|
||||
|
||||
private:
|
||||
|
||||
QSize currentDimensions() const;
|
||||
QPixmap currentImage() const;
|
||||
|
||||
anim::fvalue a_shown;
|
||||
Animation _a_shown;
|
||||
DocumentData *_doc;
|
||||
|
||||
enum CacheStatus {
|
||||
CacheNotLoaded,
|
||||
CacheThumbLoaded,
|
||||
CacheLoaded,
|
||||
};
|
||||
mutable CacheStatus _cacheStatus;
|
||||
mutable QPixmap _cache;
|
||||
|
||||
};
|
||||
|
|
|
@ -579,11 +579,23 @@ namespace {
|
|||
}
|
||||
quint32 size = 0;
|
||||
for (FileLocations::const_iterator i = _fileLocations.cbegin(), e = _fileLocations.cend(); i != e; ++i) {
|
||||
// location + type + namelen + name + date + size
|
||||
size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(i.value().name) + _dateTimeSize() + sizeof(quint32);
|
||||
// location + type + namelen + name
|
||||
size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(i.value().name());
|
||||
if (AppVersion > 9013) {
|
||||
// bookmark
|
||||
size += _bytearraySize(i.value().bookmark());
|
||||
}
|
||||
// date + size
|
||||
size += _dateTimeSize() + sizeof(quint32);
|
||||
}
|
||||
|
||||
//end mark
|
||||
size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(QString()) + _dateTimeSize() + sizeof(quint32);
|
||||
size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(QString());
|
||||
if (AppVersion > 9013) {
|
||||
size += _bytearraySize(QByteArray());
|
||||
}
|
||||
size += _dateTimeSize() + sizeof(quint32);
|
||||
|
||||
size += sizeof(quint32); // aliases count
|
||||
for (FileLocationAliases::const_iterator i = _fileLocationAliases.cbegin(), e = _fileLocationAliases.cend(); i != e; ++i) {
|
||||
// alias + location
|
||||
|
@ -592,9 +604,19 @@ namespace {
|
|||
|
||||
EncryptedDescriptor data(size);
|
||||
for (FileLocations::const_iterator i = _fileLocations.cbegin(); i != _fileLocations.cend(); ++i) {
|
||||
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint32(i.value().type) << i.value().name << i.value().modified << quint32(i.value().size);
|
||||
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint32(i.value().type) << i.value().name();
|
||||
if (AppVersion > 9013) {
|
||||
data.stream << i.value().bookmark();
|
||||
}
|
||||
data.stream << i.value().modified << quint32(i.value().size);
|
||||
}
|
||||
data.stream << quint64(0) << quint64(0) << quint32(0) << QString() << QDateTime::currentDateTime() << quint32(0);
|
||||
|
||||
data.stream << quint64(0) << quint64(0) << quint32(0) << QString();
|
||||
if (AppVersion > 9013) {
|
||||
data.stream << QByteArray();
|
||||
}
|
||||
data.stream << QDateTime::currentDateTime() << quint32(0);
|
||||
|
||||
data.stream << quint32(_fileLocationAliases.size());
|
||||
for (FileLocationAliases::const_iterator i = _fileLocationAliases.cbegin(), e = _fileLocationAliases.cend(); i != e; ++i) {
|
||||
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint64(i.value().first) << quint64(i.value().second);
|
||||
|
@ -617,11 +639,17 @@ namespace {
|
|||
bool endMarkFound = false;
|
||||
while (!locations.stream.atEnd()) {
|
||||
quint64 first, second;
|
||||
QByteArray bookmark;
|
||||
FileLocation loc;
|
||||
quint32 type;
|
||||
locations.stream >> first >> second >> type >> loc.name >> loc.modified >> loc.size;
|
||||
locations.stream >> first >> second >> type >> loc.fname;
|
||||
if (locations.version > 9013) {
|
||||
locations.stream >> bookmark;
|
||||
}
|
||||
locations.stream >> loc.modified >> loc.size;
|
||||
loc.setBookmark(bookmark);
|
||||
|
||||
if (!first && !second && !type && loc.name.isEmpty() && !loc.size) { // end mark
|
||||
if (!first && !second && !type && loc.fname.isEmpty() && !loc.size) { // end mark
|
||||
endMarkFound = true;
|
||||
break;
|
||||
}
|
||||
|
@ -629,12 +657,8 @@ namespace {
|
|||
MediaKey key(first, second);
|
||||
loc.type = StorageFileType(type);
|
||||
|
||||
if (loc.check()) {
|
||||
_fileLocations.insert(key, loc);
|
||||
_fileLocationPairs.insert(loc.name, FileLocationPair(key, loc));
|
||||
} else {
|
||||
_writeLocations();
|
||||
}
|
||||
_fileLocations.insert(key, loc);
|
||||
_fileLocationPairs.insert(loc.fname, FileLocationPair(key, loc));
|
||||
}
|
||||
|
||||
if (endMarkFound) {
|
||||
|
@ -1038,12 +1062,26 @@ namespace {
|
|||
cSetAskDownloadPath(v == 1);
|
||||
} break;
|
||||
|
||||
case dbiDownloadPath: {
|
||||
case dbiDownloadPathOld: {
|
||||
QString v;
|
||||
stream >> v;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
if (!v.isEmpty() && v != qstr("tmp") && !v.endsWith('/')) v += '/';
|
||||
cSetDownloadPath(v);
|
||||
cSetDownloadPathBookmark(QByteArray());
|
||||
} break;
|
||||
|
||||
case dbiDownloadPath: {
|
||||
QString v;
|
||||
QByteArray bookmark;
|
||||
stream >> v >> bookmark;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
if (!v.isEmpty() && v != qstr("tmp") && !v.endsWith('/')) v += '/';
|
||||
cSetDownloadPath(v);
|
||||
cSetDownloadPathBookmark(bookmark);
|
||||
psDownloadPathEnableAccess();
|
||||
} break;
|
||||
|
||||
case dbiCompressPastedImage: {
|
||||
|
@ -1054,22 +1092,12 @@ namespace {
|
|||
cSetCompressPastedImage(v == 1);
|
||||
} break;
|
||||
|
||||
case dbiEmojiTab: {
|
||||
case dbiEmojiTabOld: {
|
||||
qint32 v;
|
||||
stream >> v;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
switch (v) {
|
||||
case dbietRecent : cSetEmojiTab(dbietRecent ); break;
|
||||
case dbietPeople : cSetEmojiTab(dbietPeople ); break;
|
||||
case dbietNature : cSetEmojiTab(dbietNature ); break;
|
||||
case dbietFood : cSetEmojiTab(dbietFood ); break;
|
||||
case dbietCelebration: cSetEmojiTab(dbietCelebration); break;
|
||||
case dbietActivity : cSetEmojiTab(dbietActivity ); break;
|
||||
case dbietTravel : cSetEmojiTab(dbietTravel ); break;
|
||||
case dbietObjects : cSetEmojiTab(dbietObjects ); break;
|
||||
case dbietStickers : cSetEmojiTab(dbietStickers ); break;
|
||||
}
|
||||
// deprecated
|
||||
} break;
|
||||
|
||||
case dbiRecentEmojisOld: {
|
||||
|
@ -1362,7 +1390,7 @@ namespace {
|
|||
}
|
||||
|
||||
uint32 size = 14 * (sizeof(quint32) + sizeof(qint32));
|
||||
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
|
||||
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath()) + _bytearraySize(cAskDownloadPath() ? QByteArray() : cDownloadPathBookmark());
|
||||
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
|
||||
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
|
||||
size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
|
||||
|
@ -1380,9 +1408,8 @@ namespace {
|
|||
data.stream << quint32(dbiNotifyView) << qint32(cNotifyView());
|
||||
data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications());
|
||||
data.stream << quint32(dbiAskDownloadPath) << qint32(cAskDownloadPath());
|
||||
data.stream << quint32(dbiDownloadPath) << (cAskDownloadPath() ? QString() : cDownloadPath());
|
||||
data.stream << quint32(dbiDownloadPath) << (cAskDownloadPath() ? QString() : cDownloadPath()) << (cAskDownloadPath() ? QByteArray() : cDownloadPathBookmark());
|
||||
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
|
||||
data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab());
|
||||
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
|
||||
data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6));
|
||||
|
||||
|
@ -2178,14 +2205,14 @@ namespace Local {
|
|||
}
|
||||
|
||||
void writeFileLocation(MediaKey location, const FileLocation &local) {
|
||||
if (local.name.isEmpty()) return;
|
||||
if (local.fname.isEmpty()) return;
|
||||
|
||||
FileLocationAliases::const_iterator aliasIt = _fileLocationAliases.constFind(location);
|
||||
if (aliasIt != _fileLocationAliases.cend()) {
|
||||
location = aliasIt.value();
|
||||
}
|
||||
|
||||
FileLocationPairs::iterator i = _fileLocationPairs.find(local.name);
|
||||
FileLocationPairs::iterator i = _fileLocationPairs.find(local.fname);
|
||||
if (i != _fileLocationPairs.cend()) {
|
||||
if (i.value().second == local) {
|
||||
if (i.value().first != location) {
|
||||
|
@ -2205,7 +2232,7 @@ namespace Local {
|
|||
}
|
||||
}
|
||||
_fileLocations.insert(location, local);
|
||||
_fileLocationPairs.insert(local.name, FileLocationPair(location, local));
|
||||
_fileLocationPairs.insert(local.fname, FileLocationPair(location, local));
|
||||
_writeLocations(WriteMapFast);
|
||||
}
|
||||
|
||||
|
@ -2218,9 +2245,8 @@ namespace Local {
|
|||
FileLocations::iterator i = _fileLocations.find(location);
|
||||
for (FileLocations::iterator i = _fileLocations.find(location); (i != _fileLocations.end()) && (i.key() == location);) {
|
||||
if (check) {
|
||||
QFileInfo info(i.value().name);
|
||||
if (!info.exists() || info.lastModified() != i.value().modified || info.size() != i.value().size) {
|
||||
_fileLocationPairs.remove(i.value().name);
|
||||
if (!i.value().check()) {
|
||||
_fileLocationPairs.remove(i.value().fname);
|
||||
i = _fileLocations.erase(i);
|
||||
_writeLocations();
|
||||
continue;
|
||||
|
@ -2441,7 +2467,7 @@ namespace Local {
|
|||
|
||||
TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader) {
|
||||
StorageMap::iterator j = _stickerImagesMap.find(location);
|
||||
if (j == _stickerImagesMap.cend()) {
|
||||
if (j == _stickerImagesMap.cend() || !_localLoader) {
|
||||
return 0;
|
||||
}
|
||||
return _localLoader->addTask(new StickerImageLoadTask(j->first, location, loader));
|
||||
|
@ -2500,7 +2526,7 @@ namespace Local {
|
|||
|
||||
TaskId startAudioLoad(const StorageKey &location, mtpFileLoader *loader) {
|
||||
StorageMap::iterator j = _audiosMap.find(location);
|
||||
if (j == _audiosMap.cend()) {
|
||||
if (j == _audiosMap.cend() || !_localLoader) {
|
||||
return 0;
|
||||
}
|
||||
return _localLoader->addTask(new AudioLoadTask(j->first, location, loader));
|
||||
|
@ -2582,11 +2608,12 @@ namespace Local {
|
|||
_writeMap();
|
||||
} else {
|
||||
int32 setsCount = 0;
|
||||
quint32 size = sizeof(quint32) + _bytearraySize(cStickersHash());
|
||||
QByteArray hashToWrite = (qsl("%d:") + QString::number(cStickersHash())).toUtf8();
|
||||
quint32 size = sizeof(quint32) + _bytearraySize(hashToWrite);
|
||||
for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) {
|
||||
bool notLoaded = (i->flags & MTPDstickerSet_flag_NOT_LOADED);
|
||||
if (notLoaded) {
|
||||
if (!(i->flags & MTPDstickerSet::flag_disabled)) { // waiting to receive
|
||||
if (!(i->flags & MTPDstickerSet::flag_disabled) || (i->flags & MTPDstickerSet::flag_official)) { // waiting to receive
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -2613,7 +2640,7 @@ namespace Local {
|
|||
_writeMap(WriteMapFast);
|
||||
}
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << quint32(setsCount) << cStickersHash();
|
||||
data.stream << quint32(setsCount) << hashToWrite;
|
||||
_writeStickerSet(data.stream, CustomStickerSetId);
|
||||
for (StickerSetsOrder::const_iterator i = cStickerSetsOrder().cbegin(), e = cStickerSetsOrder().cend(); i != e; ++i) {
|
||||
_writeStickerSet(data.stream, *i);
|
||||
|
@ -2643,7 +2670,7 @@ namespace Local {
|
|||
RecentStickerPack &recent(cRefRecentStickers());
|
||||
recent.clear();
|
||||
|
||||
cSetStickersHash(QByteArray());
|
||||
cSetStickersHash(0);
|
||||
|
||||
StickerSet &def(sets.insert(DefaultStickerSetId, StickerSet(DefaultStickerSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::flag_official)).value());
|
||||
StickerSet &custom(sets.insert(CustomStickerSetId, StickerSet(CustomStickerSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)).value());
|
||||
|
@ -2801,7 +2828,11 @@ namespace Local {
|
|||
}
|
||||
}
|
||||
|
||||
cSetStickersHash(hash);
|
||||
if (hash.startsWith(qsl("%d:").toUtf8())) {
|
||||
cSetStickersHash(QString::fromUtf8(hash.mid(3)).toInt());
|
||||
} else {
|
||||
cSetStickersHash(0);
|
||||
}
|
||||
}
|
||||
|
||||
void writeBackground(int32 id, const QImage &img) {
|
||||
|
|
|
@ -183,25 +183,63 @@ void logsInit() {
|
|||
static _StreamCreator streamCreator;
|
||||
if (mainLogStream) return;
|
||||
|
||||
QString wasDir = cWorkingDir();
|
||||
QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta"));
|
||||
if (cBetaVersion()) {
|
||||
cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
|
||||
if (*BetaPrivateKey) {
|
||||
cSetBetaPrivateKey(QByteArray(BetaPrivateKey));
|
||||
}
|
||||
if (beta.open(QIODevice::WriteOnly)) {
|
||||
QDataStream dataStream(&beta);
|
||||
dataStream.setVersion(QDataStream::Qt_5_3);
|
||||
dataStream << quint64(cRealBetaVersion()) << cBetaPrivateKey();
|
||||
} else {
|
||||
LOG(("Error: could not open \"beta\" file for writing private key!"));
|
||||
}
|
||||
} else if (beta.exists()) {
|
||||
if (beta.open(QIODevice::ReadOnly)) {
|
||||
QDataStream dataStream(&beta);
|
||||
dataStream.setVersion(QDataStream::Qt_5_3);
|
||||
|
||||
quint64 v;
|
||||
QByteArray k;
|
||||
dataStream >> v >> k;
|
||||
if (dataStream.status() == QDataStream::Ok) {
|
||||
cSetBetaVersion(qMax(v, AppVersion * 1000ULL));
|
||||
cSetBetaPrivateKey(k);
|
||||
cSetRealBetaVersion(v);
|
||||
|
||||
cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cBetaVersion()) {
|
||||
cSetDebug(true);
|
||||
} else {
|
||||
QString wasDir = cWorkingDir();
|
||||
#if (defined Q_OS_MAC || defined Q_OS_LINUX)
|
||||
|
||||
#ifdef _DEBUG
|
||||
cForceWorkingDir(cExeDir());
|
||||
cForceWorkingDir(cExeDir());
|
||||
#else
|
||||
cForceWorkingDir(psAppDataPath());
|
||||
if(cWorkingDir().isEmpty()){
|
||||
cForceWorkingDir(psAppDataPath());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
|
||||
moveOldDataFiles(wasDir);
|
||||
moveOldDataFiles(wasDir);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
QString rightDir = cWorkingDir();
|
||||
cForceWorkingDir(rightDir);
|
||||
mainLog.setFileName(cWorkingDir() + "log.txt");
|
||||
mainLog.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
if (!mainLog.isOpen()) {
|
||||
if (!cBetaVersion() && !mainLog.isOpen()) {
|
||||
cForceWorkingDir(cExeDir());
|
||||
mainLog.setFileName(cWorkingDir() + "log.txt");
|
||||
mainLog.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
|
@ -224,18 +262,23 @@ void logsInit() {
|
|||
cSetTestMode(true);
|
||||
LOG(("Switched to test mode!"));
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (cWorkingDir() == psAppDataPath()) { // fix old "Telegram Win (Unofficial)" version
|
||||
moveOldDataFiles(psAppDataPathOld());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cDebug()) {
|
||||
logsInitDebug();
|
||||
} else if (QFile(cWorkingDir() + qsl("tdata/withdebug")).exists()) {
|
||||
logsInitDebug();
|
||||
cSetDebug(true);
|
||||
}
|
||||
if (!cDevVersion() && QFile(cWorkingDir() + qsl("tdata/devversion")).exists()) {
|
||||
|
||||
if (cBetaVersion()) {
|
||||
cSetDevVersion(false);
|
||||
} else if (!cDevVersion() && QFile(cWorkingDir() + qsl("tdata/devversion")).exists()) {
|
||||
cSetDevVersion(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
if (cRestartingUpdate()) {
|
||||
if (DevVersion) {
|
||||
if (!cBetaVersion() && DevVersion) {
|
||||
LOG(("Writing 'devversion' file before launching the Updater!"));
|
||||
QFile f(cWorkingDir() + qsl("tdata/devversion"));
|
||||
if (!f.exists() && f.open(QIODevice::WriteOnly)) {
|
||||
|
|
|
@ -30,6 +30,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/confirmbox.h"
|
||||
#include "boxes/stickersetbox.h"
|
||||
#include "boxes/contactsbox.h"
|
||||
#include "boxes/downloadpathbox.h"
|
||||
|
||||
#include "localstorage.h"
|
||||
|
||||
|
@ -394,6 +395,7 @@ MainWidget::MainWidget(Window *window) : TWidget(window)
|
|||
, _hider(0)
|
||||
, _peerInStack(0)
|
||||
, _msgIdInStack(0)
|
||||
, _stickerPreview(0)
|
||||
, _playerHeight(0)
|
||||
, _contentScrollAddToY(0)
|
||||
, _mediaType(this)
|
||||
|
@ -743,6 +745,20 @@ QPixmap MainWidget::grabTopBar() {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::ui_showStickerPreview(DocumentData *sticker) {
|
||||
if (!sticker || !sticker->sticker()) return;
|
||||
if (!_stickerPreview) {
|
||||
_stickerPreview = new StickerPreviewWidget(this);
|
||||
resizeEvent(0);
|
||||
}
|
||||
_stickerPreview->showPreview(sticker);
|
||||
}
|
||||
|
||||
void MainWidget::ui_hideStickerPreview() {
|
||||
if (!_stickerPreview) return;
|
||||
_stickerPreview->hidePreview();
|
||||
}
|
||||
|
||||
void MainWidget::noHider(HistoryHider *destroyed) {
|
||||
if (_hider == destroyed) {
|
||||
_hider = 0;
|
||||
|
@ -970,11 +986,17 @@ void MainWidget::addParticipants(PeerData *chatOrChannel, const QVector<UserData
|
|||
}
|
||||
} else if (chatOrChannel->isChannel()) {
|
||||
QVector<MTPInputUser> inputUsers;
|
||||
inputUsers.reserve(users.size());
|
||||
inputUsers.reserve(qMin(users.size(), int(MaxUsersPerInvite)));
|
||||
for (QVector<UserData*>::const_iterator i = users.cbegin(), e = users.cend(); i != e; ++i) {
|
||||
inputUsers.push_back((*i)->inputUser);
|
||||
if (inputUsers.size() == MaxUsersPerInvite) {
|
||||
MTP::send(MTPchannels_InviteToChannel(chatOrChannel->asChannel()->inputChannel, MTP_vector<MTPInputUser>(inputUsers)), rpcDone(&MainWidget::inviteToChannelDone, chatOrChannel->asChannel()), rpcFail(&MainWidget::addParticipantsFail, chatOrChannel->asChannel()), 0, 5);
|
||||
inputUsers.clear();
|
||||
}
|
||||
}
|
||||
if (!inputUsers.isEmpty()) {
|
||||
MTP::send(MTPchannels_InviteToChannel(chatOrChannel->asChannel()->inputChannel, MTP_vector<MTPInputUser>(inputUsers)), rpcDone(&MainWidget::inviteToChannelDone, chatOrChannel->asChannel()), rpcFail(&MainWidget::addParticipantsFail, chatOrChannel->asChannel()), 0, 5);
|
||||
}
|
||||
MTP::send(MTPchannels_InviteToChannel(chatOrChannel->asChannel()->inputChannel, MTP_vector<MTPInputUser>(inputUsers)), rpcDone(&MainWidget::inviteToChannelDone, chatOrChannel->asChannel()), rpcFail(&MainWidget::addParticipantsFail, chatOrChannel->asChannel()), 0, 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1585,6 +1607,7 @@ void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMess
|
|||
void MainWidget::videoLoadProgress(mtpFileLoader *loader) {
|
||||
VideoData *video = App::video(loader->objId());
|
||||
if (video->loader) {
|
||||
video->status = FileReady;
|
||||
if (video->loader->done()) {
|
||||
video->finish();
|
||||
QString already = video->already();
|
||||
|
@ -1614,7 +1637,17 @@ void MainWidget::loadFailed(mtpFileLoader *loader, bool started, const char *ret
|
|||
if (started) {
|
||||
connect(box, SIGNAL(confirmed()), this, retrySlot);
|
||||
} else {
|
||||
connect(box, SIGNAL(confirmed()), App::wnd(), SLOT(showSettings()));
|
||||
connect(box, SIGNAL(confirmed()), this, SLOT(onDownloadPathSettings()));
|
||||
}
|
||||
App::wnd()->showLayer(box);
|
||||
}
|
||||
|
||||
void MainWidget::onDownloadPathSettings() {
|
||||
cSetDownloadPath(QString());
|
||||
cSetDownloadPathBookmark(QByteArray());
|
||||
DownloadPathBox *box = new DownloadPathBox();
|
||||
if (App::wnd() && App::wnd()->settingsWidget()) {
|
||||
connect(box, SIGNAL(closed()), App::wnd()->settingsWidget(), SLOT(onDownloadPathEdited()));
|
||||
}
|
||||
App::wnd()->showLayer(box);
|
||||
}
|
||||
|
@ -1634,6 +1667,7 @@ void MainWidget::videoLoadRetry() {
|
|||
void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
|
||||
AudioData *audio = App::audio(loader->objId());
|
||||
if (audio->loader) {
|
||||
audio->status = FileReady;
|
||||
if (audio->loader->done()) {
|
||||
audio->finish();
|
||||
QString already = audio->already();
|
||||
|
@ -1688,7 +1722,7 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
|||
if (f.write(audio->data) == audio->data.size()) {
|
||||
f.close();
|
||||
already = filename;
|
||||
audio->location = FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename);
|
||||
audio->setLocation(FileLocation(StorageFilePartial, filename));
|
||||
Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), audio->dc, audio->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
|
||||
}
|
||||
}
|
||||
|
@ -1736,7 +1770,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
|||
if (f.write(document->data) == document->data.size()) {
|
||||
f.close();
|
||||
already = filename;
|
||||
document->location = FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename);
|
||||
document->setLocation(FileLocation(StorageFilePartial, filename));
|
||||
Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputDocumentFileLocation), document->dc, document->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
|
||||
}
|
||||
}
|
||||
|
@ -1793,6 +1827,7 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
|||
bool songPlayActivated = false;
|
||||
DocumentData *document = App::document(loader->objId());
|
||||
if (document->loader) {
|
||||
document->status = FileReady;
|
||||
if (document->loader->done()) {
|
||||
document->finish();
|
||||
QString already = document->already();
|
||||
|
@ -1813,16 +1848,22 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
|||
}
|
||||
|
||||
songPlayActivated = true;
|
||||
} else if(document->openOnSave > 0 && document->size < MediaViewImageSizeLimit) {
|
||||
QImageReader reader(already);
|
||||
if (reader.canRead()) {
|
||||
if (reader.supportsAnimation() && reader.imageCount() > 1 && item) {
|
||||
startGif(item, already);
|
||||
} else if (item) {
|
||||
App::wnd()->showDocument(document, item);
|
||||
} else if (document->openOnSave > 0 && document->size < MediaViewImageSizeLimit) {
|
||||
const FileLocation &location(document->location(true));
|
||||
if (location.accessEnable()) {
|
||||
QImageReader reader(location.name());
|
||||
if (reader.canRead()) {
|
||||
if (reader.supportsAnimation() && reader.imageCount() > 1 && item) {
|
||||
startGif(item, location);
|
||||
} else if (item) {
|
||||
App::wnd()->showDocument(document, item);
|
||||
} else {
|
||||
psOpenFile(already);
|
||||
}
|
||||
} else {
|
||||
psOpenFile(already);
|
||||
}
|
||||
location.accessDisable();
|
||||
} else {
|
||||
psOpenFile(already);
|
||||
}
|
||||
|
@ -2320,7 +2361,9 @@ void MainWidget::showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back)
|
|||
//}
|
||||
|
||||
if (!dialogs.isHidden()) {
|
||||
dialogs.scrollToPeer(peerId, showAtMsgId);
|
||||
if (!back) {
|
||||
dialogs.scrollToPeer(peerId, showAtMsgId);
|
||||
}
|
||||
dialogs.update();
|
||||
}
|
||||
App::wnd()->getTitle()->updateBackButton();
|
||||
|
@ -2491,6 +2534,7 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop)
|
|||
if (back) clearBotStartToken(history.peer());
|
||||
history.showHistory(0, 0);
|
||||
history.hide();
|
||||
if (!cWideMode()) dialogs.hide();
|
||||
|
||||
orderWidgets();
|
||||
|
||||
|
@ -2537,6 +2581,7 @@ void MainWidget::orderWidgets() {
|
|||
dialogs.raise();
|
||||
_mediaType.raise();
|
||||
if (_hider) _hider->raise();
|
||||
if (_stickerPreview) _stickerPreview->raise();
|
||||
}
|
||||
|
||||
QRect MainWidget::historyRect() const {
|
||||
|
@ -2690,6 +2735,7 @@ void MainWidget::hideAll() {
|
|||
_topBar.hide();
|
||||
_mediaType.hide();
|
||||
_player.hide();
|
||||
_playerHeight = 0;
|
||||
}
|
||||
|
||||
void MainWidget::showAll() {
|
||||
|
@ -2764,6 +2810,7 @@ void MainWidget::showAll() {
|
|||
}
|
||||
}
|
||||
}
|
||||
resizeEvent(0);
|
||||
|
||||
App::wnd()->checkHistoryActivation();
|
||||
}
|
||||
|
@ -2795,6 +2842,7 @@ void MainWidget::resizeEvent(QResizeEvent *e) {
|
|||
_mediaType.moveToLeft(width() - _mediaType.width(), _playerHeight + st::topBarHeight);
|
||||
if (profile) profile->setGeometry(history.geometry());
|
||||
if (overview) overview->setGeometry(history.geometry());
|
||||
if (_stickerPreview) _stickerPreview->setGeometry(rect());
|
||||
_contentScrollAddToY = 0;
|
||||
}
|
||||
|
||||
|
@ -3668,6 +3716,7 @@ void MainWidget::startFull(const MTPVector<MTPUser> &users) {
|
|||
}
|
||||
|
||||
void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *h) {
|
||||
PeerData *updatePeer = 0;
|
||||
switch (settings.type()) {
|
||||
case mtpc_peerNotifySettingsEmpty:
|
||||
switch (peer.type()) {
|
||||
|
@ -3675,18 +3724,15 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti
|
|||
case mtpc_notifyUsers: globalNotifyUsersPtr = EmptyNotifySettings; break;
|
||||
case mtpc_notifyChats: globalNotifyChatsPtr = EmptyNotifySettings; break;
|
||||
case mtpc_notifyPeer: {
|
||||
PeerData *data = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer));
|
||||
if (data && data->notify != EmptyNotifySettings) {
|
||||
if (data->notify != UnknownNotifySettings) {
|
||||
delete data->notify;
|
||||
updatePeer = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer));
|
||||
if (updatePeer && updatePeer->notify != EmptyNotifySettings) {
|
||||
if (updatePeer->notify != UnknownNotifySettings) {
|
||||
delete updatePeer->notify;
|
||||
}
|
||||
data->notify = EmptyNotifySettings;
|
||||
App::unregMuted(data);
|
||||
if (!h) h = App::history(data->id);
|
||||
updatePeer->notify = EmptyNotifySettings;
|
||||
App::unregMuted(updatePeer);
|
||||
if (!h) h = App::history(updatePeer->id);
|
||||
h->setMute(false);
|
||||
if (history.peer() == data) {
|
||||
history.updateNotifySettings();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -3694,19 +3740,18 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti
|
|||
case mtpc_peerNotifySettings: {
|
||||
const MTPDpeerNotifySettings &d(settings.c_peerNotifySettings());
|
||||
NotifySettingsPtr setTo = UnknownNotifySettings;
|
||||
PeerData *data = 0;
|
||||
switch (peer.type()) {
|
||||
case mtpc_notifyAll: setTo = globalNotifyAllPtr = &globalNotifyAll; break;
|
||||
case mtpc_notifyUsers: setTo = globalNotifyUsersPtr = &globalNotifyUsers; break;
|
||||
case mtpc_notifyChats: setTo = globalNotifyChatsPtr = &globalNotifyChats; break;
|
||||
case mtpc_notifyPeer: {
|
||||
data = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer));
|
||||
if (!data) break;
|
||||
updatePeer = App::peerLoaded(peerFromMTP(peer.c_notifyPeer().vpeer));
|
||||
if (!updatePeer) break;
|
||||
|
||||
if (data->notify == UnknownNotifySettings || data->notify == EmptyNotifySettings) {
|
||||
data->notify = new NotifySettings();
|
||||
if (updatePeer->notify == UnknownNotifySettings || updatePeer->notify == EmptyNotifySettings) {
|
||||
updatePeer->notify = new NotifySettings();
|
||||
}
|
||||
setTo = data->notify;
|
||||
setTo = updatePeer->notify;
|
||||
} break;
|
||||
}
|
||||
if (setTo == UnknownNotifySettings) break;
|
||||
|
@ -3715,25 +3760,28 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti
|
|||
setTo->sound = d.vsound.c_string().v;
|
||||
setTo->previews = mtpIsTrue(d.vshow_previews);
|
||||
setTo->events = d.vevents_mask.v;
|
||||
if (data) {
|
||||
if (!h) h = App::history(data->id);
|
||||
if (updatePeer) {
|
||||
if (!h) h = App::history(updatePeer->id);
|
||||
int32 changeIn = 0;
|
||||
if (isNotifyMuted(setTo, &changeIn)) {
|
||||
App::wnd()->notifyClear(h);
|
||||
h->setMute(true);
|
||||
App::regMuted(data, changeIn);
|
||||
App::regMuted(updatePeer, changeIn);
|
||||
} else {
|
||||
h->setMute(false);
|
||||
}
|
||||
if (history.peer() == data) {
|
||||
history.updateNotifySettings();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
profile->updateNotifySettings();
|
||||
if (updatePeer) {
|
||||
if (history.peer() == updatePeer) {
|
||||
history.updateNotifySettings();
|
||||
}
|
||||
dialogs.updateNotifySettings(updatePeer);
|
||||
if (profile && profile->peer() == updatePeer) {
|
||||
profile->updateNotifySettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4573,5 +4621,81 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateNewStickerSet: {
|
||||
const MTPDupdateNewStickerSet &d(update.c_updateNewStickerSet());
|
||||
if (d.vstickerset.type() == mtpc_messages_stickerSet) {
|
||||
const MTPDmessages_stickerSet &set(d.vstickerset.c_messages_stickerSet());
|
||||
if (set.vset.type() == mtpc_stickerSet) {
|
||||
const QVector<MTPDocument> &v(set.vdocuments.c_vector().v);
|
||||
StickerPack pack;
|
||||
pack.reserve(v.size());
|
||||
for (int32 i = 0, l = v.size(); i < l; ++i) {
|
||||
DocumentData *doc = App::feedDocument(v.at(i));
|
||||
if (!doc || !doc->sticker()) continue;
|
||||
|
||||
pack.push_back(doc);
|
||||
}
|
||||
|
||||
const MTPDstickerSet &s(set.vset.c_stickerSet());
|
||||
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
|
||||
sets.insert(s.vid.v, StickerSet(s.vid.v, s.vaccess_hash.v, stickerSetTitle(s), qs(s.vshort_name), s.vcount.v, s.vhash.v, s.vflags.v)).value().stickers = pack;
|
||||
|
||||
StickerSetsOrder &order(cRefStickerSetsOrder());
|
||||
int32 insertAtIndex = 0, currentIndex = order.indexOf(s.vid.v);
|
||||
if (currentIndex != insertAtIndex) {
|
||||
if (currentIndex > 0) {
|
||||
order.removeAt(currentIndex);
|
||||
}
|
||||
order.insert(insertAtIndex, s.vid.v);
|
||||
}
|
||||
|
||||
StickerSets::iterator custom = sets.find(CustomStickerSetId);
|
||||
if (custom != sets.cend()) {
|
||||
for (int32 i = 0, l = pack.size(); i < l; ++i) {
|
||||
int32 removeIndex = custom->stickers.indexOf(pack.at(i));
|
||||
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
|
||||
}
|
||||
if (custom->stickers.isEmpty()) {
|
||||
sets.erase(custom);
|
||||
}
|
||||
}
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
emit stickersUpdated();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateStickerSetsOrder: {
|
||||
const MTPDupdateStickerSetsOrder &d(update.c_updateStickerSetsOrder());
|
||||
const QVector<MTPlong> &order(d.vorder.c_vector().v);
|
||||
const StickerSets &sets(cStickerSets());
|
||||
StickerSetsOrder result;
|
||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||
if (sets.constFind(order.at(i).v) == sets.cend()) {
|
||||
break;
|
||||
}
|
||||
result.push_back(order.at(i).v);
|
||||
}
|
||||
if (result.size() != cStickerSetsOrder().size() || result.size() != order.size()) {
|
||||
cSetLastStickersUpdate(0);
|
||||
cSetStickersHash(0);
|
||||
App::main()->updateStickers();
|
||||
} else {
|
||||
cSetStickerSetsOrder(result);
|
||||
cSetStickersHash(stickersCountHash());
|
||||
Local::writeStickers();
|
||||
emit stickersUpdated();
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateStickerSets: {
|
||||
cSetLastStickersUpdate(0);
|
||||
cSetStickersHash(0);
|
||||
App::main()->updateStickers();
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,6 +178,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class StickerPreviewWidget;
|
||||
|
||||
class MainWidget : public TWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -412,6 +414,9 @@ public:
|
|||
QPixmap grabTopBar();
|
||||
QPixmap grabInner();
|
||||
|
||||
void ui_showStickerPreview(DocumentData *sticker);
|
||||
void ui_hideStickerPreview();
|
||||
|
||||
~MainWidget();
|
||||
|
||||
signals:
|
||||
|
@ -482,6 +487,8 @@ public slots:
|
|||
void onViewsIncrement();
|
||||
void onActiveChannelUpdateFull();
|
||||
|
||||
void onDownloadPathSettings();
|
||||
|
||||
private:
|
||||
|
||||
void sendReadRequest(PeerData *peer, MsgId upTo);
|
||||
|
@ -562,7 +569,9 @@ private:
|
|||
StackItems _stack;
|
||||
PeerData *_peerInStack;
|
||||
MsgId _msgIdInStack;
|
||||
|
||||
|
||||
StickerPreviewWidget *_stickerPreview;
|
||||
|
||||
int32 _playerHeight;
|
||||
int32 _contentScrollAddToY;
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ MediaView::MediaView() : TWidget(App::wnd())
|
|||
connect(_btnSaveCancel, SIGNAL(clicked()), this, SLOT(onSaveCancel()));
|
||||
_btns.push_back(_btnToMessage = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_context_to_msg))));
|
||||
connect(_btnToMessage, SIGNAL(clicked()), this, SLOT(onToMessage()));
|
||||
_btns.push_back(_btnShowInFolder = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(cPlatform() == dbipMac ? lng_context_show_in_finder : lng_context_show_in_folder))));
|
||||
_btns.push_back(_btnShowInFolder = _dropdown.addButton(new IconedButton(this, st::mvButton, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder))));
|
||||
connect(_btnShowInFolder, SIGNAL(clicked()), this, SLOT(onShowInFolder()));
|
||||
_btns.push_back(_btnCopy = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_mediaview_copy))));
|
||||
connect(_btnCopy, SIGNAL(clicked()), this, SLOT(onCopy()));
|
||||
|
@ -453,10 +453,13 @@ bool MediaView::animStep(float64 msp) {
|
|||
_docRadialFirst = _docRadialLast = _docRadialStart = 0;
|
||||
a_docRadial = anim::fvalue(0, 0);
|
||||
if (!_doc->already().isEmpty() && _doc->size < MediaViewImageSizeLimit) {
|
||||
QString fname(_doc->already(true));
|
||||
QImageReader reader(fname);
|
||||
if (reader.canRead()) {
|
||||
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
|
||||
const FileLocation &location(_doc->location(true));
|
||||
if (location.accessEnable()) {
|
||||
QImageReader reader(location.name());
|
||||
if (reader.canRead()) {
|
||||
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
|
||||
}
|
||||
location.accessDisable();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -529,8 +532,33 @@ void MediaView::onToMessage() {
|
|||
void MediaView::onSaveAs() {
|
||||
QString file;
|
||||
if (_doc) {
|
||||
QString cur = _doc->already(true);
|
||||
if (cur.isEmpty()) {
|
||||
const FileLocation &location(_doc->location(true));
|
||||
if (location.accessEnable()) {
|
||||
QFileInfo alreadyInfo(location.name());
|
||||
QDir alreadyDir(alreadyInfo.dir());
|
||||
QString name = alreadyInfo.fileName(), filter;
|
||||
MimeType mimeType = mimeTypeForName(_doc->mime);
|
||||
QStringList p = mimeType.globPatterns();
|
||||
QString pattern = p.isEmpty() ? QString() : p.front();
|
||||
if (name.isEmpty()) {
|
||||
name = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
|
||||
}
|
||||
|
||||
if (pattern.isEmpty()) {
|
||||
filter = QString();
|
||||
} else {
|
||||
filter = mimeType.filterString() + qsl(";;All files (*.*)");
|
||||
}
|
||||
|
||||
psBringToBack(this);
|
||||
file = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, true, alreadyDir);
|
||||
psShowOverAll(this);
|
||||
if (!file.isEmpty() && file != location.name()) {
|
||||
QFile(location.name()).copy(file);
|
||||
}
|
||||
|
||||
location.accessDisable();
|
||||
} else {
|
||||
if (_current.isNull() && _currentGif.isNull()) {
|
||||
DocumentSaveLink::doSave(_doc, true);
|
||||
updateControls();
|
||||
|
@ -539,30 +567,6 @@ void MediaView::onSaveAs() {
|
|||
update(_saveNav);
|
||||
}
|
||||
updateOver(_lastMouseMovePos);
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo alreadyInfo(cur);
|
||||
QDir alreadyDir(alreadyInfo.dir());
|
||||
QString name = alreadyInfo.fileName(), filter;
|
||||
MimeType mimeType = mimeTypeForName(_doc->mime);
|
||||
QStringList p = mimeType.globPatterns();
|
||||
QString pattern = p.isEmpty() ? QString() : p.front();
|
||||
if (name.isEmpty()) {
|
||||
name = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
|
||||
}
|
||||
|
||||
if (pattern.isEmpty()) {
|
||||
filter = QString();
|
||||
} else {
|
||||
filter = mimeType.filterString() + qsl(";;All files (*.*)");
|
||||
}
|
||||
|
||||
psBringToBack(this);
|
||||
file = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, true, alreadyDir);
|
||||
psShowOverAll(this);
|
||||
if (!file.isEmpty() && file != cur) {
|
||||
QFile(cur).copy(file);
|
||||
}
|
||||
} else {
|
||||
if (!_photo || !_photo->full->loaded()) return;
|
||||
|
@ -609,8 +613,15 @@ void MediaView::onDownload() {
|
|||
}
|
||||
QString toName;
|
||||
if (_doc) {
|
||||
QString cur = _doc->already(true);
|
||||
if (cur.isEmpty()) {
|
||||
const FileLocation &location(_doc->location(true));
|
||||
if (location.accessEnable()) {
|
||||
if (!QDir().exists(path)) QDir().mkpath(path);
|
||||
toName = filedialogNextFilename(_doc->name, location.name(), path);
|
||||
if (toName != location.name() && !QFile(location.name()).copy(toName)) {
|
||||
toName = QString();
|
||||
}
|
||||
location.accessDisable();
|
||||
} else {
|
||||
if (_current.isNull() && _currentGif.isNull()) {
|
||||
DocumentSaveLink::doSave(_doc);
|
||||
updateControls();
|
||||
|
@ -619,12 +630,6 @@ void MediaView::onDownload() {
|
|||
update(_saveNav);
|
||||
}
|
||||
updateOver(_lastMouseMovePos);
|
||||
} else {
|
||||
if (!QDir().exists(path)) QDir().mkpath(path);
|
||||
toName = filedialogNextFilename(_doc->name, cur, path);
|
||||
if (toName != cur && !QFile(cur).copy(toName)) {
|
||||
toName = QString();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!_photo || !_photo->full->loaded()) {
|
||||
|
@ -902,25 +907,26 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
|
|||
|
||||
_caption = Text();
|
||||
if (_doc) {
|
||||
QString already = _doc->already(true);
|
||||
const FileLocation &location(_doc->location(true));
|
||||
if (_doc->sticker() && !_doc->sticker()->img->isNull() && _doc->sticker()->img->loaded()) {
|
||||
_currentGif.stop();
|
||||
_current = _doc->sticker()->img->pix();
|
||||
} else if (!already.isEmpty()) {
|
||||
QImageReader reader(already);
|
||||
} else if (location.accessEnable()) {
|
||||
QImageReader reader(location.name());
|
||||
if (reader.canRead()) {
|
||||
if (reader.supportsAnimation() && reader.imageCount() > 1) {
|
||||
_currentGif.start(0, already);
|
||||
_currentGif.start(0, location);
|
||||
_current = QPixmap();
|
||||
} else {
|
||||
_currentGif.stop();
|
||||
QPixmap pix = QPixmap::fromImage(App::readImage(already, 0, false), Qt::ColorOnly);
|
||||
QPixmap pix = QPixmap::fromImage(App::readImage(location.name(), 0, false), Qt::ColorOnly);
|
||||
_current = pix;
|
||||
}
|
||||
} else {
|
||||
_currentGif.stop();
|
||||
_current = QPixmap();
|
||||
}
|
||||
location.accessDisable();
|
||||
} else {
|
||||
_currentGif.stop();
|
||||
_current = QPixmap();
|
||||
|
|
41
Telegram/SourceFiles/mtproto/mtpAuthKey.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
|
||||
uchar aes_key[32], aes_iv[32];
|
||||
memcpy(aes_key, key, 32);
|
||||
memcpy(aes_iv, iv, 32);
|
||||
|
||||
AES_KEY aes;
|
||||
AES_set_encrypt_key(aes_key, 256, &aes);
|
||||
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_ENCRYPT);
|
||||
}
|
||||
|
||||
void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
|
||||
uchar aes_key[32], aes_iv[32];
|
||||
memcpy(aes_key, key, 32);
|
||||
memcpy(aes_iv, iv, 32);
|
||||
|
||||
AES_KEY aes;
|
||||
AES_set_decrypt_key(aes_key, 256, &aes);
|
||||
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_DECRYPT);
|
||||
}
|
|
@ -112,15 +112,8 @@ inline bool operator==(const mtpAuthKey &a, const mtpAuthKey &b) {
|
|||
typedef QSharedPointer<mtpAuthKey> mtpAuthKeyPtr;
|
||||
typedef QVector<mtpAuthKeyPtr> mtpKeysMap;
|
||||
|
||||
inline void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
|
||||
uchar aes_key[32], aes_iv[32];
|
||||
memcpy(aes_key, key, 32);
|
||||
memcpy(aes_iv, iv, 32);
|
||||
|
||||
AES_KEY aes;
|
||||
AES_set_encrypt_key(aes_key, 256, &aes);
|
||||
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_ENCRYPT);
|
||||
}
|
||||
void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv);
|
||||
void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv);
|
||||
|
||||
inline void aesEncrypt(const void *src, void *dst, uint32 len, const mtpAuthKeyPtr &authKey, const MTPint128 &msgKey) {
|
||||
MTPint256 aesKey, aesIV;
|
||||
|
@ -136,16 +129,6 @@ inline void aesEncryptLocal(const void *src, void *dst, uint32 len, const mtpAut
|
|||
return aesEncrypt(src, dst, len, &aesKey, &aesIV);
|
||||
}
|
||||
|
||||
inline void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
|
||||
uchar aes_key[32], aes_iv[32];
|
||||
memcpy(aes_key, key, 32);
|
||||
memcpy(aes_iv, iv, 32);
|
||||
|
||||
AES_KEY aes;
|
||||
AES_set_decrypt_key(aes_key, 256, &aes);
|
||||
AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_DECRYPT);
|
||||
}
|
||||
|
||||
inline void aesDecrypt(const void *src, void *dst, uint32 len, const mtpAuthKeyPtr &authKey, const MTPint128 &msgKey) {
|
||||
MTPint256 aesKey, aesIV;
|
||||
authKey->prepareAES(msgKey, aesKey, aesIV, false);
|
||||
|
|
|
@ -361,7 +361,7 @@ namespace {
|
|||
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
if (statusCode.isValid()) {
|
||||
int status = statusCode.toInt();
|
||||
mayBeBadKey = (status == 404);
|
||||
mayBeBadKey = (status == 410);
|
||||
if (status == 429) {
|
||||
LOG(("Protocol Error: 429 flood code returned!"));
|
||||
}
|
||||
|
@ -845,7 +845,7 @@ void MTPautoConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
|||
sock.disconnectFromHost();
|
||||
emit connected();
|
||||
} else if (status == WaitingTcp || status == UsingTcp) {
|
||||
bool mayBeBadKey = (data[0] == -404) && _sentEncrypted;
|
||||
bool mayBeBadKey = (data[0] == -410) && _sentEncrypted;
|
||||
emit error(mayBeBadKey);
|
||||
} else {
|
||||
LOG(("Strange Tcp Error; status %1").arg(status));
|
||||
|
@ -1016,7 +1016,7 @@ void MTPtcpConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
|||
|
||||
mtpBuffer data = _handleTcpResponse(packet, size);
|
||||
if (data.size() == 1) {
|
||||
bool mayBeBadKey = (data[0] == -404) && _sentEncrypted;
|
||||
bool mayBeBadKey = (data[0] == -410) && _sentEncrypted;
|
||||
emit error(mayBeBadKey);
|
||||
} else if (status == UsingTcp) {
|
||||
receivedQueue.push_back(data);
|
||||
|
@ -1952,11 +1952,11 @@ void MTProtoConnectionPrivate::socketStart(bool afterConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
void MTProtoConnectionPrivate::restart(bool maybeBadKey) {
|
||||
void MTProtoConnectionPrivate::restart(bool mayBeBadKey) {
|
||||
QReadLocker lockFinished(&sessionDataMutex);
|
||||
if (!sessionData) return;
|
||||
|
||||
DEBUG_LOG(("MTP Info: restarting MTProtoConnection, maybe bad key = %1").arg(logBool(maybeBadKey)));
|
||||
DEBUG_LOG(("MTP Info: restarting MTProtoConnection, maybe bad key = %1").arg(logBool(mayBeBadKey)));
|
||||
|
||||
_waitForReceivedTimer.stop();
|
||||
_waitForConnectedTimer.stop();
|
||||
|
@ -1964,11 +1964,11 @@ void MTProtoConnectionPrivate::restart(bool maybeBadKey) {
|
|||
mtpAuthKeyPtr key(sessionData->getKey());
|
||||
if (key) {
|
||||
if (!sessionData->isCheckedKey()) {
|
||||
if (maybeBadKey) {
|
||||
if (mayBeBadKey) {
|
||||
clearMessages();
|
||||
keyId = mtpAuthKey::RecreateKeyId;
|
||||
// retryTimeout = 1; // no ddos please
|
||||
LOG(("MTP Info: key may be bad and was not checked - will be destroyed"));
|
||||
LOG(("MTP Info: key may be bad and was not checked - but won't be destroyed, no log outs because of bad server right now.."));
|
||||
}
|
||||
} else {
|
||||
sessionData->setCheckedKey(false);
|
||||
|
|
|
@ -135,7 +135,7 @@ signals:
|
|||
void receivedData();
|
||||
void receivedSome(); // to stop restart timer
|
||||
|
||||
void error(bool maybeBadKey = false);
|
||||
void error(bool mayBeBadKey = false);
|
||||
|
||||
void connected();
|
||||
void disconnected();
|
||||
|
@ -355,7 +355,7 @@ public slots:
|
|||
|
||||
void retryByTimer();
|
||||
void restartNow();
|
||||
void restart(bool maybeBadKey = false);
|
||||
void restart(bool mayBeBadKey = false);
|
||||
|
||||
void onPingSender();
|
||||
void onPingSendForce();
|
||||
|
@ -375,8 +375,8 @@ public slots:
|
|||
void onConnected6();
|
||||
void onDisconnected4();
|
||||
void onDisconnected6();
|
||||
void onError4(bool maybeBadKey = false);
|
||||
void onError6(bool maybeBadKey = false);
|
||||
void onError4(bool mayBeBadKey = false);
|
||||
void onError6(bool mayBeBadKey = false);
|
||||
|
||||
void doFinish();
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "stdafx.h"
|
||||
#include "mtpCoreTypes.h"
|
||||
|
||||
#include "lang.h"
|
||||
|
||||
#if defined _DEBUG || defined _WITH_DEBUG
|
||||
|
||||
QString mtpWrapNumber(float64 number) {
|
||||
|
@ -150,3 +152,11 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
QString stickerSetTitle(const MTPDstickerSet &s) {
|
||||
QString title = qs(s.vtitle);
|
||||
if ((s.vflags.v & MTPDstickerSet::flag_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) {
|
||||
return lang(lng_stickers_default_set);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ static const mtpTypeId mtpLayers[] = {
|
|||
mtpTypeId(mtpc_invokeWithLayer18),
|
||||
};
|
||||
static const uint32 mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
|
||||
static const mtpPrime mtpCurrentLayer = 42;
|
||||
static const mtpPrime mtpCurrentLayer = 43;
|
||||
|
||||
template <typename bareT>
|
||||
class MTPBoxed : public bareT {
|
||||
|
@ -990,3 +990,5 @@ enum { // client side flags
|
|||
|
||||
static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_int(0), MTP_vector<MTPKeyboardButtonRow>(0));
|
||||
static const MTPVector<MTPMessageEntity> MTPnullEntities = MTP_vector<MTPMessageEntity>(0);
|
||||
|
||||
QString stickerSetTitle(const MTPDstickerSet &s);
|
|
@ -2082,6 +2082,31 @@ void _serialize_wallPaperSolid(MTPStringLogger &to, int32 stage, int32 lev, Type
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_inputReportReasonSpam(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputReportReasonSpam }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputReportReasonViolence(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputReportReasonViolence }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputReportReasonPornography(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ inputReportReasonPornography }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_inputReportReasonOther(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ inputReportReasonOther");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_userFull(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -2966,6 +2991,36 @@ void _serialize_updateChatParticipantAdmin(MTPStringLogger &to, int32 stage, int
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_updateNewStickerSet(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ updateNewStickerSet");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" stickerset: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_updateStickerSetsOrder(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ updateStickerSetsOrder");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" order: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_updateStickerSets(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
to.add("{ updateStickerSets }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
|
||||
}
|
||||
|
||||
void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -4052,7 +4107,7 @@ void _serialize_messages_allStickers(MTPStringLogger &to, int32 stage, int32 lev
|
|||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" sets: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
|
@ -4970,6 +5025,19 @@ void _serialize_channels_channelParticipant(MTPStringLogger &to, int32 stage, in
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_help_termsOfService(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ help_termsOfService");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_req_pq(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -5229,6 +5297,20 @@ void _serialize_account_updateStatus(MTPStringLogger &to, int32 stage, int32 lev
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_account_reportPeer(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ account_reportPeer");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 1: to.add(" reason: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_account_checkUsername(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -5457,6 +5539,19 @@ void _serialize_messages_editChatAdmin(MTPStringLogger &to, int32 stage, int32 l
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_messages_reorderStickerSets(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ messages_reorderStickerSets");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" order: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_upload_saveFilePart(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -6835,7 +6930,7 @@ void _serialize_messages_getAllStickers(MTPStringLogger &to, int32 stage, int32
|
|||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
case 0: to.add(" hash: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
@ -7058,6 +7153,19 @@ void _serialize_help_getAppChangelog(MTPStringLogger &to, int32 stage, int32 lev
|
|||
}
|
||||
}
|
||||
|
||||
void _serialize_help_getTermsOfService(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
} else {
|
||||
to.add("{ help_getTermsOfService");
|
||||
to.add("\n").addSpaces(lev);
|
||||
}
|
||||
switch (stage) {
|
||||
case 0: to.add(" lang_code: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
|
||||
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void _serialize_channels_getParticipants(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 flag) {
|
||||
if (stage) {
|
||||
to.add(",\n").addSpaces(lev);
|
||||
|
@ -7305,6 +7413,10 @@ namespace {
|
|||
_serializers.insert(mtpc_peerNotifySettings, _serialize_peerNotifySettings);
|
||||
_serializers.insert(mtpc_wallPaper, _serialize_wallPaper);
|
||||
_serializers.insert(mtpc_wallPaperSolid, _serialize_wallPaperSolid);
|
||||
_serializers.insert(mtpc_inputReportReasonSpam, _serialize_inputReportReasonSpam);
|
||||
_serializers.insert(mtpc_inputReportReasonViolence, _serialize_inputReportReasonViolence);
|
||||
_serializers.insert(mtpc_inputReportReasonPornography, _serialize_inputReportReasonPornography);
|
||||
_serializers.insert(mtpc_inputReportReasonOther, _serialize_inputReportReasonOther);
|
||||
_serializers.insert(mtpc_userFull, _serialize_userFull);
|
||||
_serializers.insert(mtpc_contact, _serialize_contact);
|
||||
_serializers.insert(mtpc_importedContact, _serialize_importedContact);
|
||||
|
@ -7372,6 +7484,9 @@ namespace {
|
|||
_serializers.insert(mtpc_updateChannelMessageViews, _serialize_updateChannelMessageViews);
|
||||
_serializers.insert(mtpc_updateChatAdmins, _serialize_updateChatAdmins);
|
||||
_serializers.insert(mtpc_updateChatParticipantAdmin, _serialize_updateChatParticipantAdmin);
|
||||
_serializers.insert(mtpc_updateNewStickerSet, _serialize_updateNewStickerSet);
|
||||
_serializers.insert(mtpc_updateStickerSetsOrder, _serialize_updateStickerSetsOrder);
|
||||
_serializers.insert(mtpc_updateStickerSets, _serialize_updateStickerSets);
|
||||
_serializers.insert(mtpc_updates_state, _serialize_updates_state);
|
||||
_serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty);
|
||||
_serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
|
||||
|
@ -7536,6 +7651,7 @@ namespace {
|
|||
_serializers.insert(mtpc_channelRoleEditor, _serialize_channelRoleEditor);
|
||||
_serializers.insert(mtpc_channels_channelParticipants, _serialize_channels_channelParticipants);
|
||||
_serializers.insert(mtpc_channels_channelParticipant, _serialize_channels_channelParticipant);
|
||||
_serializers.insert(mtpc_help_termsOfService, _serialize_help_termsOfService);
|
||||
|
||||
_serializers.insert(mtpc_req_pq, _serialize_req_pq);
|
||||
_serializers.insert(mtpc_req_DH_params, _serialize_req_DH_params);
|
||||
|
@ -7557,6 +7673,7 @@ namespace {
|
|||
_serializers.insert(mtpc_account_updateNotifySettings, _serialize_account_updateNotifySettings);
|
||||
_serializers.insert(mtpc_account_resetNotifySettings, _serialize_account_resetNotifySettings);
|
||||
_serializers.insert(mtpc_account_updateStatus, _serialize_account_updateStatus);
|
||||
_serializers.insert(mtpc_account_reportPeer, _serialize_account_reportPeer);
|
||||
_serializers.insert(mtpc_account_checkUsername, _serialize_account_checkUsername);
|
||||
_serializers.insert(mtpc_account_deleteAccount, _serialize_account_deleteAccount);
|
||||
_serializers.insert(mtpc_account_setAccountTTL, _serialize_account_setAccountTTL);
|
||||
|
@ -7574,6 +7691,7 @@ namespace {
|
|||
_serializers.insert(mtpc_messages_installStickerSet, _serialize_messages_installStickerSet);
|
||||
_serializers.insert(mtpc_messages_uninstallStickerSet, _serialize_messages_uninstallStickerSet);
|
||||
_serializers.insert(mtpc_messages_editChatAdmin, _serialize_messages_editChatAdmin);
|
||||
_serializers.insert(mtpc_messages_reorderStickerSets, _serialize_messages_reorderStickerSets);
|
||||
_serializers.insert(mtpc_upload_saveFilePart, _serialize_upload_saveFilePart);
|
||||
_serializers.insert(mtpc_upload_saveBigFilePart, _serialize_upload_saveBigFilePart);
|
||||
_serializers.insert(mtpc_help_saveAppLog, _serialize_help_saveAppLog);
|
||||
|
@ -7693,6 +7811,7 @@ namespace {
|
|||
_serializers.insert(mtpc_help_getInviteText, _serialize_help_getInviteText);
|
||||
_serializers.insert(mtpc_help_getSupport, _serialize_help_getSupport);
|
||||
_serializers.insert(mtpc_help_getAppChangelog, _serialize_help_getAppChangelog);
|
||||
_serializers.insert(mtpc_help_getTermsOfService, _serialize_help_getTermsOfService);
|
||||
_serializers.insert(mtpc_channels_getParticipants, _serialize_channels_getParticipants);
|
||||
_serializers.insert(mtpc_channels_getParticipant, _serialize_channels_getParticipant);
|
||||
|
||||
|
|
|
@ -205,6 +205,10 @@ enum {
|
|||
mtpc_peerNotifySettings = 0x8d5e11ee,
|
||||
mtpc_wallPaper = 0xccb03657,
|
||||
mtpc_wallPaperSolid = 0x63117f24,
|
||||
mtpc_inputReportReasonSpam = 0x58dbcab8,
|
||||
mtpc_inputReportReasonViolence = 0x1e22c78d,
|
||||
mtpc_inputReportReasonPornography = 0x2e59d922,
|
||||
mtpc_inputReportReasonOther = 0xe1746d0a,
|
||||
mtpc_userFull = 0x5a89ac5b,
|
||||
mtpc_contact = 0xf911c994,
|
||||
mtpc_importedContact = 0xd0028438,
|
||||
|
@ -272,6 +276,9 @@ enum {
|
|||
mtpc_updateChannelMessageViews = 0x98a12b4b,
|
||||
mtpc_updateChatAdmins = 0x6e947941,
|
||||
mtpc_updateChatParticipantAdmin = 0xb6901959,
|
||||
mtpc_updateNewStickerSet = 0x688a30aa,
|
||||
mtpc_updateStickerSetsOrder = 0xf0dfb451,
|
||||
mtpc_updateStickerSets = 0x43ae3dec,
|
||||
mtpc_updates_state = 0xa56c2a3e,
|
||||
mtpc_updates_differenceEmpty = 0x5d75a138,
|
||||
mtpc_updates_difference = 0xf49ca0,
|
||||
|
@ -362,7 +369,7 @@ enum {
|
|||
mtpc_messages_stickers = 0x8a8ecd32,
|
||||
mtpc_stickerPack = 0x12b299d4,
|
||||
mtpc_messages_allStickersNotModified = 0xe86602c3,
|
||||
mtpc_messages_allStickers = 0xd51dafdb,
|
||||
mtpc_messages_allStickers = 0xedfd405f,
|
||||
mtpc_disabledFeature = 0xae636f24,
|
||||
mtpc_messages_affectedMessages = 0x84d19185,
|
||||
mtpc_contactLinkUnknown = 0x5f4f9247,
|
||||
|
@ -436,6 +443,7 @@ enum {
|
|||
mtpc_channelRoleEditor = 0x820bfe8c,
|
||||
mtpc_channels_channelParticipants = 0xf56ee2a8,
|
||||
mtpc_channels_channelParticipant = 0xd0d9b163,
|
||||
mtpc_help_termsOfService = 0xf1ee3e90,
|
||||
mtpc_invokeAfterMsg = 0xcb9f372d,
|
||||
mtpc_invokeAfterMsgs = 0x3dc4b4f0,
|
||||
mtpc_initConnection = 0x69796de9,
|
||||
|
@ -465,6 +473,7 @@ enum {
|
|||
mtpc_account_updateProfile = 0xf0888d68,
|
||||
mtpc_account_updateStatus = 0x6628562c,
|
||||
mtpc_account_getWallPapers = 0xc04cfac2,
|
||||
mtpc_account_reportPeer = 0xae189d5f,
|
||||
mtpc_account_checkUsername = 0x2714d86c,
|
||||
mtpc_account_updateUsername = 0x3e0bdd7c,
|
||||
mtpc_account_getPrivacy = 0xdadbc950,
|
||||
|
@ -529,7 +538,7 @@ enum {
|
|||
mtpc_messages_receivedQueue = 0x55a5bb66,
|
||||
mtpc_messages_readMessageContents = 0x36a73f77,
|
||||
mtpc_messages_getStickers = 0xae22e045,
|
||||
mtpc_messages_getAllStickers = 0xaa3bc868,
|
||||
mtpc_messages_getAllStickers = 0x1c9618b1,
|
||||
mtpc_messages_getWebPagePreview = 0x25223e24,
|
||||
mtpc_messages_exportChatInvite = 0x7d885289,
|
||||
mtpc_messages_checkChatInvite = 0x3eadb1bb,
|
||||
|
@ -543,6 +552,7 @@ enum {
|
|||
mtpc_messages_editChatAdmin = 0xa9e69f2e,
|
||||
mtpc_messages_migrateChat = 0x15a3b8e3,
|
||||
mtpc_messages_searchGlobal = 0x9e3cacb0,
|
||||
mtpc_messages_reorderStickerSets = 0x9fcfbc30,
|
||||
mtpc_updates_getState = 0xedd4882a,
|
||||
mtpc_updates_getDifference = 0xa041495,
|
||||
mtpc_updates_getChannelDifference = 0xbb32d7c0,
|
||||
|
@ -560,6 +570,7 @@ enum {
|
|||
mtpc_help_getInviteText = 0xa4a95186,
|
||||
mtpc_help_getSupport = 0x9cdf08cd,
|
||||
mtpc_help_getAppChangelog = 0x5bab7fb2,
|
||||
mtpc_help_getTermsOfService = 0x37d78f83,
|
||||
mtpc_channels_getDialogs = 0xa9d3d249,
|
||||
mtpc_channels_getImportantHistory = 0xddb929cb,
|
||||
mtpc_channels_readHistory = 0xcc104937,
|
||||
|
@ -843,6 +854,9 @@ class MTPwallPaper;
|
|||
class MTPDwallPaper;
|
||||
class MTPDwallPaperSolid;
|
||||
|
||||
class MTPreportReason;
|
||||
class MTPDinputReportReasonOther;
|
||||
|
||||
class MTPuserFull;
|
||||
class MTPDuserFull;
|
||||
|
||||
|
@ -935,6 +949,8 @@ class MTPDupdateDeleteChannelMessages;
|
|||
class MTPDupdateChannelMessageViews;
|
||||
class MTPDupdateChatAdmins;
|
||||
class MTPDupdateChatParticipantAdmin;
|
||||
class MTPDupdateNewStickerSet;
|
||||
class MTPDupdateStickerSetsOrder;
|
||||
|
||||
class MTPupdates_state;
|
||||
class MTPDupdates_state;
|
||||
|
@ -1196,6 +1212,9 @@ class MTPDchannels_channelParticipants;
|
|||
class MTPchannels_channelParticipant;
|
||||
class MTPDchannels_channelParticipant;
|
||||
|
||||
class MTPhelp_termsOfService;
|
||||
class MTPDhelp_termsOfService;
|
||||
|
||||
|
||||
// Boxed types definitions
|
||||
typedef MTPBoxed<MTPresPQ> MTPResPQ;
|
||||
|
@ -1264,6 +1283,7 @@ typedef MTPBoxed<MTPinputPeerNotifySettings> MTPInputPeerNotifySettings;
|
|||
typedef MTPBoxed<MTPpeerNotifyEvents> MTPPeerNotifyEvents;
|
||||
typedef MTPBoxed<MTPpeerNotifySettings> MTPPeerNotifySettings;
|
||||
typedef MTPBoxed<MTPwallPaper> MTPWallPaper;
|
||||
typedef MTPBoxed<MTPreportReason> MTPReportReason;
|
||||
typedef MTPBoxed<MTPuserFull> MTPUserFull;
|
||||
typedef MTPBoxed<MTPcontact> MTPContact;
|
||||
typedef MTPBoxed<MTPimportedContact> MTPImportedContact;
|
||||
|
@ -1353,6 +1373,7 @@ typedef MTPBoxed<MTPchannelParticipantsFilter> MTPChannelParticipantsFilter;
|
|||
typedef MTPBoxed<MTPchannelParticipantRole> MTPChannelParticipantRole;
|
||||
typedef MTPBoxed<MTPchannels_channelParticipants> MTPchannels_ChannelParticipants;
|
||||
typedef MTPBoxed<MTPchannels_channelParticipant> MTPchannels_ChannelParticipant;
|
||||
typedef MTPBoxed<MTPhelp_termsOfService> MTPhelp_TermsOfService;
|
||||
|
||||
// Type classes definitions
|
||||
|
||||
|
@ -4503,6 +4524,46 @@ private:
|
|||
};
|
||||
typedef MTPBoxed<MTPwallPaper> MTPWallPaper;
|
||||
|
||||
class MTPreportReason : private mtpDataOwner {
|
||||
public:
|
||||
MTPreportReason() : mtpDataOwner(0), _type(0) {
|
||||
}
|
||||
MTPreportReason(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
|
||||
MTPDinputReportReasonOther &_inputReportReasonOther() {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_inputReportReasonOther) throw mtpErrorWrongTypeId(_type, mtpc_inputReportReasonOther);
|
||||
split();
|
||||
return *(MTPDinputReportReasonOther*)data;
|
||||
}
|
||||
const MTPDinputReportReasonOther &c_inputReportReasonOther() const {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_inputReportReasonOther) throw mtpErrorWrongTypeId(_type, mtpc_inputReportReasonOther);
|
||||
return *(const MTPDinputReportReasonOther*)data;
|
||||
}
|
||||
|
||||
uint32 innerLength() const;
|
||||
mtpTypeId type() const;
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
|
||||
void write(mtpBuffer &to) const;
|
||||
|
||||
typedef void ResponseType;
|
||||
|
||||
private:
|
||||
explicit MTPreportReason(mtpTypeId type);
|
||||
explicit MTPreportReason(MTPDinputReportReasonOther *_data);
|
||||
|
||||
friend MTPreportReason MTP_inputReportReasonSpam();
|
||||
friend MTPreportReason MTP_inputReportReasonViolence();
|
||||
friend MTPreportReason MTP_inputReportReasonPornography();
|
||||
friend MTPreportReason MTP_inputReportReasonOther(const MTPstring &_text);
|
||||
|
||||
mtpTypeId _type;
|
||||
};
|
||||
typedef MTPBoxed<MTPreportReason> MTPReportReason;
|
||||
|
||||
class MTPuserFull : private mtpDataOwner {
|
||||
public:
|
||||
MTPuserFull();
|
||||
|
@ -5564,6 +5625,30 @@ public:
|
|||
return *(const MTPDupdateChatParticipantAdmin*)data;
|
||||
}
|
||||
|
||||
MTPDupdateNewStickerSet &_updateNewStickerSet() {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_updateNewStickerSet) throw mtpErrorWrongTypeId(_type, mtpc_updateNewStickerSet);
|
||||
split();
|
||||
return *(MTPDupdateNewStickerSet*)data;
|
||||
}
|
||||
const MTPDupdateNewStickerSet &c_updateNewStickerSet() const {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_updateNewStickerSet) throw mtpErrorWrongTypeId(_type, mtpc_updateNewStickerSet);
|
||||
return *(const MTPDupdateNewStickerSet*)data;
|
||||
}
|
||||
|
||||
MTPDupdateStickerSetsOrder &_updateStickerSetsOrder() {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_updateStickerSetsOrder) throw mtpErrorWrongTypeId(_type, mtpc_updateStickerSetsOrder);
|
||||
split();
|
||||
return *(MTPDupdateStickerSetsOrder*)data;
|
||||
}
|
||||
const MTPDupdateStickerSetsOrder &c_updateStickerSetsOrder() const {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
if (_type != mtpc_updateStickerSetsOrder) throw mtpErrorWrongTypeId(_type, mtpc_updateStickerSetsOrder);
|
||||
return *(const MTPDupdateStickerSetsOrder*)data;
|
||||
}
|
||||
|
||||
uint32 innerLength() const;
|
||||
mtpTypeId type() const;
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
|
||||
|
@ -5610,6 +5695,8 @@ private:
|
|||
explicit MTPupdate(MTPDupdateChannelMessageViews *_data);
|
||||
explicit MTPupdate(MTPDupdateChatAdmins *_data);
|
||||
explicit MTPupdate(MTPDupdateChatParticipantAdmin *_data);
|
||||
explicit MTPupdate(MTPDupdateNewStickerSet *_data);
|
||||
explicit MTPupdate(MTPDupdateStickerSetsOrder *_data);
|
||||
|
||||
friend MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count);
|
||||
friend MTPupdate MTP_updateMessageID(MTPint _id, const MTPlong &_random_id);
|
||||
|
@ -5648,6 +5735,9 @@ private:
|
|||
friend MTPupdate MTP_updateChannelMessageViews(MTPint _channel_id, MTPint _id, MTPint _views);
|
||||
friend MTPupdate MTP_updateChatAdmins(MTPint _chat_id, MTPBool _enabled, MTPint _version);
|
||||
friend MTPupdate MTP_updateChatParticipantAdmin(MTPint _chat_id, MTPint _user_id, MTPBool _is_admin, MTPint _version);
|
||||
friend MTPupdate MTP_updateNewStickerSet(const MTPmessages_StickerSet &_stickerset);
|
||||
friend MTPupdate MTP_updateStickerSetsOrder(const MTPVector<MTPlong> &_order);
|
||||
friend MTPupdate MTP_updateStickerSets();
|
||||
|
||||
mtpTypeId _type;
|
||||
};
|
||||
|
@ -7318,7 +7408,7 @@ private:
|
|||
explicit MTPmessages_allStickers(MTPDmessages_allStickers *_data);
|
||||
|
||||
friend MTPmessages_allStickers MTP_messages_allStickersNotModified();
|
||||
friend MTPmessages_allStickers MTP_messages_allStickers(const MTPstring &_hash, const MTPVector<MTPStickerSet> &_sets);
|
||||
friend MTPmessages_allStickers MTP_messages_allStickers(MTPint _hash, const MTPVector<MTPStickerSet> &_sets);
|
||||
|
||||
mtpTypeId _type;
|
||||
};
|
||||
|
@ -8786,6 +8876,37 @@ private:
|
|||
};
|
||||
typedef MTPBoxed<MTPchannels_channelParticipant> MTPchannels_ChannelParticipant;
|
||||
|
||||
class MTPhelp_termsOfService : private mtpDataOwner {
|
||||
public:
|
||||
MTPhelp_termsOfService();
|
||||
MTPhelp_termsOfService(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_termsOfService) : mtpDataOwner(0) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
|
||||
MTPDhelp_termsOfService &_help_termsOfService() {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
split();
|
||||
return *(MTPDhelp_termsOfService*)data;
|
||||
}
|
||||
const MTPDhelp_termsOfService &c_help_termsOfService() const {
|
||||
if (!data) throw mtpErrorUninitialized();
|
||||
return *(const MTPDhelp_termsOfService*)data;
|
||||
}
|
||||
|
||||
uint32 innerLength() const;
|
||||
mtpTypeId type() const;
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_termsOfService);
|
||||
void write(mtpBuffer &to) const;
|
||||
|
||||
typedef void ResponseType;
|
||||
|
||||
private:
|
||||
explicit MTPhelp_termsOfService(MTPDhelp_termsOfService *_data);
|
||||
|
||||
friend MTPhelp_termsOfService MTP_help_termsOfService(const MTPstring &_text);
|
||||
};
|
||||
typedef MTPBoxed<MTPhelp_termsOfService> MTPhelp_TermsOfService;
|
||||
|
||||
// Type constructors with data
|
||||
|
||||
class MTPDresPQ : public mtpDataImpl<MTPDresPQ> {
|
||||
|
@ -10403,6 +10524,16 @@ public:
|
|||
MTPint vcolor;
|
||||
};
|
||||
|
||||
class MTPDinputReportReasonOther : public mtpDataImpl<MTPDinputReportReasonOther> {
|
||||
public:
|
||||
MTPDinputReportReasonOther() {
|
||||
}
|
||||
MTPDinputReportReasonOther(const MTPstring &_text) : vtext(_text) {
|
||||
}
|
||||
|
||||
MTPstring vtext;
|
||||
};
|
||||
|
||||
class MTPDuserFull : public mtpDataImpl<MTPDuserFull> {
|
||||
public:
|
||||
MTPDuserFull() {
|
||||
|
@ -11082,6 +11213,26 @@ public:
|
|||
MTPint vversion;
|
||||
};
|
||||
|
||||
class MTPDupdateNewStickerSet : public mtpDataImpl<MTPDupdateNewStickerSet> {
|
||||
public:
|
||||
MTPDupdateNewStickerSet() {
|
||||
}
|
||||
MTPDupdateNewStickerSet(const MTPmessages_StickerSet &_stickerset) : vstickerset(_stickerset) {
|
||||
}
|
||||
|
||||
MTPmessages_StickerSet vstickerset;
|
||||
};
|
||||
|
||||
class MTPDupdateStickerSetsOrder : public mtpDataImpl<MTPDupdateStickerSetsOrder> {
|
||||
public:
|
||||
MTPDupdateStickerSetsOrder() {
|
||||
}
|
||||
MTPDupdateStickerSetsOrder(const MTPVector<MTPlong> &_order) : vorder(_order) {
|
||||
}
|
||||
|
||||
MTPVector<MTPlong> vorder;
|
||||
};
|
||||
|
||||
class MTPDupdates_state : public mtpDataImpl<MTPDupdates_state> {
|
||||
public:
|
||||
MTPDupdates_state() {
|
||||
|
@ -11914,10 +12065,10 @@ class MTPDmessages_allStickers : public mtpDataImpl<MTPDmessages_allStickers> {
|
|||
public:
|
||||
MTPDmessages_allStickers() {
|
||||
}
|
||||
MTPDmessages_allStickers(const MTPstring &_hash, const MTPVector<MTPStickerSet> &_sets) : vhash(_hash), vsets(_sets) {
|
||||
MTPDmessages_allStickers(MTPint _hash, const MTPVector<MTPStickerSet> &_sets) : vhash(_hash), vsets(_sets) {
|
||||
}
|
||||
|
||||
MTPstring vhash;
|
||||
MTPint vhash;
|
||||
MTPVector<MTPStickerSet> vsets;
|
||||
};
|
||||
|
||||
|
@ -12696,6 +12847,16 @@ public:
|
|||
MTPVector<MTPUser> vusers;
|
||||
};
|
||||
|
||||
class MTPDhelp_termsOfService : public mtpDataImpl<MTPDhelp_termsOfService> {
|
||||
public:
|
||||
MTPDhelp_termsOfService() {
|
||||
}
|
||||
MTPDhelp_termsOfService(const MTPstring &_text) : vtext(_text) {
|
||||
}
|
||||
|
||||
MTPstring vtext;
|
||||
};
|
||||
|
||||
// RPC methods
|
||||
|
||||
class MTPreq_pq { // RPC method 'req_pq'
|
||||
|
@ -14287,6 +14448,48 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MTPaccount_reportPeer { // RPC method 'account.reportPeer'
|
||||
public:
|
||||
MTPInputPeer vpeer;
|
||||
MTPReportReason vreason;
|
||||
|
||||
MTPaccount_reportPeer() {
|
||||
}
|
||||
MTPaccount_reportPeer(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_reportPeer) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPaccount_reportPeer(const MTPInputPeer &_peer, const MTPReportReason &_reason) : vpeer(_peer), vreason(_reason) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
return vpeer.innerLength() + vreason.innerLength();
|
||||
}
|
||||
mtpTypeId type() const {
|
||||
return mtpc_account_reportPeer;
|
||||
}
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_account_reportPeer) {
|
||||
vpeer.read(from, end);
|
||||
vreason.read(from, end);
|
||||
}
|
||||
void write(mtpBuffer &to) const {
|
||||
vpeer.write(to);
|
||||
vreason.write(to);
|
||||
}
|
||||
|
||||
typedef MTPBool ResponseType;
|
||||
};
|
||||
class MTPaccount_ReportPeer : public MTPBoxed<MTPaccount_reportPeer> {
|
||||
public:
|
||||
MTPaccount_ReportPeer() {
|
||||
}
|
||||
MTPaccount_ReportPeer(const MTPaccount_reportPeer &v) : MTPBoxed<MTPaccount_reportPeer>(v) {
|
||||
}
|
||||
MTPaccount_ReportPeer(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPaccount_reportPeer>(from, end, cons) {
|
||||
}
|
||||
MTPaccount_ReportPeer(const MTPInputPeer &_peer, const MTPReportReason &_reason) : MTPBoxed<MTPaccount_reportPeer>(MTPaccount_reportPeer(_peer, _reason)) {
|
||||
}
|
||||
};
|
||||
|
||||
class MTPaccount_checkUsername { // RPC method 'account.checkUsername'
|
||||
public:
|
||||
MTPstring vusername;
|
||||
|
@ -16982,14 +17185,14 @@ public:
|
|||
|
||||
class MTPmessages_getAllStickers { // RPC method 'messages.getAllStickers'
|
||||
public:
|
||||
MTPstring vhash;
|
||||
MTPint vhash;
|
||||
|
||||
MTPmessages_getAllStickers() {
|
||||
}
|
||||
MTPmessages_getAllStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getAllStickers) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPmessages_getAllStickers(const MTPstring &_hash) : vhash(_hash) {
|
||||
MTPmessages_getAllStickers(MTPint _hash) : vhash(_hash) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
|
@ -17015,7 +17218,7 @@ public:
|
|||
}
|
||||
MTPmessages_GetAllStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_getAllStickers>(from, end, cons) {
|
||||
}
|
||||
MTPmessages_GetAllStickers(const MTPstring &_hash) : MTPBoxed<MTPmessages_getAllStickers>(MTPmessages_getAllStickers(_hash)) {
|
||||
MTPmessages_GetAllStickers(MTPint _hash) : MTPBoxed<MTPmessages_getAllStickers>(MTPmessages_getAllStickers(_hash)) {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -17565,6 +17768,45 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MTPmessages_reorderStickerSets { // RPC method 'messages.reorderStickerSets'
|
||||
public:
|
||||
MTPVector<MTPlong> vorder;
|
||||
|
||||
MTPmessages_reorderStickerSets() {
|
||||
}
|
||||
MTPmessages_reorderStickerSets(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_reorderStickerSets) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPmessages_reorderStickerSets(const MTPVector<MTPlong> &_order) : vorder(_order) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
return vorder.innerLength();
|
||||
}
|
||||
mtpTypeId type() const {
|
||||
return mtpc_messages_reorderStickerSets;
|
||||
}
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_reorderStickerSets) {
|
||||
vorder.read(from, end);
|
||||
}
|
||||
void write(mtpBuffer &to) const {
|
||||
vorder.write(to);
|
||||
}
|
||||
|
||||
typedef MTPBool ResponseType;
|
||||
};
|
||||
class MTPmessages_ReorderStickerSets : public MTPBoxed<MTPmessages_reorderStickerSets> {
|
||||
public:
|
||||
MTPmessages_ReorderStickerSets() {
|
||||
}
|
||||
MTPmessages_ReorderStickerSets(const MTPmessages_reorderStickerSets &v) : MTPBoxed<MTPmessages_reorderStickerSets>(v) {
|
||||
}
|
||||
MTPmessages_ReorderStickerSets(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_reorderStickerSets>(from, end, cons) {
|
||||
}
|
||||
MTPmessages_ReorderStickerSets(const MTPVector<MTPlong> &_order) : MTPBoxed<MTPmessages_reorderStickerSets>(MTPmessages_reorderStickerSets(_order)) {
|
||||
}
|
||||
};
|
||||
|
||||
class MTPupdates_getState { // RPC method 'updates.getState'
|
||||
public:
|
||||
MTPupdates_getState() {
|
||||
|
@ -18271,6 +18513,45 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MTPhelp_getTermsOfService { // RPC method 'help.getTermsOfService'
|
||||
public:
|
||||
MTPstring vlang_code;
|
||||
|
||||
MTPhelp_getTermsOfService() {
|
||||
}
|
||||
MTPhelp_getTermsOfService(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getTermsOfService) {
|
||||
read(from, end, cons);
|
||||
}
|
||||
MTPhelp_getTermsOfService(const MTPstring &_lang_code) : vlang_code(_lang_code) {
|
||||
}
|
||||
|
||||
uint32 innerLength() const {
|
||||
return vlang_code.innerLength();
|
||||
}
|
||||
mtpTypeId type() const {
|
||||
return mtpc_help_getTermsOfService;
|
||||
}
|
||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getTermsOfService) {
|
||||
vlang_code.read(from, end);
|
||||
}
|
||||
void write(mtpBuffer &to) const {
|
||||
vlang_code.write(to);
|
||||
}
|
||||
|
||||
typedef MTPhelp_TermsOfService ResponseType;
|
||||
};
|
||||
class MTPhelp_GetTermsOfService : public MTPBoxed<MTPhelp_getTermsOfService> {
|
||||
public:
|
||||
MTPhelp_GetTermsOfService() {
|
||||
}
|
||||
MTPhelp_GetTermsOfService(const MTPhelp_getTermsOfService &v) : MTPBoxed<MTPhelp_getTermsOfService>(v) {
|
||||
}
|
||||
MTPhelp_GetTermsOfService(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPhelp_getTermsOfService>(from, end, cons) {
|
||||
}
|
||||
MTPhelp_GetTermsOfService(const MTPstring &_lang_code) : MTPBoxed<MTPhelp_getTermsOfService>(MTPhelp_getTermsOfService(_lang_code)) {
|
||||
}
|
||||
};
|
||||
|
||||
class MTPchannels_getDialogs { // RPC method 'channels.getDialogs'
|
||||
public:
|
||||
MTPint voffset;
|
||||
|
@ -23627,6 +23908,65 @@ inline MTPwallPaper MTP_wallPaperSolid(MTPint _id, const MTPstring &_title, MTPi
|
|||
return MTPwallPaper(new MTPDwallPaperSolid(_id, _title, _bg_color, _color));
|
||||
}
|
||||
|
||||
inline uint32 MTPreportReason::innerLength() const {
|
||||
switch (_type) {
|
||||
case mtpc_inputReportReasonOther: {
|
||||
const MTPDinputReportReasonOther &v(c_inputReportReasonOther());
|
||||
return v.vtext.innerLength();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
inline mtpTypeId MTPreportReason::type() const {
|
||||
if (!_type) throw mtpErrorUninitialized();
|
||||
return _type;
|
||||
}
|
||||
inline void MTPreportReason::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
|
||||
if (cons != _type) setData(0);
|
||||
switch (cons) {
|
||||
case mtpc_inputReportReasonSpam: _type = cons; break;
|
||||
case mtpc_inputReportReasonViolence: _type = cons; break;
|
||||
case mtpc_inputReportReasonPornography: _type = cons; break;
|
||||
case mtpc_inputReportReasonOther: _type = cons; {
|
||||
if (!data) setData(new MTPDinputReportReasonOther());
|
||||
MTPDinputReportReasonOther &v(_inputReportReasonOther());
|
||||
v.vtext.read(from, end);
|
||||
} break;
|
||||
default: throw mtpErrorUnexpected(cons, "MTPreportReason");
|
||||
}
|
||||
}
|
||||
inline void MTPreportReason::write(mtpBuffer &to) const {
|
||||
switch (_type) {
|
||||
case mtpc_inputReportReasonOther: {
|
||||
const MTPDinputReportReasonOther &v(c_inputReportReasonOther());
|
||||
v.vtext.write(to);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
inline MTPreportReason::MTPreportReason(mtpTypeId type) : mtpDataOwner(0), _type(type) {
|
||||
switch (type) {
|
||||
case mtpc_inputReportReasonSpam: break;
|
||||
case mtpc_inputReportReasonViolence: break;
|
||||
case mtpc_inputReportReasonPornography: break;
|
||||
case mtpc_inputReportReasonOther: setData(new MTPDinputReportReasonOther()); break;
|
||||
default: throw mtpErrorBadTypeId(type, "MTPreportReason");
|
||||
}
|
||||
}
|
||||
inline MTPreportReason::MTPreportReason(MTPDinputReportReasonOther *_data) : mtpDataOwner(_data), _type(mtpc_inputReportReasonOther) {
|
||||
}
|
||||
inline MTPreportReason MTP_inputReportReasonSpam() {
|
||||
return MTPreportReason(mtpc_inputReportReasonSpam);
|
||||
}
|
||||
inline MTPreportReason MTP_inputReportReasonViolence() {
|
||||
return MTPreportReason(mtpc_inputReportReasonViolence);
|
||||
}
|
||||
inline MTPreportReason MTP_inputReportReasonPornography() {
|
||||
return MTPreportReason(mtpc_inputReportReasonPornography);
|
||||
}
|
||||
inline MTPreportReason MTP_inputReportReasonOther(const MTPstring &_text) {
|
||||
return MTPreportReason(new MTPDinputReportReasonOther(_text));
|
||||
}
|
||||
|
||||
inline MTPuserFull::MTPuserFull() : mtpDataOwner(new MTPDuserFull()) {
|
||||
}
|
||||
|
||||
|
@ -24507,6 +24847,14 @@ inline uint32 MTPupdate::innerLength() const {
|
|||
const MTPDupdateChatParticipantAdmin &v(c_updateChatParticipantAdmin());
|
||||
return v.vchat_id.innerLength() + v.vuser_id.innerLength() + v.vis_admin.innerLength() + v.vversion.innerLength();
|
||||
}
|
||||
case mtpc_updateNewStickerSet: {
|
||||
const MTPDupdateNewStickerSet &v(c_updateNewStickerSet());
|
||||
return v.vstickerset.innerLength();
|
||||
}
|
||||
case mtpc_updateStickerSetsOrder: {
|
||||
const MTPDupdateStickerSetsOrder &v(c_updateStickerSetsOrder());
|
||||
return v.vorder.innerLength();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -24764,6 +25112,17 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
|
|||
v.vis_admin.read(from, end);
|
||||
v.vversion.read(from, end);
|
||||
} break;
|
||||
case mtpc_updateNewStickerSet: _type = cons; {
|
||||
if (!data) setData(new MTPDupdateNewStickerSet());
|
||||
MTPDupdateNewStickerSet &v(_updateNewStickerSet());
|
||||
v.vstickerset.read(from, end);
|
||||
} break;
|
||||
case mtpc_updateStickerSetsOrder: _type = cons; {
|
||||
if (!data) setData(new MTPDupdateStickerSetsOrder());
|
||||
MTPDupdateStickerSetsOrder &v(_updateStickerSetsOrder());
|
||||
v.vorder.read(from, end);
|
||||
} break;
|
||||
case mtpc_updateStickerSets: _type = cons; break;
|
||||
default: throw mtpErrorUnexpected(cons, "MTPupdate");
|
||||
}
|
||||
}
|
||||
|
@ -24979,6 +25338,14 @@ inline void MTPupdate::write(mtpBuffer &to) const {
|
|||
v.vis_admin.write(to);
|
||||
v.vversion.write(to);
|
||||
} break;
|
||||
case mtpc_updateNewStickerSet: {
|
||||
const MTPDupdateNewStickerSet &v(c_updateNewStickerSet());
|
||||
v.vstickerset.write(to);
|
||||
} break;
|
||||
case mtpc_updateStickerSetsOrder: {
|
||||
const MTPDupdateStickerSetsOrder &v(c_updateStickerSetsOrder());
|
||||
v.vorder.write(to);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) {
|
||||
|
@ -25020,6 +25387,9 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) {
|
|||
case mtpc_updateChannelMessageViews: setData(new MTPDupdateChannelMessageViews()); break;
|
||||
case mtpc_updateChatAdmins: setData(new MTPDupdateChatAdmins()); break;
|
||||
case mtpc_updateChatParticipantAdmin: setData(new MTPDupdateChatParticipantAdmin()); break;
|
||||
case mtpc_updateNewStickerSet: setData(new MTPDupdateNewStickerSet()); break;
|
||||
case mtpc_updateStickerSetsOrder: setData(new MTPDupdateStickerSetsOrder()); break;
|
||||
case mtpc_updateStickerSets: break;
|
||||
default: throw mtpErrorBadTypeId(type, "MTPupdate");
|
||||
}
|
||||
}
|
||||
|
@ -25097,6 +25467,10 @@ inline MTPupdate::MTPupdate(MTPDupdateChatAdmins *_data) : mtpDataOwner(_data),
|
|||
}
|
||||
inline MTPupdate::MTPupdate(MTPDupdateChatParticipantAdmin *_data) : mtpDataOwner(_data), _type(mtpc_updateChatParticipantAdmin) {
|
||||
}
|
||||
inline MTPupdate::MTPupdate(MTPDupdateNewStickerSet *_data) : mtpDataOwner(_data), _type(mtpc_updateNewStickerSet) {
|
||||
}
|
||||
inline MTPupdate::MTPupdate(MTPDupdateStickerSetsOrder *_data) : mtpDataOwner(_data), _type(mtpc_updateStickerSetsOrder) {
|
||||
}
|
||||
inline MTPupdate MTP_updateNewMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count) {
|
||||
return MTPupdate(new MTPDupdateNewMessage(_message, _pts, _pts_count));
|
||||
}
|
||||
|
@ -25208,6 +25582,15 @@ inline MTPupdate MTP_updateChatAdmins(MTPint _chat_id, MTPBool _enabled, MTPint
|
|||
inline MTPupdate MTP_updateChatParticipantAdmin(MTPint _chat_id, MTPint _user_id, MTPBool _is_admin, MTPint _version) {
|
||||
return MTPupdate(new MTPDupdateChatParticipantAdmin(_chat_id, _user_id, _is_admin, _version));
|
||||
}
|
||||
inline MTPupdate MTP_updateNewStickerSet(const MTPmessages_StickerSet &_stickerset) {
|
||||
return MTPupdate(new MTPDupdateNewStickerSet(_stickerset));
|
||||
}
|
||||
inline MTPupdate MTP_updateStickerSetsOrder(const MTPVector<MTPlong> &_order) {
|
||||
return MTPupdate(new MTPDupdateStickerSetsOrder(_order));
|
||||
}
|
||||
inline MTPupdate MTP_updateStickerSets() {
|
||||
return MTPupdate(mtpc_updateStickerSets);
|
||||
}
|
||||
|
||||
inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) {
|
||||
}
|
||||
|
@ -27495,7 +27878,7 @@ inline MTPmessages_allStickers::MTPmessages_allStickers(MTPDmessages_allStickers
|
|||
inline MTPmessages_allStickers MTP_messages_allStickersNotModified() {
|
||||
return MTPmessages_allStickers(mtpc_messages_allStickersNotModified);
|
||||
}
|
||||
inline MTPmessages_allStickers MTP_messages_allStickers(const MTPstring &_hash, const MTPVector<MTPStickerSet> &_sets) {
|
||||
inline MTPmessages_allStickers MTP_messages_allStickers(MTPint _hash, const MTPVector<MTPStickerSet> &_sets) {
|
||||
return MTPmessages_allStickers(new MTPDmessages_allStickers(_hash, _sets));
|
||||
}
|
||||
|
||||
|
@ -29383,6 +29766,33 @@ inline MTPchannels_channelParticipant MTP_channels_channelParticipant(const MTPC
|
|||
return MTPchannels_channelParticipant(new MTPDchannels_channelParticipant(_participant, _users));
|
||||
}
|
||||
|
||||
inline MTPhelp_termsOfService::MTPhelp_termsOfService() : mtpDataOwner(new MTPDhelp_termsOfService()) {
|
||||
}
|
||||
|
||||
inline uint32 MTPhelp_termsOfService::innerLength() const {
|
||||
const MTPDhelp_termsOfService &v(c_help_termsOfService());
|
||||
return v.vtext.innerLength();
|
||||
}
|
||||
inline mtpTypeId MTPhelp_termsOfService::type() const {
|
||||
return mtpc_help_termsOfService;
|
||||
}
|
||||
inline void MTPhelp_termsOfService::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
|
||||
if (cons != mtpc_help_termsOfService) throw mtpErrorUnexpected(cons, "MTPhelp_termsOfService");
|
||||
|
||||
if (!data) setData(new MTPDhelp_termsOfService());
|
||||
MTPDhelp_termsOfService &v(_help_termsOfService());
|
||||
v.vtext.read(from, end);
|
||||
}
|
||||
inline void MTPhelp_termsOfService::write(mtpBuffer &to) const {
|
||||
const MTPDhelp_termsOfService &v(c_help_termsOfService());
|
||||
v.vtext.write(to);
|
||||
}
|
||||
inline MTPhelp_termsOfService::MTPhelp_termsOfService(MTPDhelp_termsOfService *_data) : mtpDataOwner(_data) {
|
||||
}
|
||||
inline MTPhelp_termsOfService MTP_help_termsOfService(const MTPstring &_text) {
|
||||
return MTPhelp_termsOfService(new MTPDhelp_termsOfService(_text));
|
||||
}
|
||||
|
||||
// Human-readable text serialization
|
||||
#if (defined _DEBUG || defined _WITH_DEBUG)
|
||||
|
||||
|
|
|
@ -305,6 +305,11 @@ peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool event
|
|||
wallPaper#ccb03657 id:int title:string sizes:Vector<PhotoSize> color:int = WallPaper;
|
||||
wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper;
|
||||
|
||||
inputReportReasonSpam#58dbcab8 = ReportReason;
|
||||
inputReportReasonViolence#1e22c78d = ReportReason;
|
||||
inputReportReasonPornography#2e59d922 = ReportReason;
|
||||
inputReportReasonOther#e1746d0a text:string = ReportReason;
|
||||
|
||||
userFull#5a89ac5b user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool bot_info:BotInfo = UserFull;
|
||||
|
||||
contact#f911c994 user_id:int mutual:Bool = Contact;
|
||||
|
@ -389,6 +394,9 @@ updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector<int> pts:int
|
|||
updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update;
|
||||
updateChatAdmins#6e947941 chat_id:int enabled:Bool version:int = Update;
|
||||
updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update;
|
||||
updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update;
|
||||
updateStickerSetsOrder#f0dfb451 order:Vector<long> = Update;
|
||||
updateStickerSets#43ae3dec = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
|
@ -516,7 +524,7 @@ messages.stickers#8a8ecd32 hash:string stickers:Vector<Document> = messages.Stic
|
|||
stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
|
||||
|
||||
messages.allStickersNotModified#e86602c3 = messages.AllStickers;
|
||||
messages.allStickers#d51dafdb hash:string sets:Vector<StickerSet> = messages.AllStickers;
|
||||
messages.allStickers#edfd405f hash:int sets:Vector<StickerSet> = messages.AllStickers;
|
||||
|
||||
disabledFeature#ae636f24 feature:string description:string = DisabledFeature;
|
||||
|
||||
|
@ -625,6 +633,8 @@ channels.channelParticipants#f56ee2a8 count:int participants:Vector<ChannelParti
|
|||
|
||||
channels.channelParticipant#d0d9b163 participant:ChannelParticipant users:Vector<User> = channels.ChannelParticipant;
|
||||
|
||||
help.termsOfService#f1ee3e90 text:string = help.TermsOfService;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
|
@ -658,6 +668,7 @@ account.resetNotifySettings#db7e1747 = Bool;
|
|||
account.updateProfile#f0888d68 first_name:string last_name:string = User;
|
||||
account.updateStatus#6628562c offline:Bool = Bool;
|
||||
account.getWallPapers#c04cfac2 = Vector<WallPaper>;
|
||||
account.reportPeer#ae189d5f peer:InputPeer reason:ReportReason = Bool;
|
||||
account.checkUsername#2714d86c username:string = Bool;
|
||||
account.updateUsername#3e0bdd7c username:string = User;
|
||||
account.getPrivacy#dadbc950 key:InputPrivacyKey = account.PrivacyRules;
|
||||
|
@ -725,7 +736,7 @@ messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long da
|
|||
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
|
||||
messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages;
|
||||
messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers;
|
||||
messages.getAllStickers#aa3bc868 hash:string = messages.AllStickers;
|
||||
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
||||
messages.getWebPagePreview#25223e24 message:string = MessageMedia;
|
||||
messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite;
|
||||
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
|
||||
|
@ -739,6 +750,7 @@ messages.toggleChatAdmins#ec8bd9e1 chat_id:int enabled:Bool = Updates;
|
|||
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
||||
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
||||
messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.reorderStickerSets#9fcfbc30 order:Vector<long> = Bool;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;
|
||||
|
@ -760,6 +772,7 @@ help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
|
|||
help.getInviteText#a4a95186 lang_code:string = help.InviteText;
|
||||
help.getSupport#9cdf08cd = help.Support;
|
||||
help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_version:string lang_code:string = help.AppChangelog;
|
||||
help.getTermsOfService#37d78f83 lang_code:string = help.TermsOfService;
|
||||
|
||||
channels.getDialogs#a9d3d249 offset:int limit:int = messages.Dialogs;
|
||||
channels.getImportantHistory#ddb929cb channel:InputChannel offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
|
|
|
@ -1878,7 +1878,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
_menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true);
|
||||
} else {
|
||||
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
|
||||
_menu->addAction(lang(cPlatform() == dbipMac ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
|
||||
_menu->addAction(lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(showContextInFolder()))->setEnabled(true);
|
||||
}
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_open_video : (lnkAudio ? lng_context_open_audio : lng_context_open_file)), this, SLOT(openContextFile()))->setEnabled(true);
|
||||
_menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkAudio ? lng_context_save_audio : lng_context_save_file)), this, SLOT(saveContextFile()))->setEnabled(true);
|
||||
|
|
|
@ -78,7 +78,6 @@ void PasscodeWidget::onSubmit() {
|
|||
} else {
|
||||
if (Local::readMap(_passcode.text().toUtf8()) != Local::ReadMapPassNeeded) {
|
||||
cSetPasscodeBadTries(0);
|
||||
App::app()->checkMapVersion();
|
||||
|
||||
MTP::start();
|
||||
if (MTP::authedId()) {
|
||||
|
@ -86,6 +85,8 @@ void PasscodeWidget::onSubmit() {
|
|||
} else {
|
||||
App::wnd()->setupIntro(true);
|
||||
}
|
||||
|
||||
App::app()->checkMapVersion();
|
||||
} else {
|
||||
cSetPasscodeBadTries(cPasscodeBadTries() + 1);
|
||||
cSetPasscodeLastTry(getms(true));
|
||||
|
|
|
@ -323,7 +323,7 @@ void PlayerWidget::preloadNext() {
|
|||
}
|
||||
if (next) {
|
||||
if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) {
|
||||
if (document->document()->already(true).isEmpty() && document->document()->data.isEmpty()) {
|
||||
if (document->document()->location(true).isEmpty() && document->document()->data.isEmpty()) {
|
||||
if (!document->document()->loader) {
|
||||
DocumentOpenLink::doOpen(document->document());
|
||||
document->document()->openOnSave = 0;
|
||||
|
|
|
@ -1167,7 +1167,7 @@ namespace {
|
|||
void psRegisterCustomScheme() {
|
||||
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
||||
QString home(_psHomeDir());
|
||||
if (home.isEmpty()) return;
|
||||
if (home.isEmpty() || cBetaVersion()) return; // don't update desktop file for beta version
|
||||
|
||||
DEBUG_LOG(("App Info: placing .desktop file"));
|
||||
if (QDir(home + qsl(".local/")).exists()) {
|
||||
|
|
|
@ -175,5 +175,34 @@ void psUpdateOverlayed(QWidget *widget);
|
|||
inline QString psConvertFileUrl(const QString &url) {
|
||||
return url;
|
||||
}
|
||||
inline QByteArray psDownloadPathBookmark(const QString &path) {
|
||||
return QByteArray();
|
||||
}
|
||||
inline QByteArray psPathBookmark(const QString &path) {
|
||||
return QByteArray();
|
||||
}
|
||||
inline void psDownloadPathEnableAccess() {
|
||||
}
|
||||
|
||||
class PsFileBookmark {
|
||||
public:
|
||||
PsFileBookmark(const QByteArray &bookmark) {
|
||||
}
|
||||
bool check() const {
|
||||
return true;
|
||||
}
|
||||
bool enable() const {
|
||||
return true;
|
||||
}
|
||||
void disable() const {
|
||||
}
|
||||
const QString &name(const QString &original) const {
|
||||
return original;
|
||||
}
|
||||
QByteArray bookmark() const {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool linuxMoveFile(const char *from, const char *to);
|
||||
|
|
|
@ -684,6 +684,18 @@ QString psConvertFileUrl(const QString &url) {
|
|||
return objc_convertFileUrl(url);
|
||||
}
|
||||
|
||||
void psDownloadPathEnableAccess() {
|
||||
objc_downloadPathEnableAccess(cDownloadPathBookmark());
|
||||
}
|
||||
|
||||
QByteArray psDownloadPathBookmark(const QString &path) {
|
||||
return objc_downloadPathBookmark(path);
|
||||
}
|
||||
|
||||
QByteArray psPathBookmark(const QString &path) {
|
||||
return objc_pathBookmark(path);
|
||||
}
|
||||
|
||||
QString strNotificationAboutThemeChange() {
|
||||
const uint32 letters[] = { 0xE9005541, 0x5600DC70, 0x88001570, 0xF500D86C, 0x8100E165, 0xEE005949, 0x2900526E, 0xAE00FB74, 0x96000865, 0x7000CD72, 0x3B001566, 0x5F007361, 0xAE00B663, 0x74009A65, 0x29003054, 0xC6002668, 0x98003865, 0xFA00336D, 0xA3007A65, 0x93001443, 0xBB007868, 0xE100E561, 0x3500366E, 0xC0007A67, 0x200CA65, 0xBE00DF64, 0xE300BB4E, 0x2900D26F, 0xD500D374, 0xE900E269, 0x86008F66, 0xC4006669, 0x1C00A863, 0xE600A761, 0x8E00EE74, 0xB300B169, 0xCF00B36F, 0xE600D36E };
|
||||
return strMakeFromLetters(letters, sizeof(letters) / sizeof(letters[0]));
|
||||
|
|
|
@ -198,6 +198,35 @@ void psNewVersion();
|
|||
void psUpdateOverlayed(QWidget *widget);
|
||||
QString psConvertFileUrl(const QString &url);
|
||||
|
||||
void psDownloadPathEnableAccess();
|
||||
QByteArray psDownloadPathBookmark(const QString &path);
|
||||
QByteArray psPathBookmark(const QString &path);
|
||||
|
||||
class PsFileBookmark {
|
||||
public:
|
||||
PsFileBookmark(const QByteArray &bookmark) : _inner(bookmark) {
|
||||
}
|
||||
bool check() const {
|
||||
return _inner.valid();
|
||||
}
|
||||
bool enable() const {
|
||||
return _inner.enable();
|
||||
}
|
||||
void disable() const {
|
||||
return _inner.disable();
|
||||
}
|
||||
const QString &name(const QString &original) const {
|
||||
return _inner.name(original);
|
||||
}
|
||||
QByteArray bookmark() const {
|
||||
return _inner.bookmark();
|
||||
}
|
||||
|
||||
private:
|
||||
objc_FileBookmark _inner;
|
||||
|
||||
};
|
||||
|
||||
QString strNotificationAboutThemeChange();
|
||||
QString strStyleOfInterface();
|
||||
QString strNeedToReload();
|
||||
|
|
|
@ -82,3 +82,20 @@ QString objc_downloadPath();
|
|||
QString objc_currentCountry();
|
||||
QString objc_currentLang();
|
||||
QString objc_convertFileUrl(const QString &url);
|
||||
QByteArray objc_downloadPathBookmark(const QString &path);
|
||||
QByteArray objc_pathBookmark(const QString &path);
|
||||
void objc_downloadPathEnableAccess(const QByteArray &bookmark);
|
||||
|
||||
class objc_FileBookmark {
|
||||
public:
|
||||
objc_FileBookmark(const QByteArray &bookmark);
|
||||
bool valid() const;
|
||||
bool enable() const;
|
||||
void disable() const;
|
||||
|
||||
const QString &name(const QString &original) const;
|
||||
QByteArray bookmark() const;
|
||||
|
||||
~objc_FileBookmark();
|
||||
|
||||
};
|
||||
|
|
|
@ -931,8 +931,16 @@ void objc_start() {
|
|||
name: NSWorkspaceDidWakeNotification object: NULL];
|
||||
}
|
||||
|
||||
namespace {
|
||||
NSURL *_downloadPathUrl = nil;
|
||||
}
|
||||
|
||||
void objc_finish() {
|
||||
[_sharedDelegate release];
|
||||
if (_downloadPathUrl) {
|
||||
[_downloadPathUrl stopAccessingSecurityScopedResource];
|
||||
_downloadPathUrl = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void objc_registerCustomScheme() {
|
||||
|
@ -1054,3 +1062,38 @@ QString objc_convertFileUrl(const QString &url) {
|
|||
return objcString(nsurl);
|
||||
}
|
||||
|
||||
QByteArray objc_downloadPathBookmark(const QString &path) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray objc_pathBookmark(const QString &path) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
void objc_downloadPathEnableAccess(const QByteArray &bookmark) {
|
||||
}
|
||||
|
||||
objc_FileBookmark::objc_FileBookmark(const QByteArray &bookmark) {
|
||||
}
|
||||
|
||||
bool objc_FileBookmark::valid() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool objc_FileBookmark::enable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void objc_FileBookmark::disable() const {
|
||||
}
|
||||
|
||||
const QString &objc_FileBookmark::name(const QString &original) const {
|
||||
return original;
|
||||
}
|
||||
|
||||
QByteArray objc_FileBookmark::bookmark() const {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
objc_FileBookmark::~objc_FileBookmark() {
|
||||
}
|
||||
|
|
|
@ -72,7 +72,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#define WM_NCPOINTERUP 0x0243
|
||||
#endif
|
||||
|
||||
const WCHAR AppUserModelId[] = L"Telegram.TelegramDesktop";
|
||||
const WCHAR AppUserModelIdRelease[] = L"Telegram.TelegramDesktop";
|
||||
const WCHAR AppUserModelIdBeta[] = L"Telegram.TelegramDesktop.Beta";
|
||||
|
||||
const WCHAR *AppUserModelId() {
|
||||
return cBetaVersion() ? AppUserModelIdBeta : AppUserModelIdRelease;
|
||||
}
|
||||
|
||||
static const PROPERTYKEY pkey_AppUserModel_ID = { { 0x9F4C2855, 0x9F79, 0x4B39, { 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 5 };
|
||||
static const PROPERTYKEY pkey_AppUserModel_StartPinOption = { { 0x9F4C2855, 0x9F79, 0x4B39, { 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 12 };
|
||||
|
@ -2301,7 +2306,7 @@ void _manageAppLnk(bool create, bool silent, int path_csidl, const wchar_t *args
|
|||
hr = shellLink.As(&propertyStore);
|
||||
if (SUCCEEDED(hr)) {
|
||||
PROPVARIANT appIdPropVar;
|
||||
hr = InitPropVariantFromString(AppUserModelId, &appIdPropVar);
|
||||
hr = InitPropVariantFromString(AppUserModelId(), &appIdPropVar);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = propertyStore->SetValue(pkey_AppUserModel_ID, appIdPropVar);
|
||||
PropVariantClear(&appIdPropVar);
|
||||
|
@ -2390,11 +2395,19 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
|||
|
||||
GetLocalTime(&stLocalTime);
|
||||
|
||||
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
|
||||
szPath, szExeName, AppVersionStr,
|
||||
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
||||
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
|
||||
GetCurrentProcessId(), GetCurrentThreadId());
|
||||
if (cBetaVersion()) {
|
||||
wsprintf(szFileName, L"%s%s-%ld-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
|
||||
szPath, szExeName, cBetaVersion(),
|
||||
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
||||
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
|
||||
GetCurrentProcessId(), GetCurrentThreadId());
|
||||
} else {
|
||||
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
|
||||
szPath, szExeName, AppVersionStr,
|
||||
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
||||
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
|
||||
GetCurrentProcessId(), GetCurrentThreadId());
|
||||
}
|
||||
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -2913,7 +2926,7 @@ void CheckPinnedAppUserModelId() {
|
|||
WCHAR already[MAX_PATH];
|
||||
hr = propVariantToString(appIdPropVar, already, MAX_PATH);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (std::wstring(AppUserModelId) == already) {
|
||||
if (std::wstring(AppUserModelId()) == already) {
|
||||
LOG(("Already!"));
|
||||
PropVariantClear(&appIdPropVar);
|
||||
return;
|
||||
|
@ -2925,7 +2938,7 @@ void CheckPinnedAppUserModelId() {
|
|||
}
|
||||
PropVariantClear(&appIdPropVar);
|
||||
|
||||
hr = InitPropVariantFromString(AppUserModelId, &appIdPropVar);
|
||||
hr = InitPropVariantFromString(AppUserModelId(), &appIdPropVar);
|
||||
if (!SUCCEEDED(hr)) return;
|
||||
|
||||
hr = propertyStore->SetValue(pkey_AppUserModel_ID, appIdPropVar);
|
||||
|
@ -3020,7 +3033,7 @@ bool ValidateAppUserModelIdShortcutAt(const QString &path) {
|
|||
WCHAR already[MAX_PATH];
|
||||
hr = propVariantToString(appIdPropVar, already, MAX_PATH);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (std::wstring(AppUserModelId) == already) {
|
||||
if (std::wstring(AppUserModelId()) == already) {
|
||||
PropVariantClear(&appIdPropVar);
|
||||
return true;
|
||||
}
|
||||
|
@ -3031,7 +3044,7 @@ bool ValidateAppUserModelIdShortcutAt(const QString &path) {
|
|||
}
|
||||
PropVariantClear(&appIdPropVar);
|
||||
|
||||
hr = InitPropVariantFromString(AppUserModelId, &appIdPropVar);
|
||||
hr = InitPropVariantFromString(AppUserModelId(), &appIdPropVar);
|
||||
if (!SUCCEEDED(hr)) return false;
|
||||
|
||||
hr = propertyStore->SetValue(pkey_AppUserModel_ID, appIdPropVar);
|
||||
|
@ -3054,11 +3067,16 @@ bool ValidateAppUserModelIdShortcut() {
|
|||
QString path = systemShortcutPath();
|
||||
if (path.isEmpty()) return false;
|
||||
|
||||
if (ValidateAppUserModelIdShortcutAt(path + qsl("Telegram Desktop/Telegram.lnk"))) return true;
|
||||
if (ValidateAppUserModelIdShortcutAt(path + qsl("Telegram Win (Unofficial)/Telegram.lnk"))) return true;
|
||||
|
||||
path += qsl("Telegram.lnk");
|
||||
if (ValidateAppUserModelIdShortcutAt(path)) return true;
|
||||
if (cBetaVersion()) {
|
||||
path += qsl("TelegramBeta.lnk");
|
||||
if (ValidateAppUserModelIdShortcutAt(path)) return true;
|
||||
} else {
|
||||
if (ValidateAppUserModelIdShortcutAt(path + qsl("Telegram Desktop/Telegram.lnk"))) return true;
|
||||
if (ValidateAppUserModelIdShortcutAt(path + qsl("Telegram Win (Unofficial)/Telegram.lnk"))) return true;
|
||||
|
||||
path += qsl("Telegram.lnk");
|
||||
if (ValidateAppUserModelIdShortcutAt(path)) return true;
|
||||
}
|
||||
|
||||
ComPtr<IShellLink> shellLink;
|
||||
HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));
|
||||
|
@ -3078,7 +3096,7 @@ bool ValidateAppUserModelIdShortcut() {
|
|||
if (!SUCCEEDED(hr)) return false;
|
||||
|
||||
PROPVARIANT appIdPropVar;
|
||||
hr = InitPropVariantFromString(AppUserModelId, &appIdPropVar);
|
||||
hr = InitPropVariantFromString(AppUserModelId(), &appIdPropVar);
|
||||
if (!SUCCEEDED(hr)) return false;
|
||||
|
||||
hr = propertyStore->SetValue(pkey_AppUserModel_ID, appIdPropVar);
|
||||
|
@ -3108,13 +3126,13 @@ bool ValidateAppUserModelIdShortcut() {
|
|||
|
||||
bool InitToastManager() {
|
||||
if (!useToast || !ValidateAppUserModelIdShortcut()) return false;
|
||||
if (!SUCCEEDED(setCurrentProcessExplicitAppUserModelID(AppUserModelId))) {
|
||||
if (!SUCCEEDED(setCurrentProcessExplicitAppUserModelID(AppUserModelId()))) {
|
||||
return false;
|
||||
}
|
||||
if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &toastNotificationManager))) {
|
||||
return false;
|
||||
}
|
||||
if (!SUCCEEDED(toastNotificationManager->CreateToastNotifierWithId(StringReferenceWrapper(AppUserModelId).Get(), &toastNotifier))) {
|
||||
if (!SUCCEEDED(toastNotificationManager->CreateToastNotifierWithId(StringReferenceWrapper(AppUserModelId(), wcslen(AppUserModelId())).Get(), &toastNotifier))) {
|
||||
return false;
|
||||
}
|
||||
if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &toastNotificationFactory))) {
|
||||
|
|
|
@ -177,3 +177,32 @@ void psUpdateOverlayed(TWidget *widget);
|
|||
inline QString psConvertFileUrl(const QString &url) {
|
||||
return url;
|
||||
}
|
||||
inline QByteArray psDownloadPathBookmark(const QString &path) {
|
||||
return QByteArray();
|
||||
}
|
||||
inline QByteArray psPathBookmark(const QString &path) {
|
||||
return QByteArray();
|
||||
}
|
||||
inline void psDownloadPathEnableAccess() {
|
||||
}
|
||||
|
||||
class PsFileBookmark {
|
||||
public:
|
||||
PsFileBookmark(const QByteArray &bookmark) {
|
||||
}
|
||||
bool check() const {
|
||||
return true;
|
||||
}
|
||||
bool enable() const {
|
||||
return true;
|
||||
}
|
||||
void disable() const {
|
||||
}
|
||||
const QString &name(const QString &original) const {
|
||||
return original;
|
||||
}
|
||||
QByteArray bookmark() const {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -29,6 +29,10 @@ Qt::LayoutDirection gLangDir = gRtl ? Qt::RightToLeft : Qt::LeftToRight;
|
|||
mtpDcOptions gDcOptions;
|
||||
|
||||
bool gDevVersion = DevVersion;
|
||||
uint64 gBetaVersion = BETA_VERSION;
|
||||
uint64 gRealBetaVersion = BETA_VERSION;
|
||||
QByteArray gBetaPrivateKey;
|
||||
|
||||
bool gTestMode = false;
|
||||
bool gDebug = false;
|
||||
bool gManyInstance = false;
|
||||
|
@ -74,6 +78,7 @@ DBIDefaultAttach gDefaultAttach = dbidaDocument;
|
|||
bool gReplaceEmojis = true;
|
||||
bool gAskDownloadPath = false;
|
||||
QString gDownloadPath;
|
||||
QByteArray gDownloadPathBookmark;
|
||||
|
||||
bool gNeedConfigResave = false;
|
||||
|
||||
|
@ -99,12 +104,11 @@ bool gHasPasscode = false;
|
|||
bool gHasAudioPlayer = true;
|
||||
bool gHasAudioCapture = true;
|
||||
|
||||
DBIEmojiTab gEmojiTab = dbietRecent;
|
||||
RecentEmojiPack gRecentEmojis;
|
||||
RecentEmojisPreload gRecentEmojisPreload;
|
||||
EmojiColorVariants gEmojiVariants;
|
||||
|
||||
QByteArray gStickersHash;
|
||||
int32 gStickersHash = 0;
|
||||
|
||||
RecentStickerPreload gRecentStickersPreload;
|
||||
RecentStickerPack gRecentStickers;
|
||||
|
@ -143,6 +147,7 @@ QUrl gUpdateURL = QUrl(qsl("http://tdesktop.com/linux/tupdates/current"));
|
|||
#else
|
||||
#error Unknown platform
|
||||
#endif
|
||||
bool gIsElCapitan = false;
|
||||
|
||||
bool gContactsReceived = false;
|
||||
bool gDialogsReceived = false;
|
||||
|
@ -168,8 +173,10 @@ ReportSpamStatuses gReportSpamStatuses;
|
|||
|
||||
void settingsParseArgs(int argc, char *argv[]) {
|
||||
#ifdef Q_OS_MAC
|
||||
gIsElCapitan = (QSysInfo::macVersion() >= QSysInfo::MV_10_11);
|
||||
if (QSysInfo::macVersion() < QSysInfo::MV_10_8) {
|
||||
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));
|
||||
gPlatform = dbipMacOld;
|
||||
} else {
|
||||
gCustomNotifies = false;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,9 @@ typedef QMap<int, mtpDcOption> mtpDcOptions;
|
|||
DeclareSetting(mtpDcOptions, DcOptions);
|
||||
|
||||
DeclareSetting(bool, DevVersion);
|
||||
DeclareSetting(uint64, BetaVersion);
|
||||
DeclareSetting(uint64, RealBetaVersion);
|
||||
DeclareSetting(QByteArray, BetaPrivateKey);
|
||||
|
||||
DeclareSetting(bool, TestMode);
|
||||
DeclareSetting(QString, LoggedPhoneNumber);
|
||||
|
@ -80,8 +83,7 @@ DeclareReadSetting(bool, FromAutoStart);
|
|||
DeclareSetting(QString, WorkingDir);
|
||||
inline void cForceWorkingDir(const QString &newDir) {
|
||||
cSetWorkingDir(newDir);
|
||||
QDir dir;
|
||||
if (!gWorkingDir.isEmpty()) dir.mkpath(gWorkingDir);
|
||||
if (!gWorkingDir.isEmpty()) QDir().mkpath(gWorkingDir);
|
||||
}
|
||||
DeclareReadSetting(QString, ExeName);
|
||||
DeclareReadSetting(QString, ExeDir);
|
||||
|
@ -134,6 +136,7 @@ DeclareSetting(bool, ReplaceEmojis);
|
|||
DeclareReadSetting(bool, ManyInstance);
|
||||
DeclareSetting(bool, AskDownloadPath);
|
||||
DeclareSetting(QString, DownloadPath);
|
||||
DeclareSetting(QByteArray, DownloadPathBookmark);
|
||||
DeclareSetting(QByteArray, LocalSalt);
|
||||
DeclareSetting(DBIScale, RealScale);
|
||||
DeclareSetting(DBIScale, ScreenScale);
|
||||
|
@ -168,8 +171,6 @@ T convertScale(T v) {
|
|||
return v;
|
||||
}
|
||||
|
||||
DeclareSetting(DBIEmojiTab, EmojiTab);
|
||||
|
||||
struct EmojiData {
|
||||
EmojiData(uint16 x, uint16 y, uint32 code, uint32 code2, uint16 len, uint16 postfix, uint32 color) : x(x), y(y), code(code), code2(code2), len(len), postfix(postfix), color(color) {
|
||||
}
|
||||
|
@ -196,7 +197,7 @@ RecentEmojiPack &cGetRecentEmojis();
|
|||
|
||||
struct DocumentData;
|
||||
typedef QVector<DocumentData*> StickerPack;
|
||||
DeclareSetting(QByteArray, StickersHash);
|
||||
DeclareSetting(int32, StickersHash);
|
||||
|
||||
typedef QList<QPair<DocumentData*, int16> > RecentStickerPackOld;
|
||||
typedef QVector<QPair<uint64, ushort> > RecentStickerPreload;
|
||||
|
@ -297,6 +298,7 @@ DeclareSetting(bool, CustomNotifies);
|
|||
DeclareReadSetting(uint64, Instance);
|
||||
|
||||
DeclareReadSetting(DBIPlatform, Platform);
|
||||
DeclareReadSetting(bool, IsElCapitan);
|
||||
DeclareReadSetting(QUrl, UpdateURL);
|
||||
|
||||
DeclareSetting(bool, ContactsReceived);
|
||||
|
|
|
@ -38,6 +38,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "boxes/passcodebox.h"
|
||||
#include "boxes/autolockbox.h"
|
||||
#include "boxes/sessionsbox.h"
|
||||
#include "boxes/stickersetbox.h"
|
||||
#include "langloaderplain.h"
|
||||
#include "gui/filedialog.h"
|
||||
|
||||
|
@ -156,9 +157,10 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
|||
// chat options
|
||||
_replaceEmojis(this, lang(lng_settings_replace_emojis), cReplaceEmojis()),
|
||||
_viewEmojis(this, lang(lng_settings_view_emojis)),
|
||||
_stickers(this, lang(lng_stickers_you_have)),
|
||||
|
||||
_enterSend(this, qsl("send_key"), 0, lang(lng_settings_send_enter), !cCtrlEnter()),
|
||||
_ctrlEnterSend(this, qsl("send_key"), 1, lang((cPlatform() == dbipMac) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), cCtrlEnter()),
|
||||
_ctrlEnterSend(this, qsl("send_key"), 1, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), cCtrlEnter()),
|
||||
|
||||
_dontAskDownloadPath(this, lang(lng_download_path_dont_ask), !cAskDownloadPath()),
|
||||
_downloadPathWidth(st::linkFont->width(lang(lng_download_path_label)) + st::linkFont->spacew),
|
||||
|
@ -201,11 +203,12 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
|||
{
|
||||
if (self()) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
|
||||
|
||||
_nameText.setText(st::setNameFont, _nameCache, _textNameOptions);
|
||||
PhotoData *selfPhoto = (self()->photoId && self()->photoId != UnknownPeerPhotoId) ? App::photo(self()->photoId) : 0;
|
||||
if (selfPhoto && selfPhoto->date) _photoLink = TextLinkPtr(new PhotoLink(selfPhoto, self()));
|
||||
MTP::send(MTPusers_GetFullUser(self()->inputUser), rpcDone(&SettingsInner::gotFullSelf), RPCFailHandlerPtr(), 0, 10);
|
||||
App::api()->requestFullPeer(self());
|
||||
onReloadPassword();
|
||||
|
||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(peerUpdated(PeerData *)));
|
||||
|
@ -253,7 +256,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
|||
connect(&_dpiAutoScale, SIGNAL(changed()), this, SLOT(onScaleAuto()));
|
||||
connect(&_dpiSlider, SIGNAL(changed(int32)), this, SLOT(onScaleChange()));
|
||||
|
||||
_curVersionText = lng_settings_current_version(lt_version, QString::fromWCharArray(AppVersionStr) + (cDevVersion() ? " dev" : "")) + ' ';
|
||||
_curVersionText = lng_settings_current_version(lt_version, QString::fromWCharArray(AppVersionStr) + (cDevVersion() ? " dev" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())) + ' ';
|
||||
_curVersionWidth = st::linkFont->width(_curVersionText);
|
||||
_newVersionText = lang(lng_settings_update_ready) + ' ';
|
||||
_newVersionWidth = st::linkFont->width(_newVersionText);
|
||||
|
@ -269,6 +272,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
|||
// chat options
|
||||
connect(&_replaceEmojis, SIGNAL(changed()), this, SLOT(onReplaceEmojis()));
|
||||
connect(&_viewEmojis, SIGNAL(clicked()), this, SLOT(onViewEmojis()));
|
||||
connect(&_stickers, SIGNAL(clicked()), this, SLOT(onStickers()));
|
||||
|
||||
connect(&_enterSend, SIGNAL(changed()), this, SLOT(onEnterSend()));
|
||||
connect(&_ctrlEnterSend, SIGNAL(changed()), this, SLOT(onCtrlEnterSend()));
|
||||
|
@ -343,7 +347,7 @@ void SettingsInner::peerUpdated(PeerData *data) {
|
|||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto, self()));
|
||||
} else {
|
||||
_photoLink = TextLinkPtr();
|
||||
MTP::send(MTPusers_GetFullUser(self()->inputUser), rpcDone(&SettingsInner::gotFullSelf));
|
||||
App::api()->requestFullPeer(self());
|
||||
}
|
||||
} else {
|
||||
_photoLink = TextLinkPtr();
|
||||
|
@ -515,7 +519,8 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
|
|||
p.drawText(_left + st::setHeaderLeft, top + st::setHeaderTop + st::setHeaderFont->ascent, lang(lng_settings_section_chat));
|
||||
top += st::setHeaderSkip;
|
||||
|
||||
top += _replaceEmojis.height() + st::setSectionSkip;
|
||||
top += _replaceEmojis.height() + st::setLittleSkip;
|
||||
top += _stickers.height() + st::setSectionSkip;
|
||||
top += _enterSend.height() + st::setLittleSkip;
|
||||
top += _ctrlEnterSend.height() + st::setSectionSkip;
|
||||
|
||||
|
@ -706,7 +711,8 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
|
|||
if (self()) {
|
||||
top += st::setHeaderSkip;
|
||||
_viewEmojis.move(_left + st::setWidth - _viewEmojis.width(), top + st::cbDefFlat.textTop);
|
||||
_replaceEmojis.move(_left, top); top += _replaceEmojis.height() + st::setSectionSkip;
|
||||
_replaceEmojis.move(_left, top); top += _replaceEmojis.height() + st::setLittleSkip;
|
||||
_stickers.move(_left + st::cbDefFlat.textLeft, top); top += _stickers.height() + st::setSectionSkip;
|
||||
_enterSend.move(_left, top); top += _enterSend.height() + st::setLittleSkip;
|
||||
_ctrlEnterSend.move(_left, top); top += _ctrlEnterSend.height() + st::setSectionSkip;
|
||||
_dontAskDownloadPath.move(_left, top); top += _dontAskDownloadPath.height();
|
||||
|
@ -892,10 +898,9 @@ void SettingsInner::updateBackgroundRect() {
|
|||
update(_left, _tileBackground.y() - st::setLittleSkip - st::setBackgroundSize, st::setBackgroundSize, st::setBackgroundSize);
|
||||
}
|
||||
|
||||
void SettingsInner::gotFullSelf(const MTPUserFull &selfFull) {
|
||||
if (!self()) return;
|
||||
App::feedPhoto(selfFull.c_userFull().vprofile_photo);
|
||||
App::feedUsers(MTP_vector<MTPUser>(1, selfFull.c_userFull().vuser));
|
||||
void SettingsInner::onFullPeerUpdated(PeerData *peer) {
|
||||
if (!self() || self() != peer) return;
|
||||
|
||||
PhotoData *selfPhoto = (self()->photoId && self()->photoId != UnknownPeerPhotoId) ? App::photo(self()->photoId) : 0;
|
||||
if (selfPhoto && selfPhoto->date) {
|
||||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto, self()));
|
||||
|
@ -1040,6 +1045,7 @@ void SettingsInner::showAll() {
|
|||
} else {
|
||||
_viewEmojis.hide();
|
||||
}
|
||||
_stickers.show();
|
||||
_enterSend.show();
|
||||
_ctrlEnterSend.show();
|
||||
_dontAskDownloadPath.show();
|
||||
|
@ -1058,6 +1064,7 @@ void SettingsInner::showAll() {
|
|||
} else {
|
||||
_replaceEmojis.hide();
|
||||
_viewEmojis.hide();
|
||||
_stickers.hide();
|
||||
_enterSend.hide();
|
||||
_ctrlEnterSend.hide();
|
||||
_dontAskDownloadPath.hide();
|
||||
|
@ -1521,7 +1528,11 @@ void SettingsInner::onReplaceEmojis() {
|
|||
}
|
||||
|
||||
void SettingsInner::onViewEmojis() {
|
||||
App::wnd()->showLayer(new EmojiBox());
|
||||
App::showLayer(new EmojiBox());
|
||||
}
|
||||
|
||||
void SettingsInner::onStickers() {
|
||||
App::showLayer(new StickersBox());
|
||||
}
|
||||
|
||||
void SettingsInner::onEnterSend() {
|
||||
|
|
|
@ -77,8 +77,6 @@ public:
|
|||
|
||||
void updateOnlineDisplay();
|
||||
|
||||
void gotFullSelf(const MTPUserFull &self);
|
||||
|
||||
void showAll();
|
||||
|
||||
void chooseCustomLang();
|
||||
|
@ -107,6 +105,8 @@ public slots:
|
|||
#endif
|
||||
void onRestartNow();
|
||||
|
||||
void onFullPeerUpdated(PeerData *peer);
|
||||
|
||||
void onPasscode();
|
||||
void onPasscodeOff();
|
||||
void onAutoLock();
|
||||
|
@ -138,6 +138,7 @@ public slots:
|
|||
|
||||
void onReplaceEmojis();
|
||||
void onViewEmojis();
|
||||
void onStickers();
|
||||
|
||||
void onEnterSend();
|
||||
void onCtrlEnterSend();
|
||||
|
@ -242,7 +243,7 @@ private:
|
|||
|
||||
// chat options
|
||||
FlatCheckbox _replaceEmojis;
|
||||
LinkButton _viewEmojis;
|
||||
LinkButton _viewEmojis, _stickers;
|
||||
FlatRadiobutton _enterSend, _ctrlEnterSend;
|
||||
FlatCheckbox _dontAskDownloadPath;
|
||||
int32 _downloadPathWidth;
|
||||
|
|
|
@ -710,7 +710,7 @@ void VideoCancelLink::onClick(Qt::MouseButton button) const {
|
|||
|
||||
VideoData::VideoData(const VideoId &id, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
|
||||
id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), loader(0) {
|
||||
location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
|
||||
_location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
|
||||
}
|
||||
|
||||
void VideoData::save(const QString &toFile) {
|
||||
|
@ -722,9 +722,12 @@ void VideoData::save(const QString &toFile) {
|
|||
}
|
||||
|
||||
QString VideoData::already(bool check) {
|
||||
if (!check) return location.name;
|
||||
if (!location.check()) location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
|
||||
return location.name;
|
||||
return location(check).name();
|
||||
}
|
||||
|
||||
const FileLocation &VideoData::location(bool check) {
|
||||
if (check && !_location.check()) _location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
|
||||
return _location;
|
||||
}
|
||||
|
||||
void AudioOpenLink::onClick(Qt::MouseButton button) const {
|
||||
|
@ -804,12 +807,15 @@ void AudioCancelLink::onClick(Qt::MouseButton button) const {
|
|||
bool StickerData::setInstalled() const {
|
||||
switch (set.type()) {
|
||||
case mtpc_inputStickerSetID: {
|
||||
return (cStickerSets().constFind(set.c_inputStickerSetID().vid.v) != cStickerSets().cend());
|
||||
StickerSets::const_iterator it = cStickerSets().constFind(set.c_inputStickerSetID().vid.v);
|
||||
return (it != cStickerSets().cend()) && !(it->flags & MTPDstickerSet::flag_disabled);
|
||||
} break;
|
||||
case mtpc_inputStickerSetShortName: {
|
||||
QString name = qs(set.c_inputStickerSetShortName().vshort_name).toLower();
|
||||
for (StickerSets::const_iterator i = cStickerSets().cbegin(), e = cStickerSets().cend(); i != e; ++i) {
|
||||
if (i->shortName.toLower() == name) return true;
|
||||
for (StickerSets::const_iterator it = cStickerSets().cbegin(), e = cStickerSets().cend(); it != e; ++it) {
|
||||
if (it->shortName.toLower() == name) {
|
||||
return !(it->flags & MTPDstickerSet::flag_disabled);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -818,7 +824,7 @@ bool StickerData::setInstalled() const {
|
|||
|
||||
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
|
||||
id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), loader(0) {
|
||||
location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
|
||||
_location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
|
||||
}
|
||||
|
||||
void AudioData::save(const QString &toFile) {
|
||||
|
@ -830,17 +836,20 @@ void AudioData::save(const QString &toFile) {
|
|||
}
|
||||
|
||||
QString AudioData::already(bool check) {
|
||||
if (!check) return location.name;
|
||||
if (!location.check()) location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
|
||||
return location.name;
|
||||
return location(check).name();
|
||||
}
|
||||
|
||||
const FileLocation &AudioData::location(bool check) {
|
||||
if (check && !_location.check()) _location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
|
||||
return _location;
|
||||
}
|
||||
|
||||
void DocumentOpenLink::doOpen(DocumentData *data) {
|
||||
if (!data->date) return;
|
||||
|
||||
bool play = data->song() && App::hoveredLinkItem() && audioPlayer();
|
||||
QString already = data->already(true);
|
||||
if (!already.isEmpty() || (!data->data.isEmpty() && play)) {
|
||||
const FileLocation &location(data->location(true));
|
||||
if (!location.isEmpty() || (!data->data.isEmpty() && play)) {
|
||||
if (play) {
|
||||
SongMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
|
@ -852,21 +861,22 @@ void DocumentOpenLink::doOpen(DocumentData *data) {
|
|||
audioPlayer()->play(song);
|
||||
if (App::main()) App::main()->documentPlayProgress(song);
|
||||
}
|
||||
} else if (data->size < MediaViewImageSizeLimit) {
|
||||
QImageReader reader(already);
|
||||
} else if (data->size < MediaViewImageSizeLimit && location.accessEnable()) {
|
||||
QImageReader reader(location.name());
|
||||
if (reader.canRead()) {
|
||||
if (reader.supportsAnimation() && reader.imageCount() > 1 && App::hoveredLinkItem()) {
|
||||
startGif(App::hoveredLinkItem(), already);
|
||||
startGif(App::hoveredLinkItem(), location);
|
||||
} else if (App::hoveredLinkItem() || App::contextItem()) {
|
||||
App::wnd()->showDocument(data, App::hoveredLinkItem() ? App::hoveredLinkItem() : App::contextItem());
|
||||
} else {
|
||||
psOpenFile(already);
|
||||
psOpenFile(location.name());
|
||||
}
|
||||
} else {
|
||||
psOpenFile(already);
|
||||
psOpenFile(location.name());
|
||||
}
|
||||
location.accessDisable();
|
||||
} else {
|
||||
psOpenFile(already);
|
||||
psOpenFile(location.name());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -954,7 +964,7 @@ void DocumentCancelLink::onClick(Qt::MouseButton button) const {
|
|||
DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) :
|
||||
id(id), type(FileDocument), access(access), date(date), mime(mime), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), loader(0), _additional(0) {
|
||||
setattributes(attributes);
|
||||
location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
|
||||
_location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
|
||||
}
|
||||
|
||||
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
|
||||
|
@ -1016,9 +1026,12 @@ void DocumentData::save(const QString &toFile) {
|
|||
}
|
||||
|
||||
QString DocumentData::already(bool check) {
|
||||
if (!check) return location.name;
|
||||
if (!location.check()) location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
|
||||
return location.name;
|
||||
return location(check).name();
|
||||
}
|
||||
|
||||
const FileLocation &DocumentData::location(bool check) {
|
||||
if (check && !_location.check()) _location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
|
||||
return _location;
|
||||
}
|
||||
|
||||
WebPageData::WebPageData(const WebPageId &id, WebPageType type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill) :
|
||||
|
|
|
@ -807,7 +807,7 @@ struct VideoData {
|
|||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
}
|
||||
location = FileLocation();
|
||||
_location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = 0;
|
||||
openOnSaveMsgId = FullMsgId();
|
||||
|
@ -816,7 +816,7 @@ struct VideoData {
|
|||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
}
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
|
@ -824,6 +824,7 @@ struct VideoData {
|
|||
}
|
||||
|
||||
QString already(bool check = false);
|
||||
const FileLocation &location(bool check = false);
|
||||
|
||||
VideoId id;
|
||||
uint64 access;
|
||||
|
@ -841,7 +842,10 @@ struct VideoData {
|
|||
int32 openOnSave;
|
||||
FullMsgId openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
FileLocation location;
|
||||
|
||||
private:
|
||||
FileLocation _location;
|
||||
|
||||
};
|
||||
|
||||
class VideoLink : public ITextLink {
|
||||
|
@ -902,7 +906,7 @@ struct AudioData {
|
|||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
}
|
||||
location = FileLocation();
|
||||
_location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = 0;
|
||||
openOnSaveMsgId = FullMsgId();
|
||||
|
@ -911,7 +915,7 @@ struct AudioData {
|
|||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
data = loader->bytes();
|
||||
}
|
||||
loader->deleteLater();
|
||||
|
@ -920,6 +924,12 @@ struct AudioData {
|
|||
}
|
||||
|
||||
QString already(bool check = false);
|
||||
const FileLocation &location(bool check = false);
|
||||
void setLocation(const FileLocation &loc) {
|
||||
if (loc.check()) {
|
||||
_location = loc;
|
||||
}
|
||||
}
|
||||
|
||||
AudioId id;
|
||||
uint64 access;
|
||||
|
@ -935,9 +945,12 @@ struct AudioData {
|
|||
int32 openOnSave;
|
||||
FullMsgId openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
FileLocation location;
|
||||
QByteArray data;
|
||||
int32 md5[8];
|
||||
|
||||
private:
|
||||
FileLocation _location;
|
||||
|
||||
};
|
||||
|
||||
struct AudioMsgId {
|
||||
|
@ -1068,7 +1081,7 @@ struct DocumentData {
|
|||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
}
|
||||
location = FileLocation();
|
||||
_location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = 0;
|
||||
openOnSaveMsgId = FullMsgId();
|
||||
|
@ -1077,7 +1090,7 @@ struct DocumentData {
|
|||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
data = loader->bytes();
|
||||
if (sticker() && !loader->imagePixmap().isNull()) {
|
||||
sticker()->img = ImagePtr(data, loader->imageFormat(), loader->imagePixmap());
|
||||
|
@ -1092,6 +1105,12 @@ struct DocumentData {
|
|||
}
|
||||
|
||||
QString already(bool check = false);
|
||||
const FileLocation &location(bool check = false);
|
||||
void setLocation(const FileLocation &loc) {
|
||||
if (loc.check()) {
|
||||
_location = loc;
|
||||
}
|
||||
}
|
||||
StickerData *sticker() {
|
||||
return (type == StickerDocument) ? static_cast<StickerData*>(_additional) : 0;
|
||||
}
|
||||
|
@ -1115,12 +1134,15 @@ struct DocumentData {
|
|||
int32 openOnSave;
|
||||
FullMsgId openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
FileLocation location;
|
||||
|
||||
QByteArray data;
|
||||
DocumentAdditionalData *_additional;
|
||||
|
||||
int32 md5[8];
|
||||
|
||||
private:
|
||||
|
||||
FileLocation _location;
|
||||
};
|
||||
|
||||
struct SongMsgId {
|
||||
|
|
|
@ -258,9 +258,9 @@ enum DataBlockId {
|
|||
dbiCatsAndDogs = 0x12,
|
||||
dbiReplaceEmojis = 0x13,
|
||||
dbiAskDownloadPath = 0x14,
|
||||
dbiDownloadPath = 0x15,
|
||||
dbiDownloadPathOld = 0x15,
|
||||
dbiScale = 0x16,
|
||||
dbiEmojiTab = 0x17,
|
||||
dbiEmojiTabOld = 0x17,
|
||||
dbiRecentEmojisOld = 0x18,
|
||||
dbiLoggedPhoneNumber = 0x19,
|
||||
dbiMutedPeers = 0x1a,
|
||||
|
@ -282,6 +282,7 @@ enum DataBlockId {
|
|||
dbiWindowsNotifications = 0x30,
|
||||
dbiIncludeMuted = 0x31,
|
||||
dbiMaxMegaGroupCount = 0x32,
|
||||
dbiDownloadPath = 0x33,
|
||||
|
||||
dbiEncryptedWithSalt = 333,
|
||||
dbiEncrypted = 444,
|
||||
|
@ -341,15 +342,15 @@ enum DBIScale {
|
|||
static const int MatrixRowShift = 40000;
|
||||
|
||||
enum DBIEmojiTab {
|
||||
dbietRecent = -1,
|
||||
dbietPeople = 0,
|
||||
dbietNature = 1,
|
||||
dbietFood = 2,
|
||||
dbietCelebration = 3,
|
||||
dbietActivity = 4,
|
||||
dbietTravel = 5,
|
||||
dbietObjects = 6,
|
||||
dbietStickers = 666,
|
||||
dbietRecent = -1,
|
||||
dbietPeople = 0,
|
||||
dbietNature = 1,
|
||||
dbietFood = 2,
|
||||
dbietActivity = 3,
|
||||
dbietTravel = 4,
|
||||
dbietObjects = 5,
|
||||
dbietSymbols = 6,
|
||||
dbietStickers = 666,
|
||||
};
|
||||
static const int emojiTabCount = 8;
|
||||
inline DBIEmojiTab emojiTabAtIndex(int index) {
|
||||
|
@ -361,6 +362,7 @@ enum DBIPlatform {
|
|||
dbipMac = 1,
|
||||
dbipLinux64 = 2,
|
||||
dbipLinux32 = 3,
|
||||
dbipMacOld = 4,
|
||||
};
|
||||
|
||||
enum DBIPeerReportSpamStatus {
|
||||
|
@ -434,3 +436,10 @@ inline int32 ceilclamp(int32 value, int32 step, int32 lowest, int32 highest) {
|
|||
inline int32 ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
|
||||
return qMax(qMin(qCeil(value / step), highest), lowest);
|
||||
}
|
||||
|
||||
enum ForwardWhatMessages {
|
||||
ForwardSelectedMessages,
|
||||
ForwardContextMessage,
|
||||
ForwardPressedMessage,
|
||||
ForwardPressedLinkMessage
|
||||
};
|
||||
|
|
|
@ -453,7 +453,7 @@ void Window::firstShow() {
|
|||
QString notificationItem = lang(cDesktopNotify()
|
||||
? lng_disable_notifications_from_tray : lng_enable_notifications_from_tray);
|
||||
|
||||
if (cPlatform() == dbipWindows || cPlatform() == dbipMac) {
|
||||
if (cPlatform() == dbipWindows || cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
trayIconMenu->addAction(lang(lng_minimize_to_tray), this, SLOT(minimizeToTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(notificationItem, this, SLOT(toggleDisplayNotifyFromTray()))->setEnabled(true);
|
||||
trayIconMenu->addAction(lang(lng_quit_from_tray), this, SLOT(quitFromTray()))->setEnabled(true);
|
||||
|
@ -987,6 +987,8 @@ bool Window::eventFilter(QObject *obj, QEvent *evt) {
|
|||
psUserActionDone();
|
||||
main->checkIdleFinish();
|
||||
}
|
||||
} else if (t == QEvent::MouseButtonRelease) {
|
||||
Ui::hideStickerPreview();
|
||||
}
|
||||
if (obj == App::app()) {
|
||||
if (t == QEvent::ApplicationActivate) {
|
||||
|
@ -1056,7 +1058,7 @@ void Window::updateTrayMenu(bool force) {
|
|||
QString notificationItem = lang(cDesktopNotify()
|
||||
? lng_disable_notifications_from_tray : lng_enable_notifications_from_tray);
|
||||
|
||||
if (cPlatform() == dbipWindows || cPlatform() == dbipMac) {
|
||||
if (cPlatform() == dbipWindows || cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
QAction *toggle = trayIconMenu->actions().at(0);
|
||||
disconnect(toggle, SIGNAL(triggered(bool)), this, SLOT(minimizeToTray()));
|
||||
disconnect(toggle, SIGNAL(triggered(bool)), this, SLOT(showFromTray()));
|
||||
|
@ -1072,7 +1074,7 @@ void Window::updateTrayMenu(bool force) {
|
|||
}
|
||||
#ifndef Q_OS_WIN
|
||||
if (trayIcon) {
|
||||
trayIcon->setContextMenu((active || cPlatform() != dbipMac) ? trayIconMenu : 0);
|
||||
trayIcon->setContextMenu((active || cPlatform() == dbipLinux32 || cPlatform() == dbipLinux64) ? trayIconMenu : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1180,7 +1182,7 @@ void Window::showFromTray(QSystemTrayIcon::ActivationReason reason) {
|
|||
}
|
||||
|
||||
void Window::toggleTray(QSystemTrayIcon::ActivationReason reason) {
|
||||
if (cPlatform() == dbipMac && isActive(false)) return;
|
||||
if ((cPlatform() == dbipMac || cPlatform() == dbipMacOld) && isActive(false)) return;
|
||||
if (reason == QSystemTrayIcon::Context) {
|
||||
updateTrayMenu(true);
|
||||
QTimer::singleShot(1, this, SLOT(psShowTrayMenu()));
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.9.13</string>
|
||||
<string>0.9.15</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
|
@ -89,6 +89,7 @@ SOURCES += \
|
|||
./SourceFiles/autoupdater.cpp \
|
||||
./SourceFiles/dialogswidget.cpp \
|
||||
./SourceFiles/dropdown.cpp \
|
||||
./SourceFiles/facades.cpp \
|
||||
./SourceFiles/fileuploader.cpp \
|
||||
./SourceFiles/history.cpp \
|
||||
./SourceFiles/historywidget.cpp \
|
||||
|
@ -112,6 +113,7 @@ SOURCES += \
|
|||
./SourceFiles/types.cpp \
|
||||
./SourceFiles/window.cpp \
|
||||
./SourceFiles/mtproto/mtp.cpp \
|
||||
./SourceFiles/mtproto/mtpAuthKey.cpp \
|
||||
./SourceFiles/mtproto/mtpConnection.cpp \
|
||||
./SourceFiles/mtproto/mtpCoreTypes.cpp \
|
||||
./SourceFiles/mtproto/mtpDC.cpp \
|
||||
|
@ -175,6 +177,7 @@ HEADERS += \
|
|||
./SourceFiles/countries.h \
|
||||
./SourceFiles/dialogswidget.h \
|
||||
./SourceFiles/dropdown.h \
|
||||
./SourceFiles/facades.h \
|
||||
./SourceFiles/fileuploader.h \
|
||||
./SourceFiles/history.h \
|
||||
./SourceFiles/historywidget.h \
|
||||
|
|
|
@ -68,8 +68,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,9,13,0
|
||||
PRODUCTVERSION 0,9,13,0
|
||||
FILEVERSION 0,9,15,0
|
||||
PRODUCTVERSION 0,9,15,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -85,10 +85,10 @@ BEGIN
|
|||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileVersion", "0.9.13.0"
|
||||
VALUE "FileVersion", "0.9.15.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2013"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "0.9.13.0"
|
||||
VALUE "ProductVersion", "0.9.15.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|