From 532e7e7e81de6340b13a04a6c49cd60d7c0bf746 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Tue, 29 Mar 2016 20:48:54 +0300 Subject: [PATCH 01/17] Fixed crash when trying to update selected state in HistoryInner while _history/_migrated had pending resize items. --- Telegram/SourceFiles/historywidget.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 902fe59c5..0f4017583 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -197,6 +197,16 @@ void HistoryInner::paintEvent(QPaintEvent *e) { if (!App::main()) return; + if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) { + Notify::handlePendingHistoryUpdate(); + if (_history) { + t_assert(!_history->hasPendingResizedItems()); + } + if (_migrated) { + t_assert(!_migrated->hasPendingResizedItems()); + } + } + Painter p(this); QRect r(e->rect()); bool trivial = (rect() == r); @@ -1677,7 +1687,9 @@ void HistoryInner::onTouchSelect() { } void HistoryInner::onUpdateSelected() { - if (!_history) return; + if (!_history || _history->hasPendingResizedItems() || (_migrated && _migrated->hasPendingResizedItems())) { + return; + } QPoint mousePos(mapFromGlobal(_dragPos)); QPoint point(_widget->clampMousePosition(mousePos)); @@ -6286,7 +6298,7 @@ void HistoryWidget::notify_automaticLoadSettingsChangedGif() { } void HistoryWidget::notify_handlePendingHistoryUpdate() { - if (_history && _history->hasPendingResizedItems()) { + if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) { updateListSize(); _list->update(); } From 80365c92075d425b97151af22155b8003dbb7fc8 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Tue, 29 Mar 2016 20:57:27 +0300 Subject: [PATCH 02/17] Receiving a min user now should not force showing him in the conversations list by a phone number instead of his name. --- Telegram/SourceFiles/app.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 4887c2681..731a57ee1 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -437,6 +437,10 @@ namespace App { bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact(); bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact)); + if (minimal) { + showPhoneChanged = false; + showPhone = !isServiceUser(data->id) && (data->id != peerFromUser(MTP::authedId())) && !data->contact; + } // see also Local::readPeer From cd495654573953fa356e1f9e142e20ef4971d18c Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Tue, 29 Mar 2016 21:03:53 +0300 Subject: [PATCH 03/17] Skipping message date height when scrolling to the unread bar. --- Telegram/SourceFiles/history.cpp | 12 +++++++----- Telegram/SourceFiles/historywidget.cpp | 6 ++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 1478fe97c..7ea40b30d 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -377,11 +377,13 @@ bool History::updateTyping(uint64 ms, bool force) { return changed; } -ChannelHistory::ChannelHistory(const PeerId &peer) : History(peer), -unreadCountAll(0), -_onlyImportant(!isMegagroup()), -_otherOldLoaded(false), _otherNewLoaded(true), -_collapseMessage(0), _joinedMessage(0) { +ChannelHistory::ChannelHistory(const PeerId &peer) : History(peer) +, unreadCountAll(0) +, _onlyImportant(!isMegagroup()) +, _otherOldLoaded(false) +, _otherNewLoaded(true) +, _collapseMessage(nullptr) +, _joinedMessage(nullptr) { } bool ChannelHistory::isSwitchReadyFor(MsgId switchId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop) { diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 0f4017583..c8f665649 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -6557,8 +6557,14 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh } } else if (initial && _migrated && _migrated->unreadBar) { toY = _list->itemTop(_migrated->unreadBar); + if (_migrated->unreadBar->Has<HistoryMessageDate>()) { + toY += _migrated->unreadBar->Get<HistoryMessageDate>()->height(); + } } else if (initial && _history->unreadBar) { toY = _list->itemTop(_history->unreadBar); + if (_history->unreadBar->Has<HistoryMessageDate>()) { + toY += _history->unreadBar->Get<HistoryMessageDate>()->height(); + } } else if (_migrated && _migrated->showFrom) { toY = _list->itemTop(_migrated->showFrom); if (toY < _scroll.scrollTopMax() + st::unreadBarHeight) { From 18db57ba963e033a6774dcd833d547c86f4c3ed8 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Wed, 30 Mar 2016 01:35:36 +0400 Subject: [PATCH 04/17] Added a new project codegen_style to the solution. It should replace MetaStyle in the far future. --- .gitignore | 1 + Telegram.sln | 21 ++++- Telegram/SourceFiles/codegen/style/main.cpp | 3 + .../vc/codegen_style/codegen_style.vcxproj | 91 +++++++++++++++++++ .../codegen_style.vcxproj.filters | 28 ++++++ 5 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 Telegram/SourceFiles/codegen/style/main.cpp create mode 100644 Telegram/build/vc/codegen_style/codegen_style.vcxproj create mode 100644 Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters diff --git a/.gitignore b/.gitignore index 94b1d353e..a155d81c7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ /Telegram/SourceFiles/art/sprite_125x.png /Telegram/SourceFiles/art/sprite_150x.png /Telegram/*.user +*.vcxproj.user *.suo *.sdf *.opensdf diff --git a/Telegram.sln b/Telegram.sln index 836d4a043..6487c468a 100644 --- a/Telegram.sln +++ b/Telegram.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Telegram", "Telegram\Telegram.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" ProjectSection(ProjectDependencies) = postProject @@ -18,10 +18,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updater", "Telegram\Updater EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaLang", "Telegram\MetaLang.vcxproj", "{E417CAA4-259B-4C99-88E3-805F1300E8EB}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2F863EAD-33C9-4014-A573-93F085BA9CB1}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "codegen", "codegen", "{2F863EAD-33C9-4014-A573-93F085BA9CB1}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Packer", "Telegram\Packer.vcxproj", "{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "codegen_style", "Telegram\build\vc\codegen_style\codegen_style.vcxproj", "{E4DF8176-4DEF-4859-962F-B497E3E7A323}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -82,8 +84,21 @@ Global {56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Deploy|x64.ActiveCfg = Release|Win32 {56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|Win32.ActiveCfg = Release|Win32 {56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|x64.ActiveCfg = Release|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|Win32.ActiveCfg = Debug|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|Win32.Build.0 = Debug|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|x64.ActiveCfg = Debug|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|Win32.ActiveCfg = Debug|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|Win32.Build.0 = Debug|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|x64.ActiveCfg = Release|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|x64.Build.0 = Release|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|Win32.ActiveCfg = Release|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|Win32.Build.0 = Release|Win32 + {E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {E4DF8176-4DEF-4859-962F-B497E3E7A323} = {2F863EAD-33C9-4014-A573-93F085BA9CB1} + EndGlobalSection EndGlobal diff --git a/Telegram/SourceFiles/codegen/style/main.cpp b/Telegram/SourceFiles/codegen/style/main.cpp new file mode 100644 index 000000000..a553b5173 --- /dev/null +++ b/Telegram/SourceFiles/codegen/style/main.cpp @@ -0,0 +1,3 @@ +int main(int argc, char *argv[]) { + return 0; +} diff --git a/Telegram/build/vc/codegen_style/codegen_style.vcxproj b/Telegram/build/vc/codegen_style/codegen_style.vcxproj new file mode 100644 index 000000000..cfff29554 --- /dev/null +++ b/Telegram/build/vc/codegen_style/codegen_style.vcxproj @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\SourceFiles\codegen\style\main.cpp" /> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E4DF8176-4DEF-4859-962F-B497E3E7A323}</ProjectGuid> + <Keyword>Qt4VSv1.0</Keyword> + <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>14.0.24730.2</_ProjectFileVersion> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <OutDir>$(SolutionDir)$(Platform)\codegen\$(Configuration)\</OutDir> + <IntDir>$(SolutionDir)$(Platform)\obj\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>UNICODE;WIN32;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Optimization>Disabled</Optimization> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <AdditionalIncludeDirectories>.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <AdditionalLibraryDirectories>$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>ws2_32.lib;qtmaind.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;imageformats\qwebpd.lib;Qt5Cored.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>UNICODE;WIN32;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <DebugInformationFormat /> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <AdditionalIncludeDirectories>.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile> + <AdditionalLibraryDirectories>$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <GenerateDebugInformation>false</GenerateDebugInformation> + <AdditionalDependencies>qtmain.lib;Qt5Core.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> + <ProjectExtensions> + <VisualStudio> + <UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" Qt5Version_x0020_Win32="QtStatic" MocOptions="" /> + </VisualStudio> + </ProjectExtensions> +</Project> \ No newline at end of file diff --git a/Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters b/Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters new file mode 100644 index 000000000..3263d5640 --- /dev/null +++ b/Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;cxx;c;def</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier> + <Extensions>qrc;*</Extensions> + <ParseFiles>false</ParseFiles> + </Filter> + <Filter Include="Generated Files"> + <UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier> + <Extensions>moc;h;cpp</Extensions> + <SourceControlFiles>False</SourceControlFiles> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\SourceFiles\codegen\style\main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project> \ No newline at end of file From 00bada8d453269b1d2e60c6272eebb6787f8e4f4 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Wed, 30 Mar 2016 10:17:04 +0400 Subject: [PATCH 05/17] Added C++11 config option to MetaStyle and MetaLang .pro projects. --- Telegram/MetaLang.pro | 2 +- Telegram/MetaStyle.pro | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Telegram/MetaLang.pro b/Telegram/MetaLang.pro index dbef70ae9..0dfa29a6f 100644 --- a/Telegram/MetaLang.pro +++ b/Telegram/MetaLang.pro @@ -12,7 +12,7 @@ CONFIG(release, debug|release) { DESTDIR = ./../ReleaseLang } -CONFIG += plugin static +CONFIG += plugin static c++11 macx { QMAKE_INFO_PLIST = ./SourceFiles/_other/Lang.plist diff --git a/Telegram/MetaStyle.pro b/Telegram/MetaStyle.pro index 2ef67ea2e..a68a44385 100644 --- a/Telegram/MetaStyle.pro +++ b/Telegram/MetaStyle.pro @@ -12,7 +12,7 @@ CONFIG(release, debug|release) { DESTDIR = ./../ReleaseStyle } -CONFIG += plugin static +CONFIG += plugin static c++11 macx { QMAKE_INFO_PLIST = ./SourceFiles/_other/Style.plist From 88282d83645dd8e2901e9474d6b8b3f8977a519e Mon Sep 17 00:00:00 2001 From: Christoph <auer.chrisi@gmx.net> Date: Wed, 30 Mar 2016 21:42:16 +0200 Subject: [PATCH 06/17] Check commit message Signed-off-by: Christoph <auer.chrisi@gmx.net> --- .travis.yml | 4 ++++ .travis/build.sh | 41 +---------------------------------------- .travis/check.sh | 25 +++++++++++++++++++++++++ .travis/common.sh | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 40 deletions(-) create mode 100755 .travis/check.sh create mode 100755 .travis/common.sh diff --git a/.travis.yml b/.travis.yml index 612e30f7a..11f305e48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,5 +39,9 @@ arch: - libtool --finish /usr/lib - .travis/build.sh +before_install: + - "export TRAVIS_COMMIT_MSG=\"$(git log --format=%B --no-merges -n 1)\"" + - .travis/check.sh + script: - .travis/arch.sh \ No newline at end of file diff --git a/.travis/build.sh b/.travis/build.sh index ebbaeffc4..7deae1f95 100755 --- a/.travis/build.sh +++ b/.travis/build.sh @@ -10,23 +10,6 @@ run() { check } -# set colors -RCol='\e[0m' # Text Reset - -# Regular Bold Underline High Intensity BoldHigh Intens Background High Intensity Backgrounds -Bla='\e[0;30m'; BBla='\e[1;30m'; UBla='\e[4;30m'; IBla='\e[0;90m'; BIBla='\e[1;90m'; On_Bla='\e[40m'; On_IBla='\e[0;100m'; -Red='\e[0;31m'; BRed='\e[1;31m'; URed='\e[4;31m'; IRed='\e[0;91m'; BIRed='\e[1;91m'; On_Red='\e[41m'; On_IRed='\e[0;101m'; -Gre='\e[0;32m'; BGre='\e[1;32m'; UGre='\e[4;32m'; IGre='\e[0;92m'; BIGre='\e[1;92m'; On_Gre='\e[42m'; On_IGre='\e[0;102m'; -Yel='\e[0;33m'; BYel='\e[1;33m'; UYel='\e[4;33m'; IYel='\e[0;93m'; BIYel='\e[1;93m'; On_Yel='\e[43m'; On_IYel='\e[0;103m'; -Blu='\e[0;34m'; BBlu='\e[1;34m'; UBlu='\e[4;34m'; IBlu='\e[0;94m'; BIBlu='\e[1;94m'; On_Blu='\e[44m'; On_IBlu='\e[0;104m'; -Pur='\e[0;35m'; BPur='\e[1;35m'; UPur='\e[4;35m'; IPur='\e[0;95m'; BIPur='\e[1;95m'; On_Pur='\e[45m'; On_IPur='\e[0;105m'; -Cya='\e[0;36m'; BCya='\e[1;36m'; UCya='\e[4;36m'; ICya='\e[0;96m'; BICya='\e[1;96m'; On_Cya='\e[46m'; On_ICya='\e[0;106m'; -Whi='\e[0;37m'; BWhi='\e[1;37m'; UWhi='\e[4;37m'; IWhi='\e[0;97m'; BIWhi='\e[1;97m'; On_Whi='\e[47m'; On_IWhi='\e[0;107m'; - -# Set variables -_qtver=5.5.1 -srcdir=${PWD} - downloadLibs() { travis_fold_start "download_libs" # Move telegram project to subfolder @@ -172,28 +155,6 @@ check() { fi } -start_msg() { - echo -e "\n${Gre}$*${RCol}" -} - -info_msg() { - echo -e "\n${Cya}$*${RCol}" -} - -error_msg() { - echo -e "\n${BRed}$*${RCol}" -} - -success_msg() { - echo -e "\n${BGre}$*${RCol}" -} - -travis_fold_start() { - echo "travis_fold:start:$*" -} - -travis_fold_end() { - echo "travis_fold:end:$*" -} +source ./.travis/common.sh run diff --git a/.travis/check.sh b/.travis/check.sh new file mode 100755 index 000000000..3fe7c7fd3 --- /dev/null +++ b/.travis/check.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Checks commit message, ... + +run() { + checkCommitMessage +} + +checkCommitMessage() { + info_msg "Commit message: ${TRAVIS_COMMIT_MSG}"; + info_msg "Is pull request: ${TRAVIS_PULL_REQUEST}"; + + if [[ $TRAVIS_PULL_REQUEST != "false" ]];then + if [[ $TRAVIS_COMMIT_MSG != *"Signed-off-by: "* ]];then + error_msg "The commit message does not contain the signature!" + error_msg "More information: https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work" + exit 1 + else + success_msg "Commit message contains signature" + fi + fi +} + +source ./.travis/common.sh + +run diff --git a/.travis/common.sh b/.travis/common.sh new file mode 100755 index 000000000..dd3bb1967 --- /dev/null +++ b/.travis/common.sh @@ -0,0 +1,40 @@ +# set colors +RCol='\e[0m' # Text Reset + +# Regular Bold Underline High Intensity BoldHigh Intens Background High Intensity Backgrounds +Bla='\e[0;30m'; BBla='\e[1;30m'; UBla='\e[4;30m'; IBla='\e[0;90m'; BIBla='\e[1;90m'; On_Bla='\e[40m'; On_IBla='\e[0;100m'; +Red='\e[0;31m'; BRed='\e[1;31m'; URed='\e[4;31m'; IRed='\e[0;91m'; BIRed='\e[1;91m'; On_Red='\e[41m'; On_IRed='\e[0;101m'; +Gre='\e[0;32m'; BGre='\e[1;32m'; UGre='\e[4;32m'; IGre='\e[0;92m'; BIGre='\e[1;92m'; On_Gre='\e[42m'; On_IGre='\e[0;102m'; +Yel='\e[0;33m'; BYel='\e[1;33m'; UYel='\e[4;33m'; IYel='\e[0;93m'; BIYel='\e[1;93m'; On_Yel='\e[43m'; On_IYel='\e[0;103m'; +Blu='\e[0;34m'; BBlu='\e[1;34m'; UBlu='\e[4;34m'; IBlu='\e[0;94m'; BIBlu='\e[1;94m'; On_Blu='\e[44m'; On_IBlu='\e[0;104m'; +Pur='\e[0;35m'; BPur='\e[1;35m'; UPur='\e[4;35m'; IPur='\e[0;95m'; BIPur='\e[1;95m'; On_Pur='\e[45m'; On_IPur='\e[0;105m'; +Cya='\e[0;36m'; BCya='\e[1;36m'; UCya='\e[4;36m'; ICya='\e[0;96m'; BICya='\e[1;96m'; On_Cya='\e[46m'; On_ICya='\e[0;106m'; +Whi='\e[0;37m'; BWhi='\e[1;37m'; UWhi='\e[4;37m'; IWhi='\e[0;97m'; BIWhi='\e[1;97m'; On_Whi='\e[47m'; On_IWhi='\e[0;107m'; + +# Set variables +_qtver=5.5.1 +srcdir=${PWD} + +start_msg() { + echo -e "\n${Gre}$*${RCol}" +} + +info_msg() { + echo -e "\n${Cya}$*${RCol}" +} + +error_msg() { + echo -e "\n${BRed}$*${RCol}" +} + +success_msg() { + echo -e "\n${BGre}$*${RCol}" +} + +travis_fold_start() { + echo "travis_fold:start:$*" +} + +travis_fold_end() { + echo "travis_fold:end:$*" +} From fed715c1f414aac023cccef77cb3137df9536230 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Thu, 31 Mar 2016 14:37:58 +0400 Subject: [PATCH 07/17] Creating HistoryBlock only before adding an item to it. Now invariants always should be kept true, including indexInBlock, indexInHistory and !block->items.isEmpty() Need to backport UniquePointer from other branch. --- Telegram/SourceFiles/history.cpp | 251 ++++++++++++++++++------------- Telegram/SourceFiles/history.h | 85 ++++++++--- 2 files changed, 204 insertions(+), 132 deletions(-) diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 7ea40b30d..f53c91689 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -577,14 +577,8 @@ void ChannelHistory::addNewGroup(const MTPMessageGroup &group) { if (onlyImportant()) { if (newLoaded) { - HistoryBlock *block = blocks.isEmpty() ? pushBackNewBlock() : blocks.back(); - HistoryItem *prev = block->items.isEmpty() ? nullptr : block->items.back(); - - prev = addMessageGroupAfterPrevToBlock(d, prev, block); - if (block->items.isEmpty()) { - blocks.pop_back(); - delete block; - } + t_assert(!isBuildingFrontBlock()); + addMessageGroup(d); } } else { setNotLoadedAtBottom(); @@ -641,14 +635,12 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) { } } - // adding new item to new block - HistoryBlock *block = pushFrontNewBlock(); + startBuildingFrontBlock(); _joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags); - addItemToBlock(_joinedMessage, block); + addItemToBlock(_joinedMessage); - t_assert(blocks.size() > 1); - blocks.at(1)->items.front()->previousItemChanged(); + finishBuildingFrontBlock(); return _joinedMessage; } @@ -757,15 +749,15 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp } if (!isImportant && onlyImportant()) { - HistoryItem *item = addToHistory(msg), *prev = isEmpty() ? nullptr : blocks.back()->items.back(); + HistoryItem *item = addToHistory(msg); + + t_assert(!isBuildingFrontBlock()); + addMessageGroup([item, this](HistoryItem *previous) -> HistoryItem* { // create(..) + return HistoryGroup::create(this, item, previous ? previous->date : item->date); + }, [item](HistoryGroup *existing) { // unite(..) + existing->uniteWith(item); + }); - if (prev && prev->type() == HistoryItemGroup) { - static_cast<HistoryGroup*>(prev)->uniteWith(item); - } else { - QDateTime date = prev ? prev->date : item->date; - HistoryBlock *block = prev ? prev->block() : pushBackNewBlock(); - addItemToBlock(HistoryGroup::create(this, item, date), block); - } return item; } @@ -821,22 +813,15 @@ void ChannelHistory::switchMode() { clear(true); + t_assert(!isBuildingFrontBlock()); + newLoaded = _otherNewLoaded; oldLoaded = _otherOldLoaded; if (int count = _otherList.size()) { - blocks.reserve(qCeil(count / float64(MessagesPerPage))); - + blocks.reserve((count / MessagesPerPage) + 1); for (int i = 0; i < count;) { - HistoryBlock *block = pushBackNewBlock(); - - int willAddToBlock = qMin(int(MessagesPerPage), count - i); - block->items.reserve(willAddToBlock); - for (int till = i + willAddToBlock; i < till; ++i) { - t_assert(_otherList.at(i)->detached()); - addItemToBlock(_otherList.at(i), block); - } - - t_assert(!block->items.isEmpty()); + t_assert(_otherList.at(i)->detached()); + addItemToBlock(_otherList.at(i)); } } @@ -1550,16 +1535,10 @@ void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) { } HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) { - t_assert(adding != nullptr); - t_assert(adding->detached()); + t_assert(!isBuildingFrontBlock()); + addItemToBlock(adding); - HistoryBlock *block = blocks.isEmpty() ? pushBackNewBlock() : blocks.back(); - - adding->attachToBlock(block, block->items.size()); - block->items.push_back(adding); - adding->previousItemChanged(); setLastMessage(adding); - if (newMsg) { newItemAdded(adding); } @@ -1671,19 +1650,50 @@ void History::newItemAdded(HistoryItem *item) { } } -HistoryItem *History::addItemToBlock(HistoryItem *item, HistoryBlock *block) { +HistoryBlock *History::prepareBlockForAddingItem() { + if (isBuildingFrontBlock()) { + if (_frontBlock->block) { + return _frontBlock->block; + } + + HistoryBlock *result = _frontBlock->block = new HistoryBlock(this); + if (_frontBlock->expectedItemsCount > 0) { + result->items.reserve(_frontBlock->expectedItemsCount + 1); + } + result->setIndexInHistory(0); + blocks.push_front(result); + for (int i = 1, l = blocks.size(); i < l; ++i) { + blocks.at(i)->setIndexInHistory(i); + } + return result; + } + + bool addNewBlock = blocks.isEmpty() || (blocks.back()->items.size() >= MessagesPerPage); + if (!addNewBlock) { + return blocks.back(); + } + + HistoryBlock *result = new HistoryBlock(this); + result->setIndexInHistory(blocks.size()); + blocks.push_back(result); + + result->items.reserve(MessagesPerPage); + return result; +}; + +void History::addItemToBlock(HistoryItem *item) { + t_assert(item != nullptr); + t_assert(item->detached()); + + HistoryBlock *block = prepareBlockForAddingItem(); + item->attachToBlock(block, block->items.size()); block->items.push_back(item); item->previousItemChanged(); - return item; -} -HistoryItem *History::addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &group, HistoryItem *prev, HistoryBlock *block) { - if (prev && prev->type() == HistoryItemGroup) { - static_cast<HistoryGroup*>(prev)->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v); - return prev; + if (isBuildingFrontBlock() && _frontBlock->expectedItemsCount > 0) { + --_frontBlock->expectedItemsCount; } - return addItemToBlock(HistoryGroup::create(this, group, prev ? prev->date : date(group.vdate)), block); } void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPMessageGroup> *collapsed) { @@ -1700,10 +1710,8 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0; - HistoryItem *prev = nullptr; - HistoryBlock *block = pushFrontNewBlock(); + startBuildingFrontBlock(slice.size() + (collapsed ? collapsed->size() : 0)); - block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0)); for (auto i = slice.cend(), e = slice.cbegin(); i != e;) { --i; HistoryItem *adding = createItem(*i, false, true); @@ -1714,23 +1722,21 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM const MTPDmessageGroup &group(groupsIt->c_messageGroup()); if (group.vmin_id.v >= adding->id) break; - prev = addMessageGroupAfterPrevToBlock(group, prev, block); + addMessageGroup(group); } - prev = addItemToBlock(adding, block); + addItemToBlock(adding); } for (; groupsIt != groupsEnd; ++groupsIt) { if (groupsIt->type() != mtpc_messageGroup) continue; const MTPDmessageGroup &group(groupsIt->c_messageGroup()); - prev = addMessageGroupAfterPrevToBlock(group, prev, block); + addMessageGroup(group); } - if (block->items.isEmpty()) { - blocks.pop_front(); - delete block; - block = nullptr; - + HistoryBlock *block = finishBuildingFrontBlock(); + if (!block) { + // If no items were added it means we've loaded everything old. oldLoaded = true; } else if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors / lastParticipants bool channel = isChannel(); @@ -1808,28 +1814,6 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM } } - // some checks if there was some message history already - if (block && blocks.size() > 1) { - HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ... - HistoryItem *first = blocks.at(1)->items.front(); - - // we've added a new front block, so previous item for - // the old first item of a first block was changed - first->previousItemChanged(); - - // we've added a new front block, now we check if both - // last message of the first block and first message of - // the second block are groups, if they are - unite them - if (first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) { - static_cast<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(last)); - last->destroy(); - - // last->destroy() could've destroyed this new block - // so we can't rely on this pointer any more - block = nullptr; - } - } - if (isChannel()) { asChannelHistory()->checkJoinedMessage(); asChannelHistory()->checkMaxReadMessageDate(); @@ -1845,14 +1829,11 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM if (!lastMsg) setLastMessage(lastImportantMessage()); } + t_assert(!isBuildingFrontBlock()); if (!slice.isEmpty() || (isChannel() && collapsed && !collapsed->isEmpty())) { const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0; - HistoryItem *prev = blocks.isEmpty() ? nullptr : blocks.back()->items.back(); - - HistoryBlock *block = pushBackNewBlock(); - - block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0)); + bool atLeastOneAdded = false; for (auto i = slice.cend(), e = slice.cbegin(); i != e;) { --i; HistoryItem *adding = createItem(*i, false, true); @@ -1863,25 +1844,22 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM const MTPDmessageGroup &group(groupsIt->c_messageGroup()); if (group.vmin_id.v >= adding->id) break; - prev = addMessageGroupAfterPrevToBlock(group, prev, block); + addMessageGroup(group); } - prev = addItemToBlock(adding, block); + addItemToBlock(adding); + atLeastOneAdded = true; } for (; groupsIt != groupsEnd; ++groupsIt) { if (groupsIt->type() != mtpc_messageGroup) continue; const MTPDmessageGroup &group(groupsIt->c_messageGroup()); - prev = addMessageGroupAfterPrevToBlock(group, prev, block); + addMessageGroup(group); } - if (block->items.isEmpty()) { + if (!atLeastOneAdded) { newLoaded = true; setLastMessage(lastImportantMessage()); - - blocks.pop_back(); - delete block; - block = nullptr; } } @@ -2181,21 +2159,76 @@ HistoryItem *History::addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, return newItem; } -HistoryBlock *History::pushBackNewBlock() { - HistoryBlock *result = new HistoryBlock(this); - result->setIndexInHistory(blocks.size()); - blocks.push_back(result); - return result; +template <typename CreateGroup, typename UniteGroup> +void History::addMessageGroup(CreateGroup create, UniteGroup unite) { + HistoryItem *previous = nullptr; + if (isBuildingFrontBlock()) { + if (_frontBlock->block) { + previous = _frontBlock->block->items.back(); + } + } else { + if (!blocks.isEmpty()) { + previous = blocks.back()->items.back(); + } + } + + if (previous && previous->type() == HistoryItemGroup) { + unite(static_cast<HistoryGroup*>(previous)); + return; + } + + HistoryGroup *result = create(previous); + if (isBuildingFrontBlock()) { + addItemToBuildingFrontBlock(result); + } else { + addItemToBackBlock(result); + } } -HistoryBlock *History::pushFrontNewBlock() { - HistoryBlock *result = new HistoryBlock(this); - result->setIndexInHistory(0); - blocks.push_front(result); - for (int i = 1, l = blocks.size(); i < l; ++i) { - blocks.at(i)->setIndexInHistory(i); +void History::addMessageGroup(const MTPDmessageGroup &group) { + addMessageGroup([&group, this](HistoryItem *previous) -> HistoryItem* { // create(..) + return HistoryGroup::create(this, group, previous ? previous->date : date(group.vdate)); + }, [&group](HistoryGroup *existing) { // unite(..) + existing->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v); + }); +} + +void History::startBuildingFrontBlock(int expectedItemsCount) { + t_assert(!isBuildingFrontBlock()); + t_assert(expectedItemsCount > 0); + + _frontBlock.reset(new BuildingBlock()); + _frontBlock->expectedItemsCount = expectedItemsCount; +} + +HistoryBlock *History::finishBuildingFrontBlock() { + t_assert(isBuildingFrontBlock()); + + // Some checks if there was some message history already + HistoryBlock *block = _frontBlock->block; + if (block && blocks.size() > 1) { + HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ... + HistoryItem *first = blocks.at(1)->items.front(); + + // we've added a new front block, so previous item for + // the old first item of a first block was changed + first->previousItemChanged(); + + // we've added a new front block, now we check if both + // last message of the first block and first message of + // the second block are groups, if they are - unite them + if (first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) { + static_cast<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(last)); + last->destroy(); + + // last->destroy() could've destroyed this new block + // so we can't rely on this pointer any more + block = _frontBlock->block; + } } - return result; + + _frontBlock.clear(); + return block; } void History::clearNotifications() { @@ -2572,6 +2605,10 @@ void History::changeMsgId(MsgId oldId, MsgId newId) { void History::removeBlock(HistoryBlock *block) { t_assert(block->items.isEmpty()); + if (_frontBlock && block == _frontBlock->block) { + _frontBlock->block = nullptr; + } + int index = block->indexInHistory(); blocks.removeAt(index); for (int i = index, l = blocks.size(); i < l; ++i) { diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 497dd1060..b42e7e8b0 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -470,19 +470,64 @@ protected: void clearOnDestroy(); HistoryItem *addNewToLastBlock(const MTPMessage &msg, NewMessageType type); + friend class HistoryBlock; + + // this method just removes a block from the blocks list + // when the last item from this block was detached and + // calls the required previousItemChanged() + void removeBlock(HistoryBlock *block); + + void clearBlocks(bool leaveItems); + + HistoryItem *createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem); + HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg); + HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); + HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); + + HistoryItem *addNewItem(HistoryItem *adding, bool newMsg); + HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex); + + // All this methods add a new item to the first or last block + // depending on if we are in isBuildingFronBlock() state. + // The last block is created on the go if it is needed. + + // If the previous item is a message group the new group is + // not created but is just united with the previous one. + // create(HistoryItem *previous) should return a new HistoryGroup* + // unite(HistoryGroup *existing) should unite a new group with an existing + template <typename CreateGroup, typename UniteGroup> + void addMessageGroup(CreateGroup create, UniteGroup unite); + void addMessageGroup(const MTPDmessageGroup &group); + + // Adds the item to the back or front block, depending on + // isBuildingFrontBlock(), creating the block if necessary. + void addItemToBlock(HistoryItem *item); + + // Usually all new items are added to the last block. + // Only when we scroll up and add a new slice to the + // front we want to create a new front block. + void startBuildingFrontBlock(int expectedItemsCount = 1); + HistoryBlock *finishBuildingFrontBlock(); // Returns the built block or nullptr if nothing was added. + bool isBuildingFrontBlock() const { + return !_buildingFrontBlock.isNull(); + } + private: - enum Flag { + enum class Flag { f_has_pending_resized_items = (1 << 0), - f_pending_resize = (1 << 1), + f_pending_resize = (1 << 1), }; Q_DECLARE_FLAGS(Flags, Flag); - Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) Q_DECL_NOTHROW { + Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept { return QFlags<Flags::enum_type>(f1) | f2; } - Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) Q_DECL_NOTHROW { + Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept { return f2 | f1; } + Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator~(Flags::enum_type f) noexcept { + return ~QFlags<Flags::enum_type>(f); + } Flags _flags; ChatListLinksMap _chatListLinks; @@ -497,28 +542,18 @@ private: MediaOverviewIds overviewIds[OverviewCount]; int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded - friend class HistoryBlock; - friend class ChannelHistory; + // A pointer to the block that is currently being built. + // We hold this pointer so we can destroy it while building + // and then create a new one if it is necessary. + struct BuildingBlock { + int expectedItemsCount = 0; // optimization for block->items.reserve() call + HistoryBlock *block = nullptr; + }; + UniquePointer<BuildingBlock> _buildingFrontBlock; - // this method just removes a block from the blocks list - // when the last item from this block was detached and - // calls the required previousItemChanged() - void removeBlock(HistoryBlock *block); - - void clearBlocks(bool leaveItems); - - HistoryItem *createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem); - HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg); - HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption); - HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption); - - HistoryItem *addItemToBlock(HistoryItem *item, HistoryBlock *block); - HistoryItem *addNewItem(HistoryItem *adding, bool newMsg); - HistoryItem *addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &group, HistoryItem *prev, HistoryBlock *block); - HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex); - - HistoryBlock *pushBackNewBlock(); - HistoryBlock *pushFrontNewBlock(); + // Creates if necessary a new block for adding item. + // Depending on isBuildingFrontBlock() gets front or back block. + HistoryBlock *prepareBlockForAddingItem(); }; From 40fddc96976abfefa229a9ed64cd167ca218abf7 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Thu, 31 Mar 2016 15:18:21 +0400 Subject: [PATCH 08/17] UniquePointer backported. Fixed unifying of adding new history items. --- Telegram/SourceFiles/history.cpp | 46 +++---- Telegram/SourceFiles/history.h | 6 +- Telegram/SourceFiles/mtproto/connection.cpp | 2 +- Telegram/SourceFiles/types.h | 135 ++++++++++++++++++-- 4 files changed, 149 insertions(+), 40 deletions(-) diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index f53c91689..3231bf89f 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -752,7 +752,7 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp HistoryItem *item = addToHistory(msg); t_assert(!isBuildingFrontBlock()); - addMessageGroup([item, this](HistoryItem *previous) -> HistoryItem* { // create(..) + addMessageGroup([item, this](HistoryItem *previous) -> HistoryGroup* { // create(..) return HistoryGroup::create(this, item, previous ? previous->date : item->date); }, [item](HistoryGroup *existing) { // unite(..) existing->uniteWith(item); @@ -819,7 +819,7 @@ void ChannelHistory::switchMode() { oldLoaded = _otherOldLoaded; if (int count = _otherList.size()) { blocks.reserve((count / MessagesPerPage) + 1); - for (int i = 0; i < count;) { + for (int i = 0; i < count; ++i) { t_assert(_otherList.at(i)->detached()); addItemToBlock(_otherList.at(i)); } @@ -1652,13 +1652,13 @@ void History::newItemAdded(HistoryItem *item) { HistoryBlock *History::prepareBlockForAddingItem() { if (isBuildingFrontBlock()) { - if (_frontBlock->block) { - return _frontBlock->block; + if (_buildingFrontBlock->block) { + return _buildingFrontBlock->block; } - HistoryBlock *result = _frontBlock->block = new HistoryBlock(this); - if (_frontBlock->expectedItemsCount > 0) { - result->items.reserve(_frontBlock->expectedItemsCount + 1); + HistoryBlock *result = _buildingFrontBlock->block = new HistoryBlock(this); + if (_buildingFrontBlock->expectedItemsCount > 0) { + result->items.reserve(_buildingFrontBlock->expectedItemsCount + 1); } result->setIndexInHistory(0); blocks.push_front(result); @@ -1691,8 +1691,8 @@ void History::addItemToBlock(HistoryItem *item) { block->items.push_back(item); item->previousItemChanged(); - if (isBuildingFrontBlock() && _frontBlock->expectedItemsCount > 0) { - --_frontBlock->expectedItemsCount; + if (isBuildingFrontBlock() && _buildingFrontBlock->expectedItemsCount > 0) { + --_buildingFrontBlock->expectedItemsCount; } } @@ -2163,8 +2163,8 @@ template <typename CreateGroup, typename UniteGroup> void History::addMessageGroup(CreateGroup create, UniteGroup unite) { HistoryItem *previous = nullptr; if (isBuildingFrontBlock()) { - if (_frontBlock->block) { - previous = _frontBlock->block->items.back(); + if (_buildingFrontBlock->block) { + previous = _buildingFrontBlock->block->items.back(); } } else { if (!blocks.isEmpty()) { @@ -2174,19 +2174,13 @@ void History::addMessageGroup(CreateGroup create, UniteGroup unite) { if (previous && previous->type() == HistoryItemGroup) { unite(static_cast<HistoryGroup*>(previous)); - return; - } - - HistoryGroup *result = create(previous); - if (isBuildingFrontBlock()) { - addItemToBuildingFrontBlock(result); } else { - addItemToBackBlock(result); + addItemToBlock(create(previous)); } } void History::addMessageGroup(const MTPDmessageGroup &group) { - addMessageGroup([&group, this](HistoryItem *previous) -> HistoryItem* { // create(..) + addMessageGroup([&group, this](HistoryItem *previous) -> HistoryGroup* { // create(..) return HistoryGroup::create(this, group, previous ? previous->date : date(group.vdate)); }, [&group](HistoryGroup *existing) { // unite(..) existing->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v); @@ -2197,15 +2191,15 @@ void History::startBuildingFrontBlock(int expectedItemsCount) { t_assert(!isBuildingFrontBlock()); t_assert(expectedItemsCount > 0); - _frontBlock.reset(new BuildingBlock()); - _frontBlock->expectedItemsCount = expectedItemsCount; + _buildingFrontBlock.reset(new BuildingBlock()); + _buildingFrontBlock->expectedItemsCount = expectedItemsCount; } HistoryBlock *History::finishBuildingFrontBlock() { t_assert(isBuildingFrontBlock()); // Some checks if there was some message history already - HistoryBlock *block = _frontBlock->block; + HistoryBlock *block = _buildingFrontBlock->block; if (block && blocks.size() > 1) { HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ... HistoryItem *first = blocks.at(1)->items.front(); @@ -2223,11 +2217,11 @@ HistoryBlock *History::finishBuildingFrontBlock() { // last->destroy() could've destroyed this new block // so we can't rely on this pointer any more - block = _frontBlock->block; + block = _buildingFrontBlock->block; } } - _frontBlock.clear(); + _buildingFrontBlock.clear(); return block; } @@ -2605,8 +2599,8 @@ void History::changeMsgId(MsgId oldId, MsgId newId) { void History::removeBlock(HistoryBlock *block) { t_assert(block->items.isEmpty()); - if (_frontBlock && block == _frontBlock->block) { - _frontBlock->block = nullptr; + if (_buildingFrontBlock && block == _buildingFrontBlock->block) { + _buildingFrontBlock->block = nullptr; } int index = block->indexInHistory(); diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index b42e7e8b0..1dd9dd95e 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -1049,9 +1049,9 @@ struct HistoryMessageReply : public BaseComponent<HistoryMessageReply> { HistoryMessageReply &operator=(HistoryMessageReply &&other) { replyToMsgId = other.replyToMsgId; std::swap(replyToMsg, other.replyToMsg); - replyToLnk = std11::move(other.replyToLnk); - replyToName = std11::move(other.replyToName); - replyToText = std11::move(other.replyToText); + replyToLnk = std_::move(other.replyToLnk); + replyToName = std_::move(other.replyToName); + replyToText = std_::move(other.replyToText); replyToVersion = other.replyToVersion; _maxReplyWidth = other._maxReplyWidth; std::swap(_replyToVia, other._replyToVia); diff --git a/Telegram/SourceFiles/mtproto/connection.cpp b/Telegram/SourceFiles/mtproto/connection.cpp index d05737382..49cbd9f48 100644 --- a/Telegram/SourceFiles/mtproto/connection.cpp +++ b/Telegram/SourceFiles/mtproto/connection.cpp @@ -62,7 +62,7 @@ bool parsePQ(const string &pqStr, string &pStr, string &qStr) { break; } } - if (p > q) swap(p, q); + if (p > q) std::swap(p, q); pStr.resize(4); uchar *pChars = (uchar*)&pStr[0]; diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 836b7af37..27515b177 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -215,31 +215,86 @@ typedef double float64; using std::string; using std::exception; -using std::swap; -// we copy some parts of C++11 std:: library, because on OS X 10.6+ -// version we can use C++11, but we can't use its library :( -namespace std11 { +// we copy some parts of C++11/14/17 std:: library, because on OS X 10.6+ +// version we can use C++11/14/17, but we can not use its library :( +namespace std_ { + +template <typename T, T V> +struct integral_constant { + static constexpr T value = V; + + using value_type = T; + using type = integral_constant<T, V>; + + constexpr operator value_type() const noexcept { + return (value); + } + + constexpr value_type operator()() const noexcept { + return (value); + } +}; + +using true_type = integral_constant<bool, true>; +using false_type = integral_constant<bool, false>; template <typename T> struct remove_reference { - typedef T type; + using type = T; }; template <typename T> struct remove_reference<T&> { - typedef T type; + using type = T; }; template <typename T> struct remove_reference<T&&> { - typedef T type; + using type = T; }; template <typename T> -inline typename remove_reference<T>::type &&move(T &&value) { +struct is_lvalue_reference : false_type { +}; +template <typename T> +struct is_lvalue_reference<T&> : true_type { +}; + +template <typename T> +struct is_rvalue_reference : false_type { +}; +template <typename T> +struct is_rvalue_reference<T&&> : true_type { +}; + +template <typename T> +inline constexpr T &&forward(typename remove_reference<T>::type &value) noexcept { + return static_cast<T&&>(value); +} +template <typename T> +inline constexpr T &&forward(typename remove_reference<T>::type &&value) noexcept { + static_assert(!is_lvalue_reference<T>::value, "bad forward call"); + return static_cast<T&&>(value); +} + +template <typename T> +inline constexpr typename remove_reference<T>::type &&move(T &&value) noexcept { return static_cast<typename remove_reference<T>::type&&>(value); } -} // namespace std11 +template <typename T> +struct add_const { + using type = const T; +}; +template <typename T> +using add_const_t = typename add_const<T>::type; +template <typename T> +constexpr add_const_t<T> &as_const(T& t) noexcept { + return t; +} +template <typename T> +void as_const(const T&&) = delete; + +} // namespace std_ #include "logs.h" @@ -669,6 +724,66 @@ inline RefPairImplementation<T1, T2> RefPairCreator(T1 &first, T2 &second) { #define RefPair(Type1, Name1, Type2, Name2) Type1 Name1; Type2 Name2; RefPairCreator(Name1, Name2) +template <typename T> +class UniquePointer { +public: + explicit UniquePointer(T *p = nullptr) : _p(p) { + } + UniquePointer(const UniquePointer<T> &other) = delete; + UniquePointer &operator=(const UniquePointer<T> &other) = delete; + UniquePointer(UniquePointer<T> &&other) : _p(other.release()) { + } + UniquePointer &operator=(UniquePointer<T> &&other) { + std::swap(_p, other._p); + return *this; + } + template <typename U> + UniquePointer(UniquePointer<U> &&other) : _p(other.release()) { + } + T *data() const { + return _p; + } + T *release() { + return getPointerAndReset(_p); + } + void reset(T *p = nullptr) { + *this = UniquePointer<T>(p); + } + bool isNull() const { + return data() == nullptr; + } + + void clear() { + reset(); + } + T *operator->() const { + return data(); + } + T &operator*() const { + t_assert(!isNull()); + return *data(); + } + explicit operator bool() const { + return !isNull(); + } + ~UniquePointer() { + delete data(); + } + +private: + T *_p; + +}; +template <typename T, class... Args> +inline UniquePointer<T> MakeUnique(Args&&... args) { + return UniquePointer<T>(new T(std_::forward<Args>(args)...)); +} + +template <typename T, class... Args> +inline QSharedPointer<T> MakeShared(Args&&... args) { + return QSharedPointer<T>(new T(std_::forward<Args>(args)...)); +} + template <typename I> inline void destroyImplementation(I *&ptr) { if (ptr) { @@ -715,7 +830,7 @@ struct ComponentWrapTemplate { ((Type*)location)->~Type(); } static void Move(void *location, void *waslocation) { - *(Type*)location = std11::move(*(Type*)waslocation); + *(Type*)location = std_::move(*(Type*)waslocation); } }; From a23470f4b8cb63e63462e8e8b0f2c1208faf4db1 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Thu, 31 Mar 2016 15:55:25 +0400 Subject: [PATCH 09/17] Fixed possible crash in NotifyWindow click handler. Adding information about crashed string in TextBlock parser. --- Telegram/SourceFiles/app.cpp | 2 +- Telegram/SourceFiles/gui/text.cpp | 7 + Telegram/SourceFiles/logs.cpp | 219 ++++++++++++++++-------------- Telegram/SourceFiles/logs.h | 10 +- Telegram/SourceFiles/types.h | 2 +- Telegram/SourceFiles/window.cpp | 6 +- 6 files changed, 141 insertions(+), 105 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 731a57ee1..18dfe7ae6 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -447,7 +447,7 @@ namespace App { QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone; if (!minimal && d.is_self() && uname != data->username) { - SignalHandlers::setSelfUsername(uname); + SignalHandlers::setCrashAnnotation("Username", uname); } data->setName(fname, lname, pname, uname); if (d.has_photo()) { diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index f350a1f3e..b12fdfe3f 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -3533,7 +3533,14 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi layout.beginLayout(); layout.createLine(); + bool logCrashString = (rand_value<uchar>() % 4 == 1); + if (logCrashString) { + SignalHandlers::setCrashAnnotationRef("CrashString", &part); + } BlockParser parser(&engine, this, minResizeWidth, _from, part); + if (logCrashString) { + SignalHandlers::clearCrashAnnotationRef("CrashString"); + } layout.endLayout(); } diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index 68fa217d0..916193635 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -614,119 +614,127 @@ void _moveOldDataFiles(const QString &wasDir) { namespace SignalHandlers { - typedef std::map<std::string, std::string> AnnotationsMap; - AnnotationsMap ProcessAnnotations; +namespace internal { + using Annotations = std::map<std::string, std::string>; + using AnnotationRefs = std::map<std::string, const QString*>; + + Annotations ProcessAnnotations; + AnnotationRefs ProcessAnnotationRefs; #ifndef TDESKTOP_DISABLE_CRASH_REPORTS - QString CrashDumpPath; - FILE *CrashDumpFile = nullptr; - int CrashDumpFileNo = 0; + QString ReportPath; + FILE *ReportFile = nullptr; + int ReportFileNo = 0; char LaunchedDateTimeStr[32] = { 0 }; char LaunchedBinaryName[256] = { 0 }; - void _writeChar(char ch) { - fwrite(&ch, 1, 1, CrashDumpFile); + void writeChar(char ch) { + fwrite(&ch, 1, 1, ReportFile); } - dump::~dump() { - if (CrashDumpFile) { - fflush(CrashDumpFile); - } - } - - const dump &operator<<(const dump &stream, const char *str) { - if (!CrashDumpFile) return stream; - - fwrite(str, 1, strlen(str), CrashDumpFile); - return stream; - } - - const dump &operator<<(const dump &stream, const wchar_t *str) { - if (!CrashDumpFile) return stream; - - for (int i = 0, l = wcslen(str); i < l; ++i) { - if (str[i] >= 0 && str[i] < 128) { - _writeChar(char(str[i])); - } else { - _writeChar('?'); - } - } - return stream; - } - template <bool Unsigned, typename Type> - struct _writeNumberSignAndRemoveIt { + struct writeNumberSignAndRemoveIt { static void call(Type &number) { if (number < 0) { - _writeChar('-'); + writeChar('-'); number = -number; } } }; template <typename Type> - struct _writeNumberSignAndRemoveIt<true, Type> { + struct writeNumberSignAndRemoveIt<true, Type> { static void call(Type &number) { } }; template <typename Type> - const dump &_writeNumber(const dump &stream, Type number) { - if (!CrashDumpFile) return stream; + const dump &writeNumber(const dump &stream, Type number) { + if (!ReportFile) return stream; - _writeNumberSignAndRemoveIt<(Type(-1) > Type(0)), Type>::call(number); + writeNumberSignAndRemoveIt<(Type(-1) > Type(0)), Type>::call(number); Type upper = 1, prev = number / 10; while (prev >= upper) { upper *= 10; } while (upper > 0) { int digit = (number / upper); - _writeChar('0' + digit); + internal::writeChar('0' + digit); number -= digit * upper; upper /= 10; } return stream; } +} // namespace internal + + dump::~dump() { + if (internal::ReportFile) { + fflush(internal::ReportFile); + } + } + + const dump &operator<<(const dump &stream, const char *str) { + if (!internal::ReportFile) return stream; + + fwrite(str, 1, strlen(str), internal::ReportFile); + return stream; + } + + const dump &operator<<(const dump &stream, const wchar_t *str) { + if (!internal::ReportFile) return stream; + + for (int i = 0, l = wcslen(str); i < l; ++i) { + if (str[i] >= 0 && str[i] < 128) { + internal::writeChar(char(str[i])); + } else { + internal::writeChar('?'); + } + } + return stream; + } + const dump &operator<<(const dump &stream, int num) { - return _writeNumber(stream, num); + return internal::writeNumber(stream, num); } const dump &operator<<(const dump &stream, unsigned int num) { - return _writeNumber(stream, num); + return internal::writeNumber(stream, num); } const dump &operator<<(const dump &stream, unsigned long num) { - return _writeNumber(stream, num); + return internal::writeNumber(stream, num); } const dump &operator<<(const dump &stream, unsigned long long num) { - return _writeNumber(stream, num); + return internal::writeNumber(stream, num); } const dump &operator<<(const dump &stream, double num) { if (num < 0) { - _writeChar('-'); + internal::writeChar('-'); num = -num; } - _writeNumber(stream, uint64(floor(num))); - _writeChar('.'); + internal::writeNumber(stream, uint64(floor(num))); + internal::writeChar('.'); num -= floor(num); for (int i = 0; i < 4; ++i) { num *= 10; int digit = int(floor(num)); - _writeChar('0' + digit); + internal::writeChar('0' + digit); num -= digit; } return stream; } - Qt::HANDLE LoggingCrashThreadId = 0; - bool LoggingCrashHeaderWritten = false; - QMutex LoggingCrashMutex; +namespace internal { - const char *BreakpadDumpPath = 0; - const wchar_t *BreakpadDumpPathW = 0; + Qt::HANDLE ReportingThreadId = nullptr; + bool ReportingHeaderWritten = false; + QMutex ReportingMutex; + + const char *BreakpadDumpPath = nullptr; + const wchar_t *BreakpadDumpPathW = nullptr; #if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64 struct sigaction SIG_def[32]; @@ -753,14 +761,19 @@ namespace SignalHandlers { } Qt::HANDLE thread = QThread::currentThreadId(); - if (thread == LoggingCrashThreadId) return; + if (thread == ReportingThreadId) return; - QMutexLocker lock(&LoggingCrashMutex); - LoggingCrashThreadId = thread; + QMutexLocker lock(&ReportingMutex); + ReportingThreadId = thread; - if (!LoggingCrashHeaderWritten) { - LoggingCrashHeaderWritten = true; - const AnnotationsMap c_ProcessAnnotations(ProcessAnnotations); + if (!ReportingHeaderWritten) { + ReportingHeaderWritten = true; + + for (const auto &i : ProcessAnnotationRefs) { + ProcessAnnotations[i.first] = i.second->toUtf8().constData(); + } + + const Annotations c_ProcessAnnotations(ProcessAnnotations); for (const auto &i : c_ProcessAnnotations) { dump() << i.first.c_str() << ": " << i.second.c_str() << "\n"; } @@ -843,7 +856,7 @@ namespace SignalHandlers { dump() << "\nBacktrace:\n"; - backtrace_symbols_fd(addresses, size, CrashDumpFileNo); + backtrace_symbols_fd(addresses, size, ReportFileNo); #else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64 dump() << "\nBacktrace:\n"; @@ -853,7 +866,7 @@ namespace SignalHandlers { dump() << "\n"; - LoggingCrashThreadId = 0; + ReportingThreadId = nullptr; } bool SetSignalHandlers = true; @@ -890,8 +903,12 @@ namespace SignalHandlers { #endif // !TDESKTOP_DISABLE_CRASH_REPORTS +} // namespace internal + void StartCrashHandler() { #ifndef TDESKTOP_DISABLE_CRASH_REPORTS + using internal::ProcessAnnotations; + ProcessAnnotations["Binary"] = cExeName().toUtf8().constData(); ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData(); ProcessAnnotations["Version"] = (cBetaVersion() ? qsl("%1 beta").arg(cBetaVersion()) : (cDevVersion() ? qsl("%1 dev") : qsl("%1")).arg(AppVersion)).toUtf8().constData(); @@ -903,10 +920,10 @@ namespace SignalHandlers { QDir().mkpath(dumpspath); #ifdef Q_OS_WIN - BreakpadExceptionHandler = new google_breakpad::ExceptionHandler( + internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler( dumpspath.toStdWString(), /*FilterCallback*/ 0, - DumpCallback, + internal::DumpCallback, /*context*/ 0, true ); @@ -914,16 +931,16 @@ namespace SignalHandlers { #ifdef MAC_USE_BREAKPAD #ifndef _DEBUG - BreakpadExceptionHandler = new google_breakpad::ExceptionHandler( + internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler( QFile::encodeName(dumpspath).toStdString(), /*FilterCallback*/ 0, - DumpCallback, + internal::DumpCallback, /*context*/ 0, true, 0 ); #endif // !_DEBUG - SetSignalHandlers = false; + internal::SetSignalHandlers = false; #else // MAC_USE_BREAKPAD crashpad::CrashpadClient crashpad_client; std::string handler = (cExeDir() + cExeName() + qsl("/Contents/Helpers/crashpad_handler")).toUtf8().constData(); @@ -938,10 +955,10 @@ namespace SignalHandlers { } #endif // else for MAC_USE_BREAKPAD #elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32 - BreakpadExceptionHandler = new google_breakpad::ExceptionHandler( + internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler( google_breakpad::MinidumpDescriptor(QFile::encodeName(dumpspath).toStdString()), /*FilterCallback*/ 0, - DumpCallback, + internal::DumpCallback, /*context*/ 0, true, -1 @@ -954,9 +971,8 @@ namespace SignalHandlers { #ifndef TDESKTOP_DISABLE_CRASH_REPORTS #if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD - if (BreakpadExceptionHandler) { - google_breakpad::ExceptionHandler *h = BreakpadExceptionHandler; - BreakpadExceptionHandler = 0; + if (internal::BreakpadExceptionHandler) { + google_breakpad::ExceptionHandler *h = getPointerAndReset(internal::BreakpadExceptionHandler); delete h; } #endif // !Q_OS_MAC || MAC_USE_BREAKPAD @@ -966,15 +982,16 @@ namespace SignalHandlers { Status start() { #ifndef TDESKTOP_DISABLE_CRASH_REPORTS - CrashDumpPath = cWorkingDir() + qsl("tdata/working"); + using internal::ReportPath; + ReportPath = cWorkingDir() + qsl("tdata/working"); #ifdef Q_OS_WIN FILE *f = nullptr; - if (_wfopen_s(&f, CrashDumpPath.toStdWString().c_str(), L"rb") != 0) { + if (_wfopen_s(&f, ReportPath.toStdWString().c_str(), L"rb") != 0) { f = nullptr; } else { #else // !Q_OS_WIN - if (FILE *f = fopen(QFile::encodeName(CrashDumpPath).constData(), "rb")) { + if (FILE *f = fopen(QFile::encodeName(ReportPath).constData(), "rb")) { #endif // else for !Q_OS_WIN QByteArray lastdump; char buffer[256 * 1024] = { 0 }; @@ -986,7 +1003,7 @@ namespace SignalHandlers { Sandbox::SetLastCrashDump(lastdump); - LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(CrashDumpPath).arg(lastdump.size())); + LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(ReportPath).arg(lastdump.size())); return LastCrashed; } @@ -997,28 +1014,28 @@ namespace SignalHandlers { Status restart() { #ifndef TDESKTOP_DISABLE_CRASH_REPORTS - if (CrashDumpFile) { + if (internal::ReportFile) { return Started; } #ifdef Q_OS_WIN - if (_wfopen_s(&CrashDumpFile, CrashDumpPath.toStdWString().c_str(), L"wb") != 0) { - CrashDumpFile = nullptr; + if (_wfopen_s(&internal::ReportFile, internal::ReportPath.toStdWString().c_str(), L"wb") != 0) { + internal::ReportFile = nullptr; } #else // Q_OS_WIN CrashDumpFile = fopen(QFile::encodeName(CrashDumpPath).constData(), "wb"); #endif // else for Q_OS_WIN - if (CrashDumpFile) { + if (internal::ReportFile) { #ifdef Q_OS_WIN - CrashDumpFileNo = _fileno(CrashDumpFile); + internal::ReportFileNo = _fileno(internal::ReportFile); #else // Q_OS_WIN - CrashDumpFileNo = fileno(CrashDumpFile); + CrashDumpFileNo = fileno(internal::ReportFile); #endif // else for Q_OS_WIN - if (SetSignalHandlers) { + if (internal::SetSignalHandlers) { #ifndef Q_OS_WIN struct sigaction sigact; - sigact.sa_sigaction = SignalHandlers::Handler; + sigact.sa_sigaction = SignalHandlers::internal::Handler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; @@ -1029,16 +1046,16 @@ namespace SignalHandlers { sigaction(SIGBUS, &sigact, &SIG_def[SIGBUS]); sigaction(SIGSYS, &sigact, &SIG_def[SIGSYS]); #else // !Q_OS_WIN - signal(SIGABRT, SignalHandlers::Handler); - signal(SIGSEGV, SignalHandlers::Handler); - signal(SIGILL, SignalHandlers::Handler); - signal(SIGFPE, SignalHandlers::Handler); + signal(SIGABRT, SignalHandlers::internal::Handler); + signal(SIGSEGV, SignalHandlers::internal::Handler); + signal(SIGILL, SignalHandlers::internal::Handler); + signal(SIGFPE, SignalHandlers::internal::Handler); #endif // else for !Q_OS_WIN } return Started; } - LOG(("FATAL: Could not open '%1' for writing!").arg(CrashDumpPath)); + LOG(("FATAL: Could not open '%1' for writing!").arg(internal::ReportPath)); return CantOpen; #else // !TDESKTOP_DISABLE_CRASH_REPORTS @@ -1049,29 +1066,33 @@ namespace SignalHandlers { void finish() { #ifndef TDESKTOP_DISABLE_CRASH_REPORTS FinishCrashHandler(); - if (CrashDumpFile) { - fclose(CrashDumpFile); - CrashDumpFile = nullptr; + if (internal::ReportFile) { + fclose(internal::ReportFile); + internal::ReportFile = nullptr; #ifdef Q_OS_WIN - _wunlink(CrashDumpPath.toStdWString().c_str()); + _wunlink(internal::ReportPath.toStdWString().c_str()); #else // Q_OS_WIN - unlink(CrashDumpPath.toUtf8().constData()); + unlink(internal::ReportPath.toUtf8().constData()); #endif // else for Q_OS_WIN } #endif // !TDESKTOP_DISABLE_CRASH_REPORTS } - void setSelfUsername(const QString &username) { - if (username.trimmed().isEmpty()) { - ProcessAnnotations.erase("Username"); + void setCrashAnnotation(const std::string &key, const QString &value) { + if (value.trimmed().isEmpty()) { + internal::ProcessAnnotations.erase(key); } else { - ProcessAnnotations["Username"] = username.toUtf8().constData(); + internal::ProcessAnnotations[key] = value.toUtf8().constData(); } } - void setAssertionInfo(const QString &info) { - ProcessAnnotations["Assertion"] = info.toUtf8().constData(); + void setCrashAnnotationRef(const std::string &key, const QString *valuePtr) { + if (valuePtr) { + internal::ProcessAnnotationRefs.erase(key); + } else { + internal::ProcessAnnotationRefs[key] = valuePtr; + } } } diff --git a/Telegram/SourceFiles/logs.h b/Telegram/SourceFiles/logs.h index 6e997e4cf..737d6ecff 100644 --- a/Telegram/SourceFiles/logs.h +++ b/Telegram/SourceFiles/logs.h @@ -107,7 +107,13 @@ namespace SignalHandlers { Status restart(); // can be only CantOpen or Started void finish(); - void setSelfUsername(const QString &username); - void setAssertionInfo(const QString &info); + void setCrashAnnotation(const std::string &key, const QString &value); + + // Remembers value pointer and tries to add the value to the crash report. + // Attention! You should call clearCrashAnnotationRef(key) before destroying value. + void setCrashAnnotationRef(const std::string &key, const QString *valuePtr); + inline void clearCrashAnnotationRef(const std::string &key) { + setCrashAnnotationRef(key, nullptr); + } } diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 27515b177..3a775b9cb 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -303,7 +303,7 @@ inline void t_noop() {} inline void t_assert_fail(const char *message, const char *file, int32 line) { QString info(qsl("%1 %2:%3").arg(message).arg(file).arg(line)); LOG(("Assertion Failed! %1 %2:%3").arg(info)); - SignalHandlers::setAssertionInfo(info); + SignalHandlers::setCrashAnnotation("Assertion", info); *t_assert_nullptr = 0; } #define t_assert_full(condition, message, file, line) ((!(condition)) ? t_assert_fail(message, file, line) : t_noop()) diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index d2ce17a4f..6decac3f6 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -287,18 +287,20 @@ void NotifyWindow::startHiding() { void NotifyWindow::mousePressEvent(QMouseEvent *e) { if (!history) return; + PeerId peer = history->peer->id; + MsgId msgId = (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId; if (e->button() == Qt::RightButton) { unlinkHistoryAndNotify(); - } else if (history) { + } else { App::wnd()->showFromTray(); if (App::passcoded()) { App::wnd()->setInnerFocus(); App::wnd()->notifyClear(); } else { App::wnd()->hideSettings(); - Ui::showPeerHistory(peer, (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId); + Ui::showPeerHistory(peer, msgId); } e->ignore(); } From f1dfcef86863f4390eec1f02f3579d8df11bf7e8 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Thu, 31 Mar 2016 18:06:40 +0400 Subject: [PATCH 10/17] Styles improved for unread bar margins and sticker timestamp. Possible crash fixes: emoji color picker show, pending repaint items cleared when history items are cleared. Deleting MainWidget syncroniously when clearWidgets() is called. --- Telegram/Resources/style.txt | 7 +-- Telegram/SourceFiles/app.cpp | 33 +++++++------- Telegram/SourceFiles/app.h | 1 - Telegram/SourceFiles/dropdown.cpp | 2 + Telegram/SourceFiles/facades.cpp | 6 +++ Telegram/SourceFiles/facades.h | 2 + Telegram/SourceFiles/history.cpp | 53 ++++++++++++++-------- Telegram/SourceFiles/history.h | 10 ++++- Telegram/SourceFiles/historywidget.cpp | 62 +++++++++++++++++--------- Telegram/SourceFiles/historywidget.h | 10 ++++- Telegram/SourceFiles/mainwidget.cpp | 6 +-- Telegram/SourceFiles/types.h | 18 ++++---- Telegram/SourceFiles/window.cpp | 20 +++++---- Telegram/SourceFiles/window.h | 4 +- 14 files changed, 148 insertions(+), 86 deletions(-) diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 5ada019a8..357a487bb 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -1052,8 +1052,8 @@ msgMinWidth: 190px; msgPhotoSize: 33px; msgPhotoSkip: 40px; msgPadding: margins(13px, 7px, 13px, 8px); -msgMargin: margins(13px, 6px, 53px, 2px); -msgMarginTopAttached: 2px; +msgMargin: margins(13px, 10px, 53px, 2px); +msgMarginTopAttached: 3px; msgLnkPadding: 2px; // for media open / save links msgBorder: #f0f0f0; msgInBg: #fff; @@ -1089,7 +1089,7 @@ msgServiceBg: #89a0b47f; msgServiceSelectBg: #bbc8d4a2; msgServiceColor: #FFF; msgServicePadding: margins(12px, 3px, 12px, 4px); -msgServiceMargin: margins(10px, 9px, 80px, 5px); +msgServiceMargin: margins(10px, 10px, 80px, 2px); msgColor: #000; msgDateColor: #000; @@ -1527,6 +1527,7 @@ reportSpamBg: #fffffff0; newMsgSound: ':/gui/art/newmsg.wav'; unreadBarHeight: 32px; +unreadBarMargin: 8px; unreadBarFont: semiboldFont; unreadBarBG: #fcfbfa; unreadBarBorder: shadowColor; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 18dfe7ae6..8d33b9797 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -180,21 +180,19 @@ namespace App { return main() ? main()->api() : 0; } +namespace { bool loggedOut() { - Window *w(wnd()); if (cHasPasscode()) { cSetHasPasscode(false); } if (audioPlayer()) { audioPlayer()->stopAndClear(); } - if (w) { + if (Window *w = wnd()) { w->tempDirDelete(Local::ClearManagerAll); w->notifyClearFast(); w->setupIntro(true); } - MainWidget *m(main()); - if (m) m->destroyData(); MTP::authed(0); Local::reset(); @@ -205,13 +203,14 @@ namespace App { globalNotifyChatsPtr = UnknownNotifySettings; if (App::uploader()) App::uploader()->clear(); clearStorageImages(); - if (w) { + if (Window *w = wnd()) { w->getTitle()->updateBackButton(); w->updateTitleStatus(); w->getTitle()->resizeEvent(0); } return true; } +} // namespace void logOut() { if (MTP::started()) { @@ -1454,12 +1453,12 @@ namespace App { PeerData *peerByName(const QString &username) { QString uname(username.trimmed()); - for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) { - if (!i.value()->userName().compare(uname, Qt::CaseInsensitive)) { - return i.value(); + for_const (PeerData *peer, peersData) { + if (!peer->userName().compare(uname, Qt::CaseInsensitive)) { + return peer; } } - return 0; + return nullptr; } void updateImage(ImagePtr &old, ImagePtr now) { @@ -1867,20 +1866,20 @@ namespace App { cSetSavedPeers(SavedPeers()); cSetSavedPeersByTime(SavedPeersByTime()); cSetRecentInlineBots(RecentInlineBots()); - for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) { - delete *i; + for_const (PeerData *peer, peersData) { + delete peer; } peersData.clear(); - for (PhotosData::const_iterator i = ::photosData.cbegin(), e = ::photosData.cend(); i != e; ++i) { - delete *i; + for_const (PhotoData *photo, ::photosData) { + delete photo; } ::photosData.clear(); - for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) { - delete *i; + for_const (DocumentData *document, ::documentsData) { + delete document; } ::documentsData.clear(); - for (WebPagesData::const_iterator i = webPagesData.cbegin(), e = webPagesData.cend(); i != e; ++i) { - delete *i; + for_const (WebPageData *webpage, webPagesData) { + delete webpage; } webPagesData.clear(); if (api()) api()->clearWebPageRequests(); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index ebe1711e5..ac475da29 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -64,7 +64,6 @@ namespace App { ApiWrap *api(); void logOut(); - bool loggedOut(); QString formatPhone(QString phone); diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index ee475348b..97d672a1d 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -941,6 +941,8 @@ void EmojiPanInner::selectEmoji(EmojiPtr emoji) { } void EmojiPanInner::onShowPicker() { + if (_pickerSel < 0) return; + int tab = (_pickerSel / MatrixRowShift), sel = _pickerSel % MatrixRowShift; if (tab < emojiTabCount && sel < _emojis[tab].size() && _emojis[tab][sel]->color) { int32 y = 0; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 0b9557e3d..d89aec33f 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -86,6 +86,12 @@ namespace App { } } + void logOutDelayed() { + if (Window *w = App::wnd()) { + QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection); + } + } + } namespace Ui { diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index ba77a20a2..14b16742e 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -37,6 +37,8 @@ namespace App { void activateTextLink(TextLinkPtr link, Qt::MouseButton button); + void logOutDelayed(); + }; namespace Ui { diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 3231bf89f..9aa63c654 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -1125,6 +1125,8 @@ void Histories::clear() { for (Map::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) { delete i.value(); } + Global::RefPendingRepaintItems().clear(); + _unreadFull = _unreadMuted = 0; if (App::wnd()) { App::wnd()->updateCounter(); @@ -2753,13 +2755,17 @@ void HistoryMessageUnreadBar::init(int count) { _width = st::semiboldFont->width(_text); } -int HistoryMessageUnreadBar::height() const { - return st::unreadBarHeight; +int HistoryMessageUnreadBar::height() { + return st::unreadBarHeight + st::unreadBarMargin; +} + +int HistoryMessageUnreadBar::marginTop() { + return st::lineWidth + st::unreadBarMargin; } void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const { - p.fillRect(0, y + st::lineWidth, w, st::unreadBarHeight - 2 * st::lineWidth, st::unreadBarBG); - p.fillRect(0, y + st::unreadBarHeight - st::lineWidth, w, st::lineWidth, st::unreadBarBorder); + p.fillRect(0, y + marginTop(), w, height() - marginTop() - st::lineWidth, st::unreadBarBG); + p.fillRect(0, y + height() - st::lineWidth, w, st::lineWidth, st::unreadBarBorder); p.setFont(st::unreadBarFont); p.setPen(st::unreadBarColor); @@ -2770,7 +2776,7 @@ void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const { } w = maxwidth; - p.drawText((w - _width) / 2, y + (st::unreadBarHeight - st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text); + p.drawText((w - _width) / 2, y + marginTop() + (st::unreadBarHeight - 2 * st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text); } void HistoryMessageDate::init(const QDateTime &date) { @@ -2833,6 +2839,7 @@ void HistoryItem::destroy() { if ((!out() || isPost()) && unread() && history()->unreadCount > 0) { history()->setUnreadCount(history()->unreadCount - 1); } + Global::RefPendingRepaintItems().remove(this); delete this; } @@ -3039,7 +3046,8 @@ void RadialAnimation::update(float64 prg, bool finished, uint64 ms) { _opacity *= 1 - r; } float64 fromstart = fulldt / st::radialPeriod; - a_arcStart.update(fromstart - qFloor(fromstart), anim::linear); + float64 fromstartpart = fromstart - std::floor(fromstart); + a_arcStart.update(static_cast<int>(fromstartpart), anim::linear); } void RadialAnimation::stop() { @@ -4862,7 +4870,7 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, } if (parent->getMedia() == this) { - parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverImage); + parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverBackground); if (reply) { int32 rw = _width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom(); @@ -6630,18 +6638,24 @@ bool HistoryMessage::textHasLinks() { void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const { p.setFont(st::msgDateFont); - bool outbg = out() && !isPost(), overimg = (type == InfoDisplayOverImage); + bool outbg = out() && !isPost(); + bool invertedsprites = (type == InfoDisplayOverImage || type == InfoDisplayOverBackground); int32 infoRight = right, infoBottom = bottom; switch (type) { case InfoDisplayDefault: infoRight -= st::msgPadding.right() - st::msgDateDelta.x(); infoBottom -= st::msgPadding.bottom() - st::msgDateDelta.y(); - p.setPen((selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg))->p); + p.setPen(selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg)); break; case InfoDisplayOverImage: infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x(); infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y(); - p.setPen(st::msgDateImgColor->p); + p.setPen(st::msgDateImgColor); + break; + case InfoDisplayOverBackground: + infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x(); + infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y(); + p.setPen(st::msgServiceColor); break; } @@ -6653,6 +6667,9 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width if (type == InfoDisplayOverImage) { int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y(); App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); + } else if (type == InfoDisplayOverBackground) { + int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y(); + App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, App::msgServiceBg(), ServiceCorners); } dateX += HistoryMessage::timeLeft(); @@ -6668,35 +6685,35 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width iconPos = QPoint(infoRight - infoW + st::msgViewsPos.x(), infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y()); if (id > 0) { if (outbg) { - iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg)); + iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg)); } else { - iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg)); + iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg)); } p.drawText(iconPos.x() + st::msgViewsImg.pxWidth() + st::msgDateCheckSpace, infoBottom - st::msgDateFont->descent, views->_viewsText); } else { iconPos.setX(iconPos.x() + st::msgDateViewsSpace + views->_viewsWidth); if (outbg) { - iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg); + iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg); } else { - iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg); + iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg); } } p.drawPixmap(iconPos, App::sprite(), *iconRect); } else if (id < 0 && history()->peer->isSelf()) { iconPos = QPoint(infoRight - infoW, infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y()); - iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg); + iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg); p.drawPixmap(iconPos, App::sprite(), *iconRect); } if (outbg) { iconPos = QPoint(infoRight - st::msgCheckImg.pxWidth() + st::msgCheckPos.x(), infoBottom - st::msgCheckImg.pxHeight() + st::msgCheckPos.y()); if (id > 0) { if (unread()) { - iconRect = &(overimg ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg)); + iconRect = &(invertedsprites ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg)); } else { - iconRect = &(overimg ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg)); + iconRect = &(invertedsprites ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg)); } } else { - iconRect = &(overimg ? st::msgInvSendingImg : st::msgSendingImg); + iconRect = &(invertedsprites ? st::msgInvSendingImg : st::msgSendingImg); } p.drawPixmap(iconPos, App::sprite(), *iconRect); } diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 1dd9dd95e..4d8350488 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -987,6 +987,7 @@ enum HistoryCursorState { enum InfoDisplayType { InfoDisplayDefault, InfoDisplayOverImage, + InfoDisplayOverBackground, }; inline bool isImportantChannelMessage(MsgId id, MTPDmessage::Flags flags) { // client-side important msgs always has_views or has_from_id @@ -1130,7 +1131,9 @@ struct HistoryMessageUnreadBar : public BaseComponent<HistoryMessageUnreadBar> { } void init(int count); - int height() const; + static int height(); + static int marginTop(); + void paint(Painter &p, int y, int w) const; QString _text; @@ -1536,8 +1539,11 @@ protected: HistoryItem *previous() const { if (_block && _indexInBlock >= 0) { - if (_indexInBlock > 0) return _block->items.at(_indexInBlock - 1); + if (_indexInBlock > 0) { + return _block->items.at(_indexInBlock - 1); + } if (HistoryBlock *previousBlock = _block->previous()) { + t_assert(!previousBlock->items.isEmpty()); return previousBlock->items.back(); } } diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index c8f665649..43cd4b360 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -6444,7 +6444,9 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh if (_pinnedBar) { newScrollHeight -= st::replyHeight; } - bool wasAtBottom = _scroll.scrollTop() + 1 > _scroll.scrollTopMax(), needResize = _scroll.width() != width() || _scroll.height() != newScrollHeight; + int wasScrollTop = _scroll.scrollTop(); + bool wasAtBottom = wasScrollTop + 1 > _scroll.scrollTopMax(); + bool needResize = (_scroll.width() != width()) || (_scroll.height() != newScrollHeight); if (needResize) { _scroll.resize(width(), newScrollHeight); // on initial updateListSize we didn't put the _scroll.scrollTop correctly yet @@ -6470,14 +6472,15 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh } if ((!initial && !wasAtBottom) || (loadedDown && (!_history->showFrom || _history->unreadBar || _history->loadedAtBottom()) && (!_migrated || !_migrated->showFrom || _migrated->unreadBar || _history->loadedAtBottom()))) { - int addToY = 0; + int toY = _list->historyScrollTop(); if (change.type == ScrollChangeAdd) { - addToY = change.value; - } else if (change.type == ScrollChangeOldHistoryHeight) { - addToY = _list->historyHeight() - change.value; + toY += change.value; + } else if (change.type == ScrollChangeNoJumpToBottom) { + toY = wasScrollTop; + } + if (toY > _scroll.scrollTopMax()) { + toY = _scroll.scrollTopMax(); } - int toY = _list->historyScrollTop() + addToY; - if (toY > _scroll.scrollTopMax()) toY = _scroll.scrollTopMax(); if (_scroll.scrollTop() == toY) { visibleAreaUpdated(); } else { @@ -6555,19 +6558,11 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh } else { toY = qMax(iy + item->height() - _fixedInScrollMsgTop, 0); } - } else if (initial && _migrated && _migrated->unreadBar) { - toY = _list->itemTop(_migrated->unreadBar); - if (_migrated->unreadBar->Has<HistoryMessageDate>()) { - toY += _migrated->unreadBar->Get<HistoryMessageDate>()->height(); - } - } else if (initial && _history->unreadBar) { - toY = _list->itemTop(_history->unreadBar); - if (_history->unreadBar->Has<HistoryMessageDate>()) { - toY += _history->unreadBar->Get<HistoryMessageDate>()->height(); - } + } else if (initial && (_history->unreadBar || (_migrated && _migrated->unreadBar))) { + toY = unreadBarTop(); } else if (_migrated && _migrated->showFrom) { toY = _list->itemTop(_migrated->showFrom); - if (toY < _scroll.scrollTopMax() + st::unreadBarHeight) { + if (toY < _scroll.scrollTopMax() + HistoryMessageUnreadBar::height() - HistoryMessageUnreadBar::marginTop()) { _migrated->addUnreadBar(); if (_migrated->unreadBar) { setMsgId(ShowAtUnreadMsgId); @@ -6599,6 +6594,26 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh } } +int HistoryWidget::unreadBarTop() const { + auto getUnreadBar = [this]() -> HistoryItem* { + if (_migrated && _migrated->unreadBar) { + return _migrated->unreadBar; + } + if (_history->unreadBar) { + return _history->unreadBar; + } + return nullptr; + }; + if (HistoryItem *bar = getUnreadBar()) { + int result = _list->itemTop(bar) + HistoryMessageUnreadBar::marginTop(); + if (bar->Has<HistoryMessageDate>()) { + result += bar->Get<HistoryMessageDate>()->height(); + } + return result; + } + return -1; +} + void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) { int oldH = _list->historyHeight(); _list->messagesReceived(peer, messages, collapsed); @@ -6617,7 +6632,7 @@ void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage> void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) { _list->messagesReceivedDown(peer, messages, collapsed); if (!_firstLoadRequest) { - updateListSize(false, true); + updateListSize(false, true, { ScrollChangeNoJumpToBottom, 0 }); } } @@ -7001,7 +7016,10 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() { _topShadow.raise(); updatePinnedBar(); result = true; - _scroll.scrollToY(_scroll.scrollTop() + st::replyHeight); + + if (_scroll.scrollTop() != unreadBarTop()) { + _scroll.scrollToY(_scroll.scrollTop() + st::replyHeight); + } } else if (_pinnedBar->msgId != pinnedMsgId) { _pinnedBar->msgId = pinnedMsgId; _pinnedBar->msg = 0; @@ -7015,7 +7033,9 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() { } else if (_pinnedBar) { destroyPinnedBar(); result = true; - _scroll.scrollToY(_scroll.scrollTop() - st::replyHeight); + if (_scroll.scrollTop() != unreadBarTop()) { + _scroll.scrollToY(_scroll.scrollTop() - st::replyHeight); + } resizeEvent(0); } return result; diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 5eabc4ffb..d8d8b542e 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -834,8 +834,12 @@ private: enum ScrollChangeType { ScrollChangeNone, + + // When we toggle a pinned message. ScrollChangeAdd, - ScrollChangeOldHistoryHeight, + + // When loading a history part while scrolling down. + ScrollChangeNoJumpToBottom, }; struct ScrollChange { ScrollChangeType type; @@ -843,6 +847,10 @@ private: }; void updateListSize(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 }); + // Counts scrollTop for placing the scroll right at the unread + // messages bar, choosing from _history and _migrated unreadBar. + int unreadBarTop() const; + void saveGifDone(DocumentData *doc, const MTPBool &result); void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 2f2805d1e..b62ea7d61 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -2958,9 +2958,7 @@ void MainWidget::feedMessageIds(const MTPVector<MTPUpdate> &updates) { } bool MainWidget::updateFail(const RPCError &e) { - if (MTP::authedId()) { - App::logOut(); - } + App::logOutDelayed(); return true; } @@ -3707,7 +3705,7 @@ bool MainWidget::inviteImportFail(const RPCError &error) { void MainWidget::startFull(const MTPVector<MTPUser> &users) { const QVector<MTPUser> &v(users.c_vector().v); if (v.isEmpty() || v[0].type() != mtpc_user || !v[0].c_user().is_self()) { // wtf?.. - return App::logOut(); + return App::logOutDelayed(); } start(v[0]); } diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 3a775b9cb..bbf44693d 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -650,20 +650,20 @@ MimeType mimeTypeForName(const QString &mime); MimeType mimeTypeForFile(const QFileInfo &file); MimeType mimeTypeForData(const QByteArray &data); -inline int32 rowscount(int32 count, int32 perrow) { - return (count + perrow - 1) / perrow; +inline int rowscount(int fullCount, int countPerRow) { + return (fullCount + countPerRow - 1) / countPerRow; } -inline int32 floorclamp(int32 value, int32 step, int32 lowest, int32 highest) { +inline int floorclamp(int value, int step, int lowest, int highest) { return qMin(qMax(value / step, lowest), highest); } -inline int32 floorclamp(float64 value, int32 step, int32 lowest, int32 highest) { - return qMin(qMax(qFloor(value / step), lowest), highest); +inline int floorclamp(float64 value, int step, int lowest, int highest) { + return qMin(qMax(static_cast<int>(std::floor(value / step)), lowest), highest); } -inline int32 ceilclamp(int32 value, int32 step, int32 lowest, int32 highest) { - return qMax(qMin((value / step) + ((value % step) ? 1 : 0), highest), lowest); +inline int ceilclamp(int value, int step, int lowest, int highest) { + return qMax(qMin((value + step - 1) / step, highest), lowest); } -inline int32 ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) { - return qMax(qMin(qCeil(value / step), highest), lowest); +inline int ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) { + return qMax(qMin(static_cast<int>(std::ceil(value / step)), highest), lowest); } enum ForwardWhatMessages { diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index 6decac3f6..74d58158e 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -507,11 +507,8 @@ void Window::clearWidgets() { settings = 0; } if (main) { - main->animStop_show(); - main->hide(); - main->deleteLater(); - main->rpcClear(); - main = 0; + delete main; + main = nullptr; } if (intro) { intro->stop_show(); @@ -693,7 +690,7 @@ void Window::setupMain(bool anim, const MTPUser *self) { } void Window::updateCounter() { - if (App::quitting()) return; + if (!Global::started() || App::quitting()) return; psUpdateCounter(); title->updateCounter(); @@ -1178,7 +1175,11 @@ void Window::onLogout() { } void Window::onLogoutSure() { - App::logOut(); + if (MTP::authedId()) { + App::logOut(); + } else { + setupIntro(true); + } } void Window::updateGlobalMenu() { @@ -1944,7 +1945,10 @@ PreLaunchWindow::PreLaunchWindow(QString title) : TWidget(0) { tmp.setText(qsl("Tmp")); _size = tmp.sizeHint().height(); - setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(qFloor(_size / 2)).arg(qFloor(_size)).arg(qFloor(_size / 5))); + int paddingVertical = (_size / 2); + int paddingHorizontal = _size; + int borderRadius = (_size / 5); + setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(paddingVertical).arg(paddingHorizontal).arg(borderRadius)); if (!PreLaunchWindowInstance) { PreLaunchWindowInstance = this; } diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h index cecad8cf7..0fd5df1b4 100644 --- a/Telegram/SourceFiles/window.h +++ b/Telegram/SourceFiles/window.h @@ -362,7 +362,7 @@ public: PreLaunchWindow(QString title = QString()); void activate(); - float64 basicSize() const { + int basicSize() const { return _size; } ~PreLaunchWindow(); @@ -371,7 +371,7 @@ public: protected: - float64 _size; + int _size; }; From 829513c9ce654af4e2dc74a59164d888f45fd2e8 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Thu, 31 Mar 2016 18:12:30 +0400 Subject: [PATCH 11/17] fixed building for OS X / Linux --- Telegram/SourceFiles/logs.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index 916193635..c57528911 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -1023,13 +1023,13 @@ namespace internal { internal::ReportFile = nullptr; } #else // Q_OS_WIN - CrashDumpFile = fopen(QFile::encodeName(CrashDumpPath).constData(), "wb"); + internal::ReportFile = fopen(QFile::encodeName(internal::ReportPath).constData(), "wb"); #endif // else for Q_OS_WIN if (internal::ReportFile) { #ifdef Q_OS_WIN internal::ReportFileNo = _fileno(internal::ReportFile); #else // Q_OS_WIN - CrashDumpFileNo = fileno(internal::ReportFile); + internal::ReportFileNo = fileno(internal::ReportFile); #endif // else for Q_OS_WIN if (internal::SetSignalHandlers) { #ifndef Q_OS_WIN @@ -1039,12 +1039,12 @@ namespace internal { sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO; - sigaction(SIGABRT, &sigact, &SIG_def[SIGABRT]); - sigaction(SIGSEGV, &sigact, &SIG_def[SIGSEGV]); - sigaction(SIGILL, &sigact, &SIG_def[SIGILL]); - sigaction(SIGFPE, &sigact, &SIG_def[SIGFPE]); - sigaction(SIGBUS, &sigact, &SIG_def[SIGBUS]); - sigaction(SIGSYS, &sigact, &SIG_def[SIGSYS]); + sigaction(SIGABRT, &sigact, &internal::SIG_def[SIGABRT]); + sigaction(SIGSEGV, &sigact, &internal::SIG_def[SIGSEGV]); + sigaction(SIGILL, &sigact, &internal::SIG_def[SIGILL]); + sigaction(SIGFPE, &sigact, &internal::SIG_def[SIGFPE]); + sigaction(SIGBUS, &sigact, &internal::SIG_def[SIGBUS]); + sigaction(SIGSYS, &sigact, &internal::SIG_def[SIGSYS]); #else // !Q_OS_WIN signal(SIGABRT, SignalHandlers::internal::Handler); signal(SIGSEGV, SignalHandlers::internal::Handler); From f1c69a495ba02e8bcdd4096e3b4e4c74daf9e049 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Thu, 31 Mar 2016 18:26:38 +0400 Subject: [PATCH 12/17] 0.9.37 dev version --- Telegram/SourceFiles/config.h | 4 ++-- Telegram/Telegram.plist | 2 +- Telegram/Telegram.rc | 8 ++++---- Telegram/Telegram.xcodeproj/project.pbxproj | 12 ++++++------ Telegram/Version | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 39e5008f3..432abb6df 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -20,8 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -static const int32 AppVersion = 9036; -static const wchar_t *AppVersionStr = L"0.9.36"; +static const int32 AppVersion = 9037; +static const wchar_t *AppVersionStr = L"0.9.37"; static const bool DevVersion = true; //#define BETA_VERSION (9034004ULL) // just comment this line to build public version diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index 8e055f9b7..e697ce59e 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>0.9.36</string> + <string>0.9.37</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleURLTypes</key> diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index a6392a42a..c3b1412a0 100644 --- a/Telegram/Telegram.rc +++ b/Telegram/Telegram.rc @@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,36,0 - PRODUCTVERSION 0,9,36,0 + FILEVERSION 0,9,37,0 + PRODUCTVERSION 0,9,37,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -51,10 +51,10 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Telegram Messenger LLP" - VALUE "FileVersion", "0.9.36.0" + VALUE "FileVersion", "0.9.37.0" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.9.36.0" + VALUE "ProductVersion", "0.9.37.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index 7c99556fb..5b81e5f17 100644 --- a/Telegram/Telegram.xcodeproj/project.pbxproj +++ b/Telegram/Telegram.xcodeproj/project.pbxproj @@ -1772,7 +1772,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.36; + CURRENT_PROJECT_VERSION = 0.9.37; DEBUG_INFORMATION_FORMAT = dwarf; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1791,7 +1791,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 0.9.36; + CURRENT_PROJECT_VERSION = 0.9.37; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = fast; GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h; @@ -1820,10 +1820,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.36; + CURRENT_PROJECT_VERSION = 0.9.37; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 0.9; - DYLIB_CURRENT_VERSION = 0.9.36; + DYLIB_CURRENT_VERSION = 0.9.37; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; @@ -1961,10 +1961,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.36; + CURRENT_PROJECT_VERSION = 0.9.37; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 0.9; - DYLIB_CURRENT_VERSION = 0.9.36; + DYLIB_CURRENT_VERSION = 0.9.37; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ""; diff --git a/Telegram/Version b/Telegram/Version index 2227962ec..6c83176cd 100644 --- a/Telegram/Version +++ b/Telegram/Version @@ -1,6 +1,6 @@ -AppVersion 9036 +AppVersion 9037 AppVersionStrMajor 0.9 -AppVersionStrSmall 0.9.36 -AppVersionStr 0.9.36 +AppVersionStrSmall 0.9.37 +AppVersionStr 0.9.37 DevChannel 1 BetaVersion 0 9034004 From f96b7da7ce92440b1c72fb9eb3d29a0f33160a12 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Fri, 1 Apr 2016 00:36:46 +0400 Subject: [PATCH 13/17] Crash reporting fixed, radial progress fixed. 0.9.38 dev version. --- Telegram/SourceFiles/config.h | 4 ++-- Telegram/SourceFiles/history.cpp | 3 +-- Telegram/SourceFiles/logs.cpp | 10 +++++----- Telegram/Telegram.plist | 2 +- Telegram/Telegram.rc | 8 ++++---- Telegram/Telegram.xcodeproj/project.pbxproj | 12 ++++++------ Telegram/Version | 6 +++--- 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 432abb6df..c8a83ff05 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -20,8 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -static const int32 AppVersion = 9037; -static const wchar_t *AppVersionStr = L"0.9.37"; +static const int32 AppVersion = 9038; +static const wchar_t *AppVersionStr = L"0.9.38"; static const bool DevVersion = true; //#define BETA_VERSION (9034004ULL) // just comment this line to build public version diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 9aa63c654..bbfb98731 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -3046,8 +3046,7 @@ void RadialAnimation::update(float64 prg, bool finished, uint64 ms) { _opacity *= 1 - r; } float64 fromstart = fulldt / st::radialPeriod; - float64 fromstartpart = fromstart - std::floor(fromstart); - a_arcStart.update(static_cast<int>(fromstartpart), anim::linear); + a_arcStart.update(fromstart - std::floor(fromstart), anim::linear); } void RadialAnimation::stop() { diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index c57528911..668990da2 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -1080,18 +1080,18 @@ namespace internal { } void setCrashAnnotation(const std::string &key, const QString &value) { - if (value.trimmed().isEmpty()) { - internal::ProcessAnnotations.erase(key); - } else { + if (!value.trimmed().isEmpty()) { internal::ProcessAnnotations[key] = value.toUtf8().constData(); + } else { + internal::ProcessAnnotations.erase(key); } } void setCrashAnnotationRef(const std::string &key, const QString *valuePtr) { if (valuePtr) { - internal::ProcessAnnotationRefs.erase(key); - } else { internal::ProcessAnnotationRefs[key] = valuePtr; + } else { + internal::ProcessAnnotationRefs.erase(key); } } diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index e697ce59e..3cb7a80d9 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>0.9.37</string> + <string>0.9.38</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleURLTypes</key> diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index c3b1412a0..dc73d5daa 100644 --- a/Telegram/Telegram.rc +++ b/Telegram/Telegram.rc @@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,37,0 - PRODUCTVERSION 0,9,37,0 + FILEVERSION 0,9,38,0 + PRODUCTVERSION 0,9,38,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -51,10 +51,10 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Telegram Messenger LLP" - VALUE "FileVersion", "0.9.37.0" + VALUE "FileVersion", "0.9.38.0" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.9.37.0" + VALUE "ProductVersion", "0.9.38.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index 5b81e5f17..8f77b8522 100644 --- a/Telegram/Telegram.xcodeproj/project.pbxproj +++ b/Telegram/Telegram.xcodeproj/project.pbxproj @@ -1772,7 +1772,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.37; + CURRENT_PROJECT_VERSION = 0.9.38; DEBUG_INFORMATION_FORMAT = dwarf; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1791,7 +1791,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 0.9.37; + CURRENT_PROJECT_VERSION = 0.9.38; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = fast; GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h; @@ -1820,10 +1820,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.37; + CURRENT_PROJECT_VERSION = 0.9.38; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 0.9; - DYLIB_CURRENT_VERSION = 0.9.37; + DYLIB_CURRENT_VERSION = 0.9.38; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; @@ -1961,10 +1961,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.37; + CURRENT_PROJECT_VERSION = 0.9.38; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 0.9; - DYLIB_CURRENT_VERSION = 0.9.37; + DYLIB_CURRENT_VERSION = 0.9.38; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ""; diff --git a/Telegram/Version b/Telegram/Version index 6c83176cd..59825138f 100644 --- a/Telegram/Version +++ b/Telegram/Version @@ -1,6 +1,6 @@ -AppVersion 9037 +AppVersion 9038 AppVersionStrMajor 0.9 -AppVersionStrSmall 0.9.37 -AppVersionStr 0.9.37 +AppVersionStrSmall 0.9.38 +AppVersionStr 0.9.38 DevChannel 1 BetaVersion 0 9034004 From 1f6da4c7346cfad264411552dcfb1f2a9740f0f9 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Fri, 1 Apr 2016 11:43:14 +0400 Subject: [PATCH 14/17] Logging crashed string in hexdump ofutf8. --- Telegram/SourceFiles/logs.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index 668990da2..0040b4f1b 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -768,9 +768,24 @@ namespace internal { if (!ReportingHeaderWritten) { ReportingHeaderWritten = true; + auto dec2hex = [](int value) -> char { + if (value >= 0 && value < 10) { + return '0' + value; + } else if (value >= 10 && value < 16) { + return 'a' + (value - 10); + } + return '#'; + }; for (const auto &i : ProcessAnnotationRefs) { - ProcessAnnotations[i.first] = i.second->toUtf8().constData(); + QByteArray utf8 = i.second->toUtf8(); + std::string wrapped; + wrapped.reserve(4 * utf8.size()); + for (auto ch : utf8) { + auto uch = static_cast<uchar>(ch); + wrapped.append("\\x", 2).append(1, dec2hex(uch >> 4)).append(1, dec2hex(uch & 0x0F)); + } + ProcessAnnotations[i.first] = wrapped; } const Annotations c_ProcessAnnotations(ProcessAnnotations); From 73a27c2def85c60d1151919fc7688db8ff3ec79a Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Fri, 1 Apr 2016 11:52:25 +0400 Subject: [PATCH 15/17] Not painting anything in HistoryInner if _history or _migrated have pending resized items. --- Telegram/SourceFiles/historywidget.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 43cd4b360..a56f48750 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -193,18 +193,16 @@ void HistoryInner::enumerateUserpicsInHistory(History *h, int htop, Method metho } void HistoryInner::paintEvent(QPaintEvent *e) { - if (App::wnd() && App::wnd()->contentOverlapped(this, e)) return; + if (App::wnd() && App::wnd()->contentOverlapped(this, e)) { + return; + } - if (!App::main()) return; + if (!App::main()) { + return; + } if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) { - Notify::handlePendingHistoryUpdate(); - if (_history) { - t_assert(!_history->hasPendingResizedItems()); - } - if (_migrated) { - t_assert(!_migrated->hasPendingResizedItems()); - } + return; } Painter p(this); From 2826bb9134d35d1b791ba52fdfba8864eed8f434 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Fri, 1 Apr 2016 11:57:30 +0400 Subject: [PATCH 16/17] 0.9.39 dev version (possible crash fix) --- Telegram/SourceFiles/config.h | 4 ++-- Telegram/Telegram.plist | 2 +- Telegram/Telegram.rc | 8 ++++---- Telegram/Telegram.xcodeproj/project.pbxproj | 12 ++++++------ Telegram/Version | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index c8a83ff05..270dc855f 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -20,8 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -static const int32 AppVersion = 9038; -static const wchar_t *AppVersionStr = L"0.9.38"; +static const int32 AppVersion = 9039; +static const wchar_t *AppVersionStr = L"0.9.39"; static const bool DevVersion = true; //#define BETA_VERSION (9034004ULL) // just comment this line to build public version diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist index 3cb7a80d9..d2af99bfb 100644 --- a/Telegram/Telegram.plist +++ b/Telegram/Telegram.plist @@ -11,7 +11,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>0.9.38</string> + <string>0.9.39</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleURLTypes</key> diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc index dc73d5daa..f9be16de3 100644 --- a/Telegram/Telegram.rc +++ b/Telegram/Telegram.rc @@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,38,0 - PRODUCTVERSION 0,9,38,0 + FILEVERSION 0,9,39,0 + PRODUCTVERSION 0,9,39,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -51,10 +51,10 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Telegram Messenger LLP" - VALUE "FileVersion", "0.9.38.0" + VALUE "FileVersion", "0.9.39.0" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.9.38.0" + VALUE "ProductVersion", "0.9.39.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj index 8f77b8522..bed09ed1b 100644 --- a/Telegram/Telegram.xcodeproj/project.pbxproj +++ b/Telegram/Telegram.xcodeproj/project.pbxproj @@ -1772,7 +1772,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.38; + CURRENT_PROJECT_VERSION = 0.9.39; DEBUG_INFORMATION_FORMAT = dwarf; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1791,7 +1791,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 0.9.38; + CURRENT_PROJECT_VERSION = 0.9.39; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_OPTIMIZATION_LEVEL = fast; GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h; @@ -1820,10 +1820,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.38; + CURRENT_PROJECT_VERSION = 0.9.39; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 0.9; - DYLIB_CURRENT_VERSION = 0.9.38; + DYLIB_CURRENT_VERSION = 0.9.39; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ""; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; @@ -1961,10 +1961,10 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.9.38; + CURRENT_PROJECT_VERSION = 0.9.39; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 0.9; - DYLIB_CURRENT_VERSION = 0.9.38; + DYLIB_CURRENT_VERSION = 0.9.39; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ""; diff --git a/Telegram/Version b/Telegram/Version index 59825138f..355c48b4b 100644 --- a/Telegram/Version +++ b/Telegram/Version @@ -1,6 +1,6 @@ -AppVersion 9038 +AppVersion 9039 AppVersionStrMajor 0.9 -AppVersionStrSmall 0.9.38 -AppVersionStr 0.9.38 +AppVersionStrSmall 0.9.39 +AppVersionStr 0.9.39 DevChannel 1 BetaVersion 0 9034004 From 174302a90771bb6571454ee96b6f6bc9af42cf23 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Fri, 1 Apr 2016 12:50:02 +0400 Subject: [PATCH 17/17] Ignoring 4099 warning in VS project linking. Added <cmath> header to precompiled header and std:: math usage. --- Telegram/SourceFiles/stdafx.h | 2 ++ Telegram/SourceFiles/types.h | 2 ++ Telegram/Telegram.vcxproj | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index 12885f468..e87a6c5b0 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -25,6 +25,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #ifdef __cplusplus +#include <cmath> + #include <QtCore/QtCore> #include <QtWidgets/QtWidgets> #include <QtNetwork/QtNetwork> diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index bbf44693d..babef3cb0 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -650,6 +650,8 @@ MimeType mimeTypeForName(const QString &mime); MimeType mimeTypeForFile(const QFileInfo &file); MimeType mimeTypeForData(const QByteArray &data); +#include <cmath> + inline int rowscount(int fullCount, int countPerRow) { return (fullCount + countPerRow - 1) / countPerRow; } diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 8b18f8ada..cdde8b981 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -123,6 +123,7 @@ <OptimizeReferences>true</OptimizeReferences> <IgnoreSpecificDefaultLibraries> </IgnoreSpecificDefaultLibraries> + <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'"> @@ -154,6 +155,7 @@ <OptimizeReferences>true</OptimizeReferences> <IgnoreSpecificDefaultLibraries> </IgnoreSpecificDefaultLibraries> + <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> <ItemGroup>