mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Merge branch 'bots' of https://bitbucket.org/johnprestonmail/telegram-desktop into bots
This commit is contained in:
commit
ecce77ec4c
282 changed files with 48983 additions and 24654 deletions
30
CONTRIBUTING.md → .github/CONTRIBUTING.md
vendored
30
CONTRIBUTING.md → .github/CONTRIBUTING.md
vendored
|
@ -11,6 +11,7 @@ This document describes how you can contribute to Telegram Desktop. Please read
|
|||
* [Pull upstream changes into your fork regularly](#pull-upstream-changes-into-your-fork-regularly)
|
||||
* [How to get your pull request accepted](#how-to-get-your-pull-request-accepted)
|
||||
* [Keep your pull requests limited to a single issue](#keep-your-pull-requests-limited-to-a-single-issue)
|
||||
* [Squash your commits to a single commit](#squash-your-commits-to-a-single-commit)
|
||||
* [Don't mix code changes with whitespace cleanup](#dont-mix-code-changes-with-whitespace-cleanup)
|
||||
* [Keep your code simple!](#keep-your-code-simple)
|
||||
* [Test your changes!](#test-your-changes)
|
||||
|
@ -72,10 +73,8 @@ For more info, see [GitHub Help][help_change_commit_message].
|
|||
|
||||
## Build instructions
|
||||
|
||||
* [Visual Studio 2013][msvc]
|
||||
* [XCode 6.4][xcode]
|
||||
* [XCode 6.4 for OS X 10.6 and 10.7][xcode_old]
|
||||
* [Qt Creator 3.2.0 Ubuntu][qtcreator]
|
||||
See the [README.md](README.md#build-instructions) for details on the various build
|
||||
environments.
|
||||
|
||||
## Pull upstream changes into your fork regularly
|
||||
|
||||
|
@ -90,9 +89,13 @@ Check the log to be sure that you actually want the changes, before merging:
|
|||
|
||||
git log upstream/master
|
||||
|
||||
Then merge the changes that you fetched:
|
||||
Then rebase your changes on the latest commits in the `master` branch:
|
||||
|
||||
git merge upstream/master
|
||||
git rebase upstream/master
|
||||
|
||||
After that, you have to force push your commits:
|
||||
|
||||
git push --force
|
||||
|
||||
For more info, see [GitHub Help][help_fork_repo].
|
||||
|
||||
|
@ -107,6 +110,21 @@ Pull requests should be as small/atomic as possible. Large, wide-sweeping change
|
|||
* If you are making spelling corrections in the docs, don't modify other files.
|
||||
* If you are adding new functions don't '*cleanup*' unrelated functions. That cleanup belongs in another pull request.
|
||||
|
||||
#### Squash your commits to a single commit
|
||||
|
||||
To keep the history of the project clean, you should make one commit per pull request.
|
||||
If you already have multiple commits, you can add the commits together (squash them) with the following commands in Git Bash:
|
||||
|
||||
1. Open `Git Bash` (or `Git Shell`)
|
||||
2. Enter following command to squash the recent {N} commits: `git reset --soft HEAD~{N} && git commit` (replace `{N}` with the number of commits you want to squash)
|
||||
3. Press <kbd>i</kbd> to get into Insert-mode
|
||||
4. Enter the commit message of the new commit (and add the [signature](#sign-your-work) at the and)
|
||||
5. After adding the message, press <kbd>ESC</kbd> to get out of the Insert-mode
|
||||
6. Write `:wq` and press <kbd>Enter</kbd> to save the new message or write `:q!` to discard your changes
|
||||
7. Enter `git push --force` to push the new commit to the remote repository
|
||||
|
||||
For example, if you want to squash the last 5 commits, use `git reset --soft HEAD~5 && git commit`
|
||||
|
||||
### Don't mix code changes with whitespace cleanup
|
||||
|
||||
If you change two lines of code and correct 200 lines of whitespace issues in a file the diff on that pull request is functionally unreadable and will be **rejected**. Whitespace cleanups need to be in their own pull request.
|
26
.github/ISSUE_TEMPLATE.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<!--
|
||||
Thanks for reporting issues of Telegram Desktop!
|
||||
|
||||
To make it easier for us to help you please enter detailed information below.
|
||||
-->
|
||||
### Steps to reproduce
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
### Expected behaviour
|
||||
Tell us what should happen
|
||||
|
||||
### Actual behaviour
|
||||
Tell us what happens instead
|
||||
|
||||
### Configuration
|
||||
**Operating system:**
|
||||
|
||||
**Version of Telegram Desktop:**
|
||||
|
||||
### Logs
|
||||
Insert logs here (if necessary)
|
||||
|
||||
You can type "debugmode" in settings and then see ~/.TelegramDesktop/DebugLogs/log_...txt for log files.
|
||||
Type "debugmode" in settings again to disable logs.
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -7,9 +7,11 @@
|
|||
/Telegram/SourceFiles/art/sprite_125x.png
|
||||
/Telegram/SourceFiles/art/sprite_150x.png
|
||||
/Telegram/*.user
|
||||
*.vcxproj.user
|
||||
*.suo
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.opendb
|
||||
/Telegram/*.aps
|
||||
/Win32/
|
||||
ipch/
|
||||
|
|
47
.travis.yml
Normal file
47
.travis.yml
Normal file
|
@ -0,0 +1,47 @@
|
|||
sudo: required
|
||||
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
- BUILD_VERSION=""
|
||||
- BUILD_VERSION="disable_autoupdate"
|
||||
- BUILD_VERSION="disable_register_custom_scheme"
|
||||
- BUILD_VERSION="disable_crash_reports"
|
||||
- BUILD_VERSION="disable_network_proxy"
|
||||
|
||||
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
|
||||
|
||||
before_install:
|
||||
- "export TRAVIS_COMMIT_MSG=\"$(git log --format=%B --no-merges -n 1)\""
|
||||
- .travis/check.sh
|
||||
|
||||
script:
|
||||
- .travis/arch.sh
|
297
.travis/arch.sh
Executable file
297
.travis/arch.sh
Executable file
|
@ -0,0 +1,297 @@
|
|||
#!/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
# 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
|
||||
curl --fail -O "$ARCH_TRAVIS_MIRROR/iso/$ARCH_TRAVIS_ARCH_ISO/$archive" 2>&1
|
||||
local ret=$?
|
||||
|
||||
# if it fails, try arch iso form the previous month
|
||||
if [ $ret -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:
|
160
.travis/build.sh
Executable file
160
.travis/build.sh
Executable file
|
@ -0,0 +1,160 @@
|
|||
#!/bin/bash
|
||||
# Installs libs and compiles tdesktop
|
||||
|
||||
run() {
|
||||
info_msg "Build version: ${BUILD_VERSION}"
|
||||
|
||||
downloadLibs
|
||||
prepare
|
||||
build
|
||||
check
|
||||
}
|
||||
|
||||
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 == *"disable_autoupdate"* ]]; then
|
||||
options+="\nDEFINES += TDESKTOP_DISABLE_AUTOUPDATE"
|
||||
fi
|
||||
|
||||
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"'
|
||||
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
|
||||
}
|
||||
|
||||
source ./.travis/common.sh
|
||||
|
||||
run
|
25
.travis/check.sh
Executable file
25
.travis/check.sh
Executable file
|
@ -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
|
40
.travis/common.sh
Executable file
40
.travis/common.sh
Executable file
|
@ -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:$*"
|
||||
}
|
35
README.md
35
README.md
|
@ -2,14 +2,16 @@
|
|||
|
||||
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.
|
||||
|
||||
[](https://travis-ci.org/telegramdesktop/tdesktop)
|
||||
|
||||
The source code is published under GPLv3 with OpenSSL exception, the license is available [here][license].
|
||||
|
||||
## Supported systems
|
||||
|
||||
* Windows XP - Windows 10 (**not** RT)
|
||||
* Mac OS X 10.8 - Mac OS X 10.10
|
||||
* Mac OS X 10.8 - Mac OS X 10.11
|
||||
* Mac OS X 10.6 - Mac OS X 10.7 (separate build)
|
||||
* Ubuntu 12.04 - Ubuntu 14.04
|
||||
* Ubuntu 12.04 - Ubuntu 15.04
|
||||
* Fedora 22
|
||||
|
||||
## Third-party libraries
|
||||
|
@ -20,6 +22,8 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
|||
* libexif 0.6.20 ([LGPL](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html))
|
||||
* LZMA SDK 9.20 ([public domain](http://www.7-zip.org/sdk.html))
|
||||
* liblzma ([public domain](http://tukaani.org/xz/))
|
||||
* Google Breakpad ([License](https://chromium.googlesource.com/breakpad/breakpad/+/master/LICENSE))
|
||||
* Google Crashpad ([Apache License 2.0](https://chromium.googlesource.com/crashpad/crashpad/+/master/LICENSE))
|
||||
* OpenAL Soft ([LGPL](http://kcat.strangesoft.net/openal.html))
|
||||
* Opus codec ([BSD license](http://www.opus-codec.org/license/))
|
||||
* FFmpeg ([LGPL](https://www.ffmpeg.org/legal.html))
|
||||
|
@ -31,6 +35,7 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
|||
* [XCode 7][xcode]
|
||||
* [XCode 7 for OS X 10.6 and 10.7][xcode_old]
|
||||
* [Qt Creator 3.5.1 Ubuntu][qtcreator]
|
||||
* [Using qmake on GNU/Linux][qmake]
|
||||
|
||||
## Projects in Telegram solution
|
||||
|
||||
|
@ -46,21 +51,6 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
|||
|
||||
Compiles given files to single update file, compresses it with lzma and signs with a private key. It is not built in **Debug** and **Release** configurations of Telegram solution, because private key is inaccessible.
|
||||
|
||||
* ### Prepare
|
||||
|
||||
Prepares a release for deployment, puts all current files to deploy/{version} folder.
|
||||
|
||||
**Windows**:
|
||||
* tsetup{version}.exe installer
|
||||
* Telegram.exe
|
||||
* Telegram.pdb (debug info for crash minidumps view)
|
||||
* tupdate{updversion} binary lzma update archive
|
||||
|
||||
**Mac**:
|
||||
* tsetup{version}.dmg
|
||||
* Telegram.app
|
||||
* tmacupd{updversion} binary lzma update archive
|
||||
|
||||
* ### MetaEmoji
|
||||
|
||||
Creates four sprites and text2emoji replace code
|
||||
|
@ -92,7 +82,7 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
|||
|
||||
* ### MetaLang
|
||||
|
||||
Creates from languagepack file `Resources/lang.txt` language constants code and language file parse code:
|
||||
Creates from languagepack file `Resources/lang.strings` language constants code and language file parse code:
|
||||
* GeneratedFiles/lang.h
|
||||
* GeneratedFiles/lang.cpp
|
||||
|
||||
|
@ -102,7 +92,8 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
|||
[telegram_api]: https://core.telegram.org
|
||||
[telegram_proto]: https://core.telegram.org/mtproto
|
||||
[license]: LICENSE
|
||||
[msvc]: MSVC.md
|
||||
[xcode]: XCODE.md
|
||||
[xcode_old]: XCODEold.md
|
||||
[qtcreator]: QTCREATOR.md
|
||||
[msvc]: doc/building-msvc.md
|
||||
[xcode]: doc/building-xcode.md
|
||||
[xcode_old]: doc/building-xcode-old.md
|
||||
[qtcreator]: doc/building-qtcreator.md
|
||||
[qmake]: doc/building-qmake.md
|
||||
|
|
21
Telegram.sln
21
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
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@echo OFF
|
||||
setlocal
|
||||
|
||||
FOR /F "tokens=1,2* delims= " %%i in (Version) do set "%%i=%%j"
|
||||
|
||||
|
@ -29,6 +30,8 @@ set "HomePath=..\..\Telegram"
|
|||
set "ReleasePath=..\Win32\Deploy"
|
||||
set "DeployPath=%ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStrFull%"
|
||||
set "SignPath=..\..\TelegramPrivate\Sign.bat"
|
||||
set "BinaryName=Telegram"
|
||||
set "DropboxSymbolsPath=Z:\Dropbox\Telegram\symbols"
|
||||
|
||||
if %BetaVersion% neq 0 (
|
||||
if exist %DeployPath%\ (
|
||||
|
@ -71,9 +74,13 @@ echo .
|
|||
echo Version %AppVersionStrFull% build successfull. Preparing..
|
||||
echo .
|
||||
|
||||
echo Dumping debug symbols..
|
||||
call ..\..\Libraries\breakpad\src\tools\windows\binaries\dump_syms.exe %ReleasePath%\%BinaryName%.pdb > %ReleasePath%\%BinaryName%.sym
|
||||
echo Done!
|
||||
|
||||
set "PATH=%PATH%;C:\Program Files\7-Zip;C:\Program Files (x86)\Inno Setup 5"
|
||||
|
||||
call %SignPath% %ReleasePath%\Telegram.exe
|
||||
call %SignPath% %ReleasePath%\%BinaryName%.exe
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
call %SignPath% %ReleasePath%\Updater.exe
|
||||
|
@ -90,7 +97,7 @@ if %BetaVersion% equ 0 (
|
|||
)
|
||||
|
||||
cd %ReleasePath%
|
||||
call Packer.exe -version %VersionForPacker% -path Telegram.exe -path Updater.exe %DevParam%
|
||||
call Packer.exe -version %VersionForPacker% -path %BinaryName%.exe -path Updater.exe %DevParam%
|
||||
cd %HomePath%
|
||||
if %errorlevel% neq 0 goto error
|
||||
|
||||
|
@ -109,6 +116,21 @@ if %BetaVersion% neq 0 (
|
|||
set "PortableFile=tbeta%BetaVersion%_%BetaSignature%.zip"
|
||||
)
|
||||
|
||||
for /f ^"usebackq^ eol^=^
|
||||
|
||||
^ delims^=^" %%a in (%ReleasePath%\%BinaryName%.sym) do (
|
||||
set "SymbolsHashLine=%%a"
|
||||
goto symbolslinedone
|
||||
)
|
||||
:symbolslinedone
|
||||
FOR /F "tokens=1,2,3,4* delims= " %%i in ("%SymbolsHashLine%") do set "SymbolsHash=%%l"
|
||||
|
||||
echo Copying %BinaryName%.sym to %DropboxSymbolsPath%\%BinaryName%.pdb\%SymbolsHash%
|
||||
if not exist %DropboxSymbolsPath%\%BinaryName%.pdb mkdir %DropboxSymbolsPath%\%BinaryName%.pdb
|
||||
if not exist %DropboxSymbolsPath%\%BinaryName%.pdb\%SymbolsHash% mkdir %DropboxSymbolsPath%\%BinaryName%.pdb\%SymbolsHash%
|
||||
xcopy %ReleasePath%\%BinaryName%.sym %DropboxSymbolsPath%\%BinaryName%.pdb\%SymbolsHash%\
|
||||
echo Done!
|
||||
|
||||
if not exist %ReleasePath%\deploy mkdir %ReleasePath%\deploy
|
||||
if not exist %ReleasePath%\deploy\%AppVersionStrMajor% mkdir %ReleasePath%\deploy\%AppVersionStrMajor%
|
||||
mkdir %DeployPath%
|
||||
|
@ -144,7 +166,7 @@ if not exist %DeployPath%\%PortableFile% goto error
|
|||
if %BetaVersion% equ 0 (
|
||||
if not exist %DeployPath%\%SetupFile% goto error
|
||||
)
|
||||
if not exist %DeployPath%\Telegram.pdb goto error
|
||||
if not exist %DeployPath%\%BinaryName%.pdb goto error
|
||||
if not exist %DeployPath%\Updater.exe goto error
|
||||
if not exist %DeployPath%\Updater.pdb goto error
|
||||
if not exist %FinalReleasePath%\%AppVersionStrMajor% mkdir %FinalReleasePath%\%AppVersionStrMajor%
|
||||
|
@ -157,7 +179,7 @@ if %BetaVersion% equ 0 (
|
|||
) else (
|
||||
xcopy %DeployPath%\%BetaKeyFile% %FinalDeployPath%\ /Y
|
||||
)
|
||||
xcopy %DeployPath%\Telegram.pdb %FinalDeployPath%\
|
||||
xcopy %DeployPath%\%BinaryName%.pdb %FinalDeployPath%\
|
||||
xcopy %DeployPath%\Updater.exe %FinalDeployPath%\
|
||||
xcopy %DeployPath%\Updater.pdb %FinalDeployPath%\
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
set -e
|
||||
|
||||
FastParam="$1"
|
||||
|
||||
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||
set $line
|
||||
eval $1="$2"
|
||||
|
@ -37,6 +39,7 @@ if [ "$BuildTarget" == "linux" ]; then
|
|||
WorkPath="./../Linux"
|
||||
FixScript="$HomePath/FixMake.sh"
|
||||
ReleasePath="./../Linux/Release"
|
||||
BinaryName="Telegram"
|
||||
elif [ "$BuildTarget" == "linux32" ]; then
|
||||
echo "Building version $AppVersionStrFull for Linux 32bit.."
|
||||
UpdateFile="tlinux32upd$AppVersion"
|
||||
|
@ -44,6 +47,7 @@ elif [ "$BuildTarget" == "linux32" ]; then
|
|||
WorkPath="./../Linux"
|
||||
FixScript="$HomePath/FixMake32.sh"
|
||||
ReleasePath="./../Linux/Release"
|
||||
BinaryName="Telegram"
|
||||
elif [ "$BuildTarget" == "mac" ]; then
|
||||
echo "Building version $AppVersionStrFull for OS X 10.8+.."
|
||||
UpdateFile="tmacupd$AppVersion"
|
||||
|
@ -104,22 +108,25 @@ fi
|
|||
#fi
|
||||
|
||||
if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
||||
|
||||
DropboxSymbolsPath="/media/psf/Home/Dropbox/Telegram/symbols"
|
||||
|
||||
mkdir -p "$WorkPath/ReleaseIntermediateUpdater"
|
||||
cd "$WorkPath/ReleaseIntermediateUpdater"
|
||||
/usr/local/Qt-5.5.1/bin/qmake "$HomePath/Updater.pro"
|
||||
/usr/local/Qt-5.5.1/bin/qmake "$HomePath/Updater.pro" -r -spec linux-g++
|
||||
make
|
||||
echo "Updater build complete!"
|
||||
cd "$HomePath"
|
||||
|
||||
mkdir -p "$WorkPath/ReleaseIntermediate"
|
||||
cd "$WorkPath/ReleaseIntermediate"
|
||||
/usr/local/Qt-5.5.1/bin/qmake "$HomePath/Telegram.pro"
|
||||
/usr/local/Qt-5.5.1/bin/qmake "$HomePath/Telegram.pro" -r -spec linux-g++
|
||||
eval "$FixScript"
|
||||
make
|
||||
echo "Telegram build complete!"
|
||||
echo "$BinaryName build complete!"
|
||||
cd "$HomePath"
|
||||
if [ ! -f "$ReleasePath/Telegram" ]; then
|
||||
echo "Telegram not found!"
|
||||
if [ ! -f "$ReleasePath/$BinaryName" ]; then
|
||||
echo "$BinaryName not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -128,8 +135,16 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
echo "Dumping debug symbols.."
|
||||
"./../../Libraries/breakpad/src/tools/linux/dump_syms/dump_syms" "$ReleasePath/$BinaryName" > "$ReleasePath/$BinaryName.sym"
|
||||
echo "Done!"
|
||||
|
||||
echo "Stripping the executable.."
|
||||
strip -s "$ReleasePath/$BinaryName"
|
||||
echo "Done!"
|
||||
|
||||
echo "Preparing version $AppVersionStrFull, executing Packer.."
|
||||
cd "$ReleasePath" && "./Packer" -path Telegram -path Updater -version $VersionForPacker $DevParam && cd "$HomePath"
|
||||
cd "$ReleasePath" && "./Packer" -path "$BinaryName" -path Updater -version $VersionForPacker $DevParam && cd "$HomePath"
|
||||
echo "Packer done!"
|
||||
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
|
@ -146,6 +161,12 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
|||
SetupFile="tbeta${BetaVersion}_${BetaSignature}.tar.xz"
|
||||
fi
|
||||
|
||||
SymbolsHash=`head -n 1 "$ReleasePath/$BinaryName.sym" | awk -F " " 'END {print $4}'`
|
||||
echo "Copying $BinaryName.sym to $DropboxSymbolsPath/$BinaryName/$SymbolsHash"
|
||||
mkdir -p "$DropboxSymbolsPath/$BinaryName/$SymbolsHash"
|
||||
cp "$ReleasePath/$BinaryName.sym" "$DropboxSymbolsPath/$BinaryName/$SymbolsHash/"
|
||||
echo "Done!"
|
||||
|
||||
if [ ! -d "$ReleasePath/deploy" ]; then
|
||||
mkdir "$ReleasePath/deploy"
|
||||
fi
|
||||
|
@ -154,21 +175,25 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ]; then
|
|||
mkdir "$ReleasePath/deploy/$AppVersionStrMajor"
|
||||
fi
|
||||
|
||||
echo "Copying Telegram, Updater and $UpdateFile to deploy/$AppVersionStrMajor/$AppVersionStrFull..";
|
||||
echo "Copying $BinaryName, Updater and $UpdateFile to deploy/$AppVersionStrMajor/$AppVersionStrFull..";
|
||||
mkdir "$DeployPath"
|
||||
mkdir "$DeployPath/Telegram"
|
||||
mv "$ReleasePath/Telegram" "$DeployPath/Telegram/"
|
||||
mv "$ReleasePath/Updater" "$DeployPath/Telegram/"
|
||||
mkdir "$DeployPath/$BinaryName"
|
||||
mv "$ReleasePath/$BinaryName" "$DeployPath/$BinaryName/"
|
||||
mv "$ReleasePath/Updater" "$DeployPath/$BinaryName/"
|
||||
mv "$ReleasePath/$UpdateFile" "$DeployPath/"
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
mv "$ReleasePath/$BetaKeyFile" "$DeployPath/"
|
||||
fi
|
||||
cd "$DeployPath" && tar -cJvf "$SetupFile" "Telegram/" && cd "./../../../$HomePath"
|
||||
cd "$DeployPath" && tar -cJvf "$SetupFile" "$BinaryName/" && cd "./../../../$HomePath"
|
||||
fi
|
||||
|
||||
if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarget" == "macstore" ]; then
|
||||
|
||||
touch "./SourceFiles/telegram.qrc"
|
||||
DropboxSymbolsPath="./../../../Dropbox/Telegram/symbols"
|
||||
|
||||
if [ "$FastParam" != "fast" ]; then
|
||||
touch "./SourceFiles/telegram.qrc"
|
||||
fi
|
||||
xcodebuild -project Telegram.xcodeproj -alltargets -configuration Release build
|
||||
|
||||
if [ ! -d "$ReleasePath/$BinaryName.app" ]; then
|
||||
|
@ -181,6 +206,28 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ]; then
|
||||
echo "Removing Updater debug symbols.."
|
||||
rm -rf "$ReleasePath/$BinaryName.app/Contents/Frameworks/Updater.dSYM"
|
||||
echo "Done!"
|
||||
fi
|
||||
|
||||
echo "Dumping debug symbols.."
|
||||
"./../../Libraries/breakpad/src/tools/mac/dump_syms/build/Release/dump_syms" "$ReleasePath/$BinaryName.app.dSYM" > "$ReleasePath/$BinaryName.sym" 2>/dev/null
|
||||
echo "Done!"
|
||||
|
||||
echo "Stripping the executable.."
|
||||
strip "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName"
|
||||
echo "Done!"
|
||||
|
||||
echo "Signing the application.."
|
||||
if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ]; then
|
||||
codesign --force --deep --sign "Developer ID Application: John Preston" "$ReleasePath/$BinaryName.app"
|
||||
elif [ "$BuildTarget" == "macstore" ]; then
|
||||
codesign --force --deep --sign "3rd Party Mac Developer Application: TELEGRAM MESSENGER LLP (6N38VWS5BX)" "$ReleasePath/$BinaryName.app" --entitlements "Telegram/Telegram Desktop.entitlements"
|
||||
fi
|
||||
echo "Done!"
|
||||
|
||||
AppUUID=`dwarfdump -u "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName" | awk -F " " '{print $2}'`
|
||||
DsymUUID=`dwarfdump -u "$ReleasePath/$BinaryName.app.dSYM" | awk -F " " '{print $2}'`
|
||||
if [ "$AppUUID" != "$DsymUUID" ]; then
|
||||
|
@ -215,6 +262,12 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
|
|||
fi
|
||||
fi
|
||||
|
||||
SymbolsHash=`head -n 1 "$ReleasePath/$BinaryName.sym" | awk -F " " 'END {print $4}'`
|
||||
echo "Copying $BinaryName.sym to $DropboxSymbolsPath/$BinaryName/$SymbolsHash"
|
||||
mkdir -p "$DropboxSymbolsPath/$BinaryName/$SymbolsHash"
|
||||
cp "$ReleasePath/$BinaryName.sym" "$DropboxSymbolsPath/$BinaryName/$SymbolsHash/"
|
||||
echo "Done!"
|
||||
|
||||
if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ]; then
|
||||
if [ "$BetaVersion" == "0" ]; then
|
||||
cd "$ReleasePath"
|
||||
|
@ -254,10 +307,10 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
|
|||
if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ]; then
|
||||
echo "Copying $BinaryName.app and $UpdateFile to deploy/$AppVersionStrMajor/$AppVersionStr..";
|
||||
mkdir "$DeployPath"
|
||||
mkdir "$DeployPath/Telegram"
|
||||
cp -r "$ReleasePath/$BinaryName.app" "$DeployPath/Telegram/"
|
||||
mkdir "$DeployPath/$BinaryName"
|
||||
cp -r "$ReleasePath/$BinaryName.app" "$DeployPath/$BinaryName/"
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
cd "$DeployPath" && zip -r "$SetupFile" "Telegram" && mv "$SetupFile" "./../../../" && cd "./../../../$HomePath"
|
||||
cd "$DeployPath" && zip -r "$SetupFile" "$BinaryName" && mv "$SetupFile" "./../../../" && cd "./../../../$HomePath"
|
||||
mv "$ReleasePath/$BetaKeyFile" "$DeployPath/"
|
||||
fi
|
||||
mv "$ReleasePath/$BinaryName.app.dSYM" "$DeployPath/"
|
||||
|
@ -294,6 +347,7 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
|
|||
rm "$ReleasePath/$BinaryName.app/Contents/MacOS/$BinaryName"
|
||||
rm -rf "$ReleasePath/$BinaryName.app/Contents/_CodeSignature"
|
||||
|
||||
mkdir -p "$DropboxDeployPath"
|
||||
cp -v "$DeployPath/$BinaryName.app" "$DropboxDeployPath/"
|
||||
cp -rv "$DeployPath/$BinaryName.app.dSYM" "$DropboxDeployPath/"
|
||||
fi
|
||||
|
|
|
@ -57,7 +57,11 @@ elif [ "$BuildTarget" == "mac" ]; then
|
|||
echo "Deploying version $AppVersionStrFull for Windows.."
|
||||
else
|
||||
DeployMac="1"
|
||||
DeployMac32="1"
|
||||
if [ "$BetaVersion" != "0" ]; then
|
||||
DeployMac32="0"
|
||||
else
|
||||
DeployMac32="1"
|
||||
fi
|
||||
DeployWin="1"
|
||||
echo "Deploying three versions of $AppVersionStrFull: for Windows, OS X 10.6 and 10.7 and OS X 10.8+.."
|
||||
fi
|
||||
|
@ -165,13 +169,7 @@ fi
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$DropboxPath" ]; then
|
||||
mkdir "$DropboxPath"
|
||||
fi
|
||||
|
||||
if [ ! -d "$DropboxDeployPath" ]; then
|
||||
mkdir "$DropboxDeployPath"
|
||||
fi
|
||||
mkdir -p "$DropboxDeployPath"
|
||||
fi
|
||||
#fi
|
||||
|
||||
|
@ -194,7 +192,6 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$Build
|
|||
fi
|
||||
|
||||
if [ "$DeployMac" == "1" ]; then
|
||||
cp -v "$DeployPath/$UpdateFile" "$DropboxDeployPath/"
|
||||
cp -v "$DeployPath/$SetupFile" "$DropboxDeployPath/$DropboxSetupFile"
|
||||
if [ -d "$DropboxDeployPath/Telegram.app.dSYM" ]; then
|
||||
rm -rf "$DropboxDeployPath/Telegram.app.dSYM"
|
||||
|
@ -202,7 +199,6 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$Build
|
|||
cp -rv "$DeployPath/Telegram.app.dSYM" "$DropboxDeployPath/"
|
||||
fi
|
||||
if [ "$DeployMac32" == "1" ]; then
|
||||
mv -v "$Mac32DeployPath/$Mac32UpdateFile" "$DropboxDeployPath/"
|
||||
mv -v "$Mac32DeployPath/$Mac32SetupFile" "$DropboxDeployPath/$DropboxMac32SetupFile"
|
||||
if [ -d "$DropboxDeployPath/Telegram32.app.dSYM" ]; then
|
||||
rm -rf "$DropboxDeployPath/Telegram32.app.dSYM"
|
||||
|
@ -213,7 +209,6 @@ if [ "$BuildTarget" == "linux" ] || [ "$BuildTarget" == "linux32" ] || [ "$Build
|
|||
mv -v "$WinDeployPath/Telegram.pdb" "$DropboxDeployPath/"
|
||||
mv -v "$WinDeployPath/Updater.exe" "$DropboxDeployPath/"
|
||||
mv -v "$WinDeployPath/Updater.pdb" "$DropboxDeployPath/"
|
||||
mv -v "$WinDeployPath/$WinUpdateFile" "$DropboxDeployPath/"
|
||||
if [ "$BetaVersion" == "0" ]; then
|
||||
mv -v "$WinDeployPath/$WinSetupFile" "$DropboxDeployPath/"
|
||||
fi
|
||||
|
|
|
@ -11,12 +11,7 @@ Replace () {
|
|||
}
|
||||
|
||||
Replace '\-llzma' '\/usr\/lib\/x86_64\-linux\-gnu\/liblzma\.a'
|
||||
Replace '\-lz' '\/usr\/lib\/x86_64\-linux\-gnu\/libz\.a'
|
||||
Replace '\-lssl' '\/usr\/lib\/x86_64\-linux\-gnu\/libssl\.a'
|
||||
Replace '\-lcrypto' '\/usr\/lib\/x86_64\-linux\-gnu\/libcrypto\.a'
|
||||
Replace '\-lexif' '\/usr\/lib\/x86_64\-linux\-gnu\/libexif\.a'
|
||||
Replace '\-lgobject\-2\.0' '\/usr\/lib\/x86_64\-linux\-gnu\/libgobject\-2\.0\.a \/usr\/lib\/x86_64\-linux\-gnu\/libffi\.a'
|
||||
Replace '\-lXi' '\/usr\/lib\/x86_64\-linux\-gnu\/libXi\.a'
|
||||
Replace '\-lXi' '\/usr\/lib\/x86_64\-linux\-gnu\/libXi\.a \/usr\/lib\/x86_64\-linux\-gnu\/libXext\.a'
|
||||
Replace '\-lSM' '\/usr\/lib\/x86_64\-linux\-gnu\/libSM\.a'
|
||||
Replace '\-lICE' '\/usr\/lib\/x86_64\-linux\-gnu\/libICE\.a'
|
||||
Replace '\-lfontconfig' '\/usr\/lib\/x86_64\-linux\-gnu\/libfontconfig\.a \/usr\/lib\/x86_64\-linux\-gnu\/libexpat\.a'
|
||||
|
@ -30,3 +25,4 @@ Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a'
|
|||
Replace '\-lswscale' '\/usr\/local\/lib\/libswscale\.a'
|
||||
Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a'
|
||||
Replace '\-lva' '\/usr\/local\/lib\/libva\.a'
|
||||
Replace '\-lQt5Network' '\/usr\/local\/Qt-5.5.1\/lib\/libQt5Network.a \/usr\/local\/ssl\/lib\/libssl.a \/usr\/local\/ssl\/lib\/libcrypto.a'
|
||||
|
|
|
@ -11,12 +11,7 @@ Replace () {
|
|||
}
|
||||
|
||||
Replace '\-llzma' '\/usr\/lib\/i386\-linux\-gnu\/liblzma\.a'
|
||||
Replace '\-lz' '\/usr\/lib\/i386\-linux\-gnu\/libz\.a'
|
||||
Replace '\-lssl' '\/usr\/lib\/i386\-linux\-gnu\/libssl\.a'
|
||||
Replace '\-lcrypto' '\/usr\/lib\/i386\-linux\-gnu\/libcrypto\.a'
|
||||
Replace '\-lexif' '\/usr\/lib\/i386\-linux\-gnu\/libexif\.a'
|
||||
Replace '\-lgobject\-2\.0' '\/usr\/lib\/i386\-linux\-gnu\/libgobject\-2\.0\.a \/usr\/lib\/i386\-linux\-gnu\/libffi\.a'
|
||||
Replace '\-lXi' '\/usr\/lib\/i386\-linux\-gnu\/libXi\.a'
|
||||
Replace '\-lXi' '\/usr\/lib\/i386\-linux\-gnu\/libXi\.a \/usr\/lib\/i386\-linux\-gnu\/libXext\.a'
|
||||
Replace '\-lSM' '\/usr\/lib\/i386\-linux\-gnu\/libSM\.a'
|
||||
Replace '\-lICE' '\/usr\/lib\/i386\-linux\-gnu\/libICE\.a'
|
||||
Replace '\-lfontconfig' '\/usr\/lib\/i386\-linux\-gnu\/libfontconfig\.a \/usr\/lib\/i386\-linux\-gnu\/libexpat\.a'
|
||||
|
@ -30,3 +25,4 @@ Replace '\-lswresample' '\/usr\/local\/lib\/libswresample\.a'
|
|||
Replace '\-lswscale' '\/usr\/local\/lib\/libswscale\.a'
|
||||
Replace '\-lavutil' '\/usr\/local\/lib\/libavutil\.a'
|
||||
Replace '\-lva' '\/usr\/local\/lib\/libva\.a'
|
||||
Replace '\-lQt5Network' '\/usr\/local\/Qt-5.5.1\/lib\/libQt5Network.a \/usr\/local\/ssl\/lib\/libssl.a \/usr\/local\/ssl\/lib\/libcrypto.a'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
1
Telegram/Resources/LangList
Normal file
1
Telegram/Resources/LangList
Normal file
|
@ -0,0 +1 @@
|
|||
de,es,it,ko,nl,pt_BR
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
"lng_language_name" = "English";
|
||||
"lng_switch_to_this" = "Switch to English";
|
||||
|
@ -86,8 +86,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_cancel" = "Cancel";
|
||||
"lng_continue" = "Continue";
|
||||
"lng_close" = "Close";
|
||||
"lng_connecting" = "Connecting..";
|
||||
"lng_reconnecting" = "Reconnect {count:now|in # s|in # s}..";
|
||||
"lng_connecting" = "Connecting...";
|
||||
"lng_reconnecting" = "Reconnect {count:now|in # s|in # s}...";
|
||||
"lng_reconnecting_try_now" = "Try now";
|
||||
|
||||
"lng_status_service_notifications" = "service notifications";
|
||||
|
@ -108,7 +108,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_status_lastseen_date" = "last seen {date}";
|
||||
"lng_status_lastseen_date_time" = "last seen {date} at {time}";
|
||||
"lng_status_online" = "online";
|
||||
"lng_status_connecting" = "connecting..";
|
||||
"lng_status_connecting" = "connecting...";
|
||||
|
||||
"lng_chat_status_unaccessible" = "group is unaccessible";
|
||||
"lng_chat_status_members" = "{count:no members|# member|# members}";
|
||||
|
@ -123,8 +123,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_server_error" = "Internal server error.";
|
||||
"lng_flood_error" = "Too many tries. Please try again later.";
|
||||
"lng_gif_error" = "An error has occured while reading GIF animation :(";
|
||||
"lng_edit_error" = "You cannot edit this message";
|
||||
"lng_edit_deleted" = "This message was deleted";
|
||||
"lng_edit_too_long" = "Your message text is too long";
|
||||
"lng_edit_message" = "Edit message";
|
||||
"lng_edit_message_text" = "New message text...";
|
||||
"lng_deleted" = "Unknown";
|
||||
"lng_deleted_message" = "Deleted message";
|
||||
"lng_pinned_message" = "Pinned message";
|
||||
"lng_pinned_unpin_sure" = "Would you like to unpin this message?";
|
||||
"lng_pinned_pin_sure" = "Would you like to pin this message?";
|
||||
"lng_pinned_pin" = "Pin";
|
||||
"lng_pinned_unpin" = "Unpin";
|
||||
"lng_pinned_notify" = "Notify all members";
|
||||
|
||||
"lng_intro" = "Welcome to the official [a href=\"https://telegram.org/\"]Telegram[/a] desktop app.\nIt's [b]fast[/b] and [b]secure[/b].";
|
||||
"lng_start_msgs" = "START MESSAGING";
|
||||
|
@ -151,7 +162,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_code_telegram" = "Please enter the code you've just\nreceived in your previous [b]Telegram[/b] app.";
|
||||
"lng_code_no_telegram" = "Send code via SMS";
|
||||
"lng_code_call" = "Telegram will dial your number in {minutes}:{seconds}";
|
||||
"lng_code_calling" = "Requesting a call from Telegram..";
|
||||
"lng_code_calling" = "Requesting a call from Telegram...";
|
||||
"lng_code_called" = "Telegram dialed your number";
|
||||
|
||||
"lng_bad_phone" = "Invalid phone number. Please try again.";
|
||||
|
@ -190,7 +201,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_dlg_new_channel_name" = "Channel name";
|
||||
"lng_no_contacts" = "You have no contacts";
|
||||
"lng_no_chats" = "Your chats will be here";
|
||||
"lng_contacts_loading" = "Loading..";
|
||||
"lng_contacts_loading" = "Loading...";
|
||||
"lng_contacts_not_found" = "No contacts found";
|
||||
"lng_dlg_search_chat" = "Search in this chat";
|
||||
"lng_dlg_search_channel" = "Search in this channel";
|
||||
|
@ -199,7 +210,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_settings_save" = "Save";
|
||||
"lng_settings_upload" = "Set Profile Photo";
|
||||
"lng_settings_crop_profile" = "Select a square area for your profile photo";
|
||||
"lng_settings_uploading_photo" = "Uploading photo..";
|
||||
"lng_settings_uploading_photo" = "Uploading photo...";
|
||||
|
||||
"lng_username_title" = "Username";
|
||||
"lng_username_about" = "You can choose a username on Telegram.\nIf you do, other people will be able to find\nyou by this username and contact you\nwithout knowing your phone number.\n\nYou can use a-z, 0-9 and underscores.\nMinimum length is 5 characters.";
|
||||
|
@ -236,9 +247,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_settings_auto_update" = "Update automatically";
|
||||
"lng_settings_current_version" = "Version {version}";
|
||||
"lng_settings_check_now" = "Check for updates";
|
||||
"lng_settings_update_checking" = "Checking for updates..";
|
||||
"lng_settings_update_checking" = "Checking for updates...";
|
||||
"lng_settings_latest_installed" = "Latest version is installed";
|
||||
"lng_settings_downloading" = "Downloading update {ready} / {total} MB..";
|
||||
"lng_settings_downloading" = "Downloading update {ready} / {total} MB...";
|
||||
"lng_settings_update_ready" = "New version is ready";
|
||||
"lng_settings_update_now" = "Restart Now";
|
||||
"lng_settings_update_fail" = "Update check failed :(";
|
||||
|
@ -262,6 +273,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_settings_bg_from_gallery" = "Choose from gallery";
|
||||
"lng_settings_bg_from_file" = "Choose from file";
|
||||
"lng_settings_bg_tile" = "Tile background";
|
||||
"lng_settings_adaptive_wide" = "Adaptive layout for wide screens";
|
||||
|
||||
"lng_backgrounds_header" = "Choose your new chat background";
|
||||
|
||||
|
@ -279,7 +291,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_download_path_failed" = "File download could not be started. It could happen because of a bad download location.\n\nYou can change download path in Settings.";
|
||||
"lng_download_path_settings" = "Settings";
|
||||
"lng_download_finish_failed" = "File download could not be finished.\n\nWould you like to try again?";
|
||||
"lng_download_path_clearing" = "Clearing..";
|
||||
"lng_download_path_clearing" = "Clearing...";
|
||||
"lng_download_path_cleared" = "Cleared!";
|
||||
"lng_download_path_clear_failed" = "Clear failed :(";
|
||||
|
||||
|
@ -288,7 +300,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_settings_images_cached" = "{count:_not_used_|# image|# images}, {size}";
|
||||
"lng_settings_audios_cached" = "{count:_not_used_|# voice message|# voice messages}, {size}";
|
||||
"lng_local_storage_clear" = "Clear all";
|
||||
"lng_local_storage_clearing" = "Clearing..";
|
||||
"lng_local_storage_clearing" = "Clearing...";
|
||||
"lng_local_storage_cleared" = "Cleared!";
|
||||
"lng_local_storage_clear_failed" = "Clear failed :(";
|
||||
|
||||
|
@ -319,7 +331,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_passcode_logout" = "Log out";
|
||||
"lng_passcode_need_unblock" = "You need to unlock me first.";
|
||||
|
||||
"lng_cloud_password_waiting" = "Confirmation link sent to {email}..";
|
||||
"lng_cloud_password_waiting" = "Confirmation link sent to {email}...";
|
||||
"lng_cloud_password_change" = "Change cloud password";
|
||||
"lng_cloud_password_create" = "Cloud password";
|
||||
"lng_cloud_password_remove" = "Remove cloud password";
|
||||
|
@ -346,9 +358,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_cloud_password_is_same" = "Password was not changed";
|
||||
|
||||
"lng_connection_type" = "Connection type:";
|
||||
"lng_connection_auto_connecting" = "Default (connecting..)";
|
||||
"lng_connection_auto_connecting" = "Default (connecting...)";
|
||||
"lng_connection_auto" = "Default ({transport} used)";
|
||||
"lng_connection_proxy_connecting" = "Connecting through proxy..";
|
||||
"lng_connection_proxy_connecting" = "Connecting through proxy...";
|
||||
"lng_connection_proxy" = "{transport} with proxy";
|
||||
"lng_connection_header" = "Connection type";
|
||||
"lng_connection_auto_rb" = "Auto (TCP if available or HTTP)";
|
||||
|
@ -384,7 +396,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_sessions_other_desc" = "You can log in to Telegram from other mobile, tablet and desktop devices, using the same phone number. All your data will be instantly synchronized.";
|
||||
"lng_sessions_terminate_all" = "Terminate all other sessions";
|
||||
|
||||
"lng_preview_loading" = "Getting Link Info..";
|
||||
"lng_preview_loading" = "Getting Link Info...";
|
||||
|
||||
"lng_profile_chat_unaccessible" = "Group is unaccessible";
|
||||
"lng_topbar_info" = "Info";
|
||||
|
@ -423,10 +435,11 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_profile_add_participant" = "Add Members";
|
||||
"lng_profile_delete_and_exit" = "Leave";
|
||||
"lng_profile_kick" = "Remove";
|
||||
"lng_profile_admin" = "admin";
|
||||
"lng_profile_sure_kick" = "Remove {user} from the group?";
|
||||
"lng_profile_sure_kick_channel" = "Remove {user} from the channel?";
|
||||
"lng_profile_sure_kick_admin" = "Remove {user} from administrators?";
|
||||
"lng_profile_loading" = "Loading..";
|
||||
"lng_profile_loading" = "Loading...";
|
||||
"lng_profile_shared_media" = "Shared media";
|
||||
"lng_profile_no_media" = "No media in this conversation.";
|
||||
"lng_profile_photos" = "{count:_not_used_|# photo|# photos} »";
|
||||
|
@ -442,6 +455,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_profile_shared_links" = "{count:_not_used_|# shared link|# shared links} »";
|
||||
"lng_profile_shared_links_header" = "Shared links overview";
|
||||
"lng_profile_copy_phone" = "Copy phone number";
|
||||
"lng_profile_copy_fullname" = "Copy name";
|
||||
|
||||
"lng_channel_add_admins" = "New administrator";
|
||||
"lng_channel_add_members" = "Add members";
|
||||
|
@ -463,13 +477,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_create_group_next" = "Next";
|
||||
"lng_create_group_create" = "Create";
|
||||
"lng_create_group_title" = "New Group";
|
||||
"lng_create_group_about" = "Groups are ideal for smaller communities,\nthey can have up to {count:_not_used|# member|# members}";
|
||||
"lng_create_group_about" = "Groups are ideal for limited communities,\nthey can have up to {count:_not_used|# member|# members}";
|
||||
"lng_create_channel_title" = "New Channel";
|
||||
"lng_create_channel_about" = "Channels are a tool for broadcasting your messages to unlimited audiences";
|
||||
"lng_create_public_channel_title" = "Public Channel";
|
||||
"lng_create_public_channel_about" = "Anyone can find the channel in search and join";
|
||||
"lng_create_private_channel_title" = "Private Channel";
|
||||
"lng_create_private_channel_about" = "Only people with a special invite link may join";
|
||||
"lng_create_public_group_title" = "Public Group";
|
||||
"lng_create_public_group_about" = "Anyone can find the group in search and join, chat history is available to everybody";
|
||||
"lng_create_private_group_title" = "Private Group";
|
||||
"lng_create_private_group_about" = "People can only join if they were invited or have an invite link";
|
||||
"lng_create_channel_comments" = "Enable Comments";
|
||||
"lng_create_channel_comments_about" = "If you enable comments, members will be able to discuss your posts in the channel";
|
||||
"lng_create_group_skip" = "Skip";
|
||||
|
@ -498,7 +516,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_sure_delete_group" = "Are you sure, you want to delete this group? All members will be removed and all messages will be lost.";
|
||||
|
||||
"lng_message_empty" = "Empty Message";
|
||||
"lng_media_unsupported" = "Media Unsupported";
|
||||
"lng_message_unsupported" = "This message is not supported by your version of Telegram Desktop. Please update to the last version in Settings or install it from {link}";
|
||||
|
||||
"lng_action_add_user" = "{from} added {user}";
|
||||
"lng_action_add_users_many" = "{from} added {users}";
|
||||
|
@ -522,6 +540,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_action_created_chat" = "{from} created group «{title}»";
|
||||
"lng_action_created_channel" = "Channel «{title}» created";
|
||||
"lng_action_group_migrate" = "The group was upgraded to a supergroup";
|
||||
"lng_action_pinned_message" = "{from} pinned «{text}»";
|
||||
"lng_action_pinned_media" = "{from} pinned {media}";
|
||||
"lng_action_pinned_media_photo" = "a photo";
|
||||
"lng_action_pinned_media_video" = "a video file";
|
||||
"lng_action_pinned_media_audio" = "an audio file";
|
||||
"lng_action_pinned_media_voice" = "a voice message";
|
||||
"lng_action_pinned_media_file" = "a file";
|
||||
"lng_action_pinned_media_gif" = "a GIF animation";
|
||||
"lng_action_pinned_media_contact" = "a contact information";
|
||||
"lng_action_pinned_media_location" = "a location mark";
|
||||
"lng_action_pinned_media_sticker" = "a sticker";
|
||||
|
||||
"lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached";
|
||||
"lng_profile_migrate_about" = "If you'd like to go over this limit, you can upgrade your group to a supergroup. In supergroups:";
|
||||
|
@ -531,6 +560,16 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_profile_migrate_feature4" = "— Notifications are muted by default";
|
||||
"lng_profile_migrate_button" = "Upgrade to supergroup";
|
||||
"lng_profile_migrate_sure" = "Are you sure you want to upgrade this group to supergroup? This action cannot be undone.";
|
||||
"lng_profile_convert_button" = "Convert to supergroup";
|
||||
"lng_profile_convert_title" = "Convert to supergroup";
|
||||
"lng_profile_convert_about" = "In supergroups:";
|
||||
"lng_profile_convert_feature1" = "— New members see the full message history";
|
||||
"lng_profile_convert_feature2" = "— Messages are deleted for all members";
|
||||
"lng_profile_convert_feature3" = "— Members can edit their own messages";
|
||||
"lng_profile_convert_feature4" = "— Creator can set a public link for the group";
|
||||
"lng_profile_convert_warning" = "{bold_start}Note:{bold_end} This action can not be undone";
|
||||
"lng_profile_convert_confirm" = "Convert";
|
||||
"lng_profile_add_more_after_upgrade" = "You will be able to add up to {count:_not_used_|# member|# members} after you upgrade your group to a supergroup.";
|
||||
|
||||
"lng_channel_comments_count" = "{count:_not_used_|# comment|# comments}";
|
||||
"lng_channel_hide_comments" = "Hide comments";
|
||||
|
@ -555,9 +594,18 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_channel_public_link_copied" = "Link copied to clipboard.";
|
||||
|
||||
"lng_forwarded_from" = "Forwarded from";
|
||||
"lng_forwarded" = "Forwarded from {user}";
|
||||
"lng_forwarded_channel" = "Forwarded from {channel}";
|
||||
"lng_forwarded_via" = "Forwarded from {user} via {inline_bot}";
|
||||
"lng_forwarded_channel_via" = "Forwarded from {channel} via {inline_bot}";
|
||||
"lng_forwarded_signed" = "{channel} ({user})";
|
||||
"lng_in_reply_to" = "In reply to";
|
||||
|
||||
"lng_bot_share_location_unavailable" = "Sorry, the location sharing is currently unavailable in Telegram Desktop.";
|
||||
"lng_bot_inline_geo_unavailable" = "Sorry, this bot requires location sharing.\nIt is not unavailable in Telegram Desktop.";
|
||||
"lng_bot_share_phone" = "Share Phone Number?";
|
||||
"lng_bot_share_phone_confirm" = "Share";
|
||||
|
||||
"lng_attach_failed" = "Failed";
|
||||
"lng_attach_file" = "File";
|
||||
"lng_attach_photo" = "Photo";
|
||||
|
@ -600,6 +648,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_saved_gifs" = "Saved GIFs";
|
||||
"lng_inline_bot_results" = "Results from {inline_bot}";
|
||||
"lng_inline_bot_no_results" = "No results";
|
||||
"lng_inline_bot_via" = "via {inline_bot}";
|
||||
|
||||
"lng_box_remove" = "Remove";
|
||||
|
||||
|
@ -616,16 +665,19 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_stickers_remove" = "Delete";
|
||||
"lng_stickers_return" = "Undo";
|
||||
"lng_stickers_restore" = "Restore";
|
||||
"lng_stickers_count" = "{count:Loading..|# sticker|# stickers}";
|
||||
"lng_stickers_count" = "{count:Loading...|# sticker|# stickers}";
|
||||
|
||||
"lng_in_dlg_photo" = "Photo";
|
||||
"lng_in_dlg_video" = "Video";
|
||||
"lng_in_dlg_video" = "Video file";
|
||||
"lng_in_dlg_audio_file" = "Audio file";
|
||||
"lng_in_dlg_contact" = "Contact";
|
||||
"lng_in_dlg_audio" = "Audio";
|
||||
"lng_in_dlg_audio" = "Voice message";
|
||||
"lng_in_dlg_file" = "File";
|
||||
"lng_in_dlg_sticker" = "Sticker";
|
||||
"lng_in_dlg_sticker_emoji" = "{emoji} (sticker)";
|
||||
|
||||
"lng_ban_user" = "Ban User";
|
||||
"lng_delete_all_from" = "Delete all from this user";
|
||||
"lng_report_spam" = "Report Spam";
|
||||
"lng_report_spam_hide" = "Hide";
|
||||
"lng_report_spam_thanks" = "Thank you for your report!";
|
||||
|
@ -633,16 +685,23 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_report_spam_sure_group" = "Are you sure you want to report spam in this group?";
|
||||
"lng_report_spam_sure_channel" = "Are you sure you want to report spam in this channel?";
|
||||
"lng_report_spam_ok" = "Report";
|
||||
"lng_cant_send_to_not_contact" = "Sorry, you can only send messages to\nmutual contacts at the moment. {more_info}";
|
||||
"lng_cant_invite_not_contact" = "Sorry, you can only add mutual contacts\nto groups at the moment. {more_info}";
|
||||
"lng_cant_invite_not_contact_channel" = "Sorry, you can only add mutual contacts\nto channels at the moment. {more_info}";
|
||||
"lng_cant_send_to_not_contact" = "Sorry, you can only send messages to\nmutual contacts at the moment.\n{more_info}";
|
||||
"lng_cant_invite_not_contact" = "Sorry, you can only add mutual contacts\nto groups at the moment.\n{more_info}";
|
||||
"lng_cant_invite_not_contact_channel" = "Sorry, you can only add mutual contacts\nto channels at the moment.\n{more_info}";
|
||||
"lng_cant_more_info" = "More info »";
|
||||
"lng_cant_invite_banned" = "Sorry, only admin can add this user.";
|
||||
"lng_cant_invite_privacy" = "Sorry, you cannot add this user to groups because of the privacy settings.";
|
||||
"lng_cant_invite_privacy_channel" = "Sorry, you cannot add this user to channels because of the privacy settings.";
|
||||
"lng_cant_do_this" = "Sorry, this action is unavailable.";
|
||||
|
||||
"lng_send_button" = "Send";
|
||||
"lng_message_ph" = "Write a message..";
|
||||
"lng_comment_ph" = "Write a comment..";
|
||||
"lng_broadcast_ph" = "Broadcast a message..";
|
||||
"lng_message_ph" = "Write a message...";
|
||||
"lng_comment_ph" = "Write a comment...";
|
||||
"lng_broadcast_ph" = "Broadcast a message...";
|
||||
"lng_broadcast_silent_ph" = "Silent broadcast...";
|
||||
"lng_record_cancel" = "Release outside this field to cancel";
|
||||
"lng_will_be_notified" = "Members will be notified when you post";
|
||||
"lng_wont_be_notified" = "Members will not be notified when you post";
|
||||
"lng_empty_history" = "";
|
||||
"lng_willbe_history" = "Please select a chat to start messaging";
|
||||
"lng_message_with_from" = "[c]{from}:[/c] {message}";
|
||||
|
@ -667,28 +726,29 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_user_typing" = "{user} is typing";
|
||||
"lng_users_typing" = "{user} and {second_user} are typing";
|
||||
"lng_many_typing" = "{count:_not_used_|# is|# are} typing";
|
||||
"lng_send_action_record_video" = "recording video";
|
||||
"lng_user_action_record_video" = "{user} is recording video";
|
||||
"lng_send_action_upload_video" = "sending video";
|
||||
"lng_user_action_upload_video" = "{user} is sending video";
|
||||
"lng_send_action_record_audio" = "recording audio";
|
||||
"lng_user_action_record_audio" = "{user} is recording audio";
|
||||
"lng_send_action_upload_audio" = "sending audio";
|
||||
"lng_user_action_upload_audio" = "{user} is sending audio";
|
||||
"lng_send_action_upload_photo" = "sending photo";
|
||||
"lng_user_action_upload_photo" = "{user} is sending photo";
|
||||
"lng_send_action_upload_file" = "sending file";
|
||||
"lng_user_action_upload_file" = "{user} is sending file";
|
||||
"lng_send_action_geo_location" = "picking location";
|
||||
"lng_user_action_geo_location" = "{user} is picking location";
|
||||
"lng_send_action_choose_contact" = "choosing contact";
|
||||
"lng_user_action_choose_contact" = "{user} is choosing contact";
|
||||
"lng_send_action_record_video" = "recording a video";
|
||||
"lng_user_action_record_video" = "{user} is recording a video";
|
||||
"lng_send_action_upload_video" = "sending a video";
|
||||
"lng_user_action_upload_video" = "{user} is sending a video";
|
||||
"lng_send_action_record_audio" = "recording a voice message";
|
||||
"lng_user_action_record_audio" = "{user} is recording a voice message";
|
||||
"lng_send_action_upload_audio" = "sending a voice message";
|
||||
"lng_user_action_upload_audio" = "{user} is sending a voice message";
|
||||
"lng_send_action_upload_photo" = "sending a photo";
|
||||
"lng_user_action_upload_photo" = "{user} is sending a photo";
|
||||
"lng_send_action_upload_file" = "sending a file";
|
||||
"lng_user_action_upload_file" = "{user} is sending a file";
|
||||
"lng_send_action_geo_location" = "picking a location";
|
||||
"lng_user_action_geo_location" = "{user} is picking a location";
|
||||
"lng_send_action_choose_contact" = "choosing a contact";
|
||||
"lng_user_action_choose_contact" = "{user} is choosing a contact";
|
||||
"lng_unread_bar" = "{count:_not_used_|# unread message|# unread messages}";
|
||||
|
||||
"lng_maps_point" = "Location";
|
||||
"lng_save_photo" = "Save image";
|
||||
"lng_save_video" = "Save video";
|
||||
"lng_save_audio" = "Save audio";
|
||||
"lng_save_video" = "Save video file";
|
||||
"lng_save_audio_file" = "Save audio file";
|
||||
"lng_save_audio" = "Save voice message";
|
||||
"lng_save_file" = "Save file";
|
||||
"lng_save_downloaded" = "{ready} / {total} {mb}";
|
||||
"lng_duration_and_size" = "{duration}, {size}";
|
||||
|
@ -700,16 +760,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_context_view_group" = "View group info";
|
||||
"lng_context_view_channel" = "View channel info";
|
||||
|
||||
"lng_context_open_link" = "Open Link";
|
||||
"lng_context_copy_link" = "Copy Link";
|
||||
"lng_context_open_email" = "Write to this address";
|
||||
"lng_context_copy_post_link" = "Copy Post Link";
|
||||
"lng_context_copy_email" = "Copy email address";
|
||||
"lng_context_open_hashtag" = "Search by hashtag";
|
||||
"lng_context_copy_hashtag" = "Copy hashtag";
|
||||
"lng_context_open_mention" = "Open profile";
|
||||
"lng_context_copy_mention" = "Copy username";
|
||||
"lng_context_open_image" = "Open Image";
|
||||
"lng_context_save_image" = "Save Image As..";
|
||||
"lng_context_save_image" = "Save Image As...";
|
||||
"lng_context_forward_image" = "Forward Image";
|
||||
"lng_context_delete_image" = "Delete Image";
|
||||
"lng_context_copy_image" = "Copy Image";
|
||||
|
@ -717,14 +773,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_context_cancel_download" = "Cancel Download";
|
||||
"lng_context_show_in_folder" = "Show in Folder";
|
||||
"lng_context_show_in_finder" = "Show in Finder";
|
||||
"lng_context_open_video" = "Open Video";
|
||||
"lng_context_save_video" = "Save Video As..";
|
||||
"lng_context_open_audio" = "Open Audio";
|
||||
"lng_context_save_audio" = "Save Audio As..";
|
||||
"lng_context_save_video" = "Save Video File As...";
|
||||
"lng_context_save_audio_file" = "Save Audio File As...";
|
||||
"lng_context_save_audio" = "Save Voice Message As...";
|
||||
"lng_context_pack_info" = "Pack Info";
|
||||
"lng_context_pack_add" = "Add Stickers";
|
||||
"lng_context_open_file" = "Open File";
|
||||
"lng_context_save_file" = "Save File As..";
|
||||
"lng_context_save_file" = "Save File As...";
|
||||
"lng_context_forward_file" = "Forward File";
|
||||
"lng_context_delete_file" = "Delete File";
|
||||
"lng_context_close_file" = "Close File";
|
||||
|
@ -732,9 +786,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_context_save_gif" = "Save GIF";
|
||||
"lng_context_to_msg" = "Go To Message";
|
||||
"lng_context_reply_msg" = "Reply";
|
||||
"lng_context_edit_msg" = "Edit";
|
||||
"lng_context_forward_msg" = "Forward Message";
|
||||
"lng_context_delete_msg" = "Delete Message";
|
||||
"lng_context_select_msg" = "Select Message";
|
||||
"lng_context_pin_msg" = "Pin Message";
|
||||
"lng_context_unpin_msg" = "Unpin Message";
|
||||
"lng_context_cancel_upload" = "Cancel Upload";
|
||||
"lng_context_copy_selected" = "Copy Selected Text";
|
||||
"lng_context_forward_selected" = "Forward Selected";
|
||||
|
@ -748,7 +805,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_send_image_too_large" = "Could not send a file, because it is larger than 1.5 GB :(";
|
||||
"lng_send_folder" = "Could not send «{name}» because it is a directory :(";
|
||||
|
||||
"lng_forward_choose" = "Choose recipient..";
|
||||
"lng_forward_choose" = "Choose recipient...";
|
||||
"lng_forward_cant" = "Sorry, no way to forward here :(";
|
||||
"lng_forward_confirm" = "Forward to {recipient}?";
|
||||
"lng_forward_share_contact" = "Share contact to {recipient}?";
|
||||
|
@ -768,6 +825,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_edit_group_title" = "Edit group name";
|
||||
"lng_edit_contact_title" = "Edit contact name";
|
||||
"lng_edit_channel_title" = "Edit channel";
|
||||
"lng_edit_sign_messages" = "Sign messages";
|
||||
"lng_edit_group" = "Edit group";
|
||||
"lng_edit_self_title" = "Edit your name";
|
||||
"lng_confirm_contact_data" = "New Contact";
|
||||
|
@ -793,7 +851,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_selected_delete" = "Delete";
|
||||
"lng_selected_forward" = "Forward";
|
||||
"lng_selected_count" = "{count:_not_used_|# message|# messages}";
|
||||
"lng_selected_cancel_sure_this" = "Do you want to cancel this upload?";
|
||||
"lng_selected_cancel_sure_this" = "Cancel uploading?";
|
||||
"lng_selected_upload_stop" = "Stop";
|
||||
"lng_selected_delete_sure_this" = "Do you want to delete this message?";
|
||||
"lng_selected_delete_sure" = "Do you want to delete {count:_not_used_|# message|# messages}?";
|
||||
"lng_box_delete" = "Delete";
|
||||
|
@ -809,7 +868,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_search_global_results" = "Global search results";
|
||||
|
||||
"lng_media_save_progress" = "{ready} of {total} {mb}";
|
||||
"lng_mediaview_save_as" = "Save As..";
|
||||
"lng_mediaview_save_as" = "Save As...";
|
||||
"lng_mediaview_copy" = "Copy";
|
||||
"lng_mediaview_forward" = "Forward";
|
||||
"lng_mediaview_delete" = "Delete";
|
||||
|
@ -832,7 +891,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
||||
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
||||
"lng_new_version_text" = "GIF revolution: 10x faster sending and downloading, autoplay, save your favorite GIFs to a dedicated tab on the sticker panel.\n\nMore about GIFs:\n{gifs_link}\n\nInline bots: A new way to add bot content to any chat. Type a bot's username and your query in the text field to get instant results and send them to your chat partner. Try typing “@gif dog” in your next chat. Sample bots: @gif, @wiki, @bing, @vid, @bold.\n\nMore about inline bots:\n{bots_link}\n\nAlso in this release: New cute design for media, automatic download settings for photos, voice messages and GIFs.";
|
||||
"lng_new_version_text" = "— Visual improvements";
|
||||
|
||||
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
defaultFontFamily: 'Open Sans';
|
||||
semibold: 'Open Sans Semibold';
|
||||
|
@ -51,7 +51,10 @@ color7: #2996ad; // sea
|
|||
color8: #ce671b; // orange
|
||||
|
||||
wndMinWidth: 380px;
|
||||
wideModeWidth: 640px;
|
||||
|
||||
adaptiveNormalWidth: 640px;
|
||||
adaptiveWideWidth: 1366px;
|
||||
|
||||
wndMinHeight: 480px;
|
||||
wndDefWidth: 800px;
|
||||
wndDefHeight: 600px;
|
||||
|
@ -64,6 +67,13 @@ layerBg: black;
|
|||
|
||||
overBg: #edf2f5;
|
||||
|
||||
labelDefFlat: flatLabel {
|
||||
font: font(fsize);
|
||||
minWidth: 100px;
|
||||
width: 0px;
|
||||
align: align(left);
|
||||
}
|
||||
|
||||
boxBg: white;
|
||||
boxVerticalMargin: 10px;
|
||||
boxWidth: 320px;
|
||||
|
@ -72,6 +82,8 @@ boxPadding: margins(26px, 30px, 34px, 8px);
|
|||
boxMaxListHeight: 600px;
|
||||
boxFontSize: 14px;
|
||||
boxTextFont: font(boxFontSize);
|
||||
boxLittleSkip: 10px;
|
||||
boxMediumSkip: 20px;
|
||||
|
||||
boxTitleFg: #444444;
|
||||
boxTitleFont: font(boxFontSize bold);
|
||||
|
@ -123,6 +135,10 @@ redBoxLinkButton: linkButton(defaultBoxLinkButton) {
|
|||
overColor: #d15948;
|
||||
downColor: #db6352;
|
||||
}
|
||||
boxLabel: flatLabel(labelDefFlat) {
|
||||
font: font(boxFontSize);
|
||||
align: align(topleft);
|
||||
}
|
||||
|
||||
defaultInputArea: InputArea {
|
||||
textFg: black;
|
||||
|
@ -269,6 +285,21 @@ defaultPopupMenu: PopupMenu {
|
|||
widthMin: 180px;
|
||||
widthMax: 300px;
|
||||
}
|
||||
|
||||
defaultTooltip: Tooltip {
|
||||
textBg: #eef2f5;
|
||||
textFg: #5d6c80;
|
||||
textFont: normalFont;
|
||||
textBorder: #c9d1db;
|
||||
textPadding: margins(5px, 2px, 5px, 2px);
|
||||
|
||||
shift: point(-20px, 20px);
|
||||
skip: 10px;
|
||||
|
||||
widthMax: 800px;
|
||||
linesMax: 12;
|
||||
}
|
||||
|
||||
almostTransparent: #ffffff0d;
|
||||
boxScroll: flatScroll(solidScroll) {
|
||||
width: 18px;
|
||||
|
@ -593,13 +624,6 @@ scrollCountries: flatScroll(scrollDef) {
|
|||
|
||||
lnkText: #0f7dc7;
|
||||
|
||||
labelDefFlat: flatLabel {
|
||||
font: font(fsize);
|
||||
minWidth: 100px;
|
||||
width: 0px;
|
||||
align: align(left);
|
||||
}
|
||||
|
||||
introBtnTop: 288px;
|
||||
introSkip: 45px;
|
||||
introFinishSkip: 15px;
|
||||
|
@ -937,6 +961,7 @@ dlgActiveUnreadColor: #5b94bf;
|
|||
dlgActiveUnreadBG: white;
|
||||
dlgActiveColor: white;
|
||||
dlgActiveDateColor: #d3e2ee;
|
||||
dlgActiveUnreadMutedBG: dlgActiveDateColor;
|
||||
|
||||
topBarHeight: 54px;
|
||||
topBarBG: white;
|
||||
|
@ -950,6 +975,21 @@ topBarBackAlpha: 0.8;
|
|||
topBarBackImg: sprite(65px, 112px, 9px, 16px);
|
||||
topBarBackColor: #005faf;
|
||||
topBarBackFont: font(16px);
|
||||
topBarSearch: iconedButton(btnDefIconed) {
|
||||
bgColor: transparent;
|
||||
overBgColor: transparent;
|
||||
|
||||
icon: sprite(84px, 374px, 18px, 18px);
|
||||
iconPos: point(13px, 18px);
|
||||
downIcon: sprite(84px, 374px, 18px, 18px);
|
||||
downIconPos: point(13px, 18px);
|
||||
|
||||
opacity: 0.22;
|
||||
overOpacity: 0.36;
|
||||
|
||||
width: 44px;
|
||||
height: topBarHeight;
|
||||
}
|
||||
topBarMinPadding: 5px;
|
||||
topBarButton: flatButton(btnDefFlat) {
|
||||
color: btnYesColor;
|
||||
|
@ -1009,10 +1049,11 @@ msgServiceNameFont: semiboldFont;
|
|||
msgServicePhotoWidth: 100px;
|
||||
msgDateFont: font(13px);
|
||||
msgMinWidth: 190px;
|
||||
msgPhotoSize: 30px;
|
||||
msgPhotoSize: 33px;
|
||||
msgPhotoSkip: 40px;
|
||||
msgPadding: margins(13px, 7px, 13px, 8px);
|
||||
msgMargin: margins(13px, 4px, 53px, 4px);
|
||||
msgMargin: margins(13px, 10px, 53px, 2px);
|
||||
msgMarginTopAttached: 3px;
|
||||
msgLnkPadding: 2px; // for media open / save links
|
||||
msgBorder: #f0f0f0;
|
||||
msgInBg: #fff;
|
||||
|
@ -1044,11 +1085,27 @@ msgInReplyBarColor: #2fa9e2;
|
|||
msgOutReplyBarSelColor: #4da79f;
|
||||
msgInReplyBarSelColor: #2fa9e2;
|
||||
|
||||
msgBotKbDuration: 200;
|
||||
msgBotKbFont: semiboldFont;
|
||||
msgBotKbOverOpacity: 0.1;
|
||||
msgBotKbIconPadding: 2px;
|
||||
msgBotKbUrlIcon: sprite(188px, 338px, 10px, 10px);
|
||||
msgBotKbCallbackIcon: msgBotKbUrlIcon;
|
||||
msgBotKbRequestPhoneIcon: msgBotKbUrlIcon;
|
||||
msgBotKbRequestLocationIcon: msgBotKbUrlIcon;
|
||||
msgBotKbButton: botKeyboardButton {
|
||||
margin: 5px;
|
||||
padding: 10px;
|
||||
height: 36px;
|
||||
textTop: 8px;
|
||||
downTextTop: 9px;
|
||||
}
|
||||
|
||||
msgServiceBg: #89a0b47f;
|
||||
msgServiceSelectBg: #bbc8d4a2;
|
||||
msgServiceColor: #FFF;
|
||||
msgServicePadding: margins(12px, 3px, 12px, 4px);
|
||||
msgServiceMargin: margins(10px, 7px, 80px, 7px);
|
||||
msgServiceMargin: margins(10px, 10px, 80px, 2px);
|
||||
|
||||
msgColor: #000;
|
||||
msgDateColor: #000;
|
||||
|
@ -1107,7 +1164,7 @@ collapseButton: flatButton(btnDefFlat) {
|
|||
textTop: 3px;
|
||||
overTextTop: 3px;
|
||||
downTextTop: 3px;
|
||||
height: 24px;
|
||||
height: 25px;
|
||||
}
|
||||
collapseHideDuration: 200;
|
||||
collapseShowDuration: 200;
|
||||
|
@ -1144,6 +1201,24 @@ outTextStyle: textStyle(defaultTextStyle) {
|
|||
selectBg: msgOutBgSelected;
|
||||
selectOverlay: msgSelectOverlay;
|
||||
}
|
||||
inFwdTextStyle: textStyle(defaultTextStyle) {
|
||||
linkFlags: semiboldFont;
|
||||
linkFlagsOver: semiboldFont;
|
||||
linkFg: msgInServiceFg;
|
||||
linkFgDown: msgInServiceFg;
|
||||
}
|
||||
outFwdTextStyle: textStyle(inFwdTextStyle) {
|
||||
linkFg: msgOutServiceFg;
|
||||
linkFgDown: msgOutServiceFg;
|
||||
}
|
||||
inFwdTextStyleSelected: textStyle(inFwdTextStyle) {
|
||||
linkFg: msgInServiceFgSelected;
|
||||
linkFgDown: msgInServiceFgSelected;
|
||||
}
|
||||
outFwdTextStyleSelected: textStyle(inFwdTextStyle) {
|
||||
linkFg: msgOutServiceFgSelected;
|
||||
linkFgDown: msgOutServiceFgSelected;
|
||||
}
|
||||
medviewSaveAsTextStyle: textStyle(defaultTextStyle) {
|
||||
linkFg: #91d9ff;
|
||||
linkFgDown: #91d9ff;
|
||||
|
@ -1265,11 +1340,21 @@ msgFileBlue: sprite(60px, 425px, 20px, 20px);
|
|||
msgFileOverDuration: 200;
|
||||
msgFileRadialLine: 3px;
|
||||
|
||||
msgFileExtPadding: 8px;
|
||||
msgFileExtTop: 30px;
|
||||
|
||||
msgVideoSize: size(320px, 240px);
|
||||
|
||||
msgWaveformBar: 2px;
|
||||
msgWaveformSkip: 1px;
|
||||
msgWaveformMin: 2px;
|
||||
msgWaveformMax: 20px;
|
||||
msgWaveformInActive: #59b6eb;
|
||||
msgWaveformInActiveSelected: #51a3d3;
|
||||
msgWaveformInInactive: #d4dee6;
|
||||
msgWaveformInInactiveSelected: #9cc1e1;
|
||||
msgWaveformOutActive: #78c67f;
|
||||
msgWaveformOutActiveSelected: #6badad;
|
||||
msgWaveformOutInactive: #b3e2b4;
|
||||
msgWaveformOutInactiveSelected: #91c3c3;
|
||||
|
||||
sendPadding: 9px;
|
||||
btnSend: flatButton(btnDefFlat) {
|
||||
color: btnYesColor;
|
||||
|
@ -1349,7 +1434,7 @@ broadcastToggle: flatCheckbox {
|
|||
bgColor: white;
|
||||
disColor: black;
|
||||
|
||||
width: 36px;
|
||||
width: 34px;
|
||||
height: 46px;
|
||||
duration: 200;
|
||||
bgFunc: transition(easeOutCirc);
|
||||
|
@ -1364,13 +1449,23 @@ broadcastToggle: flatCheckbox {
|
|||
disImageRect: sprite(18px, 125px, 22px, 21px);
|
||||
chkDisImageRect: sprite(18px, 125px, 22px, 21px);
|
||||
|
||||
imagePos: point(7px, 12px);
|
||||
imagePos: point(6px, 12px);
|
||||
}
|
||||
silentToggle: flatCheckbox(broadcastToggle) {
|
||||
width: 33px;
|
||||
|
||||
imageRect: sprite(354px, 242px, 21px, 21px);
|
||||
chkImageRect: sprite(354px, 221px, 21px, 21px);
|
||||
overImageRect: sprite(375px, 242px, 21px, 21px);
|
||||
chkOverImageRect: sprite(375px, 221px, 21px, 21px);
|
||||
disImageRect: sprite(354px, 242px, 21px, 21px);
|
||||
chkDisImageRect: sprite(354px, 221px, 21px, 21px);
|
||||
}
|
||||
btnRecordAudio: sprite(379px, 390px, 16px, 24px);
|
||||
btnRecordAudioActive: sprite(379px, 366px, 16px, 24px);
|
||||
recordSignalColor: #f17077;
|
||||
recordSignalMin: 5px;
|
||||
recordSignalMax: 10px;
|
||||
recordSignalMax: 12px;
|
||||
recordCancel: #aaa;
|
||||
recordCancelActive: #ec6466;
|
||||
recordFont: font(13px);
|
||||
|
@ -1383,6 +1478,7 @@ replyTop: 8px;
|
|||
replyBottom: 6px;
|
||||
replyIconPos: point(13px, 13px);
|
||||
replyIcon: sprite(343px, 197px, 24px, 24px);
|
||||
editIcon: sprite(371px, 286px, 24px, 24px);
|
||||
replyCancel: iconedButton(btnDefIconed) {
|
||||
icon: sprite(165px, 24px, 14px, 14px);
|
||||
iconPos: point(17px, 17px);
|
||||
|
@ -1447,6 +1543,7 @@ reportSpamBg: #fffffff0;
|
|||
newMsgSound: ':/gui/art/newmsg.wav';
|
||||
|
||||
unreadBarHeight: 32px;
|
||||
unreadBarMargin: 8px;
|
||||
unreadBarFont: semiboldFont;
|
||||
unreadBarBG: #fcfbfa;
|
||||
unreadBarBorder: shadowColor;
|
||||
|
@ -2017,17 +2114,17 @@ verifiedCheckInv: sprite(299px, 221px, 14px, 14px);
|
|||
verifiedCheckPos: point(4px, 2px);
|
||||
|
||||
botKbDuration: 200;
|
||||
botKbBg: #f7f7f7;
|
||||
botKbOverBg: #e8ecef;
|
||||
botKbDownBg: #dfe3e6;
|
||||
botKbColor: #8a8a8f;
|
||||
botKbFont: font(16px);
|
||||
botKbBg: #edf1f5;
|
||||
botKbOverBg: #d8e2ec;
|
||||
botKbDownBg: #d8e2ec;
|
||||
botKbColor: #4b565f;
|
||||
botKbFont: font(15px semibold);
|
||||
botKbButton: botKeyboardButton {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
height: 36px;
|
||||
textTop: 8px;
|
||||
downTextTop: 9px;
|
||||
height: 38px;
|
||||
textTop: 9px;
|
||||
downTextTop: 10px;
|
||||
}
|
||||
botKbTinyButton: botKeyboardButton {
|
||||
margin: 4px;
|
||||
|
@ -2045,6 +2142,7 @@ minPhotoSize: 100px;
|
|||
maxMediaSize: 420px;
|
||||
maxStickerSize: 256px;
|
||||
maxGifSize: 320px;
|
||||
maxSignatureSize: 144px;
|
||||
|
||||
mvBgColor: #222;
|
||||
mvBgOpacity: 0.92;
|
||||
|
@ -2180,6 +2278,9 @@ overviewFileStatusTop: 27px;
|
|||
overviewFileDateTop: 49px;
|
||||
overviewFileChecked: #2fa9e2;
|
||||
overviewFileCheck: #00000066;
|
||||
overviewFileExtPadding: 5px;
|
||||
overviewFileExtTop: 24px;
|
||||
overviewFileExtFont: font(18px semibold);
|
||||
|
||||
// Mac specific
|
||||
|
||||
|
@ -2376,7 +2477,7 @@ linksDateMargin: margins(0px, 15px, 0px, 2px);
|
|||
linksPhotoCheck: sprite(184px, 196px, 16px, 16px);
|
||||
linksPhotoChecked: sprite(168px, 196px, 16px, 16px);
|
||||
|
||||
inlineResultsLeft: 15px;
|
||||
inlineResultsLeft: 11px;
|
||||
inlineResultsSkip: 3px;
|
||||
inlineMediaHeight: 96px;
|
||||
inlineThumbSize: 64px;
|
||||
|
@ -2385,5 +2486,12 @@ inlineDescriptionFg: #8a8a8a;
|
|||
inlineRowMargin: 6px;
|
||||
inlineRowBorder: linksBorder;
|
||||
inlineRowBorderFg: linksBorderFg;
|
||||
inlineRowFileNameTop: 2px;
|
||||
inlineRowFileDescriptionTop: 23px;
|
||||
inlineResultsMinWidth: 64px;
|
||||
inlineDurationMargin: 3px;
|
||||
|
||||
editTextArea: InputArea(defaultInputArea) {
|
||||
textMargins: margins(1px, 6px, 1px, 4px);
|
||||
heightMax: 256px;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
textStyle {
|
||||
linkFlags: font;
|
||||
|
@ -272,6 +272,20 @@ PopupMenu {
|
|||
widthMax: number;
|
||||
}
|
||||
|
||||
Tooltip {
|
||||
textBg: color;
|
||||
textFg: color;
|
||||
textFont: font;
|
||||
textBorder: color;
|
||||
textPadding: margins;
|
||||
|
||||
shift: point;
|
||||
skip: number;
|
||||
|
||||
widthMax: number;
|
||||
linesMax: number;
|
||||
}
|
||||
|
||||
botKeyboardButton {
|
||||
margin: number;
|
||||
padding: number;
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "genemoji.h"
|
||||
|
||||
|
@ -1942,7 +1942,7 @@ In addition, as a special exception, the copyright holders give permission\n\
|
|||
to link the code of portions of this program with the OpenSSL library.\n\
|
||||
\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tcpp << "#include \"stdafx.h\"\n#include \"gui/emoji_config.h\"\n\n";
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVector>
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "genlang.h"
|
||||
|
||||
|
@ -391,7 +391,7 @@ bool genLang(const QString &lang_in, const QString &lang_out) {
|
|||
th.setCodec("ISO 8859-1");
|
||||
th << "\
|
||||
/*\n\
|
||||
Created from \'/Resources/lang.txt\' by \'/MetaLang\' project\n\
|
||||
Created from \'/Resources/lang.strings\' by \'/MetaLang\' project\n\
|
||||
\n\
|
||||
WARNING! All changes made in this file will be lost!\n\
|
||||
\n\
|
||||
|
@ -412,7 +412,7 @@ In addition, as a special exception, the copyright holders give permission\n\
|
|||
to link the code of portions of this program with the OpenSSL library.\n\
|
||||
\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
th << "#pragma once\n\n";
|
||||
|
||||
|
@ -475,7 +475,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
|||
|
||||
tcpp << "\
|
||||
/*\n\
|
||||
Created from \'/Resources/lang.txt\' by \'/MetaLang\' project\n\
|
||||
Created from \'/Resources/lang.strings\' by \'/MetaLang\' project\n\
|
||||
\n\
|
||||
WARNING! All changes made in this file will be lost!\n\
|
||||
\n\
|
||||
|
@ -496,7 +496,7 @@ In addition, as a special exception, the copyright holders give permission\n\
|
|||
to link the code of portions of this program with the OpenSSL library.\n\
|
||||
\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tcpp << "#include \"stdafx.h\"\n#include \"lang.h\"\n\n";
|
||||
tcpp << "namespace {\n";
|
||||
|
@ -606,13 +606,22 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
|||
++depth;
|
||||
current += ich;
|
||||
|
||||
if (tag == current) {
|
||||
bool exact = (tag == current);
|
||||
if (exact) {
|
||||
tcpp << tab.repeated(depth + 1) << "if (ch + " << depth << " == e) {\n";
|
||||
tcpp << tab.repeated(depth + 1) << "\treturn lt_" << tag << ";\n";
|
||||
tcpp << tab.repeated(depth + 1) << "}\n";
|
||||
}
|
||||
|
||||
tcpp << tab.repeated(depth + 1) << "if (ch + " << depth << " < e) switch (*(ch + " << depth << ")) {\n";
|
||||
QByteArray nexttag = j.key();
|
||||
if (exact && depth > 0 && nexttag.mid(0, depth) != current) {
|
||||
current.chop(1);
|
||||
--depth;
|
||||
tcpp << tab.repeated(depth + 1) << "break;\n";
|
||||
break;
|
||||
} else {
|
||||
tcpp << tab.repeated(depth + 1) << "if (ch + " << depth << " < e) switch (*(ch + " << depth << ")) {\n";
|
||||
}
|
||||
} while (true);
|
||||
++j;
|
||||
}
|
||||
|
@ -637,7 +646,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
|||
tcpp << "\tswitch (*(ch + " << depth << ")) {\n";
|
||||
for (LangKeys::const_iterator i = keys.cbegin(), j = i + 1, e = keys.cend(); i != e; ++i) {
|
||||
QByteArray key = i.key();
|
||||
while (key.mid(0, depth) != current) {
|
||||
while (depth > 0 && key.mid(0, depth) != current) {
|
||||
tcpp << tab.repeated(depth - 3) << "}\n";
|
||||
current.chop(1);
|
||||
--depth;
|
||||
|
@ -661,13 +670,22 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
|||
++depth;
|
||||
current += ich;
|
||||
|
||||
if (key == current) {
|
||||
bool exact = (key == current);
|
||||
if (exact) {
|
||||
tcpp << tab.repeated(depth - 3) << "if (ch + " << depth << " == e) {\n";
|
||||
tcpp << tab.repeated(depth - 3) << "\treturn " << key << (keysTags[key].isEmpty() ? "" : "__tagged") << ";\n";
|
||||
tcpp << tab.repeated(depth - 3) << "}\n";
|
||||
}
|
||||
|
||||
tcpp << tab.repeated(depth - 3) << "if (ch + " << depth << " < e) switch (*(ch + " << depth << ")) {\n";
|
||||
QByteArray nextkey = j.key();
|
||||
if (exact && depth > 0 && nextkey.mid(0, depth) != current) {
|
||||
current.chop(1);
|
||||
--depth;
|
||||
tcpp << tab.repeated(depth - 3) << "break;\n";
|
||||
break;
|
||||
} else {
|
||||
tcpp << tab.repeated(depth - 3) << "if (ch + " << depth << " < e) switch (*(ch + " << depth << ")) {\n";
|
||||
}
|
||||
} while (true);
|
||||
++j;
|
||||
}
|
||||
|
@ -707,16 +725,25 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
|||
tcpp << "\tif (index >= lngtags_max_counted_values) return lngkeys_cnt;\n\n";
|
||||
if (!tags.isEmpty()) {
|
||||
tcpp << "\tswitch (key) {\n";
|
||||
for (int i = 0, l = keysOrder.size(); i < l; ++i) {
|
||||
QVector<QByteArray> &tagsList(keysTags[keysOrder[i]]);
|
||||
for (auto key : keysOrder) {
|
||||
QVector<QByteArray> &tagsList(keysTags[key]);
|
||||
if (tagsList.isEmpty()) continue;
|
||||
|
||||
QMap<QByteArray, QVector<QString> > &countedTags(keysCounted[keysOrder[i]]);
|
||||
tcpp << "\tcase " << keysOrder[i] << "__tagged: {\n";
|
||||
QMap<QByteArray, QVector<QString> > &countedTags(keysCounted[key]);
|
||||
bool hasCounted = false;
|
||||
for (auto tag : tagsList) {
|
||||
if (!countedTags[tag].isEmpty()) {
|
||||
hasCounted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasCounted) continue;
|
||||
|
||||
tcpp << "\tcase " << key << "__tagged: {\n";
|
||||
tcpp << "\t\tswitch (tag) {\n";
|
||||
for (int j = 0, s = tagsList.size(); j < s; ++j) {
|
||||
if (!countedTags[tagsList[j]].isEmpty()) {
|
||||
tcpp << "\t\tcase lt_" << tagsList[j] << ": return LangKey(" << keysOrder[i] << "__" << tagsList[j] << "0 + index);\n";
|
||||
for (auto tag : tagsList) {
|
||||
if (!countedTags[tag].isEmpty()) {
|
||||
tcpp << "\t\tcase lt_" << tag << ": return LangKey(" << key << "__" << tag << "0 + index);\n";
|
||||
}
|
||||
}
|
||||
tcpp << "\t\t}\n";
|
||||
|
@ -724,7 +751,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
|||
}
|
||||
tcpp << "\t}\n\n";
|
||||
}
|
||||
tcpp << "\treturn lngkeys_cnt;";
|
||||
tcpp << "\treturn lngkeys_cnt;\n";
|
||||
tcpp << "}\n\n";
|
||||
|
||||
tcpp << "bool LangLoader::feedKeyValue(LangKey key, const QString &value) {\n";
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVector>
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "genstyles.h"
|
||||
|
||||
|
@ -381,9 +381,9 @@ In addition, as a special exception, the copyright holders give permission\n\
|
|||
to link the code of portions of this program with the OpenSSL library.\n\
|
||||
\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tout << "#pragma once\n\n#include \"style.h\"\n\nnamespace style {\n";
|
||||
tout << "#pragma once\n\n#include \"gui/style.h\"\n\nnamespace style {\n";
|
||||
for (int i = 0, l = byIndex.size(); i < l; ++i) {
|
||||
ClassData &cls(byIndex[i]);
|
||||
classes.insert(cls.name, cls);
|
||||
|
@ -1542,9 +1542,9 @@ In addition, as a special exception, the copyright holders give permission\n\
|
|||
to link the code of portions of this program with the OpenSSL library.\n\
|
||||
\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tout << "#pragma once\n\n#include \"style.h\"\n\nnamespace st {\n";
|
||||
tout << "#pragma once\n\n#include \"gui/style.h\"\n\nnamespace st {\n";
|
||||
tcpp << "\
|
||||
/*\n\
|
||||
Created from \'/Resources/style.txt\' by \'/MetaStyle\' project\n\
|
||||
|
@ -1568,7 +1568,7 @@ In addition, as a special exception, the copyright holders give permission\n\
|
|||
to link the code of portions of this program with the OpenSSL library.\n\
|
||||
\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tcpp << "#include \"stdafx.h\"\n#include \"style_auto.h\"\n\nnamespace {\n";
|
||||
for (int i = 0, l = scalars.size(); i < l; ++i) {
|
||||
|
@ -1945,7 +1945,7 @@ In addition, as a special exception, the copyright holders give permission\n\
|
|||
to link the code of portions of this program with the OpenSSL library.\n\
|
||||
\n\
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org\n\
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org\n\
|
||||
*/\n";
|
||||
tnum << "#include \"stdafx.h\"\n#include \"numbers.h\"\n\n";
|
||||
tnum << "QVector<int> phoneNumberParse(const QString &number) {\n";
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVector>
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "memain.h"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "mlmain.h"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "msmain.h"
|
||||
#include <QtCore/QDir>
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "packer.h"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "updater.h"
|
||||
|
||||
|
@ -255,7 +255,7 @@ bool update() {
|
|||
} else {
|
||||
break;
|
||||
}
|
||||
} while (copyTries < 30);
|
||||
} while (copyTries < 100);
|
||||
if (!copyResult) {
|
||||
writeLog(L"Error: failed to copy, asking to retry..");
|
||||
WCHAR errMsg[2048];
|
||||
|
@ -328,14 +328,11 @@ void updateRegistry() {
|
|||
}
|
||||
}
|
||||
|
||||
#include <ShlObj.h>
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) {
|
||||
openLog();
|
||||
|
||||
#ifdef _NEED_WIN_GENERATE_DUMP
|
||||
_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
|
||||
#endif
|
||||
// CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter);
|
||||
|
||||
writeLog(L"Updaters started..");
|
||||
|
||||
|
@ -459,13 +456,12 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
|
|||
ShellExecute(0, 0, (updateTo + L"Telegram.exe").c_str(), (L"-noupdate" + targs).c_str(), 0, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
writeLog(L"Executed Telegram.exe, closing log and quiting..");
|
||||
writeLog(L"Executed Telegram.exe, closing log and quitting..");
|
||||
closeLog();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _NEED_WIN_GENERATE_DUMP
|
||||
static const WCHAR *_programName = L"Telegram Desktop"; // folder in APPDATA, if current path is unavailable for writing
|
||||
static const WCHAR *_exeName = L"Updater.exe";
|
||||
|
||||
|
@ -486,13 +482,18 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
|||
static const int maxFileLen = MAX_PATH * 10;
|
||||
|
||||
WCHAR szPath[maxFileLen];
|
||||
wsprintf(szPath, L"%stdumps\\", path);
|
||||
|
||||
wsprintf(szPath, L"%stdata\\", path);
|
||||
if (!CreateDirectory(szPath, NULL)) {
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
wsprintf(szPath, L"%sdumps\\", path);
|
||||
if (!CreateDirectory(szPath, NULL)) {
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WCHAR szFileName[maxFileLen];
|
||||
WCHAR szExeName[maxFileLen];
|
||||
|
@ -564,4 +565,10 @@ LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) {
|
|||
return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
#endif
|
||||
// see http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) {
|
||||
// When the CRT calls SetUnhandledExceptionFilter with NULL parameter
|
||||
// our handler will not get removed.
|
||||
_oldWndExceptionFilter = lpTopLevelExceptionFilter;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,13 +16,19 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4091)
|
||||
#include <DbgHelp.h>
|
||||
#include <ShlObj.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <Shellapi.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
|
@ -32,12 +38,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
using std::deque;
|
||||
using std::wstring;
|
||||
|
||||
#define _NEED_WIN_GENERATE_DUMP
|
||||
|
||||
#ifdef _NEED_WIN_GENERATE_DUMP
|
||||
extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
|
||||
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
||||
#endif _NEED_WIN_GENERATE_DUMP
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||
|
||||
static int updaterVersion = 1000;
|
||||
static const WCHAR *updaterVersionStr = L"0.1.0";
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
|
@ -324,7 +324,7 @@ bool update() {
|
|||
int main(int argc, char *argv[]) {
|
||||
bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false, testmode = false;
|
||||
|
||||
char *key = 0;
|
||||
char *key = 0, *crashreport = 0;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (equal(argv[i], "-noupdate")) {
|
||||
needupdate = false;
|
||||
|
@ -342,7 +342,9 @@ int main(int argc, char *argv[]) {
|
|||
key = argv[i];
|
||||
} else if (equal(argv[i], "-workpath") && ++i < argc) {
|
||||
workDir = argv[i];
|
||||
}
|
||||
} else if (equal(argv[i], "-crashreport") && ++i < argc) {
|
||||
crashreport = argv[i];
|
||||
}
|
||||
}
|
||||
openLog();
|
||||
|
||||
|
@ -408,24 +410,27 @@ int main(int argc, char *argv[]) {
|
|||
char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_startintray[] = "-startintray", p_testmode[] = "-testmode";
|
||||
int argIndex = 0;
|
||||
args[argIndex++] = path;
|
||||
args[argIndex++] = p_noupdate;
|
||||
if (autostart) args[argIndex++] = p_autostart;
|
||||
if (debug) args[argIndex++] = p_debug;
|
||||
if (startintray) args[argIndex++] = p_startintray;
|
||||
if (testmode) args[argIndex++] = p_testmode;
|
||||
if (tosettings) args[argIndex++] = p_tosettings;
|
||||
if (key) {
|
||||
args[argIndex++] = p_key;
|
||||
args[argIndex++] = key;
|
||||
}
|
||||
|
||||
if (crashreport) {
|
||||
args[argIndex++] = crashreport;
|
||||
} else {
|
||||
args[argIndex++] = p_noupdate;
|
||||
if (autostart) args[argIndex++] = p_autostart;
|
||||
if (debug) args[argIndex++] = p_debug;
|
||||
if (startintray) args[argIndex++] = p_startintray;
|
||||
if (testmode) args[argIndex++] = p_testmode;
|
||||
if (tosettings) args[argIndex++] = p_tosettings;
|
||||
if (key) {
|
||||
args[argIndex++] = p_key;
|
||||
args[argIndex++] = key;
|
||||
}
|
||||
}
|
||||
pid_t pid = fork();
|
||||
switch (pid) {
|
||||
case -1: writeLog("fork() failed!"); return 1;
|
||||
case 0: execv(path, args); return 1;
|
||||
}
|
||||
|
||||
writeLog("Executed Telegram, closing log and quiting..");
|
||||
writeLog("Executed Telegram, closing log and quitting..");
|
||||
closeLog();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -16,13 +16,14 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
NSString *appName = @"Telegram.app";
|
||||
NSString *appDir = nil;
|
||||
NSString *workDir = nil;
|
||||
NSString *crashReportArg = nil;
|
||||
|
||||
#ifdef _DEBUG
|
||||
BOOL _debug = YES;
|
||||
|
@ -101,6 +102,10 @@ int main(int argc, const char * argv[]) {
|
|||
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
|
||||
procId = [[formatter numberFromString:[NSString stringWithUTF8String:argv[i]]] intValue];
|
||||
}
|
||||
} else if ([@"-crashreport" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
if (++i < argc) {
|
||||
crashReportArg = [NSString stringWithUTF8String:argv[i]];
|
||||
}
|
||||
} else if ([@"-noupdate" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
update = NO;
|
||||
} else if ([@"-tosettings" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
|
@ -214,15 +219,17 @@ int main(int argc, const char * argv[]) {
|
|||
}
|
||||
|
||||
NSString *appPath = [[NSArray arrayWithObjects:appDir, appRealName, nil] componentsJoinedByString:@""];
|
||||
NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:@"-noupdate", nil];
|
||||
if (toSettings) [args addObject:@"-tosettings"];
|
||||
if (_debug) [args addObject:@"-debug"];
|
||||
if (startInTray) [args addObject:@"-startintray"];
|
||||
if (testMode) [args addObject:@"-testmode"];
|
||||
if (autoStart) [args addObject:@"-autostart"];
|
||||
if (key) {
|
||||
[args addObject:@"-key"];
|
||||
[args addObject:key];
|
||||
NSMutableArray *args = [[NSMutableArray alloc] initWithObjects: crashReportArg ? crashReportArg : @"-noupdate", nil];
|
||||
if (!crashReportArg) {
|
||||
if (toSettings) [args addObject:@"-tosettings"];
|
||||
if (_debug) [args addObject:@"-debug"];
|
||||
if (startInTray) [args addObject:@"-startintray"];
|
||||
if (testMode) [args addObject:@"-testmode"];
|
||||
if (autoStart) [args addObject:@"-autostart"];
|
||||
if (key) {
|
||||
[args addObject:@"-key"];
|
||||
[args addObject:key];
|
||||
}
|
||||
}
|
||||
writeLog([[NSArray arrayWithObjects:@"Running application '", appPath, @"' with args '", [args componentsJoinedByString:@"' '"], @"'..", nil] componentsJoinedByString:@""]);
|
||||
NSError *error = nil;
|
||||
|
|
|
@ -16,10 +16,10 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "style.h"
|
||||
#include "gui/style.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "application.h"
|
||||
|
@ -29,89 +29,65 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "localstorage.h"
|
||||
|
||||
ApiWrap::ApiWrap(QObject *parent) : QObject(parent) {
|
||||
ApiWrap::ApiWrap(QObject *parent) : QObject(parent)
|
||||
, _messageDataResolveDelayed(new SingleDelayedCall(this, "resolveMessageDatas")) {
|
||||
App::initBackground();
|
||||
|
||||
connect(&_replyToTimer, SIGNAL(timeout()), this, SLOT(resolveReplyTo()));
|
||||
connect(&_webPagesTimer, SIGNAL(timeout()), this, SLOT(resolveWebPages()));
|
||||
}
|
||||
|
||||
void ApiWrap::init() {
|
||||
}
|
||||
|
||||
void ApiWrap::itemRemoved(HistoryItem *item) {
|
||||
if (HistoryReply *reply = item->toHistoryReply()) {
|
||||
ChannelData *channel = reply->history()->peer->asChannel();
|
||||
ReplyToRequests *requests(replyToRequests(channel, true));
|
||||
if (requests) {
|
||||
ReplyToRequests::iterator i = requests->find(reply->replyToId());
|
||||
if (i != requests->cend()) {
|
||||
for (QList<HistoryReply*>::iterator j = i->replies.begin(); j != i->replies.end();) {
|
||||
if ((*j) == reply) {
|
||||
j = i->replies.erase(j);
|
||||
} else {
|
||||
++j;
|
||||
}
|
||||
}
|
||||
if (i->replies.isEmpty()) {
|
||||
requests->erase(i);
|
||||
}
|
||||
}
|
||||
if (channel && requests->isEmpty()) {
|
||||
_channelReplyToRequests.remove(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ApiWrap::requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback *callback) {
|
||||
MessageDataRequest::CallbackPtr pcallback(callback);
|
||||
MessageDataRequest &req(channel ? _channelMessageDataRequests[channel][msgId] : _messageDataRequests[msgId]);
|
||||
req.callbacks.append(pcallback);
|
||||
if (!req.req) _messageDataResolveDelayed->call();
|
||||
}
|
||||
|
||||
void ApiWrap::requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id) {
|
||||
ReplyToRequest &req(channel ? _channelReplyToRequests[channel][id] : _replyToRequests[id]);
|
||||
req.replies.append(reply);
|
||||
if (!req.req) _replyToTimer.start(1);
|
||||
}
|
||||
|
||||
ApiWrap::MessageIds ApiWrap::collectMessageIds(const ReplyToRequests &requests) {
|
||||
ApiWrap::MessageIds ApiWrap::collectMessageIds(const MessageDataRequests &requests) {
|
||||
MessageIds result;
|
||||
result.reserve(requests.size());
|
||||
for (ReplyToRequests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) {
|
||||
for (MessageDataRequests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) {
|
||||
if (i.value().req > 0) continue;
|
||||
result.push_back(MTP_int(i.key()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ApiWrap::ReplyToRequests *ApiWrap::replyToRequests(ChannelData *channel, bool onlyExisting) {
|
||||
ApiWrap::MessageDataRequests *ApiWrap::messageDataRequests(ChannelData *channel, bool onlyExisting) {
|
||||
if (channel) {
|
||||
ChannelReplyToRequests::iterator i = _channelReplyToRequests.find(channel);
|
||||
if (i == _channelReplyToRequests.cend()) {
|
||||
ChannelMessageDataRequests::iterator i = _channelMessageDataRequests.find(channel);
|
||||
if (i == _channelMessageDataRequests.cend()) {
|
||||
if (onlyExisting) return 0;
|
||||
i = _channelReplyToRequests.insert(channel, ReplyToRequests());
|
||||
i = _channelMessageDataRequests.insert(channel, MessageDataRequests());
|
||||
}
|
||||
return &i.value();
|
||||
}
|
||||
return &_replyToRequests;
|
||||
return &_messageDataRequests;
|
||||
}
|
||||
|
||||
void ApiWrap::resolveReplyTo() {
|
||||
if (_replyToRequests.isEmpty() && _channelReplyToRequests.isEmpty()) return;
|
||||
void ApiWrap::resolveMessageDatas() {
|
||||
if (_messageDataRequests.isEmpty() && _channelMessageDataRequests.isEmpty()) return;
|
||||
|
||||
MessageIds ids = collectMessageIds(_replyToRequests);
|
||||
MessageIds ids = collectMessageIds(_messageDataRequests);
|
||||
if (!ids.isEmpty()) {
|
||||
mtpRequestId req = MTP::send(MTPmessages_GetMessages(MTP_vector<MTPint>(ids)), rpcDone(&ApiWrap::gotReplyTo, (ChannelData*)0), RPCFailHandlerPtr(), 0, 5);
|
||||
for (ReplyToRequests::iterator i = _replyToRequests.begin(); i != _replyToRequests.cend(); ++i) {
|
||||
mtpRequestId req = MTP::send(MTPmessages_GetMessages(MTP_vector<MTPint>(ids)), rpcDone(&ApiWrap::gotMessageDatas, (ChannelData*)nullptr), RPCFailHandlerPtr(), 0, 5);
|
||||
for (MessageDataRequests::iterator i = _messageDataRequests.begin(); i != _messageDataRequests.cend(); ++i) {
|
||||
if (i.value().req > 0) continue;
|
||||
i.value().req = req;
|
||||
}
|
||||
}
|
||||
for (ChannelReplyToRequests::iterator j = _channelReplyToRequests.begin(); j != _channelReplyToRequests.cend();) {
|
||||
for (ChannelMessageDataRequests::iterator j = _channelMessageDataRequests.begin(); j != _channelMessageDataRequests.cend();) {
|
||||
if (j->isEmpty()) {
|
||||
j = _channelReplyToRequests.erase(j);
|
||||
j = _channelMessageDataRequests.erase(j);
|
||||
continue;
|
||||
}
|
||||
MessageIds ids = collectMessageIds(j.value());
|
||||
if (!ids.isEmpty()) {
|
||||
mtpRequestId req = MTP::send(MTPchannels_GetMessages(j.key()->inputChannel, MTP_vector<MTPint>(ids)), rpcDone(&ApiWrap::gotReplyTo, j.key()), RPCFailHandlerPtr(), 0, 5);
|
||||
for (ReplyToRequests::iterator i = j->begin(); i != j->cend(); ++i) {
|
||||
mtpRequestId req = MTP::send(MTPchannels_GetMessages(j.key()->inputChannel, MTP_vector<MTPint>(ids)), rpcDone(&ApiWrap::gotMessageDatas, j.key()), RPCFailHandlerPtr(), 0, 5);
|
||||
for (MessageDataRequests::iterator i = j->begin(); i != j->cend(); ++i) {
|
||||
if (i.value().req > 0) continue;
|
||||
i.value().req = req;
|
||||
}
|
||||
|
@ -120,7 +96,7 @@ void ApiWrap::resolveReplyTo() {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::gotReplyTo(ChannelData *channel, const MTPmessages_Messages &msgs, mtpRequestId req) {
|
||||
void ApiWrap::gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &msgs, mtpRequestId req) {
|
||||
switch (msgs.type()) {
|
||||
case mtpc_messages_messages: {
|
||||
const MTPDmessages_messages &d(msgs.c_messages_messages());
|
||||
|
@ -141,10 +117,10 @@ void ApiWrap::gotReplyTo(ChannelData *channel, const MTPmessages_Messages &msgs,
|
|||
if (channel) {
|
||||
channel->ptsReceived(d.vpts.v);
|
||||
} else {
|
||||
LOG(("App Error: received messages.channelMessages when no channel was passed! (ApiWrap::gotReplyTo)"));
|
||||
LOG(("App Error: received messages.channelMessages when no channel was passed! (ApiWrap::gotDependencyItem)"));
|
||||
}
|
||||
if (d.has_collapsed()) { // should not be returned
|
||||
LOG(("API Error: channels.getMessages and messages.getMessages should not return collapsed groups! (ApiWrap::gotReplyTo)"));
|
||||
LOG(("API Error: channels.getMessages and messages.getMessages should not return collapsed groups! (ApiWrap::gotDependencyItem)"));
|
||||
}
|
||||
|
||||
App::feedUsers(d.vusers);
|
||||
|
@ -152,16 +128,12 @@ void ApiWrap::gotReplyTo(ChannelData *channel, const MTPmessages_Messages &msgs,
|
|||
App::feedMsgs(d.vmessages, NewMessageExisting);
|
||||
} break;
|
||||
}
|
||||
ReplyToRequests *requests(replyToRequests(channel, true));
|
||||
MessageDataRequests *requests(messageDataRequests(channel, true));
|
||||
if (requests) {
|
||||
for (ReplyToRequests::iterator i = requests->begin(); i != requests->cend();) {
|
||||
for (MessageDataRequests::iterator i = requests->begin(); i != requests->cend();) {
|
||||
if (i.value().req == req) {
|
||||
for (QList<HistoryReply*>::const_iterator j = i.value().replies.cbegin(), e = i.value().replies.cend(); j != e; ++j) {
|
||||
if (*j) {
|
||||
(*j)->updateReplyTo(true);
|
||||
} else {
|
||||
App::main()->updateReplyTo();
|
||||
}
|
||||
for (MessageDataRequest::Callbacks::const_iterator j = i.value().callbacks.cbegin(), e = i.value().callbacks.cend(); j != e; ++j) {
|
||||
(*j)->call(channel, i.key());
|
||||
}
|
||||
i = requests->erase(i);
|
||||
} else {
|
||||
|
@ -169,7 +141,7 @@ void ApiWrap::gotReplyTo(ChannelData *channel, const MTPmessages_Messages &msgs,
|
|||
}
|
||||
}
|
||||
if (channel && requests->isEmpty()) {
|
||||
_channelReplyToRequests.remove(channel);
|
||||
_channelMessageDataRequests.remove(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +230,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
|||
}
|
||||
if (f.has_migrated_from_chat_id()) {
|
||||
if (!channel->mgInfo) {
|
||||
channel->flags |= MTPDchannel::flag_megagroup;
|
||||
channel->flags |= MTPDchannel::Flag::f_megagroup;
|
||||
channel->flagsUpdated();
|
||||
}
|
||||
ChatData *cfrom = App::chat(peerFromChat(f.vmigrated_from_chat_id));
|
||||
|
@ -273,7 +245,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
|||
if (!h->isEmpty()) {
|
||||
h->clear(true);
|
||||
}
|
||||
if (!hto->dialogs.isEmpty() && !h->dialogs.isEmpty()) {
|
||||
if (hto->inChatList() && h->inChatList()) {
|
||||
App::removeDialog(h);
|
||||
}
|
||||
}
|
||||
|
@ -317,6 +289,13 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
|||
h->asChannelHistory()->unreadCountAll = f.vunread_count.v;
|
||||
}
|
||||
}
|
||||
if (channel->isMegagroup()) {
|
||||
if (f.has_pinned_msg_id()) {
|
||||
channel->mgInfo->pinnedMsgId = f.vpinned_msg_id.v;
|
||||
} else {
|
||||
channel->mgInfo->pinnedMsgId = 0;
|
||||
}
|
||||
}
|
||||
channel->fullUpdated();
|
||||
|
||||
App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), f.vnotify_settings);
|
||||
|
@ -344,12 +323,21 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
|||
void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestId req) {
|
||||
const MTPDuserFull &d(result.c_userFull());
|
||||
App::feedUsers(MTP_vector<MTPUser>(1, d.vuser), false);
|
||||
App::feedPhoto(d.vprofile_photo);
|
||||
if (d.has_profile_photo()) {
|
||||
App::feedPhoto(d.vprofile_photo);
|
||||
}
|
||||
App::feedUserLink(MTP_int(peerToUser(peer->id)), d.vlink.c_contacts_link().vmy_link, d.vlink.c_contacts_link().vforeign_link, false);
|
||||
App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings);
|
||||
if (App::main()) {
|
||||
App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings);
|
||||
}
|
||||
|
||||
peer->asUser()->setBotInfo(d.vbot_info);
|
||||
peer->asUser()->blocked = mtpIsTrue(d.vblocked) ? UserIsBlocked : UserIsNotBlocked;
|
||||
if (d.has_bot_info()) {
|
||||
peer->asUser()->setBotInfo(d.vbot_info);
|
||||
} else {
|
||||
peer->asUser()->setBotInfoVersion(-1);
|
||||
}
|
||||
peer->asUser()->blocked = d.is_blocked() ? UserIsBlocked : UserIsNotBlocked;
|
||||
peer->asUser()->about = d.has_about() ? qs(d.vabout) : QString();
|
||||
|
||||
if (req) {
|
||||
QMap<PeerData*, mtpRequestId>::iterator i = _fullPeerRequests.find(peer);
|
||||
|
@ -419,13 +407,13 @@ void ApiWrap::requestLastParticipants(ChannelData *peer, bool fromStart) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
mtpRequestId req = MTP::send(MTPchannels_GetParticipants(peer->inputChannel, MTP_channelParticipantsRecent(), MTP_int(fromStart ? 0 : peer->mgInfo->lastParticipants.size()), MTP_int(cMaxGroupCount())), rpcDone(&ApiWrap::lastParticipantsDone, peer), rpcFail(&ApiWrap::lastParticipantsFail, peer));
|
||||
mtpRequestId req = MTP::send(MTPchannels_GetParticipants(peer->inputChannel, MTP_channelParticipantsRecent(), MTP_int(fromStart ? 0 : peer->mgInfo->lastParticipants.size()), MTP_int(Global::ChatSizeMax())), rpcDone(&ApiWrap::lastParticipantsDone, peer), rpcFail(&ApiWrap::lastParticipantsFail, peer));
|
||||
_participantsRequests.insert(peer, fromStart ? req : -req);
|
||||
}
|
||||
|
||||
void ApiWrap::requestBots(ChannelData *peer) {
|
||||
if (!peer || !peer->isMegagroup() || _botsRequests.contains(peer)) return;
|
||||
_botsRequests.insert(peer, MTP::send(MTPchannels_GetParticipants(peer->inputChannel, MTP_channelParticipantsBots(), MTP_int(0), MTP_int(cMaxGroupCount())), rpcDone(&ApiWrap::lastParticipantsDone, peer), rpcFail(&ApiWrap::lastParticipantsFail, peer)));
|
||||
_botsRequests.insert(peer, MTP::send(MTPchannels_GetParticipants(peer->inputChannel, MTP_channelParticipantsBots(), MTP_int(0), MTP_int(Global::ChatSizeMax())), rpcDone(&ApiWrap::lastParticipantsDone, peer), rpcFail(&ApiWrap::lastParticipantsFail, peer)));
|
||||
}
|
||||
|
||||
void ApiWrap::gotChat(PeerData *peer, const MTPmessages_Chats &result) {
|
||||
|
@ -524,7 +512,7 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
|
|||
UserData *u = App::user(userId);
|
||||
if (bots) {
|
||||
if (u->botInfo) {
|
||||
peer->mgInfo->bots.insert(u, true);
|
||||
peer->mgInfo->bots.insert(u);
|
||||
botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
|
||||
if (!u->botInfo->inited) {
|
||||
needBotsInfos = true;
|
||||
|
@ -536,9 +524,9 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
|
|||
} else {
|
||||
if (peer->mgInfo->lastParticipants.indexOf(u) < 0) {
|
||||
peer->mgInfo->lastParticipants.push_back(u);
|
||||
if (admin) peer->mgInfo->lastAdmins.insert(u, true);
|
||||
if (admin) peer->mgInfo->lastAdmins.insert(u);
|
||||
if (u->botInfo) {
|
||||
peer->mgInfo->bots.insert(u, true);
|
||||
peer->mgInfo->bots.insert(u);
|
||||
if (peer->mgInfo->botStatus != 0 && peer->mgInfo->botStatus < 2) {
|
||||
peer->mgInfo->botStatus = 2;
|
||||
}
|
||||
|
@ -645,15 +633,23 @@ void ApiWrap::kickParticipantDone(KickRequest kick, const MTPUpdates &result, mt
|
|||
int32 i = kick.first->asChannel()->mgInfo->lastParticipants.indexOf(kick.second);
|
||||
if (i >= 0) {
|
||||
kick.first->asChannel()->mgInfo->lastParticipants.removeAt(i);
|
||||
kick.first->asChannel()->mgInfo->lastAdmins.remove(kick.second);
|
||||
}
|
||||
kick.first->asChannel()->mgInfo->bots.remove(kick.second);
|
||||
if (kick.first->asChannel()->count > 1) {
|
||||
kick.first->asChannel()->count--;
|
||||
--kick.first->asChannel()->count;
|
||||
} else {
|
||||
kick.first->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated;
|
||||
kick.first->asChannel()->mgInfo->lastParticipantsCount = 0;
|
||||
}
|
||||
if (kick.first->asChannel()->mgInfo->lastAdmins.contains(kick.second)) {
|
||||
kick.first->asChannel()->mgInfo->lastAdmins.remove(kick.second);
|
||||
if (kick.first->asChannel()->adminsCount > 1) {
|
||||
--kick.first->asChannel()->adminsCount;
|
||||
}
|
||||
}
|
||||
kick.first->asChannel()->mgInfo->bots.remove(kick.second);
|
||||
if (kick.first->asChannel()->mgInfo->bots.isEmpty() && kick.first->asChannel()->mgInfo->botStatus > 0) {
|
||||
kick.first->asChannel()->mgInfo->botStatus = -1;
|
||||
}
|
||||
}
|
||||
emit fullPeerUpdated(kick.first);
|
||||
}
|
||||
|
@ -672,9 +668,9 @@ void ApiWrap::scheduleStickerSetRequest(uint64 setId, uint64 access) {
|
|||
|
||||
void ApiWrap::requestStickerSets() {
|
||||
for (QMap<uint64, QPair<uint64, mtpRequestId> >::iterator i = _stickerSetRequests.begin(), j = i, e = _stickerSetRequests.end(); i != e; i = j) {
|
||||
++j;
|
||||
if (i.value().second) continue;
|
||||
|
||||
++j;
|
||||
int32 wait = (j == e) ? 0 : 10;
|
||||
i.value().second = MTP::send(MTPmessages_GetStickerSet(MTP_inputStickerSetID(MTP_long(i.key()), MTP_long(i.value().first))), rpcDone(&ApiWrap::gotStickerSet, i.key()), rpcFail(&ApiWrap::gotStickerSetFail, i.key()), 0, wait);
|
||||
}
|
||||
|
@ -689,8 +685,8 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
if (d.vset.type() != mtpc_stickerSet) return;
|
||||
const MTPDstickerSet &s(d.vset.c_stickerSet());
|
||||
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
StickerSets::iterator it = sets.find(setId);
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend()) return;
|
||||
|
||||
it->access = s.vaccess_hash.v;
|
||||
|
@ -700,7 +696,7 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
it->flags = s.vflags.v;
|
||||
|
||||
const QVector<MTPDocument> &d_docs(d.vdocuments.c_vector().v);
|
||||
StickerSets::iterator custom = sets.find(CustomStickerSetId);
|
||||
auto custom = sets.find(Stickers::CustomSetId);
|
||||
|
||||
StickerPack pack;
|
||||
pack.reserve(d_docs.size());
|
||||
|
@ -731,12 +727,32 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
|
|||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if (pack.isEmpty()) {
|
||||
int32 removeIndex = cStickerSetsOrder().indexOf(setId);
|
||||
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
||||
int removeIndex = Global::StickerSetsOrder().indexOf(setId);
|
||||
if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex);
|
||||
sets.erase(it);
|
||||
} else {
|
||||
it->stickers = pack;
|
||||
it->emoji.clear();
|
||||
const QVector<MTPStickerPack> &v(d.vpacks.c_vector().v);
|
||||
for (int32 i = 0, l = v.size(); i < l; ++i) {
|
||||
if (v.at(i).type() != mtpc_stickerPack) continue;
|
||||
|
||||
const MTPDstickerPack &pack(v.at(i).c_stickerPack());
|
||||
if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) {
|
||||
const QVector<MTPlong> &stickers(pack.vdocuments.c_vector().v);
|
||||
StickerPack p;
|
||||
p.reserve(stickers.size());
|
||||
for (int32 j = 0, c = stickers.size(); j < c; ++j) {
|
||||
DocumentData *doc = App::document(stickers.at(j).v);
|
||||
if (!doc || !doc->sticker()) continue;
|
||||
|
||||
p.push_back(doc);
|
||||
}
|
||||
it->emoji.insert(e, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (writeRecent) {
|
||||
|
@ -887,10 +903,8 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs
|
|||
}
|
||||
|
||||
for (QMap<uint64, int32>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
|
||||
HistoryItem *item = App::histories().addNewMessage(v->at(i.value()), NewMessageExisting);
|
||||
if (item) {
|
||||
item->initDimensions();
|
||||
Notify::historyItemResized(item);
|
||||
if (HistoryItem *item = App::histories().addNewMessage(v->at(i.value()), NewMessageExisting)) {
|
||||
item->setPendingInitDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -902,8 +916,7 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs
|
|||
WebPageItems::const_iterator j = items.constFind(i.key());
|
||||
if (j != items.cend()) {
|
||||
for (HistoryItemsMap::const_iterator k = j.value().cbegin(), e = j.value().cend(); k != e; ++k) {
|
||||
k.key()->initDimensions();
|
||||
Notify::historyItemResized(k.key());
|
||||
k.key()->setPendingInitDimensions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -28,9 +28,8 @@ public:
|
|||
ApiWrap(QObject *parent);
|
||||
void init();
|
||||
|
||||
void itemRemoved(HistoryItem *item);
|
||||
|
||||
void requestReplyTo(HistoryReply *reply, ChannelData *channel, MsgId id);
|
||||
typedef SharedCallback<void, ChannelData*, MsgId> RequestMessageDataCallback;
|
||||
void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback *callback);
|
||||
|
||||
void requestFullPeer(PeerData *peer);
|
||||
void requestPeer(PeerData *peer);
|
||||
|
@ -59,28 +58,30 @@ signals:
|
|||
|
||||
public slots:
|
||||
|
||||
void resolveReplyTo();
|
||||
void resolveMessageDatas();
|
||||
void resolveWebPages();
|
||||
|
||||
void delayedRequestParticipantsCount();
|
||||
|
||||
private:
|
||||
|
||||
void gotReplyTo(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
struct ReplyToRequest {
|
||||
ReplyToRequest() : req(0) {
|
||||
void gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
struct MessageDataRequest {
|
||||
MessageDataRequest() : req(0) {
|
||||
}
|
||||
typedef SharedCallback<void, ChannelData*, MsgId>::Ptr CallbackPtr;
|
||||
typedef QList<CallbackPtr> Callbacks;
|
||||
mtpRequestId req;
|
||||
QList<HistoryReply*> replies;
|
||||
Callbacks callbacks;
|
||||
};
|
||||
typedef QMap<MsgId, ReplyToRequest> ReplyToRequests;
|
||||
ReplyToRequests _replyToRequests;
|
||||
typedef QMap<ChannelData*, ReplyToRequests> ChannelReplyToRequests;
|
||||
ChannelReplyToRequests _channelReplyToRequests;
|
||||
SingleTimer _replyToTimer;
|
||||
typedef QMap<MsgId, MessageDataRequest> MessageDataRequests;
|
||||
MessageDataRequests _messageDataRequests;
|
||||
typedef QMap<ChannelData*, MessageDataRequests> ChannelMessageDataRequests;
|
||||
ChannelMessageDataRequests _channelMessageDataRequests;
|
||||
SingleDelayedCall *_messageDataResolveDelayed;
|
||||
typedef QVector<MTPint> MessageIds;
|
||||
MessageIds collectMessageIds(const ReplyToRequests &requests);
|
||||
ReplyToRequests *replyToRequests(ChannelData *channel, bool onlyExisting = false);
|
||||
MessageIds collectMessageIds(const MessageDataRequests &requests);
|
||||
MessageDataRequests *messageDataRequests(ChannelData *channel, bool onlyExisting = false);
|
||||
|
||||
void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req);
|
||||
void gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestId req);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,13 +16,13 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "basic_types.h"
|
||||
|
||||
class Application;
|
||||
class AppClass;
|
||||
class Window;
|
||||
class MainWidget;
|
||||
class SettingsWidget;
|
||||
|
@ -36,30 +36,18 @@ class FileUploader;
|
|||
|
||||
typedef QMap<HistoryItem*, NullType> HistoryItemsMap;
|
||||
typedef QHash<PhotoData*, HistoryItemsMap> PhotoItems;
|
||||
typedef QHash<VideoData*, HistoryItemsMap> VideoItems;
|
||||
typedef QHash<AudioData*, HistoryItemsMap> AudioItems;
|
||||
typedef QHash<DocumentData*, HistoryItemsMap> DocumentItems;
|
||||
typedef QHash<WebPageData*, HistoryItemsMap> WebPageItems;
|
||||
typedef QHash<int32, HistoryItemsMap> SharedContactItems;
|
||||
typedef QHash<ClipReader*, HistoryItem*> GifItems;
|
||||
|
||||
typedef QHash<PhotoId, PhotoData*> PhotosData;
|
||||
typedef QHash<VideoId, VideoData*> VideosData;
|
||||
typedef QHash<AudioId, AudioData*> AudiosData;
|
||||
typedef QHash<DocumentId, DocumentData*> DocumentsData;
|
||||
|
||||
struct ReplyMarkup {
|
||||
ReplyMarkup(int32 flags = 0) : flags(flags) {
|
||||
}
|
||||
typedef QList<QList<QString> > Commands;
|
||||
Commands commands;
|
||||
int32 flags;
|
||||
};
|
||||
|
||||
class LayeredWidget;
|
||||
|
||||
namespace App {
|
||||
Application *app();
|
||||
AppClass *app();
|
||||
Window *wnd();
|
||||
MainWidget *main();
|
||||
SettingsWidget *settings();
|
||||
|
@ -68,7 +56,6 @@ namespace App {
|
|||
ApiWrap *api();
|
||||
|
||||
void logOut();
|
||||
bool loggedOut();
|
||||
|
||||
QString formatPhone(QString phone);
|
||||
|
||||
|
@ -85,6 +72,7 @@ namespace App {
|
|||
void feedChatAdmins(const MTPDupdateChatAdmins &d, bool emitPeerUpdated = true);
|
||||
void feedParticipantAdmin(const MTPDupdateChatParticipantAdmin &d, bool emitPeerUpdated = true);
|
||||
bool checkEntitiesAndViewsUpdate(const MTPDmessage &m); // returns true if item found and it is not detached
|
||||
void updateEditedMessage(const MTPDmessage &m);
|
||||
void addSavedGif(DocumentData *doc);
|
||||
void checkSavedGif(HistoryItem *item);
|
||||
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
|
||||
|
@ -106,9 +94,6 @@ namespace App {
|
|||
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs);
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert = 0);
|
||||
PhotoData *feedPhoto(const MTPDphoto &photo, PhotoData *convert = 0);
|
||||
VideoData *feedVideo(const MTPDvideo &video, VideoData *convert = 0);
|
||||
AudioData *feedAudio(const MTPaudio &audio, AudioData *convert = 0);
|
||||
AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert = 0);
|
||||
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb);
|
||||
DocumentData *feedDocument(const MTPdocument &document, DocumentData *convert = 0);
|
||||
DocumentData *feedDocument(const MTPDdocument &document, DocumentData *convert = 0);
|
||||
|
@ -116,36 +101,57 @@ namespace App {
|
|||
WebPageData *feedWebPage(const MTPDwebPagePending &webpage, WebPageData *convert = 0);
|
||||
WebPageData *feedWebPage(const MTPWebPage &webpage);
|
||||
|
||||
PeerData *peerLoaded(const PeerId &id);
|
||||
UserData *userLoaded(const PeerId &id);
|
||||
ChatData *chatLoaded(const PeerId &id);
|
||||
ChannelData *channelLoaded(const PeerId &id);
|
||||
UserData *userLoaded(int32 user);
|
||||
ChatData *chatLoaded(int32 chat);
|
||||
ChannelData *channelLoaded(int32 channel);
|
||||
PeerData *peer(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded);
|
||||
inline UserData *user(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asUser(peer(id, restriction));
|
||||
}
|
||||
inline ChatData *chat(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChat(peer(id, restriction));
|
||||
}
|
||||
inline ChannelData *channel(const PeerId &id, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChannel(peer(id, restriction));
|
||||
}
|
||||
inline UserData *user(UserId userId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asUser(peer(peerFromUser(userId), restriction));
|
||||
}
|
||||
inline ChatData *chat(ChatId chatId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChat(peer(peerFromChat(chatId), restriction));
|
||||
}
|
||||
inline ChannelData *channel(ChannelId channelId, PeerData::LoadedStatus restriction = PeerData::NotLoaded) {
|
||||
return asChannel(peer(peerFromChannel(channelId), restriction));
|
||||
}
|
||||
inline PeerData *peerLoaded(const PeerId &id) {
|
||||
return peer(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline UserData *userLoaded(const PeerId &id) {
|
||||
return user(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChatData *chatLoaded(const PeerId &id) {
|
||||
return chat(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChannelData *channelLoaded(const PeerId &id) {
|
||||
return channel(id, PeerData::FullLoaded);
|
||||
}
|
||||
inline UserData *userLoaded(UserId userId) {
|
||||
return user(userId, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChatData *chatLoaded(ChatId chatId) {
|
||||
return chat(chatId, PeerData::FullLoaded);
|
||||
}
|
||||
inline ChannelData *channelLoaded(ChannelId channelId) {
|
||||
return channel(channelId, PeerData::FullLoaded);
|
||||
}
|
||||
|
||||
PeerData *peer(const PeerId &id);
|
||||
UserData *user(const PeerId &id);
|
||||
ChatData *chat(const PeerId &id);
|
||||
ChannelData *channel(const PeerId &id);
|
||||
UserData *user(int32 user_id);
|
||||
ChatData *chat(int32 chat_id);
|
||||
ChannelData *channel(int32 channel_id);
|
||||
UserData *self();
|
||||
PeerData *peerByName(const QString &username);
|
||||
QString peerName(const PeerData *peer, bool forDialogs = false);
|
||||
PhotoData *photo(const PhotoId &photo);
|
||||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
|
||||
VideoData *video(const VideoId &video);
|
||||
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
|
||||
AudioData *audio(const AudioId &audio);
|
||||
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
|
||||
DocumentData *document(const DocumentId &document);
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
|
||||
WebPageData *webPage(const WebPageId &webPage);
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill);
|
||||
ImageLinkData *imageLink(const QString &imageLink);
|
||||
ImageLinkData *imageLinkSet(const QString &imageLink, ImageLinkType type, const QString &url);
|
||||
LocationData *location(const LocationCoords &coords);
|
||||
void forgetMedia();
|
||||
|
||||
MTPPhoto photoFromUserPhoto(MTPint userId, MTPint date, const MTPUserProfilePhoto &photo);
|
||||
|
@ -155,16 +161,27 @@ namespace App {
|
|||
History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead);
|
||||
History *historyLoaded(const PeerId &peer);
|
||||
HistoryItem *histItemById(ChannelId channelId, MsgId itemId);
|
||||
inline History *history(const PeerData *peer) {
|
||||
t_assert(peer != nullptr);
|
||||
return history(peer->id);
|
||||
}
|
||||
inline History *historyLoaded(const PeerData *peer) {
|
||||
return peer ? historyLoaded(peer->id) : nullptr;
|
||||
}
|
||||
inline HistoryItem *histItemById(const ChannelData *channel, MsgId itemId) {
|
||||
return histItemById(channel ? peerToChannel(channel->id) : 0, itemId);
|
||||
}
|
||||
inline HistoryItem *histItemById(const FullMsgId &msgId) {
|
||||
return histItemById(msgId.channel, msgId.msg);
|
||||
}
|
||||
void historyRegItem(HistoryItem *item);
|
||||
void historyItemDetached(HistoryItem *item);
|
||||
void historyUnregItem(HistoryItem *item);
|
||||
void historyUpdateDependent(HistoryItem *item);
|
||||
void historyClearMsgs();
|
||||
void historyClearItems();
|
||||
void historyRegReply(HistoryReply *reply, HistoryItem *to);
|
||||
void historyUnregReply(HistoryReply *reply, HistoryItem *to);
|
||||
void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
void historyUnregDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
|
||||
void historyRegRandom(uint64 randomId, const FullMsgId &itemId);
|
||||
void historyUnregRandom(uint64 randomId);
|
||||
|
@ -202,9 +219,15 @@ namespace App {
|
|||
|
||||
bool isValidPhone(QString phone);
|
||||
|
||||
enum LaunchState {
|
||||
Launched = 0,
|
||||
QuitRequested = 1,
|
||||
QuitProcessed = 2,
|
||||
};
|
||||
void quit();
|
||||
bool quiting();
|
||||
void setQuiting();
|
||||
bool quitting();
|
||||
LaunchState launchState();
|
||||
void setLaunchState(LaunchState state);
|
||||
|
||||
QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
|
||||
QImage readImage(const QString &file, QByteArray *format = 0, bool opaque = true, bool *animated = 0, QByteArray *content = 0);
|
||||
|
@ -214,16 +237,6 @@ namespace App {
|
|||
const PhotoItems &photoItems();
|
||||
const PhotosData &photosData();
|
||||
|
||||
void regVideoItem(VideoData *data, HistoryItem *item);
|
||||
void unregVideoItem(VideoData *data, HistoryItem *item);
|
||||
const VideoItems &videoItems();
|
||||
const VideosData &videosData();
|
||||
|
||||
void regAudioItem(AudioData *data, HistoryItem *item);
|
||||
void unregAudioItem(AudioData*data, HistoryItem *item);
|
||||
const AudioItems &audioItems();
|
||||
const AudiosData &audiosData();
|
||||
|
||||
void regDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
void unregDocumentItem(DocumentData *data, HistoryItem *item);
|
||||
const DocumentItems &documentItems();
|
||||
|
@ -246,16 +259,10 @@ namespace App {
|
|||
void unregMuted(PeerData *peer);
|
||||
void updateMuted();
|
||||
|
||||
void regInlineResultLoader(FileLoader *loader, InlineResult *result);
|
||||
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();
|
||||
#endif
|
||||
void setProxySettings(QTcpSocket &socket);
|
||||
|
||||
QImage **cornersMask();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,35 +16,57 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
#include <QtNetwork/QLocalServer>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
#include "window.h"
|
||||
#include "pspecific.h"
|
||||
|
||||
class MainWidget;
|
||||
class FileUploader;
|
||||
class Translator;
|
||||
class UpdateDownloader;
|
||||
|
||||
class Application : public PsApplication, public RPCSender {
|
||||
class UpdateChecker;
|
||||
class Application : public QApplication {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Application(int &argc, char **argv);
|
||||
~Application();
|
||||
|
||||
static Application *app();
|
||||
static Window *wnd();
|
||||
static QString language();
|
||||
static int32 languageId();
|
||||
static MainWidget *main();
|
||||
// Single instance application
|
||||
public slots:
|
||||
|
||||
void socketConnected();
|
||||
void socketError(QLocalSocket::LocalSocketError e);
|
||||
void socketDisconnected();
|
||||
void socketWritten(qint64 bytes);
|
||||
void socketReading();
|
||||
void newInstanceConnected();
|
||||
|
||||
void readClients();
|
||||
void removeClients();
|
||||
|
||||
void startApplication(); // will be done in exec()
|
||||
void closeApplication(); // will be done in aboutToQuit()
|
||||
|
||||
private:
|
||||
|
||||
typedef QPair<QLocalSocket*, QByteArray> LocalClient;
|
||||
typedef QList<LocalClient> LocalClients;
|
||||
|
||||
QString _localServerName, _localSocketReadData;
|
||||
QLocalServer _localServer;
|
||||
QLocalSocket _localSocket;
|
||||
LocalClients _localClients;
|
||||
bool _secondInstance;
|
||||
|
||||
void singleInstanceChecked();
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
// Autoupdating
|
||||
public:
|
||||
|
||||
void startUpdateCheck(bool forceWait);
|
||||
void stopUpdate();
|
||||
|
||||
enum UpdatingState {
|
||||
UpdatingNone,
|
||||
|
@ -52,11 +74,87 @@ public:
|
|||
UpdatingReady,
|
||||
};
|
||||
UpdatingState updatingState();
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
int32 updatingSize();
|
||||
int32 updatingReady();
|
||||
|
||||
signals:
|
||||
|
||||
void updateChecking();
|
||||
void updateLatest();
|
||||
void updateProgress(qint64 ready, qint64 total);
|
||||
void updateReady();
|
||||
void updateFailed();
|
||||
|
||||
public slots:
|
||||
|
||||
void updateCheck();
|
||||
|
||||
void updateGotCurrent();
|
||||
void updateFailedCurrent(QNetworkReply::NetworkError e);
|
||||
|
||||
void onUpdateReady();
|
||||
void onUpdateFailed();
|
||||
|
||||
private:
|
||||
|
||||
SingleTimer _updateCheckTimer;
|
||||
QNetworkReply *_updateReply;
|
||||
QNetworkAccessManager _updateManager;
|
||||
QThread *_updateThread;
|
||||
UpdateChecker *_updateChecker;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace Sandbox {
|
||||
|
||||
QRect availableGeometry();
|
||||
QRect screenGeometry(const QPoint &p);
|
||||
void setActiveWindow(QWidget *window);
|
||||
bool isSavingSession();
|
||||
|
||||
void installEventFilter(QObject *filter);
|
||||
|
||||
void execExternal(const QString &cmd);
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
void startUpdateCheck();
|
||||
void stopUpdate();
|
||||
#endif
|
||||
|
||||
Application::UpdatingState updatingState();
|
||||
int32 updatingSize();
|
||||
int32 updatingReady();
|
||||
|
||||
void updateChecking();
|
||||
void updateLatest();
|
||||
void updateProgress(qint64 ready, qint64 total);
|
||||
void updateFailed();
|
||||
void updateReady();
|
||||
|
||||
#endif
|
||||
|
||||
void connect(const char *signal, QObject *object, const char *method);
|
||||
|
||||
void launch();
|
||||
|
||||
}
|
||||
|
||||
class MainWidget;
|
||||
class FileUploader;
|
||||
class Translator;
|
||||
|
||||
class AppClass : public QObject, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
AppClass();
|
||||
~AppClass();
|
||||
|
||||
static AppClass *app();
|
||||
static Window *wnd();
|
||||
static MainWidget *main();
|
||||
|
||||
FileUploader *uploader();
|
||||
void uploadProfilePhoto(const QImage &tosend, const PeerId &peerId);
|
||||
|
@ -85,14 +183,6 @@ public:
|
|||
|
||||
signals:
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
void updateChecking();
|
||||
void updateLatest();
|
||||
void updateDownloading(qint64 ready, qint64 total);
|
||||
void updateReady();
|
||||
void updateFailed();
|
||||
#endif
|
||||
|
||||
void peerPhotoDone(PeerId peer);
|
||||
void peerPhotoFail(PeerId peer);
|
||||
|
||||
|
@ -100,31 +190,9 @@ signals:
|
|||
|
||||
public slots:
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
void startUpdateCheck(bool forceWait = false);
|
||||
#endif
|
||||
void socketConnected();
|
||||
void socketError(QLocalSocket::LocalSocketError e);
|
||||
void socketDisconnected();
|
||||
void socketWritten(qint64 bytes);
|
||||
void socketReading();
|
||||
void newInstanceConnected();
|
||||
void closeApplication();
|
||||
|
||||
void doMtpUnpause();
|
||||
|
||||
void readClients();
|
||||
void removeClients();
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
void updateGotCurrent();
|
||||
void updateFailedCurrent(QNetworkReply::NetworkError e);
|
||||
|
||||
void onUpdateReady();
|
||||
void onUpdateFailed();
|
||||
#endif
|
||||
|
||||
void photoUpdated(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file);
|
||||
|
||||
void onSwitchDebugMode();
|
||||
void onSwitchTestMode();
|
||||
|
@ -132,6 +200,8 @@ public slots:
|
|||
void killDownloadSessions();
|
||||
void onAppStateChanged(Qt::ApplicationState state);
|
||||
|
||||
void call_handleHistoryUpdate();
|
||||
|
||||
private:
|
||||
|
||||
QMap<FullMsgId, PeerId> photoUpdates;
|
||||
|
@ -139,35 +209,12 @@ private:
|
|||
QMap<int32, uint64> killDownloadSessionTimes;
|
||||
SingleTimer killDownloadSessionsTimer;
|
||||
|
||||
void startApp();
|
||||
uint64 _lastActionTime;
|
||||
|
||||
typedef QPair<QLocalSocket*, QByteArray> ClientSocket;
|
||||
typedef QVector<ClientSocket> ClientSockets;
|
||||
|
||||
QString serverName;
|
||||
QLocalSocket socket;
|
||||
QString socketRead;
|
||||
QLocalServer server;
|
||||
ClientSockets clients;
|
||||
bool closing;
|
||||
|
||||
uint64 lastActionTime;
|
||||
|
||||
void execExternal(const QString &cmd);
|
||||
|
||||
Window *window;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
mtpRequestId updateRequestId;
|
||||
QNetworkAccessManager updateManager;
|
||||
QNetworkReply *updateReply;
|
||||
SingleTimer updateCheckTimer;
|
||||
QThread *updateThread;
|
||||
UpdateDownloader *updateDownloader;
|
||||
#endif
|
||||
Window *_window;
|
||||
FileUploader *_uploader;
|
||||
Translator *_translator;
|
||||
|
||||
SingleTimer _mtpUnpauseTimer;
|
||||
|
||||
Translator *_translator;
|
||||
|
||||
};
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 178 KiB |
Binary file not shown.
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 243 KiB |
File diff suppressed because it is too large
Load diff
|
@ -16,11 +16,11 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "basic_types.h"
|
||||
|
||||
void audioInit();
|
||||
bool audioWorks();
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
void play(const AudioMsgId &audio, int64 position = 0);
|
||||
void play(const SongMsgId &song, int64 position = 0);
|
||||
void pauseresume(MediaOverviewType type, bool fast = false);
|
||||
void seek(int64 position); // type == OverviewDocuments
|
||||
void seek(int64 position); // type == OverviewFiles
|
||||
void stop(MediaOverviewType type);
|
||||
|
||||
void stopAndClear();
|
||||
|
@ -201,8 +201,8 @@ signals:
|
|||
void captureOnStart();
|
||||
void captureOnStop(bool needResult);
|
||||
|
||||
void onDone(QByteArray data, qint32 samples);
|
||||
void onUpdate(qint16 level, qint32 samples);
|
||||
void onDone(QByteArray data, VoiceWaveform waveform, qint32 samples);
|
||||
void onUpdate(quint16 level, qint32 samples);
|
||||
void onError();
|
||||
|
||||
private:
|
||||
|
@ -338,8 +338,8 @@ public:
|
|||
signals:
|
||||
|
||||
void error();
|
||||
void update(qint16 level, qint32 samples);
|
||||
void done(QByteArray data, qint32 samples);
|
||||
void update(quint16 level, qint32 samples);
|
||||
void done(QByteArray data, VoiceWaveform waveform, qint32 samples);
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -360,3 +360,4 @@ private:
|
|||
};
|
||||
|
||||
MTPDocumentAttribute audioReadSongAttributes(const QString &fname, const QByteArray &data, QImage &cover, QByteArray &coverBytes, QByteArray &coverFormat);
|
||||
VoiceWaveform audioCountWaveform(const FileLocation &file, const QByteArray &data);
|
||||
|
|
|
@ -16,13 +16,26 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "autoupdater.h"
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
#include <LzmaLib.h>
|
||||
#else // Q_OS_WIN
|
||||
#include <lzma.h>
|
||||
#endif // else of Q_OS_WIN
|
||||
|
||||
#include "application.h"
|
||||
#include "pspecific.h"
|
||||
#include "autoupdater.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
|
@ -34,7 +47,7 @@ typedef int VerInt;
|
|||
typedef wchar_t VerChar;
|
||||
#endif
|
||||
|
||||
UpdateDownloader::UpdateDownloader(QThread *thread, const QString &url) : reply(0), already(0), full(0) {
|
||||
UpdateChecker::UpdateChecker(QThread *thread, const QString &url) : reply(0), already(0), full(0) {
|
||||
updateUrl = url;
|
||||
moveToThread(thread);
|
||||
manager.moveToThread(thread);
|
||||
|
@ -44,14 +57,14 @@ UpdateDownloader::UpdateDownloader(QThread *thread, const QString &url) : reply(
|
|||
initOutput();
|
||||
}
|
||||
|
||||
void UpdateDownloader::initOutput() {
|
||||
void UpdateChecker::initOutput() {
|
||||
QString fileName;
|
||||
QRegularExpressionMatch m = QRegularExpression(qsl("/([^/\\?]+)(\\?|$)")).match(updateUrl);
|
||||
if (m.hasMatch()) {
|
||||
fileName = m.captured(1).replace(QRegularExpression(qsl("[^a-zA-Z0-9_\\-]")), QString());
|
||||
}
|
||||
if (fileName.isEmpty()) {
|
||||
fileName = qsl("tupdate-%1").arg(MTP::nonce<uint32>() % 1000000);
|
||||
fileName = qsl("tupdate-%1").arg(rand_value<uint32>() % 1000000);
|
||||
}
|
||||
QString dirStr = cWorkingDir() + qsl("tupdates/");
|
||||
fileName = dirStr + fileName;
|
||||
|
@ -99,11 +112,11 @@ void UpdateDownloader::initOutput() {
|
|||
}
|
||||
}
|
||||
|
||||
void UpdateDownloader::start() {
|
||||
void UpdateChecker::start() {
|
||||
sendRequest();
|
||||
}
|
||||
|
||||
void UpdateDownloader::sendRequest() {
|
||||
void UpdateChecker::sendRequest() {
|
||||
QNetworkRequest req(updateUrl);
|
||||
QByteArray rangeHeaderValue = "bytes=" + QByteArray::number(already) + "-";
|
||||
req.setRawHeader("Range", rangeHeaderValue);
|
||||
|
@ -115,7 +128,7 @@ void UpdateDownloader::sendRequest() {
|
|||
connect(reply, SIGNAL(metaDataChanged()), this, SLOT(partMetaGot()));
|
||||
}
|
||||
|
||||
void UpdateDownloader::partMetaGot() {
|
||||
void UpdateChecker::partMetaGot() {
|
||||
typedef QList<QNetworkReply::RawHeaderPair> Pairs;
|
||||
Pairs pairs = reply->rawHeaderPairs();
|
||||
for (Pairs::iterator i = pairs.begin(), e = pairs.end(); i != e; ++i) {
|
||||
|
@ -126,23 +139,24 @@ void UpdateDownloader::partMetaGot() {
|
|||
QMutexLocker lock(&mutex);
|
||||
full = m.captured(1).toInt();
|
||||
}
|
||||
emit App::app()->updateDownloading(already, full);
|
||||
|
||||
Sandbox::updateProgress(already, full);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32 UpdateDownloader::ready() {
|
||||
int32 UpdateChecker::ready() {
|
||||
QMutexLocker lock(&mutex);
|
||||
return already;
|
||||
}
|
||||
|
||||
int32 UpdateDownloader::size() {
|
||||
int32 UpdateChecker::size() {
|
||||
QMutexLocker lock(&mutex);
|
||||
return full;
|
||||
}
|
||||
|
||||
void UpdateDownloader::partFinished(qint64 got, qint64 total) {
|
||||
void UpdateChecker::partFinished(qint64 got, qint64 total) {
|
||||
if (!reply) return;
|
||||
|
||||
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
|
@ -179,11 +193,11 @@ void UpdateDownloader::partFinished(qint64 got, qint64 total) {
|
|||
outputFile.close();
|
||||
unpackUpdate();
|
||||
} else {
|
||||
emit App::app()->updateDownloading(already, full);
|
||||
Sandbox::updateProgress(already, full);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateDownloader::partFailed(QNetworkReply::NetworkError e) {
|
||||
void UpdateChecker::partFailed(QNetworkReply::NetworkError e) {
|
||||
if (!reply) return;
|
||||
|
||||
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
|
@ -198,15 +212,15 @@ void UpdateDownloader::partFailed(QNetworkReply::NetworkError e) {
|
|||
}
|
||||
}
|
||||
LOG(("Update Error: failed to download part starting from %1, error %2").arg(already).arg(e));
|
||||
emit App::app()->updateFailed();
|
||||
Sandbox::updateFailed();
|
||||
}
|
||||
|
||||
void UpdateDownloader::fatalFail() {
|
||||
void UpdateChecker::fatalFail() {
|
||||
clearAll();
|
||||
emit App::app()->updateFailed();
|
||||
Sandbox::updateFailed();
|
||||
}
|
||||
|
||||
void UpdateDownloader::clearAll() {
|
||||
void UpdateChecker::clearAll() {
|
||||
psDeleteDir(cWorkingDir() + qsl("tupdates"));
|
||||
}
|
||||
|
||||
|
@ -225,7 +239,7 @@ void UpdateDownloader::clearAll() {
|
|||
// return QString::fromWCharArray(errMsg);
|
||||
//}
|
||||
|
||||
void UpdateDownloader::unpackUpdate() {
|
||||
void UpdateChecker::unpackUpdate() {
|
||||
QByteArray packed;
|
||||
if (!outputFile.open(QIODevice::ReadOnly)) {
|
||||
LOG(("Update Error: cant read updates file!"));
|
||||
|
@ -465,10 +479,10 @@ void UpdateDownloader::unpackUpdate() {
|
|||
}
|
||||
outputFile.remove();
|
||||
|
||||
emit App::app()->updateReady();
|
||||
Sandbox::updateReady();
|
||||
}
|
||||
|
||||
UpdateDownloader::~UpdateDownloader() {
|
||||
UpdateChecker::~UpdateChecker() {
|
||||
delete reply;
|
||||
reply = 0;
|
||||
}
|
||||
|
@ -477,7 +491,7 @@ bool checkReadyUpdate() {
|
|||
QString readyFilePath = cWorkingDir() + qsl("tupdates/temp/ready"), readyPath = cWorkingDir() + qsl("tupdates/temp");
|
||||
if (!QFile(readyFilePath).exists()) {
|
||||
if (QDir(cWorkingDir() + qsl("tupdates/ready")).exists() || QDir(cWorkingDir() + qsl("tupdates/temp")).exists()) {
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -488,30 +502,30 @@ bool checkReadyUpdate() {
|
|||
QFile fVersion(versionPath);
|
||||
if (!fVersion.open(QIODevice::ReadOnly)) {
|
||||
LOG(("Update Error: cant read version file '%1'").arg(versionPath));
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
VerInt versionNum;
|
||||
if (fVersion.read((char*)&versionNum, sizeof(VerInt)) != sizeof(VerInt)) {
|
||||
LOG(("Update Error: cant read version from file '%1'").arg(versionPath));
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
if (versionNum == 0x7FFFFFFF) { // beta version
|
||||
quint64 betaVersion = 0;
|
||||
if (fVersion.read((char*)&betaVersion, sizeof(quint64)) != sizeof(quint64)) {
|
||||
LOG(("Update Error: cant read beta version from file '%1'").arg(versionPath));
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
if (!cBetaVersion() || betaVersion <= cBetaVersion()) {
|
||||
LOG(("Update Error: cant install beta version %1 having beta version %2").arg(betaVersion).arg(cBetaVersion()));
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
} else if (versionNum <= AppVersion) {
|
||||
LOG(("Update Error: cant install version %1 having version %2").arg(versionNum).arg(AppVersion));
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
fVersion.close();
|
||||
|
@ -530,11 +544,11 @@ bool checkReadyUpdate() {
|
|||
if (!updater.exists()) {
|
||||
QFileInfo current(curUpdater);
|
||||
if (!current.exists()) {
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
if (!QFile(current.absoluteFilePath()).copy(updater.absoluteFilePath())) {
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -545,24 +559,24 @@ bool checkReadyUpdate() {
|
|||
cSetWriteProtected(true);
|
||||
return true;
|
||||
} else {
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (DeleteFile(updater.absoluteFilePath().toStdWString().c_str()) == FALSE) {
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
#elif defined Q_OS_MAC
|
||||
QDir().mkpath(QFileInfo(curUpdater).absolutePath());
|
||||
DEBUG_LOG(("Update Info: moving %1 to %2..").arg(updater.absoluteFilePath()).arg(curUpdater));
|
||||
DEBUG_LOG(("Update Info: moving %1 to %2...").arg(updater.absoluteFilePath()).arg(curUpdater));
|
||||
if (!objc_moveFile(updater.absoluteFilePath(), curUpdater)) {
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
#elif defined Q_OS_LINUX
|
||||
if (!linuxMoveFile(QFile::encodeName(updater.absoluteFilePath()).constData(), QFile::encodeName(curUpdater).constData())) {
|
||||
UpdateDownloader::clearAll();
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -26,11 +26,11 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include <QtNetwork/QLocalServer>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
class UpdateDownloader : public QObject {
|
||||
class UpdateChecker : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UpdateDownloader(QThread *thread, const QString &url);
|
||||
UpdateChecker(QThread *thread, const QString &url);
|
||||
|
||||
void unpackUpdate();
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
|||
|
||||
static void clearAll();
|
||||
|
||||
~UpdateDownloader();
|
||||
~UpdateChecker();
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -66,6 +66,11 @@ private:
|
|||
|
||||
bool checkReadyUpdate();
|
||||
|
||||
#else
|
||||
class UpdateChecker : public QObject {
|
||||
Q_OBJECT
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
QString countBetaVersionSignature(uint64 version);
|
||||
|
|
|
@ -16,10 +16,20 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "basic_types.h"
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
#include "application.h"
|
||||
|
||||
uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
|
||||
|
@ -35,6 +45,10 @@ uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
|
|||
|
||||
// Base types compile-time check
|
||||
|
||||
#ifdef TDESKTOP_CUSTOM_NULLPTR
|
||||
NullPointerClass nullptr;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
template <typename T, int N>
|
||||
class _TypeSizeCheckerHelper {
|
||||
|
@ -106,8 +120,8 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
int32 myunixtime() {
|
||||
return (int32)time(NULL);
|
||||
TimeId myunixtime() {
|
||||
return (TimeId)time(NULL);
|
||||
}
|
||||
|
||||
void unixtimeInit() {
|
||||
|
@ -135,19 +149,19 @@ void unixtimeSet(int32 serverTime, bool force) {
|
|||
_initMsgIdConstants();
|
||||
}
|
||||
|
||||
int32 unixtime() {
|
||||
int32 result = myunixtime();
|
||||
TimeId unixtime() {
|
||||
TimeId result = myunixtime();
|
||||
|
||||
QReadLocker locker(&unixtimeLock);
|
||||
return result + unixtimeDelta;
|
||||
}
|
||||
|
||||
int32 fromServerTime(const MTPint &serverTime) {
|
||||
TimeId fromServerTime(const MTPint &serverTime) {
|
||||
QReadLocker locker(&unixtimeLock);
|
||||
return serverTime.v - unixtimeDelta;
|
||||
}
|
||||
|
||||
MTPint toServerTime(const int32 &clientTime) {
|
||||
MTPint toServerTime(const TimeId &clientTime) {
|
||||
QReadLocker locker(&unixtimeLock);
|
||||
return MTP_int(clientTime + unixtimeDelta);
|
||||
}
|
||||
|
@ -187,6 +201,32 @@ namespace {
|
|||
delete l;
|
||||
}
|
||||
|
||||
int _ffmpegLockManager(void **mutex, AVLockOp op) {
|
||||
switch (op) {
|
||||
case AV_LOCK_CREATE: {
|
||||
t_assert(*mutex == 0);
|
||||
*mutex = reinterpret_cast<void*>(new QMutex());
|
||||
} break;
|
||||
|
||||
case AV_LOCK_OBTAIN: {
|
||||
t_assert(*mutex != 0);
|
||||
reinterpret_cast<QMutex*>(*mutex)->lock();
|
||||
} break;
|
||||
|
||||
case AV_LOCK_RELEASE: {
|
||||
t_assert(*mutex != 0);
|
||||
reinterpret_cast<QMutex*>(*mutex)->unlock();
|
||||
}; break;
|
||||
|
||||
case AV_LOCK_DESTROY: {
|
||||
t_assert(*mutex != 0);
|
||||
delete reinterpret_cast<QMutex*>(*mutex);
|
||||
*mutex = 0;
|
||||
} break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float64 _msFreq;
|
||||
float64 _msgIdCoef;
|
||||
int64 _msStart = 0, _msAddToMsStart = 0, _msAddToUnixtime = 0;
|
||||
|
@ -238,36 +278,51 @@ namespace {
|
|||
_MsStarter _msStarter;
|
||||
}
|
||||
|
||||
InitOpenSSL::InitOpenSSL() {
|
||||
if (!RAND_status()) { // should be always inited in all modern OS
|
||||
char buf[16];
|
||||
memcpy(buf, &_msStart, 8);
|
||||
memcpy(buf + 8, &_msFreq, 8);
|
||||
uchar sha256Buffer[32];
|
||||
RAND_seed(hashSha256(buf, 16, sha256Buffer), 32);
|
||||
if (!RAND_status()) {
|
||||
LOG(("MTP Error: Could not init OpenSSL rand, RAND_status() is 0.."));
|
||||
namespace ThirdParty {
|
||||
|
||||
void start() {
|
||||
PlatformSpecific::ThirdParty::start();
|
||||
|
||||
if (!RAND_status()) { // should be always inited in all modern OS
|
||||
char buf[16];
|
||||
memcpy(buf, &_msStart, 8);
|
||||
memcpy(buf + 8, &_msFreq, 8);
|
||||
uchar sha256Buffer[32];
|
||||
RAND_seed(hashSha256(buf, 16, sha256Buffer), 32);
|
||||
if (!RAND_status()) {
|
||||
LOG(("MTP Error: Could not init OpenSSL rand, RAND_status() is 0..."));
|
||||
}
|
||||
}
|
||||
|
||||
int32 numLocks = CRYPTO_num_locks();
|
||||
if (numLocks) {
|
||||
_sslLocks = new QMutex[numLocks];
|
||||
CRYPTO_set_locking_callback(_sslLockingCallback);
|
||||
} else {
|
||||
LOG(("MTP Error: Could not init OpenSSL threads, CRYPTO_num_locks() returned zero!"));
|
||||
}
|
||||
CRYPTO_THREADID_set_callback(_sslThreadId);
|
||||
CRYPTO_set_dynlock_create_callback(_sslCreateFunction);
|
||||
CRYPTO_set_dynlock_lock_callback(_sslLockFunction);
|
||||
CRYPTO_set_dynlock_destroy_callback(_sslDestroyFunction);
|
||||
|
||||
av_register_all();
|
||||
avcodec_register_all();
|
||||
|
||||
av_lockmgr_register(_ffmpegLockManager);
|
||||
|
||||
_sslInited = true;
|
||||
}
|
||||
|
||||
int32 numLocks = CRYPTO_num_locks();
|
||||
if (numLocks) {
|
||||
_sslLocks = new QMutex[numLocks];
|
||||
CRYPTO_set_locking_callback(_sslLockingCallback);
|
||||
} else {
|
||||
LOG(("MTP Error: Could not init OpenSSL threads, CRYPTO_num_locks() returned zero!"));
|
||||
void finish() {
|
||||
av_lockmgr_register(0);
|
||||
|
||||
delete[] _sslLocks;
|
||||
_sslLocks = 0;
|
||||
|
||||
PlatformSpecific::ThirdParty::finish();
|
||||
}
|
||||
CRYPTO_THREADID_set_callback(_sslThreadId);
|
||||
CRYPTO_set_dynlock_create_callback(_sslCreateFunction);
|
||||
CRYPTO_set_dynlock_lock_callback(_sslLockFunction);
|
||||
CRYPTO_set_dynlock_destroy_callback(_sslDestroyFunction);
|
||||
|
||||
_sslInited = true;
|
||||
}
|
||||
|
||||
InitOpenSSL::~InitOpenSSL() {
|
||||
delete[] _sslLocks;
|
||||
_sslLocks = 0;
|
||||
}
|
||||
|
||||
bool checkms() {
|
||||
|
@ -640,10 +695,7 @@ char *hashMd5Hex(const int32 *hashmd5, void *dest) {
|
|||
}
|
||||
|
||||
void memset_rand(void *data, uint32 len) {
|
||||
if (!_sslInited) {
|
||||
LOG(("Critical Error: memset_rand() called before OpenSSL init!"));
|
||||
exit(-1);
|
||||
}
|
||||
t_assert(_sslInited);
|
||||
RAND_bytes((uchar*)data, len);
|
||||
}
|
||||
|
||||
|
@ -777,8 +829,7 @@ QString translitRusEng(const QString &rus) {
|
|||
result.reserve(rus.size() * 2);
|
||||
|
||||
int32 toSkip = 0;
|
||||
for (QString::const_iterator i = rus.cbegin(), e = rus.cend(); i != e;) {
|
||||
i += toSkip;
|
||||
for (QString::const_iterator i = rus.cbegin(), e = rus.cend(); i != e; i += toSkip) {
|
||||
result += translitLetterRusEng(*i, (i + 1 == e) ? ' ' : *(i + 1), toSkip);
|
||||
}
|
||||
return result;
|
||||
|
@ -982,3 +1033,33 @@ MimeType mimeTypeForData(const QByteArray &data) {
|
|||
}
|
||||
return MimeType(QMimeDatabase().mimeTypeForData(data));
|
||||
}
|
||||
|
||||
struct ComposerMetadatasMap {
|
||||
QMap<uint64, ComposerMetadata*> data;
|
||||
~ComposerMetadatasMap() {
|
||||
for_const (const ComposerMetadata *p, data) {
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const ComposerMetadata *GetComposerMetadata(uint64 mask) {
|
||||
static ComposerMetadatasMap ComposerMetadatas;
|
||||
static QMutex ComposerMetadatasMutex;
|
||||
|
||||
QMutexLocker lock(&ComposerMetadatasMutex);
|
||||
auto i = ComposerMetadatas.data.constFind(mask);
|
||||
if (i == ComposerMetadatas.data.cend()) {
|
||||
ComposerMetadata *meta = new ComposerMetadata(mask);
|
||||
t_assert(meta != nullptr);
|
||||
|
||||
i = ComposerMetadatas.data.insert(mask, meta);
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
||||
const ComposerMetadata *Composer::ZeroComposerMetadata = GetComposerMetadata(0);
|
||||
|
||||
ComponentWrapStruct ComponentWraps[64];
|
||||
|
||||
QAtomicInt ComponentIndexLast;
|
1362
Telegram/SourceFiles/basic_types.h
Normal file
1362
Telegram/SourceFiles/basic_types.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -44,6 +44,8 @@ AboutBox::AboutBox() : AbstractBox(st::aboutWidth)
|
|||
connect(&_done, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
||||
prepare();
|
||||
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void AboutBox::hideAll() {
|
||||
|
@ -82,7 +84,7 @@ void AboutBox::onVersion() {
|
|||
}
|
||||
url = url.arg(qsl("tbeta%1_%2").arg(cRealBetaVersion()).arg(countBetaVersionSignature(cRealBetaVersion())));
|
||||
|
||||
App::app()->clipboard()->setText(url);
|
||||
Application::clipboard()->setText(url);
|
||||
|
||||
Ui::showLayer(new InformBox("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
|
||||
} else {
|
||||
|
@ -105,10 +107,39 @@ void AboutBox::paintEvent(QPaintEvent *e) {
|
|||
paintTitle(p, qsl("Telegram Desktop"));
|
||||
}
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
QString _getCrashReportFile(const QMimeData *m) {
|
||||
if (!m || m->urls().size() != 1) return QString();
|
||||
|
||||
QString file(m->urls().at(0).toLocalFile());
|
||||
if (file.startsWith(qsl("/.file/id="))) file = psConvertFileUrl(file);
|
||||
|
||||
return file.endsWith(qstr(".telegramcrash"), Qt::CaseInsensitive) ? file : QString();
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
|
||||
void AboutBox::dragEnterEvent(QDragEnterEvent *e) {
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
if (!_getCrashReportFile(e->mimeData()).isEmpty()) {
|
||||
e->setDropAction(Qt::CopyAction);
|
||||
e->accept();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AboutBox::dropEvent(QDropEvent *e) {
|
||||
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
if (!_getCrashReportFile(e->mimeData()).isEmpty()) {
|
||||
e->acceptProposedAction();
|
||||
showCrashReportWindow(_getCrashReportFile(e->mimeData()));
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
|
||||
}
|
||||
|
||||
QString telegramFaqLink() {
|
||||
QString result = qsl("https://telegram.org/faq");
|
||||
if (cLang() > languageDefault && cLang() < languageCount) {
|
||||
const char *code = LanguageCodes[cLang()];
|
||||
const char *code = LanguageCodes[cLang()].c_str();
|
||||
if (qstr("de") == code || qstr("es") == code || qstr("it") == code || qstr("ko") == code) {
|
||||
result += qsl("/") + code;
|
||||
} else if (qstr("pt_BR") == code) {
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -32,6 +32,9 @@ public:
|
|||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *e);
|
||||
void dropEvent(QDropEvent *e);
|
||||
|
||||
public slots:
|
||||
|
||||
void onVersion();
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -178,6 +178,14 @@ void AbstractBox::resizeMaxHeight(int32 newWidth, int32 maxHeight) {
|
|||
_maxHeight = maxHeight;
|
||||
resize(newWidth, countHeight());
|
||||
if (parentWidget()) {
|
||||
QRect r = geometry();
|
||||
int32 parenth = parentWidget()->height();
|
||||
if (r.top() + r.height() + st::boxVerticalMargin > parenth) {
|
||||
int32 newTop = qMax(parenth - int(st::boxVerticalMargin) - r.height(), (parenth - r.height()) / 2);
|
||||
if (newTop != r.top()) {
|
||||
move(r.left(), newTop);
|
||||
}
|
||||
}
|
||||
parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.pxWidth(), st::boxShadow.pxHeight(), st::boxShadow.pxWidth(), st::boxShadow.pxHeight())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -188,11 +188,11 @@ void AddContactBox::onSave() {
|
|||
}
|
||||
_sentName = firstName;
|
||||
if (_user) {
|
||||
_contactId = MTP::nonce<uint64>();
|
||||
_contactId = rand_value<uint64>();
|
||||
QVector<MTPInputContact> v(1, MTP_inputPhoneContact(MTP_long(_contactId), MTP_string(_user->phone), MTP_string(firstName), MTP_string(lastName)));
|
||||
_addRequest = MTP::send(MTPcontacts_ImportContacts(MTP_vector<MTPInputContact>(v), MTP_bool(false)), rpcDone(&AddContactBox::onSaveUserDone), rpcFail(&AddContactBox::onSaveUserFail));
|
||||
} else {
|
||||
_contactId = MTP::nonce<uint64>();
|
||||
_contactId = rand_value<uint64>();
|
||||
QVector<MTPInputContact> v(1, MTP_inputPhoneContact(MTP_long(_contactId), MTP_string(phone), MTP_string(firstName), MTP_string(lastName)));
|
||||
_addRequest = MTP::send(MTPcontacts_ImportContacts(MTP_vector<MTPInputContact>(v), MTP_bool(false)), rpcDone(&AddContactBox::onImportDone));
|
||||
}
|
||||
|
@ -224,18 +224,15 @@ void AddContactBox::onImportDone(const MTPcontacts_ImportedContacts &res) {
|
|||
App::feedUsers(d.vusers);
|
||||
|
||||
const QVector<MTPImportedContact> &v(d.vimported.c_vector().v);
|
||||
int32 uid = 0;
|
||||
UserData *user = nullptr;
|
||||
if (!v.isEmpty()) {
|
||||
const MTPDimportedContact &c(v.front().c_importedContact());
|
||||
if (c.vclient_id.v != _contactId) return;
|
||||
|
||||
uid = c.vuser_id.v;
|
||||
if (uid && !App::userLoaded(uid)) {
|
||||
uid = 0;
|
||||
}
|
||||
user = App::userLoaded(c.vuser_id.v);
|
||||
}
|
||||
if (uid) {
|
||||
Notify::userIsContactChanged(App::userLoaded(peerFromUser(uid)), true);
|
||||
if (user) {
|
||||
Notify::userIsContactChanged(user, true);
|
||||
Ui::hideLayer();
|
||||
} else {
|
||||
_save.hide();
|
||||
|
@ -275,7 +272,7 @@ NewGroupBox::NewGroupBox() : AbstractBox(),
|
|||
_group(this, qsl("group_type"), 0, lang(lng_create_group_title), true),
|
||||
_channel(this, qsl("group_type"), 1, lang(lng_create_channel_title)),
|
||||
_aboutGroupWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadiobutton.textPosition.x()),
|
||||
_aboutGroup(st::normalFont, lng_create_group_about(lt_count, cMaxGroupCount()), _defaultOptions, _aboutGroupWidth),
|
||||
_aboutGroup(st::normalFont, lng_create_group_about(lt_count, Global::MegagroupSizeMax()), _defaultOptions, _aboutGroupWidth),
|
||||
_aboutChannel(st::normalFont, lang(lng_create_channel_about), _defaultOptions, _aboutGroupWidth),
|
||||
_next(this, lang(lng_create_group_next), st::defaultBoxButton),
|
||||
_cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||
|
@ -499,8 +496,8 @@ void GroupInfoBox::onNext() {
|
|||
Ui::showLayer(new ContactsBox(title, _photoBig), KeepOtherLayers);
|
||||
} else {
|
||||
bool mega = false;
|
||||
int32 flags = mega ? MTPchannels_CreateChannel::flag_megagroup : MTPchannels_CreateChannel::flag_broadcast;
|
||||
_creationRequestId = MTP::send(MTPchannels_CreateChannel(MTP_int(flags), MTP_string(title), MTP_string(description)), rpcDone(&GroupInfoBox::creationDone), rpcFail(&GroupInfoBox::creationFail));
|
||||
MTPchannels_CreateChannel::Flags flags = mega ? MTPchannels_CreateChannel::Flag::f_megagroup : MTPchannels_CreateChannel::Flag::f_broadcast;
|
||||
_creationRequestId = MTP::send(MTPchannels_CreateChannel(MTP_flags(flags), MTP_string(title), MTP_string(description)), rpcDone(&GroupInfoBox::creationDone), rpcFail(&GroupInfoBox::creationFail));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,6 +537,9 @@ bool GroupInfoBox::creationFail(const RPCError &error) {
|
|||
_title.setFocus();
|
||||
_title.showError();
|
||||
return true;
|
||||
} else if (error.type() == qstr("USER_RESTRICTED")) {
|
||||
Ui::showLayer(new InformBox(lang(lng_cant_do_this)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -605,12 +605,12 @@ void GroupInfoBox::onPhotoReady(const QImage &img) {
|
|||
SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox()
|
||||
, _channel(channel)
|
||||
, _existing(existing)
|
||||
, _public(this, qsl("channel_privacy"), 0, lang(lng_create_public_channel_title), true)
|
||||
, _private(this, qsl("channel_privacy"), 1, lang(lng_create_private_channel_title))
|
||||
, _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true)
|
||||
, _private(this, qsl("channel_privacy"), 1, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title))
|
||||
, _comments(this, lang(lng_create_channel_comments), false)
|
||||
, _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadiobutton.textPosition.x())
|
||||
, _aboutPublic(st::normalFont, lang(lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||
, _aboutPrivate(st::normalFont, lang(lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||
, _aboutPublic(st::normalFont, lang(channel->isMegagroup() ? lng_create_public_group_about : lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||
, _aboutPrivate(st::normalFont, lang(channel->isMegagroup() ? lng_create_private_group_about : lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth)
|
||||
, _aboutComments(st::normalFont, lang(lng_create_channel_comments_about), _defaultOptions, _aboutPublicWidth)
|
||||
, _link(this, st::defaultInputField, QString(), channel->username, true)
|
||||
, _linkOver(false)
|
||||
|
@ -626,7 +626,7 @@ SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : Abstract
|
|||
_checkRequestId = MTP::send(MTPchannels_CheckUsername(_channel->inputChannel, MTP_string("preston")), RPCDoneHandlerPtr(), rpcFail(&SetupChannelBox::onFirstCheckFail));
|
||||
|
||||
_aboutPublicHeight = _aboutPublic.countHeight(_aboutPublicWidth);
|
||||
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public.height() + _aboutPublicHeight + st::newGroupSkip + _private.height() + _aboutPrivate.countHeight(_aboutPublicWidth)/* + st::newGroupSkip + _comments.height() + _aboutComments.countHeight(_aboutPublicWidth)*/ + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top() + _link.height() + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom());
|
||||
updateMaxHeight();
|
||||
|
||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
connect(&_skip, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
@ -669,6 +669,14 @@ void SetupChannelBox::showDone() {
|
|||
_link.setFocus();
|
||||
}
|
||||
|
||||
void SetupChannelBox::updateMaxHeight() {
|
||||
if (!_channel->isMegagroup() || _public.checked()) {
|
||||
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public.height() + _aboutPublicHeight + st::newGroupSkip + _private.height() + _aboutPrivate.countHeight(_aboutPublicWidth)/* + st::newGroupSkip + _comments.height() + _aboutComments.countHeight(_aboutPublicWidth)*/ + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top() + _link.height() + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom());
|
||||
} else {
|
||||
setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public.height() + _aboutPublicHeight + st::newGroupSkip + _private.height() + _aboutPrivate.countHeight(_aboutPublicWidth)/* + st::newGroupSkip + _comments.height() + _aboutComments.countHeight(_aboutPublicWidth)*/ + st::newGroupSkip + st::newGroupPadding.bottom() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom());
|
||||
}
|
||||
}
|
||||
|
||||
void SetupChannelBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
|
||||
if (_link.hasFocus()) {
|
||||
|
@ -699,22 +707,26 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
|
|||
//QRect aboutComments(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadiobutton.textPosition.x(), _comments.y() + _comments.height(), _aboutPublicWidth, _aboutPublicHeight);
|
||||
//_aboutComments.drawLeft(p, aboutComments.x(), aboutComments.y(), aboutComments.width(), width());
|
||||
|
||||
p.setPen(st::black);
|
||||
p.setFont(st::newGroupLinkFont);
|
||||
p.drawTextLeft(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultInputField.textMargins.left(), _link.y() - st::newGroupLinkPadding.top() + st::newGroupLinkTop, width(), lang(_link.isHidden() ? lng_create_group_invite_link : lng_create_group_link));
|
||||
if (!_channel->isMegagroup() || !_link.isHidden()) {
|
||||
p.setPen(st::black);
|
||||
p.setFont(st::newGroupLinkFont);
|
||||
p.drawTextLeft(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultInputField.textMargins.left(), _link.y() - st::newGroupLinkPadding.top() + st::newGroupLinkTop, width(), lang(_link.isHidden() ? lng_create_group_invite_link : lng_create_group_link));
|
||||
}
|
||||
|
||||
if (_link.isHidden()) {
|
||||
QTextOption option(style::al_left);
|
||||
option.setWrapMode(QTextOption::WrapAnywhere);
|
||||
p.setFont(_linkOver ? st::boxTextFont->underline() : st::boxTextFont);
|
||||
p.setPen(st::btnDefLink.color);
|
||||
p.drawText(_invitationLink, _channel->invitationUrl, option);
|
||||
if (!_goodTextLink.isEmpty() && a_goodOpacity.current() > 0) {
|
||||
p.setOpacity(a_goodOpacity.current());
|
||||
p.setPen(st::setGoodColor);
|
||||
p.setFont(st::boxTextFont);
|
||||
p.drawTextRight(st::boxPadding.right(), _link.y() - st::newGroupLinkPadding.top() + st::newGroupLinkTop + st::newGroupLinkFont->ascent - st::boxTextFont->ascent, width(), _goodTextLink);
|
||||
p.setOpacity(1);
|
||||
if (!_channel->isMegagroup()) {
|
||||
QTextOption option(style::al_left);
|
||||
option.setWrapMode(QTextOption::WrapAnywhere);
|
||||
p.setFont(_linkOver ? st::boxTextFont->underline() : st::boxTextFont);
|
||||
p.setPen(st::btnDefLink.color);
|
||||
p.drawText(_invitationLink, _channel->invitationUrl, option);
|
||||
if (!_goodTextLink.isEmpty() && a_goodOpacity.current() > 0) {
|
||||
p.setOpacity(a_goodOpacity.current());
|
||||
p.setPen(st::setGoodColor);
|
||||
p.setFont(st::boxTextFont);
|
||||
p.drawTextRight(st::boxPadding.right(), _link.y() - st::newGroupLinkPadding.top() + st::newGroupLinkTop + st::newGroupLinkFont->ascent - st::boxTextFont->ascent, width(), _goodTextLink);
|
||||
p.setOpacity(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!_errorText.isEmpty()) {
|
||||
|
@ -750,7 +762,7 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
|
||||
mouseMoveEvent(e);
|
||||
if (_linkOver) {
|
||||
App::app()->clipboard()->setText(_channel->invitationUrl);
|
||||
Application::clipboard()->setText(_channel->invitationUrl);
|
||||
_goodTextLink = lang(lng_create_channel_link_copied);
|
||||
a_goodOpacity = anim::fvalue(1, 0);
|
||||
_a_goodFade.start();
|
||||
|
@ -827,7 +839,7 @@ void SetupChannelBox::onChange() {
|
|||
}
|
||||
_checkTimer.stop();
|
||||
} else {
|
||||
int32 i, len = name.size();
|
||||
int32 len = name.size();
|
||||
for (int32 i = 0; i < len; ++i) {
|
||||
QChar ch = name.at(i);
|
||||
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '_') {
|
||||
|
@ -879,6 +891,9 @@ void SetupChannelBox::onPrivacyChange() {
|
|||
_link.hide();
|
||||
setFocus();
|
||||
}
|
||||
if (_channel->isMegagroup()) {
|
||||
updateMaxHeight();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -929,7 +944,10 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
|
|||
|
||||
_checkRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||
if (err == qstr("CHANNEL_PUBLIC_GROUP_NA")) {
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
} else if (err == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
|
||||
if (_existing) {
|
||||
Ui::showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
|
||||
} else {
|
||||
|
@ -938,11 +956,11 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
|
|||
onPrivacyChange();
|
||||
}
|
||||
return true;
|
||||
} else if (err == "USERNAME_INVALID") {
|
||||
} else if (err == qstr("USERNAME_INVALID")) {
|
||||
_errorText = lang(lng_create_channel_link_invalid);
|
||||
update();
|
||||
return true;
|
||||
} else if (err == "USERNAME_OCCUPIED" && _checkUsername != _channel->username) {
|
||||
} else if (err == qstr("USERNAME_OCCUPIED") && _checkUsername != _channel->username) {
|
||||
_errorText = lang(lng_create_channel_link_occupied);
|
||||
update();
|
||||
return true;
|
||||
|
@ -957,7 +975,10 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
|
|||
|
||||
_checkRequestId = 0;
|
||||
QString err(error.type());
|
||||
if (err == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||
if (err == qstr("CHANNEL_PUBLIC_GROUP_NA")) {
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
} else if (err == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
|
||||
if (_existing) {
|
||||
Ui::showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
|
||||
} else {
|
||||
|
@ -1094,7 +1115,8 @@ void EditNameTitleBox::onSave() {
|
|||
}
|
||||
_sentName = first;
|
||||
if (_peer == App::self()) {
|
||||
_requestId = MTP::send(MTPaccount_UpdateProfile(MTP_string(first), MTP_string(last)), rpcDone(&EditNameTitleBox::onSaveSelfDone), rpcFail(&EditNameTitleBox::onSaveSelfFail));
|
||||
MTPaccount_UpdateProfile::Flags flags = MTPaccount_UpdateProfile::Flag::f_first_name | MTPaccount_UpdateProfile::Flag::f_last_name;
|
||||
_requestId = MTP::send(MTPaccount_UpdateProfile(MTP_flags(flags), MTP_string(first), MTP_string(last), MTPstring()), rpcDone(&EditNameTitleBox::onSaveSelfDone), rpcFail(&EditNameTitleBox::onSaveSelfFail));
|
||||
} else if (_peer->isChat()) {
|
||||
_requestId = MTP::send(MTPmessages_EditChatTitle(_peer->asChat()->inputChat, MTP_string(first)), rpcDone(&EditNameTitleBox::onSaveChatDone), rpcFail(&EditNameTitleBox::onSaveChatFail));
|
||||
}
|
||||
|
@ -1150,14 +1172,17 @@ void EditNameTitleBox::onSaveChatDone(const MTPUpdates &updates) {
|
|||
emit closed();
|
||||
}
|
||||
|
||||
EditChannelBox::EditChannelBox(ChannelData *channel) :
|
||||
_channel(channel),
|
||||
_save(this, lang(lng_settings_save), st::defaultBoxButton),
|
||||
_cancel(this, lang(lng_cancel), st::cancelBoxButton),
|
||||
_title(this, st::defaultInputField, lang(lng_dlg_new_channel_name), _channel->name),
|
||||
_description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about),
|
||||
_publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::defaultBoxLinkButton),
|
||||
_saveTitleRequestId(0), _saveDescriptionRequestId(0) {
|
||||
EditChannelBox::EditChannelBox(ChannelData *channel) : AbstractBox()
|
||||
, _channel(channel)
|
||||
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _title(this, st::defaultInputField, lang(lng_dlg_new_channel_name), _channel->name)
|
||||
, _description(this, st::newGroupDescription, lang(lng_create_group_description), _channel->about)
|
||||
, _sign(this, lang(lng_edit_sign_messages), channel->addsSignature())
|
||||
, _publicLink(this, lang(channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link), st::defaultBoxLinkButton)
|
||||
, _saveTitleRequestId(0)
|
||||
, _saveDescriptionRequestId(0)
|
||||
, _saveSignRequestId(0) {
|
||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
|
||||
|
||||
setMouseTracking(true);
|
||||
|
@ -1183,6 +1208,7 @@ _saveTitleRequestId(0), _saveDescriptionRequestId(0) {
|
|||
void EditChannelBox::hideAll() {
|
||||
_title.hide();
|
||||
_description.hide();
|
||||
_sign.hide();
|
||||
_save.hide();
|
||||
_cancel.hide();
|
||||
_publicLink.hide();
|
||||
|
@ -1193,10 +1219,15 @@ void EditChannelBox::showAll() {
|
|||
_description.show();
|
||||
_save.show();
|
||||
_cancel.show();
|
||||
if (_channel->isMegagroup()) {
|
||||
_publicLink.hide();
|
||||
} else {
|
||||
if (_channel->canEditUsername()) {
|
||||
_publicLink.show();
|
||||
} else {
|
||||
_publicLink.hide();
|
||||
}
|
||||
if (_channel->isMegagroup()) {
|
||||
_sign.hide();
|
||||
} else {
|
||||
_sign.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1224,6 +1255,7 @@ void EditChannelBox::paintEvent(QPaintEvent *e) {
|
|||
void EditChannelBox::peerUpdated(PeerData *peer) {
|
||||
if (peer == _channel) {
|
||||
_publicLink.setText(lang(_channel->isPublic() ? lng_profile_edit_public_link : lng_profile_create_public_link));
|
||||
_sign.setChecked(_channel->addsSignature());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1235,7 +1267,12 @@ void EditChannelBox::onDescriptionResized() {
|
|||
void EditChannelBox::updateMaxHeight() {
|
||||
int32 h = st::boxTitleHeight + st::newGroupInfoPadding.top() + _title.height();
|
||||
h += st::newGroupDescriptionPadding.top() + _description.height() + st::newGroupDescriptionPadding.bottom();
|
||||
h += st::newGroupPublicLinkPadding.top() + _publicLink.height() + st::newGroupPublicLinkPadding.bottom();
|
||||
if (!_channel->isMegagroup()) {
|
||||
h += st::newGroupPublicLinkPadding.top() + _sign.height() + st::newGroupPublicLinkPadding.bottom();
|
||||
}
|
||||
if (_channel->canEditUsername()) {
|
||||
h += st::newGroupPublicLinkPadding.top() + _publicLink.height() + st::newGroupPublicLinkPadding.bottom();
|
||||
}
|
||||
h += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom();
|
||||
setMaxHeight(h);
|
||||
}
|
||||
|
@ -1246,14 +1283,20 @@ void EditChannelBox::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
_description.moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _title.y() + _title.height() + st::newGroupDescriptionPadding.top());
|
||||
|
||||
_publicLink.moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description.y() + _description.height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
_sign.moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description.y() + _description.height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
|
||||
if (_channel->isMegagroup()) {
|
||||
_publicLink.moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description.y() + _description.height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
} else {
|
||||
_publicLink.moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign.y() + _sign.height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
|
||||
}
|
||||
|
||||
_save.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save.height());
|
||||
_cancel.moveToRight(st::boxButtonPadding.right() + _save.width() + st::boxButtonPadding.left(), _save.y());
|
||||
}
|
||||
|
||||
void EditChannelBox::onSave() {
|
||||
if (_saveTitleRequestId || _saveDescriptionRequestId) return;
|
||||
if (_saveTitleRequestId || _saveDescriptionRequestId || _saveSignRequestId) return;
|
||||
|
||||
QString title = prepareText(_title.getLastText()), description = prepareText(_description.getLastText(), true);
|
||||
if (title.isEmpty()) {
|
||||
|
@ -1263,7 +1306,11 @@ void EditChannelBox::onSave() {
|
|||
}
|
||||
_sentTitle = title;
|
||||
_sentDescription = description;
|
||||
_saveTitleRequestId = MTP::send(MTPchannels_EditTitle(_channel->inputChannel, MTP_string(_sentTitle)), rpcDone(&EditChannelBox::onSaveTitleDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
if (_sentTitle == _channel->name) {
|
||||
saveDescription();
|
||||
} else {
|
||||
_saveTitleRequestId = MTP::send(MTPchannels_EditTitle(_channel->inputChannel, MTP_string(_sentTitle)), rpcDone(&EditChannelBox::onSaveTitleDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
}
|
||||
}
|
||||
|
||||
void EditChannelBox::onPublicLink() {
|
||||
|
@ -1271,7 +1318,19 @@ void EditChannelBox::onPublicLink() {
|
|||
}
|
||||
|
||||
void EditChannelBox::saveDescription() {
|
||||
_saveDescriptionRequestId = MTP::send(MTPchannels_EditAbout(_channel->inputChannel, MTP_string(_sentDescription)), rpcDone(&EditChannelBox::onSaveDescriptionDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
if (_sentDescription == _channel->about) {
|
||||
saveSign();
|
||||
} else {
|
||||
_saveDescriptionRequestId = MTP::send(MTPchannels_EditAbout(_channel->inputChannel, MTP_string(_sentDescription)), rpcDone(&EditChannelBox::onSaveDescriptionDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
}
|
||||
}
|
||||
|
||||
void EditChannelBox::saveSign() {
|
||||
if (_channel->isMegagroup() || _channel->addsSignature() == _sign.checked()) {
|
||||
onClose();
|
||||
} else {
|
||||
_saveSignRequestId = MTP::send(MTPchannels_ToggleSignatures(_channel->inputChannel, MTP_bool(_sign.checked())), rpcDone(&EditChannelBox::onSaveSignDone), rpcFail(&EditChannelBox::onSaveFail));
|
||||
}
|
||||
}
|
||||
|
||||
bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
|
||||
|
@ -1295,24 +1354,46 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
|
|||
_saveDescriptionRequestId = 0;
|
||||
if (err == qstr("CHAT_ABOUT_NOT_MODIFIED")) {
|
||||
_channel->about = _sentDescription;
|
||||
if (App::api()) emit App::api()->fullPeerUpdated(_channel);
|
||||
onClose();
|
||||
if (App::api()) {
|
||||
emit App::api()->fullPeerUpdated(_channel);
|
||||
}
|
||||
saveSign();
|
||||
return true;
|
||||
} else {
|
||||
_description.setFocus();
|
||||
}
|
||||
} else if (req == _saveSignRequestId) {
|
||||
_saveSignRequestId = 0;
|
||||
if (err == qstr("CHAT_NOT_MODIFIED")) {
|
||||
onClose();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveTitleDone(const MTPUpdates &updates) {
|
||||
_saveTitleRequestId = 0;
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
if (App::main()) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
saveDescription();
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveDescriptionDone(const MTPBool &result) {
|
||||
_saveDescriptionRequestId = 0;
|
||||
_channel->about = _sentDescription;
|
||||
if (App::api()) emit App::api()->fullPeerUpdated(_channel);
|
||||
if (App::api()) {
|
||||
emit App::api()->fullPeerUpdated(_channel);
|
||||
}
|
||||
saveSign();
|
||||
}
|
||||
|
||||
void EditChannelBox::onSaveSignDone(const MTPUpdates &updates) {
|
||||
_saveSignRequestId = 0;
|
||||
if (App::main()) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
onClose();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -211,6 +211,8 @@ private:
|
|||
bool onCheckFail(const RPCError &error);
|
||||
bool onFirstCheckFail(const RPCError &error);
|
||||
|
||||
void updateMaxHeight();
|
||||
|
||||
ChannelData *_channel;
|
||||
bool _existing;
|
||||
|
||||
|
@ -315,18 +317,21 @@ private:
|
|||
|
||||
void onSaveTitleDone(const MTPUpdates &updates);
|
||||
void onSaveDescriptionDone(const MTPBool &result);
|
||||
void onSaveSignDone(const MTPUpdates &updates);
|
||||
bool onSaveFail(const RPCError &e, mtpRequestId req);
|
||||
|
||||
void saveDescription();
|
||||
void saveSign();
|
||||
|
||||
ChannelData *_channel;
|
||||
|
||||
BoxButton _save, _cancel;
|
||||
InputField _title;
|
||||
InputArea _description;
|
||||
Checkbox _sign;
|
||||
|
||||
LinkButton _publicLink;
|
||||
|
||||
mtpRequestId _saveTitleRequestId, _saveDescriptionRequestId;
|
||||
mtpRequestId _saveTitleRequestId, _saveDescriptionRequestId, _saveSignRequestId;
|
||||
QString _sentTitle, _sentDescription;
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -34,19 +34,19 @@ TextParseOptions _confirmBoxTextOptions = {
|
|||
Qt::LayoutDirectionAuto, // dir
|
||||
};
|
||||
|
||||
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, const QString &cancelText, const style::BoxButton &cancelStyle) : AbstractBox(st::boxWidth),
|
||||
_informative(false),
|
||||
_text(100),
|
||||
_confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle),
|
||||
_cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, cancelStyle) {
|
||||
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, const QString &cancelText, const style::BoxButton &cancelStyle) : AbstractBox(st::boxWidth)
|
||||
, _informative(false)
|
||||
, _text(100)
|
||||
, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle)
|
||||
, _cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, cancelStyle) {
|
||||
init(text);
|
||||
}
|
||||
|
||||
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, bool informative) : AbstractBox(st::boxWidth),
|
||||
_informative(true),
|
||||
_text(100),
|
||||
_confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle),
|
||||
_cancel(this, QString(), st::cancelBoxButton) {
|
||||
ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, bool informative) : AbstractBox(st::boxWidth)
|
||||
, _informative(true)
|
||||
, _text(100)
|
||||
, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle)
|
||||
, _cancel(this, QString(), st::cancelBoxButton) {
|
||||
init(text);
|
||||
}
|
||||
|
||||
|
@ -83,33 +83,30 @@ void ConfirmBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
void ConfirmBox::mousePressEvent(QMouseEvent *e) {
|
||||
_lastMousePos = e->globalPos();
|
||||
updateHover();
|
||||
if (textlnkOver()) {
|
||||
textlnkDown(textlnkOver());
|
||||
update();
|
||||
}
|
||||
ClickHandler::pressed();
|
||||
return LayeredWidget::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void ConfirmBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_lastMousePos = e->globalPos();
|
||||
updateHover();
|
||||
if (textlnkOver() && textlnkOver() == textlnkDown()) {
|
||||
if (ClickHandlerPtr activated = ClickHandler::unpressed()) {
|
||||
Ui::hideLayer();
|
||||
textlnkOver()->onClick(e->button());
|
||||
App::activateClickHandler(activated, e->button());
|
||||
}
|
||||
textlnkDown(TextLinkPtr());
|
||||
}
|
||||
|
||||
void ConfirmBox::leaveEvent(QEvent *e) {
|
||||
if (_myLink) {
|
||||
if (textlnkOver() == _myLink) {
|
||||
textlnkOver(TextLinkPtr());
|
||||
update();
|
||||
}
|
||||
_myLink = TextLinkPtr();
|
||||
setCursor(style::cur_default);
|
||||
update();
|
||||
}
|
||||
ClickHandler::clearActive(this);
|
||||
}
|
||||
|
||||
void ConfirmBox::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||
setCursor(active ? style::cur_pointer : style::cur_default);
|
||||
update();
|
||||
}
|
||||
|
||||
void ConfirmBox::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
||||
update();
|
||||
}
|
||||
|
||||
void ConfirmBox::updateLink() {
|
||||
|
@ -119,17 +116,12 @@ void ConfirmBox::updateLink() {
|
|||
|
||||
void ConfirmBox::updateHover() {
|
||||
QPoint m(mapFromGlobal(_lastMousePos));
|
||||
bool wasMy = (_myLink == textlnkOver());
|
||||
|
||||
textstyleSet(&st::boxTextStyle);
|
||||
_myLink = _text.linkLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width(), (_text.maxWidth() < width()) ? style::al_center : style::al_left);
|
||||
ClickHandlerPtr handler = _text.linkLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width(), style::al_left);
|
||||
textstyleRestore();
|
||||
if (_myLink != textlnkOver()) {
|
||||
if (wasMy || _myLink || rect().contains(m)) {
|
||||
textlnkOver(_myLink);
|
||||
}
|
||||
setCursor(_myLink ? style::cur_pointer : style::cur_default);
|
||||
update();
|
||||
}
|
||||
|
||||
ClickHandler::setActive(handler, this);
|
||||
}
|
||||
|
||||
void ConfirmBox::closePressed() {
|
||||
|
@ -174,22 +166,29 @@ void ConfirmBox::resizeEvent(QResizeEvent *e) {
|
|||
_cancel.moveToRight(st::boxButtonPadding.right() + _confirm.width() + st::boxButtonPadding.left(), _confirm.y());
|
||||
}
|
||||
|
||||
ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_this_link) + qsl("\n\n") + url, lang(lng_open_link)), _url(url) {
|
||||
SharePhoneConfirmBox::SharePhoneConfirmBox(PeerData *recipient)
|
||||
: ConfirmBox(lang(lng_bot_share_phone), lang(lng_bot_share_phone_confirm))
|
||||
, _recipient(recipient) {
|
||||
connect(this, SIGNAL(confirmed()), this, SLOT(onConfirm()));
|
||||
}
|
||||
|
||||
void SharePhoneConfirmBox::onConfirm() {
|
||||
emit confirmed(_recipient);
|
||||
}
|
||||
|
||||
ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_this_link) + qsl("\n\n") + url, lang(lng_open_link))
|
||||
, _url(url) {
|
||||
connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink()));
|
||||
}
|
||||
|
||||
void ConfirmLinkBox::onOpenLink() {
|
||||
if (reMailStart().match(_url).hasMatch()) {
|
||||
EmailLink(_url).onClick(Qt::LeftButton);
|
||||
} else {
|
||||
TextLink(_url).onClick(Qt::LeftButton);
|
||||
}
|
||||
Ui::hideLayer();
|
||||
UrlClickHandler::doOpen(_url);
|
||||
}
|
||||
|
||||
MaxInviteBox::MaxInviteBox(const QString &link) : AbstractBox(st::boxWidth)
|
||||
, _close(this, lang(lng_box_ok), st::defaultBoxButton)
|
||||
, _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, cMaxGroupCount()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
|
||||
, _text(st::boxTextFont, lng_participant_invite_sorry(lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right())
|
||||
, _link(link)
|
||||
, _linkOver(false)
|
||||
, a_goodOpacity(0, 0)
|
||||
|
@ -212,7 +211,7 @@ void MaxInviteBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
|
||||
mouseMoveEvent(e);
|
||||
if (_linkOver) {
|
||||
App::app()->clipboard()->setText(_link);
|
||||
Application::clipboard()->setText(_link);
|
||||
_goodTextLink = lang(lng_create_channel_link_copied);
|
||||
a_goodOpacity = anim::fvalue(1, 0);
|
||||
_a_good.start();
|
||||
|
@ -279,3 +278,228 @@ void MaxInviteBox::resizeEvent(QResizeEvent *e) {
|
|||
_close.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close.height());
|
||||
_invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height, width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height);
|
||||
}
|
||||
|
||||
ConvertToSupergroupBox::ConvertToSupergroupBox(ChatData *chat) : AbstractBox(st::boxWideWidth)
|
||||
, _chat(chat)
|
||||
, _text(100)
|
||||
, _note(100)
|
||||
, _convert(this, lang(lng_profile_convert_confirm), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||
QStringList text;
|
||||
text.push_back(lang(lng_profile_convert_feature1));
|
||||
text.push_back(lang(lng_profile_convert_feature2));
|
||||
text.push_back(lang(lng_profile_convert_feature3));
|
||||
text.push_back(lang(lng_profile_convert_feature4));
|
||||
|
||||
textstyleSet(&st::boxTextStyle);
|
||||
_text.setText(st::boxTextFont, text.join('\n'), _confirmBoxTextOptions);
|
||||
_note.setText(st::boxTextFont, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions);
|
||||
_textWidth = st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right();
|
||||
_textHeight = _text.countHeight(_textWidth);
|
||||
setMaxHeight(st::boxTitleHeight + _textHeight + st::boxPadding.bottom() + _note.countHeight(_textWidth) + st::boxButtonPadding.top() + _convert.height() + st::boxButtonPadding.bottom());
|
||||
textstyleRestore();
|
||||
|
||||
connect(&_convert, SIGNAL(clicked()), this, SLOT(onConvert()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::onConvert() {
|
||||
MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail));
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) {
|
||||
Ui::hideLayer();
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
const QVector<MTPChat> *v = 0;
|
||||
switch (updates.type()) {
|
||||
case mtpc_updates: v = &updates.c_updates().vchats.c_vector().v; break;
|
||||
case mtpc_updatesCombined: v = &updates.c_updatesCombined().vchats.c_vector().v; break;
|
||||
default: LOG(("API Error: unexpected update cons %1 (ConvertToSupergroupBox::convertDone)").arg(updates.type())); break;
|
||||
}
|
||||
|
||||
PeerData *peer = 0;
|
||||
if (v && !v->isEmpty()) {
|
||||
for (int32 i = 0, l = v->size(); i < l; ++i) {
|
||||
if (v->at(i).type() == mtpc_channel) {
|
||||
peer = App::channel(v->at(i).c_channel().vid.v);
|
||||
Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
|
||||
QTimer::singleShot(ReloadChannelMembersTimeout, App::api(), SLOT(delayedRequestParticipantsCount()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!peer) {
|
||||
LOG(("API Error: channel not found in updates (ProfileInner::migrateDone)"));
|
||||
}
|
||||
}
|
||||
|
||||
bool ConvertToSupergroupBox::convertFail(const RPCError &error) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::hideAll() {
|
||||
_convert.hide();
|
||||
_cancel.hide();
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::showAll() {
|
||||
_convert.show();
|
||||
_cancel.show();
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
|
||||
onConvert();
|
||||
} else {
|
||||
AbstractBox::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (paint(p)) return;
|
||||
|
||||
paintTitle(p, lang(lng_profile_convert_title));
|
||||
|
||||
// draw box title / text
|
||||
p.setPen(st::black);
|
||||
textstyleSet(&st::boxTextStyle);
|
||||
_text.drawLeft(p, st::boxPadding.left(), st::boxTitleHeight, _textWidth, width());
|
||||
_note.drawLeft(p, st::boxPadding.left(), st::boxTitleHeight + _textHeight + st::boxPadding.bottom(), _textWidth, width());
|
||||
textstyleRestore();
|
||||
}
|
||||
|
||||
void ConvertToSupergroupBox::resizeEvent(QResizeEvent *e) {
|
||||
_convert.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _convert.height());
|
||||
_cancel.moveToRight(st::boxButtonPadding.right() + _convert.width() + st::boxButtonPadding.left(), _convert.y());
|
||||
}
|
||||
|
||||
PinMessageBox::PinMessageBox(ChannelData *channel, MsgId msgId) : AbstractBox(st::boxWidth)
|
||||
, _channel(channel)
|
||||
, _msgId(msgId)
|
||||
, _text(this, lang(lng_pinned_pin_sure), st::boxLabel)
|
||||
, _notify(this, lang(lng_pinned_notify), true)
|
||||
, _pin(this, lang(lng_pinned_pin), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _requestId(0) {
|
||||
_text.resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
|
||||
setMaxHeight(st::boxPadding.top() + _text.height() + st::boxMediumSkip + _notify.height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _pin.height() + st::boxButtonPadding.bottom());
|
||||
|
||||
connect(&_pin, SIGNAL(clicked()), this, SLOT(onPin()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
}
|
||||
|
||||
void PinMessageBox::resizeEvent(QResizeEvent *e) {
|
||||
_text.moveToLeft(st::boxPadding.left(), st::boxPadding.top());
|
||||
_notify.moveToLeft(st::boxPadding.left(), _text.y() + _text.height() + st::boxMediumSkip);
|
||||
_pin.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _pin.height());
|
||||
_cancel.moveToRight(st::boxButtonPadding.right() + _pin.width() + st::boxButtonPadding.left(), _pin.y());
|
||||
}
|
||||
|
||||
void PinMessageBox::onPin() {
|
||||
if (_requestId) return;
|
||||
|
||||
MTPchannels_UpdatePinnedMessage::Flags flags = 0;
|
||||
if (_notify.checked()) {
|
||||
flags |= MTPchannels_UpdatePinnedMessage::Flag::f_silent;
|
||||
}
|
||||
_requestId = MTP::send(MTPchannels_UpdatePinnedMessage(MTP_flags(flags), _channel->inputChannel, MTP_int(_msgId)), rpcDone(&PinMessageBox::pinDone), rpcFail(&PinMessageBox::pinFail));
|
||||
}
|
||||
|
||||
void PinMessageBox::showAll() {
|
||||
_text.show();
|
||||
_notify.show();
|
||||
_pin.show();
|
||||
_cancel.show();
|
||||
}
|
||||
|
||||
void PinMessageBox::hideAll() {
|
||||
_text.hide();
|
||||
_notify.hide();
|
||||
_pin.hide();
|
||||
_cancel.hide();
|
||||
}
|
||||
|
||||
void PinMessageBox::pinDone(const MTPUpdates &updates) {
|
||||
if (App::main()) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
Ui::hideLayer();
|
||||
}
|
||||
|
||||
bool PinMessageBox::pinFail(const RPCError &error) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
Ui::hideLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId) : AbstractBox(st::boxWidth)
|
||||
, _channel(channel)
|
||||
, _from(from)
|
||||
, _msgId(msgId)
|
||||
, _text(this, lang(lng_selected_delete_sure_this), st::boxLabel)
|
||||
, _banUser(this, lang(lng_ban_user), false)
|
||||
, _reportSpam(this, lang(lng_report_spam), false)
|
||||
, _deleteAll(this, lang(lng_delete_all_from), false)
|
||||
, _delete(this, lang(lng_box_delete), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
|
||||
t_assert(_channel != nullptr);
|
||||
|
||||
_text.resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right());
|
||||
setMaxHeight(st::boxPadding.top() + _text.height() + st::boxMediumSkip + _banUser.height() + st::boxLittleSkip + _reportSpam.height() + st::boxLittleSkip + _deleteAll.height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _delete.height() + st::boxButtonPadding.bottom());
|
||||
|
||||
connect(&_delete, SIGNAL(clicked()), this, SLOT(onDelete()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
}
|
||||
|
||||
void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) {
|
||||
_text.moveToLeft(st::boxPadding.left(), st::boxPadding.top());
|
||||
_banUser.moveToLeft(st::boxPadding.left(), _text.y() + _text.height() + st::boxMediumSkip);
|
||||
_reportSpam.moveToLeft(st::boxPadding.left(), _banUser.y() + _banUser.height() + st::boxLittleSkip);
|
||||
_deleteAll.moveToLeft(st::boxPadding.left(), _reportSpam.y() + _reportSpam.height() + st::boxLittleSkip);
|
||||
_delete.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete.height());
|
||||
_cancel.moveToRight(st::boxButtonPadding.right() + _delete.width() + st::boxButtonPadding.left(), _delete.y());
|
||||
}
|
||||
|
||||
void RichDeleteMessageBox::onDelete() {
|
||||
if (_banUser.checked()) {
|
||||
MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), App::main()->rpcDone(&MainWidget::sentUpdatesReceived));
|
||||
}
|
||||
if (_reportSpam.checked()) {
|
||||
MTP::send(MTPchannels_ReportSpam(_channel->inputChannel, _from->inputUser, MTP_vector<MTPint>(1, MTP_int(_msgId))));
|
||||
}
|
||||
if (_deleteAll.checked()) {
|
||||
App::main()->deleteAllFromUser(_channel, _from);
|
||||
}
|
||||
if (HistoryItem *item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) {
|
||||
bool wasLast = (item->history()->lastMsg == item);
|
||||
item->destroy();
|
||||
if (_msgId > 0) {
|
||||
App::main()->deleteMessages(_channel, QVector<MTPint>(1, MTP_int(_msgId)));
|
||||
} else if (wasLast) {
|
||||
App::main()->checkPeerHistory(_channel);
|
||||
}
|
||||
}
|
||||
Ui::hideLayer();
|
||||
}
|
||||
|
||||
void RichDeleteMessageBox::showAll() {
|
||||
_text.show();
|
||||
_banUser.show();
|
||||
_reportSpam.show();
|
||||
_deleteAll.show();
|
||||
_delete.show();
|
||||
_cancel.show();
|
||||
}
|
||||
|
||||
void RichDeleteMessageBox::hideAll() {
|
||||
_text.hide();
|
||||
_banUser.hide();
|
||||
_reportSpam.hide();
|
||||
_deleteAll.hide();
|
||||
_delete.hide();
|
||||
_cancel.hide();
|
||||
}
|
||||
|
|
|
@ -16,14 +16,14 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "abstractbox.h"
|
||||
|
||||
class InformBox;
|
||||
class ConfirmBox : public AbstractBox {
|
||||
class ConfirmBox : public AbstractBox, public ClickHandlerHost {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -38,6 +38,10 @@ public:
|
|||
void leaveEvent(QEvent *e);
|
||||
void updateLink();
|
||||
|
||||
// ClickHandlerHost interface
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active);
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed);
|
||||
|
||||
public slots:
|
||||
|
||||
void onCancel();
|
||||
|
@ -69,7 +73,6 @@ private:
|
|||
void updateHover();
|
||||
|
||||
QPoint _lastMousePos;
|
||||
TextLinkPtr _myLink;
|
||||
|
||||
BoxButton _confirm, _cancel;
|
||||
};
|
||||
|
@ -80,6 +83,23 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class SharePhoneConfirmBox : public ConfirmBox {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SharePhoneConfirmBox(PeerData *recipient);
|
||||
|
||||
signals:
|
||||
void confirmed(PeerData *recipient);
|
||||
|
||||
private slots:
|
||||
void onConfirm();
|
||||
|
||||
private:
|
||||
PeerData *_recipient;
|
||||
|
||||
};
|
||||
|
||||
class ConfirmLinkBox : public ConfirmBox {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -133,3 +153,100 @@ private:
|
|||
anim::fvalue a_goodOpacity;
|
||||
Animation _a_good;
|
||||
};
|
||||
|
||||
class ConvertToSupergroupBox : public AbstractBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ConvertToSupergroupBox(ChatData *chat);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
public slots:
|
||||
|
||||
void onConvert();
|
||||
|
||||
protected:
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
|
||||
private:
|
||||
|
||||
void convertDone(const MTPUpdates &updates);
|
||||
bool convertFail(const RPCError &error);
|
||||
|
||||
ChatData *_chat;
|
||||
Text _text, _note;
|
||||
int32 _textWidth, _textHeight;
|
||||
|
||||
BoxButton _convert, _cancel;
|
||||
};
|
||||
|
||||
class PinMessageBox : public AbstractBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
PinMessageBox(ChannelData *channel, MsgId msgId);
|
||||
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
public slots:
|
||||
|
||||
void onPin();
|
||||
|
||||
protected:
|
||||
|
||||
void showAll();
|
||||
void hideAll();
|
||||
|
||||
private:
|
||||
|
||||
void pinDone(const MTPUpdates &updates);
|
||||
bool pinFail(const RPCError &error);
|
||||
|
||||
ChannelData *_channel;
|
||||
MsgId _msgId;
|
||||
|
||||
FlatLabel _text;
|
||||
Checkbox _notify;
|
||||
|
||||
BoxButton _pin, _cancel;
|
||||
|
||||
mtpRequestId _requestId;
|
||||
|
||||
};
|
||||
|
||||
class RichDeleteMessageBox : public AbstractBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId);
|
||||
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
public slots:
|
||||
|
||||
void onDelete();
|
||||
|
||||
protected:
|
||||
|
||||
void showAll();
|
||||
void hideAll();
|
||||
|
||||
private:
|
||||
|
||||
ChannelData *_channel;
|
||||
UserData *_from;
|
||||
MsgId _msgId;
|
||||
|
||||
FlatLabel _text;
|
||||
Checkbox _banUser, _reportSpam, _deleteAll;
|
||||
|
||||
BoxButton _delete, _cancel;
|
||||
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -201,8 +201,10 @@ void ConnectionBox::onSave() {
|
|||
} else {
|
||||
cSetConnectionType(dbictAuto);
|
||||
cSetConnectionProxy(ConnectionProxy());
|
||||
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(false);
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
#endif
|
||||
}
|
||||
if (cPlatform() == dbipWindows && cTryIPv6() != _tryIPv6.checked()) {
|
||||
cSetTryIPv6(_tryIPv6.checked());
|
||||
|
@ -313,9 +315,11 @@ void AutoDownloadBox::onSave() {
|
|||
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
|
||||
cSetAutoDownloadAudio(autoDownloadAudio);
|
||||
if (enabledPrivate || enabledGroups) {
|
||||
const AudiosData &data(App::audiosData());
|
||||
for (AudiosData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
const DocumentsData &data(App::documentsData());
|
||||
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
if (i.value()->voice()) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
|
@ -328,7 +332,9 @@ void AutoDownloadBox::onSave() {
|
|||
if (enabledPrivate || enabledGroups) {
|
||||
const DocumentsData &data(App::documentsData());
|
||||
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
if (i.value()->isAnimation()) {
|
||||
i.value()->automaticLoadSettingsChanged();
|
||||
}
|
||||
}
|
||||
Notify::automaticLoadSettingsChangedGif();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -33,6 +33,10 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "confirmbox.h"
|
||||
|
||||
QString cantInviteError() {
|
||||
return lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info)));
|
||||
}
|
||||
|
||||
ContactsInner::ContactsInner(CreatingGroupType creating) : TWidget()
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _newItemHeight(creating == CreatingGroupNone ? st::contactsNewItemHeight : 0)
|
||||
|
@ -224,7 +228,7 @@ void ContactsInner::onPeerNameChanged(PeerData *peer, const PeerData::Names &old
|
|||
|
||||
void ContactsInner::onAddBot() {
|
||||
if (_bot->botInfo && !_bot->botInfo->startGroupToken.isEmpty()) {
|
||||
MTP::send(MTPmessages_StartBot(_bot->inputUser, _addToPeer->input, MTP_long(MTP::nonce<uint64>()), MTP_string(_bot->botInfo->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _bot));
|
||||
MTP::send(MTPmessages_StartBot(_bot->inputUser, _addToPeer->input, MTP_long(rand_value<uint64>()), MTP_string(_bot->botInfo->startGroupToken)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::addParticipantFail, _bot));
|
||||
} else {
|
||||
App::main()->addParticipants(_addToPeer, QVector<UserData*>(1, _bot));
|
||||
}
|
||||
|
@ -257,6 +261,18 @@ void ContactsInner::addAdminDone(const MTPUpdates &result, mtpRequestId req) {
|
|||
if (req != _addAdminRequestId) return;
|
||||
|
||||
_addAdminRequestId = 0;
|
||||
if (_addAdmin && _channel && _channel->isMegagroup()) {
|
||||
if (_channel->mgInfo->lastParticipants.indexOf(_addAdmin) < 0) {
|
||||
_channel->mgInfo->lastParticipants.push_front(_addAdmin);
|
||||
}
|
||||
_channel->mgInfo->lastAdmins.insert(_addAdmin);
|
||||
if (_addAdmin->botInfo) {
|
||||
_channel->mgInfo->bots.insert(_addAdmin);
|
||||
if (_channel->mgInfo->botStatus != 0 && _channel->mgInfo->botStatus < 2) {
|
||||
_channel->mgInfo->botStatus = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_addAdminBox) _addAdminBox->onClose();
|
||||
emit adminAdded();
|
||||
}
|
||||
|
@ -272,6 +288,8 @@ bool ContactsInner::addAdminFail(const RPCError &error, mtpRequestId req) {
|
|||
Ui::showLayer(new MaxInviteBox(_channel->invitationUrl), KeepOtherLayers);
|
||||
} else if (error.type() == "ADMINS_TOO_MUCH") {
|
||||
Ui::showLayer(new InformBox(lang(lng_channel_admins_too_much)), KeepOtherLayers);
|
||||
} else if (error.type() == qstr("USER_RESTRICTED")) {
|
||||
Ui::showLayer(new InformBox(lang(lng_cant_do_this)), KeepOtherLayers);
|
||||
} else {
|
||||
emit adminAdded();
|
||||
}
|
||||
|
@ -350,7 +368,7 @@ void ContactsInner::loadProfilePhotos(int32 yFrom) {
|
|||
preloadFrom != _contacts->list.end && (_newItemHeight + preloadFrom->pos * _rowHeight) < yTo;
|
||||
preloadFrom = preloadFrom->next
|
||||
) {
|
||||
preloadFrom->history->peer->photo->load();
|
||||
preloadFrom->history->peer->loadUserpic();
|
||||
}
|
||||
}
|
||||
} else if (!_filtered.isEmpty()) {
|
||||
|
@ -361,7 +379,7 @@ void ContactsInner::loadProfilePhotos(int32 yFrom) {
|
|||
if (to > _filtered.size()) to = _filtered.size();
|
||||
|
||||
for (; from < to; ++from) {
|
||||
_filtered[from]->history->peer->photo->load();
|
||||
_filtered[from]->history->peer->loadUserpic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -427,13 +445,13 @@ void ContactsInner::paintDialog(Painter &p, PeerData *peer, ContactData *data, b
|
|||
sel = false;
|
||||
}
|
||||
} else {
|
||||
if (data->inchat || data->check || selectedCount() >= ((_channel && _channel->isMegagroup()) ? cMaxMegaGroupCount() : cMaxGroupCount())) {
|
||||
if (data->inchat || data->check || selectedCount() >= Global::MegagroupSizeMax()) {
|
||||
sel = false;
|
||||
}
|
||||
}
|
||||
p.fillRect(0, 0, width(), _rowHeight, inverse ? st::contactsBgActive : (sel ? st::contactsBgOver : st::white));
|
||||
p.setPen(inverse ? st::white : st::black);
|
||||
p.drawPixmapLeft(st::contactsPadding.left(), st::contactsPadding.top(), width(), peer->photo->pix(st::contactsPhotoSize));
|
||||
peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
|
||||
|
||||
int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
int32 iconw = (_chat || _creating != CreatingGroupNone) ? (st::contactsCheckPosition.x() * 2 + st::contactsCheckIcon.pxWidth()) : 0;
|
||||
|
@ -767,10 +785,14 @@ void ContactsInner::changeCheckState(ContactData *data, PeerData *peer) {
|
|||
data->check = false;
|
||||
_checkedContacts.remove(peer);
|
||||
--_selCount;
|
||||
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? cMaxMegaGroupCount() : cMaxGroupCount())) {
|
||||
} else if (selectedCount() < ((_channel && _channel->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
|
||||
data->check = true;
|
||||
_checkedContacts.insert(peer, true);
|
||||
++_selCount;
|
||||
} else if (_channel && !_channel->isMegagroup()) {
|
||||
Ui::showLayer(new MaxInviteBox(_channel->invitationUrl), KeepOtherLayers);
|
||||
} else if (!_channel && selectedCount() >= Global::ChatSizeMax() && selectedCount() < Global::MegagroupSizeMax()) {
|
||||
Ui::showLayer(new InformBox(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())), KeepOtherLayers);
|
||||
}
|
||||
if (cnt != _selCount) emit chosenChanged();
|
||||
}
|
||||
|
@ -1535,7 +1557,7 @@ void ContactsBox::paintEvent(QPaintEvent *e) {
|
|||
paintTitle(p, lang(lng_channel_admins));
|
||||
} else if (_inner.chat() || _inner.creating() != CreatingGroupNone) {
|
||||
QString title(lang(addingAdmin ? lng_channel_add_admin : lng_profile_add_participant));
|
||||
QString additional(addingAdmin ? QString() : QString("%1 / %2").arg(_inner.selectedCount()).arg(((_inner.channel() && _inner.channel()->isMegagroup()) ? cMaxMegaGroupCount() : cMaxGroupCount())));
|
||||
QString additional((addingAdmin || (_inner.channel() && !_inner.channel()->isMegagroup())) ? QString() : QString("%1 / %2").arg(_inner.selectedCount()).arg(Global::MegagroupSizeMax()));
|
||||
paintTitle(p, title, additional);
|
||||
} else if (_inner.bot()) {
|
||||
paintTitle(p, lang(lng_bot_choose_group));
|
||||
|
@ -1652,12 +1674,15 @@ void ContactsBox::getAdminsDone(const MTPmessages_ChatFull &result) {
|
|||
}
|
||||
}
|
||||
_saveRequestId = 0;
|
||||
for (ChatData::Admins::const_iterator i = curadmins.cbegin(), e = curadmins.cend(); i != e; ++i) {
|
||||
MTP::send(MTPmessages_EditChatAdmin(_inner.chat()->inputChat, i.key()->inputUser, MTP_boolFalse()), rpcDone(&ContactsBox::removeAdminDone, i.key()), rpcFail(&ContactsBox::editAdminFail), 0, (appoint.isEmpty() && i + 1 == e) ? 0 : 10);
|
||||
|
||||
for_const (UserData *user, curadmins) {
|
||||
MTP::send(MTPmessages_EditChatAdmin(_inner.chat()->inputChat, user->inputUser, MTP_boolFalse()), rpcDone(&ContactsBox::removeAdminDone, user), rpcFail(&ContactsBox::editAdminFail), 0, 10);
|
||||
}
|
||||
for (int32 i = 0, l = appoint.size(); i < l; ++i) {
|
||||
MTP::send(MTPmessages_EditChatAdmin(_inner.chat()->inputChat, appoint.at(i)->inputUser, MTP_boolTrue()), rpcDone(&ContactsBox::setAdminDone, appoint.at(i)), rpcFail(&ContactsBox::editAdminFail), 0, (i + 1 == l) ? 0 : 10);
|
||||
for_const (UserData *user, appoint) {
|
||||
MTP::send(MTPmessages_EditChatAdmin(_inner.chat()->inputChat, user->inputUser, MTP_boolTrue()), rpcDone(&ContactsBox::setAdminDone, user), rpcFail(&ContactsBox::editAdminFail), 0, 10);
|
||||
}
|
||||
MTP::sendAnything();
|
||||
|
||||
_saveRequestId = curadmins.size() + appoint.size();
|
||||
if (!_saveRequestId) {
|
||||
onClose();
|
||||
|
@ -1669,7 +1694,7 @@ void ContactsBox::setAdminDone(UserData *user, const MTPBool &result) {
|
|||
if (_inner.chat()->noParticipantInfo()) {
|
||||
App::api()->requestFullPeer(_inner.chat());
|
||||
} else {
|
||||
_inner.chat()->admins.insert(user, true);
|
||||
_inner.chat()->admins.insert(user);
|
||||
}
|
||||
}
|
||||
--_saveRequestId;
|
||||
|
@ -1704,7 +1729,13 @@ bool ContactsBox::editAdminFail(const RPCError &error) {
|
|||
if (mtpIsFlood(error)) return true;
|
||||
--_saveRequestId;
|
||||
_inner.chat()->invalidateParticipants();
|
||||
if (!_saveRequestId) onClose();
|
||||
if (!_saveRequestId) {
|
||||
if (error.type() == qstr("USER_RESTRICTED")) {
|
||||
Ui::showLayer(new InformBox(lang(lng_cant_do_this)));
|
||||
return true;
|
||||
}
|
||||
onClose();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1749,7 +1780,10 @@ bool ContactsBox::creationFail(const RPCError &error) {
|
|||
_filter.showError();
|
||||
return true;
|
||||
} else if (error.type() == "PEER_FLOOD") {
|
||||
Ui::showLayer(new InformBox(lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)))), KeepOtherLayers);
|
||||
Ui::showLayer(new InformBox(cantInviteError()), KeepOtherLayers);
|
||||
return true;
|
||||
} else if (error.type() == qstr("USER_RESTRICTED")) {
|
||||
Ui::showLayer(new InformBox(lang(lng_cant_do_this)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1757,7 +1791,7 @@ bool ContactsBox::creationFail(const RPCError &error) {
|
|||
|
||||
MembersInner::MembersInner(ChannelData *channel, MembersFilter filter) : TWidget()
|
||||
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
|
||||
, _newItemHeight((channel->amCreator() && (channel->count < (channel->isMegagroup() ? cMaxMegaGroupCount() : cMaxGroupCount()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilterAdmins)) ? st::contactsNewItemHeight : 0)
|
||||
, _newItemHeight((channel->amCreator() && (channel->count < (channel->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax()) || (!channel->isMegagroup() && !channel->isPublic()) || filter == MembersFilterAdmins)) ? st::contactsNewItemHeight : 0)
|
||||
, _newItemSel(false)
|
||||
, _channel(channel)
|
||||
, _filter(filter)
|
||||
|
@ -1787,7 +1821,7 @@ MembersInner::MembersInner(ChannelData *channel, MembersFilter filter) : TWidget
|
|||
|
||||
void MembersInner::load() {
|
||||
if (!_loadingRequestId) {
|
||||
_loadingRequestId = MTP::send(MTPchannels_GetParticipants(_channel->inputChannel, (_filter == MembersFilterRecent) ? MTP_channelParticipantsRecent() : MTP_channelParticipantsAdmins(), MTP_int(0), MTP_int(cMaxGroupCount())), rpcDone(&MembersInner::membersReceived), rpcFail(&MembersInner::membersFailed));
|
||||
_loadingRequestId = MTP::send(MTPchannels_GetParticipants(_channel->inputChannel, (_filter == MembersFilterRecent) ? MTP_channelParticipantsRecent() : MTP_channelParticipantsAdmins(), MTP_int(0), MTP_int(Global::ChatSizeMax())), rpcDone(&MembersInner::membersReceived), rpcFail(&MembersInner::membersFailed));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1826,7 +1860,7 @@ void MembersInner::paintEvent(QPaintEvent *e) {
|
|||
paintDialog(p, _rows[from], data(from), sel, kickSel, kickDown);
|
||||
p.translate(0, _rowHeight);
|
||||
}
|
||||
if (to == _rows.size() && _filter == MembersFilterRecent && (_rows.size() < _channel->count || _rows.size() >= cMaxGroupCount())) {
|
||||
if (to == _rows.size() && _filter == MembersFilterRecent && (_rows.size() < _channel->count || _rows.size() >= Global::ChatSizeMax())) {
|
||||
p.setPen(st::stickersReorderFg);
|
||||
_about.draw(p, st::contactsPadding.left(), st::stickersReorderPadding.top(), _aboutWidth, style::al_center);
|
||||
}
|
||||
|
@ -1895,7 +1929,7 @@ void MembersInner::paintDialog(Painter &p, PeerData *peer, MemberData *data, boo
|
|||
UserData *user = peer->asUser();
|
||||
|
||||
p.fillRect(0, 0, width(), _rowHeight, (sel ? st::contactsBgOver : st::white)->b);
|
||||
p.drawPixmapLeft(st::contactsPadding.left(), st::contactsPadding.top(), width(), peer->photo->pix(st::contactsPhotoSize));
|
||||
peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
|
||||
|
||||
p.setPen(st::black);
|
||||
|
||||
|
@ -1980,7 +2014,7 @@ void MembersInner::loadProfilePhotos(int32 yFrom) {
|
|||
if (to > _rows.size()) to = _rows.size();
|
||||
|
||||
for (; from < to; ++from) {
|
||||
_rows[from]->photo->load();
|
||||
_rows[from]->loadUserpic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2005,7 +2039,7 @@ void MembersInner::refresh() {
|
|||
} else {
|
||||
_about.setText(st::boxTextFont, lng_channel_only_last_shown(lt_count, _rows.size()));
|
||||
_aboutHeight = st::stickersReorderPadding.top() + _about.countHeight(_aboutWidth) + st::stickersReorderPadding.bottom();
|
||||
if (_filter != MembersFilterRecent || (_rows.size() >= _channel->count && _rows.size() < cMaxGroupCount())) {
|
||||
if (_filter != MembersFilterRecent || (_rows.size() >= _channel->count && _rows.size() < Global::ChatSizeMax())) {
|
||||
_aboutHeight = 0;
|
||||
}
|
||||
resize(width(), st::membersPadding.top() + _newItemHeight + _rows.size() * _rowHeight + st::membersPadding.bottom() + _aboutHeight);
|
||||
|
@ -2182,6 +2216,16 @@ void MembersInner::membersReceived(const MTPchannels_ChannelParticipants &result
|
|||
_datas.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
// update admins if we got all of them
|
||||
if (_filter == MembersFilterAdmins && _channel->isMegagroup() && _rows.size() < Global::ChatSizeMax()) {
|
||||
_channel->mgInfo->lastAdmins.clear();
|
||||
for (int32 i = 0, l = _rows.size(); i != l; ++i) {
|
||||
if (_roles.at(i) == MemberRoleCreator || _roles.at(i) == MemberRoleEditor) {
|
||||
_channel->mgInfo->lastAdmins.insert(_rows.at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_rows.isEmpty()) {
|
||||
_rows.push_back(App::self());
|
||||
|
@ -2297,7 +2341,7 @@ void MembersBox::onScroll() {
|
|||
}
|
||||
|
||||
void MembersBox::onAdd() {
|
||||
if (_inner.filter() == MembersFilterRecent && _inner.channel()->count >= (_inner.channel()->isMegagroup() ? cMaxMegaGroupCount() : cMaxGroupCount())) {
|
||||
if (_inner.filter() == MembersFilterRecent && _inner.channel()->count >= (_inner.channel()->isMegagroup() ? Global::MegagroupSizeMax() : Global::ChatSizeMax())) {
|
||||
Ui::showLayer(new MaxInviteBox(_inner.channel()->invitationUrl), KeepOtherLayers);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -28,6 +28,8 @@ enum MembersFilter {
|
|||
};
|
||||
typedef QMap<UserData*, bool> MembersAlreadyIn;
|
||||
|
||||
QString cantInviteError();
|
||||
|
||||
class ConfirmBox;
|
||||
class ContactsInner : public TWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -46,12 +46,12 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) {
|
|||
for (int32 i = 0; i < languageCount; ++i) {
|
||||
LangLoaderResult result;
|
||||
if (i) {
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i] + qsl(".strings"), LangLoaderRequest(lng_language_name));
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), LangLoaderRequest(lng_language_name));
|
||||
result = loader.found();
|
||||
} else {
|
||||
result.insert(lng_language_name, langOriginal(lng_language_name));
|
||||
}
|
||||
_langs.push_back(new Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i] + qsl(" language")), (cLang() == i), st::langsButton));
|
||||
_langs.push_back(new Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), (cLang() == i), st::langsButton));
|
||||
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
|
||||
y += _langs.back()->height() + st::boxOptionListPadding.top();
|
||||
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
|
||||
|
@ -82,14 +82,14 @@ void LanguageBox::showAll() {
|
|||
void LanguageBox::mousePressEvent(QMouseEvent *e) {
|
||||
if ((e->modifiers() & Qt::CTRL) && (e->modifiers() & Qt::ALT) && (e->modifiers() & Qt::SHIFT)) {
|
||||
for (int32 i = 1; i < languageCount; ++i) {
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i] + qsl(".strings"), LangLoaderRequest(lngkeys_cnt));
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[i].c_str() + qsl(".strings"), LangLoaderRequest(lngkeys_cnt));
|
||||
if (!loader.errors().isEmpty()) {
|
||||
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i] + qsl("\" error :(\n\nError: ") + loader.errors()));
|
||||
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" error :(\n\nError: ") + loader.errors()));
|
||||
return;
|
||||
} else if (!loader.warnings().isEmpty()) {
|
||||
QString warn = loader.warnings();
|
||||
if (warn.size() > 256) warn = warn.mid(0, 254) + qsl("..");
|
||||
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i] + qsl("\" warnings :(\n\nWarnings: ") + warn));
|
||||
if (warn.size() > 256) warn = warn.mid(0, 253) + qsl("...");
|
||||
Ui::showLayer(new InformBox(qsl("Lang \"") + LanguageCodes[i].c_str() + qsl("\" warnings :(\n\nWarnings: ") + warn));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ void LanguageBox::onChange() {
|
|||
if (_langs[i]->checked() && langId != cLang()) {
|
||||
LangLoaderResult result;
|
||||
if (langId > 0) {
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[langId] + qsl(".strings"), LangLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
|
||||
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[langId].c_str() + qsl(".strings"), LangLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
|
||||
result = loader.found();
|
||||
} else if (langId == languageTest) {
|
||||
LangLoaderPlain loader(cLangFile(), LangLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -400,12 +400,12 @@ void PasscodeBox::onSave(bool force) {
|
|||
if (!_oldPasscode.isHidden()) {
|
||||
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
||||
}
|
||||
int32 flags = MTPDaccount_passwordInputSettings::flag_new_salt | MTPDaccount_passwordInputSettings::flag_new_password_hash | MTPDaccount_passwordInputSettings::flag_hint;
|
||||
MTPDaccount_passwordInputSettings::Flags flags = MTPDaccount_passwordInputSettings::Flag::f_new_salt | MTPDaccount_passwordInputSettings::Flag::f_new_password_hash | MTPDaccount_passwordInputSettings::Flag::f_hint;
|
||||
if (_oldPasscode.isHidden() || _newPasscode.isHidden()) {
|
||||
flags |= MTPDaccount_passwordInputSettings::flag_email;
|
||||
flags |= MTPDaccount_passwordInputSettings::Flag::f_email;
|
||||
}
|
||||
MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_int(flags), MTP_string(_newSalt), MTP_string(newPasswordHash), MTP_string(hint), MTP_string(email)));
|
||||
_setRequest = MTP::send(MTPaccount_UpdatePasswordSettings(MTP_string(oldPasswordHash), settings), rpcDone(&PasscodeBox::setPasswordDone), rpcFail(&PasscodeBox::setPasswordFail));
|
||||
MTPaccount_PasswordInputSettings settings(MTP_account_passwordInputSettings(MTP_flags(flags), MTP_bytes(_newSalt), MTP_bytes(newPasswordHash), MTP_string(hint), MTP_string(email)));
|
||||
_setRequest = MTP::send(MTPaccount_UpdatePasswordSettings(MTP_bytes(oldPasswordHash), settings), rpcDone(&PasscodeBox::setPasswordDone), rpcFail(&PasscodeBox::setPasswordFail));
|
||||
}
|
||||
} else {
|
||||
cSetPasscodeBadTries(0);
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "style.h"
|
||||
#include "gui/style.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "application.h"
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "style.h"
|
||||
#include "gui/style.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "localstorage.h"
|
||||
|
@ -69,8 +69,8 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
|
|||
if (_animated) {
|
||||
int32 limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
int32 limitH = st::confirmMaxHeight;
|
||||
maxW = dimensions.width();
|
||||
maxH = dimensions.height();
|
||||
maxW = qMax(dimensions.width(), 1);
|
||||
maxH = qMax(dimensions.height(), 1);
|
||||
if (maxW * limitH > maxH * limitW) {
|
||||
if (maxW < limitW) {
|
||||
maxH = maxH * limitW / maxW;
|
||||
|
@ -82,7 +82,7 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
|
|||
maxH = limitH;
|
||||
}
|
||||
}
|
||||
_thumb = imagePix(_file->thumb.toImage(), maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), true, true, false, maxW, maxH);
|
||||
_thumb = imagePix(_file->thumb.toImage(), maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), ImagePixSmooth | ImagePixBlurred, maxW, maxH);
|
||||
} else {
|
||||
for (PreparedPhotoThumbs::const_iterator i = _file->photoThumbs.cbegin(), e = _file->photoThumbs.cend(); i != e; ++i) {
|
||||
if (i->width() >= maxW && i->height() >= maxH) {
|
||||
|
@ -124,7 +124,7 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
|
|||
} else {
|
||||
_thumbw = st::msgFileThumbSize;
|
||||
}
|
||||
_thumb = imagePix(_thumb.toImage(), _thumbw * cIntRetinaFactor(), 0, true, false, true, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
_thumb = imagePix(_thumb.toImage(), _thumbw * cIntRetinaFactor(), 0, ImagePixSmooth | ImagePixRounded, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
}
|
||||
|
||||
_name.setText(st::semiboldFont, _file->filename, _textNameOptions);
|
||||
|
@ -274,7 +274,7 @@ void PhotoSendBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
p.drawSpriteCenter(inner, _isImage ? st::msgFileOutImage : st::msgFileOutFile);
|
||||
} else {
|
||||
p.drawPixmapLeft(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), userDefPhoto(1)->pixRounded(st::msgFileSize));
|
||||
p.drawPixmapLeft(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), userDefPhoto(1)->pixCircled(st::msgFileSize));
|
||||
}
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::black);
|
||||
|
@ -359,3 +359,330 @@ void PhotoSendBox::onSend(bool ctrlShiftEnter) {
|
|||
_confirmed = true;
|
||||
onClose();
|
||||
}
|
||||
|
||||
EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
|
||||
, _msgId(msg->fullId())
|
||||
, _animated(false)
|
||||
, _photo(false)
|
||||
, _doc(false)
|
||||
, _field(0)
|
||||
, _save(this, lang(lng_settings_save), st::defaultBoxButton)
|
||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||
, _thumbx(0)
|
||||
, _thumby(0)
|
||||
, _thumbw(0)
|
||||
, _thumbh(0)
|
||||
, _statusw(0)
|
||||
, _isImage(false)
|
||||
, _previewCancelled(false)
|
||||
, _saveRequestId(0) {
|
||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
|
||||
QSize dimensions;
|
||||
ImagePtr image;
|
||||
QString caption;
|
||||
DocumentData *doc = 0;
|
||||
if (HistoryMedia *media = msg->getMedia()) {
|
||||
HistoryMediaType t = media->type();
|
||||
switch (t) {
|
||||
case MediaTypeGif: {
|
||||
_animated = true;
|
||||
doc = static_cast<HistoryGif*>(media)->getDocument();
|
||||
dimensions = doc->dimensions;
|
||||
image = doc->thumb;
|
||||
} break;
|
||||
|
||||
case MediaTypePhoto: {
|
||||
_photo = true;
|
||||
PhotoData *photo = static_cast<HistoryPhoto*>(media)->photo();
|
||||
dimensions = QSize(photo->full->width(), photo->full->height());
|
||||
image = photo->full;
|
||||
} break;
|
||||
|
||||
case MediaTypeVideo: {
|
||||
_animated = true;
|
||||
doc = static_cast<HistoryVideo*>(media)->getDocument();
|
||||
dimensions = doc->dimensions;
|
||||
image = doc->thumb;
|
||||
} break;
|
||||
|
||||
case MediaTypeFile:
|
||||
case MediaTypeMusicFile:
|
||||
case MediaTypeVoiceFile: {
|
||||
_doc = true;
|
||||
doc = static_cast<HistoryDocument*>(media)->getDocument();
|
||||
image = doc->thumb;
|
||||
} break;
|
||||
}
|
||||
caption = media->getCaption();
|
||||
}
|
||||
if ((!_animated && (dimensions.isEmpty() || doc)) || image->isNull()) {
|
||||
_animated = false;
|
||||
if (image->isNull()) {
|
||||
_thumbw = 0;
|
||||
} else {
|
||||
int32 tw = image->width(), th = image->height();
|
||||
if (tw > th) {
|
||||
_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||
} else {
|
||||
_thumbw = st::msgFileThumbSize;
|
||||
}
|
||||
_thumb = imagePix(image->pix().toImage(), _thumbw * cIntRetinaFactor(), 0, ImagePixSmooth | ImagePixRounded, st::msgFileThumbSize, st::msgFileThumbSize);
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
if (doc->voice()) {
|
||||
_name.setText(st::semiboldFont, lang(lng_media_audio), _textNameOptions);
|
||||
} else {
|
||||
_name.setText(st::semiboldFont, documentName(doc), _textNameOptions);
|
||||
}
|
||||
_status = formatSizeText(doc->size);
|
||||
_statusw = qMax(_name.maxWidth(), st::normalFont->width(_status));
|
||||
_isImage = doc->isImage();
|
||||
}
|
||||
} else {
|
||||
int32 maxW = 0, maxH = 0;
|
||||
if (_animated) {
|
||||
int32 limitW = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
int32 limitH = st::confirmMaxHeight;
|
||||
maxW = qMax(dimensions.width(), 1);
|
||||
maxH = qMax(dimensions.height(), 1);
|
||||
if (maxW * limitH > maxH * limitW) {
|
||||
if (maxW < limitW) {
|
||||
maxH = maxH * limitW / maxW;
|
||||
maxW = limitW;
|
||||
}
|
||||
} else {
|
||||
if (maxH < limitH) {
|
||||
maxW = maxW * limitH / maxH;
|
||||
maxH = limitH;
|
||||
}
|
||||
}
|
||||
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), ImagePixSmooth | ImagePixBlurred, maxW, maxH);
|
||||
} else {
|
||||
maxW = dimensions.width();
|
||||
maxH = dimensions.height();
|
||||
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), ImagePixSmooth | ImagePixRounded, maxW, maxH);
|
||||
}
|
||||
int32 tw = _thumb.width(), th = _thumb.height();
|
||||
if (!tw || !th) {
|
||||
tw = th = 1;
|
||||
}
|
||||
_thumbw = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
if (_thumb.width() < _thumbw) {
|
||||
_thumbw = (_thumb.width() > 20) ? _thumb.width() : 20;
|
||||
}
|
||||
int32 maxthumbh = qMin(qRound(1.5 * _thumbw), int(st::confirmMaxHeight));
|
||||
_thumbh = qRound(th * float64(_thumbw) / tw);
|
||||
if (_thumbh > maxthumbh) {
|
||||
_thumbw = qRound(_thumbw * float64(maxthumbh) / _thumbh);
|
||||
_thumbh = maxthumbh;
|
||||
if (_thumbw < 10) {
|
||||
_thumbw = 10;
|
||||
}
|
||||
}
|
||||
_thumbx = (width() - _thumbw) / 2;
|
||||
|
||||
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
|
||||
_thumb.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
|
||||
if (_animated || _photo || _doc) {
|
||||
_field = new InputArea(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
|
||||
_field->setMaxLength(MaxPhotoCaption);
|
||||
_field->setCtrlEnterSubmit(CtrlEnterSubmitBoth);
|
||||
} else {
|
||||
QString text = textApplyEntities(msg->originalText(), msg->originalEntities());
|
||||
_field = new InputArea(this, st::editTextArea, lang(lng_photo_caption), text);
|
||||
// _field->setMaxLength(MaxMessageSize); // entities can make text in input field larger but still valid
|
||||
_field->setCtrlEnterSubmit(cCtrlEnter() ? CtrlEnterSubmitCtrlEnter : CtrlEnterSubmitEnter);
|
||||
}
|
||||
updateBoxSize();
|
||||
connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool)));
|
||||
connect(_field, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||
connect(_field, SIGNAL(resized()), this, SLOT(onCaptionResized()));
|
||||
|
||||
QTextCursor c(_field->textCursor());
|
||||
c.movePosition(QTextCursor::End);
|
||||
_field->setTextCursor(c);
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
bool EditCaptionBox::captionFound() const {
|
||||
return _animated || _photo || _doc;
|
||||
}
|
||||
|
||||
void EditCaptionBox::onCaptionResized() {
|
||||
updateBoxSize();
|
||||
resizeEvent(0);
|
||||
update();
|
||||
}
|
||||
|
||||
void EditCaptionBox::updateBoxSize() {
|
||||
int32 bottomh = st::boxPhotoCompressedPadding.bottom() + _field->height() + st::normalFont->height + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom();
|
||||
if (_photo || _animated) {
|
||||
setMaxHeight(st::boxPhotoPadding.top() + _thumbh + bottomh);
|
||||
} else if (_thumbw) {
|
||||
setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileThumbSize + 0 + bottomh);
|
||||
} else if (_doc) {
|
||||
setMaxHeight(st::boxPhotoPadding.top() + 0 + st::msgFileSize + 0 + bottomh);
|
||||
} else {
|
||||
setMaxHeight(st::boxPhotoPadding.top() + st::boxTitleFont->height + bottomh);
|
||||
}
|
||||
}
|
||||
|
||||
void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
if (paint(p)) return;
|
||||
|
||||
if (_photo || _animated) {
|
||||
if (_thumbx > st::boxPhotoPadding.left()) {
|
||||
p.fillRect(st::boxPhotoPadding.left(), st::boxPhotoPadding.top(), _thumbx - st::boxPhotoPadding.left(), _thumbh, st::confirmBg->b);
|
||||
}
|
||||
if (_thumbx + _thumbw < width() - st::boxPhotoPadding.right()) {
|
||||
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg->b);
|
||||
}
|
||||
p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb);
|
||||
if (_animated) {
|
||||
QRect inner(_thumbx + (_thumbw - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (_thumbh - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgDateImgBg);
|
||||
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||
p.drawEllipse(inner);
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
|
||||
p.drawSpriteCenter(inner, st::msgFileInPlay);
|
||||
}
|
||||
} else if (_doc) {
|
||||
int32 w = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
int32 h = _thumbw ? (0 + st::msgFileThumbSize + 0) : (0 + st::msgFileSize + 0);
|
||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0;
|
||||
if (_thumbw) {
|
||||
nameleft = 0 + st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
nametop = st::msgFileThumbNameTop - st::msgFileThumbPadding.top();
|
||||
nameright = 0;
|
||||
statustop = st::msgFileThumbStatusTop - st::msgFileThumbPadding.top();
|
||||
} else {
|
||||
nameleft = 0 + st::msgFileSize + st::msgFilePadding.right();
|
||||
nametop = st::msgFileNameTop - st::msgFilePadding.top();
|
||||
nameright = 0;
|
||||
statustop = st::msgFileStatusTop - st::msgFilePadding.top();
|
||||
}
|
||||
int32 namewidth = w - nameleft - 0;
|
||||
if (namewidth > _statusw) {
|
||||
//w -= (namewidth - _statusw);
|
||||
//namewidth = _statusw;
|
||||
}
|
||||
int32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
|
||||
// App::roundRect(p, x, y, w, h, st::msgInBg, MessageInCorners, &st::msgInShadow);
|
||||
|
||||
if (_thumbw) {
|
||||
QRect rthumb(rtlrect(x + 0, y + 0, st::msgFileThumbSize, st::msgFileThumbSize, width()));
|
||||
p.drawPixmap(rthumb.topLeft(), _thumb);
|
||||
} else {
|
||||
QRect inner(rtlrect(x + 0, y + 0, st::msgFileSize, st::msgFileSize, width()));
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgFileInBg);
|
||||
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||
p.drawEllipse(inner);
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
|
||||
p.drawSpriteCenter(inner, _isImage ? st::msgFileInImage : st::msgFileInFile);
|
||||
}
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(st::black);
|
||||
_name.drawLeftElided(p, x + nameleft, y + nametop, namewidth, width());
|
||||
|
||||
style::color status(st::mediaInFg);
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(status);
|
||||
p.drawTextLeft(x + nameleft, y + statustop, width(), _status);
|
||||
} else {
|
||||
p.setFont(st::boxTitleFont);
|
||||
p.setPen(st::black);
|
||||
p.drawTextLeft(_field->x(), st::boxPhotoPadding.top(), width(), lang(lng_edit_message));
|
||||
}
|
||||
|
||||
if (!_error.isEmpty()) {
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(st::setErrColor);
|
||||
p.drawTextLeft(_field->x(), _field->y() + _field->height() + (st::boxButtonPadding.top() / 2), width(), _error);
|
||||
}
|
||||
}
|
||||
|
||||
void EditCaptionBox::resizeEvent(QResizeEvent *e) {
|
||||
_save.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save.height());
|
||||
_cancel.moveToRight(st::boxButtonPadding.right() + _save.width() + st::boxButtonPadding.left(), _save.y());
|
||||
_field->resize(st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right(), _field->height());
|
||||
_field->moveToLeft(st::boxPhotoPadding.left(), _save.y() - st::boxButtonPadding.top() - st::normalFont->height - _field->height());
|
||||
}
|
||||
|
||||
void EditCaptionBox::hideAll() {
|
||||
_save.hide();
|
||||
_cancel.hide();
|
||||
_field->hide();
|
||||
}
|
||||
|
||||
void EditCaptionBox::showAll() {
|
||||
_save.show();
|
||||
_cancel.show();
|
||||
_field->show();
|
||||
}
|
||||
|
||||
void EditCaptionBox::showDone() {
|
||||
setInnerFocus();
|
||||
}
|
||||
|
||||
void EditCaptionBox::onSave(bool ctrlShiftEnter) {
|
||||
if (_saveRequestId) return;
|
||||
|
||||
HistoryItem *item = App::histItemById(_msgId);
|
||||
if (!item) {
|
||||
_error = lang(lng_edit_deleted);
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
MTPmessages_EditMessage::Flags flags = 0;
|
||||
if (_previewCancelled) {
|
||||
flags |= MTPmessages_EditMessage::Flag::f_no_webpage;
|
||||
}
|
||||
MTPVector<MTPMessageEntity> sentEntities;
|
||||
if (!sentEntities.c_vector().v.isEmpty()) {
|
||||
flags |= MTPmessages_EditMessage::Flag::f_entities;
|
||||
}
|
||||
_saveRequestId = MTP::send(MTPmessages_EditMessage(MTP_flags(flags), item->history()->peer->input, MTP_int(item->id), MTP_string(_field->getLastText()), MTPnullMarkup, sentEntities), rpcDone(&EditCaptionBox::saveDone), rpcFail(&EditCaptionBox::saveFail));
|
||||
}
|
||||
|
||||
void EditCaptionBox::saveDone(const MTPUpdates &updates) {
|
||||
_saveRequestId = 0;
|
||||
onClose();
|
||||
if (App::main()) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
}
|
||||
|
||||
bool EditCaptionBox::saveFail(const RPCError &error) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
|
||||
_saveRequestId = 0;
|
||||
QString err = error.type();
|
||||
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
|
||||
_error = lang(lng_edit_error);
|
||||
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
|
||||
onClose();
|
||||
return true;
|
||||
} else if (err == qstr("MESSAGE_EMPTY")) {
|
||||
_field->setFocus();
|
||||
_field->showError();
|
||||
} else {
|
||||
_error = lang(lng_edit_error);
|
||||
}
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -42,11 +42,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
|
||||
void confirmed();
|
||||
void cancelled();
|
||||
|
||||
public slots:
|
||||
|
||||
void onCompressedChange();
|
||||
|
@ -87,3 +82,57 @@ private:
|
|||
bool _confirmed;
|
||||
|
||||
};
|
||||
|
||||
class EditCaptionBox : public AbstractBox, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
EditCaptionBox(HistoryItem *msg);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
bool captionFound() const;
|
||||
|
||||
void setInnerFocus() {
|
||||
_field->setFocus();
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
void onCaptionResized();
|
||||
void onSave(bool ctrlShiftEnter = false);
|
||||
|
||||
protected:
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
void showDone();
|
||||
|
||||
private:
|
||||
|
||||
void updateBoxSize();
|
||||
|
||||
void saveDone(const MTPUpdates &updates);
|
||||
bool saveFail(const RPCError &error);
|
||||
|
||||
FullMsgId _msgId;
|
||||
bool _animated, _photo, _doc;
|
||||
|
||||
QPixmap _thumb;
|
||||
|
||||
InputArea *_field;
|
||||
BoxButton _save, _cancel;
|
||||
|
||||
int32 _thumbx, _thumby, _thumbw, _thumbh;
|
||||
Text _name;
|
||||
QString _status;
|
||||
int32 _statusw;
|
||||
bool _isImage;
|
||||
|
||||
bool _previewCancelled;
|
||||
mtpRequestId _saveRequestId;
|
||||
|
||||
QString _error;
|
||||
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -29,9 +29,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "localstorage.h"
|
||||
|
||||
StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) :
|
||||
_loaded(false), _setId(0), _setAccess(0), _setCount(0), _setHash(0), _setFlags(0), _bottom(0),
|
||||
_input(set), _installRequest(0) {
|
||||
StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : TWidget()
|
||||
, _loaded(false)
|
||||
, _setId(0)
|
||||
, _setAccess(0)
|
||||
, _setCount(0)
|
||||
, _setHash(0)
|
||||
, _setFlags(0)
|
||||
, _bottom(0)
|
||||
, _input(set)
|
||||
, _installRequest(0)
|
||||
, _previewShown(-1) {
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
switch (set.type()) {
|
||||
case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break;
|
||||
|
@ -39,10 +47,14 @@ _input(set), _installRequest(0) {
|
|||
}
|
||||
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&StickerSetInner::gotSet), rpcFail(&StickerSetInner::failedSet));
|
||||
App::main()->updateStickers();
|
||||
|
||||
_previewTimer.setSingleShot(true);
|
||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
||||
}
|
||||
|
||||
void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
||||
_pack.clear();
|
||||
_emoji.clear();
|
||||
if (set.type() == mtpc_messages_stickerSet) {
|
||||
const MTPDmessages_stickerSet &d(set.c_messages_stickerSet());
|
||||
const QVector<MTPDocument> &v(d.vdocuments.c_vector().v);
|
||||
|
@ -53,6 +65,23 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) {
|
|||
|
||||
_pack.push_back(doc);
|
||||
}
|
||||
const QVector<MTPStickerPack> &packs(d.vpacks.c_vector().v);
|
||||
for (int32 i = 0, l = packs.size(); i < l; ++i) {
|
||||
if (packs.at(i).type() != mtpc_stickerPack) continue;
|
||||
const MTPDstickerPack &pack(packs.at(i).c_stickerPack());
|
||||
if (EmojiPtr e = emojiGetNoColor(emojiFromText(qs(pack.vemoticon)))) {
|
||||
const QVector<MTPlong> &stickers(pack.vdocuments.c_vector().v);
|
||||
StickerPack p;
|
||||
p.reserve(stickers.size());
|
||||
for (int32 j = 0, c = stickers.size(); j < c; ++j) {
|
||||
DocumentData *doc = App::document(stickers.at(j).v);
|
||||
if (!doc || !doc->sticker()) continue;
|
||||
|
||||
p.push_back(doc);
|
||||
}
|
||||
_emoji.insert(e, p);
|
||||
}
|
||||
}
|
||||
if (d.vset.type() == mtpc_stickerSet) {
|
||||
const MTPDstickerSet &s(d.vset.c_stickerSet());
|
||||
_setTitle = stickerSetTitle(s);
|
||||
|
@ -88,12 +117,17 @@ bool StickerSetInner::failedSet(const RPCError &error) {
|
|||
}
|
||||
|
||||
void StickerSetInner::installDone(const MTPBool &result) {
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
|
||||
_setFlags &= ~MTPDstickerSet::flag_disabled;
|
||||
sets.insert(_setId, StickerSet(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags)).value().stickers = _pack;
|
||||
_setFlags &= ~MTPDstickerSet::Flag::f_disabled;
|
||||
auto it = sets.find(_setId);
|
||||
if (it == sets.cend()) {
|
||||
it = sets.insert(_setId, Stickers::Set(_setId, _setAccess, _setTitle, _setShortName, _setCount, _setHash, _setFlags));
|
||||
}
|
||||
it.value().stickers = _pack;
|
||||
it.value().emoji = _emoji;
|
||||
|
||||
StickerSetsOrder &order(cRefStickerSetsOrder());
|
||||
Stickers::Order &order(Global::RefStickerSetsOrder());
|
||||
int32 insertAtIndex = 0, currentIndex = order.indexOf(_setId);
|
||||
if (currentIndex != insertAtIndex) {
|
||||
if (currentIndex > 0) {
|
||||
|
@ -102,7 +136,7 @@ void StickerSetInner::installDone(const MTPBool &result) {
|
|||
order.insert(insertAtIndex, _setId);
|
||||
}
|
||||
|
||||
StickerSets::iterator custom = sets.find(CustomStickerSetId);
|
||||
auto custom = sets.find(Stickers::CustomSetId);
|
||||
if (custom != sets.cend()) {
|
||||
for (int32 i = 0, l = _pack.size(); i < l; ++i) {
|
||||
int32 removeIndex = custom->stickers.indexOf(_pack.at(i));
|
||||
|
@ -125,6 +159,47 @@ bool StickerSetInner::installFailed(const RPCError &error) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void StickerSetInner::mousePressEvent(QMouseEvent *e) {
|
||||
int32 index = stickerFromGlobalPos(e->globalPos());
|
||||
if (index >= 0 && index < _pack.size()) {
|
||||
_previewTimer.start(QApplication::startDragTime());
|
||||
}
|
||||
}
|
||||
|
||||
void StickerSetInner::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_previewShown >= 0) {
|
||||
int32 index = stickerFromGlobalPos(e->globalPos());
|
||||
if (index >= 0 && index < _pack.size() && index != _previewShown) {
|
||||
_previewShown = index;
|
||||
Ui::showStickerPreview(_pack.at(_previewShown));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StickerSetInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_previewTimer.stop();
|
||||
}
|
||||
|
||||
void StickerSetInner::onPreview() {
|
||||
int32 index = stickerFromGlobalPos(QCursor::pos());
|
||||
if (index >= 0 && index < _pack.size()) {
|
||||
_previewShown = index;
|
||||
Ui::showStickerPreview(_pack.at(_previewShown));
|
||||
}
|
||||
}
|
||||
|
||||
int32 StickerSetInner::stickerFromGlobalPos(const QPoint &p) const {
|
||||
QPoint l(mapFromGlobal(p));
|
||||
if (rtl()) l.setX(width() - l.x());
|
||||
int32 row = (l.y() >= st::stickersPadding.top()) ? qFloor((l.y() - st::stickersPadding.top()) / st::stickersSize.height()) : -1;
|
||||
int32 col = (l.x() >= st::stickersPadding.left()) ? qFloor((l.x() - st::stickersPadding.left()) / st::stickersSize.width()) : -1;
|
||||
if (row >= 0 && col >= 0 && col < StickerPanPerRow) {
|
||||
int32 result = row * StickerPanPerRow + col;
|
||||
return (result < _pack.size()) ? result : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void StickerSetInner::paintEvent(QPaintEvent *e) {
|
||||
QRect r(e->rect());
|
||||
Painter p(this);
|
||||
|
@ -149,12 +224,8 @@ void StickerSetInner::paintEvent(QPaintEvent *e) {
|
|||
if (doc->status == FileReady) {
|
||||
doc->automaticLoad(0);
|
||||
}
|
||||
if (doc->sticker()->img->isNull() && doc->loaded() && doc->loaded(true)) {
|
||||
if (doc->data().isEmpty()) {
|
||||
doc->sticker()->img = ImagePtr(doc->already());
|
||||
} else {
|
||||
doc->sticker()->img = ImagePtr(doc->data());
|
||||
}
|
||||
if (doc->sticker()->img->isNull() && doc->loaded(DocumentData::FilePathResolveChecked)) {
|
||||
doc->sticker()->img = doc->data().isEmpty() ? ImagePtr(doc->filepath()) : ImagePtr(doc->data());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,8 +256,8 @@ bool StickerSetInner::loaded() const {
|
|||
|
||||
int32 StickerSetInner::notInstalled() const {
|
||||
if (!_loaded) return 0;
|
||||
StickerSets::const_iterator it = cStickerSets().constFind(_setId);
|
||||
if (it == cStickerSets().cend() || (it->flags & MTPDstickerSet::flag_disabled)) return _pack.size();
|
||||
auto it = Global::StickerSets().constFind(_setId);
|
||||
if (it == Global::StickerSets().cend() || (it->flags & MTPDstickerSet::Flag::f_disabled)) return _pack.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -611,14 +682,14 @@ void StickersInner::rebuild() {
|
|||
int32 namew = st::boxWideWidth - namex - st::contactsPadding.right() - st::contactsCheckPosition.x() - qMax(qMax(_returnWidth, _removeWidth), _restoreWidth);
|
||||
|
||||
clear();
|
||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||
const Stickers::Order &order(Global::StickerSetsOrder());
|
||||
_animStartTimes.reserve(order.size());
|
||||
|
||||
const StickerSets &sets(cStickerSets());
|
||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||
StickerSets::const_iterator it = sets.constFind(order.at(i));
|
||||
const Stickers::Sets &sets(Global::StickerSets());
|
||||
for (int i = 0, l = order.size(); i < l; ++i) {
|
||||
auto it = sets.constFind(order.at(i));
|
||||
if (it != sets.cend()) {
|
||||
bool disabled = (it->flags & MTPDstickerSet::flag_disabled);
|
||||
bool disabled = (it->flags & MTPDstickerSet::Flag::f_disabled);
|
||||
|
||||
DocumentData *sticker = it->stickers.isEmpty() ? 0 : it->stickers.at(0);
|
||||
int32 pixw = 0, pixh = 0;
|
||||
|
@ -643,10 +714,10 @@ void StickersInner::rebuild() {
|
|||
if (titleWidth > namew) {
|
||||
title = st::contactsNameFont->elided(title, namew);
|
||||
}
|
||||
bool official = (it->flags & MTPDstickerSet::flag_official);
|
||||
bool official = (it->flags & MTPDstickerSet::Flag::f_official);
|
||||
(disabled ? rowsDisabled : rows).push_back(new StickerSetRow(it->id, sticker, it->stickers.size(), title, official, disabled, pixw, pixh));
|
||||
_animStartTimes.push_back(0);
|
||||
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_flag_NOT_LOADED)) {
|
||||
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
App::api()->scheduleStickerSetRequest(it->id, it->access);
|
||||
}
|
||||
}
|
||||
|
@ -661,8 +732,8 @@ QVector<uint64> StickersInner::getOrder() const {
|
|||
result.reserve(_rows.size());
|
||||
for (int32 i = 0, l = _rows.size(); i < l; ++i) {
|
||||
if (_rows.at(i)->disabled) {
|
||||
StickerSets::const_iterator it = cStickerSets().constFind(_rows.at(i)->id);
|
||||
if (it == cStickerSets().cend() || !(it->flags & MTPDstickerSet::flag_official)) {
|
||||
auto it = Global::StickerSets().constFind(_rows.at(i)->id);
|
||||
if (it == Global::StickerSets().cend() || !(it->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -704,6 +775,7 @@ StickersBox::StickersBox() : ItemListBox(st::boxScroll)
|
|||
setMaxHeight(snap(countHeight(), int32(st::sessionsHeight), int32(st::boxMaxListHeight)));
|
||||
|
||||
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
|
||||
App::main()->updateStickers();
|
||||
|
||||
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
|
@ -761,7 +833,7 @@ void StickersBox::reorderDone(const MTPBool &result) {
|
|||
bool StickersBox::reorderFail(const RPCError &result) {
|
||||
if (mtpIsFlood(result)) return false;
|
||||
_reorderRequest = 0;
|
||||
cSetLastStickersUpdate(0);
|
||||
Global::SetLastStickersUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
onClose();
|
||||
return true;
|
||||
|
@ -785,12 +857,12 @@ void StickersBox::closePressed() {
|
|||
MTP::cancel(i.key());
|
||||
}
|
||||
_disenableRequests.clear();
|
||||
cSetLastStickersUpdate(0);
|
||||
Global::SetLastStickersUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
} else if (_reorderRequest) {
|
||||
MTP::cancel(_reorderRequest);
|
||||
_reorderRequest = 0;
|
||||
cSetLastStickersUpdate(0);
|
||||
Global::SetLastStickersUpdate(0);
|
||||
App::main()->updateStickers();
|
||||
}
|
||||
}
|
||||
|
@ -842,11 +914,11 @@ void StickersBox::onSave() {
|
|||
|
||||
bool writeRecent = false;
|
||||
RecentStickerPack &recent(cGetRecentStickers());
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
Stickers::Sets &sets(Global::RefStickerSets());
|
||||
|
||||
QVector<uint64> reorder = _inner.getOrder(), disabled = _inner.getDisabledSets();
|
||||
for (int32 i = 0, l = disabled.size(); i < l; ++i) {
|
||||
StickerSets::iterator it = sets.find(disabled.at(i));
|
||||
auto it = sets.find(disabled.at(i));
|
||||
if (it != sets.cend()) {
|
||||
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
|
@ -856,35 +928,35 @@ void StickersBox::onSave() {
|
|||
++i;
|
||||
}
|
||||
}
|
||||
if (!(it->flags & MTPDstickerSet::flag_disabled)) {
|
||||
if (!(it->flags & MTPDstickerSet::Flag::f_disabled)) {
|
||||
MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName));
|
||||
if (it->flags & MTPDstickerSet::flag_official) {
|
||||
if (it->flags & MTPDstickerSet::Flag::f_official) {
|
||||
_disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolTrue()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType());
|
||||
it->flags |= MTPDstickerSet::flag_disabled;
|
||||
it->flags |= MTPDstickerSet::Flag::f_disabled;
|
||||
} else {
|
||||
_disenableRequests.insert(MTP::send(MTPmessages_UninstallStickerSet(setId), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType());
|
||||
int32 removeIndex = cStickerSetsOrder().indexOf(it->id);
|
||||
if (removeIndex >= 0) cRefStickerSetsOrder().removeAt(removeIndex);
|
||||
int removeIndex = Global::StickerSetsOrder().indexOf(it->id);
|
||||
if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex);
|
||||
sets.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StickerSetsOrder &order(cRefStickerSetsOrder());
|
||||
Stickers::Order &order(Global::RefStickerSetsOrder());
|
||||
order.clear();
|
||||
for (int32 i = 0, l = reorder.size(); i < l; ++i) {
|
||||
StickerSets::iterator it = sets.find(reorder.at(i));
|
||||
for (int i = 0, l = reorder.size(); i < l; ++i) {
|
||||
auto it = sets.find(reorder.at(i));
|
||||
if (it != sets.cend()) {
|
||||
if ((it->flags & MTPDstickerSet::flag_disabled) && !disabled.contains(it->id)) {
|
||||
if ((it->flags & MTPDstickerSet::Flag::f_disabled) && !disabled.contains(it->id)) {
|
||||
MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName));
|
||||
_disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolFalse()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType());
|
||||
it->flags &= ~MTPDstickerSet::flag_disabled;
|
||||
it->flags &= ~MTPDstickerSet::Flag::f_disabled;
|
||||
}
|
||||
order.push_back(reorder.at(i));
|
||||
}
|
||||
}
|
||||
for (StickerSets::iterator it = sets.begin(); it != sets.cend();) {
|
||||
if (it->id == CustomStickerSetId || it->id == RecentStickerSetId || order.contains(it->id)) {
|
||||
for (auto it = sets.begin(); it != sets.cend();) {
|
||||
if (it->id == Stickers::CustomSetId || it->id == Stickers::RecentSetId || order.contains(it->id)) {
|
||||
++it;
|
||||
} else {
|
||||
it = sets.erase(it);
|
||||
|
@ -920,12 +992,12 @@ void StickersBox::showAll() {
|
|||
|
||||
int32 stickerPacksCount(bool includeDisabledOfficial) {
|
||||
int32 result = 0;
|
||||
const StickerSetsOrder &order(cStickerSetsOrder());
|
||||
const StickerSets &sets(cStickerSets());
|
||||
for (int32 i = 0, l = order.size(); i < l; ++i) {
|
||||
StickerSets::const_iterator it = sets.constFind(order.at(i));
|
||||
const Stickers::Order &order(Global::StickerSetsOrder());
|
||||
const Stickers::Sets &sets(Global::StickerSets());
|
||||
for (int i = 0, l = order.size(); i < l; ++i) {
|
||||
auto it = sets.constFind(order.at(i));
|
||||
if (it != sets.cend()) {
|
||||
if (!(it->flags & MTPDstickerSet::flag_disabled) || ((it->flags & MTPDstickerSet::flag_official) && includeDisabledOfficial)) {
|
||||
if (!(it->flags & MTPDstickerSet::Flag::f_disabled) || ((it->flags & MTPDstickerSet::Flag::f_official) && includeDisabledOfficial)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -29,7 +29,9 @@ public:
|
|||
|
||||
StickerSetInner(const MTPInputStickerSet &set);
|
||||
|
||||
void init();
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
|
||||
|
@ -42,10 +44,12 @@ public:
|
|||
void setScrollBottom(int32 bottom);
|
||||
void install();
|
||||
|
||||
QString getTitle() const;
|
||||
|
||||
~StickerSetInner();
|
||||
|
||||
public slots:
|
||||
|
||||
void onPreview();
|
||||
|
||||
signals:
|
||||
|
||||
void updateButtons();
|
||||
|
@ -53,6 +57,8 @@ signals:
|
|||
|
||||
private:
|
||||
|
||||
int32 stickerFromGlobalPos(const QPoint &p) const;
|
||||
|
||||
void gotSet(const MTPmessages_StickerSet &set);
|
||||
bool failedSet(const RPCError &error);
|
||||
|
||||
|
@ -60,15 +66,20 @@ private:
|
|||
bool installFailed(const RPCError &error);
|
||||
|
||||
StickerPack _pack;
|
||||
StickersByEmojiMap _emoji;
|
||||
bool _loaded;
|
||||
uint64 _setId, _setAccess;
|
||||
QString _title, _setTitle, _setShortName;
|
||||
int32 _setCount, _setHash, _setFlags;
|
||||
int32 _setCount, _setHash;
|
||||
MTPDstickerSet::Flags _setFlags;
|
||||
|
||||
int32 _bottom;
|
||||
MTPInputStickerSet _input;
|
||||
|
||||
mtpRequestId _installRequest;
|
||||
|
||||
QTimer _previewTimer;
|
||||
int32 _previewShown;
|
||||
};
|
||||
|
||||
class StickerSetBox : public ScrollableBox, public RPCSender {
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
@ -160,7 +160,7 @@ void UsernameBox::onChanged() {
|
|||
}
|
||||
_checkTimer.stop();
|
||||
} else {
|
||||
int32 i, len = name.size();
|
||||
int32 len = name.size();
|
||||
for (int32 i = 0; i < len; ++i) {
|
||||
QChar ch = name.at(i);
|
||||
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '_' && (ch != '@' || i > 0)) {
|
||||
|
@ -191,7 +191,7 @@ void UsernameBox::onChanged() {
|
|||
}
|
||||
|
||||
void UsernameBox::onLinkClick() {
|
||||
App::app()->clipboard()->setText(qsl("https://telegram.me/") + getName());
|
||||
Application::clipboard()->setText(qsl("https://telegram.me/") + getName());
|
||||
_copiedTextLink = lang(lng_username_copied);
|
||||
update();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
3
Telegram/SourceFiles/codegen/style/main.cpp
Normal file
3
Telegram/SourceFiles/codegen/style/main.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
|
@ -16,14 +16,14 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
static const int32 AppVersion = 9017;
|
||||
static const wchar_t *AppVersionStr = L"0.9.17";
|
||||
static const int32 AppVersion = 9040;
|
||||
static const wchar_t *AppVersionStr = L"0.9.40";
|
||||
static const bool DevVersion = false;
|
||||
//#define BETA_VERSION (9015008ULL) // just comment this line to build public version
|
||||
//#define BETA_VERSION (9034004ULL) // just comment this line to build public version
|
||||
|
||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||
static const wchar_t *AppName = L"Telegram Desktop";
|
||||
|
@ -51,11 +51,11 @@ enum {
|
|||
MTPIPv4ConnectionWaitTimeout = 1000, // 1 seconds waiting for ipv4, until we accept ipv6
|
||||
MTPMillerRabinIterCount = 30, // 30 Miller-Rabin iterations for dh_prime primality check
|
||||
|
||||
MTPUploadSessionsCount = 4, // max 4 upload sessions is created
|
||||
MTPDownloadSessionsCount = 4, // max 4 download sessions is created
|
||||
MTPUploadSessionsCount = 2, // max 2 upload sessions is created
|
||||
MTPDownloadSessionsCount = 2, // max 2 download sessions is created
|
||||
MTPKillFileSessionTimeout = 5000, // how much time without upload / download causes additional session kill
|
||||
|
||||
MTPEnumDCTimeout = 4000, // 4 seconds timeout for help_getConfig to work (them move to other dc)
|
||||
MTPEnumDCTimeout = 8000, // 8 seconds timeout for help_getConfig to work (then move to other dc)
|
||||
|
||||
MTPDebugBufferSize = 1024 * 1024, // 1 mb start size
|
||||
|
||||
|
@ -101,6 +101,9 @@ enum {
|
|||
MediaOverviewStartPerPage = 5,
|
||||
MediaOverviewPreloadCount = 4,
|
||||
|
||||
// a new message from the same sender is attached to previous within 15 minutes
|
||||
AttachMessageToPreviousSecondsDelta = 900,
|
||||
|
||||
AudioVoiceMsgSimultaneously = 4,
|
||||
AudioSongSimultaneously = 4,
|
||||
AudioCheckPositionTimeout = 100, // 100ms per check audio pos
|
||||
|
@ -118,6 +121,8 @@ enum {
|
|||
AudioVoiceMsgInMemory = 2 * 1024 * 1024, // 2 Mb audio is hold in memory and auto loaded
|
||||
AudioPauseDeviceTimeout = 3000, // pause in 3 secs after playing is over
|
||||
|
||||
WaveformSamplesCount = 100,
|
||||
|
||||
StickerInMemory = 2 * 1024 * 1024, // 2 Mb stickers hold in memory, auto loaded and displayed inline
|
||||
StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker
|
||||
|
||||
|
@ -127,12 +132,13 @@ enum {
|
|||
MaxZoomLevel = 7, // x8
|
||||
ZoomToScreenLevel = 1024, // just constant
|
||||
|
||||
ShortcutsCountLimit = 256, // how many shortcuts can be in json file
|
||||
|
||||
PreloadHeightsCount = 3, // when 3 screens to scroll left make a preload request
|
||||
EmojiPanPerRow = 7,
|
||||
EmojiPanRowsPerPage = 6,
|
||||
StickerPanPerRow = 5,
|
||||
StickerPanRowsPerPage = 4,
|
||||
SavedGifsMaxPerRow = 4,
|
||||
StickersUpdateTimeout = 3600000, // update not more than once in an hour
|
||||
|
||||
SearchPeopleLimit = 5,
|
||||
|
@ -140,9 +146,9 @@ enum {
|
|||
MaxUsernameLength = 32,
|
||||
UsernameCheckTimeout = 200,
|
||||
|
||||
MaxChannelDescription = 120,
|
||||
MaxChannelDescription = 255,
|
||||
MaxGroupChannelTitle = 255,
|
||||
MaxPhotoCaption = 140,
|
||||
MaxPhotoCaption = 200,
|
||||
|
||||
MaxMessageSize = 4096,
|
||||
MaxHttpRedirects = 5, // when getting external data/images
|
||||
|
@ -167,6 +173,8 @@ enum {
|
|||
|
||||
ChoosePeerByDragTimeout = 1000, // 1 second mouse not moved to choose dialog when dragging a file
|
||||
ReloadChannelMembersTimeout = 1000, // 1 second wait before reload members in channel after adding
|
||||
|
||||
PinnedMessageTextLimit = 16,
|
||||
};
|
||||
|
||||
inline bool isNotificationsUser(uint64 id) {
|
||||
|
@ -191,7 +199,7 @@ inline const char *cGUIDStr() {
|
|||
return gGuidStr;
|
||||
}
|
||||
|
||||
inline const char **cPublicRSAKeys(uint32 &cnt) {
|
||||
inline const char **cPublicRSAKeys(int &keysCount) {
|
||||
static const char *(keys[]) = {"\
|
||||
-----BEGIN RSA PUBLIC KEY-----\n\
|
||||
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n\
|
||||
|
@ -201,7 +209,7 @@ Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+\n\
|
|||
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n\
|
||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n\
|
||||
-----END RSA PUBLIC KEY-----"};
|
||||
cnt = sizeof(keys) / sizeof(const char*);
|
||||
keysCount = arraysize(keys);
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
|
|
@ -16,10 +16,10 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "style.h"
|
||||
#include "gui/style.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "application.h"
|
||||
|
@ -247,18 +247,15 @@ void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool a
|
|||
|
||||
History *history = App::history(peer->id);
|
||||
|
||||
if (peer->migrateTo()) {
|
||||
p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, peer->migrateTo()->photo->pix(st::dlgPhotoSize));
|
||||
} else {
|
||||
p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, peer->photo->pix(st::dlgPhotoSize));
|
||||
}
|
||||
PeerData *userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer);
|
||||
userpicPeer->paintUserpicLeft(p, st::dlgPhotoSize, st::dlgPaddingHor, st::dlgPaddingVer, fullWidth());
|
||||
|
||||
int32 nameleft = st::dlgPaddingHor + st::dlgPhotoSize + st::dlgPhotoPadding;
|
||||
int32 namewidth = w - nameleft - st::dlgPaddingHor;
|
||||
QRect rectForName(nameleft, st::dlgPaddingVer + st::dlgNameTop, namewidth, st::msgNameFont->height);
|
||||
|
||||
// draw chat icon
|
||||
if (peer->isChat()) {
|
||||
if (peer->isChat() || peer->isMegagroup()) {
|
||||
p.drawPixmap(QPoint(rectForName.left() + st::dlgChatImgPos.x(), rectForName.top() + st::dlgChatImgPos.y()), App::sprite(), (act ? st::dlgActiveChatImg : st::dlgChatImg));
|
||||
rectForName.setLeft(rectForName.left() + st::dlgImgSkip);
|
||||
} else if (peer->isChannel()) {
|
||||
|
@ -299,7 +296,7 @@ void DialogsInner::searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) c
|
|||
p.fillRect(fullRect, st::dlgBG->b);
|
||||
if (onlyBackground) return;
|
||||
|
||||
p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, _searchInPeer->photo->pix(st::dlgPhotoSize));
|
||||
_searchInPeer->paintUserpicLeft(p, st::dlgPhotoSize, st::dlgPaddingHor, st::dlgPaddingVer, fullWidth());
|
||||
|
||||
int32 nameleft = st::dlgPaddingHor + st::dlgPhotoSize + st::dlgPhotoPadding;
|
||||
int32 namewidth = w - nameleft - st::dlgPaddingHor * 2 - st::btnCancelSearch.width;
|
||||
|
@ -443,16 +440,12 @@ void DialogsInner::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) {
|
|||
}
|
||||
|
||||
void DialogsInner::createDialog(History *history) {
|
||||
bool creating = history->dialogs.isEmpty();
|
||||
bool creating = !history->inChatList();
|
||||
if (creating) {
|
||||
history->dialogs = dialogs.addToEnd(history);
|
||||
contactsNoDialogs.del(history->peer, history->dialogs[0]);
|
||||
DialogRow *mainRow = history->addToChatList(dialogs);
|
||||
contactsNoDialogs.del(history->peer, mainRow);
|
||||
}
|
||||
|
||||
History::DialogLinks links = history->dialogs;
|
||||
int32 movedFrom = links[0]->pos * st::dlgHeight;
|
||||
dialogs.adjustByPos(links);
|
||||
int32 movedTo = links[0]->pos * st::dlgHeight;
|
||||
RefPair(int32, movedFrom, int32, movedTo) = history->adjustByPosInChatsList(dialogs);
|
||||
|
||||
emit dialogMoved(movedFrom, movedTo);
|
||||
|
||||
|
@ -471,8 +464,7 @@ void DialogsInner::removeDialog(History *history) {
|
|||
if (sel && sel->history == history) {
|
||||
sel = 0;
|
||||
}
|
||||
dialogs.del(history->peer);
|
||||
history->dialogs = History::DialogLinks();
|
||||
history->removeFromChatList(dialogs);
|
||||
history->clearNotifications();
|
||||
if (App::wnd()) App::wnd()->notifyClear(history);
|
||||
if (contacts.list.rowByPeer.constFind(history->peer->id) != contacts.list.rowByPeer.cend()) {
|
||||
|
@ -550,8 +542,8 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
|
|||
if (_state == DefaultState) {
|
||||
if (peer) {
|
||||
if (History *h = App::historyLoaded(peer->id)) {
|
||||
if (h->dialogs.contains(0)) {
|
||||
update(0, h->dialogs.value(0)->pos * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
if (h->inChatList()) {
|
||||
update(0, h->posInChatList() * st::dlgHeight, fullWidth(), st::dlgHeight);
|
||||
}
|
||||
}
|
||||
} else if (sel) {
|
||||
|
@ -624,7 +616,7 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
|
|||
if (_menuPeer->isUser()) {
|
||||
_menu->addAction(lang(lng_profile_clear_history), this, SLOT(onContextClearHistory()))->setEnabled(true);
|
||||
_menu->addAction(lang(lng_profile_delete_conversation), this, SLOT(onContextDeleteAndLeave()))->setEnabled(true);
|
||||
if (_menuPeer->asUser()->access != UserNoAccess) {
|
||||
if (_menuPeer->asUser()->access != UserNoAccess && _menuPeer != App::self()) {
|
||||
_menu->addAction(lang((_menuPeer->asUser()->blocked == UserIsBlocked) ? (_menuPeer->asUser()->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_menuPeer->asUser()->botInfo ? lng_profile_block_bot : lng_profile_block_user)), this, SLOT(onContextToggleBlock()))->setEnabled(true);
|
||||
connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||
}
|
||||
|
@ -651,7 +643,7 @@ void DialogsInner::onContextProfile() {
|
|||
|
||||
void DialogsInner::onContextToggleNotifications() {
|
||||
if (!_menuPeer) return;
|
||||
App::main()->updateNotifySetting(_menuPeer, menuPeerMuted());
|
||||
App::main()->updateNotifySetting(_menuPeer, menuPeerMuted() ? NotifySettingSetNotify : NotifySettingSetMuted);
|
||||
}
|
||||
|
||||
void DialogsInner::onContextSearch() {
|
||||
|
@ -963,7 +955,9 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
|
|||
case mtpc_dialog: {
|
||||
const MTPDdialog &d(i->c_dialog());
|
||||
history = App::historyFromDialog(peerFromMTP(d.vpeer), d.vunread_count.v, d.vread_inbox_max_id.v);
|
||||
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, history);
|
||||
if (App::main()) {
|
||||
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, history);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_dialogChannel: {
|
||||
|
@ -986,7 +980,9 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
|
|||
if (!history->isMegagroup() && d.vtop_message.v > d.vtop_important_message.v) {
|
||||
history->setNotLoadedAtBottom();
|
||||
}
|
||||
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, history);
|
||||
if (App::main()) {
|
||||
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, history);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
|
@ -1015,7 +1011,7 @@ void DialogsInner::addSavedPeersAfter(const QDateTime &date) {
|
|||
SavedPeersByTime &saved(cRefSavedPeersByTime());
|
||||
while (!saved.isEmpty() && (date.isNull() || date < saved.lastKey())) {
|
||||
History *history = App::history(saved.last()->id);
|
||||
history->setPosInDialogsDate(saved.lastKey());
|
||||
history->setChatsListDate(saved.lastKey());
|
||||
contactsNoDialogs.del(history->peer);
|
||||
saved.remove(saved.lastKey(), saved.last());
|
||||
}
|
||||
|
@ -1040,13 +1036,16 @@ bool DialogsInner::searchReceived(const QVector<MTPMessage> &messages, DialogsSe
|
|||
_lastSearchDate = lastDateFound;
|
||||
}
|
||||
}
|
||||
if (type == DialogsSearchFromStart || type == DialogsSearchFromOffset) {
|
||||
_lastSearchPeer = item->history()->peer;
|
||||
if (item) {
|
||||
if (type == DialogsSearchFromStart || type == DialogsSearchFromOffset) {
|
||||
_lastSearchPeer = item->history()->peer;
|
||||
}
|
||||
}
|
||||
MsgId msgId = item ? item->id : idFromMessage(*i);
|
||||
if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) {
|
||||
_lastSearchMigratedId = item->id;
|
||||
_lastSearchMigratedId = msgId;
|
||||
} else {
|
||||
_lastSearchId = item->id;
|
||||
_lastSearchId = msgId;
|
||||
}
|
||||
}
|
||||
if (type == DialogsSearchMigratedFromStart || type == DialogsSearchMigratedFromOffset) {
|
||||
|
@ -1067,8 +1066,11 @@ void DialogsInner::peopleReceived(const QString &query, const QVector<MTPPeer> &
|
|||
_peopleResults.reserve(people.size());
|
||||
for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
|
||||
PeerId peerId = peerFromMTP(*i);
|
||||
History *h = App::historyLoaded(peerId);
|
||||
if (h && !h->dialogs.isEmpty()) continue; // skip dialogs
|
||||
if (History *h = App::historyLoaded(peerId)) {
|
||||
if (h->inChatList()) {
|
||||
continue; // skip existing chats
|
||||
}
|
||||
}
|
||||
|
||||
_peopleResults.push_back(App::peer(peerId));
|
||||
}
|
||||
|
@ -1359,6 +1361,8 @@ void DialogsInner::selectSkipPage(int32 pixels, int32 direction) {
|
|||
}
|
||||
|
||||
void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
||||
if (!parentWidget()) return;
|
||||
|
||||
int32 yTo = yFrom + parentWidget()->height() * 5;
|
||||
MTP::clearLoaderPriorities();
|
||||
if (_state == DefaultState) {
|
||||
|
@ -1366,7 +1370,7 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
|||
if (yFrom < otherStart) {
|
||||
dialogs.list.adjustCurrent(yFrom, st::dlgHeight);
|
||||
for (DialogRow *row = dialogs.list.current; row != dialogs.list.end && (row->pos * st::dlgHeight) < yTo; row = row->next) {
|
||||
row->history->peer->photo->load();
|
||||
row->history->peer->loadUserpic();
|
||||
}
|
||||
yFrom = 0;
|
||||
} else {
|
||||
|
@ -1376,7 +1380,7 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
|||
if (yTo > 0) {
|
||||
contactsNoDialogs.list.adjustCurrent(yFrom, st::dlgHeight);
|
||||
for (DialogRow *row = contactsNoDialogs.list.current; row != contactsNoDialogs.list.end && (row->pos * st::dlgHeight) < yTo; row = row->next) {
|
||||
row->history->peer->photo->load();
|
||||
row->history->peer->loadUserpic();
|
||||
}
|
||||
}
|
||||
} else if (_state == FilteredState || _state == SearchedState) {
|
||||
|
@ -1387,7 +1391,7 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
|||
if (to > _filterResults.size()) to = _filterResults.size();
|
||||
|
||||
for (; from < to; ++from) {
|
||||
_filterResults[from]->history->peer->photo->load();
|
||||
_filterResults[from]->history->peer->loadUserpic();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1398,7 +1402,7 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
|||
if (to > _peopleResults.size()) to = _peopleResults.size();
|
||||
|
||||
for (; from < to; ++from) {
|
||||
_peopleResults[from]->photo->load();
|
||||
_peopleResults[from]->loadUserpic();
|
||||
}
|
||||
}
|
||||
from = (yFrom > filteredOffset() + ((_peopleResults.isEmpty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight) ? ((yFrom - filteredOffset() - (_peopleResults.isEmpty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(st::dlgHeight)) : 0) - _filterResults.size() - _peopleResults.size();
|
||||
|
@ -1408,7 +1412,7 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
|||
if (to > _searchResults.size()) to = _searchResults.size();
|
||||
|
||||
for (; from < to; ++from) {
|
||||
_searchResults[from]->_item->history()->peer->photo->load();
|
||||
_searchResults[from]->_item->history()->peer->loadUserpic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1515,6 +1519,11 @@ void DialogsInner::destroyData() {
|
|||
}
|
||||
|
||||
void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const {
|
||||
if (!inPeer) {
|
||||
outPeer = 0;
|
||||
outMsg = 0;
|
||||
return;
|
||||
}
|
||||
if (_state == DefaultState) {
|
||||
DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(inPeer->id);
|
||||
if (i == dialogs.list.rowByPeer.constEnd()) {
|
||||
|
@ -1599,6 +1608,11 @@ void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&ou
|
|||
}
|
||||
|
||||
void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const {
|
||||
if (!inPeer) {
|
||||
outPeer = 0;
|
||||
outMsg = 0;
|
||||
return;
|
||||
}
|
||||
if (_state == DefaultState) {
|
||||
DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(inPeer->id);
|
||||
if (i == dialogs.list.rowByPeer.constEnd()) {
|
||||
|
@ -1777,11 +1791,11 @@ void DialogsWidget::activate() {
|
|||
}
|
||||
|
||||
void DialogsWidget::createDialog(History *history) {
|
||||
bool creating = history->dialogs.isEmpty();
|
||||
bool creating = !history->inChatList();
|
||||
_inner.createDialog(history);
|
||||
if (creating && history->peer->migrateFrom()) {
|
||||
if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) {
|
||||
if (!h->dialogs.isEmpty()) {
|
||||
if (h->inChatList()) {
|
||||
removeDialog(h);
|
||||
}
|
||||
}
|
||||
|
@ -2038,8 +2052,11 @@ bool DialogsWidget::onSearchMessages(bool searchCache) {
|
|||
MTP::cancel(_searchRequest);
|
||||
}
|
||||
if (_searchInPeer) {
|
||||
int32 flags = (_searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0;
|
||||
_searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, DialogsSearchPeerFromStart), rpcFail(&DialogsWidget::searchFailed, DialogsSearchPeerFromStart));
|
||||
MTPmessages_Search::Flags flags = 0;
|
||||
if (_searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) {
|
||||
flags |= MTPmessages_Search::Flag::f_important_only;
|
||||
}
|
||||
_searchRequest = MTP::send(MTPmessages_Search(MTP_flags(flags), _searchInPeer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, DialogsSearchPeerFromStart), rpcFail(&DialogsWidget::searchFailed, DialogsSearchPeerFromStart));
|
||||
} else {
|
||||
_searchRequest = MTP::send(MTPmessages_SearchGlobal(MTP_string(_searchQuery), MTP_int(0), MTP_inputPeerEmpty(), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, DialogsSearchFromStart), rpcFail(&DialogsWidget::searchFailed, DialogsSearchFromStart));
|
||||
}
|
||||
|
@ -2077,6 +2094,7 @@ void DialogsWidget::onChooseByDrag() {
|
|||
void DialogsWidget::searchMessages(const QString &query, PeerData *inPeer) {
|
||||
if ((_filter.getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) {
|
||||
if (inPeer) {
|
||||
onCancelSearch();
|
||||
_searchInPeer = inPeer->migrateTo() ? inPeer->migrateTo() : inPeer;
|
||||
_searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0;
|
||||
_inner.searchInPeer(_searchInPeer);
|
||||
|
@ -2098,8 +2116,11 @@ void DialogsWidget::onSearchMore() {
|
|||
PeerData *offsetPeer = _inner.lastSearchPeer();
|
||||
MsgId offsetId = _inner.lastSearchId();
|
||||
if (_searchInPeer) {
|
||||
int32 flags = (_searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0;
|
||||
_searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(offsetId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart), rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart));
|
||||
MTPmessages_Search::Flags flags = 0;
|
||||
if (_searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) {
|
||||
flags |= MTPmessages_Search::Flag::f_important_only;
|
||||
}
|
||||
_searchRequest = MTP::send(MTPmessages_Search(MTP_flags(flags), _searchInPeer->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(offsetId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart), rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchPeerFromOffset : DialogsSearchPeerFromStart));
|
||||
} else {
|
||||
_searchRequest = MTP::send(MTPmessages_SearchGlobal(MTP_string(_searchQuery), MTP_int(offsetDate), offsetPeer ? offsetPeer->input : MTP_inputPeerEmpty(), MTP_int(offsetId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart), rpcFail(&DialogsWidget::searchFailed, offsetId ? DialogsSearchFromOffset : DialogsSearchFromStart));
|
||||
}
|
||||
|
@ -2108,8 +2129,11 @@ void DialogsWidget::onSearchMore() {
|
|||
}
|
||||
} else if (_searchInMigrated && !_searchFullMigrated) {
|
||||
MsgId offsetMigratedId = _inner.lastSearchMigratedId();
|
||||
int32 flags = (_searchInMigrated->isChannel() && !_searchInMigrated->isMegagroup()) ? MTPmessages_Search::flag_important_only : 0;
|
||||
_searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInMigrated->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(offsetMigratedId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart), rpcFail(&DialogsWidget::searchFailed, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart));
|
||||
MTPmessages_Search::Flags flags = 0;
|
||||
if (_searchInMigrated->isChannel() && !_searchInMigrated->isMegagroup()) {
|
||||
flags |= MTPmessages_Search::Flag::f_important_only;
|
||||
}
|
||||
_searchRequest = MTP::send(MTPmessages_Search(MTP_flags(flags), _searchInMigrated->input, MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(offsetMigratedId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart), rpcFail(&DialogsWidget::searchFailed, offsetMigratedId ? DialogsSearchMigratedFromOffset : DialogsSearchMigratedFromStart));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2268,7 +2292,7 @@ void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) {
|
|||
_dragForward = e->mimeData()->hasFormat(qsl("application/x-td-forward-selected"));
|
||||
if (!_dragForward) _dragForward = e->mimeData()->hasFormat(qsl("application/x-td-forward-pressed-link"));
|
||||
if (!_dragForward) _dragForward = e->mimeData()->hasFormat(qsl("application/x-td-forward-pressed"));
|
||||
if (_dragForward && !cWideMode()) _dragForward = false;
|
||||
if (_dragForward && Adaptive::OneColumn()) _dragForward = false;
|
||||
if (_dragForward) {
|
||||
e->setDropAction(Qt::CopyAction);
|
||||
e->accept();
|
||||
|
@ -2540,7 +2564,7 @@ bool DialogsWidget::onCancelSearch() {
|
|||
_searchRequest = 0;
|
||||
}
|
||||
if (_searchInPeer && !clearing) {
|
||||
if (!cWideMode()) {
|
||||
if (Adaptive::OneColumn()) {
|
||||
Ui::showPeerHistory(_searchInPeer, ShowAtUnreadMsgId);
|
||||
}
|
||||
_searchInPeer = _searchInMigrated = 0;
|
||||
|
@ -2560,7 +2584,7 @@ void DialogsWidget::onCancelSearchInPeer() {
|
|||
_searchRequest = 0;
|
||||
}
|
||||
if (_searchInPeer) {
|
||||
if (!cWideMode() && !App::main()->selectingPeer()) {
|
||||
if (Adaptive::OneColumn() && !App::main()->selectingPeer()) {
|
||||
Ui::showPeerHistory(_searchInPeer, ShowAtUnreadMsgId);
|
||||
}
|
||||
_searchInPeer = _searchInMigrated = 0;
|
||||
|
@ -2570,7 +2594,7 @@ void DialogsWidget::onCancelSearchInPeer() {
|
|||
_filter.clear();
|
||||
_filter.updatePlaceholder();
|
||||
onFilterUpdate();
|
||||
if (cWideMode() && !App::main()->selectingPeer()) {
|
||||
if (!Adaptive::OneColumn() && !App::main()->selectingPeer()) {
|
||||
emit cancelled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -67,7 +67,6 @@ public:
|
|||
void selectSkipPage(int32 pixels, int32 direction);
|
||||
|
||||
void createDialog(History *history);
|
||||
void moveDialogToTop(const History::DialogLinks &links);
|
||||
void dlgUpdated(DialogRow *row);
|
||||
void dlgUpdated(History *row, MsgId msgId);
|
||||
void removeDialog(History *history);
|
||||
|
@ -220,15 +219,15 @@ public:
|
|||
void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId req);
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *e);
|
||||
void dragMoveEvent(QDragMoveEvent *e);
|
||||
void dragLeaveEvent(QDragLeaveEvent *e);
|
||||
void dropEvent(QDropEvent *e);
|
||||
void dragEnterEvent(QDragEnterEvent *e) override;
|
||||
void dragMoveEvent(QDragMoveEvent *e) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
||||
void dropEvent(QDropEvent *e) override;
|
||||
void updateDragInScroll(bool inScroll);
|
||||
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void searchInPeer(PeerData *peer);
|
||||
|
||||
|
@ -260,6 +259,11 @@ public:
|
|||
|
||||
void updateNotifySettings(PeerData *peer);
|
||||
|
||||
void rpcClear() override {
|
||||
_inner.rpcClear();
|
||||
RPCSender::rpcClear();
|
||||
}
|
||||
|
||||
void notify_userIsContactChanged(UserData *user, bool fromThisApp);
|
||||
|
||||
signals:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -157,8 +157,21 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class EmojiPanel;
|
||||
static const int EmojiColorsCount = 5;
|
||||
namespace InlineBots {
|
||||
namespace Layout {
|
||||
class ItemBase;
|
||||
} // namespace Layout
|
||||
class Result;
|
||||
} // namespace InlineBots
|
||||
|
||||
namespace internal {
|
||||
|
||||
constexpr int InlineItemsMaxPerRow = 5;
|
||||
constexpr int EmojiColorsCount = 5;
|
||||
|
||||
using InlineResult = InlineBots::Result;
|
||||
using InlineResults = QList<InlineBots::Result*>;
|
||||
using InlineItem = InlineBots::Layout::ItemBase;
|
||||
|
||||
class EmojiColorPicker : public TWidget {
|
||||
Q_OBJECT
|
||||
|
@ -222,6 +235,7 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class EmojiPanel;
|
||||
class EmojiPanInner : public TWidget {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -359,8 +373,8 @@ public:
|
|||
|
||||
uint64 currentSet(int yOffset) const;
|
||||
|
||||
void ui_repaintInlineItem(const LayoutInlineItem *layout);
|
||||
bool ui_isInlineItemVisible(const LayoutInlineItem *layout);
|
||||
void ui_repaintInlineItem(const InlineItem *layout);
|
||||
bool ui_isInlineItemVisible(const InlineItem *layout);
|
||||
bool ui_isInlineItemBeingChosen();
|
||||
|
||||
bool inlineResultsShown() const {
|
||||
|
@ -368,11 +382,7 @@ public:
|
|||
}
|
||||
int32 countHeight(bool plain = false);
|
||||
|
||||
~StickerPanInner() {
|
||||
clearInlineRows(true);
|
||||
deleteUnusedGifLayouts();
|
||||
deleteUnusedInlineLayouts();
|
||||
}
|
||||
~StickerPanInner();
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -385,7 +395,7 @@ signals:
|
|||
|
||||
void selected(DocumentData *sticker);
|
||||
void selected(PhotoData *photo);
|
||||
void selected(InlineResult *result, UserData *bot);
|
||||
void selected(InlineBots::Result *result, UserData *bot);
|
||||
|
||||
void removing(quint64 setId);
|
||||
|
||||
|
@ -420,10 +430,10 @@ private:
|
|||
int32 _top;
|
||||
|
||||
struct DisplayedSet {
|
||||
DisplayedSet(uint64 id, int32 flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), hovers(hoversSize, 0), pack(pack) {
|
||||
DisplayedSet(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), hovers(hoversSize, 0), pack(pack) {
|
||||
}
|
||||
uint64 id;
|
||||
int32 flags;
|
||||
MTPDstickerSet::Flags flags;
|
||||
QString title;
|
||||
QVector<float64> hovers;
|
||||
StickerPack pack;
|
||||
|
@ -439,7 +449,7 @@ private:
|
|||
QTimer _updateInlineItems;
|
||||
bool _inlineWithThumb;
|
||||
|
||||
typedef QVector<LayoutInlineItem*> InlineItems;
|
||||
typedef QVector<InlineItem*> InlineItems;
|
||||
struct InlineRow {
|
||||
InlineRow() : height(0) {
|
||||
}
|
||||
|
@ -450,13 +460,13 @@ private:
|
|||
InlineRows _inlineRows;
|
||||
void clearInlineRows(bool resultsDeleted);
|
||||
|
||||
typedef QMap<DocumentData*, LayoutInlineGif*> GifLayouts;
|
||||
using GifLayouts = QMap<DocumentData*, InlineItem*>;
|
||||
GifLayouts _gifLayouts;
|
||||
LayoutInlineGif *layoutPrepareSavedGif(DocumentData *doc, int32 position);
|
||||
InlineItem *layoutPrepareSavedGif(DocumentData *doc, int32 position);
|
||||
|
||||
typedef QMap<InlineResult*, LayoutInlineItem*> InlineLayouts;
|
||||
using InlineLayouts = QMap<InlineResult*, InlineItem*>;
|
||||
InlineLayouts _inlineLayouts;
|
||||
LayoutInlineItem *layoutPrepareInlineResult(InlineResult *result, int32 position);
|
||||
InlineItem *layoutPrepareInlineResult(InlineResult *result, int32 position);
|
||||
|
||||
bool inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, InlineRow &row, int32 &sumWidth);
|
||||
bool inlineRowFinalize(InlineRow &row, int32 &sumWidth, bool force = false);
|
||||
|
@ -469,7 +479,6 @@ private:
|
|||
int32 validateExistingInlineRows(const InlineResults &results);
|
||||
int32 _selected, _pressedSel;
|
||||
QPoint _lastMousePos;
|
||||
TextLinkPtr _linkOver, _linkDown;
|
||||
|
||||
LinkButton _settings;
|
||||
|
||||
|
@ -482,7 +491,7 @@ class EmojiPanel : public TWidget {
|
|||
|
||||
public:
|
||||
|
||||
EmojiPanel(QWidget *parent, const QString &text, uint64 setId, bool special, int32 wantedY); // NoneStickerSetId if in emoji
|
||||
EmojiPanel(QWidget *parent, const QString &text, uint64 setId, bool special, int32 wantedY); // Stickers::NoneSetId if in emoji
|
||||
void setText(const QString &text);
|
||||
void setDeleteVisible(bool isVisible);
|
||||
|
||||
|
@ -532,6 +541,8 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
class EmojiPan : public TWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -580,8 +591,8 @@ public:
|
|||
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||
}
|
||||
|
||||
void ui_repaintInlineItem(const LayoutInlineItem *layout);
|
||||
bool ui_isInlineItemVisible(const LayoutInlineItem *layout);
|
||||
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
|
||||
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);
|
||||
bool ui_isInlineItemBeingChosen();
|
||||
|
||||
bool inlineResultsShown() const {
|
||||
|
@ -622,7 +633,7 @@ signals:
|
|||
void emojiSelected(EmojiPtr emoji);
|
||||
void stickerSelected(DocumentData *sticker);
|
||||
void photoSelected(PhotoData *photo);
|
||||
void inlineResultSelected(InlineResult *result, UserData *bot);
|
||||
void inlineResultSelected(InlineBots::Result *result, UserData *bot);
|
||||
|
||||
void updateStickers();
|
||||
|
||||
|
@ -642,7 +653,7 @@ private:
|
|||
void updateIcons();
|
||||
|
||||
void prepareTab(int32 &left, int32 top, int32 _width, FlatRadiobutton &tab);
|
||||
void updatePanelsPositions(const QVector<EmojiPanel*> &panels, int32 st);
|
||||
void updatePanelsPositions(const QVector<internal::EmojiPanel*> &panels, int32 st);
|
||||
|
||||
void showAll();
|
||||
void hideAll();
|
||||
|
@ -661,7 +672,7 @@ private:
|
|||
BoxShadow _shadow;
|
||||
|
||||
FlatRadiobutton _recent, _people, _nature, _food, _activity, _travel, _objects, _symbols;
|
||||
QList<StickerIcon> _icons;
|
||||
QList<internal::StickerIcon> _icons;
|
||||
QVector<float64> _iconHovers;
|
||||
int32 _iconOver, _iconSel, _iconDown;
|
||||
bool _iconsDragging;
|
||||
|
@ -681,13 +692,13 @@ private:
|
|||
Animation _a_slide;
|
||||
|
||||
ScrollArea e_scroll;
|
||||
EmojiPanInner e_inner;
|
||||
QVector<EmojiPanel*> e_panels;
|
||||
EmojiSwitchButton e_switch;
|
||||
internal::EmojiPanInner e_inner;
|
||||
QVector<internal::EmojiPanel*> e_panels;
|
||||
internal::EmojiSwitchButton e_switch;
|
||||
ScrollArea s_scroll;
|
||||
StickerPanInner s_inner;
|
||||
QVector<EmojiPanel*> s_panels;
|
||||
EmojiSwitchButton s_switch;
|
||||
internal::StickerPanInner s_inner;
|
||||
QVector<internal::EmojiPanel*> s_panels;
|
||||
internal::EmojiSwitchButton s_switch;
|
||||
|
||||
uint64 _removingSetId;
|
||||
|
||||
|
@ -699,13 +710,9 @@ private:
|
|||
clearResults();
|
||||
}
|
||||
QString nextOffset;
|
||||
InlineResults results;
|
||||
void clearResults() {
|
||||
for (int32 i = 0, l = results.size(); i < l; ++i) {
|
||||
delete results.at(i);
|
||||
}
|
||||
results.clear();
|
||||
}
|
||||
QString switchPmText, switchPmStartParam;
|
||||
internal::InlineResults results;
|
||||
void clearResults();
|
||||
};
|
||||
typedef QMap<QString, InlineCacheEntry*> InlineCache;
|
||||
InlineCache _inlineCache;
|
||||
|
@ -734,18 +741,20 @@ class MentionsInner : public TWidget {
|
|||
|
||||
public:
|
||||
|
||||
MentionsInner(MentionsDropdown *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows);
|
||||
MentionsInner(MentionsDropdown *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows, StickerPack *srows);
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
void enterEvent(QEvent *e);
|
||||
void leaveEvent(QEvent *e);
|
||||
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
|
||||
void clearSel();
|
||||
bool moveSel(int direction);
|
||||
void clearSel(bool hidden = false);
|
||||
bool moveSel(int key);
|
||||
bool select();
|
||||
|
||||
void setRecentInlineBotsInRows(int32 bots);
|
||||
|
@ -755,27 +764,35 @@ public:
|
|||
signals:
|
||||
|
||||
void chosen(QString mentionOrHashtag);
|
||||
void selected(DocumentData *sticker);
|
||||
void mustScrollTo(int scrollToTop, int scrollToBottom);
|
||||
|
||||
public slots:
|
||||
|
||||
void onParentGeometryChanged();
|
||||
void onUpdateSelected(bool force = false);
|
||||
void onPreview();
|
||||
|
||||
private:
|
||||
|
||||
void updateSelectedRow();
|
||||
void setSel(int sel, bool scroll = false);
|
||||
|
||||
MentionsDropdown *_parent;
|
||||
MentionRows *_mrows;
|
||||
HashtagRows *_hrows;
|
||||
BotCommandRows *_brows;
|
||||
int32 _recentInlineBotsInRows;
|
||||
int32 _sel;
|
||||
StickerPack *_srows;
|
||||
int32 _stickersPerRow, _recentInlineBotsInRows;
|
||||
int32 _sel, _down;
|
||||
bool _mouseSel;
|
||||
QPoint _mousePos;
|
||||
|
||||
bool _overDelete;
|
||||
|
||||
bool _previewShown;
|
||||
|
||||
QTimer _previewTimer;
|
||||
};
|
||||
|
||||
class MentionsDropdown : public TWidget {
|
||||
|
@ -791,7 +808,8 @@ public:
|
|||
|
||||
bool clearFilteredBotCommands();
|
||||
void showFiltered(PeerData *peer, QString query, bool start);
|
||||
void updateFiltered(bool toDown = false);
|
||||
void showStickers(EmojiPtr emoji);
|
||||
void updateFiltered(bool resetScroll = false);
|
||||
void setBoundings(QRect boundings);
|
||||
|
||||
void step_appearance(float64 ms, bool timer);
|
||||
|
@ -807,6 +825,10 @@ public:
|
|||
bool eventFilter(QObject *obj, QEvent *e);
|
||||
QString getSelected() const;
|
||||
|
||||
bool stickersShown() const {
|
||||
return !_srows.isEmpty();
|
||||
}
|
||||
|
||||
bool overlaps(const QRect &globalRect) {
|
||||
if (isHidden() || !testAttribute(Qt::WA_OpaquePaintEvent)) return false;
|
||||
|
||||
|
@ -818,6 +840,7 @@ public:
|
|||
signals:
|
||||
|
||||
void chosen(QString mentionOrHashtag);
|
||||
void stickerSelected(DocumentData *sticker);
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -828,14 +851,15 @@ public slots:
|
|||
|
||||
private:
|
||||
|
||||
void recount(bool toDown = false);
|
||||
void recount(bool resetScroll = false);
|
||||
|
||||
QPixmap _cache;
|
||||
MentionRows _mrows;
|
||||
HashtagRows _hrows;
|
||||
BotCommandRows _brows;
|
||||
StickerPack _srows;
|
||||
|
||||
void rowsUpdated(const MentionRows &mrows, const HashtagRows &hrows, const BotCommandRows &brows, bool toDown);
|
||||
void rowsUpdated(const MentionRows &mrows, const HashtagRows &hrows, const BotCommandRows &brows, const StickerPack &srows, bool resetScroll);
|
||||
|
||||
ScrollArea _scroll;
|
||||
MentionsInner _inner;
|
||||
|
@ -843,6 +867,7 @@ private:
|
|||
ChatData *_chat;
|
||||
UserData *_user;
|
||||
ChannelData *_channel;
|
||||
EmojiPtr _emoji;
|
||||
QString _filter;
|
||||
QRect _boundings;
|
||||
bool _addInlineBots;
|
||||
|
|
|
@ -16,19 +16,26 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mainwidget.h"
|
||||
#include "application.h"
|
||||
|
||||
#include "boxes/confirmbox.h"
|
||||
|
||||
#include "layerwidget.h"
|
||||
#include "lang.h"
|
||||
|
||||
Q_DECLARE_METATYPE(ClickHandlerPtr);
|
||||
Q_DECLARE_METATYPE(Qt::MouseButton);
|
||||
|
||||
namespace App {
|
||||
|
||||
void sendBotCommand(const QString &cmd, MsgId replyTo) {
|
||||
if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo) {
|
||||
if (MainWidget *m = main()) m->sendBotCommand(peer, cmd, replyTo);
|
||||
}
|
||||
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif) {
|
||||
|
@ -36,12 +43,55 @@ namespace App {
|
|||
return false;
|
||||
}
|
||||
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer) {
|
||||
if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
|
||||
void activateBotCommand(const HistoryItem *msg, int row, int col) {
|
||||
const HistoryMessageReplyMarkup::Button *button = nullptr;
|
||||
if (auto *markup = msg->Get<HistoryMessageReplyMarkup>()) {
|
||||
if (row < markup->rows.size()) {
|
||||
const HistoryMessageReplyMarkup::ButtonRow &buttonRow(markup->rows.at(row));
|
||||
if (col < buttonRow.size()) {
|
||||
button = &buttonRow.at(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!button) return;
|
||||
|
||||
switch (button->type) {
|
||||
case HistoryMessageReplyMarkup::Button::Default: {
|
||||
// Copy string before passing it to the sending method
|
||||
// because the original button can be destroyed inside.
|
||||
MsgId replyTo = (msg->id > 0) ? msg->id : 0;
|
||||
sendBotCommand(msg->history()->peer, QString(button->text), replyTo);
|
||||
} break;
|
||||
|
||||
case HistoryMessageReplyMarkup::Button::Callback: {
|
||||
if (MainWidget *m = main()) {
|
||||
m->app_sendBotCallback(button, msg, row, col);
|
||||
}
|
||||
} break;
|
||||
|
||||
case HistoryMessageReplyMarkup::Button::Url: {
|
||||
auto url = QString::fromUtf8(button->data);
|
||||
HiddenUrlClickHandler(url).onClick(Qt::LeftButton);
|
||||
} break;
|
||||
|
||||
case HistoryMessageReplyMarkup::Button::RequestLocation: {
|
||||
Ui::showLayer(new InformBox(lang(lng_bot_share_location_unavailable)));
|
||||
} break;
|
||||
|
||||
case HistoryMessageReplyMarkup::Button::RequestPhone: {
|
||||
SharePhoneConfirmBox *box = new SharePhoneConfirmBox(msg->history()->peer);
|
||||
box->connect(box, SIGNAL(confirmed(PeerData*)), App::main(), SLOT(onSharePhoneWithBot(PeerData*)));
|
||||
Ui::showLayer(box);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
|
||||
if (MainWidget *m = main()) m->openPeerByName(username, toProfile, startToken);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer) {
|
||||
if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel() && !inPeer->isMegagroup()) ? inPeer : 0);
|
||||
}
|
||||
|
||||
void openPeerByName(const QString &username, MsgId msgId, const QString &startToken) {
|
||||
if (MainWidget *m = main()) m->openPeerByName(username, msgId, startToken);
|
||||
}
|
||||
|
||||
void joinGroupByHash(const QString &hash) {
|
||||
|
@ -62,11 +112,29 @@ namespace App {
|
|||
}
|
||||
|
||||
void removeDialog(History *history) {
|
||||
if (MainWidget *m = main()) m->removeDialog(history);
|
||||
if (MainWidget *m = main()) {
|
||||
m->removeDialog(history);
|
||||
}
|
||||
}
|
||||
|
||||
void showSettings() {
|
||||
if (Window *win = wnd()) win->showSettings();
|
||||
if (Window *w = wnd()) {
|
||||
w->showSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||
if (Window *w = wnd()) {
|
||||
qRegisterMetaType<ClickHandlerPtr>();
|
||||
qRegisterMetaType<Qt::MouseButton>();
|
||||
QMetaObject::invokeMethod(w, "app_activateClickHandler", Qt::QueuedConnection, Q_ARG(ClickHandlerPtr, handler), Q_ARG(Qt::MouseButton, button));
|
||||
}
|
||||
}
|
||||
|
||||
void logOutDelayed() {
|
||||
if (Window *w = App::wnd()) {
|
||||
QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -74,11 +142,15 @@ namespace App {
|
|||
namespace Ui {
|
||||
|
||||
void showStickerPreview(DocumentData *sticker) {
|
||||
if (MainWidget *m = App::main()) m->ui_showStickerPreview(sticker);
|
||||
if (Window *w = App::wnd()) {
|
||||
w->ui_showStickerPreview(sticker);
|
||||
}
|
||||
}
|
||||
|
||||
void hideStickerPreview() {
|
||||
if (MainWidget *m = App::main()) m->ui_hideStickerPreview();
|
||||
if (Window *w = App::wnd()) {
|
||||
w->ui_hideStickerPreview();
|
||||
}
|
||||
}
|
||||
|
||||
void showLayer(LayeredWidget *box, ShowLayerOptions options) {
|
||||
|
@ -113,16 +185,22 @@ namespace Ui {
|
|||
if (MainWidget *m = App::main()) m->ui_repaintHistoryItem(item);
|
||||
}
|
||||
|
||||
void repaintInlineItem(const LayoutInlineItem *layout) {
|
||||
void repaintInlineItem(const InlineBots::Layout::ItemBase *layout) {
|
||||
if (!layout) return;
|
||||
if (MainWidget *m = App::main()) m->ui_repaintInlineItem(layout);
|
||||
}
|
||||
|
||||
bool isInlineItemVisible(const LayoutInlineItem *layout) {
|
||||
bool isInlineItemVisible(const InlineBots::Layout::ItemBase *layout) {
|
||||
if (MainWidget *m = App::main()) return m->ui_isInlineItemVisible(layout);
|
||||
return false;
|
||||
}
|
||||
|
||||
void autoplayMediaInlineAsync(const FullMsgId &msgId) {
|
||||
if (MainWidget *m = App::main()) {
|
||||
QMetaObject::invokeMethod(m, "ui_autoplayMediaInlineAsync", Qt::QueuedConnection, Q_ARG(qint32, msgId.channel), Q_ARG(qint32, msgId.msg));
|
||||
}
|
||||
}
|
||||
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) {
|
||||
if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, back);
|
||||
}
|
||||
|
@ -133,6 +211,29 @@ namespace Ui {
|
|||
}
|
||||
}
|
||||
|
||||
PeerData *getPeerForMouseAction() {
|
||||
if (Window *w = App::wnd()) {
|
||||
return w->ui_getPeerForMouseAction();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hideWindowNoQuit() {
|
||||
if (!App::quitting()) {
|
||||
if (Window *w = App::wnd()) {
|
||||
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
|
||||
return w->minimizeToTray();
|
||||
} else if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
||||
w->hide();
|
||||
w->updateIsActive(Global::OfflineBlurTimeout());
|
||||
w->updateGlobalMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Notify {
|
||||
|
@ -153,6 +254,12 @@ namespace Notify {
|
|||
if (MainWidget *m = App::main()) m->notify_inlineBotRequesting(requesting);
|
||||
}
|
||||
|
||||
void replyMarkupUpdated(const HistoryItem *item) {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->notify_replyMarkupUpdated(item);
|
||||
}
|
||||
}
|
||||
|
||||
void migrateUpdated(PeerData *peer) {
|
||||
if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer);
|
||||
}
|
||||
|
@ -161,10 +268,6 @@ namespace Notify {
|
|||
if (MainWidget *m = App::main()) m->notify_clipStopperHidden(type);
|
||||
}
|
||||
|
||||
void historyItemResized(const HistoryItem *item, bool scrollToIt) {
|
||||
if (MainWidget *m = App::main()) m->notify_historyItemResized(item, scrollToIt);
|
||||
}
|
||||
|
||||
void historyItemLayoutChanged(const HistoryItem *item) {
|
||||
if (MainWidget *m = App::main()) m->notify_historyItemLayoutChanged(item);
|
||||
}
|
||||
|
@ -173,4 +276,263 @@ namespace Notify {
|
|||
if (MainWidget *m = App::main()) m->notify_automaticLoadSettingsChangedGif();
|
||||
}
|
||||
|
||||
void handlePendingHistoryUpdate() {
|
||||
if (MainWidget *m = App::main()) {
|
||||
m->notify_handlePendingHistoryUpdate();
|
||||
}
|
||||
for_const (HistoryItem *item, Global::PendingRepaintItems()) {
|
||||
Ui::repaintHistoryItem(item);
|
||||
}
|
||||
Global::RefPendingRepaintItems().clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define DefineReadOnlyVar(Namespace, Type, Name) const Type &Name() { \
|
||||
t_assert_full(Namespace##Data != 0, #Namespace "Data != nullptr in " #Namespace "::" #Name, __FILE__, __LINE__); \
|
||||
return Namespace##Data->Name; \
|
||||
}
|
||||
#define DefineRefVar(Namespace, Type, Name) DefineReadOnlyVar(Namespace, Type, Name) \
|
||||
Type &Ref##Name() { \
|
||||
t_assert_full(Namespace##Data != 0, #Namespace "Data != nullptr in " #Namespace "::Ref" #Name, __FILE__, __LINE__); \
|
||||
return Namespace##Data->Name; \
|
||||
}
|
||||
#define DefineVar(Namespace, Type, Name) DefineRefVar(Namespace, Type, Name) \
|
||||
void Set##Name(const Type &Name) { \
|
||||
t_assert_full(Namespace##Data != 0, #Namespace "Data != nullptr in " #Namespace "::Set" #Name, __FILE__, __LINE__); \
|
||||
Namespace##Data->Name = Name; \
|
||||
}
|
||||
|
||||
namespace Sandbox {
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct Data {
|
||||
QString LangSystemISO;
|
||||
int32 LangSystem = languageDefault;
|
||||
|
||||
QByteArray LastCrashDump;
|
||||
ConnectionProxy PreLaunchProxy;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Sandbox::internal::Data *SandboxData = 0;
|
||||
uint64 SandboxUserTag = 0;
|
||||
|
||||
namespace Sandbox {
|
||||
|
||||
bool CheckBetaVersionDir() {
|
||||
QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta"));
|
||||
if (cBetaVersion()) {
|
||||
cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
|
||||
QDir().mkpath(cWorkingDir() + qstr("tdata"));
|
||||
if (*BetaPrivateKey) {
|
||||
cSetBetaPrivateKey(QByteArray(BetaPrivateKey));
|
||||
}
|
||||
if (beta.open(QIODevice::WriteOnly)) {
|
||||
QDataStream dataStream(&beta);
|
||||
dataStream.setVersion(QDataStream::Qt_5_3);
|
||||
dataStream << quint64(cRealBetaVersion()) << cBetaPrivateKey();
|
||||
} else {
|
||||
LOG(("FATAL: Could not open '%1' for writing private key!").arg(beta.fileName()));
|
||||
return false;
|
||||
}
|
||||
} else if (beta.exists()) {
|
||||
cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
|
||||
if (beta.open(QIODevice::ReadOnly)) {
|
||||
QDataStream dataStream(&beta);
|
||||
dataStream.setVersion(QDataStream::Qt_5_3);
|
||||
|
||||
quint64 v;
|
||||
QByteArray k;
|
||||
dataStream >> v >> k;
|
||||
if (dataStream.status() == QDataStream::Ok) {
|
||||
cSetBetaVersion(qMax(v, AppVersion * 1000ULL));
|
||||
cSetBetaPrivateKey(k);
|
||||
cSetRealBetaVersion(v);
|
||||
} else {
|
||||
LOG(("FATAL: '%1' is corrupted, reinstall private beta!").arg(beta.fileName()));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(("FATAL: could not open '%1' for reading private key!").arg(beta.fileName()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorkingDirReady() {
|
||||
if (QFile(cWorkingDir() + qsl("tdata/withtestmode")).exists()) {
|
||||
cSetTestMode(true);
|
||||
}
|
||||
if (!cDebug() && QFile(cWorkingDir() + qsl("tdata/withdebug")).exists()) {
|
||||
cSetDebug(true);
|
||||
}
|
||||
if (cBetaVersion()) {
|
||||
cSetDevVersion(false);
|
||||
} else if (!cDevVersion() && QFile(cWorkingDir() + qsl("tdata/devversion")).exists()) {
|
||||
cSetDevVersion(true);
|
||||
} else if (DevVersion) {
|
||||
QFile f(cWorkingDir() + qsl("tdata/devversion"));
|
||||
if (!f.exists() && f.open(QIODevice::WriteOnly)) {
|
||||
f.write("1");
|
||||
}
|
||||
}
|
||||
|
||||
srand((int32)time(NULL));
|
||||
|
||||
SandboxUserTag = 0;
|
||||
QFile usertag(cWorkingDir() + qsl("tdata/usertag"));
|
||||
if (usertag.open(QIODevice::ReadOnly)) {
|
||||
if (usertag.read(reinterpret_cast<char*>(&SandboxUserTag), sizeof(uint64)) != sizeof(uint64)) {
|
||||
SandboxUserTag = 0;
|
||||
}
|
||||
usertag.close();
|
||||
}
|
||||
if (!SandboxUserTag) {
|
||||
do {
|
||||
memsetrnd_bad(SandboxUserTag);
|
||||
} while (!SandboxUserTag);
|
||||
|
||||
if (usertag.open(QIODevice::WriteOnly)) {
|
||||
usertag.write(reinterpret_cast<char*>(&SandboxUserTag), sizeof(uint64));
|
||||
usertag.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
SandboxData = new internal::Data();
|
||||
|
||||
SandboxData->LangSystemISO = psCurrentLanguage();
|
||||
if (SandboxData->LangSystemISO.isEmpty()) SandboxData->LangSystemISO = qstr("en");
|
||||
QByteArray l = LangSystemISO().toLatin1();
|
||||
for (int32 i = 0; i < languageCount; ++i) {
|
||||
if (l.at(0) == LanguageCodes[i][0] && l.at(1) == LanguageCodes[i][1]) {
|
||||
SandboxData->LangSystem = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void finish() {
|
||||
delete SandboxData;
|
||||
SandboxData = 0;
|
||||
}
|
||||
|
||||
uint64 UserTag() {
|
||||
return SandboxUserTag;
|
||||
}
|
||||
|
||||
DefineReadOnlyVar(Sandbox, QString, LangSystemISO);
|
||||
DefineReadOnlyVar(Sandbox, int32, LangSystem);
|
||||
DefineVar(Sandbox, QByteArray, LastCrashDump);
|
||||
DefineVar(Sandbox, ConnectionProxy, PreLaunchProxy);
|
||||
|
||||
}
|
||||
|
||||
namespace Global {
|
||||
namespace internal {
|
||||
|
||||
struct Data {
|
||||
uint64 LaunchId = 0;
|
||||
SingleDelayedCall HandleHistoryUpdate = { App::app(), "call_handleHistoryUpdate" };
|
||||
|
||||
Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout;
|
||||
bool AdaptiveForWide = true;
|
||||
|
||||
int32 DebugLoggingFlags = 0;
|
||||
|
||||
// config
|
||||
int32 ChatSizeMax = 200;
|
||||
int32 MegagroupSizeMax = 1000;
|
||||
int32 ForwardedCountMax = 100;
|
||||
int32 OnlineUpdatePeriod = 120000;
|
||||
int32 OfflineBlurTimeout = 5000;
|
||||
int32 OfflineIdleTimeout = 30000;
|
||||
int32 OnlineFocusTimeout = 1000;
|
||||
int32 OnlineCloudTimeout = 300000;
|
||||
int32 NotifyCloudDelay = 30000;
|
||||
int32 NotifyDefaultDelay = 1500;
|
||||
int32 ChatBigSize = 10;
|
||||
int32 PushChatPeriod = 60000;
|
||||
int32 PushChatLimit = 2;
|
||||
int32 SavedGifsLimit = 200;
|
||||
int32 EditTimeLimit = 172800;
|
||||
|
||||
HiddenPinnedMessagesMap HiddenPinnedMessages;
|
||||
|
||||
PendingItemsMap PendingRepaintItems;
|
||||
|
||||
Stickers::Sets StickerSets;
|
||||
Stickers::Order StickerSetsOrder;
|
||||
uint64 LastStickersUpdate = 0;
|
||||
|
||||
MTP::DcOptions DcOptions;
|
||||
|
||||
CircleMasksMap CircleMasks;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Global::internal::Data *GlobalData = 0;
|
||||
|
||||
namespace Global {
|
||||
|
||||
bool started() {
|
||||
return GlobalData != 0;
|
||||
}
|
||||
|
||||
void start() {
|
||||
GlobalData = new internal::Data();
|
||||
|
||||
memset_rand(&GlobalData->LaunchId, sizeof(GlobalData->LaunchId));
|
||||
}
|
||||
|
||||
void finish() {
|
||||
delete GlobalData;
|
||||
GlobalData = 0;
|
||||
}
|
||||
|
||||
DefineReadOnlyVar(Global, uint64, LaunchId);
|
||||
DefineRefVar(Global, SingleDelayedCall, HandleHistoryUpdate);
|
||||
|
||||
DefineVar(Global, Adaptive::Layout, AdaptiveLayout);
|
||||
DefineVar(Global, bool, AdaptiveForWide);
|
||||
|
||||
DefineVar(Global, int32, DebugLoggingFlags);
|
||||
|
||||
// config
|
||||
DefineVar(Global, int32, ChatSizeMax);
|
||||
DefineVar(Global, int32, MegagroupSizeMax);
|
||||
DefineVar(Global, int32, ForwardedCountMax);
|
||||
DefineVar(Global, int32, OnlineUpdatePeriod);
|
||||
DefineVar(Global, int32, OfflineBlurTimeout);
|
||||
DefineVar(Global, int32, OfflineIdleTimeout);
|
||||
DefineVar(Global, int32, OnlineFocusTimeout);
|
||||
DefineVar(Global, int32, OnlineCloudTimeout);
|
||||
DefineVar(Global, int32, NotifyCloudDelay);
|
||||
DefineVar(Global, int32, NotifyDefaultDelay);
|
||||
DefineVar(Global, int32, ChatBigSize);
|
||||
DefineVar(Global, int32, PushChatPeriod);
|
||||
DefineVar(Global, int32, PushChatLimit);
|
||||
DefineVar(Global, int32, SavedGifsLimit);
|
||||
DefineVar(Global, int32, EditTimeLimit);
|
||||
|
||||
DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages);
|
||||
|
||||
DefineRefVar(Global, PendingItemsMap, PendingRepaintItems);
|
||||
|
||||
DefineVar(Global, Stickers::Sets, StickerSets);
|
||||
DefineVar(Global, Stickers::Order, StickerSetsOrder);
|
||||
DefineVar(Global, uint64, LastStickersUpdate);
|
||||
|
||||
DefineVar(Global, MTP::DcOptions, DcOptions);
|
||||
|
||||
DefineRefVar(Global, CircleMasksMap, CircleMasks);
|
||||
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -24,10 +24,11 @@ class LayeredWidget;
|
|||
|
||||
namespace App {
|
||||
|
||||
void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
|
||||
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0);
|
||||
bool insertBotCommand(const QString &cmd, bool specialGif = false);
|
||||
void activateBotCommand(const HistoryItem *msg, int row, int col);
|
||||
void searchByHashtag(const QString &tag, PeerData *inPeer);
|
||||
void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
|
||||
void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
|
||||
void joinGroupByHash(const QString &hash);
|
||||
void stickersBox(const QString &name);
|
||||
void openLocalUrl(const QString &url);
|
||||
|
@ -35,9 +36,21 @@ namespace App {
|
|||
void removeDialog(History *history);
|
||||
void showSettings();
|
||||
|
||||
void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
||||
|
||||
void logOutDelayed();
|
||||
|
||||
};
|
||||
|
||||
namespace Ui { // openssl doesn't allow me to use UI :(
|
||||
namespace InlineBots {
|
||||
namespace Layout {
|
||||
|
||||
class ItemBase;
|
||||
|
||||
} // namespace Layout
|
||||
} // namespace InlineBots
|
||||
|
||||
namespace Ui {
|
||||
|
||||
void showStickerPreview(DocumentData *sticker);
|
||||
void hideStickerPreview();
|
||||
|
@ -49,8 +62,9 @@ namespace Ui { // openssl doesn't allow me to use UI :(
|
|||
bool isInlineItemBeingChosen();
|
||||
|
||||
void repaintHistoryItem(const HistoryItem *item);
|
||||
void repaintInlineItem(const LayoutInlineItem *layout);
|
||||
bool isInlineItemVisible(const LayoutInlineItem *reader);
|
||||
void repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
|
||||
bool isInlineItemVisible(const InlineBots::Layout::ItemBase *reader);
|
||||
void autoplayMediaInlineAsync(const FullMsgId &msgId);
|
||||
|
||||
void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
|
||||
inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
|
||||
|
@ -66,6 +80,12 @@ namespace Ui { // openssl doesn't allow me to use UI :(
|
|||
inline void showChatsList() {
|
||||
showPeerHistory(PeerId(0), 0);
|
||||
}
|
||||
inline void showChatsListAsync() {
|
||||
showPeerHistoryAsync(PeerId(0), 0);
|
||||
}
|
||||
PeerData *getPeerForMouseAction();
|
||||
|
||||
bool hideWindowNoQuit();
|
||||
|
||||
};
|
||||
|
||||
|
@ -81,17 +101,138 @@ namespace Notify {
|
|||
void botCommandsChanged(UserData *user);
|
||||
|
||||
void inlineBotRequesting(bool requesting);
|
||||
void replyMarkupUpdated(const HistoryItem *item);
|
||||
|
||||
void migrateUpdated(PeerData *peer);
|
||||
|
||||
void clipStopperHidden(ClipStopperType type);
|
||||
|
||||
void historyItemResized(const HistoryItem *item, bool scrollToIt = false);
|
||||
inline void historyItemsResized() {
|
||||
historyItemResized(0);
|
||||
}
|
||||
void historyItemLayoutChanged(const HistoryItem *item);
|
||||
|
||||
void automaticLoadSettingsChangedGif();
|
||||
|
||||
// handle pending resize() / paint() on history items
|
||||
void handlePendingHistoryUpdate();
|
||||
|
||||
};
|
||||
|
||||
#define DeclareReadOnlyVar(Type, Name) const Type &Name();
|
||||
#define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \
|
||||
Type &Ref##Name();
|
||||
#define DeclareVar(Type, Name) DeclareRefVar(Type, Name) \
|
||||
void Set##Name(const Type &Name);
|
||||
|
||||
namespace Sandbox {
|
||||
|
||||
bool CheckBetaVersionDir();
|
||||
void WorkingDirReady();
|
||||
|
||||
void start();
|
||||
void finish();
|
||||
|
||||
uint64 UserTag();
|
||||
|
||||
DeclareReadOnlyVar(QString, LangSystemISO);
|
||||
DeclareReadOnlyVar(int32, LangSystem);
|
||||
DeclareVar(QByteArray, LastCrashDump);
|
||||
DeclareVar(ConnectionProxy, PreLaunchProxy);
|
||||
|
||||
}
|
||||
|
||||
namespace Adaptive {
|
||||
enum Layout {
|
||||
OneColumnLayout,
|
||||
NormalLayout,
|
||||
WideLayout,
|
||||
};
|
||||
};
|
||||
|
||||
namespace DebugLogging {
|
||||
enum Flags {
|
||||
FileLoaderFlag = 0x00000001,
|
||||
};
|
||||
}
|
||||
|
||||
namespace Stickers {
|
||||
static const uint64 DefaultSetId = 0; // for backward compatibility
|
||||
static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
|
||||
static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
|
||||
struct Set {
|
||||
Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) : id(id), access(access), title(title), shortName(shortName), count(count), hash(hash), flags(flags) {
|
||||
}
|
||||
uint64 id, access;
|
||||
QString title, shortName;
|
||||
int32 count, hash;
|
||||
MTPDstickerSet::Flags flags;
|
||||
StickerPack stickers;
|
||||
StickersByEmojiMap emoji;
|
||||
};
|
||||
typedef QMap<uint64, Set> Sets;
|
||||
typedef QList<uint64> Order;
|
||||
}
|
||||
|
||||
namespace Global {
|
||||
|
||||
bool started();
|
||||
void start();
|
||||
void finish();
|
||||
|
||||
DeclareReadOnlyVar(uint64, LaunchId);
|
||||
DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate);
|
||||
|
||||
DeclareVar(Adaptive::Layout, AdaptiveLayout);
|
||||
DeclareVar(bool, AdaptiveForWide);
|
||||
|
||||
DeclareVar(int32, DebugLoggingFlags);
|
||||
|
||||
// config
|
||||
DeclareVar(int32, ChatSizeMax);
|
||||
DeclareVar(int32, MegagroupSizeMax);
|
||||
DeclareVar(int32, ForwardedCountMax);
|
||||
DeclareVar(int32, OnlineUpdatePeriod);
|
||||
DeclareVar(int32, OfflineBlurTimeout);
|
||||
DeclareVar(int32, OfflineIdleTimeout);
|
||||
DeclareVar(int32, OnlineFocusTimeout); // not from config
|
||||
DeclareVar(int32, OnlineCloudTimeout);
|
||||
DeclareVar(int32, NotifyCloudDelay);
|
||||
DeclareVar(int32, NotifyDefaultDelay);
|
||||
DeclareVar(int32, ChatBigSize);
|
||||
DeclareVar(int32, PushChatPeriod);
|
||||
DeclareVar(int32, PushChatLimit);
|
||||
DeclareVar(int32, SavedGifsLimit);
|
||||
DeclareVar(int32, EditTimeLimit);
|
||||
|
||||
typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
|
||||
DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);
|
||||
|
||||
typedef OrderedSet<HistoryItem*> PendingItemsMap;
|
||||
DeclareRefVar(PendingItemsMap, PendingRepaintItems);
|
||||
|
||||
DeclareVar(Stickers::Sets, StickerSets);
|
||||
DeclareVar(Stickers::Order, StickerSetsOrder);
|
||||
DeclareVar(uint64, LastStickersUpdate);
|
||||
|
||||
DeclareVar(MTP::DcOptions, DcOptions);
|
||||
|
||||
typedef QMap<uint64, QPixmap> CircleMasksMap;
|
||||
DeclareRefVar(CircleMasksMap, CircleMasks);
|
||||
|
||||
};
|
||||
|
||||
namespace Adaptive {
|
||||
inline bool OneColumn() {
|
||||
return Global::AdaptiveLayout() == OneColumnLayout;
|
||||
}
|
||||
inline bool Normal() {
|
||||
return Global::AdaptiveLayout() == NormalLayout;
|
||||
}
|
||||
inline bool Wide() {
|
||||
return Global::AdaptiveForWide() && (Global::AdaptiveLayout() == WideLayout);
|
||||
}
|
||||
}
|
||||
|
||||
namespace DebugLogging {
|
||||
inline bool FileLoader() {
|
||||
return (Global::DebugLoggingFlags() | FileLoaderFlag) != 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "fileuploader.h"
|
||||
|
@ -32,7 +32,7 @@ FileUploader::FileUploader() : sentSize(0) {
|
|||
void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &media) {
|
||||
if (media.type == PreparePhoto) {
|
||||
App::feedPhoto(media.photo, media.photoThumbs);
|
||||
} else if (media.type == PrepareDocument) {
|
||||
} else if (media.type == PrepareDocument || media.type == PrepareAudio) {
|
||||
DocumentData *document;
|
||||
if (media.photoThumbs.isEmpty()) {
|
||||
document = App::feedDocument(media.document);
|
||||
|
@ -40,13 +40,12 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
|||
document = App::feedDocument(media.document, media.photoThumbs.begin().value());
|
||||
}
|
||||
document->status = FileUploading;
|
||||
if (!media.data.isEmpty()) {
|
||||
document->setData(media.data);
|
||||
}
|
||||
if (!media.file.isEmpty()) {
|
||||
document->setLocation(FileLocation(StorageFilePartial, media.file));
|
||||
}
|
||||
} else if (media.type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(media.audio);
|
||||
audio->status = FileUploading;
|
||||
audio->setData(media.data);
|
||||
}
|
||||
queue.insert(msgId, File(media));
|
||||
sendNext();
|
||||
|
@ -56,7 +55,7 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
|
|||
if (file->type == PreparePhoto) {
|
||||
PhotoData *photo = App::feedPhoto(file->photo, file->photoThumbs);
|
||||
photo->uploadingData = new PhotoData::UploadingData(file->partssize);
|
||||
} else if (file->type == PrepareDocument) {
|
||||
} else if (file->type == PrepareDocument || file->type == PrepareAudio) {
|
||||
DocumentData *document;
|
||||
if (file->thumb.isNull()) {
|
||||
document = App::feedDocument(file->document);
|
||||
|
@ -64,13 +63,12 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
|
|||
document = App::feedDocument(file->document, file->thumb);
|
||||
}
|
||||
document->status = FileUploading;
|
||||
if (!file->content.isEmpty()) {
|
||||
document->setData(file->content);
|
||||
}
|
||||
if (!file->filepath.isEmpty()) {
|
||||
document->setLocation(FileLocation(StorageFilePartial, file->filepath));
|
||||
}
|
||||
} else if (file->type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(file->audio);
|
||||
audio->status = FileUploading;
|
||||
audio->setData(file->content);
|
||||
}
|
||||
queue.insert(msgId, File(file));
|
||||
sendNext();
|
||||
|
@ -87,12 +85,6 @@ void FileUploader::currentFailed() {
|
|||
doc->status = FileUploadFailed;
|
||||
}
|
||||
emit documentFailed(j.key());
|
||||
} else if (j->type() == PrepareAudio) {
|
||||
AudioData *audio = App::audio(j->id());
|
||||
if (audio->status == FileUploading) {
|
||||
audio->status = FileUploadFailed;
|
||||
}
|
||||
emit audioFailed(j.key());
|
||||
}
|
||||
queue.erase(j);
|
||||
}
|
||||
|
@ -111,7 +103,7 @@ void FileUploader::currentFailed() {
|
|||
|
||||
void FileUploader::killSessions() {
|
||||
for (int i = 0; i < MTPUploadSessionsCount; ++i) {
|
||||
MTP::stopSession(MTP::upl[i]);
|
||||
MTP::stopSession(MTP::uplDcId(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,24 +140,19 @@ void FileUploader::sendNext() {
|
|||
if (parts.isEmpty()) {
|
||||
if (i->docSentParts >= i->docPartsCount) {
|
||||
if (requestsSent.isEmpty() && docRequestsSent.isEmpty()) {
|
||||
bool silent = i->file && i->file->to.silent;
|
||||
if (i->type() == PreparePhoto) {
|
||||
emit photoReady(uploading, MTP_inputFile(MTP_long(i->id()), MTP_int(i->partsCount), MTP_string(i->filename()), MTP_string(i->file ? i->file->filemd5 : i->media.jpeg_md5)));
|
||||
} else if (i->type() == PrepareDocument) {
|
||||
emit photoReady(uploading, silent, MTP_inputFile(MTP_long(i->id()), MTP_int(i->partsCount), MTP_string(i->filename()), MTP_bytes(i->file ? i->file->filemd5 : i->media.jpeg_md5)));
|
||||
} else if (i->type() == PrepareDocument || i->type() == PrepareAudio) {
|
||||
QByteArray docMd5(32, Qt::Uninitialized);
|
||||
hashMd5Hex(i->md5Hash.result(), docMd5.data());
|
||||
|
||||
MTPInputFile doc = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename())) : MTP_inputFile(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename()), MTP_string(docMd5));
|
||||
MTPInputFile doc = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename())) : MTP_inputFile(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename()), MTP_bytes(docMd5));
|
||||
if (i->partsCount) {
|
||||
emit thumbDocumentReady(uploading, doc, MTP_inputFile(MTP_long(i->thumbId()), MTP_int(i->partsCount), MTP_string(i->file ? i->file->thumbname : (qsl("thumb.") + i->media.thumbExt)), MTP_string(i->file ? i->file->thumbmd5 : i->media.jpeg_md5)));
|
||||
emit thumbDocumentReady(uploading, silent, doc, MTP_inputFile(MTP_long(i->thumbId()), MTP_int(i->partsCount), MTP_string(i->file ? i->file->thumbname : (qsl("thumb.") + i->media.thumbExt)), MTP_bytes(i->file ? i->file->thumbmd5 : i->media.jpeg_md5)));
|
||||
} else {
|
||||
emit documentReady(uploading, doc);
|
||||
emit documentReady(uploading, silent, doc);
|
||||
}
|
||||
} else if (i->type() == PrepareAudio) {
|
||||
QByteArray audioMd5(32, Qt::Uninitialized);
|
||||
hashMd5Hex(i->md5Hash.result(), audioMd5.data());
|
||||
|
||||
MTPInputFile audio = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename())) : MTP_inputFile(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename()), MTP_string(audioMd5));
|
||||
emit audioReady(uploading, audio);
|
||||
}
|
||||
queue.remove(uploading);
|
||||
uploading = FullMsgId();
|
||||
|
@ -200,9 +187,9 @@ void FileUploader::sendNext() {
|
|||
}
|
||||
mtpRequestId requestId;
|
||||
if (i->docSize > UseBigFilesFrom) {
|
||||
requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_bytes(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::uplDcId(todc));
|
||||
} else {
|
||||
requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_bytes(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::uplDcId(todc));
|
||||
}
|
||||
docRequestsSent.insert(requestId, i->docSentParts);
|
||||
dcMap.insert(requestId, todc);
|
||||
|
@ -213,7 +200,7 @@ void FileUploader::sendNext() {
|
|||
} else {
|
||||
UploadFileParts::iterator part = parts.begin();
|
||||
|
||||
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(partsOfId), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(partsOfId), MTP_int(part.key()), MTP_bytes(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::uplDcId(todc));
|
||||
requestsSent.insert(requestId, part.value());
|
||||
dcMap.insert(requestId, todc);
|
||||
sentSize += part.value().size();
|
||||
|
@ -259,7 +246,7 @@ void FileUploader::clear() {
|
|||
dcMap.clear();
|
||||
sentSize = 0;
|
||||
for (int32 i = 0; i < MTPUploadSessionsCount; ++i) {
|
||||
MTP::stopSession(MTP::upl[i]);
|
||||
MTP::stopSession(MTP::uplDcId(i));
|
||||
sentSizes[i] = 0;
|
||||
}
|
||||
killSessionsTimer.stop();
|
||||
|
@ -303,7 +290,7 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
|||
photo->uploadingData->offset = k->fileSentSize;
|
||||
}
|
||||
emit photoProgress(k.key());
|
||||
} else if (k->type() == PrepareDocument) {
|
||||
} else if (k->type() == PrepareDocument || k->type() == PrepareAudio) {
|
||||
DocumentData *doc = App::document(k->id());
|
||||
if (doc->uploading()) {
|
||||
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
|
@ -312,15 +299,6 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
|||
}
|
||||
}
|
||||
emit documentProgress(k.key());
|
||||
} else if (k->type() == PrepareAudio) {
|
||||
AudioData *audio = App::audio(k->id());
|
||||
if (audio->uploading()) {
|
||||
audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
if (audio->uploadOffset > audio->size) {
|
||||
audio->uploadOffset = audio->size;
|
||||
}
|
||||
}
|
||||
emit audioProgress(k.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -48,18 +48,15 @@ public slots:
|
|||
|
||||
signals:
|
||||
|
||||
void photoReady(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void documentReady(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void thumbDocumentReady(const FullMsgId &msgId, const MTPInputFile &file, const MTPInputFile &thumb);
|
||||
void audioReady(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
void photoReady(const FullMsgId &msgId, bool silent, const MTPInputFile &file);
|
||||
void documentReady(const FullMsgId &msgId, bool silent, const MTPInputFile &file);
|
||||
void thumbDocumentReady(const FullMsgId &msgId, bool silent, const MTPInputFile &file, const MTPInputFile &thumb);
|
||||
|
||||
void photoProgress(const FullMsgId &msgId);
|
||||
void documentProgress(const FullMsgId &msgId);
|
||||
void audioProgress(const FullMsgId &msgId);
|
||||
|
||||
void photoFailed(const FullMsgId &msgId);
|
||||
void documentFailed(const FullMsgId &msgId);
|
||||
void audioFailed(const FullMsgId &msgId);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -16,12 +16,19 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "animation.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
|
||||
|
@ -93,6 +100,7 @@ namespace anim {
|
|||
if (!_clipThreads.isEmpty()) {
|
||||
for (int32 i = 0, l = _clipThreads.size(); i < l; ++i) {
|
||||
_clipThreads.at(i)->quit();
|
||||
DEBUG_LOG(("Waiting for clipThread to finish: %1").arg(i));
|
||||
_clipThreads.at(i)->wait();
|
||||
delete _clipManagers.at(i);
|
||||
delete _clipThreads.at(i);
|
||||
|
@ -142,7 +150,7 @@ void AnimationManager::stop(Animation *obj) {
|
|||
if (_iterating) {
|
||||
_stopping.insert(obj, NullType());
|
||||
if (!_starting.isEmpty()) {
|
||||
_starting.insert(obj, NullType());
|
||||
_starting.remove(obj);
|
||||
}
|
||||
} else {
|
||||
AnimatingObjects::iterator i = _objects.find(obj);
|
||||
|
@ -159,7 +167,9 @@ void AnimationManager::timeout() {
|
|||
_iterating = true;
|
||||
uint64 ms = getms();
|
||||
for (AnimatingObjects::const_iterator i = _objects.begin(), e = _objects.end(); i != e; ++i) {
|
||||
i.key()->step(ms, true);
|
||||
if (!_stopping.contains(i.key())) {
|
||||
i.key()->step(ms, true);
|
||||
}
|
||||
}
|
||||
_iterating = false;
|
||||
|
||||
|
@ -189,18 +199,25 @@ QPixmap _prepareFrame(const ClipFrameRequest &request, const QImage &original, b
|
|||
bool needOuter = (request.outerw != request.framew) || (request.outerh != request.frameh);
|
||||
if (badSize || needOuter || hasAlpha || request.rounded) {
|
||||
int32 factor(request.factor);
|
||||
bool fill = false;
|
||||
if (cache.width() != request.outerw || cache.height() != request.outerh) {
|
||||
bool newcache = (cache.width() != request.outerw || cache.height() != request.outerh);
|
||||
if (newcache) {
|
||||
cache = QImage(request.outerw, request.outerh, QImage::Format_ARGB32_Premultiplied);
|
||||
if (request.framew < request.outerw || request.frameh < request.outerh || hasAlpha) {
|
||||
fill = true;
|
||||
}
|
||||
cache.setDevicePixelRatio(factor);
|
||||
}
|
||||
{
|
||||
Painter p(&cache);
|
||||
if (fill) {
|
||||
p.fillRect(0, 0, cache.width() / factor, cache.height() / factor, st::black);
|
||||
if (newcache) {
|
||||
if (request.framew < request.outerw) {
|
||||
p.fillRect(0, 0, (request.outerw - request.framew) / (2 * factor), cache.height() / factor, st::black);
|
||||
p.fillRect((request.outerw - request.framew) / (2 * factor) + (request.framew / factor), 0, (cache.width() / factor) - ((request.outerw - request.framew) / (2 * factor) + (request.framew / factor)), cache.height() / factor, st::black);
|
||||
}
|
||||
if (request.frameh < request.outerh) {
|
||||
p.fillRect(qMax(0, (request.outerw - request.framew) / (2 * factor)), 0, qMin(cache.width(), request.framew) / factor, (request.outerh - request.frameh) / (2 * factor), st::black);
|
||||
p.fillRect(qMax(0, (request.outerw - request.framew) / (2 * factor)), (request.outerh - request.frameh) / (2 * factor) + (request.frameh / factor), qMin(cache.width(), request.framew) / factor, (cache.height() / factor) - ((request.outerh - request.frameh) / (2 * factor) + (request.frameh / factor)), st::black);
|
||||
}
|
||||
}
|
||||
if (hasAlpha) {
|
||||
p.fillRect(qMax(0, (request.outerw - request.framew) / (2 * factor)), qMax(0, (request.outerh - request.frameh) / (2 * factor)), qMin(cache.width(), request.framew) / factor, qMin(cache.height(), request.frameh) / factor, st::white);
|
||||
}
|
||||
QPoint position((request.outerw - request.framew) / (2 * factor), (request.outerh - request.frameh) / (2 * factor));
|
||||
if (badSize) {
|
||||
|
@ -235,7 +252,7 @@ ClipReader::ClipReader(const FileLocation &location, const QByteArray &data, Cal
|
|||
_clipManagers.push_back(new ClipReadManager(_clipThreads.back()));
|
||||
_clipThreads.back()->start();
|
||||
} else {
|
||||
_threadIndex = int32(MTP::nonce<uint32>() % _clipThreads.size());
|
||||
_threadIndex = int32(rand_value<uint32>() % _clipThreads.size());
|
||||
int32 loadLevel = 0x7FFFFFFF;
|
||||
for (int32 i = 0, l = _clipThreads.size(); i < l; ++i) {
|
||||
int32 level = _clipManagers.at(i)->loadLevel();
|
||||
|
@ -369,6 +386,7 @@ QPixmap ClipReader::current(int32 framew, int32 frameh, int32 outerw, int32 oute
|
|||
frame->request.outerh = outerh * factor;
|
||||
|
||||
QImage cacheForResize;
|
||||
frame->original.setDevicePixelRatio(factor);
|
||||
frame->pix = QPixmap();
|
||||
frame->pix = _prepareFrame(frame->request, frame->original, true, cacheForResize);
|
||||
|
||||
|
@ -418,7 +436,6 @@ void ClipReader::stop() {
|
|||
}
|
||||
|
||||
void ClipReader::error() {
|
||||
_private = 0;
|
||||
_state = ClipError;
|
||||
}
|
||||
|
||||
|
@ -477,7 +494,7 @@ public:
|
|||
, _frameDelay(0) {
|
||||
}
|
||||
|
||||
bool readNextFrame(QImage &to, bool &hasAlpha, const QSize &size) {
|
||||
bool readNextFrame() {
|
||||
if (_reader) _frameDelay = _reader->nextImageDelay();
|
||||
if (_framesLeft < 1 && !jumpToStart()) {
|
||||
return false;
|
||||
|
@ -587,6 +604,11 @@ public:
|
|||
}
|
||||
|
||||
bool readNextFrame() {
|
||||
if (_frameRead) {
|
||||
av_frame_unref(_frame);
|
||||
_frameRead = false;
|
||||
}
|
||||
|
||||
int res;
|
||||
while (true) {
|
||||
if (_avpkt.size > 0) { // previous packet not finished
|
||||
|
@ -638,6 +660,20 @@ public:
|
|||
}
|
||||
|
||||
if (got_frame) {
|
||||
int64 duration = av_frame_get_pkt_duration(_frame);
|
||||
int64 framePts = (_frame->pkt_pts == AV_NOPTS_VALUE) ? _frame->pkt_dts : _frame->pkt_pts;
|
||||
int64 frameMs = (framePts * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
_currentFrameDelay = _nextFrameDelay;
|
||||
if (_frameMs + _currentFrameDelay < frameMs) {
|
||||
_currentFrameDelay = int32(frameMs - _frameMs);
|
||||
}
|
||||
if (duration == AV_NOPTS_VALUE) {
|
||||
_nextFrameDelay = 0;
|
||||
} else {
|
||||
_nextFrameDelay = (duration * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
}
|
||||
_frameMs = frameMs;
|
||||
|
||||
_hadFrame = _frameRead = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -700,20 +736,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
int64 duration = av_frame_get_pkt_duration(_frame);
|
||||
int64 framePts = (_frame->pkt_pts == AV_NOPTS_VALUE) ? _frame->pkt_dts : _frame->pkt_pts;
|
||||
int64 frameMs = (framePts * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
_currentFrameDelay = _nextFrameDelay;
|
||||
if (_frameMs + _currentFrameDelay < frameMs) {
|
||||
_currentFrameDelay = int32(frameMs - _frameMs);
|
||||
}
|
||||
if (duration == AV_NOPTS_VALUE) {
|
||||
_nextFrameDelay = 0;
|
||||
} else {
|
||||
_nextFrameDelay = (duration * 1000LL * _fmtContext->streams[_streamId]->time_base.num) / _fmtContext->streams[_streamId]->time_base.den;
|
||||
}
|
||||
_frameMs = frameMs;
|
||||
|
||||
av_frame_unref(_frame);
|
||||
return true;
|
||||
}
|
||||
|
@ -792,6 +814,10 @@ public:
|
|||
}
|
||||
|
||||
~FFMpegReaderImplementation() {
|
||||
if (_frameRead) {
|
||||
av_frame_unref(_frame);
|
||||
_frameRead = false;
|
||||
}
|
||||
if (_ioContext) av_free(_ioContext);
|
||||
if (_codecContext) avcodec_close(_codecContext);
|
||||
if (_swsContext) sws_freeContext(_swsContext);
|
||||
|
|
|
@ -16,11 +16,11 @@ In addition, as a special exception, the copyright holders give permission
|
|||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "basic_types.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QColor>
|
||||
|
||||
|
@ -208,10 +208,10 @@ class AnimationCreator {
|
|||
public:
|
||||
AnimationCreator(AnimationImplementation *ptr) : _ptr(ptr) {}
|
||||
AnimationCreator(const AnimationCreator &other) : _ptr(other.create()) {}
|
||||
AnimationImplementation *create() const { return exchange(_ptr); }
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue