Created
October 5, 2018 04:36
-
-
Save holishing/f282d3114087d36514e30b9f7b8220af to your computer and use it in GitHub Desktop.
Telegram: diff from 1.3.14 to 1.4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff -ur work.1.3.14/tdesktop-1.3.14/.gitmodules work/tdesktop-1.4.0/.gitmodules | |
| --- work.1.3.14/tdesktop-1.3.14/.gitmodules 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/.gitmodules 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -13,3 +13,6 @@ | |
| [submodule "Telegram/ThirdParty/crl"] | |
| path = Telegram/ThirdParty/crl | |
| url = https://github.com/telegramdesktop/crl.git | |
| +[submodule "Telegram/ThirdParty/xxHash"] | |
| + path = Telegram/ThirdParty/xxHash | |
| + url = https://github.com/Cyan4973/xxHash.git | |
| diff -ur work.1.3.14/tdesktop-1.3.14/changelog.txt work/tdesktop-1.4.0/changelog.txt | |
| --- work.1.3.14/tdesktop-1.3.14/changelog.txt 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/changelog.txt 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -1,3 +1,30 @@ | |
| +1.4 (28.09.18) | |
| + | |
| +- Fully redesigned Settings section. | |
| +- New theme selector in Chat Settings. | |
| +- New local storage settings: Control how much disk space is used by the cache and for how long the cached files are stored. | |
| +- Improved local caching for images and GIF animations. | |
| +- New settings: Peer-to-Peer settings for calls, disable animations for low performance computers. | |
| +- Various other improvements. | |
| + | |
| +1.3.17 beta (26.09.18) | |
| + | |
| +- Fully redisigned Settings section. | |
| +- New theme selector in Chat Settings. | |
| +- New settings: Peer-to-Peer settings for calls, disable animations for low performance computers. | |
| +- Various other improvements. | |
| + | |
| +1.3.16 alpha (04.09.18) | |
| + | |
| +- Update libtgvoip, fix crash in calls. | |
| +- Fix crash in local cache database. | |
| +- Clear old local cache asynchronously. | |
| + | |
| +1.3.15 alpha (01.09.18) | |
| + | |
| +- Improved local caching for images and GIF animations. | |
| +- Control how much disk space is used by the cache and for how long the cached files are stored. | |
| + | |
| 1.3.14 (27.08.18) | |
| - Fix a crash in calls. | |
| diff -ur work.1.3.14/tdesktop-1.3.14/README.md work/tdesktop-1.4.0/README.md | |
| --- work.1.3.14/tdesktop-1.3.14/README.md 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/README.md 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -17,6 +17,7 @@ | |
| * Mac OS X 10.6 - Mac OS X 10.7 (separate build) | |
| * Ubuntu 12.04 - Ubuntu 18.04 | |
| * Fedora 22 - Fedora 28 | |
| +* [Snappy](https://snapcraft.io/telegram-desktop) | |
| ## Third-party | |
| @@ -39,6 +40,7 @@ | |
| * Open Sans font ([Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)) | |
| * Emoji alpha codes ([MIT License](https://github.com/emojione/emojione/blob/master/extras/alpha-codes/LICENSE.md)) | |
| * Catch test framework ([Boost License](https://github.com/philsquared/Catch/blob/master/LICENSE.txt)) | |
| +* xxHash ([BSD License](https://github.com/Cyan4973/xxHash/blob/dev/LICENSE)) | |
| ## Build instructions | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/build.bat work/tdesktop-1.4.0/Telegram/build/build.bat | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/build.bat 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/build.bat 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,15 +23,15 @@ | |
| FOR /F "tokens=1,2* delims= " %%i in (%FullScriptPath%version) do set "%%i=%%j" | |
| set "VersionForPacker=%AppVersion%" | |
| -if %BetaVersion% neq 0 ( | |
| - set "AppVersion=%BetaVersion%" | |
| - set "AppVersionStrFull=%AppVersionStr%_%BetaVersion%" | |
| - set "AlphaBetaParam=-beta %BetaVersion%" | |
| - set "BetaKeyFile=tbeta_%BetaVersion%_key" | |
| +if %AlphaVersion% neq 0 ( | |
| + set "AppVersion=%AlphaVersion%" | |
| + set "AppVersionStrFull=%AppVersionStr%_%AlphaVersion%" | |
| + set "AlphaBetaParam=-alpha %AlphaVersion%" | |
| + set "AlphaKeyFile=talpha_%AlphaVersion%_key" | |
| ) else ( | |
| - if %AlphaChannel% neq 0 ( | |
| - set "AlphaBetaParam=-alpha" | |
| - set "AppVersionStrFull=%AppVersionStr%.alpha" | |
| + if %BetaChannel% neq 0 ( | |
| + set "AlphaBetaParam=-beta" | |
| + set "AppVersionStrFull=%AppVersionStr%.beta" | |
| ) else ( | |
| set "AlphaBetaParam=" | |
| set "AppVersionStrFull=%AppVersionStr%" | |
| @@ -76,13 +76,13 @@ | |
| exit /b 1 | |
| ) | |
| ) | |
| -if %BetaVersion% neq 0 ( | |
| +if %AlphaVersion% neq 0 ( | |
| if exist %DeployPath%\ ( | |
| echo Deploy folder for version %AppVersionStr% already exists! | |
| exit /b 1 | |
| ) | |
| - if exist %ReleasePath%\%BetaKeyFile% ( | |
| - echo Beta version key file for version %AppVersion% already exists! | |
| + if exist %ReleasePath%\%AlphaKeyFile% ( | |
| + echo Alpha version key file for version %AppVersion% already exists! | |
| exit /b 1 | |
| ) | |
| ) else ( | |
| @@ -90,8 +90,8 @@ | |
| echo Deploy folder for version %AppVersionStr%.alpha already exists! | |
| exit /b 1 | |
| ) | |
| - if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%.dev\ ( | |
| - echo Deploy folder for version %AppVersionStr%.dev already exists! | |
| + if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%.beta\ ( | |
| + echo Deploy folder for version %AppVersionStr%.beta already exists! | |
| exit /b 1 | |
| ) | |
| if exist %ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStr%\ ( | |
| @@ -138,7 +138,7 @@ | |
| call "%SignPath%" "Updater.exe" | |
| if %errorlevel% neq 0 goto error | |
| - if %BetaVersion% equ 0 ( | |
| + if %AlphaVersion% equ 0 ( | |
| iscc /dMyAppVersion=%AppVersionStrSmall% /dMyAppVersionZero=%AppVersionStr% /dMyAppVersionFull=%AppVersionStrFull% "/dReleasePath=%ReleasePath%" "%FullScriptPath%setup.iss" | |
| if %errorlevel% neq 0 goto error | |
| if not exist "tsetup.%AppVersionStrFull%.exe" goto error | |
| @@ -150,19 +150,19 @@ | |
| call Packer.exe -version %VersionForPacker% -path %BinaryName%.exe -path Updater.exe %AlphaBetaParam% | |
| if %errorlevel% neq 0 goto error | |
| - if %BetaVersion% neq 0 ( | |
| - if not exist "%ReleasePath%\%BetaKeyFile%" ( | |
| - echo Beta version key file not found! | |
| + if %AlphaVersion% neq 0 ( | |
| + if not exist "%ReleasePath%\%AlphaKeyFile%" ( | |
| + echo Alpha version key file not found! | |
| exit /b 1 | |
| ) | |
| - FOR /F "tokens=1* delims= " %%i in (%ReleasePath%\%BetaKeyFile%) do set "BetaSignature=%%i" | |
| + FOR /F "tokens=1* delims= " %%i in (%ReleasePath%\%AlphaKeyFile%) do set "AlphaSignature=%%i" | |
| ) | |
| if %errorlevel% neq 0 goto error | |
| - if %BetaVersion% neq 0 ( | |
| - set "UpdateFile=!UpdateFile!_!BetaSignature!" | |
| - set "PortableFile=tbeta!BetaVersion!_!BetaSignature!.zip" | |
| + if %AlphaVersion% neq 0 ( | |
| + set "UpdateFile=!UpdateFile!_!AlphaSignature!" | |
| + set "PortableFile=talpha!AlphaVersion!_!AlphaSignature!.zip" | |
| ) | |
| ) | |
| @@ -239,10 +239,10 @@ | |
| xcopy "%ReleasePath%\Updater.pdb" "%DeployPath%\" | |
| move "%ReleasePath%\%BinaryName%.exe.pdb" "%DeployPath%\" | |
| move "%ReleasePath%\Updater.exe.pdb" "%DeployPath%\" | |
| - if %BetaVersion% equ 0 ( | |
| + if %AlphaVersion% equ 0 ( | |
| move "%ReleasePath%\%SetupFile%" "%DeployPath%\" | |
| ) else ( | |
| - move "%ReleasePath%\%BetaKeyFile%" "%DeployPath%\" | |
| + move "%ReleasePath%\%AlphaKeyFile%" "%DeployPath%\" | |
| ) | |
| move "%ReleasePath%\%UpdateFile%" "%DeployPath%\" | |
| if %errorlevel% neq 0 goto error | |
| @@ -250,6 +250,10 @@ | |
| cd "%DeployPath%" | |
| 7z a -mx9 %PortableFile% %BinaryName%\ | |
| if %errorlevel% neq 0 goto error | |
| + | |
| + move "%DeployPath%\%BinaryName%\%BinaryName%.exe" "%DeployPath%\" | |
| + rmdir "%DeployPath%\%BinaryName%" | |
| + if %errorlevel% neq 0 goto error | |
| ) | |
| set "FinalDeployPath=%FinalReleasePath%\%AppVersionStrMajor%\%AppVersionStrFull%\tsetup" | |
| @@ -261,7 +265,7 @@ | |
| if not exist "%DeployPath%\%UpdateFile%" goto error | |
| if not exist "%DeployPath%\%PortableFile%" goto error | |
| - if %BetaVersion% equ 0 ( | |
| + if %AlphaVersion% equ 0 ( | |
| if not exist "%DeployPath%\%SetupFile%" goto error | |
| ) | |
| if not exist "%DeployPath%\%BinaryName%.pdb" goto error | |
| @@ -273,10 +277,10 @@ | |
| xcopy "%DeployPath%\%UpdateFile%" "%FinalDeployPath%\" /Y | |
| xcopy "%DeployPath%\%PortableFile%" "%FinalDeployPath%\" /Y | |
| - if %BetaVersion% equ 0 ( | |
| + if %AlphaVersion% equ 0 ( | |
| xcopy "%DeployPath%\%SetupFile%" "%FinalDeployPath%\" /Y | |
| ) else ( | |
| - xcopy "%DeployPath%\%BetaKeyFile%" "%FinalDeployPath%\" /Y | |
| + xcopy "%DeployPath%\%AlphaKeyFile%" "%FinalDeployPath%\" /Y | |
| ) | |
| ) | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/build.sh work/tdesktop-1.4.0/Telegram/build/build.sh | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/build.sh 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/build.sh 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -33,17 +33,17 @@ | |
| done < "$FullScriptPath/version" | |
| VersionForPacker="$AppVersion" | |
| -if [ "$BetaVersion" != "0" ]; then | |
| - AppVersion="$BetaVersion" | |
| - AppVersionStrFull="${AppVersionStr}_${BetaVersion}" | |
| - AlphaBetaParam="-beta $BetaVersion" | |
| - BetaKeyFile="tbeta_${AppVersion}_key" | |
| -elif [ "$AlphaChannel" == "0" ]; then | |
| +if [ "$AlphaVersion" != "0" ]; then | |
| + AppVersion="$AlphaVersion" | |
| + AppVersionStrFull="${AppVersionStr}_${AlphaVersion}" | |
| + AlphaBetaParam="-alpha $AlphaVersion" | |
| + AlphaKeyFile="talpha_${AppVersion}_key" | |
| +elif [ "$BetaChannel" == "0" ]; then | |
| AppVersionStrFull="$AppVersionStr" | |
| AlphaBetaParam='' | |
| else | |
| - AppVersionStrFull="$AppVersionStr.alpha" | |
| - AlphaBetaParam='-alpha' | |
| + AppVersionStrFull="$AppVersionStr.beta" | |
| + AlphaBetaParam='-beta' | |
| fi | |
| echo "" | |
| @@ -73,8 +73,8 @@ | |
| ReleasePath="$HomePath/../out/Release" | |
| BinaryName="Telegram" | |
| elif [ "$BuildTarget" == "macstore" ]; then | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - Error "Can't build macstore beta version!" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + Error "Can't build macstore alpha version!" | |
| fi | |
| echo "Building version $AppVersionStrFull for Mac App Store.." | |
| @@ -85,9 +85,9 @@ | |
| fi | |
| #if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarget" == "macstore" ]; then | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - if [ -f "$ReleasePath/$BetaKeyFile" ]; then | |
| - Error "Beta version key file for version $AppVersion already exists!" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + if [ -f "$ReleasePath/$AlphaKeyFile" ]; then | |
| + Error "Alpha version key file for version $AppVersion already exists!" | |
| fi | |
| if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStrFull" ]; then | |
| @@ -98,8 +98,8 @@ | |
| Error "Deploy folder for version $AppVersionStr.alpha already exists!" | |
| fi | |
| - if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStr.dev" ]; then | |
| - Error "Deploy folder for version $AppVersionStr.dev already exists!" | |
| + if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStr.beta" ]; then | |
| + Error "Deploy folder for version $AppVersionStr.beta already exists!" | |
| fi | |
| if [ -d "$ReleasePath/deploy/$AppVersionStrMajor/$AppVersionStr" ]; then | |
| @@ -188,22 +188,26 @@ | |
| strip -s "$ReleasePath/$BinaryName" | |
| echo "Done!" | |
| + echo "Removing RPATH.." | |
| + chrpath -d "$ReleasePath/$BinaryName" | |
| + echo "Done!" | |
| + | |
| echo "Preparing version $AppVersionStrFull, executing Packer.." | |
| cd "$ReleasePath" | |
| "./Packer" -path "$BinaryName" -path Updater -version $VersionForPacker $AlphaBetaParam | |
| echo "Packer done!" | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - if [ ! -f "$ReleasePath/$BetaKeyFile" ]; then | |
| - Error "Beta version key file not found!" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + if [ ! -f "$ReleasePath/$AlphaKeyFile" ]; then | |
| + Error "Alpha version key file not found!" | |
| fi | |
| while IFS='' read -r line || [[ -n "$line" ]]; do | |
| - BetaSignature="$line" | |
| - done < "$ReleasePath/$BetaKeyFile" | |
| + AlphaSignature="$line" | |
| + done < "$ReleasePath/$AlphaKeyFile" | |
| - UpdateFile="${UpdateFile}_${BetaSignature}" | |
| - SetupFile="tbeta${BetaVersion}_${BetaSignature}.tar.xz" | |
| + UpdateFile="${UpdateFile}_${AlphaSignature}" | |
| + SetupFile="talpha${AlphaVersion}_${AlphaSignature}.tar.xz" | |
| fi | |
| SymbolsHash=`head -n 1 "$ReleasePath/$BinaryName.sym" | awk -F " " 'END {print $4}'` | |
| @@ -226,8 +230,8 @@ | |
| mv "$ReleasePath/$BinaryName" "$DeployPath/$BinaryName/" | |
| mv "$ReleasePath/Updater" "$DeployPath/$BinaryName/" | |
| mv "$ReleasePath/$UpdateFile" "$DeployPath/" | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - mv "$ReleasePath/$BetaKeyFile" "$DeployPath/" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + mv "$ReleasePath/$AlphaKeyFile" "$DeployPath/" | |
| fi | |
| cd "$DeployPath" | |
| tar -cJvf "$SetupFile" "$BinaryName/" | |
| @@ -235,8 +239,8 @@ | |
| mkdir -p $BackupPath | |
| cp "$SetupFile" "$BackupPath/" | |
| cp "$UpdateFile" "$BackupPath/" | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - cp -v "$BetaKeyFile" "$BackupPath/" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + cp -v "$AlphaKeyFile" "$BackupPath/" | |
| fi | |
| fi | |
| @@ -330,7 +334,7 @@ | |
| echo "Done!" | |
| if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ]; then | |
| - if [ "$BetaVersion" == "0" ]; then | |
| + if [ "$AlphaVersion" == "0" ]; then | |
| cd "$ReleasePath" | |
| cp -f tsetup_template.dmg tsetup.temp.dmg | |
| TempDiskPath=`hdiutil attach -nobrowse -noautoopenrw -readwrite tsetup.temp.dmg | awk -F "\t" 'END {print $3}'` | |
| @@ -344,17 +348,17 @@ | |
| "./Packer" -path "$BinaryName.app" -target "$BuildTarget" -version $VersionForPacker $AlphaBetaParam | |
| echo "Packer done!" | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - if [ ! -f "$ReleasePath/$BetaKeyFile" ]; then | |
| - Error "Beta version key file not found!" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + if [ ! -f "$ReleasePath/$AlphaKeyFile" ]; then | |
| + Error "Alpha version key file not found!" | |
| fi | |
| while IFS='' read -r line || [[ -n "$line" ]]; do | |
| - BetaSignature="$line" | |
| - done < "$ReleasePath/$BetaKeyFile" | |
| + AlphaSignature="$line" | |
| + done < "$ReleasePath/$AlphaKeyFile" | |
| - UpdateFile="${UpdateFile}_${BetaSignature}" | |
| - SetupFile="tbeta${BetaVersion}_${BetaSignature}.zip" | |
| + UpdateFile="${UpdateFile}_${AlphaSignature}" | |
| + SetupFile="talpha${AlphaVersion}_${AlphaSignature}.zip" | |
| fi | |
| fi | |
| @@ -371,11 +375,11 @@ | |
| mkdir "$DeployPath" | |
| mkdir "$DeployPath/$BinaryName" | |
| cp -r "$ReleasePath/$BinaryName.app" "$DeployPath/$BinaryName/" | |
| - if [ "$BetaVersion" != "0" ]; then | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| cd "$DeployPath" | |
| zip -r "$SetupFile" "$BinaryName" | |
| mv "$SetupFile" "$ReleasePath/" | |
| - mv "$ReleasePath/$BetaKeyFile" "$DeployPath/" | |
| + mv "$ReleasePath/$AlphaKeyFile" "$DeployPath/" | |
| fi | |
| mv "$ReleasePath/$BinaryName.app.dSYM" "$DeployPath/" | |
| rm "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName" | |
| @@ -389,16 +393,16 @@ | |
| mkdir -p "$BackupPath/tmac" | |
| cp "$DeployPath/$UpdateFile" "$BackupPath/tmac/" | |
| cp "$DeployPath/$SetupFile" "$BackupPath/tmac/" | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - cp -v "$DeployPath/$BetaKeyFile" "$BackupPath/tmac/" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + cp -v "$DeployPath/$AlphaKeyFile" "$BackupPath/tmac/" | |
| fi | |
| fi | |
| if [ "$BuildTarget" == "mac32" ]; then | |
| mkdir -p "$BackupPath/tmac32" | |
| cp "$DeployPath/$UpdateFile" "$BackupPath/tmac32/" | |
| cp "$DeployPath/$SetupFile" "$BackupPath/tmac32/" | |
| - if [ "$BetaVersion" != "0" ]; then | |
| - cp -v "$DeployPath/$BetaKeyFile" "$BackupPath/tmac32/" | |
| + if [ "$AlphaVersion" != "0" ]; then | |
| + cp -v "$DeployPath/$AlphaKeyFile" "$BackupPath/tmac32/" | |
| fi | |
| fi | |
| elif [ "$BuildTarget" == "macstore" ]; then | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/deploy.sh work/tdesktop-1.4.0/Telegram/build/deploy.sh | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/deploy.sh 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/deploy.sh 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -34,14 +34,14 @@ | |
| eval $1="$2" | |
| done < "$FullScriptPath/version" | |
| -if [ "$BetaVersion" != "0" ]; then | |
| - AppVersion="$BetaVersion" | |
| - AppVersionStrFull="${AppVersionStr}_${BetaVersion}" | |
| - BetaKeyFile="tbeta_${AppVersion}_key" | |
| -elif [ "$AlphaChannel" == "0" ]; then | |
| +if [ "$AlphaVersion" != "0" ]; then | |
| + AppVersion="$AlphaVersion" | |
| + AppVersionStrFull="${AppVersionStr}_${AlphaVersion}" | |
| + AlphaKeyFile="talpha_${AppVersion}_key" | |
| +elif [ "$BetaChannel" == "0" ]; then | |
| AppVersionStrFull="$AppVersionStr" | |
| else | |
| - AppVersionStrFull="$AppVersionStr.alpha" | |
| + AppVersionStrFull="$AppVersionStr.beta" | |
| fi | |
| echo "" | |
| @@ -70,7 +70,7 @@ | |
| DeployMac="1" | |
| DeployWin="1" | |
| DeployLinux="1" | |
| - if [ "$BetaVersion" == "0" ]; then | |
| + if [ "$AlphaVersion" == "0" ]; then | |
| DeployMac32="1" | |
| DeployLinux32="1" | |
| echo "Deploying five versions of $AppVersionStrFull: for Windows, OS X 10.6 and 10.7, OS X 10.8+, Linux 64 bit and Linux 32 bit.." | |
| @@ -108,36 +108,36 @@ | |
| Linux32RemoteFolder="tlinux32" | |
| DeployPath="$BackupPath/$AppVersionStrMajor/$AppVersionStrFull" | |
| -if [ "$BetaVersion" != "0" ]; then | |
| +if [ "$AlphaVersion" != "0" ]; then | |
| if [ "$DeployTarget" == "win" ]; then | |
| - BetaFilePath="$WinDeployPath/$BetaKeyFile" | |
| + AlphaFilePath="$WinDeployPath/$AlphaKeyFile" | |
| elif [ "$DeployTarget" == "mac32" ]; then | |
| - BetaFilePath="$Mac32DeployPath/$BetaKeyFile" | |
| + AlphaFilePath="$Mac32DeployPath/$AlphaKeyFile" | |
| elif [ "$DeployTarget" == "linux" ]; then | |
| - BetaFilePath="$LinuxDeployPath/$BetaKeyFile" | |
| + AlphaFilePath="$LinuxDeployPath/$AlphaKeyFile" | |
| elif [ "$DeployTarget" == "linux32" ]; then | |
| - BetaFilePath="$Linux32DeployPath/$BetaKeyFile" | |
| + AlphaFilePath="$Linux32DeployPath/$AlphaKeyFile" | |
| else | |
| - BetaFilePath="$MacDeployPath/$BetaKeyFile" | |
| + AlphaFilePath="$MacDeployPath/$AlphaKeyFile" | |
| fi | |
| - if [ ! -f "$BetaFilePath" ]; then | |
| - Error "Beta key file for $AppVersionStrFull not found." | |
| + if [ ! -f "$AlphaFilePath" ]; then | |
| + Error "Alpha key file for $AppVersionStrFull not found." | |
| fi | |
| while IFS='' read -r line || [[ -n "$line" ]]; do | |
| - BetaSignature="$line" | |
| - done < "$BetaFilePath" | |
| + AlphaSignature="$line" | |
| + done < "$AlphaFilePath" | |
| - MacUpdateFile="${MacUpdateFile}_${BetaSignature}" | |
| - MacSetupFile="tbeta${BetaVersion}_${BetaSignature}.zip" | |
| - Mac32UpdateFile="${Mac32UpdateFile}_${BetaSignature}" | |
| - Mac32SetupFile="tbeta${BetaVersion}_${BetaSignature}.zip" | |
| - WinUpdateFile="${WinUpdateFile}_${BetaSignature}" | |
| - WinPortableFile="tbeta${BetaVersion}_${BetaSignature}.zip" | |
| - LinuxUpdateFile="${LinuxUpdateFile}_${BetaSignature}" | |
| - LinuxSetupFile="tbeta${BetaVersion}_${BetaSignature}.tar.xz" | |
| - Linux32UpdateFile="${Linux32UpdateFile}_${BetaSignature}" | |
| - Linux32SetupFile="tbeta${BetaVersion}_${BetaSignature}.tar.xz" | |
| + MacUpdateFile="${MacUpdateFile}_${AlphaSignature}" | |
| + MacSetupFile="talpha${AlphaVersion}_${AlphaSignature}.zip" | |
| + Mac32UpdateFile="${Mac32UpdateFile}_${AlphaSignature}" | |
| + Mac32SetupFile="talpha${AlphaVersion}_${AlphaSignature}.zip" | |
| + WinUpdateFile="${WinUpdateFile}_${AlphaSignature}" | |
| + WinPortableFile="talpha${AlphaVersion}_${AlphaSignature}.zip" | |
| + LinuxUpdateFile="${LinuxUpdateFile}_${AlphaSignature}" | |
| + LinuxSetupFile="talpha${AlphaVersion}_${AlphaSignature}.tar.xz" | |
| + Linux32UpdateFile="${Linux32UpdateFile}_${AlphaSignature}" | |
| + Linux32SetupFile="talpha${AlphaVersion}_${AlphaSignature}.tar.xz" | |
| fi | |
| if [ "$DeployMac" == "1" ]; then | |
| @@ -160,7 +160,7 @@ | |
| if [ ! -f "$WinDeployPath/$WinUpdateFile" ]; then | |
| Error "$WinUpdateFile not found!" | |
| fi | |
| - if [ "$BetaVersion" == "0" ]; then | |
| + if [ "$AlphaVersion" == "0" ]; then | |
| if [ ! -f "$WinDeployPath/$WinSetupFile" ]; then | |
| Error "$WinSetupFile not found!" | |
| fi | |
| @@ -197,7 +197,7 @@ | |
| fi | |
| if [ "$DeployWin" == "1" ]; then | |
| Files+=("tsetup/$WinUpdateFile" "tsetup/$WinPortableFile") | |
| - if [ "$BetaVersion" == "0" ]; then | |
| + if [ "$AlphaVersion" == "0" ]; then | |
| Files+=("tsetup/$WinSetupFile") | |
| fi | |
| fi | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/release.py work/tdesktop-1.4.0/Telegram/build/release.py | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/release.py 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/release.py 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -59,8 +59,7 @@ | |
| version_parts = version.split('.') | |
| stable = 1 | |
| -alpha = 0 | |
| -dev = 0 | |
| +beta = 0 | |
| if len(version_parts) < 2: | |
| print('Error: expected at least major version ' + version) | |
| @@ -76,14 +75,10 @@ | |
| version = version_major + '.' + version_parts[2] | |
| version_full = version | |
| if len(version_parts) == 4: | |
| - if version_parts[3] == 'dev': | |
| - dev = 1 | |
| + if version_parts[3] == 'beta': | |
| + beta = 1 | |
| stable = 0 | |
| - version_full = version + '.dev' | |
| - elif version_parts[3] == 'alpha': | |
| - alpha = 1 | |
| - stable = 0 | |
| - version_full = version + '.alpha' | |
| + version_full = version + '.beta' | |
| else: | |
| print('Error: unexpected version part ' + version_parts[3]) | |
| sys.exit(1) | |
| @@ -102,16 +97,11 @@ | |
| local_folder = expanduser("~") + '/Telegram/backup/' + version_major + '/' + version_full | |
| if stable == 1: | |
| - if os.path.isdir(local_folder + '.dev'): | |
| - dev = 1 | |
| - stable = 0 | |
| - version_full = version + '.dev' | |
| - local_folder = local_folder + '.dev' | |
| - elif os.path.isdir(local_folder + '.alpha'): | |
| - alpha = 1 | |
| + if os.path.isdir(local_folder + '.beta'): | |
| + beta = 1 | |
| stable = 0 | |
| - version_full = version + '.alpha' | |
| - local_folder = local_folder + '.alpha' | |
| + version_full = version + '.beta' | |
| + local_folder = local_folder + '.beta' | |
| if not os.path.isdir(local_folder): | |
| print('Storage path not found: ' + local_folder) | |
| @@ -200,7 +190,7 @@ | |
| 'target_commitish': commit, | |
| 'name': 'v ' + version, | |
| 'body': changelog, | |
| - 'prerelease': (dev == 1 or alpha == 1), | |
| + 'prerelease': (beta == 1), | |
| })) | |
| checkResponseCode(r, 201) | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/release.sh work/tdesktop-1.4.0/Telegram/build/release.sh | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/release.sh 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/release.sh 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -30,14 +30,14 @@ | |
| done < "$FullScriptPath/version" | |
| VersionForPacker="$AppVersion" | |
| -if [ "$BetaVersion" != "0" ]; then | |
| - Error "No releases for closed beta versions" | |
| -elif [ "$AlphaChannel" == "0" ]; then | |
| +if [ "$AlphaVersion" != "0" ]; then | |
| + Error "No releases for closed alpha versions" | |
| +elif [ "$BetaChannel" == "0" ]; then | |
| AppVersionStrFull="$AppVersionStr" | |
| AlphaBetaParam='' | |
| else | |
| - AppVersionStrFull="$AppVersionStr.alpha" | |
| - AlphaBetaParam='-alpha' | |
| + AppVersionStrFull="$AppVersionStr.beta" | |
| + AlphaBetaParam='-beta' | |
| fi | |
| cd "$FullScriptPath" | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/set_version.bat work/tdesktop-1.4.0/Telegram/build/set_version.bat | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/set_version.bat 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/set_version.bat 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,14 +9,14 @@ | |
| set "VersionMinor=%%b" | |
| set "VersionPatch=%%c" | |
| if "%%d" == "" ( | |
| - set "VersionBeta=0" | |
| set "VersionAlpha=0" | |
| - ) else if "%%d" == "alpha" ( | |
| set "VersionBeta=0" | |
| - set "VersionAlpha=1" | |
| - ) else ( | |
| - set "VersionBeta=%%d" | |
| + ) else if "%%d" == "beta" ( | |
| set "VersionAlpha=0" | |
| + set "VersionBeta=1" | |
| + ) else ( | |
| + set "VersionAlpha=%%d" | |
| + set "VersionBeta=0" | |
| ) | |
| ) | |
| @@ -35,27 +35,27 @@ | |
| echo Bad patch version! | |
| exit /b 1 | |
| ) | |
| -if "%VersionAlpha%" neq "0" ( | |
| - if "%VersionAlpha%" neq "1" ( | |
| - echo Bad alpha version! | |
| +if "%VersionBeta%" neq "0" ( | |
| + if "%VersionBeta%" neq "1" ( | |
| + echo Bad beta version! | |
| exit /b 1 | |
| ) | |
| - set "VersionAlphaBool=true" | |
| + set "VersionBetaBool=true" | |
| ) else ( | |
| - set "VersionAlphaBool=false" | |
| + set "VersionBetaBool=false" | |
| ) | |
| set /a "VersionFull=%VersionMajor% * 1000000 + %VersionMinor% * 1000 + %VersionPatch%" | |
| -if "%VersionBeta%" neq "0" ( | |
| - set /a "VersionBetaCleared=%VersionBeta% %% 1000" | |
| - if "!VersionBetaCleared!" neq "%VersionBeta%" ( | |
| - echo Bad beta version! | |
| +if "%VersionAlpha%" neq "0" ( | |
| + set /a "VersionAlphaCleared=%VersionAlpha% %% 1000" | |
| + if "!VersionAlphaCleared!" neq "%VersionAlpha%" ( | |
| + echo Bad alpha version! | |
| exit /b 1 | |
| ) | |
| - set /a "VersionBetaMul=1000 + %VersionBeta%" | |
| - set "VersionFullBeta=%VersionFull%!VersionBetaMul:~1!" | |
| + set /a "VersionAlphaMul=1000 + %VersionAlpha%" | |
| + set "VersionFullAlpha=%VersionFull%!VersionAlphaMul:~1!" | |
| ) else ( | |
| - set "VersionFullBeta=0" | |
| + set "VersionFullAlpha=0" | |
| ) | |
| set "VersionStr=%VersionMajor%.%VersionMinor%.%VersionPatch%" | |
| @@ -65,10 +65,10 @@ | |
| set "VersionStrSmall=%VersionMajor%.%VersionMinor%" | |
| ) | |
| -if "%VersionAlpha%" neq "0" ( | |
| - echo Setting version: %VersionStr% alpha | |
| -) else if "%VersionBeta%" neq "0" ( | |
| - echo Setting version: %VersionStr%.%VersionBeta% closed beta | |
| +if "%VersionBeta%" neq "0" ( | |
| + echo Setting version: %VersionStr% beta | |
| +) else if "%VersionAlpha%" neq "0" ( | |
| + echo Setting version: %VersionStr%.%VersionAlpha% closed alpha | |
| ) else ( | |
| echo Setting version: %VersionStr% stable | |
| ) | |
| @@ -96,33 +96,33 @@ | |
| call :repl "Argument=(AppVersionStrMajor) (\s*)[\d\.]+/$1$2 %VersionMajor%.%VersionMinor%" "Filename=%VersionFilePath%" || goto :error | |
| call :repl "Argument=(AppVersionStrSmall) (\s*)[\d\.]+/$1$2 %VersionStrSmall%" "Filename=%VersionFilePath%" || goto :error | |
| call :repl "Argument=(AppVersionStr) (\s*)[\d\.]+/$1$2 %VersionStr%" "Filename=%VersionFilePath%" || goto :error | |
| -call :repl "Argument=(AlphaChannel) (\s*)[\d\.]+/$1$2 %VersionAlpha%" "Filename=%VersionFilePath%" || goto :error | |
| -call :repl "Argument=(BetaVersion) (\s*)\d+/$1$2 %VersionFullBeta%" "Filename=%VersionFilePath%" || goto :error | |
| +call :repl "Argument=(BetaChannel) (\s*)[\d\.]+/$1$2 %VersionBeta%" "Filename=%VersionFilePath%" || goto :error | |
| +call :repl "Argument=(AlphaVersion) (\s*)\d+/$1$2 %VersionFullAlpha%" "Filename=%VersionFilePath%" || goto :error | |
| echo Patching core/version.h... | |
| set "VersionHeaderPath=%FullScriptPath%..\SourceFiles\core\version.h" | |
| -call :repl "Argument=(BETA_VERSION_MACRO\s+)\(\d+ULL\)/$1(%VersionFullBeta%ULL)" "Filename=%VersionHeaderPath%" || goto :error | |
| +call :repl "Argument=(ALPHA_VERSION_MACRO\s+)\(\d+ULL\)/$1(%VersionFullAlpha%ULL)" "Filename=%VersionHeaderPath%" || goto :error | |
| call :repl "Argument=(AppVersion\s+=) (\s*)\d+/$1$2 %VersionFull%" "Filename=%VersionHeaderPath%" || goto :error | |
| call :repl "Argument=(AppVersionStr\s+=) (\s*)[&hat;;]+/$1$2 "%VersionStrSmall%"" "Filename=%VersionHeaderPath%" || goto :error | |
| -call :repl "Argument=(AppAlphaVersion\s+=) (\s*)[a-z]+/$1$2 %VersionAlphaBool%" "Filename=%VersionHeaderPath%" || goto :error | |
| +call :repl "Argument=(AppBetaVersion\s+=) (\s*)[a-z]+/$1$2 %VersionBetaBool%" "Filename=%VersionHeaderPath%" || goto :error | |
| echo Patching Telegram.rc... | |
| set "ResourcePath=%FullScriptPath%..\Resources\winrc\Telegram.rc" | |
| -call :repl "Argument=(FILEVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionBeta%" "Filename=%ResourcePath%" || goto :error | |
| -call :repl "Argument=(PRODUCTVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionBeta%" "Filename=%ResourcePath%" || goto :error | |
| -call :repl "Argument=("FileVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionBeta%"" "Filename=%ResourcePath%" || goto :error | |
| -call :repl "Argument=("ProductVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionBeta%"" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=(FILEVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionAlpha%" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=(PRODUCTVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionAlpha%" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=("FileVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionAlpha%"" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=("ProductVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionAlpha%"" "Filename=%ResourcePath%" || goto :error | |
| echo Patching Updater.rc... | |
| set "ResourcePath=%FullScriptPath%..\Resources\winrc\Updater.rc" | |
| -call :repl "Argument=(FILEVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionBeta%" "Filename=%ResourcePath%" || goto :error | |
| -call :repl "Argument=(PRODUCTVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionBeta%" "Filename=%ResourcePath%" || goto :error | |
| -call :repl "Argument=("FileVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionBeta%"" "Filename=%ResourcePath%" || goto :error | |
| -call :repl "Argument=("ProductVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionBeta%"" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=(FILEVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionAlpha%" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=(PRODUCTVERSION) (\s*)\d+,\d+,\d+,\d+/$1$2 %VersionMajor%,%VersionMinor%,%VersionPatch%,%VersionAlpha%" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=("FileVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionAlpha%"" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument=("ProductVersion",) (\s*)"\d+.\d+.\d+.\d+"/$1$2 "%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionAlpha%"" "Filename=%ResourcePath%" || goto :error | |
| echo Patching appxmanifest.xml... | |
| set "ResourcePath=%FullScriptPath%..\Resources\uwp\AppX\AppxManifest.xml" | |
| -call :repl "Argument= (Version=)"\d+.\d+.\d+.\d+"/ $1"%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionBeta%"" "Filename=%ResourcePath%" || goto :error | |
| +call :repl "Argument= (Version=)"\d+.\d+.\d+.\d+"/ $1"%VersionMajor%.%VersionMinor%.%VersionPatch%.%VersionAlpha%"" "Filename=%ResourcePath%" || goto :error | |
| exit /b | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/set_version.sh work/tdesktop-1.4.0/Telegram/build/set_version.sh | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/set_version.sh 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/set_version.sh 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -15,14 +15,14 @@ | |
| VersionMinor="${VersionParts[1]}" | |
| VersionPatch="${VersionParts[2]}" | |
| if [ "${VersionParts[3]}" == "" ]; then | |
| - VersionBeta=0 | |
| VersionAlpha=0 | |
| -elif [ "${VersionParts[3]}" == "alpha" ]; then | |
| VersionBeta=0 | |
| - VersionAlpha=1 | |
| -else | |
| - VersionBeta="${VersionParts[3]}" | |
| +elif [ "${VersionParts[3]}" == "beta" ]; then | |
| VersionAlpha=0 | |
| + VersionBeta=1 | |
| +else | |
| + VersionAlpha="${VersionParts[3]}" | |
| + VersionBeta=0 | |
| fi | |
| VersionMajorCleared=`echo "$VersionMajor % 1000" | bc` | |
| @@ -37,25 +37,25 @@ | |
| if [ "$VersionPatchCleared" != "$VersionPatch" ]; then | |
| Error "Bad patch version!" | |
| fi | |
| -if [ "$VersionAlpha" != "0" ]; then | |
| - if [ "$VersionAlpha" != "1" ]; then | |
| - Error "Bad alpha version!" | |
| +if [ "$VersionBeta" != "0" ]; then | |
| + if [ "$VersionBeta" != "1" ]; then | |
| + Error "Bad beta version!" | |
| fi | |
| - VersionAlphaBool=true | |
| + VersionBetaBool=true | |
| else | |
| - VersionAlphaBool=false | |
| + VersionBetaBool=false | |
| fi | |
| VersionFull=`echo "$VersionMajor * 1000000 + $VersionMinor * 1000 + $VersionPatch" | bc` | |
| -if [ "$VersionBeta" != "0" ]; then | |
| - VersionBetaCleared=`echo "$VersionBeta % 1000" | bc` | |
| - if [ "$VersionBetaCleared" != "$VersionBeta" ]; then | |
| - Error "Bad beta version!" | |
| +if [ "$VersionAlpha" != "0" ]; then | |
| + VersionAlphaCleared=`echo "$VersionAlpha % 1000" | bc` | |
| + if [ "$VersionAlphaCleared" != "$VersionAlpha" ]; then | |
| + Error "Bad alpha version!" | |
| fi | |
| - VersionBetaMul=`echo "$VersionBeta + 1000" | bc` | |
| - VersionFullBeta="$VersionFull${VersionBetaMul:1}" | |
| + VersionAlphaMul=`echo "$VersionAlpha + 1000" | bc` | |
| + VersionFullAlpha="$VersionFull${VersionAlphaMul:1}" | |
| else | |
| - VersionFullBeta=0 | |
| + VersionFullAlpha=0 | |
| fi | |
| VersionStr="$VersionMajor.$VersionMinor.$VersionPatch" | |
| @@ -65,10 +65,10 @@ | |
| VersionStrSmall="$VersionMajor.$VersionMinor" | |
| fi | |
| -if [ "$VersionAlpha" != "0" ]; then | |
| - echo "Setting version: $VersionStr alpha" | |
| -elif [ "$VersionBeta" != "0" ]; then | |
| - echo "Setting version: $VersionStr.$VersionBeta closed beta" | |
| +if [ "$VersionBeta" != "0" ]; then | |
| + echo "Setting version: $VersionStr beta" | |
| +elif [ "$VersionAlpha" != "0" ]; then | |
| + echo "Setting version: $VersionStr.$VersionAlpha closed alpha" | |
| else | |
| echo "Setting version: $VersionStr stable" | |
| fi | |
| @@ -116,30 +116,30 @@ | |
| repl "\(AppVersionStrMajor\) \([ ]*\)[0-9][0-9\.]*" "\1\2 $VersionMajor.$VersionMinor" "$VersionFilePath" | |
| repl "\(AppVersionStrSmall\) \([ ]*\)[0-9][0-9\.]*" "\1\2 $VersionStrSmall" "$VersionFilePath" | |
| repl "\(AppVersionStr\) \([ ]*\)[0-9][0-9\.]*" "\1\2 $VersionStr" "$VersionFilePath" | |
| -repl "\(AlphaChannel\) \([ ]*\)[0-9][0-9]*" "\1\2 $VersionAlpha" "$VersionFilePath" | |
| -repl "\(BetaVersion\) \([ ]*\)[0-9][0-9]*" "\1\2 $VersionFullBeta" "$VersionFilePath" | |
| +repl "\(BetaChannel\) \([ ]*\)[0-9][0-9]*" "\1\2 $VersionBeta" "$VersionFilePath" | |
| +repl "\(AlphaVersion\) \([ ]*\)[0-9][0-9]*" "\1\2 $VersionFullAlpha" "$VersionFilePath" | |
| echo "Patching core/version.h..." | |
| VersionHeaderPath="$FullScriptPath/../SourceFiles/core/version.h" | |
| -repl "\(BETA_VERSION_MACRO [ ]*\)([0-9][0-9]*ULL)" "\1(${VersionFullBeta}ULL)" "$VersionHeaderPath" | |
| +repl "\(ALPHA_VERSION_MACRO [ ]*\)([0-9][0-9]*ULL)" "\1(${VersionFullAlpha}ULL)" "$VersionHeaderPath" | |
| repl "\(AppVersion [ ]*=\) \([ ]*\)[0-9][0-9]*" "\1\2 $VersionFull" "$VersionHeaderPath" | |
| repl "\(AppVersionStr [ ]*=\) \([ ]*\)[^;][^;]*" "\1\2 \"$VersionStrSmall\"" "$VersionHeaderPath" | |
| -repl "\(AppAlphaVersion [ ]*=\) \([ ]*\)[a-z][a-z]*" "\1\2 $VersionAlphaBool" "$VersionHeaderPath" | |
| +repl "\(AppBetaVersion [ ]*=\) \([ ]*\)[a-z][a-z]*" "\1\2 $VersionBetaBool" "$VersionHeaderPath" | |
| echo "Patching Telegram.rc..." | |
| ResourcePath="$FullScriptPath/../Resources/winrc/Telegram.rc" | |
| -repl "\(FILEVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionBeta" "$ResourcePath" | |
| -repl "\(PRODUCTVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionBeta" "$ResourcePath" | |
| -repl "\(\"FileVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionBeta\"" "$ResourcePath" | |
| -repl "\(\"ProductVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionBeta\"" "$ResourcePath" | |
| +repl "\(FILEVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionAlpha" "$ResourcePath" | |
| +repl "\(PRODUCTVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionAlpha" "$ResourcePath" | |
| +repl "\(\"FileVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionAlpha\"" "$ResourcePath" | |
| +repl "\(\"ProductVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionAlpha\"" "$ResourcePath" | |
| echo "Patching Updater.rc..." | |
| ResourcePath="$FullScriptPath/../Resources/winrc/Updater.rc" | |
| -repl "\(FILEVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionBeta" "$ResourcePath" | |
| -repl "\(PRODUCTVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionBeta" "$ResourcePath" | |
| -repl "\(\"FileVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionBeta\"" "$ResourcePath" | |
| -repl "\(\"ProductVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionBeta\"" "$ResourcePath" | |
| +repl "\(FILEVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionAlpha" "$ResourcePath" | |
| +repl "\(PRODUCTVERSION\) \([ ]*\)[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*,[0-9][0-9]*" "\1\2 $VersionMajor,$VersionMinor,$VersionPatch,$VersionAlpha" "$ResourcePath" | |
| +repl "\(\"FileVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionAlpha\"" "$ResourcePath" | |
| +repl "\(\"ProductVersion\",\) \([ ]*\)\"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" "\1\2 \"$VersionMajor.$VersionMinor.$VersionPatch.$VersionAlpha\"" "$ResourcePath" | |
| echo "Patching appxmanifest.xml..." | |
| ResourcePath="$FullScriptPath/../Resources/uwp/AppX/AppxManifest.xml" | |
| -repl " \(Version=\)\"[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*\"" " \1\"$VersionMajor.$VersionMinor.$VersionPatch.$VersionBeta\"" "$ResourcePath" | |
| +repl " \(Version=\)\"[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*\"" " \1\"$VersionMajor.$VersionMinor.$VersionPatch.$VersionAlpha\"" "$ResourcePath" | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/build/version work/tdesktop-1.4.0/Telegram/build/version | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/build/version 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/build/version 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -1,6 +1,6 @@ | |
| -AppVersion 1003014 | |
| -AppVersionStrMajor 1.3 | |
| -AppVersionStrSmall 1.3.14 | |
| -AppVersionStr 1.3.14 | |
| -AlphaChannel 0 | |
| -BetaVersion 0 | |
| +AppVersion 1004000 | |
| +AppVersionStrMajor 1.4 | |
| +AppVersionStrSmall 1.4 | |
| +AppVersionStr 1.4.0 | |
| +BetaChannel 0 | |
| +AlphaVersion 0 | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/common.gypi work/tdesktop-1.4.0/Telegram/gyp/common.gypi | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/common.gypi 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/common.gypi 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -93,6 +93,9 @@ | |
| }, | |
| + 'defines': [ | |
| + 'NOMINMAX' | |
| + ], | |
| 'configurations': { | |
| 'Debug': { | |
| 'defines': [ | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/crl.gyp work/tdesktop-1.4.0/Telegram/gyp/crl.gyp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/crl.gyp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/crl.gyp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -53,6 +53,8 @@ | |
| '<(crl_src_loc)/dispatch/crl_dispatch_queue.h', | |
| '<(crl_src_loc)/dispatch/crl_dispatch_semaphore.cpp', | |
| '<(crl_src_loc)/dispatch/crl_dispatch_semaphore.h', | |
| + '<(crl_src_loc)/mac/crl_mac_time.cpp', | |
| + '<(crl_src_loc)/linux/crl_linux_time.cpp', | |
| '<(crl_src_loc)/qt/crl_qt_async.cpp', | |
| '<(crl_src_loc)/qt/crl_qt_async.h', | |
| '<(crl_src_loc)/qt/crl_qt_semaphore.cpp', | |
| @@ -64,12 +66,15 @@ | |
| '<(crl_src_loc)/winapi/crl_winapi_list.h', | |
| '<(crl_src_loc)/winapi/crl_winapi_semaphore.cpp', | |
| '<(crl_src_loc)/winapi/crl_winapi_semaphore.h', | |
| + '<(crl_src_loc)/winapi/crl_winapi_time.cpp', | |
| '<(crl_src_loc)/crl.h', | |
| '<(crl_src_loc)/crl_async.h', | |
| '<(crl_src_loc)/crl_object_on_queue.h', | |
| '<(crl_src_loc)/crl_on_main.h', | |
| '<(crl_src_loc)/crl_queue.h', | |
| '<(crl_src_loc)/crl_semaphore.h', | |
| + '<(crl_src_loc)/crl_time.cpp', | |
| + '<(crl_src_loc)/crl_time.h', | |
| ], | |
| }], | |
| } | |
| Only in work/tdesktop-1.4.0/Telegram/gyp: lib_base.gyp | |
| Only in work/tdesktop-1.4.0/Telegram/gyp: lib_storage.gyp | |
| Only in work/tdesktop-1.4.0/Telegram/gyp: openssl.gypi | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/refresh.sh work/tdesktop-1.4.0/Telegram/gyp/refresh.sh | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/refresh.sh 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/refresh.sh 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -28,7 +28,7 @@ | |
| #gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode-ninja | |
| #gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode | |
| # use patched gyp with Xcode project generator | |
| - ../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=940 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode | |
| + ../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=1000 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode | |
| fi | |
| cd ../.. | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/settings_mac.gypi work/tdesktop-1.4.0/Telegram/gyp/settings_mac.gypi | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/settings_mac.gypi 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/settings_mac.gypi 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -62,6 +62,7 @@ | |
| 'CLANG_CXX_LANGUAGE_STANDARD': 'c++1z', | |
| 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES', | |
| 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', | |
| + 'ALWAYS_SEARCH_USER_PATHS': 'NO', | |
| }, | |
| 'configurations': { | |
| 'Debug': { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/telegram_mac.gypi work/tdesktop-1.4.0/Telegram/gyp/telegram_mac.gypi | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/telegram_mac.gypi 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/telegram_mac.gypi 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -40,6 +40,7 @@ | |
| 'xcode_settings': { | |
| 'OTHER_CPLUSPLUSFLAGS': [ '-nostdinc++' ], | |
| 'OTHER_LDFLAGS': [ | |
| + '-isysroot', '/', | |
| '-lbase', | |
| '-lcrashpad_client', | |
| '-lcrashpad_util', | |
| @@ -55,14 +56,11 @@ | |
| '/usr/local/macold/lib/libexif.a', | |
| '/usr/local/macold/lib/libc++.a', | |
| '/usr/local/macold/lib/libc++abi.a', | |
| - '<(libs_loc)/macold/openssl/libssl.a', | |
| - '<(libs_loc)/macold/openssl/libcrypto.a', | |
| ], | |
| }, | |
| 'include_dirs': [ | |
| '/usr/local/macold', | |
| '/usr/local/macold/include/c++/v1', | |
| - '<(libs_loc)/macold/openssl/include', | |
| '<(libs_loc)/macold/libexif-0.6.20', | |
| '<(libs_loc)/macold/crashpad', | |
| '<(libs_loc)/macold/crashpad/third_party/mini_chromium/mini_chromium', | |
| @@ -122,14 +120,11 @@ | |
| '/usr/local/lib/libavutil.a', | |
| '/usr/local/lib/libswscale.a', | |
| '/usr/local/lib/libswresample.a', | |
| - '<(libs_loc)/openssl/libssl.a', | |
| - '<(libs_loc)/openssl/libcrypto.a', | |
| ], | |
| }, | |
| 'include_dirs': [ | |
| '<(libs_loc)/crashpad', | |
| '<(libs_loc)/crashpad/third_party/mini_chromium/mini_chromium', | |
| - '<(libs_loc)/openssl/include' | |
| ], | |
| 'configurations': { | |
| 'Debug': { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/telegram_sources.txt work/tdesktop-1.4.0/Telegram/gyp/telegram_sources.txt | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/telegram_sources.txt 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/telegram_sources.txt 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -1,38 +1,3 @@ | |
| -<(src_loc)/base/algorithm.h | |
| -<(src_loc)/base/assertion.h | |
| -<(src_loc)/base/build_config.h | |
| -<(src_loc)/base/bytes.h | |
| -<(src_loc)/base/flags.h | |
| -<(src_loc)/base/enum_mask.h | |
| -<(src_loc)/base/flat_map.h | |
| -<(src_loc)/base/flat_set.h | |
| -<(src_loc)/base/functors.h | |
| -<(src_loc)/base/index_based_iterator.h | |
| -<(src_loc)/base/match_method.h | |
| -<(src_loc)/base/observer.cpp | |
| -<(src_loc)/base/observer.h | |
| -<(src_loc)/base/ordered_set.h | |
| -<(src_loc)/base/openssl_help.h | |
| -<(src_loc)/base/optional.h | |
| -<(src_loc)/base/overload.h | |
| -<(src_loc)/base/parse_helper.cpp | |
| -<(src_loc)/base/parse_helper.h | |
| -<(src_loc)/base/qthelp_regex.h | |
| -<(src_loc)/base/qthelp_url.cpp | |
| -<(src_loc)/base/qthelp_url.h | |
| -<(src_loc)/base/runtime_composer.cpp | |
| -<(src_loc)/base/runtime_composer.h | |
| -<(src_loc)/base/timer.cpp | |
| -<(src_loc)/base/timer.h | |
| -<(src_loc)/base/type_traits.h | |
| -<(src_loc)/base/unique_any.h | |
| -<(src_loc)/base/unique_function.h | |
| -<(src_loc)/base/unique_qptr.h | |
| -<(src_loc)/base/value_ordering.h | |
| -<(src_loc)/base/variant.h | |
| -<(src_loc)/base/virtual_method.h | |
| -<(src_loc)/base/weak_ptr.h | |
| -<(src_loc)/base/zlib_help.h | |
| <(src_loc)/boxes/peers/edit_peer_info_box.cpp | |
| <(src_loc)/boxes/peers/edit_peer_info_box.h | |
| <(src_loc)/boxes/peers/manage_peer_box.cpp | |
| @@ -73,8 +38,6 @@ | |
| <(src_loc)/boxes/local_storage_box.h | |
| <(src_loc)/boxes/mute_settings_box.cpp | |
| <(src_loc)/boxes/mute_settings_box.h | |
| -<(src_loc)/boxes/notifications_box.cpp | |
| -<(src_loc)/boxes/notifications_box.h | |
| <(src_loc)/boxes/peer_list_box.cpp | |
| <(src_loc)/boxes/peer_list_box.h | |
| <(src_loc)/boxes/peer_list_controllers.cpp | |
| @@ -136,7 +99,6 @@ | |
| <(src_loc)/chat_helpers/tabbed_section.h | |
| <(src_loc)/chat_helpers/tabbed_selector.cpp | |
| <(src_loc)/chat_helpers/tabbed_selector.h | |
| -<(src_loc)/core/basic_types.h | |
| <(src_loc)/core/changelogs.cpp | |
| <(src_loc)/core/changelogs.h | |
| <(src_loc)/core/click_handler.cpp | |
| @@ -351,6 +313,8 @@ | |
| <(src_loc)/info/profile/info_profile_values.h | |
| <(src_loc)/info/profile/info_profile_widget.cpp | |
| <(src_loc)/info/profile/info_profile_widget.h | |
| +<(src_loc)/info/settings/info_settings_widget.cpp | |
| +<(src_loc)/info/settings/info_settings_widget.h | |
| <(src_loc)/inline_bots/inline_bot_layout_internal.cpp | |
| <(src_loc)/inline_bots/inline_bot_layout_internal.h | |
| <(src_loc)/inline_bots/inline_bot_layout_item.cpp | |
| @@ -568,36 +532,26 @@ | |
| <(src_loc)/profile/profile_channel_controllers.h | |
| <(src_loc)/profile/profile_cover_drop_area.cpp | |
| <(src_loc)/profile/profile_cover_drop_area.h | |
| -<(src_loc)/settings/settings_advanced_widget.cpp | |
| -<(src_loc)/settings/settings_advanced_widget.h | |
| -<(src_loc)/settings/settings_background_widget.cpp | |
| -<(src_loc)/settings/settings_background_widget.h | |
| -<(src_loc)/settings/settings_block_widget.cpp | |
| -<(src_loc)/settings/settings_block_widget.h | |
| -<(src_loc)/settings/settings_chat_settings_widget.cpp | |
| -<(src_loc)/settings/settings_chat_settings_widget.h | |
| -<(src_loc)/settings/settings_cover.cpp | |
| -<(src_loc)/settings/settings_cover.h | |
| -<(src_loc)/settings/settings_fixed_bar.cpp | |
| -<(src_loc)/settings/settings_fixed_bar.h | |
| -<(src_loc)/settings/settings_general_widget.cpp | |
| -<(src_loc)/settings/settings_general_widget.h | |
| -<(src_loc)/settings/settings_info_widget.cpp | |
| -<(src_loc)/settings/settings_info_widget.h | |
| -<(src_loc)/settings/settings_inner_widget.cpp | |
| -<(src_loc)/settings/settings_inner_widget.h | |
| -<(src_loc)/settings/settings_layer.cpp | |
| -<(src_loc)/settings/settings_layer.h | |
| -<(src_loc)/settings/settings_notifications_widget.cpp | |
| -<(src_loc)/settings/settings_notifications_widget.h | |
| +<(src_loc)/settings/settings_advanced.cpp | |
| +<(src_loc)/settings/settings_advanced.h | |
| +<(src_loc)/settings/settings_chat.cpp | |
| +<(src_loc)/settings/settings_chat.h | |
| +<(src_loc)/settings/settings_codes.cpp | |
| +<(src_loc)/settings/settings_codes.h | |
| +<(src_loc)/settings/settings_common.cpp | |
| +<(src_loc)/settings/settings_common.h | |
| +<(src_loc)/settings/settings_information.cpp | |
| +<(src_loc)/settings/settings_information.h | |
| +<(src_loc)/settings/settings_intro.cpp | |
| +<(src_loc)/settings/settings_intro.h | |
| +<(src_loc)/settings/settings_main.cpp | |
| +<(src_loc)/settings/settings_main.h | |
| +<(src_loc)/settings/settings_notifications.cpp | |
| +<(src_loc)/settings/settings_notifications.h | |
| <(src_loc)/settings/settings_privacy_controllers.cpp | |
| <(src_loc)/settings/settings_privacy_controllers.h | |
| -<(src_loc)/settings/settings_privacy_widget.cpp | |
| -<(src_loc)/settings/settings_privacy_widget.h | |
| -<(src_loc)/settings/settings_scale_widget.cpp | |
| -<(src_loc)/settings/settings_scale_widget.h | |
| -<(src_loc)/settings/settings_widget.cpp | |
| -<(src_loc)/settings/settings_widget.h | |
| +<(src_loc)/settings/settings_privacy_security.cpp | |
| +<(src_loc)/settings/settings_privacy_security.h | |
| <(src_loc)/storage/file_download.cpp | |
| <(src_loc)/storage/file_download.h | |
| <(src_loc)/storage/file_upload.cpp | |
| @@ -810,6 +764,9 @@ | |
| <(minizip_loc)/unzip.c | |
| <(minizip_loc)/unzip.h | |
| +platforms: win | |
| +<(res_loc)/winrc/Telegram.rc | |
| + | |
| platforms: mac | |
| <(sp_media_key_tap_loc)/SPMediaKeyTap.m | |
| <(sp_media_key_tap_loc)/SPMediaKeyTap.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/telegram_win.gypi work/tdesktop-1.4.0/Telegram/gyp/telegram_win.gypi | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/telegram_win.gypi 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/telegram_win.gypi 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,16 +7,10 @@ | |
| { | |
| 'conditions': [[ 'build_win', { | |
| 'msbuild_toolset': 'v141', | |
| - 'sources': [ | |
| - '<(res_loc)/winrc/Telegram.rc', | |
| - ], | |
| 'library_dirs': [ | |
| '<(libs_loc)/ffmpeg', | |
| ], | |
| 'libraries': [ | |
| - '-llibeay32', | |
| - '-lssleay32', | |
| - '-lCrypt32', | |
| '-lzlibstat', | |
| '-lLzmaLib', | |
| '-lUxTheme', | |
| @@ -41,11 +35,7 @@ | |
| }, | |
| 'configurations': { | |
| 'Debug': { | |
| - 'include_dirs': [ | |
| - '<(libs_loc)/openssl/Debug/include', | |
| - ], | |
| 'library_dirs': [ | |
| - '<(libs_loc)/openssl/Debug/lib', | |
| '<(libs_loc)/lzma/C/Util/LzmaLib/Debug', | |
| '<(libs_loc)/opus/win32/VS2015/Win32/Debug', | |
| '<(libs_loc)/openal-soft/build/Debug', | |
| @@ -54,11 +44,7 @@ | |
| ], | |
| }, | |
| 'Release': { | |
| - 'include_dirs': [ | |
| - '<(libs_loc)/openssl/Release/include', | |
| - ], | |
| 'library_dirs': [ | |
| - '<(libs_loc)/openssl/Release/lib', | |
| '<(libs_loc)/lzma/C/Util/LzmaLib/Release', | |
| '<(libs_loc)/opus/win32/VS2015/Win32/Release', | |
| '<(libs_loc)/openal-soft/build/Release', | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/Telegram.gyp work/tdesktop-1.4.0/Telegram/gyp/Telegram.gyp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/Telegram.gyp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/Telegram.gyp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -61,6 +61,7 @@ | |
| 'telegram_win.gypi', | |
| 'telegram_mac.gypi', | |
| 'telegram_linux.gypi', | |
| + 'openssl.gypi', | |
| 'qt.gypi', | |
| 'qt_moc.gypi', | |
| 'qt_rcc.gypi', | |
| @@ -77,13 +78,16 @@ | |
| 'utils.gyp:Updater', | |
| '../ThirdParty/libtgvoip/libtgvoip.gyp:libtgvoip', | |
| 'crl.gyp:crl', | |
| + 'lib_base.gyp:lib_base', | |
| 'lib_export.gyp:lib_export', | |
| + 'lib_storage.gyp:lib_storage', | |
| ], | |
| 'defines': [ | |
| 'AL_LIBTYPE_STATIC', | |
| 'AL_ALEXT_PROTOTYPES', | |
| 'TGVOIP_USE_CXX11_LIB', | |
| + 'XXH_INLINE_ALL', | |
| '<!@(python -c "for s in \'<(build_defines)\'.split(\',\'): print(s)")', | |
| ], | |
| @@ -103,6 +107,7 @@ | |
| '<(submodules_loc)/GSL/include', | |
| '<(submodules_loc)/variant/include', | |
| '<(submodules_loc)/crl/src', | |
| + '<(submodules_loc)/xxHash', | |
| ], | |
| 'sources': [ | |
| '<@(qrc_files)', | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/tests/common_test.gypi work/tdesktop-1.4.0/Telegram/gyp/tests/common_test.gypi | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/tests/common_test.gypi 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/tests/common_test.gypi 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -14,6 +14,7 @@ | |
| '<(submodules_loc)/GSL/include', | |
| '<(submodules_loc)/variant/include', | |
| '<(submodules_loc)/Catch/include', | |
| + '<(submodules_loc)/crl/src', | |
| '<(libs_loc)/range-v3/include', | |
| ], | |
| 'sources': [ | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/gyp/tests/tests.gyp work/tdesktop-1.4.0/Telegram/gyp/tests/tests.gyp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/gyp/tests/tests.gyp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/gyp/tests/tests.gyp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,6 +23,7 @@ | |
| ], | |
| 'dependencies': [ | |
| '<!@(<(list_tests_command))', | |
| + 'tests_storage', | |
| ], | |
| 'sources': [ | |
| '<!@(<(list_tests_command) --sources)', | |
| @@ -102,19 +103,40 @@ | |
| '<(src_loc)/rpl/lifetime.h', | |
| '<(src_loc)/rpl/map.h', | |
| '<(src_loc)/rpl/mappers.h', | |
| - '<(src_loc)/rpl/merge.h', | |
| + '<(src_loc)/rpl/merge.h', | |
| '<(src_loc)/rpl/never.h', | |
| '<(src_loc)/rpl/operators_tests.cpp', | |
| '<(src_loc)/rpl/producer.h', | |
| '<(src_loc)/rpl/producer_tests.cpp', | |
| '<(src_loc)/rpl/range.h', | |
| '<(src_loc)/rpl/rpl.h', | |
| - '<(src_loc)/rpl/skip.h', | |
| + '<(src_loc)/rpl/skip.h', | |
| '<(src_loc)/rpl/take.h', | |
| '<(src_loc)/rpl/then.h', | |
| '<(src_loc)/rpl/type_erased.h', | |
| '<(src_loc)/rpl/variable.h', | |
| '<(src_loc)/rpl/variable_tests.cpp', | |
| ], | |
| + }, { | |
| + 'target_name': 'tests_storage', | |
| + 'includes': [ | |
| + 'common_test.gypi', | |
| + '../openssl.gypi', | |
| + ], | |
| + 'dependencies': [ | |
| + '../lib_storage.gyp:lib_storage', | |
| + ], | |
| + 'sources': [ | |
| + '<(src_loc)/storage/storage_encrypted_file_tests.cpp', | |
| + '<(src_loc)/storage/cache/storage_cache_database_tests.cpp', | |
| + '<(src_loc)/platform/win/windows_dlls.cpp', | |
| + '<(src_loc)/platform/win/windows_dlls.h', | |
| + ], | |
| + 'conditions': [[ 'not build_win', { | |
| + 'sources!': [ | |
| + '<(src_loc)/platform/win/windows_dlls.cpp', | |
| + '<(src_loc)/platform/win/windows_dlls.h', | |
| + ], | |
| + }]], | |
| }], | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/Patches/qtbase_5_6_2.diff work/tdesktop-1.4.0/Telegram/Patches/qtbase_5_6_2.diff | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/Patches/qtbase_5_6_2.diff 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/Patches/qtbase_5_6_2.diff 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -253,7 +253,7 @@ | |
| setError(QAbstractSocket::NetworkError, AddressNotAvailableErrorString); | |
| socketState = QAbstractSocket::UnconnectedState; | |
| diff --git a/src/platformsupport/dbustray/qdbustrayicon.cpp b/src/platformsupport/dbustray/qdbustrayicon.cpp | |
| -index 4d6e707..9bdb0be 100644 | |
| +index 4d6e70720d..9bdb0beb67 100644 | |
| --- a/src/platformsupport/dbustray/qdbustrayicon.cpp | |
| +++ b/src/platformsupport/dbustray/qdbustrayicon.cpp | |
| @@ -58,9 +58,18 @@ QT_BEGIN_NAMESPACE | |
| @@ -667,7 +667,7 @@ | |
| } | |
| return ret; | |
| diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | |
| -index 8152c57ffd..5ddd7b353d 100644 | |
| +index 8152c57ffd..87ba2f3f72 100644 | |
| --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | |
| +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | |
| @@ -94,6 +94,8 @@ QT_USE_NAMESPACE | |
| @@ -783,7 +783,19 @@ | |
| systray = sys; | |
| imageCell = [[QNSImageView alloc] initWithParent:self]; | |
| [item setView: imageCell]; | |
| -@@ -482,6 +513,10 @@ QT_END_NAMESPACE | |
| +@@ -448,6 +479,11 @@ QT_END_NAMESPACE | |
| + -(void)dealloc { | |
| + [[NSStatusBar systemStatusBar] removeStatusItem:item]; | |
| + [[NSNotificationCenter defaultCenter] removeObserver:imageCell]; | |
| ++ | |
| ++ // Patch: Fix crash in macOS 10.14. | |
| ++ // Somehow item and imageCell are retained and attempt to be drawn if left in view. | |
| ++ [item setView: nil]; | |
| ++ | |
| + [imageCell release]; | |
| + [item release]; | |
| + [super dealloc]; | |
| +@@ -482,6 +518,10 @@ QT_END_NAMESPACE | |
| selector:@selector(menuTrackingDone:) | |
| name:NSMenuDidEndTrackingNotification | |
| object:m]; | |
| Only in work/tdesktop-1.4.0/Telegram/Resources: day-blue.tdesktop-theme | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons: add_contact_phone.png | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons: [email protected] | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons: add_contact_user.png | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons: [email protected] | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/menu_new_channel.png and work/tdesktop-1.4.0/Telegram/Resources/icons/menu_new_channel.png differ | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/[email protected] and work/tdesktop-1.4.0/Telegram/Resources/icons/[email protected] differ | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/menu_new_group.png and work/tdesktop-1.4.0/Telegram/Resources/icons/menu_new_group.png differ | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/[email protected] and work/tdesktop-1.4.0/Telegram/Resources/icons/[email protected] differ | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/menu_night_mode.png and work/tdesktop-1.4.0/Telegram/Resources/icons/menu_night_mode.png differ | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/[email protected] and work/tdesktop-1.4.0/Telegram/Resources/icons/[email protected] differ | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/menu_settings.png and work/tdesktop-1.4.0/Telegram/Resources/icons/menu_settings.png differ | |
| Files work.1.3.14/tdesktop-1.3.14/Telegram/Resources/icons/[email protected] and work/tdesktop-1.4.0/Telegram/Resources/icons/[email protected] differ | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_advanced.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_chat.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_edit.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_faq.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_information.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_interface_scale.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_language.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_name.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_notifications.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_phone_number.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_privacy_security.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_stickers.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_themes.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: settings_username.png | |
| Only in work/tdesktop-1.4.0/Telegram/Resources/icons: [email protected] | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/Resources/langs/lang.strings work/tdesktop-1.4.0/Telegram/Resources/langs/lang.strings | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/Resources/langs/lang.strings 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/Resources/langs/lang.strings 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -267,7 +267,7 @@ | |
| "lng_bio_placeholder" = "Bio"; | |
| "lng_bio_about" = "You can add a few lines about yourself. Anyone who opens your profile will see this text."; | |
| -"lng_settings_section_info" = "Info"; | |
| +"lng_settings_section_info" = "My info"; | |
| "lng_settings_username" = "Username:"; | |
| "lng_settings_choose_username" = "Choose username"; | |
| "lng_settings_empty_bio" = "None"; | |
| @@ -278,7 +278,6 @@ | |
| "lng_settings_show_preview" = "Show message preview"; | |
| "lng_settings_use_windows" = "Use Windows notifications"; | |
| "lng_settings_use_native_notifications" = "Use native notifications"; | |
| -"lng_settings_advanced_notifications" = "Notifications position and count"; | |
| "lng_settings_notifications_position" = "Location on the screen"; | |
| "lng_settings_notifications_count" = "Notifications count"; | |
| "lng_settings_sound_notify" = "Play sound"; | |
| @@ -294,6 +293,7 @@ | |
| "lng_languages" = "Languages"; | |
| "lng_sure_save_language" = "Telegram will restart in order to change language"; | |
| "lng_settings_update_automatically" = "Update automatically"; | |
| +"lng_settings_install_beta" = "Install beta versions"; | |
| "lng_settings_current_version_label" = "Version {version}:"; | |
| "lng_settings_current_version" = "Version {version}"; | |
| "lng_settings_check_now" = "Check for updates"; | |
| @@ -324,10 +324,47 @@ | |
| "lng_settings_bg_use_default" = "Use default color theme"; | |
| "lng_settings_bg_from_gallery" = "Choose from gallery"; | |
| "lng_settings_bg_from_file" = "Choose from file"; | |
| -"lng_settings_bg_edit_theme" = "Edit theme"; | |
| +"lng_settings_bg_edit_theme" = "Launch theme editor"; | |
| "lng_settings_bg_tile" = "Tile background"; | |
| "lng_settings_adaptive_wide" = "Adaptive layout for wide screens"; | |
| +"lng_settings_language" = "Language"; | |
| +"lng_settings_default_scale" = "Default interface scale"; | |
| +"lng_settings_connection_type" = "Connection type"; | |
| +"lng_settings_downloading_update" = "Downloading update {progress}..."; | |
| +"lng_settings_privacy_title" = "Privacy"; | |
| +"lng_settings_last_seen" = "Last seen"; | |
| +"lng_settings_calls" = "Voice calls"; | |
| +"lng_settings_groups_invite" = "Groups"; | |
| +"lng_settings_group_privacy_about" = "Change who can add you to groups and channels."; | |
| +"lng_settings_sessions_about" = "Control your sessions on other devices."; | |
| +"lng_settings_passcode_disable" = "Disable passcode"; | |
| +"lng_settings_password_disable" = "Disable cloud password"; | |
| +"lng_settings_about_bio" = "Any details such as age, occupation or city.\nExample: 23 y.o. designer from San Francisco"; | |
| +"lng_settings_name_label" = "Name"; | |
| +"lng_settings_username_label" = "Username"; | |
| +"lng_settings_phone_label" = "Phone number"; | |
| +"lng_settings_username_add" = "Add username"; | |
| +"lng_settings_close_sure" = "Are you sure you want to close this page? You didn't save your changes."; | |
| +"lng_settings_peer_to_peer" = "Peer-to-Peer"; | |
| +"lng_settings_peer_to_peer_about" = "Disabling peer-to-peer will relay all calls through Telegram servers to avoid revealing your IP address, but may slightly decrease audio quality."; | |
| +"lng_settings_advanced" = "Advanced"; | |
| +"lng_settings_stickers_emoji" = "Stickers and emoji"; | |
| +"lng_settings_messages" = "Messages"; | |
| +"lng_settings_themes" = "Themes"; | |
| +"lng_settings_data_storage" = "Data and storage"; | |
| +"lng_settings_information" = "Edit profile"; | |
| +"lng_settings_passcode_title" = "Local passcode"; | |
| +"lng_settings_password_title" = "Two-step verification"; | |
| +"lng_settings_sessions_title" = "Active sessions"; | |
| +"lng_settings_destroy_title" = "Delete my account"; | |
| +"lng_settings_network_proxy" = "Network and proxy"; | |
| +"lng_settings_version_info" = "Version and updates"; | |
| +"lng_settings_system_integration" = "System integration"; | |
| +"lng_settings_performance" = "Performance"; | |
| +"lng_settings_enable_animations" = "Enable animations"; | |
| +"lng_settings_autoplay_gifs" = "Autoplay GIFs"; | |
| + | |
| "lng_backgrounds_header" = "Choose your new chat background"; | |
| "lng_theme_sure_keep" = "Keep this theme?"; | |
| "lng_theme_reverting#one" = "Reverting to the old theme in {count} second."; | |
| @@ -335,10 +372,10 @@ | |
| "lng_theme_keep_changes" = "Keep changes"; | |
| "lng_theme_revert" = "Revert"; | |
| -"lng_download_path_dont_ask" = "Don't ask download path for each file"; | |
| -"lng_download_path_label" = "Download path:"; | |
| -"lng_download_path_temp" = "temp folder"; | |
| -"lng_download_path_default" = "default folder"; | |
| +"lng_download_path_ask" = "Ask download path for each file"; | |
| +"lng_download_path" = "Download path"; | |
| +"lng_download_path_temp" = "Temp folder"; | |
| +"lng_download_path_default" = "Default folder"; | |
| "lng_download_path_clear" = "Clear all"; | |
| "lng_download_path_header" = "Choose download path"; | |
| "lng_download_path_default_radio" = "Telegram folder in system «Downloads»"; | |
| @@ -355,14 +392,28 @@ | |
| "lng_settings_section_privacy" = "Privacy and Security"; | |
| "lng_local_storage_title" = "Local storage"; | |
| -"lng_settings_no_data_cached" = "No cached data found!"; | |
| -"lng_settings_images_cached#one" = "{count} image, {size}"; | |
| -"lng_settings_images_cached#other" = "{count} images, {size}"; | |
| -"lng_settings_audios_cached#one" = "{count} voice message, {size}"; | |
| -"lng_settings_audios_cached#other" = "{count} voice messages, {size}"; | |
| +"lng_local_storage_empty" = "No cached files"; | |
| +"lng_local_storage_image#one" = "{count} image"; | |
| +"lng_local_storage_image#other" = "{count} images"; | |
| +"lng_local_storage_sticker#one" = "{count} sticker"; | |
| +"lng_local_storage_sticker#other" = "{count} stickers"; | |
| +"lng_local_storage_voice#one" = "{count} voice message"; | |
| +"lng_local_storage_voice#other" = "{count} voice messages"; | |
| +"lng_local_storage_round#one" = "{count} video message"; | |
| +"lng_local_storage_round#other" = "{count} video messages"; | |
| +"lng_local_storage_animation#one" = "{count} animation"; | |
| +"lng_local_storage_animation#other" = "{count} animations"; | |
| +"lng_local_storage_size_limit" = "Total size limit: {size}"; | |
| +"lng_local_storage_time_limit" = "Clear files older than: {limit}"; | |
| +"lng_local_storage_limit_weeks#one" = "{count} week"; | |
| +"lng_local_storage_limit_weeks#other" = "{count} weeks"; | |
| +"lng_local_storage_limit_months#one" = "{count} month"; | |
| +"lng_local_storage_limit_months#other" = "{count} months"; | |
| +"lng_local_storage_limit_never" = "Never"; | |
| +"lng_local_storage_summary" = "Summary"; | |
| +"lng_local_storage_clear_some" = "Clear"; | |
| "lng_local_storage_clear" = "Clear all"; | |
| "lng_local_storage_clearing" = "Clearing..."; | |
| -"lng_local_storage_cleared" = "Cleared!"; | |
| "lng_settings_section_advanced_settings" = "Advanced Settings"; | |
| "lng_settings_enable_night_theme" = "Enable night mode"; | |
| @@ -376,8 +427,8 @@ | |
| "lng_passcode_remove" = "Remove local passcode"; | |
| "lng_passcode_turn_off" = "Turn off"; | |
| "lng_passcode_autolock" = "Auto-Lock"; | |
| -"lng_passcode_autolock_away" = "Auto-Lock if away for:"; | |
| -"lng_passcode_autolock_inactive" = "Auto-Lock if inactive for:"; | |
| +"lng_passcode_autolock_away" = "Auto-Lock if away for..."; | |
| +"lng_passcode_autolock_inactive" = "Auto-Lock if inactive for..."; | |
| "lng_passcode_autolock_minutes#one" = "{count} minute"; | |
| "lng_passcode_autolock_minutes#other" = "{count} minutes"; | |
| "lng_passcode_autolock_hours#one" = "{count} hour"; | |
| @@ -423,7 +474,6 @@ | |
| "lng_cloud_password_is_same" = "Password was not changed"; | |
| "lng_cloud_password_passport_losing" = "Warning! All data saved in your Telegram Passport will be lost!"; | |
| -"lng_connection_type" = "Connection type:"; | |
| "lng_connection_auto_connecting" = "Default (connecting...)"; | |
| "lng_connection_auto" = "Default ({transport} used)"; | |
| "lng_connection_proxy_connecting" = "Connecting through proxy..."; | |
| @@ -465,12 +515,9 @@ | |
| "lng_proxy_sponsor_warning" = "This proxy may display a sponsored channel in your chat list. This doesn't reveal any of your Telegram traffic."; | |
| "lng_settings_blocked_users" = "Blocked users"; | |
| -"lng_settings_last_seen_privacy" = "Last seen privacy"; | |
| -"lng_settings_calls_privacy" = "Phone calls privacy"; | |
| -"lng_settings_groups_invite_privacy" = "Group invite settings"; | |
| "lng_settings_show_sessions" = "Show all sessions"; | |
| "lng_settings_export_data" = "Export Telegram data"; | |
| -"lng_settings_self_destruct" = "Account self-destruct settings"; | |
| +"lng_settings_destroy_if" = "If away for..."; | |
| "lng_settings_change_phone" = "Change phone number"; | |
| "lng_settings_reset" = "Terminate all other sessions"; | |
| @@ -509,38 +556,29 @@ | |
| "lng_edit_privacy_exceptions" = "Add exceptions"; | |
| "lng_edit_privacy_lastseen_title" = "Last seen privacy"; | |
| -"lng_edit_privacy_lastseen_description" = "You can choose who can see your last seen time:"; | |
| +"lng_edit_privacy_lastseen_header" = "Who can see your last seen time"; | |
| "lng_edit_privacy_lastseen_warning" = "Important: you won't be able to see Last Seen times for people with whom you don't share your Last Seen time. Approximate last seen will be shown instead (recently, within a week, within a month)."; | |
| "lng_edit_privacy_lastseen_always_empty" = "Always share with"; | |
| -"lng_edit_privacy_lastseen_always#one" = "Always share with {count} user"; | |
| -"lng_edit_privacy_lastseen_always#other" = "Always share with {count} users"; | |
| "lng_edit_privacy_lastseen_never_empty" = "Never share with"; | |
| -"lng_edit_privacy_lastseen_never#one" = "Never share with {count} user"; | |
| -"lng_edit_privacy_lastseen_never#other" = "Never share with {count} users"; | |
| +"lng_edit_privacy_exceptions_count#one" = "{count} user"; | |
| +"lng_edit_privacy_exceptions_count#other" = "{count} users"; | |
| +"lng_edit_privacy_exceptions_add" = "Add users"; | |
| "lng_edit_privacy_lastseen_exceptions" = "These settings will override the values above."; | |
| "lng_edit_privacy_lastseen_always_title" = "Always share with"; | |
| "lng_edit_privacy_lastseen_never_title" = "Never share with"; | |
| "lng_edit_privacy_groups_title" = "Group invite settings"; | |
| -"lng_edit_privacy_groups_description" = "You can choose who can add you to groups and channels with granular precision:"; | |
| +"lng_edit_privacy_groups_header" = "Who can invite you to groups and channels"; | |
| "lng_edit_privacy_groups_always_empty" = "Always allow"; | |
| -"lng_edit_privacy_groups_always#one" = "Always allow {count} user"; | |
| -"lng_edit_privacy_groups_always#other" = "Always allow {count} users"; | |
| "lng_edit_privacy_groups_never_empty" = "Never allow"; | |
| -"lng_edit_privacy_groups_never#one" = "Never allow {count} user"; | |
| -"lng_edit_privacy_groups_never#other" = "Never allow {count} users"; | |
| "lng_edit_privacy_groups_exceptions" = "These users will or will not be able to add you to groups and channels regardless of the settings above."; | |
| "lng_edit_privacy_groups_always_title" = "Always allow"; | |
| "lng_edit_privacy_groups_never_title" = "Never allow"; | |
| -"lng_edit_privacy_calls_title" = "Telegram call privacy"; | |
| -"lng_edit_privacy_calls_description" = "You can restrict who can call you:"; | |
| +"lng_edit_privacy_calls_title" = "Voice calls privacy"; | |
| +"lng_edit_privacy_calls_header" = "Who can call you"; | |
| "lng_edit_privacy_calls_always_empty" = "Always allow"; | |
| -"lng_edit_privacy_calls_always#one" = "Always allow {count} user"; | |
| -"lng_edit_privacy_calls_always#other" = "Always allow {count} users"; | |
| "lng_edit_privacy_calls_never_empty" = "Never allow"; | |
| -"lng_edit_privacy_calls_never#one" = "Never allow {count} user"; | |
| -"lng_edit_privacy_calls_never#other" = "Never allow {count} users"; | |
| "lng_edit_privacy_calls_exceptions" = "These users will or will not be able to call you regardless of the settings above."; | |
| "lng_edit_privacy_calls_always_title" = "Always allow"; | |
| "lng_edit_privacy_calls_never_title" = "Never allow"; | |
| @@ -928,15 +966,15 @@ | |
| "lng_media_video" = "Video"; | |
| "lng_media_audio" = "Voice message"; | |
| -"lng_media_auto_settings" = "Automatic media download settings"; | |
| -"lng_media_auto_photo" = "Automatic photo download"; | |
| -"lng_media_auto_audio" = "Automatic voice message download"; | |
| -"lng_media_auto_gif" = "Automatic GIF download"; | |
| +"lng_media_auto_settings" = "Automatic media download"; | |
| +"lng_media_auto_title" = "Automatically download"; | |
| +"lng_media_photo_title" = "Photos"; | |
| +"lng_media_audio_title" = "Voice messages"; | |
| +"lng_media_gif_title" = "GIFs and animations"; | |
| "lng_media_auto_private_chats" = "Private chats"; | |
| "lng_media_auto_groups" = "Groups and channels"; | |
| "lng_media_auto_play" = "Autoplay"; | |
| -"lng_emoji_category0" = "Frequently used"; | |
| "lng_emoji_category1" = "People"; | |
| "lng_emoji_category2" = "Nature"; | |
| "lng_emoji_category3" = "Food & Drink"; | |
| @@ -975,7 +1013,7 @@ | |
| "lng_stickers_packs_archived" = "Some of your unused stickers have been archived to make room for the sets you've activated."; | |
| "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_you_have" = "Manage sticker packs"; | |
| "lng_stickers_return" = "Undo"; | |
| "lng_stickers_count#one" = "{count} sticker"; | |
| "lng_stickers_count#other" = "{count} stickers"; | |
| @@ -1712,12 +1750,6 @@ | |
| "lng_export_state_chats_list" = "Processing chats..."; | |
| "lng_export_state_chats" = "Chats"; | |
| "lng_export_state_progress" = "{count} / {total}"; | |
| -"lng_export_state_photo" = "Photo"; | |
| -"lng_export_state_video_file" = "Video file"; | |
| -"lng_export_state_voice_message" = "Voice message"; | |
| -"lng_export_state_video_message" = "Round video message"; | |
| -"lng_export_state_sticker" = "Sticker"; | |
| -"lng_export_state_gif" = "Animated GIF"; | |
| "lng_export_progress" = "You can close this window now. Please don't quit Telegram until the data export is completed."; | |
| "lng_export_stop" = "Stop"; | |
| "lng_export_sure_stop" = "Are you sure you want to stop exporting your data?\n\nIf you do, you'll need to start over."; | |
| Only in work/tdesktop-1.4.0/Telegram/Resources: night-green.tdesktop-theme | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/Resources/qrc/telegram.qrc work/tdesktop-1.4.0/Telegram/Resources/qrc/telegram.qrc | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/Resources/qrc/telegram.qrc 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/Resources/qrc/telegram.qrc 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -50,7 +50,9 @@ | |
| <file alias="art/logo_256.png">../art/logo_256.png</file> | |
| <file alias="art/logo_256_no_margin.png">../art/logo_256_no_margin.png</file> | |
| <file alias="art/sunrise.jpg">../art/sunrise.jpg</file> | |
| + <file alias="day-blue.tdesktop-theme">../day-blue.tdesktop-theme</file> | |
| <file alias="night.tdesktop-theme">../night.tdesktop-theme</file> | |
| + <file alias="night-green.tdesktop-theme">../night-green.tdesktop-theme</file> | |
| </qresource> | |
| <qresource prefix="/sounds"> | |
| <file alias="msg_incoming.mp3">../sounds/msg_incoming.mp3</file> | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/Resources/uwp/AppX/AppxManifest.xml work/tdesktop-1.4.0/Telegram/Resources/uwp/AppX/AppxManifest.xml | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/Resources/uwp/AppX/AppxManifest.xml 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/Resources/uwp/AppX/AppxManifest.xml 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,7 +9,7 @@ | |
| <Identity Name="TelegramMessengerLLP.TelegramDesktop" | |
| ProcessorArchitecture="ARCHITECTURE" | |
| Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" | |
| - Version="1.3.14.0" /> | |
| + Version="1.4.0.0" /> | |
| <Properties> | |
| <DisplayName>Telegram Desktop</DisplayName> | |
| <PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName> | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/Resources/winrc/Telegram.rc work/tdesktop-1.4.0/Telegram/Resources/winrc/Telegram.rc | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/Resources/winrc/Telegram.rc 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/Resources/winrc/Telegram.rc 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -34,8 +34,8 @@ | |
| // | |
| VS_VERSION_INFO VERSIONINFO | |
| - FILEVERSION 1,3,14,0 | |
| - PRODUCTVERSION 1,3,14,0 | |
| + FILEVERSION 1,4,0,0 | |
| + PRODUCTVERSION 1,4,0,0 | |
| FILEFLAGSMASK 0x3fL | |
| #ifdef _DEBUG | |
| FILEFLAGS 0x1L | |
| @@ -52,10 +52,10 @@ | |
| BEGIN | |
| VALUE "CompanyName", "Telegram Messenger LLP" | |
| VALUE "FileDescription", "Telegram Desktop" | |
| - VALUE "FileVersion", "1.3.14.0" | |
| + VALUE "FileVersion", "1.4.0.0" | |
| VALUE "LegalCopyright", "Copyright (C) 2014-2018" | |
| VALUE "ProductName", "Telegram Desktop" | |
| - VALUE "ProductVersion", "1.3.14.0" | |
| + VALUE "ProductVersion", "1.4.0.0" | |
| END | |
| END | |
| BLOCK "VarFileInfo" | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/Resources/winrc/Updater.rc work/tdesktop-1.4.0/Telegram/Resources/winrc/Updater.rc | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/Resources/winrc/Updater.rc 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/Resources/winrc/Updater.rc 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -25,8 +25,8 @@ | |
| // | |
| VS_VERSION_INFO VERSIONINFO | |
| - FILEVERSION 1,3,14,0 | |
| - PRODUCTVERSION 1,3,14,0 | |
| + FILEVERSION 1,4,0,0 | |
| + PRODUCTVERSION 1,4,0,0 | |
| FILEFLAGSMASK 0x3fL | |
| #ifdef _DEBUG | |
| FILEFLAGS 0x1L | |
| @@ -43,10 +43,10 @@ | |
| BEGIN | |
| VALUE "CompanyName", "Telegram Messenger LLP" | |
| VALUE "FileDescription", "Telegram Desktop Updater" | |
| - VALUE "FileVersion", "1.3.14.0" | |
| + VALUE "FileVersion", "1.4.0.0" | |
| VALUE "LegalCopyright", "Copyright (C) 2014-2018" | |
| VALUE "ProductName", "Telegram Desktop" | |
| - VALUE "ProductVersion", "1.3.14.0" | |
| + VALUE "ProductVersion", "1.4.0.0" | |
| END | |
| END | |
| BLOCK "VarFileInfo" | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/_other/packer.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/_other/packer.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/_other/packer.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/_other/packer.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -13,8 +13,8 @@ | |
| //Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin) | |
| #endif | |
| -bool AlphaChannel = false; | |
| -quint64 BetaVersion = 0; | |
| +bool BetaChannel = false; | |
| +quint64 AlphaVersion = 0; | |
| const char *PublicKey = "\ | |
| -----BEGIN RSA PUBLIC KEY-----\n\ | |
| @@ -24,7 +24,7 @@ | |
| -----END RSA PUBLIC KEY-----\ | |
| "; | |
| -const char *PublicAlphaKey = "\ | |
| +const char *PublicBetaKey = "\ | |
| -----BEGIN RSA PUBLIC KEY-----\n\ | |
| MIGJAoGBALWu9GGs0HED7KG7BM73CFZ6o0xufKBRQsdnq3lwA8nFQEvmdu+g/I1j\n\ | |
| 0LQ+0IQO7GW4jAgzF/4+soPDb6uHQeNFrlVx1JS9DZGhhjZ5rf65yg11nTCIHZCG\n\ | |
| @@ -33,11 +33,11 @@ | |
| "; | |
| extern const char *PrivateKey; | |
| -extern const char *PrivateAlphaKey; | |
| +extern const char *PrivateBetaKey; | |
| #include "../../../../TelegramPrivate/packer_private.h" // RSA PRIVATE KEYS for update signing | |
| -#include "../../../../TelegramPrivate/beta_private.h" // private key for beta version file generation | |
| +#include "../../../../TelegramPrivate/alpha_private.h" // private key for alpha version file generation | |
| -QString countBetaVersionSignature(quint64 version); | |
| +QString countAlphaVersionSignature(quint64 version); | |
| // sha1 hash | |
| typedef unsigned char uchar; | |
| @@ -124,7 +124,7 @@ | |
| return (int32*)sha1To; | |
| } | |
| -QString BetaSignature; | |
| +QString AlphaSignature; | |
| int main(int argc, char *argv[]) | |
| { | |
| @@ -144,18 +144,18 @@ | |
| target32 = (string("mac32") == argv[i + 1]); | |
| } else if (string("-version") == argv[i] && i + 1 < argc) { | |
| version = QString(argv[i + 1]).toInt(); | |
| - } else if (string("-alpha") == argv[i]) { | |
| - AlphaChannel = true; | |
| - } else if (string("-beta") == argv[i] && i + 1 < argc) { | |
| - BetaVersion = QString(argv[i + 1]).toULongLong(); | |
| - if (BetaVersion > version * 1000ULL && BetaVersion < (version + 1) * 1000ULL) { | |
| - AlphaChannel = false; | |
| - BetaSignature = countBetaVersionSignature(BetaVersion); | |
| - if (BetaSignature.isEmpty()) { | |
| + } else if (string("-beta") == argv[i]) { | |
| + BetaChannel = true; | |
| + } else if (string("-alpha") == argv[i] && i + 1 < argc) { | |
| + AlphaVersion = QString(argv[i + 1]).toULongLong(); | |
| + if (AlphaVersion > version * 1000ULL && AlphaVersion < (version + 1) * 1000ULL) { | |
| + BetaChannel = false; | |
| + AlphaSignature = countAlphaVersionSignature(AlphaVersion); | |
| + if (AlphaSignature.isEmpty()) { | |
| return -1; | |
| } | |
| } else { | |
| - cout << "Bad -beta param value passed, should be for the same version: " << version << ", beta: " << BetaVersion << "\n"; | |
| + cout << "Bad -alpha param value passed, should be for the same version: " << version << ", alpha: " << AlphaVersion << "\n"; | |
| return -1; | |
| } | |
| } | |
| @@ -211,9 +211,9 @@ | |
| QDataStream stream(&buffer); | |
| stream.setVersion(QDataStream::Qt_5_1); | |
| - if (BetaVersion) { | |
| + if (AlphaVersion) { | |
| stream << quint32(0x7FFFFFFF); | |
| - stream << quint64(BetaVersion); | |
| + stream << quint64(AlphaVersion); | |
| } else { | |
| stream << quint32(version); | |
| } | |
| @@ -407,7 +407,7 @@ | |
| uint32 siglen = 0; | |
| cout << "Signing..\n"; | |
| - RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>((AlphaChannel || BetaVersion) ? PrivateAlphaKey : PrivateKey), -1), 0, 0, 0); | |
| + RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>((BetaChannel || AlphaVersion) ? PrivateBetaKey : PrivateKey), -1), 0, 0, 0); | |
| if (!prKey) { | |
| cout << "Could not read RSA private key!\n"; | |
| return -1; | |
| @@ -430,7 +430,7 @@ | |
| } | |
| cout << "Checking signature..\n"; | |
| - RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>((AlphaChannel || BetaVersion) ? PublicAlphaKey : PublicKey), -1), 0, 0, 0); | |
| + RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>((BetaChannel || AlphaVersion) ? PublicBetaKey : PublicKey), -1), 0, 0, 0); | |
| if (!pbKey) { | |
| cout << "Could not read RSA public key!\n"; | |
| return -1; | |
| @@ -443,18 +443,18 @@ | |
| cout << "Signature verified!\n"; | |
| RSA_free(pbKey); | |
| #ifdef Q_OS_WIN | |
| - QString outName(QString("tupdate%1").arg(BetaVersion ? BetaVersion : version)); | |
| + QString outName(QString("tupdate%1").arg(AlphaVersion ? AlphaVersion : version)); | |
| #elif defined Q_OS_MAC | |
| - QString outName((target32 ? QString("tmac32upd%1") : QString("tmacupd%1")).arg(BetaVersion ? BetaVersion : version)); | |
| + QString outName((target32 ? QString("tmac32upd%1") : QString("tmacupd%1")).arg(AlphaVersion ? AlphaVersion : version)); | |
| #elif defined Q_OS_LINUX32 | |
| - QString outName(QString("tlinux32upd%1").arg(BetaVersion ? BetaVersion : version)); | |
| + QString outName(QString("tlinux32upd%1").arg(AlphaVersion ? AlphaVersion : version)); | |
| #elif defined Q_OS_LINUX64 | |
| - QString outName(QString("tlinuxupd%1").arg(BetaVersion ? BetaVersion : version)); | |
| + QString outName(QString("tlinuxupd%1").arg(AlphaVersion ? AlphaVersion : version)); | |
| #else | |
| #error Unknown platform! | |
| #endif | |
| - if (BetaVersion) { | |
| - outName += "_" + BetaSignature; | |
| + if (AlphaVersion) { | |
| + outName += "_" + AlphaSignature; | |
| } | |
| QFile out(outName); | |
| if (!out.open(QIODevice::WriteOnly)) { | |
| @@ -464,14 +464,14 @@ | |
| out.write(compressed); | |
| out.close(); | |
| - if (BetaVersion) { | |
| - QString keyName(QString("tbeta_%1_key").arg(BetaVersion)); | |
| + if (AlphaVersion) { | |
| + QString keyName(QString("talpha_%1_key").arg(AlphaVersion)); | |
| 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.write(AlphaSignature.toUtf8()); | |
| key.close(); | |
| } | |
| @@ -480,10 +480,10 @@ | |
| return 0; | |
| } | |
| -QString countBetaVersionSignature(quint64 version) { // duplicated in autoupdater.cpp | |
| - QByteArray cBetaPrivateKey(BetaPrivateKey); | |
| - if (cBetaPrivateKey.isEmpty()) { | |
| - cout << "Error: Trying to count beta version signature without beta private key!\n"; | |
| +QString countAlphaVersionSignature(quint64 version) { // duplicated in autoupdater.cpp | |
| + QByteArray cAlphaPrivateKey(AlphaPrivateKey); | |
| + if (cAlphaPrivateKey.isEmpty()) { | |
| + cout << "Error: Trying to count alpha version signature without alpha private key!\n"; | |
| return QString(); | |
| } | |
| @@ -496,27 +496,27 @@ | |
| uint32 siglen = 0; | |
| - RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cBetaPrivateKey.constData()), -1), 0, 0, 0); | |
| + RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cAlphaPrivateKey.constData()), -1), 0, 0, 0); | |
| if (!prKey) { | |
| - cout << "Error: Could not read beta private key!\n"; | |
| + cout << "Error: Could not read alpha private key!\n"; | |
| return QString(); | |
| } | |
| if (RSA_size(prKey) != keySize) { | |
| - cout << "Error: Bad beta private key size: " << RSA_size(prKey) << "\n"; | |
| + cout << "Error: Bad alpha 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"; | |
| + cout << "Error: Counting alpha version signature failed!\n"; | |
| RSA_free(prKey); | |
| return QString(); | |
| } | |
| RSA_free(prKey); | |
| if (siglen != keySize) { | |
| - cout << "Error: Bad beta version signature length: " << siglen << "\n"; | |
| + cout << "Error: Bad alpha version signature length: " << siglen << "\n"; | |
| return QString(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/_other/updater.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/_other/updater.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/_other/updater.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/_other/updater.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -144,7 +144,7 @@ | |
| if (!ReadFile(versionFile, &versionNum, sizeof(DWORD), &readLen, NULL) || readLen != sizeof(DWORD)) { | |
| versionNum = 0; | |
| } else { | |
| - if (versionNum == 0x7FFFFFFF) { // beta version | |
| + if (versionNum == 0x7FFFFFFF) { // alpha version | |
| } else if (!ReadFile(versionFile, &versionLen, sizeof(DWORD), &readLen, NULL) || readLen != sizeof(DWORD) || versionLen > 63) { | |
| versionNum = 0; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/apiwrap.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/apiwrap.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/apiwrap.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/apiwrap.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -18,6 +18,8 @@ | |
| #include "data/data_session.h" | |
| #include "dialogs/dialogs_key.h" | |
| #include "core/tl_help.h" | |
| +#include "core/core_cloud_password.h" | |
| +#include "base/openssl_help.h" | |
| #include "base/overload.h" | |
| #include "observer_peer.h" | |
| #include "lang/lang_keys.h" | |
| @@ -43,6 +45,7 @@ | |
| #include "ui/text_options.h" | |
| #include "storage/localimageloader.h" | |
| #include "storage/file_download.h" | |
| +#include "storage/file_upload.h" | |
| #include "storage/storage_facade.h" | |
| #include "storage/storage_shared_media.h" | |
| #include "storage/storage_user_photos.h" | |
| @@ -144,6 +147,16 @@ | |
| : history(history) { | |
| } | |
| +MTPInputPrivacyKey ApiWrap::Privacy::Input(Key key) { | |
| + switch (key) { | |
| + case Privacy::Key::Calls: return MTP_inputPrivacyKeyPhoneCall(); | |
| + case Privacy::Key::Invites: return MTP_inputPrivacyKeyChatInvite(); | |
| + case Privacy::Key::LastSeen: | |
| + return MTP_inputPrivacyKeyStatusTimestamp(); | |
| + } | |
| + Unexpected("Key in ApiWrap::Privacy::Input."); | |
| +} | |
| + | |
| ApiWrap::ApiWrap(not_null<AuthSession*> session) | |
| : _session(session) | |
| , _messageDataResolveDelayed([=] { resolveMessageDatas(); }) | |
| @@ -154,6 +167,12 @@ | |
| , _feedReadTimer([=] { readFeeds(); }) | |
| , _proxyPromotionTimer([=] { refreshProxyPromotion(); }) | |
| , _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); }) { | |
| + crl::on_main([=] { | |
| + _session->uploader().photoReady( | |
| + ) | rpl::start_with_next([=](const Storage::UploadedPhoto &data) { | |
| + photoUploadReady(data.fullId, data.file); | |
| + }, _session->lifetime()); | |
| + }); | |
| } | |
| void ApiWrap::requestChangelog( | |
| @@ -538,8 +557,8 @@ | |
| if (contact.type() != mtpc_contact) continue; | |
| const auto userId = contact.c_contact().vuser_id.v; | |
| - if (userId == _session->userId() && App::self()) { | |
| - App::self()->setContactStatus( | |
| + if (userId == _session->userId()) { | |
| + Auth().user()->setContactStatus( | |
| UserData::ContactStatus::Contact); | |
| } | |
| } | |
| @@ -591,11 +610,23 @@ | |
| // }).send(); | |
| //} | |
| -void ApiWrap::requestDialogEntry(not_null<History*> history) { | |
| - if (_dialogRequests.contains(history)) { | |
| +void ApiWrap::requestDialogEntry( | |
| + not_null<History*> history, | |
| + Fn<void()> callback) { | |
| + const auto[i, ok] = _dialogRequests.try_emplace(history); | |
| + if (callback) { | |
| + i->second.push_back(std::move(callback)); | |
| + } | |
| + if (!ok) { | |
| return; | |
| } | |
| - _dialogRequests.emplace(history); | |
| + const auto finalize = [=] { | |
| + if (const auto callbacks = _dialogRequests.take(history)) { | |
| + for (const auto callback : *callbacks) { | |
| + callback(); | |
| + } | |
| + } | |
| + }; | |
| auto peers = QVector<MTPInputDialogPeer>( | |
| 1, | |
| MTP_inputDialogPeer(history->peer->input)); | |
| @@ -604,9 +635,9 @@ | |
| )).done([=](const MTPmessages_PeerDialogs &result) { | |
| applyPeerDialogs(result); | |
| historyDialogEntryApplied(history); | |
| - _dialogRequests.remove(history); | |
| + finalize(); | |
| }).fail([=](const RPCError &error) { | |
| - _dialogRequests.remove(history); | |
| + finalize(); | |
| }).send(); | |
| } | |
| @@ -744,7 +775,9 @@ | |
| _fullPeerRequests.remove(peer); | |
| }; | |
| if (auto user = peer->asUser()) { | |
| - return request(MTPusers_GetFullUser(user->inputUser)).done([this, user](const MTPUserFull &result, mtpRequestId requestId) { | |
| + return request(MTPusers_GetFullUser( | |
| + user->inputUser | |
| + )).done([this, user](const MTPUserFull &result, mtpRequestId requestId) { | |
| gotUserFull(user, result, requestId); | |
| }).fail(failHandler).send(); | |
| } else if (auto chat = peer->asChat()) { | |
| @@ -927,6 +960,13 @@ | |
| void ApiWrap::gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req) { | |
| auto &d = result.c_userFull(); | |
| + if (user == _session->user() && !_session->validateSelf(d.vuser)) { | |
| + constexpr auto kRequestUserAgainTimeout = TimeMs(10000); | |
| + App::CallDelayed(kRequestUserAgainTimeout, _session, [=] { | |
| + requestFullPeer(user); | |
| + }); | |
| + return; | |
| + } | |
| App::feedUsers(MTP_vector<MTPUser>(1, d.vuser)); | |
| if (d.has_profile_photo()) { | |
| _session->data().photo(d.vprofile_photo); | |
| @@ -1375,7 +1415,7 @@ | |
| channel->inviter = _session->userId(); | |
| channel->inviteDate = channel->date; | |
| if (channel->mgInfo) { | |
| - channel->mgInfo->creator = App::self(); | |
| + channel->mgInfo->creator = Auth().user(); | |
| } | |
| } break; | |
| case mtpc_channelParticipantAdmin: { | |
| @@ -1871,118 +1911,150 @@ | |
| } | |
| void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules) { | |
| - auto keyTypeId = key.type(); | |
| - auto it = _privacySaveRequests.find(keyTypeId); | |
| + const auto keyTypeId = key.type(); | |
| + const auto it = _privacySaveRequests.find(keyTypeId); | |
| if (it != _privacySaveRequests.cend()) { | |
| request(it->second).cancel(); | |
| _privacySaveRequests.erase(it); | |
| } | |
| - auto requestId = request(MTPaccount_SetPrivacy(key, MTP_vector<MTPInputPrivacyRule>(std::move(rules)))).done([this, keyTypeId](const MTPaccount_PrivacyRules &result) { | |
| + const auto requestId = request(MTPaccount_SetPrivacy( | |
| + key, | |
| + MTP_vector<MTPInputPrivacyRule>(std::move(rules)) | |
| + )).done([=](const MTPaccount_PrivacyRules &result) { | |
| Expects(result.type() == mtpc_account_privacyRules); | |
| auto &rules = result.c_account_privacyRules(); | |
| App::feedUsers(rules.vusers); | |
| _privacySaveRequests.remove(keyTypeId); | |
| handlePrivacyChange(keyTypeId, rules.vrules); | |
| - }).fail([this, keyTypeId](const RPCError &error) { | |
| + }).fail([=](const RPCError &error) { | |
| _privacySaveRequests.remove(keyTypeId); | |
| }).send(); | |
| _privacySaveRequests.emplace(keyTypeId, requestId); | |
| } | |
| -void ApiWrap::handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules) { | |
| - if (keyTypeId == mtpc_privacyKeyStatusTimestamp) { | |
| - enum class Rule { | |
| - Unknown, | |
| - Allow, | |
| - Disallow, | |
| - }; | |
| - auto userRules = QMap<UserId, Rule>(); | |
| - auto contactsRule = Rule::Unknown; | |
| - auto everyoneRule = Rule::Unknown; | |
| - for (auto &rule : rules.v) { | |
| - auto type = rule.type(); | |
| - if (type != mtpc_privacyValueAllowAll && type != mtpc_privacyValueDisallowAll && contactsRule != Rule::Unknown) { | |
| - // This is simplified: we ignore per-user rules that come after a contacts rule. | |
| - // But none of the official apps provide such complicated rule sets, so its fine. | |
| - continue; | |
| - } | |
| - | |
| - switch (type) { | |
| - case mtpc_privacyValueAllowAll: everyoneRule = Rule::Allow; break; | |
| - case mtpc_privacyValueDisallowAll: everyoneRule = Rule::Disallow; break; | |
| - case mtpc_privacyValueAllowContacts: contactsRule = Rule::Allow; break; | |
| - case mtpc_privacyValueDisallowContacts: contactsRule = Rule::Disallow; break; | |
| - case mtpc_privacyValueAllowUsers: { | |
| - for_const (auto &userId, rule.c_privacyValueAllowUsers().vusers.v) { | |
| - if (!userRules.contains(userId.v)) { | |
| - userRules.insert(userId.v, Rule::Allow); | |
| - } | |
| - } | |
| - } break; | |
| - case mtpc_privacyValueDisallowUsers: { | |
| - for_const (auto &userId, rule.c_privacyValueDisallowUsers().vusers.v) { | |
| - if (!userRules.contains(userId.v)) { | |
| - userRules.insert(userId.v, Rule::Disallow); | |
| - } | |
| - } | |
| - } break; | |
| - } | |
| - if (everyoneRule != Rule::Unknown) { | |
| - break; | |
| - } | |
| +void ApiWrap::handlePrivacyChange( | |
| + mtpTypeId keyTypeId, | |
| + const MTPVector<MTPPrivacyRule> &rules) { | |
| + using Key = Privacy::Key; | |
| + const auto key = [&]() -> std::optional<Key> { | |
| + switch (keyTypeId) { | |
| + case mtpc_privacyKeyStatusTimestamp: | |
| + case mtpc_inputPrivacyKeyStatusTimestamp: return Key::LastSeen; | |
| + case mtpc_privacyKeyChatInvite: | |
| + case mtpc_inputPrivacyKeyChatInvite: return Key::Invites; | |
| + case mtpc_privacyKeyPhoneCall: | |
| + case mtpc_inputPrivacyKeyPhoneCall: return Key::Calls; | |
| } | |
| + return std::nullopt; | |
| + }(); | |
| + if (!key) { | |
| + return; | |
| + } | |
| + pushPrivacy(*key, rules.v); | |
| + if (*key == Key::LastSeen) { | |
| + updatePrivacyLastSeens(rules.v); | |
| + } | |
| +} | |
| - auto now = unixtime(); | |
| - App::enumerateUsers([&](UserData *user) { | |
| - if (user->isSelf() || user->loadedStatus != PeerData::FullLoaded) { | |
| - return; | |
| +void ApiWrap::updatePrivacyLastSeens(const QVector<MTPPrivacyRule> &rules) { | |
| + enum class Rule { | |
| + Unknown, | |
| + Allow, | |
| + Disallow, | |
| + }; | |
| + auto userRules = QMap<UserId, Rule>(); | |
| + auto contactsRule = Rule::Unknown; | |
| + auto everyoneRule = Rule::Unknown; | |
| + for (auto &rule : rules) { | |
| + auto type = rule.type(); | |
| + if (type != mtpc_privacyValueAllowAll | |
| + && type != mtpc_privacyValueDisallowAll | |
| + && contactsRule != Rule::Unknown) { | |
| + // This is simplified: we ignore per-user rules that come after a contacts rule. | |
| + // But none of the official apps provide such complicated rule sets, so its fine. | |
| + continue; | |
| + } | |
| + | |
| + switch (type) { | |
| + case mtpc_privacyValueAllowAll: everyoneRule = Rule::Allow; break; | |
| + case mtpc_privacyValueDisallowAll: everyoneRule = Rule::Disallow; break; | |
| + case mtpc_privacyValueAllowContacts: contactsRule = Rule::Allow; break; | |
| + case mtpc_privacyValueDisallowContacts: contactsRule = Rule::Disallow; break; | |
| + case mtpc_privacyValueAllowUsers: { | |
| + for_const (auto &userId, rule.c_privacyValueAllowUsers().vusers.v) { | |
| + if (!userRules.contains(userId.v)) { | |
| + userRules.insert(userId.v, Rule::Allow); | |
| + } | |
| } | |
| - if (user->onlineTill <= 0) { | |
| - return; | |
| + } break; | |
| + case mtpc_privacyValueDisallowUsers: { | |
| + for_const (auto &userId, rule.c_privacyValueDisallowUsers().vusers.v) { | |
| + if (!userRules.contains(userId.v)) { | |
| + userRules.insert(userId.v, Rule::Disallow); | |
| + } | |
| } | |
| + } break; | |
| + } | |
| + if (everyoneRule != Rule::Unknown) { | |
| + break; | |
| + } | |
| + } | |
| - if (user->onlineTill + 3 * 86400 >= now) { | |
| - user->onlineTill = -2; // recently | |
| - } else if (user->onlineTill + 7 * 86400 >= now) { | |
| - user->onlineTill = -3; // last week | |
| - } else if (user->onlineTill + 30 * 86400 >= now) { | |
| - user->onlineTill = -4; // last month | |
| - } else { | |
| - user->onlineTill = 0; | |
| - } | |
| - Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserOnlineChanged); | |
| - }); | |
| + auto now = unixtime(); | |
| + App::enumerateUsers([&](UserData *user) { | |
| + if (user->isSelf() || user->loadedStatus != PeerData::FullLoaded) { | |
| + return; | |
| + } | |
| + if (user->onlineTill <= 0) { | |
| + return; | |
| + } | |
| - if (_contactsStatusesRequestId) { | |
| - request(_contactsStatusesRequestId).cancel(); | |
| + if (user->onlineTill + 3 * 86400 >= now) { | |
| + user->onlineTill = -2; // recently | |
| + } else if (user->onlineTill + 7 * 86400 >= now) { | |
| + user->onlineTill = -3; // last week | |
| + } else if (user->onlineTill + 30 * 86400 >= now) { | |
| + user->onlineTill = -4; // last month | |
| + } else { | |
| + user->onlineTill = 0; | |
| } | |
| - _contactsStatusesRequestId = request(MTPcontacts_GetStatuses()).done([this](const MTPVector<MTPContactStatus> &result) { | |
| - _contactsStatusesRequestId = 0; | |
| - for_const (auto &item, result.v) { | |
| - Assert(item.type() == mtpc_contactStatus); | |
| - auto &data = item.c_contactStatus(); | |
| - if (auto user = App::userLoaded(data.vuser_id.v)) { | |
| - auto oldOnlineTill = user->onlineTill; | |
| - auto newOnlineTill = onlineTillFromStatus(data.vstatus, oldOnlineTill); | |
| - if (oldOnlineTill != newOnlineTill) { | |
| - user->onlineTill = newOnlineTill; | |
| - Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserOnlineChanged); | |
| - } | |
| + Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserOnlineChanged); | |
| + }); | |
| + | |
| + if (_contactsStatusesRequestId) { | |
| + request(_contactsStatusesRequestId).cancel(); | |
| + } | |
| + _contactsStatusesRequestId = request(MTPcontacts_GetStatuses( | |
| + )).done([=](const MTPVector<MTPContactStatus> &result) { | |
| + _contactsStatusesRequestId = 0; | |
| + for_const (auto &item, result.v) { | |
| + Assert(item.type() == mtpc_contactStatus); | |
| + auto &data = item.c_contactStatus(); | |
| + if (auto user = App::userLoaded(data.vuser_id.v)) { | |
| + auto oldOnlineTill = user->onlineTill; | |
| + auto newOnlineTill = OnlineTillFromStatus(data.vstatus, oldOnlineTill); | |
| + if (oldOnlineTill != newOnlineTill) { | |
| + user->onlineTill = newOnlineTill; | |
| + Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserOnlineChanged); | |
| } | |
| } | |
| - }).fail([this](const RPCError &error) { | |
| - _contactsStatusesRequestId = 0; | |
| - }).send(); | |
| - } | |
| + } | |
| + }).fail([this](const RPCError &error) { | |
| + _contactsStatusesRequestId = 0; | |
| + }).send(); | |
| } | |
| -int ApiWrap::onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill) { | |
| +int ApiWrap::OnlineTillFromStatus( | |
| + const MTPUserStatus &status, | |
| + int currentOnlineTill) { | |
| switch (status.type()) { | |
| case mtpc_userStatusEmpty: return 0; | |
| - case mtpc_userStatusRecently: return (currentOnlineTill > -10) ? -2 : currentOnlineTill; // don't modify pseudo-online | |
| + case mtpc_userStatusRecently: | |
| + // Don't modify pseudo-online. | |
| + return (currentOnlineTill > -10) ? -2 : currentOnlineTill; | |
| case mtpc_userStatusLastWeek: return -3; | |
| case mtpc_userStatusLastMonth: return -4; | |
| case mtpc_userStatusOffline: return status.c_userStatusOffline().vwas_online.v; | |
| @@ -2390,7 +2462,11 @@ | |
| request(std::move(data)).done([=](const auto &result) { | |
| const auto parsed = Data::GetFileReferences(result); | |
| - for (const auto &[origin, reference] : parsed) { | |
| + for (const auto &p : parsed) { | |
| + // Unpack here the parsed pair by hand to workaround a GCC bug. | |
| + // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87122 | |
| + const auto &origin = p.first; | |
| + const auto &reference = p.second; | |
| const auto documentId = base::get_if<DocumentFileLocationId>( | |
| &origin); | |
| if (documentId) { | |
| @@ -2441,9 +2517,11 @@ | |
| if (additional) { | |
| const auto i = _fileReferenceHandlers.find(origin); | |
| Assert(i != end(_fileReferenceHandlers)); | |
| - i->second.push_back([=](auto&&) { | |
| - additional(); | |
| - }); | |
| + if (i->second.size() == 1) { | |
| + i->second.push_back([=](auto&&) { | |
| + additional(); | |
| + }); | |
| + } | |
| } | |
| }; | |
| const auto fail = [&] { | |
| @@ -2518,7 +2596,7 @@ | |
| request( | |
| MTPmessages_GetSavedGifs(MTP_int(0)), | |
| [] { crl::on_main([] { Local::writeSavedGifs(); }); }); | |
| - }, [&](base::none_type) { | |
| + }, [&](std::nullopt_t) { | |
| fail(); | |
| }); | |
| } | |
| @@ -4172,7 +4250,7 @@ | |
| void ApiWrap::sendUploadedDocument( | |
| FullMsgId localId, | |
| const MTPInputFile &file, | |
| - const base::optional<MTPInputFile> &thumb, | |
| + const std::optional<MTPInputFile> &thumb, | |
| bool silent) { | |
| if (const auto item = App::histItemById(localId)) { | |
| auto media = item->media(); | |
| @@ -4341,7 +4419,7 @@ | |
| not_null<UserData*> bot, | |
| not_null<InlineBots::Result*> data, | |
| const SendOptions &options) { | |
| - Auth().api().sendAction(options); | |
| + sendAction(options); | |
| const auto history = options.history; | |
| const auto peer = history->peer; | |
| @@ -4372,9 +4450,9 @@ | |
| flags |= MTPDmessage::Flag::f_via_bot_id; | |
| } | |
| - auto messageFromId = channelPost ? 0 : Auth().userId(); | |
| + auto messageFromId = channelPost ? 0 : _session->userId(); | |
| auto messagePostAuthor = channelPost | |
| - ? App::peerName(Auth().user()) | |
| + ? App::peerName(_session->user()) | |
| : QString(); | |
| MTPint messageDate = MTP_int(unixtime()); | |
| UserId messageViaBotId = bot ? peerToUser(bot->id) : 0; | |
| @@ -4421,7 +4499,7 @@ | |
| Data::FileOrigin origin, | |
| TextWithEntities caption, | |
| const SendOptions &options) { | |
| - Auth().api().sendAction(options); | |
| + sendAction(options); | |
| const auto history = options.history; | |
| const auto peer = history->peer; | |
| @@ -4435,7 +4513,8 @@ | |
| sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id; | |
| } | |
| bool channelPost = peer->isChannel() && !peer->isMegagroup(); | |
| - bool silentPost = channelPost && Auth().data().notifySilentPosts(peer); | |
| + bool silentPost = channelPost | |
| + && _session->data().notifySilentPosts(peer); | |
| if (channelPost) { | |
| flags |= MTPDmessage::Flag::f_views; | |
| flags |= MTPDmessage::Flag::f_post; | |
| @@ -4448,9 +4527,10 @@ | |
| if (silentPost) { | |
| sendFlags |= MTPmessages_SendMedia::Flag::f_silent; | |
| } | |
| - auto messageFromId = channelPost ? 0 : Auth().userId(); | |
| + auto messageFromId = channelPost ? 0 : _session->userId(); | |
| auto messagePostAuthor = channelPost | |
| - ? App::peerName(Auth().user()) : QString(); | |
| + ? App::peerName(_session->user()) | |
| + : QString(); | |
| TextUtilities::Trim(caption); | |
| auto sentEntities = TextUtilities::EntitiesToMTP( | |
| @@ -4772,6 +4852,320 @@ | |
| options.replyTo); | |
| } | |
| +void ApiWrap::requestSupportContact(FnMut<void(const MTPUser &)> callback) { | |
| + _supportContactCallbacks.push_back(std::move(callback)); | |
| + if (_supportContactCallbacks.size() > 1) { | |
| + return; | |
| + } | |
| + request(MTPhelp_GetSupport( | |
| + )).done([=](const MTPhelp_Support &result) { | |
| + result.match([&](const MTPDhelp_support &data) { | |
| + for (auto &handler : base::take(_supportContactCallbacks)) { | |
| + handler(data.vuser); | |
| + } | |
| + }); | |
| + }).fail([=](const RPCError &error) { | |
| + _supportContactCallbacks.clear(); | |
| + }).send(); | |
| +} | |
| + | |
| +void ApiWrap::uploadPeerPhoto(not_null<PeerData*> peer, QImage &&image) { | |
| + const auto ready = PreparePeerPhoto(peer->id, std::move(image)); | |
| + | |
| + const auto fakeId = FullMsgId(peerToChannel(peer->id), clientMsgId()); | |
| + const auto already = ranges::find( | |
| + _peerPhotoUploads, | |
| + peer, | |
| + [](const auto &pair) { return pair.second; }); | |
| + if (already != end(_peerPhotoUploads)) { | |
| + _session->uploader().cancel(already->first); | |
| + _peerPhotoUploads.erase(already); | |
| + } | |
| + _peerPhotoUploads.emplace(fakeId, peer); | |
| + _session->uploader().uploadMedia(fakeId, ready); | |
| +} | |
| + | |
| +void ApiWrap::photoUploadReady( | |
| + const FullMsgId &msgId, | |
| + const MTPInputFile &file) { | |
| + if (const auto maybePeer = _peerPhotoUploads.take(msgId)) { | |
| + const auto peer = *maybePeer; | |
| + const auto applier = [=](const MTPUpdates &result) { | |
| + applyUpdates(result); | |
| + }; | |
| + if (peer->isSelf()) { | |
| + request(MTPphotos_UploadProfilePhoto( | |
| + file | |
| + )).done([=](const MTPphotos_Photo &result) { | |
| + result.match([&](const MTPDphotos_photo &data) { | |
| + _session->data().photo(data.vphoto); | |
| + App::feedUsers(data.vusers); | |
| + }); | |
| + }).send(); | |
| + } else if (const auto chat = peer->asChat()) { | |
| + const auto history = App::history(chat); | |
| + history->sendRequestId = request(MTPmessages_EditChatPhoto( | |
| + chat->inputChat, | |
| + MTP_inputChatUploadedPhoto(file) | |
| + )).done(applier).afterRequest(history->sendRequestId).send(); | |
| + } else if (const auto channel = peer->asChannel()) { | |
| + const auto history = App::history(channel); | |
| + history->sendRequestId = request(MTPchannels_EditPhoto( | |
| + channel->inputChannel, | |
| + MTP_inputChatUploadedPhoto(file) | |
| + )).done(applier).afterRequest(history->sendRequestId).send(); | |
| + } | |
| + } | |
| + | |
| +} | |
| + | |
| +void ApiWrap::clearPeerPhoto(not_null<PhotoData*> photo) { | |
| + const auto self = Auth().user(); | |
| + if (self->userpicPhotoId() == photo->id) { | |
| + request(MTPphotos_UpdateProfilePhoto( | |
| + MTP_inputPhotoEmpty() | |
| + )).done([=](const MTPUserProfilePhoto &result) { | |
| + self->setPhoto(result); | |
| + }).send(); | |
| + } else if (photo->peer && photo->peer->userpicPhotoId() == photo->id) { | |
| + const auto applier = [=](const MTPUpdates &result) { | |
| + applyUpdates(result); | |
| + }; | |
| + if (const auto chat = photo->peer->asChat()) { | |
| + request(MTPmessages_EditChatPhoto( | |
| + chat->inputChat, | |
| + MTP_inputChatPhotoEmpty() | |
| + )).done(applier).send(); | |
| + } else if (const auto channel = photo->peer->asChannel()) { | |
| + request(MTPchannels_EditPhoto( | |
| + channel->inputChannel, | |
| + MTP_inputChatPhotoEmpty() | |
| + )).done(applier).send(); | |
| + } | |
| + } else { | |
| + request(MTPphotos_DeletePhotos( | |
| + MTP_vector<MTPInputPhoto>(1, photo->mtpInput()) | |
| + )).send(); | |
| + _session->storage().remove(Storage::UserPhotosRemoveOne( | |
| + self->bareId(), | |
| + photo->id)); | |
| + } | |
| +} | |
| + | |
| +void ApiWrap::reloadPasswordState() { | |
| + if (_passwordRequestId) { | |
| + return; | |
| + } | |
| + _passwordRequestId = request(MTPaccount_GetPassword( | |
| + )).done([=](const MTPaccount_Password &result) { | |
| + _passwordRequestId = 0; | |
| + result.match([&](const MTPDaccount_password &data) { | |
| + openssl::AddRandomSeed(bytes::make_span(data.vsecure_random.v)); | |
| + if (_passwordState) { | |
| + *_passwordState = Core::ParseCloudPasswordState(data); | |
| + } else { | |
| + _passwordState = std::make_unique<Core::CloudPasswordState>( | |
| + Core::ParseCloudPasswordState(data)); | |
| + } | |
| + _passwordStateChanges.fire_copy(*_passwordState); | |
| + }); | |
| + }).fail([=](const RPCError &error) { | |
| + _passwordRequestId = 0; | |
| + }).send(); | |
| +} | |
| + | |
| +void ApiWrap::clearUnconfirmedPassword() { | |
| + _passwordRequestId = request(MTPaccount_UpdatePasswordSettings( | |
| + MTP_inputCheckPasswordEmpty(), | |
| + MTP_account_passwordInputSettings( | |
| + MTP_flags( | |
| + MTPDaccount_passwordInputSettings::Flag::f_email), | |
| + MTP_passwordKdfAlgoUnknown(), // new_algo | |
| + MTP_bytes(QByteArray()), // new_password_hash | |
| + MTP_string(QString()), // hint | |
| + MTP_string(QString()), // email | |
| + MTPSecureSecretSettings()) | |
| + )).done([=](const MTPBool &result) { | |
| + _passwordRequestId = 0; | |
| + reloadPasswordState(); | |
| + }).fail([=](const RPCError &error) { | |
| + _passwordRequestId = 0; | |
| + reloadPasswordState(); | |
| + }).send(); | |
| +} | |
| + | |
| +rpl::producer<Core::CloudPasswordState> ApiWrap::passwordState() const { | |
| + return _passwordState | |
| + ? _passwordStateChanges.events_starting_with_copy(*_passwordState) | |
| + : (_passwordStateChanges.events() | rpl::type_erased()); | |
| +} | |
| + | |
| +auto ApiWrap::passwordStateCurrent() const | |
| +->std::optional<Core::CloudPasswordState> { | |
| + return _passwordState | |
| + ? base::make_optional(*_passwordState) | |
| + : std::nullopt; | |
| +} | |
| + | |
| +void ApiWrap::saveSelfBio(const QString &text, FnMut<void()> done) { | |
| + if (_saveBioRequestId) { | |
| + if (text != _saveBioText) { | |
| + request(_saveBioRequestId).cancel(); | |
| + } else { | |
| + if (done) { | |
| + _saveBioDone = std::move(done); | |
| + } | |
| + return; | |
| + } | |
| + } | |
| + _saveBioText = text; | |
| + _saveBioDone = std::move(done); | |
| + _saveBioRequestId = request(MTPaccount_UpdateProfile( | |
| + MTP_flags(MTPaccount_UpdateProfile::Flag::f_about), | |
| + MTPstring(), | |
| + MTPstring(), | |
| + MTP_string(text) | |
| + )).done([=](const MTPUser &result) { | |
| + _saveBioRequestId = 0; | |
| + | |
| + App::feedUsers(MTP_vector<MTPUser>(1, result)); | |
| + Auth().user()->setAbout(_saveBioText); | |
| + if (_saveBioDone) { | |
| + _saveBioDone(); | |
| + } | |
| + }).fail([=](const RPCError &error) { | |
| + _saveBioRequestId = 0; | |
| + }).send(); | |
| +} | |
| + | |
| +void ApiWrap::reloadPrivacy(Privacy::Key key) { | |
| + if (_privacyRequestIds.contains(key)) { | |
| + return; | |
| + } | |
| + const auto requestId = request(MTPaccount_GetPrivacy( | |
| + Privacy::Input(key) | |
| + )).done([=](const MTPaccount_PrivacyRules &result) { | |
| + _privacyRequestIds.erase(key); | |
| + result.match([&](const MTPDaccount_privacyRules &data) { | |
| + App::feedUsers(data.vusers); | |
| + pushPrivacy(key, data.vrules.v); | |
| + }); | |
| + }).fail([=](const RPCError &error) { | |
| + _privacyRequestIds.erase(key); | |
| + }).send(); | |
| + _privacyRequestIds.emplace(key, requestId); | |
| +} | |
| + | |
| +auto ApiWrap::parsePrivacy(const QVector<MTPPrivacyRule> &rules) | |
| +-> Privacy { | |
| + using Option = Privacy::Option; | |
| + | |
| + // This is simplified version of privacy rules interpretation. | |
| + // But it should be fine for all the apps | |
| + // that use the same subset of features. | |
| + auto result = Privacy(); | |
| + auto optionSet = false; | |
| + const auto SetOption = [&](Option option) { | |
| + if (optionSet) return; | |
| + optionSet = true; | |
| + result.option = option; | |
| + }; | |
| + auto &always = result.always; | |
| + auto &never = result.never; | |
| + const auto Feed = [&](const MTPPrivacyRule &rule) { | |
| + rule.match([&](const MTPDprivacyValueAllowAll &) { | |
| + SetOption(Option::Everyone); | |
| + }, [&](const MTPDprivacyValueAllowContacts &) { | |
| + SetOption(Option::Contacts); | |
| + }, [&](const MTPDprivacyValueAllowUsers &data) { | |
| + const auto &users = data.vusers.v; | |
| + always.reserve(always.size() + users.size()); | |
| + for (const auto userId : users) { | |
| + const auto user = App::user(UserId(userId.v)); | |
| + if (!base::contains(never, user) | |
| + && !base::contains(always, user)) { | |
| + always.push_back(user); | |
| + } | |
| + } | |
| + }, [&](const MTPDprivacyValueDisallowContacts &) { | |
| + // not supported | |
| + }, [&](const MTPDprivacyValueDisallowAll &) { | |
| + SetOption(Option::Nobody); | |
| + }, [&](const MTPDprivacyValueDisallowUsers &data) { | |
| + const auto &users = data.vusers.v; | |
| + never.reserve(never.size() + users.size()); | |
| + for (const auto userId : users) { | |
| + const auto user = App::user(UserId(userId.v)); | |
| + if (!base::contains(always, user) | |
| + && !base::contains(never, user)) { | |
| + never.push_back(user); | |
| + } | |
| + } | |
| + }); | |
| + }; | |
| + for (const auto &rule : rules) { | |
| + Feed(rule); | |
| + } | |
| + Feed(MTP_privacyValueDisallowAll()); // disallow by default. | |
| + return result; | |
| +} | |
| + | |
| +void ApiWrap::pushPrivacy( | |
| + Privacy::Key key, | |
| + const QVector<MTPPrivacyRule> &rules) { | |
| + const auto &saved = (_privacyValues[key] = parsePrivacy(rules)); | |
| + const auto i = _privacyChanges.find(key); | |
| + if (i != end(_privacyChanges)) { | |
| + i->second.fire_copy(saved); | |
| + } | |
| +} | |
| + | |
| +auto ApiWrap::privacyValue(Privacy::Key key) -> rpl::producer<Privacy> { | |
| + if (const auto i = _privacyValues.find(key); i != end(_privacyValues)) { | |
| + return _privacyChanges[key].events_starting_with_copy(i->second); | |
| + } else { | |
| + return _privacyChanges[key].events(); | |
| + } | |
| +} | |
| + | |
| +void ApiWrap::reloadSelfDestruct() { | |
| + if (_selfDestructRequestId) { | |
| + return; | |
| + } | |
| + _selfDestructRequestId = request(MTPaccount_GetAccountTTL( | |
| + )).done([=](const MTPAccountDaysTTL &result) { | |
| + _selfDestructRequestId = 0; | |
| + result.match([&](const MTPDaccountDaysTTL &data) { | |
| + setSelfDestructDays(data.vdays.v); | |
| + }); | |
| + }).fail([=](const RPCError &error) { | |
| + _selfDestructRequestId = 0; | |
| + }).send(); | |
| +} | |
| + | |
| +rpl::producer<int> ApiWrap::selfDestructValue() const { | |
| + return _selfDestructDays | |
| + ? _selfDestructChanges.events_starting_with_copy(*_selfDestructDays) | |
| + : (_selfDestructChanges.events() | rpl::type_erased()); | |
| +} | |
| + | |
| +void ApiWrap::saveSelfDestruct(int days) { | |
| + request(_selfDestructRequestId).cancel(); | |
| + _selfDestructRequestId = request(MTPaccount_SetAccountTTL( | |
| + MTP_accountDaysTTL(MTP_int(days)) | |
| + )).done([=](const MTPBool &result) { | |
| + _selfDestructRequestId = 0; | |
| + }).fail([=](const RPCError &result) { | |
| + _selfDestructRequestId = 0; | |
| + }).send(); | |
| + setSelfDestructDays(days); | |
| +} | |
| + | |
| +void ApiWrap::setSelfDestructDays(int days) { | |
| + _selfDestructDays = days; | |
| + _selfDestructChanges.fire_copy(days); | |
| +} | |
| + | |
| void ApiWrap::readServerHistory(not_null<History*> history) { | |
| if (history->unreadCount()) { | |
| readServerHistoryForce(history); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/apiwrap.h work/tdesktop-1.4.0/Telegram/SourceFiles/apiwrap.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/apiwrap.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/apiwrap.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -37,6 +37,10 @@ | |
| class Key; | |
| } // namespace Dialogs | |
| +namespace Core { | |
| +struct CloudPasswordState; | |
| +} // namespace Core | |
| + | |
| namespace Api { | |
| inline const MTPVector<MTPChat> *getChatsFromMessagesChats(const MTPmessages_Chats &chats) { | |
| @@ -80,7 +84,9 @@ | |
| void requestContacts(); | |
| void requestDialogEntry(not_null<Data::Feed*> feed); | |
| //void requestFeedDialogsEntries(not_null<Data::Feed*> feed); | |
| - void requestDialogEntry(not_null<History*> history); | |
| + void requestDialogEntry( | |
| + not_null<History*> history, | |
| + Fn<void()> callback = nullptr); | |
| //void applyFeedSources(const MTPDchannels_feedSources &data); // #feed | |
| //void setFeedChannels( | |
| // not_null<Data::Feed*> feed, | |
| @@ -178,7 +184,9 @@ | |
| void savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules); | |
| void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules); | |
| - int onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill); | |
| + static int OnlineTillFromStatus( | |
| + const MTPUserStatus &status, | |
| + int currentOnlineTill); | |
| void clearHistory(not_null<PeerData*> peer); | |
| @@ -298,7 +306,7 @@ | |
| void sendUploadedDocument( | |
| FullMsgId localId, | |
| const MTPInputFile &file, | |
| - const base::optional<MTPInputFile> &thumb, | |
| + const std::optional<MTPInputFile> &thumb, | |
| bool silent); | |
| void cancelLocalItem(not_null<HistoryItem*> item); | |
| @@ -322,6 +330,42 @@ | |
| TextWithEntities caption, | |
| const SendOptions &options); | |
| + void requestSupportContact(FnMut<void(const MTPUser&)> callback); | |
| + | |
| + void uploadPeerPhoto(not_null<PeerData*> peer, QImage &&image); | |
| + void clearPeerPhoto(not_null<PhotoData*> photo); | |
| + | |
| + void reloadPasswordState(); | |
| + void clearUnconfirmedPassword(); | |
| + rpl::producer<Core::CloudPasswordState> passwordState() const; | |
| + std::optional<Core::CloudPasswordState> passwordStateCurrent() const; | |
| + | |
| + void saveSelfBio(const QString &text, FnMut<void()> done); | |
| + | |
| + struct Privacy { | |
| + enum class Key { | |
| + LastSeen, | |
| + Calls, | |
| + Invites, | |
| + }; | |
| + enum class Option { | |
| + Everyone, | |
| + Contacts, | |
| + Nobody, | |
| + }; | |
| + Option option = Option::Everyone; | |
| + std::vector<not_null<UserData*>> always; | |
| + std::vector<not_null<UserData*>> never; | |
| + | |
| + static MTPInputPrivacyKey Input(Key key); | |
| + }; | |
| + void reloadPrivacy(Privacy::Key key); | |
| + rpl::producer<Privacy> privacyValue(Privacy::Key key); | |
| + | |
| + void reloadSelfDestruct(); | |
| + rpl::producer<int> selfDestructValue() const; | |
| + void saveSelfDestruct(int days); | |
| + | |
| ~ApiWrap(); | |
| private: | |
| @@ -503,6 +547,16 @@ | |
| FileReferencesHandler &&handler, | |
| Request &&data); | |
| + void photoUploadReady(const FullMsgId &msgId, const MTPInputFile &file); | |
| + | |
| + Privacy parsePrivacy(const QVector<MTPPrivacyRule> &rules); | |
| + void pushPrivacy( | |
| + Privacy::Key key, | |
| + const QVector<MTPPrivacyRule> &rules); | |
| + void updatePrivacyLastSeens(const QVector<MTPPrivacyRule> &rules); | |
| + | |
| + void setSelfDestructDays(int days); | |
| + | |
| not_null<AuthSession*> _session; | |
| MessageDataRequests _messageDataRequests; | |
| @@ -570,7 +624,9 @@ | |
| mtpRequestId _contactsRequestId = 0; | |
| mtpRequestId _contactsStatusesRequestId = 0; | |
| base::flat_set<not_null<Data::Feed*>> _dialogFeedRequests; | |
| - base::flat_set<not_null<History*>> _dialogRequests; | |
| + base::flat_map< | |
| + not_null<History*>, | |
| + std::vector<Fn<void()>>> _dialogRequests; | |
| base::flat_map<not_null<History*>, mtpRequestId> _unreadMentionsRequests; | |
| @@ -648,4 +704,24 @@ | |
| TimeMs _termsUpdateSendAt = 0; | |
| mtpRequestId _termsUpdateRequestId = 0; | |
| + std::vector<FnMut<void(const MTPUser &)>> _supportContactCallbacks; | |
| + | |
| + base::flat_map<FullMsgId, not_null<PeerData*>> _peerPhotoUploads; | |
| + | |
| + mtpRequestId _passwordRequestId = 0; | |
| + std::unique_ptr<Core::CloudPasswordState> _passwordState; | |
| + rpl::event_stream<Core::CloudPasswordState> _passwordStateChanges; | |
| + | |
| + mtpRequestId _saveBioRequestId = 0; | |
| + FnMut<void()> _saveBioDone; | |
| + QString _saveBioText; | |
| + | |
| + base::flat_map<Privacy::Key, mtpRequestId> _privacyRequestIds; | |
| + base::flat_map<Privacy::Key, Privacy> _privacyValues; | |
| + std::map<Privacy::Key, rpl::event_stream<Privacy>> _privacyChanges; | |
| + | |
| + mtpRequestId _selfDestructRequestId = 0; | |
| + std::optional<int> _selfDestructDays; | |
| + rpl::event_stream<int> _selfDestructChanges; | |
| + | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/app.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/app.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/app.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/app.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -49,8 +49,6 @@ | |
| namespace { | |
| App::LaunchState _launchState = App::Launched; | |
| - UserData *self = nullptr; | |
| - | |
| std::unordered_map<PeerId, std::unique_ptr<PeerData>> peersData; | |
| using LocationsData = QHash<LocationCoords, LocationData*>; | |
| @@ -309,10 +307,6 @@ | |
| : data->phone().isEmpty() | |
| ? UserData::ContactStatus::PhoneUnknown | |
| : UserData::ContactStatus::CanAdd); | |
| - if (d.is_self() && ::self != data) { | |
| - ::self = data; | |
| - Global::RefSelfChanged().notify(); | |
| - } | |
| } | |
| if (canShareThisContact != data->canShareThisContactFast()) { | |
| @@ -329,13 +323,16 @@ | |
| if (data->loadedStatus == PeerData::NotLoaded) { | |
| data->loadedStatus = PeerData::MinimalLoaded; | |
| } | |
| - } else if (data->loadedStatus != PeerData::FullLoaded) { | |
| + } else if (data->loadedStatus != PeerData::FullLoaded | |
| + && (!data->isSelf() || !data->phone().isEmpty())) { | |
| data->loadedStatus = PeerData::FullLoaded; | |
| } | |
| if (status && !minimal) { | |
| - auto oldOnlineTill = data->onlineTill; | |
| - auto newOnlineTill = Auth().api().onlineTillFromStatus(*status, oldOnlineTill); | |
| + const auto oldOnlineTill = data->onlineTill; | |
| + const auto newOnlineTill = ApiWrap::OnlineTillFromStatus( | |
| + *status, | |
| + oldOnlineTill); | |
| if (oldOnlineTill != newOnlineTill) { | |
| data->onlineTill = newOnlineTill; | |
| update.flags |= UpdateFlag::UserOnlineChanged; | |
| @@ -344,7 +341,7 @@ | |
| if (data->contactStatus() == UserData::ContactStatus::PhoneUnknown | |
| && !data->phone().isEmpty() | |
| - && data->id != Auth().userPeerId()) { | |
| + && !data->isSelf()) { | |
| data->setContactStatus(UserData::ContactStatus::CanAdd); | |
| } | |
| if (App::main()) { | |
| @@ -918,7 +915,7 @@ | |
| } | |
| void checkSavedGif(HistoryItem *item) { | |
| - if (!item->Has<HistoryMessageForwarded>() && (item->out() || item->history()->peer == App::self())) { | |
| + if (!item->Has<HistoryMessageForwarded>() && (item->out() || item->history()->peer == Auth().user())) { | |
| if (const auto media = item->media()) { | |
| if (const auto document = media->document()) { | |
| if (document->isGifv()) { | |
| @@ -1153,10 +1150,6 @@ | |
| } | |
| } | |
| - UserData *self() { | |
| - return ::self; | |
| - } | |
| - | |
| PeerData *peerByName(const QString &username) { | |
| const auto uname = username.trimmed(); | |
| for (const auto &[peerId, peer] : peersData) { | |
| @@ -1294,8 +1287,6 @@ | |
| cSetAutoDownloadPhoto(0); | |
| cSetAutoDownloadAudio(0); | |
| cSetAutoDownloadGif(0); | |
| - ::self = nullptr; | |
| - Global::RefSelfChanged().notify(true); | |
| } | |
| void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/app.h work/tdesktop-1.4.0/Telegram/SourceFiles/app.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/app.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/app.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,7 +7,6 @@ | |
| */ | |
| #pragma once | |
| -#include "core/basic_types.h" | |
| #include "data/data_types.h" | |
| #include "data/data_peer.h" | |
| @@ -136,7 +135,6 @@ | |
| void enumerateChatsChannels( | |
| Fn<void(not_null<PeerData*>)> action); | |
| - UserData *self(); | |
| PeerData *peerByName(const QString &username); | |
| QString peerName(const PeerData *peer, bool forDialogs = false); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/application.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/application.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/application.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/application.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -15,6 +15,7 @@ | |
| #include "core/crash_reports.h" | |
| #include "messenger.h" | |
| #include "base/timer.h" | |
| +#include "base/concurrent_timer.h" | |
| #include "base/qthelp_url.h" | |
| #include "base/qthelp_regex.h" | |
| #include "core/update_checker.h" | |
| @@ -446,6 +447,7 @@ | |
| a->adjustSingleTimers(); | |
| } | |
| base::Timer::Adjust(); | |
| + base::ConcurrentTimerEnvironment::Adjust(); | |
| } | |
| void connect(const char *signal, QObject *object, const char *method) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/auth_session.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/auth_session.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/auth_session.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/auth_session.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,6 +23,7 @@ | |
| #include "window/section_widget.h" | |
| #include "chat_helpers/tabbed_selector.h" | |
| #include "boxes/send_files_box.h" | |
| +#include "observer_peer.h" | |
| namespace { | |
| @@ -72,6 +73,7 @@ | |
| stream << qint32(_variables.thirdColumnWidth.current()); | |
| stream << qint32(_variables.thirdSectionExtendedBy); | |
| stream << qint32(_variables.sendFilesWay); | |
| + stream << qint32(_variables.callsPeerToPeer.current()); | |
| } | |
| return result; | |
| } | |
| @@ -97,6 +99,7 @@ | |
| int thirdColumnWidth = _variables.thirdColumnWidth.current(); | |
| int thirdSectionExtendedBy = _variables.thirdSectionExtendedBy; | |
| qint32 sendFilesWay = static_cast<qint32>(_variables.sendFilesWay); | |
| + qint32 callsPeerToPeer = qint32(_variables.callsPeerToPeer.current()); | |
| stream >> selectorTab; | |
| stream >> lastSeenWarningSeen; | |
| if (!stream.atEnd()) { | |
| @@ -145,6 +148,12 @@ | |
| stream >> value; | |
| thirdSectionExtendedBy = value; | |
| } | |
| + if (!stream.atEnd()) { | |
| + stream >> sendFilesWay; | |
| + } | |
| + if (!stream.atEnd()) { | |
| + stream >> callsPeerToPeer; | |
| + } | |
| if (stream.status() != QDataStream::Ok) { | |
| LOG(("App Error: " | |
| "Bad data for AuthSessionSettings::constructFromSerialized()")); | |
| @@ -187,7 +196,15 @@ | |
| switch (uncheckedSendFilesWay) { | |
| case SendFilesWay::Album: | |
| case SendFilesWay::Photos: | |
| - case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay; | |
| + case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay; break; | |
| + } | |
| + auto uncheckedCallsPeerToPeer = static_cast<Calls::PeerToPeer>(callsPeerToPeer); | |
| + switch (uncheckedCallsPeerToPeer) { | |
| + case Calls::PeerToPeer::DefaultContacts: | |
| + case Calls::PeerToPeer::DefaultEveryone: | |
| + case Calls::PeerToPeer::Everyone: | |
| + case Calls::PeerToPeer::Contacts: | |
| + case Calls::PeerToPeer::Nobody: _variables.callsPeerToPeer = uncheckedCallsPeerToPeer; break; | |
| } | |
| } | |
| @@ -265,8 +282,8 @@ | |
| return *result; | |
| } | |
| -AuthSession::AuthSession(UserId userId) | |
| -: _userId(userId) | |
| +AuthSession::AuthSession(const MTPUser &user) | |
| +: _user(App::user(user.match([](const auto &data) { return data.vid.v; }))) | |
| , _autoLockTimer([this] { checkAutoLock(); }) | |
| , _api(std::make_unique<ApiWrap>(this)) | |
| , _calls(std::make_unique<Calls::Instance>()) | |
| @@ -276,7 +293,7 @@ | |
| , _notifications(std::make_unique<Window::Notifications::System>(this)) | |
| , _data(std::make_unique<Data::Session>(this)) | |
| , _changelogs(Core::Changelogs::Create(this)) { | |
| - Expects(_userId != 0); | |
| + App::feedUser(user); | |
| _saveDataTimer.setCallback([=] { | |
| Local::writeUserSettings(); | |
| @@ -294,21 +311,36 @@ | |
| }); | |
| _api->refreshProxyPromotion(); | |
| _api->requestTermsUpdate(); | |
| + _api->requestFullPeer(_user); | |
| + | |
| + crl::on_main(this, [=] { | |
| + using Flag = Notify::PeerUpdate::Flag; | |
| + const auto events = Flag::NameChanged | |
| + | Flag::UsernameChanged | |
| + | Flag::PhotoChanged | |
| + | Flag::AboutChanged | |
| + | Flag::UserPhoneChanged; | |
| + subscribe( | |
| + Notify::PeerUpdated(), | |
| + Notify::PeerUpdatedHandler( | |
| + events, | |
| + [=](const Notify::PeerUpdate &update) { | |
| + if (update.peer == _user) { | |
| + Local::writeSelf(); | |
| + } | |
| + })); | |
| + }); | |
| Window::Theme::Background()->start(); | |
| } | |
| bool AuthSession::Exists() { | |
| - if (auto messenger = Messenger::InstancePointer()) { | |
| + if (const auto messenger = Messenger::InstancePointer()) { | |
| return (messenger->authSession() != nullptr); | |
| } | |
| return false; | |
| } | |
| -UserData *AuthSession::user() const { | |
| - return App::user(userId()); | |
| -} | |
| - | |
| base::Observable<void> &AuthSession::downloaderTaskFinished() { | |
| return downloader().taskFinished(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/auth_session.h work/tdesktop-1.4.0/Telegram/SourceFiles/auth_session.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/auth_session.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/auth_session.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -19,6 +19,10 @@ | |
| class Session; | |
| } // namespace Data | |
| +namespace Calls { | |
| +enum class PeerToPeer; | |
| +} // namespace Calls | |
| + | |
| namespace Storage { | |
| class Downloader; | |
| class Uploader; | |
| @@ -144,6 +148,16 @@ | |
| _variables.groupStickersSectionHidden.remove(peerId); | |
| } | |
| + rpl::producer<Calls::PeerToPeer> callsPeerToPeerValue() const { | |
| + return _variables.callsPeerToPeer.value(); | |
| + } | |
| + Calls::PeerToPeer callsPeerToPeer() const { | |
| + return _variables.callsPeerToPeer.current(); | |
| + } | |
| + void setCallsPeerToPeer(Calls::PeerToPeer value) { | |
| + _variables.callsPeerToPeer = value; | |
| + } | |
| + | |
| private: | |
| struct Variables { | |
| Variables(); | |
| @@ -167,6 +181,8 @@ | |
| = kDefaultDialogsWidthRatio; // per-window | |
| rpl::variable<int> thirdColumnWidth | |
| = kDefaultThirdColumnWidth; // per-window | |
| + rpl::variable<Calls::PeerToPeer> callsPeerToPeer | |
| + = Calls::PeerToPeer(); | |
| }; | |
| rpl::event_stream<bool> _thirdSectionInfoEnabledValue; | |
| @@ -186,7 +202,7 @@ | |
| : public base::has_weak_ptr | |
| , private base::Subscriber { | |
| public: | |
| - AuthSession(UserId userId); | |
| + AuthSession(const MTPUser &user); | |
| AuthSession(const AuthSession &other) = delete; | |
| AuthSession &operator=(const AuthSession &other) = delete; | |
| @@ -194,12 +210,14 @@ | |
| static bool Exists(); | |
| UserId userId() const { | |
| - return _userId; | |
| + return _user->bareId(); | |
| } | |
| PeerId userPeerId() const { | |
| - return peerFromUser(userId()); | |
| + return _user->id; | |
| + } | |
| + not_null<UserData*> user() const { | |
| + return _user; | |
| } | |
| - UserData *user() const; | |
| bool validateSelf(const MTPUser &user); | |
| Storage::Downloader &downloader() { | |
| @@ -237,6 +255,10 @@ | |
| void checkAutoLock(); | |
| void checkAutoLockIn(TimeMs time); | |
| + rpl::lifetime &lifetime() { | |
| + return _lifetime; | |
| + } | |
| + | |
| base::Observable<DocumentData*> documentUpdated; | |
| base::Observable<std::pair<not_null<HistoryItem*>, MsgId>> messageIdChanging; | |
| @@ -245,7 +267,7 @@ | |
| private: | |
| static constexpr auto kDefaultSaveDelay = TimeMs(1000); | |
| - const UserId _userId = 0; | |
| + const not_null<UserData*> _user; | |
| AuthSessionSettings _settings; | |
| base::Timer _saveDataTimer; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/algorithm.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/algorithm.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/algorithm.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/algorithm.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -25,3 +25,14 @@ | |
| } | |
| } // namespace base | |
| + | |
| +template <typename T> | |
| +inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; } | |
| + | |
| +template <typename T> | |
| +inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; } | |
| + | |
| +template <size_t Size> | |
| +QLatin1String qstr(const char(&string)[Size]) { | |
| + return QLatin1String(string, Size - 1); | |
| +} | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/assertion.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/assertion.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/assertion.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/assertion.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -66,3 +66,7 @@ | |
| #undef Unexpected | |
| #endif // Unexpected | |
| #define Unexpected(message) (::base::assertion::fail("Unexpected: " message, __FILE__, __LINE__)) | |
| + | |
| +#ifdef _DEBUG | |
| +#define AssertIsDebug(...) | |
| +#endif // _DEBUG | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/base: base_pch.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/base: base_pch.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/base: basic_types.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/base: binary_guard.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/build_config.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/build_config.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/build_config.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/build_config.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -56,11 +56,11 @@ | |
| #endif | |
| #if defined(__GNUC__) | |
| -#define FORCE_INLINE inline __attribute__((always_inline)) | |
| +#define TG_FORCE_INLINE inline __attribute__((always_inline)) | |
| #elif defined(_MSC_VER) | |
| -#define FORCE_INLINE __forceinline | |
| +#define TG_FORCE_INLINE __forceinline | |
| #else | |
| -#define FORCE_INLINE inline | |
| +#define TG_FORCE_INLINE inline | |
| #endif | |
| #include <climits> | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/bytes.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/bytes.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/bytes.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/bytes.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,7 @@ | |
| */ | |
| #pragma once | |
| +#include "base/basic_types.h" | |
| #include <gsl/gsl> | |
| #include <gsl/gsl_byte> | |
| @@ -20,9 +21,15 @@ | |
| template <gsl::index Size> | |
| using array = std::array<type, Size>; | |
| +inline span make_detached_span(QByteArray &container) { | |
| + return gsl::as_writeable_bytes(gsl::make_span(container)); | |
| +} | |
| + | |
| template < | |
| typename Container, | |
| - typename = std::enable_if_t<!std::is_const_v<Container>>> | |
| + typename = std::enable_if_t< | |
| + !std::is_const_v<Container> | |
| + && !std::is_same_v<Container, QByteArray>>> | |
| inline span make_span(Container &container) { | |
| return gsl::as_writeable_bytes(gsl::make_span(container)); | |
| } | |
| @@ -80,7 +87,7 @@ | |
| memmove(destination.data(), source.data(), source.size()); | |
| } | |
| -inline void set_with_const(span destination, gsl::byte value) { | |
| +inline void set_with_const(span destination, type value) { | |
| memset( | |
| destination.data(), | |
| gsl::to_integer<unsigned char>(value), | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/base: concurrent_timer.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/base: concurrent_timer.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/flat_map_tests.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/base/flat_map_tests.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/flat_map_tests.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/flat_map_tests.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -46,6 +46,27 @@ | |
| } | |
| } | |
| +TEST_CASE("simple flat_maps tests", "[flat_map]") { | |
| + SECTION("copy constructor") { | |
| + base::flat_map<int, string> v; | |
| + v.emplace(0, "a"); | |
| + v.emplace(2, "b"); | |
| + auto u = v; | |
| + REQUIRE(u.size() == 2); | |
| + REQUIRE(u.find(0) == u.begin()); | |
| + REQUIRE(u.find(2) == u.end() - 1); | |
| + } | |
| + SECTION("assignment") { | |
| + base::flat_map<int, string> v, u; | |
| + v.emplace(0, "a"); | |
| + v.emplace(2, "b"); | |
| + u = v; | |
| + REQUIRE(u.size() == 2); | |
| + REQUIRE(u.find(0) == u.begin()); | |
| + REQUIRE(u.find(2) == u.end() - 1); | |
| + } | |
| +} | |
| + | |
| TEST_CASE("flat_maps custom comparator", "[flat_map]") { | |
| base::flat_map<int_wrap, string, int_wrap_comparator> v; | |
| v.emplace({ 0 }, "a"); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/flat_map.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/flat_map.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/flat_map.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/flat_map.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -307,6 +307,15 @@ | |
| }; | |
| + flat_multi_map() = default; | |
| + flat_multi_map(const flat_multi_map &other) = default; | |
| + flat_multi_map(flat_multi_map &&other) = default; | |
| + flat_multi_map &operator=(const flat_multi_map &other) { | |
| + auto copy = other; | |
| + return (*this = std::move(copy)); | |
| + } | |
| + flat_multi_map &operator=(flat_multi_map &&other) = default; | |
| + | |
| size_type size() const { | |
| return impl().size(); | |
| } | |
| @@ -713,10 +722,10 @@ | |
| return where->second; | |
| } | |
| - optional<Type> take(const Key &key) { | |
| + std::optional<Type> take(const Key &key) { | |
| auto it = find(key); | |
| if (it == this->end()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto result = std::move(it->second); | |
| this->erase(it); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/match_method.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/match_method.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/match_method.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/match_method.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,7 +16,8 @@ | |
| Data &&data, | |
| Method &&method, | |
| Methods &&...methods) { | |
| - if constexpr (rpl::details::is_callable_plain_v<Method, Data&&>) { | |
| + using namespace rpl::details; | |
| + if constexpr (is_callable_plain_v<Method, Data&&>) { | |
| return std::forward<Method>(method)(std::forward<Data>(data)); | |
| } else { | |
| return match_method( | |
| @@ -25,4 +26,27 @@ | |
| } | |
| } | |
| +template < | |
| + typename Data1, | |
| + typename Data2, | |
| + typename Method, | |
| + typename ...Methods> | |
| +inline decltype(auto) match_method2( | |
| + Data1 &&data1, | |
| + Data2 &&data2, | |
| + Method &&method, | |
| + Methods &&...methods) { | |
| + using namespace rpl::details; | |
| + if constexpr (is_callable_plain_v<Method, Data1&&, Data2&&>) { | |
| + return std::forward<Method>(method)( | |
| + std::forward<Data1>(data1), | |
| + std::forward<Data2>(data2)); | |
| + } else { | |
| + return match_method2( | |
| + std::forward<Data1>(data1), | |
| + std::forward<Data2>(data2), | |
| + std::forward<Methods>(methods)...); | |
| + } | |
| +} | |
| + | |
| } // namespace base | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/observer.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/base/observer.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/observer.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/observer.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -12,6 +12,7 @@ | |
| namespace { | |
| bool CantUseObservables = false; | |
| +void (*HandleDelayedMethod)() = nullptr; | |
| struct ObservableListWrap { | |
| ~ObservableListWrap() { | |
| @@ -35,7 +36,9 @@ | |
| void RegisterPendingObservable(ObservableCallHandlers *handlers) { | |
| if (CantUseObservables) return; | |
| PendingObservables().list.insert(handlers); | |
| - Global::RefHandleObservables().call(); | |
| + if (HandleDelayedMethod) { | |
| + HandleDelayedMethod(); | |
| + } | |
| } | |
| void UnregisterActiveObservable(ObservableCallHandlers *handlers) { | |
| @@ -51,6 +54,10 @@ | |
| } // namespace internal | |
| +void InitObservables(void(*HandleDelayed)()) { | |
| + internal::HandleDelayedMethod = HandleDelayed; | |
| +} | |
| + | |
| void HandleObservables() { | |
| if (internal::CantUseObservables) return; | |
| auto &active = internal::ActiveObservables().list; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/observer.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/observer.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/observer.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/observer.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -452,6 +452,7 @@ | |
| }; | |
| +void InitObservables(void(*HandleDelayed)()); | |
| void HandleObservables(); | |
| template < | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/openssl_help.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/openssl_help.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/openssl_help.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/openssl_help.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,7 +9,7 @@ | |
| #include "base/bytes.h" | |
| #include "base/algorithm.h" | |
| -#include "core/basic_types.h" | |
| +#include "base/basic_types.h" | |
| extern "C" { | |
| #include <openssl/bn.h> | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/optional.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/optional.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/optional.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/optional.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,39 +7,16 @@ | |
| */ | |
| #pragma once | |
| +#include <optional> | |
| #include <gsl/gsl_assert> | |
| #include "base/variant.h" | |
| namespace base { | |
| -struct none_type { | |
| - bool operator==(none_type other) const { | |
| - return true; | |
| - } | |
| - bool operator!=(none_type other) const { | |
| - return false; | |
| - } | |
| - bool operator<(none_type other) const { | |
| - return false; | |
| - } | |
| - bool operator<=(none_type other) const { | |
| - return true; | |
| - } | |
| - bool operator>(none_type other) const { | |
| - return false; | |
| - } | |
| - bool operator>=(none_type other) const { | |
| - return true; | |
| - } | |
| - | |
| -}; | |
| - | |
| -constexpr none_type none = {}; | |
| - | |
| template <typename... Types> | |
| class optional_variant { | |
| public: | |
| - optional_variant() : _impl(none) { | |
| + optional_variant() : _impl(std::nullopt) { | |
| } | |
| optional_variant(const optional_variant &other) : _impl(other._impl) { | |
| } | |
| @@ -63,7 +40,7 @@ | |
| } | |
| bool has_value() const { | |
| - return !is<none_type>(); | |
| + return !is<std::nullopt_t>(); | |
| } | |
| explicit operator bool() const { | |
| return has_value(); | |
| @@ -93,7 +70,7 @@ | |
| return get_unchecked<T>(); | |
| } | |
| void clear() { | |
| - _impl.template set<none_type>(); | |
| + _impl.template set<std::nullopt_t>(); | |
| } | |
| template <typename T> | |
| @@ -119,7 +96,7 @@ | |
| } | |
| private: | |
| - variant<none_type, Types...> _impl; | |
| + variant<std::nullopt_t, Types...> _impl; | |
| }; | |
| @@ -148,16 +125,13 @@ | |
| } | |
| template <typename Type> | |
| -class optional; | |
| - | |
| -template <typename Type> | |
| struct optional_wrap_once { | |
| - using type = optional<Type>; | |
| + using type = std::optional<Type>; | |
| }; | |
| template <typename Type> | |
| -struct optional_wrap_once<optional<Type>> { | |
| - using type = optional<Type>; | |
| +struct optional_wrap_once<std::optional<Type>> { | |
| + using type = std::optional<Type>; | |
| }; | |
| template <typename Type> | |
| @@ -177,57 +151,21 @@ | |
| using optional_chain_result_t = typename optional_chain_result<Type>::type; | |
| template <typename Type> | |
| -class optional : public optional_variant<Type> { | |
| - using parent = optional_variant<Type>; | |
| - | |
| -public: | |
| - using parent::parent; | |
| - | |
| - Type &operator*() & { | |
| - Expects(parent::template is<Type>()); | |
| - | |
| - return parent::template get_unchecked<Type>(); | |
| - } | |
| - Type &&operator*() && { | |
| - Expects(parent::template is<Type>()); | |
| - | |
| - return std::move(parent::template get_unchecked<Type>()); | |
| - } | |
| - const Type &operator*() const & { | |
| - Expects(parent::template is<Type>()); | |
| - | |
| - return parent::template get_unchecked<Type>(); | |
| - } | |
| - Type *operator->() { | |
| - Expects(parent::template is<Type>()); | |
| - | |
| - return std::addressof(parent::template get_unchecked<Type>()); | |
| - } | |
| - const Type *operator->() const { | |
| - Expects(parent::template is<Type>()); | |
| - | |
| - return std::addressof(parent::template get_unchecked<Type>()); | |
| - } | |
| - template <typename ...Args> | |
| - Type &emplace(Args &&...args) { | |
| - return parent::template set<Type>(std::forward<Args>(args)...); | |
| - } | |
| - | |
| -}; | |
| - | |
| -template <typename Type> | |
| optional_wrap_once_t<Type> make_optional(Type &&value) { | |
| return optional_wrap_once_t<Type> { std::forward<Type>(value) }; | |
| } | |
| +} // namespace base | |
| + | |
| template <typename Type, typename Method> | |
| -inline auto operator|(const optional<Type> &value, Method method) | |
| --> optional_chain_result_t<decltype(method(*value))> { | |
| +inline auto operator|(const std::optional<Type> &value, Method method) | |
| +-> base::optional_chain_result_t<decltype(method(*value))> { | |
| if constexpr (std::is_same_v<decltype(method(*value)), void>) { | |
| return value ? (method(*value), true) : false; | |
| } else { | |
| - return value ? make_optional(method(*value)) : none; | |
| + return value | |
| + ? base::optional_chain_result_t<decltype(method(*value))>( | |
| + method(*value)) | |
| + : std::nullopt; | |
| } | |
| } | |
| - | |
| -} // namespace base | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/qthelp_url.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/base/qthelp_url.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/qthelp_url.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/qthelp_url.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,11 +10,26 @@ | |
| namespace qthelp { | |
| namespace { | |
| -QRegularExpression RegExpProtocol() { | |
| - static const auto result = QRegularExpression("^([a-zA-Z]+)://"); | |
| +QRegularExpression CreateRegExp(const QString &expression) { | |
| + auto result = QRegularExpression( | |
| + expression, | |
| + QRegularExpression::UseUnicodePropertiesOption); | |
| +#ifndef OS_MAC_OLD | |
| + result.optimize(); | |
| +#endif // OS_MAC_OLD | |
| return result; | |
| } | |
| +QString ExpressionDomain() { | |
| + // Matches any domain name, containing at least one '.', including "file.txt". | |
| + return QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)?((?:[A-Za-z" "\xD0\x90-\xD0\xAF\xD0\x81" "\xD0\xB0-\xD1\x8F\xD1\x91" "0-9\\-\\_]+\\.){1,10}([A-Za-z" "\xD1\x80\xD1\x84" "\\-\\d]{2,22})(\\:\\d+)?)"); | |
| +} | |
| + | |
| +QString ExpressionDomainExplicit() { | |
| + // Matches any domain name, containing a protocol, including "test://localhost". | |
| + return QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)((?:[A-Za-z" "\xD0\x90-\xD0\xAF\xD0\x81" "\xD0\xB0-\xD1\x8F\xD1\x91" "0-9\\-\\_]+\\.){0,10}([A-Za-z" "\xD1\x80\xD1\x84" "\\-\\d]{2,22})(\\:\\d+)?)"); | |
| +} | |
| + | |
| bool IsGoodProtocol(const QString &protocol) { | |
| const auto equals = [&](QLatin1String string) { | |
| return protocol.compare(string, Qt::CaseInsensitive) == 0; | |
| @@ -26,6 +41,21 @@ | |
| } // namespace | |
| +const QRegularExpression &RegExpDomain() { | |
| + static const auto result = CreateRegExp(ExpressionDomain()); | |
| + return result; | |
| +} | |
| + | |
| +const QRegularExpression &RegExpDomainExplicit() { | |
| + static const auto result = CreateRegExp(ExpressionDomainExplicit()); | |
| + return result; | |
| +} | |
| + | |
| +QRegularExpression RegExpProtocol() { | |
| + static const auto result = CreateRegExp("^([a-zA-Z]+)://"); | |
| + return result; | |
| +} | |
| + | |
| QMap<QString, QString> url_parse_params( | |
| const QString ¶ms, | |
| UrlParamNameTransform transform) { | |
| @@ -77,9 +107,9 @@ | |
| if (trimmed.isEmpty()) { | |
| return QString(); | |
| } | |
| - const auto match = TextUtilities::RegExpDomainExplicit().match(trimmed); | |
| + const auto match = RegExpDomainExplicit().match(trimmed); | |
| if (!match.hasMatch()) { | |
| - const auto domain = TextUtilities::RegExpDomain().match(trimmed); | |
| + const auto domain = RegExpDomain().match(trimmed); | |
| if (!domain.hasMatch() || domain.capturedStart() != 0) { | |
| return QString(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/qthelp_url.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/qthelp_url.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/qthelp_url.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/qthelp_url.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,6 +9,10 @@ | |
| namespace qthelp { | |
| +const QRegularExpression &RegExpDomain(); | |
| +const QRegularExpression &RegExpDomainExplicit(); | |
| +QRegularExpression RegExpProtocol(); | |
| + | |
| inline QString url_encode(const QString &part) { | |
| return QString::fromLatin1(QUrl::toPercentEncoding(part)); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/runtime_composer.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/base/runtime_composer.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/runtime_composer.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/runtime_composer.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,27 +8,21 @@ | |
| #include "base/runtime_composer.h" | |
| struct RuntimeComposerMetadatasMap { | |
| - QMap<uint64, RuntimeComposerMetadata*> data; | |
| - ~RuntimeComposerMetadatasMap() { | |
| - for_const (const RuntimeComposerMetadata *p, data) { | |
| - delete p; | |
| - } | |
| - } | |
| + std::map<uint64, std::unique_ptr<RuntimeComposerMetadata>> data; | |
| + QMutex mutex; | |
| }; | |
| const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask) { | |
| static RuntimeComposerMetadatasMap RuntimeComposerMetadatas; | |
| - static QMutex RuntimeComposerMetadatasMutex; | |
| - | |
| - QMutexLocker lock(&RuntimeComposerMetadatasMutex); | |
| - auto i = RuntimeComposerMetadatas.data.constFind(mask); | |
| - if (i == RuntimeComposerMetadatas.data.cend()) { | |
| - RuntimeComposerMetadata *meta = new RuntimeComposerMetadata(mask); | |
| - Assert(meta != nullptr); | |
| - i = RuntimeComposerMetadatas.data.insert(mask, meta); | |
| + QMutexLocker lock(&RuntimeComposerMetadatas.mutex); | |
| + auto i = RuntimeComposerMetadatas.data.find(mask); | |
| + if (i == end(RuntimeComposerMetadatas.data)) { | |
| + i = RuntimeComposerMetadatas.data.emplace( | |
| + mask, | |
| + std::make_unique<RuntimeComposerMetadata>(mask)).first; | |
| } | |
| - return i.value(); | |
| + return i->second.get(); | |
| } | |
| const RuntimeComposerMetadata *RuntimeComposerBase::ZeroRuntimeComposerMetadata = GetRuntimeComposerMetadata(0); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/tests_main.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/base/tests_main.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/tests_main.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/tests_main.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,6 +10,8 @@ | |
| #include "reporters/catch_reporter_compact.hpp" | |
| #include <QFile> | |
| +int (*TestForkedMethod)()/* = nullptr*/; | |
| + | |
| namespace base { | |
| namespace assertion { | |
| @@ -84,6 +86,8 @@ | |
| for (auto i = 0; i != argc; ++i) { | |
| if (argv[i] == QString("--touch") && i + 1 != argc) { | |
| touchFile = QFile::decodeName(argv[++i]); | |
| + } else if (argv[i] == QString("--forked") && TestForkedMethod) { | |
| + return TestForkedMethod(); | |
| } | |
| } | |
| const char *catch_argv[] = { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/timer.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/base/timer.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/timer.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/timer.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,8 @@ | |
| */ | |
| #include "base/timer.h" | |
| +#include <QtCore/QTimerEvent> | |
| + | |
| namespace base { | |
| namespace { | |
| @@ -24,7 +26,6 @@ | |
| moveToThread(thread); | |
| } | |
| - | |
| Timer::Timer(Fn<void()> callback) | |
| : QObject(nullptr) | |
| , _callback(std::move(callback)) | |
| @@ -48,7 +49,7 @@ | |
| setTimeout(timeout); | |
| _timerId = startTimer(_timeout, _type); | |
| if (_timerId) { | |
| - _next = getms(true) + _timeout; | |
| + _next = crl::time() + _timeout; | |
| } else { | |
| _next = 0; | |
| } | |
| @@ -64,7 +65,7 @@ | |
| if (!isActive()) { | |
| return -1; | |
| } | |
| - auto now = getms(true); | |
| + auto now = crl::time(); | |
| return (_next > now) ? (_next - now) : TimeMs(0); | |
| } | |
| @@ -101,7 +102,7 @@ | |
| if (_adjusted) { | |
| start(_timeout, _type, repeat()); | |
| } else { | |
| - _next = getms(true) + _timeout; | |
| + _next = crl::time() + _timeout; | |
| } | |
| } else { | |
| cancel(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/unique_function.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/unique_function.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/unique_function.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/unique_function.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -124,12 +124,8 @@ | |
| _impl.swap(other._impl); | |
| } | |
| - template < | |
| - typename ...OtherArgs, | |
| - typename = decltype(std::declval<std::function<Return(Args...)>>()( | |
| - std::declval<OtherArgs>()...))> | |
| - Return operator()(OtherArgs &&...args) { | |
| - return _impl(std::forward<OtherArgs>(args)...); | |
| + Return operator()(Args ...args) { | |
| + return _impl(std::forward<Args>(args)...); | |
| } | |
| explicit operator bool() const { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/variant.h work/tdesktop-1.4.0/Telegram/SourceFiles/base/variant.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/base/variant.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/base/variant.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,27 @@ | |
| */ | |
| #pragma once | |
| +#include <optional> | |
| + | |
| +inline bool operator<(std::nullopt_t, std::nullopt_t) { | |
| + return false; | |
| +} | |
| +inline bool operator>(std::nullopt_t, std::nullopt_t) { | |
| + return false; | |
| +} | |
| +inline bool operator<=(std::nullopt_t, std::nullopt_t) { | |
| + return true; | |
| +} | |
| +inline bool operator>=(std::nullopt_t, std::nullopt_t) { | |
| + return true; | |
| +} | |
| +inline bool operator==(std::nullopt_t, std::nullopt_t) { | |
| + return true; | |
| +} | |
| +inline bool operator!=(std::nullopt_t, std::nullopt_t) { | |
| + return false; | |
| +} | |
| + | |
| #include <mapbox/variant.hpp> | |
| #include <rpl/details/type_list.h> | |
| #include "base/match_method.h" | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/about_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/about_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/about_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/about_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -20,7 +20,7 @@ | |
| #include "core/update_checker.h" | |
| AboutBox::AboutBox(QWidget *parent) | |
| -: _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? " alpha" : "") + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString())), st::aboutVersionLink) | |
| +: _version(this, lng_about_version(lt_version, QString::fromLatin1(AppVersionStr.c_str()) + (cAlphaVersion() ? qsl(" alpha %1").arg(cAlphaVersion()) : (AppBetaVersion ? " beta" : ""))), st::aboutVersionLink) | |
| , _text1(this, lang(lng_about_text_1), Ui::FlatLabel::InitType::Rich, st::aboutLabel) | |
| , _text2(this, lang(lng_about_text_2), Ui::FlatLabel::InitType::Rich, st::aboutLabel) | |
| , _text3(this, st::aboutLabel) { | |
| @@ -59,7 +59,7 @@ | |
| } | |
| void AboutBox::showVersionHistory() { | |
| - if (cRealBetaVersion()) { | |
| + if (cRealAlphaVersion()) { | |
| auto url = qsl("https://tdesktop.com/"); | |
| switch (cPlatform()) { | |
| case dbipWindows: url += qsl("win/%1.zip"); break; | |
| @@ -68,11 +68,11 @@ | |
| 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(Core::countBetaVersionSignature(cRealBetaVersion()))); | |
| + url = url.arg(qsl("talpha%1_%2").arg(cRealAlphaVersion()).arg(Core::countAlphaVersionSignature(cRealAlphaVersion()))); | |
| Application::clipboard()->setText(url); | |
| - Ui::show(Box<InformBox>("The link to the current private beta version of Telegram Desktop was copied to the clipboard.")); | |
| + Ui::show(Box<InformBox>("The link to the current private alpha version of Telegram Desktop was copied to the clipboard.")); | |
| } else { | |
| QDesktopServices::openUrl(qsl("https://desktop.telegram.org/changelog")); | |
| } | |
| @@ -100,10 +100,9 @@ | |
| QString currentVersionText() { | |
| auto result = QString::fromLatin1(AppVersionStr.c_str()); | |
| if (cAlphaVersion()) { | |
| - result += " alpha"; | |
| - } | |
| - if (cBetaVersion()) { | |
| - result += qsl(" beta %1").arg(cBetaVersion() % 1000); | |
| + result += qsl(" alpha %1").arg(cAlphaVersion() % 1000); | |
| + } else if (AppBetaVersion) { | |
| + result += " beta"; | |
| } | |
| return result; | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/add_contact_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/add_contact_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/add_contact_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/add_contact_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -34,17 +34,18 @@ | |
| constexpr auto kMaxGroupChannelTitle = 255; // See also edit_peer_info_box. | |
| constexpr auto kMaxChannelDescription = 255; // See also edit_peer_info_box. | |
| -constexpr auto kMaxBioLength = 70; | |
| constexpr auto kMinUsernameLength = 5; | |
| +} // namespace | |
| + | |
| style::InputField CreateBioFieldStyle() { | |
| auto result = st::newGroupDescription; | |
| - result.textMargins.setRight(st::boxTextFont->spacew + st::boxTextFont->width(QString::number(kMaxBioLength))); | |
| + result.textMargins.setRight( | |
| + st::boxTextFont->spacew | |
| + + st::boxTextFont->width(QString::number(kMaxBioLength))); | |
| return result; | |
| } | |
| -} // namespace | |
| - | |
| QString PeerFloodErrorText(PeerFloodType type) { | |
| auto link = textcmdLink( | |
| Messenger::Instance().createInternalLinkFull(qsl("spambot")), | |
| @@ -148,8 +149,16 @@ | |
| auto textHeight = height() - st::contactPadding.top() - st::contactPadding.bottom() - st::boxPadding.bottom(); | |
| p.drawText(QRect(st::boxPadding.left(), st::contactPadding.top(), width() - st::boxPadding.left() - st::boxPadding.right(), textHeight), lng_contact_not_joined(lt_name, _sentName), style::al_topleft); | |
| } else { | |
| - st::contactUserIcon.paint(p, st::boxPadding.left(), _first->y() + st::contactIconTop, width()); | |
| - st::contactPhoneIcon.paint(p, st::boxPadding.left(), _phone->y() + st::contactIconTop, width()); | |
| + st::contactUserIcon.paint( | |
| + p, | |
| + st::boxPadding.left() + st::contactIconPosition.x(), | |
| + _first->y() + st::contactIconPosition.y(), | |
| + width()); | |
| + st::contactPhoneIcon.paint( | |
| + p, | |
| + st::boxPadding.left() + st::contactIconPosition.x(), | |
| + _phone->y() + st::contactIconPosition.y(), | |
| + width()); | |
| } | |
| } | |
| @@ -405,7 +414,7 @@ | |
| App::main()->sentUpdatesReceived(result); | |
| auto success = base::make_optional(&result) | |
| - | [](auto updates) -> base::optional<const QVector<MTPChat>*> { | |
| + | [](auto updates) -> std::optional<const QVector<MTPChat>*> { | |
| switch (updates->type()) { | |
| case mtpc_updates: | |
| return &updates->c_updates().vchats.v; | |
| @@ -413,12 +422,12 @@ | |
| return &updates->c_updatesCombined().vchats.v; | |
| } | |
| LOG(("API Error: unexpected update cons %1 (GroupInfoBox::creationDone)").arg(updates->type())); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| | [](auto chats) { | |
| return (!chats->empty() && chats->front().type() == mtpc_chat) | |
| ? base::make_optional(chats) | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| | [](auto chats) { | |
| return App::chat(chats->front().c_chat().vid.v); | |
| @@ -426,9 +435,7 @@ | |
| | [this](not_null<ChatData*> chat) { | |
| auto image = _photo->takeResultImage(); | |
| if (!image.isNull()) { | |
| - Messenger::Instance().uploadProfilePhoto( | |
| - std::move(image), | |
| - chat->id); | |
| + Auth().api().uploadPeerPhoto(chat, std::move(image)); | |
| } | |
| Ui::showPeerHistory(chat, ShowAtUnreadMsgId); | |
| }; | |
| @@ -510,7 +517,7 @@ | |
| App::main()->sentUpdatesReceived(result); | |
| auto success = base::make_optional(&result) | |
| - | [](auto updates) -> base::optional<const QVector<MTPChat>*> { | |
| + | [](auto updates) -> std::optional<const QVector<MTPChat>*> { | |
| switch (updates->type()) { | |
| case mtpc_updates: | |
| return &updates->c_updates().vchats.v; | |
| @@ -518,12 +525,12 @@ | |
| return &updates->c_updatesCombined().vchats.v; | |
| } | |
| LOG(("API Error: unexpected update cons %1 (GroupInfoBox::createChannel)").arg(updates->type())); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| | [](auto chats) { | |
| return (!chats->empty() && chats->front().type() == mtpc_channel) | |
| ? base::make_optional(chats) | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| | [](auto chats) { | |
| return App::channel(chats->front().c_channel().vid.v); | |
| @@ -531,9 +538,7 @@ | |
| | [this](not_null<ChannelData*> channel) { | |
| auto image = _photo->takeResultImage(); | |
| if (!image.isNull()) { | |
| - Messenger::Instance().uploadProfilePhoto( | |
| - std::move(image), | |
| - channel->id); | |
| + Auth().api().uploadPeerPhoto(channel, std::move(image)); | |
| } | |
| _createdChannel = channel; | |
| _creationRequestId = request( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/add_contact_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/add_contact_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/add_contact_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/add_contact_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -14,6 +14,10 @@ | |
| class ConfirmBox; | |
| class PeerListBox; | |
| +constexpr auto kMaxBioLength = 70; | |
| + | |
| +style::InputField CreateBioFieldStyle(); | |
| + | |
| namespace Ui { | |
| class FlatLabel; | |
| class InputField; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/autolock_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/autolock_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/autolock_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/autolock_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -14,8 +14,6 @@ | |
| } // namespace Ui | |
| class AutoLockBox : public BoxContent { | |
| - Q_OBJECT | |
| - | |
| public: | |
| AutoLockBox(QWidget*) { | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/boxes.style work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/boxes.style | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/boxes.style 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/boxes.style 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -199,9 +199,9 @@ | |
| textFg: windowSubTextFg; | |
| } | |
| -contactUserIcon: icon {{ "add_contact_user", menuIconFg }}; | |
| -contactPhoneIcon: icon {{ "add_contact_phone", menuIconFg }}; | |
| -contactIconTop: 28px; | |
| +contactUserIcon: icon {{ "settings_name", menuIconFg }}; | |
| +contactPhoneIcon: icon {{ "settings_phone_number", menuIconFg }}; | |
| +contactIconPosition: point(-5px, 23px); | |
| contactsAddIconAbove: icon {{ "contacts_add", activeButtonFg, point(18px, 18px) }}; | |
| contactsAdd: TwoIconButton { | |
| @@ -354,7 +354,35 @@ | |
| } | |
| } | |
| -localStorageBoxSkip: 10px; | |
| +localStorageRowHeight: 50px; | |
| +localStorageRowPadding: margins(23px, 5px, 20px, 5px); | |
| +localStorageRowTitle: FlatLabel(defaultFlatLabel) { | |
| + textFg: windowBoldFg; | |
| + maxHeight: 20px; | |
| + style: TextStyle(defaultTextStyle) { | |
| + font: font(14px semibold); | |
| + linkFont: font(14px semibold); | |
| + linkFontOver: font(14px semibold); | |
| + } | |
| +} | |
| +localStorageRowSize: FlatLabel(defaultFlatLabel) { | |
| + textFg: contactsStatusFg; | |
| + maxHeight: 20px; | |
| + style: TextStyle(defaultTextStyle) { | |
| + font: font(14px); | |
| + linkFont: font(14px); | |
| + linkFontOver: font(14px); | |
| + } | |
| +} | |
| +localStorageClear: defaultBoxButton; | |
| +localStorageLimitLabel: LabelSimple(defaultLabelSimple) { | |
| + font: boxTextFont; | |
| +} | |
| +localStorageLimitLabelMargin: margins(23px, 10px, 20px, 5px); | |
| +localStorageLimitSlider: MediaSlider(defaultContinuousSlider) { | |
| + seekSize: size(15px, 15px); | |
| +} | |
| +localStorageLimitMargin: margins(23px, 5px, 20px, 10px); | |
| shareRowsTop: 12px; | |
| shareRowHeight: 108px; | |
| @@ -375,13 +403,9 @@ | |
| shareActivateDuration: 150; | |
| shareScrollDuration: 300; | |
| -notificationsBoxHeight: 420px; | |
| -notificationsBoxMonitorTop: 63px; | |
| notificationsBoxMonitor: icon {{ "monitor", notificationsBoxMonitorFg }}; | |
| notificationsBoxScreenTop: 10px; | |
| notificationsBoxScreenSize: size(280px, 160px); | |
| -notificationsBoxCountLabelTop: 80px; | |
| -notificationsBoxCountTop: 30px; | |
| notificationsSampleSkip: 5px; | |
| notificationsSampleTopSkip: 5px; | |
| @@ -591,27 +615,6 @@ | |
| colorResultInput: InputField(colorValueInput) { | |
| } | |
| -editPrivacyOptionMargin: margins(23px, 14px, 21px, 0px); | |
| -editPrivacyPadding: margins(23px, 0px, 21px, 0px); | |
| -editPrivacyWarningPadding: margins(23px, 14px, 21px, 0px); | |
| -editPrivacyTitle: FlatLabel(defaultFlatLabel) { | |
| - minWidth: 320px; | |
| - textFg: boxTitleFg; | |
| - maxHeight: 56px; | |
| - style: TextStyle(defaultTextStyle) { | |
| - font: boxTitleFont; | |
| - linkFont: boxTitleFont; | |
| - linkFontOver: boxTitleFont; | |
| - } | |
| -} | |
| -editPrivacyTitlePadding: margins(23px, 20px, 21px, 13px); | |
| -editPrivacyLabel: FlatLabel(defaultFlatLabel) { | |
| - minWidth: 320px; | |
| - textFg: membersAboutLimitFg; | |
| - style: defaultTextStyle; | |
| -} | |
| -editPrivacyLinkMargin: margins(0px, 0px, 0px, 8px); | |
| - | |
| changePhoneIcon: icon { | |
| { "phone_simcard_from", changePhoneSimcardFrom }, | |
| { "phone_simcard_migrate", changePhoneSimcardTo, point(30px, 11px) }, | |
| @@ -791,3 +794,10 @@ | |
| } | |
| termsPadding: margins(23px, 4px, 16px, 16px); | |
| termsAgePadding: margins(23px, 16px, 16px, 0px); | |
| + | |
| +themesSmallSkip: 10px; | |
| +themesBackgroundSize: 120px; | |
| +themesScroll: ScrollArea(defaultScrollArea) { | |
| + bottomsh: 0px; | |
| + topsh: 0px; | |
| +} | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/connection_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/connection_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/connection_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/connection_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -32,10 +32,12 @@ | |
| #include "ui/effects/radial_animation.h" | |
| #include "ui/text_options.h" | |
| #include "history/history_location_manager.h" | |
| +#include "settings/settings_common.h" | |
| #include "application.h" | |
| #include "styles/style_boxes.h" | |
| #include "styles/style_chat_helpers.h" | |
| #include "styles/style_info.h" | |
| +#include "styles/style_settings.h" | |
| namespace { | |
| @@ -253,7 +255,7 @@ | |
| } | |
| void ProxyRow::step_radial(TimeMs ms, bool timer) { | |
| - if (timer) { | |
| + if (timer && !anim::Disabled()) { | |
| update(); | |
| } | |
| } | |
| @@ -375,13 +377,20 @@ | |
| p.setPen(pen); | |
| p.setBrush(_st->bg); | |
| const auto rect = rtlrect(QRectF(left, top, _st->diameter, _st->diameter).marginsRemoved(QMarginsF(_st->thickness / 2., _st->thickness / 2., _st->thickness / 2., _st->thickness / 2.)), outerWidth); | |
| - if (loading.arcLength < FullArcLength) { | |
| + if (_progress && loading.shown > 0 && anim::Disabled()) { | |
| + anim::DrawStaticLoading( | |
| + p, | |
| + rect, | |
| + _st->thickness, | |
| + pen.color(), | |
| + _st->bg); | |
| + } else if (loading.arcLength < FullArcLength) { | |
| p.drawArc(rect, loading.arcFrom, loading.arcLength); | |
| } else { | |
| p.drawEllipse(rect); | |
| } | |
| - if (toggled > 0) { | |
| + if (toggled > 0 && (!_progress || !anim::Disabled())) { | |
| p.setPen(Qt::NoPen); | |
| p.setBrush(anim::brush(_st->untoggledFg, _st->toggledFg, toggled * set)); | |
| @@ -910,111 +919,108 @@ | |
| } // namespace | |
| -AutoDownloadBox::AutoDownloadBox(QWidget *parent) | |
| -: _photoPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadPhoto() & dbiadNoPrivate), st::defaultBoxCheckbox) | |
| -, _photoGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadPhoto() & dbiadNoGroups), st::defaultBoxCheckbox) | |
| -, _audioPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadAudio() & dbiadNoPrivate), st::defaultBoxCheckbox) | |
| -, _audioGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadAudio() & dbiadNoGroups), st::defaultBoxCheckbox) | |
| -, _gifPrivate(this, lang(lng_media_auto_private_chats), !(cAutoDownloadGif() & dbiadNoPrivate), st::defaultBoxCheckbox) | |
| -, _gifGroups(this, lang(lng_media_auto_groups), !(cAutoDownloadGif() & dbiadNoGroups), st::defaultBoxCheckbox) | |
| -, _gifPlay(this, lang(lng_media_auto_play), cAutoPlayGif(), st::defaultBoxCheckbox) | |
| -, _sectionHeight(st::boxTitleHeight + 2 * (st::defaultCheck.diameter + st::setLittleSkip)) { | |
| +AutoDownloadBox::AutoDownloadBox(QWidget *parent) { | |
| } | |
| void AutoDownloadBox::prepare() { | |
| - addButton(langFactory(lng_connection_save), [this] { onSave(); }); | |
| - addButton(langFactory(lng_cancel), [this] { closeBox(); }); | |
| - | |
| - setDimensions(st::boxWidth, 3 * _sectionHeight - st::autoDownloadTopDelta + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip); | |
| + setupContent(); | |
| } | |
| -void AutoDownloadBox::paintEvent(QPaintEvent *e) { | |
| - BoxContent::paintEvent(e); | |
| +void AutoDownloadBox::setupContent() { | |
| + using namespace Settings; | |
| - Painter p(this); | |
| + setTitle(langFactory(lng_media_auto_title)); | |
| - p.setPen(st::boxTitleFg); | |
| - p.setFont(st::autoDownloadTitleFont); | |
| - p.drawTextLeft(st::autoDownloadTitlePosition.x(), st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_photo)); | |
| - p.drawTextLeft(st::autoDownloadTitlePosition.x(), _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_audio)); | |
| - p.drawTextLeft(st::autoDownloadTitlePosition.x(), 2 * _sectionHeight + st::autoDownloadTitlePosition.y(), width(), lang(lng_media_auto_gif)); | |
| -} | |
| - | |
| -void AutoDownloadBox::resizeEvent(QResizeEvent *e) { | |
| - BoxContent::resizeEvent(e); | |
| - | |
| - auto top = st::boxTitleHeight - st::autoDownloadTopDelta; | |
| - _photoPrivate->moveToLeft(st::boxTitlePosition.x(), top + st::setLittleSkip); | |
| - _photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip); | |
| - | |
| - _audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + top + st::setLittleSkip); | |
| - _audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip); | |
| - | |
| - _gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + top + st::setLittleSkip); | |
| - _gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip); | |
| - _gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip); | |
| -} | |
| - | |
| -void AutoDownloadBox::onSave() { | |
| - auto photosChanged = false; | |
| - auto documentsChanged = false; | |
| - auto autoplayChanged = false; | |
| - auto photosEnabled = false; | |
| - auto voiceEnabled = false; | |
| - auto animationsEnabled = false; | |
| - auto autoDownloadPhoto = (_photoPrivate->checked() ? 0 : dbiadNoPrivate) | |
| - | (_photoGroups->checked() ? 0 : dbiadNoGroups); | |
| - if (cAutoDownloadPhoto() != autoDownloadPhoto) { | |
| - const auto enabledPrivate = (cAutoDownloadPhoto() & dbiadNoPrivate) | |
| - && !(autoDownloadPhoto & dbiadNoPrivate); | |
| - const auto enabledGroups = (cAutoDownloadPhoto() & dbiadNoGroups) | |
| - && !(autoDownloadPhoto & dbiadNoGroups); | |
| - photosEnabled = enabledPrivate || enabledGroups; | |
| - photosChanged = true; | |
| - cSetAutoDownloadPhoto(autoDownloadPhoto); | |
| - } | |
| - auto autoDownloadAudio = (_audioPrivate->checked() ? 0 : dbiadNoPrivate) | |
| - | (_audioGroups->checked() ? 0 : dbiadNoGroups); | |
| - if (cAutoDownloadAudio() != autoDownloadAudio) { | |
| - const auto enabledPrivate = (cAutoDownloadAudio() & dbiadNoPrivate) | |
| - && !(autoDownloadAudio & dbiadNoPrivate); | |
| - const auto enabledGroups = (cAutoDownloadAudio() & dbiadNoGroups) | |
| - && !(autoDownloadAudio & dbiadNoGroups); | |
| - voiceEnabled = enabledPrivate || enabledGroups; | |
| - documentsChanged = true; | |
| - cSetAutoDownloadAudio(autoDownloadAudio); | |
| - } | |
| - auto autoDownloadGif = (_gifPrivate->checked() ? 0 : dbiadNoPrivate) | |
| - | (_gifGroups->checked() ? 0 : dbiadNoGroups); | |
| - if (cAutoDownloadGif() != autoDownloadGif) { | |
| - const auto enabledPrivate = (cAutoDownloadGif() & dbiadNoPrivate) | |
| - && !(autoDownloadGif & dbiadNoPrivate); | |
| - const auto enabledGroups = (cAutoDownloadGif() & dbiadNoGroups) | |
| - && !(autoDownloadGif & dbiadNoGroups); | |
| - animationsEnabled = enabledPrivate || enabledGroups; | |
| - documentsChanged = true; | |
| - cSetAutoDownloadGif(autoDownloadGif); | |
| - } | |
| - if (cAutoPlayGif() != _gifPlay->checked()) { | |
| - cSetAutoPlayGif(_gifPlay->checked()); | |
| - if (!cAutoPlayGif()) { | |
| - Auth().data().stopAutoplayAnimations(); | |
| - } | |
| - autoplayChanged = true; | |
| - } | |
| - if (photosChanged || documentsChanged || autoplayChanged) { | |
| - Local::writeUserSettings(); | |
| - } | |
| - if (photosEnabled) { | |
| - Auth().data().photoLoadSettingsChanged(); | |
| - } | |
| - if (voiceEnabled) { | |
| - Auth().data().voiceLoadSettingsChanged(); | |
| - } | |
| - if (animationsEnabled) { | |
| - Auth().data().animationLoadSettingsChanged(); | |
| - } | |
| - closeBox(); | |
| + auto wrap = object_ptr<Ui::VerticalLayout>(this); | |
| + const auto content = wrap.data(); | |
| + setInnerWidget(object_ptr<Ui::OverrideMargins>( | |
| + this, | |
| + std::move(wrap))); | |
| + | |
| + using pair = std::pair<Ui::Checkbox*, Ui::Checkbox*>; | |
| + const auto pairValue = [](pair checkboxes) { | |
| + return (checkboxes.first->checked() ? 0 : dbiadNoPrivate) | |
| + | (checkboxes.second->checked() ? 0 : dbiadNoGroups); | |
| + }; | |
| + const auto enabledSomething = [](int32 oldValue, int32 newValue) { | |
| + return (uint32(oldValue) & ~uint32(newValue)) != 0; | |
| + }; | |
| + const auto addCheckbox = [&](int32 value, DBIAutoDownloadFlags flag) { | |
| + const auto label = (flag == dbiadNoPrivate) | |
| + ? lng_media_auto_private_chats | |
| + : lng_media_auto_groups; | |
| + return content->add( | |
| + object_ptr<Ui::Checkbox>( | |
| + content, | |
| + lang(label), | |
| + !(value & flag), | |
| + st::settingsSendType), | |
| + st::settingsSendTypePadding); | |
| + }; | |
| + const auto addPair = [&](int32 value) { | |
| + const auto first = addCheckbox(value, dbiadNoPrivate); | |
| + const auto second = addCheckbox(value, dbiadNoGroups); | |
| + return pair(first, second); | |
| + }; | |
| + | |
| + AddSubsectionTitle(content, lng_media_photo_title); | |
| + const auto photo = addPair(cAutoDownloadPhoto()); | |
| + AddSkip(content); | |
| + | |
| + AddSkip(content); | |
| + AddSubsectionTitle(content, lng_media_audio_title); | |
| + const auto audio = addPair(cAutoDownloadAudio()); | |
| + AddSkip(content); | |
| + | |
| + AddSkip(content); | |
| + AddSubsectionTitle(content, lng_media_gif_title); | |
| + const auto gif = addPair(cAutoDownloadGif()); | |
| + AddSkip(content); | |
| + | |
| + addButton(langFactory(lng_connection_save), [=] { | |
| + const auto photoValue = pairValue(photo); | |
| + const auto audioValue = pairValue(audio); | |
| + const auto gifValue = pairValue(gif); | |
| + const auto photosEnabled = enabledSomething( | |
| + cAutoDownloadPhoto(), | |
| + photoValue); | |
| + const auto audioEnabled = enabledSomething( | |
| + cAutoDownloadAudio(), | |
| + audioValue); | |
| + const auto gifEnabled = enabledSomething( | |
| + cAutoDownloadGif(), | |
| + gifValue); | |
| + const auto photosChanged = (cAutoDownloadPhoto() != photoValue); | |
| + const auto documentsChanged = (cAutoDownloadAudio() != audioValue) | |
| + || (cAutoDownloadGif() != gifValue); | |
| + cSetAutoDownloadAudio(audioValue); | |
| + cSetAutoDownloadGif(gifValue); | |
| + cSetAutoDownloadPhoto(photoValue); | |
| + if (photosChanged || documentsChanged) { | |
| + Local::writeUserSettings(); | |
| + } | |
| + if (photosEnabled) { | |
| + Auth().data().photoLoadSettingsChanged(); | |
| + } | |
| + if (audioEnabled) { | |
| + Auth().data().voiceLoadSettingsChanged(); | |
| + } | |
| + if (gifEnabled) { | |
| + Auth().data().animationLoadSettingsChanged(); | |
| + } | |
| + closeBox(); | |
| + }); | |
| + addButton(langFactory(lng_cancel), [=] { closeBox(); }); | |
| + | |
| + widthValue( | |
| + ) | rpl::start_with_next([=](int width) { | |
| + content->resizeToWidth(width); | |
| + }, content->lifetime()); | |
| + | |
| + content->heightValue( | |
| + ) | rpl::start_with_next([=](int height) { | |
| + setDimensions(st::boxWideWidth, height); | |
| + }, content->lifetime()); | |
| } | |
| ProxiesBoxController::ProxiesBoxController() | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/connection_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/connection_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/connection_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/connection_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,30 +23,14 @@ | |
| } // namespace Ui | |
| class AutoDownloadBox : public BoxContent { | |
| - Q_OBJECT | |
| - | |
| public: | |
| AutoDownloadBox(QWidget *parent); | |
| protected: | |
| void prepare() override; | |
| - void paintEvent(QPaintEvent *e) override; | |
| - void resizeEvent(QResizeEvent *e) override; | |
| - | |
| -private slots: | |
| - void onSave(); | |
| - | |
| private: | |
| - object_ptr<Ui::Checkbox> _photoPrivate; | |
| - object_ptr<Ui::Checkbox> _photoGroups; | |
| - object_ptr<Ui::Checkbox> _audioPrivate; | |
| - object_ptr<Ui::Checkbox> _audioGroups; | |
| - object_ptr<Ui::Checkbox> _gifPrivate; | |
| - object_ptr<Ui::Checkbox> _gifGroups; | |
| - object_ptr<Ui::Checkbox> _gifPlay; | |
| - | |
| - int _sectionHeight = 0; | |
| + void setupContent(); | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/edit_caption_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/edit_caption_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/edit_caption_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/edit_caption_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -416,7 +416,7 @@ | |
| }; | |
| const auto prepareFlags = Ui::ItemTextOptions( | |
| item->history(), | |
| - App::self()).flags; | |
| + Auth().user()).flags; | |
| TextUtilities::PrepareForSending(sending, prepareFlags); | |
| TextUtilities::Trim(sending); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/edit_privacy_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/edit_privacy_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/edit_privacy_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/edit_privacy_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,16 +7,22 @@ | |
| */ | |
| #include "boxes/edit_privacy_box.h" | |
| -#include "styles/style_boxes.h" | |
| #include "ui/widgets/checkbox.h" | |
| #include "ui/widgets/labels.h" | |
| #include "ui/widgets/buttons.h" | |
| #include "ui/wrap/slide_wrap.h" | |
| +#include "ui/wrap/vertical_layout.h" | |
| #include "history/history.h" | |
| #include "boxes/peer_list_controllers.h" | |
| +#include "info/profile/info_profile_button.h" | |
| +#include "settings/settings_common.h" | |
| +#include "calls/calls_instance.h" | |
| +#include "base/binary_guard.h" | |
| +#include "lang/lang_keys.h" | |
| #include "apiwrap.h" | |
| #include "auth_session.h" | |
| -#include "lang/lang_keys.h" | |
| +#include "styles/style_settings.h" | |
| +#include "styles/style_boxes.h" | |
| namespace { | |
| @@ -77,100 +83,33 @@ | |
| } // namespace | |
| -EditPrivacyBox::EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller) : BoxContent() | |
| -, _controller(std::move(controller)) | |
| -, _loading(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout) { | |
| +EditPrivacyBox::EditPrivacyBox( | |
| + QWidget*, | |
| + std::unique_ptr<Controller> controller, | |
| + const Value &value) | |
| +: _controller(std::move(controller)) | |
| +, _value(value) { | |
| } | |
| void EditPrivacyBox::prepare() { | |
| _controller->setView(this); | |
| - setTitle([this] { return _controller->title(); }); | |
| - addButton(langFactory(lng_cancel), [this] { closeBox(); }); | |
| - | |
| - loadData(); | |
| - | |
| - setDimensions(st::boxWideWidth, countDefaultHeight(st::boxWideWidth)); | |
| -} | |
| - | |
| -int EditPrivacyBox::resizeGetHeight(int newWidth) { | |
| - auto top = 0; | |
| - auto layoutRow = [&](auto &widget, style::margins padding) { | |
| - if (!widget) return; | |
| - widget->resizeToNaturalWidth(newWidth - padding.left() - padding.right()); | |
| - widget->moveToLeft(padding.left(), top + padding.top()); | |
| - top = widget->bottomNoMargins() + padding.bottom(); | |
| - }; | |
| - | |
| - layoutRow(_description, st::editPrivacyPadding); | |
| - layoutRow(_everyone, st::editPrivacyOptionMargin); | |
| - layoutRow(_contacts, st::editPrivacyOptionMargin); | |
| - layoutRow(_nobody, st::editPrivacyOptionMargin); | |
| - layoutRow(_warning, st::editPrivacyWarningPadding); | |
| - layoutRow(_exceptionsTitle, st::editPrivacyTitlePadding); | |
| - auto linksTop = top; | |
| - layoutRow(_alwaysLink, st::editPrivacyPadding); | |
| - layoutRow(_neverLink, st::editPrivacyPadding); | |
| - auto linksHeight = top - linksTop; | |
| - layoutRow(_exceptionsDescription, st::editPrivacyPadding); | |
| - | |
| - // Add full width of both links in any case | |
| - auto linkMargins = exceptionLinkMargins(); | |
| - top -= linksHeight; | |
| - top += linkMargins.top() + st::boxLinkButton.font->height + linkMargins.bottom(); | |
| - top += linkMargins.top() + st::boxLinkButton.font->height + linkMargins.bottom(); | |
| - | |
| - return top; | |
| -} | |
| - | |
| -void EditPrivacyBox::resizeEvent(QResizeEvent *e) { | |
| - if (_loading) { | |
| - _loading->moveToLeft((width() - _loading->width()) / 2, height() / 3); | |
| - } | |
| + setupContent(); | |
| } | |
| -int EditPrivacyBox::countDefaultHeight(int newWidth) { | |
| - auto height = 0; | |
| - auto optionHeight = [this](Option option) { | |
| - if (!_controller->hasOption(option)) { | |
| - return 0; | |
| - } | |
| - return st::editPrivacyOptionMargin.top() + st::defaultCheck.diameter + st::editPrivacyOptionMargin.bottom(); | |
| - }; | |
| - auto labelHeight = [newWidth](const QString &text, const style::FlatLabel &st, style::margins padding) { | |
| - if (text.isEmpty()) { | |
| - return 0; | |
| - } | |
| - | |
| - auto fake = object_ptr<Ui::FlatLabel>(nullptr, text, Ui::FlatLabel::InitType::Simple, st); | |
| - fake->resizeToNaturalWidth(newWidth - padding.left() - padding.right()); | |
| - return padding.top() + fake->heightNoMargins() + padding.bottom(); | |
| - }; | |
| - auto linkHeight = [this]() { | |
| - auto linkMargins = exceptionLinkMargins(); | |
| - return linkMargins.top() + st::boxLinkButton.font->height + linkMargins.bottom(); | |
| - }; | |
| - height += labelHeight(_controller->description(), st::editPrivacyLabel, st::editPrivacyPadding); | |
| - height += optionHeight(Option::Everyone); | |
| - height += optionHeight(Option::Contacts); | |
| - height += optionHeight(Option::Nobody); | |
| - height += labelHeight(_controller->warning(), st::editPrivacyLabel, st::editPrivacyWarningPadding); | |
| - height += labelHeight(lang(lng_edit_privacy_exceptions), st::editPrivacyTitle, st::editPrivacyTitlePadding); | |
| - height += linkHeight(); | |
| - height += linkHeight(); | |
| - height += labelHeight(_controller->exceptionsDescription(), st::editPrivacyLabel, st::editPrivacyPadding); | |
| - return height; | |
| -} | |
| - | |
| -void EditPrivacyBox::editExceptionUsers(Exception exception) { | |
| - auto controller = std::make_unique<PrivacyExceptionsBoxController>(crl::guard(this, [this, exception] { | |
| - return _controller->exceptionBoxTitle(exception); | |
| - }), exceptionUsers(exception)); | |
| - auto initBox = [this, exception, controller = controller.get()](not_null<PeerListBox*> box) { | |
| - box->addButton(langFactory(lng_settings_save), crl::guard(this, [this, box, exception, controller] { | |
| +void EditPrivacyBox::editExceptionUsers( | |
| + Exception exception, | |
| + Fn<void()> done) { | |
| + auto controller = std::make_unique<PrivacyExceptionsBoxController>( | |
| + crl::guard(this, [=] { | |
| + return _controller->exceptionBoxTitle(exception); | |
| + }), | |
| + exceptionUsers(exception)); | |
| + auto initBox = [=, controller = controller.get()]( | |
| + not_null<PeerListBox*> box) { | |
| + box->addButton(langFactory(lng_settings_save), crl::guard(this, [=] { | |
| exceptionUsers(exception) = controller->getResult(); | |
| - exceptionLink(exception)->entity()->setText(exceptionLinkText(exception)); | |
| - auto removeFrom = ([exception] { | |
| + const auto removeFrom = ([=] { | |
| switch (exception) { | |
| case Exception::Always: return Exception::Never; | |
| case Exception::Never: return Exception::Always; | |
| @@ -178,30 +117,20 @@ | |
| Unexpected("Invalid exception value."); | |
| })(); | |
| auto &removeFromUsers = exceptionUsers(removeFrom); | |
| - auto removedSome = false; | |
| - for (auto user : exceptionUsers(exception)) { | |
| - auto removedStart = std::remove(removeFromUsers.begin(), removeFromUsers.end(), user); | |
| - if (removedStart != removeFromUsers.end()) { | |
| - removeFromUsers.erase(removedStart, removeFromUsers.end()); | |
| - removedSome = true; | |
| - } | |
| - } | |
| - if (removedSome) { | |
| - exceptionLink(removeFrom)->entity()->setText(exceptionLinkText(removeFrom)); | |
| + for (const auto user : exceptionUsers(exception)) { | |
| + const auto from = ranges::remove(removeFromUsers, user); | |
| + removeFromUsers.erase(from, end(removeFromUsers)); | |
| } | |
| + done(); | |
| box->closeBox(); | |
| })); | |
| - box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); }); | |
| + box->addButton(langFactory(lng_cancel), [=] { box->closeBox(); }); | |
| }; | |
| Ui::show( | |
| Box<PeerListBox>(std::move(controller), std::move(initBox)), | |
| LayerOption::KeepOther); | |
| } | |
| -QString EditPrivacyBox::exceptionLinkText(Exception exception) { | |
| - return _controller->exceptionLinkText(exception, exceptionUsers(exception).size()); | |
| -} | |
| - | |
| QVector<MTPInputPrivacyRule> EditPrivacyBox::collectResult() { | |
| auto collectInputUsers = [](auto &users) { | |
| auto result = QVector<MTPInputUser>(); | |
| @@ -215,162 +144,193 @@ | |
| constexpr auto kMaxRules = 3; // allow users, disallow users, option | |
| auto result = QVector<MTPInputPrivacyRule>(); | |
| result.reserve(kMaxRules); | |
| - if (showExceptionLink(Exception::Always) && !_alwaysUsers.empty()) { | |
| - result.push_back(MTP_inputPrivacyValueAllowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_alwaysUsers)))); | |
| + if (showExceptionLink(Exception::Always) && !_value.always.empty()) { | |
| + result.push_back(MTP_inputPrivacyValueAllowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.always)))); | |
| } | |
| - if (showExceptionLink(Exception::Never) && !_neverUsers.empty()) { | |
| - result.push_back(MTP_inputPrivacyValueDisallowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_neverUsers)))); | |
| - } | |
| - switch (_option) { | |
| - case Option::Everyone: result.push_back(MTP_inputPrivacyValueAllowAll()); break; | |
| - case Option::Contacts: result.push_back(MTP_inputPrivacyValueAllowContacts()); break; | |
| - case Option::Nobody: result.push_back(MTP_inputPrivacyValueDisallowAll()); break; | |
| + if (showExceptionLink(Exception::Never) && !_value.never.empty()) { | |
| + result.push_back(MTP_inputPrivacyValueDisallowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.never)))); | |
| } | |
| + result.push_back([&] { | |
| + switch (_value.option) { | |
| + case Option::Everyone: return MTP_inputPrivacyValueAllowAll(); | |
| + case Option::Contacts: return MTP_inputPrivacyValueAllowContacts(); | |
| + case Option::Nobody: return MTP_inputPrivacyValueDisallowAll(); | |
| + } | |
| + Unexpected("Option value in EditPrivacyBox::collectResult."); | |
| + }()); | |
| return result; | |
| } | |
| -style::margins EditPrivacyBox::exceptionLinkMargins() const { | |
| - return st::editPrivacyLinkMargin; | |
| -} | |
| - | |
| std::vector<not_null<UserData*>> &EditPrivacyBox::exceptionUsers(Exception exception) { | |
| switch (exception) { | |
| - case Exception::Always: return _alwaysUsers; | |
| - case Exception::Never: return _neverUsers; | |
| - } | |
| - Unexpected("Invalid exception value."); | |
| -} | |
| - | |
| -object_ptr<Ui::SlideWrap<Ui::LinkButton>> &EditPrivacyBox::exceptionLink(Exception exception) { | |
| - switch (exception) { | |
| - case Exception::Always: return _alwaysLink; | |
| - case Exception::Never: return _neverLink; | |
| + case Exception::Always: return _value.always; | |
| + case Exception::Never: return _value.never; | |
| } | |
| Unexpected("Invalid exception value."); | |
| } | |
| bool EditPrivacyBox::showExceptionLink(Exception exception) const { | |
| switch (exception) { | |
| - case Exception::Always: return (_option == Option::Contacts) || (_option == Option::Nobody); | |
| - case Exception::Never: return (_option == Option::Everyone) || (_option == Option::Contacts); | |
| + case Exception::Always: | |
| + return (_value.option == Option::Contacts) | |
| + || (_value.option == Option::Nobody); | |
| + case Exception::Never: | |
| + return (_value.option == Option::Everyone) | |
| + || (_value.option == Option::Contacts); | |
| } | |
| Unexpected("Invalid exception value."); | |
| } | |
| -void EditPrivacyBox::createWidgets() { | |
| - _loading.destroy(); | |
| - _optionGroup = std::make_shared<Ui::RadioenumGroup<Option>>(_option); | |
| - | |
| - auto createOption = [this](object_ptr<Ui::Radioenum<Option>> &widget, Option option, const QString &label) { | |
| - if (_controller->hasOption(option) || (_option == option)) { | |
| - widget.create(this, _optionGroup, option, label, st::defaultBoxCheckbox); | |
| - } | |
| - }; | |
| - auto createLabel = [this](object_ptr<Ui::FlatLabel> &widget, const QString &text, const style::FlatLabel &st) { | |
| - if (text.isEmpty()) { | |
| - return; | |
| +Ui::Radioenum<EditPrivacyBox::Option> *EditPrivacyBox::AddOption( | |
| + not_null<Ui::VerticalLayout*> container, | |
| + const std::shared_ptr<Ui::RadioenumGroup<Option>> &group, | |
| + Option option) { | |
| + const auto label = [&] { | |
| + switch (option) { | |
| + case Option::Everyone: return lng_edit_privacy_everyone; | |
| + case Option::Contacts: return lng_edit_privacy_contacts; | |
| + case Option::Nobody: return lng_edit_privacy_nobody; | |
| } | |
| - widget.create(this, text, Ui::FlatLabel::InitType::Simple, st); | |
| + Unexpected("Option value in EditPrivacyBox::AddOption."); | |
| + }(); | |
| + return container->add( | |
| + object_ptr<Ui::Radioenum<Option>>( | |
| + container, | |
| + group, | |
| + option, | |
| + lang(label), | |
| + st::settingsSendType), | |
| + st::settingsSendTypePadding); | |
| +} | |
| + | |
| +Ui::FlatLabel *EditPrivacyBox::AddLabel( | |
| + not_null<Ui::VerticalLayout*> container, | |
| + rpl::producer<QString> text) { | |
| + const auto wrap = container->add( | |
| + object_ptr<Ui::SlideWrap<Ui::FlatLabel>>( | |
| + container, | |
| + object_ptr<Ui::FlatLabel>( | |
| + container, | |
| + rpl::duplicate(text), | |
| + st::boxDividerLabel), | |
| + st::settingsPrivacyEditLabelPadding)); | |
| + wrap->hide(anim::type::instant); | |
| + wrap->toggleOn(std::move( | |
| + text | |
| + ) | rpl::map([](const QString &text) { | |
| + return !text.isEmpty(); | |
| + })); | |
| + return wrap->entity(); | |
| +} | |
| + | |
| +void EditPrivacyBox::setupContent() { | |
| + using namespace Settings; | |
| + | |
| + setTitle([=] { return _controller->title(); }); | |
| + | |
| + auto wrap = object_ptr<Ui::VerticalLayout>(this); | |
| + const auto content = wrap.data(); | |
| + setInnerWidget(object_ptr<Ui::OverrideMargins>( | |
| + this, | |
| + std::move(wrap))); | |
| + | |
| + const auto group = std::make_shared<Ui::RadioenumGroup<Option>>( | |
| + _value.option); | |
| + const auto toggle = Ui::AttachAsChild(content, rpl::event_stream<>()); | |
| + | |
| + group->setChangedCallback([=](Option value) { | |
| + _value.option = value; | |
| + toggle->fire({}); | |
| + }); | |
| + | |
| + const auto addOption = [&](Option option) { | |
| + return (_controller->hasOption(option) || (_value.option == option)) | |
| + ? AddOption(content, group, option) | |
| + : nullptr; | |
| }; | |
| - auto createExceptionLink = [this](Exception exception) { | |
| - exceptionLink(exception).create(this, object_ptr<Ui::LinkButton>(this, exceptionLinkText(exception)), exceptionLinkMargins()); | |
| - exceptionLink(exception)->heightValue( | |
| - ) | rpl::start_with_next([this] { | |
| - resizeToWidth(width()); | |
| - }, lifetime()); | |
| - exceptionLink(exception)->entity()->setClickedCallback([this, exception] { editExceptionUsers(exception); }); | |
| + const auto addExceptionLink = [=](Exception exception) { | |
| + const auto update = Ui::AttachAsChild( | |
| + content, | |
| + rpl::event_stream<>()); | |
| + auto label = update->events_starting_with( | |
| + rpl::empty_value() | |
| + ) | rpl::map([=] { | |
| + return exceptionUsers(exception).size(); | |
| + }) | rpl::map([](int count) { | |
| + return count | |
| + ? lng_edit_privacy_exceptions_count(lt_count, count) | |
| + : lang(lng_edit_privacy_exceptions_add); | |
| + }); | |
| + auto text = _controller->exceptionButtonTextKey(exception); | |
| + const auto button = content->add( | |
| + object_ptr<Ui::SlideWrap<Button>>( | |
| + content, | |
| + object_ptr<Button>( | |
| + content, | |
| + Lang::Viewer(text), | |
| + st::settingsButton))); | |
| + CreateRightLabel( | |
| + button->entity(), | |
| + std::move(label), | |
| + st::settingsButton, | |
| + text); | |
| + button->toggleOn(toggle->events_starting_with( | |
| + rpl::empty_value() | |
| + ) | rpl::map([=] { | |
| + return showExceptionLink(exception); | |
| + }))->entity()->addClickHandler([=] { | |
| + editExceptionUsers(exception, [=] { update->fire({}); }); | |
| + }); | |
| + return button; | |
| }; | |
| - createLabel(_description, _controller->description(), st::editPrivacyLabel); | |
| - createOption(_everyone, Option::Everyone, lang(lng_edit_privacy_everyone)); | |
| - createOption(_contacts, Option::Contacts, lang(lng_edit_privacy_contacts)); | |
| - createOption(_nobody, Option::Nobody, lang(lng_edit_privacy_nobody)); | |
| - createLabel(_warning, _controller->warning(), st::editPrivacyLabel); | |
| - createLabel(_exceptionsTitle, lang(lng_edit_privacy_exceptions), st::editPrivacyTitle); | |
| - createExceptionLink(Exception::Always); | |
| - createExceptionLink(Exception::Never); | |
| - createLabel(_exceptionsDescription, _controller->exceptionsDescription(), st::editPrivacyLabel); | |
| - | |
| - clearButtons(); | |
| - addButton(langFactory(lng_settings_save), [this] { | |
| - auto someAreDisallowed = (_option != Option::Everyone) || !_neverUsers.empty(); | |
| - _controller->confirmSave(someAreDisallowed, crl::guard(this, [this] { | |
| - Auth().api().savePrivacy(_controller->key(), collectResult()); | |
| + AddSubsectionTitle(content, _controller->optionsTitleKey()); | |
| + addOption(Option::Everyone); | |
| + addOption(Option::Contacts); | |
| + addOption(Option::Nobody); | |
| + AddLabel(content, _controller->warning()); | |
| + AddSkip(content); | |
| + | |
| + AddDivider(content); | |
| + AddSkip(content); | |
| + AddSubsectionTitle(content, lng_edit_privacy_exceptions); | |
| + const auto always = addExceptionLink(Exception::Always); | |
| + const auto never = addExceptionLink(Exception::Never); | |
| + AddLabel(content, _controller->exceptionsDescription()); | |
| + AddSkip(content); | |
| + | |
| + const auto saveAdditional = _controller->setupAdditional(content); | |
| + | |
| + addButton(langFactory(lng_settings_save), [=] { | |
| + const auto someAreDisallowed = (_value.option != Option::Everyone) | |
| + || !_value.never.empty(); | |
| + _controller->confirmSave(someAreDisallowed, crl::guard(this, [=] { | |
| + Auth().api().savePrivacy( | |
| + _controller->apiKey(), | |
| + collectResult()); | |
| + if (saveAdditional) { | |
| + saveAdditional(); | |
| + } | |
| closeBox(); | |
| })); | |
| }); | |
| addButton(langFactory(lng_cancel), [this] { closeBox(); }); | |
| - _optionGroup->setChangedCallback([this](Option value) { | |
| - _option = value; | |
| - _alwaysLink->toggle( | |
| - showExceptionLink(Exception::Always), | |
| - anim::type::normal); | |
| - _neverLink->toggle( | |
| - showExceptionLink(Exception::Never), | |
| - anim::type::normal); | |
| - }); | |
| - | |
| - showChildren(); | |
| - _alwaysLink->toggle( | |
| - showExceptionLink(Exception::Always), | |
| - anim::type::instant); | |
| - _neverLink->toggle( | |
| - showExceptionLink(Exception::Never), | |
| - anim::type::instant); | |
| - | |
| - setDimensions(st::boxWideWidth, resizeGetHeight(st::boxWideWidth)); | |
| -} | |
| - | |
| -void EditPrivacyBox::loadData() { | |
| - request(MTPaccount_GetPrivacy(_controller->key())).done([this](const MTPaccount_PrivacyRules &result) { | |
| - Expects(result.type() == mtpc_account_privacyRules); | |
| - auto &rules = result.c_account_privacyRules(); | |
| - App::feedUsers(rules.vusers); | |
| - | |
| - // This is simplified version of privacy rules interpretation. | |
| - // But it should be fine for all the apps that use the same subset of features. | |
| - auto optionSet = false; | |
| - auto setOption = [this, &optionSet](Option option) { | |
| - if (optionSet) return; | |
| - optionSet = true; | |
| - _option = option; | |
| - }; | |
| - auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) { | |
| - switch (rule.type()) { | |
| - case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break; | |
| - case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break; | |
| - case mtpc_privacyValueAllowUsers: { | |
| - auto &users = rule.c_privacyValueAllowUsers().vusers.v; | |
| - _alwaysUsers.reserve(_alwaysUsers.size() + users.size()); | |
| - for (auto &userId : users) { | |
| - auto user = App::user(UserId(userId.v)); | |
| - if (!base::contains(_neverUsers, user) && !base::contains(_alwaysUsers, user)) { | |
| - _alwaysUsers.push_back(user); | |
| - } | |
| - } | |
| - } break; | |
| - case mtpc_privacyValueDisallowContacts: // not supported, fall through | |
| - case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break; | |
| - case mtpc_privacyValueDisallowUsers: { | |
| - auto &users = rule.c_privacyValueDisallowUsers().vusers.v; | |
| - _neverUsers.reserve(_neverUsers.size() + users.size()); | |
| - for (auto &userId : users) { | |
| - auto user = App::user(UserId(userId.v)); | |
| - if (!base::contains(_alwaysUsers, user) && !base::contains(_neverUsers, user)) { | |
| - _neverUsers.push_back(user); | |
| - } | |
| - } | |
| - } break; | |
| - } | |
| - }; | |
| - for (auto &rule : rules.vrules.v) { | |
| - feedRule(rule); | |
| - } | |
| - feedRule(MTP_privacyValueDisallowAll()); // disallow by default. | |
| - | |
| - createWidgets(); | |
| - }).send(); | |
| + const auto linkHeight = st::settingsButton.padding.top() | |
| + + st::settingsButton.height | |
| + + st::settingsButton.padding.bottom(); | |
| + | |
| + widthValue( | |
| + ) | rpl::start_with_next([=](int width) { | |
| + content->resizeToWidth(width); | |
| + }, content->lifetime()); | |
| + | |
| + content->heightValue( | |
| + ) | rpl::map([=](int height) { | |
| + return height - always->height() - never->height() + 2 * linkHeight; | |
| + }) | rpl::distinct_until_changed( | |
| + ) | rpl::start_with_next([=](int height) { | |
| + setDimensions(st::boxWideWidth, height); | |
| + }, content->lifetime()); | |
| } | |
| - | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/edit_privacy_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/edit_privacy_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/edit_privacy_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/edit_privacy_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,8 +9,16 @@ | |
| #include "boxes/abstract_box.h" | |
| #include "mtproto/sender.h" | |
| +#include "apiwrap.h" | |
| + | |
| +enum LangKey : int; | |
| + | |
| +namespace Calls { | |
| +enum class PeerToPeer; | |
| +} // namespace Calls | |
| namespace Ui { | |
| +class VerticalLayout; | |
| class FlatLabel; | |
| class LinkButton; | |
| template <typename Enum> | |
| @@ -23,11 +31,8 @@ | |
| class EditPrivacyBox : public BoxContent, private MTP::Sender { | |
| public: | |
| - enum class Option { | |
| - Everyone, | |
| - Contacts, | |
| - Nobody, | |
| - }; | |
| + using Value = ApiWrap::Privacy; | |
| + using Option = Value::Option; | |
| enum class Exception { | |
| Always, | |
| Never, | |
| @@ -35,23 +40,32 @@ | |
| class Controller { | |
| public: | |
| - virtual MTPInputPrivacyKey key() = 0; | |
| + using Key = ApiWrap::Privacy::Key; | |
| + | |
| + virtual Key key() = 0; | |
| + virtual MTPInputPrivacyKey apiKey() = 0; | |
| virtual QString title() = 0; | |
| virtual bool hasOption(Option option) { | |
| return true; | |
| } | |
| - virtual QString description() = 0; | |
| - virtual QString warning() { | |
| - return QString(); | |
| + virtual LangKey optionsTitleKey() = 0; | |
| + virtual rpl::producer<QString> warning() { | |
| + return rpl::never<QString>(); | |
| } | |
| - virtual QString exceptionLinkText(Exception exception, int count) = 0; | |
| + virtual LangKey exceptionButtonTextKey(Exception exception) = 0; | |
| virtual QString exceptionBoxTitle(Exception exception) = 0; | |
| - virtual QString exceptionsDescription() = 0; | |
| + virtual rpl::producer<QString> exceptionsDescription() = 0; | |
| - virtual void confirmSave(bool someAreDisallowed, FnMut<void()> saveCallback) { | |
| + virtual void confirmSave( | |
| + bool someAreDisallowed, | |
| + FnMut<void()> saveCallback) { | |
| saveCallback(); | |
| } | |
| + virtual Fn<void()> setupAdditional( | |
| + not_null<Ui::VerticalLayout*> container) { | |
| + return nullptr; | |
| + } | |
| virtual ~Controller() = default; | |
| @@ -71,43 +85,31 @@ | |
| }; | |
| - EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller); | |
| + EditPrivacyBox( | |
| + QWidget*, | |
| + std::unique_ptr<Controller> controller, | |
| + const Value &value); | |
| + | |
| + static Ui::Radioenum<Option> *AddOption( | |
| + not_null<Ui::VerticalLayout*> container, | |
| + const std::shared_ptr<Ui::RadioenumGroup<Option>> &group, | |
| + Option option); | |
| + static Ui::FlatLabel *AddLabel( | |
| + not_null<Ui::VerticalLayout*> container, | |
| + rpl::producer<QString> text); | |
| protected: | |
| void prepare() override; | |
| - int resizeGetHeight(int newWidth) override; | |
| - | |
| - void resizeEvent(QResizeEvent *e) override; | |
| private: | |
| - style::margins exceptionLinkMargins() const; | |
| bool showExceptionLink(Exception exception) const; | |
| - void createWidgets(); | |
| + void setupContent(); | |
| QVector<MTPInputPrivacyRule> collectResult(); | |
| - void loadData(); | |
| - int countDefaultHeight(int newWidth); | |
| - void editExceptionUsers(Exception exception); | |
| - QString exceptionLinkText(Exception exception); | |
| + void editExceptionUsers(Exception exception, Fn<void()> done); | |
| std::vector<not_null<UserData*>> &exceptionUsers(Exception exception); | |
| - object_ptr<Ui::SlideWrap<Ui::LinkButton>> &exceptionLink(Exception exception); | |
| std::unique_ptr<Controller> _controller; | |
| - Option _option = Option::Everyone; | |
| - | |
| - std::shared_ptr<Ui::RadioenumGroup<Option>> _optionGroup; | |
| - object_ptr<Ui::FlatLabel> _loading; | |
| - object_ptr<Ui::FlatLabel> _description = { nullptr }; | |
| - object_ptr<Ui::Radioenum<Option>> _everyone = { nullptr }; | |
| - object_ptr<Ui::Radioenum<Option>> _contacts = { nullptr }; | |
| - object_ptr<Ui::Radioenum<Option>> _nobody = { nullptr }; | |
| - object_ptr<Ui::FlatLabel> _warning = { nullptr }; | |
| - object_ptr<Ui::FlatLabel> _exceptionsTitle = { nullptr }; | |
| - object_ptr<Ui::SlideWrap<Ui::LinkButton>> _alwaysLink = { nullptr }; | |
| - object_ptr<Ui::SlideWrap<Ui::LinkButton>> _neverLink = { nullptr }; | |
| - object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr }; | |
| - | |
| - std::vector<not_null<UserData*>> _alwaysUsers; | |
| - std::vector<not_null<UserData*>> _neverUsers; | |
| + Value _value; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/language_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/language_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/language_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/language_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -14,6 +14,7 @@ | |
| #include "boxes/confirm_box.h" | |
| #include "mainwidget.h" | |
| #include "mainwindow.h" | |
| +#include "messenger.h" | |
| #include "lang/lang_instance.h" | |
| #include "lang/lang_cloud_manager.h" | |
| #include "styles/style_boxes.h" | |
| @@ -150,3 +151,27 @@ | |
| } | |
| _inner->setSelected(currentIndex); | |
| } | |
| + | |
| +base::binary_guard LanguageBox::Show() { | |
| + auto result = base::binary_guard(); | |
| + | |
| + const auto manager = Messenger::Instance().langCloudManager(); | |
| + if (manager->languageList().isEmpty()) { | |
| + auto guard = std::make_shared<base::binary_guard>(); | |
| + std::tie(result, *guard) = base::make_binary_guard(); | |
| + auto alive = std::make_shared<std::unique_ptr<base::Subscription>>( | |
| + std::make_unique<base::Subscription>()); | |
| + **alive = manager->languageListChanged().add_subscription([=] { | |
| + const auto show = guard->alive(); | |
| + *alive = nullptr; | |
| + if (show) { | |
| + Ui::show(Box<LanguageBox>()); | |
| + } | |
| + }); | |
| + } else { | |
| + Ui::show(Box<LanguageBox>()); | |
| + } | |
| + manager->requestLanguageList(); | |
| + | |
| + return result; | |
| +} | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/language_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/language_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/language_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/language_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,6 +10,7 @@ | |
| #include "lang/lang_cloud_manager.h" | |
| #include "boxes/abstract_box.h" | |
| #include "mtproto/sender.h" | |
| +#include "base/binary_guard.h" | |
| namespace Ui { | |
| class RadiobuttonGroup; | |
| @@ -21,6 +22,8 @@ | |
| LanguageBox(QWidget*) { | |
| } | |
| + static base::binary_guard Show(); | |
| + | |
| protected: | |
| void prepare() override; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/local_storage_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/local_storage_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/local_storage_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/local_storage_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,112 +8,476 @@ | |
| #include "boxes/local_storage_box.h" | |
| #include "styles/style_boxes.h" | |
| +#include "ui/wrap/vertical_layout.h" | |
| +#include "ui/wrap/slide_wrap.h" | |
| +#include "ui/widgets/labels.h" | |
| #include "ui/widgets/buttons.h" | |
| +#include "ui/widgets/shadow.h" | |
| +#include "ui/widgets/continuous_sliders.h" | |
| +#include "ui/effects/radial_animation.h" | |
| #include "storage/localstorage.h" | |
| +#include "storage/cache/storage_cache_database.h" | |
| +#include "data/data_session.h" | |
| #include "lang/lang_keys.h" | |
| #include "mainwindow.h" | |
| #include "auth_session.h" | |
| #include "layout.h" | |
| -LocalStorageBox::LocalStorageBox(QWidget *parent) | |
| -: _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) { | |
| +namespace { | |
| + | |
| +constexpr auto kSizeLimitsCount = 20; | |
| +constexpr auto kTimeLimitsCount = 16; | |
| +constexpr auto kMaxTimeLimitValue = std::numeric_limits<size_type>::max(); | |
| + | |
| +int64 SizeLimitInMB(int index) { | |
| + if (index < 10) { | |
| + return int64(index + 1) * 100; | |
| + } | |
| + return int64(index - 9) * 1024; | |
| } | |
| -void LocalStorageBox::prepare() { | |
| - setTitle(langFactory(lng_local_storage_title)); | |
| +int64 SizeLimit(int index) { | |
| + return SizeLimitInMB(index) * 1024 * 1024; | |
| +} | |
| - addButton(langFactory(lng_box_ok), [this] { closeBox(); }); | |
| +QString SizeLimitText(int64 limit) { | |
| + const auto mb = (limit / (1024 * 1024)); | |
| + const auto gb = (mb / 1024); | |
| + return (gb > 0) | |
| + ? (QString::number(gb) + " GB") | |
| + : (QString::number(mb) + " MB"); | |
| +} | |
| + | |
| +size_type TimeLimitInDays(int index) { | |
| + if (index < 3) { | |
| + const auto weeks = (index + 1); | |
| + return size_type(weeks) * 7; | |
| + } else if (index < 15) { | |
| + const auto month = (index - 2); | |
| + return (size_type(month) * 30) | |
| + + ((month >= 12) ? 5 : | |
| + (month >= 10) ? 4 : | |
| + (month >= 8) ? 3 : | |
| + (month >= 7) ? 2 : | |
| + (month >= 5) ? 1 : | |
| + (month >= 3) ? 0 : | |
| + (month >= 2) ? -1 : | |
| + (month >= 1) ? 1 : 0); | |
| + //+ (month >= 1 ? 1 : 0) | |
| + //- (month >= 2 ? 2 : 0) | |
| + //+ (month >= 3 ? 1 : 0) | |
| + //+ (month >= 5 ? 1 : 0) | |
| + //+ (month >= 7 ? 1 : 0) | |
| + //+ (month >= 8 ? 1 : 0) | |
| + //+ (month >= 10 ? 1 : 0) | |
| + //+ (month >= 12 ? 1 : 0); | |
| + } | |
| + return 0; | |
| +} | |
| - _clear->setClickedCallback([this] { clearStorage(); }); | |
| +size_type TimeLimit(int index) { | |
| + const auto days = TimeLimitInDays(index); | |
| + return days | |
| + ? (days * 24 * 60 * 60) | |
| + : kMaxTimeLimitValue; | |
| +} | |
| - connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int))); | |
| - connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); | |
| +QString TimeLimitText(size_type limit) { | |
| + const auto days = (limit / (24 * 60 * 60)); | |
| + const auto weeks = (days / 7); | |
| + const auto months = (days / 29); | |
| + return (months > 0) | |
| + ? lng_local_storage_limit_months(lt_count, months) | |
| + : (limit > 0) | |
| + ? lng_local_storage_limit_weeks(lt_count, weeks) | |
| + : lang(lng_local_storage_limit_never); | |
| +} | |
| - subscribe(Auth().downloaderTaskFinished(), [this] { update(); }); | |
| +size_type LimitToValue(size_type timeLimit) { | |
| + return timeLimit ? timeLimit : kMaxTimeLimitValue; | |
| +} | |
| - updateControls(); | |
| +size_type ValueToLimit(size_type timeLimit) { | |
| + return (timeLimit != kMaxTimeLimitValue) ? timeLimit : 0; | |
| +} | |
| - checkLocalStoredCounts(); | |
| +} // namespace | |
| + | |
| +class LocalStorageBox::Row : public Ui::RpWidget { | |
| +public: | |
| + Row( | |
| + QWidget *parent, | |
| + Fn<QString(size_type)> title, | |
| + Fn<QString()> clear, | |
| + const Database::TaggedSummary &data); | |
| + | |
| + void update(const Database::TaggedSummary &data); | |
| + void toggleProgress(bool shown); | |
| + | |
| + rpl::producer<> clearRequests() const; | |
| + | |
| +protected: | |
| + int resizeGetHeight(int newWidth) override; | |
| + void paintEvent(QPaintEvent *e) override; | |
| + | |
| +private: | |
| + QString titleText(const Database::TaggedSummary &data) const; | |
| + QString sizeText(const Database::TaggedSummary &data) const; | |
| + void step_radial(TimeMs ms, bool timer); | |
| + | |
| + Fn<QString(size_type)> _titleFactory; | |
| + object_ptr<Ui::FlatLabel> _title; | |
| + object_ptr<Ui::FlatLabel> _description; | |
| + object_ptr<Ui::FlatLabel> _clearing = { nullptr }; | |
| + object_ptr<Ui::RoundButton> _clear; | |
| + std::unique_ptr<Ui::InfiniteRadialAnimation> _progress; | |
| + | |
| +}; | |
| + | |
| +LocalStorageBox::Row::Row( | |
| + QWidget *parent, | |
| + Fn<QString(size_type)> title, | |
| + Fn<QString()> clear, | |
| + const Database::TaggedSummary &data) | |
| +: RpWidget(parent) | |
| +, _titleFactory(std::move(title)) | |
| +, _title( | |
| + this, | |
| + titleText(data), | |
| + Ui::FlatLabel::InitType::Simple, | |
| + st::localStorageRowTitle) | |
| +, _description( | |
| + this, | |
| + sizeText(data), | |
| + Ui::FlatLabel::InitType::Simple, | |
| + st::localStorageRowSize) | |
| +, _clear(this, std::move(clear), st::localStorageClear) { | |
| + _clear->setVisible(data.count != 0); | |
| } | |
| -void LocalStorageBox::updateControls() { | |
| - auto rowsHeight = 0; | |
| - if (_imagesCount > 0 && _audiosCount > 0) { | |
| - rowsHeight = 2 * (st::linkFont->height + st::localStorageBoxSkip); | |
| - } else { | |
| - rowsHeight = st::linkFont->height + st::localStorageBoxSkip; | |
| +void LocalStorageBox::Row::update(const Database::TaggedSummary &data) { | |
| + if (data.count != 0) { | |
| + _title->setText(titleText(data)); | |
| } | |
| - _clear->setVisible(_imagesCount > 0 || _audiosCount > 0); | |
| - setDimensions(st::boxWidth, st::localStorageBoxSkip + rowsHeight + _clear->height()); | |
| - _clear->moveToLeft(st::boxPadding.left(), st::localStorageBoxSkip + rowsHeight); | |
| - update(); | |
| -} | |
| - | |
| -void LocalStorageBox::checkLocalStoredCounts() { | |
| - int imagesCount = Local::hasImages() + Local::hasStickers() + Local::hasWebFiles(); | |
| - int audiosCount = Local::hasAudios(); | |
| - if (imagesCount != _imagesCount || audiosCount != _audiosCount) { | |
| - _imagesCount = imagesCount; | |
| - _audiosCount = audiosCount; | |
| - if (_imagesCount > 0 || _audiosCount > 0) { | |
| - _state = State::Normal; | |
| - } | |
| - updateControls(); | |
| + _description->setText(sizeText(data)); | |
| + _clear->setVisible(data.count != 0); | |
| +} | |
| + | |
| +void LocalStorageBox::Row::toggleProgress(bool shown) { | |
| + if (!shown) { | |
| + _progress = nullptr; | |
| + _description->show(); | |
| + _clearing.destroy(); | |
| + } else if (!_progress) { | |
| + _progress = std::make_unique<Ui::InfiniteRadialAnimation>( | |
| + animation(this, &Row::step_radial), | |
| + st::proxyCheckingAnimation); | |
| + _progress->start(); | |
| + _clearing = object_ptr<Ui::FlatLabel>( | |
| + this, | |
| + lang(lng_local_storage_clearing), | |
| + Ui::FlatLabel::InitType::Simple, | |
| + st::localStorageRowSize); | |
| + _clearing->show(); | |
| + _description->hide(); | |
| + resizeToWidth(width()); | |
| + RpWidget::update(); | |
| } | |
| } | |
| -void LocalStorageBox::paintEvent(QPaintEvent *e) { | |
| - BoxContent::paintEvent(e); | |
| +void LocalStorageBox::Row::step_radial(TimeMs ms, bool timer) { | |
| + if (timer && !anim::Disabled()) { | |
| + RpWidget::update(); | |
| + } | |
| +} | |
| + | |
| +rpl::producer<> LocalStorageBox::Row::clearRequests() const { | |
| + return _clear->clicks() | rpl::map([] { return rpl::empty_value(); }); | |
| +} | |
| + | |
| +int LocalStorageBox::Row::resizeGetHeight(int newWidth) { | |
| + const auto height = st::localStorageRowHeight; | |
| + const auto padding = st::localStorageRowPadding; | |
| + const auto available = newWidth - padding.left() - padding.right(); | |
| + _title->resizeToWidth(available); | |
| + _description->resizeToWidth(available); | |
| + _title->moveToLeft(padding.left(), padding.top(), newWidth); | |
| + _description->moveToLeft( | |
| + padding.left(), | |
| + height - padding.bottom() - _description->height(), | |
| + newWidth); | |
| + if (_clearing) { | |
| + const auto progressShift = st::proxyCheckingPosition.x() | |
| + + st::proxyCheckingAnimation.size.width() | |
| + + st::proxyCheckingSkip; | |
| + _clearing->resizeToWidth(available - progressShift); | |
| + _clearing->moveToLeft( | |
| + padding.left(),// + progressShift, | |
| + _description->y(), | |
| + newWidth); | |
| + } | |
| + _clear->moveToRight( | |
| + st::boxLayerButtonPadding.right(), | |
| + (height - _clear->height()) / 2, | |
| + newWidth); | |
| + return height; | |
| +} | |
| +void LocalStorageBox::Row::paintEvent(QPaintEvent *e) { | |
| + if (!_progress || true) { | |
| + return; | |
| + } | |
| Painter p(this); | |
| - p.setFont(st::boxTextFont); | |
| - p.setPen(st::windowFg); | |
| - checkLocalStoredCounts(); | |
| - auto top = st::localStorageBoxSkip; | |
| - if (_imagesCount > 0) { | |
| - auto text = lng_settings_images_cached(lt_count, _imagesCount, lt_size, formatSizeText(Local::storageImagesSize() + Local::storageStickersSize() + Local::storageWebFilesSize())); | |
| - p.drawTextLeft(st::boxPadding.left(), top, width(), text); | |
| - top += st::boxTextFont->height + st::localStorageBoxSkip; | |
| - } | |
| - if (_audiosCount > 0) { | |
| - auto text = lng_settings_audios_cached(lt_count, _audiosCount, lt_size, formatSizeText(Local::storageAudiosSize())); | |
| - p.drawTextLeft(st::boxPadding.left(), top, width(), text); | |
| - top += st::boxTextFont->height + st::localStorageBoxSkip; | |
| - } else if (_imagesCount <= 0) { | |
| - p.drawTextLeft(st::boxPadding.left(), top, width(), lang(lng_settings_no_data_cached)); | |
| - top += st::boxTextFont->height + st::localStorageBoxSkip; | |
| - } | |
| - auto text = ([this]() -> QString { | |
| - switch (_state) { | |
| - case State::Clearing: return lang(lng_local_storage_clearing); | |
| - case State::Cleared: return lang(lng_local_storage_cleared); | |
| - case State::ClearFailed: return Lang::Hard::ClearPathFailed(); | |
| + const auto padding = st::localStorageRowPadding; | |
| + const auto height = st::localStorageRowHeight; | |
| + const auto bottom = height - padding.bottom() - _description->height(); | |
| + _progress->step(crl::time()); | |
| + _progress->draw( | |
| + p, | |
| + { | |
| + st::proxyCheckingPosition.x() + padding.left(), | |
| + st::proxyCheckingPosition.y() + bottom | |
| + }, | |
| + width()); | |
| +} | |
| + | |
| +QString LocalStorageBox::Row::titleText(const Database::TaggedSummary &data) const { | |
| + return _titleFactory(data.count); | |
| +} | |
| + | |
| +QString LocalStorageBox::Row::sizeText(const Database::TaggedSummary &data) const { | |
| + return data.totalSize | |
| + ? formatSizeText(data.totalSize) | |
| + : lang(lng_local_storage_empty); | |
| +} | |
| + | |
| +LocalStorageBox::LocalStorageBox( | |
| + QWidget*, | |
| + not_null<Database*> db, | |
| + CreateTag) | |
| +: _db(db) { | |
| + const auto &settings = Local::cacheSettings(); | |
| + _sizeLimit = settings.totalSizeLimit; | |
| + _timeLimit = settings.totalTimeLimit; | |
| +} | |
| + | |
| +void LocalStorageBox::Show(not_null<Database*> db) { | |
| + auto shared = std::make_shared<object_ptr<LocalStorageBox>>( | |
| + Box<LocalStorageBox>(db, CreateTag())); | |
| + const auto weak = shared->data(); | |
| + db->statsOnMain( | |
| + ) | rpl::start_with_next([=](Database::Stats &&stats) { | |
| + weak->update(std::move(stats)); | |
| + if (auto &strong = *shared) { | |
| + Ui::show(std::move(strong)); | |
| } | |
| - return QString(); | |
| - })(); | |
| - if (!text.isEmpty()) { | |
| - p.drawTextLeft(st::boxPadding.left(), top, width(), text); | |
| - top += st::boxTextFont->height + st::localStorageBoxSkip; | |
| + }, weak->lifetime()); | |
| +} | |
| + | |
| +void LocalStorageBox::prepare() { | |
| + setTitle(langFactory(lng_local_storage_title)); | |
| + | |
| + addButton(langFactory(lng_box_ok), [this] { closeBox(); }); | |
| + | |
| + setupControls(); | |
| +} | |
| + | |
| +void LocalStorageBox::updateRow( | |
| + not_null<Ui::SlideWrap<Row>*> row, | |
| + Database::TaggedSummary *data) { | |
| + const auto summary = (_rows.find(0)->second == row); | |
| + const auto shown = (data && data->count && data->totalSize) || summary; | |
| + if (shown) { | |
| + row->entity()->update(*data); | |
| } | |
| + row->toggle(shown, anim::type::normal); | |
| } | |
| -void LocalStorageBox::clearStorage() { | |
| - App::wnd()->tempDirDelete(Local::ClearManagerStorage); | |
| - _state = State::Clearing; | |
| - updateControls(); | |
| +void LocalStorageBox::update(Database::Stats &&stats) { | |
| + _stats = std::move(stats); | |
| + if (const auto i = _rows.find(0); i != end(_rows)) { | |
| + i->second->entity()->toggleProgress(_stats.clearing); | |
| + } | |
| + for (const auto &entry : _rows) { | |
| + if (entry.first) { | |
| + const auto i = _stats.tagged.find(entry.first); | |
| + updateRow( | |
| + entry.second, | |
| + (i != end(_stats.tagged)) ? &i->second : nullptr); | |
| + } else { | |
| + updateRow(entry.second, &_stats.full); | |
| + } | |
| + } | |
| } | |
| -void LocalStorageBox::onTempDirCleared(int task) { | |
| - if (task & Local::ClearManagerStorage) { | |
| - _state = State::Cleared; | |
| +void LocalStorageBox::clearByTag(uint8 tag) { | |
| + if (tag) { | |
| + _db->clearByTag(tag); | |
| + } else { | |
| + _db->clear(); | |
| } | |
| - updateControls(); | |
| } | |
| -void LocalStorageBox::onTempDirClearFailed(int task) { | |
| - if (task & Local::ClearManagerStorage) { | |
| - _state = State::ClearFailed; | |
| +void LocalStorageBox::setupControls() { | |
| + const auto container = setInnerWidget( | |
| + object_ptr<Ui::VerticalLayout>(this)); | |
| + const auto createRow = [&]( | |
| + uint8 tag, | |
| + Fn<QString(size_type)> title, | |
| + Fn<QString()> clear, | |
| + const Database::TaggedSummary &data) { | |
| + auto result = container->add(object_ptr<Ui::SlideWrap<Row>>( | |
| + container, | |
| + object_ptr<Row>( | |
| + container, | |
| + std::move(title), | |
| + std::move(clear), | |
| + data))); | |
| + const auto shown = (data.count && data.totalSize) || !tag; | |
| + result->toggle(shown, anim::type::instant); | |
| + result->entity()->clearRequests( | |
| + ) | rpl::start_with_next([=] { | |
| + clearByTag(tag); | |
| + }, result->lifetime()); | |
| + _rows.emplace(tag, result); | |
| + return result; | |
| + }; | |
| + auto tracker = Ui::MultiSlideTracker(); | |
| + const auto createTagRow = [&](uint8 tag, auto &&titleFactory) { | |
| + static const auto empty = Database::TaggedSummary(); | |
| + const auto i = _stats.tagged.find(tag); | |
| + const auto &data = (i != end(_stats.tagged)) ? i->second : empty; | |
| + auto factory = std::forward<decltype(titleFactory)>(titleFactory); | |
| + auto title = [factory = std::move(factory)](size_type count) { | |
| + return factory(lt_count, count); | |
| + }; | |
| + tracker.track(createRow( | |
| + tag, | |
| + std::move(title), | |
| + langFactory(lng_local_storage_clear_some), | |
| + data)); | |
| + }; | |
| + auto summaryTitle = [](size_type) { | |
| + return lang(lng_local_storage_summary); | |
| + }; | |
| + createRow( | |
| + 0, | |
| + std::move(summaryTitle), | |
| + langFactory(lng_local_storage_clear), | |
| + _stats.full); | |
| + setupLimits(container); | |
| + const auto shadow = container->add(object_ptr<Ui::SlideWrap<>>( | |
| + container, | |
| + object_ptr<Ui::PlainShadow>(container), | |
| + st::localStorageRowPadding)); | |
| + createTagRow(Data::kImageCacheTag, lng_local_storage_image); | |
| + createTagRow(Data::kStickerCacheTag, lng_local_storage_sticker); | |
| + createTagRow(Data::kVoiceMessageCacheTag, lng_local_storage_voice); | |
| + createTagRow(Data::kVideoMessageCacheTag, lng_local_storage_round); | |
| + createTagRow(Data::kAnimationCacheTag, lng_local_storage_animation); | |
| + shadow->toggleOn( | |
| + std::move(tracker).atLeastOneShownValue() | |
| + ); | |
| + container->resizeToWidth(st::boxWidth); | |
| + container->heightValue( | |
| + ) | rpl::start_with_next([=](int height) { | |
| + setDimensions(st::boxWidth, height); | |
| + }, container->lifetime()); | |
| +} | |
| + | |
| +template < | |
| + typename Value, | |
| + typename Convert, | |
| + typename Callback, | |
| + typename> | |
| +void LocalStorageBox::createLimitsSlider( | |
| + not_null<Ui::VerticalLayout*> container, | |
| + int valuesCount, | |
| + Convert &&convert, | |
| + Value currentValue, | |
| + Callback &&callback) { | |
| + const auto label = container->add( | |
| + object_ptr<Ui::LabelSimple>(container, st::localStorageLimitLabel), | |
| + st::localStorageLimitLabelMargin); | |
| + callback(label, currentValue); | |
| + const auto slider = container->add( | |
| + object_ptr<Ui::MediaSlider>(container, st::localStorageLimitSlider), | |
| + st::localStorageLimitMargin); | |
| + slider->resize(st::localStorageLimitSlider.seekSize); | |
| + slider->setPseudoDiscrete( | |
| + valuesCount, | |
| + std::forward<Convert>(convert), | |
| + currentValue, | |
| + [=, callback = std::forward<Callback>(callback)](Value value) { | |
| + callback(label, value); | |
| + }); | |
| +} | |
| + | |
| +void LocalStorageBox::setupLimits(not_null<Ui::VerticalLayout*> container) { | |
| + const auto shadow = container->add( | |
| + object_ptr<Ui::PlainShadow>(container), | |
| + st::localStorageRowPadding); | |
| + | |
| + createLimitsSlider( | |
| + container, | |
| + kSizeLimitsCount, | |
| + SizeLimit, | |
| + _sizeLimit, | |
| + [=](not_null<Ui::LabelSimple*> label, int64 limit) { | |
| + const auto text = SizeLimitText(limit); | |
| + label->setText(lng_local_storage_size_limit(lt_size, text)); | |
| + _sizeLimit = limit; | |
| + limitsChanged(); | |
| + }); | |
| + | |
| + createLimitsSlider( | |
| + container, | |
| + kTimeLimitsCount, | |
| + TimeLimit, | |
| + LimitToValue(_timeLimit), | |
| + [=](not_null<Ui::LabelSimple*> label, size_type limit) { | |
| + const auto text = TimeLimitText(ValueToLimit(limit)); | |
| + label->setText(lng_local_storage_time_limit(lt_limit, text)); | |
| + _timeLimit = limit; | |
| + limitsChanged(); | |
| + }); | |
| +} | |
| + | |
| +void LocalStorageBox::limitsChanged() { | |
| + const auto &settings = Local::cacheSettings(); | |
| + const auto changed = (settings.totalSizeLimit != _sizeLimit) | |
| + || (settings.totalTimeLimit != _timeLimit); | |
| + if (_limitsChanged != changed) { | |
| + _limitsChanged = changed; | |
| + clearButtons(); | |
| + if (_limitsChanged) { | |
| + addButton(langFactory(lng_settings_save), [=] { save(); }); | |
| + addButton(langFactory(lng_cancel), [=] { closeBox(); }); | |
| + } else { | |
| + addButton(langFactory(lng_box_ok), [=] { closeBox(); }); | |
| + } | |
| } | |
| - updateControls(); | |
| +} | |
| + | |
| +void LocalStorageBox::save() { | |
| + if (!_limitsChanged) { | |
| + closeBox(); | |
| + return; | |
| + } | |
| + auto update = Storage::Cache::Database::SettingsUpdate(); | |
| + update.totalSizeLimit = _sizeLimit; | |
| + update.totalTimeLimit = _timeLimit; | |
| + Local::updateCacheSettings(update); | |
| + Auth().data().cache().updateSettings(update); | |
| + closeBox(); | |
| +} | |
| + | |
| +void LocalStorageBox::paintEvent(QPaintEvent *e) { | |
| + BoxContent::paintEvent(e); | |
| + | |
| + Painter p(this); | |
| + | |
| + p.setFont(st::boxTextFont); | |
| + p.setPen(st::windowFg); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/local_storage_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/local_storage_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/local_storage_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/local_storage_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,20 +8,31 @@ | |
| #pragma once | |
| #include "boxes/abstract_box.h" | |
| +#include "storage/cache/storage_cache_database.h" | |
| + | |
| +namespace Storage { | |
| +namespace Cache { | |
| +class Database; | |
| +} // namespace Cache | |
| +} // namespace Storage | |
| namespace Ui { | |
| -class LinkButton; | |
| +class VerticalLayout; | |
| +template <typename Widget> | |
| +class SlideWrap; | |
| +class LabelSimple; | |
| } // namespace Ui | |
| class LocalStorageBox : public BoxContent { | |
| - Q_OBJECT | |
| + struct CreateTag { | |
| + }; | |
| public: | |
| - LocalStorageBox(QWidget*); | |
| + using Database = Storage::Cache::Database; | |
| + | |
| + LocalStorageBox(QWidget*, not_null<Database*> db, CreateTag); | |
| -private slots: | |
| - void onTempDirCleared(int task); | |
| - void onTempDirClearFailed(int task); | |
| + static void Show(not_null<Database*> db); | |
| protected: | |
| void prepare() override; | |
| @@ -29,21 +40,42 @@ | |
| void paintEvent(QPaintEvent *e) override; | |
| private: | |
| - void clearStorage(); | |
| - void updateControls(); | |
| - void checkLocalStoredCounts(); | |
| - | |
| - enum class State { | |
| - Normal, | |
| - Clearing, | |
| - Cleared, | |
| - ClearFailed, | |
| - }; | |
| - State _state = State::Normal; | |
| - | |
| - object_ptr<Ui::LinkButton> _clear; | |
| + class Row; | |
| - int _imagesCount = -1; | |
| - int _audiosCount = -1; | |
| + void clearByTag(uint8 tag); | |
| + void update(Database::Stats &&stats); | |
| + void updateRow( | |
| + not_null<Ui::SlideWrap<Row>*> row, | |
| + Database::TaggedSummary *data); | |
| + void setupControls(); | |
| + void setupLimits(not_null<Ui::VerticalLayout*> container); | |
| + void limitsChanged(); | |
| + void save(); | |
| + | |
| + template < | |
| + typename Value, | |
| + typename Convert, | |
| + typename Callback, | |
| + typename = std::enable_if_t< | |
| + rpl::details::is_callable_plain_v< | |
| + Callback, | |
| + not_null<Ui::LabelSimple*>, | |
| + Value> | |
| + && std::is_same_v<Value, decltype(std::declval<Convert>()(1))>>> | |
| + void createLimitsSlider( | |
| + not_null<Ui::VerticalLayout*> container, | |
| + int valuesCount, | |
| + Convert &&convert, | |
| + Value currentValue, | |
| + Callback &&callback); | |
| + | |
| + not_null<Storage::Cache::Database*> _db; | |
| + Database::Stats _stats; | |
| + | |
| + base::flat_map<uint8, not_null<Ui::SlideWrap<Row>*>> _rows; | |
| + | |
| + int64 _sizeLimit = 0; | |
| + size_type _timeLimit = 0; | |
| + bool _limitsChanged = false; | |
| }; | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes: notifications_box.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes: notifications_box.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/peer_list_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/peer_list_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/peer_list_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/peer_list_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -982,6 +982,9 @@ | |
| row->addRipple(_st.item, size, point, std::move(updateCallback)); | |
| } | |
| } | |
| + if (anim::Disabled()) { | |
| + mousePressReleased(e->button()); | |
| + } | |
| } | |
| void PeerListContent::mouseReleaseEvent(QMouseEvent *e) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/peer_list_controllers.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/peer_list_controllers.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/peer_list_controllers.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/peer_list_controllers.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -263,10 +263,8 @@ | |
| }; | |
| auto added = 0; | |
| if (respectSavedMessagesChat()) { | |
| - if (auto self = App::self()) { | |
| - if (appendRow(App::history(self))) { | |
| - ++added; | |
| - } | |
| + if (appendRow(App::history(Auth().user()))) { | |
| + ++added; | |
| } | |
| } | |
| added += appendList(App::main()->dialogsList()); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -93,12 +93,12 @@ | |
| Ui::Checkbox *signatures = nullptr; | |
| }; | |
| struct Saving { | |
| - base::optional<QString> username; | |
| - base::optional<QString> title; | |
| - base::optional<QString> description; | |
| - base::optional<bool> hiddenPreHistory; | |
| - base::optional<bool> signatures; | |
| - base::optional<bool> everyoneInvites; | |
| + std::optional<QString> username; | |
| + std::optional<QString> title; | |
| + std::optional<QString> description; | |
| + std::optional<bool> hiddenPreHistory; | |
| + std::optional<bool> signatures; | |
| + std::optional<bool> everyoneInvites; | |
| }; | |
| Fn<QString()> computeTitle() const; | |
| @@ -143,7 +143,7 @@ | |
| void revokeInviteLink(); | |
| void exportInviteLink(const QString &confirmation); | |
| - base::optional<Saving> validate() const; | |
| + std::optional<Saving> validate() const; | |
| bool validateUsername(Saving &to) const; | |
| bool validateTitle(Saving &to) const; | |
| bool validateDescription(Saving &to) const; | |
| @@ -1087,7 +1087,7 @@ | |
| } | |
| } | |
| -base::optional<Controller::Saving> Controller::validate() const { | |
| +std::optional<Controller::Saving> Controller::validate() const { | |
| auto result = Saving(); | |
| if (validateUsername(result) | |
| && validateTitle(result) | |
| @@ -1391,9 +1391,7 @@ | |
| ? _controls.photo->takeResultImage() | |
| : QImage(); | |
| if (!image.isNull()) { | |
| - Messenger::Instance().uploadProfilePhoto( | |
| - std::move(image), | |
| - _peer->id); | |
| + Auth().api().uploadPeerPhoto(_peer, std::move(image)); | |
| } | |
| _box->closeBox(); | |
| } | |
| @@ -1442,7 +1440,7 @@ | |
| ) | rpl::start_with_next([this](int height) { | |
| setDimensions(st::boxWideWidth, height); | |
| }, content->lifetime()); | |
| - setInnerWidget(object_ptr<Ui::IgnoreMargins>( | |
| + setInnerWidget(object_ptr<Ui::OverrideMargins>( | |
| this, | |
| std::move(content))); | |
| Ui::AttachAsChild(this, std::move(controller)); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/report_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/report_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/report_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/report_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -44,7 +44,7 @@ | |
| bool reportFail(const RPCError &error); | |
| not_null<PeerData*> _peer; | |
| - base::optional<MessageIdsList> _ids; | |
| + std::optional<MessageIdsList> _ids; | |
| std::shared_ptr<Ui::RadioenumGroup<Reason>> _reasonGroup; | |
| object_ptr<Ui::Radioenum<Reason>> _reasonSpam = { nullptr }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/self_destruction_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/self_destruction_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/self_destruction_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/self_destruction_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,59 +10,109 @@ | |
| #include "lang/lang_keys.h" | |
| #include "ui/widgets/checkbox.h" | |
| #include "ui/widgets/labels.h" | |
| +#include "apiwrap.h" | |
| +#include "auth_session.h" | |
| #include "styles/style_boxes.h" | |
| +SelfDestructionBox::SelfDestructionBox( | |
| + QWidget*, | |
| + rpl::producer<int> preloaded) | |
| +: _ttlValues{ 30, 90, 180, 365 } | |
| +, _loading( | |
| + this, | |
| + lang(lng_contacts_loading), | |
| + Ui::FlatLabel::InitType::Simple, | |
| + st::membersAbout) { | |
| + std::move( | |
| + preloaded | |
| + ) | rpl::take( | |
| + 1 | |
| + ) | rpl::start_with_next([=](int days) { | |
| + gotCurrent(days); | |
| + }, lifetime()); | |
| +} | |
| + | |
| +void SelfDestructionBox::gotCurrent(int days) { | |
| + Expects(!_ttlValues.empty()); | |
| + | |
| + _loading.destroy(); | |
| + | |
| + auto daysAdjusted = _ttlValues[0]; | |
| + for (const auto value : _ttlValues) { | |
| + if (qAbs(days - value) < qAbs(days - daysAdjusted)) { | |
| + daysAdjusted = value; | |
| + } | |
| + } | |
| + _ttlGroup = std::make_shared<Ui::RadiobuttonGroup>(daysAdjusted); | |
| + | |
| + if (_prepared) { | |
| + showContent(); | |
| + } | |
| +} | |
| + | |
| +void SelfDestructionBox::showContent() { | |
| + auto y = st::boxOptionListPadding.top(); | |
| + _description.create( | |
| + this, | |
| + lang(lng_self_destruct_description), | |
| + Ui::FlatLabel::InitType::Simple, | |
| + st::boxLabel); | |
| + _description->moveToLeft(st::boxPadding.left(), y); | |
| + y += _description->height() + st::boxMediumSkip; | |
| + | |
| + const auto count = int(_ttlValues.size()); | |
| + for (const auto value : _ttlValues) { | |
| + const auto button = Ui::CreateChild<Ui::Radiobutton>( | |
| + this, | |
| + _ttlGroup, | |
| + value, | |
| + DaysLabel(value), | |
| + st::langsButton); | |
| + button->moveToLeft(st::boxPadding.left(), y); | |
| + y += button->heightNoMargins() + st::boxOptionListSkip; | |
| + } | |
| + showChildren(); | |
| + | |
| + clearButtons(); | |
| + addButton(langFactory(lng_settings_save), [=] { | |
| + Auth().api().saveSelfDestruct(_ttlGroup->value()); | |
| + closeBox(); | |
| + }); | |
| + addButton(langFactory(lng_cancel), [=] { closeBox(); }); | |
| +} | |
| + | |
| +QString SelfDestructionBox::DaysLabel(int days) { | |
| + return (days > 364) | |
| + ? lng_self_destruct_years(lt_count, days / 365) | |
| + : lng_self_destruct_months(lt_count, qMax(days / 30, 1)); | |
| +} | |
| + | |
| void SelfDestructionBox::prepare() { | |
| setTitle(langFactory(lng_self_destruct_title)); | |
| - _ttlValues = { 30, 90, 180, 365 }; | |
| - | |
| - auto fake = object_ptr<Ui::FlatLabel>(this, lang(lng_self_destruct_description), Ui::FlatLabel::InitType::Simple, st::boxLabel); | |
| - auto boxHeight = st::boxOptionListPadding.top() | |
| + auto fake = object_ptr<Ui::FlatLabel>( | |
| + this, | |
| + lang(lng_self_destruct_description), | |
| + Ui::FlatLabel::InitType::Simple, | |
| + st::boxLabel); | |
| + const auto boxHeight = st::boxOptionListPadding.top() | |
| + fake->height() + st::boxMediumSkip | |
| - + _ttlValues.size() * (st::defaultRadio.diameter + st::boxOptionListSkip) - st::boxOptionListSkip | |
| + + (_ttlValues.size() | |
| + * (st::defaultRadio.diameter + st::boxOptionListSkip)) | |
| + - st::boxOptionListSkip | |
| + st::boxOptionListPadding.bottom() + st::boxPadding.bottom(); | |
| fake.destroy(); | |
| setDimensions(st::boxWidth, boxHeight); | |
| - auto loading = object_ptr<Ui::FlatLabel>(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout); | |
| - loading->moveToLeft((st::boxWidth - loading->width()) / 2, boxHeight / 3); | |
| - | |
| addButton(langFactory(lng_cancel), [this] { closeBox(); }); | |
| - request(MTPaccount_GetAccountTTL()).done([this, loading = std::move(loading)](const MTPAccountDaysTTL &result) mutable { | |
| - Expects(result.type() == mtpc_accountDaysTTL); | |
| - Expects(!_ttlValues.empty()); | |
| - | |
| - loading.destroy(); | |
| - auto y = st::boxOptionListPadding.top(); | |
| - _description.create(this, lang(lng_self_destruct_description), Ui::FlatLabel::InitType::Simple, st::boxLabel); | |
| - _description->moveToLeft(st::boxPadding.left(), y); | |
| - y += _description->height() + st::boxMediumSkip; | |
| - | |
| - auto current = result.c_accountDaysTTL().vdays.v; | |
| - auto currentAdjusted = _ttlValues[0]; | |
| - for (auto days : _ttlValues) { | |
| - if (qAbs(current - days) < qAbs(current - currentAdjusted)) { | |
| - currentAdjusted = days; | |
| - } | |
| - } | |
| - auto group = std::make_shared<Ui::RadiobuttonGroup>(currentAdjusted); | |
| - auto count = int(_ttlValues.size()); | |
| - _options.reserve(count); | |
| - for (auto days : _ttlValues) { | |
| - _options.emplace_back(this, group, days, (days > 364) ? lng_self_destruct_years(lt_count, days / 365) : lng_self_destruct_months(lt_count, qMax(days / 30, 1)), st::langsButton); | |
| - _options.back()->moveToLeft(st::boxPadding.left(), y); | |
| - y += _options.back()->heightNoMargins() + st::boxOptionListSkip; | |
| - } | |
| - showChildren(); | |
| - | |
| - clearButtons(); | |
| - addButton(langFactory(lng_settings_save), [this, group] { | |
| - MTP::send(MTPaccount_SetAccountTTL(MTP_accountDaysTTL(MTP_int(group->value())))); | |
| - closeBox(); | |
| - }); | |
| - addButton(langFactory(lng_cancel), [this] { closeBox(); }); | |
| - }).send(); | |
| + if (_loading) { | |
| + _loading->moveToLeft( | |
| + (st::boxWidth - _loading->width()) / 2, | |
| + boxHeight / 3); | |
| + _prepared = true; | |
| + } else { | |
| + showContent(); | |
| + } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/self_destruction_box.h work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/self_destruction_box.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/self_destruction_box.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/self_destruction_box.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -17,19 +17,22 @@ | |
| } // namespace Ui | |
| class SelfDestructionBox : public BoxContent, private MTP::Sender { | |
| - Q_OBJECT | |
| - | |
| public: | |
| - SelfDestructionBox(QWidget*) { | |
| - } | |
| + SelfDestructionBox(QWidget*, rpl::producer<int> preloaded); | |
| + | |
| + static QString DaysLabel(int days); | |
| protected: | |
| void prepare() override; | |
| private: | |
| + void gotCurrent(int days); | |
| + void showContent(); | |
| + | |
| + bool _prepared = false; | |
| std::vector<int> _ttlValues; | |
| object_ptr<Ui::FlatLabel> _description = { nullptr }; | |
| + object_ptr<Ui::FlatLabel> _loading; | |
| std::shared_ptr<Ui::RadiobuttonGroup> _ttlGroup; | |
| - std::vector<object_ptr<Ui::Radiobutton>> _options; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/send_files_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/send_files_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/send_files_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/send_files_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -136,7 +136,7 @@ | |
| void drawSimpleFrame(Painter &p, QRect to, QSize size) const; | |
| Ui::GroupMediaLayout _layout; | |
| - base::optional<QRect> _animateFromGeometry; | |
| + std::optional<QRect> _animateFromGeometry; | |
| const QImage _fullPreview; | |
| const int _shrinkSize = 0; | |
| QPixmap _albumImage; | |
| @@ -229,7 +229,7 @@ | |
| } | |
| void AlbumThumb::resetLayoutAnimation() { | |
| - _animateFromGeometry = base::none; | |
| + _animateFromGeometry = std::nullopt; | |
| } | |
| void AlbumThumb::animateLayoutToInitial() { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/share_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/share_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/share_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/share_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -294,10 +294,9 @@ | |
| setAttribute(Qt::WA_OpaquePaintEvent); | |
| const auto dialogs = App::main()->dialogsList(); | |
| - if (const auto self = App::self()) { | |
| - if (_filterCallback(App::self())) { | |
| - _chatsIndexed->addToEnd(App::history(self)); | |
| - } | |
| + const auto self = Auth().user(); | |
| + if (_filterCallback(self)) { | |
| + _chatsIndexed->addToEnd(App::history(self)); | |
| } | |
| for (const auto row : dialogs->all()) { | |
| if (const auto history = row->history()) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/stickers_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/stickers_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/stickers_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/stickers_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -659,7 +659,9 @@ | |
| void StickersBox::Inner::paintEvent(QPaintEvent *e) { | |
| Painter p(this); | |
| - _a_shifting.step(); | |
| + if (_a_shifting.animating()) { | |
| + _a_shifting.step(); | |
| + } | |
| auto clip = e->rect(); | |
| auto ms = getms(); | |
| @@ -1204,6 +1206,9 @@ | |
| } | |
| void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) { | |
| + if (anim::Disabled()) { | |
| + ms += st::stickersRowDuration; | |
| + } | |
| auto animating = false; | |
| auto updateMin = -1; | |
| auto updateMax = 0; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/username_box.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/username_box.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/boxes/username_box.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/boxes/username_box.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,6 +16,7 @@ | |
| #include "ui/toast/toast.h" | |
| #include "styles/style_boxes.h" | |
| #include "messenger.h" | |
| +#include "auth_session.h" | |
| namespace { | |
| @@ -24,14 +25,21 @@ | |
| } // namespace | |
| UsernameBox::UsernameBox(QWidget*) | |
| -: _username(this, st::defaultInputField, [] { return qsl("@username"); }, App::self()->username, false) | |
| +: _username( | |
| + this, | |
| + st::defaultInputField, | |
| + [] { return qsl("@username"); }, | |
| + Auth().user()->username, | |
| + false) | |
| , _link(this, QString(), st::boxLinkButton) | |
| , _about(st::boxWidth - st::usernamePadding.left()) | |
| , _checkTimer(this) { | |
| } | |
| void UsernameBox::prepare() { | |
| - _goodText = App::self()->username.isEmpty() ? QString() : lang(lng_username_available); | |
| + _goodText = Auth().user()->username.isEmpty() | |
| + ? QString() | |
| + : lang(lng_username_available); | |
| setTitle(langFactory(lng_username_title)); | |
| @@ -170,9 +178,14 @@ | |
| if (MTP::isDefaultHandledError(error)) return false; | |
| _saveRequestId = 0; | |
| - QString err(error.type()); | |
| - if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == App::self()->username) { | |
| - App::self()->setName(TextUtilities::SingleLine(App::self()->firstName), TextUtilities::SingleLine(App::self()->lastName), TextUtilities::SingleLine(App::self()->nameOrPhone), TextUtilities::SingleLine(_sentUsername)); | |
| + const auto self = Auth().user(); | |
| + const auto err = error.type(); | |
| + if (err == qstr("USERNAME_NOT_MODIFIED") || _sentUsername == self->username) { | |
| + self->setName( | |
| + TextUtilities::SingleLine(self->firstName), | |
| + TextUtilities::SingleLine(self->lastName), | |
| + TextUtilities::SingleLine(self->nameOrPhone), | |
| + TextUtilities::SingleLine(_sentUsername)); | |
| closeBox(); | |
| return true; | |
| } else if (err == qstr("USERNAME_INVALID")) { | |
| @@ -194,8 +207,13 @@ | |
| void UsernameBox::onCheckDone(const MTPBool &result) { | |
| _checkRequestId = 0; | |
| - QString newError = (mtpIsTrue(result) || _checkUsername == App::self()->username) ? QString() : lang(lng_username_occupied); | |
| - QString newGood = newError.isEmpty() ? lang(lng_username_available) : QString(); | |
| + const auto newError = (mtpIsTrue(result) | |
| + || _checkUsername == Auth().user()->username) | |
| + ? QString() | |
| + : lang(lng_username_occupied); | |
| + const auto newGood = newError.isEmpty() | |
| + ? lang(lng_username_available) | |
| + : QString(); | |
| if (_errorText != newError || _goodText != newGood) { | |
| _errorText = newError; | |
| _goodText = newGood; | |
| @@ -212,7 +230,7 @@ | |
| _errorText = lang(lng_username_invalid); | |
| update(); | |
| return true; | |
| - } else if (err == qstr("USERNAME_OCCUPIED") && _checkUsername != App::self()->username) { | |
| + } else if (err == qstr("USERNAME_OCCUPIED") && _checkUsername != Auth().user()->username) { | |
| _errorText = lang(lng_username_occupied); | |
| update(); | |
| return true; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/calls/calls_call.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/calls/calls_call.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/calls/calls_call.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/calls/calls_call.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -119,6 +119,8 @@ | |
| reset(); | |
| } | |
| +Call::Delegate::~Delegate() = default; | |
| + | |
| Call::Call( | |
| not_null<Delegate*> delegate, | |
| not_null<UserData*> user, | |
| @@ -534,14 +536,16 @@ | |
| if (Logs::DebugEnabled()) { | |
| auto callLogFolder = cWorkingDir() + qsl("DebugLogs"); | |
| auto callLogPath = callLogFolder + qsl("/last_call_log.txt"); | |
| - auto callLogNative = QFile::encodeName(QDir::toNativeSeparators(callLogPath)); | |
| - auto callLogBytesSrc = bytes::make_span(callLogNative); | |
| - auto callLogBytesDst = bytes::make_span(config.logFilePath); | |
| - if (callLogBytesSrc.size() + 1 <= callLogBytesDst.size()) { // +1 - zero-terminator | |
| - QFile(callLogPath).remove(); | |
| - QDir().mkpath(callLogFolder); | |
| - bytes::copy(callLogBytesDst, callLogBytesSrc); | |
| - } | |
| + auto callLogNative = QDir::toNativeSeparators(callLogPath); | |
| +#ifdef Q_OS_WIN | |
| + config.logFilePath = callLogNative.toStdWString(); | |
| +#else // Q_OS_WIN | |
| + const auto callLogUtf = QFile::encodeName(callLogNative); | |
| + config.logFilePath.resize(callLogUtf.size()); | |
| + ranges::copy(callLogUtf, config.logFilePath.begin()); | |
| +#endif // Q_OS_WIN | |
| + QFile(callLogPath).remove(); | |
| + QDir().mkpath(callLogFolder); | |
| } | |
| const auto &protocol = call.vprotocol.c_phoneCallProtocol(); | |
| @@ -570,7 +574,20 @@ | |
| _controller->SetMicMute(_mute); | |
| } | |
| _controller->implData = static_cast<void*>(this); | |
| - _controller->SetRemoteEndpoints(endpoints, true, protocol.vmax_layer.v); | |
| + const auto p2p = [&] { | |
| + switch (Auth().settings().callsPeerToPeer()) { | |
| + case PeerToPeer::DefaultContacts: | |
| + case PeerToPeer::Contacts: | |
| + return _user->isContact(); | |
| + case PeerToPeer::DefaultEveryone: | |
| + case PeerToPeer::Everyone: | |
| + return true; | |
| + case PeerToPeer::Nobody: | |
| + return false; | |
| + } | |
| + Unexpected("Calls::PeerToPeer value in Auth().settings()."); | |
| + }(); | |
| + _controller->SetRemoteEndpoints(endpoints, p2p, protocol.vmax_layer.v); | |
| _controller->SetConfig(config); | |
| _controller->SetEncryptionKey(reinterpret_cast<char*>(_authKey.data()), (_type == Type::Outgoing)); | |
| _controller->SetCallbacks(callbacks); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/calls/calls_call.h work/tdesktop-1.4.0/Telegram/SourceFiles/calls/calls_call.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/calls/calls_call.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/calls/calls_call.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -47,6 +47,8 @@ | |
| }; | |
| virtual void playSound(Sound sound) = 0; | |
| + virtual ~Delegate(); | |
| + | |
| }; | |
| static constexpr auto kSoundSampleMs = 100; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/calls/calls_instance.h work/tdesktop-1.4.0/Telegram/SourceFiles/calls/calls_instance.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/calls/calls_instance.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/calls/calls_instance.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -18,6 +18,14 @@ | |
| namespace Calls { | |
| +enum class PeerToPeer { | |
| + DefaultContacts, | |
| + DefaultEveryone, | |
| + Everyone, | |
| + Contacts, | |
| + Nobody, | |
| +}; | |
| + | |
| class Panel; | |
| class Instance : private MTP::Sender, private Call::Delegate, private base::Subscriber { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -11,6 +11,9 @@ | |
| #include "styles/style_chat_helpers.h" | |
| #include "ui/widgets/shadow.h" | |
| #include "lang/lang_keys.h" | |
| +#include "emoji_suggestions_data.h" | |
| +#include "emoji_suggestions_helper.h" | |
| +#include "facades.h" | |
| namespace ChatHelpers { | |
| @@ -460,7 +463,7 @@ | |
| if (info.section > 0 && r.top() < info.rowsTop) { | |
| p.setFont(st::emojiPanHeaderFont); | |
| p.setPen(st::emojiPanHeaderFg); | |
| - p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, info.top + st::emojiPanHeaderTop, width(), lang(LangKey(lng_emoji_category0 + info.section))); | |
| + p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, info.top + st::emojiPanHeaderTop, width(), lang(LangKey(lng_emoji_category1 + info.section - 1))); | |
| } | |
| if (r.top() + r.height() > info.rowsTop) { | |
| ensureLoaded(info.section); | |
| @@ -667,6 +670,28 @@ | |
| return static_cast<Section>(sectionInfoByOffset(yOffset).section); | |
| } | |
| +QString EmojiListWidget::tooltipText() const { | |
| + const auto &replacements = Ui::Emoji::internal::GetAllReplacements(); | |
| + const auto section = (_selected / MatrixRowShift); | |
| + const auto sel = _selected % MatrixRowShift; | |
| + if (_selected >= 0 && section < kEmojiSectionCount && sel < _emoji[section].size()) { | |
| + const auto emoji = _emoji[section][sel]; | |
| + const auto text = emoji->text(); | |
| + // find the replacement belonging to the emoji | |
| + const auto it = ranges::find_if(replacements, [&text](auto &one) { | |
| + return text == Ui::Emoji::QStringFromUTF16(one.emoji); | |
| + }); | |
| + if (it != replacements.end()) { | |
| + return Ui::Emoji::QStringFromUTF16(it->replacement); | |
| + } | |
| + } | |
| + return ""; | |
| +} | |
| + | |
| +QPoint EmojiListWidget::tooltipPos() const { | |
| + return _lastMousePos; | |
| +} | |
| + | |
| TabbedSelector::InnerFooter *EmojiListWidget::getFooter() const { | |
| return _footer; | |
| } | |
| @@ -729,6 +754,10 @@ | |
| _selected = newSelected; | |
| updateSelected(); | |
| + if (_selected >= 0 && Global::SuggestEmoji()) { | |
| + Ui::Tooltip::Show(1000, this); | |
| + } | |
| + | |
| setCursor((_selected >= 0) ? style::cur_pointer : style::cur_default); | |
| if (_selected >= 0 && !_picker->isHidden()) { | |
| if (_selected != _pickerSel) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,6 +8,7 @@ | |
| #pragma once | |
| #include "chat_helpers/tabbed_selector.h" | |
| +#include "ui/widgets/tooltip.h" | |
| namespace Window { | |
| class Controller; | |
| @@ -74,7 +75,7 @@ | |
| }; | |
| -class EmojiListWidget : public TabbedSelector::Inner { | |
| +class EmojiListWidget : public TabbedSelector::Inner, public Ui::AbstractTooltipShower { | |
| Q_OBJECT | |
| public: | |
| @@ -89,6 +90,10 @@ | |
| void showEmojiSection(Section section); | |
| Section currentSection(int yOffset) const; | |
| + // Ui::AbstractTooltipShower interface. | |
| + QString tooltipText() const override; | |
| + QPoint tooltipPos() const override; | |
| + | |
| public slots: | |
| void onShowPicker(); | |
| void onPickerHidden(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/message_field.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/message_field.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/message_field.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/message_field.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -74,7 +74,7 @@ | |
| }; | |
| //bool ValidateUrl(const QString &value) { | |
| -// const auto match = TextUtilities::RegExpDomain().match(value); | |
| +// const auto match = qthelp::RegExpDomain().match(value); | |
| // if (!match.hasMatch() || match.capturedStart() != 0) { | |
| // return false; | |
| // } | |
| @@ -596,7 +596,7 @@ | |
| const auto len = text.size(); | |
| const QChar *start = text.unicode(), *end = start + text.size(); | |
| for (auto offset = 0, matchOffset = offset; offset < len;) { | |
| - auto m = TextUtilities::RegExpDomain().match(text, matchOffset); | |
| + auto m = qthelp::RegExpDomain().match(text, matchOffset); | |
| if (!m.hasMatch()) break; | |
| auto domainOffset = m.capturedStart(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -653,6 +653,9 @@ | |
| } | |
| void StickersListWidget::Footer::step_icons(TimeMs ms, bool timer) { | |
| + if (anim::Disabled()) { | |
| + ms += st::stickerIconMove; | |
| + } | |
| if (_iconsStartAnim) { | |
| auto dt = (ms - _iconsStartAnim) / float64(st::stickerIconMove); | |
| if (dt >= 1) { | |
| @@ -1495,7 +1498,7 @@ | |
| _previewTimer.stop(); | |
| auto pressed = _pressed; | |
| - setPressed(base::none); | |
| + setPressed(std::nullopt); | |
| if (pressed != _selected) { | |
| update(); | |
| } | |
| @@ -1649,8 +1652,8 @@ | |
| } | |
| void StickersListWidget::clearSelection() { | |
| - setPressed(base::none); | |
| - setSelected(base::none); | |
| + setPressed(std::nullopt); | |
| + setSelected(std::nullopt); | |
| update(); | |
| } | |
| @@ -2055,7 +2058,7 @@ | |
| return; | |
| } | |
| - auto newSelected = OverState { base::none }; | |
| + auto newSelected = OverState { std::nullopt }; | |
| auto p = mapFromGlobal(_lastMousePosition); | |
| if (!rect().contains(p) | |
| || p.y() < getVisibleTop() || p.y() >= getVisibleBottom() | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/stickers.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/stickers.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/stickers.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/stickers.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -176,9 +176,17 @@ | |
| LayerOption::KeepOther); | |
| } | |
| -bool IsFaved(not_null<DocumentData*> document) { | |
| - auto it = Auth().data().stickerSets().constFind(FavedSetId); | |
| - return (it != Auth().data().stickerSets().cend()) && it->stickers.contains(document); | |
| +bool IsFaved(not_null<const DocumentData*> document) { | |
| + const auto it = Auth().data().stickerSets().constFind(FavedSetId); | |
| + if (it == Auth().data().stickerSets().cend()) { | |
| + return false; | |
| + } | |
| + for (const auto sticker : it->stickers) { | |
| + if (sticker == document) { | |
| + return true; | |
| + } | |
| + } | |
| + return false; | |
| } | |
| void CheckFavedLimit(Set &set) { | |
| @@ -231,7 +239,7 @@ | |
| void RequestSetToPushFaved(not_null<DocumentData*> document); | |
| -void SetIsFaved(not_null<DocumentData*> document, base::optional<std::vector<not_null<EmojiPtr>>> emojiList = base::none) { | |
| +void SetIsFaved(not_null<DocumentData*> document, std::optional<std::vector<not_null<EmojiPtr>>> emojiList = std::nullopt) { | |
| auto &sets = Auth().data().stickerSetsRef(); | |
| auto it = sets.find(FavedSetId); | |
| if (it == sets.end()) { | |
| @@ -817,17 +825,17 @@ | |
| }) | ranges::to_vector; | |
| } | |
| -base::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet( | |
| +std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet( | |
| not_null<DocumentData*> document) { | |
| if (auto sticker = document->sticker()) { | |
| auto &inputSet = sticker->set; | |
| if (inputSet.type() != mtpc_inputStickerSetID) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto &sets = Auth().data().stickerSets(); | |
| auto it = sets.constFind(inputSet.c_inputStickerSetID().vid.v); | |
| if (it == sets.cend()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto result = std::vector<not_null<EmojiPtr>>(); | |
| for (auto i = it->emoji.cbegin(), e = it->emoji.cend(); i != e; ++i) { | |
| @@ -836,11 +844,11 @@ | |
| } | |
| } | |
| if (result.empty()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return std::move(result); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| Set *FeedSet(const MTPDstickerSet &set) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/stickers.h work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/stickers.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/chat_helpers/stickers.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/chat_helpers/stickers.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -69,7 +69,7 @@ | |
| bool ApplyArchivedResultFake(); // For testing. | |
| void InstallLocally(uint64 setId); | |
| void UndoInstallLocally(uint64 setId); | |
| -bool IsFaved(not_null<DocumentData*> document); | |
| +bool IsFaved(not_null<const DocumentData*> document); | |
| void SetFaved(not_null<DocumentData*> document, bool faved); | |
| void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash); | |
| @@ -89,7 +89,7 @@ | |
| std::vector<not_null<DocumentData*>> GetListByEmoji( | |
| not_null<EmojiPtr> emoji, | |
| uint64 seed); | |
| -base::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet( | |
| +std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet( | |
| not_null<DocumentData*> document); | |
| Set *FeedSet(const MTPDstickerSet &data); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/config.h work/tdesktop-1.4.0/Telegram/SourceFiles/config.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/config.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/config.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -186,7 +186,7 @@ | |
| -----END RSA PUBLIC KEY-----\ | |
| "; | |
| -static const char *UpdatesPublicAlphaKey = "\ | |
| +static const char *UpdatesPublicBetaKey = "\ | |
| -----BEGIN RSA PUBLIC KEY-----\n\ | |
| MIGJAoGBALWu9GGs0HED7KG7BM73CFZ6o0xufKBRQsdnq3lwA8nFQEvmdu+g/I1j\n\ | |
| 0LQ+0IQO7GW4jAgzF/4+soPDb6uHQeNFrlVx1JS9DZGhhjZ5rf65yg11nTCIHZCG\n\ | |
| @@ -205,14 +205,14 @@ | |
| #error "Only little endian is supported!" | |
| #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN | |
| -#ifndef BETA_VERSION_MACRO | |
| -#error "Beta version macro is not defined." | |
| +#ifndef ALPHA_VERSION_MACRO | |
| +#error "Alpha version macro is not defined." | |
| #endif | |
| -#if (defined CUSTOM_API_ID) && (BETA_VERSION_MACRO > 0ULL) | |
| -#include "../../../TelegramPrivate/beta_private.h" // private key for downloading closed betas | |
| +#if (defined CUSTOM_API_ID) && (ALPHA_VERSION_MACRO > 0ULL) | |
| +#include "../../../TelegramPrivate/alpha_private.h" // private key for downloading closed alphas | |
| #else | |
| -static const char *BetaPrivateKey = ""; | |
| +static const char *AlphaPrivateKey = ""; | |
| #endif | |
| extern QString gKeyFile; | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core: basic_types.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/changelogs.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/changelogs.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/changelogs.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/changelogs.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,7 +16,7 @@ | |
| namespace Core { | |
| namespace { | |
| -std::map<int, const char*> AlphaLogs() { | |
| +std::map<int, const char*> BetaLogs() { | |
| return { | |
| { | |
| 1002024, | |
| @@ -40,7 +40,25 @@ | |
| "\xE2\x80\x94 You can now assign custom themes " | |
| "as night and day themes to quickly switch between them." | |
| - } | |
| + }, | |
| + { | |
| + 1003015, | |
| + "\xE2\x80\x94 Improved local caching " | |
| + "for images and GIF animations.\n" | |
| + | |
| + "\xE2\x80\x94 Control how much disk space is used by the cache " | |
| + "and for how long the cached files are stored." | |
| + }, | |
| + { | |
| + 1003017, | |
| + "\xE2\x80\x94 Fully redisigned Settings section.\n" | |
| + | |
| + "\xE2\x80\x94 New theme selector in Chat Settings.\n" | |
| + "\xE2\x80\x94 New settings: Peer-to-Peer settings for calls, " | |
| + "disable animations for low performance computers.\n" | |
| + | |
| + "\xE2\x80\x94 Various other improvements." | |
| + }, | |
| }; | |
| } | |
| @@ -110,8 +128,8 @@ | |
| } | |
| void Changelogs::addLocalLogs() { | |
| - if (cAlphaVersion() || cBetaVersion()) { | |
| - addAlphaLogs(); | |
| + if (AppBetaVersion || cAlphaVersion()) { | |
| + addBetaLogs(); | |
| } | |
| if (!_addedSomeLocal) { | |
| const auto text = lng_new_version_wrap( | |
| @@ -128,20 +146,19 @@ | |
| void Changelogs::addLocalLog(const QString &text) { | |
| auto textWithEntities = TextWithEntities{ text }; | |
| TextUtilities::ParseEntities(textWithEntities, TextParseLinks); | |
| - App::wnd()->serviceNotification( | |
| + _session->data().serviceNotification( | |
| textWithEntities, | |
| - MTP_messageMediaEmpty(), | |
| - unixtime()); | |
| + MTP_messageMediaEmpty()); | |
| _addedSomeLocal = true; | |
| }; | |
| -void Changelogs::addAlphaLogs() { | |
| - for (const auto[version, changes] : AlphaLogs()) { | |
| - addAlphaLog(version, changes); | |
| +void Changelogs::addBetaLogs() { | |
| + for (const auto[version, changes] : BetaLogs()) { | |
| + addBetaLog(version, changes); | |
| } | |
| } | |
| -void Changelogs::addAlphaLog(int changeVersion, const char *changes) { | |
| +void Changelogs::addBetaLog(int changeVersion, const char *changes) { | |
| if (_oldVersion >= changeVersion) { | |
| return; | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/changelogs.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/changelogs.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/changelogs.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/changelogs.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -24,8 +24,8 @@ | |
| void requestCloudLogs(); | |
| void addLocalLogs(); | |
| void addLocalLog(const QString &text); | |
| - void addAlphaLogs(); | |
| - void addAlphaLog(int changeVersion, const char *changes); | |
| + void addBetaLogs(); | |
| + void addBetaLog(int changeVersion, const char *changes); | |
| const not_null<AuthSession*> _session; | |
| const int _oldVersion = 0; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/core_cloud_password.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/core_cloud_password.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/core_cloud_password.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/core_cloud_password.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -157,7 +157,7 @@ | |
| } | |
| bytes::vector ComputeHash( | |
| - base::none_type, | |
| + std::nullopt_t, | |
| bytes::const_span password) { | |
| Unexpected("Bad secure secret algorithm."); | |
| } | |
| @@ -203,7 +203,7 @@ | |
| CloudPasswordAlgo ValidateNewCloudPasswordAlgo(CloudPasswordAlgo &&parsed) { | |
| if (!parsed.is<CloudPasswordAlgoModPow>()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto &value = parsed.get_unchecked<CloudPasswordAlgoModPow>(); | |
| const auto already = value.salt1.size(); | |
| @@ -219,7 +219,7 @@ | |
| MTP_bytes(data.salt2), | |
| MTP_int(data.g), | |
| MTP_bytes(data.p)); | |
| - }, [](base::none_type) { | |
| + }, [](std::nullopt_t) { | |
| return MTP_passwordKdfAlgoUnknown(); | |
| }); | |
| } | |
| @@ -233,7 +233,7 @@ | |
| bytes::const_span password) { | |
| return algo.match([&](const CloudPasswordAlgoModPow &data) { | |
| return ComputeHash(data, password); | |
| - }, [](base::none_type) -> bytes::vector { | |
| + }, [](std::nullopt_t) -> bytes::vector { | |
| Unexpected("Bad cloud password algorithm."); | |
| }); | |
| } | |
| @@ -243,7 +243,7 @@ | |
| bytes::const_span password) { | |
| return algo.match([&](const CloudPasswordAlgoModPow &data) { | |
| return ComputeDigest(data, password); | |
| - }, [](base::none_type) -> CloudPasswordDigest { | |
| + }, [](std::nullopt_t) -> CloudPasswordDigest { | |
| Unexpected("Bad cloud password algorithm."); | |
| }); | |
| } | |
| @@ -253,7 +253,7 @@ | |
| bytes::const_span hash) { | |
| return request.algo.match([&](const CloudPasswordAlgoModPow &data) { | |
| return ComputeCheck(request, data, hash); | |
| - }, [](base::none_type) -> CloudPasswordResult { | |
| + }, [](std::nullopt_t) -> CloudPasswordResult { | |
| Unexpected("Bad cloud password algorithm."); | |
| }); | |
| } | |
| @@ -274,7 +274,7 @@ | |
| SecureSecretAlgo ValidateNewSecureSecretAlgo(SecureSecretAlgo &&parsed) { | |
| if (!parsed.is<SecureSecretAlgoPBKDF2>()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto &value = parsed.get_unchecked<SecureSecretAlgoPBKDF2>(); | |
| const auto already = value.salt.size(); | |
| @@ -290,7 +290,7 @@ | |
| MTP_bytes(data.salt)); | |
| }, [](const SecureSecretAlgoSHA512 &data) { | |
| return MTP_securePasswordKdfAlgoSHA512(MTP_bytes(data.salt)); | |
| - }, [](base::none_type) { | |
| + }, [](std::nullopt_t) { | |
| return MTP_securePasswordKdfAlgoUnknown(); | |
| }); | |
| } | |
| @@ -303,4 +303,22 @@ | |
| }); | |
| } | |
| +CloudPasswordState ParseCloudPasswordState( | |
| + const MTPDaccount_password &data) { | |
| + auto result = CloudPasswordState(); | |
| + result.request = ParseCloudPasswordCheckRequest(data); | |
| + result.unknownAlgorithm = data.has_current_algo() && !result.request; | |
| + result.hasRecovery = data.is_has_recovery(); | |
| + result.notEmptyPassport = data.is_has_secure_values(); | |
| + result.hint = data.has_hint() ? qs(data.vhint) : QString(); | |
| + result.newPassword = ValidateNewCloudPasswordAlgo( | |
| + ParseCloudPasswordAlgo(data.vnew_algo)); | |
| + result.newSecureSecret = ValidateNewSecureSecretAlgo( | |
| + ParseSecureSecretAlgo(data.vnew_secure_algo)); | |
| + result.unconfirmedPattern = data.has_email_unconfirmed_pattern() | |
| + ? qs(data.vemail_unconfirmed_pattern) | |
| + : QString(); | |
| + return result; | |
| +} | |
| + | |
| } // namespace Core | |
| \ No newline at end of file | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/core_cloud_password.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/core_cloud_password.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/core_cloud_password.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/core_cloud_password.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -120,4 +120,18 @@ | |
| const SecureSecretAlgo &algo, | |
| bytes::const_span password); | |
| +struct CloudPasswordState { | |
| + CloudPasswordCheckRequest request; | |
| + bool unknownAlgorithm = false; | |
| + bool hasRecovery = false; | |
| + bool notEmptyPassport = false; | |
| + QString hint; | |
| + CloudPasswordAlgo newPassword; | |
| + SecureSecretAlgo newSecureSecret; | |
| + QString unconfirmedPattern; | |
| +}; | |
| + | |
| +CloudPasswordState ParseCloudPasswordState( | |
| + const MTPDaccount_password &data); | |
| + | |
| } // namespace Core | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/crash_report_window.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/crash_report_window.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/crash_report_window.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/crash_report_window.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -228,7 +228,7 @@ | |
| : std::make_unique<UpdaterData>(this)) { | |
| excludeReportUsername(); | |
| - if (!cAlphaVersion() && !cBetaVersion()) { // currently accept crash reports only from testers | |
| + if (!cInstallBetaVersion() && !cAlphaVersion()) { // currently accept crash reports only from testers | |
| _sendingState = SendingNoReport; | |
| } | |
| if (_sendingState != SendingNoReport) { | |
| @@ -281,7 +281,7 @@ | |
| } | |
| if (_sendingState != SendingNoReport) { | |
| QString version = getReportField(qstr("version"), qstr("Version:")); | |
| - QString current = cBetaVersion() ? qsl("-%1").arg(cBetaVersion()) : QString::number(AppVersion); | |
| + QString current = cAlphaVersion() ? qsl("-%1").arg(cAlphaVersion()) : QString::number(AppVersion); | |
| if (version != current) { // currently don't accept crash reports from not current app version | |
| _sendingState = SendingNoReport; | |
| } | |
| @@ -418,7 +418,7 @@ | |
| QString data = lines.at(i).trimmed().mid(prefix.size()).trimmed(); | |
| if (name == qstr("version")) { | |
| - if (data.endsWith(qstr(" beta"))) { | |
| + if (data.endsWith(qstr(" alpha"))) { | |
| data = QString::number(-data.replace(QRegularExpression(qsl("[^\\d]")), "").toLongLong()); | |
| } else { | |
| data = QString::number(data.replace(QRegularExpression(qsl("[^\\d]")), "").toLongLong()); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/crash_reports.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/crash_reports.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/crash_reports.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/crash_reports.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -310,7 +310,7 @@ | |
| #ifndef TDESKTOP_DISABLE_CRASH_REPORTS | |
| ProcessAnnotations["Binary"] = cExeName().toUtf8().constData(); | |
| ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData(); | |
| - ProcessAnnotations["Version"] = (cBetaVersion() ? qsl("%1 beta").arg(cBetaVersion()) : (cAlphaVersion() ? qsl("%1 alpha") : qsl("%1")).arg(AppVersion)).toUtf8().constData(); | |
| + ProcessAnnotations["Version"] = (cAlphaVersion() ? qsl("%1 alpha").arg(cAlphaVersion()) : (AppBetaVersion ? qsl("%1 beta") : qsl("%1")).arg(AppVersion)).toUtf8().constData(); | |
| ProcessAnnotations["Launched"] = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss").toUtf8().constData(); | |
| ProcessAnnotations["Platform"] = cPlatformString().toUtf8().constData(); | |
| ProcessAnnotations["UserTag"] = QString::number(Sandbox::UserTag(), 16).toUtf8().constData(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/launcher.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/launcher.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/launcher.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/launcher.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -12,6 +12,7 @@ | |
| #include "core/crash_reports.h" | |
| #include "core/main_queue_processor.h" | |
| #include "core/update_checker.h" | |
| +#include "base/concurrent_timer.h" | |
| #include "application.h" | |
| namespace Core { | |
| @@ -220,7 +221,8 @@ | |
| gTestMode = parseResult.contains("-testmode"); | |
| Logs::SetDebugEnabled(parseResult.contains("-debug")); | |
| gManyInstance = parseResult.contains("-many"); | |
| - gKeyFile = parseResult.value("-key", QStringList()).join(QString()); | |
| + gKeyFile = parseResult.value("-key", {}).join(QString()).toLower(); | |
| + gKeyFile = gKeyFile.replace(QRegularExpression("[^a-z0-9\\-_]"), {}); | |
| gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart | |
| : parseResult.contains("-fixprevious") ? LaunchModeFixPrevious | |
| : parseResult.contains("-cleanup") ? LaunchModeCleanup | |
| @@ -228,8 +230,8 @@ | |
| gNoStartUpdate = parseResult.contains("-noupdate"); | |
| gStartToSettings = parseResult.contains("-tosettings"); | |
| gStartInTray = parseResult.contains("-startintray"); | |
| - gSendPaths = parseResult.value("-sendpath", QStringList()); | |
| - gWorkingDir = parseResult.value("-workdir", QStringList()).join(QString()); | |
| + gSendPaths = parseResult.value("-sendpath", {}); | |
| + gWorkingDir = parseResult.value("-workdir", {}).join(QString()); | |
| if (!gWorkingDir.isEmpty()) { | |
| if (QDir().exists(gWorkingDir)) { | |
| _customWorkingDir = true; | |
| @@ -237,11 +239,13 @@ | |
| gWorkingDir = QString(); | |
| } | |
| } | |
| - gStartUrl = parseResult.value("--", QStringList()).join(QString()); | |
| + gStartUrl = parseResult.value("--", {}).join(QString()); | |
| } | |
| int Launcher::executeApplication() { | |
| MainQueueProcessor processor; | |
| + base::ConcurrentTimerEnvironment environment; | |
| + | |
| Application app(this, _argc, _argv); | |
| return app.exec(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/launcher.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/launcher.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/launcher.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/launcher.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -41,10 +41,10 @@ | |
| void processArguments(); | |
| QStringList readArguments(int argc, char *argv[]) const; | |
| - virtual base::optional<QStringList> readArgumentsHook( | |
| + virtual std::optional<QStringList> readArgumentsHook( | |
| int argc, | |
| char *argv[]) const { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| void init(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/main_queue_processor.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/main_queue_processor.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/main_queue_processor.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/main_queue_processor.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -47,11 +47,17 @@ | |
| } | |
| } | |
| +void ProcessObservables() { | |
| + Global::RefHandleObservables().call(); | |
| +} | |
| + | |
| } // namespace | |
| MainQueueProcessor::MainQueueProcessor() { | |
| acquire(); | |
| crl::init_main_queue(ProcessMainQueue); | |
| + | |
| + base::InitObservables(ProcessObservables); | |
| } | |
| bool MainQueueProcessor::event(QEvent *event) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/main_queue_processor.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/main_queue_processor.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/main_queue_processor.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/main_queue_processor.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -12,7 +12,6 @@ | |
| class MainQueueProcessor : public QObject { | |
| public: | |
| MainQueueProcessor(); | |
| - | |
| ~MainQueueProcessor(); | |
| protected: | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/single_timer.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/single_timer.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/single_timer.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/single_timer.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,8 +7,6 @@ | |
| */ | |
| #pragma once | |
| -#include "core/basic_types.h" | |
| - | |
| class SingleTimer : public QTimer { // single shot timer with check | |
| Q_OBJECT | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/update_checker.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/update_checker.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/update_checker.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/update_checker.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,7 +16,10 @@ | |
| #include "mtproto/session.h" | |
| #include "mainwindow.h" | |
| #include "core/click_handler_types.h" | |
| -#include "settings/settings_widget.h" | |
| +#include "info/info_memento.h" | |
| +#include "info/settings/info_settings_widget.h" | |
| +#include "window/window_controller.h" | |
| +#include "settings/settings_intro.h" | |
| extern "C" { | |
| #include <openssl/rsa.h> | |
| @@ -155,12 +158,12 @@ | |
| void gotFailure(QNetworkReply::NetworkError e); | |
| void clearSentRequest(); | |
| bool handleResponse(const QByteArray &response); | |
| - base::optional<QString> parseOldResponse( | |
| + std::optional<QString> parseOldResponse( | |
| const QByteArray &response) const; | |
| - base::optional<QString> parseResponse(const QByteArray &response) const; | |
| + std::optional<QString> parseResponse(const QByteArray &response) const; | |
| QString validateLatestUrl( | |
| uint64 availableVersion, | |
| - bool isAvailableBeta, | |
| + bool isAvailableAlpha, | |
| QString url) const; | |
| std::unique_ptr<QNetworkAccessManager> _manager; | |
| @@ -259,14 +262,14 @@ | |
| const QString &username, | |
| Fn<void(const MTPInputChannel &channel)> callback); | |
| void gotMessage(const MTPmessages_Messages &result); | |
| - base::optional<FileLocation> parseMessage( | |
| + std::optional<FileLocation> parseMessage( | |
| const MTPmessages_Messages &result) const; | |
| - base::optional<FileLocation> parseText(const QByteArray &text) const; | |
| + std::optional<FileLocation> parseText(const QByteArray &text) const; | |
| FileLocation validateLatestLocation( | |
| uint64 availableVersion, | |
| const FileLocation &location) const; | |
| void gotFile(const MTPmessages_Messages &result); | |
| - base::optional<ParsedFile> parseFile( | |
| + std::optional<ParsedFile> parseFile( | |
| const MTPmessages_Messages &result) const; | |
| MtpWeak _mtp; | |
| @@ -388,25 +391,22 @@ | |
| return false; | |
| } | |
| - RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicAlphaKey : UpdatesPublicKey), -1), 0, 0, 0); | |
| + RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppBetaVersion ? UpdatesPublicBetaKey : UpdatesPublicKey), -1), 0, 0, 0); | |
| if (!pbKey) { | |
| LOG(("Update Error: cant read public rsa key!")); | |
| return false; | |
| } | |
| if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature | |
| RSA_free(pbKey); | |
| - if (cAlphaVersion() || cBetaVersion()) { // try other public key, if we are in alpha or beta version | |
| - pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicKey : UpdatesPublicAlphaKey), -1), 0, 0, 0); | |
| - if (!pbKey) { | |
| - LOG(("Update Error: cant read public rsa key!")); | |
| - return false; | |
| - } | |
| - if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature | |
| - RSA_free(pbKey); | |
| - LOG(("Update Error: bad RSA signature of update file!")); | |
| - return false; | |
| - } | |
| - } else { | |
| + | |
| + // try other public key, if we update from beta to stable or vice versa | |
| + pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppBetaVersion ? UpdatesPublicKey : UpdatesPublicBetaKey), -1), 0, 0, 0); | |
| + if (!pbKey) { | |
| + LOG(("Update Error: cant read public rsa key!")); | |
| + return false; | |
| + } | |
| + if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature | |
| + RSA_free(pbKey); | |
| LOG(("Update Error: bad RSA signature of update file!")); | |
| return false; | |
| } | |
| @@ -485,15 +485,15 @@ | |
| return false; | |
| } | |
| - quint64 betaVersion = 0; | |
| - if (version == 0x7FFFFFFF) { // beta version | |
| - stream >> betaVersion; | |
| + quint64 alphaVersion = 0; | |
| + if (version == 0x7FFFFFFF) { // alpha version | |
| + stream >> alphaVersion; | |
| if (stream.status() != QDataStream::Ok) { | |
| - LOG(("Update Error: cant read beta version from downloaded stream, status: %1").arg(stream.status())); | |
| + LOG(("Update Error: cant read alpha version from downloaded stream, status: %1").arg(stream.status())); | |
| return false; | |
| } | |
| - if (!cBetaVersion() || betaVersion <= cBetaVersion()) { | |
| - LOG(("Update Error: downloaded beta version %1 is not greater, than mine %2").arg(betaVersion).arg(cBetaVersion())); | |
| + if (!cAlphaVersion() || alphaVersion <= cAlphaVersion()) { | |
| + LOG(("Update Error: downloaded alpha version %1 is not greater, than mine %2").arg(alphaVersion).arg(cAlphaVersion())); | |
| return false; | |
| } | |
| } else if (int32(version) <= AppVersion) { | |
| @@ -568,8 +568,8 @@ | |
| return false; | |
| } | |
| fVersion.write((const char*)&versionNum, sizeof(VersionInt)); | |
| - if (versionNum == 0x7FFFFFFF) { // beta version | |
| - fVersion.write((const char*)&betaVersion, sizeof(quint64)); | |
| + if (versionNum == 0x7FFFFFFF) { // alpha version | |
| + fVersion.write((const char*)&alphaVersion, sizeof(quint64)); | |
| } else { | |
| fVersion.write((const char*)&versionLen, sizeof(VersionInt)); | |
| fVersion.write((const char*)&versionStr[0], versionLen); | |
| @@ -594,7 +594,7 @@ | |
| return true; | |
| } | |
| -base::optional<MTPInputChannel> ExtractChannel( | |
| +std::optional<MTPInputChannel> ExtractChannel( | |
| const MTPcontacts_ResolvedPeer &result) { | |
| const auto &data = result.c_contacts_resolvedPeer(); | |
| if (const auto peer = peerFromMTP(data.vpeer)) { | |
| @@ -609,7 +609,7 @@ | |
| } | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| template <typename Callback> | |
| @@ -650,14 +650,14 @@ | |
| } | |
| const auto types = (*it).toObject(); | |
| const auto list = [&]() -> std::vector<QString> { | |
| - if (cBetaVersion()) { | |
| + if (cAlphaVersion()) { | |
| return { "alpha", "beta", "stable" }; | |
| - } else if (cAlphaVersion()) { | |
| + } else if (cInstallBetaVersion()) { | |
| return { "beta", "stable" }; | |
| } | |
| return { "stable" }; | |
| }(); | |
| - auto bestIsAvailableBeta = false; | |
| + auto bestIsAvailableAlpha = false; | |
| auto bestAvailableVersion = 0ULL; | |
| for (const auto &type : list) { | |
| const auto it = types.constFind(type); | |
| @@ -674,7 +674,7 @@ | |
| if (version == map.constEnd()) { | |
| continue; | |
| } | |
| - const auto isAvailableBeta = (type == "alpha"); | |
| + const auto isAvailableAlpha = (type == "alpha"); | |
| const auto availableVersion = [&] { | |
| if ((*version).isString()) { | |
| const auto string = (*version).toString(); | |
| @@ -692,16 +692,16 @@ | |
| ).arg(platform).arg(type).arg(key)); | |
| return false; | |
| } | |
| - const auto compare = isAvailableBeta | |
| + const auto compare = isAvailableAlpha | |
| ? availableVersion | |
| : availableVersion * 1000; | |
| - const auto bestCompare = bestIsAvailableBeta | |
| + const auto bestCompare = bestIsAvailableAlpha | |
| ? bestAvailableVersion | |
| : bestAvailableVersion * 1000; | |
| if (compare > bestCompare) { | |
| bestAvailableVersion = availableVersion; | |
| - bestIsAvailableBeta = isAvailableBeta; | |
| - if (!callback(availableVersion, isAvailableBeta, map)) { | |
| + bestIsAvailableAlpha = isAvailableAlpha; | |
| + if (!callback(availableVersion, isAvailableAlpha, map)) { | |
| return false; | |
| } | |
| } | |
| @@ -714,11 +714,11 @@ | |
| return true; | |
| } | |
| -base::optional<MTPMessage> GetMessagesElement( | |
| +std::optional<MTPMessage> GetMessagesElement( | |
| const MTPmessages_Messages &list) { | |
| - const auto get = [](auto &&data) -> base::optional<MTPMessage> { | |
| + const auto get = [](auto &&data) -> std::optional<MTPMessage> { | |
| return data.vmessages.v.isEmpty() | |
| - ? base::none | |
| + ? std::nullopt | |
| : base::make_optional(data.vmessages.v[0]); | |
| }; | |
| switch (list.type()) { | |
| @@ -729,7 +729,7 @@ | |
| case mtpc_messages_channelMessages: | |
| return get(list.c_messages_channelMessages()); | |
| case mtpc_messages_messagesNotModified: | |
| - return base::none; | |
| + return std::nullopt; | |
| default: Unexpected("Type of messages.Messages (GetMessagesElement)"); | |
| } | |
| } | |
| @@ -958,35 +958,35 @@ | |
| fail(); | |
| } | |
| -base::optional<QString> HttpChecker::parseOldResponse( | |
| +std::optional<QString> HttpChecker::parseOldResponse( | |
| const QByteArray &response) const { | |
| const auto string = QString::fromLatin1(response); | |
| const auto old = QRegularExpression( | |
| qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$") | |
| ).match(string); | |
| if (!old.hasMatch()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto availableVersion = old.captured(1).toULongLong(); | |
| const auto url = old.captured(2); | |
| - const auto isAvailableBeta = url.startsWith(qstr("beta_")); | |
| + const auto isAvailableAlpha = url.startsWith(qstr("beta_")); | |
| return validateLatestUrl( | |
| availableVersion, | |
| - isAvailableBeta, | |
| - isAvailableBeta ? url.mid(5) + "_{signature}" : url); | |
| + isAvailableAlpha, | |
| + isAvailableAlpha ? url.mid(5) + "_{signature}" : url); | |
| } | |
| -base::optional<QString> HttpChecker::parseResponse( | |
| +std::optional<QString> HttpChecker::parseResponse( | |
| const QByteArray &response) const { | |
| auto bestAvailableVersion = 0ULL; | |
| - auto bestIsAvailableBeta = false; | |
| + auto bestIsAvailableAlpha = false; | |
| auto bestLink = QString(); | |
| const auto accumulate = [&]( | |
| uint64 version, | |
| - bool isBeta, | |
| + bool isAlpha, | |
| const QJsonObject &map) { | |
| bestAvailableVersion = version; | |
| - bestIsAvailableBeta = isBeta; | |
| + bestIsAvailableAlpha = isAlpha; | |
| const auto link = map.constFind("link"); | |
| if (link == map.constEnd()) { | |
| LOG(("Update Error: Link not found for version %1." | |
| @@ -1002,32 +1002,32 @@ | |
| }; | |
| const auto result = ParseCommonMap(response, testing(), accumulate); | |
| if (!result) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return validateLatestUrl( | |
| bestAvailableVersion, | |
| - bestIsAvailableBeta, | |
| + bestIsAvailableAlpha, | |
| Local::readAutoupdatePrefix() + bestLink); | |
| } | |
| QString HttpChecker::validateLatestUrl( | |
| uint64 availableVersion, | |
| - bool isAvailableBeta, | |
| + bool isAvailableAlpha, | |
| QString url) const { | |
| - const auto myVersion = isAvailableBeta | |
| - ? cBetaVersion() | |
| + const auto myVersion = isAvailableAlpha | |
| + ? cAlphaVersion() | |
| : uint64(AppVersion); | |
| - const auto validVersion = (cBetaVersion() || !isAvailableBeta); | |
| + const auto validVersion = (cAlphaVersion() || !isAvailableAlpha); | |
| if (!validVersion || availableVersion <= myVersion) { | |
| return QString(); | |
| } | |
| const auto versionUrl = url.replace( | |
| "{version}", | |
| QString::number(availableVersion)); | |
| - const auto finalUrl = isAvailableBeta | |
| + const auto finalUrl = isAvailableAlpha | |
| ? QString(versionUrl).replace( | |
| "{signature}", | |
| - countBetaVersionSignature(availableVersion)) | |
| + countAlphaVersionSignature(availableVersion)) | |
| : versionUrl; | |
| return finalUrl; | |
| } | |
| @@ -1347,25 +1347,25 @@ | |
| } | |
| auto MtpChecker::parseMessage(const MTPmessages_Messages &result) const | |
| --> base::optional<FileLocation> { | |
| +-> std::optional<FileLocation> { | |
| const auto message = GetMessagesElement(result); | |
| if (!message || message->type() != mtpc_message) { | |
| LOG(("Update Error: MTP feed message not found.")); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return parseText(message->c_message().vmessage.v); | |
| } | |
| auto MtpChecker::parseText(const QByteArray &text) const | |
| --> base::optional<FileLocation> { | |
| +-> std::optional<FileLocation> { | |
| auto bestAvailableVersion = 0ULL; | |
| auto bestLocation = FileLocation(); | |
| const auto accumulate = [&]( | |
| uint64 version, | |
| - bool isBeta, | |
| + bool isAlpha, | |
| const QJsonObject &map) { | |
| - if (isBeta) { | |
| - LOG(("Update Error: MTP closed beta found.")); | |
| + if (isAlpha) { | |
| + LOG(("Update Error: MTP closed alpha found.")); | |
| return false; | |
| } | |
| bestAvailableVersion = version; | |
| @@ -1401,7 +1401,7 @@ | |
| }; | |
| const auto result = ParseCommonMap(text, testing(), accumulate); | |
| if (!result) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return validateLatestLocation(bestAvailableVersion, bestLocation); | |
| } | |
| @@ -1427,23 +1427,23 @@ | |
| } | |
| auto MtpChecker::parseFile(const MTPmessages_Messages &result) const | |
| --> base::optional<ParsedFile> { | |
| +-> std::optional<ParsedFile> { | |
| const auto message = GetMessagesElement(result); | |
| if (!message || message->type() != mtpc_message) { | |
| LOG(("Update Error: MTP file message not found.")); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto &data = message->c_message(); | |
| if (!data.has_media() | |
| || data.vmedia.type() != mtpc_messageMediaDocument) { | |
| LOG(("Update Error: MTP file media not found.")); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto &document = data.vmedia.c_messageMediaDocument(); | |
| if (!document.has_document() | |
| || document.vdocument.type() != mtpc_document) { | |
| LOG(("Update Error: MTP file not found.")); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto &fields = document.vdocument.c_document(); | |
| const auto name = [&] { | |
| @@ -1457,12 +1457,12 @@ | |
| }(); | |
| if (name.isEmpty()) { | |
| LOG(("Update Error: MTP file name not found.")); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto size = fields.vsize.v; | |
| if (size <= 0) { | |
| LOG(("Update Error: MTP file size is invalid.")); | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto location = MTP_inputDocumentFileLocation( | |
| fields.vid, | |
| @@ -1635,7 +1635,7 @@ | |
| Implementation _httpImplementation; | |
| Implementation _mtpImplementation; | |
| std::shared_ptr<Loader> _activeLoader; | |
| - bool _usingMtprotoLoader = (cBetaVersion() != 0); | |
| + bool _usingMtprotoLoader = (cAlphaVersion() != 0); | |
| QPointer<MTP::Instance> _mtproto; | |
| rpl::lifetime _lifetime; | |
| @@ -1758,8 +1758,8 @@ | |
| } | |
| _retryTimer.cancel(); | |
| - const auto constDelay = cBetaVersion() ? 600 : UpdateDelayConstPart; | |
| - const auto randDelay = cBetaVersion() ? 300 : UpdateDelayRandPart; | |
| + const auto constDelay = cAlphaVersion() ? 600 : UpdateDelayConstPart; | |
| + const auto randDelay = cAlphaVersion() ? 300 : UpdateDelayRandPart; | |
| const auto updateInSecs = cLastUpdateCheck() | |
| + constDelay | |
| + int(rand() % randDelay) | |
| @@ -2039,15 +2039,15 @@ | |
| ClearAll(); | |
| return false; | |
| } | |
| - 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)); | |
| + if (versionNum == 0x7FFFFFFF) { // alpha version | |
| + quint64 alphaVersion = 0; | |
| + if (fVersion.read((char*)&alphaVersion, sizeof(quint64)) != sizeof(quint64)) { | |
| + LOG(("Update Error: cant read alpha version from file '%1'").arg(versionPath)); | |
| ClearAll(); | |
| return false; | |
| } | |
| - if (!cBetaVersion() || betaVersion <= cBetaVersion()) { | |
| - LOG(("Update Error: cant install beta version %1 having beta version %2").arg(betaVersion).arg(cBetaVersion())); | |
| + if (!cAlphaVersion() || alphaVersion <= cAlphaVersion()) { | |
| + LOG(("Update Error: cant install alpha version %1 having alpha version %2").arg(alphaVersion).arg(cAlphaVersion())); | |
| ClearAll(); | |
| return false; | |
| } | |
| @@ -2124,23 +2124,29 @@ | |
| }(); | |
| UrlClickHandler::Open(url); | |
| } else { | |
| - cSetLastUpdateCheck(0); | |
| - Core::UpdateChecker().start(); | |
| + cSetAutoUpdate(true); | |
| if (const auto window = App::wnd()) { | |
| - auto settings = Box<Settings::Widget>(); | |
| - const auto weak = make_weak(settings.data()); | |
| - window->showSpecialLayer(std::move(settings), anim::type::normal); | |
| - if (weak) { | |
| - weak->scrollToUpdateRow(); | |
| + if (const auto controller = window->controller()) { | |
| + controller->showSection( | |
| + Info::Memento( | |
| + Info::Settings::Tag{ Auth().user() }, | |
| + Info::Section::SettingsType::Advanced), | |
| + Window::SectionShow()); | |
| + } else { | |
| + window->showSpecialLayer( | |
| + Box<Settings::LayerWidget>(), | |
| + anim::type::normal); | |
| } | |
| window->showFromTray(); | |
| } | |
| + cSetLastUpdateCheck(0); | |
| + Core::UpdateChecker().start(); | |
| } | |
| } | |
| -QString countBetaVersionSignature(uint64 version) { // duplicated in packer.cpp | |
| - if (cBetaPrivateKey().isEmpty()) { | |
| - LOG(("Error: Trying to count beta version signature without beta private key!")); | |
| +QString countAlphaVersionSignature(uint64 version) { // duplicated in packer.cpp | |
| + if (cAlphaPrivateKey().isEmpty()) { | |
| + LOG(("Error: Trying to count alpha version signature without alpha private key!")); | |
| return QString(); | |
| } | |
| @@ -2153,27 +2159,27 @@ | |
| uint32 siglen = 0; | |
| - RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cBetaPrivateKey().constData()), -1), 0, 0, 0); | |
| + RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cAlphaPrivateKey().constData()), -1), 0, 0, 0); | |
| if (!prKey) { | |
| - LOG(("Error: Could not read beta private key!")); | |
| + LOG(("Error: Could not read alpha private key!")); | |
| return QString(); | |
| } | |
| if (RSA_size(prKey) != keySize) { | |
| - LOG(("Error: Bad beta private key size: %1").arg(RSA_size(prKey))); | |
| + LOG(("Error: Bad alpha 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!")); | |
| + LOG(("Error: Counting alpha version signature failed!")); | |
| RSA_free(prKey); | |
| return QString(); | |
| } | |
| RSA_free(prKey); | |
| if (siglen != keySize) { | |
| - LOG(("Error: Bad beta version signature length: %1").arg(siglen)); | |
| + LOG(("Error: Bad alpha version signature length: %1").arg(siglen)); | |
| return QString(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/update_checker.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/update_checker.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/update_checker.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/update_checker.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -55,6 +55,6 @@ | |
| bool checkReadyUpdate(); | |
| void UpdateApplication(); | |
| -QString countBetaVersionSignature(uint64 version); | |
| +QString countAlphaVersionSignature(uint64 version); | |
| } // namespace Core | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/utils.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/core/utils.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/utils.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/utils.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -194,52 +194,34 @@ | |
| return 0; | |
| } | |
| - float64 _msFreq; | |
| float64 _msgIdCoef; | |
| - TimeMs _msStart = 0, _msAddToMsStart = 0, _msAddToUnixtime = 0; | |
| - int32 _timeStart = 0; | |
| - | |
| - class _MsInitializer { | |
| + class _MsStarter { | |
| public: | |
| - _MsInitializer() { | |
| + _MsStarter() { | |
| #ifdef Q_OS_WIN | |
| LARGE_INTEGER li; | |
| QueryPerformanceFrequency(&li); | |
| - _msFreq = 1000. / float64(li.QuadPart); | |
| // 0xFFFF0000L istead of 0x100000000L to make msgId grow slightly slower, than unixtime and we had time to reconfigure | |
| _msgIdCoef = float64(0xFFFF0000L) / float64(li.QuadPart); | |
| QueryPerformanceCounter(&li); | |
| - _msStart = li.QuadPart; | |
| + const auto seed = li.QuadPart; | |
| #elif defined Q_OS_MAC | |
| mach_timebase_info_data_t tb = { 0, 0 }; | |
| mach_timebase_info(&tb); | |
| - _msFreq = (float64(tb.numer) / tb.denom) / 1000000.; | |
| - | |
| - _msgIdCoef = _msFreq * (float64(0xFFFF0000L) / 1000.); | |
| + const auto freq = (float64(tb.numer) / tb.denom) / 1000000.; | |
| + _msgIdCoef = freq * (float64(0xFFFF0000L) / 1000.); | |
| - _msStart = mach_absolute_time(); | |
| + const auto seed = mach_absolute_time(); | |
| #else | |
| - timespec ts; | |
| - clock_gettime(CLOCK_MONOTONIC, &ts); | |
| - //_msFreq = 1 / 1000000.; | |
| - _msgIdCoef = float64(0xFFFF0000L) / 1000000000.; | |
| - _msStart = 1000LL * static_cast<TimeMs>(ts.tv_sec) + (static_cast<TimeMs>(ts.tv_nsec) / 1000000LL); | |
| -#endif | |
| - _timeStart = LocalUnixtime(); | |
| - srand((uint32)(_msStart & 0xFFFFFFFFL)); | |
| - } | |
| - }; | |
| + _msgIdCoef = float64(0xFFFF0000L) / 1000000000.; | |
| - void _msInitialize() { | |
| - static _MsInitializer _msInitializer; | |
| - } | |
| - | |
| - class _MsStarter { | |
| - public: | |
| - _MsStarter() { | |
| - getms(); | |
| + timespec ts; | |
| + clock_gettime(CLOCK_MONOTONIC, &ts); | |
| + const auto seed = 1000LL * static_cast<TimeMs>(ts.tv_sec) + (static_cast<TimeMs>(ts.tv_nsec) / 1000000LL); | |
| +#endif | |
| + srand((uint32)(seed & 0xFFFFFFFFL)); | |
| } | |
| }; | |
| _MsStarter _msStarter; | |
| @@ -365,11 +347,25 @@ | |
| Platform::ThirdParty::start(); | |
| if (!RAND_status()) { // should be always inited in all modern OS | |
| - char buf[16]; | |
| - memcpy(buf, &_msStart, 8); | |
| - memcpy(buf + 8, &_msFreq, 8); | |
| - uchar sha256Buffer[32]; | |
| - RAND_seed(hashSha256(buf, 16, sha256Buffer), 32); | |
| + const auto FeedSeed = [](auto value) { | |
| + RAND_seed(&value, sizeof(value)); | |
| + }; | |
| +#ifdef Q_OS_WIN | |
| + LARGE_INTEGER li; | |
| + QueryPerformanceFrequency(&li); | |
| + FeedSeed(li.QuadPart); | |
| + QueryPerformanceCounter(&li); | |
| + FeedSeed(li.QuadPart); | |
| +#elif defined Q_OS_MAC | |
| + mach_timebase_info_data_t tb = { 0 }; | |
| + mach_timebase_info(&tb); | |
| + FeedSeed(tb); | |
| + FeedSeed(mach_absolute_time()); | |
| +#else | |
| + timespec ts = { 0 }; | |
| + clock_gettime(CLOCK_MONOTONIC, &ts); | |
| + FeedSeed(ts); | |
| +#endif | |
| if (!RAND_status()) { | |
| LOG(("MTP Error: Could not init OpenSSL rand, RAND_status() is 0...")); | |
| } | |
| @@ -429,12 +425,7 @@ | |
| } | |
| bool checkms() { | |
| - auto unixms = (LocalUnixtime() - _timeStart) * 1000LL + _msAddToUnixtime; | |
| - auto ms = getms(true); | |
| - if (ms > unixms + 1000LL) { | |
| - _msAddToUnixtime = ((ms - unixms) / 1000LL) * 1000LL; | |
| - } else if (unixms > ms + 1000LL) { | |
| - _msAddToMsStart += ((unixms - ms) / 1000LL) * 1000LL; | |
| + if (crl::adjust_time()) { | |
| Sandbox::adjustSingleTimers(); | |
| return true; | |
| } | |
| @@ -442,24 +433,7 @@ | |
| } | |
| TimeMs getms(bool checked) { | |
| - _msInitialize(); | |
| -#ifdef Q_OS_WIN | |
| - LARGE_INTEGER li; | |
| - QueryPerformanceCounter(&li); | |
| - return ((li.QuadPart - _msStart) * _msFreq) + (checked ? _msAddToMsStart : 0LL); | |
| -#elif defined Q_OS_MAC | |
| - auto msCount = static_cast<TimeMs>(mach_absolute_time()); | |
| - return ((msCount - _msStart) * _msFreq) + (checked ? _msAddToMsStart : 0LL); | |
| -#else | |
| - timespec ts; | |
| - auto res = clock_gettime(CLOCK_MONOTONIC, &ts); | |
| - if (res != 0) { | |
| - LOG(("Bad clock_gettime result: %1").arg(res)); | |
| - return 0; | |
| - } | |
| - auto msCount = 1000LL * static_cast<TimeMs>(ts.tv_sec) + (static_cast<TimeMs>(ts.tv_nsec) / 1000000LL); | |
| - return (msCount - _msStart) + (checked ? _msAddToMsStart : 0LL); | |
| -#endif | |
| + return crl::time(); | |
| } | |
| uint64 msgid() { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/utils.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/utils.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/utils.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/utils.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,7 +8,7 @@ | |
| #pragma once | |
| #include "logs.h" | |
| -#include "core/basic_types.h" | |
| +#include "base/basic_types.h" | |
| #include "base/flags.h" | |
| #include "base/algorithm.h" | |
| #include "base/assertion.h" | |
| @@ -21,23 +21,7 @@ | |
| #include <cmath> | |
| #include <set> | |
| -// Define specializations for QByteArray for Qt 5.3.2, because | |
| -// QByteArray in Qt 5.3.2 doesn't declare "pointer" subtype. | |
| -#ifdef OS_MAC_OLD | |
| -namespace gsl { | |
| - | |
| -template <> | |
| -inline span<char> make_span<QByteArray>(QByteArray &cont) { | |
| - return span<char>(cont.data(), cont.size()); | |
| -} | |
| - | |
| -template <> | |
| -inline span<const char> make_span(const QByteArray &cont) { | |
| - return span<const char>(cont.constData(), cont.size()); | |
| -} | |
| - | |
| -} // namespace gsl | |
| -#endif // OS_MAC_OLD | |
| +#define qsl(s) QStringLiteral(s) | |
| namespace base { | |
| @@ -183,12 +167,6 @@ | |
| return QByteArray::fromRawData(str.c_str(), str.size()); | |
| } | |
| -template <typename T> | |
| -inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; } | |
| - | |
| -template <typename T> | |
| -inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; } | |
| - | |
| void unixtimeInit(); | |
| void unixtimeSet(TimeId serverTime, bool force = false); | |
| TimeId unixtime(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/version.h work/tdesktop-1.4.0/Telegram/SourceFiles/core/version.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/core/version.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/core/version.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,9 +9,9 @@ | |
| #include "core/utils.h" | |
| -#define BETA_VERSION_MACRO (0ULL) | |
| +#define ALPHA_VERSION_MACRO (0ULL) | |
| -constexpr int AppVersion = 1003014; | |
| -constexpr str_const AppVersionStr = "1.3.14"; | |
| -constexpr bool AppAlphaVersion = false; | |
| -constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO; | |
| +constexpr int AppVersion = 1004000; | |
| +constexpr str_const AppVersionStr = "1.4"; | |
| +constexpr bool AppBetaVersion = false; | |
| +constexpr uint64 AppAlphaVersion = ALPHA_VERSION_MACRO; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_document.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_document.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_document.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_document.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -20,6 +20,7 @@ | |
| #include "history/history_item.h" | |
| #include "history/history_media_types.h" | |
| #include "window/window_controller.h" | |
| +#include "storage/cache/storage_cache_database.h" | |
| #include "auth_session.h" | |
| #include "mainwindow.h" | |
| #include "messenger.h" | |
| @@ -770,13 +771,15 @@ | |
| &_urlLocation, | |
| size, | |
| fromCloud, | |
| - autoLoading); | |
| + autoLoading, | |
| + cacheTag()); | |
| } else if (!_access && !_url.isEmpty()) { | |
| _loader = new webFileLoader( | |
| _url, | |
| toFile, | |
| fromCloud, | |
| - autoLoading); | |
| + autoLoading, | |
| + cacheTag()); | |
| } else { | |
| _loader = new mtpFileLoader( | |
| _dc, | |
| @@ -789,7 +792,8 @@ | |
| size, | |
| (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), | |
| fromCloud, | |
| - autoLoading); | |
| + autoLoading, | |
| + cacheTag()); | |
| } | |
| _loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*))); | |
| @@ -1000,7 +1004,11 @@ | |
| Data::FileOrigin DocumentData::stickerSetOrigin() const { | |
| if (const auto data = sticker()) { | |
| - return data->setOrigin(); | |
| + if (const auto result = data->setOrigin()) { | |
| + return result; | |
| + } else if (Stickers::IsFaved(this)) { | |
| + return Data::FileOriginStickerSet(Stickers::FavedSetId, 0); | |
| + } | |
| } | |
| return Data::FileOrigin(); | |
| } | |
| @@ -1063,6 +1071,15 @@ | |
| _fileReference = value; | |
| } | |
| +void DocumentData::refreshStickerThumbFileReference() { | |
| + if (const auto data = sticker()) { | |
| + if (thumb->loading()) { | |
| + data->loc.refreshFileReference( | |
| + thumb->location().fileReference()); | |
| + } | |
| + } | |
| +} | |
| + | |
| QString DocumentData::filename() const { | |
| return _filename; | |
| } | |
| @@ -1083,6 +1100,29 @@ | |
| return ::mediaKey(locationType(), _dc, id); | |
| } | |
| +Storage::Cache::Key DocumentData::cacheKey() const { | |
| + if (hasWebLocation()) { | |
| + return Data::WebDocumentCacheKey(_urlLocation); | |
| + } else if (!_access && !_url.isEmpty()) { | |
| + return Data::UrlCacheKey(_url); | |
| + } else { | |
| + return Data::DocumentCacheKey(_dc, id); | |
| + } | |
| +} | |
| + | |
| +uint8 DocumentData::cacheTag() const { | |
| + if (type == StickerDocument) { | |
| + return Data::kStickerCacheTag; | |
| + } else if (isVoiceMessage()) { | |
| + return Data::kVoiceMessageCacheTag; | |
| + } else if (isVideoMessage()) { | |
| + return Data::kVideoMessageCacheTag; | |
| + } else if (isAnimation()) { | |
| + return Data::kAnimationCacheTag; | |
| + } | |
| + return 0; | |
| +} | |
| + | |
| QString DocumentData::composeNameString() const { | |
| if (auto songData = song()) { | |
| return ComposeNameString( | |
| @@ -1203,17 +1243,9 @@ | |
| void DocumentData::collectLocalData(DocumentData *local) { | |
| if (local == this) return; | |
| + _session->data().cache().copyIfEmpty(local->cacheKey(), cacheKey()); | |
| if (!local->_data.isEmpty()) { | |
| _data = local->_data; | |
| - if (isVoiceMessage()) { | |
| - if (!Local::copyAudio(local->mediaKey(), mediaKey())) { | |
| - Local::writeAudio(mediaKey(), _data); | |
| - } | |
| - } else { | |
| - if (!Local::copyStickerImage(local->mediaKey(), mediaKey())) { | |
| - Local::writeStickerImage(mediaKey(), _data); | |
| - } | |
| - } | |
| } | |
| if (!local->_location.isEmpty()) { | |
| _location = local->_location; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_document.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_document.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_document.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_document.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,6 +9,12 @@ | |
| #include "data/data_types.h" | |
| +namespace Storage { | |
| +namespace Cache { | |
| +struct Key; | |
| +} // namespace Cache | |
| +} // namespace Storage | |
| + | |
| class AuthSession; | |
| class mtpFileLoader; | |
| @@ -160,6 +166,7 @@ | |
| MTPInputDocument mtpInput() const; | |
| QByteArray fileReference() const; | |
| void refreshFileReference(const QByteArray &value); | |
| + void refreshStickerThumbFileReference(); | |
| // When we have some client-side generated document | |
| // (for example for displaying an external inline bot result) | |
| @@ -173,6 +180,8 @@ | |
| void setMimeString(const QString &mime); | |
| MediaKey mediaKey() const; | |
| + Storage::Cache::Key cacheKey() const; | |
| + uint8 cacheTag() const; | |
| static QString ComposeNameString( | |
| const QString &filename, | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_feed.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_feed.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_feed.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_feed.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -250,7 +250,7 @@ | |
| // After that we restore it. | |
| const auto oldLastMessage = base::take(_lastMessage); | |
| for (const auto channel : add) { | |
| - _lastMessage = base::none; | |
| + _lastMessage = std::nullopt; | |
| channel->setFeed(this); | |
| } | |
| _lastMessage = oldLastMessage; | |
| @@ -282,7 +282,7 @@ | |
| } | |
| void Feed::recountLastMessage() { | |
| - _lastMessage = base::none; | |
| + _lastMessage = std::nullopt; | |
| for (const auto history : _channels) { | |
| if (!history->lastMessageKnown()) { | |
| _parent->session().api().requestDialogEntry(this); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_feed.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_feed.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_feed.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_feed.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -103,10 +103,10 @@ | |
| QString _name; | |
| base::flat_set<QString> _nameWords; | |
| base::flat_set<QChar> _nameFirstLetters; | |
| - base::optional<HistoryItem*> _lastMessage; | |
| + std::optional<HistoryItem*> _lastMessage; | |
| rpl::variable<MessagePosition> _unreadPosition; | |
| - base::optional<int> _unreadCount; | |
| + std::optional<int> _unreadCount; | |
| rpl::event_stream<int> _unreadCountChanges; | |
| int _unreadMutedCount = 0; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_media_types.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_media_types.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_media_types.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_media_types.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -312,22 +312,20 @@ | |
| if (media.type() != mtpc_messageMediaPhoto) { | |
| return false; | |
| } | |
| - auto &photo = media.c_messageMediaPhoto(); | |
| - if (photo.has_photo() && !photo.has_ttl_seconds()) { | |
| - if (auto existing = Auth().data().photo(photo.vphoto)) { | |
| - if (existing == _photo) { | |
| - return true; | |
| - } else { | |
| - // collect data | |
| - } | |
| + auto &data = media.c_messageMediaPhoto(); | |
| + if (data.has_photo() && !data.has_ttl_seconds()) { | |
| + const auto photo = Auth().data().photo(data.vphoto); | |
| + if (photo == _photo) { | |
| + return true; | |
| + } else { | |
| + photo->collectLocalData(_photo); | |
| } | |
| } else { | |
| LOG(("API Error: " | |
| "Got MTPMessageMediaPhoto without photo " | |
| "or with ttl_seconds in updateInlineResultMedia()")); | |
| } | |
| - // Can return false if we collect the data. | |
| - return true; | |
| + return false; | |
| } | |
| bool MediaPhoto::updateSentMedia(const MTPMessageMedia &media) { | |
| @@ -347,6 +345,24 @@ | |
| if (photo.type() != mtpc_photo) { | |
| return false; | |
| } | |
| + const auto saveImageToCache = []( | |
| + const MTPDfileLocation &location, | |
| + const ImagePtr &image) { | |
| + const auto key = StorageImageLocation(0, 0, location); | |
| + if (key.isNull() || image->isNull() || !image->loaded()) { | |
| + return; | |
| + } | |
| + if (image->savedData().isEmpty()) { | |
| + image->forget(); | |
| + } else if (image->savedData().size() > Storage::kMaxFileInMemory) { | |
| + return; | |
| + } | |
| + Auth().data().cache().putIfEmpty( | |
| + Data::StorageCacheKey(key), | |
| + Storage::Cache::Database::TaggedValue( | |
| + image->savedData(), | |
| + Data::kImageCacheTag)); | |
| + }; | |
| auto &sizes = photo.c_photo().vsizes.v; | |
| auto max = 0; | |
| const MTPDfileLocation *maxLocation = 0; | |
| @@ -369,23 +385,24 @@ | |
| if (!loc || loc->type() != mtpc_fileLocation) { | |
| continue; | |
| } | |
| + const auto &location = loc->c_fileLocation(); | |
| if (size == 's') { | |
| - Local::writeImage(storageKey(loc->c_fileLocation()), _photo->thumb); | |
| + saveImageToCache(location, _photo->thumb); | |
| } else if (size == 'm') { | |
| - Local::writeImage(storageKey(loc->c_fileLocation()), _photo->medium); | |
| + saveImageToCache(location, _photo->medium); | |
| } else if (size == 'x' && max < 1) { | |
| max = 1; | |
| - maxLocation = &loc->c_fileLocation(); | |
| + maxLocation = &location; | |
| } else if (size == 'y' && max < 2) { | |
| max = 2; | |
| - maxLocation = &loc->c_fileLocation(); | |
| + maxLocation = &location; | |
| //} else if (size == 'w' && max < 3) { | |
| // max = 3; | |
| // maxLocation = &loc->c_fileLocation(); | |
| } | |
| } | |
| if (maxLocation) { | |
| - Local::writeImage(storageKey(*maxLocation), _photo->full); | |
| + saveImageToCache(*maxLocation, _photo->full); | |
| } | |
| return true; | |
| } | |
| @@ -637,13 +654,6 @@ | |
| return false; | |
| } | |
| Auth().data().documentConvert(_document, data.vdocument); | |
| - if (!_document->data().isEmpty()) { | |
| - if (_document->isVoiceMessage()) { | |
| - Local::writeAudio(_document->mediaKey(), _document->data()); | |
| - } else { | |
| - Local::writeStickerImage(_document->mediaKey(), _document->data()); | |
| - } | |
| - } | |
| return true; | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_messages.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_messages.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_messages.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_messages.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -93,7 +93,7 @@ | |
| void MessagesList::addRange( | |
| const Range &messages, | |
| MessagesRange noSkipRange, | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| bool incrementCount) { | |
| Expects(!count || !incrementCount); | |
| @@ -119,13 +119,13 @@ | |
| void MessagesList::addNew(MessagePosition messageId) { | |
| auto range = { messageId }; | |
| - addRange(range, { messageId, MaxMessagePosition }, base::none, true); | |
| + addRange(range, { messageId, MaxMessagePosition }, std::nullopt, true); | |
| } | |
| void MessagesList::addSlice( | |
| std::vector<MessagePosition> &&messageIds, | |
| MessagesRange noSkipRange, | |
| - base::optional<int> count) { | |
| + std::optional<int> count) { | |
| addRange(messageIds, noSkipRange, count); | |
| } | |
| @@ -167,7 +167,7 @@ | |
| void MessagesList::invalidate() { | |
| _slices.clear(); | |
| - _count = base::none; | |
| + _count = std::nullopt; | |
| } | |
| void MessagesList::invalidateBottom() { | |
| @@ -181,7 +181,7 @@ | |
| }); | |
| } | |
| } | |
| - _count = base::none; | |
| + _count = std::nullopt; | |
| } | |
| rpl::producer<MessagesResult> MessagesList::query( | |
| @@ -272,10 +272,10 @@ | |
| } | |
| auto skippedBefore = (update.range.from == MinMessagePosition) | |
| ? 0 | |
| - : base::optional<int> {}; | |
| + : std::optional<int> {}; | |
| auto skippedAfter = (update.range.till == MaxMessagePosition) | |
| ? 0 | |
| - : base::optional<int> {}; | |
| + : std::optional<int> {}; | |
| mergeSliceData( | |
| update.count, | |
| needMergeMessages | |
| @@ -331,20 +331,20 @@ | |
| ++i; | |
| } | |
| } | |
| - _skippedBefore = _skippedAfter = base::none; | |
| + _skippedBefore = _skippedAfter = std::nullopt; | |
| checkInsufficient(); | |
| return true; | |
| } | |
| bool MessagesSliceBuilder::invalidated() { | |
| - _fullCount = _skippedBefore = _skippedAfter = base::none; | |
| + _fullCount = _skippedBefore = _skippedAfter = std::nullopt; | |
| _ids.clear(); | |
| checkInsufficient(); | |
| return false; | |
| } | |
| bool MessagesSliceBuilder::bottomInvalidated() { | |
| - _fullCount = _skippedAfter = base::none; | |
| + _fullCount = _skippedAfter = std::nullopt; | |
| checkInsufficient(); | |
| return true; | |
| } | |
| @@ -354,10 +354,10 @@ | |
| } | |
| void MessagesSliceBuilder::mergeSliceData( | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| const base::flat_set<MessagePosition> &messageIds, | |
| - base::optional<int> skippedBefore, | |
| - base::optional<int> skippedAfter) { | |
| + std::optional<int> skippedBefore, | |
| + std::optional<int> skippedAfter) { | |
| if (messageIds.empty()) { | |
| if (count && _fullCount != count) { | |
| _fullCount = count; | |
| @@ -388,7 +388,7 @@ | |
| } else if (wasMinId != impossible && _skippedBefore) { | |
| adjustSkippedBefore(wasMinId, *_skippedBefore); | |
| } else { | |
| - _skippedBefore = base::none; | |
| + _skippedBefore = std::nullopt; | |
| } | |
| auto adjustSkippedAfter = [&](MessagePosition oldId, int oldSkippedAfter) { | |
| @@ -402,7 +402,7 @@ | |
| } else if (wasMaxId != impossible && _skippedAfter) { | |
| adjustSkippedAfter(wasMaxId, *_skippedAfter); | |
| } else { | |
| - _skippedAfter = base::none; | |
| + _skippedAfter = std::nullopt; | |
| } | |
| fillSkippedAndSliceToLimits(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_messages.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_messages.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_messages.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_messages.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -93,9 +93,9 @@ | |
| struct MessagesSlice { | |
| std::vector<FullMsgId> ids; | |
| - base::optional<int> skippedBefore; | |
| - base::optional<int> skippedAfter; | |
| - base::optional<int> fullCount; | |
| + std::optional<int> skippedBefore; | |
| + std::optional<int> skippedAfter; | |
| + std::optional<int> fullCount; | |
| }; | |
| @@ -116,16 +116,16 @@ | |
| }; | |
| struct MessagesResult { | |
| - base::optional<int> count; | |
| - base::optional<int> skippedBefore; | |
| - base::optional<int> skippedAfter; | |
| + std::optional<int> count; | |
| + std::optional<int> skippedBefore; | |
| + std::optional<int> skippedAfter; | |
| base::flat_set<MessagePosition> messageIds; | |
| }; | |
| struct MessagesSliceUpdate { | |
| const base::flat_set<MessagePosition> *messages = nullptr; | |
| MessagesRange range; | |
| - base::optional<int> count; | |
| + std::optional<int> count; | |
| }; | |
| class MessagesList { | |
| @@ -134,7 +134,7 @@ | |
| void addSlice( | |
| std::vector<MessagePosition> &&messageIds, | |
| MessagesRange noSkipRange, | |
| - base::optional<int> count); | |
| + std::optional<int> count); | |
| void removeOne(MessagePosition messageId); | |
| void removeAll(ChannelId channelId); | |
| void invalidate(); | |
| @@ -178,14 +178,14 @@ | |
| void addRange( | |
| const Range &messages, | |
| MessagesRange noSkipRange, | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| bool incrementCount = false); | |
| MessagesResult queryFromSlice( | |
| const MessagesQuery &query, | |
| const Slice &slice) const; | |
| - base::optional<int> _count; | |
| + std::optional<int> _count; | |
| base::flat_set<Slice> _slices; | |
| rpl::event_stream<MessagesSliceUpdate> _sliceUpdated; | |
| @@ -234,17 +234,17 @@ | |
| void sliceToLimits(); | |
| void mergeSliceData( | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| const base::flat_set<MessagePosition> &messageIds, | |
| - base::optional<int> skippedBefore = base::none, | |
| - base::optional<int> skippedAfter = base::none); | |
| + std::optional<int> skippedBefore = std::nullopt, | |
| + std::optional<int> skippedAfter = std::nullopt); | |
| MessagePosition _key; | |
| base::flat_set<MessagePosition> _ids; | |
| MessagesRange _range; | |
| - base::optional<int> _fullCount; | |
| - base::optional<int> _skippedBefore; | |
| - base::optional<int> _skippedAfter; | |
| + std::optional<int> _fullCount; | |
| + std::optional<int> _skippedBefore; | |
| + std::optional<int> _skippedAfter; | |
| int _limitBefore = 0; | |
| int _limitAfter = 0; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_notify_settings.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_notify_settings.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_notify_settings.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_notify_settings.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -28,24 +28,24 @@ | |
| bool change(const MTPDpeerNotifySettings &data); | |
| bool change( | |
| - base::optional<int> muteForSeconds, | |
| - base::optional<bool> silentPosts); | |
| + std::optional<int> muteForSeconds, | |
| + std::optional<bool> silentPosts); | |
| - base::optional<TimeId> muteUntil() const; | |
| - base::optional<bool> silentPosts() const; | |
| + std::optional<TimeId> muteUntil() const; | |
| + std::optional<bool> silentPosts() const; | |
| MTPinputPeerNotifySettings serialize() const; | |
| private: | |
| bool change( | |
| - base::optional<int> mute, | |
| - base::optional<QString> sound, | |
| - base::optional<bool> showPreviews, | |
| - base::optional<bool> silentPosts); | |
| - | |
| - base::optional<TimeId> _mute; | |
| - base::optional<QString> _sound; | |
| - base::optional<bool> _silent; | |
| - base::optional<bool> _showPreviews; | |
| + std::optional<int> mute, | |
| + std::optional<QString> sound, | |
| + std::optional<bool> showPreviews, | |
| + std::optional<bool> silentPosts); | |
| + | |
| + std::optional<TimeId> _mute; | |
| + std::optional<QString> _sound; | |
| + std::optional<bool> _silent; | |
| + std::optional<bool> _showPreviews; | |
| }; | |
| @@ -57,18 +57,18 @@ | |
| bool NotifySettingsValue::change(const MTPDpeerNotifySettings &data) { | |
| return change(data.has_mute_until() | |
| ? base::make_optional(data.vmute_until.v) | |
| - : base::none, data.has_sound() | |
| + : std::nullopt, data.has_sound() | |
| ? base::make_optional(qs(data.vsound)) | |
| - : base::none, data.has_show_previews() | |
| + : std::nullopt, data.has_show_previews() | |
| ? base::make_optional(mtpIsTrue(data.vshow_previews)) | |
| - : base::none, data.has_silent() | |
| + : std::nullopt, data.has_silent() | |
| ? base::make_optional(mtpIsTrue(data.vsilent)) | |
| - : base::none); | |
| + : std::nullopt); | |
| } | |
| bool NotifySettingsValue::change( | |
| - base::optional<int> muteForSeconds, | |
| - base::optional<bool> silentPosts) { | |
| + std::optional<int> muteForSeconds, | |
| + std::optional<bool> silentPosts) { | |
| const auto now = unixtime(); | |
| const auto notMuted = muteForSeconds | |
| ? !(*muteForSeconds) | |
| @@ -92,10 +92,10 @@ | |
| } | |
| bool NotifySettingsValue::change( | |
| - base::optional<int> mute, | |
| - base::optional<QString> sound, | |
| - base::optional<bool> showPreviews, | |
| - base::optional<bool> silentPosts) { | |
| + std::optional<int> mute, | |
| + std::optional<QString> sound, | |
| + std::optional<bool> showPreviews, | |
| + std::optional<bool> silentPosts) { | |
| if (_mute == mute | |
| && _sound == sound | |
| && _showPreviews == showPreviews | |
| @@ -109,11 +109,11 @@ | |
| return true; | |
| } | |
| -base::optional<TimeId> NotifySettingsValue::muteUntil() const { | |
| +std::optional<TimeId> NotifySettingsValue::muteUntil() const { | |
| return _mute; | |
| } | |
| -base::optional<bool> NotifySettingsValue::silentPosts() const { | |
| +std::optional<bool> NotifySettingsValue::silentPosts() const { | |
| return _silent; | |
| } | |
| @@ -157,8 +157,8 @@ | |
| } | |
| bool NotifySettings::change( | |
| - base::optional<int> muteForSeconds, | |
| - base::optional<bool> silentPosts) { | |
| + std::optional<int> muteForSeconds, | |
| + std::optional<bool> silentPosts) { | |
| if (!muteForSeconds && !silentPosts) { | |
| return false; | |
| } else if (_value) { | |
| @@ -178,20 +178,20 @@ | |
| MTPstring())); | |
| } | |
| -base::optional<TimeId> NotifySettings::muteUntil() const { | |
| +std::optional<TimeId> NotifySettings::muteUntil() const { | |
| return _value | |
| ? _value->muteUntil() | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| bool NotifySettings::settingsUnknown() const { | |
| return !_known; | |
| } | |
| -base::optional<bool> NotifySettings::silentPosts() const { | |
| +std::optional<bool> NotifySettings::silentPosts() const { | |
| return _value | |
| ? _value->silentPosts() | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| MTPinputPeerNotifySettings NotifySettings::serialize() const { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_notify_settings.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_notify_settings.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_notify_settings.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_notify_settings.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -19,12 +19,12 @@ | |
| bool change(const MTPPeerNotifySettings &settings); | |
| bool change( | |
| - base::optional<int> muteForSeconds, | |
| - base::optional<bool> silentPosts); | |
| + std::optional<int> muteForSeconds, | |
| + std::optional<bool> silentPosts); | |
| bool settingsUnknown() const; | |
| - base::optional<TimeId> muteUntil() const; | |
| - base::optional<bool> silentPosts() const; | |
| + std::optional<TimeId> muteUntil() const; | |
| + std::optional<bool> silentPosts() const; | |
| MTPinputPeerNotifySettings serialize() const; | |
| ~NotifySettings(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_peer_values.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_peer_values.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_peer_values.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_peer_values.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -39,7 +39,7 @@ | |
| return std::max(static_cast<TimeId>(nowFull.secsTo(tomorrow)), 0); | |
| } | |
| -base::optional<QString> OnlineTextSpecial(not_null<UserData*> user) { | |
| +std::optional<QString> OnlineTextSpecial(not_null<UserData*> user) { | |
| if (isNotificationsUser(user->id)) { | |
| return lang(lng_status_service_notifications); | |
| } else if (user->botInfo) { | |
| @@ -47,10 +47,10 @@ | |
| } else if (isServiceUser(user->id)) { | |
| return lang(lng_status_support); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| -base::optional<QString> OnlineTextCommon(TimeId online, TimeId now) { | |
| +std::optional<QString> OnlineTextCommon(TimeId online, TimeId now) { | |
| if (online <= 0) { | |
| switch (online) { | |
| case 0: | |
| @@ -65,7 +65,7 @@ | |
| } else if (online > now) { | |
| return lang(lng_status_online); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| } // namespace | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_peer.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_peer.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_peer.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_peer.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -115,7 +115,6 @@ | |
| return; | |
| } | |
| } | |
| - | |
| ++nameVersion; | |
| name = newName; | |
| nameText.setText(st::msgNameStyle, name, Ui::NameTextOptions()); | |
| @@ -437,8 +436,6 @@ | |
| void UserData::setPhone(const QString &newPhone) { | |
| if (_phone != newPhone) { | |
| _phone = newPhone; | |
| - if (bareId() == Auth().userId()) { | |
| - } | |
| } | |
| } | |
| @@ -1042,15 +1039,16 @@ | |
| } | |
| _adminRights.set(rights.c_channelAdminRights().vflags.v); | |
| if (isMegagroup()) { | |
| + const auto self = Auth().user(); | |
| if (hasAdminRights()) { | |
| if (!amCreator()) { | |
| auto me = MegagroupInfo::Admin { rights }; | |
| me.canEdit = false; | |
| - mgInfo->lastAdmins.emplace(App::self(), me); | |
| + mgInfo->lastAdmins.emplace(self, me); | |
| } | |
| - mgInfo->lastRestricted.remove(App::self()); | |
| + mgInfo->lastRestricted.remove(self); | |
| } else { | |
| - mgInfo->lastAdmins.remove(App::self()); | |
| + mgInfo->lastAdmins.remove(self); | |
| } | |
| auto amAdmin = hasAdminRights() || amCreator(); | |
| @@ -1067,15 +1065,16 @@ | |
| _restrictedUntill = rights.c_channelBannedRights().vuntil_date.v; | |
| _restrictions.set(rights.c_channelBannedRights().vflags.v); | |
| if (isMegagroup()) { | |
| + const auto self = Auth().user(); | |
| if (hasRestrictions()) { | |
| if (!amCreator()) { | |
| auto me = MegagroupInfo::Restricted { rights }; | |
| - mgInfo->lastRestricted.emplace(App::self(), me); | |
| + mgInfo->lastRestricted.emplace(self, me); | |
| } | |
| - mgInfo->lastAdmins.remove(App::self()); | |
| + mgInfo->lastAdmins.remove(self); | |
| Data::ChannelAdminChanges(this).feed(Auth().userId(), false); | |
| } else { | |
| - mgInfo->lastRestricted.remove(App::self()); | |
| + mgInfo->lastRestricted.remove(self); | |
| } | |
| } | |
| Notify::peerUpdatedDelayed(this, UpdateFlag::ChannelRightsChanged | UpdateFlag::AdminsChanged | UpdateFlag::BannedUsersChanged); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_peer.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_peer.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_peer.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_peer.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -68,21 +68,21 @@ | |
| bool isVerified() const; | |
| bool isMegagroup() const; | |
| - base::optional<TimeId> notifyMuteUntil() const { | |
| + std::optional<TimeId> notifyMuteUntil() const { | |
| return _notify.muteUntil(); | |
| } | |
| bool notifyChange(const MTPPeerNotifySettings &settings) { | |
| return _notify.change(settings); | |
| } | |
| bool notifyChange( | |
| - base::optional<int> muteForSeconds, | |
| - base::optional<bool> silentPosts) { | |
| + std::optional<int> muteForSeconds, | |
| + std::optional<bool> silentPosts) { | |
| return _notify.change(muteForSeconds, silentPosts); | |
| } | |
| bool notifySettingsUnknown() const { | |
| return _notify.settingsUnknown(); | |
| } | |
| - base::optional<bool> notifySilentPosts() const { | |
| + std::optional<bool> notifySilentPosts() const { | |
| return _notify.silentPosts(); | |
| } | |
| MTPinputPeerNotifySettings notifySerialize() const { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_photo.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_photo.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_photo.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_photo.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -111,13 +111,29 @@ | |
| ImagePtr PhotoData::makeReplyPreview(Data::FileOrigin origin) { | |
| if (replyPreview->isNull() && !thumb->isNull()) { | |
| - if (thumb->loaded()) { | |
| - int w = thumb->width(), h = thumb->height(); | |
| + const auto previewFromImage = [&](const ImagePtr &image) { | |
| + if (!image->loaded()) { | |
| + image->load(origin); | |
| + return ImagePtr(); | |
| + } | |
| + int w = image->width(), h = image->height(); | |
| if (w <= 0) w = 1; | |
| if (h <= 0) h = 1; | |
| - replyPreview = ImagePtr(w > h ? thumb->pix(origin, w * st::msgReplyBarSize.height() / h, st::msgReplyBarSize.height()) : thumb->pix(origin, st::msgReplyBarSize.height()), "PNG"); | |
| + return ImagePtr( | |
| + (w > h | |
| + ? image->pix( | |
| + origin, | |
| + w * st::msgReplyBarSize.height() / h, | |
| + st::msgReplyBarSize.height()) | |
| + : image->pix(origin, st::msgReplyBarSize.height())), | |
| + "PNG"); | |
| + }; | |
| + if (thumb->toDelayedStorageImage() | |
| + && !full->isNull() | |
| + && !full->toDelayedStorageImage()) { | |
| + return previewFromImage(full); | |
| } else { | |
| - thumb->load(origin); | |
| + return previewFromImage(thumb); | |
| } | |
| } | |
| return replyPreview; | |
| @@ -130,6 +146,21 @@ | |
| MTP_bytes(fileReference)); | |
| } | |
| +void PhotoData::collectLocalData(PhotoData *local) { | |
| + if (local == this) return; | |
| + | |
| + const auto copyImage = [](const ImagePtr &src, const ImagePtr &dst) { | |
| + if (const auto from = src->cacheKey()) { | |
| + if (const auto to = dst->cacheKey()) { | |
| + Auth().data().cache().copyIfEmpty(*from, *to); | |
| + } | |
| + } | |
| + }; | |
| + copyImage(local->thumb, thumb); | |
| + copyImage(local->medium, medium); | |
| + copyImage(local->full, full); | |
| +} | |
| + | |
| void PhotoOpenClickHandler::onClickImpl() const { | |
| Messenger::Instance().showPhoto(this); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_photo.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_photo.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_photo.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_photo.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -43,6 +43,12 @@ | |
| MTPInputPhoto mtpInput() const; | |
| + // When we have some client-side generated photo | |
| + // (for example for displaying an external inline bot result) | |
| + // and it has downloaded full image, we can collect image from it | |
| + // to (this) received from the server "same" photo. | |
| + void collectLocalData(PhotoData *local); | |
| + | |
| PhotoId id = 0; | |
| uint64 access = 0; | |
| QByteArray fileReference; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_search_controller.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_search_controller.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_search_controller.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_search_controller.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -180,7 +180,7 @@ | |
| : peerData(App::peer(query.peerId)) | |
| , migratedData(query.migratedPeerId | |
| ? base::make_optional(Data(App::peer(query.migratedPeerId))) | |
| - : base::none) { | |
| + : std::nullopt) { | |
| } | |
| bool SearchController::hasInCache(const Query &query) const { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_search_controller.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_search_controller.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_search_controller.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_search_controller.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -64,7 +64,7 @@ | |
| struct SavedState { | |
| Query query; | |
| IdsList peerList; | |
| - base::optional<IdsList> migratedList; | |
| + std::optional<IdsList> migratedList; | |
| }; | |
| void setQuery(const Query &query); | |
| @@ -100,7 +100,7 @@ | |
| CacheEntry(const Query &query); | |
| Data peerData; | |
| - base::optional<Data> migratedData; | |
| + std::optional<Data> migratedData; | |
| }; | |
| struct CacheLess { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_session.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_session.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_session.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_session.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,6 +10,7 @@ | |
| #include "observer_peer.h" | |
| #include "auth_session.h" | |
| #include "apiwrap.h" | |
| +#include "messenger.h" | |
| #include "export/export_controller.h" | |
| #include "export/view/export_view_panel_controller.h" | |
| #include "window/notifications_manager.h" | |
| @@ -19,6 +20,7 @@ | |
| #include "history/view/history_view_element.h" | |
| #include "inline_bots/inline_bot_layout_item.h" | |
| #include "storage/localstorage.h" | |
| +#include "storage/storage_encrypted_file.h" | |
| #include "boxes/abstract_box.h" | |
| #include "passport/passport_form_controller.h" | |
| #include "data/data_media_types.h" | |
| @@ -66,12 +68,21 @@ | |
| Session::Session(not_null<AuthSession*> session) | |
| : _session(session) | |
| +, _cache(Messenger::Instance().databases().get( | |
| + Local::cachePath(), | |
| + Local::cacheSettings())) | |
| , _groups(this) | |
| , _unmuteByFinishedTimer([=] { unmuteByFinished(); }) { | |
| + _cache->open(Local::cacheKey()); | |
| + | |
| setupContactViewsViewer(); | |
| setupChannelLeavingViewer(); | |
| } | |
| +Storage::Cache::Database &Session::cache() { | |
| + return *_cache; | |
| +} | |
| + | |
| void Session::startExport(PeerData *peer) { | |
| startExport(peer ? peer->input : MTP_inputPeerEmpty()); | |
| } | |
| @@ -318,7 +329,7 @@ | |
| view->refreshDataId(); | |
| }; | |
| enumerateItemViews(event.item, refreshViewDataId); | |
| - if (const auto group = Auth().data().groups().find(event.item)) { | |
| + if (const auto group = groups().find(event.item)) { | |
| const auto leader = group->items.back(); | |
| if (leader != event.item) { | |
| enumerateItemViews(leader, refreshViewDataId); | |
| @@ -1061,6 +1072,7 @@ | |
| Unexpected("Type in Session::documentConvert()."); | |
| }(); | |
| const auto oldKey = original->mediaKey(); | |
| + const auto oldCacheKey = original->cacheKey(); | |
| const auto idChanged = (original->id != id); | |
| const auto sentSticker = idChanged && (original->sticker() != nullptr); | |
| if (idChanged) { | |
| @@ -1083,14 +1095,7 @@ | |
| } | |
| documentApplyFields(original, data); | |
| if (idChanged) { | |
| - const auto newKey = original->mediaKey(); | |
| - if (oldKey != newKey) { | |
| - if (original->isVoiceMessage()) { | |
| - Local::copyAudio(oldKey, newKey); | |
| - } else if (original->sticker() || original->isAnimation()) { | |
| - Local::copyStickerImage(oldKey, newKey); | |
| - } | |
| - } | |
| + cache().moveIfEmpty(oldCacheKey, original->cacheKey()); | |
| if (savedGifs().indexOf(original) >= 0) { | |
| Local::writeSavedGifs(); | |
| } | |
| @@ -1837,8 +1842,8 @@ | |
| void Session::updateNotifySettings( | |
| not_null<PeerData*> peer, | |
| - base::optional<int> muteForSeconds, | |
| - base::optional<bool> silentPosts) { | |
| + std::optional<int> muteForSeconds, | |
| + std::optional<bool> silentPosts) { | |
| if (peer->notifyChange(muteForSeconds, silentPosts)) { | |
| updateNotifySettingsLocal(peer); | |
| _session->api().updateNotifySettingsDelayed(peer); | |
| @@ -1917,6 +1922,77 @@ | |
| : defaultChatNotifyUpdates(); | |
| } | |
| +void Session::serviceNotification( | |
| + const TextWithEntities &message, | |
| + const MTPMessageMedia &media) { | |
| + const auto date = unixtime(); | |
| + if (!App::userLoaded(ServiceUserId)) { | |
| + App::feedUsers(MTP_vector<MTPUser>(1, MTP_user( | |
| + MTP_flags( | |
| + MTPDuser::Flag::f_first_name | |
| + | MTPDuser::Flag::f_phone | |
| + | MTPDuser::Flag::f_status | |
| + | MTPDuser::Flag::f_verified), | |
| + MTP_int(ServiceUserId), | |
| + MTPlong(), | |
| + MTP_string("Telegram"), | |
| + MTPstring(), | |
| + MTPstring(), | |
| + MTP_string("42777"), | |
| + MTP_userProfilePhotoEmpty(), | |
| + MTP_userStatusRecently(), | |
| + MTPint(), | |
| + MTPstring(), | |
| + MTPstring(), | |
| + MTPstring()))); | |
| + } | |
| + const auto history = App::history(peerFromUser(ServiceUserId)); | |
| + if (!history->lastMessageKnown()) { | |
| + _session->api().requestDialogEntry(history, [=] { | |
| + insertCheckedServiceNotification(message, media, date); | |
| + }); | |
| + } else { | |
| + insertCheckedServiceNotification(message, media, date); | |
| + } | |
| +} | |
| + | |
| +void Session::insertCheckedServiceNotification( | |
| + const TextWithEntities &message, | |
| + const MTPMessageMedia &media, | |
| + TimeId date) { | |
| + const auto history = App::history(peerFromUser(ServiceUserId)); | |
| + if (!history->isReadyFor(ShowAtUnreadMsgId)) { | |
| + history->setUnreadCount(0); | |
| + history->getReadyFor(ShowAtTheEndMsgId); | |
| + } | |
| + const auto flags = MTPDmessage::Flag::f_entities | |
| + | MTPDmessage::Flag::f_from_id | |
| + | MTPDmessage_ClientFlag::f_clientside_unread; | |
| + auto sending = TextWithEntities(), left = message; | |
| + while (TextUtilities::CutPart(sending, left, MaxMessageSize)) { | |
| + App::histories().addNewMessage( | |
| + MTP_message( | |
| + MTP_flags(flags), | |
| + MTP_int(clientMsgId()), | |
| + MTP_int(ServiceUserId), | |
| + MTP_peerUser(MTP_int(_session->userId())), | |
| + MTPnullFwdHeader, | |
| + MTPint(), | |
| + MTPint(), | |
| + MTP_int(date), | |
| + MTP_string(sending.text), | |
| + media, | |
| + MTPnullMarkup, | |
| + TextUtilities::EntitiesToMTP(sending.entities), | |
| + MTPint(), | |
| + MTPint(), | |
| + MTPstring(), | |
| + MTPlong()), | |
| + NewMessageUnread); | |
| + } | |
| + sendHistoryChangeNotifications(); | |
| +} | |
| + | |
| void Session::forgetMedia() { | |
| for (const auto &[id, photo] : _photos) { | |
| photo->forget(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_session.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_session.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_session.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_session.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,7 @@ | |
| */ | |
| #pragma once | |
| +#include "storage/storage_databases.h" | |
| #include "chat_helpers/stickers.h" | |
| #include "dialogs/dialogs_key.h" | |
| #include "data/data_groups.h" | |
| @@ -71,6 +72,8 @@ | |
| TimeMs rememberFor); | |
| void forgetPassportCredentials(); | |
| + Storage::Cache::Database &cache(); | |
| + | |
| [[nodiscard]] base::Variable<bool> &contactsLoaded() { | |
| return _contactsLoaded; | |
| } | |
| @@ -393,8 +396,8 @@ | |
| const MTPPeerNotifySettings &settings); | |
| void updateNotifySettings( | |
| not_null<PeerData*> peer, | |
| - base::optional<int> muteForSeconds, | |
| - base::optional<bool> silentPosts = base::none); | |
| + std::optional<int> muteForSeconds, | |
| + std::optional<bool> silentPosts = std::nullopt); | |
| bool notifyIsMuted( | |
| not_null<const PeerData*> peer, | |
| TimeMs *changesIn = nullptr) const; | |
| @@ -407,6 +410,10 @@ | |
| rpl::producer<> defaultNotifyUpdates( | |
| not_null<const PeerData*> peer) const; | |
| + void serviceNotification( | |
| + const TextWithEntities &message, | |
| + const MTPMessageMedia &media); | |
| + | |
| void forgetMedia(); | |
| void setMimeForwardIds(MessageIdsList &&list); | |
| @@ -518,8 +525,15 @@ | |
| not_null<const HistoryItem*> item, | |
| Method method); | |
| + void insertCheckedServiceNotification( | |
| + const TextWithEntities &message, | |
| + const MTPMessageMedia &media, | |
| + TimeId date); | |
| + | |
| not_null<AuthSession*> _session; | |
| + Storage::DatabasePointer _cache; | |
| + | |
| std::unique_ptr<Export::ControllerWrap> _export; | |
| std::unique_ptr<Export::View::PanelController> _exportPanel; | |
| rpl::event_stream<Export::View::PanelController*> _exportViewChanges; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_shared_media.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_shared_media.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_shared_media.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_shared_media.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -30,7 +30,7 @@ | |
| } // namespace | |
| -base::optional<Storage::SharedMediaType> SharedMediaOverviewType( | |
| +std::optional<Storage::SharedMediaType> SharedMediaOverviewType( | |
| Storage::SharedMediaType type) { | |
| switch (type) { | |
| case Type::Photo: | |
| @@ -40,7 +40,7 @@ | |
| case Type::VoiceFile: | |
| case Type::Link: return type; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| void SharedMediaShowOverview( | |
| @@ -177,7 +177,7 @@ | |
| SharedMediaWithLastSlice::SharedMediaWithLastSlice( | |
| Key key, | |
| SparseIdsMergedSlice slice, | |
| - base::optional<SparseIdsMergedSlice> ending) | |
| + std::optional<SparseIdsMergedSlice> ending) | |
| : _key(key) | |
| , _slice(std::move(slice)) | |
| , _ending(std::move(ending)) | |
| @@ -187,21 +187,21 @@ | |
| : false) { | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::fullCount() const { | |
| +std::optional<int> SharedMediaWithLastSlice::fullCount() const { | |
| return Add( | |
| _slice.fullCount(), | |
| _isolatedLastPhoto | [](bool isolated) { return isolated ? 1 : 0; }); | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::skippedBeforeImpl() const { | |
| +std::optional<int> SharedMediaWithLastSlice::skippedBeforeImpl() const { | |
| return _slice.skippedBefore(); | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::skippedBefore() const { | |
| +std::optional<int> SharedMediaWithLastSlice::skippedBefore() const { | |
| return _reversed ? skippedAfterImpl() : skippedBeforeImpl(); | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::skippedAfterImpl() const { | |
| +std::optional<int> SharedMediaWithLastSlice::skippedAfterImpl() const { | |
| return isolatedInSlice() | |
| ? Add( | |
| _slice.skippedAfter(), | |
| @@ -209,21 +209,21 @@ | |
| : (lastPhotoSkip() | [](int) { return 0; }); | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::skippedAfter() const { | |
| +std::optional<int> SharedMediaWithLastSlice::skippedAfter() const { | |
| return _reversed ? skippedBeforeImpl() : skippedAfterImpl(); | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::indexOfImpl(Value value) const { | |
| +std::optional<int> SharedMediaWithLastSlice::indexOfImpl(Value value) const { | |
| return base::get_if<FullMsgId>(&value) | |
| ? _slice.indexOf(*base::get_if<FullMsgId>(&value)) | |
| : (isolatedInSlice() | |
| || !_lastPhotoId | |
| || (*base::get_if<not_null<PhotoData*>>(&value))->id != *_lastPhotoId) | |
| - ? base::none | |
| + ? std::nullopt | |
| : Add(_slice.size() - 1, lastPhotoSkip()); | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::indexOf(Value value) const { | |
| +std::optional<int> SharedMediaWithLastSlice::indexOf(Value value) const { | |
| const auto result = indexOfImpl(value); | |
| if (result && (*result < 0 || *result >= size())) { | |
| // Should not happen. | |
| @@ -296,7 +296,7 @@ | |
| : Value(Auth().data().photo(*_lastPhotoId)); | |
| } | |
| -base::optional<int> SharedMediaWithLastSlice::distance( | |
| +std::optional<int> SharedMediaWithLastSlice::distance( | |
| const Key &a, | |
| const Key &b) const { | |
| if (auto i = indexOf(ComputeId(a))) { | |
| @@ -304,29 +304,29 @@ | |
| return *j - *i; | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| void SharedMediaWithLastSlice::reverse() { | |
| _reversed = !_reversed; | |
| } | |
| -base::optional<PhotoId> SharedMediaWithLastSlice::LastPeerPhotoId( | |
| +std::optional<PhotoId> SharedMediaWithLastSlice::LastPeerPhotoId( | |
| PeerId peerId) { | |
| if (auto peer = App::peerLoaded(peerId)) { | |
| return peer->userpicPhotoUnknown() | |
| - ? base::none | |
| + ? std::nullopt | |
| : base::make_optional(peer->userpicPhotoId()); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| -base::optional<bool> SharedMediaWithLastSlice::IsLastIsolated( | |
| +std::optional<bool> SharedMediaWithLastSlice::IsLastIsolated( | |
| const SparseIdsMergedSlice &slice, | |
| - const base::optional<SparseIdsMergedSlice> &ending, | |
| - base::optional<PhotoId> lastPeerPhotoId) { | |
| + const std::optional<SparseIdsMergedSlice> &ending, | |
| + std::optional<PhotoId> lastPeerPhotoId) { | |
| if (!lastPeerPhotoId) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } else if (!*lastPeerPhotoId) { | |
| return false; | |
| } | |
| @@ -338,12 +338,12 @@ | |
| | [&](PhotoId photoId) { return *lastPeerPhotoId != photoId; }; | |
| } | |
| -base::optional<FullMsgId> SharedMediaWithLastSlice::LastFullMsgId( | |
| +std::optional<FullMsgId> SharedMediaWithLastSlice::LastFullMsgId( | |
| const SparseIdsMergedSlice &slice) { | |
| if (slice.fullCount() == 0) { | |
| return FullMsgId(); | |
| } else if (slice.size() == 0 || slice.skippedAfter() != 0) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return slice[slice.size() - 1]; | |
| } | |
| @@ -364,7 +364,7 @@ | |
| consumer.put_next(SharedMediaWithLastSlice( | |
| key, | |
| std::move(update), | |
| - base::none)); | |
| + std::nullopt)); | |
| }); | |
| } | |
| return rpl::combine( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_shared_media.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_shared_media.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_shared_media.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_shared_media.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -11,7 +11,7 @@ | |
| #include "base/weak_ptr.h" | |
| #include "data/data_sparse_ids.h" | |
| -base::optional<Storage::SharedMediaType> SharedMediaOverviewType( | |
| +std::optional<Storage::SharedMediaType> SharedMediaOverviewType( | |
| Storage::SharedMediaType type); | |
| void SharedMediaShowOverview( | |
| Storage::SharedMediaType type, | |
| @@ -93,15 +93,15 @@ | |
| SharedMediaWithLastSlice( | |
| Key key, | |
| SparseIdsMergedSlice slice, | |
| - base::optional<SparseIdsMergedSlice> ending); | |
| + std::optional<SparseIdsMergedSlice> ending); | |
| - base::optional<int> fullCount() const; | |
| - base::optional<int> skippedBefore() const; | |
| - base::optional<int> skippedAfter() const; | |
| - base::optional<int> indexOf(Value fullId) const; | |
| + std::optional<int> fullCount() const; | |
| + std::optional<int> skippedBefore() const; | |
| + std::optional<int> skippedAfter() const; | |
| + std::optional<int> indexOf(Value fullId) const; | |
| int size() const; | |
| Value operator[](int index) const; | |
| - base::optional<int> distance(const Key &a, const Key &b) const; | |
| + std::optional<int> distance(const Key &a, const Key &b) const; | |
| void reverse(); | |
| @@ -123,23 +123,23 @@ | |
| } | |
| private: | |
| - static base::optional<SparseIdsMergedSlice> EndingSlice(const Key &key) { | |
| + static std::optional<SparseIdsMergedSlice> EndingSlice(const Key &key) { | |
| return base::get_if<MessageId>(&key.universalId) | |
| ? base::make_optional(SparseIdsMergedSlice(EndingKey(key))) | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| - static base::optional<PhotoId> LastPeerPhotoId(PeerId peerId); | |
| - static base::optional<bool> IsLastIsolated( | |
| + static std::optional<PhotoId> LastPeerPhotoId(PeerId peerId); | |
| + static std::optional<bool> IsLastIsolated( | |
| const SparseIdsMergedSlice &slice, | |
| - const base::optional<SparseIdsMergedSlice> &ending, | |
| - base::optional<PhotoId> lastPeerPhotoId); | |
| - static base::optional<FullMsgId> LastFullMsgId( | |
| + const std::optional<SparseIdsMergedSlice> &ending, | |
| + std::optional<PhotoId> lastPeerPhotoId); | |
| + static std::optional<FullMsgId> LastFullMsgId( | |
| const SparseIdsMergedSlice &slice); | |
| - static base::optional<int> Add( | |
| - const base::optional<int> &a, | |
| - const base::optional<int> &b) { | |
| - return (a && b) ? base::make_optional(*a + *b) : base::none; | |
| + static std::optional<int> Add( | |
| + const std::optional<int> &a, | |
| + const std::optional<int> &b) { | |
| + return (a && b) ? base::make_optional(*a + *b) : std::nullopt; | |
| } | |
| static Value ComputeId(PeerId peerId, MsgId msgId) { | |
| return FullMsgId( | |
| @@ -158,20 +158,20 @@ | |
| bool isolatedInSlice() const { | |
| return (_slice.skippedAfter() != 0); | |
| } | |
| - base::optional<int> lastPhotoSkip() const { | |
| + std::optional<int> lastPhotoSkip() const { | |
| return _isolatedLastPhoto | |
| | [](bool isolated) { return isolated ? 1 : 0; }; | |
| } | |
| - base::optional<int> skippedBeforeImpl() const; | |
| - base::optional<int> skippedAfterImpl() const; | |
| - base::optional<int> indexOfImpl(Value fullId) const; | |
| + std::optional<int> skippedBeforeImpl() const; | |
| + std::optional<int> skippedAfterImpl() const; | |
| + std::optional<int> indexOfImpl(Value fullId) const; | |
| Key _key; | |
| SparseIdsMergedSlice _slice; | |
| - base::optional<SparseIdsMergedSlice> _ending; | |
| - base::optional<PhotoId> _lastPhotoId; | |
| - base::optional<bool> _isolatedLastPhoto; | |
| + std::optional<SparseIdsMergedSlice> _ending; | |
| + std::optional<PhotoId> _lastPhotoId; | |
| + std::optional<bool> _isolatedLastPhoto; | |
| bool _reversed = false; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_sparse_ids.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_sparse_ids.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_sparse_ids.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_sparse_ids.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -13,9 +13,9 @@ | |
| SparseIdsSlice::SparseIdsSlice( | |
| const base::flat_set<MsgId> &ids, | |
| MsgRange range, | |
| - base::optional<int> fullCount, | |
| - base::optional<int> skippedBefore, | |
| - base::optional<int> skippedAfter) | |
| + std::optional<int> fullCount, | |
| + std::optional<int> skippedBefore, | |
| + std::optional<int> skippedAfter) | |
| : _ids(ids) | |
| , _range(range) | |
| , _fullCount(fullCount) | |
| @@ -23,12 +23,12 @@ | |
| , _skippedAfter(skippedAfter) { | |
| } | |
| -base::optional<int> SparseIdsSlice::indexOf(MsgId msgId) const { | |
| +std::optional<int> SparseIdsSlice::indexOf(MsgId msgId) const { | |
| auto it = _ids.find(msgId); | |
| if (it != _ids.end()) { | |
| return (it - _ids.begin()); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| MsgId SparseIdsSlice::operator[](int index) const { | |
| @@ -37,7 +37,7 @@ | |
| return *(_ids.begin() + index); | |
| } | |
| -base::optional<int> SparseIdsSlice::distance( | |
| +std::optional<int> SparseIdsSlice::distance( | |
| MsgId a, | |
| MsgId b) const { | |
| if (auto i = indexOf(a)) { | |
| @@ -45,14 +45,14 @@ | |
| return *j - *i; | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| -base::optional<MsgId> SparseIdsSlice::nearest(MsgId msgId) const { | |
| +std::optional<MsgId> SparseIdsSlice::nearest(MsgId msgId) const { | |
| if (auto it = ranges::lower_bound(_ids, msgId); it != _ids.end()) { | |
| return *it; | |
| } else if (_ids.empty()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return _ids.back(); | |
| } | |
| @@ -67,19 +67,19 @@ | |
| SparseIdsMergedSlice::SparseIdsMergedSlice( | |
| Key key, | |
| SparseIdsSlice part, | |
| - base::optional<SparseIdsSlice> migrated) | |
| + std::optional<SparseIdsSlice> migrated) | |
| : _key(key) | |
| , _part(std::move(part)) | |
| , _migrated(std::move(migrated)) { | |
| } | |
| -base::optional<int> SparseIdsMergedSlice::fullCount() const { | |
| +std::optional<int> SparseIdsMergedSlice::fullCount() const { | |
| return Add( | |
| _part.fullCount(), | |
| _migrated ? _migrated->fullCount() : 0); | |
| } | |
| -base::optional<int> SparseIdsMergedSlice::skippedBefore() const { | |
| +std::optional<int> SparseIdsMergedSlice::skippedBefore() const { | |
| return Add( | |
| isolatedInMigrated() ? 0 : _part.skippedBefore(), | |
| _migrated | |
| @@ -90,22 +90,22 @@ | |
| ); | |
| } | |
| -base::optional<int> SparseIdsMergedSlice::skippedAfter() const { | |
| +std::optional<int> SparseIdsMergedSlice::skippedAfter() const { | |
| return Add( | |
| isolatedInMigrated() ? _part.fullCount() : _part.skippedAfter(), | |
| isolatedInPart() ? 0 : _migrated->skippedAfter() | |
| ); | |
| } | |
| -base::optional<int> SparseIdsMergedSlice::indexOf( | |
| +std::optional<int> SparseIdsMergedSlice::indexOf( | |
| FullMsgId fullId) const { | |
| return isFromPart(fullId) | |
| ? (_part.indexOf(fullId.msg) | func::add(migratedSize())) | |
| : isolatedInPart() | |
| - ? base::none | |
| + ? std::nullopt | |
| : isFromMigrated(fullId) | |
| ? _migrated->indexOf(fullId.msg) | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| int SparseIdsMergedSlice::size() const { | |
| @@ -125,7 +125,7 @@ | |
| return ComputeId(_key.peerId, _part[index]); | |
| } | |
| -base::optional<int> SparseIdsMergedSlice::distance( | |
| +std::optional<int> SparseIdsMergedSlice::distance( | |
| const Key &a, | |
| const Key &b) const { | |
| if (auto i = indexOf(ComputeId(a))) { | |
| @@ -133,11 +133,11 @@ | |
| return *j - *i; | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto SparseIdsMergedSlice::nearest( | |
| - UniversalMsgId id) const -> base::optional<FullMsgId> { | |
| + UniversalMsgId id) const -> std::optional<FullMsgId> { | |
| auto convertFromPartNearest = [&](MsgId result) { | |
| return ComputeId(_key.peerId, result); | |
| }; | |
| @@ -149,18 +149,18 @@ | |
| return partNearestId | |
| | convertFromPartNearest; | |
| } else if (isolatedInPart()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return _migrated->nearest(ServerMaxMsgId - 1) | |
| | convertFromMigratedNearest; | |
| } | |
| if (auto migratedNearestId = _migrated | |
| ? _migrated->nearest(id + ServerMaxMsgId) | |
| - : base::none) { | |
| + : std::nullopt) { | |
| return migratedNearestId | |
| | convertFromMigratedNearest; | |
| } else if (isolatedInMigrated()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return _part.nearest(0) | |
| | convertFromPartNearest; | |
| @@ -201,10 +201,10 @@ | |
| } | |
| auto skippedBefore = (update.range.from == 0) | |
| ? 0 | |
| - : base::optional<int> {}; | |
| + : std::optional<int> {}; | |
| auto skippedAfter = (update.range.till == ServerMaxMsgId) | |
| ? 0 | |
| - : base::optional<int> {}; | |
| + : std::optional<int> {}; | |
| mergeSliceData( | |
| update.count, | |
| needMergeMessages | |
| @@ -253,7 +253,7 @@ | |
| } | |
| bool SparseIdsSliceBuilder::invalidateBottom() { | |
| - _fullCount = _skippedAfter = base::none; | |
| + _fullCount = _skippedAfter = std::nullopt; | |
| if (_range.till == ServerMaxMsgId) { | |
| _range.till = _ids.empty() ? _range.from : _ids.back(); | |
| } | |
| @@ -266,10 +266,10 @@ | |
| } | |
| void SparseIdsSliceBuilder::mergeSliceData( | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| const base::flat_set<MsgId> &messageIds, | |
| - base::optional<int> skippedBefore, | |
| - base::optional<int> skippedAfter) { | |
| + std::optional<int> skippedBefore, | |
| + std::optional<int> skippedAfter) { | |
| if (messageIds.empty()) { | |
| if (count && _fullCount != count) { | |
| _fullCount = count; | |
| @@ -299,7 +299,7 @@ | |
| } else if (wasMinId >= 0 && _skippedBefore) { | |
| adjustSkippedBefore(wasMinId, *_skippedBefore); | |
| } else { | |
| - _skippedBefore = base::none; | |
| + _skippedBefore = std::nullopt; | |
| } | |
| auto adjustSkippedAfter = [&](MsgId oldId, int oldSkippedAfter) { | |
| @@ -313,7 +313,7 @@ | |
| } else if (wasMaxId >= 0 && _skippedAfter) { | |
| adjustSkippedAfter(wasMaxId, *_skippedAfter); | |
| } else { | |
| - _skippedAfter = base::none; | |
| + _skippedAfter = std::nullopt; | |
| } | |
| fillSkippedAndSliceToLimits(); | |
| } | |
| @@ -420,7 +420,7 @@ | |
| consumer.put_next(SparseIdsMergedSlice( | |
| key, | |
| std::move(part), | |
| - base::none)); | |
| + std::nullopt)); | |
| }); | |
| } | |
| auto migratedViewer = simpleViewer( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_sparse_ids.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_sparse_ids.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_sparse_ids.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_sparse_ids.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -22,25 +22,25 @@ | |
| SparseIdsSlice( | |
| const base::flat_set<MsgId> &ids, | |
| MsgRange range, | |
| - base::optional<int> fullCount, | |
| - base::optional<int> skippedBefore, | |
| - base::optional<int> skippedAfter); | |
| - | |
| - base::optional<int> fullCount() const { return _fullCount; } | |
| - base::optional<int> skippedBefore() const { return _skippedBefore; } | |
| - base::optional<int> skippedAfter() const { return _skippedAfter; } | |
| - base::optional<int> indexOf(MsgId msgId) const; | |
| + std::optional<int> fullCount, | |
| + std::optional<int> skippedBefore, | |
| + std::optional<int> skippedAfter); | |
| + | |
| + std::optional<int> fullCount() const { return _fullCount; } | |
| + std::optional<int> skippedBefore() const { return _skippedBefore; } | |
| + std::optional<int> skippedAfter() const { return _skippedAfter; } | |
| + std::optional<int> indexOf(MsgId msgId) const; | |
| int size() const { return _ids.size(); } | |
| MsgId operator[](int index) const; | |
| - base::optional<int> distance(MsgId a, MsgId b) const; | |
| - base::optional<MsgId> nearest(MsgId msgId) const; | |
| + std::optional<int> distance(MsgId a, MsgId b) const; | |
| + std::optional<MsgId> nearest(MsgId msgId) const; | |
| private: | |
| base::flat_set<MsgId> _ids; | |
| MsgRange _range; | |
| - base::optional<int> _fullCount; | |
| - base::optional<int> _skippedBefore; | |
| - base::optional<int> _skippedAfter; | |
| + std::optional<int> _fullCount; | |
| + std::optional<int> _skippedBefore; | |
| + std::optional<int> _skippedAfter; | |
| }; | |
| @@ -76,16 +76,16 @@ | |
| SparseIdsMergedSlice( | |
| Key key, | |
| SparseIdsSlice part, | |
| - base::optional<SparseIdsSlice> migrated); | |
| + std::optional<SparseIdsSlice> migrated); | |
| - base::optional<int> fullCount() const; | |
| - base::optional<int> skippedBefore() const; | |
| - base::optional<int> skippedAfter() const; | |
| - base::optional<int> indexOf(FullMsgId fullId) const; | |
| + std::optional<int> fullCount() const; | |
| + std::optional<int> skippedBefore() const; | |
| + std::optional<int> skippedAfter() const; | |
| + std::optional<int> indexOf(FullMsgId fullId) const; | |
| int size() const; | |
| FullMsgId operator[](int index) const; | |
| - base::optional<int> distance(const Key &a, const Key &b) const; | |
| - base::optional<FullMsgId> nearest(UniversalMsgId id) const; | |
| + std::optional<int> distance(const Key &a, const Key &b) const; | |
| + std::optional<FullMsgId> nearest(UniversalMsgId id) const; | |
| using SimpleViewerFunction = rpl::producer<SparseIdsSlice>( | |
| PeerId peerId, | |
| @@ -107,10 +107,10 @@ | |
| ? (ServerMaxMsgId + key.universalId) | |
| : (key.universalId > 0) ? (ServerMaxMsgId - 1) : 0; | |
| } | |
| - static base::optional<SparseIdsSlice> MigratedSlice(const Key &key) { | |
| + static std::optional<SparseIdsSlice> MigratedSlice(const Key &key) { | |
| return key.migratedPeerId | |
| ? base::make_optional(SparseIdsSlice()) | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| static bool IsFromSlice(PeerId peerId, FullMsgId fullId) { | |
| @@ -128,10 +128,10 @@ | |
| ? ComputeId(key.peerId, key.universalId) | |
| : ComputeId(key.migratedPeerId, ServerMaxMsgId + key.universalId); | |
| } | |
| - static base::optional<int> Add( | |
| - const base::optional<int> &a, | |
| - const base::optional<int> &b) { | |
| - return (a && b) ? base::make_optional(*a + *b) : base::none; | |
| + static std::optional<int> Add( | |
| + const std::optional<int> &a, | |
| + const std::optional<int> &b) { | |
| + return (a && b) ? base::make_optional(*a + *b) : std::nullopt; | |
| } | |
| bool isFromPart(FullMsgId fullId) const { | |
| @@ -156,7 +156,7 @@ | |
| Key _key; | |
| SparseIdsSlice _part; | |
| - base::optional<SparseIdsSlice> _migrated; | |
| + std::optional<SparseIdsSlice> _migrated; | |
| }; | |
| @@ -200,17 +200,17 @@ | |
| void sliceToLimits(); | |
| void mergeSliceData( | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| const base::flat_set<MsgId> &messageIds, | |
| - base::optional<int> skippedBefore = base::none, | |
| - base::optional<int> skippedAfter = base::none); | |
| + std::optional<int> skippedBefore = std::nullopt, | |
| + std::optional<int> skippedAfter = std::nullopt); | |
| Key _key; | |
| base::flat_set<MsgId> _ids; | |
| MsgRange _range; | |
| - base::optional<int> _fullCount; | |
| - base::optional<int> _skippedBefore; | |
| - base::optional<int> _skippedAfter; | |
| + std::optional<int> _fullCount; | |
| + std::optional<int> _skippedBefore; | |
| + std::optional<int> _skippedAfter; | |
| int _limitBefore = 0; | |
| int _limitAfter = 0; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_types.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_types.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_types.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_types.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,6 +9,72 @@ | |
| #include "data/data_document.h" | |
| #include "ui/widgets/input_fields.h" | |
| +#include "storage/cache/storage_cache_types.h" | |
| +#include "base/openssl_help.h" | |
| + | |
| +namespace Data { | |
| +namespace { | |
| + | |
| +constexpr auto kDocumentCacheTag = 0x0000000000000100ULL; | |
| +constexpr auto kDocumentCacheMask = 0x00000000000000FFULL; | |
| +constexpr auto kStorageCacheTag = 0x0000010000000000ULL; | |
| +constexpr auto kStorageCacheMask = 0x000000FFFFFFFFFFULL; | |
| +constexpr auto kWebDocumentCacheTag = 0x0000020000000000ULL; | |
| +constexpr auto kWebDocumentCacheMask = 0x000000FFFFFFFFFFULL; | |
| +constexpr auto kUrlCacheTag = 0x0000030000000000ULL; | |
| +constexpr auto kUrlCacheMask = 0x000000FFFFFFFFFFULL; | |
| + | |
| +} // namespace | |
| + | |
| +Storage::Cache::Key DocumentCacheKey(int32 dcId, uint64 id) { | |
| + return Storage::Cache::Key{ | |
| + Data::kDocumentCacheTag | (uint64(dcId) & Data::kDocumentCacheMask), | |
| + id | |
| + }; | |
| +} | |
| + | |
| +Storage::Cache::Key StorageCacheKey(const StorageImageLocation &location) { | |
| + const auto dcId = uint64(location.dc()) & 0xFFULL; | |
| + return Storage::Cache::Key{ | |
| + Data::kStorageCacheTag | (dcId << 32) | uint32(location.local()), | |
| + location.volume() | |
| + }; | |
| +} | |
| + | |
| +Storage::Cache::Key WebDocumentCacheKey(const WebFileLocation &location) { | |
| + const auto dcId = uint64(location.dc()) & 0xFFULL; | |
| + const auto url = location.url(); | |
| + const auto hash = openssl::Sha256(bytes::make_span(url)); | |
| + const auto bytes = bytes::make_span(hash); | |
| + const auto bytes1 = bytes.subspan(0, sizeof(uint32)); | |
| + const auto bytes2 = bytes.subspan(sizeof(uint32), sizeof(uint64)); | |
| + const auto part1 = *reinterpret_cast<const uint32*>(bytes1.data()); | |
| + const auto part2 = *reinterpret_cast<const uint64*>(bytes2.data()); | |
| + return Storage::Cache::Key{ | |
| + Data::kWebDocumentCacheTag | (dcId << 32) | part1, | |
| + part2 | |
| + }; | |
| +} | |
| + | |
| +Storage::Cache::Key UrlCacheKey(const QString &location) { | |
| + const auto url = location.toUtf8(); | |
| + const auto hash = openssl::Sha256(bytes::make_span(url)); | |
| + const auto bytes = bytes::make_span(hash); | |
| + const auto bytes1 = bytes.subspan(0, sizeof(uint32)); | |
| + const auto bytes2 = bytes.subspan(sizeof(uint32), sizeof(uint64)); | |
| + const auto bytes3 = bytes.subspan( | |
| + sizeof(uint32) + sizeof(uint64), | |
| + sizeof(uint16)); | |
| + const auto part1 = *reinterpret_cast<const uint32*>(bytes1.data()); | |
| + const auto part2 = *reinterpret_cast<const uint64*>(bytes2.data()); | |
| + const auto part3 = *reinterpret_cast<const uint16*>(bytes3.data()); | |
| + return Storage::Cache::Key{ | |
| + Data::kUrlCacheTag | (uint64(part3) << 32) | part1, | |
| + part2 | |
| + }; | |
| +} | |
| + | |
| +} // namespace Data | |
| void AudioMsgId::setTypeFromAudio() { | |
| if (_audio->isVoiceMessage() || _audio->isVideoMessage()) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_types.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_types.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_types.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_types.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,6 +10,12 @@ | |
| #include "base/value_ordering.h" | |
| #include "ui/text/text.h" // For QFIXED_MAX | |
| +namespace Storage { | |
| +namespace Cache { | |
| +struct Key; | |
| +} // namespace Cache | |
| +} // namespace Storage | |
| + | |
| class HistoryItem; | |
| using HistoryItemsList = std::vector<not_null<HistoryItem*>>; | |
| @@ -17,6 +23,9 @@ | |
| class InputField; | |
| } // namespace Ui | |
| +class StorageImageLocation; | |
| +class WebFileLocation; | |
| + | |
| namespace Data { | |
| struct UploadState { | |
| @@ -27,6 +36,17 @@ | |
| bool waitingForAlbum = false; | |
| }; | |
| +Storage::Cache::Key DocumentCacheKey(int32 dcId, uint64 id); | |
| +Storage::Cache::Key StorageCacheKey(const StorageImageLocation &location); | |
| +Storage::Cache::Key WebDocumentCacheKey(const WebFileLocation &location); | |
| +Storage::Cache::Key UrlCacheKey(const QString &location); | |
| + | |
| +constexpr auto kImageCacheTag = uint8(0x01); | |
| +constexpr auto kStickerCacheTag = uint8(0x02); | |
| +constexpr auto kVoiceMessageCacheTag = uint8(0x03); | |
| +constexpr auto kVideoMessageCacheTag = uint8(0x04); | |
| +constexpr auto kAnimationCacheTag = uint8(0x05); | |
| + | |
| } // namespace Data | |
| struct MessageGroupId { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_user_photos.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_user_photos.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_user_photos.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_user_photos.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -29,16 +29,16 @@ | |
| private: | |
| void mergeSliceData( | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| const std::deque<PhotoId> &photoIds, | |
| - base::optional<int> skippedBefore, | |
| + std::optional<int> skippedBefore, | |
| int skippedAfter); | |
| void sliceToLimits(); | |
| Key _key; | |
| std::deque<PhotoId> _ids; | |
| - base::optional<int> _fullCount; | |
| - base::optional<int> _skippedBefore; | |
| + std::optional<int> _fullCount; | |
| + std::optional<int> _skippedBefore; | |
| int _skippedAfter = 0; | |
| int _limitBefore = 0; | |
| int _limitAfter = 0; | |
| @@ -51,17 +51,17 @@ | |
| : UserPhotosSlice( | |
| key, | |
| {}, | |
| - base::none, | |
| - base::none, | |
| - base::none) { | |
| + std::nullopt, | |
| + std::nullopt, | |
| + std::nullopt) { | |
| } | |
| UserPhotosSlice::UserPhotosSlice( | |
| Key key, | |
| std::deque<PhotoId> &&ids, | |
| - base::optional<int> fullCount, | |
| - base::optional<int> skippedBefore, | |
| - base::optional<int> skippedAfter) | |
| + std::optional<int> fullCount, | |
| + std::optional<int> skippedBefore, | |
| + std::optional<int> skippedAfter) | |
| : _key(key) | |
| , _ids(std::move(ids)) | |
| , _fullCount(fullCount) | |
| @@ -74,12 +74,12 @@ | |
| std::swap(_skippedBefore, _skippedAfter); | |
| } | |
| -base::optional<int> UserPhotosSlice::indexOf(PhotoId photoId) const { | |
| +std::optional<int> UserPhotosSlice::indexOf(PhotoId photoId) const { | |
| auto it = ranges::find(_ids, photoId); | |
| if (it != _ids.end()) { | |
| return (it - _ids.begin()); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| PhotoId UserPhotosSlice::operator[](int index) const { | |
| @@ -88,17 +88,17 @@ | |
| return *(_ids.begin() + index); | |
| } | |
| -base::optional<int> UserPhotosSlice::distance(const Key &a, const Key &b) const { | |
| +std::optional<int> UserPhotosSlice::distance(const Key &a, const Key &b) const { | |
| if (a.userId != _key.userId | |
| || b.userId != _key.userId) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| if (auto i = indexOf(a.photoId)) { | |
| if (auto j = indexOf(b.photoId)) { | |
| return *j - *i; | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| UserPhotosSliceBuilder::UserPhotosSliceBuilder( | |
| @@ -137,9 +137,9 @@ | |
| } | |
| void UserPhotosSliceBuilder::mergeSliceData( | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| const std::deque<PhotoId> &photoIds, | |
| - base::optional<int> skippedBefore, | |
| + std::optional<int> skippedBefore, | |
| int skippedAfter) { | |
| if (photoIds.empty()) { | |
| if (_fullCount != count) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_user_photos.h work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_user_photos.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/data/data_user_photos.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/data/data_user_photos.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -18,28 +18,28 @@ | |
| UserPhotosSlice( | |
| Key key, | |
| std::deque<PhotoId> &&ids, | |
| - base::optional<int> fullCount, | |
| - base::optional<int> skippedBefore, | |
| - base::optional<int> skippedAfter); | |
| + std::optional<int> fullCount, | |
| + std::optional<int> skippedBefore, | |
| + std::optional<int> skippedAfter); | |
| void reverse(); | |
| const Key &key() const { return _key; } | |
| - base::optional<int> fullCount() const { return _fullCount; } | |
| - base::optional<int> skippedBefore() const { return _skippedBefore; } | |
| - base::optional<int> skippedAfter() const { return _skippedAfter; } | |
| - base::optional<int> indexOf(PhotoId msgId) const; | |
| + std::optional<int> fullCount() const { return _fullCount; } | |
| + std::optional<int> skippedBefore() const { return _skippedBefore; } | |
| + std::optional<int> skippedAfter() const { return _skippedAfter; } | |
| + std::optional<int> indexOf(PhotoId msgId) const; | |
| int size() const { return _ids.size(); } | |
| PhotoId operator[](int index) const; | |
| - base::optional<int> distance(const Key &a, const Key &b) const; | |
| + std::optional<int> distance(const Key &a, const Key &b) const; | |
| private: | |
| Key _key; | |
| std::deque<PhotoId> _ids; | |
| - base::optional<int> _fullCount; | |
| - base::optional<int> _skippedBefore; | |
| - base::optional<int> _skippedAfter; | |
| + std::optional<int> _fullCount; | |
| + std::optional<int> _skippedBefore; | |
| + std::optional<int> _skippedAfter; | |
| friend class UserPhotosSliceBuilder; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -219,7 +219,9 @@ | |
| auto fullWidth = getFullWidth(); | |
| auto ms = getms(); | |
| if (_state == State::Default) { | |
| - _a_pinnedShifting.step(ms, false); | |
| + if (_a_pinnedShifting.animating()) { | |
| + _a_pinnedShifting.step(ms, false); | |
| + } | |
| auto rows = shownDialogs(); | |
| auto dialogsClip = r; | |
| @@ -834,6 +836,10 @@ | |
| rtlupdate(0, searchedOffset() + index * st::dialogsRowHeight, getFullWidth(), st::dialogsRowHeight); | |
| }); | |
| } | |
| + if (anim::Disabled() | |
| + && (!_pressed || !_pressed->entry()->isPinnedDialog())) { | |
| + mousePressReleased(e->button()); | |
| + } | |
| } | |
| void DialogsInner::checkReorderPinnedStart(QPoint localPosition) { | |
| @@ -1000,12 +1006,18 @@ | |
| } | |
| void DialogsInner::step_pinnedShifting(TimeMs ms, bool timer) { | |
| + if (anim::Disabled()) { | |
| + ms += st::stickersRowDuration; | |
| + } | |
| + | |
| + auto wasAnimating = false; | |
| auto animating = false; | |
| auto updateMin = -1; | |
| auto updateMax = 0; | |
| for (auto i = 0, l = static_cast<int>(_pinnedRows.size()); i != l; ++i) { | |
| auto start = _pinnedRows[i].animStartTime; | |
| if (start) { | |
| + wasAnimating = true; | |
| if (updateMin < 0) updateMin = i; | |
| updateMax = i; | |
| if (start + st::stickersRowDuration > ms && ms >= start) { | |
| @@ -1017,7 +1029,7 @@ | |
| } | |
| } | |
| } | |
| - if (timer) { | |
| + if (timer || (wasAnimating && !animating)) { | |
| updateReorderIndexGetCount(); | |
| if (_draggingIndex >= 0) { | |
| if (updateMin < 0 || updateMin > _draggingIndex) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/dialogs/dialogs_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/dialogs/dialogs_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/dialogs/dialogs_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/dialogs/dialogs_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -232,7 +232,7 @@ | |
| } | |
| void DialogsWidget::dialogsToUp() { | |
| - if (_filter->getLastText().trimmed().isEmpty()) { | |
| + if (_filter->getLastText().trimmed().isEmpty() && !_searchInChat) { | |
| _scroll->scrollToY(0); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/data/export_data_types.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/data/export_data_types.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/data/export_data_types.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/data/export_data_types.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,7 +10,7 @@ | |
| #include "export/export_settings.h" | |
| #include "export/output/export_output_file.h" | |
| #include "core/mime_type.h" | |
| - | |
| +#include "core/utils.h" | |
| #include <QtCore/QDateTime> | |
| #include <QtCore/QRegularExpression> | |
| #include <QtGui/QImageReader> | |
| @@ -30,6 +30,19 @@ | |
| constexpr auto kChatPeerIdShift = (2ULL << 32); | |
| constexpr auto kMaxImageSize = 10000; | |
| +QString PrepareFileNameDatePart(TimeId date) { | |
| + return date | |
| + ? ('@' + QString::fromUtf8(FormatDateTime(date, '-', '-', '_'))) | |
| + : QString(); | |
| +} | |
| + | |
| +QString PreparePhotoFileName(int index, TimeId date) { | |
| + return "photo_" | |
| + + QString::number(index) | |
| + + PrepareFileNameDatePart(date) | |
| + + ".jpg"; | |
| +} | |
| + | |
| } // namespace | |
| PeerId UserPeerId(int32 userId) { | |
| @@ -288,7 +301,8 @@ | |
| QString ComputeDocumentName( | |
| ParseMediaContext &context, | |
| - const Document &data) { | |
| + const Document &data, | |
| + TimeId date) { | |
| if (!data.name.isEmpty()) { | |
| return QString::fromUtf8(data.name); | |
| } | |
| @@ -303,6 +317,7 @@ | |
| const auto isMP3 = hasMimeType(qstr("audio/mp3")); | |
| return qsl("audio_") | |
| + QString::number(++context.audios) | |
| + + PrepareFileNameDatePart(date) | |
| + (isMP3 ? qsl(".mp3") : qsl(".ogg")); | |
| } else if (data.isVideoFile) { | |
| const auto extension = pattern.isEmpty() | |
| @@ -310,6 +325,7 @@ | |
| : QString(pattern).replace('*', QString()); | |
| return qsl("video_") | |
| + QString::number(++context.videos) | |
| + + PrepareFileNameDatePart(date) | |
| + extension; | |
| } else { | |
| const auto extension = pattern.isEmpty() | |
| @@ -317,6 +333,7 @@ | |
| : QString(pattern).replace('*', QString()); | |
| return qsl("file_") | |
| + QString::number(++context.files) | |
| + + PrepareFileNameDatePart(date) | |
| + extension; | |
| } | |
| } | |
| @@ -386,7 +403,8 @@ | |
| Document ParseDocument( | |
| ParseMediaContext &context, | |
| const MTPDocument &data, | |
| - const QString &suggestedFolder) { | |
| + const QString &suggestedFolder, | |
| + TimeId date) { | |
| auto result = Document(); | |
| data.match([&](const MTPDdocument &data) { | |
| result.id = data.vid.v; | |
| @@ -402,7 +420,7 @@ | |
| data.vfile_reference); | |
| const auto path = result.file.suggestedPath = suggestedFolder | |
| + DocumentFolder(result) + '/' | |
| - + CleanDocumentName(ComputeDocumentName(context, result)); | |
| + + CleanDocumentName(ComputeDocumentName(context, result, date)); | |
| result.thumb = data.vthumb.match([](const MTPDphotoSizeEmpty &) { | |
| return Image(); | |
| @@ -497,7 +515,11 @@ | |
| result.list.reserve(list.size()); | |
| for (const auto &photo : list) { | |
| const auto suggestedPath = "profile_pictures/" | |
| - "photo_" + QString::number(++baseIndex) + ".jpg"; | |
| + + PreparePhotoFileName( | |
| + ++baseIndex, | |
| + (photo.type() == mtpc_photo | |
| + ? photo.c_photo().vdate.v | |
| + : TimeId(0))); | |
| result.list.push_back(ParsePhoto(photo, suggestedPath)); | |
| } | |
| return result; | |
| @@ -507,8 +529,8 @@ | |
| const QString &basePath, | |
| const QString &largePath, | |
| Fn<QSize(QSize)> convertSize, | |
| - base::optional<QByteArray> format, | |
| - base::optional<int> quality, | |
| + std::optional<QByteArray> format, | |
| + std::optional<int> quality, | |
| const QString &postfix) { | |
| if (largePath.isEmpty()) { | |
| return {}; | |
| @@ -560,8 +582,8 @@ | |
| basePath, | |
| largePath, | |
| [=](QSize size) { return QSize(width, height); }, | |
| - base::none, | |
| - base::none, | |
| + std::nullopt, | |
| + std::nullopt, | |
| postfix).first; | |
| } | |
| @@ -802,7 +824,8 @@ | |
| Media ParseMedia( | |
| ParseMediaContext &context, | |
| const MTPMessageMedia &data, | |
| - const QString &folder) { | |
| + const QString &folder, | |
| + TimeId date) { | |
| Expects(folder.isEmpty() || folder.endsWith(QChar('/'))); | |
| auto result = Media(); | |
| @@ -810,8 +833,9 @@ | |
| auto photo = data.has_photo() | |
| ? ParsePhoto( | |
| data.vphoto, | |
| - folder + "photos/" | |
| - "photo_" + QString::number(++context.photos) + ".jpg") | |
| + folder | |
| + + "photos/" | |
| + + PreparePhotoFileName(++context.photos, date)) | |
| : Photo(); | |
| if (data.has_ttl_seconds()) { | |
| result.ttl = data.vttl_seconds.v; | |
| @@ -826,7 +850,7 @@ | |
| result.content = UnsupportedMedia(); | |
| }, [&](const MTPDmessageMediaDocument &data) { | |
| auto document = data.has_document() | |
| - ? ParseDocument(context, data.vdocument, folder) | |
| + ? ParseDocument(context, data.vdocument, folder, date) | |
| : Document(); | |
| if (data.has_ttl_seconds()) { | |
| result.ttl = data.vttl_seconds.v; | |
| @@ -851,7 +875,8 @@ | |
| ServiceAction ParseServiceAction( | |
| ParseMediaContext &context, | |
| const MTPMessageAction &data, | |
| - const QString &mediaFolder) { | |
| + const QString &mediaFolder, | |
| + TimeId date) { | |
| auto result = ServiceAction(); | |
| data.match([&](const MTPDmessageActionChatCreate &data) { | |
| auto content = ActionChatCreate(); | |
| @@ -869,8 +894,9 @@ | |
| auto content = ActionChatEditPhoto(); | |
| content.photo = ParsePhoto( | |
| data.vphoto, | |
| - mediaFolder + "photos/" | |
| - "photo_" + QString::number(++context.photos) + ".jpg"); | |
| + mediaFolder | |
| + + "photos/" | |
| + + PreparePhotoFileName(++context.photos, date)); | |
| result.content = content; | |
| }, [&](const MTPDmessageActionChatDeletePhoto &data) { | |
| result.content = ActionChatDeletePhoto(); | |
| @@ -1083,7 +1109,8 @@ | |
| result.media = ParseMedia( | |
| context, | |
| data.vmedia, | |
| - mediaFolder); | |
| + mediaFolder, | |
| + result.date); | |
| if (result.media.ttl && !data.is_out()) { | |
| result.media.file() = File(); | |
| result.media.thumb().file = File(); | |
| @@ -1099,7 +1126,8 @@ | |
| result.action = ParseServiceAction( | |
| context, | |
| data.vaction, | |
| - mediaFolder); | |
| + mediaFolder, | |
| + result.date); | |
| }, [&](const MTPDmessageEmpty &data) { | |
| result.id = data.vid.v; | |
| }); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/data/export_data_types.h work/tdesktop-1.4.0/Telegram/SourceFiles/export/data/export_data_types.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/data/export_data_types.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/data/export_data_types.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -87,8 +87,8 @@ | |
| const QString &basePath, | |
| const QString &largePath, | |
| Fn<QSize(QSize)> convertSize, | |
| - base::optional<QByteArray> format = base::none, | |
| - base::optional<int> quality = base::none, | |
| + std::optional<QByteArray> format = std::nullopt, | |
| + std::optional<int> quality = std::nullopt, | |
| const QString &postfix = "_thumb"); | |
| QString WriteImageThumb( | |
| @@ -318,7 +318,8 @@ | |
| Media ParseMedia( | |
| ParseMediaContext &context, | |
| const MTPMessageMedia &data, | |
| - const QString &folder); | |
| + const QString &folder, | |
| + TimeId date); | |
| struct ActionChatCreate { | |
| Utf8String title; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_api_wrap.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_api_wrap.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_api_wrap.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_api_wrap.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -14,7 +14,6 @@ | |
| #include "mtproto/rpc_sender.h" | |
| #include "base/value_ordering.h" | |
| #include "base/bytes.h" | |
| - | |
| #include <set> | |
| #include <deque> | |
| @@ -98,7 +97,7 @@ | |
| LoadedFileCache(int limit); | |
| void save(const Location &location, const QString &relativePath); | |
| - base::optional<QString> find(const Location &location) const; | |
| + std::optional<QString> find(const Location &location) const; | |
| private: | |
| int _limit = 0; | |
| @@ -136,7 +135,7 @@ | |
| FnMut<void()> finish; | |
| int processed = 0; | |
| - base::optional<Data::UserpicsSlice> slice; | |
| + std::optional<Data::UserpicsSlice> slice; | |
| uint64 maxId = 0; | |
| bool lastSlice = false; | |
| int fileIndex = 0; | |
| @@ -208,7 +207,7 @@ | |
| int32 largestIdPlusOne = 1; | |
| Data::ParseMediaContext context; | |
| - base::optional<Data::MessagesSlice> slice; | |
| + std::optional<Data::MessagesSlice> slice; | |
| bool lastSlice = false; | |
| int fileIndex = 0; | |
| }; | |
| @@ -310,16 +309,16 @@ | |
| } | |
| } | |
| -base::optional<QString> ApiWrap::LoadedFileCache::find( | |
| +std::optional<QString> ApiWrap::LoadedFileCache::find( | |
| const Location &location) const { | |
| if (!location) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto key = ComputeLocationKey(location); | |
| if (const auto i = _map.find(key); i != end(_map)) { | |
| return i->second; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| ApiWrap::FileProcess::FileProcess(const QString &path, Output::Stats *stats) | |
| @@ -955,7 +954,7 @@ | |
| } | |
| void ApiWrap::finishExport(FnMut<void()> done) { | |
| - const auto guard = gsl::finally([&] { _takeoutId = base::none; }); | |
| + const auto guard = gsl::finally([&] { _takeoutId = std::nullopt; }); | |
| mainRequest(MTPaccount_FinishTakeoutSession( | |
| MTP_flags(MTPaccount_FinishTakeoutSession::Flag::f_success) | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_api_wrap.h work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_api_wrap.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_api_wrap.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_api_wrap.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -191,7 +191,7 @@ | |
| void ioError(const Output::Result &result); | |
| MTP::ConcurrentSender _mtp; | |
| - base::optional<uint64> _takeoutId; | |
| + std::optional<uint64> _takeoutId; | |
| Output::Stats *_stats = nullptr; | |
| std::unique_ptr<Settings> _settings; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_pch.h work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_pch.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_pch.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_pch.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -17,6 +17,10 @@ | |
| #include <QtCore/QReadWriteLock> | |
| #include <QtCore/QRegularExpression> | |
| +#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) | |
| +#define OS_MAC_OLD | |
| +#endif // QT_VERSION < 5.5.0 | |
| + | |
| #include <crl/crl.h> | |
| #include <rpl/rpl.h> | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_settings.h work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_settings.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/export_settings.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/export_settings.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -70,6 +70,7 @@ | |
| friend inline constexpr auto is_flag_type(Type) { return true; }; | |
| QString path; | |
| + bool forceSubPath = false; | |
| Output::Format format = Output::Format(); | |
| Types types = DefaultTypes(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_abstract.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_abstract.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_abstract.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_abstract.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,12 +23,12 @@ | |
| QDir folder(settings.path); | |
| const auto path = folder.absolutePath(); | |
| auto result = path.endsWith('/') ? path : (path + '/'); | |
| - if (!folder.exists()) { | |
| + if (!folder.exists() && !settings.forceSubPath) { | |
| return result; | |
| } | |
| const auto mode = QDir::AllEntries | QDir::NoDotAndDotDot; | |
| const auto list = folder.entryInfoList(mode); | |
| - if (list.isEmpty()) { | |
| + if (list.isEmpty() && !settings.forceSubPath) { | |
| return result; | |
| } | |
| const auto date = QDate::currentDate(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_file.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_file.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_file.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_file.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -32,7 +32,7 @@ | |
| Result File::writeBlock(const QByteArray &block) { | |
| const auto result = writeBlockAttempt(block); | |
| if (!result) { | |
| - _file.clear(); | |
| + _file.reset(); | |
| } | |
| return result; | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_file.h work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_file.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_file.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_file.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -46,7 +46,7 @@ | |
| QString _path; | |
| int _offset = 0; | |
| - base::optional<QFile> _file; | |
| + std::optional<QFile> _file; | |
| Stats *_stats = nullptr; | |
| bool _inStats = false; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_html.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_html.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_html.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_html.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -1058,7 +1058,7 @@ | |
| } | |
| return "You have sent the following documents: " | |
| + SerializeList(list); | |
| - }, [](const base::none_type &) { return QByteArray(); }); | |
| + }, [](std::nullopt_t) { return QByteArray(); }); | |
| if (!serviceText.isEmpty()) { | |
| const auto &content = message.action.content; | |
| @@ -1658,7 +1658,7 @@ | |
| result.status = Data::FormatMoneyAmount(data.amount, data.currency); | |
| }, [](const UnsupportedMedia &data) { | |
| Unexpected("Unsupported message."); | |
| - }, [](const base::none_type &) {}); | |
| + }, [](std::nullopt_t) {}); | |
| return result; | |
| } | |
| @@ -2276,7 +2276,7 @@ | |
| ? ((_messagesCount - 1) / kMessagesInFile) | |
| : 0; | |
| auto previous = _lastMessageInfo.get(); | |
| - auto saved = base::optional<MessageInfo>(); | |
| + auto saved = std::optional<MessageInfo>(); | |
| auto block = QByteArray(); | |
| for (const auto &message : data.list) { | |
| const auto newIndex = (_messagesCount / kMessagesInFile); | |
| @@ -2291,7 +2291,7 @@ | |
| block = QByteArray(); | |
| _lastMessageInfo = nullptr; | |
| previous = nullptr; | |
| - saved = base::none; | |
| + saved = std::nullopt; | |
| oldIndex = newIndex; | |
| } else { | |
| return next; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_json.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_json.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_json.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_json.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -458,7 +458,7 @@ | |
| }())); | |
| } | |
| pushBare("values", SerializeArray(context, list)); | |
| - }, [](const base::none_type &) {}); | |
| + }, [](std::nullopt_t) {}); | |
| if (!message.action.content) { | |
| pushFrom(); | |
| @@ -572,7 +572,7 @@ | |
| })); | |
| }, [](const UnsupportedMedia &data) { | |
| Unexpected("Unsupported message."); | |
| - }, [](const base::none_type &) {}); | |
| + }, [](std::nullopt_t) {}); | |
| pushBare("text", SerializeText(context, message.text)); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_text.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_text.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/output/export_output_text.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/output/export_output_text.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -332,7 +332,7 @@ | |
| } else if (!list.empty()) { | |
| push("Values", JoinList(", ", list)); | |
| } | |
| - }, [](const base::none_type &) {}); | |
| + }, [](std::nullopt_t) {}); | |
| if (!message.action.content) { | |
| pushFrom(); | |
| @@ -435,7 +435,7 @@ | |
| })); | |
| }, [](const UnsupportedMedia &data) { | |
| Unexpected("Unsupported message."); | |
| - }, [](const base::none_type &) {}); | |
| + }, [](std::nullopt_t) {}); | |
| auto value = JoinList(QByteArray(), ranges::view::all( | |
| message.text | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -102,13 +102,30 @@ | |
| } | |
| } | |
| +bool IsDefaultPath(const QString &path) { | |
| + const auto check = [](const QString &value) { | |
| + const auto result = value.endsWith('/') | |
| + ? value.mid(0, value.size() - 1) | |
| + : value; | |
| + return (cPlatform() == dbipWindows) ? result.toLower() : result; | |
| + }; | |
| + return (check(path) == check(psDownloadPath())); | |
| +} | |
| + | |
| +void ResolveSettings(Settings &settings) { | |
| + if (settings.path.isEmpty()) { | |
| + settings.path = psDownloadPath(); | |
| + settings.forceSubPath = true; | |
| + } else { | |
| + settings.forceSubPath = IsDefaultPath(settings.path); | |
| + } | |
| +} | |
| + | |
| PanelController::PanelController(not_null<ControllerWrap*> process) | |
| : _process(process) | |
| , _settings(std::make_unique<Settings>(Local::ReadExportSettings())) | |
| , _saveSettingsTimer([=] { saveSettings(); }) { | |
| - if (_settings->path.isEmpty()) { | |
| - _settings->path = psDownloadPath(); | |
| - } | |
| + ResolveSettings(*_settings); | |
| _process->state( | |
| ) | rpl::start_with_next([=](State &&state) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_panel_controller.h work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_panel_controller.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_panel_controller.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_panel_controller.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -27,6 +27,8 @@ | |
| Environment PrepareEnvironment(); | |
| QPointer<BoxContent> SuggestStart(); | |
| void ClearSuggestStart(); | |
| +bool IsDefaultPath(const QString &path); | |
| +void ResolveSettings(Settings &settings); | |
| class Panel; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_progress.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_progress.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_progress.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_progress.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -266,7 +266,7 @@ | |
| rpl::producer<> ProgressWidget::cancelClicks() const { | |
| return _cancel | |
| - ? _cancel->clicks() | |
| + ? (_cancel->clicks() | rpl::map([] { return rpl::empty_value(); })) | |
| : (rpl::never<>() | rpl::type_erased()); | |
| } | |
| @@ -322,7 +322,10 @@ | |
| if (_done->width() < desired) { | |
| _done->setFullWidth(desired); | |
| } | |
| - _done->clicks() | rpl::start_to_stream(_doneClicks, _done->lifetime()); | |
| + _done->clicks( | |
| + ) | rpl::map([] { | |
| + return rpl::empty_value(); | |
| + }) | rpl::start_to_stream(_doneClicks, _done->lifetime()); | |
| setupBottomButton(_done.get()); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_settings.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_settings.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_settings.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_settings.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,6 +8,7 @@ | |
| #include "export/view/export_view_settings.h" | |
| #include "export/output/export_output_abstract.h" | |
| +#include "export/view/export_view_panel_controller.h" | |
| #include "lang/lang_keys.h" | |
| #include "ui/widgets/checkbox.h" | |
| #include "ui/widgets/buttons.h" | |
| @@ -76,6 +77,7 @@ | |
| : RpWidget(parent) | |
| , _singlePeerId(ReadPeerId(data.singlePeer)) | |
| , _internal_data(std::move(data)) { | |
| + ResolveSettings(_internal_data); | |
| setupContent(); | |
| } | |
| @@ -93,9 +95,10 @@ | |
| const auto scroll = Ui::CreateChild<Ui::ScrollArea>( | |
| this, | |
| st::boxLayerScroll); | |
| - const auto wrap = scroll->setOwnedWidget(object_ptr<Ui::IgnoreMargins>( | |
| - scroll, | |
| - object_ptr<Ui::VerticalLayout>(scroll))); | |
| + const auto wrap = scroll->setOwnedWidget( | |
| + object_ptr<Ui::OverrideMargins>( | |
| + scroll, | |
| + object_ptr<Ui::VerticalLayout>(scroll))); | |
| const auto content = static_cast<Ui::VerticalLayout*>(wrap->entity()); | |
| const auto buttons = setupButtons(scroll, wrap); | |
| @@ -239,13 +242,7 @@ | |
| return data.path; | |
| }) | rpl::distinct_until_changed( | |
| ) | rpl::map([](const QString &path) { | |
| - const auto check = [](const QString &value) { | |
| - const auto result = value.endsWith('/') | |
| - ? value.mid(0, value.size() - 1) | |
| - : value; | |
| - return (cPlatform() == dbipWindows) ? result.toLower() : result; | |
| - }; | |
| - const auto text = (check(path) == check(psDownloadPath())) | |
| + const auto text = IsDefaultPath(path) | |
| ? QString("Downloads/Telegram Desktop") | |
| : path; | |
| auto pathLink = TextWithEntities{ | |
| @@ -300,7 +297,7 @@ | |
| })); | |
| value() | rpl::map([](const Settings &data) { | |
| - return data.types != Types(0); | |
| + return (data.types != Types(0)) || data.onlySinglePeer(); | |
| }) | rpl::distinct_until_changed( | |
| ) | rpl::start_with_next([=](bool canStart) { | |
| refreshButtons(buttons, canStart); | |
| @@ -469,27 +466,19 @@ | |
| object_ptr<Ui::MediaSlider>(container, st::exportFileSizeSlider), | |
| st::exportFileSizePadding); | |
| slider->resize(st::exportFileSizeSlider.seekSize); | |
| - slider->setAlwaysDisplayMarker(true); | |
| - slider->setDirection(Ui::ContinuousSlider::Direction::Horizontal); | |
| - for (auto i = 0; i != kSizeValueCount + 1; ++i) { | |
| - if (readData().media.sizeLimit <= SizeLimitByIndex(i)) { | |
| - slider->setValue(i / float64(kSizeValueCount)); | |
| - break; | |
| - } | |
| - } | |
| + slider->setPseudoDiscrete( | |
| + kSizeValueCount + 1, | |
| + SizeLimitByIndex, | |
| + readData().media.sizeLimit, | |
| + [=](int limit) { | |
| + changeData([&](Settings &data) { | |
| + data.media.sizeLimit = limit; | |
| + }); | |
| + }); | |
| const auto label = Ui::CreateChild<Ui::LabelSimple>( | |
| container.get(), | |
| st::exportFileSizeLabel); | |
| - slider->setAdjustCallback([=](float64 value) { | |
| - return std::round(value * kSizeValueCount) / kSizeValueCount; | |
| - }); | |
| - slider->setChangeProgressCallback([=](float64 value) { | |
| - const auto index = int(std::round(value * kSizeValueCount)); | |
| - changeData([&](Settings &data) { | |
| - data.media.sizeLimit = SizeLimitByIndex(index); | |
| - }); | |
| - }); | |
| value() | rpl::map([](const Settings &data) { | |
| return data.media.sizeLimit; | |
| }) | rpl::start_with_next([=](int sizeLimit) { | |
| @@ -511,7 +500,6 @@ | |
| st::exportFileSizePadding.right(), | |
| geometry.y() - label->height() - st::exportFileSizeLabelBottom); | |
| }, label->lifetime()); | |
| - | |
| } | |
| void SettingsWidget::refreshButtons( | |
| @@ -532,7 +520,10 @@ | |
| : nullptr; | |
| if (start) { | |
| start->show(); | |
| - _startClicks = start->clicks(); | |
| + _startClicks = start->clicks( | |
| + ) | rpl::map([] { | |
| + return rpl::empty_value(); | |
| + }); | |
| container->sizeValue( | |
| ) | rpl::start_with_next([=](QSize size) { | |
| @@ -547,7 +538,10 @@ | |
| langFactory(lng_cancel), | |
| st::defaultBoxButton); | |
| cancel->show(); | |
| - _cancelClicks = cancel->clicks(); | |
| + _cancelClicks = cancel->clicks( | |
| + ) | rpl::map([] { | |
| + return rpl::empty_value(); | |
| + }); | |
| rpl::combine( | |
| container->sizeValue(), | |
| @@ -564,6 +558,7 @@ | |
| const auto callback = [=](QString &&result) { | |
| changeData([&](Settings &data) { | |
| data.path = std::move(result); | |
| + data.forceSubPath = IsDefaultPath(data.path); | |
| }); | |
| }; | |
| FileDialog::GetFolder( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_top_bar.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_top_bar.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_top_bar.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_top_bar.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -30,7 +30,7 @@ | |
| updateData(std::move(content)); | |
| } | |
| -rpl::producer<> TopBar::clicks() const { | |
| +rpl::producer<Qt::MouseButton> TopBar::clicks() const { | |
| return _button->clicks(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_top_bar.h work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_top_bar.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export_view_top_bar.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export_view_top_bar.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -25,7 +25,7 @@ | |
| public: | |
| TopBar(QWidget *parent, Content &&content); | |
| - rpl::producer<> clicks() const; | |
| + rpl::producer<Qt::MouseButton> clicks() const; | |
| void updateData(Content &&content); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export.style work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export.style | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/export/view/export.style 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/export/view/export.style 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -21,16 +21,8 @@ | |
| } | |
| } | |
| exportHeaderPadding: margins(22px, 20px, 22px, 9px); | |
| -exportFileSizeSlider: MediaSlider { | |
| - width: 3px; | |
| - activeFg: mediaPlayerActiveFg; | |
| - inactiveFg: mediaPlayerInactiveFg; | |
| - activeFgOver: mediaPlayerActiveFg; | |
| - inactiveFgOver: mediaPlayerInactiveFg; | |
| - activeFgDisabled: mediaPlayerInactiveFg; | |
| - inactiveFgDisabled: windowBg; | |
| +exportFileSizeSlider: MediaSlider(defaultContinuousSlider) { | |
| seekSize: size(15px, 15px); | |
| - duration: 150; | |
| } | |
| exportFileSizeLabel: LabelSimple(defaultLabelSimple) { | |
| font: boxTextFont; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/facades.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/facades.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/facades.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/facades.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -119,7 +119,7 @@ | |
| Ui::showPeerHistory(history, ShowAtTheEndMsgId); | |
| auto options = ApiWrap::SendOptions(history); | |
| options.replyTo = msgId; | |
| - Auth().api().shareContact(App::self(), options); | |
| + Auth().api().shareContact(Auth().user(), options); | |
| })); | |
| } break; | |
| @@ -371,68 +371,128 @@ | |
| namespace Sandbox { | |
| -bool CheckBetaVersionDir() { | |
| - QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta")); | |
| - if (cBetaVersion()) { | |
| - cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/")); | |
| +bool MoveLegacyAlphaFolder() { | |
| + const auto was = cExeDir() + qsl("TelegramBeta_data"); | |
| + const auto now = cExeDir() + qsl("TelegramAlpha_data"); | |
| + if (QDir(was).exists() && !QDir(now).exists()) { | |
| + const auto oldFile = was + "/tdata/beta"; | |
| + const auto newFile = was + "/tdata/alpha"; | |
| + if (QFile(oldFile).exists() && !QFile(newFile).exists()) { | |
| + if (!QFile(oldFile).copy(newFile)) { | |
| + LOG(("FATAL: Could not copy '%1' to '%2'" | |
| + ).arg(oldFile | |
| + ).arg(newFile)); | |
| + return false; | |
| + } | |
| + } | |
| + if (!QDir().rename(was, now)) { | |
| + LOG(("FATAL: Could not rename '%1' to '%2'" | |
| + ).arg(was | |
| + ).arg(now)); | |
| + return false; | |
| + } | |
| + } | |
| + return true; | |
| +} | |
| + | |
| +bool CheckAlphaVersionDir() { | |
| + if (!MoveLegacyAlphaFolder()) { | |
| + return false; | |
| + } | |
| + QFile alpha(cExeDir() + qsl("TelegramAlpha_data/tdata/alpha")); | |
| + if (cAlphaVersion()) { | |
| + cForceWorkingDir(cExeDir() + qsl("TelegramAlpha_data/")); | |
| QDir().mkpath(cWorkingDir() + qstr("tdata")); | |
| - if (*BetaPrivateKey) { | |
| - cSetBetaPrivateKey(QByteArray(BetaPrivateKey)); | |
| + if (*AlphaPrivateKey) { | |
| + cSetAlphaPrivateKey(QByteArray(AlphaPrivateKey)); | |
| } | |
| - if (beta.open(QIODevice::WriteOnly)) { | |
| - QDataStream dataStream(&beta); | |
| + if (alpha.open(QIODevice::WriteOnly)) { | |
| + QDataStream dataStream(&alpha); | |
| dataStream.setVersion(QDataStream::Qt_5_3); | |
| - dataStream << quint64(cRealBetaVersion()) << cBetaPrivateKey(); | |
| + dataStream << quint64(cRealAlphaVersion()) << cAlphaPrivateKey(); | |
| } else { | |
| - LOG(("FATAL: Could not open '%1' for writing private key!").arg(beta.fileName())); | |
| + LOG(("FATAL: Could not open '%1' for writing private key!").arg(alpha.fileName())); | |
| return false; | |
| } | |
| - } else if (beta.exists()) { | |
| - cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/")); | |
| - if (beta.open(QIODevice::ReadOnly)) { | |
| - QDataStream dataStream(&beta); | |
| + } else if (alpha.exists()) { | |
| + cForceWorkingDir(cExeDir() + qsl("TelegramAlpha_data/")); | |
| + if (alpha.open(QIODevice::ReadOnly)) { | |
| + QDataStream dataStream(&alpha); | |
| dataStream.setVersion(QDataStream::Qt_5_3); | |
| quint64 v; | |
| QByteArray k; | |
| dataStream >> v >> k; | |
| if (dataStream.status() == QDataStream::Ok && !k.isEmpty()) { | |
| - cSetBetaVersion(AppVersion * 1000ULL); | |
| - cSetBetaPrivateKey(k); | |
| - cSetRealBetaVersion(v); | |
| + cSetAlphaVersion(AppVersion * 1000ULL); | |
| + cSetAlphaPrivateKey(k); | |
| + cSetRealAlphaVersion(v); | |
| } else { | |
| - LOG(("FATAL: '%1' is corrupted, reinstall private beta!").arg(beta.fileName())); | |
| + LOG(("FATAL: '%1' is corrupted, reinstall private alpha!").arg(alpha.fileName())); | |
| return false; | |
| } | |
| } else { | |
| - LOG(("FATAL: could not open '%1' for reading private key!").arg(beta.fileName())); | |
| + LOG(("FATAL: could not open '%1' for reading private key!").arg(alpha.fileName())); | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| -void WorkingDirReady() { | |
| +QString InstallBetaVersionsSettingPath() { | |
| + return cWorkingDir() + qsl("tdata/devversion"); | |
| +} | |
| + | |
| +void WriteInstallBetaVersionsSetting() { | |
| + QFile f(InstallBetaVersionsSettingPath()); | |
| + if (f.open(QIODevice::WriteOnly)) { | |
| + f.write(cInstallBetaVersion() ? "1" : "0"); | |
| + } | |
| +} | |
| + | |
| +QString DebugModeSettingPath() { | |
| + return cWorkingDir() + qsl("tdata/withdebug"); | |
| +} | |
| + | |
| +void WriteDebugModeSetting() { | |
| + QFile f(DebugModeSettingPath()); | |
| + if (f.open(QIODevice::WriteOnly)) { | |
| + f.write(Logs::DebugEnabled() ? "1" : "0"); | |
| + } | |
| +} | |
| + | |
| +void ComputeTestMode() { | |
| if (QFile(cWorkingDir() + qsl("tdata/withtestmode")).exists()) { | |
| cSetTestMode(true); | |
| } | |
| - if (!Logs::DebugEnabled() | |
| - && QFile(cWorkingDir() + qsl("tdata/withdebug")).exists()) { | |
| - Logs::SetDebugEnabled(true); | |
| - } | |
| - if (cBetaVersion()) { | |
| - cSetAlphaVersion(false); | |
| - } else if (!cAlphaVersion() && QFile(cWorkingDir() + qsl("tdata/devversion")).exists()) { | |
| - cSetAlphaVersion(true); | |
| - } else if (AppAlphaVersion) { | |
| - QFile f(cWorkingDir() + qsl("tdata/devversion")); | |
| - if (!f.exists() && f.open(QIODevice::WriteOnly)) { | |
| - f.write("1"); | |
| +} | |
| + | |
| +void ComputeDebugMode() { | |
| + Logs::SetDebugEnabled(cAlphaVersion() != 0); | |
| + const auto debugModeSettingPath = DebugModeSettingPath(); | |
| + if (QFile(debugModeSettingPath).exists()) { | |
| + QFile f(debugModeSettingPath); | |
| + if (f.open(QIODevice::ReadOnly)) { | |
| + Logs::SetDebugEnabled(f.read(1) != "0"); | |
| } | |
| } | |
| +} | |
| - srand((int32)time(NULL)); | |
| +void ComputeInstallBetaVersions() { | |
| + const auto installBetaSettingPath = InstallBetaVersionsSettingPath(); | |
| + if (cAlphaVersion()) { | |
| + cSetInstallBetaVersion(false); | |
| + } else if (QFile(installBetaSettingPath).exists()) { | |
| + QFile f(installBetaSettingPath); | |
| + if (f.open(QIODevice::ReadOnly)) { | |
| + cSetInstallBetaVersion(f.read(1) != "0"); | |
| + } | |
| + } else if (AppBetaVersion) { | |
| + WriteInstallBetaVersionsSetting(); | |
| + } | |
| +} | |
| +void ComputeUserTag() { | |
| SandboxUserTag = 0; | |
| QFile usertag(cWorkingDir() + qsl("tdata/usertag")); | |
| if (usertag.open(QIODevice::ReadOnly)) { | |
| @@ -453,6 +513,15 @@ | |
| } | |
| } | |
| +void WorkingDirReady() { | |
| + srand((int32)time(NULL)); | |
| + | |
| + ComputeTestMode(); | |
| + ComputeDebugMode(); | |
| + ComputeInstallBetaVersions(); | |
| + ComputeUserTag(); | |
| +} | |
| + | |
| void start() { | |
| SandboxData = std::make_unique<internal::Data>(); | |
| } | |
| @@ -551,8 +620,6 @@ | |
| CircleMasksMap CircleMasks; | |
| - base::Observable<void> SelfChanged; | |
| - | |
| bool AskDownloadPath = false; | |
| QString DownloadPath; | |
| QByteArray DownloadPathBookmark; | |
| @@ -681,8 +748,6 @@ | |
| DefineRefVar(Global, CircleMasksMap, CircleMasks); | |
| -DefineRefVar(Global, base::Observable<void>, SelfChanged); | |
| - | |
| DefineVar(Global, bool, AskDownloadPath); | |
| DefineVar(Global, QString, DownloadPath); | |
| DefineVar(Global, QByteArray, DownloadPathBookmark); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/facades.h work/tdesktop-1.4.0/Telegram/SourceFiles/facades.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/facades.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/facades.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -185,8 +185,10 @@ | |
| namespace Sandbox { | |
| -bool CheckBetaVersionDir(); | |
| +bool CheckAlphaVersionDir(); | |
| void WorkingDirReady(); | |
| +void WriteInstallBetaVersionsSetting(); | |
| +void WriteDebugModeSetting(); | |
| void MainThreadTaskAdded(); | |
| @@ -292,8 +294,6 @@ | |
| typedef QMap<uint64, QPixmap> CircleMasksMap; | |
| DeclareRefVar(CircleMasksMap, CircleMasks); | |
| -DeclareRefVar(base::Observable<void>, SelfChanged); | |
| - | |
| DeclareVar(bool, AskDownloadPath); | |
| DeclareVar(QString, DownloadPath); | |
| DeclareVar(QByteArray, DownloadPathBookmark); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -75,7 +75,7 @@ | |
| void UserCheckbox::setChecked(bool checked, NotifyAboutChange notify) { | |
| if (_check->checked() != checked) { | |
| - _check->setCheckedAnimated(checked); | |
| + _check->setChecked(checked, anim::type::normal); | |
| if (notify == NotifyAboutChange::Notify) { | |
| checkedChanged.notify(checked, true); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -411,7 +411,7 @@ | |
| } | |
| }); | |
| if (_admins.empty()) { | |
| - _admins.push_back(App::self()); | |
| + _admins.push_back(Auth().user()); | |
| } | |
| if (_showFilterCallback) { | |
| showFilter(std::move(_showFilterCallback)); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/feed/history_feed_section.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/feed/history_feed_section.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/feed/history_feed_section.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/feed/history_feed_section.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -199,7 +199,7 @@ | |
| return; | |
| } | |
| - const auto scrollDownIsVisible = [&]() -> base::optional<bool> { | |
| + const auto scrollDownIsVisible = [&]() -> std::optional<bool> { | |
| const auto top = _scroll->scrollTop() + st::historyToDownShownAfter; | |
| if (top < _scroll->scrollTopMax()) { | |
| return true; | |
| @@ -207,7 +207,7 @@ | |
| if (_inner->loadedAtBottomKnown()) { | |
| return !_inner->loadedAtBottom(); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| }; | |
| const auto scrollDownIsShown = scrollDownIsVisible(); | |
| if (!scrollDownIsShown) { | |
| @@ -368,11 +368,11 @@ | |
| } | |
| } | |
| -base::optional<int> Widget::listUnreadBarView( | |
| +std::optional<int> Widget::listUnreadBarView( | |
| const std::vector<not_null<Element*>> &elements) { | |
| const auto position = _feed->unreadPosition(); | |
| if (!position || elements.empty() || !_feed->unreadCount()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto minimal = ranges::upper_bound( | |
| elements, | |
| @@ -380,14 +380,14 @@ | |
| std::less<>(), | |
| [](auto view) { return view->data()->position(); }); | |
| if (minimal == end(elements)) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto view = *minimal; | |
| const auto unreadMessagesHeight = elements.back()->y() | |
| + elements.back()->height() | |
| - view->y(); | |
| if (unreadMessagesHeight < _scroll->height()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return base::make_optional(int(minimal - begin(elements))); | |
| } | |
| @@ -482,7 +482,7 @@ | |
| const auto contentWidth = width(); | |
| const auto newScrollTop = _scroll->isHidden() | |
| - ? base::none | |
| + ? std::nullopt | |
| : base::make_optional(_scroll->scrollTop() + topDelta()); | |
| _topBar->resizeToWidth(contentWidth); | |
| _topBarShadow->resize(contentWidth, st::lineWidth); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/feed/history_feed_section.h work/tdesktop-1.4.0/Telegram/SourceFiles/history/feed/history_feed_section.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/feed/history_feed_section.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/feed/history_feed_section.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -86,7 +86,7 @@ | |
| void listSelectionChanged( | |
| HistoryView::SelectedItems &&items) override; | |
| void listVisibleItemsChanged(HistoryItemsList &&items) override; | |
| - base::optional<int> listUnreadBarView( | |
| + std::optional<int> listUnreadBarView( | |
| const std::vector<not_null<Element*>> &elements) override; | |
| void listContentRefreshed() override; | |
| ClickHandlerPtr listDateLink(not_null<Element*> view) override; | |
| @@ -135,7 +135,7 @@ | |
| FullMsgId _currentMessageId; | |
| FullMsgId _highlightMessageId; | |
| - base::optional<Data::MessagePosition> _nextAnimatedScrollPosition; | |
| + std::optional<Data::MessagePosition> _nextAnimatedScrollPosition; | |
| int _nextAnimatedScrollDelta = 0; | |
| Animation _scrollDownShown; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_inner_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_inner_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_inner_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_inner_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -1945,7 +1945,7 @@ | |
| if (_migrated->blocks.back()->messages.back()->dateTime().date() == _history->blocks.front()->messages.front()->dateTime().date()) { | |
| if (_migrated->blocks.back()->messages.back()->data()->isGroupMigrate() && _history->blocks.front()->messages.front()->data()->isGroupMigrate()) { | |
| _historySkipHeight += _history->blocks.front()->messages.front()->height(); | |
| - } else { | |
| + } else if (_migrated->height() > _history->blocks.front()->messages.front()->displayedDateHeight()) { | |
| _historySkipHeight += _history->blocks.front()->messages.front()->displayedDateHeight(); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_item_components.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_item_components.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_item_components.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_item_components.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -616,6 +616,9 @@ | |
| } | |
| void ReplyKeyboard::step_selected(TimeMs ms, bool timer) { | |
| + if (anim::Disabled()) { | |
| + ms += st::botKbDuration; | |
| + } | |
| for (auto i = _animations.begin(); i != _animations.end();) { | |
| const auto index = std::abs(i->first) - 1; | |
| const auto row = (index / MatrixRowShift); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_media_types.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_media_types.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_media_types.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_media_types.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -205,10 +205,18 @@ | |
| } | |
| void HistoryFileMedia::step_radial(TimeMs ms, bool timer) { | |
| + const auto updateRadial = [&] { | |
| + return _animation->radial.update( | |
| + dataProgress(), | |
| + dataFinished(), | |
| + ms); | |
| + }; | |
| if (timer) { | |
| - Auth().data().requestViewRepaint(_parent); | |
| + if (!anim::Disabled() || updateRadial()) { | |
| + Auth().data().requestViewRepaint(_parent); | |
| + } | |
| } else { | |
| - _animation->radial.update(dataProgress(), dataFinished(), ms); | |
| + updateRadial(); | |
| if (!_animation->radial.animating()) { | |
| checkAnimationFinished(); | |
| } | |
| @@ -1848,6 +1856,9 @@ | |
| } | |
| void HistoryDocument::step_voiceProgress(float64 ms, bool timer) { | |
| + if (anim::Disabled()) { | |
| + ms += (2 * AudioVoiceMsgUpdateView); | |
| + } | |
| if (auto voice = Get<HistoryDocumentVoice>()) { | |
| if (voice->_playback) { | |
| float64 dt = ms / (2 * AudioVoiceMsgUpdateView); | |
| @@ -4320,7 +4331,14 @@ | |
| } | |
| void HistoryInvoice::fillFromData(not_null<Data::Invoice*> invoice) { | |
| - // init attach | |
| + if (invoice->photo) { | |
| + _attach = std::make_unique<HistoryPhoto>( | |
| + _parent, | |
| + _parent->data(), | |
| + invoice->photo); | |
| + } else { | |
| + _attach = nullptr; | |
| + } | |
| auto labelText = [&] { | |
| if (invoice->receiptMsgId) { | |
| if (invoice->isTest) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -2916,7 +2916,9 @@ | |
| : WebPageId(0)); | |
| const auto textWithTags = _field->getTextWithAppliedMarkdown(); | |
| - const auto prepareFlags = Ui::ItemTextOptions(_history, App::self()).flags; | |
| + const auto prepareFlags = Ui::ItemTextOptions( | |
| + _history, | |
| + Auth().user()).flags; | |
| auto sending = TextWithEntities(); | |
| auto left = TextWithEntities { textWithTags.text, ConvertTextTagsToEntities(textWithTags.tags) }; | |
| TextUtilities::PrepareForSending(left, prepareFlags); | |
| @@ -3230,14 +3232,16 @@ | |
| } | |
| void HistoryWidget::step_recording(float64 ms, bool timer) { | |
| - float64 dt = ms / AudioVoiceMsgUpdateView; | |
| + const auto dt = anim::Disabled() ? 1. : (ms / AudioVoiceMsgUpdateView); | |
| if (dt >= 1) { | |
| _a_recording.stop(); | |
| a_recordingLevel.finish(); | |
| } else { | |
| a_recordingLevel.update(dt, anim::linear); | |
| } | |
| - if (timer) update(_attachToggle->geometry()); | |
| + if (timer && !anim::Disabled()) { | |
| + update(_attachToggle->geometry()); | |
| + } | |
| } | |
| void HistoryWidget::chooseAttach() { | |
| @@ -4448,7 +4452,7 @@ | |
| }; | |
| const auto prepareFlags = Ui::ItemTextOptions( | |
| history, | |
| - App::self()).flags; | |
| + Auth().user()).flags; | |
| TextUtilities::PrepareForSending(caption, prepareFlags); | |
| TextUtilities::Trim(caption); | |
| auto localEntities = TextUtilities::EntitiesToMTP(caption.entities); | |
| @@ -4580,7 +4584,7 @@ | |
| const FullMsgId &newId, | |
| bool silent, | |
| const MTPInputFile &file) { | |
| - Auth().api().sendUploadedDocument(newId, file, base::none, silent); | |
| + Auth().api().sendUploadedDocument(newId, file, std::nullopt, silent); | |
| } | |
| void HistoryWidget::thumbDocumentUploaded( | |
| @@ -5067,7 +5071,7 @@ | |
| || (_migrated && _migrated->hasPendingResizedItems()); | |
| } | |
| -base::optional<int> HistoryWidget::unreadBarTop() const { | |
| +std::optional<int> HistoryWidget::unreadBarTop() const { | |
| auto getUnreadBar = [this]() -> HistoryView::Element* { | |
| if (const auto bar = _migrated ? _migrated->unreadBar() : nullptr) { | |
| return bar; | |
| @@ -5084,7 +5088,7 @@ | |
| } | |
| return result; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| HistoryView::Element *HistoryWidget::firstUnreadMessage() const { | |
| @@ -5351,6 +5355,8 @@ | |
| } | |
| } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { | |
| onListEnterPressed(); | |
| + } else if (e->key() == Qt::Key_O && e->modifiers() == Qt::ControlModifier) { | |
| + chooseAttach(); | |
| } else { | |
| e->ignore(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/history_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -684,7 +684,7 @@ | |
| // Counts scrollTop for placing the scroll right at the unread | |
| // messages bar, choosing from _history and _migrated unreadBar. | |
| - base::optional<int> unreadBarTop() const; | |
| + std::optional<int> unreadBarTop() const; | |
| int itemTopForHighlight(not_null<HistoryView::Element*> view) const; | |
| void scrollToCurrentVoiceMessage(FullMsgId fromId, FullMsgId toId); | |
| HistoryView::Element *firstUnreadMessage() const; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/history.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/history.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -294,7 +294,7 @@ | |
| void History::itemRemoved(not_null<HistoryItem*> item) { | |
| item->removeMainView(); | |
| if (lastMessage() == item) { | |
| - _lastMessage = base::none; | |
| + _lastMessage = std::nullopt; | |
| if (loadedAtBottom()) { | |
| if (const auto last = lastAvailableMessage()) { | |
| setLastMessage(last); | |
| @@ -423,7 +423,7 @@ | |
| void History::clearSentDraftText(const QString &text) { | |
| if (_lastSentDraftText && *_lastSentDraftText == text) { | |
| - _lastSentDraftText = base::none; | |
| + _lastSentDraftText = std::nullopt; | |
| } | |
| accumulate_max(_lastSentDraftTime, unixtime()); | |
| } | |
| @@ -632,7 +632,7 @@ | |
| } | |
| } | |
| auto result = (!_typing.isEmpty() || !_sendActions.isEmpty()); | |
| - if (changed || result) { | |
| + if (changed || (result && !anim::Disabled())) { | |
| App::histories().sendActionAnimationUpdated().notify({ | |
| this, | |
| _sendActionAnimation.width(), | |
| @@ -2135,7 +2135,11 @@ | |
| } | |
| if (!isReadyFor(msgId)) { | |
| unloadBlocks(); | |
| - | |
| + if (const auto migratePeer = peer->migrateFrom()) { | |
| + if (const auto migrated = App::historyLoaded(migratePeer)) { | |
| + migrated->unloadBlocks(); | |
| + } | |
| + } | |
| if (msgId == ShowAtTheEndMsgId) { | |
| _loadedAtBottom = true; | |
| } | |
| @@ -2172,8 +2176,13 @@ | |
| void History::setLastMessage(HistoryItem *item) { | |
| if (item) { | |
| - if (_lastMessage && !*_lastMessage) { | |
| - Local::removeSavedPeer(peer); | |
| + if (_lastMessage) { | |
| + if (!*_lastMessage) { | |
| + Local::removeSavedPeer(peer); | |
| + } else if (!IsServerMsgId((*_lastMessage)->id) | |
| + && (*_lastMessage)->date() > item->date()) { | |
| + return; | |
| + } | |
| } | |
| _lastMessage = item; | |
| if (const auto feed = peer->feed()) { | |
| @@ -2276,12 +2285,25 @@ | |
| } | |
| } | |
| +bool History::skipUnreadUpdateForClientSideUnread() const { | |
| + if (peer->id != peerFromUser(ServiceUserId)) { | |
| + return false; | |
| + } else if (!_unreadCount || !*_unreadCount) { | |
| + return false; | |
| + } else if (!_lastMessage || IsServerMsgId((*_lastMessage)->id)) { | |
| + return false; | |
| + } | |
| + return true; | |
| +} | |
| + | |
| void History::applyDialogFields( | |
| int unreadCount, | |
| MsgId maxInboxRead, | |
| MsgId maxOutboxRead) { | |
| - setUnreadCount(unreadCount); | |
| - setInboxReadTill(maxInboxRead); | |
| + if (!skipUnreadUpdateForClientSideUnread()) { | |
| + setUnreadCount(unreadCount); | |
| + setInboxReadTill(maxInboxRead); | |
| + } | |
| setOutboxReadTill(maxOutboxRead); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history.h work/tdesktop-1.4.0/Telegram/SourceFiles/history/history.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/history.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/history.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -471,6 +471,7 @@ | |
| void addItemsToLists(const std::vector<not_null<HistoryItem*>> &items); | |
| void clearSendAction(not_null<UserData*> from); | |
| + bool skipUnreadUpdateForClientSideUnread() const; | |
| HistoryItem *lastAvailableMessage() const; | |
| void getNextFirstUnreadMessage(); | |
| @@ -491,12 +492,12 @@ | |
| bool _loadedAtTop = false; | |
| bool _loadedAtBottom = true; | |
| - base::optional<MsgId> _inboxReadBefore; | |
| - base::optional<MsgId> _outboxReadBefore; | |
| - base::optional<int> _unreadCount; | |
| - base::optional<int> _unreadMentionsCount; | |
| + std::optional<MsgId> _inboxReadBefore; | |
| + std::optional<MsgId> _outboxReadBefore; | |
| + std::optional<int> _unreadCount; | |
| + std::optional<int> _unreadMentionsCount; | |
| base::flat_set<MsgId> _unreadMentions; | |
| - base::optional<HistoryItem*> _lastMessage; | |
| + std::optional<HistoryItem*> _lastMessage; | |
| bool _unreadMark = false; | |
| // A pointer to the block that is currently being built. | |
| @@ -510,7 +511,7 @@ | |
| std::unique_ptr<Data::Draft> _localDraft, _cloudDraft; | |
| std::unique_ptr<Data::Draft> _editDraft; | |
| - base::optional<QString> _lastSentDraftText; | |
| + std::optional<QString> _lastSentDraftText; | |
| TimeId _lastSentDraftTime = 0; | |
| MessageIdsList _forwardDraft; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/view/history_view_list_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/view/history_view_list_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/view/history_view_list_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/view/history_view_list_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -328,24 +328,24 @@ | |
| _delegate->listContentRefreshed(); | |
| } | |
| -base::optional<int> ListWidget::scrollTopForPosition( | |
| +std::optional<int> ListWidget::scrollTopForPosition( | |
| Data::MessagePosition position) const { | |
| if (position == Data::MaxMessagePosition) { | |
| if (loadedAtBottom()) { | |
| return height(); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } else if (_items.empty() | |
| || isBelowPosition(position) | |
| || isAbovePosition(position)) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| const auto index = findNearestItem(position); | |
| const auto view = _items[index]; | |
| return scrollTopForView(_items[index]); | |
| } | |
| -base::optional<int> ListWidget::scrollTopForView( | |
| +std::optional<int> ListWidget::scrollTopForView( | |
| not_null<Element*> view) const { | |
| if (view->isHiddenByGroup()) { | |
| if (const auto group = Auth().data().groups().find(view->data())) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/view/history_view_list_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/history/view/history_view_list_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/view/history_view_list_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/view/history_view_list_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -62,7 +62,7 @@ | |
| not_null<HistoryItem*> second) = 0; | |
| virtual void listSelectionChanged(SelectedItems &&items) = 0; | |
| virtual void listVisibleItemsChanged(HistoryItemsList &&items) = 0; | |
| - virtual base::optional<int> listUnreadBarView( | |
| + virtual std::optional<int> listUnreadBarView( | |
| const std::vector<not_null<Element*>> &elements) = 0; | |
| virtual void listContentRefreshed() = 0; | |
| virtual ClickHandlerPtr listDateLink(not_null<Element*> view) = 0; | |
| @@ -136,9 +136,9 @@ | |
| void saveState(not_null<ListMemento*> memento); | |
| void restoreState(not_null<ListMemento*> memento); | |
| - base::optional<int> scrollTopForPosition( | |
| + std::optional<int> scrollTopForPosition( | |
| Data::MessagePosition position) const; | |
| - base::optional<int> scrollTopForView(not_null<Element*> view) const; | |
| + std::optional<int> scrollTopForView(not_null<Element*> view) const; | |
| enum class AnimatedScroll { | |
| Full, | |
| Part, | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -152,7 +152,7 @@ | |
| } | |
| void TopBarWidget::step_connecting(TimeMs ms, bool timer) { | |
| - if (timer) { | |
| + if (timer && !anim::Disabled()) { | |
| update(); | |
| } | |
| } | |
| @@ -760,12 +760,13 @@ | |
| text = lng_chat_status_members(lt_count, chat->count); | |
| } | |
| } else { | |
| + const auto self = Auth().user(); | |
| auto online = 0; | |
| auto onlyMe = true; | |
| for (auto [user, v] : chat->participants) { | |
| if (user->onlineTill > now) { | |
| ++online; | |
| - if (onlyMe && user != App::self()) onlyMe = false; | |
| + if (onlyMe && user != self) onlyMe = false; | |
| } | |
| } | |
| if (online > 0 && !onlyMe) { | |
| @@ -783,12 +784,13 @@ | |
| if (channel->mgInfo->lastParticipants.empty() || channel->lastParticipantsCountOutdated()) { | |
| Auth().api().requestLastParticipants(channel); | |
| } | |
| + const auto self = Auth().user(); | |
| auto online = 0; | |
| - bool onlyMe = true; | |
| + auto onlyMe = true; | |
| for (auto &participant : std::as_const(channel->mgInfo->lastParticipants)) { | |
| if (participant->onlineTill > now) { | |
| ++online; | |
| - if (onlyMe && participant != App::self()) { | |
| + if (onlyMe && participant != self) { | |
| onlyMe = false; | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/feed/info_feed_channels.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/feed/info_feed_channels.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/feed/info_feed_channels.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/feed/info_feed_channels.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -33,7 +33,7 @@ | |
| class Memento; | |
| struct ChannelsState { | |
| std::unique_ptr<PeerListState> list; | |
| - base::optional<QString> search; | |
| + std::optional<QString> search; | |
| }; | |
| class Channels | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_content_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_content_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_content_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_content_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -160,10 +160,6 @@ | |
| _scrollTopSkip = scrollTopSkip; | |
| } | |
| -rpl::producer<Section> ContentWidget::sectionRequest() const { | |
| - return rpl::never<Section>(); | |
| -} | |
| - | |
| rpl::producer<int> ContentWidget::scrollHeightValue() const { | |
| return _scroll->heightValue(); | |
| } | |
| @@ -226,6 +222,14 @@ | |
| return rpl::single(SelectedItems(Storage::SharedMediaType::Photo)); | |
| } | |
| +rpl::producer<bool> ContentWidget::canSaveChanges() const { | |
| + return rpl::single(false); | |
| +} | |
| + | |
| +void ContentWidget::saveChanges(FnMut<void()> done) { | |
| + done(); | |
| +} | |
| + | |
| void ContentWidget::refreshSearchField(bool shown) { | |
| auto search = _controller->searchFieldController(); | |
| if (search && shown) { | |
| @@ -253,4 +257,18 @@ | |
| } | |
| } | |
| +Key ContentMemento::key() const { | |
| + if (const auto peerId = this->peerId()) { | |
| + return Key(App::peer(peerId)); | |
| + } else if (const auto feed = this->feed()) { | |
| + return Key(feed); | |
| + } else { | |
| + return Settings::Tag{ settingsSelf() }; | |
| + } | |
| +} | |
| + | |
| +ContentMemento::ContentMemento(Settings::Tag settings) | |
| +: _settingsSelf(settings.self.get()) { | |
| +} | |
| + | |
| } // namespace Info | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_content_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_content_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_content_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_content_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -28,6 +28,9 @@ | |
| } // namespace Data | |
| namespace Info { | |
| +namespace Settings { | |
| +struct Tag; | |
| +} // namespace Settings | |
| class ContentMemento; | |
| class Controller; | |
| @@ -42,13 +45,12 @@ | |
| not_null<ContentMemento*> memento) = 0; | |
| std::unique_ptr<ContentMemento> createMemento(); | |
| - virtual rpl::producer<Section> sectionRequest() const; | |
| virtual void setIsStackBottom(bool isStackBottom) { | |
| } | |
| rpl::producer<int> scrollHeightValue() const; | |
| rpl::producer<int> desiredHeightValue() const override; | |
| - rpl::producer<bool> desiredShadowVisibility() const; | |
| + virtual rpl::producer<bool> desiredShadowVisibility() const; | |
| bool hasTopBarShadow() const; | |
| virtual void setInnerFocus(); | |
| @@ -71,6 +73,9 @@ | |
| virtual void cancelSelection() { | |
| } | |
| + virtual rpl::producer<bool> canSaveChanges() const; | |
| + virtual void saveChanges(FnMut<void()> done); | |
| + | |
| protected: | |
| template <typename Widget> | |
| Widget *setInnerWidget(object_ptr<Widget> inner) { | |
| @@ -119,9 +124,9 @@ | |
| : _peerId(peerId) | |
| , _migratedPeerId(migratedPeerId) { | |
| } | |
| - explicit ContentMemento(not_null<Data::Feed*> feed) | |
| - : _feed(feed) { | |
| + explicit ContentMemento(not_null<Data::Feed*> feed) : _feed(feed) { | |
| } | |
| + explicit ContentMemento(Settings::Tag settings); | |
| virtual object_ptr<ContentWidget> createWidget( | |
| QWidget *parent, | |
| @@ -137,6 +142,10 @@ | |
| Data::Feed *feed() const { | |
| return _feed; | |
| } | |
| + UserData *settingsSelf() const { | |
| + return _settingsSelf; | |
| + } | |
| + Key key() const; | |
| virtual Section section() const = 0; | |
| @@ -171,6 +180,7 @@ | |
| const PeerId _peerId = 0; | |
| const PeerId _migratedPeerId = 0; | |
| Data::Feed * const _feed = nullptr; | |
| + UserData * const _settingsSelf = nullptr; | |
| int _scrollTop = 0; | |
| QString _searchFieldQuery; | |
| bool _searchEnabledByContent = false; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_controller.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_controller.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_controller.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_controller.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -38,6 +38,9 @@ | |
| Key::Key(not_null<Data::Feed*> feed) : _value(feed) { | |
| } | |
| +Key::Key(Settings::Tag settings) : _value(settings) { | |
| +} | |
| + | |
| PeerData *Key::peer() const { | |
| if (const auto peer = base::get_if<not_null<PeerData*>>(&_value)) { | |
| return *peer; | |
| @@ -52,6 +55,13 @@ | |
| return nullptr; | |
| } | |
| +UserData *Key::settingsSelf() const { | |
| + if (const auto tag = base::get_if<Settings::Tag>(&_value)) { | |
| + return tag->self; | |
| + } | |
| + return nullptr; | |
| +} | |
| + | |
| rpl::producer<SparseIdsMergedSlice> AbstractController::mediaSource( | |
| SparseIdsMergedSlice::UniversalMsgId aroundId, | |
| int limitBefore, | |
| @@ -88,9 +98,7 @@ | |
| not_null<ContentMemento*> memento) | |
| : AbstractController(window) | |
| , _widget(widget) | |
| -, _key(memento->peerId() | |
| - ? Key(App::peer(memento->peerId())) | |
| - : Key(memento->feed())) | |
| +, _key(memento->key()) | |
| , _migrated(memento->migratedPeerId() | |
| ? App::peer(memento->migratedPeerId()) | |
| : nullptr) | |
| @@ -135,7 +143,8 @@ | |
| not_null<ContentMemento*> memento) const { | |
| return memento->peerId() == peerId() | |
| && memento->migratedPeerId() == migratedPeerId() | |
| - && memento->feed() == feed(); | |
| + && memento->feed() == feed() | |
| + && memento->settingsSelf() == settingsSelf(); | |
| } | |
| void Controller::setSection(not_null<ContentMemento*> memento) { | |
| @@ -260,6 +269,18 @@ | |
| limitAfter); | |
| } | |
| +void Controller::setCanSaveChanges(rpl::producer<bool> can) { | |
| + _canSaveChanges = std::move(can); | |
| +} | |
| + | |
| +rpl::producer<bool> Controller::canSaveChanges() const { | |
| + return _canSaveChanges.value(); | |
| +} | |
| + | |
| +bool Controller::canSaveChangesNow() const { | |
| + return _canSaveChanges.current(); | |
| +} | |
| + | |
| Controller::~Controller() = default; | |
| } // namespace Info | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_controller.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_controller.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_controller.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_controller.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,23 +10,39 @@ | |
| #include <rpl/variable.h> | |
| #include "data/data_search_controller.h" | |
| #include "window/window_controller.h" | |
| +#include "settings/settings_common.h" | |
| namespace Ui { | |
| class SearchFieldController; | |
| } // namespace Ui | |
| namespace Info { | |
| +namespace Settings { | |
| + | |
| +struct Tag { | |
| + explicit Tag(not_null<UserData*> self) : self(self) { | |
| + } | |
| + | |
| + not_null<UserData*> self; | |
| +}; | |
| + | |
| +} // namespace Settings | |
| class Key { | |
| public: | |
| Key(not_null<PeerData*> peer); | |
| Key(not_null<Data::Feed*> feed); | |
| + Key(Settings::Tag settings); | |
| PeerData *peer() const; | |
| Data::Feed *feed() const; | |
| + UserData *settingsSelf() const; | |
| private: | |
| - base::variant<not_null<PeerData*>, not_null<Data::Feed*>> _value; | |
| + base::variant< | |
| + not_null<PeerData*>, | |
| + not_null<Data::Feed*>, | |
| + Settings::Tag> _value; | |
| }; | |
| @@ -43,28 +59,41 @@ | |
| CommonGroups, | |
| Members, | |
| Channels, | |
| + Settings, | |
| }; | |
| + using SettingsType = ::Settings::Type; | |
| using MediaType = Storage::SharedMediaType; | |
| Section(Type type) : _type(type) { | |
| - Expects(type != Type::Media); | |
| + Expects(type != Type::Media && type != Type::Settings); | |
| } | |
| Section(MediaType mediaType) | |
| : _type(Type::Media) | |
| , _mediaType(mediaType) { | |
| } | |
| + Section(SettingsType settingsType) | |
| + : _type(Type::Settings) | |
| + , _settingsType(settingsType) { | |
| + } | |
| Type type() const { | |
| return _type; | |
| } | |
| MediaType mediaType() const { | |
| Expects(_type == Type::Media); | |
| + | |
| return _mediaType; | |
| } | |
| + SettingsType settingsType() const { | |
| + Expects(_type == Type::Settings); | |
| + | |
| + return _settingsType; | |
| + } | |
| private: | |
| Type _type; | |
| - Storage::SharedMediaType _mediaType; | |
| + MediaType _mediaType = MediaType(); | |
| + SettingsType _settingsType = SettingsType(); | |
| }; | |
| @@ -93,6 +122,9 @@ | |
| Data::Feed *feed() const { | |
| return key().feed(); | |
| } | |
| + UserData *settingsSelf() const { | |
| + return key().settingsSelf(); | |
| + } | |
| virtual void setSearchEnabledByContent(bool enabled) { | |
| } | |
| @@ -156,6 +188,10 @@ | |
| return base::take(_searchStartsFocused); | |
| } | |
| + void setCanSaveChanges(rpl::producer<bool> can); | |
| + rpl::producer<bool> canSaveChanges() const; | |
| + bool canSaveChangesNow() const; | |
| + | |
| void saveSearchState(not_null<ContentMemento*> memento); | |
| void showSection( | |
| @@ -186,6 +222,7 @@ | |
| std::unique_ptr<Ui::SearchFieldController> _searchFieldController; | |
| std::unique_ptr<Api::DelayedSearchController> _searchController; | |
| rpl::variable<bool> _seachEnabledByContent = false; | |
| + rpl::variable<bool> _canSaveChanges = false; | |
| bool _searchStartsFocused = false; | |
| rpl::lifetime _lifetime; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_layer_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_layer_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_layer_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_layer_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,7 +7,6 @@ | |
| */ | |
| #include "info/info_layer_widget.h" | |
| -#include <rpl/mappers.h> | |
| #include "info/info_content_widget.h" | |
| #include "info/info_top_bar.h" | |
| #include "info/info_memento.h" | |
| @@ -19,7 +18,6 @@ | |
| #include "window/main_window.h" | |
| #include "auth_session.h" | |
| #include "styles/style_info.h" | |
| -#include "styles/style_settings.h" | |
| #include "styles/style_window.h" | |
| #include "styles/style_boxes.h" | |
| @@ -133,6 +131,10 @@ | |
| return false; | |
| } | |
| +bool LayerWidget::closeByOutsideClick() const { | |
| + return _content->closeByOutsideClick(); | |
| +} | |
| + | |
| int LayerWidget::MinimalSupportedWidth() { | |
| auto minimalMargins = 2 * st::infoMinimalLayerMargin; | |
| return st::infoMinimalWidth + minimalMargins; | |
| @@ -190,6 +192,10 @@ | |
| return desiredHeight; | |
| } | |
| +void LayerWidget::doSetInnerFocus() { | |
| + _content->setInnerFocus(); | |
| +} | |
| + | |
| void LayerWidget::paintEvent(QPaintEvent *e) { | |
| Painter p(this); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_layer_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_layer_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_layer_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_layer_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -37,10 +37,13 @@ | |
| not_null<Window::SectionMemento*> memento, | |
| const Window::SectionShow ¶ms) override; | |
| + bool closeByOutsideClick() const override; | |
| + | |
| static int MinimalSupportedWidth(); | |
| protected: | |
| int resizeGetHeight(int newWidth) override; | |
| + void doSetInnerFocus() override; | |
| void paintEvent(QPaintEvent *e) override; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_memento.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_memento.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_memento.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_memento.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -13,6 +13,7 @@ | |
| #include "info/channels/info_channels_widget.h" | |
| #include "info/common_groups/info_common_groups_widget.h" | |
| #include "info/feed/info_feed_profile_widget.h" | |
| +#include "info/settings/info_settings_widget.h" | |
| #include "info/info_section_widget.h" | |
| #include "info/info_layer_widget.h" | |
| #include "info/info_controller.h" | |
| @@ -32,6 +33,10 @@ | |
| : Memento(DefaultStack(feed, section)) { | |
| } | |
| +Memento::Memento(Settings::Tag settings, Section section) | |
| +: Memento(DefaultStack(settings, section)) { | |
| +} | |
| + | |
| Memento::Memento(std::vector<std::unique_ptr<ContentMemento>> stack) | |
| : _stack(std::move(stack)) { | |
| } | |
| @@ -52,6 +57,16 @@ | |
| return result; | |
| } | |
| +std::vector<std::unique_ptr<ContentMemento>> Memento::DefaultStack( | |
| + Settings::Tag settings, | |
| + Section section) { | |
| + auto result = std::vector<std::unique_ptr<ContentMemento>>(); | |
| + result.push_back(std::make_unique<Settings::Memento>( | |
| + settings.self, | |
| + section.settingsType())); | |
| + return result; | |
| +} | |
| + | |
| Section Memento::DefaultSection(Dialogs::Key key) { | |
| if (const auto peer = key.peer()) { | |
| if (peer->isSelf()) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_memento.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_memento.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_memento.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_memento.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -26,16 +26,20 @@ | |
| } // namespace Ui | |
| namespace Info { | |
| +namespace Settings { | |
| +struct Tag; | |
| +} // namespace Settings | |
| class ContentMemento; | |
| class WrapWidget; | |
| class Memento final : public Window::SectionMemento { | |
| public: | |
| - Memento(PeerId peerId); | |
| + explicit Memento(PeerId peerId); | |
| Memento(PeerId peerId, Section section); | |
| Memento(not_null<Data::Feed*> feed, Section section); | |
| - Memento(std::vector<std::unique_ptr<ContentMemento>> stack); | |
| + Memento(Settings::Tag settings, Section section); | |
| + explicit Memento(std::vector<std::unique_ptr<ContentMemento>> stack); | |
| object_ptr<Window::SectionWidget> createWidget( | |
| QWidget *parent, | |
| @@ -54,6 +58,7 @@ | |
| not_null<ContentMemento*> content() { | |
| Expects(!_stack.empty()); | |
| + | |
| return _stack.back().get(); | |
| } | |
| @@ -69,6 +74,9 @@ | |
| static std::vector<std::unique_ptr<ContentMemento>> DefaultStack( | |
| not_null<Data::Feed*> feed, | |
| Section section); | |
| + static std::vector<std::unique_ptr<ContentMemento>> DefaultStack( | |
| + Settings::Tag settings, | |
| + Section section); | |
| static std::unique_ptr<ContentMemento> DefaultContent( | |
| not_null<Data::Feed*> feed, | |
| Section section); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_top_bar.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_top_bar.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_top_bar.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_top_bar.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -99,8 +99,10 @@ | |
| st::infoTopBarScale); | |
| _back->setDuration(st::infoTopBarDuration); | |
| _back->toggle(!selectionMode(), anim::type::instant); | |
| - _back->entity()->clicks() | |
| - | rpl::start_to_stream(_backClicks, _back->lifetime()); | |
| + _back->entity()->clicks( | |
| + ) | rpl::map([] { | |
| + return rpl::empty_value(); | |
| + }) | rpl::start_to_stream(_backClicks, _back->lifetime()); | |
| registerToggleControlCallback(_back.data(), [=] { | |
| return !selectionMode(); | |
| }); | |
| @@ -152,6 +154,13 @@ | |
| return weak; | |
| } | |
| +void TopBar::forceButtonVisibility( | |
| + Ui::FadeWrap<Ui::RpWidget> *button, | |
| + rpl::producer<bool> shown) { | |
| + _updateControlCallbacks.erase(button); | |
| + button->toggleOn(std::move(shown)); | |
| +} | |
| + | |
| void TopBar::setSearchField( | |
| base::unique_qptr<Ui::InputField> field, | |
| rpl::producer<bool> &&shown, | |
| @@ -427,7 +436,9 @@ | |
| st::infoTopBarScale)); | |
| _cancelSelection->setDuration(st::infoTopBarDuration); | |
| _cancelSelection->entity()->clicks( | |
| - ) | rpl::start_to_stream( | |
| + ) | rpl::map([] { | |
| + return rpl::empty_value(); | |
| + }) | rpl::start_to_stream( | |
| _cancelSelectionClicks, | |
| _cancelSelection->lifetime()); | |
| _selectionText = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::LabelWithNumbers>>( | |
| @@ -587,6 +598,22 @@ | |
| case Section::Type::Channels: | |
| return lng_info_feed_channels; | |
| + case Section::Type::Settings: | |
| + switch (section.settingsType()) { | |
| + case Section::SettingsType::Main: | |
| + return lng_menu_settings; | |
| + case Section::SettingsType::Information: | |
| + return lng_settings_section_info; | |
| + case Section::SettingsType::Notifications: | |
| + return lng_settings_section_notify; | |
| + case Section::SettingsType::PrivacySecurity: | |
| + return lng_settings_section_privacy; | |
| + case Section::SettingsType::Advanced: | |
| + return lng_settings_advanced; | |
| + case Section::SettingsType::Chat: | |
| + return lng_settings_section_chat_settings; | |
| + } | |
| + Unexpected("Bad settings type in Info::TitleValue()"); | |
| } | |
| Unexpected("Bad section type in Info::TitleValue()"); | |
| }()); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_top_bar.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_top_bar.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_top_bar.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_top_bar.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -56,6 +56,17 @@ | |
| return result; | |
| } | |
| + template <typename ButtonWidget> | |
| + ButtonWidget *addButtonWithVisibility( | |
| + base::unique_qptr<ButtonWidget> button, | |
| + rpl::producer<bool> shown) { | |
| + auto result = button.get(); | |
| + forceButtonVisibility( | |
| + pushButton(std::move(button)), | |
| + std::move(shown)); | |
| + return result; | |
| + } | |
| + | |
| void createSearchView( | |
| not_null<Ui::SearchFieldController*> controller, | |
| rpl::producer<bool> &&shown, | |
| @@ -79,7 +90,11 @@ | |
| void updateControlsGeometry(int newWidth); | |
| void updateDefaultControlsGeometry(int newWidth); | |
| void updateSelectionControlsGeometry(int newWidth); | |
| - Ui::FadeWrap<Ui::RpWidget> *pushButton(base::unique_qptr<Ui::RpWidget> button); | |
| + Ui::FadeWrap<Ui::RpWidget> *pushButton( | |
| + base::unique_qptr<Ui::RpWidget> button); | |
| + void forceButtonVisibility( | |
| + Ui::FadeWrap<Ui::RpWidget> *button, | |
| + rpl::producer<bool> shown); | |
| void removeButton(not_null<Ui::RpWidget*> button); | |
| void startHighlightAnimation(); | |
| void updateControlsVisibility(anim::type animated); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_wrap_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_wrap_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_wrap_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_wrap_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -25,6 +25,7 @@ | |
| #include "window/window_slide_animation.h" | |
| #include "window/window_peer_menu.h" | |
| #include "boxes/peer_list_box.h" | |
| +#include "boxes/confirm_box.h" | |
| #include "auth_session.h" | |
| #include "data/data_session.h" | |
| #include "mainwidget.h" | |
| @@ -200,6 +201,8 @@ | |
| return Dialogs::RowDescriptor(App::history(peer), FullMsgId()); | |
| } else if (const auto feed = key().feed()) { | |
| return Dialogs::RowDescriptor(feed, FullMsgId()); | |
| + } else if (key().settingsSelf()) { | |
| + return Dialogs::RowDescriptor(); | |
| } | |
| Unexpected("Owner in WrapWidget::activeChat()."); | |
| } | |
| @@ -348,8 +351,8 @@ | |
| if (wrapValue == Wrap::Narrow || hasStackHistory()) { | |
| _topBar->enableBackButton(); | |
| _topBar->backRequest( | |
| - ) | rpl::start_with_next([this] { | |
| - _controller->showBackFromStack(); | |
| + ) | rpl::start_with_next([=] { | |
| + checkBeforeClose([=] { _controller->showBackFromStack(); }); | |
| }, _topBar->lifetime()); | |
| } else if (wrapValue == Wrap::Side) { | |
| auto close = _topBar->addButton( | |
| @@ -366,7 +369,9 @@ | |
| _topBar, | |
| st::infoLayerTopBarClose)); | |
| close->addClickHandler([this] { | |
| - _controller->parentController()->hideSpecialLayer(); | |
| + checkBeforeClose([=] { | |
| + _controller->parentController()->hideSpecialLayer(); | |
| + }); | |
| }); | |
| } else if (requireTopBarSearch()) { | |
| auto search = _controller->searchFieldController(); | |
| @@ -376,11 +381,18 @@ | |
| _controller->searchEnabledByContent(), | |
| _controller->takeSearchStartsFocused()); | |
| } | |
| - if (_controller->section().type() == Section::Type::Profile | |
| + const auto section = _controller->section(); | |
| + if (section.type() == Section::Type::Profile | |
| && (wrapValue != Wrap::Side || hasStackHistory())) { | |
| - addProfileMenuButton(); | |
| + addTopBarMenuButton(); | |
| addProfileCallsButton(); | |
| // addProfileNotificationsButton(); | |
| + } else if (section.type() == Section::Type::Settings | |
| + && section.settingsType() == Section::SettingsType::Main) { | |
| + addTopBarMenuButton(); | |
| + } else if (section.type() == Section::Type::Settings | |
| + && section.settingsType() == Section::SettingsType::Information) { | |
| + addContentSaveButton(); | |
| } | |
| _topBar->lower(); | |
| @@ -389,7 +401,23 @@ | |
| _topBar->show(); | |
| } | |
| -void WrapWidget::addProfileMenuButton() { | |
| +void WrapWidget::checkBeforeClose(Fn<void()> close) { | |
| + const auto confirmed = [=] { | |
| + const auto copy = close; | |
| + Ui::hideLayer(); | |
| + copy(); | |
| + }; | |
| + if (_controller->canSaveChangesNow()) { | |
| + Ui::show(Box<ConfirmBox>( | |
| + lang(lng_settings_close_sure), | |
| + lang(lng_close), | |
| + confirmed)); | |
| + } else { | |
| + confirmed(); | |
| + } | |
| +} | |
| + | |
| +void WrapWidget::addTopBarMenuButton() { | |
| Expects(_topBar != nullptr); | |
| _topBarMenuToggle.reset(_topBar->addButton( | |
| @@ -399,10 +427,31 @@ | |
| ? st::infoLayerTopBarMenu | |
| : st::infoTopBarMenu)))); | |
| _topBarMenuToggle->addClickHandler([this] { | |
| - showProfileMenu(); | |
| + showTopBarMenu(); | |
| }); | |
| } | |
| +void WrapWidget::addContentSaveButton() { | |
| + Expects(_topBar != nullptr); | |
| + | |
| + _topBar->addButtonWithVisibility( | |
| + base::make_unique_q<Ui::IconButton>( | |
| + _topBar, | |
| + (wrap() == Wrap::Layer | |
| + ? st::infoLayerTopBarSave | |
| + : st::infoTopBarSave)), | |
| + _controller->canSaveChanges() | |
| + )->addClickHandler([=] { | |
| + _content->saveChanges(crl::guard(_content.data(), [=] { | |
| + _controller->showBackFromStack(); | |
| + })); | |
| + }); | |
| +} | |
| + | |
| +bool WrapWidget::closeByOutsideClick() const { | |
| + return !_controller->canSaveChangesNow(); | |
| +} | |
| + | |
| void WrapWidget::addProfileCallsButton() { | |
| Expects(_topBar != nullptr); | |
| @@ -469,7 +518,7 @@ | |
| }, notifications->lifetime()); | |
| } | |
| -void WrapWidget::showProfileMenu() { | |
| +void WrapWidget::showTopBarMenu() { | |
| if (_topBarMenu) { | |
| _topBarMenu->hideAnimated( | |
| Ui::InnerDropdown::HideOption::IgnoreShow); | |
| @@ -512,6 +561,13 @@ | |
| feed, | |
| addAction, | |
| Window::PeerMenuSource::Profile); | |
| + } else if (const auto self = key().settingsSelf()) { | |
| + const auto showOther = [=](::Settings::Type type) { | |
| + const auto controller = _controller.get(); | |
| + _topBarMenu = nullptr; | |
| + controller->showSettings(type); | |
| + }; | |
| + ::Settings::FillMenu(showOther, addAction); | |
| } else { | |
| _topBarMenu = nullptr; | |
| return; | |
| @@ -915,9 +971,9 @@ | |
| } | |
| void WrapWidget::keyPressEvent(QKeyEvent *e) { | |
| - if (e->key() == Qt::Key_Escape) { | |
| + if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { | |
| if (hasStackHistory() || wrap() != Wrap::Layer) { | |
| - _controller->showBackFromStack(); | |
| + checkBeforeClose([=] { _controller->showBackFromStack(); }); | |
| return; | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_wrap_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_wrap_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info_wrap_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info_wrap_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -118,6 +118,8 @@ | |
| object_ptr<Ui::RpWidget> createTopBarSurrogate(QWidget *parent); | |
| + bool closeByOutsideClick() const; | |
| + | |
| void updateGeometry(QRect newGeometry, int additionalScroll); | |
| int scrollTillBottom(int forHeight) const; | |
| rpl::producer<int> scrollTillBottomChanges() const; | |
| @@ -150,6 +152,7 @@ | |
| void injectActiveFeedProfile(not_null<Data::Feed*> feed); | |
| void injectActiveProfileMemento( | |
| std::unique_ptr<ContentMemento> memento); | |
| + void checkBeforeClose(Fn<void()> close); | |
| void restoreHistoryStack( | |
| std::vector<std::unique_ptr<ContentMemento>> stack); | |
| bool hasStackHistory() const { | |
| @@ -191,10 +194,11 @@ | |
| rpl::producer<SelectedItems> selectedListValue() const; | |
| bool requireTopBarSearch() const; | |
| - void addProfileMenuButton(); | |
| + void addTopBarMenuButton(); | |
| + void addContentSaveButton(); | |
| void addProfileCallsButton(); | |
| void addProfileNotificationsButton(); | |
| - void showProfileMenu(); | |
| + void showTopBarMenu(); | |
| rpl::variable<Wrap> _wrap; | |
| std::unique_ptr<Controller> _controller; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info.style work/tdesktop-1.4.0/Telegram/SourceFiles/info/info.style | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/info.style 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/info.style 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -155,6 +155,15 @@ | |
| icon: icon {{ "top_bar_call", boxTitleCloseFg }}; | |
| iconOver: icon {{ "top_bar_call", boxTitleCloseFgOver }}; | |
| } | |
| +infoTopBarSave: IconButton(infoTopBarNotifications) { | |
| + width: 48px; | |
| + icon: icon {{ "passport_ready", windowActiveTextFg }}; | |
| + iconOver: icon {{ "passport_ready", windowActiveTextFg }}; | |
| + iconPosition: point(11px, 17px); | |
| + ripple: RippleAnimation(defaultRippleAnimation) { | |
| + color: lightButtonBgOver; | |
| + } | |
| +} | |
| infoTopBarForward: IconButton(infoTopBarBack) { | |
| width: 46px; | |
| icon: icon {{ "info_media_forward", boxTitleCloseFg }}; | |
| @@ -222,6 +231,14 @@ | |
| icon: icon {{ "top_bar_call", boxTitleCloseFg }}; | |
| iconOver: icon {{ "top_bar_call", boxTitleCloseFgOver }}; | |
| } | |
| +infoLayerTopBarSave: IconButton(infoLayerTopBarNotifications) { | |
| + icon: icon {{ "passport_ready", windowActiveTextFg }}; | |
| + iconOver: icon {{ "passport_ready", windowActiveTextFg }}; | |
| + iconPosition: point(13px, 18px); | |
| + ripple: RippleAnimation(defaultRippleAnimation) { | |
| + color: lightButtonBgOver; | |
| + } | |
| +} | |
| infoLayerTopBarForward: IconButton(infoLayerTopBarBack) { | |
| width: 45px; | |
| icon: icon {{ "info_media_forward", boxTitleCloseFg }}; | |
| @@ -378,8 +395,6 @@ | |
| infoBlockHeaderPosition: point(79px, 22px); | |
| infoProfileToggle: Toggle(defaultToggle) { | |
| - diameter: 16px; | |
| - width: 14px; | |
| untoggledFg: menuIconFg; | |
| } | |
| infoProfileToggleOver: Toggle(infoProfileToggle) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_list_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_list_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_list_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_list_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -217,6 +217,7 @@ | |
| bool ListWidget::Section::belongsHere( | |
| not_null<BaseLayout*> item) const { | |
| Expects(!_items.empty()); | |
| + | |
| auto date = item->dateTime().date(); | |
| auto myDate = _items.back().second->dateTime().date(); | |
| @@ -980,7 +981,7 @@ | |
| } | |
| auto ListWidget::findItemById( | |
| - UniversalMsgId universalId) -> base::optional<FoundItem> { | |
| + UniversalMsgId universalId) -> std::optional<FoundItem> { | |
| auto sectionIt = findSectionByItem(universalId); | |
| if (sectionIt != _sections.end()) { | |
| auto item = sectionIt->findItemNearId(universalId); | |
| @@ -988,14 +989,14 @@ | |
| return foundItemInSection(item, *sectionIt); | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto ListWidget::findItemDetails( | |
| - BaseLayout *item) -> base::optional<FoundItem> { | |
| + BaseLayout *item) -> std::optional<FoundItem> { | |
| return item | |
| ? findItemById(GetUniversalId(item)) | |
| - : base::none; | |
| + : std::nullopt; | |
| } | |
| auto ListWidget::foundItemInSection( | |
| @@ -1057,7 +1058,7 @@ | |
| auto delta = _slice.distance( | |
| sliceKey(_universalAroundId), | |
| sliceKey(universalId)); | |
| - Assert(delta != base::none); | |
| + Assert(delta != std::nullopt); | |
| preloadRequired = (qAbs(*delta) >= minUniversalIdDelta); | |
| } | |
| if (preloadRequired) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_list_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_list_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_list_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_list_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -230,8 +230,8 @@ | |
| std::vector<Section>::const_iterator from, | |
| int bottom) const; | |
| FoundItem findItemByPoint(QPoint point) const; | |
| - base::optional<FoundItem> findItemById(UniversalMsgId universalId); | |
| - base::optional<FoundItem> findItemDetails(BaseLayout *item); | |
| + std::optional<FoundItem> findItemById(UniversalMsgId universalId); | |
| + std::optional<FoundItem> findItemDetails(BaseLayout *item); | |
| FoundItem foundItemInSection( | |
| const FoundItem &item, | |
| const Section §ion) const; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,13 +16,13 @@ | |
| namespace Info { | |
| namespace Media { | |
| -base::optional<int> TypeToTabIndex(Type type) { | |
| +std::optional<int> TypeToTabIndex(Type type) { | |
| switch (type) { | |
| case Type::Photo: return 0; | |
| case Type::Video: return 1; | |
| case Type::File: return 2; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| Type TabIndexToType(int index) { | |
| @@ -97,7 +97,7 @@ | |
| if (!controller()->validateMementoPeer(memento)) { | |
| return false; | |
| } | |
| - if (auto mediaMemento = dynamic_cast<Memento*>(memento.get())) { | |
| + if (const auto mediaMemento = dynamic_cast<Memento*>(memento.get())) { | |
| if (_inner->showInternal(mediaMemento)) { | |
| return true; | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/media/info_media_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/media/info_media_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -17,7 +17,7 @@ | |
| using Type = Storage::SharedMediaType; | |
| -base::optional<int> TypeToTabIndex(Type type); | |
| +std::optional<int> TypeToTabIndex(Type type); | |
| Type TabIndexToType(int index); | |
| class InnerWidget; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_button.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_button.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_button.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_button.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -40,12 +40,12 @@ | |
| false, | |
| [this] { rtlupdate(toggleRect()); }); | |
| addClickHandler([this] { | |
| - _toggle->setCheckedAnimated(!_toggle->checked()); | |
| + _toggle->setChecked(!_toggle->checked(), anim::type::normal); | |
| }); | |
| std::move( | |
| toggled | |
| ) | rpl::start_with_next([this](bool toggled) { | |
| - _toggle->setCheckedAnimated(toggled); | |
| + _toggle->setChecked(toggled, anim::type::normal); | |
| }, lifetime()); | |
| _toggle->finishAnimating(); | |
| return this; | |
| @@ -58,7 +58,11 @@ | |
| return rpl::never<bool>(); | |
| } | |
| -void Button::setColorOverride(base::optional<QColor> textColorOverride) { | |
| +bool Button::toggled() const { | |
| + return _toggle ? _toggle->checked() : false; | |
| +} | |
| + | |
| +void Button::setColorOverride(std::optional<QColor> textColorOverride) { | |
| _textColorOverride = textColorOverride; | |
| update(); | |
| } | |
| @@ -67,7 +71,7 @@ | |
| Painter p(this); | |
| auto ms = getms(); | |
| - auto paintOver = (isOver() || isDown()); | |
| + auto paintOver = (isOver() || isDown()) && !isDisabled(); | |
| p.fillRect(e->rect(), paintOver ? _st.textBgOver : _st.textBg); | |
| paintRipple(p, 0, 0, ms); | |
| @@ -94,6 +98,7 @@ | |
| QRect Button::toggleRect() const { | |
| Expects(_toggle != nullptr); | |
| + | |
| auto size = _toggle->getSize(); | |
| auto left = width() - _st.toggleSkip - size.width(); | |
| auto top = (height() - size.height()) / 2; | |
| @@ -108,10 +113,13 @@ | |
| void Button::onStateChanged( | |
| State was, | |
| StateChangeSource source) { | |
| - RippleButton::onStateChanged(was, source); | |
| + if (!isDisabled() || !isDown()) { | |
| + RippleButton::onStateChanged(was, source); | |
| + } | |
| if (_toggle) { | |
| _toggle->setStyle(isOver() ? _st.toggleOver : _st.toggle); | |
| } | |
| + setPointerCursor(!isDisabled()); | |
| } | |
| void Button::setText(QString &&text) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_button.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_button.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_button.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_button.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -28,8 +28,9 @@ | |
| Button *toggleOn(rpl::producer<bool> &&toggled); | |
| rpl::producer<bool> toggledValue() const; | |
| + bool toggled() const; | |
| - void setColorOverride(base::optional<QColor> textColorOverride); | |
| + void setColorOverride(std::optional<QColor> textColorOverride); | |
| protected: | |
| int resizeGetHeight(int newWidth) override; | |
| @@ -50,7 +51,7 @@ | |
| int _originalWidth = 0; | |
| int _textWidth = 0; | |
| std::unique_ptr<Ui::ToggleView> _toggle; | |
| - base::optional<QColor> _textColorOverride; | |
| + std::optional<QColor> _textColorOverride; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_cover.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_cover.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_cover.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_cover.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -212,17 +212,17 @@ | |
| Cover::Cover( | |
| QWidget *parent, | |
| - not_null<Controller*> controller) | |
| + not_null<PeerData*> peer, | |
| + not_null<Window::Controller*> controller) | |
| : SectionWithToggle( | |
| parent, | |
| st::infoProfilePhotoTop | |
| + st::infoProfilePhoto.size.height() | |
| + st::infoProfilePhotoBottom) | |
| -, _controller(controller) | |
| -, _peer(_controller->key().peer()) | |
| +, _peer(peer) | |
| , _userpic( | |
| this, | |
| - controller->parentController(), | |
| + controller, | |
| _peer, | |
| Ui::UserpicButton::Role::OpenPhoto, | |
| st::infoProfilePhoto) | |
| @@ -274,12 +274,13 @@ | |
| void Cover::initViewers() { | |
| using Flag = Notify::PeerUpdate::Flag; | |
| - Notify::PeerUpdateValue( | |
| - _peer, | |
| - Flag::NameChanged | |
| - ) | rpl::start_with_next( | |
| - [this] { refreshNameText(); }, | |
| - lifetime()); | |
| + NameValue( | |
| + _peer | |
| + ) | rpl::start_with_next([=](const TextWithEntities &name) { | |
| + _name->setText(name.text); | |
| + refreshNameGeometry(width()); | |
| + }, lifetime()); | |
| + | |
| Notify::PeerUpdateValue( | |
| _peer, | |
| Flag::UserOnlineChanged | Flag::MembersChanged | |
| @@ -293,6 +294,8 @@ | |
| ) | rpl::start_with_next( | |
| [this] { refreshUploadPhotoOverlay(); }, | |
| lifetime()); | |
| + } else if (_peer->isSelf()) { | |
| + refreshUploadPhotoOverlay(); | |
| } | |
| VerifiedValue( | |
| _peer | |
| @@ -303,12 +306,12 @@ | |
| void Cover::refreshUploadPhotoOverlay() { | |
| _userpic->switchChangePhotoOverlay([&] { | |
| - if (auto chat = _peer->asChat()) { | |
| + if (const auto chat = _peer->asChat()) { | |
| return chat->canEdit(); | |
| - } else if (auto channel = _peer->asChannel()) { | |
| + } else if (const auto channel = _peer->asChannel()) { | |
| return channel->canEditInformation(); | |
| } | |
| - return false; | |
| + return _peer->isSelf(); | |
| }()); | |
| } | |
| @@ -331,11 +334,6 @@ | |
| refreshNameGeometry(width()); | |
| } | |
| -void Cover::refreshNameText() { | |
| - _name->setText(App::peerName(_peer)); | |
| - refreshNameGeometry(width()); | |
| -} | |
| - | |
| void Cover::refreshStatusText() { | |
| auto hasMembersLink = [&] { | |
| if (auto megagroup = _peer->asMegagroup()) { | |
| @@ -376,9 +374,7 @@ | |
| _status->setRichText(statusText); | |
| if (hasMembersLink) { | |
| _status->setLink(1, std::make_shared<LambdaClickHandler>([=] { | |
| - _controller->showSection(Info::Memento( | |
| - _controller->peerId(), | |
| - Section::Type::Members)); | |
| + _showSection.fire(Section::Type::Members); | |
| })); | |
| } | |
| refreshStatusGeometry(width()); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_cover.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_cover.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_cover.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_cover.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -11,6 +11,10 @@ | |
| #include "ui/widgets/checkbox.h" | |
| #include "base/timer.h" | |
| +namespace Window { | |
| +class Controller; | |
| +} // namespace Window | |
| + | |
| namespace style { | |
| struct InfoToggle; | |
| } // namespace style | |
| @@ -24,6 +28,7 @@ | |
| namespace Info { | |
| class Controller; | |
| +class Section; | |
| } // namespace Info | |
| namespace Info { | |
| @@ -52,7 +57,8 @@ | |
| public: | |
| Cover( | |
| QWidget *parent, | |
| - not_null<Controller*> controller); | |
| + not_null<PeerData*> peer, | |
| + not_null<Window::Controller*> controller); | |
| Cover *setOnlineCount(rpl::producer<int> &&count); | |
| @@ -61,19 +67,21 @@ | |
| SectionWithToggle::setToggleShown(std::move(shown))); | |
| } | |
| + rpl::producer<Section> showSection() const { | |
| + return _showSection.events(); | |
| + } | |
| + | |
| ~Cover(); | |
| private: | |
| void setupChildGeometry(); | |
| void initViewers(); | |
| - void refreshNameText(); | |
| void refreshStatusText(); | |
| void refreshNameGeometry(int newWidth); | |
| void refreshStatusGeometry(int newWidth); | |
| void refreshUploadPhotoOverlay(); | |
| void setVerified(bool verified); | |
| - not_null<Controller*> _controller; | |
| not_null<PeerData*> _peer; | |
| int _onlineCount = 0; | |
| @@ -84,6 +92,8 @@ | |
| //object_ptr<CoverDropArea> _dropArea = { nullptr }; | |
| base::Timer _refreshStatusTimer; | |
| + rpl::event_stream<Section> _showSection; | |
| + | |
| }; | |
| class SharedMediaCover : public SectionWithToggle { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -77,7 +77,12 @@ | |
| auto result = object_ptr<Ui::VerticalLayout>(parent); | |
| _cover = result->add(object_ptr<Cover>( | |
| result, | |
| - _controller)); | |
| + _peer, | |
| + _controller->parentController())); | |
| + _cover->showSection( | |
| + ) | rpl::start_with_next([=](Section section) { | |
| + _controller->showSection(Info::Memento(_peer->id, section)); | |
| + }, _cover->lifetime()); | |
| _cover->setOnlineCount(rpl::single(0)); | |
| auto details = SetupDetails(_controller, parent, _peer); | |
| if (canHideDetailsEver()) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_members.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_members.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_members.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_members.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -34,7 +34,7 @@ | |
| class Memento; | |
| struct MembersState { | |
| std::unique_ptr<PeerListState> list; | |
| - base::optional<QString> search; | |
| + std::optional<QString> search; | |
| }; | |
| class Members | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_values.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_values.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_values.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_values.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,6 +23,16 @@ | |
| namespace Info { | |
| namespace Profile { | |
| +rpl::producer<TextWithEntities> NameValue( | |
| + not_null<PeerData*> peer) { | |
| + return Notify::PeerUpdateValue( | |
| + peer, | |
| + Notify::PeerUpdate::Flag::NameChanged | |
| + ) | rpl::map([=] { | |
| + return App::peerName(peer); | |
| + }) | WithEmptyEntities(); | |
| +} | |
| + | |
| rpl::producer<TextWithEntities> PhoneValue( | |
| not_null<UserData*> user) { | |
| return Notify::PeerUpdateValue( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_values.h work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_values.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/info/profile/info_profile_values.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/info/profile/info_profile_values.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -42,6 +42,8 @@ | |
| }); | |
| } | |
| +rpl::producer<TextWithEntities> NameValue( | |
| + not_null<PeerData*> peer); | |
| rpl::producer<TextWithEntities> PhoneValue( | |
| not_null<UserData*> user); | |
| rpl::producer<TextWithEntities> BioValue( | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/info: settings | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -326,11 +326,19 @@ | |
| } | |
| void Gif::step_radial(TimeMs ms, bool timer) { | |
| + const auto document = getShownDocument(); | |
| + const auto updateRadial = [&] { | |
| + return _animation->radial.update( | |
| + document->progress(), | |
| + !document->loading() || document->loaded(), | |
| + ms); | |
| + }; | |
| if (timer) { | |
| - update(); | |
| + if (!anim::Disabled() || updateRadial()) { | |
| + update(); | |
| + } | |
| } else { | |
| - DocumentData *document = getShownDocument(); | |
| - _animation->radial.update(document->progress(), !document->loading() || document->loaded(), ms); | |
| + updateRadial(); | |
| if (!_animation->radial.animating() && document->loaded()) { | |
| _animation.reset(); | |
| } | |
| @@ -819,13 +827,18 @@ | |
| } | |
| void File::step_radial(TimeMs ms, bool timer) { | |
| - if (timer) { | |
| - update(); | |
| - } else { | |
| - _animation->radial.update( | |
| + const auto updateRadial = [&] { | |
| + return _animation->radial.update( | |
| _document->progress(), | |
| !_document->loading() || _document->loaded(), | |
| ms); | |
| + }; | |
| + if (timer) { | |
| + if (!anim::Disabled() || updateRadial()) { | |
| + update(); | |
| + } | |
| + } else { | |
| + updateRadial(); | |
| if (!_animation->radial.animating()) { | |
| checkAnimationFinished(); | |
| } | |
| @@ -1333,11 +1346,19 @@ | |
| } | |
| void Game::step_radial(TimeMs ms, bool timer) { | |
| + const auto document = getResultDocument(); | |
| + const auto updateRadial = [&] { | |
| + return _radial->update( | |
| + document->progress(), | |
| + !document->loading() || document->loaded(), | |
| + ms); | |
| + }; | |
| if (timer) { | |
| - update(); | |
| + if (!anim::Disabled() || updateRadial()) { | |
| + update(); | |
| + } | |
| } else { | |
| - auto document = getResultDocument(); | |
| - _radial->update(document->progress(), !document->loading() || document->loaded(), ms); | |
| + updateRadial(); | |
| if (!_radial->animating() && document->loaded()) { | |
| _radial.reset(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/inline_bots/inline_bot_result.h work/tdesktop-1.4.0/Telegram/SourceFiles/inline_bots/inline_bot_result.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/inline_bots/inline_bot_result.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/inline_bots/inline_bot_result.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,8 +7,6 @@ | |
| */ | |
| #pragma once | |
| -#include "core/basic_types.h" | |
| - | |
| class FileLoader; | |
| namespace InlineBots { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h work/tdesktop-1.4.0/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,7 +7,6 @@ | |
| */ | |
| #pragma once | |
| -#include "core/basic_types.h" | |
| #include "history/history_location_manager.h" | |
| namespace InlineBots { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/intro/introphone.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/intro/introphone.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/intro/introphone.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/intro/introphone.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -25,8 +25,9 @@ | |
| void SendToBannedHelp(const QString &phone) { | |
| const auto version = QString::fromLatin1(AppVersionStr.c_str()) | |
| - + (cAlphaVersion() ? " alpha" : "") | |
| - + (cBetaVersion() ? qsl(" beta %1").arg(cBetaVersion()) : QString()); | |
| + + (cAlphaVersion() | |
| + ? qsl(" alpha %1").arg(cAlphaVersion()) | |
| + : (AppBetaVersion ? " beta" : "")); | |
| const auto subject = qsl("Banned phone number: ") + phone; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/intro/introwidget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/intro/introwidget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/intro/introwidget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/intro/introwidget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -573,11 +573,13 @@ | |
| void Widget::keyPressEvent(QKeyEvent *e) { | |
| if (_a_show.animating() || getStep()->animating()) return; | |
| - if (e->key() == Qt::Key_Escape) { | |
| + if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) { | |
| if (getStep()->hasBack()) { | |
| historyMove(Direction::Back); | |
| } | |
| - } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return || e->key() == Qt::Key_Space) { | |
| + } else if (e->key() == Qt::Key_Enter | |
| + || e->key() == Qt::Key_Return | |
| + || e->key() == Qt::Key_Space) { | |
| getStep()->submit(); | |
| } | |
| } | |
| @@ -594,7 +596,9 @@ | |
| } | |
| void Widget::Step::finish(const MTPUser &user, QImage &&photo) { | |
| - if (user.type() != mtpc_user || !user.c_user().is_self()) { | |
| + if (user.type() != mtpc_user | |
| + || !user.c_user().is_self() | |
| + || !user.c_user().vid.v) { | |
| // No idea what to do here. | |
| // We could've reset intro and MTP, but this really should not happen. | |
| Ui::show(Box<InformBox>("Internal error: bad user.is_self() after sign in.")); | |
| @@ -610,18 +614,13 @@ | |
| Local::writeLangPack(); | |
| } | |
| - Messenger::Instance().authSessionCreate(user.c_user().vid.v); | |
| + Messenger::Instance().authSessionCreate(user); | |
| Local::writeMtpData(); | |
| - App::wnd()->setupMain(&user); | |
| + App::wnd()->setupMain(); | |
| // "this" is already deleted here by creating the main widget. | |
| - if (auto user = App::self()) { | |
| - Auth().api().requestFullPeer(user); | |
| - } | |
| - if (!photo.isNull()) { | |
| - Messenger::Instance().uploadProfilePhoto( | |
| - std::move(photo), | |
| - Auth().userId()); | |
| + if (AuthSession::Exists() && !photo.isNull()) { | |
| + Auth().api().uploadPeerPhoto(Auth().user(), std::move(photo)); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/lang/lang_cloud_manager.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/lang/lang_cloud_manager.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/lang/lang_cloud_manager.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/lang/lang_cloud_manager.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -220,26 +220,28 @@ | |
| QVector<MTPstring> keys; | |
| keys.reserve(3); | |
| keys.push_back(MTP_string("lng_sure_save_language")); | |
| - keys.push_back(MTP_string("lng_box_ok")); | |
| - keys.push_back(MTP_string("lng_cancel")); | |
| _switchingToLanguageRequest = request(MTPlangpack_GetStrings( | |
| MTP_string(Lang::CloudLangPackName()), | |
| MTP_string(id), | |
| MTP_vector<MTPstring>(std::move(keys)) | |
| )).done([=](const MTPVector<MTPLangPackString> &result) { | |
| - auto values = Instance::ParseStrings(result); | |
| - auto getValue = [&values](LangKey key) { | |
| + const auto values = Instance::ParseStrings(result); | |
| + const auto getValue = [&](LangKey key) { | |
| auto it = values.find(key); | |
| return (it == values.cend()) | |
| ? GetOriginalValue(key) | |
| : it->second; | |
| }; | |
| - auto text = getValue(lng_sure_save_language); | |
| - auto save = getValue(lng_box_ok); | |
| - auto cancel = getValue(lng_cancel); | |
| - Ui::show(Box<ConfirmBox>(text, save, cancel, [this, id] { | |
| - performSwitchAndRestart(id); | |
| - }), LayerOption::KeepOther); | |
| + const auto text = lang(lng_sure_save_language) | |
| + + "\n\n" | |
| + + getValue(lng_sure_save_language); | |
| + Ui::show( | |
| + Box<ConfirmBox>( | |
| + text, | |
| + lang(lng_box_ok), | |
| + lang(lng_cancel), | |
| + [=] { performSwitchAndRestart(id); }), | |
| + LayerOption::KeepOther); | |
| }).send(); | |
| } | |
| } | |
| @@ -253,24 +255,33 @@ | |
| } | |
| auto filePath = result.paths.front(); | |
| - Lang::FileParser loader(filePath, { lng_sure_save_language, lng_box_ok, lng_cancel }); | |
| + Lang::FileParser loader(filePath, { lng_sure_save_language }); | |
| if (loader.errors().isEmpty()) { | |
| weak->request(weak->_switchingToLanguageRequest).cancel(); | |
| if (weak->canApplyWithoutRestart(qsl("custom"))) { | |
| weak->_langpack.switchToCustomFile(filePath); | |
| } else { | |
| - auto values = loader.found(); | |
| - auto getValue = [&values](LangKey key) { | |
| - auto it = values.find(key); | |
| - return (it == values.cend()) ? GetOriginalValue(key) : it.value(); | |
| + const auto values = loader.found(); | |
| + const auto getValue = [&](LangKey key) { | |
| + const auto it = values.find(key); | |
| + return (it == values.cend()) | |
| + ? GetOriginalValue(key) | |
| + : it.value(); | |
| }; | |
| - auto text = getValue(lng_sure_save_language); | |
| - auto save = getValue(lng_box_ok); | |
| - auto cancel = getValue(lng_cancel); | |
| - Ui::show(Box<ConfirmBox>(text, save, cancel, [weak, filePath] { | |
| + const auto text = lang(lng_sure_save_language) | |
| + + "\n\n" | |
| + + getValue(lng_sure_save_language); | |
| + const auto change = [=] { | |
| weak->_langpack.switchToCustomFile(filePath); | |
| App::restart(); | |
| - }), LayerOption::KeepOther); | |
| + }; | |
| + Ui::show( | |
| + Box<ConfirmBox>( | |
| + text, | |
| + lang(lng_box_ok), | |
| + lang(lng_cancel), | |
| + change), | |
| + LayerOption::KeepOther); | |
| } | |
| } else { | |
| Ui::show( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/logs.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/logs.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/logs.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/logs.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -322,7 +322,7 @@ | |
| void start(not_null<Core::Launcher*> launcher) { | |
| Assert(LogsData == 0); | |
| - if (!Sandbox::CheckBetaVersionDir()) { | |
| + if (!Sandbox::CheckAlphaVersionDir()) { | |
| return; | |
| } | |
| @@ -330,8 +330,7 @@ | |
| auto moveOldDataFrom = QString(); | |
| auto workingDirChosen = false; | |
| - if (cBetaVersion()) { | |
| - SetDebugEnabled(true); | |
| + if (cAlphaVersion()) { | |
| workingDirChosen = true; | |
| #if defined Q_OS_MAC || defined Q_OS_LINUX | |
| } else { | |
| @@ -397,14 +396,24 @@ | |
| LogsData = 0; | |
| } | |
| - LOG(("Launched version: %1, alpha: %2, beta: %3, debug mode: %4, test dc: %5").arg(AppVersion).arg(Logs::b(cAlphaVersion())).arg(cBetaVersion()).arg(Logs::b(DebugEnabled())).arg(Logs::b(cTestMode()))); | |
| + LOG(("Launched version: %1, " | |
| + "install beta: %2, " | |
| + "alpha: %3, " | |
| + "debug mode: %4, " | |
| + "test dc: %5" | |
| + ).arg(AppVersion | |
| + ).arg(Logs::b(cInstallBetaVersion()) | |
| + ).arg(cAlphaVersion() | |
| + ).arg(Logs::b(DebugEnabled()) | |
| + ).arg(Logs::b(cTestMode()))); | |
| LOG(("Executable dir: %1, name: %2").arg(cExeDir()).arg(cExeName())); | |
| LOG(("Initial working dir: %1").arg(initialWorkingDir)); | |
| LOG(("Working dir: %1").arg(cWorkingDir())); | |
| LOG(("Command line: %1").arg(launcher->argumentsString())); | |
| if (!LogsData) { | |
| - LOG(("FATAL: Could not open '%1' for writing log!").arg(_logsFilePath(LogDataMain, qsl("_startXX")))); | |
| + LOG(("FATAL: Could not open '%1' for writing log!" | |
| + ).arg(_logsFilePath(LogDataMain, qsl("_startXX")))); | |
| return; | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/logs.h work/tdesktop-1.4.0/Telegram/SourceFiles/logs.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/logs.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/logs.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,8 @@ | |
| */ | |
| #pragma once | |
| +#include "base/basic_types.h" | |
| + | |
| namespace Core { | |
| class Launcher; | |
| } // namespace Core | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwidget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/mainwidget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwidget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mainwidget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -960,22 +960,8 @@ | |
| void MainWidget::deletePhotoLayer(PhotoData *photo) { | |
| if (!photo) return; | |
| Ui::show(Box<ConfirmBox>(lang(lng_delete_photo_sure), lang(lng_box_delete), crl::guard(this, [=] { | |
| + Auth().api().clearPeerPhoto(photo); | |
| Ui::hideLayer(); | |
| - | |
| - auto me = App::self(); | |
| - if (!me) return; | |
| - | |
| - if (me->userpicPhotoId() == photo->id) { | |
| - Messenger::Instance().peerClearPhoto(me->id); | |
| - } else if (photo->peer && !photo->peer->isUser() && photo->peer->userpicPhotoId() == photo->id) { | |
| - Messenger::Instance().peerClearPhoto(photo->peer->id); | |
| - } else { | |
| - MTP::send(MTPphotos_DeletePhotos( | |
| - MTP_vector<MTPInputPhoto>(1, photo->mtpInput()))); | |
| - Auth().storage().remove(Storage::UserPhotosRemoveOne( | |
| - me->bareId(), | |
| - photo->id)); | |
| - } | |
| }))); | |
| } | |
| @@ -1126,7 +1112,12 @@ | |
| void MainWidget::deleteAndExit(ChatData *chat) { | |
| PeerData *peer = chat; | |
| - MTP::send(MTPmessages_DeleteChatUser(chat->inputChat, App::self()->inputUser), rpcDone(&MainWidget::deleteHistoryAfterLeave, peer), rpcFail(&MainWidget::leaveChatFailed, peer)); | |
| + MTP::send( | |
| + MTPmessages_DeleteChatUser( | |
| + chat->inputChat, | |
| + Auth().user()->inputUser), | |
| + rpcDone(&MainWidget::deleteHistoryAfterLeave, peer), | |
| + rpcFail(&MainWidget::leaveChatFailed, peer)); | |
| } | |
| void MainWidget::addParticipants( | |
| @@ -1699,71 +1690,6 @@ | |
| _history->activate(); | |
| } | |
| -void MainWidget::insertCheckedServiceNotification(const TextWithEntities &message, const MTPMessageMedia &media, int32 date) { | |
| - auto flags = MTPDmessage::Flag::f_entities | MTPDmessage::Flag::f_from_id | MTPDmessage_ClientFlag::f_clientside_unread; | |
| - auto sending = TextWithEntities(), left = message; | |
| - HistoryItem *item = nullptr; | |
| - while (TextUtilities::CutPart(sending, left, MaxMessageSize)) { | |
| - auto localEntities = TextUtilities::EntitiesToMTP(sending.entities); | |
| - item = App::histories().addNewMessage( | |
| - MTP_message( | |
| - MTP_flags(flags), | |
| - MTP_int(clientMsgId()), | |
| - MTP_int(ServiceUserId), | |
| - MTP_peerUser(MTP_int(Auth().userId())), | |
| - MTPnullFwdHeader, | |
| - MTPint(), | |
| - MTPint(), | |
| - MTP_int(date), | |
| - MTP_string(sending.text), | |
| - media, | |
| - MTPnullMarkup, | |
| - localEntities, | |
| - MTPint(), | |
| - MTPint(), | |
| - MTPstring(), | |
| - MTPlong()), | |
| - NewMessageUnread); | |
| - } | |
| - Auth().data().sendHistoryChangeNotifications(); | |
| -} | |
| - | |
| -void MainWidget::serviceHistoryDone(const MTPmessages_Messages &msgs) { | |
| - auto handleResult = [&](auto &&result) { | |
| - App::feedUsers(result.vusers); | |
| - App::feedChats(result.vchats); | |
| - App::feedMsgs(result.vmessages, NewMessageLast); | |
| - }; | |
| - | |
| - switch (msgs.type()) { | |
| - case mtpc_messages_messages: | |
| - handleResult(msgs.c_messages_messages()); | |
| - break; | |
| - | |
| - case mtpc_messages_messagesSlice: | |
| - handleResult(msgs.c_messages_messagesSlice()); | |
| - break; | |
| - | |
| - case mtpc_messages_channelMessages: | |
| - LOG(("API Error: received messages.channelMessages! (MainWidget::serviceHistoryDone)")); | |
| - handleResult(msgs.c_messages_channelMessages()); | |
| - break; | |
| - | |
| - case mtpc_messages_messagesNotModified: | |
| - LOG(("API Error: received messages.messagesNotModified! (MainWidget::serviceHistoryDone)")); | |
| - break; | |
| - } | |
| - | |
| - App::wnd()->showDelayedServiceMsgs(); | |
| -} | |
| - | |
| -bool MainWidget::serviceHistoryFail(const RPCError &error) { | |
| - if (MTP::isDefaultHandledError(error)) return false; | |
| - | |
| - App::wnd()->showDelayedServiceMsgs(); | |
| - return false; | |
| -} | |
| - | |
| bool MainWidget::isIdle() const { | |
| return _isIdle; | |
| } | |
| @@ -2413,6 +2339,9 @@ | |
| auto direction = (back || settingSection->forceAnimateBack()) | |
| ? Window::SlideDirection::FromLeft | |
| : Window::SlideDirection::FromRight; | |
| + if (Adaptive::OneColumn()) { | |
| + _controller->removeLayerBlackout(); | |
| + } | |
| settingSection->showAnimated(direction, animationParams); | |
| } else { | |
| settingSection->showFast(); | |
| @@ -3658,32 +3587,18 @@ | |
| MTP::ping(); | |
| } | |
| -void MainWidget::start(const MTPUser *self) { | |
| +void MainWidget::start() { | |
| Auth().api().requestNotifySettings(MTP_inputNotifyUsers()); | |
| Auth().api().requestNotifySettings(MTP_inputNotifyChats()); | |
| - if (!self) { | |
| - MTP::send(MTPusers_GetFullUser(MTP_inputUserSelf()), rpcDone(&MainWidget::startWithSelf)); | |
| - return; | |
| - } else if (!Auth().validateSelf(*self)) { | |
| - constexpr auto kRequestUserAgainTimeout = TimeMs(10000); | |
| - App::CallDelayed(kRequestUserAgainTimeout, this, [=] { | |
| - MTP::send(MTPusers_GetFullUser(MTP_inputUserSelf()), rpcDone(&MainWidget::startWithSelf)); | |
| - }); | |
| - return; | |
| - } | |
| - | |
| Local::readSavedPeers(); | |
| cSetOtherOnline(0); | |
| - if (const auto user = App::feedUsers(MTP_vector<MTPUser>(1, *self))) { | |
| - user->loadUserpic(); | |
| - } | |
| + Auth().user()->loadUserpic(); | |
| MTP::send(MTPupdates_GetState(), rpcDone(&MainWidget::gotState)); | |
| update(); | |
| _started = true; | |
| - App::wnd()->sendServiceHistoryRequest(); | |
| Local::readInstalledStickers(); | |
| Local::readFeaturedStickers(); | |
| Local::readRecentStickers(); | |
| @@ -3949,15 +3864,6 @@ | |
| return true; | |
| } | |
| -void MainWidget::startWithSelf(const MTPUserFull &result) { | |
| - Expects(result.type() == mtpc_userFull); | |
| - auto &d = result.c_userFull(); | |
| - start(&d.vuser); | |
| - if (auto user = App::self()) { | |
| - Auth().api().processFullPeer(user, result); | |
| - } | |
| -} | |
| - | |
| void MainWidget::incrementSticker(DocumentData *sticker) { | |
| if (!sticker || !sticker->sticker()) return; | |
| if (sticker->sticker()->set.type() == mtpc_inputStickerSetEmpty) return; | |
| @@ -4156,12 +4062,11 @@ | |
| _lastSetOnline = ms; | |
| _onlineRequest = MTP::send(MTPaccount_UpdateStatus(MTP_bool(!isOnline))); | |
| - if (App::self()) { | |
| - App::self()->onlineTill = unixtime() + (isOnline ? (Global::OnlineUpdatePeriod() / 1000) : -1); | |
| - Notify::peerUpdatedDelayed( | |
| - App::self(), | |
| - Notify::PeerUpdate::Flag::UserOnlineChanged); | |
| - } | |
| + const auto self = Auth().user(); | |
| + self->onlineTill = unixtime() + (isOnline ? (Global::OnlineUpdatePeriod() / 1000) : -1); | |
| + Notify::peerUpdatedDelayed( | |
| + self, | |
| + Notify::PeerUpdate::Flag::UserOnlineChanged); | |
| if (!isOnline) { // Went offline, so we need to save message draft to the cloud. | |
| saveDraftToCloud(); | |
| } | |
| @@ -4934,7 +4839,7 @@ | |
| } else if (d.is_popup()) { | |
| Ui::show(Box<InformBox>(text)); | |
| } else { | |
| - App::wnd()->serviceNotification(text, d.vmedia); | |
| + Auth().data().serviceNotification(text, d.vmedia); | |
| emit App::wnd()->checkNewAuthorization(); | |
| } | |
| } break; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwidget.h work/tdesktop-1.4.0/Telegram/SourceFiles/mainwidget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwidget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mainwidget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -95,7 +95,7 @@ | |
| void showAnimated(const QPixmap &bgAnimCache, bool back = false); | |
| - void start(const MTPUser *self = nullptr); | |
| + void start(); | |
| void openPeerByName( | |
| const QString &name, | |
| @@ -239,10 +239,6 @@ | |
| void checkLastUpdate(bool afterSleep); | |
| - void insertCheckedServiceNotification(const TextWithEntities &message, const MTPMessageMedia &media, int32 date); | |
| - void serviceHistoryDone(const MTPmessages_Messages &msgs); | |
| - bool serviceHistoryFail(const RPCError &error); | |
| - | |
| bool isIdle() const; | |
| QPixmap cachedBackground(const QRect &forRect, int &x, int &y); | |
| @@ -443,8 +439,6 @@ | |
| Window::SectionSlideParams prepareHistoryAnimation(PeerId historyPeerId); | |
| Window::SectionSlideParams prepareDialogsAnimation(); | |
| - void startWithSelf(const MTPUserFull &user); | |
| - | |
| void saveSectionInStack(); | |
| void getChannelDifference(ChannelData *channel, ChannelDifferenceRequest from = ChannelDifferenceRequest::Unknown); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwindow.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/mainwindow.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwindow.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mainwindow.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -33,7 +33,7 @@ | |
| #include "mediaview.h" | |
| #include "storage/localstorage.h" | |
| #include "apiwrap.h" | |
| -#include "settings/settings_widget.h" | |
| +#include "settings/settings_intro.h" | |
| #include "platform/platform_notifications_manager.h" | |
| #include "window/layer_widget.h" | |
| #include "window/notifications_manager.h" | |
| @@ -79,7 +79,9 @@ | |
| setLocale(QLocale(QLocale::English, QLocale::UnitedStates)); | |
| - subscribe(Global::RefSelfChanged(), [this] { updateGlobalMenu(); }); | |
| + subscribe(Messenger::Instance().authSessionChanged(), [this] { | |
| + updateGlobalMenu(); | |
| + }); | |
| subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) { | |
| themeUpdated(data); | |
| }); | |
| @@ -210,74 +212,9 @@ | |
| } | |
| fixOrder(); | |
| - | |
| - _delayedServiceMsgs.clear(); | |
| - if (_serviceHistoryRequest) { | |
| - MTP::cancel(_serviceHistoryRequest); | |
| - _serviceHistoryRequest = 0; | |
| - } | |
| -} | |
| - | |
| -void MainWindow::serviceNotification(const TextWithEntities &message, const MTPMessageMedia &media, int32 date, bool force) { | |
| - if (date <= 0) date = unixtime(); | |
| - auto h = (_main && App::userLoaded(ServiceUserId)) ? App::history(ServiceUserId).get() : nullptr; | |
| - if (!h || (!force && h->isEmpty())) { | |
| - _delayedServiceMsgs.push_back(DelayedServiceMsg(message, media, date)); | |
| - return sendServiceHistoryRequest(); | |
| - } | |
| - | |
| - _main->insertCheckedServiceNotification(message, media, date); | |
| -} | |
| - | |
| -void MainWindow::showDelayedServiceMsgs() { | |
| - for (auto &delayed : base::take(_delayedServiceMsgs)) { | |
| - serviceNotification(delayed.message, delayed.media, delayed.date, true); | |
| - } | |
| -} | |
| - | |
| -void MainWindow::sendServiceHistoryRequest() { | |
| - if (!_main || !_main->started() || _delayedServiceMsgs.isEmpty() || _serviceHistoryRequest) return; | |
| - | |
| - auto user = App::userLoaded(ServiceUserId); | |
| - if (!user) { | |
| - auto userFlags = MTPDuser::Flag::f_first_name | MTPDuser::Flag::f_phone | MTPDuser::Flag::f_status | MTPDuser::Flag::f_verified; | |
| - user = App::feedUsers(MTP_vector<MTPUser>(1, MTP_user( | |
| - MTP_flags(userFlags), | |
| - MTP_int(ServiceUserId), | |
| - MTPlong(), | |
| - MTP_string("Telegram"), | |
| - MTPstring(), | |
| - MTPstring(), | |
| - MTP_string("42777"), | |
| - MTP_userProfilePhotoEmpty(), | |
| - MTP_userStatusRecently(), | |
| - MTPint(), | |
| - MTPstring(), | |
| - MTPstring(), | |
| - MTPstring()))); | |
| - } | |
| - auto offsetId = 0; | |
| - auto offsetDate = 0; | |
| - auto addOffset = 0; | |
| - auto limit = 1; | |
| - auto maxId = 0; | |
| - auto minId = 0; | |
| - auto historyHash = 0; | |
| - _serviceHistoryRequest = MTP::send( | |
| - MTPmessages_GetHistory( | |
| - user->input, | |
| - MTP_int(offsetId), | |
| - MTP_int(offsetDate), | |
| - MTP_int(addOffset), | |
| - MTP_int(limit), | |
| - MTP_int(maxId), | |
| - MTP_int(minId), | |
| - MTP_int(historyHash)), | |
| - _main->rpcDone(&MainWidget::serviceHistoryDone), | |
| - _main->rpcFail(&MainWidget::serviceHistoryFail)); | |
| } | |
| -void MainWindow::setupMain(const MTPUser *self) { | |
| +void MainWindow::setupMain() { | |
| Expects(AuthSession::Exists()); | |
| auto animated = (_intro || _passcodeLock); | |
| @@ -294,7 +231,7 @@ | |
| } else { | |
| _main->activate(); | |
| } | |
| - _main->start(self); | |
| + _main->start(); | |
| fixOrder(); | |
| } | |
| @@ -302,7 +239,11 @@ | |
| void MainWindow::showSettings() { | |
| if (isHidden()) showFromTray(); | |
| - controller()->showSpecialLayer(Box<Settings::Widget>()); | |
| + if (const auto controller = this->controller()) { | |
| + controller->showSettings(); | |
| + } else { | |
| + showSpecialLayer(Box<Settings::LayerWidget>(), anim::type::normal); | |
| + } | |
| } | |
| void MainWindow::showSpecialLayer( | |
| @@ -367,6 +308,12 @@ | |
| } | |
| } | |
| +void MainWindow::ui_removeLayerBlackout() { | |
| + if (_layer) { | |
| + _layer->removeBodyCache(); | |
| + } | |
| +} | |
| + | |
| MainWidget *MainWindow::mainWidget() { | |
| return _main; | |
| } | |
| @@ -595,7 +542,7 @@ | |
| void MainWindow::onShowAddContact() { | |
| if (isHidden()) showFromTray(); | |
| - if (App::self()) { | |
| + if (AuthSession::Exists()) { | |
| Ui::show(Box<AddContactBox>(), LayerOption::KeepOther); | |
| } | |
| } | |
| @@ -603,7 +550,7 @@ | |
| void MainWindow::onShowNewGroup() { | |
| if (isHidden()) showFromTray(); | |
| - if (App::self()) { | |
| + if (AuthSession::Exists()) { | |
| Ui::show( | |
| Box<GroupInfoBox>(CreatingGroupGroup, false), | |
| LayerOption::KeepOther); | |
| @@ -794,7 +741,7 @@ | |
| if (_clearManager && _clearManager->hasTask(Local::ClearManagerStorage)) { | |
| return TempDirRemoving; | |
| } | |
| - return (Local::hasImages() || Local::hasStickers() || Local::hasWebFiles() || Local::hasAudios()) ? TempDirExists : TempDirEmpty; | |
| + return TempDirEmpty; | |
| } | |
| void MainWindow::tempDirDelete(int task) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwindow.h work/tdesktop-1.4.0/Telegram/SourceFiles/mainwindow.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mainwindow.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mainwindow.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -52,10 +52,7 @@ | |
| void setupPasscodeLock(); | |
| void clearPasscodeLock(); | |
| void setupIntro(); | |
| - void setupMain(const MTPUser *user = nullptr); | |
| - void serviceNotification(const TextWithEntities &message, const MTPMessageMedia &media = MTP_messageMediaEmpty(), int32 date = 0, bool force = false); | |
| - void sendServiceHistoryRequest(); | |
| - void showDelayedServiceMsgs(); | |
| + void setupMain(); | |
| MainWidget *chatsWidget() { | |
| return mainWidget(); | |
| @@ -111,6 +108,7 @@ | |
| LayerOptions options, | |
| anim::type animated); | |
| void ui_hideSettingsAndLayer(anim::type animated); | |
| + void ui_removeLayerBlackout(); | |
| bool ui_isLayerShown(); | |
| void ui_showMediaPreview( | |
| Data::FileOrigin origin, | |
| @@ -165,15 +163,6 @@ | |
| void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) override; | |
| QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64; | |
| - struct DelayedServiceMsg { | |
| - DelayedServiceMsg(const TextWithEntities &message, const MTPMessageMedia &media, int32 date) : message(message), media(media), date(date) { | |
| - } | |
| - TextWithEntities message; | |
| - MTPMessageMedia media; | |
| - int32 date; | |
| - }; | |
| - QList<DelayedServiceMsg> _delayedServiceMsgs; | |
| - mtpRequestId _serviceHistoryRequest = 0; | |
| TimeMs _lastTrayClickTime = 0; | |
| object_ptr<Window::PasscodeLockWidget> _passcodeLock = { nullptr }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/media_audio.h work/tdesktop-1.4.0/Telegram/SourceFiles/media/media_audio.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/media_audio.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/media/media_audio.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -324,11 +324,11 @@ | |
| namespace Media { | |
| namespace Audio { | |
| -FORCE_INLINE uint16 ReadOneSample(uchar data) { | |
| +TG_FORCE_INLINE uint16 ReadOneSample(uchar data) { | |
| return qAbs((static_cast<int16>(data) - 0x80) * 0x100); | |
| } | |
| -FORCE_INLINE uint16 ReadOneSample(int16 data) { | |
| +TG_FORCE_INLINE uint16 ReadOneSample(int16 data) { | |
| return qAbs(data); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/player/media_player_instance.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/media/player/media_player_instance.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/player/media_player_instance.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/media/player/media_player_instance.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -54,11 +54,6 @@ | |
| subscribe(Media::Player::Updated(), [this](const AudioMsgId &audioId) { | |
| handleSongUpdate(audioId); | |
| }); | |
| - subscribe(Global::RefSelfChanged(), [this] { | |
| - if (!App::self()) { | |
| - handleLogout(); | |
| - } | |
| - }); | |
| // While we have one Media::Player::Instance for all authsessions we have to do this. | |
| auto handleAuthSessionChange = [this] { | |
| @@ -69,9 +64,11 @@ | |
| pause(AudioMsgId::Type::Song); | |
| } | |
| }); | |
| + } else { | |
| + handleLogout(); | |
| } | |
| }; | |
| - subscribe(Messenger::Instance().authSessionChanged(), [handleAuthSessionChange] { | |
| + subscribe(Messenger::Instance().authSessionChanged(), [=] { | |
| handleAuthSessionChange(); | |
| }); | |
| handleAuthSessionChange(); | |
| @@ -130,7 +127,7 @@ | |
| const auto fullId = data->current.contextId(); | |
| data->playlistIndex = data->playlistSlice->indexOf(fullId); | |
| } else { | |
| - data->playlistIndex = base::none; | |
| + data->playlistIndex = std::nullopt; | |
| } | |
| data->playlistChanges.fire({}); | |
| } | |
| @@ -149,7 +146,7 @@ | |
| return [&](const SparseIdsMergedSlice &data) { | |
| return inSameDomain(a, b) | |
| ? data.distance(a, b) | |
| - : base::optional<int>(); | |
| + : std::optional<int>(); | |
| }; | |
| }; | |
| @@ -183,14 +180,14 @@ | |
| playlistUpdated(data); | |
| }, data->playlistLifetime); | |
| } else { | |
| - data->playlistSlice = base::none; | |
| - data->playlistSliceKey = data->playlistRequestedKey = base::none; | |
| + data->playlistSlice = std::nullopt; | |
| + data->playlistSliceKey = data->playlistRequestedKey = std::nullopt; | |
| playlistUpdated(data); | |
| } | |
| } | |
| auto Instance::playlistKey(not_null<Data*> data) const | |
| --> base::optional<SliceKey> { | |
| +-> std::optional<SliceKey> { | |
| const auto contextId = data->current.contextId(); | |
| const auto history = data->history; | |
| if (!contextId || !history || !IsServerMsgId(contextId.msg)) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/player/media_player_instance.h work/tdesktop-1.4.0/Telegram/SourceFiles/media/player/media_player_instance.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/player/media_player_instance.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/media/player/media_player_instance.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -139,10 +139,10 @@ | |
| Storage::SharedMediaType overview; | |
| AudioMsgId current; | |
| AudioMsgId seeking; | |
| - base::optional<SparseIdsMergedSlice> playlistSlice; | |
| - base::optional<SliceKey> playlistSliceKey; | |
| - base::optional<SliceKey> playlistRequestedKey; | |
| - base::optional<int> playlistIndex; | |
| + std::optional<SparseIdsMergedSlice> playlistSlice; | |
| + std::optional<SliceKey> playlistSliceKey; | |
| + std::optional<SliceKey> playlistRequestedKey; | |
| + std::optional<int> playlistIndex; | |
| rpl::lifetime playlistLifetime; | |
| rpl::event_stream<> playlistChanges; | |
| History *history = nullptr; | |
| @@ -156,7 +156,7 @@ | |
| void setCurrent(const AudioMsgId &audioId); | |
| void refreshPlaylist(not_null<Data*> data); | |
| - base::optional<SliceKey> playlistKey(not_null<Data*> data) const; | |
| + std::optional<SliceKey> playlistKey(not_null<Data*> data) const; | |
| bool validPlaylist(not_null<Data*> data); | |
| void validatePlaylist(not_null<Data*> data); | |
| void playlistUpdated(not_null<Data*> data); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/player/media_player.style work/tdesktop-1.4.0/Telegram/SourceFiles/media/player/media_player.style | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/player/media_player.style 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/media/player/media_player.style 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -193,17 +193,7 @@ | |
| mediaPlayerPanelPlayTop: 58px; | |
| mediaPlayerPanelPlaybackTop: 32px; | |
| mediaPlayerPanelPlaybackPadding: 8px; | |
| -mediaPlayerPanelPlayback: MediaSlider { | |
| - width: 3px; | |
| - activeFg: mediaPlayerActiveFg; | |
| - inactiveFg: mediaPlayerInactiveFg; | |
| - activeFgOver: mediaPlayerActiveFg; | |
| - inactiveFgOver: mediaPlayerInactiveFg; | |
| - activeFgDisabled: mediaPlayerInactiveFg; | |
| - inactiveFgDisabled: windowBg; | |
| - seekSize: size(9px, 9px); | |
| - duration: 150; | |
| -} | |
| +mediaPlayerPanelPlayback: defaultContinuousSlider; | |
| mediaPlayerPanelVolumeTop: 65px; | |
| mediaPlayerPanelVolumeSkip: 3px; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/view/media_clip_playback.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/media/view/media_clip_playback.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/view/media_clip_playback.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/media/view/media_clip_playback.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -94,7 +94,7 @@ | |
| } | |
| void Playback::step_value(float64 ms, bool timer) { | |
| - auto dt = ms / kPlaybackAnimationDurationMs; | |
| + auto dt = anim::Disabled() ? 1. : (ms / kPlaybackAnimationDurationMs); | |
| if (dt >= 1.) { | |
| _a_value.stop(); | |
| a_value.finish(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -53,7 +53,7 @@ | |
| if (const auto peer = (*photo)->peer) { | |
| return peer->id; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } else if (const auto msgId = base::get_if<FullMsgId>(&value)) { | |
| if (const auto item = App::histItemById(*msgId)) { | |
| if (!item->toHistoryMessage()) { | |
| @@ -62,7 +62,7 @@ | |
| return groupId; | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| Unexpected("Variant in ComputeContext(SharedMediaWithLastSlice::Value)"); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mediaview.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/mediaview.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mediaview.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mediaview.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -336,12 +336,12 @@ | |
| const auto dNow = QDateTime::currentDateTime(); | |
| const auto d = [&] { | |
| - if (_photo) { | |
| + if (const auto item = App::histItemById(_msgid)) { | |
| + return ItemDateTime(item); | |
| + } else if (_photo) { | |
| return ParseDateTime(_photo->date); | |
| } else if (_doc) { | |
| return ParseDateTime(_doc->date); | |
| - } else if (const auto item = App::histItemById(_msgid)) { | |
| - return ItemDateTime(item); | |
| } | |
| return dNow; | |
| }(); | |
| @@ -442,7 +442,7 @@ | |
| auto canDelete = [&] { | |
| if (_canDeleteItem) { | |
| return true; | |
| - } else if (!_msgid && _photo && App::self() && _user == App::self()) { | |
| + } else if (!_msgid && _photo && _user && _user == Auth().user()) { | |
| return _userPhotosData && _fullIndex && _fullCount; | |
| } else if (_photo && _photo->peer && _photo->peer->userpicPhotoId() == _photo->id) { | |
| if (auto chat = _photo->peer->asChat()) { | |
| @@ -464,7 +464,7 @@ | |
| } | |
| auto MediaView::computeOverviewType() const | |
| --> base::optional<SharedMediaType> { | |
| +-> std::optional<SharedMediaType> { | |
| if (const auto mediaType = sharedMediaType()) { | |
| if (const auto overviewType = SharedMediaOverviewType(*mediaType)) { | |
| return overviewType; | |
| @@ -476,12 +476,15 @@ | |
| } | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| void MediaView::step_state(TimeMs ms, bool timer) { | |
| + if (anim::Disabled()) { | |
| + ms += st::mediaviewShowDuration + st::mediaviewHideDuration; | |
| + } | |
| bool result = false; | |
| - for (Showing::iterator i = _animations.begin(); i != _animations.end();) { | |
| + for (auto i = _animations.begin(); i != _animations.end();) { | |
| TimeMs start = i.value(); | |
| switch (i.key()) { | |
| case OverLeftNav: update(_leftNav); break; | |
| @@ -584,8 +587,11 @@ | |
| return; | |
| } | |
| const auto wasAnimating = _radial.animating(); | |
| - _radial.update(radialProgress(), !radialLoading(), ms + radialTimeShift()); | |
| - if (timer && (wasAnimating || _radial.animating())) { | |
| + const auto updated = _radial.update( | |
| + radialProgress(), | |
| + !radialLoading(), | |
| + ms + radialTimeShift()); | |
| + if (timer && (wasAnimating || _radial.animating()) && (!anim::Disabled() || updated)) { | |
| update(radialRect()); | |
| } | |
| const auto ready = _doc && _doc->loaded(); | |
| @@ -691,7 +697,7 @@ | |
| stopGif(); | |
| delete _menu; | |
| _menu = nullptr; | |
| - setContext(base::none); | |
| + setContext(std::nullopt); | |
| _from = nullptr; | |
| _photo = nullptr; | |
| _doc = nullptr; | |
| @@ -1076,7 +1082,7 @@ | |
| } | |
| } | |
| -base::optional<MediaView::SharedMediaType> MediaView::sharedMediaType() const { | |
| +std::optional<MediaView::SharedMediaType> MediaView::sharedMediaType() const { | |
| using Type = SharedMediaType; | |
| if (auto item = App::histItemById(_msgid)) { | |
| if (_photo) { | |
| @@ -1093,10 +1099,10 @@ | |
| return Type::File; | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| -base::optional<MediaView::SharedMediaKey> MediaView::sharedMediaKey() const { | |
| +std::optional<MediaView::SharedMediaKey> MediaView::sharedMediaKey() const { | |
| if (!_msgid && _peer && !_user && _photo && _peer->userpicPhotoId() == _photo->id) { | |
| return SharedMediaKey { | |
| _history->peer->id, | |
| @@ -1106,7 +1112,7 @@ | |
| }; | |
| } | |
| if (!IsServerMsgId(_msgid.msg)) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| auto keyForType = [this](SharedMediaType type) -> SharedMediaKey { | |
| return { | |
| @@ -1146,7 +1152,7 @@ | |
| return [&](const SharedMediaWithLastSlice &data) { | |
| return inSameDomain(a, b) | |
| ? data.distance(a, b) | |
| - : base::optional<int>(); | |
| + : std::optional<int>(); | |
| }; | |
| }; | |
| @@ -1182,15 +1188,15 @@ | |
| }, _sharedMedia->lifetime); | |
| } else { | |
| _sharedMedia = nullptr; | |
| - _sharedMediaData = base::none; | |
| - _sharedMediaDataKey = base::none; | |
| + _sharedMediaData = std::nullopt; | |
| + _sharedMediaDataKey = std::nullopt; | |
| } | |
| } | |
| void MediaView::handleSharedMediaUpdate(SharedMediaWithLastSlice &&update) { | |
| if ((!_photo && !_doc) || !_sharedMedia) { | |
| - _sharedMediaData = base::none; | |
| - _sharedMediaDataKey = base::none; | |
| + _sharedMediaData = std::nullopt; | |
| + _sharedMediaDataKey = std::nullopt; | |
| } else { | |
| _sharedMediaData = std::move(update); | |
| _sharedMediaDataKey = _sharedMedia->key; | |
| @@ -1200,14 +1206,14 @@ | |
| preloadData(0); | |
| } | |
| -base::optional<MediaView::UserPhotosKey> MediaView::userPhotosKey() const { | |
| +std::optional<MediaView::UserPhotosKey> MediaView::userPhotosKey() const { | |
| if (!_msgid && _user && _photo) { | |
| return UserPhotosKey { | |
| _user->bareId(), | |
| _photo->id | |
| }; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| bool MediaView::validUserPhotos() const { | |
| @@ -1245,13 +1251,13 @@ | |
| }, _userPhotos->lifetime); | |
| } else { | |
| _userPhotos = nullptr; | |
| - _userPhotosData = base::none; | |
| + _userPhotosData = std::nullopt; | |
| } | |
| } | |
| void MediaView::handleUserPhotosUpdate(UserPhotosSlice &&update) { | |
| if (!_photo || !_userPhotos) { | |
| - _userPhotosData = base::none; | |
| + _userPhotosData = std::nullopt; | |
| } else { | |
| _userPhotosData = std::move(update); | |
| } | |
| @@ -1352,7 +1358,7 @@ | |
| if (context) { | |
| setContext(context); | |
| } else { | |
| - setContext(base::none); | |
| + setContext(std::nullopt); | |
| } | |
| _firstOpenedPeerPhoto = false; | |
| @@ -1404,7 +1410,7 @@ | |
| if (context) { | |
| setContext(context); | |
| } else { | |
| - setContext(base::none); | |
| + setContext(std::nullopt); | |
| } | |
| _photo = nullptr; | |
| @@ -2461,19 +2467,19 @@ | |
| Expects(!!_userPhotosData); | |
| if (index < 0 || index >= _userPhotosData->size()) { | |
| - return { base::none, nullptr }; | |
| + return { std::nullopt, nullptr }; | |
| } | |
| if (auto photo = Auth().data().photo((*_userPhotosData)[index])) { | |
| return { photo, nullptr }; | |
| } | |
| - return { base::none, nullptr }; | |
| + return { std::nullopt, nullptr }; | |
| } | |
| MediaView::Entity MediaView::entityForSharedMedia(int index) const { | |
| Expects(!!_sharedMediaData); | |
| if (index < 0 || index >= _sharedMediaData->size()) { | |
| - return { base::none, nullptr }; | |
| + return { std::nullopt, nullptr }; | |
| } | |
| auto value = (*_sharedMediaData)[index]; | |
| if (const auto photo = base::get_if<not_null<PhotoData*>>(&value)) { | |
| @@ -2482,7 +2488,7 @@ | |
| } else if (const auto itemId = base::get_if<FullMsgId>(&value)) { | |
| return entityForItemId(*itemId); | |
| } | |
| - return { base::none, nullptr }; | |
| + return { std::nullopt, nullptr }; | |
| } | |
| MediaView::Entity MediaView::entityForItemId(const FullMsgId &itemId) const { | |
| @@ -2494,9 +2500,9 @@ | |
| return { document, item }; | |
| } | |
| } | |
| - return { base::none, item }; | |
| + return { std::nullopt, item }; | |
| } | |
| - return { base::none, nullptr }; | |
| + return { std::nullopt, nullptr }; | |
| } | |
| MediaView::Entity MediaView::entityByIndex(int index) const { | |
| @@ -2505,7 +2511,7 @@ | |
| } else if (_userPhotosData) { | |
| return entityForUserPhotos(index); | |
| } | |
| - return { base::none, nullptr }; | |
| + return { std::nullopt, nullptr }; | |
| } | |
| void MediaView::setContext(base::optional_variant< | |
| @@ -2557,7 +2563,7 @@ | |
| } else if (_peer) { | |
| setContext(_peer); | |
| } else { | |
| - setContext(base::none); | |
| + setContext(std::nullopt); | |
| } | |
| stopGif(); | |
| if (auto photo = base::get_if<not_null<PhotoData*>>(&entity.data)) { | |
| @@ -2998,10 +3004,10 @@ | |
| void MediaView::setVisible(bool visible) { | |
| if (!visible) { | |
| _sharedMedia = nullptr; | |
| - _sharedMediaData = base::none; | |
| - _sharedMediaDataKey = base::none; | |
| + _sharedMediaData = std::nullopt; | |
| + _sharedMediaDataKey = std::nullopt; | |
| _userPhotos = nullptr; | |
| - _userPhotosData = base::none; | |
| + _userPhotosData = std::nullopt; | |
| if (_menu) _menu->hideMenu(true); | |
| _controlsHideTimer.stop(); | |
| _controlsState = ControlsShown; | |
| @@ -3058,19 +3064,19 @@ | |
| if (_sharedMediaData) { | |
| _index = _msgid | |
| ? _sharedMediaData->indexOf(_msgid) | |
| - : _photo ? _sharedMediaData->indexOf(_photo) : base::none; | |
| + : _photo ? _sharedMediaData->indexOf(_photo) : std::nullopt; | |
| _fullIndex = _sharedMediaData->skippedBefore() | |
| ? (_index | func::add(*_sharedMediaData->skippedBefore())) | |
| - : base::none; | |
| + : std::nullopt; | |
| _fullCount = _sharedMediaData->fullCount(); | |
| } else if (_userPhotosData) { | |
| - _index = _photo ? _userPhotosData->indexOf(_photo->id) : base::none; | |
| + _index = _photo ? _userPhotosData->indexOf(_photo->id) : std::nullopt; | |
| _fullIndex = _userPhotosData->skippedBefore() | |
| ? (_index | func::add(*_userPhotosData->skippedBefore())) | |
| - : base::none; | |
| + : std::nullopt; | |
| _fullCount = _userPhotosData->fullCount(); | |
| } else { | |
| - _index = _fullIndex = _fullCount = base::none; | |
| + _index = _fullIndex = _fullCount = std::nullopt; | |
| } | |
| } | |
| @@ -3099,7 +3105,7 @@ | |
| _headerText = lang(lng_mediaview_single_photo); | |
| } | |
| } | |
| - _headerHasLink = computeOverviewType() != base::none; | |
| + _headerHasLink = computeOverviewType() != std::nullopt; | |
| auto hwidth = st::mediaviewThickFont->width(_headerText); | |
| if (hwidth > width() / 3) { | |
| hwidth = width() / 3; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mediaview.h work/tdesktop-1.4.0/Telegram/SourceFiles/mediaview.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mediaview.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mediaview.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -161,16 +161,16 @@ | |
| struct SharedMedia; | |
| using SharedMediaType = SharedMediaWithLastSlice::Type; | |
| using SharedMediaKey = SharedMediaWithLastSlice::Key; | |
| - base::optional<SharedMediaType> sharedMediaType() const; | |
| - base::optional<SharedMediaKey> sharedMediaKey() const; | |
| - base::optional<SharedMediaType> computeOverviewType() const; | |
| + std::optional<SharedMediaType> sharedMediaType() const; | |
| + std::optional<SharedMediaKey> sharedMediaKey() const; | |
| + std::optional<SharedMediaType> computeOverviewType() const; | |
| bool validSharedMedia() const; | |
| void validateSharedMedia(); | |
| void handleSharedMediaUpdate(SharedMediaWithLastSlice &&update); | |
| struct UserPhotos; | |
| using UserPhotosKey = UserPhotosSlice::Key; | |
| - base::optional<UserPhotosKey> userPhotosKey() const; | |
| + std::optional<UserPhotosKey> userPhotosKey() const; | |
| bool validUserPhotos() const; | |
| void validateUserPhotos(); | |
| void handleUserPhotosUpdate(UserPhotosSlice &&update); | |
| @@ -249,10 +249,10 @@ | |
| PhotoData *_photo = nullptr; | |
| DocumentData *_doc = nullptr; | |
| std::unique_ptr<SharedMedia> _sharedMedia; | |
| - base::optional<SharedMediaWithLastSlice> _sharedMediaData; | |
| - base::optional<SharedMediaWithLastSlice::Key> _sharedMediaDataKey; | |
| + std::optional<SharedMediaWithLastSlice> _sharedMediaData; | |
| + std::optional<SharedMediaWithLastSlice::Key> _sharedMediaDataKey; | |
| std::unique_ptr<UserPhotos> _userPhotos; | |
| - base::optional<UserPhotosSlice> _userPhotosData; | |
| + std::optional<UserPhotosSlice> _userPhotosData; | |
| QRect _closeNav, _closeNavIcon; | |
| QRect _leftNav, _leftNavIcon, _rightNav, _rightNavIcon; | |
| @@ -332,9 +332,9 @@ | |
| PeerData *_from = nullptr; | |
| Text _fromName; | |
| - base::optional<int> _index; // Index in current _sharedMedia data. | |
| - base::optional<int> _fullIndex; // Index in full shared media. | |
| - base::optional<int> _fullCount; | |
| + std::optional<int> _index; // Index in current _sharedMedia data. | |
| + std::optional<int> _fullIndex; // Index in full shared media. | |
| + std::optional<int> _fullCount; | |
| FullMsgId _msgid; | |
| bool _canForwardItem = false; | |
| bool _canDeleteItem = false; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/messenger.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/messenger.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/messenger.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/messenger.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -29,7 +29,7 @@ | |
| #include "core/update_checker.h" | |
| #include "passport/passport_form_controller.h" | |
| #include "observer_peer.h" | |
| -#include "storage/file_upload.h" | |
| +#include "storage/storage_databases.h" | |
| #include "mainwidget.h" | |
| #include "mediaview.h" | |
| #include "mtproto/dc_options.h" | |
| @@ -66,6 +66,8 @@ | |
| struct Messenger::Private { | |
| UserId authSessionUserId = 0; | |
| + QByteArray authSessionUserSerialized; | |
| + int32 authSessionUserStreamVersion = 0; | |
| std::unique_ptr<AuthSessionSettings> storedAuthSession; | |
| MTP::Instance::Config mtpConfig; | |
| MTP::AuthKeysList mtpKeysToDestroy; | |
| @@ -76,6 +78,7 @@ | |
| : QObject() | |
| , _launcher(launcher) | |
| , _private(std::make_unique<Private>()) | |
| +, _databases(std::make_unique<Storage::Databases>()) | |
| , _langpack(std::make_unique<Lang::Instance>()) | |
| , _audio(std::make_unique<Media::Audio::Instance>()) | |
| , _logo(Window::LoadLogo()) | |
| @@ -370,12 +373,19 @@ | |
| void Messenger::setAuthSessionUserId(UserId userId) { | |
| Expects(!authSession()); | |
| + | |
| _private->authSessionUserId = userId; | |
| } | |
| -void Messenger::setAuthSessionFromStorage(std::unique_ptr<AuthSessionSettings> data) { | |
| +void Messenger::setAuthSessionFromStorage( | |
| + std::unique_ptr<AuthSessionSettings> data, | |
| + QByteArray &&selfSerialized, | |
| + int32 selfStreamVersion) { | |
| Expects(!authSession()); | |
| + | |
| _private->storedAuthSession = std::move(data); | |
| + _private->authSessionUserSerialized = std::move(selfSerialized); | |
| + _private->authSessionUserStreamVersion = selfStreamVersion; | |
| } | |
| AuthSessionSettings *Messenger::getAuthSessionSettings() { | |
| @@ -453,7 +463,23 @@ | |
| } | |
| if (_private->authSessionUserId) { | |
| - authSessionCreate(base::take(_private->authSessionUserId)); | |
| + authSessionCreate(MTP_user( | |
| + MTP_flags(MTPDuser::Flag::f_self), | |
| + MTP_int(base::take(_private->authSessionUserId)), | |
| + MTPlong(), // access_hash | |
| + MTPstring(), // first_name | |
| + MTPstring(), // last_name | |
| + MTPstring(), // username | |
| + MTPstring(), // phone | |
| + MTPUserProfilePhoto(), | |
| + MTPUserStatus(), | |
| + MTPint(), // bot_info_version | |
| + MTPstring(), // restriction_reason | |
| + MTPstring(), // bot_inline_placeholder | |
| + MTPstring())); // lang_code | |
| + Local::readSelf( | |
| + base::take(_private->authSessionUserSerialized), | |
| + base::take(_private->authSessionUserStreamVersion)); | |
| } | |
| if (_private->storedAuthSession) { | |
| if (_authSession) { | |
| @@ -469,6 +495,11 @@ | |
| if (!Core::UpdaterDisabled()) { | |
| Core::UpdateChecker().setMtproto(mtp()); | |
| } | |
| + | |
| + if (_authSession) { | |
| + // Skip all pending self updates so that we won't Local::writeSelf. | |
| + Notify::peerUpdatedSendDelayed(); | |
| + } | |
| } | |
| void Messenger::destroyMtpKeys(MTP::AuthKeysList &&keys) { | |
| @@ -537,15 +568,8 @@ | |
| }); | |
| subscribe(authSessionChanged(), [this] { | |
| InvokeQueued(this, [this] { | |
| - if (_mtproto) { | |
| - _mtproto->requestConfig(); | |
| - } | |
| - }); | |
| - }); | |
| - subscribe(Global::RefSelfChanged(), [=] { | |
| - InvokeQueued(this, [=] { | |
| - const auto phone = App::self() | |
| - ? App::self()->phone() | |
| + const auto phone = AuthSession::Exists() | |
| + ? Auth().user()->phone() | |
| : QString(); | |
| if (cLoggedPhoneNumber() != phone) { | |
| cSetLoggedPhoneNumber(phone); | |
| @@ -554,87 +578,13 @@ | |
| } | |
| Local::writeSettings(); | |
| } | |
| + if (_mtproto) { | |
| + _mtproto->requestConfig(); | |
| + } | |
| }); | |
| }); | |
| } | |
| -void Messenger::regPhotoUpdate(const PeerId &peer, const FullMsgId &msgId) { | |
| - photoUpdates.insert(msgId, peer); | |
| -} | |
| - | |
| -bool Messenger::isPhotoUpdating(const PeerId &peer) { | |
| - for (QMap<FullMsgId, PeerId>::iterator i = photoUpdates.begin(), e = photoUpdates.end(); i != e; ++i) { | |
| - if (i.value() == peer) { | |
| - return true; | |
| - } | |
| - } | |
| - return false; | |
| -} | |
| - | |
| -void Messenger::cancelPhotoUpdate(const PeerId &peer) { | |
| - for (QMap<FullMsgId, PeerId>::iterator i = photoUpdates.begin(), e = photoUpdates.end(); i != e;) { | |
| - if (i.value() == peer) { | |
| - i = photoUpdates.erase(i); | |
| - } else { | |
| - ++i; | |
| - } | |
| - } | |
| -} | |
| - | |
| -void Messenger::selfPhotoCleared(const MTPUserProfilePhoto &result) { | |
| - if (!App::self()) return; | |
| - App::self()->setPhoto(result); | |
| - emit peerPhotoDone(App::self()->id); | |
| -} | |
| - | |
| -void Messenger::chatPhotoCleared(PeerId peer, const MTPUpdates &updates) { | |
| - if (App::main()) { | |
| - App::main()->sentUpdatesReceived(updates); | |
| - } | |
| - cancelPhotoUpdate(peer); | |
| - emit peerPhotoDone(peer); | |
| -} | |
| - | |
| -void Messenger::selfPhotoDone(const MTPphotos_Photo &result) { | |
| - if (!App::self()) return; | |
| - const auto &photo = result.c_photos_photo(); | |
| - Auth().data().photo(photo.vphoto); | |
| - App::feedUsers(photo.vusers); | |
| - cancelPhotoUpdate(App::self()->id); | |
| - emit peerPhotoDone(App::self()->id); | |
| -} | |
| - | |
| -void Messenger::chatPhotoDone(PeerId peer, const MTPUpdates &updates) { | |
| - if (App::main()) { | |
| - App::main()->sentUpdatesReceived(updates); | |
| - } | |
| - cancelPhotoUpdate(peer); | |
| - emit peerPhotoDone(peer); | |
| -} | |
| - | |
| -bool Messenger::peerPhotoFailed(PeerId peer, const RPCError &error) { | |
| - if (MTP::isDefaultHandledError(error)) return false; | |
| - | |
| - LOG(("Application Error: update photo failed %1: %2").arg(error.type()).arg(error.description())); | |
| - cancelPhotoUpdate(peer); | |
| - emit peerPhotoFail(peer); | |
| - return true; | |
| -} | |
| - | |
| -void Messenger::peerClearPhoto(PeerId id) { | |
| - if (!AuthSession::Exists()) return; | |
| - | |
| - if (id == Auth().userPeerId()) { | |
| - MTP::send(MTPphotos_UpdateProfilePhoto(MTP_inputPhotoEmpty()), rpcDone(&Messenger::selfPhotoCleared), rpcFail(&Messenger::peerPhotoFailed, id)); | |
| - } else if (peerIsChat(id)) { | |
| - MTP::send(MTPmessages_EditChatPhoto(peerToBareMTPInt(id), MTP_inputChatPhotoEmpty()), rpcDone(&Messenger::chatPhotoCleared, id), rpcFail(&Messenger::peerPhotoFailed, id)); | |
| - } else if (peerIsChannel(id)) { | |
| - if (auto channel = App::channelLoaded(id)) { | |
| - MTP::send(MTPchannels_EditPhoto(channel->inputChannel, MTP_inputChatPhotoEmpty()), rpcDone(&Messenger::chatPhotoCleared, id), rpcFail(&Messenger::peerPhotoFailed, id)); | |
| - } | |
| - } | |
| -} | |
| - | |
| void Messenger::killDownloadSessionsStart(MTP::DcId dcId) { | |
| if (killDownloadSessionTimes.constFind(dcId) == killDownloadSessionTimes.cend()) { | |
| killDownloadSessionTimes.insert(dcId, getms() + MTPAckSendWaiting + MTPKillFileSessionTimeout); | |
| @@ -668,7 +618,8 @@ | |
| } | |
| void Messenger::checkLocalTime() { | |
| - if (App::main()) App::main()->checkLastUpdate(checkms()); | |
| + const auto updated = checkms(); | |
| + if (App::main()) App::main()->checkLastUpdate(updated); | |
| } | |
| void Messenger::onAppStateChanged(Qt::ApplicationState state) { | |
| @@ -725,37 +676,15 @@ | |
| } | |
| } | |
| -void Messenger::photoUpdated(const FullMsgId &msgId, const MTPInputFile &file) { | |
| - Expects(AuthSession::Exists()); | |
| - | |
| - auto i = photoUpdates.find(msgId); | |
| - if (i != photoUpdates.end()) { | |
| - auto id = i.value(); | |
| - if (id == Auth().userPeerId()) { | |
| - MTP::send(MTPphotos_UploadProfilePhoto(file), rpcDone(&Messenger::selfPhotoDone), rpcFail(&Messenger::peerPhotoFailed, id)); | |
| - } else if (peerIsChat(id)) { | |
| - auto history = App::history(id); | |
| - history->sendRequestId = MTP::send(MTPmessages_EditChatPhoto(history->peer->asChat()->inputChat, MTP_inputChatUploadedPhoto(file)), rpcDone(&Messenger::chatPhotoDone, id), rpcFail(&Messenger::peerPhotoFailed, id), 0, 0, history->sendRequestId); | |
| - } else if (peerIsChannel(id)) { | |
| - auto history = App::history(id); | |
| - history->sendRequestId = MTP::send(MTPchannels_EditPhoto(history->peer->asChannel()->inputChannel, MTP_inputChatUploadedPhoto(file)), rpcDone(&Messenger::chatPhotoDone, id), rpcFail(&Messenger::peerPhotoFailed, id), 0, 0, history->sendRequestId); | |
| - } | |
| - } | |
| -} | |
| - | |
| void Messenger::onSwitchDebugMode() { | |
| if (Logs::DebugEnabled()) { | |
| - QFile(cWorkingDir() + qsl("tdata/withdebug")).remove(); | |
| Logs::SetDebugEnabled(false); | |
| + Sandbox::WriteDebugModeSetting(); | |
| App::restart(); | |
| } else { | |
| Logs::SetDebugEnabled(true); | |
| + Sandbox::WriteDebugModeSetting(); | |
| DEBUG_LOG(("Debug logs started.")); | |
| - QFile f(cWorkingDir() + qsl("tdata/withdebug")); | |
| - if (f.open(QIODevice::WriteOnly)) { | |
| - f.write("1"); | |
| - f.close(); | |
| - } | |
| Ui::hideLayer(); | |
| } | |
| } | |
| @@ -782,20 +711,20 @@ | |
| App::restart(); | |
| } | |
| -void Messenger::authSessionCreate(UserId userId) { | |
| +void Messenger::authSessionCreate(const MTPUser &user) { | |
| Expects(_mtproto != nullptr); | |
| - _authSession = std::make_unique<AuthSession>(userId); | |
| + _authSession = std::make_unique<AuthSession>(user); | |
| authSessionChanged().notify(true); | |
| } | |
| void Messenger::authSessionDestroy() { | |
| unlockTerms(); | |
| - _uploaderSubscription = rpl::lifetime(); | |
| _authSession.reset(); | |
| _private->storedAuthSession.reset(); | |
| _private->authSessionUserId = 0; | |
| + _private->authSessionUserSerialized = {}; | |
| authSessionChanged().notify(true); | |
| } | |
| @@ -995,54 +924,6 @@ | |
| return false; | |
| } | |
| -void Messenger::uploadProfilePhoto(QImage &&tosend, const PeerId &peerId) { | |
| - PreparedPhotoThumbs photoThumbs; | |
| - QVector<MTPPhotoSize> photoSizes; | |
| - | |
| - auto thumb = App::pixmapFromImageInPlace(tosend.scaled(160, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation)); | |
| - photoThumbs.insert('a', thumb); | |
| - photoSizes.push_back(MTP_photoSize(MTP_string("a"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0))); | |
| - | |
| - auto medium = App::pixmapFromImageInPlace(tosend.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)); | |
| - photoThumbs.insert('b', medium); | |
| - photoSizes.push_back(MTP_photoSize(MTP_string("b"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0))); | |
| - | |
| - auto full = QPixmap::fromImage(tosend, Qt::ColorOnly); | |
| - photoThumbs.insert('c', full); | |
| - photoSizes.push_back(MTP_photoSize(MTP_string("c"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0))); | |
| - | |
| - QByteArray jpeg; | |
| - QBuffer jpegBuffer(&jpeg); | |
| - full.save(&jpegBuffer, "JPG", 87); | |
| - | |
| - PhotoId id = rand_value<PhotoId>(); | |
| - | |
| - auto photo = MTP_photo( | |
| - MTP_flags(0), | |
| - MTP_long(id), | |
| - MTP_long(0), | |
| - MTP_bytes(QByteArray()), | |
| - MTP_int(unixtime()), | |
| - MTP_vector<MTPPhotoSize>(photoSizes)); | |
| - | |
| - QString file, filename; | |
| - int32 filesize = 0; | |
| - QByteArray data; | |
| - | |
| - SendMediaReady ready(SendMediaType::Photo, file, filename, filesize, data, id, id, qsl("jpg"), peerId, photo, photoThumbs, MTP_documentEmpty(MTP_long(0)), jpeg, 0); | |
| - | |
| - if (!_uploaderSubscription) { | |
| - _uploaderSubscription = Auth().uploader().photoReady( | |
| - ) | rpl::start_with_next([=](const Storage::UploadedPhoto &data) { | |
| - photoUpdated(data.fullId, data.file); | |
| - }); | |
| - } | |
| - | |
| - FullMsgId newId(peerToChannel(peerId), clientMsgId()); | |
| - regPhotoUpdate(peerId, newId); | |
| - Auth().uploader().uploadMedia(newId, ready); | |
| -} | |
| - | |
| void Messenger::lockByPasscode() { | |
| _passcodeLock = true; | |
| _window->setupPasscodeLock(); | |
| @@ -1084,8 +965,8 @@ | |
| } | |
| } | |
| -base::optional<Window::TermsLock> Messenger::termsLocked() const { | |
| - return _termsLock ? base::make_optional(*_termsLock) : base::none; | |
| +std::optional<Window::TermsLock> Messenger::termsLocked() const { | |
| + return _termsLock ? base::make_optional(*_termsLock) : std::nullopt; | |
| } | |
| rpl::producer<bool> Messenger::termsLockChanges() const { | |
| @@ -1225,6 +1106,10 @@ | |
| w->setupIntro(); | |
| } | |
| App::histories().clear(); | |
| + if (const auto session = authSession()) { | |
| + session->data().cache().close(); | |
| + session->data().cache().clear(); | |
| + } | |
| authSessionDestroy(); | |
| if (_mediaView) { | |
| hideMediaView(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/messenger.h work/tdesktop-1.4.0/Telegram/SourceFiles/messenger.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/messenger.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/messenger.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -19,6 +19,10 @@ | |
| class MediaView; | |
| class BoxContent; | |
| +namespace Storage { | |
| +class Databases; | |
| +} // namespace Storage | |
| + | |
| namespace Core { | |
| class Launcher; | |
| } // namespace Core | |
| @@ -111,7 +115,9 @@ | |
| void setMtpKey(MTP::DcId dcId, const MTP::AuthKey::Data &keyData); | |
| void setAuthSessionUserId(UserId userId); | |
| void setAuthSessionFromStorage( | |
| - std::unique_ptr<AuthSessionSettings> data); | |
| + std::unique_ptr<AuthSessionSettings> data, | |
| + QByteArray &&selfSerialized, | |
| + int32 selfStreamVersion); | |
| AuthSessionSettings *getAuthSessionSettings(); | |
| // Serialization. | |
| @@ -125,6 +131,11 @@ | |
| void suggestMainDcId(MTP::DcId mainDcId); | |
| void destroyStaleAuthorizationKeys(); | |
| + // Databases | |
| + Storage::Databases &databases() { | |
| + return *_databases; | |
| + } | |
| + | |
| // AuthSession component. | |
| AuthSession *authSession() { | |
| return _authSession.get(); | |
| @@ -135,7 +146,7 @@ | |
| Lang::CloudManager *langCloudManager() { | |
| return _langCloudManager.get(); | |
| } | |
| - void authSessionCreate(UserId userId); | |
| + void authSessionCreate(const MTPUser &user); | |
| base::Observable<void> &authSessionChanged() { | |
| return _authSessionChanged; | |
| } | |
| @@ -153,20 +164,6 @@ | |
| void checkStartUrl(); | |
| bool openLocalUrl(const QString &url, QVariant context); | |
| - void uploadProfilePhoto(QImage &&tosend, const PeerId &peerId); | |
| - void regPhotoUpdate(const PeerId &peer, const FullMsgId &msgId); | |
| - bool isPhotoUpdating(const PeerId &peer); | |
| - void cancelPhotoUpdate(const PeerId &peer); | |
| - | |
| - void selfPhotoCleared(const MTPUserProfilePhoto &result); | |
| - void chatPhotoCleared(PeerId peer, const MTPUpdates &updates); | |
| - void selfPhotoDone(const MTPphotos_Photo &result); | |
| - void chatPhotoDone(PeerId peerId, const MTPUpdates &updates); | |
| - bool peerPhotoFailed(PeerId peerId, const RPCError &e); | |
| - void peerClearPhoto(PeerId peer); | |
| - | |
| - void writeUserConfigIn(TimeMs ms); | |
| - | |
| void killDownloadSessionsStart(MTP::DcId dcId); | |
| void killDownloadSessionsStop(MTP::DcId dcId); | |
| @@ -180,7 +177,7 @@ | |
| void lockByTerms(const Window::TermsLock &data); | |
| void unlockTerms(); | |
| - [[nodiscard]] base::optional<Window::TermsLock> termsLocked() const; | |
| + [[nodiscard]] std::optional<Window::TermsLock> termsLocked() const; | |
| rpl::producer<bool> termsLockChanges() const; | |
| rpl::producer<bool> termsLockValue() const; | |
| void termsDeleteNow(); | |
| @@ -208,10 +205,6 @@ | |
| protected: | |
| bool eventFilter(QObject *object, QEvent *event) override; | |
| -signals: | |
| - void peerPhotoDone(PeerId peer); | |
| - void peerPhotoFail(PeerId peer); | |
| - | |
| public slots: | |
| void onAllKeysDestroyed(); | |
| @@ -230,7 +223,6 @@ | |
| static void QuitAttempt(); | |
| void quitDelayed(); | |
| - void photoUpdated(const FullMsgId &msgId, const MTPInputFile &file); | |
| void resetAuthorizationKeys(); | |
| void authSessionDestroy(); | |
| void clearPasscodeLock(); | |
| @@ -238,8 +230,6 @@ | |
| not_null<Core::Launcher*> _launcher; | |
| - QMap<FullMsgId, PeerId> photoUpdates; | |
| - | |
| QMap<MTP::DcId, TimeMs> killDownloadSessionTimes; | |
| SingleTimer killDownloadSessionsTimer; | |
| @@ -249,6 +239,7 @@ | |
| QWidget _globalShortcutParent; | |
| + std::unique_ptr<Storage::Databases> _databases; | |
| std::unique_ptr<MainWindow> _window; | |
| std::unique_ptr<MediaView> _mediaView; | |
| std::unique_ptr<Lang::Instance> _langpack; | |
| @@ -262,9 +253,6 @@ | |
| base::Observable<void> _passcodedChanged; | |
| QPointer<BoxContent> _badProxyDisableBox; | |
| - // While profile photo uploading is not moved to apiwrap. | |
| - rpl::lifetime _uploaderSubscription; | |
| - | |
| std::unique_ptr<Media::Audio::Instance> _audio; | |
| QImage _logo; | |
| QImage _logoNoMargin; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/auth_key.h work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/auth_key.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/auth_key.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/auth_key.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -56,6 +56,9 @@ | |
| void write(QDataStream &to) const { | |
| to.writeRawData(reinterpret_cast<const char*>(_key.data()), _key.size()); | |
| } | |
| + bytes::const_span data() const { | |
| + return _key; | |
| + } | |
| bool equals(const std::shared_ptr<AuthKey> &other) const { | |
| return other ? (_key == other->_key) : false; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/core_types.h work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/core_types.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/core_types.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/core_types.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -12,7 +12,7 @@ | |
| #include <QtCore/QString> | |
| #include <QtCore/QByteArray> | |
| #include <rpl/details/callable.h> | |
| -#include "core/basic_types.h" | |
| +#include "base/basic_types.h" | |
| #include "base/match_method.h" | |
| #include "base/flags.h" | |
| #include "base/bytes.h" | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/mtp_instance.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/mtp_instance.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/mtp_instance.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/mtp_instance.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,6 +16,7 @@ | |
| #include "mtproto/sender.h" | |
| #include "mtproto/rsa_public_key.h" | |
| #include "storage/localstorage.h" | |
| +#include "calls/calls_instance.h" | |
| #include "auth_session.h" | |
| #include "application.h" | |
| #include "apiwrap.h" | |
| @@ -150,9 +151,9 @@ | |
| void configLoadDone(const MTPConfig &result); | |
| bool configLoadFail(const RPCError &error); | |
| - base::optional<ShiftedDcId> queryRequestByDc( | |
| + std::optional<ShiftedDcId> queryRequestByDc( | |
| mtpRequestId requestId) const; | |
| - base::optional<ShiftedDcId> changeRequestByDc( | |
| + std::optional<ShiftedDcId> changeRequestByDc( | |
| mtpRequestId requestId, DcId newdc); | |
| // RPCError::NoError means do not toggle onError callback. | |
| @@ -782,6 +783,18 @@ | |
| + (data.vexpires.v - unixtime()) * TimeMs(1000); | |
| requestConfigIfExpired(); | |
| + if (AuthSession::Exists()) { | |
| + using PeerToPeer = Calls::PeerToPeer; | |
| + const auto current = Auth().settings().callsPeerToPeer(); | |
| + if (current == PeerToPeer::DefaultContacts | |
| + || current == PeerToPeer::DefaultEveryone) { | |
| + Auth().settings().setCallsPeerToPeer( | |
| + (data.is_default_p2p_contacts() | |
| + ? PeerToPeer::DefaultContacts | |
| + : PeerToPeer::DefaultEveryone)); | |
| + } | |
| + } | |
| + | |
| emit _instance->configLoaded(); | |
| } | |
| @@ -793,17 +806,17 @@ | |
| return false; | |
| } | |
| -base::optional<ShiftedDcId> Instance::Private::queryRequestByDc( | |
| +std::optional<ShiftedDcId> Instance::Private::queryRequestByDc( | |
| mtpRequestId requestId) const { | |
| QMutexLocker locker(&_requestByDcLock); | |
| auto it = _requestsByDc.find(requestId); | |
| if (it != _requestsByDc.cend()) { | |
| return it->second; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| -base::optional<ShiftedDcId> Instance::Private::changeRequestByDc( | |
| +std::optional<ShiftedDcId> Instance::Private::changeRequestByDc( | |
| mtpRequestId requestId, | |
| DcId newdc) { | |
| QMutexLocker locker(&_requestByDcLock); | |
| @@ -816,7 +829,7 @@ | |
| } | |
| return it->second; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| void Instance::Private::checkDelayedRequests() { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/rpc_sender.h work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/rpc_sender.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/mtproto/rpc_sender.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/mtproto/rpc_sender.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,8 +7,9 @@ | |
| */ | |
| #pragma once | |
| -#include <rpl/details/callable.h> | |
| #include "base/flat_set.h" | |
| +#include "core/utils.h" | |
| +#include <rpl/details/callable.h> | |
| class RPCError { | |
| public: | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles: old_settings | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/overview/overview_layout.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/overview/overview_layout.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/overview/overview_layout.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/overview/overview_layout.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -227,10 +227,15 @@ | |
| } | |
| void RadialProgressItem::step_radial(TimeMs ms, bool timer) { | |
| + const auto updateRadial = [&] { | |
| + return _radial->update(dataProgress(), dataFinished(), ms); | |
| + }; | |
| if (timer) { | |
| - Auth().data().requestItemRepaint(parent()); | |
| + if (!anim::Disabled() || updateRadial()) { | |
| + Auth().data().requestItemRepaint(parent()); | |
| + } | |
| } else { | |
| - _radial->update(dataProgress(), dataFinished(), ms); | |
| + updateRadial(); | |
| if (!_radial->animating()) { | |
| checkRadialFinished(); | |
| } | |
| @@ -863,7 +868,7 @@ | |
| bool selected = (selection == FullSelection); | |
| _data->automaticLoad(parent()->fullId(), parent()); | |
| - bool loaded = _data->loaded() || Local::willStickerImageLoad(_data->mediaKey()), displayLoading = _data->displayLoading(); | |
| + bool loaded = _data->loaded(), displayLoading = _data->displayLoading(); | |
| if (displayLoading) { | |
| ensureRadial(); | |
| @@ -1024,8 +1029,7 @@ | |
| TextState Document::getState( | |
| QPoint point, | |
| StateRequest request) const { | |
| - const auto loaded = _data->loaded() | |
| - || Local::willStickerImageLoad(_data->mediaKey()); | |
| + const auto loaded = _data->loaded(); | |
| const auto wthumb = withThumb(); | |
| if (_data->isAudioFile()) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_encryption.h work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_encryption.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_encryption.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_encryption.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -24,7 +24,7 @@ | |
| struct DataError { | |
| // QByteArray - bad existing scan with such file_hash | |
| // QString - bad data field value with such key | |
| - // base::none - additional scan required | |
| + // std::nullopt - additional scan required | |
| base::optional_variant<QByteArray, QString> key; | |
| QString type; // personal_details, passport, etc. | |
| QString text; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_form_controller.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_form_controller.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_form_controller.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_form_controller.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -559,7 +559,7 @@ | |
| Unexpected("Type in Value::filesInEdit() const."); | |
| } | |
| -EditFile &Value::fileInEdit(FileType type, base::optional<int> fileIndex) { | |
| +EditFile &Value::fileInEdit(FileType type, std::optional<int> fileIndex) { | |
| switch (type) { | |
| case FileType::Scan: | |
| case FileType::Translation: { | |
| @@ -577,7 +577,7 @@ | |
| const EditFile &Value::fileInEdit( | |
| FileType type, | |
| - base::optional<int> fileIndex) const { | |
| + std::optional<int> fileIndex) const { | |
| switch (type) { | |
| case FileType::Scan: | |
| case FileType::Translation: { | |
| @@ -1232,7 +1232,7 @@ | |
| // Check if additional values should be copied from fallback values. | |
| const auto scheme = GetDocumentScheme( | |
| Scope::Type::PersonalDetails, | |
| - base::none, | |
| + std::nullopt, | |
| true); | |
| const auto dependencyIt = values.fields.find( | |
| scheme.additionalDependencyKey); | |
| @@ -1363,7 +1363,7 @@ | |
| return; | |
| } | |
| const auto nonconst = findValue(value); | |
| - const auto fileIndex = [&]() -> base::optional<int> { | |
| + const auto fileIndex = [&]() -> std::optional<int> { | |
| auto scanInEdit = EditFile{ nonconst, type, File(), nullptr }; | |
| if (type == FileType::Scan || type == FileType::Translation) { | |
| auto &list = nonconst->filesInEdit(type); | |
| @@ -1379,7 +1379,7 @@ | |
| type, | |
| std::move(scanInEdit)).first; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| }(); | |
| auto &scan = nonconst->fileInEdit(type, fileIndex); | |
| encryptFile(scan, std::move(content), [=](UploadScanData &&result) { | |
| @@ -1392,14 +1392,14 @@ | |
| void FormController::deleteScan( | |
| not_null<const Value*> value, | |
| FileType type, | |
| - base::optional<int> fileIndex) { | |
| + std::optional<int> fileIndex) { | |
| scanDeleteRestore(value, type, fileIndex, true); | |
| } | |
| void FormController::restoreScan( | |
| not_null<const Value*> value, | |
| FileType type, | |
| - base::optional<int> fileIndex) { | |
| + std::optional<int> fileIndex) { | |
| scanDeleteRestore(value, type, fileIndex, false); | |
| } | |
| @@ -1454,7 +1454,7 @@ | |
| void FormController::scanDeleteRestore( | |
| not_null<const Value*> value, | |
| FileType type, | |
| - base::optional<int> fileIndex, | |
| + std::optional<int> fileIndex, | |
| bool deleted) { | |
| const auto nonconst = findValue(value); | |
| auto &scan = nonconst->fileInEdit(type, fileIndex); | |
| @@ -1579,10 +1579,7 @@ | |
| } | |
| QString FormController::defaultPhoneNumber() const { | |
| - if (const auto self = App::self()) { | |
| - return self->phone(); | |
| - } | |
| - return QString(); | |
| + return Auth().user()->phone(); | |
| } | |
| auto FormController::scanUpdated() const | |
| @@ -1726,13 +1723,14 @@ | |
| file.id, | |
| file.accessHash, | |
| QByteArray(), // file_reference | |
| - base::none, // origin | |
| + std::nullopt, // origin | |
| SecureFileLocation, | |
| QString(), | |
| file.size, | |
| LoadToCacheAsWell, | |
| LoadFromCloudOrLocal, | |
| - false)); | |
| + false, | |
| + Data::kImageCacheTag)); | |
| const auto loader = j->second.get(); | |
| loader->connect(loader, &mtpFileLoader::progress, [=] { | |
| if (loader->finished()) { | |
| @@ -2301,10 +2299,10 @@ | |
| auto FormController::parseFile( | |
| const MTPSecureFile &data, | |
| const std::vector<EditFile> &editData) const | |
| --> base::optional<File> { | |
| +-> std::optional<File> { | |
| switch (data.type()) { | |
| case mtpc_secureFileEmpty: | |
| - return base::none; | |
| + return std::nullopt; | |
| case mtpc_secureFile: { | |
| const auto &fields = data.c_secureFile(); | |
| @@ -2338,16 +2336,17 @@ | |
| if (!i->uploadData) { | |
| return; | |
| } | |
| - Local::writeImage( | |
| - StorageKey( | |
| - storageMix32To64( | |
| - SecureFileLocation, | |
| - destination.dcId), | |
| - destination.id), | |
| - StorageImageSaved(QByteArray::fromRawData( | |
| - reinterpret_cast<const char*>( | |
| - i->uploadData->bytes.data()), | |
| - i->uploadData->bytes.size()))); | |
| + const auto &bytes = i->uploadData->bytes; | |
| + if (bytes.size() > Storage::kMaxFileInMemory) { | |
| + return; | |
| + } | |
| + Auth().data().cache().put( | |
| + Data::DocumentCacheKey(destination.dcId, destination.id), | |
| + Storage::Cache::Database::TaggedValue( | |
| + QByteArray( | |
| + reinterpret_cast<const char*>(bytes.data()), | |
| + bytes.size()), | |
| + Data::kImageCacheTag)); | |
| } | |
| auto FormController::parseValue( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_form_controller.h work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_form_controller.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_form_controller.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_form_controller.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -205,10 +205,10 @@ | |
| const QString &fileMissingError(FileType type) const; | |
| std::vector<EditFile> &filesInEdit(FileType type); | |
| const std::vector<EditFile> &filesInEdit(FileType type) const; | |
| - EditFile &fileInEdit(FileType type, base::optional<int> fileIndex); | |
| + EditFile &fileInEdit(FileType type, std::optional<int> fileIndex); | |
| const EditFile &fileInEdit( | |
| FileType type, | |
| - base::optional<int> fileIndex) const; | |
| + std::optional<int> fileIndex) const; | |
| std::vector<EditFile> takeAllFilesInEdit(); | |
| @@ -345,11 +345,11 @@ | |
| void deleteScan( | |
| not_null<const Value*> value, | |
| FileType type, | |
| - base::optional<int> fileIndex); | |
| + std::optional<int> fileIndex); | |
| void restoreScan( | |
| not_null<const Value*> value, | |
| FileType type, | |
| - base::optional<int> fileIndex); | |
| + std::optional<int> fileIndex); | |
| rpl::producer<> secretReadyEvents() const; | |
| @@ -407,7 +407,7 @@ | |
| std::vector<File> parseFiles( | |
| const QVector<MTPSecureFile> &data, | |
| const std::vector<EditFile> &editData) const; | |
| - base::optional<File> parseFile( | |
| + std::optional<File> parseFile( | |
| const MTPSecureFile &data, | |
| const std::vector<EditFile> &editData) const; | |
| void fillDownloadedFile( | |
| @@ -474,7 +474,7 @@ | |
| void scanDeleteRestore( | |
| not_null<const Value*> value, | |
| FileType type, | |
| - base::optional<int> fileIndex, | |
| + std::optional<int> fileIndex, | |
| bool deleted); | |
| QString getPhoneFromValue(not_null<const Value*> value) const; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_form_view_controller.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_form_view_controller.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_form_view_controller.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_form_view_controller.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -376,7 +376,7 @@ | |
| } | |
| const auto scheme = GetDocumentScheme( | |
| scope.type, | |
| - document ? base::make_optional(document->type) : base::none, | |
| + document ? base::make_optional(document->type) : std::nullopt, | |
| scope.details ? scope.details->nativeNames : false); | |
| using ValueClass = EditDocumentScheme::ValueClass; | |
| const auto skipAdditional = [&] { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_controller.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_controller.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_controller.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_controller.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -106,7 +106,7 @@ | |
| EditDocumentScheme GetDocumentScheme( | |
| Scope::Type type, | |
| - base::optional<Value::Type> scansType, | |
| + std::optional<Value::Type> scansType, | |
| bool nativeNames) { | |
| using Scheme = EditDocumentScheme; | |
| using ValueClass = Scheme::ValueClass; | |
| @@ -127,7 +127,7 @@ | |
| const auto FromBoolean = [](auto validation) { | |
| return [=](const QString &value) { | |
| return validation(value) | |
| - ? base::none | |
| + ? std::nullopt | |
| : base::make_optional(QString()); | |
| }; | |
| }; | |
| @@ -136,7 +136,7 @@ | |
| return (value.size() >= min) && (value.size() <= max); | |
| }); | |
| }; | |
| - using Result = base::optional<QString>; | |
| + using Result = std::optional<QString>; | |
| const auto NameValidate = [](const QString &value) -> Result { | |
| if (value.isEmpty() || value.size() > kMaxNameSize) { | |
| return QString(); | |
| @@ -145,7 +145,7 @@ | |
| ).match(value).hasMatch()) { | |
| return lang(lng_passport_bad_name); | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| }; | |
| const auto NativeNameValidate = LimitedValidate(kMaxNameSize); | |
| const auto NativeNameOrEmptyValidate = LimitedValidate(kMaxNameSize, 0); | |
| @@ -174,7 +174,7 @@ | |
| }); | |
| const auto NameOrEmptyValidate = [=](const QString &value) -> Result { | |
| if (value.isEmpty()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| return NameValidate(value); | |
| }; | |
| @@ -765,7 +765,7 @@ | |
| void PanelController::deleteScan( | |
| FileType type, | |
| - base::optional<int> fileIndex) { | |
| + std::optional<int> fileIndex) { | |
| Expects(_editScope != nullptr); | |
| Expects(_editDocument != nullptr); | |
| Expects(_editDocument->requiresScan(type)); | |
| @@ -775,7 +775,7 @@ | |
| void PanelController::restoreScan( | |
| FileType type, | |
| - base::optional<int> fileIndex) { | |
| + std::optional<int> fileIndex) { | |
| Expects(_editScope != nullptr); | |
| Expects(_editDocument != nullptr); | |
| Expects(_editDocument->requiresScan(type)); | |
| @@ -808,13 +808,13 @@ | |
| } | |
| auto PanelController::deleteValueLabel() const | |
| --> base::optional<rpl::producer<QString>> { | |
| +-> std::optional<rpl::producer<QString>> { | |
| Expects(_editScope != nullptr); | |
| if (hasValueDocument()) { | |
| return Lang::Viewer(lng_passport_delete_document); | |
| } else if (!hasValueFields()) { | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| switch (_editScope->type) { | |
| case Scope::Type::PersonalDetails: | |
| @@ -969,7 +969,7 @@ | |
| } | |
| } | |
| -base::optional<int> PanelController::findBestDocumentIndex( | |
| +std::optional<int> PanelController::findBestDocumentIndex( | |
| const Scope &scope) const { | |
| Expects(!scope.documents.empty()); | |
| @@ -981,7 +981,7 @@ | |
| return document->whatNotFilled(); | |
| }); | |
| return ((*i)->whatNotFilled() == Value::kNothingFilled) | |
| - ? base::none | |
| + ? std::nullopt | |
| : base::make_optional(int(i - begin(documents))); | |
| return -1; | |
| } | |
| @@ -992,7 +992,7 @@ | |
| const auto &scope = _scopes[index]; | |
| if (scope.documents.empty()) { | |
| - editScope(index, base::none); | |
| + editScope(index, std::nullopt); | |
| } else { | |
| const auto documentIndex = findBestDocumentIndex(scope); | |
| if (documentIndex || scope.documents.size() == 1) { | |
| @@ -1106,7 +1106,7 @@ | |
| bool PanelController::editRequiresScanUpload( | |
| int index, | |
| - base::optional<int> documentIndex) const { | |
| + std::optional<int> documentIndex) const { | |
| Expects(index >= 0 && index < _scopes.size()); | |
| Expects(!documentIndex | |
| || (*documentIndex >= 0 | |
| @@ -1125,7 +1125,7 @@ | |
| void PanelController::editScope( | |
| int index, | |
| - base::optional<int> documentIndex) { | |
| + std::optional<int> documentIndex) { | |
| if (editRequiresScanUpload(index, documentIndex)) { | |
| editWithUpload(index, *documentIndex); | |
| } else { | |
| @@ -1135,7 +1135,7 @@ | |
| void PanelController::startScopeEdit( | |
| int index, | |
| - base::optional<int> documentIndex) { | |
| + std::optional<int> documentIndex) { | |
| Expects(_panel != nullptr); | |
| Expects(index >= 0 && index < _scopes.size()); | |
| Expects(_scopes[index].details != 0 || documentIndex.has_value()); | |
| @@ -1168,7 +1168,7 @@ | |
| ? base::make_optional(PrepareScanListData( | |
| *_editDocument, | |
| FileType::Translation)) | |
| - : base::none; | |
| + : std::nullopt; | |
| auto result = _editValue | |
| ? object_ptr<PanelEditDocument>( | |
| _panel->widget(), | |
| @@ -1210,7 +1210,7 @@ | |
| this, | |
| GetDocumentScheme( | |
| _editScope->type, | |
| - base::none, | |
| + std::nullopt, | |
| _editValue->nativeNames), | |
| _editValue->error, | |
| _editValue->data.parsedInEdit); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_controller.h work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_controller.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_controller.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_controller.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -22,7 +22,7 @@ | |
| EditDocumentScheme GetDocumentScheme( | |
| Scope::Type type, | |
| - base::optional<Value::Type> scansType, | |
| + std::optional<Value::Type> scansType, | |
| bool nativeNames); | |
| EditContactScheme GetContactScheme(Scope::Type type); | |
| @@ -98,13 +98,13 @@ | |
| bool canAddScan(FileType type) const; | |
| void uploadScan(FileType type, QByteArray &&content); | |
| - void deleteScan(FileType type, base::optional<int> fileIndex); | |
| - void restoreScan(FileType type, base::optional<int> fileIndex); | |
| + void deleteScan(FileType type, std::optional<int> fileIndex); | |
| + void restoreScan(FileType type, std::optional<int> fileIndex); | |
| rpl::producer<ScanInfo> scanUpdated() const; | |
| rpl::producer<ScopeError> saveErrors() const; | |
| void readScanError(ReadScanError error); | |
| - base::optional<rpl::producer<QString>> deleteValueLabel() const; | |
| + std::optional<rpl::producer<QString>> deleteValueLabel() const; | |
| void deleteValue(); | |
| QString defaultEmail() const; | |
| @@ -149,13 +149,13 @@ | |
| private: | |
| void ensurePanelCreated(); | |
| - void editScope(int index, base::optional<int> documentIndex); | |
| + void editScope(int index, std::optional<int> documentIndex); | |
| void editWithUpload(int index, int documentIndex); | |
| bool editRequiresScanUpload( | |
| int index, | |
| - base::optional<int> documentIndex) const; | |
| - void startScopeEdit(int index, base::optional<int> documentIndex); | |
| - base::optional<int> findBestDocumentIndex(const Scope &scope) const; | |
| + std::optional<int> documentIndex) const; | |
| + void startScopeEdit(int index, std::optional<int> documentIndex); | |
| + std::optional<int> findBestDocumentIndex(const Scope &scope) const; | |
| void requestScopeFilesType(int index); | |
| void cancelValueEdit(); | |
| void processValueSaveFinished(not_null<const Value*> value); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_details_row.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_details_row.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_details_row.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_details_row.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,6 +16,7 @@ | |
| #include "ui/widgets/checkbox.h" | |
| #include "ui/wrap/slide_wrap.h" | |
| #include "ui/countryinput.h" | |
| +#include "auth_session.h" | |
| #include "styles/style_boxes.h" | |
| #include "styles/style_passport.h" | |
| @@ -224,7 +225,7 @@ | |
| Female, | |
| }; | |
| - static base::optional<Gender> StringToGender(const QString &value); | |
| + static std::optional<Gender> StringToGender(const QString &value); | |
| static QString GenderToString(Gender gender); | |
| int resizeInner(int left, int top, int width) override; | |
| @@ -365,7 +366,7 @@ | |
| void CountryRow::errorAnimationCallback() { | |
| const auto error = _errorAnimation.current(_errorShown ? 1. : 0.); | |
| if (error == 0.) { | |
| - _link->setColorOverride(base::none); | |
| + _link->setColorOverride(std::nullopt); | |
| } else { | |
| _link->setColorOverride(anim::color( | |
| st::boxLinkButton.color, | |
| @@ -377,7 +378,8 @@ | |
| void CountryRow::chooseCountry() { | |
| const auto top = _value.current(); | |
| const auto name = CountrySelectBox::NameByISO(top); | |
| - const auto isoByPhone = CountrySelectBox::ISOByPhone(App::self()->phone()); | |
| + const auto isoByPhone = CountrySelectBox::ISOByPhone( | |
| + Auth().user()->phone()); | |
| const auto box = _controller->show(Box<CountrySelectBox>(!name.isEmpty() | |
| ? top | |
| : !isoByPhone.isEmpty() | |
| @@ -875,13 +877,13 @@ | |
| } | |
| auto GenderRow::StringToGender(const QString &value) | |
| --> base::optional<Gender> { | |
| +-> std::optional<Gender> { | |
| if (value == qstr("male")) { | |
| return Gender::Male; | |
| } else if (value == qstr("female")) { | |
| return Gender::Female; | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| QString GenderRow::GenderToString(Gender gender) { | |
| @@ -934,8 +936,8 @@ | |
| void GenderRow::errorAnimationCallback() { | |
| const auto error = _errorAnimation.current(_errorShown ? 1. : 0.); | |
| if (error == 0.) { | |
| - _maleRadio->setUntoggledOverride(base::none); | |
| - _femaleRadio->setUntoggledOverride(base::none); | |
| + _maleRadio->setUntoggledOverride(std::nullopt); | |
| + _femaleRadio->setUntoggledOverride(std::nullopt); | |
| } else { | |
| const auto color = anim::color( | |
| st::defaultRadio.untoggledFg, | |
| @@ -1039,7 +1041,7 @@ | |
| return result; | |
| } | |
| -void PanelDetailsRow::showError(base::optional<QString> error) { | |
| +void PanelDetailsRow::showError(std::optional<QString> error) { | |
| if (!_errorHideSubscription) { | |
| _errorHideSubscription = true; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_details_row.h work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_details_row.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_details_row.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_details_row.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -54,7 +54,7 @@ | |
| virtual bool setFocusFast(); | |
| virtual rpl::producer<QString> value() const = 0; | |
| virtual QString valueCurrent() const = 0; | |
| - void showError(base::optional<QString> error = base::none); | |
| + void showError(std::optional<QString> error = std::nullopt); | |
| bool errorShown() const; | |
| void hideError(); | |
| void finishAnimating(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_document.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -215,7 +215,7 @@ | |
| const QString &scansError, | |
| const ValueMap &scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles) | |
| : _controller(controller) | |
| , _scheme(std::move(scheme)) | |
| @@ -243,7 +243,7 @@ | |
| const QString &scansError, | |
| const ValueMap &scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles) | |
| : _controller(controller) | |
| , _scheme(std::move(scheme)) | |
| @@ -288,7 +288,7 @@ | |
| const QString *scansError, | |
| const ValueMap *scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles) { | |
| const auto inner = setupContent( | |
| error, | |
| @@ -316,7 +316,7 @@ | |
| const QString *scansError, | |
| const ValueMap *scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles) { | |
| const auto inner = _scroll->setOwnedWidget( | |
| object_ptr<Ui::VerticalLayout>(this)); | |
| @@ -629,7 +629,7 @@ | |
| bool PanelEditDocument::validate() { | |
| auto error = _editScans | |
| ? _editScans->validateGetErrorTop() | |
| - : base::none; | |
| + : std::nullopt; | |
| if (error) { | |
| const auto errortop = _editScans->mapToGlobal(QPoint(0, *error)); | |
| const auto scrolltop = _scroll->mapToGlobal(QPoint(0, 0)); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_document.h work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_document.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_document.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_document.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -50,7 +50,7 @@ | |
| Shown, | |
| }; | |
| struct Row { | |
| - using Validator = Fn<base::optional<QString>(const QString &value)>; | |
| + using Validator = Fn<std::optional<QString>(const QString &value)>; | |
| using Formatter = Fn<QString(const QString &value)>; | |
| ValueClass valueClass = ValueClass::Fields; | |
| PanelDetailsType inputType = PanelDetailsType(); | |
| @@ -87,7 +87,7 @@ | |
| const QString &scansError, | |
| const ValueMap &scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles); | |
| PanelEditDocument( | |
| QWidget *parent, | |
| @@ -96,7 +96,7 @@ | |
| const QString &scansError, | |
| const ValueMap &scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles); | |
| PanelEditDocument( | |
| QWidget *parent, | |
| @@ -119,7 +119,7 @@ | |
| const QString *scansError, | |
| const ValueMap *scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles); | |
| not_null<Ui::RpWidget*> setupContent( | |
| const QString *error, | |
| @@ -127,7 +127,7 @@ | |
| const QString *scansError, | |
| const ValueMap *scansData, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations, | |
| + std::optional<ScanListData> &&translations, | |
| std::map<FileType, ScanInfo> &&specialFiles); | |
| void updateControlsGeometry(); | |
| void updateCommonError(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_scans.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_scans.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_scans.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_scans.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -81,10 +81,12 @@ | |
| void setError(bool error); | |
| rpl::producer<> deleteClicks() const { | |
| - return _delete->entity()->clicks(); | |
| + return _delete->entity()->clicks( | |
| + ) | rpl::map([] { return rpl::empty_value(); }); | |
| } | |
| rpl::producer<> restoreClicks() const { | |
| - return _restore->entity()->clicks(); | |
| + return _restore->entity()->clicks( | |
| + ) | rpl::map([] { return rpl::empty_value(); }); | |
| } | |
| protected: | |
| @@ -158,10 +160,10 @@ | |
| EditScans::List::List( | |
| not_null<PanelController*> controller, | |
| - base::optional<ScanListData> &&data) | |
| + std::optional<ScanListData> &&data) | |
| : controller(controller) | |
| , files(data ? std::move(data->files) : std::vector<ScanInfo>()) | |
| -, initialCount(data ? base::make_optional(int(files.size())) : base::none) | |
| +, initialCount(data ? base::make_optional(int(files.size())) : std::nullopt) | |
| , errorMissing(data ? std::move(data->errorMissing) : QString()) { | |
| } | |
| @@ -230,7 +232,7 @@ | |
| void EditScans::List::errorAnimationCallback() { | |
| const auto error = errorAnimation.current(errorShown ? 1. : 0.); | |
| if (error == 0.) { | |
| - upload->setColorOverride(base::none); | |
| + upload->setColorOverride(std::nullopt); | |
| } else { | |
| upload->setColorOverride(anim::color( | |
| st::passportUploadButton.textFg, | |
| @@ -426,7 +428,7 @@ | |
| const QString &header, | |
| const QString &error, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations) | |
| + std::optional<ScanListData> &&translations) | |
| : RpWidget(parent) | |
| , _controller(controller) | |
| , _error(error) | |
| @@ -442,7 +444,7 @@ | |
| const QString &header, | |
| const QString &error, | |
| std::map<FileType, ScanInfo> &&specialFiles, | |
| - base::optional<ScanListData> &&translations) | |
| + std::optional<ScanListData> &&translations) | |
| : RpWidget(parent) | |
| , _controller(controller) | |
| , _error(error) | |
| @@ -452,8 +454,8 @@ | |
| setupSpecialScans(header, std::move(specialFiles)); | |
| } | |
| -base::optional<int> EditScans::validateGetErrorTop() { | |
| - auto result = base::optional<int>(); | |
| +std::optional<int> EditScans::validateGetErrorTop() { | |
| + auto result = std::optional<int>(); | |
| const auto suggestResult = [&](int value) { | |
| if (!result || *result > value) { | |
| result = value; | |
| @@ -826,12 +828,12 @@ | |
| row->deleteClicks( | |
| ) | rpl::start_with_next([=] { | |
| - _controller->deleteScan(type, base::none); | |
| + _controller->deleteScan(type, std::nullopt); | |
| }, row->lifetime()); | |
| row->restoreClicks( | |
| ) | rpl::start_with_next([=] { | |
| - _controller->restoreScan(type, base::none); | |
| + _controller->restoreScan(type, std::nullopt); | |
| }, row->lifetime()); | |
| scan.rowCreated = !info.deleted; | |
| @@ -972,7 +974,7 @@ | |
| const auto error = scan.errorAnimation.current( | |
| scan.errorShown ? 1. : 0.); | |
| if (error == 0.) { | |
| - scan.upload->setColorOverride(base::none); | |
| + scan.upload->setColorOverride(std::nullopt); | |
| } else { | |
| scan.upload->setColorOverride(anim::color( | |
| st::passportUploadButton.textFg, | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_scans.h work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_scans.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/passport/passport_panel_edit_scans.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/passport/passport_panel_edit_scans.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -51,16 +51,16 @@ | |
| const QString &header, | |
| const QString &error, | |
| ScanListData &&scans, | |
| - base::optional<ScanListData> &&translations); | |
| + std::optional<ScanListData> &&translations); | |
| EditScans( | |
| QWidget *parent, | |
| not_null<PanelController*> controller, | |
| const QString &header, | |
| const QString &error, | |
| std::map<FileType, ScanInfo> &&specialFiles, | |
| - base::optional<ScanListData> &&translations); | |
| + std::optional<ScanListData> &&translations); | |
| - base::optional<int> validateGetErrorTop(); | |
| + std::optional<int> validateGetErrorTop(); | |
| void scanFieldsChanged(bool changed); | |
| @@ -78,7 +78,7 @@ | |
| List(not_null<PanelController*> controller, ScanListData &&data); | |
| List( | |
| not_null<PanelController*> controller, | |
| - base::optional<ScanListData> &&data = base::none); | |
| + std::optional<ScanListData> &&data = std::nullopt); | |
| bool uploadedSomeMore() const; | |
| bool uploadMoreRequired() const; | |
| @@ -92,7 +92,7 @@ | |
| not_null<PanelController*> controller; | |
| std::vector<ScanInfo> files; | |
| - base::optional<int> initialCount; | |
| + std::optional<int> initialCount; | |
| QString errorMissing; | |
| QPointer<Ui::SlideWrap<BoxContentDivider>> divider; | |
| QPointer<Ui::SlideWrap<Ui::FlatLabel>> header; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/linux/specific_linux.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/platform/linux/specific_linux.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/linux/specific_linux.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/linux/specific_linux.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,6 +16,7 @@ | |
| #include "platform/platform_notifications_manager.h" | |
| #include "storage/localstorage.h" | |
| #include "core/crash_reports.h" | |
| +#include "core/update_checker.h" | |
| #include <sys/stat.h> | |
| #include <sys/types.h> | |
| @@ -174,81 +175,6 @@ | |
| return result; | |
| } | |
| -QString psPrepareCrashDump(const QByteArray &crashdump, QString dumpfile) { | |
| - QString initial = QString::fromUtf8(crashdump), result; | |
| - QStringList lines = initial.split('\n'); | |
| - result.reserve(initial.size()); | |
| - int32 i = 0, l = lines.size(); | |
| - | |
| - while (i < l) { | |
| - uint64 addresses[1024] = { 0 }; | |
| - for (; i < l; ++i) { | |
| - result.append(lines.at(i)).append('\n'); | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line == qstr("Backtrace:")) { | |
| - ++i; | |
| - break; | |
| - } | |
| - } | |
| - | |
| - int32 start = i; | |
| - for (; i < l; ++i) { | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line.isEmpty()) break; | |
| - | |
| - QRegularExpressionMatch m1 = QRegularExpression(qsl("^(.+)\\(([^+]+)\\+([^\\)]+)\\)\\[(.+)\\]$")).match(line); | |
| - QRegularExpressionMatch m2 = QRegularExpression(qsl("^(.+)\\[(.+)\\]$")).match(line); | |
| - QString addrstr = m1.hasMatch() ? m1.captured(4) : (m2.hasMatch() ? m2.captured(2) : QString()); | |
| - if (!addrstr.isEmpty()) { | |
| - uint64 addr = addrstr.startsWith(qstr("0x")) ? addrstr.mid(2).toULongLong(0, 16) : addrstr.toULongLong(); | |
| - if (addr > 1) { | |
| - addresses[i - start] = addr; | |
| - } | |
| - } | |
| - } | |
| - | |
| - QStringList addr2line = addr2linestr(addresses, i - start); | |
| - for (i = start; i < l; ++i) { | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line.isEmpty()) break; | |
| - | |
| - result.append(qsl("\n%1. ").arg(i - start)); | |
| - if (line.startsWith(qstr("ERROR: "))) { | |
| - result.append(line).append('\n'); | |
| - continue; | |
| - } | |
| - if (line == qstr("[0x1]")) { | |
| - result.append(qsl("(0x1 separator)\n")); | |
| - continue; | |
| - } | |
| - | |
| - QRegularExpressionMatch m1 = QRegularExpression(qsl("^(.+)\\(([^+]*)\\+([^\\)]+)\\)(.+)$")).match(line); | |
| - QRegularExpressionMatch m2 = QRegularExpression(qsl("^(.+)\\[(.+)\\]$")).match(line); | |
| - if (!m1.hasMatch() && !m2.hasMatch()) { | |
| - result.append(qstr("BAD LINE: ")).append(line).append('\n'); | |
| - continue; | |
| - } | |
| - | |
| - if (m1.hasMatch()) { | |
| - result.append(demanglestr(m1.captured(2))).append(qsl(" + ")).append(m1.captured(3)).append(qsl(" [")).append(m1.captured(1)).append(qsl("] ")); | |
| - if (!addr2line.at(i - start).isEmpty() && addr2line.at(i - start) != qsl("??:0")) { | |
| - result.append(qsl(" (")).append(addr2line.at(i - start)).append(qsl(")\n")); | |
| - } else { | |
| - result.append(m1.captured(4)).append(qsl(" (demangled)")).append('\n'); | |
| - } | |
| - } else { | |
| - result.append('[').append(m2.captured(1)).append(']'); | |
| - if (!addr2line.at(i - start).isEmpty() && addr2line.at(i - start) != qsl("??:0")) { | |
| - result.append(qsl(" (")).append(addr2line.at(i - start)).append(qsl(")\n")); | |
| - } else { | |
| - result.append(' ').append(m2.captured(2)).append('\n'); | |
| - } | |
| - } | |
| - } | |
| - } | |
| - return result; | |
| -} | |
| - | |
| bool _removeDirectory(const QString &path) { // from http://stackoverflow.com/questions/2256945/removing-a-non-empty-directory-programmatically-in-c-or-c | |
| QByteArray pathRaw = QFile::encodeName(path); | |
| DIR *d = opendir(pathRaw.constData()); | |
| @@ -408,7 +334,9 @@ | |
| void RegisterCustomScheme() { | |
| #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME | |
| auto home = getHomeDir(); | |
| - if (home.isEmpty() || cBetaVersion() || cExeName().isEmpty()) return; // don't update desktop file for beta version | |
| + if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty()) return; // don't update desktop file for alpha version | |
| + if (Core::UpdaterDisabled()) | |
| + return; | |
| #ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION | |
| DEBUG_LOG(("App Info: placing .desktop file")); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/linux/specific_linux.h work/tdesktop-1.4.0/Telegram/SourceFiles/platform/linux/specific_linux.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/linux/specific_linux.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/linux/specific_linux.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -44,7 +44,6 @@ | |
| } | |
| void psWriteDump(); | |
| -QString psPrepareCrashDump(const QByteArray &crashdump, QString dumpfile); | |
| void psDeleteDir(const QString &dir); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/main_window_mac.mm work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/main_window_mac.mm | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/main_window_mac.mm 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/main_window_mac.mm 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -12,6 +12,7 @@ | |
| #include "mainwidget.h" | |
| #include "application.h" | |
| #include "messenger.h" | |
| +#include "auth_session.h" | |
| #include "history/history.h" | |
| #include "history/history_widget.h" | |
| #include "history/history_inner_widget.h" | |
| @@ -605,7 +606,7 @@ | |
| connect(psContacts, &QAction::triggered, psContacts, [] { | |
| if (App::wnd() && App::wnd()->isHidden()) App::wnd()->showFromTray(); | |
| - if (!App::self()) return; | |
| + if (!AuthSession::Exists()) return; | |
| Ui::show(Box<PeerListBox>(std::make_unique<ContactsBoxController>(), [](not_null<PeerListBox*> box) { | |
| box->addButton(langFactory(lng_close), [box] { box->closeBox(); }); | |
| box->addLeftButton(langFactory(lng_profile_add_contact), [] { App::wnd()->onShowAddContact(); }); | |
| @@ -695,7 +696,7 @@ | |
| canDelete = list->canDeleteSelected(); | |
| } | |
| App::wnd()->updateIsActive(0); | |
| - const auto logged = !!App::self(); | |
| + const auto logged = AuthSession::Exists(); | |
| const auto locked = !Messenger::Instance().locked(); | |
| const auto inactive = !logged || locked; | |
| _forceDisabled(psLogout, !logged && !locked); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/specific_mac_p.mm work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/specific_mac_p.mm | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/specific_mac_p.mm 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/specific_mac_p.mm 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -29,7 +29,7 @@ | |
| constexpr auto kIgnoreActivationTimeoutMs = 500; | |
| -base::optional<bool> ApplicationIsActive; | |
| +std::optional<bool> ApplicationIsActive; | |
| } // namespace | |
| @@ -121,7 +121,16 @@ | |
| }); | |
| #ifndef OS_MAC_STORE | |
| if ([SPMediaKeyTap usesGlobalMediaKeyTap]) { | |
| - _keyTap = [[SPMediaKeyTap alloc] initWithDelegate:self]; | |
| +#ifndef OS_MAC_OLD | |
| + if (QSysInfo::macVersion() < Q_MV_OSX(10, 14)) { | |
| +#else // OS_MAC_OLD | |
| + if (true) { | |
| +#endif // OS_MAC_OLD | |
| + _keyTap = [[SPMediaKeyTap alloc] initWithDelegate:self]; | |
| + } else { | |
| + // In macOS Mojave it requires accessibility features. | |
| + LOG(("Media key monitoring disabled in Mojave.")); | |
| + } | |
| } else { | |
| LOG(("Media key monitoring disabled")); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/specific_mac.h work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/specific_mac.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/specific_mac.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/specific_mac.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -43,7 +43,6 @@ | |
| } | |
| void psWriteDump(); | |
| -QString psPrepareCrashDump(const QByteArray &crashdump, QString dumpfile); | |
| void psDeleteDir(const QString &dir); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/specific_mac.mm work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/specific_mac.mm | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/mac/specific_mac.mm 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/mac/specific_mac.mm 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -164,127 +164,6 @@ | |
| } | |
| -QString psPrepareCrashDump(const QByteArray &crashdump, QString dumpfile) { | |
| - QString initial = QString::fromUtf8(crashdump), result; | |
| - QStringList lines = initial.split('\n'); | |
| - result.reserve(initial.size()); | |
| - int32 i = 0, l = lines.size(); | |
| - | |
| - while (i < l) { | |
| - uint64 addresses[1024] = { 0 }; | |
| - for (; i < l; ++i) { | |
| - result.append(lines.at(i)).append('\n'); | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line == qstr("Base image addresses:")) { | |
| - ++i; | |
| - break; | |
| - } | |
| - } | |
| - | |
| - uint64 base = 0; | |
| - for (int32 start = i; i < l; ++i) { | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line.isEmpty()) break; | |
| - | |
| - if (!base) { | |
| - QRegularExpressionMatch m = QRegularExpression(qsl("^\\d+ (\\d+) \\((.+)\\)")).match(line); | |
| - if (m.hasMatch()) { | |
| - if (uint64 address = m.captured(1).toULongLong()) { | |
| - if (m.captured(2).endsWith(qstr("Contents/MacOS/Telegram"))) { | |
| - base = address; | |
| - } | |
| - } | |
| - } | |
| - } | |
| - } | |
| - if (base) { | |
| - result.append(qsl("(base address read: 0x%1)\n").arg(base, 0, 16)); | |
| - } else { | |
| - result.append(qsl("ERROR: base address not read!\n")); | |
| - } | |
| - | |
| - for (; i < l; ++i) { | |
| - result.append(lines.at(i)).append('\n'); | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line == qstr("Backtrace:")) { | |
| - ++i; | |
| - break; | |
| - } | |
| - } | |
| - | |
| - int32 start = i; | |
| - for (; i < l; ++i) { | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line.isEmpty()) break; | |
| - | |
| - if (QRegularExpression(qsl("^\\d+")).match(line).hasMatch()) { | |
| - QStringList lst = line.split(' ', QString::SkipEmptyParts); | |
| - if (lst.size() > 2) { | |
| - uint64 addr = lst.at(2).startsWith(qstr("0x")) ? lst.at(2).mid(2).toULongLong(0, 16) : lst.at(2).toULongLong(); | |
| - addresses[i - start] = addr; | |
| - } | |
| - } | |
| - } | |
| - | |
| - QStringList atos = atosstr(addresses, i - start, base); | |
| - for (i = start; i < l; ++i) { | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line.isEmpty()) break; | |
| - | |
| - if (!QRegularExpression(qsl("^\\d+")).match(line).hasMatch()) { | |
| - if (!lines.at(i).startsWith(qstr("ERROR: "))) { | |
| - result.append(qstr("BAD LINE: ")); | |
| - } | |
| - result.append(line).append('\n'); | |
| - continue; | |
| - } | |
| - QStringList lst = line.split(' ', QString::SkipEmptyParts); | |
| - result.append('\n').append(lst.at(0)).append(qsl(". ")); | |
| - if (lst.size() < 3) { | |
| - result.append(qstr("BAD LINE: ")).append(line).append('\n'); | |
| - continue; | |
| - } | |
| - if (lst.size() > 5 && lst.at(3) == qsl("0x0") && lst.at(4) == qsl("+") && lst.at(5) == qsl("1")) { | |
| - result.append(qsl("(0x1 separator)\n")); | |
| - continue; | |
| - } | |
| - if (i - start < atos.size()) { | |
| - if (!atos.at(i - start).isEmpty()) { | |
| - result.append(atos.at(i - start)).append('\n'); | |
| - continue; | |
| - } | |
| - } | |
| - | |
| - for (int j = 1, s = lst.size();;) { | |
| - if (lst.at(j).startsWith('_')) { | |
| - result.append(demanglestr(lst.at(j))); | |
| - if (++j < s) { | |
| - result.append(' '); | |
| - for (;;) { | |
| - result.append(lst.at(j)); | |
| - if (++j < s) { | |
| - result.append(' '); | |
| - } else { | |
| - break; | |
| - } | |
| - } | |
| - } | |
| - break; | |
| - } else if (j > 2) { | |
| - result.append(lst.at(j)); | |
| - } | |
| - if (++j < s) { | |
| - result.append(' '); | |
| - } else { | |
| - break; | |
| - } | |
| - } | |
| - result.append(qsl(" [demangled]")).append('\n'); | |
| - } | |
| - } | |
| - return result; | |
| -} | |
| - | |
| void psDeleteDir(const QString &dir) { | |
| objc_deleteDir(dir); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/launcher_win.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/launcher_win.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/launcher_win.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/launcher_win.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -40,7 +40,7 @@ | |
| : Core::Launcher(argc, argv, DeviceModel(), SystemVersion()) { | |
| } | |
| -base::optional<QStringList> Launcher::readArgumentsHook( | |
| +std::optional<QStringList> Launcher::readArgumentsHook( | |
| int argc, | |
| char *argv[]) const { | |
| auto count = 0; | |
| @@ -55,7 +55,7 @@ | |
| return result; | |
| } | |
| } | |
| - return base::none; | |
| + return std::nullopt; | |
| } | |
| bool Launcher::launchUpdater(UpdaterLaunch action) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/launcher_win.h work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/launcher_win.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/launcher_win.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/launcher_win.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -16,7 +16,7 @@ | |
| Launcher(int argc, char *argv[]); | |
| private: | |
| - base::optional<QStringList> readArgumentsHook( | |
| + std::optional<QStringList> readArgumentsHook( | |
| int argc, | |
| char *argv[]) const override; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/specific_win.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/specific_win.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/specific_win.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/specific_win.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -1069,172 +1069,6 @@ | |
| void psWriteDump() { | |
| } | |
| -char ImageHlpSymbol64[sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength]; | |
| -QString psPrepareCrashDump(const QByteArray &crashdump, QString dumpfile) { | |
| - if (!LoadDbgHelp(true) || cExeName().isEmpty()) { | |
| - return qsl("ERROR: could not init dbghelp.dll!"); | |
| - } | |
| - | |
| - HANDLE hProcess = GetCurrentProcess(); | |
| - | |
| - QString initial = QString::fromUtf8(crashdump), result; | |
| - QStringList lines = initial.split('\n'); | |
| - result.reserve(initial.size()); | |
| - int32 i = 0, l = lines.size(); | |
| - QString versionstr; | |
| - uint64 version = 0, betaversion = 0; | |
| - for (; i < l; ++i) { | |
| - result.append(lines.at(i)).append('\n'); | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line.startsWith(qstr("Version: "))) { | |
| - versionstr = line.mid(qstr("Version: ").size()).trimmed(); | |
| - version = versionstr.toULongLong(); | |
| - if (versionstr.endsWith(qstr("beta"))) { | |
| - if (version % 1000) { | |
| - betaversion = version; | |
| - } else { | |
| - version /= 1000; | |
| - } | |
| - } | |
| - ++i; | |
| - break; | |
| - } | |
| - } | |
| - | |
| - // maybe need to launch another executable | |
| - QString tolaunch; | |
| - if ((betaversion && betaversion != cBetaVersion()) || (!betaversion && version && version != AppVersion)) { | |
| - QString path = cExeDir(); | |
| - QRegularExpressionMatch m = QRegularExpression("deploy/\\d+\\.\\d+/\\d+\\.\\d+\\.\\d+(/|\\.dev/|\\.alpha/|_\\d+/)(Telegram/)?$").match(path); | |
| - if (m.hasMatch()) { | |
| - QString base = path.mid(0, m.capturedStart()) + qstr("deploy/"); | |
| - int32 major = version / 1000000, minor = (version % 1000000) / 1000, micro = (version % 1000); | |
| - base += qsl("%1.%2/%3.%4.%5").arg(major).arg(minor).arg(major).arg(minor).arg(micro); | |
| - if (betaversion) { | |
| - base += qsl("_%1").arg(betaversion); | |
| - } else if (QDir(base + qstr(".dev")).exists()) { | |
| - base += qstr(".dev"); | |
| - } else if (QDir(base + qstr(".alpha")).exists()) { | |
| - base += qstr(".alpha"); | |
| - } | |
| - if (QFile(base + qstr("/Telegram/Telegram.exe")).exists()) { | |
| - base += qstr("/Telegram"); | |
| - } | |
| - tolaunch = base + qstr("Telegram.exe"); | |
| - } | |
| - } | |
| - if (!tolaunch.isEmpty()) { | |
| - result.append(qsl("ERROR: for this crashdump executable '%1' should be used!").arg(tolaunch)); | |
| - } | |
| - | |
| - while (i < l) { | |
| - for (; i < l; ++i) { | |
| - result.append(lines.at(i)).append('\n'); | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line == qstr("Backtrace:")) { | |
| - ++i; | |
| - break; | |
| - } | |
| - } | |
| - | |
| - IMAGEHLP_SYMBOL64 *pSym = NULL; | |
| - IMAGEHLP_MODULEW64 Module; | |
| - IMAGEHLP_LINEW64 Line; | |
| - | |
| - pSym = (IMAGEHLP_SYMBOL64*)ImageHlpSymbol64; | |
| - memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength); | |
| - pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); | |
| - pSym->MaxNameLength = StackEntryMaxNameLength; | |
| - | |
| - memset(&Line, 0, sizeof(Line)); | |
| - Line.SizeOfStruct = sizeof(Line); | |
| - | |
| - memset(&Module, 0, sizeof(Module)); | |
| - Module.SizeOfStruct = sizeof(Module); | |
| - | |
| - StackEntry csEntry; | |
| - for (int32 start = i; i < l; ++i) { | |
| - QString line = lines.at(i).trimmed(); | |
| - if (line.isEmpty()) break; | |
| - | |
| - result.append(qsl("%1. ").arg(i + 1 - start)); | |
| - if (!QRegularExpression(qsl("^\\d+$")).match(line).hasMatch()) { | |
| - if (!lines.at(i).startsWith(qstr("ERROR: "))) { | |
| - result.append(qstr("BAD LINE: ")); | |
| - } | |
| - result.append(line).append('\n'); | |
| - continue; | |
| - } | |
| - | |
| - DWORD64 address = line.toULongLong(); | |
| - | |
| - csEntry.offset = address; | |
| - csEntry.name[0] = 0; | |
| - csEntry.undName[0] = 0; | |
| - csEntry.undFullName[0] = 0; | |
| - csEntry.offsetFromSmybol = 0; | |
| - csEntry.offsetFromLine = 0; | |
| - csEntry.lineFileName[0] = 0; | |
| - csEntry.lineNumber = 0; | |
| - csEntry.loadedImageName[0] = 0; | |
| - csEntry.moduleName[0] = 0; | |
| - | |
| - if (symGetSymFromAddr64(hProcess, address, &(csEntry.offsetFromSmybol), pSym) != FALSE) { | |
| - // TODO: Mache dies sicher...! | |
| - strcpy_s(csEntry.name, pSym->Name); | |
| - | |
| - unDecorateSymbolName(pSym->Name, csEntry.undName, StackEntryMaxNameLength, UNDNAME_NAME_ONLY); | |
| - unDecorateSymbolName(pSym->Name, csEntry.undFullName, StackEntryMaxNameLength, UNDNAME_COMPLETE); | |
| - | |
| - if (symGetLineFromAddr64) { | |
| - if (symGetLineFromAddr64(hProcess, address, &(csEntry.offsetFromLine), &Line) != FALSE) { | |
| - csEntry.lineNumber = Line.LineNumber; | |
| - | |
| - // TODO: Mache dies sicher...! | |
| - wcscpy_s(csEntry.lineFileName, Line.FileName); | |
| - } | |
| - } | |
| - } else { | |
| - result.append("ERROR: could not get Sym from Addr! for ").append(QString::number(address)).append('\n'); | |
| - continue; | |
| - } | |
| - | |
| - if (_getModuleInfo(hProcess, address, &Module) != FALSE) { | |
| - // TODO: Mache dies sicher...! | |
| - wcscpy_s(csEntry.moduleName, Module.ModuleName); | |
| - } | |
| - if (csEntry.name[0] == 0) { | |
| - strcpy_s(csEntry.name, "(function-name not available)"); | |
| - } | |
| - if (csEntry.undName[0] != 0) { | |
| - strcpy_s(csEntry.name, csEntry.undName); | |
| - } | |
| - if (csEntry.undFullName[0] != 0) { | |
| - strcpy_s(csEntry.name, csEntry.undFullName); | |
| - } | |
| - if (csEntry.lineFileName[0] == 0) { | |
| - if (csEntry.moduleName[0] == 0) { | |
| - wcscpy_s(csEntry.moduleName, L"module-name not available"); | |
| - } | |
| - result.append(csEntry.name).append(qsl(" (%1) 0x%3").arg(QString::fromWCharArray(csEntry.moduleName)).arg(address, 0, 16)).append('\n'); | |
| - } else { | |
| - QString file = QString::fromWCharArray(csEntry.lineFileName).toLower(); | |
| - int32 index = file.indexOf(qstr("tbuild\\tdesktop\\telegram\\")); | |
| - if (index >= 0) { | |
| - file = file.mid(index + qstr("tbuild\\tdesktop\\telegram\\").size()); | |
| - if (file.startsWith(qstr("sourcefiles\\"))) { | |
| - file = file.mid(qstr("sourcefiles\\").size()); | |
| - } | |
| - } | |
| - result.append(csEntry.name).append(qsl(" (%1 - %2) 0x%3").arg(file).arg(csEntry.lineNumber).arg(address, 0, 16)).append('\n'); | |
| - } | |
| - } | |
| - } | |
| - | |
| - symCleanup(hProcess); | |
| - return result; | |
| -} | |
| - | |
| void psWriteStackTrace() { | |
| #ifndef TDESKTOP_DISABLE_CRASH_REPORTS | |
| if (!LoadDbgHelp()) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/specific_win.h work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/specific_win.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/specific_win.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/specific_win.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -53,7 +53,6 @@ | |
| void psWriteDump(); | |
| void psWriteStackTrace(); | |
| -QString psPrepareCrashDump(const QByteArray &crashdump, QString dumpfile); | |
| void psDeleteDir(const QString &dir); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -30,7 +30,7 @@ | |
| #else // OS_WIN_STORE | |
| const WCHAR AppUserModelIdRelease[] = L"Telegram.TelegramDesktop"; | |
| #endif // OS_WIN_STORE | |
| -const WCHAR AppUserModelIdBeta[] = L"Telegram.TelegramDesktop.Beta"; | |
| +const WCHAR AppUserModelIdAlpha[] = L"Telegram.TelegramDesktop.Alpha"; | |
| } // namespace | |
| @@ -252,8 +252,8 @@ | |
| QString path = systemShortcutPath(); | |
| if (path.isEmpty() || cExeName().isEmpty()) return false; | |
| - if (cBetaVersion()) { | |
| - path += qsl("TelegramBeta.lnk"); | |
| + if (cAlphaVersion()) { | |
| + path += qsl("TelegramAlpha.lnk"); | |
| if (validateShortcutAt(path)) return true; | |
| } else { | |
| if (validateShortcutAt(path + qsl("Telegram Desktop/Telegram.lnk"))) return true; | |
| @@ -310,7 +310,7 @@ | |
| } | |
| const WCHAR *getId() { | |
| - return cBetaVersion() ? AppUserModelIdBeta : AppUserModelIdRelease; | |
| + return cAlphaVersion() ? AppUserModelIdAlpha : AppUserModelIdRelease; | |
| } | |
| const PROPERTYKEY &getKey() { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/windows_dlls.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/windows_dlls.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/windows_dlls.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/windows_dlls.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,8 @@ | |
| */ | |
| #include "platform/win/windows_dlls.h" | |
| +#include <QtCore/QSysInfo> | |
| + | |
| namespace Platform { | |
| namespace Dlls { | |
| @@ -43,6 +45,11 @@ | |
| f_PropVariantToString PropVariantToString; | |
| f_PSStringFromPropertyKey PSStringFromPropertyKey; | |
| f_DwmIsCompositionEnabled DwmIsCompositionEnabled; | |
| +f_RmStartSession RmStartSession; | |
| +f_RmRegisterResources RmRegisterResources; | |
| +f_RmGetList RmGetList; | |
| +f_RmShutdown RmShutdown; | |
| +f_RmEndSession RmEndSession; | |
| HINSTANCE LibUxTheme; | |
| HINSTANCE LibShell32; | |
| @@ -50,6 +57,7 @@ | |
| HINSTANCE LibPropSys; | |
| HINSTANCE LibComBase; | |
| HINSTANCE LibDwmApi; | |
| +HINSTANCE LibRstrtMgr; | |
| void start() { | |
| init(); | |
| @@ -63,10 +71,6 @@ | |
| load(LibShell32, "SHChangeNotify", SHChangeNotify); | |
| load(LibShell32, "SetCurrentProcessExplicitAppUserModelID", SetCurrentProcessExplicitAppUserModelID); | |
| - if (cBetaVersion() == 10020001 && SHChangeNotify) { // Temp - app icon was changed | |
| - SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr); | |
| - } | |
| - | |
| LibUxTheme = LoadLibrary(L"UXTHEME.DLL"); | |
| load(LibUxTheme, "SetWindowTheme", SetWindowTheme); | |
| @@ -89,6 +93,13 @@ | |
| LibDwmApi = LoadLibrary(L"DWMAPI.DLL"); | |
| load(LibDwmApi, "DwmIsCompositionEnabled", DwmIsCompositionEnabled); | |
| + | |
| + LibRstrtMgr = LoadLibrary(L"RSTRTMGR.DLL"); | |
| + load(LibRstrtMgr, "RmStartSession", RmStartSession); | |
| + load(LibRstrtMgr, "RmRegisterResources", RmRegisterResources); | |
| + load(LibRstrtMgr, "RmGetList", RmGetList); | |
| + load(LibRstrtMgr, "RmShutdown", RmShutdown); | |
| + load(LibRstrtMgr, "RmEndSession", RmEndSession); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/windows_dlls.h work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/windows_dlls.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/platform/win/windows_dlls.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/platform/win/windows_dlls.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -11,6 +11,7 @@ | |
| #include <shlobj.h> | |
| #include <roapi.h> | |
| #include <dwmapi.h> | |
| +#include <RestartManager.h> | |
| namespace Platform { | |
| namespace Dlls { | |
| @@ -32,62 +33,138 @@ | |
| } | |
| // UXTHEME.DLL | |
| -using f_SetWindowTheme = HRESULT(FAR STDAPICALLTYPE*)(HWND hWnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); | |
| +using f_SetWindowTheme = HRESULT(FAR STDAPICALLTYPE*)( | |
| + HWND hWnd, | |
| + LPCWSTR pszSubAppName, | |
| + LPCWSTR pszSubIdList); | |
| extern f_SetWindowTheme SetWindowTheme; | |
| // SHELL32.DLL | |
| -using f_SHAssocEnumHandlers = HRESULT(FAR STDAPICALLTYPE*)(PCWSTR pszExtra, ASSOC_FILTER afFilter, IEnumAssocHandlers **ppEnumHandler); | |
| +using f_SHAssocEnumHandlers = HRESULT(FAR STDAPICALLTYPE*)( | |
| + PCWSTR pszExtra, | |
| + ASSOC_FILTER afFilter, | |
| + IEnumAssocHandlers **ppEnumHandler); | |
| extern f_SHAssocEnumHandlers SHAssocEnumHandlers; | |
| -using f_SHCreateItemFromParsingName = HRESULT(FAR STDAPICALLTYPE*)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv); | |
| +using f_SHCreateItemFromParsingName = HRESULT(FAR STDAPICALLTYPE*)( | |
| + PCWSTR pszPath, | |
| + IBindCtx *pbc, | |
| + REFIID riid, | |
| + void **ppv); | |
| extern f_SHCreateItemFromParsingName SHCreateItemFromParsingName; | |
| -using f_SHOpenWithDialog = HRESULT(FAR STDAPICALLTYPE*)(HWND hwndParent, const OPENASINFO *poainfo); | |
| +using f_SHOpenWithDialog = HRESULT(FAR STDAPICALLTYPE*)( | |
| + HWND hwndParent, | |
| + const OPENASINFO *poainfo); | |
| extern f_SHOpenWithDialog SHOpenWithDialog; | |
| -using f_OpenAs_RunDLL = HRESULT(FAR STDAPICALLTYPE*)(HWND hWnd, HINSTANCE hInstance, LPCWSTR lpszCmdLine, int nCmdShow); | |
| +using f_OpenAs_RunDLL = HRESULT(FAR STDAPICALLTYPE*)( | |
| + HWND hWnd, | |
| + HINSTANCE hInstance, | |
| + LPCWSTR lpszCmdLine, | |
| + int nCmdShow); | |
| extern f_OpenAs_RunDLL OpenAs_RunDLL; | |
| -using f_SHQueryUserNotificationState = HRESULT(FAR STDAPICALLTYPE*)(QUERY_USER_NOTIFICATION_STATE *pquns); | |
| +using f_SHQueryUserNotificationState = HRESULT(FAR STDAPICALLTYPE*)( | |
| + QUERY_USER_NOTIFICATION_STATE *pquns); | |
| extern f_SHQueryUserNotificationState SHQueryUserNotificationState; | |
| -using f_SHChangeNotify = void(FAR STDAPICALLTYPE*)(LONG wEventId, UINT uFlags, __in_opt LPCVOID dwItem1, __in_opt LPCVOID dwItem2); | |
| +using f_SHChangeNotify = void(FAR STDAPICALLTYPE*)( | |
| + LONG wEventId, | |
| + UINT uFlags, | |
| + __in_opt LPCVOID dwItem1, | |
| + __in_opt LPCVOID dwItem2); | |
| extern f_SHChangeNotify SHChangeNotify; | |
| -using f_SetCurrentProcessExplicitAppUserModelID = HRESULT(FAR STDAPICALLTYPE*)(__in PCWSTR AppID); | |
| +using f_SetCurrentProcessExplicitAppUserModelID | |
| + = HRESULT(FAR STDAPICALLTYPE*)(__in PCWSTR AppID); | |
| extern f_SetCurrentProcessExplicitAppUserModelID SetCurrentProcessExplicitAppUserModelID; | |
| // WTSAPI32.DLL | |
| -using f_WTSRegisterSessionNotification = BOOL(FAR STDAPICALLTYPE*)(HWND hWnd, DWORD dwFlags); | |
| +using f_WTSRegisterSessionNotification = BOOL(FAR STDAPICALLTYPE*)( | |
| + HWND hWnd, | |
| + DWORD dwFlags); | |
| extern f_WTSRegisterSessionNotification WTSRegisterSessionNotification; | |
| -using f_WTSUnRegisterSessionNotification = BOOL(FAR STDAPICALLTYPE*)(HWND hWnd); | |
| +using f_WTSUnRegisterSessionNotification = BOOL(FAR STDAPICALLTYPE*)( | |
| + HWND hWnd); | |
| extern f_WTSUnRegisterSessionNotification WTSUnRegisterSessionNotification; | |
| // PROPSYS.DLL | |
| -using f_PropVariantToString = HRESULT(FAR STDAPICALLTYPE*)(_In_ REFPROPVARIANT propvar, _Out_writes_(cch) PWSTR psz, _In_ UINT cch); | |
| +using f_PropVariantToString = HRESULT(FAR STDAPICALLTYPE*)( | |
| + _In_ REFPROPVARIANT propvar, | |
| + _Out_writes_(cch) PWSTR psz, | |
| + _In_ UINT cch); | |
| extern f_PropVariantToString PropVariantToString; | |
| -using f_PSStringFromPropertyKey = HRESULT(FAR STDAPICALLTYPE*)(_In_ REFPROPERTYKEY pkey, _Out_writes_(cch) LPWSTR psz, _In_ UINT cch); | |
| +using f_PSStringFromPropertyKey = HRESULT(FAR STDAPICALLTYPE*)( | |
| + _In_ REFPROPERTYKEY pkey, | |
| + _Out_writes_(cch) LPWSTR psz, | |
| + _In_ UINT cch); | |
| extern f_PSStringFromPropertyKey PSStringFromPropertyKey; | |
| // COMBASE.DLL | |
| -using f_RoGetActivationFactory = HRESULT(FAR STDAPICALLTYPE*)(_In_ HSTRING activatableClassId, _In_ REFIID iid, _COM_Outptr_ void ** factory); | |
| +using f_RoGetActivationFactory = HRESULT(FAR STDAPICALLTYPE*)( | |
| + _In_ HSTRING activatableClassId, | |
| + _In_ REFIID iid, | |
| + _COM_Outptr_ void ** factory); | |
| extern f_RoGetActivationFactory RoGetActivationFactory; | |
| -using f_WindowsCreateStringReference = HRESULT(FAR STDAPICALLTYPE*)(_In_reads_opt_(length + 1) PCWSTR sourceString, UINT32 length, _Out_ HSTRING_HEADER * hstringHeader, _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING * string); | |
| +using f_WindowsCreateStringReference = HRESULT(FAR STDAPICALLTYPE*)( | |
| + _In_reads_opt_(length + 1) PCWSTR sourceString, | |
| + UINT32 length, | |
| + _Out_ HSTRING_HEADER * hstringHeader, | |
| + _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING * string); | |
| extern f_WindowsCreateStringReference WindowsCreateStringReference; | |
| -using f_WindowsDeleteString = HRESULT(FAR STDAPICALLTYPE*)(_In_opt_ HSTRING string); | |
| +using f_WindowsDeleteString = HRESULT(FAR STDAPICALLTYPE*)( | |
| + _In_opt_ HSTRING string); | |
| extern f_WindowsDeleteString WindowsDeleteString; | |
| // DWMAPI.DLL | |
| -using f_DwmIsCompositionEnabled = HRESULT(FAR STDAPICALLTYPE*)(_Out_ BOOL* pfEnabled); | |
| +using f_DwmIsCompositionEnabled = HRESULT(FAR STDAPICALLTYPE*)( | |
| + _Out_ BOOL* pfEnabled); | |
| extern f_DwmIsCompositionEnabled DwmIsCompositionEnabled; | |
| +// RSTRTMGR.DLL | |
| + | |
| +using f_RmStartSession = DWORD(FAR STDAPICALLTYPE*)( | |
| + _Out_ DWORD *pSessionHandle, | |
| + _Reserved_ DWORD dwSessionFlags, | |
| + _Out_writes_(CCH_RM_SESSION_KEY + 1) WCHAR strSessionKey[]); | |
| +extern f_RmStartSession RmStartSession; | |
| + | |
| +using f_RmRegisterResources = DWORD(FAR STDAPICALLTYPE*)( | |
| + _In_ DWORD dwSessionHandle, | |
| + _In_ UINT nFiles, | |
| + _In_reads_opt_(nFiles) LPCWSTR rgsFileNames[], | |
| + _In_ UINT nApplications, | |
| + _In_reads_opt_(nApplications) RM_UNIQUE_PROCESS rgApplications[], | |
| + _In_ UINT nServices, | |
| + _In_reads_opt_(nServices) LPCWSTR rgsServiceNames[]); | |
| +extern f_RmRegisterResources RmRegisterResources; | |
| + | |
| +using f_RmGetList = DWORD(FAR STDAPICALLTYPE*)( | |
| + _In_ DWORD dwSessionHandle, | |
| + _Out_ UINT *pnProcInfoNeeded, | |
| + _Inout_ UINT *pnProcInfo, | |
| + _Inout_updates_opt_(*pnProcInfo) RM_PROCESS_INFO rgAffectedApps[], | |
| + _Out_ LPDWORD lpdwRebootReasons); | |
| +extern f_RmGetList RmGetList; | |
| + | |
| +using f_RmShutdown = DWORD(FAR STDAPICALLTYPE*)( | |
| + _In_ DWORD dwSessionHandle, | |
| + _In_ ULONG lActionFlags, | |
| + _In_opt_ RM_WRITE_STATUS_CALLBACK fnStatus); | |
| +extern f_RmShutdown RmShutdown; | |
| + | |
| +using f_RmEndSession = DWORD(FAR STDAPICALLTYPE*)( | |
| + _In_ DWORD dwSessionHandle); | |
| +extern f_RmEndSession RmEndSession; | |
| + | |
| } // namespace Dlls | |
| } // namespace Platform | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/profile/profile_block_group_members.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/profile/profile_block_group_members.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/profile/profile_block_group_members.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/profile/profile_block_group_members.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -343,7 +343,7 @@ | |
| void GroupMembersWidget::checkSelfAdmin(ChatData *chat) { | |
| if (chat->participants.empty()) return; | |
| - auto self = App::self(); | |
| + const auto self = Auth().user(); | |
| if (chat->amAdmin() && !chat->admins.contains(self)) { | |
| chat->admins.insert(self); | |
| } else if (!chat->amAdmin() && chat->admins.contains(self)) { | |
| @@ -404,7 +404,7 @@ | |
| _sortByOnline = true; | |
| reserveItemsForSize(chat->participants.size()); | |
| - addUser(chat, App::self())->onlineForSort | |
| + addUser(chat, Auth().user())->onlineForSort | |
| = std::numeric_limits<TimeId>::max(); | |
| for (auto [user, v] : chat->participants) { | |
| if (!user->isSelf()) { | |
| @@ -454,7 +454,7 @@ | |
| clearItems(); | |
| reserveItemsForSize(membersList.size()); | |
| if (megagroup->amIn()) { | |
| - addUser(megagroup, App::self())->onlineForSort | |
| + addUser(megagroup, Auth().user())->onlineForSort | |
| = std::numeric_limits<TimeId>::max(); | |
| } | |
| } else if (membersList.size() >= itemsCount()) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/profile/profile_channel_controllers.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/profile/profile_channel_controllers.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/profile/profile_channel_controllers.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/profile/profile_channel_controllers.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -801,7 +801,7 @@ | |
| } | |
| } else { | |
| // It won't be replaced if the entry already exists. | |
| - _additional.adminPromotedBy.emplace(user, App::self()); | |
| + _additional.adminPromotedBy.emplace(user, Auth().user()); | |
| _additional.adminCanEdit.emplace(user); | |
| _additional.adminRights[user] = rights; | |
| _additional.kicked.erase(user); | |
| @@ -859,7 +859,7 @@ | |
| _additional.adminRights.erase(user); | |
| _additional.adminCanEdit.erase(user); | |
| _additional.adminPromotedBy.erase(user); | |
| - _additional.restrictedBy.emplace(user, App::self()); | |
| + _additional.restrictedBy.emplace(user, Auth().user()); | |
| if (fullBanned) { | |
| _additional.kicked.emplace(user); | |
| _additional.restrictedRights.erase(user); | |
| @@ -1472,7 +1472,7 @@ | |
| _additional.adminCanEdit.emplace(user); | |
| auto it = _additional.adminPromotedBy.find(user); | |
| if (it == _additional.adminPromotedBy.end()) { | |
| - _additional.adminPromotedBy.emplace(user, App::self()); | |
| + _additional.adminPromotedBy.emplace(user, Auth().user()); | |
| } | |
| } | |
| if (_adminDoneCallback) { | |
| @@ -1557,7 +1557,7 @@ | |
| } else { | |
| _additional.kicked.erase(user); | |
| } | |
| - _additional.restrictedBy.emplace(user, App::self()); | |
| + _additional.restrictedBy.emplace(user, Auth().user()); | |
| } | |
| if (_bannedDoneCallback) { | |
| _bannedDoneCallback(user, rights); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/combine_previous.h work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/combine_previous.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/combine_previous.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/combine_previous.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -22,7 +22,7 @@ | |
| initial = std::move(initial) | |
| ](const auto &consumer) mutable { | |
| auto previous = consumer.template make_state< | |
| - base::optional<Value> | |
| + std::optional<Value> | |
| >(); | |
| return std::move(initial).start( | |
| [consumer, previous](auto &&value) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/combine.h work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/combine.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/combine.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/combine.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -21,17 +21,17 @@ | |
| template <typename ...Values> | |
| struct combine_state { | |
| - combine_state() : accumulated(std::tuple<base::optional<Values>...>()) { | |
| + combine_state() : accumulated(std::tuple<std::optional<Values>...>()) { | |
| } | |
| - base::optional<std::tuple<base::optional<Values>...>> accumulated; | |
| - base::optional<std::tuple<Values...>> latest; | |
| + std::optional<std::tuple<std::optional<Values>...>> accumulated; | |
| + std::optional<std::tuple<Values...>> latest; | |
| int invalid = sizeof...(Values); | |
| int working = sizeof...(Values); | |
| }; | |
| template <typename ...Values, std::size_t ...I> | |
| inline std::tuple<Values...> combine_make_first( | |
| - std::tuple<base::optional<Values>...> &&accumulated, | |
| + std::tuple<std::optional<Values>...> &&accumulated, | |
| std::index_sequence<I...>) { | |
| return std::make_tuple(std::move(*std::get<I>(accumulated))...); | |
| } | |
| @@ -65,7 +65,7 @@ | |
| state->latest = combine_make_first( | |
| std::move(*state->accumulated), | |
| std::make_index_sequence<kArity>()); | |
| - state->accumulated = base::none; | |
| + state->accumulated = std::nullopt; | |
| consumer.put_next_copy(*state->latest); | |
| } | |
| } | |
| @@ -276,7 +276,7 @@ | |
| template <typename Value> | |
| struct combine_vector_state { | |
| - std::vector<base::optional<Value>> accumulated; | |
| + std::vector<std::optional<Value>> accumulated; | |
| std::vector<Value> latest; | |
| int invalid = 0; | |
| int working = 0; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/distinct_until_changed.h work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/distinct_until_changed.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/distinct_until_changed.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/distinct_until_changed.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -22,7 +22,7 @@ | |
| initial = std::move(initial) | |
| ](const auto &consumer) mutable { | |
| auto previous = consumer.template make_state< | |
| - base::optional<Value> | |
| + std::optional<Value> | |
| >(); | |
| return std::move(initial).start( | |
| [consumer, previous](auto &&value) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/event_stream.h work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/event_stream.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/event_stream.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/event_stream.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -34,7 +34,7 @@ | |
| void fire_copy(const Value &value) const { | |
| return fire_forward(value); | |
| } | |
| -#if defined _MSC_VER && _MSC_VER >= 1914 | |
| +#if defined _MSC_VER && _MSC_VER >= 1914 && false | |
| producer<Value> events() const { | |
| #else // _MSC_VER >= 1914 | |
| auto events() const { | |
| @@ -65,6 +65,9 @@ | |
| auto events_starting_with_copy(const Value &value) const { | |
| return single(value) | then(events()); | |
| } | |
| + bool has_consumers() const { | |
| + return (_data != nullptr) && !_data->consumers.empty(); | |
| + } | |
| ~event_stream(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/filter.h work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/filter.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/filter.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/filter.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -95,13 +95,13 @@ | |
| template <typename Value> | |
| inline const Value &deref_optional_helper( | |
| - const base::optional<Value> &value) { | |
| + const std::optional<Value> &value) { | |
| return *value; | |
| } | |
| template <typename Value> | |
| inline Value &&deref_optional_helper( | |
| - base::optional<Value> &&value) { | |
| + std::optional<Value> &&value) { | |
| return std::move(*value); | |
| } | |
| @@ -109,7 +109,7 @@ | |
| public: | |
| template <typename Value, typename Error, typename Generator> | |
| auto operator()(producer< | |
| - base::optional<Value>, | |
| + std::optional<Value>, | |
| Error, | |
| Generator> &&initial) const { | |
| return make_producer<Value, Error>([ | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/producer.h work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/producer.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/producer.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/producer.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -13,7 +13,7 @@ | |
| #include <rpl/details/superset_type.h> | |
| #include <rpl/details/callable.h> | |
| -#if defined _DEBUG | |
| +#if defined _DEBUG || defined COMPILER_MSVC | |
| #define RPL_PRODUCER_TYPE_ERASED_ALWAYS | |
| #endif // _DEBUG | |
| @@ -443,9 +443,9 @@ | |
| inline auto make_producer(Generator &&generator) | |
| #ifdef RPL_PRODUCER_TYPE_ERASED_ALWAYS | |
| -> producer<Value, Error> { | |
| -#else // RPL_CONSUMER_TYPE_ERASED_ALWAYS | |
| +#else // RPL_PRODUCER_TYPE_ERASED_ALWAYS | |
| -> producer<Value, Error, std::decay_t<Generator>> { | |
| -#endif // !RPL_CONSUMER_TYPE_ERASED_ALWAYS | |
| +#endif // !RPL_PRODUCER_TYPE_ERASED_ALWAYS | |
| return std::forward<Generator>(generator); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/variable.h work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/variable.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/rpl/variable.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/rpl/variable.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -96,7 +96,7 @@ | |
| std::is_assignable_v<Type&, OtherType>>> | |
| variable(producer<OtherType, Error, Generator> &&stream) { | |
| std::move(stream) | |
| - | start_with_next([this](auto &&data) { | |
| + | start_with_next([=](auto &&data) { | |
| assign(std::forward<decltype(data)>(data)); | |
| }, _lifetime); | |
| } | |
| @@ -111,9 +111,10 @@ | |
| producer<OtherType, Error, Generator> &&stream) { | |
| _lifetime.destroy(); | |
| std::move(stream) | |
| - | start_with_next([this](auto &&data) { | |
| + | start_with_next([=](auto &&data) { | |
| assign(std::forward<decltype(data)>(data)); | |
| }, _lifetime); | |
| + return *this; | |
| } | |
| Type current() const { | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_advanced_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_advanced_widget.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_advanced.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_advanced.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_background_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_background_widget.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_block_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_block_widget.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_chat_settings_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_chat_settings_widget.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_chat.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_chat.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_codes.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_codes.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_common.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_common.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_cover.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_cover.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_fixed_bar.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_fixed_bar.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_general_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_general_widget.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_info_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_info_widget.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_information.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_information.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_inner_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_inner_widget.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_intro.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_intro.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_layer.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_layer.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_main.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_main.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_notifications_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_notifications_widget.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_notifications.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_notifications.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,7 @@ | |
| */ | |
| #include "settings/settings_privacy_controllers.h" | |
| +#include "settings/settings_common.h" | |
| #include "lang/lang_keys.h" | |
| #include "apiwrap.h" | |
| #include "observer_peer.h" | |
| @@ -14,8 +15,13 @@ | |
| #include "auth_session.h" | |
| #include "storage/localstorage.h" | |
| #include "history/history.h" | |
| +#include "calls/calls_instance.h" | |
| +#include "ui/widgets/checkbox.h" | |
| +#include "ui/wrap/vertical_layout.h" | |
| #include "boxes/peer_list_controllers.h" | |
| #include "boxes/confirm_box.h" | |
| +#include "styles/style_boxes.h" | |
| +#include "styles/style_settings.h" | |
| namespace Settings { | |
| namespace { | |
| @@ -208,19 +214,25 @@ | |
| std::unique_ptr<PeerListRow> BlockedBoxController::createRow(UserData *user) const { | |
| auto row = std::make_unique<PeerListRowWithLink>(user); | |
| row->setActionLink(lang(lng_blocked_list_unblock)); | |
| - auto status = [user]() -> QString { | |
| - if (user->botInfo) { | |
| + const auto status = [&] { | |
| + if (!user->phone().isEmpty()) { | |
| + return App::formatPhone(user->phone()); | |
| + } else if (!user->username.isEmpty()) { | |
| + return '@' + user->username; | |
| + } else if (user->botInfo) { | |
| return lang(lng_status_bot); | |
| - } else if (user->phone().isEmpty()) { | |
| - return lang(lng_blocked_list_unknown_phone); | |
| } | |
| - return App::formatPhone(user->phone()); | |
| - }; | |
| - row->setCustomStatus(status()); | |
| + return lang(lng_blocked_list_unknown_phone); | |
| + }(); | |
| + row->setCustomStatus(status); | |
| return std::move(row); | |
| } | |
| -MTPInputPrivacyKey LastSeenPrivacyController::key() { | |
| +ApiWrap::Privacy::Key LastSeenPrivacyController::key() { | |
| + return Key::LastSeen; | |
| +} | |
| + | |
| +MTPInputPrivacyKey LastSeenPrivacyController::apiKey() { | |
| return MTP_inputPrivacyKeyStatusTimestamp(); | |
| } | |
| @@ -228,18 +240,21 @@ | |
| return lang(lng_edit_privacy_lastseen_title); | |
| } | |
| -QString LastSeenPrivacyController::description() { | |
| - return lang(lng_edit_privacy_lastseen_description); | |
| +LangKey LastSeenPrivacyController::optionsTitleKey() { | |
| + return lng_edit_privacy_lastseen_header; | |
| } | |
| -QString LastSeenPrivacyController::warning() { | |
| - return lang(lng_edit_privacy_lastseen_warning); | |
| +rpl::producer<QString> LastSeenPrivacyController::warning() { | |
| + return Lang::Viewer(lng_edit_privacy_lastseen_warning); | |
| } | |
| -QString LastSeenPrivacyController::exceptionLinkText(Exception exception, int count) { | |
| +LangKey LastSeenPrivacyController::exceptionButtonTextKey( | |
| + Exception exception) { | |
| switch (exception) { | |
| - case Exception::Always: return (count > 0) ? lng_edit_privacy_lastseen_always(lt_count, count) : lang(lng_edit_privacy_lastseen_always_empty); | |
| - case Exception::Never: return (count > 0) ? lng_edit_privacy_lastseen_never(lt_count, count) : lang(lng_edit_privacy_lastseen_never_empty); | |
| + case Exception::Always: | |
| + return lng_edit_privacy_lastseen_always_empty; | |
| + case Exception::Never: | |
| + return lng_edit_privacy_lastseen_never_empty; | |
| } | |
| Unexpected("Invalid exception value."); | |
| } | |
| @@ -252,8 +267,8 @@ | |
| Unexpected("Invalid exception value."); | |
| } | |
| -QString LastSeenPrivacyController::exceptionsDescription() { | |
| - return lang(lng_edit_privacy_lastseen_exceptions); | |
| +rpl::producer<QString> LastSeenPrivacyController::exceptionsDescription() { | |
| + return Lang::Viewer(lng_edit_privacy_lastseen_exceptions); | |
| } | |
| void LastSeenPrivacyController::confirmSave(bool someAreDisallowed, FnMut<void()> saveCallback) { | |
| @@ -274,7 +289,11 @@ | |
| } | |
| } | |
| -MTPInputPrivacyKey GroupsInvitePrivacyController::key() { | |
| +ApiWrap::Privacy::Key GroupsInvitePrivacyController::key() { | |
| + return Key::Invites; | |
| +} | |
| + | |
| +MTPInputPrivacyKey GroupsInvitePrivacyController::apiKey() { | |
| return MTP_inputPrivacyKeyChatInvite(); | |
| } | |
| @@ -286,14 +305,15 @@ | |
| return (option != Option::Nobody); | |
| } | |
| -QString GroupsInvitePrivacyController::description() { | |
| - return lang(lng_edit_privacy_groups_description); | |
| +LangKey GroupsInvitePrivacyController::optionsTitleKey() { | |
| + return lng_edit_privacy_groups_header; | |
| } | |
| -QString GroupsInvitePrivacyController::exceptionLinkText(Exception exception, int count) { | |
| +LangKey GroupsInvitePrivacyController::exceptionButtonTextKey( | |
| + Exception exception) { | |
| switch (exception) { | |
| - case Exception::Always: return (count > 0) ? lng_edit_privacy_groups_always(lt_count, count) : lang(lng_edit_privacy_groups_always_empty); | |
| - case Exception::Never: return (count > 0) ? lng_edit_privacy_groups_never(lt_count, count) : lang(lng_edit_privacy_groups_never_empty); | |
| + case Exception::Always: return lng_edit_privacy_groups_always_empty; | |
| + case Exception::Never: return lng_edit_privacy_groups_never_empty; | |
| } | |
| Unexpected("Invalid exception value."); | |
| } | |
| @@ -306,11 +326,16 @@ | |
| Unexpected("Invalid exception value."); | |
| } | |
| -QString GroupsInvitePrivacyController::exceptionsDescription() { | |
| - return lang(lng_edit_privacy_groups_exceptions); | |
| +auto GroupsInvitePrivacyController::exceptionsDescription() | |
| +-> rpl::producer<QString> { | |
| + return Lang::Viewer(lng_edit_privacy_groups_exceptions); | |
| +} | |
| + | |
| +ApiWrap::Privacy::Key CallsPrivacyController::key() { | |
| + return Key::Calls; | |
| } | |
| -MTPInputPrivacyKey CallsPrivacyController::key() { | |
| +MTPInputPrivacyKey CallsPrivacyController::apiKey() { | |
| return MTP_inputPrivacyKeyPhoneCall(); | |
| } | |
| @@ -318,14 +343,15 @@ | |
| return lang(lng_edit_privacy_calls_title); | |
| } | |
| -QString CallsPrivacyController::description() { | |
| - return lang(lng_edit_privacy_calls_description); | |
| +LangKey CallsPrivacyController::optionsTitleKey() { | |
| + return lng_edit_privacy_calls_header; | |
| } | |
| -QString CallsPrivacyController::exceptionLinkText(Exception exception, int count) { | |
| +LangKey CallsPrivacyController::exceptionButtonTextKey( | |
| + Exception exception) { | |
| switch (exception) { | |
| - case Exception::Always: return (count > 0) ? lng_edit_privacy_calls_always(lt_count, count) : lang(lng_edit_privacy_calls_always_empty); | |
| - case Exception::Never: return (count > 0) ? lng_edit_privacy_calls_never(lt_count, count) : lang(lng_edit_privacy_calls_never_empty); | |
| + case Exception::Always: return lng_edit_privacy_calls_always_empty; | |
| + case Exception::Never: return lng_edit_privacy_calls_never_empty; | |
| } | |
| Unexpected("Invalid exception value."); | |
| } | |
| @@ -338,8 +364,54 @@ | |
| Unexpected("Invalid exception value."); | |
| } | |
| -QString CallsPrivacyController::exceptionsDescription() { | |
| - return lang(lng_edit_privacy_calls_exceptions); | |
| +rpl::producer<QString> CallsPrivacyController::exceptionsDescription() { | |
| + return Lang::Viewer(lng_edit_privacy_calls_exceptions); | |
| +} | |
| + | |
| +Fn<void()> CallsPrivacyController::setupAdditional( | |
| + not_null<Ui::VerticalLayout*> container) { | |
| + using PeerToPeer = Calls::PeerToPeer; | |
| + const auto convert = [](PeerToPeer value) { | |
| + switch (value) { | |
| + case PeerToPeer::DefaultContacts: return Option::Contacts; | |
| + case PeerToPeer::DefaultEveryone: return Option::Everyone; | |
| + case PeerToPeer::Everyone: return Option::Everyone; | |
| + case PeerToPeer::Contacts: return Option::Contacts; | |
| + case PeerToPeer::Nobody: return Option::Nobody; | |
| + } | |
| + Unexpected("Calls::PeerToPeer value."); | |
| + }; | |
| + const auto group = std::make_shared<Ui::RadioenumGroup<Option>>( | |
| + convert(Auth().settings().callsPeerToPeer())); | |
| + const auto changed = Ui::AttachAsChild(container, false); | |
| + group->setChangedCallback([=](Option) { | |
| + *changed = true; | |
| + }); | |
| + | |
| + AddDivider(container); | |
| + AddSkip(container); | |
| + AddSubsectionTitle(container, lng_settings_peer_to_peer); | |
| + EditPrivacyBox::AddOption(container, group, Option::Everyone); | |
| + EditPrivacyBox::AddOption(container, group, Option::Contacts); | |
| + EditPrivacyBox::AddOption(container, group, Option::Nobody); | |
| + EditPrivacyBox::AddLabel( | |
| + container, | |
| + Lang::Viewer(lng_settings_peer_to_peer_about)); | |
| + AddSkip(container); | |
| + | |
| + return [=] { | |
| + if (*changed) { | |
| + Auth().settings().setCallsPeerToPeer([&] { | |
| + switch (group->value()) { | |
| + case Option::Everyone: return PeerToPeer::Everyone; | |
| + case Option::Contacts: return PeerToPeer::Contacts; | |
| + case Option::Nobody: return PeerToPeer::Nobody; | |
| + } | |
| + Unexpected("PeerToPeer edit value."); | |
| + }()); | |
| + Auth().saveSettingsDelayed(); | |
| + } | |
| + }; | |
| } | |
| } // namespace Settings | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings/settings_privacy_controllers.h work/tdesktop-1.4.0/Telegram/SourceFiles/settings/settings_privacy_controllers.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings/settings_privacy_controllers.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/settings/settings_privacy_controllers.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -41,14 +41,15 @@ | |
| using Option = EditPrivacyBox::Option; | |
| using Exception = EditPrivacyBox::Exception; | |
| - MTPInputPrivacyKey key() override; | |
| + Key key() override; | |
| + MTPInputPrivacyKey apiKey() override; | |
| QString title() override; | |
| - QString description() override; | |
| - QString warning() override; | |
| - QString exceptionLinkText(Exception exception, int count) override; | |
| + LangKey optionsTitleKey() override; | |
| + rpl::producer<QString> warning() override; | |
| + LangKey exceptionButtonTextKey(Exception exception) override; | |
| QString exceptionBoxTitle(Exception exception) override; | |
| - QString exceptionsDescription() override; | |
| + rpl::producer<QString> exceptionsDescription() override; | |
| void confirmSave(bool someAreDisallowed, FnMut<void()> saveCallback) override; | |
| @@ -59,14 +60,15 @@ | |
| using Option = EditPrivacyBox::Option; | |
| using Exception = EditPrivacyBox::Exception; | |
| - MTPInputPrivacyKey key() override; | |
| + Key key() override; | |
| + MTPInputPrivacyKey apiKey() override; | |
| QString title() override; | |
| bool hasOption(Option option) override; | |
| - QString description() override; | |
| - QString exceptionLinkText(Exception exception, int count) override; | |
| + LangKey optionsTitleKey() override; | |
| + LangKey exceptionButtonTextKey(Exception exception) override; | |
| QString exceptionBoxTitle(Exception exception) override; | |
| - QString exceptionsDescription() override; | |
| + rpl::producer<QString> exceptionsDescription() override; | |
| }; | |
| @@ -75,13 +77,17 @@ | |
| using Option = EditPrivacyBox::Option; | |
| using Exception = EditPrivacyBox::Exception; | |
| - MTPInputPrivacyKey key() override; | |
| + Key key() override; | |
| + MTPInputPrivacyKey apiKey() override; | |
| QString title() override; | |
| - QString description() override; | |
| - QString exceptionLinkText(Exception exception, int count) override; | |
| + LangKey optionsTitleKey() override; | |
| + LangKey exceptionButtonTextKey(Exception exception) override; | |
| QString exceptionBoxTitle(Exception exception) override; | |
| - QString exceptionsDescription() override; | |
| + rpl::producer<QString> exceptionsDescription() override; | |
| + | |
| + Fn<void()> setupAdditional( | |
| + not_null<Ui::VerticalLayout*> container) override; | |
| }; | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_privacy_security.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/settings: settings_privacy_security.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_privacy_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_privacy_widget.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_scale_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_scale_widget.h | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_widget.cpp | |
| Only in work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings: settings_widget.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings/settings.style work/tdesktop-1.4.0/Telegram/SourceFiles/settings/settings.style | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings/settings.style 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/settings/settings.style 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -6,103 +6,180 @@ | |
| https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | |
| */ | |
| using "basic.style"; | |
| -using "dialogs/dialogs.style"; | |
| using "ui/widgets/widgets.style"; | |
| +using "info/info.style"; | |
| using "boxes/boxes.style"; | |
| -settingsScroll: ScrollArea(defaultScrollArea) { | |
| - bottomsh: 0px; | |
| - topsh: 0px; | |
| -} | |
| - | |
| -settingsMaxWidth: 520px; | |
| -settingsMaxPadding: 48px; | |
| -settingsMinPadding: 32px; | |
| -settingsMargin: 48px; | |
| - | |
| -settingsFixedBarHeight: boxLayerTitleHeight; | |
| -settingsFixedBarFont: boxTitleFont; | |
| -settingsFixedBarTextPosition: boxLayerTitlePosition; | |
| -settingsFixedBarClose: IconButton(boxTitleClose) { | |
| - width: settingsFixedBarHeight; | |
| - height: settingsFixedBarHeight; | |
| -} | |
| - | |
| -settingsMarginTop: 34px; | |
| -settingsPhoto: UserpicButton(defaultUserpicButton) { | |
| - size: size(112px, 112px); | |
| - photoSize: 112px; | |
| -} | |
| -settingsPhotoLeft: -8px; | |
| -settingsPhotoDuration: 500; | |
| -settingsNameLeft: 26px; | |
| -settingsNameTop: 9px; | |
| -settingsNameLabel: FlatLabel(defaultFlatLabel) { | |
| - margin: margins(10px, 5px, 10px, 5px); | |
| - minWidth: 160px; | |
| - maxHeight: 24px; | |
| - textFg: windowBoldFg; | |
| - style: TextStyle(defaultTextStyle) { | |
| - font: font(16px semibold); | |
| - linkFont: font(16px semibold); | |
| - linkFontOver: font(16px semibold underline); | |
| - } | |
| +settingsSectionButton: InfoProfileButton(infoProfileButton) { | |
| + font: boxTextFont; | |
| + padding: margins(79px, 13px, 22px, 11px); | |
| +} | |
| +settingsButton: InfoProfileButton(settingsSectionButton) { | |
| + padding: margins(22px, 10px, 22px, 8px); | |
| +} | |
| +settingsSectionSkip: 9px; | |
| +settingsSectionIconLeft: 22px; | |
| +settingsSeparatorPadding: margins(22px, infoProfileSkip, 0px, infoProfileSkip); | |
| +settingsButtonRightSkip: 28px; | |
| +settingsButtonRight: FlatLabel(defaultFlatLabel) { | |
| + textFg: windowActiveTextFg; | |
| + style: boxTextStyle; | |
| + maxHeight: 20px; | |
| +} | |
| +settingsScalePadding: margins(79px, 10px, 28px, 8px); | |
| +settingsBigScalePadding: margins(22px, 10px, 22px, 8px); | |
| +settingsSlider: SettingsSlider(defaultSettingsSlider) { | |
| + barFg: windowBgOver; | |
| + labelFg: windowSubTextFg; | |
| + labelFgActive: windowActiveTextFg; | |
| +} | |
| +settingsUpdateToggle: InfoProfileButton(settingsButton) { | |
| + height: 40px; | |
| + padding: margins(22px, 8px, 22px, 8px); | |
| +} | |
| +settingsUpdateState: FlatLabel(defaultFlatLabel) { | |
| + textFg: windowSubTextFg; | |
| +} | |
| +settingsUpdate: InfoProfileButton(infoMainButton, settingsButton) { | |
| } | |
| -settingsStatusLeft: 27px; | |
| -settingsStatusTop: 35px; | |
| -settingsStatusFont: normalFont; | |
| -settingsStatusFg: windowSubTextFg; | |
| -settingsStatusFgActive: windowActiveTextFg; | |
| -settingsMarginBottom: 35px; | |
| - | |
| -settingsButtonLeft: 27px; | |
| -settingsButtonTop: 75px; | |
| -settingsButtonSkip: 10px; | |
| -settingsPrimaryButton: defaultActiveButton; | |
| -settingsSecondaryButton: defaultLightButton; | |
| -settingsEditButton: IconButton { | |
| - width: 24px; | |
| - height: 34px; | |
| - | |
| - icon: icon {{ "settings_edit_name", menuIconFg }}; | |
| - iconPosition: point(3px, 9px); | |
| -} | |
| - | |
| -settingsBlocksTop: 7px; | |
| -settingsBlocksBottom: 20px; | |
| -settingsBlockMarginTop: 14px; | |
| -settingsBlockMarginRight: 10px; | |
| -settingsBlockMarginBottom: 10px; | |
| -settingsBlockTitleHeight: 31px; | |
| -settingsBlockTitleFont: font(15px semibold); | |
| -settingsBlockTitleFg: windowBoldFg; | |
| -settingsBlockTitleTop: 0px; | |
| -settingsPrimaryLabel: FlatLabel(defaultFlatLabel) { | |
| - style: TextStyle(defaultTextStyle) { | |
| - font: boxTextFont; | |
| - linkFont: boxTextFont; | |
| - linkFontOver: font(boxFontSize underline); | |
| +settingsUpdateStatePosition: point(22px, 29px); | |
| +settingsDividerLabelPadding: margins(22px, 10px, 22px, 19px); | |
| + | |
| +settingsIconInformation: icon {{ "settings_information", menuIconFg }}; | |
| +settingsIconNotifications: icon {{ "settings_notifications", menuIconFg }}; | |
| +settingsIconChat: icon {{ "settings_chat", menuIconFg }}; | |
| +settingsIconGeneral: icon {{ "settings_advanced", menuIconFg }}; | |
| +settingsIconPrivacySecurity: icon {{ "settings_privacy_security", menuIconFg }}; | |
| +settingsIconLanguage: icon {{ "settings_language", menuIconFg }}; | |
| +settingsIconInterfaceScale: icon {{ "settings_interface_scale", menuIconFg }}; | |
| +settingsIconFaq: icon {{ "settings_faq", menuIconFg }}; | |
| +settingsIconStickers: icon {{ "settings_stickers", menuIconFg }}; | |
| +settingsIconThemes: icon {{ "settings_themes", menuIconFg }}; | |
| + | |
| +settingsSetPhotoSkip: 7px; | |
| + | |
| +settingsCheckbox: Checkbox(defaultBoxCheckbox) { | |
| + textPosition: point(15px, 1px); | |
| +} | |
| +settingsCheckboxPadding: margins(22px, 10px, 10px, 10px); | |
| +settingsLink: boxLinkButton; | |
| +settingsAdvancedNotificationsPadding: margins(22px, 20px, 10px, 10px); | |
| +settingsLinkLabel: defaultFlatLabel; | |
| +settingsCheckboxesSkip: 12px; | |
| + | |
| +settingsSendType: settingsCheckbox; | |
| +settingsSendTypePadding: margins(22px, 5px, 10px, 5px); | |
| +settingsSendTypeSkip: 5px; | |
| + | |
| +settingsBackgroundThumb: 76px; | |
| +settingsThumbSkip: 16px; | |
| +settingsSubsectionTitle: FlatLabel(defaultFlatLabel) { | |
| + style: TextStyle(semiboldTextStyle) { | |
| + font: font(boxFontSize semibold); | |
| + linkFont: font(boxFontSize semibold); | |
| + linkFontOver: font(boxFontSize semibold underline); | |
| } | |
| + textFg: windowActiveTextFg; | |
| } | |
| -settingsBlockLabel: FlatLabel(settingsPrimaryLabel) { | |
| +settingsSubsectionTitlePadding: margins(22px, 7px, 10px, 9px); | |
| +settingsBackgroundPadding: margins(22px, 11px, 10px, 12px); | |
| +settingsTileSkip: 15px; | |
| +settingsFromGalleryTop: 2px; | |
| +settingsFromFileTop: 14px; | |
| +settingsPrivacySecurityPadding: 12px; | |
| +settingsPrivacySkip: 14px; | |
| + | |
| +settingsCloudPasswordLabel: FlatLabel(defaultFlatLabel) { | |
| textFg: windowSubTextFg; | |
| + style: boxTextStyle; | |
| + maxHeight: 20px; | |
| } | |
| -settingsBlockOneLineTextPart: FlatLabel(settingsPrimaryLabel) { | |
| - minWidth: 0px; // No need to set minWidth in one-line text. | |
| - margin: margins(5px, 5px, 5px, 5px); | |
| +settingsCloudPasswordLabelPadding: margins(22px, 8px, 10px, 8px); | |
| + | |
| +settingsInfoPhotoHeight: 175px; | |
| +settingsInfoPhotoSize: 84px; | |
| +settingsInfoPhoto: UserpicButton(defaultUserpicButton) { | |
| + size: size(settingsInfoPhotoSize, settingsInfoPhotoSize); | |
| + photoSize: settingsInfoPhotoSize; | |
| +} | |
| +settingsInfoPhotoTop: 17px; | |
| +settingsInfoPhotoSkip: 16px; | |
| +settingsInfoPhotoSet: defaultActiveButton; | |
| + | |
| +settingsInfoRow: InfoProfileButton(settingsButton) { | |
| + height: 62px; | |
| + padding: margins(0px, 0px, 0px, 0px); | |
| +} | |
| +settingsInfoIconPosition: point(22px, 18px); | |
| +settingsInfoValue: FlatLabel(defaultFlatLabel) { | |
| + textFg: windowFg; | |
| + style: boxTextStyle; | |
| maxHeight: 20px; | |
| } | |
| -settingsBioValue: FlatLabel(settingsBlockOneLineTextPart) { | |
| - minWidth: 120px; | |
| - maxHeight: 0px; | |
| +settingsInfoValuePosition: point(78px, 14px); | |
| +settingsInfoAbout: FlatLabel(settingsInfoValue) { | |
| + textFg: windowSubTextFg; | |
| + style: defaultTextStyle; | |
| } | |
| -settingsSubSkip: 4px; | |
| -settingsSmallSkip: 10px; | |
| -settingsSkip: 14px; | |
| -settingsLargeSkip: 23px; | |
| +settingsInfoAboutPosition: point(78px, 34px); | |
| +settingsInfoRightSkip: 60px; | |
| +settingsInfoEditRight: 14px; | |
| +settingsInfoEditIconOver: icon {{ "settings_edit", menuIconFgOver }}; | |
| +settingsBio: InputField(defaultInputField) { | |
| + textBg: transparent; | |
| + textMargins: margins(0px, 7px, 0px, 13px); | |
| + | |
| + placeholderFg: placeholderFg; | |
| + placeholderFgActive: placeholderFgActive; | |
| + placeholderFgError: placeholderFgActive; | |
| + placeholderMargins: margins(2px, 0px, 2px, 0px); | |
| + placeholderScale: 0.; | |
| + placeholderFont: normalFont; | |
| + | |
| + heightMin: 32px; | |
| + | |
| + font: boxTextFont; | |
| +} | |
| +settingsInfoAfterSkip: 14px; | |
| +settingsInfoName: icon {{ "settings_name", menuIconFg }}; | |
| +settingsInfoPhone: icon {{ "settings_phone_number", menuIconFg }}; | |
| +settingsInfoUsername: icon {{ "settings_username", menuIconFg }}; | |
| + | |
| +settingsBioMargins: margins(20px, 6px, 20px, 6px); | |
| +settingsBioCountdown: FlatLabel(defaultFlatLabel) { | |
| + style: boxTextStyle; | |
| + textFg: windowSubTextFg; | |
| +} | |
| +settingsBioLabelPadding: margins(22px, 11px, 22px, 0px); | |
| + | |
| +settingsPrivacyEditLabelPadding: margins(22px, 11px, 22px, 11px); | |
| + | |
| +settingsChatButton: InfoProfileButton(settingsSectionButton) { | |
| + padding: margins(59px, 13px, 22px, 11px); | |
| +} | |
| +settingsChatIconLeft: 19px; | |
| -settingsActionPadding: margins(0px, 4px, 0px, 5px); | |
| +settingsThemesTopSkip: 10px; | |
| +settingsThemesBottomSkip: 8px; | |
| +settingsTheme: Checkbox(defaultCheckbox) { | |
| + textFg: windowSubTextFg; | |
| + textFgActive: windowActiveTextFg; | |
| + | |
| + width: 80px; | |
| + margin: margins(0px, 0px, 0px, 0px); | |
| + | |
| + textPosition: point(0px, 86px); | |
| + checkPosition: point(0px, 0px); | |
| -settingsBackgroundSize: 120px; | |
| + style: defaultTextStyle; | |
| + | |
| + disabledOpacity: 0.5; | |
| +} | |
| -settingsUpdateFg: windowSubTextFg; | |
| +settingsThemePreviewSize: size(80px, 80px); | |
| +settingsThemeBubbleSize: size(40px, 14px); | |
| +settingsThemeBubbleRadius: 2px; | |
| +settingsThemeBubblePosition: point(6px, 8px); | |
| +settingsThemeBubbleSkip: 4px; | |
| +settingsThemeRadioBottom: 8px; | |
| +settingsThemeMinSkip: 4px; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/settings.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/settings.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,10 +10,10 @@ | |
| bool gRtl = false; | |
| Qt::LayoutDirection gLangDir = gRtl ? Qt::RightToLeft : Qt::LeftToRight; | |
| -bool gAlphaVersion = AppAlphaVersion; | |
| -uint64 gBetaVersion = AppBetaVersion; | |
| -uint64 gRealBetaVersion = AppBetaVersion; | |
| -QByteArray gBetaPrivateKey; | |
| +bool gInstallBetaVersion = AppBetaVersion; | |
| +uint64 gAlphaVersion = AppAlphaVersion; | |
| +uint64 gRealAlphaVersion = AppAlphaVersion; | |
| +QByteArray gAlphaPrivateKey; | |
| bool gTestMode = false; | |
| bool gManyInstance = false; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings.h work/tdesktop-1.4.0/Telegram/SourceFiles/settings.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/settings.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/settings.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -28,10 +28,10 @@ | |
| return cRtl(); | |
| } | |
| -DeclareSetting(bool, AlphaVersion); | |
| -DeclareSetting(uint64, BetaVersion); | |
| -DeclareSetting(uint64, RealBetaVersion); | |
| -DeclareSetting(QByteArray, BetaPrivateKey); | |
| +DeclareSetting(bool, InstallBetaVersion); | |
| +DeclareSetting(uint64, AlphaVersion); | |
| +DeclareSetting(uint64, RealAlphaVersion); | |
| +DeclareSetting(QByteArray, AlphaPrivateKey); | |
| DeclareSetting(bool, TestMode); | |
| DeclareSetting(QString, LoggedPhoneNumber); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/stdafx.h work/tdesktop-1.4.0/Telegram/SourceFiles/stdafx.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/stdafx.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/stdafx.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -6,7 +6,6 @@ | |
| https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | |
| */ | |
| -#define NOMINMAX // no min() and max() macro declarations | |
| #define __HUGE | |
| // Fix Google Breakpad build for Mac App Store version | |
| @@ -56,6 +55,7 @@ | |
| #include <unordered_set> | |
| #include <algorithm> | |
| #include <memory> | |
| +#include <optional> | |
| #include <range/v3/all.hpp> | |
| #ifdef Q_OS_WIN | |
| @@ -79,7 +79,7 @@ | |
| #include "base/flat_map.h" | |
| #include "base/weak_ptr.h" | |
| -#include "core/basic_types.h" | |
| +#include "base/basic_types.h" | |
| #include "logs.h" | |
| #include "core/utils.h" | |
| #include "config.h" | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: cache | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/file_download.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/file_download.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/file_download.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/file_download.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,6 +8,7 @@ | |
| #include "storage/file_download.h" | |
| #include "data/data_document.h" | |
| +#include "data/data_session.h" | |
| #include "mainwidget.h" | |
| #include "mainwindow.h" | |
| #include "messenger.h" | |
| @@ -36,6 +37,7 @@ | |
| void Downloader::requestedAmountIncrement(MTP::DcId dcId, int index, int amount) { | |
| Expects(index >= 0 && index < MTP::kDownloadSessionsCount); | |
| + | |
| auto it = _requestedBytesAmount.find(dcId); | |
| if (it == _requestedBytesAmount.cend()) { | |
| it = _requestedBytesAmount.emplace(dcId, RequestedInDc { { 0 } }).first; | |
| @@ -105,9 +107,17 @@ | |
| } // namespace | |
| -FileLoader::FileLoader(const QString &toFile, int32 size, LocationType locationType, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading) | |
| +FileLoader::FileLoader( | |
| + const QString &toFile, | |
| + int32 size, | |
| + LocationType locationType, | |
| + LoadToCacheSetting toCache, | |
| + LoadFromCloudSetting fromCloud, | |
| + bool autoLoading, | |
| + uint8 cacheTag) | |
| : _downloader(&Auth().downloader()) | |
| , _autoLoading(autoLoading) | |
| +, _cacheTag(cacheTag) | |
| , _filename(toFile) | |
| , _file(_filename) | |
| , _toCache(toCache) | |
| @@ -206,16 +216,16 @@ | |
| } | |
| FileLoader::~FileLoader() { | |
| - if (_localTaskId) { | |
| - Local::cancelTask(_localTaskId); | |
| - } | |
| removeFromQueue(); | |
| } | |
| -void FileLoader::localLoaded(const StorageImageSaved &result, const QByteArray &imageFormat, const QPixmap &imagePixmap) { | |
| - _localTaskId = 0; | |
| +void FileLoader::localLoaded( | |
| + const StorageImageSaved &result, | |
| + const QByteArray &imageFormat, | |
| + const QPixmap &imagePixmap) { | |
| + _localLoading.kill(); | |
| if (result.data.isEmpty()) { | |
| - _localStatus = LocalFailed; | |
| + _localStatus = LocalStatus::NotFound; | |
| start(true); | |
| return; | |
| } | |
| @@ -224,7 +234,7 @@ | |
| _imageFormat = imageFormat; | |
| _imagePixmap = imagePixmap; | |
| } | |
| - _localStatus = LocalLoaded; | |
| + _localStatus = LocalStatus::Loaded; | |
| if (!_filename.isEmpty() && _toCache == LoadToCacheAsWell) { | |
| if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly); | |
| if (!_fileIsOpen) { | |
| @@ -241,7 +251,8 @@ | |
| if (_fileIsOpen) { | |
| _file.close(); | |
| _fileIsOpen = false; | |
| - Platform::File::PostprocessDownloaded(QFileInfo(_file).absoluteFilePath()); | |
| + Platform::File::PostprocessDownloaded( | |
| + QFileInfo(_file).absoluteFilePath()); | |
| } | |
| _downloader->taskFinished().notify(); | |
| @@ -254,9 +265,9 @@ | |
| if (_paused) { | |
| _paused = false; | |
| } | |
| - if (_finished || tryLoadLocal()) return; | |
| - | |
| - if (_fromCloud == LoadFromLocalOnly) { | |
| + if (_finished || tryLoadLocal()) { | |
| + return; | |
| + } else if (_fromCloud == LoadFromLocalOnly) { | |
| cancel(); | |
| return; | |
| } | |
| @@ -357,6 +368,77 @@ | |
| return startLoading(loadFirst, prior); | |
| } | |
| +void FileLoader::loadLocal(const Storage::Cache::Key &key) { | |
| + const auto readImage = (_locationType != AudioFileLocation); | |
| + auto [first, second] = base::make_binary_guard(); | |
| + _localLoading = std::move(first); | |
| + auto done = [=, guard = std::move(second)]( | |
| + QByteArray &&value, | |
| + QImage &&image, | |
| + QByteArray &&format) mutable { | |
| + crl::on_main([ | |
| + =, | |
| + value = std::move(value), | |
| + image = std::move(image), | |
| + format = std::move(format), | |
| + guard = std::move(guard) | |
| + ]() mutable { | |
| + if (!guard.alive()) { | |
| + return; | |
| + } | |
| + localLoaded( | |
| + StorageImageSaved(std::move(value)), | |
| + format, | |
| + App::pixmapFromImageInPlace(std::move(image))); | |
| + }); | |
| + }; | |
| + Auth().data().cache().get(key, [=, callback = std::move(done)]( | |
| + QByteArray &&value) mutable { | |
| + if (readImage) { | |
| + crl::async([ | |
| + value = std::move(value), | |
| + done = std::move(callback) | |
| + ]() mutable { | |
| + auto format = QByteArray(); | |
| + auto image = App::readImage(value, &format, false); | |
| + if (!image.isNull()) { | |
| + done( | |
| + std::move(value), | |
| + std::move(image), | |
| + std::move(format)); | |
| + } else { | |
| + done(std::move(value), {}, {}); | |
| + } | |
| + }); | |
| + } else { | |
| + callback(std::move(value), {}, {}); | |
| + } | |
| + }); | |
| +} | |
| + | |
| +bool FileLoader::tryLoadLocal() { | |
| + if (_localStatus == LocalStatus::NotFound | |
| + || _localStatus == LocalStatus::Loaded) { | |
| + return false; | |
| + } else if (_localStatus == LocalStatus::Loading) { | |
| + return true; | |
| + } | |
| + | |
| + if (const auto key = cacheKey()) { | |
| + loadLocal(*key); | |
| + emit progress(this); | |
| + } | |
| + | |
| + if (_localStatus != LocalStatus::NotTried) { | |
| + return _finished; | |
| + } else if (_localLoading.alive()) { | |
| + _localStatus = LocalStatus::Loading; | |
| + return true; | |
| + } | |
| + _localStatus = LocalStatus::NotFound; | |
| + return false; | |
| +} | |
| + | |
| void FileLoader::cancel() { | |
| cancel(false); | |
| } | |
| @@ -397,15 +479,17 @@ | |
| not_null<StorageImageLocation*> location, | |
| Data::FileOrigin origin, | |
| int32 size, | |
| - LoadFromCloudSetting fromCloud | |
| - , bool autoLoading) | |
| + LoadFromCloudSetting fromCloud, | |
| + bool autoLoading, | |
| + uint8 cacheTag) | |
| : FileLoader( | |
| QString(), | |
| size, | |
| UnknownFileLocation, | |
| LoadToCacheAsWell, | |
| fromCloud, | |
| - autoLoading) | |
| + autoLoading, | |
| + cacheTag) | |
| , _dcId(location->dc()) | |
| , _location(location) | |
| , _origin(origin) { | |
| @@ -428,14 +512,16 @@ | |
| int32 size, | |
| LoadToCacheSetting toCache, | |
| LoadFromCloudSetting fromCloud, | |
| - bool autoLoading) | |
| + bool autoLoading, | |
| + uint8 cacheTag) | |
| : FileLoader( | |
| to, | |
| size, | |
| type, | |
| toCache, | |
| fromCloud, | |
| - autoLoading) | |
| + autoLoading, | |
| + cacheTag) | |
| , _dcId(dc) | |
| , _id(id) | |
| , _accessHash(accessHash) | |
| @@ -453,14 +539,16 @@ | |
| const WebFileLocation *location, | |
| int32 size, | |
| LoadFromCloudSetting fromCloud, | |
| - bool autoLoading) | |
| + bool autoLoading, | |
| + uint8 cacheTag) | |
| : FileLoader( | |
| QString(), | |
| size, | |
| UnknownFileLocation, | |
| LoadToCacheAsWell, | |
| fromCloud, | |
| - autoLoading) | |
| + autoLoading, | |
| + cacheTag) | |
| , _dcId(location->dc()) | |
| , _urlLocation(location) { | |
| auto shiftedDcId = MTP::downloadDcId(_dcId, 0); | |
| @@ -695,7 +783,7 @@ | |
| state.ivec[12] = static_cast<uchar>((counterOffset >> 24) & 0xFF); | |
| auto decryptInPlace = result.c_upload_cdnFile().vbytes.v; | |
| - auto buffer = bytes::make_span(decryptInPlace); | |
| + auto buffer = bytes::make_detached_span(decryptInPlace); | |
| MTP::aesCtrEncrypt(buffer, key.data(), &state); | |
| switch (checkCdnFileHash(offset, buffer)) { | |
| @@ -822,17 +910,7 @@ | |
| return false; | |
| } | |
| } else { | |
| - if (offset > 100 * 1024 * 1024) { | |
| - // Debugging weird out of memory crashes. | |
| - auto info = QString("offset: %1, size: %2, cancelled: %3, finished: %4, filename: '%5', tocache: %6, fromcloud: %7, data: %8, fullsize: %9").arg(offset).arg(buffer.size()).arg(Logs::b(_cancelled)).arg(Logs::b(_finished)).arg(_filename).arg(int(_toCache)).arg(int(_fromCloud)).arg(_data.size()).arg(_size); | |
| - info += QString(", locationtype: %1, inqueue: %2, localstatus: %3").arg(int(_locationType)).arg(Logs::b(_inQueue)).arg(int(_localStatus)); | |
| - CrashReports::SetAnnotation("DebugInfo", info); | |
| - } | |
| _data.reserve(offset + buffer.size()); | |
| - if (offset > 100 * 1024 * 1024) { | |
| - CrashReports::ClearAnnotation("DebugInfo"); | |
| - } | |
| - | |
| if (offset > _data.size()) { | |
| _skippedBytes += offset - _data.size(); | |
| _data.resize(offset); | |
| @@ -844,7 +922,9 @@ | |
| if (int64(offset + buffer.size()) > _data.size()) { | |
| _data.resize(offset + buffer.size()); | |
| } | |
| - auto dst = bytes::make_span(_data).subspan(offset, buffer.size()); | |
| + const auto dst = bytes::make_detached_span(_data).subspan( | |
| + offset, | |
| + buffer.size()); | |
| bytes::copy(dst, buffer); | |
| } | |
| } | |
| @@ -872,29 +952,25 @@ | |
| } | |
| removeFromQueue(); | |
| - if (_localStatus == LocalNotFound || _localStatus == LocalFailed) { | |
| - if (_urlLocation) { | |
| - Local::writeImage(storageKey(*_urlLocation), StorageImageSaved(_data)); | |
| - } else if (_locationType != UnknownFileLocation) { // audio, video, document | |
| - auto mkey = mediaKey(_locationType, _dcId, _id); | |
| - if (!_filename.isEmpty()) { | |
| - Local::writeFileLocation(mkey, FileLocation(_filename)); | |
| - } | |
| - if (_toCache == LoadToCacheAsWell) { | |
| - if (_locationType == DocumentFileLocation) { | |
| - Local::writeStickerImage(mkey, _data); | |
| - } else if (_locationType == AudioFileLocation) { | |
| - Local::writeAudio(mkey, _data); | |
| - } else if (_locationType == SecureFileLocation) { | |
| - Local::writeImage( | |
| - StorageKey( | |
| - storageMix32To64(_locationType, _dcId), | |
| - _id), | |
| - StorageImageSaved(_data)); | |
| + if (_localStatus == LocalStatus::NotFound) { | |
| + if (_locationType != UnknownFileLocation | |
| + && !_filename.isEmpty()) { | |
| + Local::writeFileLocation( | |
| + mediaKey(_locationType, _dcId, _id), | |
| + FileLocation(_filename)); | |
| + } | |
| + if (_urlLocation | |
| + || _locationType == UnknownFileLocation | |
| + || _toCache == LoadToCacheAsWell) { | |
| + if (const auto key = cacheKey()) { | |
| + if (_data.size() <= Storage::kMaxFileInMemory) { | |
| + Auth().data().cache().put( | |
| + *key, | |
| + Storage::Cache::Database::TaggedValue( | |
| + base::duplicate(_data), | |
| + _cacheTag)); | |
| } | |
| } | |
| - } else { | |
| - Local::writeImage(storageKey(*_location), StorageImageSaved(_data)); | |
| } | |
| } | |
| } | |
| @@ -1026,51 +1102,35 @@ | |
| makeRequest(offset); | |
| } | |
| -bool mtpFileLoader::tryLoadLocal() { | |
| - if (_localStatus == LocalNotFound || _localStatus == LocalLoaded || _localStatus == LocalFailed) { | |
| - return false; | |
| - } | |
| - if (_localStatus == LocalLoading) { | |
| - return true; | |
| - } | |
| - | |
| +std::optional<Storage::Cache::Key> mtpFileLoader::cacheKey() const { | |
| if (_urlLocation) { | |
| - _localTaskId = Local::startImageLoad(storageKey(*_urlLocation), this); | |
| + return Data::WebDocumentCacheKey(*_urlLocation); | |
| } else if (_location) { | |
| - _localTaskId = Local::startImageLoad(storageKey(*_location), this); | |
| - } else { | |
| - if (_toCache == LoadToCacheAsWell) { | |
| - MediaKey mkey = mediaKey(_locationType, _dcId, _id); | |
| - if (_locationType == DocumentFileLocation) { | |
| - _localTaskId = Local::startStickerImageLoad(mkey, this); | |
| - } else if (_locationType == AudioFileLocation) { | |
| - _localTaskId = Local::startAudioLoad(mkey, this); | |
| - } else if (_locationType == SecureFileLocation) { | |
| - _localTaskId = Local::startImageLoad(StorageKey( | |
| - storageMix32To64(_locationType, _dcId), | |
| - _id), this); | |
| - } | |
| - } | |
| + return Data::StorageCacheKey(*_location); | |
| + } else if (_toCache == LoadToCacheAsWell) { | |
| + return Data::DocumentCacheKey(_dcId, _id); | |
| } | |
| - | |
| - emit progress(this); | |
| - | |
| - if (_localStatus != LocalNotTried) { | |
| - return _finished; | |
| - } else if (_localTaskId) { | |
| - _localStatus = LocalLoading; | |
| - return true; | |
| - } | |
| - _localStatus = LocalNotFound; | |
| - return false; | |
| + return std::nullopt; | |
| } | |
| mtpFileLoader::~mtpFileLoader() { | |
| cancelRequests(); | |
| } | |
| -webFileLoader::webFileLoader(const QString &url, const QString &to, LoadFromCloudSetting fromCloud, bool autoLoading) | |
| -: FileLoader(QString(), 0, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading) | |
| +webFileLoader::webFileLoader( | |
| + const QString &url, | |
| + const QString &to, | |
| + LoadFromCloudSetting fromCloud, | |
| + bool autoLoading, | |
| + uint8 cacheTag) | |
| +: FileLoader( | |
| + QString(), | |
| + 0, | |
| + UnknownFileLocation, | |
| + LoadToCacheAsWell, | |
| + fromCloud, | |
| + autoLoading, | |
| + cacheTag) | |
| , _url(url) | |
| , _requestSent(false) | |
| , _already(0) { | |
| @@ -1129,8 +1189,16 @@ | |
| } | |
| removeFromQueue(); | |
| - if (_localStatus == LocalNotFound || _localStatus == LocalFailed) { | |
| - Local::writeWebFile(_url, _data); | |
| + if (_localStatus == LocalStatus::NotFound) { | |
| + if (const auto key = cacheKey()) { | |
| + if (_data.size() <= Storage::kMaxFileInMemory) { | |
| + Auth().data().cache().put( | |
| + *key, | |
| + Storage::Cache::Database::TaggedValue( | |
| + base::duplicate(_data), | |
| + _cacheTag)); | |
| + } | |
| + } | |
| } | |
| _downloader->taskFinished().notify(); | |
| @@ -1143,23 +1211,8 @@ | |
| cancel(true); | |
| } | |
| -bool webFileLoader::tryLoadLocal() { | |
| - if (_localStatus == LocalNotFound || _localStatus == LocalLoaded || _localStatus == LocalFailed) { | |
| - return false; | |
| - } | |
| - if (_localStatus == LocalLoading) { | |
| - return true; | |
| - } | |
| - | |
| - _localTaskId = Local::startWebFileLoad(_url, this); | |
| - if (_localStatus != LocalNotTried) { | |
| - return _finished; | |
| - } else if (_localTaskId) { | |
| - _localStatus = LocalLoading; | |
| - return true; | |
| - } | |
| - _localStatus = LocalNotFound; | |
| - return false; | |
| +std::optional<Storage::Cache::Key> webFileLoader::cacheKey() const { | |
| + return Data::UrlCacheKey(_url); | |
| } | |
| void webFileLoader::cancelRequests() { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/file_download.h work/tdesktop-1.4.0/Telegram/SourceFiles/storage/file_download.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/file_download.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/file_download.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,10 +8,13 @@ | |
| #pragma once | |
| #include "base/observer.h" | |
| -#include "storage/localimageloader.h" // for TaskId | |
| #include "data/data_file_origin.h" | |
| +#include "base/binary_guard.h" | |
| namespace Storage { | |
| +namespace Cache { | |
| +struct Key; | |
| +} // namespace Cache | |
| constexpr auto kMaxFileInMemory = 10 * 1024 * 1024; // 10 MB max file could be hold in memory | |
| constexpr auto kMaxVoiceInMemory = 2 * 1024 * 1024; // 2 MB audio is hold in memory and auto loaded | |
| @@ -61,14 +64,6 @@ | |
| }; | |
| -enum LocalLoadStatus { | |
| - LocalNotTried, | |
| - LocalNotFound, | |
| - LocalLoading, | |
| - LocalLoaded, | |
| - LocalFailed, | |
| -}; | |
| - | |
| class mtpFileLoader; | |
| class webFileLoader; | |
| @@ -77,7 +72,15 @@ | |
| Q_OBJECT | |
| public: | |
| - FileLoader(const QString &toFile, int32 size, LocationType locationType, LoadToCacheSetting, LoadFromCloudSetting fromCloud, bool autoLoading); | |
| + FileLoader( | |
| + const QString &toFile, | |
| + int32 size, | |
| + LocationType locationType, | |
| + LoadToCacheSetting toCache, | |
| + LoadFromCloudSetting fromCloud, | |
| + bool autoLoading, | |
| + uint8 cacheTag); | |
| + | |
| bool finished() const { | |
| return _finished; | |
| } | |
| @@ -119,7 +122,7 @@ | |
| return _inQueue || _paused; | |
| } | |
| bool loadingLocal() const { | |
| - return (_localStatus == LocalLoading); | |
| + return (_localStatus == LocalStatus::Loading); | |
| } | |
| bool autoLoading() const { | |
| return _autoLoading; | |
| @@ -129,15 +132,37 @@ | |
| } | |
| virtual ~FileLoader(); | |
| - void localLoaded(const StorageImageSaved &result, const QByteArray &imageFormat = QByteArray(), const QPixmap &imagePixmap = QPixmap()); | |
| + void localLoaded( | |
| + const StorageImageSaved &result, | |
| + const QByteArray &imageFormat = QByteArray(), | |
| + const QPixmap &imagePixmap = QPixmap()); | |
| signals: | |
| void progress(FileLoader *loader); | |
| void failed(FileLoader *loader, bool started); | |
| protected: | |
| + enum class LocalStatus { | |
| + NotTried, | |
| + NotFound, | |
| + Loading, | |
| + Loaded, | |
| + }; | |
| + | |
| void readImage(const QSize &shrinkBox) const; | |
| + bool tryLoadLocal(); | |
| + void loadLocal(const Storage::Cache::Key &key); | |
| + virtual std::optional<Storage::Cache::Key> cacheKey() const = 0; | |
| + virtual void cancelRequests() = 0; | |
| + | |
| + void startLoading(bool loadFirst, bool prior); | |
| + void removeFromQueue(); | |
| + void cancel(bool failed); | |
| + | |
| + void loadNext(); | |
| + virtual bool loadPart() = 0; | |
| + | |
| not_null<Storage::Downloader*> _downloader; | |
| FileLoader *_prev = nullptr; | |
| FileLoader *_next = nullptr; | |
| @@ -146,20 +171,11 @@ | |
| bool _paused = false; | |
| bool _autoLoading = false; | |
| + uint8 _cacheTag = 0; | |
| bool _inQueue = false; | |
| bool _finished = false; | |
| bool _cancelled = false; | |
| - mutable LocalLoadStatus _localStatus = LocalNotTried; | |
| - | |
| - virtual bool tryLoadLocal() = 0; | |
| - virtual void cancelRequests() = 0; | |
| - | |
| - void startLoading(bool loadFirst, bool prior); | |
| - void removeFromQueue(); | |
| - void cancel(bool failed); | |
| - | |
| - void loadNext(); | |
| - virtual bool loadPart() = 0; | |
| + mutable LocalStatus _localStatus = LocalStatus::NotTried; | |
| QString _filename; | |
| QFile _file; | |
| @@ -173,7 +189,7 @@ | |
| int32 _size; | |
| LocationType _locationType; | |
| - TaskId _localTaskId = 0; | |
| + base::binary_guard _localLoading; | |
| mutable QByteArray _imageFormat; | |
| mutable QPixmap _imagePixmap; | |
| @@ -190,7 +206,8 @@ | |
| Data::FileOrigin origin, | |
| int32 size, | |
| LoadFromCloudSetting fromCloud, | |
| - bool autoLoading); | |
| + bool autoLoading, | |
| + uint8 cacheTag); | |
| mtpFileLoader( | |
| int32 dc, | |
| uint64 id, | |
| @@ -202,12 +219,14 @@ | |
| int32 size, | |
| LoadToCacheSetting toCache, | |
| LoadFromCloudSetting fromCloud, | |
| - bool autoLoading); | |
| + bool autoLoading, | |
| + uint8 cacheTag); | |
| mtpFileLoader( | |
| const WebFileLocation *location, | |
| int32 size, | |
| LoadFromCloudSetting fromCloud, | |
| - bool autoLoading); | |
| + bool autoLoading, | |
| + uint8 cacheTag); | |
| int32 currentOffset(bool includeSkipped = false) const override; | |
| Data::FileOrigin fileOrigin() const override; | |
| @@ -238,8 +257,7 @@ | |
| int limit = 0; | |
| QByteArray hash; | |
| }; | |
| - | |
| - bool tryLoadLocal() override; | |
| + std::optional<Storage::Cache::Key> cacheKey() const override; | |
| void cancelRequests() override; | |
| int partSize() const; | |
| @@ -307,32 +325,29 @@ | |
| Q_OBJECT | |
| public: | |
| + webFileLoader( | |
| + const QString &url, | |
| + const QString &to, | |
| + LoadFromCloudSetting fromCloud, | |
| + bool autoLoading, | |
| + uint8 cacheTag); | |
| - webFileLoader(const QString &url, const QString &to, LoadFromCloudSetting fromCloud, bool autoLoading); | |
| - | |
| - virtual int32 currentOffset(bool includeSkipped = false) const; | |
| - virtual webFileLoader *webLoader() { | |
| - return this; | |
| - } | |
| - virtual const webFileLoader *webLoader() const { | |
| - return this; | |
| - } | |
| + int32 currentOffset(bool includeSkipped = false) const override; | |
| void onProgress(qint64 already, qint64 size); | |
| void onFinished(const QByteArray &data); | |
| void onError(); | |
| - virtual void stop() { | |
| + void stop() override { | |
| cancelRequests(); | |
| } | |
| ~webFileLoader(); | |
| protected: | |
| - | |
| - virtual void cancelRequests(); | |
| - virtual bool tryLoadLocal(); | |
| - virtual bool loadPart(); | |
| + void cancelRequests() override; | |
| + std::optional<Storage::Cache::Key> cacheKey() const override; | |
| + bool loadPart() override; | |
| QString _url; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/file_upload.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/file_upload.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/file_upload.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/file_upload.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -8,6 +8,7 @@ | |
| #include "storage/file_upload.h" | |
| #include "storage/localimageloader.h" | |
| +#include "storage/file_download.h" | |
| #include "data/data_document.h" | |
| #include "data/data_photo.h" | |
| #include "data/data_session.h" | |
| @@ -126,6 +127,14 @@ | |
| : Auth().data().document(media.document, media.photoThumbs.begin().value()); | |
| if (!media.data.isEmpty()) { | |
| document->setData(media.data); | |
| + if (document->saveToCache() | |
| + && media.data.size() <= Storage::kMaxFileInMemory) { | |
| + Auth().data().cache().put( | |
| + document->cacheKey(), | |
| + Storage::Cache::Database::TaggedValue( | |
| + base::duplicate(media.data), | |
| + document->cacheTag())); | |
| + } | |
| } | |
| if (!media.file.isEmpty()) { | |
| document->setLocation(FileLocation(media.file)); | |
| @@ -148,6 +157,14 @@ | |
| document->uploadingData = std::make_unique<Data::UploadState>(document->size); | |
| if (!file->content.isEmpty()) { | |
| document->setData(file->content); | |
| + if (document->saveToCache() | |
| + && file->content.size() <= Storage::kMaxFileInMemory) { | |
| + Auth().data().cache().put( | |
| + document->cacheKey(), | |
| + Storage::Cache::Database::TaggedValue( | |
| + base::duplicate(file->content), | |
| + document->cacheTag())); | |
| + } | |
| } | |
| if (!file->filepath.isEmpty()) { | |
| document->setLocation(FileLocation(file->filepath)); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localimageloader.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localimageloader.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localimageloader.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localimageloader.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -22,6 +22,66 @@ | |
| using Storage::ValidateThumbDimensions; | |
| +SendMediaReady PreparePeerPhoto(PeerId peerId, QImage &&image) { | |
| + PreparedPhotoThumbs photoThumbs; | |
| + QVector<MTPPhotoSize> photoSizes; | |
| + | |
| + QByteArray jpeg; | |
| + QBuffer jpegBuffer(&jpeg); | |
| + image.save(&jpegBuffer, "JPG", 87); | |
| + | |
| + const auto scaled = [&](int size) { | |
| + return App::pixmapFromImageInPlace(image.scaled( | |
| + size, | |
| + size, | |
| + Qt::KeepAspectRatio, | |
| + Qt::SmoothTransformation)); | |
| + }; | |
| + const auto push = [&](const char *type, QPixmap &&pixmap) { | |
| + photoSizes.push_back(MTP_photoSize( | |
| + MTP_string(type), | |
| + MTP_fileLocationUnavailable( | |
| + MTP_long(0), | |
| + MTP_int(0), | |
| + MTP_long(0)), | |
| + MTP_int(pixmap.width()), | |
| + MTP_int(pixmap.height()), MTP_int(0))); | |
| + photoThumbs.insert(type[0], std::move(pixmap)); | |
| + }; | |
| + push("a", scaled(160)); | |
| + push("b", scaled(320)); | |
| + push("c", App::pixmapFromImageInPlace(std::move(image))); | |
| + | |
| + const auto id = rand_value<PhotoId>(); | |
| + const auto photo = MTP_photo( | |
| + MTP_flags(0), | |
| + MTP_long(id), | |
| + MTP_long(0), | |
| + MTP_bytes(QByteArray()), | |
| + MTP_int(unixtime()), | |
| + MTP_vector<MTPPhotoSize>(photoSizes)); | |
| + | |
| + QString file, filename; | |
| + int32 filesize = 0; | |
| + QByteArray data; | |
| + | |
| + return SendMediaReady( | |
| + SendMediaType::Photo, | |
| + file, | |
| + filename, | |
| + filesize, | |
| + data, | |
| + id, | |
| + id, | |
| + qsl("jpg"), | |
| + peerId, | |
| + photo, | |
| + photoThumbs, | |
| + MTP_documentEmpty(MTP_long(0)), | |
| + jpeg, | |
| + 0); | |
| +} | |
| + | |
| TaskQueue::TaskQueue(TimeMs stopTimeoutMs) { | |
| if (stopTimeoutMs > 0) { | |
| _stopTimer = new QTimer(this); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localimageloader.h work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localimageloader.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localimageloader.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localimageloader.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -89,6 +89,8 @@ | |
| }; | |
| +SendMediaReady PreparePeerPhoto(PeerId peerId, QImage &&image); | |
| + | |
| using TaskId = void*; // no interface, just id | |
| class Task { | |
| @@ -163,7 +165,7 @@ | |
| } | |
| TaskId taskId; | |
| FullMsgId msgId; | |
| - base::optional<MTPInputSingleMedia> media; | |
| + std::optional<MTPInputSingleMedia> media; | |
| }; | |
| SendingAlbum(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localstorage.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localstorage.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localstorage.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localstorage.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,6 +9,8 @@ | |
| #include "storage/serialize_document.h" | |
| #include "storage/serialize_common.h" | |
| +#include "storage/storage_encrypted_file.h" | |
| +#include "storage/storage_clear_legacy.h" | |
| #include "chat_helpers/stickers.h" | |
| #include "data/data_drafts.h" | |
| #include "boxes/send_files_box.h" | |
| @@ -49,6 +51,7 @@ | |
| constexpr auto kSinglePeerTypeSelf = qint32(4); | |
| constexpr auto kSinglePeerTypeEmpty = qint32(0); | |
| +using Database = Storage::Cache::Database; | |
| using FileKey = quint64; | |
| constexpr char tdfMagic[] = { 'T', 'D', 'F', '$' }; | |
| @@ -65,7 +68,7 @@ | |
| return result; | |
| } | |
| -QString _basePath, _userBasePath; | |
| +QString _basePath, _userBasePath, _userDbPath; | |
| bool _started = false; | |
| internal::Manager *_manager = nullptr; | |
| @@ -510,6 +513,7 @@ | |
| lskFavedStickers = 0x12, // no data | |
| lskExportSettings = 0x13, // no data | |
| lskBackground = 0x14, // no data | |
| + lskSelfSerialized = 0x15, // serialized self | |
| }; | |
| enum { | |
| @@ -589,6 +593,8 @@ | |
| dbiTxtDomainString = 0x53, | |
| dbiThemeKey = 0x54, | |
| dbiTileBackground = 0x55, | |
| + dbiCacheSettings = 0x56, | |
| + dbiAnimationsDisabled = 0x57, | |
| dbiEncryptedWithSalt = 333, | |
| dbiEncrypted = 444, | |
| @@ -620,9 +626,6 @@ | |
| FileLocationPairs _fileLocationPairs; | |
| typedef QMap<MediaKey, MediaKey> FileLocationAliases; | |
| FileLocationAliases _fileLocationAliases; | |
| -typedef QMap<QString, FileDesc> WebFilesMap; | |
| -WebFilesMap _webFilesMap; | |
| -uint64 _storageWebFilesSize = 0; | |
| FileKey _locationsKey = 0, _reportSpamStatusesKey = 0, _trustedBotsKey = 0; | |
| using TrustedBots = OrderedSet<uint64>; | |
| @@ -649,16 +652,14 @@ | |
| FileKey _userSettingsKey = 0; | |
| FileKey _recentHashtagsAndBotsKey = 0; | |
| bool _recentHashtagsAndBotsWereRead = false; | |
| +qint64 _cacheTotalSizeLimit = Database::Settings().totalSizeLimit; | |
| +qint32 _cacheTotalTimeLimit = Database::Settings().totalTimeLimit; | |
| FileKey _exportSettingsKey = 0; | |
| FileKey _savedPeersKey = 0; | |
| FileKey _langPackKey = 0; | |
| -typedef QMap<StorageKey, FileDesc> StorageMap; | |
| -StorageMap _imagesMap, _stickerImagesMap, _audiosMap; | |
| -qint64 _storageImagesSize = 0, _storageStickersSize = 0, _storageAudiosSize = 0; | |
| - | |
| bool _mapChanged = false; | |
| int32 _oldMapVersion = 0, _oldSettingsVersion = 0; | |
| @@ -686,7 +687,7 @@ | |
| if (!_working()) return; | |
| _manager->writingLocations(); | |
| - if (_fileLocations.isEmpty() && _webFilesMap.isEmpty()) { | |
| + if (_fileLocations.isEmpty()) { | |
| if (_locationsKey) { | |
| clearKey(_locationsKey); | |
| _locationsKey = 0; | |
| @@ -724,12 +725,6 @@ | |
| size += sizeof(quint64) * 2 + sizeof(quint64) * 2; | |
| } | |
| - size += sizeof(quint32); // web files count | |
| - for (WebFilesMap::const_iterator i = _webFilesMap.cbegin(), e = _webFilesMap.cend(); i != e; ++i) { | |
| - // url + filekey + size | |
| - size += Serialize::stringSize(i.key()) + sizeof(quint64) + sizeof(qint32); | |
| - } | |
| - | |
| EncryptedDescriptor data(size); | |
| auto legacyTypeField = 0; | |
| for (FileLocations::const_iterator i = _fileLocations.cbegin(); i != _fileLocations.cend(); ++i) { | |
| @@ -751,11 +746,6 @@ | |
| data.stream << quint64(i.key().first) << quint64(i.key().second) << quint64(i.value().first) << quint64(i.value().second); | |
| } | |
| - data.stream << quint32(_webFilesMap.size()); | |
| - for (WebFilesMap::const_iterator i = _webFilesMap.cbegin(), e = _webFilesMap.cend(); i != e; ++i) { | |
| - data.stream << i.key() << quint64(i.value().first) << qint32(i.value().second); | |
| - } | |
| - | |
| FileWriteDescriptor file(_locationsKey); | |
| file.writeEncrypted(data); | |
| } | |
| @@ -804,9 +794,6 @@ | |
| } | |
| if (!locations.stream.atEnd()) { | |
| - _storageWebFilesSize = 0; | |
| - _webFilesMap.clear(); | |
| - | |
| quint32 webLocationsCount; | |
| locations.stream >> webLocationsCount; | |
| for (quint32 i = 0; i < webLocationsCount; ++i) { | |
| @@ -814,8 +801,7 @@ | |
| quint64 key; | |
| qint32 size; | |
| locations.stream >> url >> key >> size; | |
| - _webFilesMap.insert(url, FileDesc(key, size)); | |
| - _storageWebFilesSize += size; | |
| + clearKey(key, FileOption::User); | |
| } | |
| } | |
| } | |
| @@ -1031,6 +1017,30 @@ | |
| cSetUseExternalVideoPlayer(v == 1); | |
| } break; | |
| + case dbiCacheSettings: { | |
| + qint64 size; | |
| + qint32 time; | |
| + stream >> size >> time; | |
| + if (!_checkStreamStatus(stream) | |
| + || size <= Database::Settings().maxDataSize | |
| + || time < 0) { | |
| + return false; | |
| + } | |
| + | |
| + _cacheTotalSizeLimit = size; | |
| + _cacheTotalTimeLimit = time; | |
| + } break; | |
| + | |
| + case dbiAnimationsDisabled: { | |
| + qint32 disabled; | |
| + stream >> disabled; | |
| + if (!_checkStreamStatus(stream)) { | |
| + return false; | |
| + } | |
| + | |
| + anim::SetDisabled(disabled == 1); | |
| + } break; | |
| + | |
| case dbiSoundNotify: { | |
| qint32 v; | |
| stream >> v; | |
| @@ -1926,6 +1936,7 @@ | |
| size += sizeof(quint32) + 3 * sizeof(qint32); | |
| size += sizeof(quint32) + 2 * sizeof(qint32); | |
| size += sizeof(quint32) + 2 * sizeof(qint32); | |
| + size += sizeof(quint32) + sizeof(qint64) + sizeof(qint32); | |
| if (!Global::HiddenPinnedMessages().isEmpty()) { | |
| size += sizeof(quint32) + sizeof(qint32) + Global::HiddenPinnedMessages().size() * (sizeof(PeerId) + sizeof(MsgId)); | |
| } | |
| @@ -1961,6 +1972,7 @@ | |
| data.stream << quint32(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 1 : 0); | |
| data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0); | |
| data.stream << quint32(dbiUseExternalVideoPlayer) << qint32(cUseExternalVideoPlayer()); | |
| + data.stream << quint32(dbiCacheSettings) << qint64(_cacheTotalSizeLimit) << qint32(_cacheTotalTimeLimit); | |
| if (!userData.isEmpty()) { | |
| data.stream << quint32(dbiAuthSessionSettings) << userData; | |
| } | |
| @@ -2071,6 +2083,10 @@ | |
| hashMd5(dataNameUtf8.constData(), dataNameUtf8.size(), dataNameHash); | |
| _dataNameKey = dataNameHash[0]; | |
| _userBasePath = _basePath + toFilePart(_dataNameKey) + QChar('/'); | |
| + _userDbPath = _basePath | |
| + + "user_" + cDataFile() | |
| + + (cTestMode() ? "[test]" : "") | |
| + + '/'; | |
| FileReadDescriptor mapData; | |
| if (!readFile(mapData, qsl("map"))) { | |
| @@ -2111,10 +2127,9 @@ | |
| } | |
| LOG(("App Info: reading encrypted map...")); | |
| + QByteArray selfSerialized; | |
| DraftsMap draftsMap, draftCursorsMap; | |
| DraftsNotReadMap draftsNotReadMap; | |
| - StorageMap imagesMap, stickerImagesMap, audiosMap; | |
| - qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0; | |
| quint64 locationsKey = 0, reportSpamStatusesKey = 0, trustedBotsKey = 0; | |
| quint64 recentStickersKeyOld = 0; | |
| quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0; | |
| @@ -2136,6 +2151,9 @@ | |
| draftsNotReadMap.insert(p, true); | |
| } | |
| } break; | |
| + case lskSelfSerialized: { | |
| + map.stream >> selfSerialized; | |
| + } break; | |
| case lskDraftPosition: { | |
| quint32 count = 0; | |
| map.stream >> count; | |
| @@ -2146,30 +2164,8 @@ | |
| draftCursorsMap.insert(p, key); | |
| } | |
| } break; | |
| - case lskImages: { | |
| - quint32 count = 0; | |
| - map.stream >> count; | |
| - for (quint32 i = 0; i < count; ++i) { | |
| - FileKey key; | |
| - quint64 first, second; | |
| - qint32 size; | |
| - map.stream >> key >> first >> second >> size; | |
| - imagesMap.insert(StorageKey(first, second), FileDesc(key, size)); | |
| - storageImagesSize += size; | |
| - } | |
| - } break; | |
| - case lskStickerImages: { | |
| - quint32 count = 0; | |
| - map.stream >> count; | |
| - for (quint32 i = 0; i < count; ++i) { | |
| - FileKey key; | |
| - quint64 first, second; | |
| - qint32 size; | |
| - map.stream >> key >> first >> second >> size; | |
| - stickerImagesMap.insert(StorageKey(first, second), FileDesc(key, size)); | |
| - storageStickersSize += size; | |
| - } | |
| - } break; | |
| + case lskImages: | |
| + case lskStickerImages: | |
| case lskAudios: { | |
| quint32 count = 0; | |
| map.stream >> count; | |
| @@ -2178,8 +2174,7 @@ | |
| quint64 first, second; | |
| qint32 size; | |
| map.stream >> key >> first >> second >> size; | |
| - audiosMap.insert(StorageKey(first, second), FileDesc(key, size)); | |
| - storageAudiosSize += size; | |
| + // Just ignore the key, it will be removed as a leaked one. | |
| } | |
| } break; | |
| case lskLocations: { | |
| @@ -2243,13 +2238,6 @@ | |
| _draftCursorsMap = draftCursorsMap; | |
| _draftsNotReadMap = draftsNotReadMap; | |
| - _imagesMap = imagesMap; | |
| - _storageImagesSize = storageImagesSize; | |
| - _stickerImagesMap = stickerImagesMap; | |
| - _storageStickersSize = storageStickersSize; | |
| - _audiosMap = audiosMap; | |
| - _storageAudiosSize = storageAudiosSize; | |
| - | |
| _locationsKey = locationsKey; | |
| _reportSpamStatusesKey = reportSpamStatusesKey; | |
| _trustedBotsKey = trustedBotsKey; | |
| @@ -2284,7 +2272,10 @@ | |
| _readUserSettings(); | |
| _readMtpData(); | |
| - Messenger::Instance().setAuthSessionFromStorage(std::move(StoredAuthSessionCache)); | |
| + Messenger::Instance().setAuthSessionFromStorage( | |
| + std::move(StoredAuthSessionCache), | |
| + std::move(selfSerialized), | |
| + _oldMapVersion); | |
| LOG(("Map read time: %1").arg(getms() - ms)); | |
| if (_oldSettingsVersion < AppVersion) { | |
| @@ -2326,11 +2317,29 @@ | |
| map.writeData(_passKeyEncrypted); | |
| uint32 mapSize = 0; | |
| + const auto self = [] { | |
| + if (!AuthSession::Exists()) { | |
| + return QByteArray(); | |
| + } | |
| + const auto self = Auth().user(); | |
| + if (self->phone().isEmpty()) { | |
| + return QByteArray(); | |
| + } | |
| + auto result = QByteArray(); | |
| + result.reserve(Serialize::peerSize(self) | |
| + + Serialize::stringSize(self->about())); | |
| + { | |
| + QBuffer buffer(&result); | |
| + buffer.open(QIODevice::WriteOnly); | |
| + QDataStream stream(&buffer); | |
| + Serialize::writePeer(stream, self); | |
| + stream << self->about(); | |
| + } | |
| + return result; | |
| + }(); | |
| + if (!self.isEmpty()) mapSize += sizeof(quint32) + Serialize::bytearraySize(self); | |
| if (!_draftsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsMap.size() * sizeof(quint64) * 2; | |
| if (!_draftCursorsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftCursorsMap.size() * sizeof(quint64) * 2; | |
| - if (!_imagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _imagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32)); | |
| - if (!_stickerImagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _stickerImagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32)); | |
| - if (!_audiosMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _audiosMap.size() * (sizeof(quint64) * 3 + sizeof(qint32)); | |
| if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64); | |
| if (_reportSpamStatusesKey) mapSize += sizeof(quint32) + sizeof(quint64); | |
| if (_trustedBotsKey) mapSize += sizeof(quint32) + sizeof(quint64); | |
| @@ -2346,18 +2355,10 @@ | |
| if (_recentHashtagsAndBotsKey) mapSize += sizeof(quint32) + sizeof(quint64); | |
| if (_exportSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64); | |
| - if (mapSize > 30 * 1024 * 1024) { | |
| - CrashReports::SetAnnotation("MapSize", QString("%1,%2,%3,%4,%5" | |
| - ).arg(_draftsMap.size() | |
| - ).arg(_draftCursorsMap.size() | |
| - ).arg(_imagesMap.size() | |
| - ).arg(_stickerImagesMap.size() | |
| - ).arg(_audiosMap.size() | |
| - )); | |
| - } | |
| - | |
| EncryptedDescriptor mapData(mapSize); | |
| - | |
| + if (!self.isEmpty()) { | |
| + mapData.stream << quint32(lskSelfSerialized) << self; | |
| + } | |
| if (!_draftsMap.isEmpty()) { | |
| mapData.stream << quint32(lskDraft) << quint32(_draftsMap.size()); | |
| for (DraftsMap::const_iterator i = _draftsMap.cbegin(), e = _draftsMap.cend(); i != e; ++i) { | |
| @@ -2370,24 +2371,6 @@ | |
| mapData.stream << quint64(i.value()) << quint64(i.key()); | |
| } | |
| } | |
| - if (!_imagesMap.isEmpty()) { | |
| - mapData.stream << quint32(lskImages) << quint32(_imagesMap.size()); | |
| - for (StorageMap::const_iterator i = _imagesMap.cbegin(), e = _imagesMap.cend(); i != e; ++i) { | |
| - mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second); | |
| - } | |
| - } | |
| - if (!_stickerImagesMap.isEmpty()) { | |
| - mapData.stream << quint32(lskStickerImages) << quint32(_stickerImagesMap.size()); | |
| - for (StorageMap::const_iterator i = _stickerImagesMap.cbegin(), e = _stickerImagesMap.cend(); i != e; ++i) { | |
| - mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second); | |
| - } | |
| - } | |
| - if (!_audiosMap.isEmpty()) { | |
| - mapData.stream << quint32(lskAudios) << quint32(_audiosMap.size()); | |
| - for (StorageMap::const_iterator i = _audiosMap.cbegin(), e = _audiosMap.cend(); i != e; ++i) { | |
| - mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second); | |
| - } | |
| - } | |
| if (_locationsKey) { | |
| mapData.stream << quint32(lskLocations) << quint64(_locationsKey); | |
| } | |
| @@ -2431,10 +2414,6 @@ | |
| map.writeEncrypted(mapData); | |
| _mapChanged = false; | |
| - | |
| - if (mapSize > 30 * 1024 * 1024) { | |
| - CrashReports::ClearAnnotation("MapSize"); | |
| - } | |
| } | |
| } // namespace | |
| @@ -2573,6 +2552,7 @@ | |
| data.stream << quint32(dbiDcOptions) << dcOptionsSerialized; | |
| data.stream << quint32(dbiLoggedPhoneNumber) << cLoggedPhoneNumber(); | |
| data.stream << quint32(dbiTxtDomainString) << Global::TxtDomainString(); | |
| + data.stream << quint32(dbiAnimationsDisabled) << qint32(anim::Disabled() ? 1 : 0); | |
| data.stream << quint32(dbiConnectionType) << qint32(dbictProxiesList); | |
| data.stream << qint32(proxies.size()); | |
| @@ -2683,13 +2663,7 @@ | |
| _fileLocations.clear(); | |
| _fileLocationPairs.clear(); | |
| _fileLocationAliases.clear(); | |
| - _imagesMap.clear(); | |
| _draftsNotReadMap.clear(); | |
| - _stickerImagesMap.clear(); | |
| - _audiosMap.clear(); | |
| - _storageImagesSize = _storageStickersSize = _storageAudiosSize = 0; | |
| - _webFilesMap.clear(); | |
| - _storageWebFilesSize = 0; | |
| _locationsKey = _reportSpamStatusesKey = _trustedBotsKey = 0; | |
| _recentStickersKeyOld = 0; | |
| _installedStickersKey = _featuredStickersKey = _recentStickersKey = _favedStickersKey = _archivedStickersKey = 0; | |
| @@ -2698,6 +2672,8 @@ | |
| Window::Theme::Background()->reset(); | |
| _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = _exportSettingsKey = 0; | |
| _oldMapVersion = _oldSettingsVersion = 0; | |
| + _cacheTotalSizeLimit = Database::Settings().totalSizeLimit; | |
| + _cacheTotalTimeLimit = Database::Settings().totalTimeLimit; | |
| StoredAuthSessionCache.reset(); | |
| _mapChanged = true; | |
| _writeMap(WriteMapWhen::Now); | |
| @@ -2725,12 +2701,62 @@ | |
| Global::RefLocalPasscodeChanged().notify(); | |
| } | |
| +base::flat_set<QString> CollectGoodNames() { | |
| + const auto keys = { | |
| + _locationsKey, | |
| + _reportSpamStatusesKey, | |
| + _userSettingsKey, | |
| + _installedStickersKey, | |
| + _featuredStickersKey, | |
| + _recentStickersKey, | |
| + _favedStickersKey, | |
| + _archivedStickersKey, | |
| + _recentStickersKeyOld, | |
| + _savedGifsKey, | |
| + _backgroundKeyNight, | |
| + _backgroundKeyDay, | |
| + _recentHashtagsAndBotsKey, | |
| + _exportSettingsKey, | |
| + _savedPeersKey, | |
| + _trustedBotsKey | |
| + }; | |
| + auto result = base::flat_set<QString>{ "map0", "map1" }; | |
| + const auto push = [&](FileKey key) { | |
| + if (!key) { | |
| + return; | |
| + } | |
| + auto name = toFilePart(key) + '0'; | |
| + result.emplace(name); | |
| + name[name.size() - 1] = '1'; | |
| + result.emplace(name); | |
| + }; | |
| + for (const auto &value : _draftsMap) { | |
| + push(value); | |
| + } | |
| + for (const auto &value : _draftCursorsMap) { | |
| + push(value); | |
| + } | |
| + for (const auto &value : keys) { | |
| + push(value); | |
| + } | |
| + return result; | |
| +} | |
| + | |
| +void FilterLegacyFiles(FnMut<void(base::flat_set<QString>&&)> then) { | |
| + crl::on_main([then = std::move(then)]() mutable { | |
| + then(CollectGoodNames()); | |
| + }); | |
| +} | |
| + | |
| ReadMapState readMap(const QByteArray &pass) { | |
| ReadMapState result = _readMap(pass); | |
| if (result == ReadMapFailed) { | |
| _mapChanged = true; | |
| _writeMap(WriteMapWhen::Now); | |
| } | |
| + if (result != ReadMapPassNeeded) { | |
| + Storage::ClearLegacyFiles(_userBasePath, FilterLegacyFiles); | |
| + } | |
| return result; | |
| } | |
| @@ -3011,400 +3037,38 @@ | |
| return result; | |
| } | |
| -void writeImage(const StorageKey &location, const ImagePtr &image) { | |
| - if (image->isNull() || !image->loaded()) return; | |
| - if (_imagesMap.constFind(location) != _imagesMap.cend()) return; | |
| - | |
| - image->forget(); | |
| - writeImage(location, StorageImageSaved(image->savedData()), false); | |
| -} | |
| - | |
| -void writeImage(const StorageKey &location, const StorageImageSaved &image, bool overwrite) { | |
| - if (!_working()) return; | |
| - | |
| - qint32 size = _storageImageSize(image.data.size()); | |
| - StorageMap::const_iterator i = _imagesMap.constFind(location); | |
| - if (i == _imagesMap.cend()) { | |
| - i = _imagesMap.insert(location, FileDesc(genKey(FileOption::User), size)); | |
| - _storageImagesSize += size; | |
| - _mapChanged = true; | |
| - _writeMap(); | |
| - } else if (!overwrite) { | |
| - return; | |
| - } | |
| - | |
| - auto legacyTypeField = 0; | |
| - | |
| - EncryptedDescriptor data(sizeof(quint64) * 2 + sizeof(quint32) + sizeof(quint32) + image.data.size()); | |
| - data.stream << quint64(location.first) << quint64(location.second) << quint32(legacyTypeField) << image.data; | |
| - | |
| - FileWriteDescriptor file(i.value().first, FileOption::User); | |
| - file.writeEncrypted(data); | |
| - if (i.value().second != size) { | |
| - _storageImagesSize += size; | |
| - _storageImagesSize -= i.value().second; | |
| - _imagesMap[location].second = size; | |
| - } | |
| -} | |
| - | |
| -class AbstractCachedLoadTask : public Task { | |
| -public: | |
| - | |
| - AbstractCachedLoadTask(const FileKey &key, const StorageKey &location, bool readImageFlag, mtpFileLoader *loader) : | |
| - _key(key), _location(location), _readImageFlag(readImageFlag), _loader(loader), _result(0) { | |
| - } | |
| - void process() { | |
| - FileReadDescriptor image; | |
| - if (!readEncryptedFile(image, _key, FileOption::User)) { | |
| - return; | |
| - } | |
| - | |
| - QByteArray imageData; | |
| - quint64 locFirst, locSecond; | |
| - quint32 legacyTypeField = 0; | |
| - readFromStream(image.stream, locFirst, locSecond, imageData); | |
| - | |
| - // we're saving files now before we have actual location | |
| - //if (locFirst != _location.first || locSecond != _location.second) { | |
| - // return; | |
| - //} | |
| - | |
| - _result = new Result(imageData, _readImageFlag); | |
| - } | |
| - void finish() { | |
| - if (_result) { | |
| - _loader->localLoaded(_result->image, _result->format, _result->pixmap); | |
| - } else { | |
| - clearInMap(); | |
| - _loader->localLoaded(StorageImageSaved()); | |
| - } | |
| - } | |
| - virtual void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, QByteArray &data) = 0; | |
| - virtual void clearInMap() = 0; | |
| - virtual ~AbstractCachedLoadTask() { | |
| - delete base::take(_result); | |
| - } | |
| - | |
| -protected: | |
| - FileKey _key; | |
| - StorageKey _location; | |
| - bool _readImageFlag; | |
| - struct Result { | |
| - Result(const QByteArray &data, bool readImageFlag) : image(data) { | |
| - if (readImageFlag) { | |
| - auto realFormat = QByteArray(); | |
| - pixmap = App::pixmapFromImageInPlace(App::readImage(data, &realFormat, false)); | |
| - if (!pixmap.isNull()) { | |
| - format = realFormat; | |
| - } | |
| - } | |
| - } | |
| - StorageImageSaved image; | |
| - QByteArray format; | |
| - QPixmap pixmap; | |
| +QString cachePath() { | |
| + Expects(!_userDbPath.isEmpty()); | |
| - }; | |
| - mtpFileLoader *_loader; | |
| - Result *_result; | |
| - | |
| -}; | |
| - | |
| -class ImageLoadTask : public AbstractCachedLoadTask { | |
| -public: | |
| - ImageLoadTask(const FileKey &key, const StorageKey &location, mtpFileLoader *loader) : | |
| - AbstractCachedLoadTask(key, location, true, loader) { | |
| - } | |
| - void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, QByteArray &data) override { | |
| - qint32 legacyTypeField = 0; | |
| - stream >> first >> second >> legacyTypeField >> data; | |
| - } | |
| - void clearInMap() override { | |
| - StorageMap::iterator j = _imagesMap.find(_location); | |
| - if (j != _imagesMap.cend() && j->first == _key) { | |
| - clearKey(_key, FileOption::User); | |
| - _storageImagesSize -= j->second; | |
| - _imagesMap.erase(j); | |
| - } | |
| - } | |
| -}; | |
| - | |
| -TaskId startImageLoad(const StorageKey &location, mtpFileLoader *loader) { | |
| - StorageMap::const_iterator j = _imagesMap.constFind(location); | |
| - if (j == _imagesMap.cend() || !_localLoader) { | |
| - return 0; | |
| - } | |
| - return _localLoader->addTask( | |
| - std::make_unique<ImageLoadTask>(j->first, location, loader)); | |
| -} | |
| - | |
| -bool willImageLoad(const StorageKey &location) { | |
| - return _imagesMap.constFind(location) != _imagesMap.cend(); | |
| + return _userDbPath + "cache"; | |
| } | |
| -int32 hasImages() { | |
| - return _imagesMap.size(); | |
| -} | |
| +Storage::EncryptionKey cacheKey() { | |
| + Expects(LocalKey != nullptr); | |
| -qint64 storageImagesSize() { | |
| - return _storageImagesSize; | |
| + return Storage::EncryptionKey(bytes::make_vector(LocalKey->data())); | |
| } | |
| -void writeStickerImage(const StorageKey &location, const QByteArray &sticker, bool overwrite) { | |
| - if (!_working()) return; | |
| - | |
| - qint32 size = _storageStickerSize(sticker.size()); | |
| - StorageMap::const_iterator i = _stickerImagesMap.constFind(location); | |
| - if (i == _stickerImagesMap.cend()) { | |
| - i = _stickerImagesMap.insert(location, FileDesc(genKey(FileOption::User), size)); | |
| - _storageStickersSize += size; | |
| - _mapChanged = true; | |
| - _writeMap(); | |
| - } else if (!overwrite) { | |
| - return; | |
| - } | |
| - EncryptedDescriptor data(sizeof(quint64) * 2 + sizeof(quint32) + sizeof(quint32) + sticker.size()); | |
| - data.stream << quint64(location.first) << quint64(location.second) << sticker; | |
| - FileWriteDescriptor file(i.value().first, FileOption::User); | |
| - file.writeEncrypted(data); | |
| - if (i.value().second != size) { | |
| - _storageStickersSize += size; | |
| - _storageStickersSize -= i.value().second; | |
| - _stickerImagesMap[location].second = size; | |
| - } | |
| -} | |
| - | |
| -class StickerImageLoadTask : public AbstractCachedLoadTask { | |
| -public: | |
| - StickerImageLoadTask(const FileKey &key, const StorageKey &location, mtpFileLoader *loader) : | |
| - AbstractCachedLoadTask(key, location, true, loader) { | |
| - } | |
| - void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, QByteArray &data) { | |
| - stream >> first >> second >> data; | |
| - } | |
| - void clearInMap() { | |
| - auto j = _stickerImagesMap.find(_location); | |
| - if (j != _stickerImagesMap.cend() && j->first == _key) { | |
| - clearKey(j.value().first, FileOption::User); | |
| - _storageStickersSize -= j.value().second; | |
| - _stickerImagesMap.erase(j); | |
| - } | |
| - } | |
| -}; | |
| - | |
| -TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader) { | |
| - auto j = _stickerImagesMap.constFind(location); | |
| - if (j == _stickerImagesMap.cend() || !_localLoader) { | |
| - return 0; | |
| - } | |
| - return _localLoader->addTask( | |
| - std::make_unique<StickerImageLoadTask>(j->first, location, loader)); | |
| -} | |
| - | |
| -bool willStickerImageLoad(const StorageKey &location) { | |
| - return _stickerImagesMap.constFind(location) != _stickerImagesMap.cend(); | |
| -} | |
| - | |
| -bool copyStickerImage(const StorageKey &oldLocation, const StorageKey &newLocation) { | |
| - auto i = _stickerImagesMap.constFind(oldLocation); | |
| - if (i == _stickerImagesMap.cend()) { | |
| - return false; | |
| - } | |
| - _stickerImagesMap.insert(newLocation, i.value()); | |
| - _mapChanged = true; | |
| - _writeMap(); | |
| - return true; | |
| -} | |
| - | |
| -int32 hasStickers() { | |
| - return _stickerImagesMap.size(); | |
| -} | |
| - | |
| -qint64 storageStickersSize() { | |
| - return _storageStickersSize; | |
| -} | |
| - | |
| -void writeAudio(const StorageKey &location, const QByteArray &audio, bool overwrite) { | |
| - if (!_working()) return; | |
| - | |
| - qint32 size = _storageAudioSize(audio.size()); | |
| - StorageMap::const_iterator i = _audiosMap.constFind(location); | |
| - if (i == _audiosMap.cend()) { | |
| - i = _audiosMap.insert(location, FileDesc(genKey(FileOption::User), size)); | |
| - _storageAudiosSize += size; | |
| - _mapChanged = true; | |
| - _writeMap(); | |
| - } else if (!overwrite) { | |
| - return; | |
| - } | |
| - EncryptedDescriptor data(sizeof(quint64) * 2 + sizeof(quint32) + sizeof(quint32) + audio.size()); | |
| - data.stream << quint64(location.first) << quint64(location.second) << audio; | |
| - FileWriteDescriptor file(i.value().first, FileOption::User); | |
| - file.writeEncrypted(data); | |
| - if (i.value().second != size) { | |
| - _storageAudiosSize += size; | |
| - _storageAudiosSize -= i.value().second; | |
| - _audiosMap[location].second = size; | |
| - } | |
| -} | |
| - | |
| -class AudioLoadTask : public AbstractCachedLoadTask { | |
| -public: | |
| - AudioLoadTask(const FileKey &key, const StorageKey &location, mtpFileLoader *loader) : | |
| - AbstractCachedLoadTask(key, location, false, loader) { | |
| - } | |
| - void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, QByteArray &data) { | |
| - stream >> first >> second >> data; | |
| - } | |
| - void clearInMap() { | |
| - auto j = _audiosMap.find(_location); | |
| - if (j != _audiosMap.cend() && j->first == _key) { | |
| - clearKey(j.value().first, FileOption::User); | |
| - _storageAudiosSize -= j.value().second; | |
| - _audiosMap.erase(j); | |
| - } | |
| - } | |
| -}; | |
| - | |
| -TaskId startAudioLoad(const StorageKey &location, mtpFileLoader *loader) { | |
| - auto j = _audiosMap.constFind(location); | |
| - if (j == _audiosMap.cend() || !_localLoader) { | |
| - return 0; | |
| - } | |
| - return _localLoader->addTask( | |
| - std::make_unique<AudioLoadTask>(j->first, location, loader)); | |
| -} | |
| - | |
| -bool copyAudio(const StorageKey &oldLocation, const StorageKey &newLocation) { | |
| - auto i = _audiosMap.constFind(oldLocation); | |
| - if (i == _audiosMap.cend()) { | |
| - return false; | |
| - } | |
| - _audiosMap.insert(newLocation, i.value()); | |
| - _mapChanged = true; | |
| - _writeMap(); | |
| - return true; | |
| -} | |
| - | |
| -bool willAudioLoad(const StorageKey &location) { | |
| - return _audiosMap.constFind(location) != _audiosMap.cend(); | |
| -} | |
| - | |
| -int32 hasAudios() { | |
| - return _audiosMap.size(); | |
| -} | |
| - | |
| -qint64 storageAudiosSize() { | |
| - return _storageAudiosSize; | |
| -} | |
| - | |
| -qint32 _storageWebFileSize(const QString &url, qint32 rawlen) { | |
| - // fulllen + url + len + data | |
| - qint32 result = sizeof(uint32) + Serialize::stringSize(url) + sizeof(quint32) + rawlen; | |
| - if (result & 0x0F) result += 0x10 - (result & 0x0F); | |
| - result += tdfMagicLen + sizeof(qint32) + sizeof(quint32) + 0x10 + 0x10; // magic + version + len of encrypted + part of sha1 + md5 | |
| +Storage::Cache::Database::Settings cacheSettings() { | |
| + auto result = Storage::Cache::Database::Settings(); | |
| + result.clearOnWrongKey = true; | |
| + result.totalSizeLimit = _cacheTotalSizeLimit; | |
| + result.totalTimeLimit = _cacheTotalTimeLimit; | |
| + result.maxDataSize = Storage::kMaxFileInMemory; | |
| return result; | |
| } | |
| -void writeWebFile(const QString &url, const QByteArray &content, bool overwrite) { | |
| - if (!_working()) return; | |
| +void updateCacheSettings(Storage::Cache::Database::SettingsUpdate &update) { | |
| + Expects(update.totalSizeLimit > Database::Settings().maxDataSize); | |
| + Expects(update.totalTimeLimit >= 0); | |
| - qint32 size = _storageWebFileSize(url, content.size()); | |
| - WebFilesMap::const_iterator i = _webFilesMap.constFind(url); | |
| - if (i == _webFilesMap.cend()) { | |
| - i = _webFilesMap.insert(url, FileDesc(genKey(FileOption::User), size)); | |
| - _storageWebFilesSize += size; | |
| - _writeLocations(); | |
| - } else if (!overwrite) { | |
| + if (_cacheTotalSizeLimit == update.totalSizeLimit | |
| + && _cacheTotalTimeLimit == update.totalTimeLimit) { | |
| return; | |
| } | |
| - EncryptedDescriptor data(Serialize::stringSize(url) + sizeof(quint32) + sizeof(quint32) + content.size()); | |
| - data.stream << url << content; | |
| - FileWriteDescriptor file(i.value().first, FileOption::User); | |
| - file.writeEncrypted(data); | |
| - if (i.value().second != size) { | |
| - _storageWebFilesSize += size; | |
| - _storageWebFilesSize -= i.value().second; | |
| - _webFilesMap[url].second = size; | |
| - } | |
| -} | |
| - | |
| -class WebFileLoadTask : public Task { | |
| -public: | |
| - WebFileLoadTask(const FileKey &key, const QString &url, webFileLoader *loader) | |
| - : _key(key) | |
| - , _url(url) | |
| - , _loader(loader) | |
| - , _result(0) { | |
| - } | |
| - void process() { | |
| - FileReadDescriptor image; | |
| - if (!readEncryptedFile(image, _key, FileOption::User)) { | |
| - return; | |
| - } | |
| - | |
| - QByteArray imageData; | |
| - QString url; | |
| - image.stream >> url >> imageData; | |
| - | |
| - _result = new Result(imageData); | |
| - } | |
| - void finish() { | |
| - if (_result) { | |
| - _loader->localLoaded(_result->image, _result->format, _result->pixmap); | |
| - } else { | |
| - WebFilesMap::iterator j = _webFilesMap.find(_url); | |
| - if (j != _webFilesMap.cend() && j->first == _key) { | |
| - clearKey(j.value().first, FileOption::User); | |
| - _storageWebFilesSize -= j.value().second; | |
| - _webFilesMap.erase(j); | |
| - } | |
| - _loader->localLoaded(StorageImageSaved()); | |
| - } | |
| - } | |
| - virtual ~WebFileLoadTask() { | |
| - delete base::take(_result); | |
| - } | |
| - | |
| -protected: | |
| - FileKey _key; | |
| - QString _url; | |
| - struct Result { | |
| - explicit Result(const QByteArray &data) : image(data) { | |
| - QByteArray guessFormat; | |
| - pixmap = App::pixmapFromImageInPlace(App::readImage(data, &guessFormat, false)); | |
| - if (!pixmap.isNull()) { | |
| - format = guessFormat; | |
| - } | |
| - } | |
| - StorageImageSaved image; | |
| - QByteArray format; | |
| - QPixmap pixmap; | |
| - | |
| - }; | |
| - webFileLoader *_loader; | |
| - Result *_result; | |
| - | |
| -}; | |
| - | |
| -TaskId startWebFileLoad(const QString &url, webFileLoader *loader) { | |
| - WebFilesMap::const_iterator j = _webFilesMap.constFind(url); | |
| - if (j == _webFilesMap.cend() || !_localLoader) { | |
| - return 0; | |
| - } | |
| - return _localLoader->addTask( | |
| - std::make_unique<WebFileLoadTask>(j->first, url, loader)); | |
| -} | |
| - | |
| -bool willWebFileLoad(const QString &url) { | |
| - return _webFilesMap.constFind(url) != _webFilesMap.cend(); | |
| -} | |
| - | |
| -int32 hasWebFiles() { | |
| - return _webFilesMap.size(); | |
| -} | |
| - | |
| -qint64 storageWebFilesSize() { | |
| - return _storageWebFilesSize; | |
| + _cacheTotalSizeLimit = update.totalSizeLimit; | |
| + _cacheTotalTimeLimit = update.totalTimeLimit; | |
| + _writeUserSettings(); | |
| } | |
| class CountWaveformTask : public Task { | |
| @@ -3546,7 +3210,7 @@ | |
| void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::Order &order) { | |
| if (!_working()) return; | |
| - auto &sets = Auth().data().stickerSets(); | |
| + const auto &sets = Auth().data().stickerSets(); | |
| if (sets.isEmpty()) { | |
| if (stickersKey) { | |
| clearKey(stickersKey); | |
| @@ -3559,7 +3223,7 @@ | |
| int32 setsCount = 0; | |
| QByteArray hashToWrite; | |
| quint32 size = sizeof(quint32) + Serialize::bytearraySize(hashToWrite); | |
| - for_const (auto &set, sets) { | |
| + for (const auto &set : sets) { | |
| auto result = checkSet(set); | |
| if (result == StickerSetCheckResult::Abort) { | |
| return; | |
| @@ -3569,7 +3233,8 @@ | |
| // id + access + title + shortName + stickersCount + hash + flags + installDate | |
| size += sizeof(quint64) * 2 + Serialize::stringSize(set.title) + Serialize::stringSize(set.shortName) + sizeof(quint32) + sizeof(qint32) * 3; | |
| - for_const (auto &sticker, set.stickers) { | |
| + for (const auto sticker : std::as_const(set.stickers)) { | |
| + sticker->refreshStickerThumbFileReference(); | |
| size += Serialize::Document::sizeInStream(sticker); | |
| } | |
| size += sizeof(qint32); // dates count | |
| @@ -4419,211 +4084,6 @@ | |
| return Window::Theme::CopyColorsToPalette(path, themeContent); | |
| } | |
| -uint32 _peerSize(not_null<PeerData*> peer) { | |
| - uint32 result = sizeof(quint64) | |
| - + sizeof(quint64) | |
| - + Serialize::storageImageLocationSize(peer->userpicLocation()); | |
| - if (peer->isUser()) { | |
| - UserData *user = peer->asUser(); | |
| - | |
| - // first + last + phone + username + access | |
| - result += Serialize::stringSize(user->firstName) + Serialize::stringSize(user->lastName) + Serialize::stringSize(user->phone()) + Serialize::stringSize(user->username) + sizeof(quint64); | |
| - | |
| - // flags | |
| - if (AppVersion >= 9012) { | |
| - result += sizeof(qint32); | |
| - } | |
| - | |
| - // onlineTill + contact + botInfoVersion | |
| - result += sizeof(qint32) + sizeof(qint32) + sizeof(qint32); | |
| - } else if (peer->isChat()) { | |
| - ChatData *chat = peer->asChat(); | |
| - | |
| - // name + count + date + version + admin + old forbidden + left + inviteLink | |
| - result += Serialize::stringSize(chat->name) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint32) + Serialize::stringSize(chat->inviteLink()); | |
| - } else if (peer->isChannel()) { | |
| - ChannelData *channel = peer->asChannel(); | |
| - | |
| - // name + access + date + version + old forbidden + flags + inviteLink | |
| - result += Serialize::stringSize(channel->name) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint32) + Serialize::stringSize(channel->inviteLink()); | |
| - } | |
| - return result; | |
| -} | |
| - | |
| -void _writePeer(QDataStream &stream, PeerData *peer) { | |
| - stream << quint64(peer->id) << quint64(peer->userpicPhotoId()); | |
| - Serialize::writeStorageImageLocation(stream, peer->userpicLocation()); | |
| - if (const auto user = peer->asUser()) { | |
| - stream | |
| - << user->firstName | |
| - << user->lastName | |
| - << user->phone() | |
| - << user->username | |
| - << quint64(user->accessHash()); | |
| - if (AppVersion >= 9012) { | |
| - stream << qint32(user->flags()); | |
| - } | |
| - if (AppVersion >= 9016) { | |
| - const auto botInlinePlaceholder = user->botInfo | |
| - ? user->botInfo->inlinePlaceholder | |
| - : QString(); | |
| - stream << botInlinePlaceholder; | |
| - } | |
| - const auto contactSerialized = [&] { | |
| - switch (user->contactStatus()) { | |
| - case UserData::ContactStatus::Contact: return 1; | |
| - case UserData::ContactStatus::CanAdd: return 0; | |
| - case UserData::ContactStatus::PhoneUnknown: return -1; | |
| - } | |
| - Unexpected("contactStatus in _writePeer()"); | |
| - }(); | |
| - stream | |
| - << qint32(user->onlineTill) | |
| - << qint32(contactSerialized) | |
| - << qint32(user->botInfo ? user->botInfo->version : -1); | |
| - } else if (const auto chat = peer->asChat()) { | |
| - stream | |
| - << chat->name | |
| - << qint32(chat->count) | |
| - << qint32(chat->date) | |
| - << qint32(chat->version) | |
| - << qint32(chat->creator) | |
| - << qint32(0) | |
| - << quint32(chat->flags()) | |
| - << chat->inviteLink(); | |
| - } else if (const auto channel = peer->asChannel()) { | |
| - stream | |
| - << channel->name | |
| - << quint64(channel->access) | |
| - << qint32(channel->date) | |
| - << qint32(channel->version) | |
| - << qint32(0) | |
| - << quint32(channel->flags()) | |
| - << channel->inviteLink(); | |
| - } | |
| -} | |
| - | |
| -PeerData *_readPeer(int streamAppVersion, QDataStream &stream) { | |
| - quint64 peerId = 0, photoId = 0; | |
| - stream >> peerId >> photoId; | |
| - if (!peerId) { | |
| - return nullptr; | |
| - } | |
| - | |
| - auto photoLoc = Serialize::readStorageImageLocation( | |
| - streamAppVersion, | |
| - stream); | |
| - | |
| - PeerData *result = App::peerLoaded(peerId); | |
| - bool wasLoaded = (result != nullptr); | |
| - if (!wasLoaded) { | |
| - result = App::peer(peerId); | |
| - result->loadedStatus = PeerData::FullLoaded; | |
| - } | |
| - if (const auto user = result->asUser()) { | |
| - QString first, last, phone, username, inlinePlaceholder; | |
| - quint64 access; | |
| - qint32 flags = 0, onlineTill, contact, botInfoVersion; | |
| - stream >> first >> last >> phone >> username >> access; | |
| - if (streamAppVersion >= 9012) { | |
| - stream >> flags; | |
| - } | |
| - if (streamAppVersion >= 9016) { | |
| - stream >> inlinePlaceholder; | |
| - } | |
| - stream >> onlineTill >> contact >> botInfoVersion; | |
| - | |
| - const auto showPhone = !isServiceUser(user->id) | |
| - && (user->id != Auth().userPeerId()) | |
| - && (contact <= 0); | |
| - const auto pname = (showPhone && !phone.isEmpty()) | |
| - ? App::formatPhone(phone) | |
| - : QString(); | |
| - | |
| - if (!wasLoaded) { | |
| - user->setPhone(phone); | |
| - user->setName(first, last, pname, username); | |
| - | |
| - user->setFlags(MTPDuser::Flags::from_raw(flags)); | |
| - user->setAccessHash(access); | |
| - user->onlineTill = onlineTill; | |
| - user->setContactStatus((contact > 0) | |
| - ? UserData::ContactStatus::Contact | |
| - : (contact == 0) | |
| - ? UserData::ContactStatus::CanAdd | |
| - : UserData::ContactStatus::PhoneUnknown); | |
| - user->setBotInfoVersion(botInfoVersion); | |
| - if (!inlinePlaceholder.isEmpty() && user->botInfo) { | |
| - user->botInfo->inlinePlaceholder = inlinePlaceholder; | |
| - } | |
| - | |
| - if (user->id == Auth().userPeerId()) { | |
| - user->input = MTP_inputPeerSelf(); | |
| - user->inputUser = MTP_inputUserSelf(); | |
| - } else { | |
| - user->input = MTP_inputPeerUser(MTP_int(peerToUser(user->id)), MTP_long(user->accessHash())); | |
| - user->inputUser = MTP_inputUser(MTP_int(peerToUser(user->id)), MTP_long(user->accessHash())); | |
| - } | |
| - } | |
| - } else if (const auto chat = result->asChat()) { | |
| - QString name, inviteLink; | |
| - qint32 count, date, version, creator, oldForbidden; | |
| - quint32 flagsData, flags; | |
| - stream >> name >> count >> date >> version >> creator >> oldForbidden >> flagsData >> inviteLink; | |
| - | |
| - if (streamAppVersion >= 9012) { | |
| - flags = flagsData; | |
| - } else { | |
| - // flagsData was haveLeft | |
| - flags = (flagsData == 1) | |
| - ? MTPDchat::Flags(MTPDchat::Flag::f_left) | |
| - : MTPDchat::Flags(0); | |
| - } | |
| - if (oldForbidden) { | |
| - flags |= quint32(MTPDchat_ClientFlag::f_forbidden); | |
| - } | |
| - if (!wasLoaded) { | |
| - chat->setName(name); | |
| - chat->count = count; | |
| - chat->date = date; | |
| - chat->version = version; | |
| - chat->creator = creator; | |
| - chat->setFlags(MTPDchat::Flags::from_raw(flags)); | |
| - chat->setInviteLink(inviteLink); | |
| - | |
| - chat->input = MTP_inputPeerChat(MTP_int(peerToChat(chat->id))); | |
| - chat->inputChat = MTP_int(peerToChat(chat->id)); | |
| - } | |
| - } else if (const auto channel = result->asChannel()) { | |
| - QString name, inviteLink; | |
| - quint64 access; | |
| - qint32 date, version, oldForbidden; | |
| - quint32 flags; | |
| - stream >> name >> access >> date >> version >> oldForbidden >> flags >> inviteLink; | |
| - if (oldForbidden) { | |
| - flags |= quint32(MTPDchannel_ClientFlag::f_forbidden); | |
| - } | |
| - if (!wasLoaded) { | |
| - channel->setName(name, QString()); | |
| - channel->access = access; | |
| - channel->date = date; | |
| - channel->version = version; | |
| - channel->setFlags(MTPDchannel::Flags::from_raw(flags)); | |
| - channel->setInviteLink(inviteLink); | |
| - | |
| - channel->input = MTP_inputPeerChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access)); | |
| - channel->inputChannel = MTP_inputChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access)); | |
| - } | |
| - } | |
| - if (!wasLoaded) { | |
| - result->setUserpic( | |
| - photoId, | |
| - photoLoc, | |
| - photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc)); | |
| - } | |
| - return result; | |
| -} | |
| - | |
| void writeRecentHashtagsAndBots() { | |
| if (!_working()) return; | |
| @@ -4657,7 +4117,7 @@ | |
| } | |
| } | |
| for (auto i = bots.cbegin(), e = bots.cend(); i != e; ++i) { | |
| - size += _peerSize(*i); | |
| + size += Serialize::peerSize(*i); | |
| } | |
| EncryptedDescriptor data(size); | |
| @@ -4670,7 +4130,7 @@ | |
| } | |
| data.stream << quint32(botsCnt); | |
| for (auto i = bots.cbegin(), e = bots.cend(); i != e; ++i) { | |
| - _writePeer(data.stream, *i); | |
| + Serialize::writePeer(data.stream, *i); | |
| } | |
| FileWriteDescriptor file(_recentHashtagsAndBotsKey); | |
| file.writeEncrypted(data); | |
| @@ -4721,7 +4181,7 @@ | |
| if (botsCount) { | |
| bots.reserve(botsCount); | |
| for (auto i = 0; i < botsCount; ++i) { | |
| - const auto peer = _readPeer( | |
| + const auto peer = Serialize::readPeer( | |
| hashtags.version, | |
| hashtags.stream); | |
| if (!peer) { | |
| @@ -4773,7 +4233,7 @@ | |
| } | |
| } | |
| -base::optional<RecentHashtagPack> saveRecentHashtags( | |
| +std::optional<RecentHashtagPack> saveRecentHashtags( | |
| Fn<RecentHashtagPack()> getPack, | |
| const QString &text) { | |
| auto found = false; | |
| @@ -4803,7 +4263,7 @@ | |
| found = true; | |
| incrementRecentHashtag(recent, tag); | |
| } | |
| - return found ? base::make_optional(recent) : base::none; | |
| + return found ? base::make_optional(recent) : std::nullopt; | |
| } | |
| void saveRecentSentHashtags(const QString &text) { | |
| @@ -4972,13 +4432,13 @@ | |
| } | |
| quint32 size = sizeof(quint32); | |
| for (SavedPeers::const_iterator i = saved.cbegin(); i != saved.cend(); ++i) { | |
| - size += _peerSize(i.key()) + Serialize::dateTimeSize(); | |
| + size += Serialize::peerSize(i.key()) + Serialize::dateTimeSize(); | |
| } | |
| EncryptedDescriptor data(size); | |
| data.stream << quint32(saved.size()); | |
| for (SavedPeers::const_iterator i = saved.cbegin(); i != saved.cend(); ++i) { | |
| - _writePeer(data.stream, i.key()); | |
| + Serialize::writePeer(data.stream, i.key()); | |
| data.stream << i.value(); | |
| } | |
| @@ -5011,7 +4471,7 @@ | |
| QList<PeerData*> peers; | |
| peers.reserve(count); | |
| for (uint32 i = 0; i < count; ++i) { | |
| - const auto peer = _readPeer(saved.version, saved.stream); | |
| + const auto peer = Serialize::readPeer(saved.version, saved.stream); | |
| if (!peer) break; | |
| QDateTime t; | |
| @@ -5055,6 +4515,25 @@ | |
| _writeReportSpamStatuses(); | |
| } | |
| +void writeSelf() { | |
| + _mapChanged = true; | |
| + _writeMap(); | |
| +} | |
| + | |
| +void readSelf(const QByteArray &serialized, int32 streamVersion) { | |
| + QDataStream stream(serialized); | |
| + const auto self = Serialize::readPeer(streamVersion, stream); | |
| + if (!self || !self->isSelf() || self != Auth().user()) { | |
| + return; | |
| + } | |
| + | |
| + QString about; | |
| + stream >> about; | |
| + if (_checkStreamStatus(stream)) { | |
| + self->asUser()->setAbout(about); | |
| + } | |
| +} | |
| + | |
| void writeTrustedBots() { | |
| if (!_working()) return; | |
| @@ -5136,8 +4615,6 @@ | |
| struct ClearManagerData { | |
| QThread *thread; | |
| - StorageMap images, stickers, audios; | |
| - WebFilesMap webFiles; | |
| QMutex mutex; | |
| QList<int> tasks; | |
| bool working; | |
| @@ -5155,21 +4632,6 @@ | |
| if (!data->tasks.isEmpty() && (data->tasks.at(0) == ClearManagerAll)) return true; | |
| if (task == ClearManagerAll) { | |
| data->tasks.clear(); | |
| - if (!_imagesMap.isEmpty()) { | |
| - _imagesMap.clear(); | |
| - _storageImagesSize = 0; | |
| - _mapChanged = true; | |
| - } | |
| - if (!_stickerImagesMap.isEmpty()) { | |
| - _stickerImagesMap.clear(); | |
| - _storageStickersSize = 0; | |
| - _mapChanged = true; | |
| - } | |
| - if (!_audiosMap.isEmpty()) { | |
| - _audiosMap.clear(); | |
| - _storageAudiosSize = 0; | |
| - _mapChanged = true; | |
| - } | |
| if (!_draftsMap.isEmpty()) { | |
| _draftsMap.clear(); | |
| _mapChanged = true; | |
| @@ -5208,73 +4670,6 @@ | |
| } | |
| _writeMap(); | |
| } else { | |
| - if (task & ClearManagerStorage) { | |
| - if (data->images.isEmpty()) { | |
| - data->images = _imagesMap; | |
| - } else { | |
| - for (StorageMap::const_iterator i = _imagesMap.cbegin(), e = _imagesMap.cend(); i != e; ++i) { | |
| - StorageKey k = i.key(); | |
| - while (data->images.constFind(k) != data->images.cend()) { | |
| - ++k.second; | |
| - } | |
| - data->images.insert(k, i.value()); | |
| - } | |
| - } | |
| - if (!_imagesMap.isEmpty()) { | |
| - _imagesMap.clear(); | |
| - _storageImagesSize = 0; | |
| - _mapChanged = true; | |
| - } | |
| - if (data->stickers.isEmpty()) { | |
| - data->stickers = _stickerImagesMap; | |
| - } else { | |
| - for (StorageMap::const_iterator i = _stickerImagesMap.cbegin(), e = _stickerImagesMap.cend(); i != e; ++i) { | |
| - StorageKey k = i.key(); | |
| - while (data->stickers.constFind(k) != data->stickers.cend()) { | |
| - ++k.second; | |
| - } | |
| - data->stickers.insert(k, i.value()); | |
| - } | |
| - } | |
| - if (!_stickerImagesMap.isEmpty()) { | |
| - _stickerImagesMap.clear(); | |
| - _storageStickersSize = 0; | |
| - _mapChanged = true; | |
| - } | |
| - if (data->webFiles.isEmpty()) { | |
| - data->webFiles = _webFilesMap; | |
| - } else { | |
| - for (WebFilesMap::const_iterator i = _webFilesMap.cbegin(), e = _webFilesMap.cend(); i != e; ++i) { | |
| - QString k = i.key(); | |
| - while (data->webFiles.constFind(k) != data->webFiles.cend()) { | |
| - k += '#'; | |
| - } | |
| - data->webFiles.insert(k, i.value()); | |
| - } | |
| - } | |
| - if (!_webFilesMap.isEmpty()) { | |
| - _webFilesMap.clear(); | |
| - _storageWebFilesSize = 0; | |
| - _writeLocations(); | |
| - } | |
| - if (data->audios.isEmpty()) { | |
| - data->audios = _audiosMap; | |
| - } else { | |
| - for (StorageMap::const_iterator i = _audiosMap.cbegin(), e = _audiosMap.cend(); i != e; ++i) { | |
| - StorageKey k = i.key(); | |
| - while (data->audios.constFind(k) != data->audios.cend()) { | |
| - ++k.second; | |
| - } | |
| - data->audios.insert(k, i.value()); | |
| - } | |
| - } | |
| - if (!_audiosMap.isEmpty()) { | |
| - _audiosMap.clear(); | |
| - _storageAudiosSize = 0; | |
| - _mapChanged = true; | |
| - } | |
| - _writeMap(); | |
| - } | |
| for (int32 i = 0, l = data->tasks.size(); i < l; ++i) { | |
| if (data->tasks.at(i) == task) return true; | |
| } | |
| @@ -5319,8 +4714,6 @@ | |
| while (true) { | |
| int task = 0; | |
| bool result = false; | |
| - StorageMap images, stickers, audios; | |
| - WebFilesMap webFiles; | |
| { | |
| QMutexLocker lock(&data->mutex); | |
| if (data->tasks.isEmpty()) { | |
| @@ -5328,10 +4721,6 @@ | |
| break; | |
| } | |
| task = data->tasks.at(0); | |
| - images = data->images; | |
| - stickers = data->stickers; | |
| - audios = data->audios; | |
| - webFiles = data->webFiles; | |
| } | |
| switch (task) { | |
| case ClearManagerAll: { | |
| @@ -5354,18 +4743,6 @@ | |
| result = QDir(cTempDir()).removeRecursively(); | |
| break; | |
| case ClearManagerStorage: | |
| - for (StorageMap::const_iterator i = images.cbegin(), e = images.cend(); i != e; ++i) { | |
| - clearKey(i.value().first, FileOption::User); | |
| - } | |
| - for (StorageMap::const_iterator i = stickers.cbegin(), e = stickers.cend(); i != e; ++i) { | |
| - clearKey(i.value().first, FileOption::User); | |
| - } | |
| - for (StorageMap::const_iterator i = audios.cbegin(), e = audios.cend(); i != e; ++i) { | |
| - clearKey(i.value().first, FileOption::User); | |
| - } | |
| - for (WebFilesMap::const_iterator i = webFiles.cbegin(), e = webFiles.cend(); i != e; ++i) { | |
| - clearKey(i.value().first, FileOption::User); | |
| - } | |
| result = true; | |
| break; | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localstorage.h work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localstorage.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/localstorage.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/localstorage.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,10 +7,15 @@ | |
| */ | |
| #pragma once | |
| -#include "core/basic_types.h" | |
| #include "storage/file_download.h" | |
| +#include "storage/cache/storage_cache_database.h" | |
| +#include "storage/localimageloader.h" | |
| #include "auth_session.h" | |
| +namespace Storage { | |
| +class EncryptionKey; | |
| +} // namespace Storage | |
| + | |
| namespace Window { | |
| namespace Theme { | |
| struct Saved; | |
| @@ -99,32 +104,10 @@ | |
| void writeFileLocation(MediaKey location, const FileLocation &local); | |
| FileLocation readFileLocation(MediaKey location, bool check = true); | |
| -void writeImage(const StorageKey &location, const ImagePtr &img); | |
| -void writeImage(const StorageKey &location, const StorageImageSaved &jpeg, bool overwrite = true); | |
| -TaskId startImageLoad(const StorageKey &location, mtpFileLoader *loader); | |
| -bool willImageLoad(const StorageKey &location); | |
| -int32 hasImages(); | |
| -qint64 storageImagesSize(); | |
| - | |
| -void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true); | |
| -TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader); | |
| -bool willStickerImageLoad(const StorageKey &location); | |
| -bool copyStickerImage(const StorageKey &oldLocation, const StorageKey &newLocation); | |
| -int32 hasStickers(); | |
| -qint64 storageStickersSize(); | |
| - | |
| -void writeAudio(const StorageKey &location, const QByteArray &data, bool overwrite = true); | |
| -TaskId startAudioLoad(const StorageKey &location, mtpFileLoader *loader); | |
| -bool willAudioLoad(const StorageKey &location); | |
| -bool copyAudio(const StorageKey &oldLocation, const StorageKey &newLocation); | |
| -int32 hasAudios(); | |
| -qint64 storageAudiosSize(); | |
| - | |
| -void writeWebFile(const QString &url, const QByteArray &data, bool overwrite = true); | |
| -TaskId startWebFileLoad(const QString &url, webFileLoader *loader); | |
| -bool willWebFileLoad(const QString &url); | |
| -int32 hasWebFiles(); | |
| -qint64 storageWebFilesSize(); | |
| +QString cachePath(); | |
| +Storage::EncryptionKey cacheKey(); | |
| +Storage::Cache::Database::Settings cacheSettings(); | |
| +void updateCacheSettings(Storage::Cache::Database::SettingsUpdate &update); | |
| void countVoiceWaveform(DocumentData *document); | |
| @@ -173,6 +156,9 @@ | |
| void writeReportSpamStatuses(); | |
| +void writeSelf(); | |
| +void readSelf(const QByteArray &serialized, int32 streamVersion); | |
| + | |
| void makeBotTrusted(UserData *bot); | |
| bool isBotTrusted(UserData *bot); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/serialize_common.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/serialize_common.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/serialize_common.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/serialize_common.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,6 +7,8 @@ | |
| */ | |
| #include "storage/serialize_common.h" | |
| +#include "auth_session.h" | |
| + | |
| namespace Serialize { | |
| void writeStorageImageLocation( | |
| @@ -53,4 +55,209 @@ | |
| + bytearraySize(location.fileReference()); | |
| } | |
| +uint32 peerSize(not_null<PeerData*> peer) { | |
| + uint32 result = sizeof(quint64) | |
| + + sizeof(quint64) | |
| + + storageImageLocationSize(peer->userpicLocation()); | |
| + if (peer->isUser()) { | |
| + UserData *user = peer->asUser(); | |
| + | |
| + // first + last + phone + username + access | |
| + result += stringSize(user->firstName) + stringSize(user->lastName) + stringSize(user->phone()) + stringSize(user->username) + sizeof(quint64); | |
| + | |
| + // flags | |
| + if (AppVersion >= 9012) { | |
| + result += sizeof(qint32); | |
| + } | |
| + | |
| + // onlineTill + contact + botInfoVersion | |
| + result += sizeof(qint32) + sizeof(qint32) + sizeof(qint32); | |
| + } else if (peer->isChat()) { | |
| + ChatData *chat = peer->asChat(); | |
| + | |
| + // name + count + date + version + admin + old forbidden + left + inviteLink | |
| + result += stringSize(chat->name) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint32) + stringSize(chat->inviteLink()); | |
| + } else if (peer->isChannel()) { | |
| + ChannelData *channel = peer->asChannel(); | |
| + | |
| + // name + access + date + version + old forbidden + flags + inviteLink | |
| + result += stringSize(channel->name) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint32) + stringSize(channel->inviteLink()); | |
| + } | |
| + return result; | |
| +} | |
| + | |
| +void writePeer(QDataStream &stream, PeerData *peer) { | |
| + stream << quint64(peer->id) << quint64(peer->userpicPhotoId()); | |
| + writeStorageImageLocation(stream, peer->userpicLocation()); | |
| + if (const auto user = peer->asUser()) { | |
| + stream | |
| + << user->firstName | |
| + << user->lastName | |
| + << user->phone() | |
| + << user->username | |
| + << quint64(user->accessHash()); | |
| + if (AppVersion >= 9012) { | |
| + stream << qint32(user->flags()); | |
| + } | |
| + if (AppVersion >= 9016) { | |
| + const auto botInlinePlaceholder = user->botInfo | |
| + ? user->botInfo->inlinePlaceholder | |
| + : QString(); | |
| + stream << botInlinePlaceholder; | |
| + } | |
| + const auto contactSerialized = [&] { | |
| + switch (user->contactStatus()) { | |
| + case UserData::ContactStatus::Contact: return 1; | |
| + case UserData::ContactStatus::CanAdd: return 0; | |
| + case UserData::ContactStatus::PhoneUnknown: return -1; | |
| + } | |
| + Unexpected("contactStatus in _writePeer()"); | |
| + }(); | |
| + stream | |
| + << qint32(user->onlineTill) | |
| + << qint32(contactSerialized) | |
| + << qint32(user->botInfo ? user->botInfo->version : -1); | |
| + } else if (const auto chat = peer->asChat()) { | |
| + stream | |
| + << chat->name | |
| + << qint32(chat->count) | |
| + << qint32(chat->date) | |
| + << qint32(chat->version) | |
| + << qint32(chat->creator) | |
| + << qint32(0) | |
| + << quint32(chat->flags()) | |
| + << chat->inviteLink(); | |
| + } else if (const auto channel = peer->asChannel()) { | |
| + stream | |
| + << channel->name | |
| + << quint64(channel->access) | |
| + << qint32(channel->date) | |
| + << qint32(channel->version) | |
| + << qint32(0) | |
| + << quint32(channel->flags()) | |
| + << channel->inviteLink(); | |
| + } | |
| +} | |
| + | |
| +PeerData *readPeer(int streamAppVersion, QDataStream &stream) { | |
| + quint64 peerId = 0, photoId = 0; | |
| + stream >> peerId >> photoId; | |
| + if (!peerId) { | |
| + return nullptr; | |
| + } | |
| + | |
| + auto photoLoc = readStorageImageLocation( | |
| + streamAppVersion, | |
| + stream); | |
| + | |
| + PeerData *result = App::peerLoaded(peerId); | |
| + bool wasLoaded = (result != nullptr); | |
| + if (!wasLoaded) { | |
| + result = App::peer(peerId); | |
| + result->loadedStatus = PeerData::FullLoaded; | |
| + } | |
| + if (const auto user = result->asUser()) { | |
| + QString first, last, phone, username, inlinePlaceholder; | |
| + quint64 access; | |
| + qint32 flags = 0, onlineTill, contact, botInfoVersion; | |
| + stream >> first >> last >> phone >> username >> access; | |
| + if (streamAppVersion >= 9012) { | |
| + stream >> flags; | |
| + } | |
| + if (streamAppVersion >= 9016) { | |
| + stream >> inlinePlaceholder; | |
| + } | |
| + stream >> onlineTill >> contact >> botInfoVersion; | |
| + | |
| + const auto showPhone = !isServiceUser(user->id) | |
| + && (user->id != Auth().userPeerId()) | |
| + && (contact <= 0); | |
| + const auto pname = (showPhone && !phone.isEmpty()) | |
| + ? App::formatPhone(phone) | |
| + : QString(); | |
| + | |
| + if (!wasLoaded) { | |
| + user->setPhone(phone); | |
| + user->setName(first, last, pname, username); | |
| + | |
| + user->setFlags(MTPDuser::Flags::from_raw(flags)); | |
| + user->setAccessHash(access); | |
| + user->onlineTill = onlineTill; | |
| + user->setContactStatus((contact > 0) | |
| + ? UserData::ContactStatus::Contact | |
| + : (contact == 0) | |
| + ? UserData::ContactStatus::CanAdd | |
| + : UserData::ContactStatus::PhoneUnknown); | |
| + user->setBotInfoVersion(botInfoVersion); | |
| + if (!inlinePlaceholder.isEmpty() && user->botInfo) { | |
| + user->botInfo->inlinePlaceholder = inlinePlaceholder; | |
| + } | |
| + | |
| + if (user->id == Auth().userPeerId()) { | |
| + user->input = MTP_inputPeerSelf(); | |
| + user->inputUser = MTP_inputUserSelf(); | |
| + } else { | |
| + user->input = MTP_inputPeerUser(MTP_int(peerToUser(user->id)), MTP_long(user->accessHash())); | |
| + user->inputUser = MTP_inputUser(MTP_int(peerToUser(user->id)), MTP_long(user->accessHash())); | |
| + } | |
| + } | |
| + } else if (const auto chat = result->asChat()) { | |
| + QString name, inviteLink; | |
| + qint32 count, date, version, creator, oldForbidden; | |
| + quint32 flagsData, flags; | |
| + stream >> name >> count >> date >> version >> creator >> oldForbidden >> flagsData >> inviteLink; | |
| + | |
| + if (streamAppVersion >= 9012) { | |
| + flags = flagsData; | |
| + } else { | |
| + // flagsData was haveLeft | |
| + flags = (flagsData == 1) | |
| + ? MTPDchat::Flags(MTPDchat::Flag::f_left) | |
| + : MTPDchat::Flags(0); | |
| + } | |
| + if (oldForbidden) { | |
| + flags |= quint32(MTPDchat_ClientFlag::f_forbidden); | |
| + } | |
| + if (!wasLoaded) { | |
| + chat->setName(name); | |
| + chat->count = count; | |
| + chat->date = date; | |
| + chat->version = version; | |
| + chat->creator = creator; | |
| + chat->setFlags(MTPDchat::Flags::from_raw(flags)); | |
| + chat->setInviteLink(inviteLink); | |
| + | |
| + chat->input = MTP_inputPeerChat(MTP_int(peerToChat(chat->id))); | |
| + chat->inputChat = MTP_int(peerToChat(chat->id)); | |
| + } | |
| + } else if (const auto channel = result->asChannel()) { | |
| + QString name, inviteLink; | |
| + quint64 access; | |
| + qint32 date, version, oldForbidden; | |
| + quint32 flags; | |
| + stream >> name >> access >> date >> version >> oldForbidden >> flags >> inviteLink; | |
| + if (oldForbidden) { | |
| + flags |= quint32(MTPDchannel_ClientFlag::f_forbidden); | |
| + } | |
| + if (!wasLoaded) { | |
| + channel->setName(name, QString()); | |
| + channel->access = access; | |
| + channel->date = date; | |
| + channel->version = version; | |
| + channel->setFlags(MTPDchannel::Flags::from_raw(flags)); | |
| + channel->setInviteLink(inviteLink); | |
| + | |
| + channel->input = MTP_inputPeerChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access)); | |
| + channel->inputChannel = MTP_inputChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access)); | |
| + } | |
| + } | |
| + if (!wasLoaded) { | |
| + result->setUserpic( | |
| + photoId, | |
| + photoLoc, | |
| + photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc)); | |
| + } | |
| + return result; | |
| +} | |
| + | |
| } // namespace Serialize | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/serialize_common.h work/tdesktop-1.4.0/Telegram/SourceFiles/storage/serialize_common.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/serialize_common.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/serialize_common.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -107,4 +107,8 @@ | |
| return result; | |
| } | |
| +uint32 peerSize(not_null<PeerData*> peer); | |
| +void writePeer(QDataStream &stream, PeerData *peer); | |
| +PeerData *readPeer(int streamAppVersion, QDataStream &stream); | |
| + | |
| } // namespace Serialize | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_clear_legacy_posix.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_clear_legacy_win.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_clear_legacy.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_clear_legacy.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_databases.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_databases.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_encrypted_file_tests.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_encrypted_file.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_encrypted_file.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_encryption.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_encryption.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_feed_messages.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_feed_messages.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_feed_messages.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_feed_messages.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -36,7 +36,7 @@ | |
| feedIt->second.addSlice( | |
| std::move(query.messageIds), | |
| query.noSkipRange, | |
| - base::none); | |
| + std::nullopt); | |
| } | |
| void FeedMessages::remove(FeedMessagesRemoveOne &&query) { | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_file_lock_posix.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_file_lock_win.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_file_lock.h | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_pch.cpp | |
| Only in work/tdesktop-1.4.0/Telegram/SourceFiles/storage: storage_pch.h | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_shared_media.h work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_shared_media.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_shared_media.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_shared_media.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -73,7 +73,7 @@ | |
| SharedMediaType type, | |
| std::vector<MsgId> &&messageIds, | |
| MsgRange noSkipRange, | |
| - base::optional<int> count = base::none) | |
| + std::optional<int> count = std::nullopt) | |
| : peerId(peerId) | |
| , messageIds(std::move(messageIds)) | |
| , noSkipRange(noSkipRange) | |
| @@ -85,7 +85,7 @@ | |
| std::vector<MsgId> messageIds; | |
| MsgRange noSkipRange; | |
| SharedMediaType type = SharedMediaType::kCount; | |
| - base::optional<int> count; | |
| + std::optional<int> count; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_sparse_ids_list.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -93,7 +93,7 @@ | |
| void SparseIdsList::addRange( | |
| const Range &messages, | |
| MsgRange noSkipRange, | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| bool incrementCount) { | |
| Expects(!count || !incrementCount); | |
| @@ -119,20 +119,20 @@ | |
| void SparseIdsList::addNew(MsgId messageId) { | |
| auto range = { messageId }; | |
| - addRange(range, { messageId, ServerMaxMsgId }, base::none, true); | |
| + addRange(range, { messageId, ServerMaxMsgId }, std::nullopt, true); | |
| } | |
| void SparseIdsList::addExisting( | |
| MsgId messageId, | |
| MsgRange noSkipRange) { | |
| auto range = { messageId }; | |
| - addRange(range, noSkipRange, base::none); | |
| + addRange(range, noSkipRange, std::nullopt); | |
| } | |
| void SparseIdsList::addSlice( | |
| std::vector<MsgId> &&messageIds, | |
| MsgRange noSkipRange, | |
| - base::optional<int> count) { | |
| + std::optional<int> count) { | |
| addRange(messageIds, noSkipRange, count); | |
| } | |
| @@ -169,7 +169,7 @@ | |
| }); | |
| } | |
| } | |
| - _count = base::none; | |
| + _count = std::nullopt; | |
| } | |
| rpl::producer<SparseIdsListResult> SparseIdsList::query( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_sparse_ids_list.h work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_sparse_ids_list.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_sparse_ids_list.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_sparse_ids_list.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -26,16 +26,16 @@ | |
| }; | |
| struct SparseIdsListResult { | |
| - base::optional<int> count; | |
| - base::optional<int> skippedBefore; | |
| - base::optional<int> skippedAfter; | |
| + std::optional<int> count; | |
| + std::optional<int> skippedBefore; | |
| + std::optional<int> skippedAfter; | |
| base::flat_set<MsgId> messageIds; | |
| }; | |
| struct SparseIdsSliceUpdate { | |
| const base::flat_set<MsgId> *messages = nullptr; | |
| MsgRange range; | |
| - base::optional<int> count; | |
| + std::optional<int> count; | |
| }; | |
| class SparseIdsList { | |
| @@ -45,7 +45,7 @@ | |
| void addSlice( | |
| std::vector<MsgId> &&messageIds, | |
| MsgRange noSkipRange, | |
| - base::optional<int> count); | |
| + std::optional<int> count); | |
| void removeOne(MsgId messageId); | |
| void removeAll(); | |
| void invalidateBottom(); | |
| @@ -84,14 +84,14 @@ | |
| void addRange( | |
| const Range &messages, | |
| MsgRange noSkipRange, | |
| - base::optional<int> count, | |
| + std::optional<int> count, | |
| bool incrementCount = false); | |
| SparseIdsListResult queryFromSlice( | |
| const SparseIdsListQuery &query, | |
| const Slice &slice) const; | |
| - base::optional<int> _count; | |
| + std::optional<int> _count; | |
| base::flat_set<Slice> _slices; | |
| rpl::event_stream<SparseIdsSliceUpdate> _sliceUpdated; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_user_photos.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_user_photos.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_user_photos.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_user_photos.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -38,7 +38,7 @@ | |
| void UserPhotos::List::removeOne(PhotoId photoId) { | |
| auto position = ranges::find(_photoIds, photoId); | |
| if (position == _photoIds.end()) { | |
| - _count = base::none; | |
| + _count = std::nullopt; | |
| } else { | |
| if (_count) { | |
| --*_count; | |
| @@ -51,7 +51,7 @@ | |
| void UserPhotos::List::removeAfter(PhotoId photoId) { | |
| auto position = ranges::find(_photoIds, photoId); | |
| if (position == _photoIds.end()) { | |
| - _count = base::none; | |
| + _count = std::nullopt; | |
| _photoIds.clear(); | |
| } else { | |
| if (_count) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_user_photos.h work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_user_photos.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/storage/storage_user_photos.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/storage/storage_user_photos.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -102,8 +102,8 @@ | |
| }; | |
| struct UserPhotosResult { | |
| - base::optional<int> count; | |
| - base::optional<int> skippedBefore; | |
| + std::optional<int> count; | |
| + std::optional<int> skippedBefore; | |
| int skippedAfter = 0; | |
| std::deque<PhotoId> photoIds; | |
| }; | |
| @@ -112,7 +112,7 @@ | |
| UserPhotosSliceUpdate( | |
| UserId userId, | |
| const std::deque<PhotoId> *photoIds, | |
| - base::optional<int> count) | |
| + std::optional<int> count) | |
| : userId(userId) | |
| , photoIds(photoIds) | |
| , count(count) { | |
| @@ -120,7 +120,7 @@ | |
| UserId userId = 0; | |
| const std::deque<PhotoId> *photoIds = nullptr; | |
| - base::optional<int> count; | |
| + std::optional<int> count; | |
| }; | |
| class UserPhotos { | |
| @@ -146,14 +146,14 @@ | |
| struct SliceUpdate { | |
| const std::deque<PhotoId> *photoIds = nullptr; | |
| - base::optional<int> count; | |
| + std::optional<int> count; | |
| }; | |
| rpl::producer<SliceUpdate> sliceUpdated() const; | |
| private: | |
| void sendUpdate(); | |
| - base::optional<int> _count; | |
| + std::optional<int> _count; | |
| std::deque<PhotoId> _photoIds; | |
| rpl::event_stream<SliceUpdate> _sliceUpdated; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/abstract_button.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/abstract_button.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/abstract_button.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/abstract_button.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -78,7 +78,7 @@ | |
| emit clicked(); | |
| } | |
| if (weak) { | |
| - _clicks.fire({}); | |
| + _clicks.fire(e->button()); | |
| } | |
| } else { | |
| setOver(false, StateChangeSource::ByHover); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/abstract_button.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/abstract_button.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/abstract_button.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/abstract_button.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -43,7 +43,7 @@ | |
| _clickedCallback = std::move(callback); | |
| } | |
| - rpl::producer<> clicks() const { | |
| + rpl::producer<Qt::MouseButton> clicks() const { | |
| return _clicks.events(); | |
| } | |
| template <typename Handler> | |
| @@ -100,7 +100,7 @@ | |
| Fn<void()> _clickedCallback; | |
| - rpl::event_stream<> _clicks; | |
| + rpl::event_stream<Qt::MouseButton> _clicks; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/animation.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/animation.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/animation.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/animation.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -93,8 +93,10 @@ | |
| Media::Clip::Finish(); | |
| } | |
| -void registerClipManager(Media::Clip::Manager *manager) { | |
| - manager->connect(manager, SIGNAL(callback(Media::Clip::Reader*,qint32,qint32)), _manager, SLOT(clipCallback(Media::Clip::Reader*,qint32,qint32))); | |
| +void registerClipManager(not_null<Media::Clip::Manager*> manager) { | |
| + Expects(_manager != nullptr); | |
| + | |
| + _manager->registerClip(manager); | |
| } | |
| bool Disabled() { | |
| @@ -104,7 +106,35 @@ | |
| void SetDisabled(bool disabled) { | |
| AnimationsDisabled = disabled; | |
| if (disabled && _manager) { | |
| - _manager->timeout(); | |
| + _manager->step(); | |
| + } | |
| +} | |
| + | |
| +void DrawStaticLoading( | |
| + QPainter &p, | |
| + QRectF rect, | |
| + int stroke, | |
| + QPen pen, | |
| + QBrush brush) { | |
| + PainterHighQualityEnabler hq(p); | |
| + | |
| + p.setBrush(brush); | |
| + pen.setWidthF(stroke); | |
| + pen.setCapStyle(Qt::RoundCap); | |
| + pen.setJoinStyle(Qt::RoundJoin); | |
| + p.setPen(pen); | |
| + p.drawEllipse(rect); | |
| + | |
| + const auto center = rect.center(); | |
| + const auto first = QPointF(center.x(), rect.y() + 1.5 * stroke); | |
| + const auto delta = center.y() - first.y(); | |
| + const auto second = QPointF(center.x() + delta * 2 / 3., center.y()); | |
| + if (delta > 0) { | |
| + QPainterPath path; | |
| + path.moveTo(first); | |
| + path.lineTo(center); | |
| + path.lineTo(second); | |
| + p.drawPath(path); | |
| } | |
| } | |
| @@ -125,19 +155,19 @@ | |
| _manager->stop(this); | |
| } | |
| -AnimationManager::AnimationManager() : _timer(this), _iterating(false) { | |
| +AnimationManager::AnimationManager() : _timer(this) { | |
| _timer.setSingleShot(false); | |
| - connect(&_timer, SIGNAL(timeout()), this, SLOT(timeout())); | |
| + connect(&_timer, &QTimer::timeout, this, &AnimationManager::step); | |
| } | |
| void AnimationManager::start(BasicAnimation *obj) { | |
| if (_iterating) { | |
| _starting.insert(obj); | |
| - if (!_stopping.isEmpty()) { | |
| - _stopping.remove(obj); | |
| + if (!_stopping.empty()) { | |
| + _stopping.erase(obj); | |
| } | |
| } else { | |
| - if (_objects.isEmpty()) { | |
| + if (_objects.empty()) { | |
| _timer.start(AnimationTimerDelta); | |
| } | |
| _objects.insert(obj); | |
| @@ -147,8 +177,8 @@ | |
| void AnimationManager::stop(BasicAnimation *obj) { | |
| if (_iterating) { | |
| _stopping.insert(obj); | |
| - if (!_starting.isEmpty()) { | |
| - _starting.remove(obj); | |
| + if (!_starting.empty()) { | |
| + _starting.erase(obj); | |
| } | |
| } else { | |
| auto i = _objects.find(obj); | |
| @@ -161,25 +191,33 @@ | |
| } | |
| } | |
| -void AnimationManager::timeout() { | |
| +void AnimationManager::registerClip(not_null<Media::Clip::Manager*> clip) { | |
| + connect( | |
| + clip, | |
| + &Media::Clip::Manager::callback, | |
| + this, | |
| + &AnimationManager::clipCallback); | |
| +} | |
| + | |
| +void AnimationManager::step() { | |
| _iterating = true; | |
| - auto ms = getms(); | |
| - for_const (auto object, _objects) { | |
| + const auto ms = getms(); | |
| + for (const auto object : _objects) { | |
| if (!_stopping.contains(object)) { | |
| object->step(ms, true); | |
| } | |
| } | |
| _iterating = false; | |
| - if (!_starting.isEmpty()) { | |
| - for_const (auto object, _starting) { | |
| - _objects.insert(object); | |
| + if (!_starting.empty()) { | |
| + for (const auto object : _starting) { | |
| + _objects.emplace(object); | |
| } | |
| _starting.clear(); | |
| } | |
| - if (!_stopping.isEmpty()) { | |
| - for_const (auto object, _stopping) { | |
| - _objects.remove(object); | |
| + if (!_stopping.empty()) { | |
| + for (const auto object : _stopping) { | |
| + _objects.erase(object); | |
| } | |
| _stopping.clear(); | |
| } | |
| @@ -188,7 +226,13 @@ | |
| } | |
| } | |
| -void AnimationManager::clipCallback(Media::Clip::Reader *reader, qint32 threadIndex, qint32 notification) { | |
| - Media::Clip::Reader::callback(reader, threadIndex, Media::Clip::Notification(notification)); | |
| +void AnimationManager::clipCallback( | |
| + Media::Clip::Reader *reader, | |
| + qint32 threadIndex, | |
| + qint32 notification) { | |
| + Media::Clip::Reader::callback( | |
| + reader, | |
| + threadIndex, | |
| + Media::Clip::Notification(notification)); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/animation.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/animation.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/animation.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/animation.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -7,9 +7,10 @@ | |
| */ | |
| #pragma once | |
| -#include "core/basic_types.h" | |
| #include <QtCore/QTimer> | |
| #include <QtGui/QColor> | |
| +#include "base/binary_guard.h" | |
| +#include "base/flat_set.h" | |
| namespace Media { | |
| namespace Clip { | |
| @@ -162,9 +163,9 @@ | |
| void startManager(); | |
| void stopManager(); | |
| -void registerClipManager(Media::Clip::Manager *manager); | |
| +void registerClipManager(not_null<Media::Clip::Manager*> manager); | |
| -FORCE_INLINE int interpolate(int a, int b, float64 b_ratio) { | |
| +TG_FORCE_INLINE int interpolate(int a, int b, float64 b_ratio) { | |
| return qRound(a + float64(b - a) * b_ratio); | |
| } | |
| @@ -184,36 +185,36 @@ | |
| uint32 high = 0; | |
| }; | |
| -FORCE_INLINE Shifted operator+(Shifted a, Shifted b) { | |
| +TG_FORCE_INLINE Shifted operator+(Shifted a, Shifted b) { | |
| return Shifted(a.low + b.low, a.high + b.high); | |
| } | |
| -FORCE_INLINE Shifted operator*(Shifted shifted, ShiftedMultiplier multiplier) { | |
| +TG_FORCE_INLINE Shifted operator*(Shifted shifted, ShiftedMultiplier multiplier) { | |
| return Shifted(shifted.low * multiplier, shifted.high * multiplier); | |
| } | |
| -FORCE_INLINE Shifted operator*(ShiftedMultiplier multiplier, Shifted shifted) { | |
| +TG_FORCE_INLINE Shifted operator*(ShiftedMultiplier multiplier, Shifted shifted) { | |
| return Shifted(shifted.low * multiplier, shifted.high * multiplier); | |
| } | |
| -FORCE_INLINE Shifted shifted(uint32 components) { | |
| +TG_FORCE_INLINE Shifted shifted(uint32 components) { | |
| return Shifted( | |
| (components & 0x000000FFU) | ((components & 0x0000FF00U) << 8), | |
| ((components & 0x00FF0000U) >> 16) | ((components & 0xFF000000U) >> 8)); | |
| } | |
| -FORCE_INLINE uint32 unshifted(Shifted components) { | |
| +TG_FORCE_INLINE uint32 unshifted(Shifted components) { | |
| return ((components.low & 0x0000FF00U) >> 8) | |
| | ((components.low & 0xFF000000U) >> 16) | |
| | ((components.high & 0x0000FF00U) << 8) | |
| | (components.high & 0xFF000000U); | |
| } | |
| -FORCE_INLINE Shifted reshifted(Shifted components) { | |
| +TG_FORCE_INLINE Shifted reshifted(Shifted components) { | |
| return Shifted((components.low >> 8) & 0x00FF00FFU, (components.high >> 8) & 0x00FF00FFU); | |
| } | |
| -FORCE_INLINE Shifted shifted(QColor color) { | |
| +TG_FORCE_INLINE Shifted shifted(QColor color) { | |
| // Make it premultiplied. | |
| auto alpha = static_cast<uint32>((color.alpha() & 0xFF) + 1); | |
| auto components = Shifted(static_cast<uint32>(color.blue() & 0xFF) | (static_cast<uint32>(color.green() & 0xFF) << 16), | |
| @@ -221,7 +222,7 @@ | |
| return reshifted(components * alpha); | |
| } | |
| -FORCE_INLINE uint32 getPremultiplied(QColor color) { | |
| +TG_FORCE_INLINE uint32 getPremultiplied(QColor color) { | |
| // Make it premultiplied. | |
| auto alpha = static_cast<uint32>((color.alpha() & 0xFF) + 1); | |
| auto components = Shifted(static_cast<uint32>(color.blue() & 0xFF) | (static_cast<uint32>(color.green() & 0xFF) << 16), | |
| @@ -229,16 +230,16 @@ | |
| return unshifted(components * alpha); | |
| } | |
| -FORCE_INLINE uint32 getAlpha(Shifted components) { | |
| +TG_FORCE_INLINE uint32 getAlpha(Shifted components) { | |
| return (components.high & 0x00FF0000U) >> 16; | |
| } | |
| -FORCE_INLINE Shifted non_premultiplied(QColor color) { | |
| +TG_FORCE_INLINE Shifted non_premultiplied(QColor color) { | |
| return Shifted(static_cast<uint32>(color.blue() & 0xFF) | (static_cast<uint32>(color.green() & 0xFF) << 16), | |
| static_cast<uint32>(color.red() & 0xFF) | (static_cast<uint32>(color.alpha() & 0xFF) << 16)); | |
| } | |
| -FORCE_INLINE QColor color(QColor a, QColor b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QColor color(QColor a, QColor b, float64 b_ratio) { | |
| auto bOpacity = snap(interpolate(0, 255, b_ratio), 0, 255) + 1; | |
| auto aOpacity = (256 - bOpacity); | |
| auto components = (non_premultiplied(a) * aOpacity + non_premultiplied(b) * bOpacity); | |
| @@ -263,19 +264,19 @@ | |
| uint64 value = 0; | |
| }; | |
| -FORCE_INLINE Shifted operator+(Shifted a, Shifted b) { | |
| +TG_FORCE_INLINE Shifted operator+(Shifted a, Shifted b) { | |
| return Shifted(a.value + b.value); | |
| } | |
| -FORCE_INLINE Shifted operator*(Shifted shifted, ShiftedMultiplier multiplier) { | |
| +TG_FORCE_INLINE Shifted operator*(Shifted shifted, ShiftedMultiplier multiplier) { | |
| return Shifted(shifted.value * multiplier); | |
| } | |
| -FORCE_INLINE Shifted operator*(ShiftedMultiplier multiplier, Shifted shifted) { | |
| +TG_FORCE_INLINE Shifted operator*(ShiftedMultiplier multiplier, Shifted shifted) { | |
| return Shifted(shifted.value * multiplier); | |
| } | |
| -FORCE_INLINE Shifted shifted(uint32 components) { | |
| +TG_FORCE_INLINE Shifted shifted(uint32 components) { | |
| auto wide = static_cast<uint64>(components); | |
| return (wide & 0x00000000000000FFULL) | |
| | ((wide & 0x000000000000FF00ULL) << 8) | |
| @@ -283,18 +284,18 @@ | |
| | ((wide & 0x00000000FF000000ULL) << 24); | |
| } | |
| -FORCE_INLINE uint32 unshifted(Shifted components) { | |
| +TG_FORCE_INLINE uint32 unshifted(Shifted components) { | |
| return static_cast<uint32>((components.value & 0x000000000000FF00ULL) >> 8) | |
| | static_cast<uint32>((components.value & 0x00000000FF000000ULL) >> 16) | |
| | static_cast<uint32>((components.value & 0x0000FF0000000000ULL) >> 24) | |
| | static_cast<uint32>((components.value & 0xFF00000000000000ULL) >> 32); | |
| } | |
| -FORCE_INLINE Shifted reshifted(Shifted components) { | |
| +TG_FORCE_INLINE Shifted reshifted(Shifted components) { | |
| return (components.value >> 8) & 0x00FF00FF00FF00FFULL; | |
| } | |
| -FORCE_INLINE Shifted shifted(QColor color) { | |
| +TG_FORCE_INLINE Shifted shifted(QColor color) { | |
| // Make it premultiplied. | |
| auto alpha = static_cast<uint64>((color.alpha() & 0xFF) + 1); | |
| auto components = static_cast<uint64>(color.blue() & 0xFF) | |
| @@ -304,7 +305,7 @@ | |
| return reshifted(components * alpha); | |
| } | |
| -FORCE_INLINE uint32 getPremultiplied(QColor color) { | |
| +TG_FORCE_INLINE uint32 getPremultiplied(QColor color) { | |
| // Make it premultiplied. | |
| auto alpha = static_cast<uint64>((color.alpha() & 0xFF) + 1); | |
| auto components = static_cast<uint64>(color.blue() & 0xFF) | |
| @@ -314,18 +315,18 @@ | |
| return unshifted(components * alpha); | |
| } | |
| -FORCE_INLINE uint32 getAlpha(Shifted components) { | |
| +TG_FORCE_INLINE uint32 getAlpha(Shifted components) { | |
| return (components.value & 0x00FF000000000000ULL) >> 48; | |
| } | |
| -FORCE_INLINE Shifted non_premultiplied(QColor color) { | |
| +TG_FORCE_INLINE Shifted non_premultiplied(QColor color) { | |
| return static_cast<uint64>(color.blue() & 0xFF) | |
| | (static_cast<uint64>(color.green() & 0xFF) << 16) | |
| | (static_cast<uint64>(color.red() & 0xFF) << 32) | |
| | (static_cast<uint64>(color.alpha() & 0xFF) << 48); | |
| } | |
| -FORCE_INLINE QColor color(QColor a, QColor b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QColor color(QColor a, QColor b, float64 b_ratio) { | |
| auto bOpacity = snap(interpolate(0, 255, b_ratio), 0, 255) + 1; | |
| auto aOpacity = (256 - bOpacity); | |
| auto components = (non_premultiplied(a) * aOpacity + non_premultiplied(b) * bOpacity); | |
| @@ -339,47 +340,47 @@ | |
| #endif // SHIFTED_USE_32BIT | |
| -FORCE_INLINE QColor color(style::color a, QColor b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QColor color(style::color a, QColor b, float64 b_ratio) { | |
| return color(a->c, b, b_ratio); | |
| } | |
| -FORCE_INLINE QColor color(QColor a, style::color b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QColor color(QColor a, style::color b, float64 b_ratio) { | |
| return color(a, b->c, b_ratio); | |
| } | |
| -FORCE_INLINE QColor color(style::color a, style::color b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QColor color(style::color a, style::color b, float64 b_ratio) { | |
| return color(a->c, b->c, b_ratio); | |
| } | |
| -FORCE_INLINE QPen pen(QColor a, QColor b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QPen pen(QColor a, QColor b, float64 b_ratio) { | |
| return color(a, b, b_ratio); | |
| } | |
| -FORCE_INLINE QPen pen(style::color a, QColor b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QPen pen(style::color a, QColor b, float64 b_ratio) { | |
| return (b_ratio > 0) ? pen(a->c, b, b_ratio) : a; | |
| } | |
| -FORCE_INLINE QPen pen(QColor a, style::color b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QPen pen(QColor a, style::color b, float64 b_ratio) { | |
| return (b_ratio < 1) ? pen(a, b->c, b_ratio) : b; | |
| } | |
| -FORCE_INLINE QPen pen(style::color a, style::color b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QPen pen(style::color a, style::color b, float64 b_ratio) { | |
| return (b_ratio > 0) ? ((b_ratio < 1) ? pen(a->c, b->c, b_ratio) : b) : a; | |
| } | |
| -FORCE_INLINE QBrush brush(QColor a, QColor b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QBrush brush(QColor a, QColor b, float64 b_ratio) { | |
| return color(a, b, b_ratio); | |
| } | |
| -FORCE_INLINE QBrush brush(style::color a, QColor b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QBrush brush(style::color a, QColor b, float64 b_ratio) { | |
| return (b_ratio > 0) ? brush(a->c, b, b_ratio) : a; | |
| } | |
| -FORCE_INLINE QBrush brush(QColor a, style::color b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QBrush brush(QColor a, style::color b, float64 b_ratio) { | |
| return (b_ratio < 1) ? brush(a, b->c, b_ratio) : b; | |
| } | |
| -FORCE_INLINE QBrush brush(style::color a, style::color b, float64 b_ratio) { | |
| +TG_FORCE_INLINE QBrush brush(style::color a, style::color b, float64 b_ratio) { | |
| return (b_ratio > 0) ? ((b_ratio < 1) ? brush(a->c, b->c, b_ratio) : b) : a; | |
| } | |
| @@ -417,6 +418,13 @@ | |
| bool Disabled(); | |
| void SetDisabled(bool disabled); | |
| +void DrawStaticLoading( | |
| + QPainter &p, | |
| + QRectF rect, | |
| + int stroke, | |
| + QPen pen, | |
| + QBrush brush = Qt::NoBrush); | |
| + | |
| }; | |
| class BasicAnimation; | |
| @@ -663,12 +671,14 @@ | |
| struct Data { | |
| template <typename Lambda> | |
| Data(float64 from, Lambda updateCallback) | |
| - : value(from, from) | |
| - , a_animation(animation(this, &Data::step)) | |
| - , updateCallback(std::move(updateCallback)) { | |
| + : value(from, from) | |
| + , a_animation(animation(this, &Data::step)) | |
| + , updateCallback(std::move(updateCallback)) { | |
| } | |
| void step(float64 ms, bool timer) { | |
| - auto dt = (ms >= duration || anim::Disabled()) ? 1. : (ms / duration); | |
| + const auto dt = (ms >= duration || anim::Disabled()) | |
| + ? 1. | |
| + : (ms / duration); | |
| if (dt >= 1) { | |
| value.finish(); | |
| a_animation.stop(); | |
| @@ -691,23 +701,23 @@ | |
| }; | |
| class AnimationManager : public QObject { | |
| - Q_OBJECT | |
| - | |
| public: | |
| AnimationManager(); | |
| void start(BasicAnimation *obj); | |
| void stop(BasicAnimation *obj); | |
| -public slots: | |
| - void timeout(); | |
| - | |
| - void clipCallback(Media::Clip::Reader *reader, qint32 threadIndex, qint32 notification); | |
| + void registerClip(not_null<Media::Clip::Manager*> clip); | |
| + void step(); | |
| private: | |
| - using AnimatingObjects = OrderedSet<BasicAnimation*>; | |
| - AnimatingObjects _objects, _starting, _stopping; | |
| + void clipCallback( | |
| + Media::Clip::Reader *reader, | |
| + qint32 threadIndex, | |
| + qint32 notification); | |
| + | |
| + base::flat_set<BasicAnimation*> _objects, _starting, _stopping; | |
| QTimer _timer; | |
| - bool _iterating; | |
| + bool _iterating = false; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/cross_animation.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/cross_animation.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/cross_animation.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/cross_animation.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -11,6 +11,7 @@ | |
| namespace { | |
| constexpr auto kPointCount = 12; | |
| +constexpr auto kStaticLoadingValue = float64(-666); | |
| // | |
| // 1 3 | |
| @@ -90,7 +91,26 @@ | |
| } // namespace | |
| -void CrossAnimation::paint(Painter &p, const style::CrossAnimation &st, style::color color, int x, int y, int outerWidth, float64 shown, float64 loading) { | |
| +void CrossAnimation::paintStaticLoading( | |
| + Painter &p, | |
| + const style::CrossAnimation &st, | |
| + style::color color, | |
| + int x, | |
| + int y, | |
| + int outerWidth, | |
| + float64 shown) { | |
| + paint(p, st, color, x, y, outerWidth, shown, kStaticLoadingValue); | |
| +} | |
| + | |
| +void CrossAnimation::paint( | |
| + Painter &p, | |
| + const style::CrossAnimation &st, | |
| + style::color color, | |
| + int x, | |
| + int y, | |
| + int outerWidth, | |
| + float64 shown, | |
| + float64 loading) { | |
| PainterHighQualityEnabler hq(p); | |
| auto sqrt2 = sqrt(2.); | |
| @@ -117,7 +137,8 @@ | |
| } }; | |
| auto pathDeleteSize = kPointCount; | |
| - auto loadingArcLength = 0; | |
| + const auto staticLoading = (loading == kStaticLoadingValue); | |
| + auto loadingArcLength = staticLoading ? FullArcLength : 0; | |
| if (loading > 0.) { | |
| transformLoadingCross(loading, pathDelete, pathDeleteSize); | |
| @@ -125,44 +146,50 @@ | |
| loadingArcLength = qRound(-loadingArc * 2 * FullArcLength); | |
| } | |
| - if (shown < 1.) { | |
| - auto alpha = -(shown - 1.) * M_PI_2; | |
| - auto cosalpha = cos(alpha); | |
| - auto sinalpha = sin(alpha); | |
| - auto shiftx = deleteLeft + (deleteWidth / 2.); | |
| - auto shifty = deleteTop + (deleteHeight / 2.); | |
| - for (auto &point : pathDelete) { | |
| - auto x = point.x() - shiftx; | |
| - auto y = point.y() - shifty; | |
| - point.setX(shiftx + x * cosalpha - y * sinalpha); | |
| - point.setY(shifty + y * cosalpha + x * sinalpha); | |
| + if (!staticLoading) { | |
| + if (shown < 1.) { | |
| + auto alpha = -(shown - 1.) * M_PI_2; | |
| + auto cosalpha = cos(alpha); | |
| + auto sinalpha = sin(alpha); | |
| + auto shiftx = deleteLeft + (deleteWidth / 2.); | |
| + auto shifty = deleteTop + (deleteHeight / 2.); | |
| + for (auto &point : pathDelete) { | |
| + auto x = point.x() - shiftx; | |
| + auto y = point.y() - shifty; | |
| + point.setX(shiftx + x * cosalpha - y * sinalpha); | |
| + point.setY(shifty + y * cosalpha + x * sinalpha); | |
| + } | |
| } | |
| + QPainterPath path; | |
| + path.moveTo(pathDelete[0]); | |
| + for (int i = 1; i != pathDeleteSize; ++i) { | |
| + path.lineTo(pathDelete[i]); | |
| + } | |
| + path.lineTo(pathDelete[0]); | |
| + p.fillPath(path, color); | |
| } | |
| - QPainterPath path; | |
| - path.moveTo(pathDelete[0]); | |
| - for (int i = 1; i != pathDeleteSize; ++i) { | |
| - path.lineTo(pathDelete[i]); | |
| - } | |
| - path.lineTo(pathDelete[0]); | |
| - p.fillPath(path, color); | |
| - | |
| if (loadingArcLength != 0) { | |
| - auto loadingArcStart = FullArcLength / 8; | |
| auto roundSkip = (st.size * (1 - sqrt2) + 2 * sqrt2 * deleteSkip + st.stroke) / 2; | |
| auto roundPart = QRectF(x + roundSkip, y + roundSkip, st.size - 2 * roundSkip, st.size - 2 * roundSkip); | |
| - if (shown < 1.) { | |
| - loadingArcStart -= qRound(-(shown - 1.) * FullArcLength / 4.); | |
| - } | |
| - p.setBrush(Qt::NoBrush); | |
| - auto pen = color->p; | |
| - pen.setWidthF(st.stroke); | |
| - pen.setCapStyle(Qt::RoundCap); | |
| - p.setPen(pen); | |
| - if (loadingArcLength < 0) { | |
| - loadingArcStart += loadingArcLength; | |
| - loadingArcLength = -loadingArcLength; | |
| + if (staticLoading) { | |
| + anim::DrawStaticLoading(p, roundPart, st.stroke, color); | |
| + } else { | |
| + auto loadingArcStart = FullArcLength / 8; | |
| + if (shown < 1.) { | |
| + loadingArcStart -= qRound(-(shown - 1.) * FullArcLength / 4.); | |
| + } | |
| + if (loadingArcLength < 0) { | |
| + loadingArcStart += loadingArcLength; | |
| + loadingArcLength = -loadingArcLength; | |
| + } | |
| + | |
| + p.setBrush(Qt::NoBrush); | |
| + auto pen = color->p; | |
| + pen.setWidthF(st.stroke); | |
| + pen.setCapStyle(Qt::RoundCap); | |
| + p.setPen(pen); | |
| + p.drawArc(roundPart, loadingArcStart, loadingArcLength); | |
| } | |
| - p.drawArc(roundPart, loadingArcStart, loadingArcLength); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/cross_animation.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/cross_animation.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/cross_animation.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/cross_animation.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -13,7 +13,23 @@ | |
| class CrossAnimation { | |
| public: | |
| - static void paint(Painter &p, const style::CrossAnimation &st, style::color color, int x, int y, int outerWidth, float64 shown, float64 loading = 0.); | |
| + static void paint( | |
| + Painter &p, | |
| + const style::CrossAnimation &st, | |
| + style::color color, | |
| + int x, | |
| + int y, | |
| + int outerWidth, | |
| + float64 shown, | |
| + float64 loading = 0.); | |
| + static void paintStaticLoading( | |
| + Painter &p, | |
| + const style::CrossAnimation &st, | |
| + style::color color, | |
| + int x, | |
| + int y, | |
| + int outerWidth, | |
| + float64 shown); | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/radial_animation.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/radial_animation.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/radial_animation.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/radial_animation.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,9 +23,10 @@ | |
| _animation.start(); | |
| } | |
| -void RadialAnimation::update(float64 prg, bool finished, TimeMs ms) { | |
| - auto iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength); | |
| - if (iprg != qRound(a_arcEnd.to())) { | |
| +bool RadialAnimation::update(float64 prg, bool finished, TimeMs ms) { | |
| + const auto iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength); | |
| + const auto result = (iprg != qRound(a_arcEnd.to())); | |
| + if (result) { | |
| a_arcEnd.start(iprg); | |
| _lastStart = _lastTime; | |
| } | |
| @@ -34,7 +35,12 @@ | |
| auto dt = float64(ms - _lastStart); | |
| auto fulldt = float64(ms - _firstStart); | |
| _opacity = qMin(fulldt / st::radialDuration, 1.); | |
| - if (!finished) { | |
| + if (anim::Disabled()) { | |
| + a_arcEnd.update(1., anim::linear); | |
| + if (finished) { | |
| + stop(); | |
| + } | |
| + } else if (!finished) { | |
| a_arcEnd.update(1. - (st::radialDuration / (st::radialDuration + dt)), anim::linear); | |
| } else if (dt >= st::radialDuration) { | |
| a_arcEnd.update(1., anim::linear); | |
| @@ -46,6 +52,7 @@ | |
| } | |
| auto fromstart = fulldt / st::radialPeriod; | |
| a_arcStart.update(fromstart - std::floor(fromstart), anim::linear); | |
| + return result; | |
| } | |
| void RadialAnimation::stop() { | |
| @@ -69,7 +76,9 @@ | |
| p.setPen(pen); | |
| auto len = MinArcLength + qRound(a_arcEnd.current()); | |
| - auto from = QuarterArcLength - qRound(a_arcStart.current()) - len; | |
| + auto from = QuarterArcLength | |
| + - len | |
| + - (anim::Disabled() ? 0 : qRound(a_arcStart.current())); | |
| if (rtl()) { | |
| from = QuarterArcLength - (from - QuarterArcLength) - len; | |
| if (from < 0) from += FullArcLength; | |
| @@ -104,6 +113,9 @@ | |
| void InfiniteRadialAnimation::stop() { | |
| const auto now = getms(); | |
| + if (anim::Disabled()) { | |
| + _workFinished = now; | |
| + } | |
| if (!_workFinished) { | |
| const auto zero = _workStarted - _st.sineDuration; | |
| const auto index = (now - zero + _st.sinePeriod - _st.sineShift) | |
| @@ -138,26 +150,32 @@ | |
| auto o = p.opacity(); | |
| p.setOpacity(o * state.shown); | |
| - auto pen = _st.color->p; | |
| - auto was = p.pen(); | |
| - pen.setWidth(_st.thickness); | |
| - pen.setCapStyle(Qt::RoundCap); | |
| - p.setPen(pen); | |
| - | |
| - { | |
| - PainterHighQualityEnabler hq(p); | |
| - p.drawArc( | |
| - rtlrect( | |
| - position.x(), | |
| - position.y(), | |
| - size.width(), | |
| - size.height(), | |
| - outerWidth), | |
| - state.arcFrom, | |
| - state.arcLength); | |
| + const auto rect = rtlrect( | |
| + position.x(), | |
| + position.y(), | |
| + size.width(), | |
| + size.height(), | |
| + outerWidth); | |
| + const auto was = p.pen(); | |
| + const auto brush = p.brush(); | |
| + if (anim::Disabled()) { | |
| + anim::DrawStaticLoading(p, rect, _st.thickness, _st.color); | |
| + } else { | |
| + auto pen = _st.color->p; | |
| + pen.setWidth(_st.thickness); | |
| + pen.setCapStyle(Qt::RoundCap); | |
| + p.setPen(pen); | |
| + | |
| + { | |
| + PainterHighQualityEnabler hq(p); | |
| + p.drawArc( | |
| + rect, | |
| + state.arcFrom, | |
| + state.arcLength); | |
| + } | |
| } | |
| - | |
| p.setPen(was); | |
| + p.setBrush(brush); | |
| p.setOpacity(o); | |
| } | |
| @@ -173,6 +191,10 @@ | |
| linear, | |
| FullArcLength }; | |
| } | |
| + if (anim::Disabled()) { | |
| + const auto shown = 1.; | |
| + return { 1., 0, FullArcLength }; | |
| + } | |
| const auto min = int(std::round(FullArcLength * _st.arcMin)); | |
| const auto max = int(std::round(FullArcLength * _st.arcMax)); | |
| if (now <= _workStarted) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/radial_animation.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/radial_animation.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/radial_animation.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/radial_animation.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -25,7 +25,7 @@ | |
| } | |
| void start(float64 prg); | |
| - void update(float64 prg, bool finished, TimeMs ms); | |
| + bool update(float64 prg, bool finished, TimeMs ms); | |
| void stop(); | |
| void step(TimeMs ms); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/send_action_animations.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/send_action_animations.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/send_action_animations.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/send_action_animations.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -190,6 +190,23 @@ | |
| return Implementations->value(type, &TypingAnimation::kMeta) == metaData(); | |
| } | |
| +void SendActionAnimation::Impl::paint( | |
| + Painter &p, | |
| + style::color color, | |
| + int x, | |
| + int y, | |
| + int outerWidth, | |
| + TimeMs ms) { | |
| + paintFrame( | |
| + p, | |
| + color, | |
| + x, | |
| + y, | |
| + outerWidth, | |
| + anim::Disabled() ? 0 : (qMax(ms - _started, 0LL) % _period)); | |
| +} | |
| + | |
| + | |
| void SendActionAnimation::start(Type type) { | |
| if (!_impl || !_impl->supports(type)) { | |
| _impl = createByType(type); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/send_action_animations.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/send_action_animations.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/effects/send_action_animations.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/effects/send_action_animations.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -44,9 +44,13 @@ | |
| bool supports(Type type) const; | |
| virtual int width() const = 0; | |
| - void paint(Painter &p, style::color color, int x, int y, int outerWidth, TimeMs ms) { | |
| - paintFrame(p, color, x, y, outerWidth, qMax(ms - _started, 0LL) % _period); | |
| - } | |
| + void paint( | |
| + Painter &p, | |
| + style::color color, | |
| + int x, | |
| + int y, | |
| + int outerWidth, | |
| + TimeMs ms); | |
| virtual ~Impl() = default; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/images.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/images.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/images.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/images.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,15 +9,17 @@ | |
| #include "mainwidget.h" | |
| #include "storage/localstorage.h" | |
| +#include "storage/cache/storage_cache_database.h" | |
| #include "platform/platform_specific.h" | |
| #include "auth_session.h" | |
| #include "history/history_item.h" | |
| #include "history/history.h" | |
| +#include "data/data_session.h" | |
| namespace Images { | |
| namespace { | |
| -FORCE_INLINE uint64 blurGetColors(const uchar *p) { | |
| +TG_FORCE_INLINE uint64 blurGetColors(const uchar *p) { | |
| return (uint64)p[0] + ((uint64)p[1] << 16) + ((uint64)p[2] << 32) + ((uint64)p[3] << 48); | |
| } | |
| @@ -915,6 +917,10 @@ | |
| _forgot = false; | |
| } | |
| +std::optional<Storage::Cache::Key> Image::cacheKey() const { | |
| + return std::nullopt; | |
| +} | |
| + | |
| void Image::invalidateSizeCache() const { | |
| for (auto &pix : _sizesCache) { | |
| if (!pix.isNull()) { | |
| @@ -989,13 +995,13 @@ | |
| void RemoteImage::loadLocal() { | |
| if (loaded() || amLoading()) return; | |
| - _loader = createLoader(base::none, LoadFromLocalOnly, true); | |
| + _loader = createLoader(std::nullopt, LoadFromLocalOnly, true); | |
| if (_loader) _loader->start(); | |
| } | |
| -void RemoteImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) { | |
| - QBuffer buffer(&bytes); | |
| - | |
| +void RemoteImage::setImageBytes( | |
| + const QByteArray &bytes, | |
| + const QByteArray &bytesFormat) { | |
| if (!_data.isNull()) { | |
| globalAcquiredSize -= int64(_data.width()) * _data.height() * 4; | |
| } | |
| @@ -1013,6 +1019,17 @@ | |
| _saved = bytes; | |
| _format = fmt; | |
| _forgot = false; | |
| + | |
| + const auto location = this->location(); | |
| + if (!location.isNull() | |
| + && !bytes.isEmpty() | |
| + && bytes.size() <= Storage::kMaxFileInMemory) { | |
| + Auth().data().cache().putIfEmpty( | |
| + Data::StorageCacheKey(location), | |
| + Storage::Cache::Database::TaggedValue( | |
| + base::duplicate(bytes), | |
| + Data::kImageCacheTag)); | |
| + } | |
| } | |
| bool RemoteImage::amLoading() const { | |
| @@ -1113,13 +1130,18 @@ | |
| , _size(size) { | |
| } | |
| -StorageImage::StorageImage(const StorageImageLocation &location, QByteArray &bytes) | |
| +StorageImage::StorageImage( | |
| + const StorageImageLocation &location, | |
| + const QByteArray &bytes) | |
| : _location(location) | |
| , _size(bytes.size()) { | |
| - setData(bytes); | |
| - if (!_location.isNull()) { | |
| - Local::writeImage(storageKey(_location), StorageImageSaved(bytes)); | |
| - } | |
| + setImageBytes(bytes); | |
| +} | |
| + | |
| +std::optional<Storage::Cache::Key> StorageImage::cacheKey() const { | |
| + return _location.isNull() | |
| + ? std::nullopt | |
| + : base::make_optional(Data::StorageCacheKey(_location)); | |
| } | |
| int32 StorageImage::countWidth() const { | |
| @@ -1130,10 +1152,6 @@ | |
| return _location.height(); | |
| } | |
| -bool StorageImage::hasLocalCopy() const { | |
| - return Local::willImageLoad(storageKey(_location)); | |
| -} | |
| - | |
| void StorageImage::setInformation(int32 size, int32 width, int32 height) { | |
| _size = size; | |
| _location.setSize(width, height); | |
| @@ -1151,7 +1169,8 @@ | |
| origin, | |
| _size, | |
| fromCloud, | |
| - autoLoading); | |
| + autoLoading, | |
| + Data::kImageCacheTag); | |
| } | |
| WebFileImage::WebFileImage( | |
| @@ -1176,6 +1195,12 @@ | |
| , _size(size) { | |
| } | |
| +std::optional<Storage::Cache::Key> WebFileImage::cacheKey() const { | |
| + return _location.isNull() | |
| + ? std::nullopt | |
| + : base::make_optional(Data::WebDocumentCacheKey(_location)); | |
| +} | |
| + | |
| int WebFileImage::countWidth() const { | |
| return _width; | |
| } | |
| @@ -1184,10 +1209,6 @@ | |
| return _height; | |
| } | |
| -bool WebFileImage::hasLocalCopy() const { | |
| - return Local::willImageLoad(storageKey(_location)); | |
| -} | |
| - | |
| void WebFileImage::setInformation(int size, int width, int height) { | |
| _size = size; | |
| _width = width; | |
| @@ -1204,7 +1225,8 @@ | |
| &_location, | |
| _size, | |
| fromCloud, | |
| - autoLoading); | |
| + autoLoading, | |
| + Data::kImageCacheTag); | |
| } | |
| DelayedStorageImage::DelayedStorageImage() : StorageImage(StorageImageLocation()) | |
| @@ -1219,13 +1241,13 @@ | |
| , _loadCancelled(false) | |
| , _loadFromCloud(false) { | |
| } | |
| - | |
| -DelayedStorageImage::DelayedStorageImage(QByteArray &bytes) | |
| -: StorageImage(StorageImageLocation(), bytes) | |
| -, _loadRequested(false) | |
| -, _loadCancelled(false) | |
| -, _loadFromCloud(false) { | |
| -} | |
| +// | |
| +//DelayedStorageImage::DelayedStorageImage(QByteArray &bytes) | |
| +//: StorageImage(StorageImageLocation(), bytes) | |
| +//, _loadRequested(false) | |
| +//, _loadCancelled(false) | |
| +//, _loadFromCloud(false) { | |
| +//} | |
| void DelayedStorageImage::setStorageLocation( | |
| Data::FileOrigin origin, | |
| @@ -1317,6 +1339,10 @@ | |
| , _height(height) { | |
| } | |
| +std::optional<Storage::Cache::Key> WebImage::cacheKey() const { | |
| + return Data::UrlCacheKey(_url); | |
| +} | |
| + | |
| void WebImage::setSize(int width, int height) { | |
| _width = width; | |
| _height = height; | |
| @@ -1330,10 +1356,6 @@ | |
| return _height; | |
| } | |
| -bool WebImage::hasLocalCopy() const { | |
| - return Local::willWebFileLoad(_url); | |
| -} | |
| - | |
| void WebImage::setInformation(int32 size, int32 width, int32 height) { | |
| _size = size; | |
| setSize(width, height); | |
| @@ -1343,7 +1365,12 @@ | |
| Data::FileOrigin origin, | |
| LoadFromCloudSetting fromCloud, | |
| bool autoLoading) { | |
| - return new webFileLoader(_url, QString(), fromCloud, autoLoading); | |
| + return new webFileLoader( | |
| + _url, | |
| + QString(), | |
| + fromCloud, | |
| + autoLoading, | |
| + Data::kImageCacheTag); | |
| } | |
| namespace internal { | |
| @@ -1404,25 +1431,27 @@ | |
| } | |
| StorageImage *getImage(const StorageImageLocation &location, int32 size) { | |
| - StorageKey key(storageKey(location)); | |
| - StorageImages::const_iterator i = storageImages.constFind(key); | |
| + const auto key = storageKey(location); | |
| + auto i = storageImages.constFind(key); | |
| if (i == storageImages.cend()) { | |
| i = storageImages.insert(key, new StorageImage(location, size)); | |
| + } else { | |
| + i.value()->refreshFileReference(location.fileReference()); | |
| } | |
| return i.value(); | |
| } | |
| -StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes) { | |
| - StorageKey key(storageKey(location)); | |
| - StorageImages::const_iterator i = storageImages.constFind(key); | |
| +StorageImage *getImage( | |
| + const StorageImageLocation &location, | |
| + const QByteArray &bytes) { | |
| + const auto key = storageKey(location); | |
| + auto i = storageImages.constFind(key); | |
| if (i == storageImages.cend()) { | |
| - QByteArray bytesArr(bytes); | |
| - i = storageImages.insert(key, new StorageImage(location, bytesArr)); | |
| - } else if (!i.value()->loaded()) { | |
| - QByteArray bytesArr(bytes); | |
| - i.value()->setData(bytesArr); | |
| - if (!location.isNull()) { | |
| - Local::writeImage(key, StorageImageSaved(bytes)); | |
| + i = storageImages.insert(key, new StorageImage(location, bytes)); | |
| + } else { | |
| + i.value()->refreshFileReference(location.fileReference()); | |
| + if (!i.value()->loaded()) { | |
| + i.value()->setImageBytes(bytes); | |
| } | |
| } | |
| return i.value(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/images.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/images.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/images.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/images.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -10,6 +10,12 @@ | |
| #include "base/flags.h" | |
| #include "data/data_file_origin.h" | |
| +namespace Storage { | |
| +namespace Cache { | |
| +struct Key; | |
| +} // namespace Cache | |
| +} // namespace Storage | |
| + | |
| enum class ImageRoundRadius { | |
| None, | |
| Large, | |
| @@ -153,7 +159,9 @@ | |
| return _fileReference; | |
| } | |
| void refreshFileReference(const QByteArray &data) { | |
| - _fileReference = data; | |
| + if (!data.isEmpty()) { | |
| + _fileReference = data; | |
| + } | |
| } | |
| static StorageImageLocation FromMTP( | |
| @@ -370,6 +378,7 @@ | |
| virtual const StorageImageLocation &location() const { | |
| return StorageImageLocation::Null; | |
| } | |
| + virtual std::optional<Storage::Cache::Key> cacheKey() const; | |
| bool isNull() const; | |
| @@ -410,10 +419,6 @@ | |
| return _data.height(); | |
| } | |
| - virtual bool hasLocalCopy() const { | |
| - return false; | |
| - } | |
| - | |
| mutable QByteArray _saved, _format; | |
| mutable bool _forgot; | |
| mutable QPixmap _data; | |
| @@ -462,8 +467,8 @@ | |
| float64 progress() const override; | |
| int32 loadOffset() const override; | |
| - void setData( | |
| - QByteArray &bytes, | |
| + void setImageBytes( | |
| + const QByteArray &bytes, | |
| const QByteArray &format = QByteArray()); | |
| void load( | |
| @@ -505,12 +510,16 @@ | |
| class StorageImage : public RemoteImage { | |
| public: | |
| - StorageImage(const StorageImageLocation &location, int32 size = 0); | |
| - StorageImage(const StorageImageLocation &location, QByteArray &bytes); | |
| + explicit StorageImage(const StorageImageLocation &location, int32 size = 0); | |
| + StorageImage(const StorageImageLocation &location, const QByteArray &bytes); | |
| const StorageImageLocation &location() const override { | |
| return _location; | |
| } | |
| + std::optional<Storage::Cache::Key> cacheKey() const override; | |
| + void refreshFileReference(const QByteArray &data) { | |
| + _location.refreshFileReference(data); | |
| + } | |
| protected: | |
| void setInformation(int32 size, int32 width, int32 height) override; | |
| @@ -519,8 +528,6 @@ | |
| LoadFromCloudSetting fromCloud, | |
| bool autoLoading) override; | |
| - bool hasLocalCopy() const override; | |
| - | |
| int32 countWidth() const override; | |
| int32 countHeight() const override; | |
| @@ -538,6 +545,8 @@ | |
| int height, | |
| int size = 0); | |
| + std::optional<Storage::Cache::Key> cacheKey() const override; | |
| + | |
| protected: | |
| void setInformation(int size, int width, int height) override; | |
| FileLoader *createLoader( | |
| @@ -549,8 +558,6 @@ | |
| return _box; | |
| } | |
| - bool hasLocalCopy() const override; | |
| - | |
| int countWidth() const override; | |
| int countHeight() const override; | |
| @@ -566,7 +573,7 @@ | |
| public: | |
| DelayedStorageImage(); | |
| DelayedStorageImage(int32 w, int32 h); | |
| - DelayedStorageImage(QByteArray &bytes); | |
| + //DelayedStorageImage(QByteArray &bytes); | |
| void setStorageLocation( | |
| Data::FileOrigin origin, | |
| @@ -612,6 +619,8 @@ | |
| void setSize(int width, int height); | |
| + std::optional<Storage::Cache::Key> cacheKey() const override; | |
| + | |
| protected: | |
| QSize shrinkBox() const override { | |
| return _box; | |
| @@ -625,8 +634,6 @@ | |
| int32 countWidth() const override; | |
| int32 countHeight() const override; | |
| - bool hasLocalCopy() const override; | |
| - | |
| private: | |
| QString _url; | |
| QSize _box; | |
| @@ -647,7 +654,7 @@ | |
| const QPixmap &pixmap); | |
| Image *getImage(int32 width, int32 height); | |
| StorageImage *getImage(const StorageImageLocation &location, int size = 0); | |
| -StorageImage *getImage( | |
| +StorageImage *getImage( // photoCachedSize | |
| const StorageImageLocation &location, | |
| const QByteArray &bytes); | |
| Image *getImage(const MTPWebDocument &location); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/rp_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/rp_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/rp_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/rp_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,6 +9,20 @@ | |
| namespace Ui { | |
| +void ResizeFitChild( | |
| + not_null<RpWidget*> parent, | |
| + not_null<RpWidget*> child) { | |
| + parent->widthValue( | |
| + ) | rpl::start_with_next([=](int width) { | |
| + child->resizeToWidth(width); | |
| + }, child->lifetime()); | |
| + | |
| + child->heightValue( | |
| + ) | rpl::start_with_next([=](int height) { | |
| + parent->resize(parent->width(), height); | |
| + }, child->lifetime()); | |
| +} | |
| + | |
| rpl::producer<QRect> RpWidgetMethods::geometryValue() const { | |
| auto &stream = eventStreams().geometry; | |
| return stream.events_starting_with_copy(callGetGeometry()); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/rp_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/rp_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/rp_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/rp_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -24,6 +24,10 @@ | |
| , _value(std::forward<OtherValue>(value)) { | |
| } | |
| + not_null<Value*> value() { | |
| + return &_value; | |
| + } | |
| + | |
| private: | |
| Value _value; | |
| @@ -31,6 +35,8 @@ | |
| } // namespace details | |
| +class RpWidget; | |
| + | |
| template <typename Widget, typename ...Args> | |
| inline base::unique_qptr<Widget> CreateObject(Args &&...args) { | |
| return base::make_unique_q<Widget>( | |
| @@ -50,12 +56,18 @@ | |
| delete child; | |
| } | |
| +void ResizeFitChild( | |
| + not_null<RpWidget*> parent, | |
| + not_null<RpWidget*> child); | |
| + | |
| template <typename Value> | |
| -inline void AttachAsChild(not_null<QObject*> parent, Value &&value) { | |
| - using PlainValue = std::decay_t<Value>; | |
| - CreateChild<details::AttachmentOwner<PlainValue>>( | |
| +inline not_null<std::decay_t<Value>*> AttachAsChild( | |
| + not_null<QObject*> parent, | |
| + Value &&value) { | |
| + return CreateChild<details::AttachmentOwner<std::decay_t<Value>>>( | |
| parent.get(), | |
| - std::forward<Value>(value)); | |
| + std::forward<Value>(value) | |
| + )->value(); | |
| } | |
| template <typename Widget> | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/special_buttons.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/special_buttons.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/special_buttons.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/special_buttons.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -23,6 +23,7 @@ | |
| #include "window/window_controller.h" | |
| #include "lang/lang_keys.h" | |
| #include "auth_session.h" | |
| +#include "apiwrap.h" | |
| #include "mainwidget.h" | |
| #include "messenger.h" | |
| #include "observer_peer.h" | |
| @@ -181,28 +182,50 @@ | |
| p.fillRect(e->rect(), st::historyComposeAreaBg); | |
| paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, _rippleOverride ? &(*_rippleOverride)->c : nullptr); | |
| + const auto over = isOver(); | |
| const auto loadingState = _loading | |
| ? _loading->computeState() | |
| : Ui::InfiniteRadialAnimation::State{ 0., 0, FullArcLength }; | |
| - p.setOpacity(1. - loadingState.shown); | |
| + if (loadingState.shown < 1.) { | |
| + p.setOpacity(1. - loadingState.shown); | |
| - auto over = isOver(); | |
| - auto icon = _iconOverride ? _iconOverride : &(over ? _st.iconOver : _st.icon); | |
| - icon->paint(p, _st.iconPosition, width()); | |
| + auto icon = _iconOverride ? _iconOverride : &(over ? _st.iconOver : _st.icon); | |
| + icon->paint(p, _st.iconPosition, width()); | |
| - p.setOpacity(1.); | |
| - auto pen = _colorOverride ? (*_colorOverride)->p : (over ? st::historyEmojiCircleFgOver : st::historyEmojiCircleFg)->p; | |
| - pen.setWidth(st::historyEmojiCircleLine); | |
| - pen.setCapStyle(Qt::RoundCap); | |
| - p.setPen(pen); | |
| - p.setBrush(Qt::NoBrush); | |
| + p.setOpacity(1.); | |
| + } | |
| - PainterHighQualityEnabler hq(p); | |
| QRect inner(QPoint((width() - st::historyEmojiCircle.width()) / 2, st::historyEmojiCircleTop), st::historyEmojiCircle); | |
| - if (loadingState.arcLength < FullArcLength) { | |
| - p.drawArc(inner, loadingState.arcFrom, loadingState.arcLength); | |
| + const auto color = (_colorOverride | |
| + ? *_colorOverride | |
| + : (over | |
| + ? st::historyEmojiCircleFgOver | |
| + : st::historyEmojiCircleFg)); | |
| + if (anim::Disabled() && _loading && _loading->animating()) { | |
| + anim::DrawStaticLoading( | |
| + p, | |
| + inner, | |
| + st::historyEmojiCircleLine, | |
| + color); | |
| } else { | |
| - p.drawEllipse(inner); | |
| + auto pen = color->p; | |
| + pen.setWidth(st::historyEmojiCircleLine); | |
| + pen.setCapStyle(Qt::RoundCap); | |
| + p.setPen(pen); | |
| + p.setBrush(Qt::NoBrush); | |
| + | |
| + PainterHighQualityEnabler hq(p); | |
| + if (loadingState.arcLength < FullArcLength) { | |
| + p.drawArc(inner, loadingState.arcFrom, loadingState.arcLength); | |
| + } else { | |
| + p.drawEllipse(inner); | |
| + } | |
| + } | |
| +} | |
| + | |
| +void EmojiButton::step_loading(TimeMs ms, bool timer) { | |
| + if (timer && !anim::Disabled()) { | |
| + update(); | |
| } | |
| } | |
| @@ -214,8 +237,10 @@ | |
| } | |
| if (loading) { | |
| _loading->start(); | |
| + update(); | |
| } else if (_loading) { | |
| _loading->stop(); | |
| + update(); | |
| } | |
| } | |
| @@ -478,14 +503,9 @@ | |
| } | |
| void UserpicButton::uploadNewPeerPhoto() { | |
| - auto callback = crl::guard( | |
| - this, | |
| - [this](QImage &&image) { | |
| - Messenger::Instance().uploadProfilePhoto( | |
| - std::move(image), | |
| - _peer->id | |
| - ); | |
| - }); | |
| + auto callback = crl::guard(this, [=](QImage &&image) { | |
| + Auth().api().uploadPeerPhoto(_peer, std::move(image)); | |
| + }); | |
| ShowChoosePhotoBox(this, _peerForCrop, std::move(callback)); | |
| } | |
| @@ -984,7 +1004,7 @@ | |
| Ui::Tooltip::Show(0, this); | |
| Auth().data().updateNotifySettings( | |
| _channel, | |
| - base::none, | |
| + std::nullopt, | |
| _checked); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/special_buttons.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/special_buttons.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/special_buttons.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/special_buttons.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -65,11 +65,7 @@ | |
| QPoint prepareRippleStartPosition() const override; | |
| private: | |
| - void step_loading(TimeMs ms, bool timer) { | |
| - if (timer) { | |
| - update(); | |
| - } | |
| - } | |
| + void step_loading(TimeMs ms, bool timer); | |
| const style::IconButton &_st; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/text/text_entity.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/text/text_entity.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/text/text_entity.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/text/text_entity.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,20 +9,11 @@ | |
| #include "auth_session.h" | |
| #include "lang/lang_tag.h" | |
| +#include "base/qthelp_url.h" | |
| namespace TextUtilities { | |
| namespace { | |
| -QString ExpressionDomain() { | |
| - // Matches any domain name, containing at least one '.', including "file.txt". | |
| - return QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)?((?:[A-Za-z" "\xD0\x90-\xD0\xAF\xD0\x81" "\xD0\xB0-\xD1\x8F\xD1\x91" "0-9\\-\\_]+\\.){1,10}([A-Za-z" "\xD1\x80\xD1\x84" "\\-\\d]{2,22})(\\:\\d+)?)"); | |
| -} | |
| - | |
| -QString ExpressionDomainExplicit() { | |
| - // Matches any domain name, containing a protocol, including "test://localhost". | |
| - return QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)((?:[A-Za-z" "\xD0\x90-\xD0\xAF\xD0\x81" "\xD0\xB0-\xD1\x8F\xD1\x91" "0-9\\-\\_]+\\.){0,10}([A-Za-z" "\xD1\x80\xD1\x84" "\\-\\d]{2,22})(\\:\\d+)?)"); | |
| -} | |
| - | |
| QString ExpressionMailNameAtEnd() { | |
| // Matches email first part (before '@') at the end of the string. | |
| // First we find a domain without protocol (like "gmail.com"), then | |
| @@ -1138,16 +1129,6 @@ | |
| } // namespace | |
| -const QRegularExpression &RegExpDomain() { | |
| - static const auto result = CreateRegExp(ExpressionDomain()); | |
| - return result; | |
| -} | |
| - | |
| -const QRegularExpression &RegExpDomainExplicit() { | |
| - static const auto result = CreateRegExp(ExpressionDomainExplicit()); | |
| - return result; | |
| -} | |
| - | |
| const QRegularExpression &RegExpMailNameAtEnd() { | |
| static const auto result = CreateRegExp(ExpressionMailNameAtEnd()); | |
| return result; | |
| @@ -1604,8 +1585,8 @@ | |
| } | |
| } | |
| } | |
| - auto mDomain = RegExpDomain().match(result.text, matchOffset); | |
| - auto mExplicitDomain = RegExpDomainExplicit().match(result.text, matchOffset); | |
| + auto mDomain = qthelp::RegExpDomain().match(result.text, matchOffset); | |
| + auto mExplicitDomain = qthelp::RegExpDomainExplicit().match(result.text, matchOffset); | |
| auto mHashtag = withHashtags ? RegExpHashtag().match(result.text, matchOffset) : QRegularExpressionMatch(); | |
| auto mMention = withMentions ? RegExpMention().match(result.text, qMax(mentionSkip, matchOffset)) : QRegularExpressionMatch(); | |
| auto mBotCommand = withBotCommands ? RegExpBotCommand().match(result.text, matchOffset) : QRegularExpressionMatch(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/text/text_entity.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/text/text_entity.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/text/text_entity.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/text/text_entity.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -157,8 +157,6 @@ | |
| bool IsValidProtocol(const QString &protocol); | |
| bool IsValidTopDomain(const QString &domain); | |
| -const QRegularExpression &RegExpDomain(); | |
| -const QRegularExpression &RegExpDomainExplicit(); | |
| const QRegularExpression &RegExpMailNameAtEnd(); | |
| const QRegularExpression &RegExpHashtag(); | |
| const QRegularExpression &RegExpHashtagExclude(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/twidget.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/twidget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/twidget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/twidget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -179,7 +179,7 @@ | |
| class PainterHighQualityEnabler { | |
| public: | |
| - PainterHighQualityEnabler(Painter &p) : _painter(p) { | |
| + PainterHighQualityEnabler(QPainter &p) : _painter(p) { | |
| static constexpr QPainter::RenderHint Hints[] = { | |
| QPainter::Antialiasing, | |
| QPainter::SmoothPixmapTransform, | |
| @@ -187,8 +187,8 @@ | |
| QPainter::HighQualityAntialiasing | |
| }; | |
| - auto hints = _painter.renderHints(); | |
| - for_const (auto hint, Hints) { | |
| + const auto hints = _painter.renderHints(); | |
| + for (const auto hint : Hints) { | |
| if (!(hints & hint)) { | |
| _hints |= hint; | |
| } | |
| @@ -197,8 +197,12 @@ | |
| _painter.setRenderHints(_hints); | |
| } | |
| } | |
| - PainterHighQualityEnabler(const PainterHighQualityEnabler &other) = delete; | |
| - PainterHighQualityEnabler &operator=(const PainterHighQualityEnabler &other) = delete; | |
| + | |
| + PainterHighQualityEnabler( | |
| + const PainterHighQualityEnabler &other) = delete; | |
| + PainterHighQualityEnabler &operator=( | |
| + const PainterHighQualityEnabler &other) = delete; | |
| + | |
| ~PainterHighQualityEnabler() { | |
| if (_hints) { | |
| _painter.setRenderHints(_hints, false); | |
| @@ -206,7 +210,7 @@ | |
| } | |
| private: | |
| - Painter &_painter; | |
| + QPainter &_painter; | |
| QPainter::RenderHints _hints = 0; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/buttons.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/buttons.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/buttons.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/buttons.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -45,7 +45,7 @@ | |
| p.setPen(pen); | |
| const auto left = _st.padding.left(); | |
| const auto top = _st.padding.top() + font->ascent; | |
| - if (width() > naturalWidth()) { | |
| + if (width() < naturalWidth()) { | |
| const auto available = width() - left - _st.padding.right(); | |
| p.drawText(left, top, font->elided(_text, available)); | |
| } else { | |
| @@ -60,7 +60,7 @@ | |
| update(); | |
| } | |
| -void LinkButton::setColorOverride(base::optional<QColor> textFg) { | |
| +void LinkButton::setColorOverride(std::optional<QColor> textFg) { | |
| _textFgOverride = textFg; | |
| update(); | |
| } | |
| @@ -266,6 +266,11 @@ | |
| refreshText(); | |
| } | |
| +void RoundButton::setFullRadius(bool enabled) { | |
| + _fullRadius = enabled; | |
| + update(); | |
| +} | |
| + | |
| void RoundButton::refreshText() { | |
| _text = computeFullText(); | |
| _textWidth = _text.isEmpty() ? 0 : _st.font->width(_text); | |
| @@ -319,12 +324,24 @@ | |
| if (_fullWidthOverride < 0) { | |
| rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height()); | |
| } | |
| - App::roundRect(p, myrtlrect(rounded), _st.textBg, ImageRoundRadius::Small); | |
| + const auto drawRect = [&](const style::color &color) { | |
| + const auto fill = myrtlrect(rounded); | |
| + if (_fullRadius) { | |
| + const auto radius = rounded.height() / 2; | |
| + PainterHighQualityEnabler hq(p); | |
| + p.setPen(Qt::NoPen); | |
| + p.setBrush(color); | |
| + p.drawRoundedRect(fill, radius, radius); | |
| + } else { | |
| + App::roundRect(p, fill, color, ImageRoundRadius::Small); | |
| + } | |
| + }; | |
| + drawRect(_st.textBg); | |
| auto over = isOver(); | |
| auto down = isDown(); | |
| if (over || down) { | |
| - App::roundRect(p, myrtlrect(rounded), _st.textBgOver, ImageRoundRadius::Small); | |
| + drawRect(_st.textBgOver); | |
| } | |
| auto ms = getms(); | |
| @@ -369,7 +386,9 @@ | |
| if (_fullWidthOverride < 0) { | |
| rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height()); | |
| } | |
| - return RippleAnimation::roundRectMask(rounded.size(), st::buttonRadius); | |
| + return RippleAnimation::roundRectMask( | |
| + rounded.size(), | |
| + _fullRadius ? (rounded.height() / 2) : st::buttonRadius); | |
| } | |
| QPoint RoundButton::prepareRippleStartPosition() const { | |
| @@ -519,8 +538,8 @@ | |
| void CrossButton::step_loading(TimeMs ms, bool timer) { | |
| if (stopLoadingAnimation(ms)) { | |
| _a_loading.stop(); | |
| - } | |
| - if (timer) { | |
| + update(); | |
| + } else if (timer && !anim::Disabled()) { | |
| update(); | |
| } | |
| } | |
| @@ -565,11 +584,30 @@ | |
| if (_a_loading.animating()) { | |
| if (stopLoadingAnimation(ms)) { | |
| _a_loading.stop(); | |
| + } else if (anim::Disabled()) { | |
| + CrossAnimation::paintStaticLoading( | |
| + p, | |
| + _st.cross, | |
| + over ? _st.crossFgOver : _st.crossFg, | |
| + _st.crossPosition.x(), | |
| + _st.crossPosition.y(), | |
| + width(), | |
| + shown); | |
| + return; | |
| } else { | |
| - loading = ((ms - _loadingStartMs) % _st.loadingPeriod) / float64(_st.loadingPeriod); | |
| + loading = ((ms - _loadingStartMs) % _st.loadingPeriod) | |
| + / float64(_st.loadingPeriod); | |
| } | |
| } | |
| - CrossAnimation::paint(p, _st.cross, over ? _st.crossFgOver : _st.crossFg, _st.crossPosition.x(), _st.crossPosition.y(), width(), shown, loading); | |
| + CrossAnimation::paint( | |
| + p, | |
| + _st.cross, | |
| + over ? _st.crossFgOver : _st.crossFg, | |
| + _st.crossPosition.x(), | |
| + _st.crossPosition.y(), | |
| + width(), | |
| + shown, | |
| + loading); | |
| } | |
| bool CrossButton::stopLoadingAnimation(TimeMs ms) { | |
| @@ -598,6 +636,9 @@ | |
| _a_loading.stop(); | |
| } | |
| } | |
| + if (anim::Disabled()) { | |
| + update(); | |
| + } | |
| } | |
| void CrossButton::onStateChanged(State was, StateChangeSource source) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/buttons.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/buttons.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/buttons.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/buttons.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -24,7 +24,7 @@ | |
| int naturalWidth() const override; | |
| void setText(const QString &text); | |
| - void setColorOverride(base::optional<QColor> textFg); | |
| + void setColorOverride(std::optional<QColor> textFg); | |
| protected: | |
| void paintEvent(QPaintEvent *e) override; | |
| @@ -35,7 +35,7 @@ | |
| const style::LinkButton &_st; | |
| QString _text; | |
| int _textWidth = 0; | |
| - base::optional<QColor> _textFgOverride; | |
| + std::optional<QColor> _textFgOverride; | |
| }; | |
| @@ -100,7 +100,10 @@ | |
| class RoundButton : public RippleButton, private base::Subscriber { | |
| public: | |
| - RoundButton(QWidget *parent, Fn<QString()> textFactory, const style::RoundButton &st); | |
| + RoundButton( | |
| + QWidget *parent, | |
| + Fn<QString()> textFactory, | |
| + const style::RoundButton &st); | |
| void setText(Fn<QString()> textFactory); | |
| @@ -117,6 +120,7 @@ | |
| int contentWidth() const; | |
| void setFullWidth(int newFullWidth); | |
| + void setFullRadius(bool enabled); | |
| enum class TextTransform { | |
| NoTransform, | |
| @@ -150,6 +154,7 @@ | |
| const style::RoundButton &_st; | |
| TextTransform _transform = TextTransform::ToUpper; | |
| + bool _fullRadius = false; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/checkbox.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/checkbox.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/checkbox.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/checkbox.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -28,11 +28,24 @@ | |
| , _updateCallback(std::move(updateCallback)) { | |
| } | |
| -void AbstractCheckView::setCheckedFast(bool checked) { | |
| +void AbstractCheckView::setChecked(bool checked, anim::type animated) { | |
| + const auto changed = (_checked != checked); | |
| _checked = checked; | |
| - finishAnimating(); | |
| - if (_updateCallback) { | |
| - _updateCallback(); | |
| + if (animated == anim::type::instant) { | |
| + finishAnimating(); | |
| + if (_updateCallback) { | |
| + _updateCallback(); | |
| + } | |
| + } else if (changed) { | |
| + _toggleAnimation.start( | |
| + _updateCallback, | |
| + _checked ? 0. : 1., | |
| + _checked ? 1. : 0., | |
| + _duration); | |
| + } | |
| + if (changed) { | |
| + checkedChangedHook(animated); | |
| + _checks.fire_copy(_checked); | |
| } | |
| } | |
| @@ -49,13 +62,6 @@ | |
| } | |
| } | |
| -void AbstractCheckView::setCheckedAnimated(bool checked) { | |
| - if (_checked != checked) { | |
| - _checked = checked; | |
| - _toggleAnimation.start(_updateCallback, _checked ? 0. : 1., _checked ? 1. : 0., _duration); | |
| - } | |
| -} | |
| - | |
| void AbstractCheckView::finishAnimating() { | |
| _toggleAnimation.finish(); | |
| } | |
| @@ -64,6 +70,10 @@ | |
| return ms ? _toggleAnimation.current(ms, _checked ? 1. : 0.) : _toggleAnimation.current(_checked ? 1. : 0.); | |
| } | |
| +bool AbstractCheckView::animating() const { | |
| + return _toggleAnimation.animating(); | |
| +} | |
| + | |
| ToggleView::ToggleView( | |
| const style::Toggle &st, | |
| bool checked, | |
| @@ -253,7 +263,7 @@ | |
| } | |
| void CheckView::setUntoggledOverride( | |
| - base::optional<QColor> untoggledOverride) { | |
| + std::optional<QColor> untoggledOverride) { | |
| _untoggledOverride = untoggledOverride; | |
| update(); | |
| } | |
| @@ -278,9 +288,13 @@ | |
| PainterHighQualityEnabler hq(p); | |
| auto toggled = currentAnimationValue(ms); | |
| - auto pen = _untoggledOverride | |
| - ? anim::pen(*_untoggledOverride, _st->toggledFg, toggled) | |
| - : anim::pen(_st->untoggledFg, _st->toggledFg, toggled); | |
| + auto pen = _toggledOverride | |
| + ? (_untoggledOverride | |
| + ? anim::pen(*_untoggledOverride, *_toggledOverride, toggled) | |
| + : anim::pen(_st->untoggledFg, *_toggledOverride, toggled)) | |
| + : (_untoggledOverride | |
| + ? anim::pen(*_untoggledOverride, _st->toggledFg, toggled) | |
| + : anim::pen(_st->untoggledFg, _st->toggledFg, toggled)); | |
| pen.setWidth(_st->thickness); | |
| p.setPen(pen); | |
| p.setBrush(_st->bg); | |
| @@ -290,9 +304,13 @@ | |
| if (toggled > 0) { | |
| p.setPen(Qt::NoPen); | |
| - p.setBrush(_untoggledOverride | |
| - ? anim::brush(*_untoggledOverride, _st->toggledFg, toggled) | |
| - : anim::brush(_st->untoggledFg, _st->toggledFg, toggled)); | |
| + p.setBrush(_toggledOverride | |
| + ? (_untoggledOverride | |
| + ? anim::brush(*_untoggledOverride, *_toggledOverride, toggled) | |
| + : anim::brush(_st->untoggledFg, *_toggledOverride, toggled)) | |
| + : (_untoggledOverride | |
| + ? anim::brush(*_untoggledOverride, _st->toggledFg, toggled) | |
| + : anim::brush(_st->untoggledFg, _st->toggledFg, toggled))); | |
| auto skip0 = _st->diameter / 2., skip1 = _st->skip / 10., checkSkip = skip0 * (1. - toggled) + skip1 * toggled; | |
| p.drawEllipse(rtlrect(QRectF(left, top, _st->diameter, _st->diameter).marginsRemoved(QMarginsF(checkSkip, checkSkip, checkSkip, checkSkip)), outerWidth)); | |
| @@ -322,8 +340,13 @@ | |
| return QRect(QPoint(0, 0), rippleSize()).contains(position); | |
| } | |
| +void RadioView::setToggledOverride(std::optional<QColor> toggledOverride) { | |
| + _toggledOverride = toggledOverride; | |
| + update(); | |
| +} | |
| + | |
| void RadioView::setUntoggledOverride( | |
| - base::optional<QColor> untoggledOverride) { | |
| + std::optional<QColor> untoggledOverride) { | |
| _untoggledOverride = untoggledOverride; | |
| update(); | |
| } | |
| @@ -415,7 +438,7 @@ | |
| void Checkbox::setChecked(bool checked, NotifyAboutChange notify) { | |
| if (_check->checked() != checked) { | |
| - _check->setCheckedAnimated(checked); | |
| + _check->setChecked(checked, anim::type::normal); | |
| if (notify == NotifyAboutChange::Notify) { | |
| checkedChanged.notify(checked, true); | |
| } | |
| @@ -442,10 +465,10 @@ | |
| auto check = checkRect(); | |
| auto ms = getms(); | |
| + auto active = _check->currentAnimationValue(ms); | |
| if (isDisabled()) { | |
| p.setOpacity(_st.disabledOpacity); | |
| } else { | |
| - auto active = _check->currentAnimationValue(ms); | |
| auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active); | |
| paintRipple( | |
| p, | |
| @@ -471,8 +494,7 @@ | |
| auto availableTextWidth = qMax(width() - leftSkip, 1); | |
| if (!_text.isEmpty()) { | |
| - Assert(!(_checkAlignment & Qt::AlignHCenter)); | |
| - p.setPen(_st.textFg); | |
| + p.setPen(anim::pen(_st.textFg, _st.textFgActive, active)); | |
| auto textSkip = _st.checkPosition.x() | |
| + check.width() | |
| + _st.textPosition.x(); | |
| @@ -484,13 +506,21 @@ | |
| textTop, | |
| availableTextWidth, | |
| width()); | |
| - } else { | |
| + } else if (_checkAlignment & Qt::AlignRight) { | |
| _text.drawRightElided( | |
| p, | |
| textSkip, | |
| textTop, | |
| availableTextWidth, | |
| width()); | |
| + } else { | |
| + _text.drawLeft( | |
| + p, | |
| + _st.margin.left(), | |
| + textTop, | |
| + width() - _st.margin.left() - _st.margin.right(), | |
| + width(), | |
| + style::al_top); | |
| } | |
| } | |
| } | |
| @@ -532,7 +562,15 @@ | |
| } | |
| int Checkbox::resizeGetHeight(int newWidth) { | |
| - return _check->getSize().height(); | |
| + const auto result = _check->getSize().height(); | |
| + if (!(_checkAlignment & Qt::AlignHCenter)) { | |
| + return result; | |
| + } | |
| + const auto textBottom = _st.margin.top() | |
| + + _st.textPosition.y() | |
| + + _text.countHeight( | |
| + newWidth - _st.margin.left() - _st.margin.right()); | |
| + return std::max(result, textBottom); | |
| } | |
| QImage Checkbox::prepareRippleMask() const { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/checkbox.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/checkbox.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/checkbox.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/checkbox.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -17,8 +17,7 @@ | |
| public: | |
| AbstractCheckView(int duration, bool checked, Fn<void()> updateCallback); | |
| - void setCheckedFast(bool checked); | |
| - void setCheckedAnimated(bool checked); | |
| + void setChecked(bool checked, anim::type animated); | |
| void finishAnimating(); | |
| void setUpdateCallback(Fn<void()> updateCallback); | |
| bool checked() const { | |
| @@ -26,6 +25,7 @@ | |
| } | |
| void update(); | |
| float64 currentAnimationValue(TimeMs ms); | |
| + bool animating() const; | |
| auto checkedValue() const { | |
| return _checks.events_starting_with(checked()); | |
| @@ -47,6 +47,9 @@ | |
| virtual ~AbstractCheckView() = default; | |
| private: | |
| + virtual void checkedChangedHook(anim::type animated) { | |
| + } | |
| + | |
| int _duration = 0; | |
| bool _checked = false; | |
| Fn<void()> _updateCallback; | |
| @@ -71,13 +74,13 @@ | |
| bool checkRippleStartPosition(QPoint position) const override; | |
| void setUntoggledOverride( | |
| - base::optional<QColor> untoggledOverride); | |
| + std::optional<QColor> untoggledOverride); | |
| private: | |
| QSize rippleSize() const; | |
| not_null<const style::Check*> _st; | |
| - base::optional<QColor> _untoggledOverride; | |
| + std::optional<QColor> _untoggledOverride; | |
| }; | |
| @@ -90,7 +93,8 @@ | |
| void setStyle(const style::Radio &st); | |
| - void setUntoggledOverride(base::optional<QColor> untoggledOverride); | |
| + void setToggledOverride(std::optional<QColor> toggledOverride); | |
| + void setUntoggledOverride(std::optional<QColor> untoggledOverride); | |
| QSize getSize() const override; | |
| void paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) override; | |
| @@ -101,7 +105,8 @@ | |
| QSize rippleSize() const; | |
| not_null<const style::Radio*> _st; | |
| - base::optional<QColor> _untoggledOverride; | |
| + std::optional<QColor> _toggledOverride; | |
| + std::optional<QColor> _untoggledOverride; | |
| }; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/continuous_sliders.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/continuous_sliders.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/continuous_sliders.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/continuous_sliders.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -130,6 +130,43 @@ | |
| } | |
| void disablePaint(bool disabled); | |
| + template < | |
| + typename Value, | |
| + typename Convert, | |
| + typename Callback, | |
| + typename = std::enable_if_t< | |
| + rpl::details::is_callable_plain_v<Callback, Value> | |
| + && std::is_same_v<Value, decltype(std::declval<Convert>()(1))>>> | |
| + void setPseudoDiscrete( | |
| + int valuesCount, | |
| + Convert &&convert, | |
| + Value current, | |
| + Callback &&callback) { | |
| + Expects(valuesCount > 1); | |
| + | |
| + setAlwaysDisplayMarker(true); | |
| + setDirection(Ui::ContinuousSlider::Direction::Horizontal); | |
| + | |
| + const auto sectionsCount = (valuesCount - 1); | |
| + for (auto index = index_type(); index != valuesCount; ++index) { | |
| + if (current <= convert(index)) { | |
| + setValue(index / float64(sectionsCount)); | |
| + break; | |
| + } | |
| + } | |
| + setAdjustCallback([=](float64 value) { | |
| + return std::round(value * sectionsCount) / sectionsCount; | |
| + }); | |
| + setChangeProgressCallback([ | |
| + =, | |
| + convert = std::forward<Convert>(convert), | |
| + callback = std::forward<Callback>(callback) | |
| + ](float64 value) { | |
| + const auto index = int(std::round(value * sectionsCount)); | |
| + callback(convert(index)); | |
| + }); | |
| + } | |
| + | |
| protected: | |
| void paintEvent(QPaintEvent *e) override; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/input_fields.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/input_fields.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/input_fields.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/input_fields.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -15,6 +15,7 @@ | |
| #include "lang/lang_keys.h" | |
| #include "mainwindow.h" | |
| #include "numbers.h" | |
| +#include "auth_session.h" | |
| #include "messenger.h" | |
| namespace Ui { | |
| @@ -2851,7 +2852,7 @@ | |
| int from, | |
| int till, | |
| const QString &with, | |
| - base::optional<QString> checkOriginal) { | |
| + std::optional<QString> checkOriginal) { | |
| const auto original = getTextWithTagsPart(from, till).text; | |
| if (checkOriginal | |
| && checkOriginal->compare(original, Qt::CaseInsensitive) != 0) { | |
| @@ -4122,10 +4123,11 @@ | |
| void PhoneInput::clearText() { | |
| QString phone; | |
| - if (App::self()) { | |
| - QVector<int> newPattern = phoneNumberParse(App::self()->phone()); | |
| + if (AuthSession::Exists()) { | |
| + const auto self = Auth().user(); | |
| + QVector<int> newPattern = phoneNumberParse(self->phone()); | |
| if (!newPattern.isEmpty()) { | |
| - phone = App::self()->phone().mid(0, newPattern.at(0)); | |
| + phone = self->phone().mid(0, newPattern.at(0)); | |
| } | |
| } | |
| setText(phone); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/input_fields.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/input_fields.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/input_fields.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/input_fields.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -221,7 +221,7 @@ | |
| int from, | |
| int till, | |
| const QString &with, | |
| - base::optional<QString> checkOriginal = base::none); | |
| + std::optional<QString> checkOriginal = std::nullopt); | |
| bool commitMarkdownReplacement( | |
| int from, | |
| int till, | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/menu.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/menu.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/menu.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/menu.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -132,7 +132,7 @@ | |
| auto updateCallback = [this, index] { updateItem(index); }; | |
| if (data.toggle) { | |
| data.toggle->setUpdateCallback(updateCallback); | |
| - data.toggle->setCheckedAnimated(action->isChecked()); | |
| + data.toggle->setChecked(action->isChecked(), anim::type::normal); | |
| } else { | |
| data.toggle = std::make_unique<ToggleView>(_st.itemToggle, action->isChecked(), updateCallback); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/separate_panel.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/separate_panel.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/separate_panel.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/separate_panel.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -87,13 +87,15 @@ | |
| rpl::producer<> SeparatePanel::backRequests() const { | |
| return rpl::merge( | |
| - _back->entity()->clicks(), | |
| + _back->entity()->clicks( | |
| + ) | rpl::map([] { return rpl::empty_value(); }), | |
| _synteticBackRequests.events()); | |
| } | |
| rpl::producer<> SeparatePanel::closeRequests() const { | |
| return rpl::merge( | |
| - _close->clicks(), | |
| + _close->clicks( | |
| + ) | rpl::map([] { return rpl::empty_value(); }), | |
| _userCloseRequests.events()); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/widgets.style work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/widgets.style | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/widgets/widgets.style 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/widgets/widgets.style 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -142,6 +142,7 @@ | |
| Checkbox { | |
| textFg: color; | |
| + textFgActive: color; | |
| width: pixels; | |
| margin: margins; | |
| @@ -754,8 +755,8 @@ | |
| duration: 120; | |
| border: 2px; | |
| shift: 1px; | |
| - diameter: 20px; | |
| - width: 16px; | |
| + diameter: 16px; | |
| + width: 14px; | |
| xsize: 0px; | |
| vsize: 0px; | |
| vshift: 0px; | |
| @@ -888,6 +889,18 @@ | |
| shadow: defaultRoundShadow; | |
| } | |
| +defaultContinuousSlider: MediaSlider { | |
| + width: 3px; | |
| + activeFg: mediaPlayerActiveFg; | |
| + inactiveFg: mediaPlayerInactiveFg; | |
| + activeFgOver: mediaPlayerActiveFg; | |
| + inactiveFgOver: mediaPlayerInactiveFg; | |
| + activeFgDisabled: mediaPlayerInactiveFg; | |
| + inactiveFgDisabled: windowBg; | |
| + seekSize: size(9px, 9px); | |
| + duration: 150; | |
| +} | |
| + | |
| defaultRoundCheckbox: RoundCheckbox { | |
| border: windowBg; | |
| bgActive: windowBgActive; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/wrap/padding_wrap.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/wrap/padding_wrap.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/wrap/padding_wrap.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/wrap/padding_wrap.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -92,7 +92,7 @@ | |
| class FixedHeightWidget : public RpWidget { | |
| public: | |
| - FixedHeightWidget(QWidget *parent, int height) | |
| + explicit FixedHeightWidget(QWidget *parent, int height = 0) | |
| : RpWidget(parent) { | |
| resize(width(), height); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -62,7 +62,7 @@ | |
| + row.widget->heightNoMargins() | |
| + row.margin.bottom(); | |
| } | |
| - return result - margins.bottom(); | |
| + return result; | |
| } | |
| void VerticalLayout::visibleTopBottomUpdated( | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/wrap/wrap.h work/tdesktop-1.4.0/Telegram/SourceFiles/ui/wrap/wrap.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/ui/wrap/wrap.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/ui/wrap/wrap.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -145,12 +145,15 @@ | |
| }; | |
| -class IgnoreMargins : public Wrap<RpWidget> { | |
| +class OverrideMargins : public Wrap<RpWidget> { | |
| using Parent = Wrap<RpWidget>; | |
| public: | |
| - IgnoreMargins(QWidget *parent, object_ptr<RpWidget> &&child) | |
| - : Parent(parent, std::move(child)) { | |
| + OverrideMargins( | |
| + QWidget *parent, | |
| + object_ptr<RpWidget> &&child, | |
| + QMargins margins = QMargins()) | |
| + : Parent(parent, std::move(child)), _margins(margins) { | |
| if (auto weak = wrapped()) { | |
| auto margins = weak->getMargins(); | |
| resizeToWidth(weak->width() | |
| @@ -160,14 +163,14 @@ | |
| } | |
| QMargins getMargins() const override { | |
| - return QMargins(); | |
| + return _margins; | |
| } | |
| protected: | |
| int resizeGetHeight(int newWidth) override { | |
| if (auto weak = wrapped()) { | |
| weak->resizeToWidth(newWidth); | |
| - weak->moveToLeft(0, 0); | |
| + weak->moveToLeft(_margins.left(), _margins.top()); | |
| return weak->heightNoMargins(); | |
| } | |
| return height(); | |
| @@ -177,10 +180,20 @@ | |
| void wrappedSizeUpdated(QSize size) override { | |
| auto margins = wrapped()->getMargins(); | |
| resize( | |
| - size.width() - margins.left() - margins.right(), | |
| - size.height() - margins.top() - margins.bottom()); | |
| + (size.width() | |
| + - margins.left() | |
| + - margins.right() | |
| + + _margins.left() | |
| + + _margins.right()), | |
| + (size.height() | |
| + - margins.top() | |
| + - margins.bottom() | |
| + + _margins.top() | |
| + + _margins.bottom())); | |
| } | |
| + QMargins _margins; | |
| + | |
| }; | |
| } // namespace Ui | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/layer_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/layer_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/layer_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/layer_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -43,7 +43,12 @@ | |
| } | |
| void setLayerBoxes(const QRect &specialLayerBox, const QRect &layerBox); | |
| - void setCacheImages(QPixmap &&bodyCache, QPixmap &&mainMenuCache, QPixmap &&specialLayerCache, QPixmap &&layerCache); | |
| + void setCacheImages( | |
| + QPixmap &&bodyCache, | |
| + QPixmap &&mainMenuCache, | |
| + QPixmap &&specialLayerCache, | |
| + QPixmap &&layerCache); | |
| + void removeBodyCache(); | |
| void startAnimation(Action action); | |
| void skipAnimation(Action action); | |
| void finishAnimating(); | |
| @@ -91,7 +96,11 @@ | |
| }; | |
| -void LayerStackWidget::BackgroundWidget::setCacheImages(QPixmap &&bodyCache, QPixmap &&mainMenuCache, QPixmap &&specialLayerCache, QPixmap &&layerCache) { | |
| +void LayerStackWidget::BackgroundWidget::setCacheImages( | |
| + QPixmap &&bodyCache, | |
| + QPixmap &&mainMenuCache, | |
| + QPixmap &&specialLayerCache, | |
| + QPixmap &&layerCache) { | |
| _bodyCache = std::move(bodyCache); | |
| _mainMenuCache = std::move(mainMenuCache); | |
| _specialLayerCache = std::move(specialLayerCache); | |
| @@ -101,6 +110,13 @@ | |
| setAttribute(Qt::WA_OpaquePaintEvent, !_bodyCache.isNull()); | |
| } | |
| +void LayerStackWidget::BackgroundWidget::removeBodyCache() { | |
| + if (!_bodyCache.isNull()) { | |
| + _bodyCache = {}; | |
| + setAttribute(Qt::WA_OpaquePaintEvent, false); | |
| + } | |
| +} | |
| + | |
| void LayerStackWidget::BackgroundWidget::startAnimation(Action action) { | |
| if (action == Action::ShowMainMenu) { | |
| setMainMenuShown(true); | |
| @@ -135,8 +151,8 @@ | |
| return; | |
| } | |
| _wasAnimating = false; | |
| - _bodyCache = _mainMenuCache = _specialLayerCache = _layerCache = QPixmap(); | |
| - setAttribute(Qt::WA_OpaquePaintEvent, false); | |
| + _mainMenuCache = _specialLayerCache = _layerCache = QPixmap(); | |
| + removeBodyCache(); | |
| if (_doneCallback) { | |
| _doneCallback(); | |
| } | |
| @@ -361,6 +377,10 @@ | |
| if (!layer->closeByOutsideClick()) { | |
| return; | |
| } | |
| + } else if (const auto special = _specialLayer.data()) { | |
| + if (!special->closeByOutsideClick()) { | |
| + return; | |
| + } | |
| } | |
| hideCurrent(anim::type::normal); | |
| } | |
| @@ -385,15 +405,20 @@ | |
| } | |
| void LayerStackWidget::hideTopLayer(anim::type animated) { | |
| - if (_specialLayer) { | |
| + if (_specialLayer || _mainMenu) { | |
| hideLayers(animated); | |
| } else { | |
| hideAll(animated); | |
| } | |
| } | |
| +void LayerStackWidget::removeBodyCache() { | |
| + _background->removeBodyCache(); | |
| + setAttribute(Qt::WA_OpaquePaintEvent, false); | |
| +} | |
| + | |
| bool LayerStackWidget::layerShown() const { | |
| - return _specialLayer || currentLayer(); | |
| + return _specialLayer || currentLayer() || _mainMenu; | |
| } | |
| void LayerStackWidget::setCacheImages() { | |
| @@ -418,7 +443,7 @@ | |
| setFocus(); | |
| } | |
| if (_mainMenu) { | |
| - setAttribute(Qt::WA_OpaquePaintEvent, false); | |
| + removeBodyCache(); | |
| hideChildren(); | |
| bodyCache = Ui::GrabWidget(parentWidget()); | |
| showChildren(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/layer_widget.h work/tdesktop-1.4.0/Telegram/SourceFiles/window/layer_widget.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/layer_widget.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/layer_widget.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -111,6 +111,7 @@ | |
| void hideAll(anim::type animated); | |
| void hideTopLayer(anim::type animated); | |
| void setHideByBackgroundClick(bool hide); | |
| + void removeBodyCache(); | |
| bool showSectionInternal( | |
| not_null<SectionMemento*> memento, | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/notifications_manager_default.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/notifications_manager_default.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/notifications_manager_default.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/notifications_manager_default.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -393,6 +393,9 @@ | |
| } | |
| void Widget::step_shift(float64 ms, bool timer) { | |
| + if (anim::Disabled()) { | |
| + ms += st::notifyFastAnim; | |
| + } | |
| float64 dt = ms / float64(st::notifyFastAnim); | |
| if (dt >= 1) { | |
| a_shift.finish(); | |
| @@ -403,7 +406,18 @@ | |
| } | |
| void Widget::hideSlow() { | |
| - hideAnimated(st::notifySlowHide, anim::easeInCirc); | |
| + if (anim::Disabled()) { | |
| + _hiding = true; | |
| + auto [left, right] = base::make_binary_guard(); | |
| + _hidingDelayed = std::move(left); | |
| + App::CallDelayed(st::notifySlowHide, this, [=, guard = std::move(right)] { | |
| + if (guard.alive() && _hiding) { | |
| + hideFast(); | |
| + } | |
| + }); | |
| + } else { | |
| + hideAnimated(st::notifySlowHide, anim::easeInCirc); | |
| + } | |
| } | |
| void Widget::hideFast() { | |
| @@ -413,6 +427,7 @@ | |
| void Widget::hideStop() { | |
| if (_hiding) { | |
| _hiding = false; | |
| + _hidingDelayed = {}; | |
| _a_opacity.start([this] { opacityAnimationCallback(); }, 0., 1., st::notifyFastAnim); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/notifications_manager_default.h work/tdesktop-1.4.0/Telegram/SourceFiles/window/notifications_manager_default.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/notifications_manager_default.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/notifications_manager_default.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -145,6 +145,7 @@ | |
| bool _hiding = false; | |
| bool _deleted = false; | |
| + base::binary_guard _hidingDelayed; | |
| Animation _a_opacity; | |
| QPoint _startPosition; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -310,7 +310,9 @@ | |
| bool EditorBlock::selectSkip(int direction) { | |
| _mouseSelection = false; | |
| - auto maxSelected = (isSearch() ? _searchResults.size() : _data.size()) - 1; | |
| + auto maxSelected = size_type(isSearch() | |
| + ? _searchResults.size() | |
| + : _data.size()) - 1; | |
| auto newSelected = _selected + direction; | |
| if (newSelected < -1 || newSelected > maxSelected) { | |
| newSelected = maxSelected; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme_editor.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme_editor.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme_editor.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme_editor.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -14,7 +14,6 @@ | |
| #include "storage/localstorage.h" | |
| #include "boxes/confirm_box.h" | |
| #include "styles/style_window.h" | |
| -#include "styles/style_settings.h" | |
| #include "styles/style_dialogs.h" | |
| #include "styles/style_boxes.h" | |
| #include "ui/widgets/scroll_area.h" | |
| @@ -391,10 +390,10 @@ | |
| void Editor::Inner::paintEvent(QPaintEvent *e) { | |
| Painter p(this); | |
| - p.setFont(st::settingsFixedBarFont); | |
| + p.setFont(st::boxTitleFont); | |
| p.setPen(st::windowFg); | |
| if (!_newRows->isHidden()) { | |
| - p.drawTextLeft(st::themeEditorMargin.left(), _existingRows->y() + _existingRows->height() + st::settingsFixedBarTextPosition.y(), width(), lang(lng_theme_editor_new_keys)); | |
| + p.drawTextLeft(st::themeEditorMargin.left(), _existingRows->y() + _existingRows->height() + st::boxLayerTitlePosition.y(), width(), lang(lng_theme_editor_new_keys)); | |
| } | |
| } | |
| @@ -404,7 +403,7 @@ | |
| _newRows->resizeToWidth(rowsWidth); | |
| _existingRows->moveToLeft(0, 0); | |
| - _newRows->moveToLeft(0, _existingRows->height() + st::settingsFixedBarHeight); | |
| + _newRows->moveToLeft(0, _existingRows->height() + st::boxLayerTitleHeight); | |
| auto lowest = (_newRows->isHidden() ? _existingRows : _newRows).data(); | |
| @@ -573,7 +572,7 @@ | |
| addButton(langFactory(lng_theme_editor_export), [this] { exportTheme(); }); | |
| addButton(langFactory(lng_cancel), [this] { closeBox(); }); | |
| - auto height = st::settingsSmallSkip + st::settingsBackgroundSize + st::settingsSmallSkip + _tileBackground->height(); | |
| + auto height = st::themesSmallSkip + st::themesBackgroundSize + st::themesSmallSkip + _tileBackground->height(); | |
| setDimensions(st::boxWideWidth, height); | |
| @@ -585,23 +584,23 @@ | |
| Painter p(this); | |
| - auto linkLeft = st::boxPadding.left() + st::settingsBackgroundSize + st::settingsSmallSkip; | |
| + auto linkLeft = st::boxPadding.left() + st::themesBackgroundSize + st::themesSmallSkip; | |
| p.setPen(st::boxTextFg); | |
| p.setFont(st::boxTextFont); | |
| - p.drawTextLeft(linkLeft, st::settingsSmallSkip, width(), _imageText); | |
| + p.drawTextLeft(linkLeft, st::themesSmallSkip, width(), _imageText); | |
| - p.drawPixmapLeft(st::boxPadding.left(), st::settingsSmallSkip, width(), _thumbnail); | |
| + p.drawPixmapLeft(st::boxPadding.left(), st::themesSmallSkip, width(), _thumbnail); | |
| } | |
| void ThemeExportBox::resizeEvent(QResizeEvent *e) { | |
| - auto linkLeft = st::boxPadding.left() + st::settingsBackgroundSize + st::settingsSmallSkip; | |
| - _chooseFromFile->moveToLeft(linkLeft, st::settingsSmallSkip + st::boxTextFont->height + st::settingsSmallSkip); | |
| - _tileBackground->moveToLeft(st::boxPadding.left(), st::settingsSmallSkip + st::settingsBackgroundSize + 2 * st::settingsSmallSkip); | |
| + auto linkLeft = st::boxPadding.left() + st::themesBackgroundSize + st::themesSmallSkip; | |
| + _chooseFromFile->moveToLeft(linkLeft, st::themesSmallSkip + st::boxTextFont->height + st::themesSmallSkip); | |
| + _tileBackground->moveToLeft(st::boxPadding.left(), st::themesSmallSkip + st::themesBackgroundSize + 2 * st::themesSmallSkip); | |
| } | |
| void ThemeExportBox::updateThumbnail() { | |
| - int32 size = st::settingsBackgroundSize * cIntRetinaFactor(); | |
| + int32 size = st::themesBackgroundSize * cIntRetinaFactor(); | |
| QImage back(size, size, QImage::Format_ARGB32_Premultiplied); | |
| back.setDevicePixelRatio(cRetinaFactor()); | |
| { | |
| @@ -612,7 +611,7 @@ | |
| int sx = (pix.width() > pix.height()) ? ((pix.width() - pix.height()) / 2) : 0; | |
| int sy = (pix.height() > pix.width()) ? ((pix.height() - pix.width()) / 2) : 0; | |
| int s = (pix.width() > pix.height()) ? pix.height() : pix.width(); | |
| - p.drawImage(QRect(0, 0, st::settingsBackgroundSize, st::settingsBackgroundSize), pix, QRect(sx, sy, s, s)); | |
| + p.drawImage(QRect(0, 0, st::themesBackgroundSize, st::themesBackgroundSize), pix, QRect(sx, sy, s, s)); | |
| } | |
| Images::prepareRound(back, ImageRoundRadius::Small); | |
| _thumbnail = App::pixmapFromImageInPlace(std::move(back)); | |
| @@ -690,7 +689,7 @@ | |
| } | |
| Editor::Editor(QWidget*, const QString &path) | |
| -: _scroll(this, st::settingsScroll) | |
| +: _scroll(this, st::themesScroll) | |
| , _close(this, st::contactsMultiSelect.fieldCancel) | |
| , _select(this, st::contactsMultiSelect, langFactory(lng_country_ph)) | |
| , _leftShadow(this) | |
| @@ -779,7 +778,7 @@ | |
| p.fillRect(e->rect(), st::dialogsBg); | |
| - p.setFont(st::settingsFixedBarFont); | |
| + p.setFont(st::boxTitleFont); | |
| p.setPen(st::windowFg); | |
| p.drawTextLeft(st::themeEditorMargin.left(), st::themeEditorMargin.top(), width(), lang(lng_theme_editor_title)); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -33,6 +33,7 @@ | |
| QByteArray content; | |
| QByteArray paletteForRevert; | |
| Cached cached; | |
| + Fn<void()> overrideKeep; | |
| }; | |
| ChatBackground background; | |
| @@ -336,24 +337,6 @@ | |
| color.set(original.red(), original.green(), original.blue(), original.alpha()); | |
| } | |
| -void ApplyDefaultWithNightMode(bool nightMode) { | |
| - if (nightMode) { | |
| - if (auto preview = PreviewFromFile(NightThemePath())) { | |
| - Apply(std::move(preview)); | |
| - } | |
| - } else { | |
| - instance.createIfNull(); | |
| - instance->applying.pathRelative = QString(); | |
| - instance->applying.pathAbsolute = QString(); | |
| - instance->applying.content = QByteArray(); | |
| - instance->applying.cached = Cached(); | |
| - if (instance->applying.paletteForRevert.isEmpty()) { | |
| - instance->applying.paletteForRevert = style::main_palette::save(); | |
| - } | |
| - Background()->setTestingDefaultTheme(); | |
| - } | |
| -} | |
| - | |
| void WriteAppliedTheme() { | |
| auto saved = Saved(); | |
| saved.pathRelative = instance->applying.pathRelative; | |
| @@ -723,6 +706,13 @@ | |
| || _id != kDefaultBackground); | |
| } | |
| +bool ChatBackground::isNonDefaultBackground() { | |
| + start(); | |
| + return _themeAbsolutePath.isEmpty() | |
| + ? (_id != kDefaultBackground) | |
| + : (_id != kThemeBackground); | |
| +} | |
| + | |
| void ChatBackground::writeNewBackgroundSettings() { | |
| if (tile() != _tileForRevert) { | |
| Local::writeUserSettings(); | |
| @@ -755,11 +745,12 @@ | |
| return _nightMode; | |
| } | |
| -void ChatBackground::toggleNightMode() { | |
| +void ChatBackground::toggleNightMode(std::optional<QString> themePath) { | |
| + const auto settingDefault = themePath.has_value(); | |
| const auto oldNightMode = _nightMode; | |
| const auto newNightMode = !_nightMode; | |
| _nightMode = newNightMode; | |
| - auto read = Local::readThemeAfterSwitch(); | |
| + auto read = settingDefault ? Saved() : Local::readThemeAfterSwitch(); | |
| auto path = read.pathAbsolute; | |
| _nightMode = oldNightMode; | |
| @@ -784,30 +775,34 @@ | |
| return true; | |
| }(); | |
| if (!alreadyOnDisk) { | |
| - path = newNightMode ? NightThemePath() : QString(); | |
| - ApplyDefaultWithNightMode(newNightMode); | |
| + path = themePath | |
| + ? *themePath | |
| + : (newNightMode ? NightThemePath() : QString()); | |
| + ApplyDefaultWithPath(path); | |
| } | |
| // Theme editor could have already reverted the testing of this toggle. | |
| if (AreTestingTheme()) { | |
| - _nightMode = newNightMode; | |
| + instance->applying.overrideKeep = [=] { | |
| + _nightMode = newNightMode; | |
| - // Restore the value, it was set inside theme testing. | |
| - (oldNightMode ? _tileNightValue : _tileDayValue) = oldTileValue; | |
| + // Restore the value, it was set inside theme testing. | |
| + (oldNightMode ? _tileNightValue : _tileDayValue) = oldTileValue; | |
| - if (!alreadyOnDisk) { | |
| - // First-time switch to default night mode should write it. | |
| - WriteAppliedTheme(); | |
| - } | |
| - ClearApplying(); | |
| - keepApplied(path, false); | |
| - if (tile() != _tileForRevert) { | |
| - Local::writeUserSettings(); | |
| - } | |
| - Local::writeSettings(); | |
| - if (!Local::readBackground()) { | |
| - setImage(kThemeBackground); | |
| - } | |
| + if (!alreadyOnDisk) { | |
| + // First-time switch to default night mode should write it. | |
| + WriteAppliedTheme(); | |
| + } | |
| + ClearApplying(); | |
| + keepApplied(path, settingDefault); | |
| + if (tile() != _tileForRevert) { | |
| + Local::writeUserSettings(); | |
| + } | |
| + Local::writeSettings(); | |
| + if (!settingDefault && !Local::readBackground()) { | |
| + setImage(kThemeBackground); | |
| + } | |
| + }; | |
| } | |
| } | |
| @@ -863,7 +858,25 @@ | |
| } | |
| void ApplyDefault() { | |
| - ApplyDefaultWithNightMode(IsNightMode()); | |
| + ApplyDefaultWithPath(IsNightMode() ? NightThemePath() : QString()); | |
| +} | |
| + | |
| +void ApplyDefaultWithPath(const QString &themePath) { | |
| + if (!themePath.isEmpty()) { | |
| + if (auto preview = PreviewFromFile(themePath)) { | |
| + Apply(std::move(preview)); | |
| + } | |
| + } else { | |
| + instance.createIfNull(); | |
| + instance->applying.pathRelative = QString(); | |
| + instance->applying.pathAbsolute = QString(); | |
| + instance->applying.content = QByteArray(); | |
| + instance->applying.cached = Cached(); | |
| + if (instance->applying.paletteForRevert.isEmpty()) { | |
| + instance->applying.paletteForRevert = style::main_palette::save(); | |
| + } | |
| + Background()->setTestingDefaultTheme(); | |
| + } | |
| } | |
| bool ApplyEditedPalette(const QString &path, const QByteArray &content) { | |
| @@ -895,6 +908,13 @@ | |
| void KeepApplied() { | |
| if (!AreTestingTheme()) { | |
| return; | |
| + } else if (instance->applying.overrideKeep) { | |
| + // This callback will be destroyed while running. | |
| + // And it won't be able to safely access captures after that. | |
| + // So we save it on stack for the time while it is running. | |
| + const auto saved = base::take(instance->applying.overrideKeep); | |
| + saved(); | |
| + return; | |
| } | |
| const auto path = instance->applying.pathAbsolute; | |
| WriteAppliedTheme(); | |
| @@ -921,6 +941,10 @@ | |
| return Background()->isNonDefaultThemeOrBackground(); | |
| } | |
| +bool IsNonDefaultBackground() { | |
| + return Background()->isNonDefaultBackground(); | |
| +} | |
| + | |
| bool IsNightMode() { | |
| return instance ? Background()->nightMode() : false; | |
| } | |
| @@ -932,7 +956,11 @@ | |
| } | |
| void ToggleNightMode() { | |
| - Background()->toggleNightMode(); | |
| + Background()->toggleNightMode(std::nullopt); | |
| +} | |
| + | |
| +void ToggleNightMode(const QString &path) { | |
| + Background()->toggleNightMode(path); | |
| } | |
| bool SuggestThemeReset() { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme.h work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/themes/window_theme.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/themes/window_theme.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -57,12 +57,15 @@ | |
| bool Apply(const QString &filepath); | |
| bool Apply(std::unique_ptr<Preview> preview); | |
| void ApplyDefault(); | |
| +void ApplyDefaultWithPath(const QString &themePath); | |
| bool ApplyEditedPalette(const QString &path, const QByteArray &content); | |
| void KeepApplied(); | |
| QString NightThemePath(); | |
| bool IsNightMode(); | |
| void SetNightModeValue(bool nightMode); | |
| void ToggleNightMode(); | |
| +void ToggleNightMode(const QString &themePath); | |
| +bool IsNonDefaultBackground(); | |
| bool IsNonDefaultThemeOrBackground(); | |
| bool SuggestThemeReset(); | |
| void Revert(); | |
| @@ -140,14 +143,17 @@ | |
| void setNightModeValue(bool nightMode); | |
| bool nightMode() const; | |
| - void toggleNightMode(); | |
| + void toggleNightMode(std::optional<QString> themePath); | |
| void keepApplied(const QString &path, bool write); | |
| bool isNonDefaultThemeOrBackground(); | |
| + bool isNonDefaultBackground(); | |
| friend bool IsNightMode(); | |
| friend void SetNightModeValue(bool nightMode); | |
| friend void ToggleNightMode(); | |
| + friend void ToggleNightMode(const QString &themePath); | |
| friend void KeepApplied(); | |
| + friend bool IsNonDefaultBackground(); | |
| friend bool IsNonDefaultThemeOrBackground(); | |
| int32 _id = internal::kUninitializedBackground; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_connecting_widget.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_connecting_widget.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_connecting_widget.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_connecting_widget.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -59,7 +59,7 @@ | |
| } | |
| void Progress::step(TimeMs ms, bool timer) { | |
| - if (timer) { | |
| + if (timer && !anim::Disabled()) { | |
| update(); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_controller.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_controller.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_controller.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_controller.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -9,6 +9,7 @@ | |
| #include "window/main_window.h" | |
| #include "info/info_memento.h" | |
| +#include "info/info_controller.h" | |
| #include "history/history.h" | |
| #include "history/history_item.h" | |
| #include "history/view/history_view_element.h" | |
| @@ -473,6 +474,20 @@ | |
| showPeerInfo(history->peer->id, params); | |
| } | |
| +void Navigation::showSettings( | |
| + Settings::Type type, | |
| + const SectionShow ¶ms) { | |
| + showSection( | |
| + Info::Memento( | |
| + Info::Settings::Tag{ Auth().user() }, | |
| + Info::Section(type)), | |
| + params); | |
| +} | |
| + | |
| +void Navigation::showSettings(const SectionShow ¶ms) { | |
| + showSettings(Settings::Type::Main, params); | |
| +} | |
| + | |
| void Controller::showSection( | |
| SectionMemento &&memento, | |
| const SectionShow ¶ms) { | |
| @@ -494,6 +509,10 @@ | |
| App::wnd()->showSpecialLayer(std::move(layer), animated); | |
| } | |
| +void Controller::removeLayerBlackout() { | |
| + App::wnd()->ui_removeLayerBlackout(); | |
| +} | |
| + | |
| not_null<MainWidget*> Controller::chats() const { | |
| return App::wnd()->chatsWidget(); | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_controller.h work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_controller.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_controller.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_controller.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -15,6 +15,10 @@ | |
| class HistoryMessage; | |
| class HistoryService; | |
| +namespace Settings { | |
| +enum class Type; | |
| +} // namespace Settings | |
| + | |
| namespace Media { | |
| namespace Player { | |
| class RoundController; | |
| @@ -114,6 +118,11 @@ | |
| not_null<History*> history, | |
| const SectionShow ¶ms = SectionShow()); | |
| + void showSettings( | |
| + Settings::Type type, | |
| + const SectionShow ¶ms = SectionShow()); | |
| + void showSettings(const SectionShow ¶ms = SectionShow()); | |
| + | |
| virtual ~Navigation() = default; | |
| }; | |
| @@ -200,6 +209,7 @@ | |
| anim::type animated = anim::type::normal) { | |
| showSpecialLayer(nullptr, animated); | |
| } | |
| + void removeLayerBlackout(); | |
| void showJumpToDate( | |
| Dialogs::Key chat, | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_lock_widgets.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_lock_widgets.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_lock_widgets.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_lock_widgets.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -179,7 +179,7 @@ | |
| TextUtilities::EntitiesFromMTP(data.ventities.v) }, | |
| (data.has_min_age_confirm() | |
| ? base::make_optional(data.vmin_age_confirm.v) | |
| - : base::none), | |
| + : std::nullopt), | |
| data.is_popup() | |
| }; | |
| } | |
| @@ -200,7 +200,7 @@ | |
| Fn<QString()> agree, | |
| Fn<QString()> cancel, | |
| bool attentionAgree) | |
| -: _data{ {}, text, base::none, false } | |
| +: _data{ {}, text, std::nullopt, false } | |
| , _agree(agree) | |
| , _cancel(cancel) | |
| , _attentionAgree(attentionAgree) { | |
| @@ -263,7 +263,7 @@ | |
| const auto error = _ageErrorAnimation.current( | |
| _ageErrorShown ? 1. : 0.); | |
| if (error == 0.) { | |
| - check->setUntoggledOverride(base::none); | |
| + check->setUntoggledOverride(std::nullopt); | |
| } else { | |
| const auto color = anim::color( | |
| st::defaultCheck.untoggledFg, | |
| @@ -293,11 +293,15 @@ | |
| return false; | |
| } | |
| return true; | |
| + }) | rpl::map([] { | |
| + return rpl::empty_value(); | |
| }) | rpl::start_to_stream(_agreeClicks, lifetime()); | |
| if (_cancel) { | |
| addButton(_cancel, [=] {})->clicks( | |
| - ) | rpl::start_to_stream(_cancelClicks, lifetime()); | |
| + ) | rpl::map([] { | |
| + return rpl::empty_value(); | |
| + }) | rpl::start_to_stream(_cancelClicks, lifetime()); | |
| } | |
| if (age) { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_lock_widgets.h work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_lock_widgets.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_lock_widgets.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_lock_widgets.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -66,7 +66,7 @@ | |
| struct TermsLock { | |
| bytes::vector id; | |
| TextWithEntities text; | |
| - base::optional<int> minAge; | |
| + std::optional<int> minAge; | |
| bool popup = false; | |
| inline bool operator==(const TermsLock &other) const { | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_main_menu.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_main_menu.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_main_menu.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_main_menu.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -38,16 +38,27 @@ | |
| , _version(this, st::mainMenuVersionLabel) { | |
| setAttribute(Qt::WA_OpaquePaintEvent); | |
| - subscribe(Global::RefSelfChanged(), [this] { | |
| - checkSelf(); | |
| - }); | |
| - checkSelf(); | |
| + auto showSelfChat = [] { | |
| + App::main()->choosePeer(Auth().userPeerId(), ShowAtUnreadMsgId); | |
| + }; | |
| + _userpicButton.create( | |
| + this, | |
| + _controller, | |
| + Auth().user(), | |
| + Ui::UserpicButton::Role::Custom, | |
| + st::mainMenuUserpic); | |
| + _userpicButton->setClickedCallback(showSelfChat); | |
| + _userpicButton->show(); | |
| + _cloudButton.create(this, st::mainMenuCloudButton); | |
| + _cloudButton->setClickedCallback(showSelfChat); | |
| + _cloudButton->show(); | |
| _nightThemeSwitch.setCallback([this] { | |
| if (const auto action = *_nightThemeAction) { | |
| const auto nightMode = Window::Theme::IsNightMode(); | |
| if (action->isChecked() != nightMode) { | |
| Window::Theme::ToggleNightMode(); | |
| + Window::Theme::KeepApplied(); | |
| } | |
| } | |
| }); | |
| @@ -120,32 +131,6 @@ | |
| updatePhone(); | |
| } | |
| -void MainMenu::checkSelf() { | |
| - if (auto self = App::self()) { | |
| - auto showSelfChat = [] { | |
| - if (auto self = App::self()) { | |
| - App::main()->choosePeer(self->id, ShowAtUnreadMsgId); | |
| - } | |
| - }; | |
| - _userpicButton.create( | |
| - this, | |
| - _controller, | |
| - self, | |
| - Ui::UserpicButton::Role::Custom, | |
| - st::mainMenuUserpic); | |
| - _userpicButton->setClickedCallback(showSelfChat); | |
| - _userpicButton->show(); | |
| - _cloudButton.create(this, st::mainMenuCloudButton); | |
| - _cloudButton->setClickedCallback(showSelfChat); | |
| - _cloudButton->show(); | |
| - update(); | |
| - updateControlsGeometry(); | |
| - } else { | |
| - _userpicButton.destroy(); | |
| - _cloudButton.destroy(); | |
| - } | |
| -} | |
| - | |
| void MainMenu::resizeEvent(QResizeEvent *e) { | |
| _menu->setForceWidth(width()); | |
| updateControlsGeometry(); | |
| @@ -164,11 +149,7 @@ | |
| } | |
| void MainMenu::updatePhone() { | |
| - if (auto self = App::self()) { | |
| - _phoneText = App::formatPhone(self->phone()); | |
| - } else { | |
| - _phoneText = QString(); | |
| - } | |
| + _phoneText = App::formatPhone(Auth().user()->phone()); | |
| update(); | |
| } | |
| @@ -180,11 +161,14 @@ | |
| p.fillRect(cover, st::mainMenuCoverBg); | |
| p.setPen(st::mainMenuCoverFg); | |
| p.setFont(st::semiboldFont); | |
| - if (auto self = App::self()) { | |
| - self->nameText.drawLeftElided(p, st::mainMenuCoverTextLeft, st::mainMenuCoverNameTop, width() - 2 * st::mainMenuCoverTextLeft, width()); | |
| - p.setFont(st::normalFont); | |
| - p.drawTextLeft(st::mainMenuCoverTextLeft, st::mainMenuCoverStatusTop, width(), _phoneText); | |
| - } | |
| + Auth().user()->nameText.drawLeftElided( | |
| + p, | |
| + st::mainMenuCoverTextLeft, | |
| + st::mainMenuCoverNameTop, | |
| + width() - 2 * st::mainMenuCoverTextLeft, | |
| + width()); | |
| + p.setFont(st::normalFont); | |
| + p.drawTextLeft(st::mainMenuCoverTextLeft, st::mainMenuCoverStatusTop, width(), _phoneText); | |
| if (_cloudButton) { | |
| Ui::EmptyUserpic::PaintSavedMessages( | |
| p, | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_main_menu.h work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_main_menu.h | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_main_menu.h 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_main_menu.h 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -33,7 +33,6 @@ | |
| void resizeEvent(QResizeEvent *e) override; | |
| private: | |
| - void checkSelf(); | |
| void updateControlsGeometry(); | |
| void updatePhone(); | |
| void refreshMenu(); | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_peer_menu.cpp work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_peer_menu.cpp | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window_peer_menu.cpp 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window_peer_menu.cpp 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -352,7 +352,7 @@ | |
| _addAction( | |
| lang(lng_profile_clear_history), | |
| ClearHistoryHandler(user)); | |
| - if (!user->isInaccessible() && user != App::self()) { | |
| + if (!user->isInaccessible() && user != Auth().user()) { | |
| addBlockUser(user); | |
| } | |
| } | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window.style work/tdesktop-1.4.0/Telegram/SourceFiles/window/window.style | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/SourceFiles/window/window.style 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/SourceFiles/window/window.style 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -113,7 +113,7 @@ | |
| itemFg: windowBoldFg; | |
| itemFgOver: windowBoldFgOver; | |
| itemFont: semiboldFont; | |
| - itemIconPosition: point(28px, 10px); | |
| + itemIconPosition: point(26px, 8px); | |
| itemPadding: margins(76px, 13px, 28px, 13px); | |
| itemToggle: Toggle(defaultMenuToggle) { | |
| toggledFg: mainMenuCoverBg; | |
| @@ -127,10 +127,10 @@ | |
| mainMenuNewGroupOver: icon {{ "menu_new_group", menuIconFgOver }}; | |
| mainMenuNewChannel: icon {{ "menu_new_channel", menuIconFg }}; | |
| mainMenuNewChannelOver: icon {{ "menu_new_channel", menuIconFgOver }}; | |
| -mainMenuContacts: icon {{ "menu_contacts", menuIconFg }}; | |
| -mainMenuContactsOver: icon {{ "menu_contacts", menuIconFgOver }}; | |
| -mainMenuCalls: icon {{ "menu_calls", menuIconFg }}; | |
| -mainMenuCallsOver: icon {{ "menu_calls", menuIconFgOver }}; | |
| +mainMenuContacts: icon {{ "settings_name", menuIconFg }}; | |
| +mainMenuContactsOver: icon {{ "settings_name", menuIconFgOver }}; | |
| +mainMenuCalls: icon {{ "settings_phone_number", menuIconFg }}; | |
| +mainMenuCallsOver: icon {{ "settings_phone_number", menuIconFgOver }}; | |
| mainMenuSettings: icon {{ "menu_settings", menuIconFg }}; | |
| mainMenuSettingsOver: icon {{ "menu_settings", menuIconFgOver }}; | |
| mainMenuNightMode: icon {{ "menu_night_mode", menuIconFg }}; | |
| diff -ur work.1.3.14/tdesktop-1.3.14/Telegram/Telegram.plist work/tdesktop-1.4.0/Telegram/Telegram.plist | |
| --- work.1.3.14/tdesktop-1.3.14/Telegram/Telegram.plist 2018-08-28 00:07:59.000000000 +0800 | |
| +++ work/tdesktop-1.4.0/Telegram/Telegram.plist 2018-09-28 21:08:38.000000000 +0800 | |
| @@ -37,6 +37,8 @@ | |
| <string>$(MACOSX_DEPLOYMENT_TARGET)</string> | |
| <key>NOTE</key> | |
| <string></string> | |
| + <key>NSMicrophoneUsageDescription</key> | |
| + <string>We need access to your microphone so that you can record voice messages and make calls.</string> | |
| <key>NSPrincipalClass</key> | |
| <string>NSApplication</string> | |
| <key>NSSupportsAutomaticGraphicsSwitching</key> | |
| Only in work/tdesktop-1.4.0/Telegram/ThirdParty: xxHash |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment