From f8379b140bf09d1dd7ff31461d925c7aae22b5c5 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 4 Jan 2016 19:44:18 +0800 Subject: [PATCH 001/103] updated docs --- QTCREATOR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QTCREATOR.md b/QTCREATOR.md index 83f021060..13baf5442 100644 --- a/QTCREATOR.md +++ b/QTCREATOR.md @@ -61,7 +61,7 @@ In Terminal go to **/home/user/TBuild/Libraries** and run sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev sudo apt-get install yasm - ./configure --prefix=/usr/local --disable-programs --disable-doc --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=flac --enable-decoder=gif --enable-decoder=h264 --enable-decoder=h264_vdpau --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=mpeg4 --enable-decoder=mpeg4_vdpau --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wavpack --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-hwaccel=h264_vaapi --enable-hwaccel=h264_vdpau --enable-hwaccel=mpeg4_vaapi --enable-hwaccel=mpeg4_vdpau --enable-parser=aac --enable-parser=aac_latm --enable-parser=flac --enable-parser=h264 --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=flac --enable-demuxer=gif --enable-demuxer=h264 --enable-demuxer=mov --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=wav --enable-muxer=ogg --enable-muxer=opus + ./configure --prefix=/usr/local --disable-programs --disable-pthreads --disable-doc --disable-everything --enable-libopus --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=aasc --enable-decoder=flac --enable-decoder=gif --enable-decoder=h264 --enable-decoder=h264_vdpau --enable-decoder=mp1 --enable-decoder=mp1float --enable-decoder=mp2 --enable-decoder=mp2float --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=mpeg4 --enable-decoder=mpeg4_vdpau --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=opus --enable-decoder=vorbis --enable-decoder=wavpack --enable-decoder=wmalossless --enable-decoder=wmapro --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmavoice --enable-encoder=libopus --enable-hwaccel=h264_vaapi --enable-hwaccel=h264_vdpau --enable-hwaccel=mpeg4_vaapi --enable-hwaccel=mpeg4_vdpau --enable-parser=aac --enable-parser=aac_latm --enable-parser=flac --enable-parser=h264 --enable-parser=mpeg4video --enable-parser=mpegaudio --enable-parser=opus --enable-parser=vorbis --enable-demuxer=aac --enable-demuxer=flac --enable-demuxer=gif --enable-demuxer=h264 --enable-demuxer=mov --enable-demuxer=mp3 --enable-demuxer=ogg --enable-demuxer=wav --enable-muxer=ogg --enable-muxer=opus make sudo make install From 3a919628b3a8875dc46f96348b2303ff4949a903 Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Thu, 18 Feb 2016 21:28:38 -0300 Subject: [PATCH 002/103] Include some reference XDG files Include a .desktop file (for app menu in xdg-complaint desktops), and tg.protocol (for having xdg-complaint apps pick up the tg: protocol). Signed-off-by: Hugo Osvaldo Barrera (github: hobarrera) --- lib/xdg/telegramdesktop.desktop | 12 ++++++++++++ lib/xdg/tg.protocol | 11 +++++++++++ 2 files changed, 23 insertions(+) create mode 100644 lib/xdg/telegramdesktop.desktop create mode 100644 lib/xdg/tg.protocol diff --git a/lib/xdg/telegramdesktop.desktop b/lib/xdg/telegramdesktop.desktop new file mode 100644 index 000000000..2151d0ad4 --- /dev/null +++ b/lib/xdg/telegramdesktop.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=Telegram Desktop +Comment=Official desktop version of Telegram messaging app +Exec=/usr/bin/telegram-desktop -- %u +Icon=telegram-desktop +Terminal=false +StartupWMClass=Telegram +Type=Application +Categories=Network; +MimeType=application/x-xdg-protocol-tg;x-scheme-handler/tg; diff --git a/lib/xdg/tg.protocol b/lib/xdg/tg.protocol new file mode 100644 index 000000000..a4b083acb --- /dev/null +++ b/lib/xdg/tg.protocol @@ -0,0 +1,11 @@ +[Protocol] +exec=/usr/bin/telegram-desktop -- %u +protocol=tg +input=none +output=none +helper=true +listing=false +reading=false +writing=false +makedir=false +deleting=false From 580306d090c84dc5f1042b2947f7b7f7dd6955ce Mon Sep 17 00:00:00 2001 From: Christoph Auer Date: Thu, 17 Mar 2016 20:46:09 +0100 Subject: [PATCH 003/103] Fix path in doc/building-xcode.md Closes #1794 Signed-off-by: Christoph Auer --- doc/building-xcode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/building-xcode.md b/doc/building-xcode.md index e52069781..a88516bc0 100644 --- a/doc/building-xcode.md +++ b/doc/building-xcode.md @@ -235,7 +235,7 @@ In Terminal go to **/Users/user/TBuild/Libraries** and run: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git cd gyp ./setup.py build - sudo setup.py install + sudo ./setup.py install cd .. #####Build crashpad From 729a024ddf2330bbe5b5587848467c64d7f0542a Mon Sep 17 00:00:00 2001 From: Christoph Auer Date: Wed, 24 Feb 2016 22:10:28 +0100 Subject: [PATCH 004/103] Add Travis CI files Signed-off-by: Christoph Auer --- .travis.yml | 42 +++++++ .travis/arch.sh | 296 +++++++++++++++++++++++++++++++++++++++++++++++ .travis/build.sh | 191 ++++++++++++++++++++++++++++++ 3 files changed, 529 insertions(+) create mode 100644 .travis.yml create mode 100755 .travis/arch.sh create mode 100755 .travis/build.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..11a9c3adb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,42 @@ +sudo: required + +language: cpp + +env: + - BUILD_VERSION="" + - BUILD_VERSION="no_autoupdate" + - BUILD_VERSION="no_custom_scheme" + - BUILD_VERSION="no_autoupdate+no_custom_scheme" + +arch: + packages: + - bzr + - wget + - qt5-base + + - git + - patch + - libunity + - libappindicator-gtk2 + + - ffmpeg + - icu + - jasper + - libexif + - libmng + - libwebp + - libxkbcommon-x11 + - libinput + - libproxy + - mtdev + - openal + - libva + - desktop-file-utils + - gtk-update-icon-cache + + script: + - libtool --finish /usr/lib + - .travis/build.sh + +script: + - .travis/arch.sh \ No newline at end of file diff --git a/.travis/arch.sh b/.travis/arch.sh new file mode 100755 index 000000000..fbe132bbd --- /dev/null +++ b/.travis/arch.sh @@ -0,0 +1,296 @@ +#!/bin/bash +# Copyright (C) 2016 Mikkel Oscar Lyderik Larsen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Source: https://raw.githubusercontent.com/mikkeloscar/arch-travis/master/arch-travis.sh + +# Script for setting up and running a travis-ci build in an up to date +# Arch Linux chroot + +ARCH_TRAVIS_MIRROR=${ARCH_TRAVIS_MIRROR:-"https://lug.mtu.edu/archlinux"} +ARCH_TRAVIS_ARCH_ISO=${ARCH_TRAVIS_ARCH_ISO:-"$(date +%Y.%m).01"} +mirror_entry='Server = '$ARCH_TRAVIS_MIRROR'/\$repo/os/\$arch' +archive="archlinux-bootstrap-$ARCH_TRAVIS_ARCH_ISO-x86_64.tar.gz" +default_root="root.x86_64" +ARCH_TRAVIS_CHROOT=${ARCH_TRAVIS_CHROOT:-"$default_root"} +user="travis" +user_home="/home/$user" +user_build_dir="/build" +user_uid=$UID + +if [ -n "$CC" ]; then + # store travis CC + TRAVIS_CC=$CC + # reset to gcc for building arch packages + CC=gcc +fi + + +# default packages +default_packages=("base-devel" "git") + +# pacman.conf repository line +repo_line=70 + +# setup working Arch Linux chroot +setup_chroot() { + arch_msg "Setting up Arch chroot" + + if [ ! -f $archive ]; then + # get root fs + local curl=$(curl --fail -O "$ARCH_TRAVIS_MIRROR/iso/$ARCH_TRAVIS_ARCH_ISO/$archive" 2>&1) + + # if it fails, try arch iso form the previous month + if [ $? -gt 0 ]; then + ARCH_TRAVIS_ARCH_ISO="$(date +%Y.%m -d "-1 month").01" + archive="archlinux-bootstrap-$ARCH_TRAVIS_ARCH_ISO-x86_64.tar.gz" + as_normal "curl -O $ARCH_TRAVIS_MIRROR/iso/$ARCH_TRAVIS_ARCH_ISO/$archive" + fi + fi + + # extract root fs + as_root "tar xf $archive" + + # remove archive if ARCH_TRAVIS_CLEAN_CHROOT is set + if [ -n "$ARCH_TRAVIS_CLEAN_CHROOT" ]; then + as_root "rm $archive" + fi + + if [ "$ARCH_TRAVIS_CHROOT" != "$default_root" ]; then + as_root "mv $default_root $ARCH_TRAVIS_CHROOT" + fi + + # don't care for signed packages + as_root "sed -i 's|SigLevel = Required DatabaseOptional|SigLevel = Never|' $ARCH_TRAVIS_CHROOT/etc/pacman.conf" + + # enable multilib + as_root "sed -i 's|#\[multilib\]|\[multilib\]\nInclude = /etc/pacman.d/mirrorlist|' $ARCH_TRAVIS_CHROOT/etc/pacman.conf" + + # add mirror + as_root "echo $mirror_entry >> $ARCH_TRAVIS_CHROOT/etc/pacman.d/mirrorlist" + + # add nameserver to resolv.conf + as_root "echo nameserver 8.8.8.8 >> $ARCH_TRAVIS_CHROOT/etc/resolv.conf" + + sudo mount $ARCH_TRAVIS_CHROOT $ARCH_TRAVIS_CHROOT --bind + sudo mount --bind /proc $ARCH_TRAVIS_CHROOT/proc + sudo mount --bind /sys $ARCH_TRAVIS_CHROOT/sys + sudo mount --bind /dev $ARCH_TRAVIS_CHROOT/dev + sudo mount --bind /dev/pts $ARCH_TRAVIS_CHROOT/dev/pts + sudo mount --bind /dev/shm $ARCH_TRAVIS_CHROOT/dev/shm + sudo mount --bind /run $ARCH_TRAVIS_CHROOT/run + + # update packages + chroot_as_root "pacman -Syy" + chroot_as_root "pacman -Syu ${default_packages[*]} --noconfirm" + + # use LANG=en_US.UTF-8 as expected in travis environments + as_root "sed -i 's|#en_US.UTF-8|en_US.UTF-8|' $ARCH_TRAVIS_CHROOT/etc/locale.gen" + chroot_as_root "locale-gen" + + # setup non-root user + chroot_as_root "useradd -u $user_uid -m -s /bin/bash $user" + + # disable password for sudo users + as_root "echo \"$user ALL=(ALL) NOPASSWD: ALL\" >> $ARCH_TRAVIS_CHROOT/etc/sudoers.d/$user" + + # Add build dir + chroot_as_root "mkdir $user_build_dir && chown $user $user_build_dir" + + # bind $TRAVIS_BUILD_DIR to chroot build dir + sudo mount --bind $TRAVIS_BUILD_DIR $ARCH_TRAVIS_CHROOT$user_build_dir + + # add custom repos + add_repositories + + # setup pacaur for AUR packages + setup_pacaur +} + +# add custom repositories to pacman.conf +add_repositories() { + if [ ${#CONFIG_REPOS[@]} -gt 0 ]; then + for r in "${CONFIG_REPOS[@]}"; do + local splitarr=(${r//=/ }) + ((repo_line+=1)) + as_root "sed -i '${repo_line}i[${splitarr[0]}]' $ARCH_TRAVIS_CHROOT/etc/pacman.conf" + ((repo_line+=1)) + as_root "sed -i '${repo_line}iServer = ${splitarr[1]}\n' $ARCH_TRAVIS_CHROOT/etc/pacman.conf" + ((repo_line+=1)) + done + + # update repos + chroot_as_root "pacman -Syy" + fi +} + +# a wrapper which can be used to eventually add fakeroot support. +sudo_wrapper() { + sudo "$@" +} + +# run command as normal user +as_normal() { + local str="$@" + run /bin/bash -c "$str" +} + +# run command as root +as_root() { + local str="$@" + run sudo_wrapper /bin/bash -c "$str" +} + +# run command in chroot as root +chroot_as_root() { + local str="$@" + run sudo_wrapper chroot $ARCH_TRAVIS_CHROOT /bin/bash -c "$str" +} + +# run command in chroot as normal user +chroot_as_normal() { + local str="$@" + run sudo_wrapper chroot --userspec=$user:$user $ARCH_TRAVIS_CHROOT /bin/bash \ + -c "export HOME=$user_home USER=$user TRAVIS_BUILD_DIR=$user_build_dir && cd $user_build_dir && $str" +} + +# run command +run() { + "$@" + local ret=$? + + if [ $ret -gt 0 ]; then + takedown_chroot + exit $ret + fi +} + +# run build script +run_build_script() { + local cmd="$@" + echo "$ $cmd" + sudo_wrapper chroot --userspec=$user:$user $ARCH_TRAVIS_CHROOT /bin/bash -c "export HOME=$user_home USER=$user TRAVIS_BUILD_DIR=$user_build_dir && cd $user_build_dir && $cmd" + local ret=$? + + if [ $ret -gt 0 ]; then + takedown_chroot + exit $ret + fi +} + +# setup pacaur +setup_pacaur() { + local cowerarchive="cower.tar.gz" + local aururl="https://aur.archlinux.org/cgit/aur.git/snapshot/" + # install cower + as_normal "curl -O $aururl/$cowerarchive" + as_normal "tar xf $cowerarchive" + chroot_as_normal "cd cower && makepkg -is --skippgpcheck --noconfirm" + as_root "rm -r cower" + as_normal "rm $cowerarchive" + # install pacaur + chroot_as_normal "cower -dd pacaur" + chroot_as_normal "cd pacaur && makepkg -is --noconfirm" + chroot_as_normal "rm -rf pacaur" +} + +# install package through pacaur +_pacaur() { + local pacaur="pacaur -S $@ --noconfirm --noedit" + chroot_as_normal "$pacaur" +} + +# takedown chroot +# unmounts anything mounted in the chroot setup +takedown_chroot() { + sudo umount $ARCH_TRAVIS_CHROOT/{run,dev/shm,dev/pts,dev,sys,proc} + sudo umount $ARCH_TRAVIS_CHROOT$user_build_dir + sudo umount $ARCH_TRAVIS_CHROOT + + if [ -n "$ARCH_TRAVIS_CLEAN_CHROOT" ]; then + as_root "rm -rf $ARCH_TRAVIS_CHROOT" + fi +} + +# read value from .travis.yml +travis_yml() { + ruby -ryaml -e 'puts ARGV[1..-1].inject(YAML.load(File.read(ARGV[0]))) {|acc, key| acc[key] }' .travis.yml $@ +} + +read_config() { + old_ifs=$IFS + IFS=$'\n' + CONFIG_BUILD_SCRIPTS=($(travis_yml arch script)) + CONFIG_PACKAGES=($(travis_yml arch packages)) + CONFIG_REPOS=($(travis_yml arch repos)) + IFS=$old_ifs +} + +# run build scripts defined in .travis.yml +build_scripts() { + if [ ${#CONFIG_BUILD_SCRIPTS[@]} -gt 0 ]; then + for script in "${CONFIG_BUILD_SCRIPTS[@]}"; do + run_build_script $script + done + else + echo "No build scripts defined" + takedown_chroot + exit 1 + fi +} + +# install packages defined in .travis.yml +install_packages() { + for package in "${CONFIG_PACKAGES[@]}"; do + _pacaur $package + done +} + +# install custom compiler if CC != gcc +install_c_compiler() { + if [ "$TRAVIS_CC" != "gcc" ]; then + _pacaur "$TRAVIS_CC" + fi +} + +arch_msg() { + lightblue='\033[1;34m' + reset='\e[0m' + echo -e "${lightblue}$@${reset}" +} + +# read .travis.yml +read_config + +echo "travis_fold:start:arch_travis" +setup_chroot + +install_packages + +if [ -n "$CC" ]; then + install_c_compiler + + # restore CC + CC=$TRAVIS_CC +fi +echo "travis_fold:end:arch_travis" +echo "" + +arch_msg "Running travis build" +build_scripts + +takedown_chroot + +# vim:set ts=2 sw=2 et: diff --git a/.travis/build.sh b/.travis/build.sh new file mode 100755 index 000000000..62635d970 --- /dev/null +++ b/.travis/build.sh @@ -0,0 +1,191 @@ +#!/bin/bash +# Installs libs and compiles tdesktop + +run() { + info_msg "Build version: ${BUILD_VERSION}" + + downloadLibs + prepare + build + 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 + mkdir tdesktop + mv -f Telegram tdesktop + + # Download libraries + info_msg "QT-Version: ${_qtver}, SRC-Dir: ${srcdir}" + + echo -e "\nDownload and extract qt" + qt_file=qt-everywhere-opensource-src-$_qtver.tar.xz + echo -e "QT-File: ${qt_file}" + + wget "http://download.qt.io/official_releases/qt/${_qtver%.*}/$_qtver/single/$qt_file" + tar xf $qt_file + rm $qt_file + + echo -e "Clone Breakpad" + git clone https://chromium.googlesource.com/breakpad/breakpad breakpad + + echo -e "\nClone Linux Syscall Support" + git clone https://chromium.googlesource.com/linux-syscall-support breakpad-lss + + echo -e "\nLets view the folder content" + ls + travis_fold_end "download_libs" +} + +prepare() { + travis_fold_start "prepare" + start_msg "Preparing the libraries..." + + cd "$srcdir/tdesktop" + + mkdir -p "$srcdir/Libraries" + + local qt_patch_file="$srcdir/tdesktop/Telegram/_qtbase_${_qtver//./_}_patch.diff" + if [ "$qt_patch_file" -nt "$srcdir/Libraries/QtStatic" ]; then + rm -rf "$srcdir/Libraries/QtStatic" + mv "$srcdir/qt-everywhere-opensource-src-$_qtver" "$srcdir/Libraries/QtStatic" + cd "$srcdir/Libraries/QtStatic/qtbase" + patch -p1 -i "$qt_patch_file" + fi + + if [ ! -h "$srcdir/Libraries/breakpad" ]; then + ln -s "$srcdir/breakpad" "$srcdir/Libraries/breakpad" + ln -s "$srcdir/breakpad-lss" "$srcdir/Libraries/breakpad/src/third_party/lss" + fi + + sed -i 's/CUSTOM_API_ID//g' "$srcdir/tdesktop/Telegram/Telegram.pro" + sed -i 's,LIBS += /usr/local/lib/libxkbcommon.a,,g' "$srcdir/tdesktop/Telegram/Telegram.pro" + sed -i 's,LIBS += /usr/local/lib/libz.a,LIBS += -lz,g' "$srcdir/tdesktop/Telegram/Telegram.pro" + + local options="" + + if [[ $BUILD_VERSION == *"no_autoupdate"* ]]; then + options+="\nDEFINES += TDESKTOP_DISABLE_AUTOUPDATE" + fi + + if [[ $BUILD_VERSION == *"no_custom_scheme"* ]]; then + options+="\nDEFINES += TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME" + fi + + options+='\nINCLUDEPATH += "/usr/lib/glib-2.0/include"' + options+='\nINCLUDEPATH += "/usr/lib/gtk-2.0/include"' + options+='\nINCLUDEPATH += "/usr/include/opus"' + options+='\nLIBS += -lcrypto -lssl' + + info_msg "Build options: ${options}" + + echo -e "${options}" >> "$srcdir/tdesktop/Telegram/Telegram.pro" + + success_msg "Prepare done! :)" + travis_fold_end "prepare" +} + +build() { + start_msg "Building the projects..." + + info_msg "Build patched Qt" + # Build patched Qt + cd "$srcdir/Libraries/QtStatic" + ./configure -prefix "$srcdir/qt" -release -opensource -confirm-license -qt-zlib \ + -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -qt-pcre -qt-xcb \ + -qt-xkbcommon-x11 -no-opengl -static -nomake examples -nomake tests + make --silent module-qtbase module-qtimageformats + make --silent module-qtbase-install_subtargets module-qtimageformats-install_subtargets + + export PATH="$srcdir/qt/bin:$PATH" + + info_msg "Build breakpad" + # Build breakpad + cd "$srcdir/Libraries/breakpad" + ./configure + make --silent + + info_msg "Build MetaStyle" + # Build MetaStyle + mkdir -p "$srcdir/tdesktop/Linux/DebugIntermediateStyle" + cd "$srcdir/tdesktop/Linux/DebugIntermediateStyle" + qmake CONFIG+=debug "../../Telegram/MetaStyle.pro" + make --silent + + info_msg "Build MetaLang" + # Build MetaLang + mkdir -p "$srcdir/tdesktop/Linux/DebugIntermediateLang" + cd "$srcdir/tdesktop/Linux/DebugIntermediateLang" + qmake CONFIG+=debug "../../Telegram/MetaLang.pro" + make --silent + + info_msg "Build Telegram Desktop" + # Build Telegram Desktop + mkdir -p "$srcdir/tdesktop/Linux/ReleaseIntermediate" + cd "$srcdir/tdesktop/Linux/ReleaseIntermediate" + + qmake CONFIG+=release "../../Telegram/Telegram.pro" + local pattern="^PRE_TARGETDEPS +=" + grep "$pattern" "$srcdir/tdesktop/Telegram/Telegram.pro" | sed "s/$pattern//g" | xargs make + + qmake CONFIG+=release "../../Telegram/Telegram.pro" + make +} + +check() { + local filePath="$srcdir/tdesktop/Linux/Release/Telegram" + if test -f "$filePath"; then + success_msg "Build successful done! :)" + + local size; + size=$(stat -c %s "$filePath") + success_msg "File size of ${filePath}: ${size} Bytes" + else + error_msg "Build error, output file does not exist" + exit 1 + 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:$*" +} + +run From 6e441312cb4755f3763174799b8f77ab107c87c6 Mon Sep 17 00:00:00 2001 From: Christoph Auer Date: Thu, 17 Mar 2016 22:21:46 +0100 Subject: [PATCH 005/103] Remove duplicated information Signed-off-by: Christoph Auer --- doc/building-xcode.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/building-xcode.md b/doc/building-xcode.md index a88516bc0..c63831068 100644 --- a/doc/building-xcode.md +++ b/doc/building-xcode.md @@ -90,10 +90,6 @@ In Terminal go to **/Users/user/TBuild/Libraries/xz-5.0.5** and there run: make sudo make install -####zlib 1.2.8 - -Using the system lib - ####libexif 0.6.20 #####Get the source code From 8cc7e86793ece8f423c87b69430fea09828e22b2 Mon Sep 17 00:00:00 2001 From: Christoph Date: Fri, 18 Mar 2016 21:06:16 +0100 Subject: [PATCH 006/103] Add build status badge to readme Signed-off-by: Christoph Auer --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4f9b406f7..f4edaa479 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ This is the complete source code and the build instructions for the alpha version of the official desktop client for the [Telegram][telegram] messenger, based on the [Telegram API][telegram_api] and the [MTProto][telegram_proto] secure protocol. +[![Build Status](https://travis-ci.org/telegramdesktop/tdesktop.svg?branch=master)](https://travis-ci.org/telegramdesktop/tdesktop) + The source code is published under GPLv3 with OpenSSL exception, the license is available [here][license]. ## Supported systems From 0b6dea311b890431a6ce227c7bef5a89b5d08cb4 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 24 Mar 2016 23:34:47 +0300 Subject: [PATCH 007/103] scheme for new bot keyboards --- Telegram/SourceFiles/app.cpp | 16 ++ Telegram/SourceFiles/mtproto/scheme.tl | 6 +- Telegram/SourceFiles/mtproto/scheme_auto.cpp | 60 ++++- Telegram/SourceFiles/mtproto/scheme_auto.h | 252 +++++++++++++++++-- 4 files changed, 314 insertions(+), 20 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index e9d2bbe5c..5c1e17c62 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -2450,6 +2450,22 @@ namespace App { case mtpc_keyboardButton: { btns.push_back(qs(b.at(j).c_keyboardButton().vtext)); } break; + + case mtpc_keyboardButtonCallback: { + + } break; + + case mtpc_keyboardButtonRequestGeoLocation: { + + } break; + + case mtpc_keyboardButtonRequestPhone: { + + } break; + + case mtpc_keyboardButtonUrl: { + + } break; } } if (!btns.isEmpty()) commands.push_back(btns); diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl index e01da730d..120ad0b7f 100644 --- a/Telegram/SourceFiles/mtproto/scheme.tl +++ b/Telegram/SourceFiles/mtproto/scheme.tl @@ -557,12 +557,16 @@ botCommand#c27ac8c7 command:string description:string = BotCommand; botInfo#98e81d3a user_id:int description:string commands:Vector = BotInfo; keyboardButton#a2fa4880 text:string = KeyboardButton; +keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton; +keyboardButtonCallback#2aae4183 text:string = KeyboardButton; +keyboardButtonRequestPhone#b16a6c29 text:string = KeyboardButton; +keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton; keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; replyKeyboardHide#a03e5b85 flags:# selective:flags.2?true = ReplyMarkup; replyKeyboardForceReply#f4108aa0 flags:# single_use:flags.1?true selective:flags.2?true = ReplyMarkup; -replyKeyboardMarkup#3502758c flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true rows:Vector = ReplyMarkup; +replyKeyboardMarkup#3502758c flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true inline:flags.3?true rows:Vector = ReplyMarkup; help.appChangelogEmpty#af7e0394 = help.AppChangelog; help.appChangelog#4668e6bd text:string = help.AppChangelog; diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.cpp b/Telegram/SourceFiles/mtproto/scheme_auto.cpp index 272945bd8..1fe0a87a4 100644 --- a/Telegram/SourceFiles/mtproto/scheme_auto.cpp +++ b/Telegram/SourceFiles/mtproto/scheme_auto.cpp @@ -4391,6 +4391,59 @@ void _serialize_keyboardButton(MTPStringLogger &to, int32 stage, int32 lev, Type } } +void _serialize_keyboardButtonUrl(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ keyboardButtonUrl"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 1: to.add(" url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_keyboardButtonCallback(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ keyboardButtonCallback"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_keyboardButtonRequestPhone(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ keyboardButtonRequestPhone"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + +void _serialize_keyboardButtonRequestGeoLocation(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { + if (stage) { + to.add(",\n").addSpaces(lev); + } else { + to.add("{ keyboardButtonRequestGeoLocation"); + to.add("\n").addSpaces(lev); + } + switch (stage) { + case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; + } +} + void _serialize_keyboardButtonRow(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) { if (stage) { to.add(",\n").addSpaces(lev); @@ -4451,7 +4504,8 @@ void _serialize_replyKeyboardMarkup(MTPStringLogger &to, int32 stage, int32 lev, case 1: to.add(" resize: "); ++stages.back(); if (flag & MTPDreplyKeyboardMarkup::Flag::f_resize) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break; case 2: to.add(" single_use: "); ++stages.back(); if (flag & MTPDreplyKeyboardMarkup::Flag::f_single_use) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break; case 3: to.add(" selective: "); ++stages.back(); if (flag & MTPDreplyKeyboardMarkup::Flag::f_selective) { to.add("YES [ BY BIT 2 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break; - case 4: to.add(" rows: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; + case 4: to.add(" inline: "); ++stages.back(); if (flag & MTPDreplyKeyboardMarkup::Flag::f_inline) { to.add("YES [ BY BIT 3 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break; + case 5: to.add(" rows: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break; default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break; } } @@ -8097,6 +8151,10 @@ namespace { _serializers.insert(mtpc_botCommand, _serialize_botCommand); _serializers.insert(mtpc_botInfo, _serialize_botInfo); _serializers.insert(mtpc_keyboardButton, _serialize_keyboardButton); + _serializers.insert(mtpc_keyboardButtonUrl, _serialize_keyboardButtonUrl); + _serializers.insert(mtpc_keyboardButtonCallback, _serialize_keyboardButtonCallback); + _serializers.insert(mtpc_keyboardButtonRequestPhone, _serialize_keyboardButtonRequestPhone); + _serializers.insert(mtpc_keyboardButtonRequestGeoLocation, _serialize_keyboardButtonRequestGeoLocation); _serializers.insert(mtpc_keyboardButtonRow, _serialize_keyboardButtonRow); _serializers.insert(mtpc_replyKeyboardHide, _serialize_replyKeyboardHide); _serializers.insert(mtpc_replyKeyboardForceReply, _serialize_replyKeyboardForceReply); diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.h b/Telegram/SourceFiles/mtproto/scheme_auto.h index 69f6e3311..00a5ab2a6 100644 --- a/Telegram/SourceFiles/mtproto/scheme_auto.h +++ b/Telegram/SourceFiles/mtproto/scheme_auto.h @@ -398,6 +398,10 @@ enum { mtpc_botCommand = 0xc27ac8c7, mtpc_botInfo = 0x98e81d3a, mtpc_keyboardButton = 0xa2fa4880, + mtpc_keyboardButtonUrl = 0x258aff05, + mtpc_keyboardButtonCallback = 0x2aae4183, + mtpc_keyboardButtonRequestPhone = 0xb16a6c29, + mtpc_keyboardButtonRequestGeoLocation = 0xfc796b3f, mtpc_keyboardButtonRow = 0x77608b83, mtpc_replyKeyboardHide = 0xa03e5b85, mtpc_replyKeyboardForceReply = 0xf4108aa0, @@ -1160,6 +1164,10 @@ class MTPDbotInfo; class MTPkeyboardButton; class MTPDkeyboardButton; +class MTPDkeyboardButtonUrl; +class MTPDkeyboardButtonCallback; +class MTPDkeyboardButtonRequestPhone; +class MTPDkeyboardButtonRequestGeoLocation; class MTPkeyboardButtonRow; class MTPDkeyboardButtonRow; @@ -7614,32 +7622,90 @@ typedef MTPBoxed MTPBotInfo; class MTPkeyboardButton : private mtpDataOwner { public: - MTPkeyboardButton(); - MTPkeyboardButton(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_keyboardButton) : mtpDataOwner(0) { + MTPkeyboardButton() : mtpDataOwner(0), _type(0) { + } + MTPkeyboardButton(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) { read(from, end, cons); } MTPDkeyboardButton &_keyboardButton() { if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButton) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButton); split(); return *(MTPDkeyboardButton*)data; } const MTPDkeyboardButton &c_keyboardButton() const { if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButton) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButton); return *(const MTPDkeyboardButton*)data; } + MTPDkeyboardButtonUrl &_keyboardButtonUrl() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonUrl) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonUrl); + split(); + return *(MTPDkeyboardButtonUrl*)data; + } + const MTPDkeyboardButtonUrl &c_keyboardButtonUrl() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonUrl) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonUrl); + return *(const MTPDkeyboardButtonUrl*)data; + } + + MTPDkeyboardButtonCallback &_keyboardButtonCallback() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonCallback) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonCallback); + split(); + return *(MTPDkeyboardButtonCallback*)data; + } + const MTPDkeyboardButtonCallback &c_keyboardButtonCallback() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonCallback) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonCallback); + return *(const MTPDkeyboardButtonCallback*)data; + } + + MTPDkeyboardButtonRequestPhone &_keyboardButtonRequestPhone() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonRequestPhone) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonRequestPhone); + split(); + return *(MTPDkeyboardButtonRequestPhone*)data; + } + const MTPDkeyboardButtonRequestPhone &c_keyboardButtonRequestPhone() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonRequestPhone) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonRequestPhone); + return *(const MTPDkeyboardButtonRequestPhone*)data; + } + + MTPDkeyboardButtonRequestGeoLocation &_keyboardButtonRequestGeoLocation() { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonRequestGeoLocation) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonRequestGeoLocation); + split(); + return *(MTPDkeyboardButtonRequestGeoLocation*)data; + } + const MTPDkeyboardButtonRequestGeoLocation &c_keyboardButtonRequestGeoLocation() const { + if (!data) throw mtpErrorUninitialized(); + if (_type != mtpc_keyboardButtonRequestGeoLocation) throw mtpErrorWrongTypeId(_type, mtpc_keyboardButtonRequestGeoLocation); + return *(const MTPDkeyboardButtonRequestGeoLocation*)data; + } + uint32 innerLength() const; mtpTypeId type() const; - void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_keyboardButton); + void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons); void write(mtpBuffer &to) const; typedef void ResponseType; private: + explicit MTPkeyboardButton(mtpTypeId type); explicit MTPkeyboardButton(MTPDkeyboardButton *_data); + explicit MTPkeyboardButton(MTPDkeyboardButtonUrl *_data); + explicit MTPkeyboardButton(MTPDkeyboardButtonCallback *_data); + explicit MTPkeyboardButton(MTPDkeyboardButtonRequestPhone *_data); + explicit MTPkeyboardButton(MTPDkeyboardButtonRequestGeoLocation *_data); friend class MTP::internal::TypeCreator; + + mtpTypeId _type; }; typedef MTPBoxed MTPKeyboardButton; @@ -12503,6 +12569,47 @@ public: MTPstring vtext; }; +class MTPDkeyboardButtonUrl : public mtpDataImpl { +public: + MTPDkeyboardButtonUrl() { + } + MTPDkeyboardButtonUrl(const MTPstring &_text, const MTPstring &_url) : vtext(_text), vurl(_url) { + } + + MTPstring vtext; + MTPstring vurl; +}; + +class MTPDkeyboardButtonCallback : public mtpDataImpl { +public: + MTPDkeyboardButtonCallback() { + } + MTPDkeyboardButtonCallback(const MTPstring &_text) : vtext(_text) { + } + + MTPstring vtext; +}; + +class MTPDkeyboardButtonRequestPhone : public mtpDataImpl { +public: + MTPDkeyboardButtonRequestPhone() { + } + MTPDkeyboardButtonRequestPhone(const MTPstring &_text) : vtext(_text) { + } + + MTPstring vtext; +}; + +class MTPDkeyboardButtonRequestGeoLocation : public mtpDataImpl { +public: + MTPDkeyboardButtonRequestGeoLocation() { + } + MTPDkeyboardButtonRequestGeoLocation(const MTPstring &_text) : vtext(_text) { + } + + MTPstring vtext; +}; + class MTPDkeyboardButtonRow : public mtpDataImpl { public: MTPDkeyboardButtonRow() { @@ -12561,8 +12668,9 @@ public: f_resize = (1 << 0), f_single_use = (1 << 1), f_selective = (1 << 2), + f_inline = (1 << 3), - MAX_FIELD = (1 << 2), + MAX_FIELD = (1 << 3), }; Q_DECLARE_FLAGS(Flags, Flag); friend inline Flags operator~(Flag v) { return QFlag(~static_cast(v)); } @@ -12570,6 +12678,7 @@ public: bool is_resize() const { return vflags.v & Flag::f_resize; } bool is_single_use() const { return vflags.v & Flag::f_single_use; } bool is_selective() const { return vflags.v & Flag::f_selective; } + bool is_inline() const { return vflags.v & Flag::f_inline; } MTPDreplyKeyboardMarkup() { } @@ -21936,6 +22045,18 @@ public: inline static MTPkeyboardButton new_keyboardButton(const MTPstring &_text) { return MTPkeyboardButton(new MTPDkeyboardButton(_text)); } + inline static MTPkeyboardButton new_keyboardButtonUrl(const MTPstring &_text, const MTPstring &_url) { + return MTPkeyboardButton(new MTPDkeyboardButtonUrl(_text, _url)); + } + inline static MTPkeyboardButton new_keyboardButtonCallback(const MTPstring &_text) { + return MTPkeyboardButton(new MTPDkeyboardButtonCallback(_text)); + } + inline static MTPkeyboardButton new_keyboardButtonRequestPhone(const MTPstring &_text) { + return MTPkeyboardButton(new MTPDkeyboardButtonRequestPhone(_text)); + } + inline static MTPkeyboardButton new_keyboardButtonRequestGeoLocation(const MTPstring &_text) { + return MTPkeyboardButton(new MTPDkeyboardButtonRequestGeoLocation(_text)); + } inline static MTPkeyboardButtonRow new_keyboardButtonRow(const MTPVector &_buttons) { return MTPkeyboardButtonRow(new MTPDkeyboardButtonRow(_buttons)); } @@ -30840,32 +30961,127 @@ inline MTPbotInfo MTP_botInfo(MTPint _user_id, const MTPstring &_description, co return MTP::internal::TypeCreator::new_botInfo(_user_id, _description, _commands); } -inline MTPkeyboardButton::MTPkeyboardButton() : mtpDataOwner(new MTPDkeyboardButton()) { -} - inline uint32 MTPkeyboardButton::innerLength() const { - const MTPDkeyboardButton &v(c_keyboardButton()); - return v.vtext.innerLength(); + switch (_type) { + case mtpc_keyboardButton: { + const MTPDkeyboardButton &v(c_keyboardButton()); + return v.vtext.innerLength(); + } + case mtpc_keyboardButtonUrl: { + const MTPDkeyboardButtonUrl &v(c_keyboardButtonUrl()); + return v.vtext.innerLength() + v.vurl.innerLength(); + } + case mtpc_keyboardButtonCallback: { + const MTPDkeyboardButtonCallback &v(c_keyboardButtonCallback()); + return v.vtext.innerLength(); + } + case mtpc_keyboardButtonRequestPhone: { + const MTPDkeyboardButtonRequestPhone &v(c_keyboardButtonRequestPhone()); + return v.vtext.innerLength(); + } + case mtpc_keyboardButtonRequestGeoLocation: { + const MTPDkeyboardButtonRequestGeoLocation &v(c_keyboardButtonRequestGeoLocation()); + return v.vtext.innerLength(); + } + } + return 0; } inline mtpTypeId MTPkeyboardButton::type() const { - return mtpc_keyboardButton; + if (!_type) throw mtpErrorUninitialized(); + return _type; } inline void MTPkeyboardButton::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) { - if (cons != mtpc_keyboardButton) throw mtpErrorUnexpected(cons, "MTPkeyboardButton"); - - if (!data) setData(new MTPDkeyboardButton()); - MTPDkeyboardButton &v(_keyboardButton()); - v.vtext.read(from, end); + if (cons != _type) setData(0); + switch (cons) { + case mtpc_keyboardButton: _type = cons; { + if (!data) setData(new MTPDkeyboardButton()); + MTPDkeyboardButton &v(_keyboardButton()); + v.vtext.read(from, end); + } break; + case mtpc_keyboardButtonUrl: _type = cons; { + if (!data) setData(new MTPDkeyboardButtonUrl()); + MTPDkeyboardButtonUrl &v(_keyboardButtonUrl()); + v.vtext.read(from, end); + v.vurl.read(from, end); + } break; + case mtpc_keyboardButtonCallback: _type = cons; { + if (!data) setData(new MTPDkeyboardButtonCallback()); + MTPDkeyboardButtonCallback &v(_keyboardButtonCallback()); + v.vtext.read(from, end); + } break; + case mtpc_keyboardButtonRequestPhone: _type = cons; { + if (!data) setData(new MTPDkeyboardButtonRequestPhone()); + MTPDkeyboardButtonRequestPhone &v(_keyboardButtonRequestPhone()); + v.vtext.read(from, end); + } break; + case mtpc_keyboardButtonRequestGeoLocation: _type = cons; { + if (!data) setData(new MTPDkeyboardButtonRequestGeoLocation()); + MTPDkeyboardButtonRequestGeoLocation &v(_keyboardButtonRequestGeoLocation()); + v.vtext.read(from, end); + } break; + default: throw mtpErrorUnexpected(cons, "MTPkeyboardButton"); + } } inline void MTPkeyboardButton::write(mtpBuffer &to) const { - const MTPDkeyboardButton &v(c_keyboardButton()); - v.vtext.write(to); + switch (_type) { + case mtpc_keyboardButton: { + const MTPDkeyboardButton &v(c_keyboardButton()); + v.vtext.write(to); + } break; + case mtpc_keyboardButtonUrl: { + const MTPDkeyboardButtonUrl &v(c_keyboardButtonUrl()); + v.vtext.write(to); + v.vurl.write(to); + } break; + case mtpc_keyboardButtonCallback: { + const MTPDkeyboardButtonCallback &v(c_keyboardButtonCallback()); + v.vtext.write(to); + } break; + case mtpc_keyboardButtonRequestPhone: { + const MTPDkeyboardButtonRequestPhone &v(c_keyboardButtonRequestPhone()); + v.vtext.write(to); + } break; + case mtpc_keyboardButtonRequestGeoLocation: { + const MTPDkeyboardButtonRequestGeoLocation &v(c_keyboardButtonRequestGeoLocation()); + v.vtext.write(to); + } break; + } } -inline MTPkeyboardButton::MTPkeyboardButton(MTPDkeyboardButton *_data) : mtpDataOwner(_data) { +inline MTPkeyboardButton::MTPkeyboardButton(mtpTypeId type) : mtpDataOwner(0), _type(type) { + switch (type) { + case mtpc_keyboardButton: setData(new MTPDkeyboardButton()); break; + case mtpc_keyboardButtonUrl: setData(new MTPDkeyboardButtonUrl()); break; + case mtpc_keyboardButtonCallback: setData(new MTPDkeyboardButtonCallback()); break; + case mtpc_keyboardButtonRequestPhone: setData(new MTPDkeyboardButtonRequestPhone()); break; + case mtpc_keyboardButtonRequestGeoLocation: setData(new MTPDkeyboardButtonRequestGeoLocation()); break; + default: throw mtpErrorBadTypeId(type, "MTPkeyboardButton"); + } +} +inline MTPkeyboardButton::MTPkeyboardButton(MTPDkeyboardButton *_data) : mtpDataOwner(_data), _type(mtpc_keyboardButton) { +} +inline MTPkeyboardButton::MTPkeyboardButton(MTPDkeyboardButtonUrl *_data) : mtpDataOwner(_data), _type(mtpc_keyboardButtonUrl) { +} +inline MTPkeyboardButton::MTPkeyboardButton(MTPDkeyboardButtonCallback *_data) : mtpDataOwner(_data), _type(mtpc_keyboardButtonCallback) { +} +inline MTPkeyboardButton::MTPkeyboardButton(MTPDkeyboardButtonRequestPhone *_data) : mtpDataOwner(_data), _type(mtpc_keyboardButtonRequestPhone) { +} +inline MTPkeyboardButton::MTPkeyboardButton(MTPDkeyboardButtonRequestGeoLocation *_data) : mtpDataOwner(_data), _type(mtpc_keyboardButtonRequestGeoLocation) { } inline MTPkeyboardButton MTP_keyboardButton(const MTPstring &_text) { return MTP::internal::TypeCreator::new_keyboardButton(_text); } +inline MTPkeyboardButton MTP_keyboardButtonUrl(const MTPstring &_text, const MTPstring &_url) { + return MTP::internal::TypeCreator::new_keyboardButtonUrl(_text, _url); +} +inline MTPkeyboardButton MTP_keyboardButtonCallback(const MTPstring &_text) { + return MTP::internal::TypeCreator::new_keyboardButtonCallback(_text); +} +inline MTPkeyboardButton MTP_keyboardButtonRequestPhone(const MTPstring &_text) { + return MTP::internal::TypeCreator::new_keyboardButtonRequestPhone(_text); +} +inline MTPkeyboardButton MTP_keyboardButtonRequestGeoLocation(const MTPstring &_text) { + return MTP::internal::TypeCreator::new_keyboardButtonRequestGeoLocation(_text); +} inline MTPkeyboardButtonRow::MTPkeyboardButtonRow() : mtpDataOwner(new MTPDkeyboardButtonRow()) { } From f227740e93faaa0182f21c3a6c8def6084a86f97 Mon Sep 17 00:00:00 2001 From: Christoph Auer Date: Thu, 24 Mar 2016 23:56:21 +0100 Subject: [PATCH 008/103] Add new macros to travis Signed-off-by: Christoph Auer --- .travis.yml | 7 ++++--- .travis/build.sh | 12 ++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 11a9c3adb..612e30f7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,10 @@ language: cpp env: - BUILD_VERSION="" - - BUILD_VERSION="no_autoupdate" - - BUILD_VERSION="no_custom_scheme" - - BUILD_VERSION="no_autoupdate+no_custom_scheme" + - BUILD_VERSION="disable_autoupdate" + - BUILD_VERSION="disable_register_custom_scheme" + - BUILD_VERSION="disable_crash_reports" + - BUILD_VERSION="disable_network_proxy" arch: packages: diff --git a/.travis/build.sh b/.travis/build.sh index 62635d970..ebbaeffc4 100755 --- a/.travis/build.sh +++ b/.travis/build.sh @@ -82,14 +82,22 @@ prepare() { local options="" - if [[ $BUILD_VERSION == *"no_autoupdate"* ]]; then + if [[ $BUILD_VERSION == *"disable_autoupdate"* ]]; then options+="\nDEFINES += TDESKTOP_DISABLE_AUTOUPDATE" fi - if [[ $BUILD_VERSION == *"no_custom_scheme"* ]]; then + if [[ $BUILD_VERSION == *"disable_register_custom_scheme"* ]]; then options+="\nDEFINES += TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME" fi + if [[ $BUILD_VERSION == *"disable_crash_reports"* ]]; then + options+="\nDEFINES += TDESKTOP_DISABLE_CRASH_REPORTS" + fi + + if [[ $BUILD_VERSION == *"disable_network_proxy"* ]]; then + options+="\nDEFINES += TDESKTOP_DISABLE_NETWORK_PROXY" + fi + options+='\nINCLUDEPATH += "/usr/lib/glib-2.0/include"' options+='\nINCLUDEPATH += "/usr/lib/gtk-2.0/include"' options+='\nINCLUDEPATH += "/usr/include/opus"' From 96e1f8e7cd1c824e68b992ffb7dbf9f488aa5578 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 26 Mar 2016 11:13:57 +0300 Subject: [PATCH 009/103] Fixed duplicate save file dialog --- Telegram/SourceFiles/structs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index 85932fb31..122380730 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -951,7 +951,7 @@ void GifOpenLink::onClick(Qt::MouseButton button) const { void DocumentSaveLink::doSave(DocumentData *data, bool forceSavingAs) { if (!data->date) return; - QString filepath = data->filepath(DocumentData::FilePathResolveSaveFromData, forceSavingAs); + QString filepath = data->filepath(DocumentData::FilePathResolveSaveFromDataSilent, forceSavingAs); if (!filepath.isEmpty() && !forceSavingAs) { QPoint pos(QCursor::pos()); if (!psShowOpenWithMenu(pos.x(), pos.y(), filepath)) { @@ -1376,7 +1376,7 @@ QString DocumentData::filepath(FilePathResolveType type, bool forceSavingAs) con if (saveFromData) { if (type != FilePathResolveSaveFromData && type != FilePathResolveSaveFromDataSilent) { saveFromData = false; - } else if (type == FilePathResolveSaveFromDataSilent && cAskDownloadPath()) { + } else if (type == FilePathResolveSaveFromDataSilent && (cAskDownloadPath() || forceSavingAs)) { saveFromData = false; } } From daa5016c2341069e4676b5ff4eb9fdf8f9073b38 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 28 Mar 2016 15:51:22 +0300 Subject: [PATCH 010/103] Components are now almost plain structs Moved reply markups to history items which hold them --- Telegram/Resources/style.txt | 10 ++ Telegram/SourceFiles/apiwrap.h | 4 +- Telegram/SourceFiles/app.cpp | 116 ------------ Telegram/SourceFiles/app.h | 12 -- Telegram/SourceFiles/facades.cpp | 5 + Telegram/SourceFiles/facades.h | 1 + Telegram/SourceFiles/gui/animation.h | 4 +- Telegram/SourceFiles/history.cpp | 200 +++++++++++++++------ Telegram/SourceFiles/history.h | 131 +++++++++----- Telegram/SourceFiles/historywidget.cpp | 45 ++--- Telegram/SourceFiles/historywidget.h | 16 +- Telegram/SourceFiles/layout.h | 16 +- Telegram/SourceFiles/mtproto/core_types.h | 2 +- Telegram/SourceFiles/mtproto/generate.py | 1 + Telegram/SourceFiles/mtproto/scheme_auto.h | 8 + Telegram/SourceFiles/overviewwidget.cpp | 28 +-- Telegram/SourceFiles/shortcuts.cpp | 2 +- Telegram/SourceFiles/types.h | 143 ++++++++++----- 18 files changed, 409 insertions(+), 335 deletions(-) diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt index 5ada019a8..196059ae5 100644 --- a/Telegram/Resources/style.txt +++ b/Telegram/Resources/style.txt @@ -1085,6 +1085,16 @@ msgInReplyBarColor: #2fa9e2; msgOutReplyBarSelColor: #4da79f; msgInReplyBarSelColor: #2fa9e2; +msgBotKbDuration: 200; +msgBotKbFont: semiboldFont; +msgBotKbButton: botKeyboardButton { + margin: 5px; + padding: 10px; + height: 36px; + textTop: 8px; + downTextTop: 9px; +} + msgServiceBg: #89a0b47f; msgServiceSelectBg: #bbc8d4a2; msgServiceColor: #FFF; diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 3ea5eca0f..8845d90bd 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -28,7 +28,7 @@ public: ApiWrap(QObject *parent); void init(); - typedef SharedCallback2 RequestMessageDataCallback; + typedef SharedCallback RequestMessageDataCallback; void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback *callback); void requestFullPeer(PeerData *peer); @@ -69,7 +69,7 @@ private: struct MessageDataRequest { MessageDataRequest() : req(0) { } - typedef SharedCallback2::Ptr CallbackPtr; + typedef SharedCallback::Ptr CallbackPtr; typedef QList Callbacks; mtpRequestId req; Callbacks callbacks; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 29cb00368..1edee0a39 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -55,12 +55,6 @@ namespace { typedef QHash WebPagesData; WebPagesData webPagesData; - typedef QMap ReplyMarkups; - ReplyMarkups replyMarkups; - ReplyMarkup zeroMarkup(qFlags(MTPDreplyKeyboardMarkup_ClientFlag::f_zero)); - typedef QMap ChannelReplyMarkups; - ChannelReplyMarkups channelReplyMarkups; - PhotoItems photoItems; DocumentItems documentItems; WebPageItems webPageItems; @@ -1851,8 +1845,6 @@ namespace App { } ::hoveredItem = ::pressedItem = ::hoveredLinkItem = ::pressedLinkItem = ::contextItem = 0; - replyMarkups.clear(); - channelReplyMarkups.clear(); } void historyClearItems() { @@ -2396,114 +2388,6 @@ namespace App { ::inlineResultLoaders.remove(loader); } - InlineResult *inlineResultFromLoader(FileLoader *loader) { - InlineResultLoaders::const_iterator i = ::inlineResultLoaders.find(loader); - return (i == ::inlineResultLoaders.cend()) ? 0 : i.value(); - } - - inline void insertReplyMarkup(ChannelId channelId, MsgId msgId, const ReplyMarkup &markup) { - if (channelId == NoChannel) { - replyMarkups.insert(msgId, markup); - } else { - channelReplyMarkups[channelId].insert(msgId, markup); - } - } - - void feedReplyMarkup(ChannelId channelId, MsgId msgId, const MTPReplyMarkup &markup) { - ReplyMarkup data; - ReplyMarkup::Commands &commands(data.commands); - switch (markup.type()) { - case mtpc_replyKeyboardMarkup: { - const MTPDreplyKeyboardMarkup &d(markup.c_replyKeyboardMarkup()); - data.flags = d.vflags.v; - - const QVector &v(d.vrows.c_vector().v); - if (!v.isEmpty()) { - commands.reserve(v.size()); - for (int32 i = 0, l = v.size(); i < l; ++i) { - switch (v.at(i).type()) { - case mtpc_keyboardButtonRow: { - const MTPDkeyboardButtonRow &r(v.at(i).c_keyboardButtonRow()); - const QVector &b(r.vbuttons.c_vector().v); - if (!b.isEmpty()) { - QList btns; - btns.reserve(b.size()); - for (int32 j = 0, s = b.size(); j < s; ++j) { - switch (b.at(j).type()) { - case mtpc_keyboardButton: { - btns.push_back(qs(b.at(j).c_keyboardButton().vtext)); - } break; - - case mtpc_keyboardButtonCallback: { - - } break; - - case mtpc_keyboardButtonRequestGeoLocation: { - - } break; - - case mtpc_keyboardButtonRequestPhone: { - - } break; - - case mtpc_keyboardButtonUrl: { - - } break; - } - } - if (!btns.isEmpty()) commands.push_back(btns); - } - } break; - } - } - if (!commands.isEmpty()) { - insertReplyMarkup(channelId, msgId, data); - } - } - } break; - - case mtpc_replyKeyboardHide: { - const MTPDreplyKeyboardHide &d(markup.c_replyKeyboardHide()); - if (d.vflags.v) { - insertReplyMarkup(channelId, msgId, ReplyMarkup(mtpCastFlags(d.vflags.v) | MTPDreplyKeyboardMarkup_ClientFlag::f_zero)); - } - } break; - - case mtpc_replyKeyboardForceReply: { - const MTPDreplyKeyboardForceReply &d(markup.c_replyKeyboardForceReply()); - insertReplyMarkup(channelId, msgId, ReplyMarkup(mtpCastFlags(d.vflags.v) | MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply)); - } break; - } - } - - void clearReplyMarkup(ChannelId channelId, MsgId msgId) { - if (channelId == NoChannel) { - replyMarkups.remove(msgId); - } else { - ChannelReplyMarkups::iterator i = channelReplyMarkups.find(channelId); - if (i != channelReplyMarkups.cend()) { - i->remove(msgId); - if (i->isEmpty()) { - channelReplyMarkups.erase(i); - } - } - } - } - - inline const ReplyMarkup &replyMarkup(const ReplyMarkups &markups, MsgId msgId) { - ReplyMarkups::const_iterator i = markups.constFind(msgId); - if (i == markups.cend()) return zeroMarkup; - return i.value(); - } - const ReplyMarkup &replyMarkup(ChannelId channelId, MsgId msgId) { - if (channelId == NoChannel) { - return replyMarkup(replyMarkups, msgId); - } - ChannelReplyMarkups::const_iterator j = channelReplyMarkups.constFind(channelId); - if (j == channelReplyMarkups.cend()) return zeroMarkup; - return replyMarkup(*j, msgId); - } - void setProxySettings(QNetworkAccessManager &manager) { #ifndef TDESKTOP_DISABLE_NETWORK_PROXY manager.setProxy(getHttpProxySettings()); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index ebe1711e5..a4039571e 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -44,14 +44,6 @@ typedef QHash GifItems; typedef QHash PhotosData; typedef QHash DocumentsData; -struct ReplyMarkup { - ReplyMarkup(MTPDreplyKeyboardMarkup::Flags flags = 0) : flags(flags) { - } - typedef QList > Commands; - Commands commands; - MTPDreplyKeyboardMarkup::Flags flags; -}; - class LayeredWidget; namespace App { @@ -272,10 +264,6 @@ namespace App { void unregInlineResultLoader(FileLoader *loader); InlineResult *inlineResultFromLoader(FileLoader *loader); - void feedReplyMarkup(ChannelId channelId, MsgId msgId, const MTPReplyMarkup &markup); - void clearReplyMarkup(ChannelId channelId, MsgId msgId); - const ReplyMarkup &replyMarkup(ChannelId channelId, MsgId msgId); - void setProxySettings(QNetworkAccessManager &manager); #ifndef TDESKTOP_DISABLE_NETWORK_PROXY QNetworkProxy getHttpProxySettings(); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 0b9557e3d..9e955b272 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -41,6 +41,11 @@ namespace App { return false; } + void activateBotCommand(const HistoryMessageReplyMarkup::Button &button, MsgId replyTo) { + QString cmd(button.text); + App::sendBotCommand(cmd, replyTo); + } + void searchByHashtag(const QString &tag, PeerData *inPeer) { if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0); } diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index ba77a20a2..462299987 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -26,6 +26,7 @@ namespace App { void sendBotCommand(const QString &cmd, MsgId replyTo = 0); bool insertBotCommand(const QString &cmd, bool specialGif = false); + void activateBotCommand(const HistoryMessageReplyMarkup::Button &button, MsgId replyTo = 0); void searchByHashtag(const QString &tag, PeerData *inPeer); void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString()); void joinGroupByHash(const QString &hash); diff --git a/Telegram/SourceFiles/gui/animation.h b/Telegram/SourceFiles/gui/animation.h index cb61a09e0..e31c08d29 100644 --- a/Telegram/SourceFiles/gui/animation.h +++ b/Telegram/SourceFiles/gui/animation.h @@ -211,7 +211,7 @@ public: AnimationImplementation *create() const { return getPointerAndReset(_ptr); } ~AnimationCreator() { deleteAndMark(_ptr); } private: - AnimationCreator &operator=(const AnimationCreator &other); + AnimationCreator &operator=(const AnimationCreator &other) = delete; mutable AnimationImplementation *_ptr; }; class AnimationCallbacks { @@ -222,7 +222,7 @@ public: ~AnimationCallbacks() { deleteAndMark(_implementation); } private: AnimationCallbacks(const AnimationCallbacks &other); - AnimationCallbacks &operator=(const AnimationCallbacks &other); + AnimationCallbacks &operator=(const AnimationCallbacks &other) = delete; AnimationImplementation *_implementation; }; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 1478fe97c..155081491 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -1291,9 +1291,6 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction, result = HistoryService::create(this, m.vid.v, date(m.vdate), lang(lng_message_empty), m.vflags.v, nullptr, m.has_from_id() ? m.vfrom_id.v : 0); } else { result = HistoryMessage::create(this, m); - if (m.has_reply_markup()) { - App::feedReplyMarkup(channelId(), msgId, m.vreply_markup); - } } } break; @@ -1589,8 +1586,8 @@ HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) { } } } - if (adding->hasReplyMarkup()) { - MTPDreplyKeyboardMarkup::Flags markupFlags = App::replyMarkup(channelId(), adding->id).flags; + if (adding->definesReplyKeyboard()) { + MTPDreplyKeyboardMarkup::Flags markupFlags = adding->replyKeyboardFlags(); if (!(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_selective) || adding->mentionsMe()) { OrderedSet *markupSenders = 0; if (peer->isChat()) { @@ -1759,8 +1756,8 @@ void History::addOlderSlice(const QVector &slice, const QVectorauthor()->id) { if (markupSenders) { // chats with bots - if (!lastKeyboardInited && item->hasReplyMarkup() && !item->out()) { - MTPDreplyKeyboardMarkup::Flags markupFlags = App::replyMarkup(channelId(), item->id).flags; + if (!lastKeyboardInited && item->definesReplyKeyboard() && !item->out()) { + MTPDreplyKeyboardMarkup::Flags markupFlags = item->replyKeyboardFlags(); if (!(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_selective) || item->mentionsMe()) { bool wasKeyboardHide = markupSenders->contains(item->author()); if (!wasKeyboardHide) { @@ -1786,8 +1783,8 @@ void History::addOlderSlice(const QVector &slice, const QVectorhasReplyMarkup() && !item->out()) { // conversations with bots - MTPDreplyKeyboardMarkup::Flags markupFlags = App::replyMarkup(channelId(), item->id).flags; + } else if (!lastKeyboardInited && item->definesReplyKeyboard() && !item->out()) { // conversations with bots + MTPDreplyKeyboardMarkup::Flags markupFlags = item->replyKeyboardFlags(); if (!(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_selective) || item->mentionsMe()) { if (markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_zero) { clearLastKeyboard(); @@ -2708,6 +2705,63 @@ void HistoryBlock::removeItem(HistoryItem *item) { } } +void HistoryMessageReplyMarkup::create(const MTPReplyMarkup &markup) { + switch (markup.type()) { + case mtpc_replyKeyboardMarkup: { + const MTPDreplyKeyboardMarkup &d(markup.c_replyKeyboardMarkup()); + flags = d.vflags.v; + + const QVector &v(d.vrows.c_vector().v); + if (!v.isEmpty()) { + rows.reserve(v.size()); + for_const (const MTPKeyboardButtonRow &row, v) { + switch (row.type()) { + case mtpc_keyboardButtonRow: { + const MTPDkeyboardButtonRow &r(row.c_keyboardButtonRow()); + const QVector &b(r.vbuttons.c_vector().v); + if (!b.isEmpty()) { + ButtonRow buttonRow; + buttonRow.reserve(b.size()); + for_const (const MTPKeyboardButton &button, b) { + switch (button.type()) { + case mtpc_keyboardButton: { + buttonRow.push_back({ Button::Default, qs(button.c_keyboardButton().vtext), QString() }); + } break; + case mtpc_keyboardButtonCallback: { + buttonRow.push_back({ Button::Callback, qs(button.c_keyboardButtonCallback().vtext), QString() }); + } break; + case mtpc_keyboardButtonRequestGeoLocation: { + buttonRow.push_back({ Button::RequestLocation, qs(button.c_keyboardButtonRequestGeoLocation().vtext), QString() }); + } break; + case mtpc_keyboardButtonRequestPhone: { + buttonRow.push_back({ Button::RequestPhone, qs(button.c_keyboardButtonRequestPhone().vtext), QString() }); + } break; + case mtpc_keyboardButtonUrl: { + const MTPDkeyboardButtonUrl &u(button.c_keyboardButtonUrl()); + buttonRow.push_back({ Button::Url, qs(u.vtext), qs(u.vurl) }); + } break; + } + } + if (!buttonRow.isEmpty()) rows.push_back(buttonRow); + } + } break; + } + } + } + } break; + + case mtpc_replyKeyboardHide: { + const MTPDreplyKeyboardHide &d(markup.c_replyKeyboardHide()); + flags = mtpCastFlags(d.vflags) | MTPDreplyKeyboardMarkup_ClientFlag::f_zero; + } break; + + case mtpc_replyKeyboardForceReply: { + const MTPDreplyKeyboardForceReply &d(markup.c_replyKeyboardForceReply()); + flags = mtpCastFlags(d.vflags) | MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply; + } break; + } +} + void HistoryDependentItemCallback::call(ChannelData *channel, MsgId msgId) const { if (HistoryItem *item = App::histItemById(_dependent)) { item->updateDependencyItem(); @@ -3789,7 +3843,7 @@ void HistoryDocumentVoice::checkPlaybackFinished() const { HistoryDocument::HistoryDocument(DocumentData *document, const QString &caption, const HistoryItem *parent) : HistoryFileMedia() , _parent(nullptr) , _data(document) { - createInterfaces(!caption.isEmpty()); + createComponents(!caption.isEmpty()); if (auto *named = Get()) { named->_name = documentName(_data); named->_namew = st::semiboldFont->width(named->_name); @@ -3809,7 +3863,7 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi , _parent(nullptr) , _data(other._data) { auto *captioned = other.Get(); - createInterfaces(captioned != 0); + createComponents(captioned != 0); if (auto *named = Get()) { if (auto *othernamed = other.Get()) { named->_name = othernamed->_name; @@ -3829,7 +3883,7 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi } } -void HistoryDocument::createInterfaces(bool caption) { +void HistoryDocument::createComponents(bool caption) { uint64 mask = 0; if (_data->voice()) { mask |= HistoryDocumentVoice::Bit(); @@ -6041,7 +6095,7 @@ bool HistoryMessageReply::updateData(HistoryMessage *holder, bool force) { replyToLnk = TextLinkPtr(new MessageLink(replyToMsg->history()->peer->id, replyToMsg->id)); if (!replyToMsg->Has()) { if (UserData *bot = replyToMsg->viaBot()) { - _replyToVia = new HistoryMessageVia(0); + _replyToVia.reset(new HistoryMessageVia()); _replyToVia->create(peerToUser(bot->id)); } } @@ -6055,8 +6109,7 @@ bool HistoryMessageReply::updateData(HistoryMessage *holder, bool force) { } void HistoryMessageReply::clearData(HistoryMessage *holder) { - delete _replyToVia; - _replyToVia = nullptr; + _replyToVia.clear(); if (replyToMsg) { App::historyUnregDependency(holder, replyToMsg); replyToMsg = nullptr; @@ -6164,20 +6217,22 @@ void HistoryMessageReply::paint(Painter &p, const HistoryItem *holder, int x, in HistoryMessage::HistoryMessage(History *history, const MTPDmessage &msg) : HistoryItem(history, msg.vid.v, msg.vflags.v, ::date(msg.vdate), msg.has_from_id() ? msg.vfrom_id.v : 0) { - PeerId authorOriginalId = 0, fromOriginalId = 0; - MsgId originalId = 0; + CreateConfig config; + if (msg.has_fwd_from() && msg.vfwd_from.type() == mtpc_messageFwdHeader) { const MTPDmessageFwdHeader &f(msg.vfwd_from.c_messageFwdHeader()); if (f.has_from_id() || f.has_channel_id()) { - authorOriginalId = f.has_channel_id() ? peerFromChannel(f.vchannel_id) : peerFromUser(f.vfrom_id); - fromOriginalId = f.has_from_id() ? peerFromUser(f.vfrom_id) : peerFromChannel(f.vchannel_id); - if (f.has_channel_post()) originalId = f.vchannel_post.v; + config.authorIdOriginal = f.has_channel_id() ? peerFromChannel(f.vchannel_id) : peerFromUser(f.vfrom_id); + config.fromIdOriginal = f.has_from_id() ? peerFromUser(f.vfrom_id) : peerFromChannel(f.vchannel_id); + if (f.has_channel_post()) config.originalId = f.vchannel_post.v; } } - MsgId replyTo = msg.has_reply_to_msg_id() ? msg.vreply_to_msg_id.v : 0; - int32 viaBotId = msg.has_via_bot_id() ? msg.vvia_bot_id.v : 0; - int views = msg.has_views() ? msg.vviews.v : -1; - createInterfaces(replyTo, viaBotId, views, authorOriginalId, fromOriginalId, originalId); + if (msg.has_reply_to_msg_id()) config.replyTo = msg.vreply_to_msg_id.v; + if (msg.has_via_bot_id()) config.viaBotId = msg.vvia_bot_id.v; + if (msg.has_views()) config.viewsCount = msg.vviews.v; + if (msg.has_reply_markup()) config.markup = &msg.vreply_markup; + + createComponents(config); QString text(textClean(qs(msg.vmessage))); initMedia(msg.has_media() ? (&msg.vmedia) : 0, text); @@ -6186,11 +6241,18 @@ HistoryMessage::HistoryMessage(History *history, const MTPDmessage &msg) HistoryMessage::HistoryMessage(History *history, MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *fwd) : HistoryItem(history, id, newForwardedFlags(history->peer, from, fwd) | flags, date, from) { + CreateConfig config; + UserData *fwdViaBot = fwd->viaBot(); - int32 viaBotId = fwdViaBot ? peerToUser(fwdViaBot->id) : 0; - int fwdViewsCount = fwd->viewsCount(), views = (fwdViewsCount > 0) ? fwdViewsCount : (isPost() ? 1 : -1); - MsgId replyTo = 0; - createInterfaces(replyTo, viaBotId, views, fwd->authorOriginal()->id, fwd->fromOriginal()->id, fwd->authorOriginal()->isChannel() ? fwd->id : 0); + if (fwdViaBot) config.viaBotId = peerToUser(fwdViaBot->id); + int fwdViewsCount = fwd->viewsCount(); + if (fwdViewsCount > 0) { + config.viewsCount = fwdViewsCount; + } else if (isPost()) { + config.viewsCount = 1; + } + + createComponents(config); if (HistoryMedia *mediaOriginal = fwd->getMedia()) { _media = mediaOriginal->clone(); @@ -6201,14 +6263,14 @@ HistoryMessage::HistoryMessage(History *history, MsgId id, MTPDmessage::Flags fl HistoryMessage::HistoryMessage(History *history, MsgId id, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, const QString &msg, const EntitiesInText &entities) : HistoryItem(history, id, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) { - createInterfacesHelper(flags, replyTo, viaBotId); + createComponentsHelper(flags, replyTo, viaBotId); setText(msg, entities); } HistoryMessage::HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, DocumentData *doc, const QString &caption) : HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) { - createInterfacesHelper(flags, replyTo, viaBotId); + createComponentsHelper(flags, replyTo, viaBotId); initMediaFromDocument(doc, caption); setText(QString(), EntitiesInText()); @@ -6216,56 +6278,70 @@ HistoryMessage::HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags HistoryMessage::HistoryMessage(History *history, MsgId msgId, MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, QDateTime date, int32 from, PhotoData *photo, const QString &caption) : HistoryItem(history, msgId, flags, date, (flags & MTPDmessage::Flag::f_from_id) ? from : 0) { - createInterfacesHelper(flags, replyTo, viaBotId); + createComponentsHelper(flags, replyTo, viaBotId); _media = new HistoryPhoto(photo, caption, this); _media->attachToItem(this); setText(QString(), EntitiesInText()); } -void HistoryMessage::createInterfacesHelper(MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId) { - if (!(flags & MTPDmessage::Flag::f_via_bot_id)) viaBotId = 0; - if (!(flags & MTPDmessage::Flag::f_reply_to_msg_id)) replyTo = 0; - createInterfaces(replyTo, viaBotId, isPost() ? 1 : -1); +void HistoryMessage::createComponentsHelper(MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId) { + CreateConfig config; + + if (flags & MTPDmessage::Flag::f_via_bot_id) config.viaBotId = viaBotId; + if (flags & MTPDmessage::Flag::f_reply_to_msg_id) config.replyTo = replyTo; + if (isPost()) config.viewsCount = 1; + + createComponents(config); } -void HistoryMessage::createInterfaces(MsgId replyTo, int32 viaBotId, int32 viewsCount, const PeerId &authorIdOriginal, const PeerId &fromIdOriginal, MsgId originalId) { +void HistoryMessage::createComponents(const CreateConfig &config) { uint64 mask = 0; - if (replyTo) { + if (config.replyTo) { mask |= HistoryMessageReply::Bit(); } - if (viaBotId) { + if (config.viaBotId) { mask |= HistoryMessageVia::Bit(); } - if (viewsCount >= 0) { + if (config.viewsCount >= 0) { mask |= HistoryMessageViews::Bit(); } if (isPost() && _from->isUser()) { mask |= HistoryMessageSigned::Bit(); } - if (authorIdOriginal && fromIdOriginal) { + if (config.authorIdOriginal && config.fromIdOriginal) { mask |= HistoryMessageForwarded::Bit(); } + if (config.markup) { + // optimization: don't create markup component for the case + // MTPDreplyKeyboardHide with flags = 0, assume it has f_zero flag + if (config.markup->type() != mtpc_replyKeyboardHide || config.markup->c_replyKeyboardHide().vflags.v != 0) { + mask |= HistoryMessageReplyMarkup::Bit(); + } + } UpdateComponents(mask); if (auto *reply = Get()) { - reply->replyToMsgId = replyTo; + reply->replyToMsgId = config.replyTo; if (!reply->updateData(this) && App::api()) { - App::api()->requestMessageData(history()->peer->asChannel(), replyTo, new HistoryDependentItemCallback(fullId())); + App::api()->requestMessageData(history()->peer->asChannel(), reply->replyToMsgId, new HistoryDependentItemCallback(fullId())); } } if (auto *via = Get()) { - via->create(viaBotId); + via->create(config.viaBotId); } if (auto *views = Get()) { - views->_views = viewsCount; + views->_views = config.viewsCount; } if (auto *msgsigned = Get()) { msgsigned->create(_from->asUser(), date); } if (auto *fwd = Get()) { - fwd->_authorOriginal = App::peer(authorIdOriginal); - fwd->_fromOriginal = App::peer(fromIdOriginal); - fwd->_originalId = originalId; + fwd->_authorOriginal = App::peer(config.authorIdOriginal); + fwd->_fromOriginal = App::peer(config.fromIdOriginal); + fwd->_originalId = config.originalId; + } + if (auto *markup = Get()) { + markup->create(*config.markup); } initTime(); } @@ -6368,7 +6444,6 @@ int32 HistoryMessage::plainMaxWidth() const { } void HistoryMessage::initDimensions() { - auto *reply = Get(); if (drawBubble()) { auto fwd = Get(); auto via = Get(); @@ -6427,7 +6502,7 @@ void HistoryMessage::initDimensions() { _maxw = _media->maxWidth(); _minh = _media->minHeight(); } - if (reply) { + if (auto *reply = Get()) { reply->updateName(); if (!_media) { int replyw = st::msgPadding.left() + reply->_maxReplyWidth - st::msgReplyPadding.left() - st::msgReplyPadding.right() + st::msgPadding.right(); @@ -6437,6 +6512,8 @@ void HistoryMessage::initDimensions() { if (replyw > _maxw) _maxw = replyw; } } + if (HistoryMessageReplyMarkup *markup = inlineReplyMarkup()) { + } } void HistoryMessage::countPositionAndSize(int32 &left, int32 &width) const { @@ -6741,11 +6818,15 @@ void HistoryMessage::draw(Painter &p, const QRect &r, uint32 selection, uint64 m textstyleSet(&(outbg ? st::outTextStyle : st::inTextStyle)); - //if (displayFromPhoto()) { - // int photoleft = left + ((outbg && !Adaptive::Wide()) ? (width + (st::msgPhotoSkip - st::msgPhotoSize)) : (-st::msgPhotoSkip)); - // int phototop = marginTop(); - // author()->paintUserpic(p, st::msgPhotoSize, photoleft, phototop); - //} + if (auto *markup = inlineReplyMarkup()) { + height -= markup->rows.size() * (st::msgBotKbButton.margin + st::msgBotKbButton.height); + int y = marginTop() + height + st::msgBotKbButton.margin; + for_const (const HistoryMessageReplyMarkup::ButtonRow &row, markup->rows) { + for_const (const HistoryMessageReplyMarkup::Button &button, row) { + + } + } + } auto *reply = Get(); if (reply) { @@ -6945,6 +7026,10 @@ int HistoryMessage::resizeGetHeight_(int width) { } else { _height = _media->resize(width, this); } + if (HistoryMessageReplyMarkup *markup = inlineReplyMarkup()) { + _height += (st::msgBotKbButton.margin + st::msgBotKbButton.height) * markup->rows.size(); + } + _height += marginTop() + marginBottom(); return _height; } @@ -6996,6 +7081,10 @@ void HistoryMessage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 //} if (width < 1) return; + if (const HistoryMessageReplyMarkup *markup = inlineReplyMarkup()) { + height -= (st::msgBotKbButton.margin + st::msgBotKbButton.height) * markup->rows.size(); + } + if (drawBubble()) { auto *fwd = Get(); auto *via = Get(); @@ -7172,9 +7261,6 @@ HistoryMessage::~HistoryMessage() { if (auto *reply = Get()) { reply->clearData(this); } - if (_flags & MTPDmessage::Flag::f_reply_markup) { - App::clearReplyMarkup(channelId(), id); - } } void HistoryService::setMessageByAction(const MTPmessageAction &action) { diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 497dd1060..5f617c80e 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -966,8 +966,6 @@ enum HistoryItemType { }; struct HistoryMessageVia : public BaseComponent { - HistoryMessageVia(Composer*) { - } void create(int32 userId); void resize(int32 availw) const; @@ -979,18 +977,12 @@ struct HistoryMessageVia : public BaseComponent { }; struct HistoryMessageViews : public BaseComponent { - HistoryMessageViews(Composer*) { - } - QString _viewsText; int _views = 0; int _viewsWidth = 0; }; struct HistoryMessageSigned : public BaseComponent { - HistoryMessageSigned(Composer*) { - } - void create(UserData *from, const QDateTime &date); int maxWidth() const; @@ -998,8 +990,6 @@ struct HistoryMessageSigned : public BaseComponent { }; struct HistoryMessageForwarded : public BaseComponent { - HistoryMessageForwarded(Composer*) { - } void create(const HistoryMessageVia *via) const; PeerData *_authorOriginal = nullptr; @@ -1009,24 +999,23 @@ struct HistoryMessageForwarded : public BaseComponent { }; struct HistoryMessageReply : public BaseComponent { - HistoryMessageReply(Composer*) { - } 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); + _replyToVia = std_::move(other._replyToVia); return *this; } ~HistoryMessageReply() { // clearData() should be called by holder t_assert(replyToMsg == nullptr); - t_assert(_replyToVia == nullptr); + t_assert(_replyToVia.data() == nullptr); } + bool updateData(HistoryMessage *holder, bool force = false); void clearData(HistoryMessage *holder); // must be called before destructor @@ -1058,12 +1047,45 @@ struct HistoryMessageReply : public BaseComponent { mutable Text replyToName, replyToText; mutable int replyToVersion = 0; mutable int _maxReplyWidth = 0; - HistoryMessageVia *_replyToVia = nullptr; + UniquePointer _replyToVia; int toWidth = 0; }; Q_DECLARE_OPERATORS_FOR_FLAGS(HistoryMessageReply::PaintFlags); -class HistoryDependentItemCallback : public SharedCallback2 { +class ReplyKeyboard { +public: + ReplyKeyboard(HistoryItem *item); + +}; + +struct HistoryMessageReplyMarkup : public BaseComponent { + HistoryMessageReplyMarkup() = default; + HistoryMessageReplyMarkup(MTPDreplyKeyboardMarkup::Flags f) : flags(f) { + } + + void create(const MTPReplyMarkup &markup); + + struct Button { + enum Type { + Default, + Url, + Callback, + RequestPhone, + RequestLocation, + }; + Type type; + QString text, url; + }; + using ButtonRow = QVector