mirror of https://github.com/procxx/kepka.git
Merge 9e1a45295f
into 63669c1612
This commit is contained in:
commit
5374f4799a
|
@ -55,3 +55,7 @@ xcuserdata
|
|||
/Linux/
|
||||
/Telegram/Makefile
|
||||
*.*~
|
||||
|
||||
_build_
|
||||
_conan_build_
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
[submodule "Telegram/ThirdParty/libtgvoip"]
|
||||
path = Telegram/ThirdParty/libtgvoip
|
||||
url = https://github.com/telegramdesktop/libtgvoip
|
||||
[submodule "Telegram/ThirdParty/variant"]
|
||||
path = Telegram/ThirdParty/variant
|
||||
url = https://github.com/mapbox/variant
|
||||
[submodule "Telegram/ThirdParty/GSL"]
|
||||
path = Telegram/ThirdParty/GSL
|
||||
url = https://github.com/Microsoft/GSL.git
|
||||
[submodule "Telegram/ThirdParty/Catch"]
|
||||
path = Telegram/ThirdParty/Catch
|
||||
url = https://github.com/philsquared/Catch
|
|
@ -0,0 +1,42 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(telegram-desktop)
|
||||
|
||||
if(EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
else()
|
||||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cotire/CMake;${PROJECT_SOURCE_DIR}/modules/")
|
||||
include(cotire)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
# Ignore automoc-ing generated files (@tbd?)
|
||||
cmake_policy(SET CMP0071 OLD)
|
||||
|
||||
# Needs OpenAL-SOFT
|
||||
# Install via `brew install openal-soft` and configure with `env OPENALDIR=/usr/local/opt/openal-soft`
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(FFmpeg REQUIRED)
|
||||
find_package(Zlib REQUIRED)
|
||||
#@todo Turn into find_package(Opus REQUIRED)
|
||||
find_library(OPUS_LIB opus)
|
||||
find_path(OPUS_INCLUDE_DIR opus/opus.h)
|
||||
|
||||
if (NOT SWSCALE_FOUND)
|
||||
message(FATAL_ERROR "FFmpeg swscale is required")
|
||||
endif()
|
||||
if (NOT SWRESAMPLE_FOUND)
|
||||
message(FATAL_ERROR "FFmpeg swresample is required")
|
||||
endif()
|
||||
if (NOT OPUS_LIB)
|
||||
message(FATAL_ERROR "opus codec is required")
|
||||
endif()
|
||||
|
||||
add_subdirectory(Telegram)
|
17
README.md
17
README.md
|
@ -1,6 +1,14 @@
|
|||
# [Telegram Desktop][telegram_desktop] – Official Messenger
|
||||
# [Telegram Desktop][telegram_desktop] - pro.cxx fork
|
||||
|
||||
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.
|
||||
This is the complete source code and the build instructions for the alpha version of the pro.cxx fork of desktop client for the [Telegram][telegram] messenger, based on the [Telegram API][telegram_api] and the [MTProto][telegram_proto] secure protocol.
|
||||
|
||||
## Build instructions
|
||||
|
||||
mkdir _build_
|
||||
cd _build_
|
||||
conan install .. --build missing
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5/ ..
|
||||
ninja
|
||||
|
||||
[](https://github.com/telegramdesktop/tdesktop/releases)
|
||||
[](https://travis-ci.org/telegramdesktop/tdesktop)
|
||||
|
@ -28,7 +36,6 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
|||
* 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))
|
||||
* GYP ([BSD License](https://github.com/bnoordhuis/gyp/blob/master/LICENSE))
|
||||
* Ninja ([Apache License 2.0](https://github.com/ninja-build/ninja/blob/master/COPYING))
|
||||
* OpenAL Soft ([LGPL](http://kcat.strangesoft.net/openal.html))
|
||||
* Opus codec ([BSD License](http://www.opus-codec.org/license/))
|
||||
|
@ -39,10 +46,6 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
|
|||
* Emoji alpha codes ([MIT License](https://github.com/emojione/emojione/blob/master/extras/alpha-codes/LICENSE.md))
|
||||
* Catch test framework ([Boost License](https://github.com/philsquared/Catch/blob/master/LICENSE.txt))
|
||||
|
||||
## Build instructions
|
||||
|
||||
* [Visual Studio 2017][msvc]
|
||||
* [Xcode 8][xcode]
|
||||
* [GYP/CMake on GNU/Linux][cmake]
|
||||
|
||||
[//]: # (LINKS)
|
||||
|
|
|
@ -0,0 +1,671 @@
|
|||
find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED)
|
||||
|
||||
|
||||
# defines
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_definitions(-DQ_OS_LINUX64)
|
||||
else()
|
||||
add_definitions(-DQ_OS_LINUX32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_program(CCACHE ccache)
|
||||
if (CCACHE)
|
||||
message(STATUS "Enabling ccache")
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
|
||||
endif()
|
||||
|
||||
##======================
|
||||
## Codegen Tools
|
||||
##======================
|
||||
|
||||
include_directories(SourceFiles)
|
||||
add_subdirectory(SourceFiles/codegen)
|
||||
|
||||
#-w<(PRODUCT_DIR)/../.. -- wtf is that
|
||||
add_custom_command(
|
||||
COMMENT "Generating palette"
|
||||
OUTPUT
|
||||
styles/palette.h
|
||||
styles/palette.cpp
|
||||
COMMAND
|
||||
codegen_style -I${CMAKE_CURRENT_SOURCE_DIR}/Resources -I${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-o${CMAKE_CURRENT_BINARY_DIR}/styles -w${CMAKE_SOURCE_DIR}
|
||||
colors.palette
|
||||
WORKING_DIRECTORY styles
|
||||
DEPENDS
|
||||
codegen_style
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Resources/colors.palette
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/Resources/colors.palette
|
||||
)
|
||||
add_custom_target(palette_output
|
||||
DEPENDS styles/palette.h styles/palette.cpp)
|
||||
|
||||
add_custom_command(
|
||||
COMMENT "Generating numbers"
|
||||
OUTPUT
|
||||
numbers.h
|
||||
numbers.cpp
|
||||
COMMAND
|
||||
codegen_numbers -o${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Resources/numbers.txt
|
||||
WORKING_DIRECTORY .
|
||||
DEPENDS
|
||||
codegen_numbers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Resources/numbers.txt
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/Resources/numbers.txt
|
||||
)
|
||||
add_custom_target(numbers_output
|
||||
DEPENDS numbers.h numbers.cpp)
|
||||
|
||||
add_custom_command(
|
||||
COMMENT "Generating langs"
|
||||
OUTPUT
|
||||
lang_auto.h
|
||||
lang_auto.cpp
|
||||
COMMAND
|
||||
codegen_lang -o${CMAKE_CURRENT_BINARY_DIR} -w${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Resources/langs/lang.strings
|
||||
WORKING_DIRECTORY .
|
||||
DEPENDS
|
||||
codegen_lang
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Resources/langs/lang.strings
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/Resources/langs/lang.strings
|
||||
)
|
||||
add_custom_target(lang_output
|
||||
DEPENDS lang_auto.h lang_auto.cpp)
|
||||
|
||||
add_custom_command(
|
||||
COMMENT "Generating emoji"
|
||||
OUTPUT
|
||||
emoji.cpp
|
||||
emoji.h
|
||||
emoji_suggestions_data.cpp
|
||||
emoji_suggestions_data.h
|
||||
COMMAND
|
||||
codegen_emoji ${CMAKE_CURRENT_SOURCE_DIR}/Resources/emoji_autocomplete.json -o ${CMAKE_CURRENT_BINARY_DIR}
|
||||
WORKING_DIRECTORY .
|
||||
DEPENDS
|
||||
codegen_emoji
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Resources/emoji_autocomplete.json
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(emoji_output
|
||||
DEPENDS
|
||||
emoji.h
|
||||
emoji.cpp
|
||||
emoji_suggestions_data.cpp
|
||||
emoji_suggestions_data.h
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
COMMENT "Generating scheme"
|
||||
OUTPUT
|
||||
scheme.cpp
|
||||
scheme.h
|
||||
COMMAND
|
||||
python ${CMAKE_CURRENT_SOURCE_DIR}/SourceFiles/codegen/scheme/codegen_scheme.py -o${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Resources/scheme.tl
|
||||
WORKING_DIRECTORY .
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/SourceFiles/codegen/scheme/codegen_scheme.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Resources/scheme.tl
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/Resources/scheme.tl
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(scheme_output
|
||||
DEPENDS scheme.h scheme.cpp)
|
||||
|
||||
##========
|
||||
|
||||
list(APPEND style_files
|
||||
Resources/basic
|
||||
SourceFiles/boxes/boxes
|
||||
SourceFiles/calls/calls
|
||||
SourceFiles/chat_helpers/chat_helpers
|
||||
SourceFiles/dialogs/dialogs
|
||||
SourceFiles/history/history
|
||||
SourceFiles/intro/intro
|
||||
SourceFiles/media/player/media_player
|
||||
SourceFiles/media/view/mediaview
|
||||
SourceFiles/overview/overview
|
||||
SourceFiles/profile/profile
|
||||
SourceFiles/settings/settings
|
||||
SourceFiles/ui/widgets/widgets
|
||||
SourceFiles/window/window
|
||||
)
|
||||
|
||||
foreach (src ${style_files})
|
||||
# '-w<(PRODUCT_DIR)/../..',
|
||||
get_filename_component(src_file ${src} NAME)
|
||||
add_custom_command(
|
||||
COMMENT "Generating ${src_file}"
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/styles/style_${src_file}.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/styles/style_${src_file}.cpp
|
||||
COMMAND
|
||||
codegen_style -I${CMAKE_CURRENT_SOURCE_DIR}/Resources -I${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/SourceFiles
|
||||
-o${CMAKE_CURRENT_BINARY_DIR}/styles -w${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${src}.style
|
||||
DEPENDS
|
||||
codegen_style
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${src}.style
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${src}.style
|
||||
)
|
||||
add_custom_target(${src_file}_styles_output
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/styles/style_${src_file}.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/styles/style_${src_file}.cpp
|
||||
)
|
||||
|
||||
list(APPEND style_sources
|
||||
${CMAKE_CURRENT_BINARY_DIR}/styles/style_${src_file}.cpp)
|
||||
|
||||
endforeach()
|
||||
|
||||
##======================
|
||||
## Main app
|
||||
##======================
|
||||
|
||||
#add_subdirectory(SourceFiles/boxes) - see comment in that dir
|
||||
|
||||
set(APP_SRC
|
||||
${CMAKE_CURRENT_BINARY_DIR}/styles/palette.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/numbers.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/lang_auto.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/scheme.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/emoji.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/emoji_suggestions_data.cpp
|
||||
${style_sources}
|
||||
|
||||
SourceFiles/base/observer.cpp
|
||||
SourceFiles/base/parse_helper.cpp
|
||||
SourceFiles/base/qthelp_url.cpp
|
||||
SourceFiles/base/runtime_composer.cpp
|
||||
SourceFiles/base/task_queue.cpp
|
||||
SourceFiles/base/timer.cpp
|
||||
|
||||
SourceFiles/boxes/about_box.cpp
|
||||
SourceFiles/boxes/abstract_box.cpp
|
||||
SourceFiles/boxes/add_contact_box.cpp
|
||||
SourceFiles/boxes/autolock_box.cpp
|
||||
SourceFiles/boxes/background_box.cpp
|
||||
SourceFiles/boxes/calendar_box.cpp
|
||||
SourceFiles/boxes/change_phone_box.cpp
|
||||
SourceFiles/boxes/confirm_box.cpp
|
||||
SourceFiles/boxes/confirm_phone_box.cpp
|
||||
SourceFiles/boxes/connection_box.cpp
|
||||
SourceFiles/boxes/download_path_box.cpp
|
||||
SourceFiles/boxes/edit_color_box.cpp
|
||||
SourceFiles/boxes/edit_participant_box.cpp
|
||||
SourceFiles/boxes/edit_privacy_box.cpp
|
||||
SourceFiles/boxes/language_box.cpp
|
||||
SourceFiles/boxes/local_storage_box.cpp
|
||||
SourceFiles/boxes/mute_settings_box.cpp
|
||||
SourceFiles/boxes/notifications_box.cpp
|
||||
SourceFiles/boxes/passcode_box.cpp
|
||||
SourceFiles/boxes/peer_list_box.cpp
|
||||
SourceFiles/boxes/peer_list_controllers.cpp
|
||||
SourceFiles/boxes/photo_crop_box.cpp
|
||||
SourceFiles/boxes/rate_call_box.cpp
|
||||
SourceFiles/boxes/report_box.cpp
|
||||
SourceFiles/boxes/self_destruction_box.cpp
|
||||
SourceFiles/boxes/send_files_box.cpp
|
||||
SourceFiles/boxes/sessions_box.cpp
|
||||
SourceFiles/boxes/share_box.cpp
|
||||
SourceFiles/boxes/sticker_set_box.cpp
|
||||
SourceFiles/boxes/stickers_box.cpp
|
||||
SourceFiles/boxes/username_box.cpp
|
||||
|
||||
SourceFiles/calls/calls_box_controller.cpp
|
||||
SourceFiles/calls/calls_call.cpp
|
||||
SourceFiles/calls/calls_emoji_fingerprint.cpp
|
||||
SourceFiles/calls/calls_instance.cpp
|
||||
SourceFiles/calls/calls_panel.cpp
|
||||
SourceFiles/calls/calls_top_bar.cpp
|
||||
|
||||
SourceFiles/chat_helpers/bot_keyboard.cpp
|
||||
SourceFiles/chat_helpers/emoji_list_widget.cpp
|
||||
SourceFiles/chat_helpers/emoji_suggestions_widget.cpp
|
||||
SourceFiles/chat_helpers/field_autocomplete.cpp
|
||||
SourceFiles/chat_helpers/gifs_list_widget.cpp
|
||||
SourceFiles/chat_helpers/message_field.cpp
|
||||
SourceFiles/chat_helpers/stickers.cpp
|
||||
SourceFiles/chat_helpers/stickers_list_widget.cpp
|
||||
SourceFiles/chat_helpers/tabbed_panel.cpp
|
||||
SourceFiles/chat_helpers/tabbed_section.cpp
|
||||
SourceFiles/chat_helpers/tabbed_selector.cpp
|
||||
|
||||
SourceFiles/core/click_handler.cpp
|
||||
SourceFiles/core/click_handler_types.cpp
|
||||
SourceFiles/core/file_utilities.cpp
|
||||
SourceFiles/core/single_timer.cpp
|
||||
SourceFiles/core/utils.cpp
|
||||
|
||||
SourceFiles/data/data_abstract_structure.cpp
|
||||
SourceFiles/data/data_drafts.cpp
|
||||
|
||||
SourceFiles/dialogs/dialogs_indexed_list.cpp
|
||||
SourceFiles/dialogs/dialogs_inner_widget.cpp
|
||||
SourceFiles/dialogs/dialogs_layout.cpp
|
||||
SourceFiles/dialogs/dialogs_list.cpp
|
||||
SourceFiles/dialogs/dialogs_row.cpp
|
||||
SourceFiles/dialogs/dialogs_search_from_controllers.cpp
|
||||
SourceFiles/dialogs/dialogs_widget.cpp
|
||||
|
||||
SourceFiles/history/history.cpp
|
||||
SourceFiles/history/history_admin_log_filter.cpp
|
||||
SourceFiles/history/history_admin_log_inner.cpp
|
||||
SourceFiles/history/history_admin_log_item.cpp
|
||||
SourceFiles/history/history_admin_log_section.cpp
|
||||
SourceFiles/history/history_drag_area.cpp
|
||||
SourceFiles/history/history_inner_widget.cpp
|
||||
SourceFiles/history/history_item.cpp
|
||||
SourceFiles/history/history_location_manager.cpp
|
||||
SourceFiles/history/history_media_types.cpp
|
||||
SourceFiles/history/history_message.cpp
|
||||
SourceFiles/history/history_service.cpp
|
||||
SourceFiles/history/history_service_layout.cpp
|
||||
SourceFiles/history/history_widget.cpp
|
||||
|
||||
SourceFiles/inline_bots/inline_bot_layout_internal.cpp
|
||||
SourceFiles/inline_bots/inline_bot_layout_item.cpp
|
||||
SourceFiles/inline_bots/inline_bot_result.cpp
|
||||
SourceFiles/inline_bots/inline_bot_send_data.cpp
|
||||
SourceFiles/inline_bots/inline_results_widget.cpp
|
||||
|
||||
SourceFiles/intro/introcode.cpp
|
||||
SourceFiles/intro/introphone.cpp
|
||||
SourceFiles/intro/intropwdcheck.cpp
|
||||
SourceFiles/intro/introsignup.cpp
|
||||
SourceFiles/intro/introstart.cpp
|
||||
SourceFiles/intro/introwidget.cpp
|
||||
|
||||
SourceFiles/lang/lang_cloud_manager.cpp
|
||||
SourceFiles/lang/lang_file_parser.cpp
|
||||
SourceFiles/lang/lang_instance.cpp
|
||||
SourceFiles/lang/lang_keys.cpp
|
||||
SourceFiles/lang/lang_tag.cpp
|
||||
SourceFiles/lang/lang_translator.cpp
|
||||
|
||||
SourceFiles/media/player/media_player_button.cpp
|
||||
SourceFiles/media/player/media_player_cover.cpp
|
||||
SourceFiles/media/player/media_player_float.cpp
|
||||
SourceFiles/media/player/media_player_instance.cpp
|
||||
SourceFiles/media/player/media_player_list.cpp
|
||||
SourceFiles/media/player/media_player_panel.cpp
|
||||
SourceFiles/media/player/media_player_volume_controller.cpp
|
||||
SourceFiles/media/player/media_player_widget.cpp
|
||||
|
||||
SourceFiles/media/view/media_clip_controller.cpp
|
||||
SourceFiles/media/view/media_clip_playback.cpp
|
||||
SourceFiles/media/view/media_clip_volume_controller.cpp
|
||||
|
||||
SourceFiles/media/media_audio.cpp
|
||||
SourceFiles/media/media_audio_capture.cpp
|
||||
SourceFiles/media/media_audio_ffmpeg_loader.cpp
|
||||
SourceFiles/media/media_audio_loader.cpp
|
||||
SourceFiles/media/media_audio_loaders.cpp
|
||||
SourceFiles/media/media_audio_track.cpp
|
||||
SourceFiles/media/media_child_ffmpeg_loader.cpp
|
||||
SourceFiles/media/media_clip_ffmpeg.cpp
|
||||
SourceFiles/media/media_clip_implementation.cpp
|
||||
SourceFiles/media/media_clip_qtgif.cpp
|
||||
SourceFiles/media/media_clip_reader.cpp
|
||||
|
||||
SourceFiles/mtproto/auth_key.cpp
|
||||
SourceFiles/mtproto/config_loader.cpp
|
||||
SourceFiles/mtproto/connection.cpp
|
||||
SourceFiles/mtproto/connection_abstract.cpp
|
||||
SourceFiles/mtproto/connection_auto.cpp
|
||||
SourceFiles/mtproto/connection_http.cpp
|
||||
SourceFiles/mtproto/connection_tcp.cpp
|
||||
SourceFiles/mtproto/core_types.cpp
|
||||
SourceFiles/mtproto/dc_options.cpp
|
||||
SourceFiles/mtproto/dcenter.cpp
|
||||
SourceFiles/mtproto/facade.cpp
|
||||
SourceFiles/mtproto/mtp_instance.cpp
|
||||
SourceFiles/mtproto/rpc_sender.cpp
|
||||
SourceFiles/mtproto/rsa_public_key.cpp
|
||||
SourceFiles/mtproto/session.cpp
|
||||
SourceFiles/mtproto/special_config_request.cpp
|
||||
SourceFiles/mtproto/type_utils.cpp
|
||||
|
||||
SourceFiles/overview/overview_layout.cpp
|
||||
|
||||
SourceFiles/profile/profile_back_button.cpp
|
||||
SourceFiles/profile/profile_block_actions.cpp
|
||||
SourceFiles/profile/profile_block_channel_members.cpp
|
||||
SourceFiles/profile/profile_block_group_members.cpp
|
||||
SourceFiles/profile/profile_block_info.cpp
|
||||
SourceFiles/profile/profile_block_invite_link.cpp
|
||||
SourceFiles/profile/profile_block_peer_list.cpp
|
||||
SourceFiles/profile/profile_block_settings.cpp
|
||||
SourceFiles/profile/profile_block_shared_media.cpp
|
||||
SourceFiles/profile/profile_block_widget.cpp
|
||||
SourceFiles/profile/profile_channel_controllers.cpp
|
||||
SourceFiles/profile/profile_common_groups_section.cpp
|
||||
SourceFiles/profile/profile_cover.cpp
|
||||
SourceFiles/profile/profile_cover_drop_area.cpp
|
||||
SourceFiles/profile/profile_fixed_bar.cpp
|
||||
SourceFiles/profile/profile_inner_widget.cpp
|
||||
SourceFiles/profile/profile_section_memento.cpp
|
||||
SourceFiles/profile/profile_userpic_button.cpp
|
||||
SourceFiles/profile/profile_widget.cpp
|
||||
|
||||
SourceFiles/settings/settings_advanced_widget.cpp
|
||||
SourceFiles/settings/settings_background_widget.cpp
|
||||
SourceFiles/settings/settings_block_widget.cpp
|
||||
SourceFiles/settings/settings_chat_settings_widget.cpp
|
||||
SourceFiles/settings/settings_cover.cpp
|
||||
SourceFiles/settings/settings_fixed_bar.cpp
|
||||
SourceFiles/settings/settings_general_widget.cpp
|
||||
SourceFiles/settings/settings_info_widget.cpp
|
||||
SourceFiles/settings/settings_inner_widget.cpp
|
||||
SourceFiles/settings/settings_layer.cpp
|
||||
SourceFiles/settings/settings_notifications_widget.cpp
|
||||
SourceFiles/settings/settings_privacy_controllers.cpp
|
||||
SourceFiles/settings/settings_privacy_widget.cpp
|
||||
SourceFiles/settings/settings_scale_widget.cpp
|
||||
SourceFiles/settings/settings_widget.cpp
|
||||
|
||||
SourceFiles/storage/file_download.cpp
|
||||
SourceFiles/storage/file_upload.cpp
|
||||
SourceFiles/storage/localimageloader.cpp
|
||||
SourceFiles/storage/localstorage.cpp
|
||||
SourceFiles/storage/serialize_common.cpp
|
||||
SourceFiles/storage/serialize_document.cpp
|
||||
|
||||
SourceFiles/ui/effects/cross_animation.cpp
|
||||
SourceFiles/ui/effects/panel_animation.cpp
|
||||
SourceFiles/ui/effects/radial_animation.cpp
|
||||
SourceFiles/ui/effects/ripple_animation.cpp
|
||||
SourceFiles/ui/effects/round_checkbox.cpp
|
||||
SourceFiles/ui/effects/send_action_animations.cpp
|
||||
SourceFiles/ui/effects/slide_animation.cpp
|
||||
SourceFiles/ui/effects/widget_fade_wrap.cpp
|
||||
SourceFiles/ui/effects/widget_slide_wrap.cpp
|
||||
|
||||
SourceFiles/ui/style/style_core.cpp
|
||||
SourceFiles/ui/style/style_core_color.cpp
|
||||
SourceFiles/ui/style/style_core_font.cpp
|
||||
SourceFiles/ui/style/style_core_icon.cpp
|
||||
SourceFiles/ui/style/style_core_types.cpp
|
||||
|
||||
SourceFiles/ui/text/text.cpp
|
||||
SourceFiles/ui/text/text_block.cpp
|
||||
SourceFiles/ui/text/text_entity.cpp
|
||||
|
||||
SourceFiles/ui/toast/toast.cpp
|
||||
SourceFiles/ui/toast/toast_manager.cpp
|
||||
SourceFiles/ui/toast/toast_widget.cpp
|
||||
|
||||
SourceFiles/ui/widgets/buttons.cpp
|
||||
SourceFiles/ui/widgets/checkbox.cpp
|
||||
SourceFiles/ui/widgets/continuous_sliders.cpp
|
||||
SourceFiles/ui/widgets/discrete_sliders.cpp
|
||||
SourceFiles/ui/widgets/dropdown_menu.cpp
|
||||
SourceFiles/ui/widgets/inner_dropdown.cpp
|
||||
SourceFiles/ui/widgets/input_fields.cpp
|
||||
SourceFiles/ui/widgets/labels.cpp
|
||||
SourceFiles/ui/widgets/menu.cpp
|
||||
SourceFiles/ui/widgets/multi_select.cpp
|
||||
SourceFiles/ui/widgets/popup_menu.cpp
|
||||
SourceFiles/ui/widgets/scroll_area.cpp
|
||||
SourceFiles/ui/widgets/shadow.cpp
|
||||
SourceFiles/ui/widgets/tooltip.cpp
|
||||
|
||||
SourceFiles/ui/abstract_button.cpp
|
||||
SourceFiles/ui/animation.cpp
|
||||
SourceFiles/ui/countryinput.cpp
|
||||
SourceFiles/ui/emoji_config.cpp
|
||||
SourceFiles/ui/images.cpp
|
||||
SourceFiles/ui/special_buttons.cpp
|
||||
SourceFiles/ui/twidget.cpp
|
||||
|
||||
SourceFiles/window/themes/window_theme.cpp
|
||||
SourceFiles/window/themes/window_theme_editor.cpp
|
||||
SourceFiles/window/themes/window_theme_editor_block.cpp
|
||||
SourceFiles/window/themes/window_theme_preview.cpp
|
||||
SourceFiles/window/themes/window_theme_warning.cpp
|
||||
|
||||
SourceFiles/window/main_window.cpp
|
||||
SourceFiles/window/notifications_manager.cpp
|
||||
SourceFiles/window/notifications_manager_default.cpp
|
||||
SourceFiles/window/notifications_utilities.cpp
|
||||
SourceFiles/window/player_wrap_widget.cpp
|
||||
SourceFiles/window/section_widget.cpp
|
||||
SourceFiles/window/top_bar_widget.cpp
|
||||
SourceFiles/window/window_controller.cpp
|
||||
SourceFiles/window/window_main_menu.cpp
|
||||
SourceFiles/window/window_slide_animation.cpp
|
||||
|
||||
SourceFiles/apiwrap.cpp
|
||||
SourceFiles/app.cpp
|
||||
SourceFiles/application.cpp
|
||||
SourceFiles/auth_session.cpp
|
||||
SourceFiles/facades.cpp
|
||||
SourceFiles/layerwidget.cpp
|
||||
SourceFiles/layout.cpp
|
||||
SourceFiles/logs.cpp
|
||||
SourceFiles/main.cpp
|
||||
SourceFiles/mainwidget.cpp
|
||||
SourceFiles/mainwindow.cpp
|
||||
SourceFiles/mediaview.cpp
|
||||
SourceFiles/messenger.cpp
|
||||
SourceFiles/observer_peer.cpp
|
||||
SourceFiles/overviewwidget.cpp
|
||||
SourceFiles/passcodewidget.cpp
|
||||
SourceFiles/qt_functions.cpp
|
||||
SourceFiles/settings.cpp
|
||||
SourceFiles/shortcuts.cpp
|
||||
SourceFiles/structs.cpp
|
||||
)
|
||||
|
||||
set(PLAT_SRC)
|
||||
|
||||
if (APPLE)
|
||||
set(PLAT_SRC ${PLAT_SRC}
|
||||
SourceFiles/platform/mac/file_utilities_mac.mm
|
||||
SourceFiles/platform/mac/mac_utilities.mm
|
||||
SourceFiles/platform/mac/main_window_mac.mm
|
||||
SourceFiles/platform/mac/notifications_manager_mac.mm
|
||||
SourceFiles/platform/mac/specific_mac.mm
|
||||
SourceFiles/platform/mac/specific_mac_p.mm
|
||||
SourceFiles/platform/mac/window_title_mac.mm
|
||||
)
|
||||
set(tg_RESOURCES Resources/qrc/telegram_mac.qrc)
|
||||
endif()
|
||||
if (WIN32)
|
||||
set(PLAT_SRC ${PLAT_SRC}
|
||||
SourceFiles/platform/win/audio_win.cpp
|
||||
SourceFiles/platform/win/file_utilities_win.cpp
|
||||
SourceFiles/platform/win/main_window_win.cpp
|
||||
SourceFiles/platform/win/notifications_manager_win.cpp
|
||||
SourceFiles/platform/win/specific_win.cpp
|
||||
SourceFiles/platform/win/window_title_win.cpp
|
||||
SourceFiles/platform/win/windows_app_user_model_id.cpp
|
||||
SourceFiles/platform/win/windows_dlls.cpp
|
||||
SourceFiles/platform/win/windows_event_filter.cpp
|
||||
)
|
||||
set(tg_RESOURCES Resources/qrc/telegram_wnd.qrc)
|
||||
endif()
|
||||
if (WINRT)
|
||||
set(PLAT_SRC ${PLAT_SRC}
|
||||
SourceFiles/platform/winrt/main_window_winrt.cpp
|
||||
)
|
||||
endif()
|
||||
if (LINUX)
|
||||
set(PLAT_SRC ${PLAT_SRC}
|
||||
SourceFiles/platform/linux/file_utilities_linux.cpp
|
||||
SourceFiles/platform/linux/linux_desktop_environment.cpp
|
||||
SourceFiles/platform/linux/linux_gdk_helper.cpp
|
||||
SourceFiles/platform/linux/linux_libnotify.cpp
|
||||
SourceFiles/platform/linux/linux_libs.cpp
|
||||
SourceFiles/platform/linux/main_window_linux.cpp
|
||||
SourceFiles/platform/linux/notifications_manager_linux.cpp
|
||||
SourceFiles/platform/linux/specific_linux.cpp
|
||||
)
|
||||
set(tg_RESOURCES Resources/qrc/telegram_linux.qrc)
|
||||
endif()
|
||||
|
||||
list(APPEND tg_RESOURCES
|
||||
Resources/qrc/telegram.qrc
|
||||
Resources/qrc/telegram_sounds.qrc
|
||||
Resources/qrc/telegram_emoji.qrc
|
||||
Resources/qrc/telegram_emoji_large.qrc
|
||||
)
|
||||
|
||||
qt5_add_resources(tg_RESOURCES_RCC ${tg_RESOURCES})
|
||||
|
||||
set(THIRD_PARTY_SRC)
|
||||
|
||||
if (APPLE)
|
||||
list(APPEND THIRD_PARTY_SRC
|
||||
ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m
|
||||
ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m
|
||||
)
|
||||
include_directories(ThirdParty/SPMediaKeyTap)
|
||||
endif()
|
||||
|
||||
list(APPEND THIRD_PARTY_SRC
|
||||
ThirdParty/minizip/ioapi.c
|
||||
ThirdParty/minizip/zip.c
|
||||
ThirdParty/minizip/unzip.c
|
||||
|
||||
ThirdParty/emoji_suggestions/emoji_suggestions.cpp
|
||||
)
|
||||
|
||||
include_directories(ThirdParty) # For minizip/ but we use fully-qualified include path to avoid ambiguity
|
||||
include_directories(ThirdParty/GSL/include ThirdParty/variant/include
|
||||
ThirdParty/emoji_suggestions ThirdParty/libtgvoip)
|
||||
|
||||
##======================
|
||||
## Telegram
|
||||
##======================
|
||||
|
||||
include_directories(SourceFiles SourceFiles/core)
|
||||
|
||||
include_directories(${OPENAL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS}
|
||||
${LIBZIP_INCLUDE_DIR_ZIP} ${LIBZIP_INCLUDE_DIR_ZIPCONF}
|
||||
${OPENSSL_INCLUDE_DIR} ${LIBLZMA_INCLUDE_DIRS}
|
||||
${ICONV_INCLUDE_DIR} ${OPUS_INCLUDE_DIR}
|
||||
${FFMPEG_INCLUDE_DIRS})
|
||||
|
||||
add_subdirectory(ThirdParty/libtgvoip)
|
||||
|
||||
# Shut up for testbuilding, remove me
|
||||
include_directories(/usr/local/opt/openal-soft/include)
|
||||
# End remove me
|
||||
|
||||
if(NOT WIN32)
|
||||
add_definitions(-Wno-switch)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -DWIN32 -D_WINDOWS -DUNICODE -DWIN64 -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP)
|
||||
list(APPEND APP_SRC Resources/winrc/Telegram.rc)
|
||||
endif()
|
||||
|
||||
add_definitions(-DTDESKTOP_DISABLE_CRASH_REPORTS)
|
||||
|
||||
if (APPLE)
|
||||
set(MACOSX_BUNDLE_ICON_FILE Icon.icns)
|
||||
|
||||
add_custom_command(
|
||||
COMMENT "Generating icon file"
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${MACOSX_BUNDLE_ICON_FILE}
|
||||
COMMAND
|
||||
iconutil -c icns -o ${CMAKE_CURRENT_BINARY_DIR}/${MACOSX_BUNDLE_ICON_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/Telegram/Images.xcassets/Icon.iconset/
|
||||
WORKING_DIRECTORY .
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Telegram/Images.xcassets/Icon.iconset
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/Telegram/Images.xcassets/Icon.iconset
|
||||
)
|
||||
add_custom_target(iconset_output
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MACOSX_BUNDLE_ICON_FILE})
|
||||
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${MACOSX_BUNDLE_ICON_FILE}
|
||||
PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION Resources)
|
||||
set(APPLE_BUNDLE_SRC ${CMAKE_CURRENT_BINARY_DIR}/${MACOSX_BUNDLE_ICON_FILE})
|
||||
endif()
|
||||
|
||||
add_executable(Telegram WIN32 MACOSX_BUNDLE
|
||||
${APP_SRC}
|
||||
${PLAT_SRC}
|
||||
${THIRD_PARTY_SRC}
|
||||
${tg_RESOURCES}
|
||||
${tg_RESOURCES_RCC}
|
||||
${APPLE_BUNDLE_SRC}
|
||||
)
|
||||
|
||||
# Disable a single annoying warning about c++17
|
||||
if(NOT WIN32)
|
||||
target_compile_options(Telegram PRIVATE -Wno-c++1z-extensions)
|
||||
endif()
|
||||
|
||||
# Enable C++14 support for msvc (@todo this should be done in cmake)
|
||||
if(WIN32)
|
||||
target_compile_options(Telegram PRIVATE /std:c++14)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(Telegram PRIVATE ${FFMPEG_DEFINITIONS})
|
||||
|
||||
target_link_libraries(Telegram
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
Qt5::GuiPrivate
|
||||
tgvoip
|
||||
${OPENAL_LIBRARY}
|
||||
${FFMPEG_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${SWRESAMPLE_LIBRARIES}
|
||||
${SWSCALE_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${OPUS_LIB}
|
||||
${CONAN_LIBS}
|
||||
) # crashpad::crashpad_client)
|
||||
|
||||
add_dependencies(Telegram boxes_styles_output)
|
||||
|
||||
if (APPLE)
|
||||
add_dependencies(Telegram iconset_output)
|
||||
|
||||
set_target_properties(Telegram
|
||||
PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Telegram.plist
|
||||
)
|
||||
find_library(COREFOUNDATION_LIB CoreFoundation)
|
||||
find_library(COREAUDIO_LIB CoreAudio)
|
||||
find_library(AUDIOUNIT_LIB AudioUnit)
|
||||
find_library(AUDIOTOOLBOX_LIB AudioToolbox)
|
||||
find_library(COCOA_LIB Cocoa)
|
||||
find_library(CARBON_LIB Carbon)
|
||||
find_library(IOKIT_LIB IOKit)
|
||||
target_link_libraries(Telegram
|
||||
${COREFOUNDATION_LIB}
|
||||
${COCOA_LIB}
|
||||
${CARBON_LIB}
|
||||
${COREAUDIO_LIB}
|
||||
${AUDIOUNIT_LIB}
|
||||
${AUDIOTOOLBOX_LIB}
|
||||
${IOKIT_LIB}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(Telegram winmm imm32 ws2_32 kernel32 user32 gdi32 winspool comdlg32 advapi32 shell32 ole32 oleaut32 uuid odbc32 odbccp32 Shlwapi Iphlpapi Gdiplus Strmiids)
|
||||
endif()
|
||||
|
||||
set_target_properties(Telegram
|
||||
PROPERTIES
|
||||
COTIRE_CXX_PREFIX_HEADER_INIT SourceFiles/stdafx.h
|
||||
COTIRE_ADD_UNITY_BUILD FALSE
|
||||
)
|
||||
cotire(Telegram)
|
||||
|
||||
# See https://github.com/sakra/cotire/blob/master/MANUAL.md#objective-c
|
||||
# ObjC and ObjC++ files cannot be cotired, so they have to include appropriate Qt and Tg
|
||||
# headers themselves, this applies to macOS platform sources.
|
|
@ -1,52 +0,0 @@
|
|||
diff --git a/base/mac/scoped_nsobject.h b/base/mac/scoped_nsobject.h
|
||||
index 2e157a4..5a306a1 100644
|
||||
--- a/base/mac/scoped_nsobject.h
|
||||
+++ b/base/mac/scoped_nsobject.h
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/mac/scoped_typeref.h"
|
||||
+#include "base/template_util.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
@@ -55,7 +56,7 @@ class scoped_nsobject : public scoped_nsprotocol<NST*> {
|
||||
public:
|
||||
using scoped_nsprotocol<NST*>::scoped_nsprotocol;
|
||||
|
||||
- static_assert(std::is_same<NST, NSAutoreleasePool>::value == false,
|
||||
+ static_assert(is_same<NST, NSAutoreleasePool>::value == false,
|
||||
"Use ScopedNSAutoreleasePool instead");
|
||||
};
|
||||
|
||||
diff --git a/base/macros.h b/base/macros.h
|
||||
index 5d96783..096704c 100644
|
||||
--- a/base/macros.h
|
||||
+++ b/base/macros.h
|
||||
@@ -42,8 +42,9 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
|
||||
|
||||
template <typename Dest, typename Source>
|
||||
inline Dest bit_cast(const Source& source) {
|
||||
+#if __cplusplus >= 201103L
|
||||
static_assert(sizeof(Dest) == sizeof(Source), "sizes must be equal");
|
||||
-
|
||||
+#endif
|
||||
Dest dest;
|
||||
memcpy(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
diff --git a/build/common.gypi b/build/common.gypi
|
||||
index 1affc70..6e8f292 100644
|
||||
--- a/build/common.gypi
|
||||
+++ b/build/common.gypi
|
||||
@@ -66,6 +66,11 @@
|
||||
'conditions': [
|
||||
['clang!=0', {
|
||||
'CLANG_CXX_LANGUAGE_STANDARD': 'c++11', # -std=c++11
|
||||
+ 'conditions': [
|
||||
+ ['mac_deployment_target=="10.8"', {
|
||||
+ 'CLANG_CXX_LIBRARY': 'libc++', # force -stdlib=libc++ for 10.8
|
||||
+ }]
|
||||
+ ],
|
||||
|
||||
# Don't link in libarclite_macosx.a, see http://crbug.com/156530.
|
||||
'CLANG_LINK_OBJC_RUNTIME': 'NO', # -fno-objc-link-runtime
|
|
@ -1,22 +0,0 @@
|
|||
diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c
|
||||
index 9d8f8e9..8c8e44a 100644
|
||||
--- a/Alc/backends/winmm.c
|
||||
+++ b/Alc/backends/winmm.c
|
||||
@@ -219,7 +219,7 @@ FORCE_ALIGN static int ALCwinmmPlayback_mixerProc(void *arg)
|
||||
SetRTPriority();
|
||||
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
|
||||
|
||||
- while(GetMessage(&msg, NULL, 0, 0))
|
||||
+ if (!self->killNow) while(GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if(msg.message != WOM_DONE)
|
||||
continue;
|
||||
@@ -504,7 +504,7 @@ static int ALCwinmmCapture_captureProc(void *arg)
|
||||
|
||||
althrd_setname(althrd_current(), RECORD_THREAD_NAME);
|
||||
|
||||
- while(GetMessage(&msg, NULL, 0, 0))
|
||||
+ if (!self->killNow) while(GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if(msg.message != WIM_DATA)
|
||||
continue;
|
|
@ -1,539 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "packer.h"
|
||||
|
||||
#include <QtCore/QtPlugin>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
//Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)
|
||||
#endif
|
||||
|
||||
bool AlphaChannel = false;
|
||||
quint64 BetaVersion = 0;
|
||||
|
||||
const char *PublicKey = "\
|
||||
-----BEGIN RSA PUBLIC KEY-----\n\
|
||||
MIGJAoGBAMA4ViQrjkPZ9xj0lrer3r23JvxOnrtE8nI69XLGSr+sRERz9YnUptnU\n\
|
||||
BZpkIfKaRcl6XzNJiN28cVwO1Ui5JSa814UAiDHzWUqCaXUiUEQ6NmNTneiGx2sQ\n\
|
||||
+9PKKlb8mmr3BB9A45ZNwLT6G9AK3+qkZLHojeSA+m84/a6GP4svAgMBAAE=\n\
|
||||
-----END RSA PUBLIC KEY-----\
|
||||
";
|
||||
|
||||
const char *PublicAlphaKey = "\
|
||||
-----BEGIN RSA PUBLIC KEY-----\n\
|
||||
MIGJAoGBALWu9GGs0HED7KG7BM73CFZ6o0xufKBRQsdnq3lwA8nFQEvmdu+g/I1j\n\
|
||||
0LQ+0IQO7GW4jAgzF/4+soPDb6uHQeNFrlVx1JS9DZGhhjZ5rf65yg11nTCIHZCG\n\
|
||||
w/CVnbwQOw0g5GBwwFV3r0uTTvy44xx8XXxk+Qknu4eBCsmrAFNnAgMBAAE=\n\
|
||||
-----END RSA PUBLIC KEY-----\
|
||||
";
|
||||
|
||||
extern const char *PrivateKey;
|
||||
extern const char *PrivateAlphaKey;
|
||||
#include "../../../../TelegramPrivate/packer_private.h" // RSA PRIVATE KEYS for update signing
|
||||
#include "../../../../TelegramPrivate/beta_private.h" // private key for beta version file generation
|
||||
|
||||
QString countBetaVersionSignature(quint64 version);
|
||||
|
||||
// sha1 hash
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int int32;
|
||||
|
||||
namespace{
|
||||
|
||||
inline uint32 sha1Shift(uint32 v, uint32 shift) {
|
||||
return ((v << shift) | (v >> (32 - shift)));
|
||||
}
|
||||
|
||||
void sha1PartHash(uint32 *sha, uint32 *temp) {
|
||||
uint32 a = sha[0], b = sha[1], c = sha[2], d = sha[3], e = sha[4], round = 0;
|
||||
|
||||
#define _shiftswap(f, v) { \
|
||||
uint32 t = sha1Shift(a, 5) + (f) + e + v + temp[round]; \
|
||||
e = d; \
|
||||
d = c; \
|
||||
c = sha1Shift(b, 30); \
|
||||
b = a; \
|
||||
a = t; \
|
||||
++round; \
|
||||
}
|
||||
|
||||
#define _shiftshiftswap(f, v) { \
|
||||
temp[round] = sha1Shift((temp[round - 3] ^ temp[round - 8] ^ temp[round - 14] ^ temp[round - 16]), 1); \
|
||||
_shiftswap(f, v) \
|
||||
}
|
||||
|
||||
while (round < 16) _shiftswap((b & c) | (~b & d), 0x5a827999)
|
||||
while (round < 20) _shiftshiftswap((b & c) | (~b & d), 0x5a827999)
|
||||
while (round < 40) _shiftshiftswap(b ^ c ^ d, 0x6ed9eba1)
|
||||
while (round < 60) _shiftshiftswap((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
|
||||
while (round < 80) _shiftshiftswap(b ^ c ^ d, 0xca62c1d6)
|
||||
|
||||
#undef _shiftshiftswap
|
||||
#undef _shiftswap
|
||||
|
||||
sha[0] += a;
|
||||
sha[1] += b;
|
||||
sha[2] += c;
|
||||
sha[3] += d;
|
||||
sha[4] += e;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int32 *hashSha1(const void *data, uint32 len, void *dest) {
|
||||
const uchar *buf = (const uchar *)data;
|
||||
|
||||
uint32 temp[80], block = 0, end;
|
||||
uint32 sha[5] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0};
|
||||
for (end = block + 64; block + 64 <= len; end = block + 64) {
|
||||
for (uint32 i = 0; block < end; block += 4) {
|
||||
temp[i++] = (uint32) buf[block + 3]
|
||||
| (((uint32) buf[block + 2]) << 8)
|
||||
| (((uint32) buf[block + 1]) << 16)
|
||||
| (((uint32) buf[block]) << 24);
|
||||
}
|
||||
sha1PartHash(sha, temp);
|
||||
}
|
||||
|
||||
end = len - block;
|
||||
memset(temp, 0, sizeof(uint32) * 16);
|
||||
uint32 last = 0;
|
||||
for (; last < end; ++last) {
|
||||
temp[last >> 2] |= (uint32)buf[last + block] << ((3 - (last & 0x03)) << 3);
|
||||
}
|
||||
temp[last >> 2] |= 0x80 << ((3 - (last & 3)) << 3);
|
||||
if (end >= 56) {
|
||||
sha1PartHash(sha, temp);
|
||||
memset(temp, 0, sizeof(uint32) * 16);
|
||||
}
|
||||
temp[15] = len << 3;
|
||||
sha1PartHash(sha, temp);
|
||||
|
||||
uchar *sha1To = (uchar*)dest;
|
||||
|
||||
for (int32 i = 19; i >= 0; --i) {
|
||||
sha1To[i] = (sha[i >> 2] >> (((3 - i) & 0x03) << 3)) & 0xFF;
|
||||
}
|
||||
|
||||
return (int32*)sha1To;
|
||||
}
|
||||
|
||||
QString BetaSignature;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QString workDir;
|
||||
|
||||
QString remove;
|
||||
int version = 0;
|
||||
bool target32 = false;
|
||||
QFileInfoList files;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (string("-path") == argv[i] && i + 1 < argc) {
|
||||
QString path = workDir + QString(argv[i + 1]);
|
||||
QFileInfo info(path);
|
||||
files.push_back(info);
|
||||
if (remove.isEmpty()) remove = info.canonicalPath() + "/";
|
||||
} else if (string("-target") == argv[i] && i + 1 < argc) {
|
||||
target32 = (string("mac32") == argv[i + 1]);
|
||||
} else if (string("-version") == argv[i] && i + 1 < argc) {
|
||||
version = QString(argv[i + 1]).toInt();
|
||||
} else if (string("-alpha") == argv[i]) {
|
||||
AlphaChannel = true;
|
||||
} else if (string("-beta") == argv[i] && i + 1 < argc) {
|
||||
BetaVersion = QString(argv[i + 1]).toULongLong();
|
||||
if (BetaVersion > version * 1000ULL && BetaVersion < (version + 1) * 1000ULL) {
|
||||
AlphaChannel = false;
|
||||
BetaSignature = countBetaVersionSignature(BetaVersion);
|
||||
if (BetaSignature.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
cout << "Bad -beta param value passed, should be for the same version: " << version << ", beta: " << BetaVersion << "\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (files.isEmpty() || remove.isEmpty() || version <= 1016 || version > 999999999) {
|
||||
#ifdef Q_OS_WIN
|
||||
cout << "Usage: Packer.exe -path {file} -version {version} OR Packer.exe -path {dir} -version {version}\n";
|
||||
#elif defined Q_OS_MAC
|
||||
cout << "Usage: Packer.app -path {file} -version {version} OR Packer.app -path {dir} -version {version}\n";
|
||||
#else
|
||||
cout << "Usage: Packer -path {file} -version {version} OR Packer -path {dir} -version {version}\n";
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool hasDirs = true;
|
||||
while (hasDirs) {
|
||||
hasDirs = false;
|
||||
for (QFileInfoList::iterator i = files.begin(); i != files.end(); ++i) {
|
||||
QFileInfo info(*i);
|
||||
QString fullPath = info.canonicalFilePath();
|
||||
if (info.isDir()) {
|
||||
hasDirs = true;
|
||||
files.erase(i);
|
||||
QDir d = QDir(info.absoluteFilePath());
|
||||
QString fullDir = d.canonicalPath();
|
||||
QStringList entries = d.entryList(QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
||||
files.append(d.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot));
|
||||
break;
|
||||
} else if (!info.isReadable()) {
|
||||
cout << "Can't read: " << info.absoluteFilePath().toUtf8().constData() << "\n";
|
||||
return -1;
|
||||
} else if (info.isHidden()) {
|
||||
hasDirs = true;
|
||||
files.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (QFileInfoList::iterator i = files.begin(); i != files.end(); ++i) {
|
||||
QFileInfo info(*i);
|
||||
if (!info.canonicalFilePath().startsWith(remove)) {
|
||||
cout << "Can't find '" << remove.toUtf8().constData() << "' in file '" << info.canonicalFilePath().toUtf8().constData() << "' :(\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray result;
|
||||
{
|
||||
QBuffer buffer(&result);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QDataStream stream(&buffer);
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
|
||||
if (BetaVersion) {
|
||||
stream << quint32(0x7FFFFFFF);
|
||||
stream << quint64(BetaVersion);
|
||||
} else {
|
||||
stream << quint32(version);
|
||||
}
|
||||
|
||||
stream << quint32(files.size());
|
||||
cout << "Found " << files.size() << " file" << (files.size() == 1 ? "" : "s") << "..\n";
|
||||
for (QFileInfoList::iterator i = files.begin(); i != files.end(); ++i) {
|
||||
QFileInfo info(*i);
|
||||
QString fullName = info.canonicalFilePath();
|
||||
QString name = fullName.mid(remove.length());
|
||||
cout << name.toUtf8().constData() << " (" << info.size() << ")\n";
|
||||
|
||||
QFile f(fullName);
|
||||
if (!f.open(QIODevice::ReadOnly)) {
|
||||
cout << "Can't open '" << fullName.toUtf8().constData() << "' for read..\n";
|
||||
return -1;
|
||||
}
|
||||
QByteArray inner = f.readAll();
|
||||
stream << name << quint32(inner.size()) << inner;
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
stream << (QFileInfo(fullName).isExecutable() ? true : false);
|
||||
#endif
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
cout << "Stream status is bad: " << stream.status() << "\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32 resultSize = result.size();
|
||||
cout << "Compression start, size: " << resultSize << "\n";
|
||||
|
||||
QByteArray compressed, resultCheck;
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
|
||||
|
||||
compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size
|
||||
|
||||
size_t compressedLen = compressed.size() - hSize;
|
||||
size_t outPropsSize = LZMA_PROPS_SIZE;
|
||||
uchar *_dest = (uchar*)(compressed.data() + hSize);
|
||||
size_t *_destLen = &compressedLen;
|
||||
const uchar *_src = (const uchar*)(result.constData());
|
||||
size_t _srcLen = result.size();
|
||||
uchar *_outProps = (uchar*)(compressed.data() + hSigLen + hShaLen);
|
||||
int res = LzmaCompress(_dest, _destLen, _src, _srcLen, _outProps, &outPropsSize, 9, 64 * 1024 * 1024, 4, 0, 2, 273, 2);
|
||||
if (res != SZ_OK) {
|
||||
cout << "Error in compression: " << res << "\n";
|
||||
return -1;
|
||||
}
|
||||
compressed.resize(int(hSize + compressedLen));
|
||||
memcpy(compressed.data() + hSigLen + hShaLen + hPropsLen, &resultSize, hOriginalSizeLen);
|
||||
|
||||
cout << "Compressed to size: " << compressedLen << "\n";
|
||||
|
||||
cout << "Checking uncompressed..\n";
|
||||
|
||||
int32 resultCheckLen;
|
||||
memcpy(&resultCheckLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen);
|
||||
if (resultCheckLen <= 0 || resultCheckLen > 1024 * 1024 * 1024) {
|
||||
cout << "Bad result len: " << resultCheckLen << "\n";
|
||||
return -1;
|
||||
}
|
||||
resultCheck.resize(resultCheckLen);
|
||||
|
||||
size_t resultLen = resultCheck.size();
|
||||
SizeT srcLen = compressedLen;
|
||||
int uncompressRes = LzmaUncompress((uchar*)resultCheck.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE);
|
||||
if (uncompressRes != SZ_OK) {
|
||||
cout << "Uncompress failed: " << uncompressRes << "\n";
|
||||
return -1;
|
||||
}
|
||||
if (resultLen != size_t(result.size())) {
|
||||
cout << "Uncompress bad size: " << resultLen << ", was: " << result.size() << "\n";
|
||||
return -1;
|
||||
}
|
||||
#else // use liblzma for others
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header
|
||||
|
||||
compressed.resize(hSize + resultSize + 1024 * 1024); // rsa signature + sha1 + lzma props + max compressed size
|
||||
|
||||
size_t compressedLen = compressed.size() - hSize;
|
||||
|
||||
lzma_stream stream = LZMA_STREAM_INIT;
|
||||
|
||||
int preset = 9 | LZMA_PRESET_EXTREME;
|
||||
lzma_ret ret = lzma_easy_encoder(&stream, preset, LZMA_CHECK_CRC64);
|
||||
if (ret != LZMA_OK) {
|
||||
const char *msg;
|
||||
switch (ret) {
|
||||
case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
|
||||
case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break;
|
||||
case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break;
|
||||
default: msg = "Unknown error, possibly a bug"; break;
|
||||
}
|
||||
cout << "Error initializing the encoder: " << msg << " (error code " << ret << ")\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream.avail_in = resultSize;
|
||||
stream.next_in = (uint8_t*)result.constData();
|
||||
stream.avail_out = compressedLen;
|
||||
stream.next_out = (uint8_t*)(compressed.data() + hSize);
|
||||
|
||||
lzma_ret res = lzma_code(&stream, LZMA_FINISH);
|
||||
compressedLen -= stream.avail_out;
|
||||
lzma_end(&stream);
|
||||
if (res != LZMA_OK && res != LZMA_STREAM_END) {
|
||||
const char *msg;
|
||||
switch (res) {
|
||||
case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
|
||||
case LZMA_DATA_ERROR: msg = "File size limits exceeded"; break;
|
||||
default: msg = "Unknown error, possibly a bug"; break;
|
||||
}
|
||||
cout << "Error in compression: " << msg << " (error code " << res << ")\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
compressed.resize(int(hSize + compressedLen));
|
||||
memcpy(compressed.data() + hSigLen + hShaLen, &resultSize, hOriginalSizeLen);
|
||||
|
||||
cout << "Compressed to size: " << compressedLen << "\n";
|
||||
|
||||
cout << "Checking uncompressed..\n";
|
||||
|
||||
int32 resultCheckLen;
|
||||
memcpy(&resultCheckLen, compressed.constData() + hSigLen + hShaLen, hOriginalSizeLen);
|
||||
if (resultCheckLen <= 0 || resultCheckLen > 1024 * 1024 * 1024) {
|
||||
cout << "Bad result len: " << resultCheckLen << "\n";
|
||||
return -1;
|
||||
}
|
||||
resultCheck.resize(resultCheckLen);
|
||||
|
||||
size_t resultLen = resultCheck.size();
|
||||
|
||||
stream = LZMA_STREAM_INIT;
|
||||
|
||||
ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED);
|
||||
if (ret != LZMA_OK) {
|
||||
const char *msg;
|
||||
switch (ret) {
|
||||
case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
|
||||
case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break;
|
||||
case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break;
|
||||
default: msg = "Unknown error, possibly a bug"; break;
|
||||
}
|
||||
cout << "Error initializing the decoder: " << msg << " (error code " << ret << ")\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream.avail_in = compressedLen;
|
||||
stream.next_in = (uint8_t*)(compressed.constData() + hSize);
|
||||
stream.avail_out = resultLen;
|
||||
stream.next_out = (uint8_t*)resultCheck.data();
|
||||
|
||||
res = lzma_code(&stream, LZMA_FINISH);
|
||||
if (stream.avail_in) {
|
||||
cout << "Error in decompression, " << stream.avail_in << " bytes left in _in of " << compressedLen << " whole.\n";
|
||||
return -1;
|
||||
} else if (stream.avail_out) {
|
||||
cout << "Error in decompression, " << stream.avail_out << " bytes free left in _out of " << resultLen << " whole.\n";
|
||||
return -1;
|
||||
}
|
||||
lzma_end(&stream);
|
||||
if (res != LZMA_OK && res != LZMA_STREAM_END) {
|
||||
const char *msg;
|
||||
switch (res) {
|
||||
case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
|
||||
case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break;
|
||||
case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break;
|
||||
case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break;
|
||||
case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break;
|
||||
default: msg = "Unknown error, possibly a bug"; break;
|
||||
}
|
||||
cout << "Error in decompression: " << msg << " (error code " << res << ")\n";
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (memcmp(result.constData(), resultCheck.constData(), resultLen)) {
|
||||
cout << "Data differ :(\n";
|
||||
return -1;
|
||||
}
|
||||
/**/
|
||||
result = resultCheck = QByteArray();
|
||||
|
||||
cout << "Counting SHA1 hash..\n";
|
||||
|
||||
uchar sha1Buffer[20];
|
||||
memcpy(compressed.data() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, uint32(compressedLen + hPropsLen + hOriginalSizeLen), sha1Buffer), hShaLen); // count sha1
|
||||
|
||||
uint32 siglen = 0;
|
||||
|
||||
cout << "Signing..\n";
|
||||
RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>((AlphaChannel || BetaVersion) ? PrivateAlphaKey : PrivateKey), -1), 0, 0, 0);
|
||||
if (!prKey) {
|
||||
cout << "Could not read RSA private key!\n";
|
||||
return -1;
|
||||
}
|
||||
if (RSA_size(prKey) != hSigLen) {
|
||||
cout << "Bad private key, size: " << RSA_size(prKey) << "\n";
|
||||
RSA_free(prKey);
|
||||
return -1;
|
||||
}
|
||||
if (RSA_sign(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (uchar*)(compressed.data()), &siglen, prKey) != 1) { // count signature
|
||||
cout << "Signing failed!\n";
|
||||
RSA_free(prKey);
|
||||
return -1;
|
||||
}
|
||||
RSA_free(prKey);
|
||||
|
||||
if (siglen != hSigLen) {
|
||||
cout << "Bad signature length: " << siglen << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
cout << "Checking signature..\n";
|
||||
RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>((AlphaChannel || BetaVersion) ? PublicAlphaKey : PublicKey), -1), 0, 0, 0);
|
||||
if (!pbKey) {
|
||||
cout << "Could not read RSA public key!\n";
|
||||
return -1;
|
||||
}
|
||||
if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), siglen, pbKey) != 1) { // verify signature
|
||||
RSA_free(pbKey);
|
||||
cout << "Signature verification failed!\n";
|
||||
return -1;
|
||||
}
|
||||
cout << "Signature verified!\n";
|
||||
RSA_free(pbKey);
|
||||
#ifdef Q_OS_WIN
|
||||
QString outName(QString("tupdate%1").arg(BetaVersion ? BetaVersion : version));
|
||||
#elif defined Q_OS_MAC
|
||||
QString outName((target32 ? QString("tmac32upd%1") : QString("tmacupd%1")).arg(BetaVersion ? BetaVersion : version));
|
||||
#elif defined Q_OS_LINUX32
|
||||
QString outName(QString("tlinux32upd%1").arg(BetaVersion ? BetaVersion : version));
|
||||
#elif defined Q_OS_LINUX64
|
||||
QString outName(QString("tlinuxupd%1").arg(BetaVersion ? BetaVersion : version));
|
||||
#else
|
||||
#error Unknown platform!
|
||||
#endif
|
||||
if (BetaVersion) {
|
||||
outName += "_" + BetaSignature;
|
||||
}
|
||||
QFile out(outName);
|
||||
if (!out.open(QIODevice::WriteOnly)) {
|
||||
cout << "Can't open '" << outName.toUtf8().constData() << "' for write..\n";
|
||||
return -1;
|
||||
}
|
||||
out.write(compressed);
|
||||
out.close();
|
||||
|
||||
if (BetaVersion) {
|
||||
QString keyName(QString("tbeta_%1_key").arg(BetaVersion));
|
||||
QFile key(keyName);
|
||||
if (!key.open(QIODevice::WriteOnly)) {
|
||||
cout << "Can't open '" << keyName.toUtf8().constData() << "' for write..\n";
|
||||
return -1;
|
||||
}
|
||||
key.write(BetaSignature.toUtf8());
|
||||
key.close();
|
||||
}
|
||||
|
||||
cout << "Update file '" << outName.toUtf8().constData() << "' written successfully!\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString countBetaVersionSignature(quint64 version) { // duplicated in autoupdate.cpp
|
||||
QByteArray cBetaPrivateKey(BetaPrivateKey);
|
||||
if (cBetaPrivateKey.isEmpty()) {
|
||||
cout << "Error: Trying to count beta version signature without beta private key!\n";
|
||||
return QString();
|
||||
}
|
||||
|
||||
QByteArray signedData = (QLatin1String("TelegramBeta_") + QString::number(version, 16).toLower()).toUtf8();
|
||||
|
||||
static const int32 shaSize = 20, keySize = 128;
|
||||
|
||||
uchar sha1Buffer[shaSize];
|
||||
hashSha1(signedData.constData(), signedData.size(), sha1Buffer); // count sha1
|
||||
|
||||
uint32 siglen = 0;
|
||||
|
||||
RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cBetaPrivateKey.constData()), -1), 0, 0, 0);
|
||||
if (!prKey) {
|
||||
cout << "Error: Could not read beta private key!\n";
|
||||
return QString();
|
||||
}
|
||||
if (RSA_size(prKey) != keySize) {
|
||||
cout << "Error: Bad beta private key size: " << RSA_size(prKey) << "\n";
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
QByteArray signature;
|
||||
signature.resize(keySize);
|
||||
if (RSA_sign(NID_sha1, (const uchar*)(sha1Buffer), shaSize, (uchar*)(signature.data()), &siglen, prKey) != 1) { // count signature
|
||||
cout << "Error: Counting beta version signature failed!\n";
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
RSA_free(prKey);
|
||||
|
||||
if (siglen != keySize) {
|
||||
cout << "Error: Bad beta version signature length: " << siglen << "\n";
|
||||
return QString();
|
||||
}
|
||||
|
||||
signature = signature.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
signature = signature.replace('-', '8').replace('_', 'B');
|
||||
return QString::fromUtf8(signature.mid(19, 32));
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QBuffer>
|
||||
#include <QtCore/QDataStream>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
#include <LzmaLib.h>
|
||||
#else
|
||||
#include <lzma.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::cout;
|
|
@ -1,590 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "updater.h"
|
||||
|
||||
bool _debug = false;
|
||||
|
||||
wstring updaterName, updaterDir, updateTo, exeName;
|
||||
|
||||
bool equal(const wstring &a, const wstring &b) {
|
||||
return !_wcsicmp(a.c_str(), b.c_str());
|
||||
}
|
||||
|
||||
void updateError(const WCHAR *msg, DWORD errorCode) {
|
||||
WCHAR errMsg[2048];
|
||||
LPWSTR errorText = NULL, errorTextDefault = L"(Unknown error)";
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&errorText, 0, 0);
|
||||
if (!errorText) {
|
||||
errorText = errorTextDefault;
|
||||
}
|
||||
wsprintf(errMsg, L"%s, error code: %d\nError message: %s", msg, errorCode, errorText);
|
||||
|
||||
MessageBox(0, errMsg, L"Update error!", MB_ICONERROR);
|
||||
|
||||
if (errorText != errorTextDefault) {
|
||||
LocalFree(errorText);
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE _logFile = 0;
|
||||
void openLog() {
|
||||
if (!_debug || _logFile) return;
|
||||
wstring logPath = L"DebugLogs";
|
||||
if (!CreateDirectory(logPath.c_str(), NULL)) {
|
||||
DWORD errorCode = GetLastError();
|
||||
if (errorCode && errorCode != ERROR_ALREADY_EXISTS) {
|
||||
updateError(L"Failed to create log directory", errorCode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SYSTEMTIME stLocalTime;
|
||||
|
||||
GetLocalTime(&stLocalTime);
|
||||
|
||||
static const int maxFileLen = MAX_PATH * 10;
|
||||
WCHAR logName[maxFileLen];
|
||||
wsprintf(logName, L"DebugLogs\\%04d%02d%02d_%02d%02d%02d_upd.txt",
|
||||
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
||||
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
|
||||
_logFile = CreateFile(logName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (_logFile == INVALID_HANDLE_VALUE) { // :(
|
||||
updateError(L"Failed to create log file", GetLastError());
|
||||
_logFile = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void closeLog() {
|
||||
if (!_logFile) return;
|
||||
|
||||
CloseHandle(_logFile);
|
||||
_logFile = 0;
|
||||
}
|
||||
|
||||
void writeLog(const wstring &msg) {
|
||||
if (!_logFile) return;
|
||||
|
||||
wstring full = msg + L'\n';
|
||||
DWORD written = 0;
|
||||
BOOL result = WriteFile(_logFile, full.c_str(), full.size() * sizeof(wchar_t), &written, 0);
|
||||
if (!result) {
|
||||
updateError((L"Failed to write log entry '" + msg + L"'").c_str(), GetLastError());
|
||||
closeLog();
|
||||
return;
|
||||
}
|
||||
BOOL flushr = FlushFileBuffers(_logFile);
|
||||
if (!flushr) {
|
||||
updateError((L"Failed to flush log on entry '" + msg + L"'").c_str(), GetLastError());
|
||||
closeLog();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void fullClearPath(const wstring &dir) {
|
||||
WCHAR path[4096];
|
||||
memcpy(path, dir.c_str(), (dir.size() + 1) * sizeof(WCHAR));
|
||||
path[dir.size() + 1] = 0;
|
||||
writeLog(L"Fully clearing path '" + dir + L"'..");
|
||||
SHFILEOPSTRUCT file_op = {
|
||||
NULL,
|
||||
FO_DELETE,
|
||||
path,
|
||||
L"",
|
||||
FOF_NOCONFIRMATION |
|
||||
FOF_NOERRORUI |
|
||||
FOF_SILENT,
|
||||
false,
|
||||
0,
|
||||
L""
|
||||
};
|
||||
int res = SHFileOperation(&file_op);
|
||||
if (res) writeLog(L"Error: failed to clear path! :(");
|
||||
}
|
||||
|
||||
void delFolder() {
|
||||
wstring delPathOld = L"tupdates\\ready", delPath = L"tupdates\\temp", delFolder = L"tupdates";
|
||||
fullClearPath(delPathOld);
|
||||
fullClearPath(delPath);
|
||||
RemoveDirectory(delFolder.c_str());
|
||||
}
|
||||
|
||||
DWORD versionNum = 0, versionLen = 0, readLen = 0;
|
||||
WCHAR versionStr[32] = { 0 };
|
||||
|
||||
bool update() {
|
||||
writeLog(L"Update started..");
|
||||
|
||||
wstring updDir = L"tupdates\\temp", readyFilePath = L"tupdates\\temp\\ready", tdataDir = L"tupdates\\temp\\tdata";
|
||||
{
|
||||
HANDLE readyFile = CreateFile(readyFilePath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (readyFile != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(readyFile);
|
||||
} else {
|
||||
updDir = L"tupdates\\ready"; // old
|
||||
tdataDir = L"tupdates\\ready\\tdata";
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE versionFile = CreateFile((tdataDir + L"\\version").c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (versionFile != INVALID_HANDLE_VALUE) {
|
||||
if (!ReadFile(versionFile, &versionNum, sizeof(DWORD), &readLen, NULL) || readLen != sizeof(DWORD)) {
|
||||
versionNum = 0;
|
||||
} else {
|
||||
if (versionNum == 0x7FFFFFFF) { // beta version
|
||||
|
||||
} else if (!ReadFile(versionFile, &versionLen, sizeof(DWORD), &readLen, NULL) || readLen != sizeof(DWORD) || versionLen > 63) {
|
||||
versionNum = 0;
|
||||
} else if (!ReadFile(versionFile, versionStr, versionLen, &readLen, NULL) || readLen != versionLen) {
|
||||
versionNum = 0;
|
||||
}
|
||||
}
|
||||
CloseHandle(versionFile);
|
||||
writeLog(L"Version file read.");
|
||||
} else {
|
||||
writeLog(L"Could not open version file to update registry :(");
|
||||
}
|
||||
|
||||
deque<wstring> dirs;
|
||||
dirs.push_back(updDir);
|
||||
|
||||
deque<wstring> from, to, forcedirs;
|
||||
|
||||
do {
|
||||
wstring dir = dirs.front();
|
||||
dirs.pop_front();
|
||||
|
||||
wstring toDir = updateTo;
|
||||
if (dir.size() > updDir.size() + 1) {
|
||||
toDir += (dir.substr(updDir.size() + 1) + L"\\");
|
||||
forcedirs.push_back(toDir);
|
||||
writeLog(L"Parsing dir '" + toDir + L"' in update tree..");
|
||||
}
|
||||
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE findHandle = FindFirstFileEx((dir + L"\\*").c_str(), FindExInfoStandard, &findData, FindExSearchNameMatch, 0, 0);
|
||||
if (findHandle == INVALID_HANDLE_VALUE) {
|
||||
DWORD errorCode = GetLastError();
|
||||
if (errorCode == ERROR_PATH_NOT_FOUND) { // no update is ready
|
||||
return true;
|
||||
}
|
||||
writeLog(L"Error: failed to find update files :(");
|
||||
updateError(L"Failed to find update files", errorCode);
|
||||
delFolder();
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
wstring fname = dir + L"\\" + findData.cFileName;
|
||||
if (fname.substr(0, tdataDir.size()) == tdataDir && (fname.size() <= tdataDir.size() || fname.at(tdataDir.size()) == '/')) {
|
||||
writeLog(L"Skipped 'tdata' path '" + fname + L"'");
|
||||
} else if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if (findData.cFileName != wstring(L".") && findData.cFileName != wstring(L"..")) {
|
||||
dirs.push_back(fname);
|
||||
writeLog(L"Added dir '" + fname + L"' in update tree..");
|
||||
}
|
||||
} else {
|
||||
wstring tofname = updateTo + fname.substr(updDir.size() + 1);
|
||||
if (equal(tofname, updaterName)) { // bad update - has Updater.exe - delete all dir
|
||||
writeLog(L"Error: bad update, has Updater.exe! '" + tofname + L"' equal '" + updaterName + L"'");
|
||||
delFolder();
|
||||
return false;
|
||||
} else if (equal(tofname, updateTo + L"Telegram.exe") && exeName != L"Telegram.exe") {
|
||||
wstring fullBinaryPath = updateTo + exeName;
|
||||
writeLog(L"Target binary found: '" + tofname + L"', changing to '" + fullBinaryPath + L"'");
|
||||
tofname = fullBinaryPath;
|
||||
}
|
||||
if (equal(fname, readyFilePath)) {
|
||||
writeLog(L"Skipped ready file '" + fname + L"'");
|
||||
} else {
|
||||
from.push_back(fname);
|
||||
to.push_back(tofname);
|
||||
writeLog(L"Added file '" + fname + L"' to be copied to '" + tofname + L"'");
|
||||
}
|
||||
}
|
||||
} while (FindNextFile(findHandle, &findData));
|
||||
DWORD errorCode = GetLastError();
|
||||
if (errorCode && errorCode != ERROR_NO_MORE_FILES) { // everything is found
|
||||
writeLog(L"Error: failed to find next update file :(");
|
||||
updateError(L"Failed to find next update file", errorCode);
|
||||
delFolder();
|
||||
return false;
|
||||
}
|
||||
FindClose(findHandle);
|
||||
} while (!dirs.empty());
|
||||
|
||||
for (size_t i = 0; i < forcedirs.size(); ++i) {
|
||||
wstring forcedir = forcedirs[i];
|
||||
writeLog(L"Forcing dir '" + forcedir + L"'..");
|
||||
if (!forcedir.empty() && !CreateDirectory(forcedir.c_str(), NULL)) {
|
||||
DWORD errorCode = GetLastError();
|
||||
if (errorCode && errorCode != ERROR_ALREADY_EXISTS) {
|
||||
writeLog(L"Error: failed to create dir '" + forcedir + L"'..");
|
||||
updateError(L"Failed to create directory", errorCode);
|
||||
delFolder();
|
||||
return false;
|
||||
}
|
||||
writeLog(L"Already exists!");
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < from.size(); ++i) {
|
||||
wstring fname = from[i], tofname = to[i];
|
||||
BOOL copyResult;
|
||||
do {
|
||||
writeLog(L"Copying file '" + fname + L"' to '" + tofname + L"'..");
|
||||
int copyTries = 0;
|
||||
do {
|
||||
copyResult = CopyFile(fname.c_str(), tofname.c_str(), FALSE);
|
||||
if (!copyResult) {
|
||||
++copyTries;
|
||||
Sleep(100);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (copyTries < 100);
|
||||
if (!copyResult) {
|
||||
writeLog(L"Error: failed to copy, asking to retry..");
|
||||
WCHAR errMsg[2048];
|
||||
wsprintf(errMsg, L"Failed to update Telegram :(\n%s is not accessible.", tofname.c_str());
|
||||
if (MessageBox(0, errMsg, L"Update error!", MB_ICONERROR | MB_RETRYCANCEL) != IDRETRY) {
|
||||
delFolder();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while (!copyResult);
|
||||
}
|
||||
|
||||
writeLog(L"Update succeed! Clearing folder..");
|
||||
delFolder();
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateRegistry() {
|
||||
if (versionNum && versionNum != 0x7FFFFFFF) {
|
||||
writeLog(L"Updating registry..");
|
||||
versionStr[versionLen / 2] = 0;
|
||||
HKEY rkey;
|
||||
LSTATUS status = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{53F49750-6209-4FBF-9CA8-7A333C87D1ED}_is1", 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &rkey);
|
||||
if (status == ERROR_SUCCESS) {
|
||||
writeLog(L"Checking registry install location..");
|
||||
static const int bufSize = 4096;
|
||||
DWORD locationType, locationSize = bufSize * 2;
|
||||
WCHAR locationStr[bufSize], exp[bufSize];
|
||||
if (RegQueryValueEx(rkey, L"InstallLocation", 0, &locationType, (BYTE*)locationStr, &locationSize) == ERROR_SUCCESS) {
|
||||
locationSize /= 2;
|
||||
if (locationStr[locationSize - 1]) {
|
||||
locationStr[locationSize++] = 0;
|
||||
}
|
||||
if (locationType == REG_EXPAND_SZ) {
|
||||
DWORD copy = ExpandEnvironmentStrings(locationStr, exp, bufSize);
|
||||
if (copy <= bufSize) {
|
||||
memcpy(locationStr, exp, copy * sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
if (locationType == REG_EXPAND_SZ || locationType == REG_SZ) {
|
||||
if (PathCanonicalize(exp, locationStr)) {
|
||||
memcpy(locationStr, exp, bufSize * sizeof(WCHAR));
|
||||
if (GetFullPathName(L".", bufSize, exp, 0) < bufSize) {
|
||||
wstring installpath = locationStr, mypath = exp;
|
||||
if (installpath == mypath + L"\\" || true) { // always update reg info, if we found it
|
||||
WCHAR nameStr[bufSize], dateStr[bufSize], publisherStr[bufSize], icongroupStr[bufSize];
|
||||
SYSTEMTIME stLocalTime;
|
||||
GetLocalTime(&stLocalTime);
|
||||
RegSetValueEx(rkey, L"DisplayVersion", 0, REG_SZ, (BYTE*)versionStr, ((versionLen / 2) + 1) * sizeof(WCHAR));
|
||||
wsprintf(nameStr, L"Telegram Desktop version %s", versionStr);
|
||||
RegSetValueEx(rkey, L"DisplayName", 0, REG_SZ, (BYTE*)nameStr, (wcslen(nameStr) + 1) * sizeof(WCHAR));
|
||||
wsprintf(publisherStr, L"Telegram Messenger LLP");
|
||||
RegSetValueEx(rkey, L"Publisher", 0, REG_SZ, (BYTE*)publisherStr, (wcslen(publisherStr) + 1) * sizeof(WCHAR));
|
||||
wsprintf(icongroupStr, L"Telegram Desktop");
|
||||
RegSetValueEx(rkey, L"Inno Setup: Icon Group", 0, REG_SZ, (BYTE*)icongroupStr, (wcslen(icongroupStr) + 1) * sizeof(WCHAR));
|
||||
wsprintf(dateStr, L"%04d%02d%02d", stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay);
|
||||
RegSetValueEx(rkey, L"InstallDate", 0, REG_SZ, (BYTE*)dateStr, (wcslen(dateStr) + 1) * sizeof(WCHAR));
|
||||
|
||||
WCHAR *appURL = L"https://desktop.telegram.org";
|
||||
RegSetValueEx(rkey, L"HelpLink", 0, REG_SZ, (BYTE*)appURL, (wcslen(appURL) + 1) * sizeof(WCHAR));
|
||||
RegSetValueEx(rkey, L"URLInfoAbout", 0, REG_SZ, (BYTE*)appURL, (wcslen(appURL) + 1) * sizeof(WCHAR));
|
||||
RegSetValueEx(rkey, L"URLUpdateInfo", 0, REG_SZ, (BYTE*)appURL, (wcslen(appURL) + 1) * sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RegCloseKey(rkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) {
|
||||
openLog();
|
||||
|
||||
_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
|
||||
// CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter);
|
||||
|
||||
writeLog(L"Updaters started..");
|
||||
|
||||
LPWSTR *args;
|
||||
int argsCount;
|
||||
|
||||
bool needupdate = false, autostart = false, debug = false, writeprotected = false, startintray = false, testmode = false;
|
||||
args = CommandLineToArgvW(GetCommandLine(), &argsCount);
|
||||
if (args) {
|
||||
for (int i = 1; i < argsCount; ++i) {
|
||||
if (equal(args[i], L"-update")) {
|
||||
needupdate = true;
|
||||
} else if (equal(args[i], L"-autostart")) {
|
||||
autostart = true;
|
||||
} else if (equal(args[i], L"-debug")) {
|
||||
debug = _debug = true;
|
||||
openLog();
|
||||
} else if (equal(args[i], L"-startintray")) {
|
||||
startintray = true;
|
||||
} else if (equal(args[i], L"-testmode")) {
|
||||
testmode = true;
|
||||
} else if (equal(args[i], L"-writeprotected") && ++i < argsCount) {
|
||||
writeprotected = true;
|
||||
updateTo = args[i];
|
||||
for (int i = 0, l = updateTo.size(); i < l; ++i) {
|
||||
if (updateTo[i] == L'/') {
|
||||
updateTo[i] = L'\\';
|
||||
}
|
||||
}
|
||||
} else if (equal(args[i], L"-exename") && ++i < argsCount) {
|
||||
exeName = args[i];
|
||||
for (int i = 0, l = exeName.size(); i < l; ++i) {
|
||||
if (exeName[i] == L'/' || exeName[i] == L'\\') {
|
||||
exeName = L"Telegram.exe";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exeName.empty()) {
|
||||
exeName = L"Telegram.exe";
|
||||
}
|
||||
if (needupdate) writeLog(L"Need to update!");
|
||||
if (autostart) writeLog(L"From autostart!");
|
||||
if (writeprotected) writeLog(L"Write Protected folder!");
|
||||
|
||||
updaterName = args[0];
|
||||
writeLog(L"Updater name is: " + updaterName);
|
||||
if (updaterName.size() > 11) {
|
||||
if (equal(updaterName.substr(updaterName.size() - 11), L"Updater.exe")) {
|
||||
updaterDir = updaterName.substr(0, updaterName.size() - 11);
|
||||
writeLog(L"Updater dir is: " + updaterDir);
|
||||
if (!writeprotected) {
|
||||
updateTo = updaterDir;
|
||||
}
|
||||
writeLog(L"Update to: " + updateTo);
|
||||
if (needupdate && update()) {
|
||||
updateRegistry();
|
||||
}
|
||||
if (writeprotected) { // if we can't clear all tupdates\ready (Updater.exe is there) - clear only version
|
||||
if (DeleteFile(L"tupdates\\temp\\tdata\\version") || DeleteFile(L"tupdates\\ready\\tdata\\version")) {
|
||||
writeLog(L"Version file deleted!");
|
||||
} else {
|
||||
writeLog(L"Error: could not delete version file");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeLog(L"Error: bad exe name!");
|
||||
}
|
||||
} else {
|
||||
writeLog(L"Error: short exe name!");
|
||||
}
|
||||
LocalFree(args);
|
||||
} else {
|
||||
writeLog(L"Error: No command line arguments!");
|
||||
}
|
||||
|
||||
wstring targs;
|
||||
if (autostart) targs += L" -autostart";
|
||||
if (debug) targs += L" -debug";
|
||||
if (startintray) targs += L" -startintray";
|
||||
if (testmode) targs += L" -testmode";
|
||||
|
||||
bool executed = false;
|
||||
if (writeprotected) { // run un-elevated
|
||||
writeLog(L"Trying to run un-elevated by temp.lnk");
|
||||
|
||||
HRESULT hres = CoInitialize(0);
|
||||
if (SUCCEEDED(hres)) {
|
||||
IShellLink* psl;
|
||||
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
||||
if (SUCCEEDED(hres)) {
|
||||
IPersistFile* ppf;
|
||||
|
||||
wstring exe = updateTo + exeName, dir = updateTo;
|
||||
psl->SetArguments((targs.size() ? targs.substr(1) : targs).c_str());
|
||||
psl->SetPath(exe.c_str());
|
||||
psl->SetWorkingDirectory(dir.c_str());
|
||||
psl->SetDescription(L"");
|
||||
|
||||
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
|
||||
|
||||
if (SUCCEEDED(hres)) {
|
||||
wstring lnk = L"tupdates\\temp\\temp.lnk";
|
||||
hres = ppf->Save(lnk.c_str(), TRUE);
|
||||
if (!SUCCEEDED(hres)) {
|
||||
lnk = L"tupdates\\ready\\temp.lnk"; // old
|
||||
hres = ppf->Save(lnk.c_str(), TRUE);
|
||||
}
|
||||
ppf->Release();
|
||||
|
||||
if (SUCCEEDED(hres)) {
|
||||
writeLog(L"Executing un-elevated through link..");
|
||||
ShellExecute(0, 0, L"explorer.exe", lnk.c_str(), 0, SW_SHOWNORMAL);
|
||||
executed = true;
|
||||
} else {
|
||||
writeLog(L"Error: ppf->Save failed");
|
||||
}
|
||||
} else {
|
||||
writeLog(L"Error: Could not create interface IID_IPersistFile");
|
||||
}
|
||||
psl->Release();
|
||||
} else {
|
||||
writeLog(L"Error: could not create instance of IID_IShellLink");
|
||||
}
|
||||
CoUninitialize();
|
||||
} else {
|
||||
writeLog(L"Error: Could not initialize COM");
|
||||
}
|
||||
}
|
||||
if (!executed) {
|
||||
ShellExecute(0, 0, (updateTo + exeName).c_str(), (L"-noupdate" + targs).c_str(), 0, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
writeLog(L"Executed '" + exeName + L"', closing log and quitting..");
|
||||
closeLog();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const WCHAR *_programName = L"Telegram Desktop"; // folder in APPDATA, if current path is unavailable for writing
|
||||
static const WCHAR *_exeName = L"Updater.exe";
|
||||
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter = 0;
|
||||
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_miniDumpWriteDump)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD ProcessId,
|
||||
_In_ HANDLE hFile,
|
||||
_In_ MINIDUMP_TYPE DumpType,
|
||||
_In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
_In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
_In_opt_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||
);
|
||||
t_miniDumpWriteDump miniDumpWriteDump = 0;
|
||||
|
||||
HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
||||
static const int maxFileLen = MAX_PATH * 10;
|
||||
|
||||
WCHAR szPath[maxFileLen];
|
||||
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];
|
||||
|
||||
wcscpy_s(szExeName, _exeName);
|
||||
WCHAR *dotFrom = wcschr(szExeName, WCHAR(L'.'));
|
||||
if (dotFrom) {
|
||||
wsprintf(dotFrom, L"");
|
||||
}
|
||||
|
||||
SYSTEMTIME stLocalTime;
|
||||
|
||||
GetLocalTime(&stLocalTime);
|
||||
|
||||
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
|
||||
szPath, szExeName, updaterVersionStr,
|
||||
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
||||
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
|
||||
GetCurrentProcessId(), GetCurrentThreadId());
|
||||
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
||||
}
|
||||
|
||||
void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
|
||||
static const int maxFileLen = MAX_PATH * 10;
|
||||
|
||||
closeLog();
|
||||
|
||||
HMODULE hDll = LoadLibrary(L"DBGHELP.DLL");
|
||||
if (!hDll) return;
|
||||
|
||||
miniDumpWriteDump = (t_miniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
|
||||
if (!miniDumpWriteDump) return;
|
||||
|
||||
HANDLE hDumpFile = 0;
|
||||
|
||||
WCHAR szPath[maxFileLen];
|
||||
DWORD len = GetModuleFileName(GetModuleHandle(0), szPath, maxFileLen);
|
||||
if (!len) return;
|
||||
|
||||
WCHAR *pathEnd = szPath + len;
|
||||
|
||||
if (!_wcsicmp(pathEnd - wcslen(_exeName), _exeName)) {
|
||||
wsprintf(pathEnd - wcslen(_exeName), L"");
|
||||
hDumpFile = _generateDumpFileAtPath(szPath);
|
||||
}
|
||||
if (!hDumpFile || hDumpFile == INVALID_HANDLE_VALUE) {
|
||||
WCHAR wstrPath[maxFileLen];
|
||||
DWORD wstrPathLen;
|
||||
if (wstrPathLen = GetEnvironmentVariable(L"APPDATA", wstrPath, maxFileLen)) {
|
||||
wsprintf(wstrPath + wstrPathLen, L"\\%s\\", _programName);
|
||||
hDumpFile = _generateDumpFileAtPath(wstrPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hDumpFile || hDumpFile == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION ExpParam = {0};
|
||||
ExpParam.ThreadId = GetCurrentThreadId();
|
||||
ExpParam.ExceptionPointers = pExceptionPointers;
|
||||
ExpParam.ClientPointers = TRUE;
|
||||
|
||||
miniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);
|
||||
}
|
||||
|
||||
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) {
|
||||
_generateDump(pExceptionPointers);
|
||||
return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 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>
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
using std::deque;
|
||||
using std::wstring;
|
||||
|
||||
extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
|
||||
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
||||
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";
|
|
@ -1,476 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
|
||||
using std::string;
|
||||
using std::deque;
|
||||
using std::cout;
|
||||
|
||||
bool do_mkdir(const char *path) { // from http://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux
|
||||
struct stat statbuf;
|
||||
if (stat(path, &statbuf) != 0) {
|
||||
/* Directory does not exist. EEXIST for race condition */
|
||||
if (mkdir(path, S_IRWXU) != 0 && errno != EEXIST) return false;
|
||||
} else if (!S_ISDIR(statbuf.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _debug = false;
|
||||
string updaterDir;
|
||||
string updaterName;
|
||||
string workDir;
|
||||
string exeName;
|
||||
string exePath;
|
||||
|
||||
FILE *_logFile = 0;
|
||||
void openLog() {
|
||||
if (!_debug || _logFile) return;
|
||||
|
||||
if (!do_mkdir((workDir + "DebugLogs").c_str())) {
|
||||
return;
|
||||
}
|
||||
|
||||
time_t timer;
|
||||
|
||||
time(&timer);
|
||||
struct tm *t = localtime(&timer);
|
||||
|
||||
static const int maxFileLen = 65536;
|
||||
char logName[maxFileLen];
|
||||
sprintf(logName, "%sDebugLogs/%04d%02d%02d_%02d%02d%02d_upd.txt", workDir.c_str(),
|
||||
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
_logFile = fopen(logName, "w");
|
||||
}
|
||||
|
||||
void closeLog() {
|
||||
if (!_logFile) return;
|
||||
|
||||
fclose(_logFile);
|
||||
_logFile = 0;
|
||||
}
|
||||
|
||||
void writeLog(const char *format, ...) {
|
||||
if (!_logFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(_logFile, format, args);
|
||||
fprintf(_logFile, "\n");
|
||||
fflush(_logFile);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
bool copyFile(const char *from, const char *to) {
|
||||
FILE *ffrom = fopen(from, "rb"), *fto = fopen(to, "wb");
|
||||
if (!ffrom) {
|
||||
if (fto) fclose(fto);
|
||||
return false;
|
||||
}
|
||||
if (!fto) {
|
||||
fclose(ffrom);
|
||||
return false;
|
||||
}
|
||||
static const int BufSize = 65536;
|
||||
char buf[BufSize];
|
||||
while (size_t size = fread(buf, 1, BufSize, ffrom)) {
|
||||
fwrite(buf, 1, size, fto);
|
||||
}
|
||||
|
||||
struct stat fst; // from http://stackoverflow.com/questions/5486774/keeping-fileowner-and-permissions-after-copying-file-in-c
|
||||
//let's say this wont fail since you already worked OK on that fp
|
||||
if (fstat(fileno(ffrom), &fst) != 0) {
|
||||
fclose(ffrom);
|
||||
fclose(fto);
|
||||
return false;
|
||||
}
|
||||
//update to the same uid/gid
|
||||
if (fchown(fileno(fto), fst.st_uid, fst.st_gid) != 0) {
|
||||
fclose(ffrom);
|
||||
fclose(fto);
|
||||
return false;
|
||||
}
|
||||
//update the permissions
|
||||
if (fchmod(fileno(fto), fst.st_mode) != 0) {
|
||||
fclose(ffrom);
|
||||
fclose(fto);
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(ffrom);
|
||||
fclose(fto);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool remove_directory(const string &path) { // from http://stackoverflow.com/questions/2256945/removing-a-non-empty-directory-programmatically-in-c-or-c
|
||||
DIR *d = opendir(path.c_str());
|
||||
writeLog("Removing dir '%s'", path.c_str());
|
||||
|
||||
if (!d) {
|
||||
writeLog("Could not open dir '%s'", path.c_str());
|
||||
return (errno == ENOENT);
|
||||
}
|
||||
|
||||
while (struct dirent *p = readdir(d)) {
|
||||
/* Skip the names "." and ".." as we don't want to recurse on them. */
|
||||
if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) continue;
|
||||
|
||||
string fname = path + '/' + p->d_name;
|
||||
struct stat statbuf;
|
||||
writeLog("Trying to get stat() for '%s'", fname.c_str());
|
||||
if (!stat(fname.c_str(), &statbuf)) {
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
if (!remove_directory(fname.c_str())) {
|
||||
closedir(d);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
writeLog("Unlinking file '%s'", fname.c_str());
|
||||
if (unlink(fname.c_str())) {
|
||||
writeLog("Failed to unlink '%s'", fname.c_str());
|
||||
closedir(d);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeLog("Failed to call stat() on '%s'", fname.c_str());
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
writeLog("Finally removing dir '%s'", path.c_str());
|
||||
return !rmdir(path.c_str());
|
||||
}
|
||||
|
||||
bool mkpath(const char *path) {
|
||||
int status = 0, pathsize = strlen(path) + 1;
|
||||
char *copypath = new char[pathsize];
|
||||
memcpy(copypath, path, pathsize);
|
||||
|
||||
char *pp = copypath, *sp;
|
||||
while (status == 0 && (sp = strchr(pp, '/')) != 0) {
|
||||
if (sp != pp) {
|
||||
/* Neither root nor double slash in path */
|
||||
*sp = '\0';
|
||||
if (!do_mkdir(copypath)) {
|
||||
delete[] copypath;
|
||||
return false;
|
||||
}
|
||||
*sp = '/';
|
||||
}
|
||||
pp = sp + 1;
|
||||
}
|
||||
delete[] copypath;
|
||||
return do_mkdir(path);
|
||||
}
|
||||
|
||||
bool equal(string a, string b) {
|
||||
std::transform(a.begin(), a.end(), a.begin(), ::tolower);
|
||||
std::transform(b.begin(), b.end(), b.begin(), ::tolower);
|
||||
return a == b;
|
||||
}
|
||||
|
||||
void delFolder() {
|
||||
string delPathOld = workDir + "tupdates/ready", delPath = workDir + "tupdates/temp", delFolder = workDir + "tupdates";
|
||||
writeLog("Fully clearing old path '%s'..", delPathOld.c_str());
|
||||
if (!remove_directory(delPathOld)) {
|
||||
writeLog("Failed to clear old path! :( New path was used?..");
|
||||
}
|
||||
writeLog("Fully clearing path '%s'..", delPath.c_str());
|
||||
if (!remove_directory(delPath)) {
|
||||
writeLog("Error: failed to clear path! :(");
|
||||
}
|
||||
rmdir(delFolder.c_str());
|
||||
}
|
||||
|
||||
bool update() {
|
||||
writeLog("Update started..");
|
||||
|
||||
string updDir = workDir + "tupdates/temp", readyFilePath = workDir + "tupdates/temp/ready", tdataDir = workDir + "tupdates/temp/tdata";
|
||||
{
|
||||
FILE *readyFile = fopen(readyFilePath.c_str(), "rb");
|
||||
if (readyFile) {
|
||||
fclose(readyFile);
|
||||
writeLog("Ready file found! Using new path '%s'..", updDir.c_str());
|
||||
} else {
|
||||
updDir = workDir + "tupdates/ready"; // old
|
||||
tdataDir = workDir + "tupdates/ready/tdata";
|
||||
writeLog("Ready file not found! Using old path '%s'..", updDir.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
deque<string> dirs;
|
||||
dirs.push_back(updDir);
|
||||
|
||||
deque<string> from, to, forcedirs;
|
||||
|
||||
do {
|
||||
string dir = dirs.front();
|
||||
dirs.pop_front();
|
||||
|
||||
string toDir = exePath;
|
||||
if (dir.size() > updDir.size() + 1) {
|
||||
toDir += (dir.substr(updDir.size() + 1) + '/');
|
||||
forcedirs.push_back(toDir);
|
||||
writeLog("Parsing dir '%s' in update tree..", toDir.c_str());
|
||||
}
|
||||
|
||||
DIR *d = opendir(dir.c_str());
|
||||
if (!d) {
|
||||
writeLog("Failed to open dir %s", dir.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
while (struct dirent *p = readdir(d)) {
|
||||
/* Skip the names "." and ".." as we don't want to recurse on them. */
|
||||
if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) continue;
|
||||
|
||||
string fname = dir + '/' + p->d_name;
|
||||
struct stat statbuf;
|
||||
if (fname.substr(0, tdataDir.size()) == tdataDir && (fname.size() <= tdataDir.size() || fname.at(tdataDir.size()) == '/')) {
|
||||
writeLog("Skipping 'tdata' path '%s'", fname.c_str());
|
||||
} else if (!stat(fname.c_str(), &statbuf)) {
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
dirs.push_back(fname);
|
||||
writeLog("Added dir '%s' in update tree..", fname.c_str());
|
||||
} else {
|
||||
string tofname = exePath + fname.substr(updDir.size() + 1);
|
||||
if (equal(tofname, updaterName)) { // bad update - has Updater - delete all dir
|
||||
writeLog("Error: bad update, has Updater! '%s' equal '%s'", tofname.c_str(), updaterName.c_str());
|
||||
delFolder();
|
||||
return false;
|
||||
} else if (equal(tofname, exePath + "Telegram") && exeName != "Telegram") {
|
||||
string fullBinaryPath = exePath + exeName;
|
||||
writeLog("Target binary found: '%s', changing to '%s'", tofname.c_str(), fullBinaryPath.c_str());
|
||||
tofname = fullBinaryPath;
|
||||
}
|
||||
if (fname == readyFilePath) {
|
||||
writeLog("Skipped ready file '%s'", fname.c_str());
|
||||
} else {
|
||||
from.push_back(fname);
|
||||
to.push_back(tofname);
|
||||
writeLog("Added file '%s' to be copied to '%s'", fname.c_str(), tofname.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeLog("Could not get stat() for file %s", fname.c_str());
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
} while (!dirs.empty());
|
||||
|
||||
for (size_t i = 0; i < forcedirs.size(); ++i) {
|
||||
string forcedir = forcedirs[i];
|
||||
writeLog("Forcing dir '%s'..", forcedir.c_str());
|
||||
if (!forcedir.empty() && !mkpath(forcedir.c_str())) {
|
||||
writeLog("Error: failed to create dir '%s'..", forcedir.c_str());
|
||||
delFolder();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < from.size(); ++i) {
|
||||
string fname = from[i], tofname = to[i];
|
||||
writeLog("Copying file '%s' to '%s'..", fname.c_str(), tofname.c_str());
|
||||
int copyTries = 0, triesLimit = 30;
|
||||
do {
|
||||
if (!copyFile(fname.c_str(), tofname.c_str())) {
|
||||
++copyTries;
|
||||
usleep(100000);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (copyTries < triesLimit);
|
||||
if (copyTries == triesLimit) {
|
||||
writeLog("Error: failed to copy, asking to retry..");
|
||||
delFolder();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
writeLog("Update succeed! Clearing folder..");
|
||||
delFolder();
|
||||
return true;
|
||||
}
|
||||
|
||||
string CurrentExecutablePath(int argc, char *argv[]) {
|
||||
constexpr auto kMaxPath = 1024;
|
||||
char result[kMaxPath] = { 0 };
|
||||
auto count = readlink("/proc/self/exe", result, kMaxPath);
|
||||
if (count > 0) {
|
||||
return string(result);
|
||||
}
|
||||
|
||||
// Fallback to the first command line argument.
|
||||
return argc ? string(argv[0]) : string();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false, testmode = false;
|
||||
|
||||
char *key = 0, *crashreport = 0;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (equal(argv[i], "-noupdate")) {
|
||||
needupdate = false;
|
||||
} else if (equal(argv[i], "-autostart")) {
|
||||
autostart = true;
|
||||
} else if (equal(argv[i], "-debug")) {
|
||||
debug = _debug = true;
|
||||
} else if (equal(argv[i], "-startintray")) {
|
||||
startintray = true;
|
||||
} else if (equal(argv[i], "-testmode")) {
|
||||
testmode = true;
|
||||
} else if (equal(argv[i], "-tosettings")) {
|
||||
tosettings = true;
|
||||
} else if (equal(argv[i], "-key") && ++i < argc) {
|
||||
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];
|
||||
} else if (equal(argv[i], "-exename") && ++i < argc) {
|
||||
exeName = argv[i];
|
||||
} else if (equal(argv[i], "-exepath") && ++i < argc) {
|
||||
exePath = argv[i];
|
||||
}
|
||||
}
|
||||
if (exeName.empty() || exeName.find('/') != string::npos) {
|
||||
exeName = "Telegram";
|
||||
}
|
||||
openLog();
|
||||
|
||||
writeLog("Updater started..");
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
writeLog("Argument: '%s'", argv[i]);
|
||||
}
|
||||
if (needupdate) writeLog("Need to update!");
|
||||
if (autostart) writeLog("From autostart!");
|
||||
|
||||
updaterName = CurrentExecutablePath(argc, argv);
|
||||
writeLog("Updater binary full path is: %s", updaterName.c_str());
|
||||
if (exePath.empty()) {
|
||||
writeLog("Executable path is not specified :(");
|
||||
} else {
|
||||
writeLog("Executable path: %s", exePath.c_str());
|
||||
}
|
||||
if (updaterName.size() >= 7) {
|
||||
if (equal(updaterName.substr(updaterName.size() - 7), "Updater")) {
|
||||
updaterDir = updaterName.substr(0, updaterName.size() - 7);
|
||||
writeLog("Updater binary dir is: %s", updaterDir.c_str());
|
||||
if (exePath.empty()) {
|
||||
exePath = updaterDir;
|
||||
writeLog("Using updater binary dir.", exePath.c_str());
|
||||
}
|
||||
if (needupdate) {
|
||||
if (workDir.empty()) { // old app launched, update prepared in tupdates/ready (not in tupdates/temp)
|
||||
writeLog("No workdir, trying to figure it out");
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
if (pw && pw->pw_dir && strlen(pw->pw_dir)) {
|
||||
string tryDir = pw->pw_dir + string("/.TelegramDesktop/");
|
||||
struct stat statbuf;
|
||||
writeLog("Trying to use '%s' as workDir, getting stat() for tupdates/ready", tryDir.c_str());
|
||||
if (!stat((tryDir + "tupdates/ready").c_str(), &statbuf)) {
|
||||
writeLog("Stat got");
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
writeLog("It is directory, using home work dir");
|
||||
workDir = tryDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (workDir.empty()) {
|
||||
workDir = exePath;
|
||||
|
||||
struct stat statbuf;
|
||||
writeLog("Trying to use current as workDir, getting stat() for tupdates/ready");
|
||||
if (!stat("tupdates/ready", &statbuf)) {
|
||||
writeLog("Stat got");
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
writeLog("It is directory, using current dir");
|
||||
workDir = string();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeLog("Passed workpath is '%s'", workDir.c_str());
|
||||
}
|
||||
update();
|
||||
}
|
||||
} else {
|
||||
writeLog("Error: bad exe name!");
|
||||
}
|
||||
} else {
|
||||
writeLog("Error: short exe name!");
|
||||
}
|
||||
|
||||
static const int MaxLen = 65536, MaxArgsCount = 128;
|
||||
|
||||
char path[MaxLen] = {0};
|
||||
string fullBinaryPath = exePath + exeName;
|
||||
strcpy(path, fullBinaryPath.c_str());
|
||||
|
||||
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;
|
||||
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 quitting..");
|
||||
closeLog();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,272 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 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;
|
||||
#else
|
||||
BOOL _debug = NO;
|
||||
#endif
|
||||
|
||||
NSFileHandle *_logFile = nil;
|
||||
void openLog() {
|
||||
if (!_debug || _logFile) return;
|
||||
NSString *logDir = [workDir stringByAppendingString:@"DebugLogs"];
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:logDir withIntermediateDirectories:YES attributes:nil error:nil]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSDateFormatter *fmt = [[NSDateFormatter alloc] initWithDateFormat:@"DebugLogs/%Y%m%d_%H%M%S_upd.txt" allowNaturalLanguage:NO];
|
||||
NSString *logPath = [workDir stringByAppendingString:[fmt stringFromDate:[NSDate date]]];
|
||||
[[NSFileManager defaultManager] createFileAtPath:logPath contents:nil attributes:nil];
|
||||
_logFile = [NSFileHandle fileHandleForWritingAtPath:logPath];
|
||||
}
|
||||
|
||||
void closeLog() {
|
||||
if (!_logFile) return;
|
||||
|
||||
[_logFile closeFile];
|
||||
}
|
||||
|
||||
void writeLog(NSString *msg) {
|
||||
if (!_logFile) return;
|
||||
|
||||
[_logFile writeData:[[msg stringByAppendingString:@"\n"] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[_logFile synchronizeFile];
|
||||
}
|
||||
|
||||
void delFolder() {
|
||||
writeLog([@"Fully clearing old path: " stringByAppendingString:[workDir stringByAppendingString:@"tupdates/ready"]]);
|
||||
if (![[NSFileManager defaultManager] removeItemAtPath:[workDir stringByAppendingString:@"tupdates/ready"] error:nil]) {
|
||||
writeLog(@"Failed to clear old path! :( New path was used?..");
|
||||
}
|
||||
writeLog([@"Fully clearing new path: " stringByAppendingString:[workDir stringByAppendingString:@"tupdates/temp"]]);
|
||||
if (![[NSFileManager defaultManager] removeItemAtPath:[workDir stringByAppendingString:@"tupdates/temp"] error:nil]) {
|
||||
writeLog(@"Error: failed to clear new path! :(");
|
||||
}
|
||||
rmdir([[workDir stringByAppendingString:@"tupdates"] fileSystemRepresentation]);
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
NSString *path = [[NSBundle mainBundle] bundlePath];
|
||||
if (!path) {
|
||||
return -1;
|
||||
}
|
||||
NSRange range = [path rangeOfString:@".app/" options:NSBackwardsSearch];
|
||||
if (range.location == NSNotFound) {
|
||||
return -1;
|
||||
}
|
||||
path = [path substringToIndex:range.location > 0 ? range.location : 0];
|
||||
|
||||
range = [path rangeOfString:@"/" options:NSBackwardsSearch];
|
||||
NSString *appRealName = (range.location == NSNotFound) ? path : [path substringFromIndex:range.location + 1];
|
||||
appRealName = [[NSArray arrayWithObjects:appRealName, @".app", nil] componentsJoinedByString:@""];
|
||||
appDir = (range.location == NSNotFound) ? @"" : [path substringToIndex:range.location + 1];
|
||||
NSString *appDirFull = [appDir stringByAppendingString:appRealName];
|
||||
|
||||
openLog();
|
||||
pid_t procId = 0;
|
||||
BOOL update = YES, toSettings = NO, autoStart = NO, startInTray = NO, testMode = NO;
|
||||
NSString *key = nil;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if ([@"-workpath" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
if (++i < argc) {
|
||||
workDir = [NSString stringWithUTF8String:argv[i]];
|
||||
}
|
||||
} else if ([@"-procid" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
if (++i < argc) {
|
||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
||||
[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]]]) {
|
||||
toSettings = YES;
|
||||
} else if ([@"-autostart" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
autoStart = YES;
|
||||
} else if ([@"-debug" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
_debug = YES;
|
||||
} else if ([@"-startintray" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
startInTray = YES;
|
||||
} else if ([@"-testmode" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
testMode = YES;
|
||||
} else if ([@"-key" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
|
||||
if (++i < argc) key = [NSString stringWithUTF8String:argv[i]];
|
||||
}
|
||||
}
|
||||
if (!workDir) workDir = appDir;
|
||||
openLog();
|
||||
NSMutableArray *argsArr = [[NSMutableArray alloc] initWithCapacity:argc];
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
[argsArr addObject:[NSString stringWithUTF8String:argv[i]]];
|
||||
}
|
||||
writeLog([[NSArray arrayWithObjects:@"Arguments: '", [argsArr componentsJoinedByString:@"' '"], @"'..", nil] componentsJoinedByString:@""]);
|
||||
if (key) writeLog([@"Key: " stringByAppendingString:key]);
|
||||
if (toSettings) writeLog(@"To Settings!");
|
||||
|
||||
if (procId) {
|
||||
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:procId];
|
||||
for (int i = 0; i < 5 && app != nil && ![app isTerminated]; ++i) {
|
||||
usleep(200000);
|
||||
app = [NSRunningApplication runningApplicationWithProcessIdentifier:procId];
|
||||
}
|
||||
if (app) [app forceTerminate];
|
||||
app = [NSRunningApplication runningApplicationWithProcessIdentifier:procId];
|
||||
for (int i = 0; i < 5 && app != nil && ![app isTerminated]; ++i) {
|
||||
usleep(200000);
|
||||
app = [NSRunningApplication runningApplicationWithProcessIdentifier:procId];
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *readyFilePath = [workDir stringByAppendingString:@"tupdates/temp/ready"];
|
||||
NSString *srcDir = [workDir stringByAppendingString:@"tupdates/temp/"], *srcEnum = [workDir stringByAppendingString:@"tupdates/temp"];
|
||||
if ([fileManager fileExistsAtPath:readyFilePath]) {
|
||||
writeLog([@"Ready file found! Using new path: " stringByAppendingString: srcEnum]);
|
||||
} else {
|
||||
srcDir = [workDir stringByAppendingString:@"tupdates/ready/"]; // old
|
||||
srcEnum = [workDir stringByAppendingString:@"tupdates/ready"];
|
||||
writeLog([@"Ready file not found! Using old path: " stringByAppendingString: srcEnum]);
|
||||
}
|
||||
|
||||
writeLog([@"Starting update files iteration, path: " stringByAppendingString: srcEnum]);
|
||||
|
||||
// Take the Updater (this currently running binary) from the place where it was placed by Telegram
|
||||
// and copy it to the folder with the new version of the app (ready),
|
||||
// so it won't be deleted when we will clear the "Telegram.app/Contents" folder.
|
||||
NSString *oldVersionUpdaterPath = [appDirFull stringByAppendingString: @"/Contents/Frameworks/Updater" ];
|
||||
NSString *newVersionUpdaterPath = [srcEnum stringByAppendingString:[[NSArray arrayWithObjects:@"/", appName, @"/Contents/Frameworks/Updater", nil] componentsJoinedByString:@""]];
|
||||
writeLog([[NSArray arrayWithObjects: @"Copying Updater from old path ", oldVersionUpdaterPath, @" to new path ", newVersionUpdaterPath, nil] componentsJoinedByString:@""]);
|
||||
if (![fileManager fileExistsAtPath:newVersionUpdaterPath]) {
|
||||
if (![fileManager copyItemAtPath:oldVersionUpdaterPath toPath:newVersionUpdaterPath error:nil]) {
|
||||
writeLog([[NSArray arrayWithObjects: @"Failed to copy file from ", oldVersionUpdaterPath, @" to ", newVersionUpdaterPath, nil] componentsJoinedByString:@""]);
|
||||
delFolder();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NSString *contentsPath = [appDirFull stringByAppendingString: @"/Contents"];
|
||||
writeLog([[NSArray arrayWithObjects: @"Clearing dir ", contentsPath, nil] componentsJoinedByString:@""]);
|
||||
if (![fileManager removeItemAtPath:contentsPath error:nil]) {
|
||||
writeLog([@"Failed to clear path for directory " stringByAppendingString:contentsPath]);
|
||||
delFolder();
|
||||
return -1;
|
||||
}
|
||||
|
||||
NSArray *keys = [NSArray arrayWithObject:NSURLIsDirectoryKey];
|
||||
NSDirectoryEnumerator *enumerator = [fileManager
|
||||
enumeratorAtURL:[NSURL fileURLWithPath:srcEnum]
|
||||
includingPropertiesForKeys:keys
|
||||
options:0
|
||||
errorHandler:^(NSURL *url, NSError *error) {
|
||||
writeLog([[[@"Error in enumerating " stringByAppendingString:[url absoluteString]] stringByAppendingString: @" error is: "] stringByAppendingString: [error description]]);
|
||||
return NO;
|
||||
}];
|
||||
for (NSURL *url in enumerator) {
|
||||
NSString *srcPath = [url path];
|
||||
writeLog([@"Handling file " stringByAppendingString:srcPath]);
|
||||
NSRange r = [srcPath rangeOfString:srcDir];
|
||||
if (r.location != 0) {
|
||||
writeLog([@"Bad file found, no base path " stringByAppendingString:srcPath]);
|
||||
delFolder();
|
||||
break;
|
||||
}
|
||||
NSString *pathPart = [srcPath substringFromIndex:r.length];
|
||||
r = [pathPart rangeOfString:appName];
|
||||
if (r.location != 0) {
|
||||
writeLog([@"Skipping not app file " stringByAppendingString:srcPath]);
|
||||
continue;
|
||||
}
|
||||
NSString *dstPath = [appDirFull stringByAppendingString:[pathPart substringFromIndex:r.length]];
|
||||
NSError *error;
|
||||
NSNumber *isDirectory = nil;
|
||||
if (![url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error]) {
|
||||
writeLog([@"Failed to get IsDirectory for file " stringByAppendingString:[url path]]);
|
||||
delFolder();
|
||||
break;
|
||||
}
|
||||
if ([isDirectory boolValue]) {
|
||||
writeLog([[NSArray arrayWithObjects: @"Copying dir ", srcPath, @" to ", dstPath, nil] componentsJoinedByString:@""]);
|
||||
if (![fileManager createDirectoryAtPath:dstPath withIntermediateDirectories:YES attributes:nil error:nil]) {
|
||||
writeLog([@"Failed to force path for directory " stringByAppendingString:dstPath]);
|
||||
delFolder();
|
||||
break;
|
||||
}
|
||||
} else if ([srcPath isEqualToString:readyFilePath]) {
|
||||
writeLog([[NSArray arrayWithObjects: @"Skipping ready file ", srcPath, nil] componentsJoinedByString:@""]);
|
||||
} else if ([fileManager fileExistsAtPath:dstPath]) {
|
||||
if (![[NSData dataWithContentsOfFile:srcPath] writeToFile:dstPath atomically:YES]) {
|
||||
writeLog([@"Failed to edit file " stringByAppendingString:dstPath]);
|
||||
delFolder();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (![fileManager copyItemAtPath:srcPath toPath:dstPath error:nil]) {
|
||||
writeLog([@"Failed to copy file to " stringByAppendingString:dstPath]);
|
||||
delFolder();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
delFolder();
|
||||
}
|
||||
|
||||
NSString *appPath = [[NSArray arrayWithObjects:appDir, appRealName, nil] componentsJoinedByString:@""];
|
||||
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;
|
||||
NSRunningApplication *result = [[NSWorkspace sharedWorkspace]
|
||||
launchApplicationAtURL:[NSURL fileURLWithPath:appPath]
|
||||
options:NSWorkspaceLaunchDefault
|
||||
configuration:[NSDictionary
|
||||
dictionaryWithObject:args
|
||||
forKey:NSWorkspaceLaunchConfigurationArguments]
|
||||
error:&error];
|
||||
if (!result) {
|
||||
writeLog([@"Could not run application, error: " stringByAppendingString:error ? [error localizedDescription] : @"(nil)"]);
|
||||
}
|
||||
closeLog();
|
||||
return result ? 0 : -1;
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ void ApiWrap::addLocalChangelogs(int oldAppVersion) {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId) {
|
||||
void ApiWrap::applyUpdates(const MTPUpdates &updates, uint64_t sentMessageRandomId) {
|
||||
App::main()->feedUpdates(updates, sentMessageRandomId);
|
||||
}
|
||||
|
||||
|
@ -796,7 +796,7 @@ void ApiWrap::unblockParticipant(PeerData *peer, UserData *user) {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::scheduleStickerSetRequest(uint64 setId, uint64 access) {
|
||||
void ApiWrap::scheduleStickerSetRequest(uint64_t setId, uint64_t access) {
|
||||
if (!_stickerSetRequests.contains(setId)) {
|
||||
_stickerSetRequests.insert(setId, qMakePair(access, 0));
|
||||
}
|
||||
|
@ -1274,7 +1274,7 @@ PeerData *ApiWrap::notifySettingReceived(MTPInputNotifyPeer notifyPeer, const MT
|
|||
return requestedPeer;
|
||||
}
|
||||
|
||||
void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) {
|
||||
void ApiWrap::gotStickerSet(uint64_t setId, const MTPmessages_StickerSet &result) {
|
||||
_stickerSetRequests.remove(setId);
|
||||
Stickers::FeedSetFull(result);
|
||||
}
|
||||
|
@ -1302,13 +1302,13 @@ void ApiWrap::clearWebPageRequests() {
|
|||
|
||||
void ApiWrap::resolveWebPages() {
|
||||
auto ids = QVector<MTPint>(); // temp_req_id = -1
|
||||
using IndexAndMessageIds = QPair<int32, QVector<MTPint>>;
|
||||
using IndexAndMessageIds = QPair<int32_t, QVector<MTPint>>;
|
||||
using MessageIdsByChannel = QMap<ChannelData*, IndexAndMessageIds>;
|
||||
MessageIdsByChannel idsByChannel; // temp_req_id = -index - 2
|
||||
|
||||
auto &items = App::webPageItems();
|
||||
ids.reserve(_webPagesPending.size());
|
||||
int32 t = unixtime(), m = INT_MAX;
|
||||
int32_t t = unixtime(), m = INT_MAX;
|
||||
for (auto i = _webPagesPending.begin(); i != _webPagesPending.cend(); ++i) {
|
||||
if (i.value() > 0) continue;
|
||||
if (i.key()->pendingTill <= t) {
|
||||
|
@ -1405,13 +1405,13 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs
|
|||
}
|
||||
|
||||
if (!v) return;
|
||||
QMap<uint64, int32> msgsIds; // copied from feedMsgs
|
||||
for (int32 i = 0, l = v->size(); i < l; ++i) {
|
||||
QMap<uint64_t, int32_t> msgsIds; // copied from feedMsgs
|
||||
for (int32_t i = 0, l = v->size(); i < l; ++i) {
|
||||
const auto &msg(v->at(i));
|
||||
switch (msg.type()) {
|
||||
case mtpc_message: msgsIds.insert((uint64(uint32(msg.c_message().vid.v)) << 32) | uint64(i), i); break;
|
||||
case mtpc_messageEmpty: msgsIds.insert((uint64(uint32(msg.c_messageEmpty().vid.v)) << 32) | uint64(i), i); break;
|
||||
case mtpc_messageService: msgsIds.insert((uint64(uint32(msg.c_messageService().vid.v)) << 32) | uint64(i), i); break;
|
||||
case mtpc_message: msgsIds.insert((uint64_t(uint32_t(msg.c_message().vid.v)) << 32) | uint64_t(i), i); break;
|
||||
case mtpc_messageEmpty: msgsIds.insert((uint64_t(uint32_t(msg.c_messageEmpty().vid.v)) << 32) | uint64_t(i), i); break;
|
||||
case mtpc_messageService: msgsIds.insert((uint64_t(uint32_t(msg.c_messageService().vid.v)) << 32) | uint64_t(i), i); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include "base/timer.h"
|
||||
#include <QtCore/QObject>
|
||||
#include "mtproto/rpc_sender.h"
|
||||
#include "mtproto/core_types.h"
|
||||
#include "core/single_timer.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "base/flat_map.h"
|
||||
|
@ -45,7 +48,7 @@ public:
|
|||
ApiWrap(not_null<AuthSession*> session);
|
||||
|
||||
void start();
|
||||
void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0);
|
||||
void applyUpdates(const MTPUpdates &updates, uint64_t sentMessageRandomId = 0);
|
||||
|
||||
using RequestMessageDataCallback = base::lambda<void(ChannelData*, MsgId)>;
|
||||
void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback);
|
||||
|
@ -68,7 +71,7 @@ public:
|
|||
void clearWebPageRequest(WebPageData *page);
|
||||
void clearWebPageRequests();
|
||||
|
||||
void scheduleStickerSetRequest(uint64 setId, uint64 access);
|
||||
void scheduleStickerSetRequest(uint64_t setId, uint64_t access);
|
||||
void requestStickerSets();
|
||||
void saveStickerSets(const Stickers::Order &localOrder, const Stickers::Order &localRemoved);
|
||||
void updateStickers();
|
||||
|
@ -136,7 +139,7 @@ private:
|
|||
void lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelParticipants &result, mtpRequestId req);
|
||||
void resolveWebPages();
|
||||
void gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
|
||||
void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result);
|
||||
void gotStickerSet(uint64_t setId, const MTPmessages_StickerSet &result);
|
||||
|
||||
PeerData *notifySettingReceived(MTPInputNotifyPeer peer, const MTPPeerNotifySettings &settings);
|
||||
|
||||
|
@ -177,7 +180,7 @@ private:
|
|||
QMap<WebPageData*, mtpRequestId> _webPagesPending;
|
||||
base::Timer _webPagesTimer;
|
||||
|
||||
QMap<uint64, QPair<uint64, mtpRequestId> > _stickerSetRequests;
|
||||
QMap<uint64_t, QPair<uint64_t, mtpRequestId> > _stickerSetRequests;
|
||||
|
||||
QMap<ChannelData*, mtpRequestId> _channelAmInRequests;
|
||||
QMap<UserData*, mtpRequestId> _blockRequests;
|
||||
|
|
|
@ -91,10 +91,10 @@ namespace {
|
|||
using ChannelMsgsData = QMap<ChannelId, MsgsData>;
|
||||
ChannelMsgsData channelMsgsData;
|
||||
|
||||
using RandomData = QMap<uint64, FullMsgId>;
|
||||
using RandomData = QMap<uint64_t, FullMsgId>;
|
||||
RandomData randomData;
|
||||
|
||||
using SentData = QMap<uint64, QPair<PeerId, QString>>;
|
||||
using SentData = QMap<uint64_t, QPair<PeerId, QString>>;
|
||||
SentData sentData;
|
||||
|
||||
HistoryItem *hoveredItem = nullptr,
|
||||
|
@ -111,7 +111,7 @@ namespace {
|
|||
QPixmap p[4];
|
||||
};
|
||||
QVector<CornersPixmaps> corners;
|
||||
using CornersMap = QMap<uint32, CornersPixmaps>;
|
||||
using CornersMap = QMap<uint32_t, CornersPixmaps>;
|
||||
CornersMap cornersMap;
|
||||
QImage cornersMaskLarge[4], cornersMaskSmall[4];
|
||||
|
||||
|
@ -119,7 +119,7 @@ namespace {
|
|||
EmojiImagesMap MainEmojiMap;
|
||||
QMap<int, EmojiImagesMap> OtherEmojiMap;
|
||||
|
||||
int32 serviceImageCacheSize = 0;
|
||||
int32_t serviceImageCacheSize = 0;
|
||||
|
||||
using LastPhotosList = QLinkedList<PhotoData*>;
|
||||
LastPhotosList lastPhotos;
|
||||
|
@ -145,8 +145,8 @@ namespace App {
|
|||
QString result;
|
||||
result.reserve(number.size() + groups.size() + 1);
|
||||
result.append('+');
|
||||
int32 sum = 0;
|
||||
for (int32 i = 0, l = groups.size(); i < l; ++i) {
|
||||
int32_t sum = 0;
|
||||
for (int32_t i = 0, l = groups.size(); i < l; ++i) {
|
||||
result.append(number.midRef(sum, groups.at(i)));
|
||||
sum += groups.at(i);
|
||||
if (sum < number.size()) result.append(' ');
|
||||
|
@ -227,17 +227,17 @@ namespace {
|
|||
|
||||
case -2: {
|
||||
QDate yesterday(date(now).date());
|
||||
return int32(QDateTime(yesterday.addDays(-3)).toTime_t()) + (unixtime() - myunixtime());
|
||||
return int32_t(QDateTime(yesterday.addDays(-3)).toTime_t()) + (unixtime() - myunixtime());
|
||||
} break;
|
||||
|
||||
case -3: {
|
||||
QDate weekago(date(now).date());
|
||||
return int32(QDateTime(weekago.addDays(-7)).toTime_t()) + (unixtime() - myunixtime());
|
||||
return int32_t(QDateTime(weekago.addDays(-7)).toTime_t()) + (unixtime() - myunixtime());
|
||||
} break;
|
||||
|
||||
case -4: {
|
||||
QDate monthago(date(now).date());
|
||||
return int32(QDateTime(monthago.addDays(-30)).toTime_t()) + (unixtime() - myunixtime());
|
||||
return int32_t(QDateTime(monthago.addDays(-30)).toTime_t()) + (unixtime() - myunixtime());
|
||||
} break;
|
||||
}
|
||||
return -online;
|
||||
|
@ -245,14 +245,14 @@ namespace {
|
|||
return online;
|
||||
}
|
||||
|
||||
int32 onlineWillChangeIn(UserData *user, TimeId now) {
|
||||
int32_t onlineWillChangeIn(UserData *user, TimeId now) {
|
||||
if (isServiceUser(user->id) || user->botInfo) {
|
||||
return 86400;
|
||||
}
|
||||
return onlineWillChangeIn(user->onlineTill, now);
|
||||
}
|
||||
|
||||
int32 onlineWillChangeIn(TimeId online, TimeId now) {
|
||||
int32_t onlineWillChangeIn(TimeId online, TimeId now) {
|
||||
if (online <= 0) {
|
||||
if (-online > now) return -online - now;
|
||||
return 86400;
|
||||
|
@ -260,11 +260,11 @@ namespace {
|
|||
if (online > now) {
|
||||
return online - now;
|
||||
}
|
||||
int32 minutes = (now - online) / 60;
|
||||
int32_t minutes = (now - online) / 60;
|
||||
if (minutes < 60) {
|
||||
return (minutes + 1) * 60 - (now - online);
|
||||
}
|
||||
int32 hours = (now - online) / 3600;
|
||||
int32_t hours = (now - online) / 3600;
|
||||
if (hours < 12) {
|
||||
return (hours + 1) * 3600 - (now - online);
|
||||
}
|
||||
|
@ -307,13 +307,13 @@ namespace {
|
|||
}
|
||||
return lng_status_lastseen_date_time(lt_date, dOnline.date().toString(qsl("dd.MM.yy")), lt_time, dOnline.time().toString(cTimeFormat()));
|
||||
}
|
||||
int32 minutes = (now - online) / 60;
|
||||
int32_t minutes = (now - online) / 60;
|
||||
if (!minutes) {
|
||||
return lang(lng_status_lastseen_now);
|
||||
} else if (minutes < 60) {
|
||||
return lng_status_lastseen_minutes(lt_count, minutes);
|
||||
}
|
||||
int32 hours = (now - online) / 3600;
|
||||
int32_t hours = (now - online) / 3600;
|
||||
if (hours < 12) {
|
||||
return lng_status_lastseen_hours(lt_count, hours);
|
||||
}
|
||||
|
@ -790,12 +790,12 @@ namespace {
|
|||
chat->version = d.vversion.v;
|
||||
auto &v = d.vparticipants.v;
|
||||
chat->count = v.size();
|
||||
int32 pversion = chat->participants.isEmpty() ? 1 : (chat->participants.begin().value() + 1);
|
||||
int32_t pversion = chat->participants.isEmpty() ? 1 : (chat->participants.begin().value() + 1);
|
||||
chat->invitedByMe.clear();
|
||||
chat->admins.clear();
|
||||
chat->flags &= ~MTPDchat::Flag::f_admin;
|
||||
for (auto i = v.cbegin(), e = v.cend(); i != e; ++i) {
|
||||
int32 uid = 0, inviter = 0;
|
||||
int32_t uid = 0, inviter = 0;
|
||||
switch (i->type()) {
|
||||
case mtpc_chatParticipantCreator: {
|
||||
const auto &p(i->c_chatParticipantCreator());
|
||||
|
@ -835,7 +835,7 @@ namespace {
|
|||
if (!chat->participants.isEmpty()) {
|
||||
History *h = App::historyLoaded(chat->id);
|
||||
bool found = !h || !h->lastKeyboardFrom;
|
||||
int32 botStatus = -1;
|
||||
int32_t botStatus = -1;
|
||||
for (auto i = chat->participants.begin(), e = chat->participants.end(); i != e;) {
|
||||
if (i.value() < pversion) {
|
||||
i = chat->participants.erase(i);
|
||||
|
@ -934,7 +934,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
if (chat->botStatus > 0 && user->botInfo) {
|
||||
int32 botStatus = -1;
|
||||
int32_t botStatus = -1;
|
||||
for (auto j = chat->participants.cbegin(), e = chat->participants.cend(); j != e; ++j) {
|
||||
if (j.key()->botInfo) {
|
||||
if (true || botStatus > 0/* || !j.key()->botInfo->readsAllHistory*/) {
|
||||
|
@ -1060,7 +1060,7 @@ namespace {
|
|||
|
||||
void addSavedGif(DocumentData *doc) {
|
||||
SavedGifs &saved(cRefSavedGifs());
|
||||
int32 index = saved.indexOf(doc);
|
||||
int32_t index = saved.indexOf(doc);
|
||||
if (index) {
|
||||
if (index > 0) saved.remove(index);
|
||||
saved.push_front(doc);
|
||||
|
@ -1086,8 +1086,8 @@ namespace {
|
|||
}
|
||||
|
||||
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type) {
|
||||
QMap<uint64, int32> msgsIds;
|
||||
for (int32 i = 0, l = msgs.size(); i < l; ++i) {
|
||||
QMap<uint64_t, int32_t> msgsIds;
|
||||
for (int32_t i = 0, l = msgs.size(); i < l; ++i) {
|
||||
const auto &msg(msgs.at(i));
|
||||
switch (msg.type()) {
|
||||
case mtpc_message: {
|
||||
|
@ -1100,14 +1100,14 @@ namespace {
|
|||
}
|
||||
}
|
||||
if (needToAdd) {
|
||||
msgsIds.insert((uint64(uint32(d.vid.v)) << 32) | uint64(i), i);
|
||||
msgsIds.insert((uint64_t(uint32_t(d.vid.v)) << 32) | uint64_t(i), i);
|
||||
}
|
||||
} break;
|
||||
case mtpc_messageEmpty: msgsIds.insert((uint64(uint32(msg.c_messageEmpty().vid.v)) << 32) | uint64(i), i); break;
|
||||
case mtpc_messageService: msgsIds.insert((uint64(uint32(msg.c_messageService().vid.v)) << 32) | uint64(i), i); break;
|
||||
case mtpc_messageEmpty: msgsIds.insert((uint64_t(uint32_t(msg.c_messageEmpty().vid.v)) << 32) | uint64_t(i), i); break;
|
||||
case mtpc_messageService: msgsIds.insert((uint64_t(uint32_t(msg.c_messageService().vid.v)) << 32) | uint64_t(i), i); break;
|
||||
}
|
||||
}
|
||||
for (QMap<uint64, int32>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
|
||||
for (QMap<uint64_t, int32_t>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) {
|
||||
histories().addNewMessage(msgs.at(i.value()), type);
|
||||
}
|
||||
}
|
||||
|
@ -1140,7 +1140,7 @@ namespace {
|
|||
return ImagePtr();
|
||||
}
|
||||
|
||||
StorageImageLocation imageLocation(int32 w, int32 h, const MTPFileLocation &loc) {
|
||||
StorageImageLocation imageLocation(int32_t w, int32_t h, const MTPFileLocation &loc) {
|
||||
if (loc.type() == mtpc_fileLocation) {
|
||||
const auto &l(loc.c_fileLocation());
|
||||
return StorageImageLocation(w, h, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v);
|
||||
|
@ -1279,9 +1279,9 @@ namespace {
|
|||
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs) {
|
||||
const QPixmap *thumb = 0, *medium = 0, *full = 0;
|
||||
int32 thumbLevel = -1, mediumLevel = -1, fullLevel = -1;
|
||||
int32_t thumbLevel = -1, mediumLevel = -1, fullLevel = -1;
|
||||
for (PreparedPhotoThumbs::const_iterator i = thumbs.cbegin(), e = thumbs.cend(); i != e; ++i) {
|
||||
int32 newThumbLevel = -1, newMediumLevel = -1, newFullLevel = -1;
|
||||
int32_t newThumbLevel = -1, newMediumLevel = -1, newFullLevel = -1;
|
||||
switch (i.key()) {
|
||||
case 's': newThumbLevel = 0; newMediumLevel = 5; newFullLevel = 4; break; // box 100x100
|
||||
case 'm': newThumbLevel = 2; newMediumLevel = 0; newFullLevel = 3; break; // box 320x320
|
||||
|
@ -1325,7 +1325,7 @@ namespace {
|
|||
PhotoData *feedPhoto(const MTPDphoto &photo, PhotoData *convert) {
|
||||
auto &sizes = photo.vsizes.v;
|
||||
const MTPPhotoSize *thumb = 0, *medium = 0, *full = 0;
|
||||
int32 thumbLevel = -1, mediumLevel = -1, fullLevel = -1;
|
||||
int32_t thumbLevel = -1, mediumLevel = -1, fullLevel = -1;
|
||||
for (QVector<MTPPhotoSize>::const_iterator i = sizes.cbegin(), e = sizes.cend(); i != e; ++i) {
|
||||
char size = 0;
|
||||
switch (i->type()) {
|
||||
|
@ -1341,7 +1341,7 @@ namespace {
|
|||
}
|
||||
if (!size) continue;
|
||||
|
||||
int32 newThumbLevel = -1, newMediumLevel = -1, newFullLevel = -1;
|
||||
int32_t newThumbLevel = -1, newMediumLevel = -1, newFullLevel = -1;
|
||||
switch (size) {
|
||||
case 's': newThumbLevel = 0; newMediumLevel = 5; newFullLevel = 4; break; // box 100x100
|
||||
case 'm': newThumbLevel = 2; newMediumLevel = 0; newFullLevel = 3; break; // box 320x320
|
||||
|
@ -1468,6 +1468,7 @@ namespace {
|
|||
return nullptr;
|
||||
}
|
||||
} break;
|
||||
case PeerData::NotLoaded: break;
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
@ -1514,7 +1515,7 @@ namespace {
|
|||
return i.value();
|
||||
}
|
||||
|
||||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
|
||||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64_t &access, int32_t date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
|
||||
if (convert) {
|
||||
if (convert->id != photo) {
|
||||
PhotosData::iterator i = ::photosData.find(convert->id);
|
||||
|
@ -1575,7 +1576,7 @@ namespace {
|
|||
return i.value();
|
||||
}
|
||||
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) {
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64_t &access, int32_t version, int32_t date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32_t dc, int32_t size, const StorageImageLocation &thumbLocation) {
|
||||
bool versionChanged = false;
|
||||
bool sentSticker = false;
|
||||
if (convert) {
|
||||
|
@ -1697,7 +1698,7 @@ namespace {
|
|||
return i.value();
|
||||
}
|
||||
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *document, int32 duration, const QString &author, int32 pendingTill) {
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *document, int32_t duration, const QString &author, int32_t pendingTill) {
|
||||
if (convert) {
|
||||
if (convert->id != webPage) {
|
||||
auto i = webPagesData.find(convert->id);
|
||||
|
@ -1769,7 +1770,7 @@ namespace {
|
|||
return i.value();
|
||||
}
|
||||
|
||||
GameData *gameSet(const GameId &game, GameData *convert, const uint64 &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *document) {
|
||||
GameData *gameSet(const GameId &game, GameData *convert, const uint64_t &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *document) {
|
||||
if (convert) {
|
||||
if (convert->id != game) {
|
||||
auto i = gamesData.find(convert->id);
|
||||
|
@ -1862,7 +1863,7 @@ namespace {
|
|||
return ::histories.findOrInsert(peer);
|
||||
}
|
||||
|
||||
History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead, int32 maxOutboxRead) {
|
||||
History *historyFromDialog(const PeerId &peer, int32_t unreadCnt, int32_t maxInboxRead, int32_t maxOutboxRead) {
|
||||
return ::histories.findOrInsert(peer, unreadCnt, maxInboxRead, maxOutboxRead);
|
||||
}
|
||||
|
||||
|
@ -2056,15 +2057,15 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void historyRegRandom(uint64 randomId, const FullMsgId &itemId) {
|
||||
void historyRegRandom(uint64_t randomId, const FullMsgId &itemId) {
|
||||
randomData.insert(randomId, itemId);
|
||||
}
|
||||
|
||||
void historyUnregRandom(uint64 randomId) {
|
||||
void historyUnregRandom(uint64_t randomId) {
|
||||
randomData.remove(randomId);
|
||||
}
|
||||
|
||||
FullMsgId histItemByRandom(uint64 randomId) {
|
||||
FullMsgId histItemByRandom(uint64_t randomId) {
|
||||
RandomData::const_iterator i = randomData.constFind(randomId);
|
||||
if (i != randomData.cend()) {
|
||||
return i.value();
|
||||
|
@ -2072,23 +2073,23 @@ namespace {
|
|||
return FullMsgId();
|
||||
}
|
||||
|
||||
void historyRegSentData(uint64 randomId, const PeerId &peerId, const QString &text) {
|
||||
void historyRegSentData(uint64_t randomId, const PeerId &peerId, const QString &text) {
|
||||
sentData.insert(randomId, qMakePair(peerId, text));
|
||||
}
|
||||
|
||||
void historyUnregSentData(uint64 randomId) {
|
||||
void historyUnregSentData(uint64_t randomId) {
|
||||
sentData.remove(randomId);
|
||||
}
|
||||
|
||||
void histSentDataByItem(uint64 randomId, PeerId &peerId, QString &text) {
|
||||
void histSentDataByItem(uint64_t randomId, PeerId &peerId, QString &text) {
|
||||
QPair<PeerId, QString> d = sentData.value(randomId);
|
||||
peerId = d.first;
|
||||
text = d.second;
|
||||
}
|
||||
|
||||
void prepareCorners(RoundCorners index, int32 radius, const QBrush &brush, const style::color *shadow = nullptr, QImage *cors = nullptr) {
|
||||
void prepareCorners(RoundCorners index, int32_t radius, const QBrush &brush, const style::color *shadow = nullptr, QImage *cors = nullptr) {
|
||||
Expects(::corners.size() > index);
|
||||
int32 r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor();
|
||||
int32_t r = radius * cIntRetinaFactor(), s = st::msgShadow * cIntRetinaFactor();
|
||||
QImage rect(r * 3, r * 3 + (shadow ? s : 0), QImage::Format_ARGB32_Premultiplied), localCors[4];
|
||||
{
|
||||
Painter p(&rect);
|
||||
|
@ -2335,7 +2336,7 @@ namespace {
|
|||
return *::emojiLarge;
|
||||
}
|
||||
|
||||
const QPixmap &emojiSingle(EmojiPtr emoji, int32 fontHeight) {
|
||||
const QPixmap &emojiSingle(EmojiPtr emoji, int32_t fontHeight) {
|
||||
auto &map = (fontHeight == st::msgFont->height) ? MainEmojiMap : OtherEmojiMap[fontHeight];
|
||||
auto i = map.constFind(emoji->index());
|
||||
if (i == map.cend()) {
|
||||
|
@ -2352,7 +2353,7 @@ namespace {
|
|||
}
|
||||
|
||||
void checkImageCacheSize() {
|
||||
int64 nowImageCacheSize = imageCacheSize();
|
||||
int64_t nowImageCacheSize = imageCacheSize();
|
||||
if (nowImageCacheSize > serviceImageCacheSize + MemoryForImageCache) {
|
||||
App::forgetMedia();
|
||||
serviceImageCacheSize = imageCacheSize();
|
||||
|
@ -2392,17 +2393,8 @@ namespace {
|
|||
}
|
||||
|
||||
void restart() {
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
bool updateReady = (Sandbox::updatingState() == Application::UpdatingReady);
|
||||
#else // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
bool updateReady = false;
|
||||
#endif // else for !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
if (updateReady) {
|
||||
cSetRestartingUpdate(true);
|
||||
} else {
|
||||
cSetRestarting(true);
|
||||
cSetRestartingToSettings(true);
|
||||
}
|
||||
cSetRestarting(true);
|
||||
cSetRestartingToSettings(true);
|
||||
App::quit();
|
||||
}
|
||||
|
||||
|
@ -2532,7 +2524,7 @@ namespace {
|
|||
return ::gameItems;
|
||||
}
|
||||
|
||||
void regSharedContactItem(int32 userId, HistoryItem *item) {
|
||||
void regSharedContactItem(int32_t userId, HistoryItem *item) {
|
||||
auto user = App::userLoaded(userId);
|
||||
auto canShareThisContact = user ? user->canShareThisContact() : false;
|
||||
::sharedContactItems[userId].insert(item);
|
||||
|
@ -2541,7 +2533,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void unregSharedContactItem(int32 userId, HistoryItem *item) {
|
||||
void unregSharedContactItem(int32_t userId, HistoryItem *item) {
|
||||
auto user = App::userLoaded(userId);
|
||||
auto canShareThisContact = user ? user->canShareThisContact() : false;
|
||||
::sharedContactItems[userId].remove(item);
|
||||
|
@ -2575,7 +2567,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
QString phoneFromSharedContact(int32 userId) {
|
||||
QString phoneFromSharedContact(int32_t userId) {
|
||||
auto i = ::sharedContactItems.constFind(userId);
|
||||
if (i != ::sharedContactItems.cend() && !i->isEmpty()) {
|
||||
if (auto media = (*i->cbegin())->getMedia()) {
|
||||
|
@ -2587,7 +2579,7 @@ namespace {
|
|||
return QString();
|
||||
}
|
||||
|
||||
void regMuted(PeerData *peer, int32 changeIn) {
|
||||
void regMuted(PeerData *peer, int32_t changeIn) {
|
||||
::mutedPeers.insert(peer, true);
|
||||
if (App::main()) App::main()->updateMutedIn(changeIn);
|
||||
}
|
||||
|
@ -2597,9 +2589,9 @@ namespace {
|
|||
}
|
||||
|
||||
void updateMuted() {
|
||||
int32 changeInMin = 0;
|
||||
int32_t changeInMin = 0;
|
||||
for (MutedPeers::iterator i = ::mutedPeers.begin(); i != ::mutedPeers.end();) {
|
||||
int32 changeIn = 0;
|
||||
int32_t changeIn = 0;
|
||||
History *h = App::history(i.key()->id);
|
||||
if (isNotifyMuted(i.key()->notify, &changeIn)) {
|
||||
h->setMute(true);
|
||||
|
@ -2694,7 +2686,7 @@ namespace {
|
|||
return ::cornersMaskSmall;
|
||||
}
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) {
|
||||
void roundRect(Painter &p, int32_t x, int32_t y, int32_t w, int32_t h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) {
|
||||
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
|
||||
if (w < 2 * cornerWidth || h < 2 * cornerHeight) return;
|
||||
|
@ -2738,11 +2730,11 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, RoundCorners index, const style::color *shadow, RectParts parts) {
|
||||
void roundRect(Painter &p, int32_t x, int32_t y, int32_t w, int32_t h, style::color bg, RoundCorners index, const style::color *shadow, RectParts parts) {
|
||||
roundRect(p, x, y, w, h, bg, ::corners[index], shadow, parts);
|
||||
}
|
||||
|
||||
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts) {
|
||||
void roundShadow(Painter &p, int32_t x, int32_t y, int32_t w, int32_t h, style::color shadow, RoundCorners index, RectParts parts) {
|
||||
auto &corner = ::corners[index];
|
||||
auto cornerWidth = corner.p[0].width() / cIntRetinaFactor();
|
||||
auto cornerHeight = corner.p[0].height() / cIntRetinaFactor();
|
||||
|
@ -2759,8 +2751,8 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts) {
|
||||
auto colorKey = ((uint32(bg->c.alpha()) & 0xFF) << 24) | ((uint32(bg->c.red()) & 0xFF) << 16) | ((uint32(bg->c.green()) & 0xFF) << 8) | ((uint32(bg->c.blue()) & 0xFF) << 24);
|
||||
void roundRect(Painter &p, int32_t x, int32_t y, int32_t w, int32_t h, style::color bg, ImageRoundRadius radius, RectParts parts) {
|
||||
auto colorKey = ((uint32_t(bg->c.alpha()) & 0xFF) << 24) | ((uint32_t(bg->c.red()) & 0xFF) << 16) | ((uint32_t(bg->c.green()) & 0xFF) << 8) | ((uint32_t(bg->c.blue()) & 0xFF) << 24);
|
||||
auto i = cornersMap.find(colorKey);
|
||||
if (i == cornersMap.cend()) {
|
||||
QImage images[4];
|
||||
|
|
|
@ -34,7 +34,7 @@ using PhotoItems = QHash<PhotoData*, HistoryItemsMap>;
|
|||
using DocumentItems = QHash<DocumentData*, HistoryItemsMap>;
|
||||
using WebPageItems = QHash<WebPageData*, HistoryItemsMap>;
|
||||
using GameItems = QHash<GameData*, HistoryItemsMap>;
|
||||
using SharedContactItems = QHash<int32, HistoryItemsMap>;
|
||||
using SharedContactItems = QHash<int32_t, HistoryItemsMap>;
|
||||
using GifItems = QHash<Media::Clip::Reader*, HistoryItem*>;
|
||||
|
||||
using PhotosData = QHash<PhotoId, PhotoData*>;
|
||||
|
@ -53,8 +53,8 @@ namespace App {
|
|||
QString formatPhone(QString phone);
|
||||
|
||||
TimeId onlineForSort(UserData *user, TimeId now);
|
||||
int32 onlineWillChangeIn(UserData *user, TimeId now);
|
||||
int32 onlineWillChangeIn(TimeId online, TimeId now);
|
||||
int32_t onlineWillChangeIn(UserData *user, TimeId now);
|
||||
int32_t onlineWillChangeIn(TimeId online, TimeId now);
|
||||
QString onlineText(UserData *user, TimeId now, bool precise = false);
|
||||
QString onlineText(TimeId online, TimeId now, bool precise = false);
|
||||
bool onlineColorUse(UserData *user, TimeId now);
|
||||
|
@ -82,7 +82,7 @@ namespace App {
|
|||
void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink);
|
||||
|
||||
ImagePtr image(const MTPPhotoSize &size);
|
||||
StorageImageLocation imageLocation(int32 w, int32 h, const MTPFileLocation &loc);
|
||||
StorageImageLocation imageLocation(int32_t w, int32_t h, const MTPFileLocation &loc);
|
||||
StorageImageLocation imageLocation(const MTPPhotoSize &size);
|
||||
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs);
|
||||
|
@ -143,13 +143,13 @@ namespace App {
|
|||
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);
|
||||
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64_t &access, int32_t date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
|
||||
DocumentData *document(const DocumentId &document);
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
|
||||
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64_t &access, int32_t version, int32_t date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32_t dc, int32_t size, const StorageImageLocation &thumbLocation);
|
||||
WebPageData *webPage(const WebPageId &webPage);
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill);
|
||||
WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *doc, int32_t duration, const QString &author, int32_t pendingTill);
|
||||
GameData *game(const GameId &game);
|
||||
GameData *gameSet(const GameId &game, GameData *convert, const uint64 &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc);
|
||||
GameData *gameSet(const GameId &game, GameData *convert, const uint64_t &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc);
|
||||
LocationData *location(const LocationCoords &coords);
|
||||
void forgetMedia();
|
||||
|
||||
|
@ -157,7 +157,7 @@ namespace App {
|
|||
|
||||
Histories &histories();
|
||||
not_null<History*> history(const PeerId &peer);
|
||||
History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead, int32 maxOutboxRead);
|
||||
History *historyFromDialog(const PeerId &peer, int32_t unreadCnt, int32_t maxInboxRead, int32_t maxOutboxRead);
|
||||
History *historyLoaded(const PeerId &peer);
|
||||
HistoryItem *histItemById(ChannelId channelId, MsgId itemId);
|
||||
inline not_null<History*> history(const PeerData *peer) {
|
||||
|
@ -182,12 +182,12 @@ namespace App {
|
|||
void historyRegDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
void historyUnregDependency(HistoryItem *dependent, HistoryItem *dependency);
|
||||
|
||||
void historyRegRandom(uint64 randomId, const FullMsgId &itemId);
|
||||
void historyUnregRandom(uint64 randomId);
|
||||
FullMsgId histItemByRandom(uint64 randomId);
|
||||
void historyRegSentData(uint64 randomId, const PeerId &peerId, const QString &text);
|
||||
void historyUnregSentData(uint64 randomId);
|
||||
void histSentDataByItem(uint64 randomId, PeerId &peerId, QString &text);
|
||||
void historyRegRandom(uint64_t randomId, const FullMsgId &itemId);
|
||||
void historyUnregRandom(uint64_t randomId);
|
||||
FullMsgId histItemByRandom(uint64_t randomId);
|
||||
void historyRegSentData(uint64_t randomId, const PeerId &peerId, const QString &text);
|
||||
void historyUnregSentData(uint64_t randomId);
|
||||
void histSentDataByItem(uint64_t randomId, PeerId &peerId, QString &text);
|
||||
|
||||
void hoveredItem(HistoryItem *item);
|
||||
HistoryItem *hoveredItem();
|
||||
|
@ -206,7 +206,7 @@ namespace App {
|
|||
const style::font &monofont();
|
||||
const QPixmap &emoji();
|
||||
const QPixmap &emojiLarge();
|
||||
const QPixmap &emojiSingle(EmojiPtr emoji, int32 fontHeight);
|
||||
const QPixmap &emojiSingle(EmojiPtr emoji, int32_t fontHeight);
|
||||
|
||||
void clearHistories();
|
||||
|
||||
|
@ -252,17 +252,17 @@ namespace App {
|
|||
void unregGameItem(GameData *data, HistoryItem *item);
|
||||
const GameItems &gameItems();
|
||||
|
||||
void regSharedContactItem(int32 userId, HistoryItem *item);
|
||||
void unregSharedContactItem(int32 userId, HistoryItem *item);
|
||||
void regSharedContactItem(int32_t userId, HistoryItem *item);
|
||||
void unregSharedContactItem(int32_t userId, HistoryItem *item);
|
||||
const SharedContactItems &sharedContactItems();
|
||||
QString phoneFromSharedContact(int32 userId);
|
||||
QString phoneFromSharedContact(int32_t userId);
|
||||
|
||||
void regGifItem(Media::Clip::Reader *reader, HistoryItem *item);
|
||||
void unregGifItem(Media::Clip::Reader *reader);
|
||||
void stopRoundVideoPlayback();
|
||||
void stopGifItems();
|
||||
|
||||
void regMuted(PeerData *peer, int32 changeIn);
|
||||
void regMuted(PeerData *peer, int32_t changeIn);
|
||||
void unregMuted(PeerData *peer);
|
||||
void updateMuted();
|
||||
|
||||
|
@ -276,23 +276,23 @@ namespace App {
|
|||
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners);
|
||||
|
||||
QImage *cornersMask(ImageRoundRadius radius);
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
|
||||
void roundRect(Painter &p, int32_t x, int32_t y, int32_t w, int32_t h, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, RoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
|
||||
}
|
||||
void roundShadow(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full);
|
||||
void roundShadow(Painter &p, int32_t x, int32_t y, int32_t w, int32_t h, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full);
|
||||
inline void roundShadow(Painter &p, const QRect &rect, style::color shadow, RoundCorners index, RectParts parts = RectPart::Full) {
|
||||
return roundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts);
|
||||
}
|
||||
void roundRect(Painter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
|
||||
void roundRect(Painter &p, int32_t x, int32_t y, int32_t w, int32_t h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
|
||||
inline void roundRect(Painter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) {
|
||||
return roundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts);
|
||||
}
|
||||
|
||||
struct WallPaper {
|
||||
WallPaper(int32 id, ImagePtr thumb, ImagePtr full) : id(id), thumb(thumb), full(full) {
|
||||
WallPaper(int32_t id, ImagePtr thumb, ImagePtr full) : id(id), thumb(thumb), full(full) {
|
||||
}
|
||||
int32 id;
|
||||
int32_t id;
|
||||
ImagePtr thumb;
|
||||
ImagePtr full;
|
||||
};
|
||||
|
|
|
@ -24,13 +24,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "autoupdater.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "messenger.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// @todo are there no other ways to get/set hex?
|
||||
QChar _toHex(ushort v) {
|
||||
v = v & 0x000F;
|
||||
return QChar::fromLatin1((v >= 10) ? ('a' + (v - 10)) : ('0' + v));
|
||||
|
@ -39,6 +39,7 @@ ushort _fromHex(QChar c) {
|
|||
return ((c.unicode() >= uchar('a')) ? (c.unicode() - uchar('a') + 10) : (c.unicode() - uchar('0'))) & 0x000F;
|
||||
}
|
||||
|
||||
// @todo urlencode/decode functions might help here??
|
||||
QString _escapeTo7bit(const QString &str) {
|
||||
QString result;
|
||||
result.reserve(str.size() * 2);
|
||||
|
@ -85,20 +86,13 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
|
|||
connect(&_localSocket, SIGNAL(connected()), this, SLOT(socketConnected()));
|
||||
connect(&_localSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
|
||||
connect(&_localSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(socketError(QLocalSocket::LocalSocketError)));
|
||||
connect(&_localSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(socketWritten(qint64)));
|
||||
connect(&_localSocket, SIGNAL(bytesWritten(int64_t)), this, SLOT(socketWritten(int64_t)));
|
||||
connect(&_localSocket, SIGNAL(readyRead()), this, SLOT(socketReading()));
|
||||
connect(&_localServer, SIGNAL(newConnection()), this, SLOT(newInstanceConnected()));
|
||||
|
||||
QTimer::singleShot(0, this, SLOT(startApplication()));
|
||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(closeApplication()));
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
_updateCheckTimer.create(this);
|
||||
connect(_updateCheckTimer, SIGNAL(timeout()), this, SLOT(updateCheck()));
|
||||
connect(this, SIGNAL(updateFailed()), this, SLOT(onUpdateFailed()));
|
||||
connect(this, SIGNAL(updateReady()), this, SLOT(onUpdateReady()));
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
if (cManyInstance()) {
|
||||
LOG(("Many instance allowed, starting..."));
|
||||
singleInstanceChecked();
|
||||
|
@ -135,7 +129,7 @@ void Application::socketConnected() {
|
|||
_localSocket.write(commands.toLatin1());
|
||||
}
|
||||
|
||||
void Application::socketWritten(qint64/* bytes*/) {
|
||||
void Application::socketWritten(int64_t/* bytes*/) {
|
||||
if (_localSocket.state() != QLocalSocket::ConnectedState) {
|
||||
LOG(("Socket is not connected %1").arg(_localSocket.state()));
|
||||
return;
|
||||
|
@ -153,7 +147,7 @@ void Application::socketReading() {
|
|||
}
|
||||
_localSocketReadData.append(_localSocket.readAll());
|
||||
if (QRegularExpression("RES:(\\d+);").match(_localSocketReadData).hasMatch()) {
|
||||
uint64 pid = _localSocketReadData.mid(4, _localSocketReadData.length() - 5).toULongLong();
|
||||
uint64_t pid = _localSocketReadData.mid(4, _localSocketReadData.length() - 5).toULongLong();
|
||||
psActivateProcess(pid);
|
||||
LOG(("Show command response received, pid = %1, activating and quitting...").arg(pid));
|
||||
return App::quit();
|
||||
|
@ -185,14 +179,6 @@ void Application::socketError(QLocalSocket::LocalSocketError e) {
|
|||
}
|
||||
#endif // !Q_OS_WINRT
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
if (!cNoStartUpdate() && checkReadyUpdate()) {
|
||||
cSetRestartingUpdate(true);
|
||||
DEBUG_LOG(("Application Info: installing update instead of starting app..."));
|
||||
return App::quit();
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
singleInstanceChecked();
|
||||
}
|
||||
|
||||
|
@ -249,8 +235,8 @@ void Application::readClients() {
|
|||
i->second.append(i->first->readAll());
|
||||
if (i->second.size()) {
|
||||
QString cmds(QString::fromLatin1(i->second));
|
||||
int32 from = 0, l = cmds.length();
|
||||
for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
|
||||
int32_t from = 0, l = cmds.length();
|
||||
for (int32_t to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
|
||||
QStringRef cmd(&cmds, from, to - from);
|
||||
if (cmd.startsWith(qsl("CMD:"))) {
|
||||
Sandbox::execExternal(cmds.mid(from + 4, to - from - 4));
|
||||
|
@ -332,171 +318,8 @@ void Application::closeApplication() {
|
|||
_localClients.clear();
|
||||
|
||||
_localSocket.close();
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
delete _updateReply;
|
||||
_updateReply = 0;
|
||||
if (_updateChecker) _updateChecker->deleteLater();
|
||||
_updateChecker = 0;
|
||||
if (_updateThread) {
|
||||
_updateThread->quit();
|
||||
}
|
||||
_updateThread = 0;
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
}
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
void Application::updateCheck() {
|
||||
startUpdateCheck(false);
|
||||
}
|
||||
|
||||
void Application::updateGotCurrent() {
|
||||
if (!_updateReply || _updateThread) return;
|
||||
|
||||
cSetLastUpdateCheck(unixtime());
|
||||
QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromLatin1(_updateReply->readAll()));
|
||||
if (m.hasMatch()) {
|
||||
uint64 currentVersion = m.captured(1).toULongLong();
|
||||
QString url = m.captured(2);
|
||||
bool betaVersion = false;
|
||||
if (url.startsWith(qstr("beta_"))) {
|
||||
betaVersion = true;
|
||||
url = url.mid(5) + '_' + countBetaVersionSignature(currentVersion);
|
||||
}
|
||||
if ((!betaVersion || cBetaVersion()) && currentVersion > (betaVersion ? cBetaVersion() : uint64(AppVersion))) {
|
||||
_updateThread = new QThread();
|
||||
connect(_updateThread, SIGNAL(finished()), _updateThread, SLOT(deleteLater()));
|
||||
_updateChecker = new UpdateChecker(_updateThread, url);
|
||||
_updateThread->start();
|
||||
}
|
||||
}
|
||||
if (_updateReply) _updateReply->deleteLater();
|
||||
_updateReply = 0;
|
||||
if (!_updateThread) {
|
||||
QDir updates(cWorkingDir() + "tupdates");
|
||||
if (updates.exists()) {
|
||||
QFileInfoList list = updates.entryInfoList(QDir::Files);
|
||||
for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
|
||||
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+(_[a-z\\d]+)?$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
||||
QFile(i->absoluteFilePath()).remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
emit updateLatest();
|
||||
}
|
||||
startUpdateCheck(true);
|
||||
Local::writeSettings();
|
||||
}
|
||||
|
||||
void Application::updateFailedCurrent(QNetworkReply::NetworkError e) {
|
||||
LOG(("App Error: could not get current version (update check): %1").arg(e));
|
||||
if (_updateReply) _updateReply->deleteLater();
|
||||
_updateReply = 0;
|
||||
|
||||
emit updateFailed();
|
||||
startUpdateCheck(true);
|
||||
}
|
||||
|
||||
void Application::onUpdateReady() {
|
||||
if (_updateChecker) {
|
||||
_updateChecker->deleteLater();
|
||||
_updateChecker = nullptr;
|
||||
}
|
||||
_updateCheckTimer->stop();
|
||||
|
||||
cSetLastUpdateCheck(unixtime());
|
||||
Local::writeSettings();
|
||||
}
|
||||
|
||||
void Application::onUpdateFailed() {
|
||||
if (_updateChecker) {
|
||||
_updateChecker->deleteLater();
|
||||
_updateChecker = 0;
|
||||
if (_updateThread) _updateThread->quit();
|
||||
_updateThread = 0;
|
||||
}
|
||||
|
||||
cSetLastUpdateCheck(unixtime());
|
||||
Local::writeSettings();
|
||||
}
|
||||
|
||||
Application::UpdatingState Application::updatingState() {
|
||||
if (!_updateThread) return Application::UpdatingNone;
|
||||
if (!_updateChecker) return Application::UpdatingReady;
|
||||
return Application::UpdatingDownload;
|
||||
}
|
||||
|
||||
int32 Application::updatingSize() {
|
||||
if (!_updateChecker) return 0;
|
||||
return _updateChecker->size();
|
||||
}
|
||||
|
||||
int32 Application::updatingReady() {
|
||||
if (!_updateChecker) return 0;
|
||||
return _updateChecker->ready();
|
||||
}
|
||||
|
||||
void Application::stopUpdate() {
|
||||
if (_updateReply) {
|
||||
_updateReply->abort();
|
||||
_updateReply->deleteLater();
|
||||
_updateReply = 0;
|
||||
}
|
||||
if (_updateChecker) {
|
||||
_updateChecker->deleteLater();
|
||||
_updateChecker = 0;
|
||||
if (_updateThread) _updateThread->quit();
|
||||
_updateThread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::startUpdateCheck(bool forceWait) {
|
||||
if (!Sandbox::started()) return;
|
||||
|
||||
_updateCheckTimer->stop();
|
||||
if (_updateThread || _updateReply || !cAutoUpdate() || cExeName().isEmpty()) return;
|
||||
|
||||
int32 constDelay = cBetaVersion() ? 600 : UpdateDelayConstPart, randDelay = cBetaVersion() ? 300 : UpdateDelayRandPart;
|
||||
int32 updateInSecs = cLastUpdateCheck() + constDelay + int32(rand() % randDelay) - unixtime();
|
||||
bool sendRequest = (updateInSecs <= 0 || updateInSecs > (constDelay + randDelay));
|
||||
if (!sendRequest && !forceWait) {
|
||||
QDir updates(cWorkingDir() + "tupdates");
|
||||
if (updates.exists()) {
|
||||
QFileInfoList list = updates.entryInfoList(QDir::Files);
|
||||
for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
|
||||
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+(_[a-z\\d]+)?$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
||||
sendRequest = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cManyInstance() && !cDebug()) return; // only main instance is updating
|
||||
|
||||
if (sendRequest) {
|
||||
QUrl url(cUpdateURL());
|
||||
if (cBetaVersion()) {
|
||||
url.setQuery(qsl("version=%1&beta=%2").arg(AppVersion).arg(cBetaVersion()));
|
||||
} else if (cAlphaVersion()) {
|
||||
url.setQuery(qsl("version=%1&alpha=1").arg(AppVersion));
|
||||
} else {
|
||||
url.setQuery(qsl("version=%1").arg(AppVersion));
|
||||
}
|
||||
QString u = url.toString();
|
||||
QNetworkRequest checkVersion(url);
|
||||
if (_updateReply) _updateReply->deleteLater();
|
||||
|
||||
App::setProxySettings(_updateManager);
|
||||
_updateReply = _updateManager.get(checkVersion);
|
||||
connect(_updateReply, SIGNAL(finished()), this, SLOT(updateGotCurrent()));
|
||||
connect(_updateReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(updateFailedCurrent(QNetworkReply::NetworkError)));
|
||||
emit updateChecking();
|
||||
} else {
|
||||
_updateCheckTimer->start((updateInSecs + 5) * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
inline Application *application() {
|
||||
return qobject_cast<Application*>(QApplication::instance());
|
||||
}
|
||||
|
@ -548,73 +371,6 @@ void adjustSingleTimers() {
|
|||
base::Timer::Adjust();
|
||||
}
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
void startUpdateCheck() {
|
||||
if (auto a = application()) {
|
||||
return a->startUpdateCheck(false);
|
||||
}
|
||||
}
|
||||
|
||||
void stopUpdate() {
|
||||
if (auto a = application()) {
|
||||
return a->stopUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
Application::UpdatingState updatingState() {
|
||||
if (auto a = application()) {
|
||||
return a->updatingState();
|
||||
}
|
||||
return Application::UpdatingNone;
|
||||
}
|
||||
|
||||
int32 updatingSize() {
|
||||
if (auto a = application()) {
|
||||
return a->updatingSize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 updatingReady() {
|
||||
if (auto a = application()) {
|
||||
return a->updatingReady();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateChecking() {
|
||||
if (auto a = application()) {
|
||||
emit a->updateChecking();
|
||||
}
|
||||
}
|
||||
|
||||
void updateLatest() {
|
||||
if (auto a = application()) {
|
||||
emit a->updateLatest();
|
||||
}
|
||||
}
|
||||
|
||||
void updateProgress(qint64 ready, qint64 total) {
|
||||
if (auto a = application()) {
|
||||
emit a->updateProgress(ready, total);
|
||||
}
|
||||
}
|
||||
|
||||
void updateFailed() {
|
||||
if (auto a = application()) {
|
||||
emit a->updateFailed();
|
||||
}
|
||||
}
|
||||
|
||||
void updateReady() {
|
||||
if (auto a = application()) {
|
||||
emit a->updateReady();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
void connect(const char *signal, QObject *object, const char *method) {
|
||||
if (auto a = application()) {
|
||||
a->connect(a, signal, object, method);
|
||||
|
@ -624,7 +380,7 @@ void connect(const char *signal, QObject *object, const char *method) {
|
|||
void launch() {
|
||||
Assert(application() != 0);
|
||||
|
||||
float64 dpi = Application::primaryScreen()->logicalDotsPerInch();
|
||||
double dpi = Application::primaryScreen()->logicalDotsPerInch();
|
||||
if (dpi <= 108) { // 0-96-108
|
||||
cSetScreenScale(dbisOne);
|
||||
} else if (dpi <= 132) { // 108-120-132
|
||||
|
@ -646,7 +402,7 @@ void launch() {
|
|||
}
|
||||
cSetRetina(true);
|
||||
cSetRetinaFactor(devicePixelRatio);
|
||||
cSetIntRetinaFactor(int32(cRetinaFactor()));
|
||||
cSetIntRetinaFactor(int32_t(cRetinaFactor()));
|
||||
cSetConfigScale(dbisOne);
|
||||
cSetRealScale(dbisOne);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
class UpdateChecker;
|
||||
#include "stdafx.h"
|
||||
#include <QApplication>
|
||||
|
||||
class Application : public QApplication {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -41,7 +43,7 @@ public slots:
|
|||
void socketConnected();
|
||||
void socketError(QLocalSocket::LocalSocketError e);
|
||||
void socketDisconnected();
|
||||
void socketWritten(qint64 bytes);
|
||||
void socketWritten(int64_t bytes);
|
||||
void socketReading();
|
||||
void newInstanceConnected();
|
||||
|
||||
|
@ -64,47 +66,6 @@ private:
|
|||
bool _secondInstance = false;
|
||||
|
||||
void singleInstanceChecked();
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
// Autoupdating
|
||||
public:
|
||||
void startUpdateCheck(bool forceWait);
|
||||
void stopUpdate();
|
||||
|
||||
enum UpdatingState {
|
||||
UpdatingNone,
|
||||
UpdatingDownload,
|
||||
UpdatingReady,
|
||||
};
|
||||
UpdatingState updatingState();
|
||||
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:
|
||||
object_ptr<SingleTimer> _updateCheckTimer = { nullptr };
|
||||
QNetworkReply *_updateReply = nullptr;
|
||||
QNetworkAccessManager _updateManager;
|
||||
QThread *_updateThread = nullptr;
|
||||
UpdateChecker *_updateChecker = nullptr;
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
};
|
||||
|
||||
namespace Sandbox {
|
||||
|
@ -118,23 +79,6 @@ void execExternal(const QString &cmd);
|
|||
|
||||
void adjustSingleTimers();
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
void startUpdateCheck();
|
||||
void stopUpdate();
|
||||
|
||||
Application::UpdatingState updatingState();
|
||||
int32 updatingSize();
|
||||
int32 updatingReady();
|
||||
|
||||
void updateChecking();
|
||||
void updateLatest();
|
||||
void updateProgress(qint64 ready, qint64 total);
|
||||
void updateFailed();
|
||||
void updateReady();
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
void connect(const char *signal, QObject *object, const char *method);
|
||||
|
||||
void launch();
|
||||
|
|
|
@ -45,30 +45,30 @@ AuthSessionData::Variables::Variables()
|
|||
}
|
||||
|
||||
QByteArray AuthSessionData::serialize() const {
|
||||
auto size = sizeof(qint32) * 8;
|
||||
auto size = sizeof(int32_t) * 8;
|
||||
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
|
||||
size += Serialize::stringSize(i.key()) + Serialize::stringSize(i.value());
|
||||
}
|
||||
size += _variables.groupStickersSectionHidden.size() * sizeof(quint64);
|
||||
size += _variables.groupStickersSectionHidden.size() * sizeof(uint64_t);
|
||||
|
||||
auto result = QByteArray();
|
||||
result.reserve(size);
|
||||
{
|
||||
QDataStream stream(&result, QIODevice::WriteOnly);
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
stream << static_cast<qint32>(_variables.selectorTab);
|
||||
stream << qint32(_variables.lastSeenWarningSeen ? 1 : 0);
|
||||
stream << qint32(_variables.tabbedSelectorSectionEnabled ? 1 : 0);
|
||||
stream << qint32(_variables.soundOverrides.size());
|
||||
stream << static_cast<int32_t>(_variables.selectorTab);
|
||||
stream << int32_t(_variables.lastSeenWarningSeen ? 1 : 0);
|
||||
stream << int32_t(_variables.tabbedSelectorSectionEnabled ? 1 : 0);
|
||||
stream << int32_t(_variables.soundOverrides.size());
|
||||
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
|
||||
stream << i.key() << i.value();
|
||||
}
|
||||
stream << qint32(_variables.tabbedSelectorSectionTooltipShown);
|
||||
stream << qint32(_variables.floatPlayerColumn);
|
||||
stream << qint32(_variables.floatPlayerCorner);
|
||||
stream << qint32(_variables.groupStickersSectionHidden.size());
|
||||
stream << int32_t(_variables.tabbedSelectorSectionTooltipShown);
|
||||
stream << int32_t(_variables.floatPlayerColumn);
|
||||
stream << int32_t(_variables.floatPlayerCorner);
|
||||
stream << int32_t(_variables.groupStickersSectionHidden.size());
|
||||
for (auto peerId : _variables.groupStickersSectionHidden) {
|
||||
stream << quint64(peerId);
|
||||
stream << uint64_t(peerId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -81,12 +81,12 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
|
|||
|
||||
QDataStream stream(serialized);
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
qint32 selectorTab = static_cast<qint32>(ChatHelpers::SelectorTab::Emoji);
|
||||
qint32 lastSeenWarningSeen = 0;
|
||||
qint32 tabbedSelectorSectionEnabled = 1;
|
||||
qint32 tabbedSelectorSectionTooltipShown = 0;
|
||||
qint32 floatPlayerColumn = static_cast<qint32>(Window::Column::Second);
|
||||
qint32 floatPlayerCorner = static_cast<qint32>(RectPart::TopRight);
|
||||
int32_t selectorTab = static_cast<int32_t>(ChatHelpers::SelectorTab::Emoji);
|
||||
int32_t lastSeenWarningSeen = 0;
|
||||
int32_t tabbedSelectorSectionEnabled = 1;
|
||||
int32_t tabbedSelectorSectionTooltipShown = 0;
|
||||
int32_t floatPlayerColumn = static_cast<int32_t>(Window::Column::Second);
|
||||
int32_t floatPlayerCorner = static_cast<int32_t>(RectPart::TopRight);
|
||||
QMap<QString, QString> soundOverrides;
|
||||
OrderedSet<PeerId> groupStickersSectionHidden;
|
||||
stream >> selectorTab;
|
||||
|
@ -95,7 +95,7 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
|
|||
stream >> tabbedSelectorSectionEnabled;
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
auto count = qint32(0);
|
||||
auto count = int32_t(0);
|
||||
stream >> count;
|
||||
if (stream.status() == QDataStream::Ok) {
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
|
@ -112,11 +112,11 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
|
|||
stream >> floatPlayerColumn >> floatPlayerCorner;
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
auto count = qint32(0);
|
||||
auto count = int32_t(0);
|
||||
stream >> count;
|
||||
if (stream.status() == QDataStream::Ok) {
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
quint64 peerId;
|
||||
uint64_t peerId;
|
||||
stream >> peerId;
|
||||
groupStickersSectionHidden.insert(peerId);
|
||||
}
|
||||
|
|
|
@ -1,627 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
|
||||
#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 "platform/platform_specific.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
typedef DWORD VerInt;
|
||||
typedef WCHAR VerChar;
|
||||
#else // Q_OS_WIN
|
||||
typedef int VerInt;
|
||||
typedef wchar_t VerChar;
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
UpdateChecker::UpdateChecker(QThread *thread, const QString &url) : reply(0), already(0), full(0) {
|
||||
updateUrl = url;
|
||||
moveToThread(thread);
|
||||
manager.moveToThread(thread);
|
||||
App::setProxySettings(manager);
|
||||
|
||||
connect(thread, SIGNAL(started()), this, SLOT(start()));
|
||||
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(rand_value<uint32>() % 1000000);
|
||||
}
|
||||
QString dirStr = cWorkingDir() + qsl("tupdates/");
|
||||
fileName = dirStr + fileName;
|
||||
QFileInfo file(fileName);
|
||||
|
||||
QDir dir(dirStr);
|
||||
if (dir.exists()) {
|
||||
QFileInfoList all = dir.entryInfoList(QDir::Files);
|
||||
for (QFileInfoList::iterator i = all.begin(), e = all.end(); i != e; ++i) {
|
||||
if (i->absoluteFilePath() != file.absoluteFilePath()) {
|
||||
QFile::remove(i->absoluteFilePath());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dir.mkdir(dir.absolutePath());
|
||||
}
|
||||
outputFile.setFileName(fileName);
|
||||
if (file.exists()) {
|
||||
uint64 fullSize = file.size();
|
||||
if (fullSize < INT_MAX) {
|
||||
int32 goodSize = (int32)fullSize;
|
||||
if (goodSize % UpdateChunk) {
|
||||
goodSize = goodSize - (goodSize % UpdateChunk);
|
||||
if (goodSize) {
|
||||
if (outputFile.open(QIODevice::ReadOnly)) {
|
||||
QByteArray goodData = outputFile.readAll().mid(0, goodSize);
|
||||
outputFile.close();
|
||||
if (outputFile.open(QIODevice::WriteOnly)) {
|
||||
outputFile.write(goodData);
|
||||
outputFile.close();
|
||||
|
||||
QMutexLocker lock(&mutex);
|
||||
already = goodSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QMutexLocker lock(&mutex);
|
||||
already = goodSize;
|
||||
}
|
||||
}
|
||||
if (!already) {
|
||||
QFile::remove(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateChecker::start() {
|
||||
sendRequest();
|
||||
}
|
||||
|
||||
void UpdateChecker::sendRequest() {
|
||||
QNetworkRequest req(updateUrl);
|
||||
QByteArray rangeHeaderValue = "bytes=" + QByteArray::number(already) + "-";
|
||||
req.setRawHeader("Range", rangeHeaderValue);
|
||||
req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
|
||||
if (reply) reply->deleteLater();
|
||||
reply = manager.get(req);
|
||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(partFinished(qint64,qint64)));
|
||||
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(partFailed(QNetworkReply::NetworkError)));
|
||||
connect(reply, SIGNAL(metaDataChanged()), this, SLOT(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) {
|
||||
if (QString::fromUtf8(i->first).toLower() == "content-range") {
|
||||
QRegularExpressionMatch m = QRegularExpression(qsl("/(\\d+)([^\\d]|$)")).match(QString::fromUtf8(i->second));
|
||||
if (m.hasMatch()) {
|
||||
{
|
||||
QMutexLocker lock(&mutex);
|
||||
full = m.captured(1).toInt();
|
||||
}
|
||||
|
||||
Sandbox::updateProgress(already, full);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32 UpdateChecker::ready() {
|
||||
QMutexLocker lock(&mutex);
|
||||
return already;
|
||||
}
|
||||
|
||||
int32 UpdateChecker::size() {
|
||||
QMutexLocker lock(&mutex);
|
||||
return full;
|
||||
}
|
||||
|
||||
void UpdateChecker::partFinished(qint64 got, qint64 total) {
|
||||
if (!reply) return;
|
||||
|
||||
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
if (statusCode.isValid()) {
|
||||
int status = statusCode.toInt();
|
||||
if (status != 200 && status != 206 && status != 416) {
|
||||
LOG(("Update Error: Bad HTTP status received in partFinished(): %1").arg(status));
|
||||
return fatalFail();
|
||||
}
|
||||
}
|
||||
|
||||
if (!already && !full) {
|
||||
QMutexLocker lock(&mutex);
|
||||
full = total;
|
||||
}
|
||||
DEBUG_LOG(("Update Info: part %1 of %2").arg(got).arg(total));
|
||||
|
||||
if (!outputFile.isOpen()) {
|
||||
if (!outputFile.open(QIODevice::Append)) {
|
||||
LOG(("Update Error: Could not open output file '%1' for appending").arg(outputFile.fileName()));
|
||||
return fatalFail();
|
||||
}
|
||||
}
|
||||
QByteArray r = reply->readAll();
|
||||
if (!r.isEmpty()) {
|
||||
outputFile.write(r);
|
||||
|
||||
QMutexLocker lock(&mutex);
|
||||
already += r.size();
|
||||
}
|
||||
if (got >= total) {
|
||||
reply->deleteLater();
|
||||
reply = 0;
|
||||
outputFile.close();
|
||||
unpackUpdate();
|
||||
} else {
|
||||
Sandbox::updateProgress(already, full);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateChecker::partFailed(QNetworkReply::NetworkError e) {
|
||||
if (!reply) return;
|
||||
|
||||
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
reply->deleteLater();
|
||||
reply = 0;
|
||||
if (statusCode.isValid()) {
|
||||
int status = statusCode.toInt();
|
||||
if (status == 416) { // Requested range not satisfiable
|
||||
outputFile.close();
|
||||
unpackUpdate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG(("Update Error: failed to download part starting from %1, error %2").arg(already).arg(e));
|
||||
Sandbox::updateFailed();
|
||||
}
|
||||
|
||||
void UpdateChecker::fatalFail() {
|
||||
clearAll();
|
||||
Sandbox::updateFailed();
|
||||
}
|
||||
|
||||
void UpdateChecker::clearAll() {
|
||||
psDeleteDir(cWorkingDir() + qsl("tupdates"));
|
||||
}
|
||||
|
||||
//QString winapiErrorWrap() {
|
||||
// WCHAR errMsg[2048];
|
||||
// DWORD errorCode = GetLastError();
|
||||
// LPTSTR errorText = NULL, errorTextDefault = L"(Unknown error)";
|
||||
// FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorText, 0, 0);
|
||||
// if (!errorText) {
|
||||
// errorText = errorTextDefault;
|
||||
// }
|
||||
// StringCbPrintf(errMsg, sizeof(errMsg), L"Error code: %d, error message: %s", errorCode, errorText);
|
||||
// if (errorText != errorTextDefault) {
|
||||
// LocalFree(errorText);
|
||||
// }
|
||||
// return QString::fromWCharArray(errMsg);
|
||||
//}
|
||||
|
||||
void UpdateChecker::unpackUpdate() {
|
||||
QByteArray packed;
|
||||
if (!outputFile.open(QIODevice::ReadOnly)) {
|
||||
LOG(("Update Error: cant read updates file!"));
|
||||
return fatalFail();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = LZMA_PROPS_SIZE, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hPropsLen + hOriginalSizeLen; // header
|
||||
#else // Q_OS_WIN
|
||||
const int32 hSigLen = 128, hShaLen = 20, hPropsLen = 0, hOriginalSizeLen = sizeof(int32), hSize = hSigLen + hShaLen + hOriginalSizeLen; // header
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
QByteArray compressed = outputFile.readAll();
|
||||
int32 compressedLen = compressed.size() - hSize;
|
||||
if (compressedLen <= 0) {
|
||||
LOG(("Update Error: bad compressed size: %1").arg(compressed.size()));
|
||||
return fatalFail();
|
||||
}
|
||||
outputFile.close();
|
||||
|
||||
QString tempDirPath = cWorkingDir() + qsl("tupdates/temp"), readyFilePath = cWorkingDir() + qsl("tupdates/temp/ready");
|
||||
psDeleteDir(tempDirPath);
|
||||
|
||||
QDir tempDir(tempDirPath);
|
||||
if (tempDir.exists() || QFile(readyFilePath).exists()) {
|
||||
LOG(("Update Error: cant clear tupdates/temp dir!"));
|
||||
return fatalFail();
|
||||
}
|
||||
|
||||
uchar sha1Buffer[20];
|
||||
bool goodSha1 = !memcmp(compressed.constData() + hSigLen, hashSha1(compressed.constData() + hSigLen + hShaLen, compressedLen + hPropsLen + hOriginalSizeLen, sha1Buffer), hShaLen);
|
||||
if (!goodSha1) {
|
||||
LOG(("Update Error: bad SHA1 hash of update file!"));
|
||||
return fatalFail();
|
||||
}
|
||||
|
||||
RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicAlphaKey : UpdatesPublicKey), -1), 0, 0, 0);
|
||||
if (!pbKey) {
|
||||
LOG(("Update Error: cant read public rsa key!"));
|
||||
return fatalFail();
|
||||
}
|
||||
if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature
|
||||
RSA_free(pbKey);
|
||||
if (cAlphaVersion() || cBetaVersion()) { // try other public key, if we are in alpha or beta version
|
||||
pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast<char*>(AppAlphaVersion ? UpdatesPublicKey : UpdatesPublicAlphaKey), -1), 0, 0, 0);
|
||||
if (!pbKey) {
|
||||
LOG(("Update Error: cant read public rsa key!"));
|
||||
return fatalFail();
|
||||
}
|
||||
if (RSA_verify(NID_sha1, (const uchar*)(compressed.constData() + hSigLen), hShaLen, (const uchar*)(compressed.constData()), hSigLen, pbKey) != 1) { // verify signature
|
||||
RSA_free(pbKey);
|
||||
LOG(("Update Error: bad RSA signature of update file!"));
|
||||
return fatalFail();
|
||||
}
|
||||
} else {
|
||||
LOG(("Update Error: bad RSA signature of update file!"));
|
||||
return fatalFail();
|
||||
}
|
||||
}
|
||||
RSA_free(pbKey);
|
||||
|
||||
QByteArray uncompressed;
|
||||
|
||||
int32 uncompressedLen;
|
||||
memcpy(&uncompressedLen, compressed.constData() + hSigLen + hShaLen + hPropsLen, hOriginalSizeLen);
|
||||
uncompressed.resize(uncompressedLen);
|
||||
|
||||
size_t resultLen = uncompressed.size();
|
||||
#ifdef Q_OS_WIN // use Lzma SDK for win
|
||||
SizeT srcLen = compressedLen;
|
||||
int uncompressRes = LzmaUncompress((uchar*)uncompressed.data(), &resultLen, (const uchar*)(compressed.constData() + hSize), &srcLen, (const uchar*)(compressed.constData() + hSigLen + hShaLen), LZMA_PROPS_SIZE);
|
||||
if (uncompressRes != SZ_OK) {
|
||||
LOG(("Update Error: could not uncompress lzma, code: %1").arg(uncompressRes));
|
||||
return fatalFail();
|
||||
}
|
||||
#else // Q_OS_WIN
|
||||
lzma_stream stream = LZMA_STREAM_INIT;
|
||||
|
||||
lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, LZMA_CONCATENATED);
|
||||
if (ret != LZMA_OK) {
|
||||
const char *msg;
|
||||
switch (ret) {
|
||||
case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
|
||||
case LZMA_OPTIONS_ERROR: msg = "Specified preset is not supported"; break;
|
||||
case LZMA_UNSUPPORTED_CHECK: msg = "Specified integrity check is not supported"; break;
|
||||
default: msg = "Unknown error, possibly a bug"; break;
|
||||
}
|
||||
LOG(("Error initializing the decoder: %1 (error code %2)").arg(msg).arg(ret));
|
||||
return fatalFail();
|
||||
}
|
||||
|
||||
stream.avail_in = compressedLen;
|
||||
stream.next_in = (uint8_t*)(compressed.constData() + hSize);
|
||||
stream.avail_out = resultLen;
|
||||
stream.next_out = (uint8_t*)uncompressed.data();
|
||||
|
||||
lzma_ret res = lzma_code(&stream, LZMA_FINISH);
|
||||
if (stream.avail_in) {
|
||||
LOG(("Error in decompression, %1 bytes left in _in of %2 whole.").arg(stream.avail_in).arg(compressedLen));
|
||||
return fatalFail();
|
||||
} else if (stream.avail_out) {
|
||||
LOG(("Error in decompression, %1 bytes free left in _out of %2 whole.").arg(stream.avail_out).arg(resultLen));
|
||||
return fatalFail();
|
||||
}
|
||||
lzma_end(&stream);
|
||||
if (res != LZMA_OK && res != LZMA_STREAM_END) {
|
||||
const char *msg;
|
||||
switch (res) {
|
||||
case LZMA_MEM_ERROR: msg = "Memory allocation failed"; break;
|
||||
case LZMA_FORMAT_ERROR: msg = "The input data is not in the .xz format"; break;
|
||||
case LZMA_OPTIONS_ERROR: msg = "Unsupported compression options"; break;
|
||||
case LZMA_DATA_ERROR: msg = "Compressed file is corrupt"; break;
|
||||
case LZMA_BUF_ERROR: msg = "Compressed data is truncated or otherwise corrupt"; break;
|
||||
default: msg = "Unknown error, possibly a bug"; break;
|
||||
}
|
||||
LOG(("Error in decompression: %1 (error code %2)").arg(msg).arg(res));
|
||||
return fatalFail();
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
tempDir.mkdir(tempDir.absolutePath());
|
||||
|
||||
quint32 version;
|
||||
{
|
||||
QDataStream stream(uncompressed);
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
|
||||
stream >> version;
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("Update Error: cant read version from downloaded stream, status: %1").arg(stream.status()));
|
||||
return fatalFail();
|
||||
}
|
||||
|
||||
quint64 betaVersion = 0;
|
||||
if (version == 0x7FFFFFFF) { // beta version
|
||||
stream >> betaVersion;
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("Update Error: cant read beta version from downloaded stream, status: %1").arg(stream.status()));
|
||||
return fatalFail();
|
||||
}
|
||||
if (!cBetaVersion() || betaVersion <= cBetaVersion()) {
|
||||
LOG(("Update Error: downloaded beta version %1 is not greater, than mine %2").arg(betaVersion).arg(cBetaVersion()));
|
||||
return fatalFail();
|
||||
}
|
||||
} else if (int32(version) <= AppVersion) {
|
||||
LOG(("Update Error: downloaded version %1 is not greater, than mine %2").arg(version).arg(AppVersion));
|
||||
return fatalFail();
|
||||
}
|
||||
|
||||
quint32 filesCount;
|
||||
stream >> filesCount;
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("Update Error: cant read files count from downloaded stream, status: %1").arg(stream.status()));
|
||||
return fatalFail();
|
||||
}
|
||||
if (!filesCount) {
|
||||
LOG(("Update Error: update is empty!"));
|
||||
return fatalFail();
|
||||
}
|
||||
for (uint32 i = 0; i < filesCount; ++i) {
|
||||
QString relativeName;
|
||||
quint32 fileSize;
|
||||
QByteArray fileInnerData;
|
||||
bool executable = false;
|
||||
|
||||
stream >> relativeName >> fileSize >> fileInnerData;
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
stream >> executable;
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("Update Error: cant read file from downloaded stream, status: %1").arg(stream.status()));
|
||||
return fatalFail();
|
||||
}
|
||||
if (fileSize != quint32(fileInnerData.size())) {
|
||||
LOG(("Update Error: bad file size %1 not matching data size %2").arg(fileSize).arg(fileInnerData.size()));
|
||||
return fatalFail();
|
||||
}
|
||||
|
||||
QFile f(tempDirPath + '/' + relativeName);
|
||||
if (!QDir().mkpath(QFileInfo(f).absolutePath())) {
|
||||
LOG(("Update Error: cant mkpath for file '%1'").arg(tempDirPath + '/' + relativeName));
|
||||
return fatalFail();
|
||||
}
|
||||
if (!f.open(QIODevice::WriteOnly)) {
|
||||
LOG(("Update Error: cant open file '%1' for writing").arg(tempDirPath + '/' + relativeName));
|
||||
return fatalFail();
|
||||
}
|
||||
auto writtenBytes = f.write(fileInnerData);
|
||||
if (writtenBytes != fileSize) {
|
||||
f.close();
|
||||
LOG(("Update Error: cant write file '%1', desiredSize: %2, write result: %3").arg(tempDirPath + '/' + relativeName).arg(fileSize).arg(writtenBytes));
|
||||
return fatalFail();
|
||||
}
|
||||
f.close();
|
||||
if (executable) {
|
||||
QFileDevice::Permissions p = f.permissions();
|
||||
p |= QFileDevice::ExeOwner | QFileDevice::ExeUser | QFileDevice::ExeGroup | QFileDevice::ExeOther;
|
||||
f.setPermissions(p);
|
||||
}
|
||||
}
|
||||
|
||||
// create tdata/version file
|
||||
tempDir.mkdir(QDir(tempDirPath + qsl("/tdata")).absolutePath());
|
||||
std::wstring versionString = ((version % 1000) ? QString("%1.%2.%3").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000)).arg(int(version % 1000)) : QString("%1.%2").arg(int(version / 1000000)).arg(int((version % 1000000) / 1000))).toStdWString();
|
||||
|
||||
VerInt versionNum = VerInt(version), versionLen = VerInt(versionString.size() * sizeof(VerChar));
|
||||
VerChar versionStr[32];
|
||||
memcpy(versionStr, versionString.c_str(), versionLen);
|
||||
|
||||
QFile fVersion(tempDirPath + qsl("/tdata/version"));
|
||||
if (!fVersion.open(QIODevice::WriteOnly)) {
|
||||
LOG(("Update Error: cant write version file '%1'").arg(tempDirPath + qsl("/version")));
|
||||
return fatalFail();
|
||||
}
|
||||
fVersion.write((const char*)&versionNum, sizeof(VerInt));
|
||||
if (versionNum == 0x7FFFFFFF) { // beta version
|
||||
fVersion.write((const char*)&betaVersion, sizeof(quint64));
|
||||
} else {
|
||||
fVersion.write((const char*)&versionLen, sizeof(VerInt));
|
||||
fVersion.write((const char*)&versionStr[0], versionLen);
|
||||
}
|
||||
fVersion.close();
|
||||
}
|
||||
|
||||
QFile readyFile(readyFilePath);
|
||||
if (readyFile.open(QIODevice::WriteOnly)) {
|
||||
if (readyFile.write("1", 1)) {
|
||||
readyFile.close();
|
||||
} else {
|
||||
LOG(("Update Error: cant write ready file '%1'").arg(readyFilePath));
|
||||
return fatalFail();
|
||||
}
|
||||
} else {
|
||||
LOG(("Update Error: cant create ready file '%1'").arg(readyFilePath));
|
||||
return fatalFail();
|
||||
}
|
||||
outputFile.remove();
|
||||
|
||||
Sandbox::updateReady();
|
||||
}
|
||||
|
||||
UpdateChecker::~UpdateChecker() {
|
||||
delete reply;
|
||||
reply = 0;
|
||||
}
|
||||
|
||||
bool checkReadyUpdate() {
|
||||
QString readyFilePath = cWorkingDir() + qsl("tupdates/temp/ready"), readyPath = cWorkingDir() + qsl("tupdates/temp");
|
||||
if (!QFile(readyFilePath).exists() || cExeName().isEmpty()) {
|
||||
if (QDir(cWorkingDir() + qsl("tupdates/ready")).exists() || QDir(cWorkingDir() + qsl("tupdates/temp")).exists()) {
|
||||
UpdateChecker::clearAll();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// check ready version
|
||||
QString versionPath = readyPath + qsl("/tdata/version");
|
||||
{
|
||||
QFile fVersion(versionPath);
|
||||
if (!fVersion.open(QIODevice::ReadOnly)) {
|
||||
LOG(("Update Error: cant read version file '%1'").arg(versionPath));
|
||||
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));
|
||||
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));
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
if (!cBetaVersion() || betaVersion <= cBetaVersion()) {
|
||||
LOG(("Update Error: cant install beta version %1 having beta version %2").arg(betaVersion).arg(cBetaVersion()));
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
} else if (versionNum <= AppVersion) {
|
||||
LOG(("Update Error: cant install version %1 having version %2").arg(versionNum).arg(AppVersion));
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
fVersion.close();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QString curUpdater = (cExeDir() + qsl("Updater.exe"));
|
||||
QFileInfo updater(cWorkingDir() + qsl("tupdates/temp/Updater.exe"));
|
||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
QString curUpdater = (cExeDir() + cExeName() + qsl("/Contents/Frameworks/Updater"));
|
||||
QFileInfo updater(cWorkingDir() + qsl("tupdates/temp/Telegram.app/Contents/Frameworks/Updater"));
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
QString curUpdater = (cExeDir() + qsl("Updater"));
|
||||
QFileInfo updater(cWorkingDir() + qsl("tupdates/temp/Updater"));
|
||||
#endif // Q_OS_LINUX
|
||||
if (!updater.exists()) {
|
||||
QFileInfo current(curUpdater);
|
||||
if (!current.exists()) {
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
if (!QFile(current.absoluteFilePath()).copy(updater.absoluteFilePath())) {
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
if (CopyFile(updater.absoluteFilePath().toStdWString().c_str(), curUpdater.toStdWString().c_str(), FALSE) == FALSE) {
|
||||
DWORD errorCode = GetLastError();
|
||||
if (errorCode == ERROR_ACCESS_DENIED) { // we are in write-protected dir, like Program Files
|
||||
cSetWriteProtected(true);
|
||||
return true;
|
||||
} else {
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (DeleteFile(updater.absoluteFilePath().toStdWString().c_str()) == FALSE) {
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
QDir().mkpath(QFileInfo(curUpdater).absolutePath());
|
||||
DEBUG_LOG(("Update Info: moving %1 to %2...").arg(updater.absoluteFilePath()).arg(curUpdater));
|
||||
if (!objc_moveFile(updater.absoluteFilePath(), curUpdater)) {
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
if (!linuxMoveFile(QFile::encodeName(updater.absoluteFilePath()).constData(), QFile::encodeName(curUpdater).constData())) {
|
||||
UpdateChecker::clearAll();
|
||||
return false;
|
||||
}
|
||||
#endif // Q_OS_LINUX
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
QString countBetaVersionSignature(uint64 version) { // duplicated in packer.cpp
|
||||
if (cBetaPrivateKey().isEmpty()) {
|
||||
LOG(("Error: Trying to count beta version signature without beta private key!"));
|
||||
return QString();
|
||||
}
|
||||
|
||||
QByteArray signedData = (qstr("TelegramBeta_") + QString::number(version, 16).toLower()).toUtf8();
|
||||
|
||||
static const int32 shaSize = 20, keySize = 128;
|
||||
|
||||
uchar sha1Buffer[shaSize];
|
||||
hashSha1(signedData.constData(), signedData.size(), sha1Buffer); // count sha1
|
||||
|
||||
uint32 siglen = 0;
|
||||
|
||||
RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast<char*>(cBetaPrivateKey().constData()), -1), 0, 0, 0);
|
||||
if (!prKey) {
|
||||
LOG(("Error: Could not read beta private key!"));
|
||||
return QString();
|
||||
}
|
||||
if (RSA_size(prKey) != keySize) {
|
||||
LOG(("Error: Bad beta private key size: %1").arg(RSA_size(prKey)));
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
QByteArray signature;
|
||||
signature.resize(keySize);
|
||||
if (RSA_sign(NID_sha1, (const uchar*)(sha1Buffer), shaSize, (uchar*)(signature.data()), &siglen, prKey) != 1) { // count signature
|
||||
LOG(("Error: Counting beta version signature failed!"));
|
||||
RSA_free(prKey);
|
||||
return QString();
|
||||
}
|
||||
RSA_free(prKey);
|
||||
|
||||
if (siglen != keySize) {
|
||||
LOG(("Error: Bad beta version signature length: %1").arg(siglen));
|
||||
return QString();
|
||||
}
|
||||
|
||||
signature = signature.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
signature = signature.replace('-', '8').replace('_', 'B');
|
||||
return QString::fromUtf8(signature.mid(19, 32));
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
#include <QtNetwork/QLocalServer>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
class UpdateChecker : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UpdateChecker(QThread *thread, const QString &url);
|
||||
|
||||
void unpackUpdate();
|
||||
|
||||
int32 ready();
|
||||
int32 size();
|
||||
|
||||
static void clearAll();
|
||||
|
||||
~UpdateChecker();
|
||||
|
||||
public slots:
|
||||
|
||||
void start();
|
||||
void partMetaGot();
|
||||
void partFinished(qint64 got, qint64 total);
|
||||
void partFailed(QNetworkReply::NetworkError e);
|
||||
void sendRequest();
|
||||
|
||||
private:
|
||||
void initOutput();
|
||||
|
||||
void fatalFail();
|
||||
|
||||
QString updateUrl;
|
||||
QNetworkAccessManager manager;
|
||||
QNetworkReply *reply;
|
||||
int32 already, full;
|
||||
QFile outputFile;
|
||||
|
||||
QMutex mutex;
|
||||
|
||||
};
|
||||
|
||||
bool checkReadyUpdate();
|
||||
|
||||
#else // TDESKTOP_DISABLE_AUTOUPDATE
|
||||
class UpdateChecker : public QObject {
|
||||
Q_OBJECT
|
||||
};
|
||||
|
||||
#endif // TDESKTOP_DISABLE_AUTOUPDATE
|
||||
|
||||
QString countBetaVersionSignature(uint64 version);
|
|
@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
namespace base {
|
||||
|
||||
// @todo use ranges-v3 here
|
||||
template <typename Range, typename Method>
|
||||
decltype(auto) for_each(Range &&range, Method &&method) {
|
||||
return std::for_each(
|
||||
|
|
|
@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <QSharedPointer>
|
||||
#include "base/type_traits.h"
|
||||
|
||||
namespace base {
|
||||
|
|
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "base/runtime_composer.h"
|
||||
|
||||
struct RuntimeComposerMetadatasMap {
|
||||
QMap<uint64, RuntimeComposerMetadata*> data;
|
||||
QMap<uint64_t, RuntimeComposerMetadata*> data;
|
||||
~RuntimeComposerMetadatasMap() {
|
||||
for_const (const RuntimeComposerMetadata *p, data) {
|
||||
delete p;
|
||||
|
@ -29,7 +29,7 @@ struct RuntimeComposerMetadatasMap {
|
|||
}
|
||||
};
|
||||
|
||||
const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask) {
|
||||
const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64_t mask) {
|
||||
static RuntimeComposerMetadatasMap RuntimeComposerMetadatas;
|
||||
static QMutex RuntimeComposerMetadatasMutex;
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ struct RuntimeComponent {
|
|||
}
|
||||
return MyIndex.loadAcquire() - 1;
|
||||
}
|
||||
static uint64 Bit() {
|
||||
static uint64_t Bit() {
|
||||
return (1ULL << Index());
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ protected:
|
|||
|
||||
class RuntimeComposerMetadata {
|
||||
public:
|
||||
RuntimeComposerMetadata(uint64 mask) : _mask(mask) {
|
||||
RuntimeComposerMetadata(uint64_t mask) : _mask(mask) {
|
||||
for (int i = 0; i != 64; ++i) {
|
||||
auto componentBit = (1ULL << i);
|
||||
if (_mask & componentBit) {
|
||||
|
@ -130,26 +130,26 @@ public:
|
|||
std::size_t offsets[64] = { 0 };
|
||||
int last = 64;
|
||||
|
||||
bool equals(uint64 mask) const {
|
||||
bool equals(uint64_t mask) const {
|
||||
return _mask == mask;
|
||||
}
|
||||
uint64 maskadd(uint64 mask) const {
|
||||
uint64_t maskadd(uint64_t mask) const {
|
||||
return _mask | mask;
|
||||
}
|
||||
uint64 maskremove(uint64 mask) const {
|
||||
uint64_t maskremove(uint64_t mask) const {
|
||||
return _mask & (~mask);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64 _mask;
|
||||
uint64_t _mask;
|
||||
|
||||
};
|
||||
|
||||
const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask);
|
||||
const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64_t mask);
|
||||
|
||||
class RuntimeComposer {
|
||||
public:
|
||||
RuntimeComposer(uint64 mask = 0) : _data(zerodata()) {
|
||||
RuntimeComposer(uint64_t mask = 0) : _data(zerodata()) {
|
||||
if (mask) {
|
||||
auto meta = GetRuntimeComposerMetadata(mask);
|
||||
|
||||
|
@ -212,7 +212,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
void UpdateComponents(uint64 mask = 0) {
|
||||
void UpdateComponents(uint64_t mask = 0) {
|
||||
if (!_meta()->equals(mask)) {
|
||||
RuntimeComposer tmp(mask);
|
||||
tmp.swap(*this);
|
||||
|
@ -228,10 +228,10 @@ protected:
|
|||
}
|
||||
}
|
||||
}
|
||||
void AddComponents(uint64 mask = 0) {
|
||||
void AddComponents(uint64_t mask = 0) {
|
||||
UpdateComponents(_meta()->maskadd(mask));
|
||||
}
|
||||
void RemoveComponents(uint64 mask = 0) {
|
||||
void RemoveComponents(uint64_t mask = 0) {
|
||||
UpdateComponents(_meta()->maskremove(mask));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,717 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace base {
|
||||
|
||||
template <typename Object, typename ParentObject = void>
|
||||
class virtual_object;
|
||||
|
||||
template <typename ConcreteMethod, typename ReturnType, typename ...Args>
|
||||
class virtual_method;
|
||||
|
||||
template <typename ConcreteMethod, typename BaseMethod>
|
||||
class virtual_override;
|
||||
|
||||
namespace virtual_methods {
|
||||
|
||||
struct child_entry;
|
||||
using is_parent_check = bool(*)(const child_entry &possible_parent);
|
||||
struct child_entry {
|
||||
is_parent_check check_is_parent;
|
||||
int *table_index;
|
||||
};
|
||||
using child_entries = std::vector<child_entry>;
|
||||
|
||||
// Recursive method to find if some class is a child of some other class.
|
||||
template <typename ConcreteObject>
|
||||
struct is_parent {
|
||||
static inline bool check(const child_entry &possible_parent) {
|
||||
// Generate a good error message if ConcreteObject is not a child of virtual_object<>.
|
||||
using all_objects_must_derive_virtual_object = typename ConcreteObject::virtual_object_parent;
|
||||
using ConcreteObjectParent = all_objects_must_derive_virtual_object;
|
||||
return (possible_parent.check_is_parent == &is_parent<ConcreteObject>::check)
|
||||
|| is_parent<ConcreteObjectParent>::check(possible_parent);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_parent<void> {
|
||||
static inline bool check(const child_entry &possible_parent) {
|
||||
return (possible_parent.check_is_parent == &is_parent<void>::check);
|
||||
}
|
||||
};
|
||||
|
||||
// Just force the compiler not to optimize away the object that "enforce" points at.
|
||||
inline void dont_optimize_away(void *enforce) {
|
||||
static volatile void *result = nullptr;
|
||||
if (result) {
|
||||
result = enforce;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type, Type Value>
|
||||
struct dont_optimize_away_struct {
|
||||
};
|
||||
|
||||
inline bool first_dispatch_fired(bool did_fire = false) {
|
||||
static bool fired = false;
|
||||
if (did_fire) {
|
||||
fired = true;
|
||||
}
|
||||
return fired;
|
||||
}
|
||||
|
||||
template <typename Object, void (*Creator)(const child_entry &)>
|
||||
class object_registrator {
|
||||
public:
|
||||
inline object_registrator() {
|
||||
Assert(!first_dispatch_fired());
|
||||
Creator(child_entry {
|
||||
&is_parent<Object>::check,
|
||||
&_index,
|
||||
});
|
||||
}
|
||||
static inline int &Index() {
|
||||
return _index;
|
||||
}
|
||||
|
||||
private:
|
||||
static int _index;
|
||||
|
||||
};
|
||||
|
||||
template <typename Object, void (*Creator)(const child_entry &)>
|
||||
int object_registrator<Object, Creator>::_index = -1;
|
||||
|
||||
class object_base {
|
||||
protected:
|
||||
virtual ~object_base() = default;
|
||||
|
||||
};
|
||||
|
||||
template <typename ...ConcreteArgs>
|
||||
struct multi_index_collector;
|
||||
template <int M, typename ...ConcreteArgs>
|
||||
struct override_key_collector_helper;
|
||||
template <typename Call, typename ...Args>
|
||||
struct table_fill_entry_helper;
|
||||
template <typename ...Args>
|
||||
struct table_count_size;
|
||||
|
||||
} // namespace virtual_methods
|
||||
|
||||
// This should be a base class for every child object in your hierarchy.
|
||||
// It registers this child in the root virtual_objects classes list.
|
||||
// Also it holds its own index in the classes list that is used for fast
|
||||
// invoking of methods from the virtual tables in different virtual_methods.
|
||||
template <typename Object, typename ParentObject>
|
||||
class virtual_object : public ParentObject {
|
||||
protected:
|
||||
virtual ~virtual_object() {
|
||||
virtual_methods::dont_optimize_away(&_virtual_object_registrator);
|
||||
}
|
||||
|
||||
private:
|
||||
using virtual_object_parent = ParentObject;
|
||||
|
||||
friend struct virtual_methods::is_parent<Object>;
|
||||
template <typename ...Args>
|
||||
friend struct virtual_methods::multi_index_collector;
|
||||
template <int M, typename ...ConcreteArgs>
|
||||
friend struct virtual_methods::override_key_collector_helper;
|
||||
template <typename OtherObject, typename OtherParentObject>
|
||||
friend class virtual_object;
|
||||
template <typename BaseMethod, typename ReturnType, typename ...Args>
|
||||
friend class virtual_method;
|
||||
|
||||
static inline void virtual_object_register_child(const virtual_methods::child_entry &entry) {
|
||||
return ParentObject::virtual_object_register_child(entry);
|
||||
}
|
||||
|
||||
using virtual_object_registrator = virtual_methods::object_registrator<Object, &virtual_object::virtual_object_register_child>;
|
||||
static virtual_object_registrator _virtual_object_registrator;
|
||||
using virtual_object_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct<virtual_object_registrator*, &_virtual_object_registrator>;
|
||||
|
||||
static inline int &virtual_object_child_index_static() {
|
||||
return virtual_object_registrator::Index();
|
||||
}
|
||||
int &virtual_object_child_index() override {
|
||||
return virtual_object_child_index_static();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Object, typename ParentObject>
|
||||
typename virtual_object<Object, ParentObject>::virtual_object_registrator virtual_object<Object, ParentObject>::_virtual_object_registrator = {};
|
||||
|
||||
// This should be a base class for the root of the whole hierarchy.
|
||||
// It holds the table of all child classes in a list.
|
||||
// This list is used by virtual_methods to generate virtual table.
|
||||
template <typename Object>
|
||||
class virtual_object<Object, void> : public virtual_methods::object_base {
|
||||
protected:
|
||||
virtual ~virtual_object() {
|
||||
virtual_methods::dont_optimize_away(&_virtual_object_registrator);
|
||||
}
|
||||
|
||||
private:
|
||||
using virtual_object_parent = void;
|
||||
|
||||
friend struct virtual_methods::is_parent<Object>;
|
||||
template <typename ...Args>
|
||||
friend struct virtual_methods::table_count_size;
|
||||
template <typename ...Args>
|
||||
friend struct virtual_methods::multi_index_collector;
|
||||
template <int M, typename ...ConcreteArgs>
|
||||
friend struct virtual_methods::override_key_collector_helper;
|
||||
template <typename Call, typename ...Args>
|
||||
friend struct virtual_methods::table_fill_entry_helper;
|
||||
template <typename OtherObject, typename OtherParentObject>
|
||||
friend class virtual_object;
|
||||
template <typename BaseMethod, typename ReturnType, typename ...Args>
|
||||
friend class virtual_method;
|
||||
|
||||
static inline virtual_methods::child_entries &virtual_object_get_child_entries() {
|
||||
static virtual_methods::child_entries entries;
|
||||
return entries;
|
||||
}
|
||||
|
||||
// Registers a new child class.
|
||||
// After that on the next call to virtual_method::virtual_method_prepare_table() will
|
||||
// generate a new virtual table for that virtual method.
|
||||
static inline void virtual_object_register_child(const virtual_methods::child_entry &entry) {
|
||||
auto &entries = virtual_object_get_child_entries();
|
||||
for (auto i = entries.begin(), e = entries.end(); i != e; ++i) {
|
||||
if (entry.check_is_parent(*i)) {
|
||||
*entry.table_index = (i - entries.begin());
|
||||
i = entries.insert(i, entry);
|
||||
for (++i, e = entries.end(); i != e; ++i) {
|
||||
++*(i->table_index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
*entry.table_index = entries.size();
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
||||
using virtual_object_registrator = virtual_methods::object_registrator<Object, &virtual_object::virtual_object_register_child>;
|
||||
static virtual_object_registrator _virtual_object_registrator;
|
||||
using virtual_object_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct<virtual_object_registrator*, &_virtual_object_registrator>;
|
||||
|
||||
static inline int &virtual_object_child_index_static() {
|
||||
return virtual_object_registrator::Index();
|
||||
}
|
||||
virtual int &virtual_object_child_index() {
|
||||
return virtual_object_child_index_static();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Object>
|
||||
typename virtual_object<Object, void>::virtual_object_registrator virtual_object<Object, void>::_virtual_object_registrator = {};
|
||||
|
||||
namespace virtual_methods {
|
||||
|
||||
template <typename Arg>
|
||||
struct is_virtual_argument : public std::integral_constant<bool,
|
||||
base::type_traits<Arg>::is_pointer::value
|
||||
? std::is_base_of<object_base, typename base::type_traits<Arg>::pointed_type>::value
|
||||
: false> {
|
||||
};
|
||||
|
||||
template <int N, int Instance>
|
||||
class multi_int_wrap {
|
||||
public:
|
||||
inline multi_int_wrap(int *indices) : _indices(indices) {
|
||||
}
|
||||
inline multi_int_wrap<N - 1, Instance> subindex() const {
|
||||
static_assert(N > 0, "Wrong multi_int_wrap created!");
|
||||
return multi_int_wrap<N - 1, Instance>(_indices + 1);
|
||||
}
|
||||
inline int ¤t() const {
|
||||
return *_indices;
|
||||
}
|
||||
|
||||
private:
|
||||
int *_indices;
|
||||
|
||||
};
|
||||
|
||||
template <int Instance>
|
||||
class multi_int_wrap<0, Instance> {
|
||||
public:
|
||||
inline multi_int_wrap(int *indices) {
|
||||
}
|
||||
inline int current() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <int N>
|
||||
using multi_index_wrap = multi_int_wrap<N, 0>;
|
||||
template <int N>
|
||||
using multi_size_wrap = multi_int_wrap<N, 1>;
|
||||
|
||||
template <typename ConcreteArg, typename ...ConcreteArgs>
|
||||
struct multi_index_collector<ConcreteArg, ConcreteArgs...> {
|
||||
static constexpr int N = sizeof...(ConcreteArgs) + 1;
|
||||
static inline void call(multi_index_wrap<N> indices, ConcreteArg arg, ConcreteArgs... args) {
|
||||
indices.current() = computeIndex(is_virtual_argument<ConcreteArg>(), arg);
|
||||
multi_index_collector<ConcreteArgs...>::call(indices.subindex(), args...);
|
||||
}
|
||||
|
||||
static inline int computeIndex(std::integral_constant<bool, false>, ConcreteArg arg) {
|
||||
return 0;
|
||||
}
|
||||
static inline int computeIndex(std::integral_constant<bool, true>, ConcreteArg arg) {
|
||||
return arg->virtual_object_child_index();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct multi_index_collector<> {
|
||||
static inline void call(multi_index_wrap<0> indices) {
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
class override_key;
|
||||
|
||||
template <int N, int Instance>
|
||||
class multi_int {
|
||||
public:
|
||||
inline multi_int_wrap<N, Instance> data_wrap() {
|
||||
return multi_int_wrap<N, Instance>(_indices);
|
||||
}
|
||||
|
||||
template <typename ...ConcreteArgs>
|
||||
static inline multi_int<N, Instance> collect(ConcreteArgs... args) {
|
||||
multi_int<N, Instance> result;
|
||||
multi_index_collector<ConcreteArgs...>::call(result.data_wrap(), args...);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
memset(_indices, 0, sizeof(_indices));
|
||||
}
|
||||
|
||||
inline int value(int index) const {
|
||||
return _indices[index];
|
||||
}
|
||||
|
||||
inline void copy(multi_int_wrap<N, Instance> other) {
|
||||
memcpy(_indices, &other.current(), sizeof(_indices));
|
||||
}
|
||||
|
||||
private:
|
||||
int _indices[N] = { 0 };
|
||||
friend class override_key<N>;
|
||||
|
||||
};
|
||||
|
||||
template <int N>
|
||||
using multi_index = multi_int<N, 0>;
|
||||
template <int N>
|
||||
using multi_size = multi_int<N, 1>;
|
||||
|
||||
template <typename Call, int N>
|
||||
class table_data_wrap {
|
||||
public:
|
||||
inline table_data_wrap(Call *data, multi_size_wrap<N> size) : _data(data), _size(size) {
|
||||
}
|
||||
inline table_data_wrap<Call, N - 1> operator[](int index) const {
|
||||
return table_data_wrap<Call, N - 1>(_data + index * _size.subindex().current(), _size.subindex());
|
||||
}
|
||||
inline Call &operator[](multi_index_wrap<N> index) const {
|
||||
return (*this)[index.current()][index.subindex()];
|
||||
}
|
||||
inline int size() const {
|
||||
return count_size(std::integral_constant<int,N>());
|
||||
}
|
||||
|
||||
private:
|
||||
template <int M>
|
||||
inline int count_size(std::integral_constant<int,M>) const {
|
||||
return _size.current() / _size.subindex().current();
|
||||
}
|
||||
inline int count_size(std::integral_constant<int,1>) const {
|
||||
return _size.current();
|
||||
}
|
||||
|
||||
Call *_data;
|
||||
multi_size_wrap<N> _size;
|
||||
|
||||
};
|
||||
|
||||
template <typename Call>
|
||||
class table_data_wrap<Call, 0> {
|
||||
public:
|
||||
inline table_data_wrap(Call *data, multi_size_wrap<0> size) : _data(data) {
|
||||
}
|
||||
inline Call &operator[](multi_index_wrap<0> index) const {
|
||||
return *_data;
|
||||
}
|
||||
|
||||
private:
|
||||
Call *_data;
|
||||
|
||||
};
|
||||
|
||||
template <typename Call, int N>
|
||||
class table_data_wrap;
|
||||
|
||||
template <typename Arg, typename ...Args>
|
||||
struct table_count_size<Arg, Args...> {
|
||||
static constexpr int N = sizeof...(Args) + 1;
|
||||
static inline void call(multi_size_wrap<N> index) {
|
||||
auto subindex = index.subindex();
|
||||
table_count_size<Args...>::call(subindex);
|
||||
index.current() = count(is_virtual_argument<Arg>()) * subindex.current();
|
||||
}
|
||||
|
||||
static inline int count(std::integral_constant<bool, false>) {
|
||||
return 1;
|
||||
}
|
||||
static inline int count(std::integral_constant<bool, true>) {
|
||||
return base::type_traits<Arg>::pointed_type::virtual_object_get_child_entries().size();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct table_count_size<> {
|
||||
static inline void call(multi_size_wrap<0> index) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Call, int N>
|
||||
class table_data {
|
||||
public:
|
||||
inline table_data_wrap<Call, N> data_wrap() {
|
||||
return table_data_wrap<Call, N>(_data.data(), _size.data_wrap());
|
||||
}
|
||||
|
||||
inline Call &operator[](multi_index<N> index) {
|
||||
int flat_index = 0;
|
||||
for (int i = 0; i != N - 1; ++i) {
|
||||
flat_index += _size.value(i + 1) * index.value(i);
|
||||
}
|
||||
flat_index += index.value(N - 1);
|
||||
return _data[flat_index];
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline bool changed() {
|
||||
if (!_data.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
multi_size<N> size;
|
||||
table_count_size<Args...>::call(size.data_wrap());
|
||||
_size = size;
|
||||
_data.resize(_size.value(0), nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Call> _data;
|
||||
multi_size<N> _size;
|
||||
|
||||
};
|
||||
|
||||
template <typename Call>
|
||||
class table_data<Call, 0> {
|
||||
public:
|
||||
inline table_data_wrap<Call, 0> data_wrap() {
|
||||
return table_data_wrap<Call, 0>(&_call, multi_size_wrap<0>(nullptr));
|
||||
}
|
||||
|
||||
inline Call &operator[](multi_index<0> index) {
|
||||
return _call;
|
||||
}
|
||||
|
||||
inline bool changed() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Call _call = nullptr;
|
||||
|
||||
};
|
||||
|
||||
template <typename Call, typename ...Args>
|
||||
struct table_fill_entry_helper;
|
||||
|
||||
template <typename Call, typename Arg, typename ...Args>
|
||||
struct table_fill_entry_helper<Call, Arg, Args...> {
|
||||
static constexpr int N = sizeof...(Args) + 1;
|
||||
|
||||
static inline bool call(table_data_wrap<Call, N> table, multi_index_wrap<N> index, Call &fill) {
|
||||
auto start = index.current();
|
||||
for (auto i = start, count = table.size(); i != count; ++i) {
|
||||
auto foundGoodType = good(is_virtual_argument<Arg>(), start, index.current());
|
||||
if (foundGoodType) {
|
||||
index.current() = i;
|
||||
if (table_fill_entry_helper<Call, Args...>::call(table[i], index.subindex(), fill)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
index.current() = start;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool good(std::integral_constant<bool,false>, int start, int current) {
|
||||
return (start == current);
|
||||
}
|
||||
static inline bool good(std::integral_constant<bool,true>, int start, int current) {
|
||||
using BaseObject = typename base::type_traits<Arg>::pointed_type;
|
||||
auto &entries = BaseObject::virtual_object_get_child_entries();
|
||||
return (start == current) || entries[start].check_is_parent(entries[current]);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Call>
|
||||
struct table_fill_entry_helper<Call> {
|
||||
static inline bool call(table_data_wrap<Call, 0> table, multi_index_wrap<0> index, Call &fill) {
|
||||
if (auto overrideMethod = table[index]) {
|
||||
fill = overrideMethod;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Call, int N>
|
||||
struct table_fill_entry;
|
||||
|
||||
template <typename ReturnType, int N, typename BaseMethod, typename ...Args>
|
||||
struct table_fill_entry<ReturnType(*)(BaseMethod*, Args...), N> {
|
||||
using Call = ReturnType(*)(BaseMethod*, Args...);
|
||||
static inline void call(table_data_wrap<Call, N> table, multi_index_wrap<N> index, Call &fill) {
|
||||
table_fill_entry_helper<Call, Args...>::call(table, index, fill);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Call, int N>
|
||||
inline void fill_entry(table_data_wrap<Call, N> table, multi_index_wrap<N> index, Call &fill) {
|
||||
return virtual_methods::table_fill_entry<Call, N>::call(table, index, fill);
|
||||
}
|
||||
|
||||
template <int M, typename ...ConcreteArgs>
|
||||
struct override_key_collector_helper;
|
||||
|
||||
template <int M, typename ConcreteArg, typename ...ConcreteArgs>
|
||||
struct override_key_collector_helper<M, ConcreteArg, ConcreteArgs...> {
|
||||
static inline void call(int **indices) {
|
||||
setValue(is_virtual_argument<ConcreteArg>(), indices);
|
||||
override_key_collector_helper<M + 1, ConcreteArgs...>::call(indices);
|
||||
}
|
||||
|
||||
static inline void setValue(std::integral_constant<bool,false>, int **indices) {
|
||||
indices[M] = nullptr;
|
||||
}
|
||||
static inline void setValue(std::integral_constant<bool,true>, int **indices) {
|
||||
using ConcreteObject = typename base::type_traits<ConcreteArg>::pointed_type;
|
||||
using IsParentCheckStruct = is_parent<ConcreteObject>;
|
||||
using IsParentCheckPointer = decltype(&IsParentCheckStruct::check);
|
||||
using override_key_collector_dont_optimize_away = dont_optimize_away_struct<IsParentCheckPointer, &IsParentCheckStruct::check>;
|
||||
override_key_collector_dont_optimize_away dont_optimize_away_object;
|
||||
(void)dont_optimize_away_object;
|
||||
|
||||
// Check that is_parent<> can be instantiated.
|
||||
// So every ConcreteObject is a valid child of virtual_object<>.
|
||||
dont_optimize_away(reinterpret_cast<void*>(&IsParentCheckStruct::check));
|
||||
indices[M] = &ConcreteObject::virtual_object_child_index_static();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <int M>
|
||||
struct override_key_collector_helper<M> {
|
||||
static inline void call(int **indices) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CallSignature>
|
||||
struct override_key_collector;
|
||||
|
||||
template <typename ReturnType, typename BaseMethod, typename ...ConcreteArgs>
|
||||
struct override_key_collector<ReturnType(*)(BaseMethod, ConcreteArgs...)> {
|
||||
static inline void call(int **indices) {
|
||||
override_key_collector_helper<0, ConcreteArgs...>::call(indices);
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
class override_key {
|
||||
public:
|
||||
inline multi_index<N> value() const {
|
||||
multi_index<N> result;
|
||||
for (int i = 0; i != N; ++i) {
|
||||
auto pointer = _indices[i];
|
||||
result._indices[i] = (pointer ? *pointer : 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
friend inline bool operator<(const override_key &k1, const override_key &k2) {
|
||||
for (int i = 0; i != N; ++i) {
|
||||
auto pointer1 = k1._indices[i], pointer2 = k2._indices[i];
|
||||
if (pointer1 < pointer2) {
|
||||
return true;
|
||||
} else if (pointer1 > pointer2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename CallSignature>
|
||||
inline void collect() {
|
||||
override_key_collector<CallSignature>::call(_indices);
|
||||
}
|
||||
|
||||
private:
|
||||
int *_indices[N];
|
||||
|
||||
};
|
||||
|
||||
template <typename BaseMethod, typename ConcreteMethod, typename CallSignature, typename ...Args>
|
||||
struct static_cast_helper;
|
||||
|
||||
template <typename BaseMethod, typename ConcreteMethod, typename ReturnType, typename ...ConcreteArgs, typename ...Args>
|
||||
struct static_cast_helper<BaseMethod, ConcreteMethod, ReturnType(*)(BaseMethod *, ConcreteArgs...), Args...> {
|
||||
static inline ReturnType call(BaseMethod *context, Args ...args) {
|
||||
return ConcreteMethod::call(context, static_cast<ConcreteArgs>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace virtual_methods
|
||||
|
||||
// This is a base class for all your virtual methods.
|
||||
// It dispatches a call to one of the registered virtual_overrides
|
||||
// or calls the fallback method of the BaseMethod class.
|
||||
template <typename BaseMethod, typename ReturnType, typename ...Args>
|
||||
class virtual_method {
|
||||
static constexpr int N = sizeof...(Args);
|
||||
using virtual_method_call = ReturnType(*)(BaseMethod *context, Args... args);
|
||||
|
||||
public:
|
||||
inline ReturnType call(Args... args) {
|
||||
auto context = static_cast<BaseMethod*>(this);
|
||||
auto index = virtual_methods::multi_index<N>::collect(args...);
|
||||
auto &table = virtual_method_prepare_table();
|
||||
auto &entry = table[index];
|
||||
if (!entry) {
|
||||
virtual_methods::fill_entry(table.data_wrap(), index.data_wrap(), entry);
|
||||
if (!entry) {
|
||||
entry = &virtual_method::virtual_method_base_instance;
|
||||
}
|
||||
}
|
||||
return (*entry)(context, args...);
|
||||
}
|
||||
|
||||
private:
|
||||
// This map of methods contains only the original registered overrides.
|
||||
using virtual_method_override_key = virtual_methods::override_key<N>;
|
||||
using virtual_method_override_map = std::map<virtual_method_override_key, virtual_method_call>;
|
||||
static inline virtual_method_override_map &virtual_method_get_override_map() {
|
||||
static virtual_method_override_map override_map;
|
||||
return override_map;
|
||||
}
|
||||
|
||||
// This method generates and returns a virtual table which holds a method
|
||||
// for any child in the hierarchy or nullptr if none of the virtual_overrides fit.
|
||||
using virtual_method_table_data = virtual_methods::table_data<virtual_method_call, N>;
|
||||
static inline virtual_method_table_data &virtual_method_get_table_data() {
|
||||
static virtual_method_table_data virtual_table;
|
||||
return virtual_table;
|
||||
}
|
||||
|
||||
static inline virtual_method_table_data &virtual_method_prepare_table() {
|
||||
auto &virtual_table = virtual_method_get_table_data();
|
||||
if (virtual_table.template changed<Args...>()) {
|
||||
virtual_methods::first_dispatch_fired(true);
|
||||
|
||||
// The class hierarchy has changed - we need to generate the virtual table once again.
|
||||
// All other handlers will be placed if they're called.
|
||||
for (auto &i : virtual_method_get_override_map()) {
|
||||
virtual_table[i.first.value()] = i.second;
|
||||
}
|
||||
}
|
||||
return virtual_table;
|
||||
}
|
||||
|
||||
static ReturnType virtual_method_base_instance(BaseMethod *context, Args... args) {
|
||||
return BaseMethod::default_call(context, args...);
|
||||
}
|
||||
|
||||
template <typename ConcreteMethod>
|
||||
static ReturnType virtual_method_override_instance(BaseMethod *context, Args... args) {
|
||||
return virtual_methods::static_cast_helper<BaseMethod, ConcreteMethod, decltype(&ConcreteMethod::call), Args...>::call(context, args...);
|
||||
}
|
||||
|
||||
template <typename ConcreteMethod>
|
||||
static inline void virtual_method_register_override() {
|
||||
auto call = &virtual_method_override_instance<ConcreteMethod>;
|
||||
|
||||
virtual_methods::override_key<N> key;
|
||||
key.template collect<decltype(&ConcreteMethod::call)>();
|
||||
|
||||
virtual_method_get_override_map()[key] = call;
|
||||
}
|
||||
|
||||
template <typename ConcreteMethod, typename OtherBaseMethod>
|
||||
friend class virtual_override;
|
||||
|
||||
};
|
||||
|
||||
template <typename ConcreteMethod, typename BaseMethod>
|
||||
class virtual_override {
|
||||
protected:
|
||||
virtual ~virtual_override() {
|
||||
virtual_methods::dont_optimize_away(&_virtual_override_registrator);
|
||||
}
|
||||
|
||||
private:
|
||||
class virtual_override_registrator {
|
||||
public:
|
||||
inline virtual_override_registrator() {
|
||||
Assert(!virtual_methods::first_dispatch_fired());
|
||||
BaseMethod::template virtual_method_register_override<ConcreteMethod>();
|
||||
}
|
||||
|
||||
};
|
||||
static virtual_override_registrator _virtual_override_registrator;
|
||||
using virtual_override_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct<virtual_override_registrator*, &_virtual_override_registrator>;
|
||||
|
||||
};
|
||||
|
||||
template <typename ConcreteMethod, typename BaseMethod>
|
||||
typename virtual_override<ConcreteMethod, BaseMethod>::virtual_override_registrator virtual_override<ConcreteMethod, BaseMethod>::_virtual_override_registrator = {};
|
||||
|
||||
} // namespace base
|
|
@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
// @todo replace this with std::experimental::observer_ptr
|
||||
|
||||
namespace base {
|
||||
|
||||
class enable_weak_from_this;
|
||||
|
|
|
@ -23,8 +23,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "zip.h"
|
||||
#include "unzip.h"
|
||||
#include "minizip/zip.h"
|
||||
#include "minizip/unzip.h"
|
||||
|
||||
namespace zlib {
|
||||
namespace internal {
|
||||
|
@ -243,7 +243,7 @@ public:
|
|||
}
|
||||
|
||||
auto size = fileInfo.uncompressed_size;
|
||||
if (size > static_cast<uint32>(fileSizeLimit)) {
|
||||
if (size > static_cast<uint32_t>(fileSizeLimit)) {
|
||||
if (_error == UNZ_OK) _error = -1;
|
||||
LOG(("Error: current file is too large (should be less than %1, got %2) in a zip file.").arg(fileSizeLimit).arg(size));
|
||||
return QByteArray();
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# Unused: cotire PCH needs more rigid structure.
|
||||
# To do: get rid of the PCH requirement for more flexible build structure.
|
||||
add_library(tg_boxes STATIC
|
||||
about_box.cpp
|
||||
abstract_box.cpp
|
||||
add_contact_box.cpp
|
||||
autolock_box.cpp
|
||||
background_box.cpp
|
||||
calendar_box.cpp
|
||||
change_phone_box.cpp
|
||||
confirm_box.cpp
|
||||
confirm_phone_box.cpp
|
||||
connection_box.cpp
|
||||
download_path_box.cpp
|
||||
edit_color_box.cpp
|
||||
edit_participant_box.cpp
|
||||
edit_privacy_box.cpp
|
||||
language_box.cpp
|
||||
local_storage_box.cpp
|
||||
mute_settings_box.cpp
|
||||
notifications_box.cpp
|
||||
passcode_box.cpp
|
||||
peer_list_box.cpp
|
||||
peer_list_controllers.cpp
|
||||
photo_crop_box.cpp
|
||||
rate_call_box.cpp
|
||||
report_box.cpp
|
||||
self_destruction_box.cpp
|
||||
send_files_box.cpp
|
||||
sessions_box.cpp
|
||||
share_box.cpp
|
||||
sticker_set_box.cpp
|
||||
stickers_box.cpp
|
||||
username_box.cpp
|
||||
)
|
||||
add_dependencies(tg_boxes boxes_styles_output)
|
|
@ -23,7 +23,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "autoupdater.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "application.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
@ -61,23 +60,7 @@ void AboutBox::resizeEvent(QResizeEvent *e) {
|
|||
}
|
||||
|
||||
void AboutBox::showVersionHistory() {
|
||||
if (cRealBetaVersion()) {
|
||||
auto url = qsl("https://tdesktop.com/");
|
||||
switch (cPlatform()) {
|
||||
case dbipWindows: url += qsl("win/%1.zip"); break;
|
||||
case dbipMac: url += qsl("mac/%1.zip"); break;
|
||||
case dbipMacOld: url += qsl("mac32/%1.zip"); break;
|
||||
case dbipLinux32: url += qsl("linux32/%1.tar.xz"); break;
|
||||
case dbipLinux64: url += qsl("linux/%1.tar.xz"); break;
|
||||
}
|
||||
url = url.arg(qsl("tbeta%1_%2").arg(cRealBetaVersion()).arg(countBetaVersionSignature(cRealBetaVersion())));
|
||||
|
||||
Application::clipboard()->setText(url);
|
||||
|
||||
Ui::show(Box<InformBox>("The link to the current private beta version of Telegram Desktop was copied to the clipboard."));
|
||||
} else {
|
||||
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/changelog"));
|
||||
}
|
||||
QDesktopServices::openUrl(qsl("https://desktop.telegram.org/changelog"));
|
||||
}
|
||||
|
||||
void AboutBox::keyPressEvent(QKeyEvent *e) {
|
||||
|
|
|
@ -104,7 +104,7 @@ void BoxContent::onDraggingScrollDelta(int delta) {
|
|||
}
|
||||
|
||||
void BoxContent::onDraggingScrollTimer() {
|
||||
auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32(MaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32(MaxScrollSpeed));
|
||||
auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32_t(MaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32_t(MaxScrollSpeed));
|
||||
_scroll->scrollToY(_scroll->scrollTop() + delta);
|
||||
}
|
||||
|
||||
|
|
|
@ -221,11 +221,11 @@ void AddContactBox::onSave() {
|
|||
}
|
||||
_sentName = firstName;
|
||||
if (_user) {
|
||||
_contactId = rand_value<uint64>();
|
||||
_contactId = rand_value<uint64_t>();
|
||||
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)), rpcDone(&AddContactBox::onSaveUserDone), rpcFail(&AddContactBox::onSaveUserFail));
|
||||
} else {
|
||||
_contactId = rand_value<uint64>();
|
||||
_contactId = rand_value<uint64_t>();
|
||||
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)), rpcDone(&AddContactBox::onImportDone));
|
||||
}
|
||||
|
@ -745,8 +745,8 @@ void SetupChannelBox::onChange() {
|
|||
}
|
||||
_checkTimer.stop();
|
||||
} else {
|
||||
int32 len = name.size();
|
||||
for (int32 i = 0; i < len; ++i) {
|
||||
int32_t len = name.size();
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
QChar ch = name.at(i);
|
||||
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '_') {
|
||||
if (_errorText != lang(lng_create_channel_link_bad_symbols)) {
|
||||
|
@ -1498,8 +1498,8 @@ void RevokePublicLinkBox::Inner::paintChat(Painter &p, const ChatRow &row, bool
|
|||
|
||||
p.setPen(st::contactsNameFg);
|
||||
|
||||
int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
int32 namew = width() - namex - st::contactsPadding.right() - (_revokeWidth + st::contactsCheckPosition.x() * 2);
|
||||
int32_t namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
int32_t namew = width() - namex - st::contactsPadding.right() - (_revokeWidth + st::contactsCheckPosition.x() * 2);
|
||||
if (peer->isVerified()) {
|
||||
auto icon = &st::dialogsVerifiedIcon;
|
||||
namew -= icon->width();
|
||||
|
|
|
@ -84,7 +84,7 @@ private:
|
|||
bool _retrying = false;
|
||||
bool _invertOrder = false;
|
||||
|
||||
uint64 _contactId = 0;
|
||||
uint64_t _contactId = 0;
|
||||
|
||||
mtpRequestId _addRequest = 0;
|
||||
QString _sentName;
|
||||
|
@ -185,7 +185,7 @@ private:
|
|||
std::shared_ptr<Ui::RadioenumGroup<Privacy>> _privacyGroup;
|
||||
object_ptr<Ui::Radioenum<Privacy>> _public;
|
||||
object_ptr<Ui::Radioenum<Privacy>> _private;
|
||||
int32 _aboutPublicWidth, _aboutPublicHeight;
|
||||
int32_t _aboutPublicWidth, _aboutPublicHeight;
|
||||
Text _aboutPublic, _aboutPrivate;
|
||||
|
||||
object_ptr<Ui::UsernameInput> _link;
|
||||
|
|
|
@ -115,10 +115,10 @@ void BackgroundBox::Inner::gotWallpapers(const MTPVector<MTPWallPaper> &result)
|
|||
auto &d = w.c_wallPaper();
|
||||
auto &sizes = d.vsizes.v;
|
||||
const MTPPhotoSize *thumb = 0, *full = 0;
|
||||
int32 thumbLevel = -1, fullLevel = -1;
|
||||
int32_t thumbLevel = -1, fullLevel = -1;
|
||||
for (QVector<MTPPhotoSize>::const_iterator j = sizes.cbegin(), e = sizes.cend(); j != e; ++j) {
|
||||
char size = 0;
|
||||
int32 w = 0, h = 0;
|
||||
int32_t w = 0, h = 0;
|
||||
switch (j->type()) {
|
||||
case mtpc_photoSize: {
|
||||
auto &s = j->c_photoSize().vtype.v;
|
||||
|
@ -136,7 +136,7 @@ void BackgroundBox::Inner::gotWallpapers(const MTPVector<MTPWallPaper> &result)
|
|||
}
|
||||
if (!size || !w || !h) continue;
|
||||
|
||||
int32 newThumbLevel = qAbs((st::backgroundSize.width() * cIntRetinaFactor()) - w), newFullLevel = qAbs(2560 - w);
|
||||
int32_t newThumbLevel = qAbs((st::backgroundSize.width() * cIntRetinaFactor()) - w), newFullLevel = qAbs(2560 - w);
|
||||
if (thumbLevel < 0 || newThumbLevel < thumbLevel) {
|
||||
thumbLevel = newThumbLevel;
|
||||
thumb = &(*j);
|
||||
|
|
|
@ -115,7 +115,7 @@ private:
|
|||
not_null<ChannelData*> _channel;
|
||||
|
||||
Text _text;
|
||||
int32 _textWidth, _textHeight;
|
||||
int32_t _textWidth, _textHeight;
|
||||
|
||||
QRect _invitationLink;
|
||||
bool _linkOver = false;
|
||||
|
@ -141,7 +141,7 @@ private:
|
|||
|
||||
ChatData *_chat;
|
||||
Text _text, _note;
|
||||
int32 _textWidth, _textHeight;
|
||||
int32_t _textWidth, _textHeight;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
void AutoDownloadBox::onSave() {
|
||||
bool changed = false;
|
||||
int32 autoDownloadPhoto = (_photoPrivate->checked() ? 0 : dbiadNoPrivate) | (_photoGroups->checked() ? 0 : dbiadNoGroups);
|
||||
int32_t autoDownloadPhoto = (_photoPrivate->checked() ? 0 : dbiadNoPrivate) | (_photoGroups->checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadPhoto() != autoDownloadPhoto) {
|
||||
bool enabledPrivate = ((cAutoDownloadPhoto() & dbiadNoPrivate) && !(autoDownloadPhoto & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadPhoto() & dbiadNoGroups) && !(autoDownloadPhoto & dbiadNoGroups));
|
||||
|
@ -316,7 +316,7 @@ void AutoDownloadBox::onSave() {
|
|||
}
|
||||
changed = true;
|
||||
}
|
||||
int32 autoDownloadAudio = (_audioPrivate->checked() ? 0 : dbiadNoPrivate) | (_audioGroups->checked() ? 0 : dbiadNoGroups);
|
||||
int32_t autoDownloadAudio = (_audioPrivate->checked() ? 0 : dbiadNoPrivate) | (_audioGroups->checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadAudio() != autoDownloadAudio) {
|
||||
bool enabledPrivate = ((cAutoDownloadAudio() & dbiadNoPrivate) && !(autoDownloadAudio & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
|
||||
|
@ -330,7 +330,7 @@ void AutoDownloadBox::onSave() {
|
|||
}
|
||||
changed = true;
|
||||
}
|
||||
int32 autoDownloadGif = (_gifPrivate->checked() ? 0 : dbiadNoPrivate) | (_gifGroups->checked() ? 0 : dbiadNoGroups);
|
||||
int32_t autoDownloadGif = (_gifPrivate->checked() ? 0 : dbiadNoPrivate) | (_gifGroups->checked() ? 0 : dbiadNoGroups);
|
||||
if (cAutoDownloadGif() != autoDownloadGif) {
|
||||
bool enabledPrivate = ((cAutoDownloadGif() & dbiadNoPrivate) && !(autoDownloadGif & dbiadNoPrivate));
|
||||
bool enabledGroups = ((cAutoDownloadGif() & dbiadNoGroups) && !(autoDownloadGif & dbiadNoGroups));
|
||||
|
|
|
@ -30,10 +30,10 @@ class EditColorBox::Picker : public TWidget {
|
|||
public:
|
||||
Picker(QWidget *parent, QColor color);
|
||||
|
||||
float64 valueX() const {
|
||||
double valueX() const {
|
||||
return _x;
|
||||
}
|
||||
float64 valueY() const {
|
||||
double valueY() const {
|
||||
return _y;
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,8 @@ private:
|
|||
|
||||
QImage _palette;
|
||||
bool _paletteInvalidated = false;
|
||||
float64 _x = 0.;
|
||||
float64 _y = 0.;
|
||||
double _x = 0.;
|
||||
double _y = 0.;
|
||||
|
||||
bool _choosing = false;
|
||||
base::Observable<void> _changed;
|
||||
|
@ -150,8 +150,8 @@ void EditColorBox::Picker::preparePalette() {
|
|||
_paletteInvalidated = false;
|
||||
|
||||
auto size = _palette.width();
|
||||
auto ints = reinterpret_cast<uint32*>(_palette.bits());
|
||||
auto intsAddPerLine = (_palette.bytesPerLine() - size * sizeof(uint32)) / sizeof(uint32);
|
||||
auto ints = reinterpret_cast<uint32_t*>(_palette.bits());
|
||||
auto intsAddPerLine = (_palette.bytesPerLine() - size * sizeof(uint32_t)) / sizeof(uint32_t);
|
||||
|
||||
constexpr auto Large = 1024 * 1024;
|
||||
constexpr auto LargeBit = 20; // n / Large == (n >> LargeBit)
|
||||
|
@ -190,8 +190,8 @@ void EditColorBox::Picker::preparePalette() {
|
|||
}
|
||||
|
||||
void EditColorBox::Picker::updateCurrentPoint(QPoint localPosition) {
|
||||
auto x = snap(localPosition.x(), 0, width()) / float64(width());
|
||||
auto y = snap(localPosition.y(), 0, height()) / float64(height());
|
||||
auto x = snap(localPosition.x(), 0, width()) / double(width());
|
||||
auto y = snap(localPosition.y(), 0, height()) / double(height());
|
||||
if (_x != x || _y != y) {
|
||||
_x = x;
|
||||
_y = y;
|
||||
|
@ -236,10 +236,10 @@ public:
|
|||
base::Observable<void> &changed() {
|
||||
return _changed;
|
||||
}
|
||||
float64 value() const {
|
||||
double value() const {
|
||||
return _value;
|
||||
}
|
||||
void setValue(float64 value) {
|
||||
void setValue(double value) {
|
||||
_value = snap(value, 0., 1.);
|
||||
update();
|
||||
}
|
||||
|
@ -256,8 +256,8 @@ protected:
|
|||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
float64 valueFromColor(QColor color) const;
|
||||
float64 valueFromHue(int hue) const;
|
||||
double valueFromColor(QColor color) const;
|
||||
double valueFromHue(int hue) const;
|
||||
bool isHorizontal() const {
|
||||
return (_direction == Direction::Horizontal);
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ private:
|
|||
Type _type = Type::Hue;
|
||||
|
||||
QColor _color;
|
||||
float64 _value = 0;
|
||||
double _value = 0;
|
||||
|
||||
QImage _mask;
|
||||
QPixmap _pixmap;
|
||||
|
@ -339,8 +339,8 @@ void EditColorBox::Slider::generatePixmap() {
|
|||
auto size = (isHorizontal() ? width() : height()) * cIntRetinaFactor();
|
||||
auto image = QImage(size, cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(cRetinaFactor());
|
||||
auto ints = reinterpret_cast<uint32*>(image.bits());
|
||||
auto intsPerLine = image.bytesPerLine() / sizeof(uint32);
|
||||
auto ints = reinterpret_cast<uint32_t*>(image.bits());
|
||||
auto intsPerLine = image.bytesPerLine() / sizeof(uint32_t);
|
||||
auto intsPerLineAdded = intsPerLine - size;
|
||||
|
||||
constexpr auto Large = 1024 * 1024;
|
||||
|
@ -408,11 +408,11 @@ void EditColorBox::Slider::colorUpdated() {
|
|||
update();
|
||||
}
|
||||
|
||||
float64 EditColorBox::Slider::valueFromColor(QColor color) const {
|
||||
double EditColorBox::Slider::valueFromColor(QColor color) const {
|
||||
return (_type == Type::Hue) ? valueFromHue(color.hsvHue()) : color.alphaF();
|
||||
}
|
||||
|
||||
float64 EditColorBox::Slider::valueFromHue(int hue) const {
|
||||
double EditColorBox::Slider::valueFromHue(int hue) const {
|
||||
return (1. - snap(hue, 0, 360) / 360.);
|
||||
}
|
||||
|
||||
|
@ -430,7 +430,7 @@ void EditColorBox::Slider::updatePixmapFromMask() {
|
|||
void EditColorBox::Slider::updateCurrentPoint(QPoint localPosition) {
|
||||
auto coord = (isHorizontal() ? localPosition.x() : localPosition.y()) - st::colorSliderSkip;
|
||||
auto maximum = (isHorizontal() ? width() : height()) - 2 * st::colorSliderSkip;
|
||||
auto value = snap(coord, 0, maximum) / float64(maximum);
|
||||
auto value = snap(coord, 0, maximum) / double(maximum);
|
||||
if (_value != value) {
|
||||
_value = value;
|
||||
update();
|
||||
|
@ -909,4 +909,4 @@ void EditColorBox::setRGB(int red, int green, int blue, int alpha) {
|
|||
updateControlsFromColor();
|
||||
updateHSVFields();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,8 +141,8 @@ void PasscodeBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
Painter p(this);
|
||||
|
||||
int32 w = st::boxWidth - st::boxPadding.left() * 1.5;
|
||||
int32 abouty = (_passwordHint->isHidden() ? ((_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip) : _passwordHint->y()) + _oldPasscode->height() + st::passcodeLittleSkip + st::passcodeAboutSkip;
|
||||
int32_t w = st::boxWidth - st::boxPadding.left() * 1.5;
|
||||
int32_t abouty = (_passwordHint->isHidden() ? ((_reenterPasscode->isHidden() ? (_oldPasscode->y() + (_hasRecovery && !_hintText.isEmpty() ? st::passcodeTextLine : 0)) : _reenterPasscode->y()) + st::passcodeSkip) : _passwordHint->y()) + _oldPasscode->height() + st::passcodeLittleSkip + st::passcodeAboutSkip;
|
||||
p.setPen(st::boxTextFg);
|
||||
_about.drawLeft(p, st::boxPadding.left(), abouty, w, width());
|
||||
|
||||
|
@ -170,7 +170,7 @@ void PasscodeBox::resizeEvent(QResizeEvent *e) {
|
|||
BoxContent::resizeEvent(e);
|
||||
|
||||
bool has = _cloudPwd ? (!_curSalt.isEmpty()) : Global::LocalPasscode();
|
||||
int32 w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right();
|
||||
int32_t w = st::boxWidth - st::boxPadding.left() - st::boxPadding.right();
|
||||
_oldPasscode->resize(w, _oldPasscode->height());
|
||||
_oldPasscode->moveToLeft(st::boxPadding.left(), st::passcodePadding.top());
|
||||
_newPasscode->resize(w, _newPasscode->height());
|
||||
|
@ -443,7 +443,7 @@ void RecoverBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(st::boxTextFg);
|
||||
int32 w = st::boxWidth - st::boxPadding.left() * 1.5;
|
||||
int32_t w = st::boxWidth - st::boxPadding.left() * 1.5;
|
||||
p.drawText(QRect(st::boxPadding.left(), _recoverCode->y() - st::passcodeTextLine - st::passcodePadding.top(), w, st::passcodePadding.top() + st::passcodeTextLine), _pattern, style::al_left);
|
||||
|
||||
if (!_error.isEmpty()) {
|
||||
|
|
|
@ -34,9 +34,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "storage/file_download.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
|
||||
PeerListBox::PeerListBox(QWidget*, std::unique_ptr<PeerListController> controller, base::lambda<void(not_null<PeerListBox*>)> init)
|
||||
: _controller(std::move(controller))
|
||||
, _init(std::move(init)) {
|
||||
PeerListBox::PeerListBox(QWidget*
|
||||
, std::unique_ptr<PeerListController> controller
|
||||
, base::lambda<void(not_null<PeerListBox*>)> init)
|
||||
: _controller(std::move(controller))
|
||||
, _init(std::move(init))
|
||||
{
|
||||
Expects(_controller != nullptr);
|
||||
}
|
||||
|
||||
|
@ -49,7 +52,7 @@ void PeerListBox::createMultiSelect() {
|
|||
_select.create(this, std::move(entity), margins, std::move(callback));
|
||||
_select->entity()->setSubmittedCallback([this](bool chtrlShiftEnter) { _inner->submitted(); });
|
||||
_select->entity()->setQueryChangedCallback([this](const QString &query) { searchQueryChanged(query); });
|
||||
_select->entity()->setItemRemovedCallback([this](uint64 itemId) {
|
||||
_select->entity()->setItemRemovedCallback([this](uint64_t itemId) {
|
||||
if (auto peer = App::peerLoaded(itemId)) {
|
||||
if (auto row = peerListFindRow(peer->id)) {
|
||||
_inner->changeCheckState(row, false, PeerListRow::SetStyle::Animated);
|
||||
|
@ -341,7 +344,7 @@ int PeerListBox::peerListSelectedRowsCount() {
|
|||
|
||||
std::vector<not_null<PeerData*>> PeerListBox::peerListCollectSelectedRows() {
|
||||
auto result = std::vector<not_null<PeerData*>> {};
|
||||
auto items = _select ? _select->entity()->getItems() : QVector<uint64> {};
|
||||
auto items = _select ? _select->entity()->getItems() : QVector<uint64_t> {};
|
||||
if (!items.empty()) {
|
||||
result.reserve(items.size());
|
||||
for_const (auto itemId, items) {
|
||||
|
@ -496,7 +499,7 @@ void PeerListRow::setStatusText(const QString &text) {
|
|||
_status.setText(st::defaultTextStyle, text, _textNameOptions);
|
||||
}
|
||||
|
||||
float64 PeerListRow::checkedRatio() {
|
||||
double PeerListRow::checkedRatio() {
|
||||
return _checkbox ? _checkbox->checkedAnimationRatio() : 0.;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ inline auto PaintUserpicCallback(PeerData *peer) {
|
|||
};
|
||||
}
|
||||
|
||||
using PeerListRowId = uint64;
|
||||
using PeerListRowId = uint64_t;
|
||||
class PeerListRow {
|
||||
public:
|
||||
PeerListRow(not_null<PeerData*> peer);
|
||||
|
@ -139,7 +139,7 @@ public:
|
|||
void stopLastRipple();
|
||||
void paintRipple(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
void paintUserpic(Painter &p, TimeMs ms, int x, int y, int outerWidth);
|
||||
float64 checkedRatio();
|
||||
double checkedRatio();
|
||||
|
||||
void setNameFirstChars(const OrderedSet<QChar> &nameFirstChars) {
|
||||
_nameFirstChars = nameFirstChars;
|
||||
|
|
|
@ -717,7 +717,7 @@ void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
|
|||
}
|
||||
auto history = App::historyLoaded(chat);
|
||||
auto afterRequestId = history ? history->sendRequestId : 0;
|
||||
auto randomId = rand_value<uint64>();
|
||||
auto randomId = rand_value<uint64_t>();
|
||||
auto gameShortName = bot->botInfo->shareGameShortName;
|
||||
auto inputGame = MTP_inputGameShortName(
|
||||
bot->inputUser,
|
||||
|
@ -764,7 +764,7 @@ void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
|
|||
auto request = MTPmessages_StartBot(
|
||||
bot->inputUser,
|
||||
chat->input,
|
||||
MTP_long(rand_value<uint64>()),
|
||||
MTP_long(rand_value<uint64_t>()),
|
||||
MTP_string(info->startGroupToken));
|
||||
auto done = App::main()->rpcDone(
|
||||
&MainWidget::sentUpdatesReceived);
|
||||
|
|
|
@ -56,7 +56,7 @@ void PhotoCropBox::prepare() {
|
|||
connect(this, SIGNAL(ready(const QImage&)), this, SLOT(onReady(const QImage&)));
|
||||
}
|
||||
|
||||
int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
int32_t s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
_thumb = App::pixmapFromImageInPlace(_img.scaled(s * cIntRetinaFactor(), s * cIntRetinaFactor(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
_thumb.setDevicePixelRatio(cRetinaFactor());
|
||||
_mask = QImage(_thumb.size(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
@ -94,7 +94,7 @@ void PhotoCropBox::mousePressEvent(QMouseEvent *e) {
|
|||
|
||||
int PhotoCropBox::mouseState(QPoint p) {
|
||||
p -= QPoint(_thumbx, _thumby);
|
||||
int32 delta = st::cropPointSize, mdelta(-delta / 2);
|
||||
int32_t delta = st::cropPointSize, mdelta(-delta / 2);
|
||||
if (QRect(_cropx + mdelta, _cropy + mdelta, delta, delta).contains(p)) {
|
||||
return 1;
|
||||
} else if (QRect(_cropx + _cropw + mdelta, _cropy + mdelta, delta, delta).contains(p)) {
|
||||
|
@ -122,7 +122,7 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
}
|
||||
if (_downState) {
|
||||
if (_downState == 1) {
|
||||
int32 dx = e->pos().x() - _fromposx, dy = e->pos().y() - _fromposy, d = (dx < dy) ? dx : dy;
|
||||
int32_t dx = e->pos().x() - _fromposx, dy = e->pos().y() - _fromposy, d = (dx < dy) ? dx : dy;
|
||||
if (_fromcropx + d < 0) {
|
||||
d = -_fromcropx;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
update();
|
||||
}
|
||||
} else if (_downState == 2) {
|
||||
int32 dx = _fromposx - e->pos().x(), dy = e->pos().y() - _fromposy, d = (dx < dy) ? dx : dy;
|
||||
int32_t dx = _fromposx - e->pos().x(), dy = e->pos().y() - _fromposy, d = (dx < dy) ? dx : dy;
|
||||
if (_fromcropx + _fromcropw - d > _thumbw) {
|
||||
d = _fromcropx + _fromcropw - _thumbw;
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
update();
|
||||
}
|
||||
} else if (_downState == 3) {
|
||||
int32 dx = _fromposx - e->pos().x(), dy = _fromposy - e->pos().y(), d = (dx < dy) ? dx : dy;
|
||||
int32_t dx = _fromposx - e->pos().x(), dy = _fromposy - e->pos().y(), d = (dx < dy) ? dx : dy;
|
||||
if (_fromcropx + _fromcropw - d > _thumbw) {
|
||||
d = _fromcropx + _fromcropw - _thumbw;
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
update();
|
||||
}
|
||||
} else if (_downState == 4) {
|
||||
int32 dx = e->pos().x() - _fromposx, dy = _fromposy - e->pos().y(), d = (dx < dy) ? dx : dy;
|
||||
int32_t dx = e->pos().x() - _fromposx, dy = _fromposy - e->pos().y(), d = (dx < dy) ? dx : dy;
|
||||
if (_fromcropx + d < 0) {
|
||||
d = -_fromcropx;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
update();
|
||||
}
|
||||
} else if (_downState == 5) {
|
||||
int32 dx = e->pos().x() - _fromposx, dy = e->pos().y() - _fromposy;
|
||||
int32_t dx = e->pos().x() - _fromposx, dy = e->pos().y() - _fromposy;
|
||||
if (_fromcropx + dx < 0) {
|
||||
dx = -_fromcropx;
|
||||
} else if (_fromcropx + _fromcropw + dx > _thumbw) {
|
||||
|
@ -204,7 +204,7 @@ void PhotoCropBox::mouseMoveEvent(QMouseEvent *e) {
|
|||
}
|
||||
}
|
||||
}
|
||||
int32 cursorState = _downState ? _downState : mouseState(e->pos());
|
||||
int32_t cursorState = _downState ? _downState : mouseState(e->pos());
|
||||
QCursor cur(style::cur_default);
|
||||
if (cursorState == 1 || cursorState == 3) {
|
||||
cur = style::cur_sizefdiag;
|
||||
|
@ -260,8 +260,8 @@ void PhotoCropBox::sendPhoto() {
|
|||
if (_img.width() < _thumb.width()) {
|
||||
from = _thumb.toImage();
|
||||
}
|
||||
float64 x = float64(_cropx) / _thumbw, y = float64(_cropy) / _thumbh, w = float64(_cropw) / _thumbw;
|
||||
int32 ix = int32(x * from.width()), iy = int32(y * from.height()), iw = int32(w * from.width());
|
||||
double x = double(_cropx) / _thumbw, y = double(_cropy) / _thumbh, w = double(_cropw) / _thumbw;
|
||||
int32_t ix = int32_t(x * from.width()), iy = int32_t(y * from.height()), iw = int32_t(w * from.width());
|
||||
if (ix < 0) {
|
||||
ix = 0;
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ void PhotoCropBox::sendPhoto() {
|
|||
if (iy + iw > from.height()) {
|
||||
iw = from.height() - iy;
|
||||
}
|
||||
int32 offset = ix * from.depth() / 8 + iy * from.bytesPerLine();
|
||||
int32_t offset = ix * from.depth() / 8 + iy * from.bytesPerLine();
|
||||
QImage cropped(from.constBits() + offset, iw, iw, from.bytesPerLine(), from.format()), tosend;
|
||||
if (from.format() == QImage::Format_Indexed8) {
|
||||
cropped.setColorCount(from.colorCount());
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
PhotoCropBox(QWidget*, const QImage &img, const PeerId &peer);
|
||||
PhotoCropBox(QWidget*, const QImage &img, PeerData *peer);
|
||||
|
||||
int32 mouseState(QPoint p);
|
||||
int32_t mouseState(QPoint p);
|
||||
|
||||
signals:
|
||||
void ready(const QImage &tosend);
|
||||
|
@ -51,10 +51,10 @@ private:
|
|||
void sendPhoto();
|
||||
|
||||
QString _title;
|
||||
int32 _downState = 0;
|
||||
int32 _thumbx, _thumby, _thumbw, _thumbh;
|
||||
int32 _cropx, _cropy, _cropw;
|
||||
int32 _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw;
|
||||
int32_t _downState = 0;
|
||||
int32_t _thumbx, _thumby, _thumbw, _thumbh;
|
||||
int32_t _cropx, _cropy, _cropw;
|
||||
int32_t _fromposx, _fromposy, _fromcropx, _fromcropy, _fromcropw;
|
||||
QImage _img;
|
||||
QPixmap _thumb;
|
||||
QImage _mask, _fade;
|
||||
|
|
|
@ -36,7 +36,7 @@ constexpr auto kMaxRating = 5;
|
|||
|
||||
} // namespace
|
||||
|
||||
RateCallBox::RateCallBox(QWidget*, uint64 callId, uint64 callAccessHash)
|
||||
RateCallBox::RateCallBox(QWidget*, uint64_t callId, uint64_t callAccessHash)
|
||||
: _callId(callId)
|
||||
, _callAccessHash(callAccessHash) {
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class RateCallBox : public BoxContent, private MTP::Sender {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RateCallBox(QWidget*, uint64 callId, uint64 callAccessHash);
|
||||
RateCallBox(QWidget*, uint64_t callId, uint64_t callAccessHash);
|
||||
|
||||
private slots:
|
||||
void onSend();
|
||||
|
@ -52,8 +52,8 @@ private:
|
|||
void updateMaxHeight();
|
||||
void ratingChanged(int value);
|
||||
|
||||
uint64 _callId = 0;
|
||||
uint64 _callAccessHash = 0;
|
||||
uint64_t _callId = 0;
|
||||
uint64_t _callAccessHash = 0;
|
||||
int _rating = 0;
|
||||
|
||||
std::vector<object_ptr<Ui::IconButton>> _stars;
|
||||
|
|
|
@ -112,9 +112,9 @@ void SendFilesBox::prepareSingleFileLayout() {
|
|||
_previewWidth = qMax(image.width(), kMinPreviewWidth);
|
||||
}
|
||||
auto maxthumbh = qMin(qRound(1.5 * _previewWidth), st::confirmMaxHeight);
|
||||
_previewHeight = qRound(originalHeight * float64(_previewWidth) / originalWidth);
|
||||
_previewHeight = qRound(originalHeight * double(_previewWidth) / originalWidth);
|
||||
if (_previewHeight > maxthumbh) {
|
||||
_previewWidth = qRound(_previewWidth * float64(maxthumbh) / _previewHeight);
|
||||
_previewWidth = qRound(_previewWidth * double(maxthumbh) / _previewHeight);
|
||||
accumulate_max(_previewWidth, kMinPreviewWidth);
|
||||
_previewHeight = maxthumbh;
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
|
|||
linktop = st::msgFileThumbLinkTop;
|
||||
}
|
||||
auto namewidth = w - nameleft - (_fileThumb.isNull() ? st::msgFilePadding.left() : st::msgFileThumbPadding.left());
|
||||
int32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
int32_t x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
|
||||
App::roundRect(p, x, y, w, h, st::msgOutBg, MessageOutCorners, &st::msgOutShadow);
|
||||
|
||||
|
@ -493,7 +493,7 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
if (image->isNull()) {
|
||||
_thumbw = 0;
|
||||
} else {
|
||||
int32 tw = image->width(), th = image->height();
|
||||
int32_t tw = image->width(), th = image->height();
|
||||
if (tw > th) {
|
||||
_thumbw = (tw * st::msgFileThumbSize) / th;
|
||||
} else {
|
||||
|
@ -515,10 +515,10 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
_isAudio = (doc->voice() || doc->song());
|
||||
}
|
||||
} else {
|
||||
int32 maxW = 0, maxH = 0;
|
||||
int32_t maxW = 0, maxH = 0;
|
||||
if (_animated) {
|
||||
int32 limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
int32 limitH = st::confirmMaxHeight;
|
||||
int32_t limitW = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
int32_t limitH = st::confirmMaxHeight;
|
||||
maxW = qMax(dimensions.width(), 1);
|
||||
maxH = qMax(dimensions.height(), 1);
|
||||
if (maxW * limitH > maxH * limitW) {
|
||||
|
@ -539,7 +539,7 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
maxH = dimensions.height();
|
||||
_thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), Images::Option::Smooth, maxW, maxH);
|
||||
}
|
||||
int32 tw = _thumb.width(), th = _thumb.height();
|
||||
int32_t tw = _thumb.width(), th = _thumb.height();
|
||||
if (!tw || !th) {
|
||||
tw = th = 1;
|
||||
}
|
||||
|
@ -547,10 +547,10 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
|
|||
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);
|
||||
int32_t maxthumbh = qMin(qRound(1.5 * _thumbw), int(st::confirmMaxHeight));
|
||||
_thumbh = qRound(th * double(_thumbw) / tw);
|
||||
if (_thumbh > maxthumbh) {
|
||||
_thumbw = qRound(_thumbw * float64(maxthumbh) / _thumbh);
|
||||
_thumbw = qRound(_thumbw * double(maxthumbh) / _thumbh);
|
||||
_thumbh = maxthumbh;
|
||||
if (_thumbw < 10) {
|
||||
_thumbw = 10;
|
||||
|
@ -677,9 +677,9 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
icon->paintInCenter(p, inner);
|
||||
}
|
||||
} 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;
|
||||
int32_t w = width() - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
|
||||
int32_t h = _thumbw ? (0 + st::msgFileThumbSize + 0) : (0 + st::msgFileSize + 0);
|
||||
int32_t nameleft = 0, nametop = 0, nameright = 0, statustop = 0;
|
||||
if (_thumbw) {
|
||||
nameleft = 0 + st::msgFileThumbSize + st::msgFileThumbPadding.right();
|
||||
nametop = st::msgFileThumbNameTop - st::msgFileThumbPadding.top();
|
||||
|
@ -691,12 +691,12 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
nameright = 0;
|
||||
statustop = st::msgFileStatusTop - st::msgFilePadding.top();
|
||||
}
|
||||
int32 namewidth = w - nameleft - 0;
|
||||
int32_t namewidth = w - nameleft - 0;
|
||||
if (namewidth > _statusw) {
|
||||
//w -= (namewidth - _statusw);
|
||||
//namewidth = _statusw;
|
||||
}
|
||||
int32 x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
int32_t x = (width() - w) / 2, y = st::boxPhotoPadding.top();
|
||||
|
||||
// App::roundRect(p, x, y, w, h, st::msgInBg, MessageInCorners, &st::msgInShadow);
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
|||
// deviceModel = qsl("Linux");
|
||||
// }
|
||||
if (appVer == QString::number(appVer.toInt())) {
|
||||
int32 ver = appVer.toInt();
|
||||
int32_t ver = appVer.toInt();
|
||||
appVer = QString("%1.%2").arg(ver / 1000000).arg((ver % 1000000) / 1000) + ((ver % 1000) ? ('.' + QString::number(ver % 1000)) : QString());
|
||||
//} else {
|
||||
// appVer = QString();
|
||||
|
@ -140,7 +140,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
|||
if (!data.hash || (d.vflags.v & 1)) {
|
||||
data.active = lang(lng_sessions_header);
|
||||
data.activeWidth = st::sessionWhenFont->width(lang(lng_sessions_header));
|
||||
int32 availForName = availCurrent - st::sessionPadding.right() - data.activeWidth;
|
||||
int32_t availForName = availCurrent - st::sessionPadding.right() - data.activeWidth;
|
||||
if (data.nameWidth > availForName) {
|
||||
data.name = st::sessionNameFont->elided(data.name, availForName);
|
||||
data.nameWidth = st::sessionNameFont->width(data.name);
|
||||
|
@ -168,7 +168,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
|||
data.active = lastDate.toString(qsl("d.MM.yy"));
|
||||
}
|
||||
data.activeWidth = st::sessionWhenFont->width(data.active);
|
||||
int32 availForName = availOther - st::sessionPadding.right() - data.activeWidth;
|
||||
int32_t availForName = availOther - st::sessionPadding.right() - data.activeWidth;
|
||||
if (data.nameWidth > availForName) {
|
||||
data.name = st::sessionNameFont->elided(data.name, availForName);
|
||||
data.nameWidth = st::sessionNameFont->width(data.name);
|
||||
|
@ -185,7 +185,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
|
|||
}
|
||||
|
||||
_list.push_back(data);
|
||||
for (int32 i = _list.size(); i > 1;) {
|
||||
for (int32_t i = _list.size(); i > 1;) {
|
||||
--i;
|
||||
if (_list.at(i).activeTime > _list.at(i - 1).activeTime) {
|
||||
qSwap(_list[i], _list[i - 1]);
|
||||
|
@ -242,8 +242,8 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
p.fillRect(r, st::boxBg);
|
||||
int32 x = st::sessionPadding.left(), xact = st::sessionTerminateSkip + st::sessionTerminate.iconPosition.x();// st::sessionTerminateSkip + st::sessionTerminate.width + st::sessionTerminateSkip;
|
||||
int32 w = width();
|
||||
int32_t x = st::sessionPadding.left(), xact = st::sessionTerminateSkip + st::sessionTerminate.iconPosition.x();// st::sessionTerminateSkip + st::sessionTerminate.width + st::sessionTerminateSkip;
|
||||
int32_t w = width();
|
||||
|
||||
if (_current->active.isEmpty() && _list->isEmpty()) {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
|
@ -277,11 +277,11 @@ void SessionsBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
p.setFont(st::linkFont->f);
|
||||
int32 count = _list->size();
|
||||
int32 from = floorclamp(r.y() - st::sessionCurrentHeight, st::sessionHeight, 0, count);
|
||||
int32 to = ceilclamp(r.y() + r.height() - st::sessionCurrentHeight, st::sessionHeight, 0, count);
|
||||
int32_t count = _list->size();
|
||||
int32_t from = floorclamp(r.y() - st::sessionCurrentHeight, st::sessionHeight, 0, count);
|
||||
int32_t to = ceilclamp(r.y() + r.height() - st::sessionCurrentHeight, st::sessionHeight, 0, count);
|
||||
p.translate(0, from * st::sessionHeight);
|
||||
for (int32 i = from; i < to; ++i) {
|
||||
for (int32_t i = from; i < to; ++i) {
|
||||
const SessionsBox::Data &auth(_list->at(i));
|
||||
|
||||
p.setFont(st::sessionNameFont);
|
||||
|
@ -334,8 +334,8 @@ void SessionsBox::Inner::onTerminateAll() {
|
|||
})), KeepOtherLayers);
|
||||
}
|
||||
|
||||
void SessionsBox::Inner::terminateDone(uint64 hash, const MTPBool &result) {
|
||||
for (int32 i = 0, l = _list->size(); i < l; ++i) {
|
||||
void SessionsBox::Inner::terminateDone(uint64_t hash, const MTPBool &result) {
|
||||
for (int32_t i = 0, l = _list->size(); i < l; ++i) {
|
||||
if (_list->at(i).hash == hash) {
|
||||
_list->removeAt(i);
|
||||
break;
|
||||
|
@ -345,7 +345,7 @@ void SessionsBox::Inner::terminateDone(uint64 hash, const MTPBool &result) {
|
|||
emit oneTerminated();
|
||||
}
|
||||
|
||||
bool SessionsBox::Inner::terminateFail(uint64 hash, const RPCError &error) {
|
||||
bool SessionsBox::Inner::terminateFail(uint64_t hash, const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
TerminateButtons::iterator i = _terminateButtons.find(hash);
|
||||
|
@ -379,7 +379,7 @@ void SessionsBox::Inner::listUpdated() {
|
|||
for (TerminateButtons::iterator i = _terminateButtons.begin(), e = _terminateButtons.end(); i != e; ++i) {
|
||||
i.value()->move(0, -1);
|
||||
}
|
||||
for (int32 i = 0, l = _list->size(); i < l; ++i) {
|
||||
for (int32_t i = 0, l = _list->size(); i < l; ++i) {
|
||||
TerminateButtons::iterator j = _terminateButtons.find(_list->at(i).hash);
|
||||
if (j == _terminateButtons.cend()) {
|
||||
j = _terminateButtons.insert(_list->at(i).hash, new Ui::IconButton(this, st::sessionTerminate));
|
||||
|
|
|
@ -52,10 +52,10 @@ private slots:
|
|||
private:
|
||||
void setLoading(bool loading);
|
||||
struct Data {
|
||||
uint64 hash;
|
||||
uint64_t hash;
|
||||
|
||||
int32 activeTime;
|
||||
int32 nameWidth, activeWidth, infoWidth, ipWidth;
|
||||
int32_t activeTime;
|
||||
int32_t nameWidth, activeWidth, infoWidth, ipWidth;
|
||||
QString name, active, info, ip;
|
||||
};
|
||||
using List = QList<Data>;
|
||||
|
@ -98,8 +98,8 @@ public slots:
|
|||
void onTerminateAll();
|
||||
|
||||
private:
|
||||
void terminateDone(uint64 hash, const MTPBool &result);
|
||||
bool terminateFail(uint64 hash, const RPCError &error);
|
||||
void terminateDone(uint64_t hash, const MTPBool &result);
|
||||
bool terminateFail(uint64_t hash, const RPCError &error);
|
||||
|
||||
void terminateAllDone(const MTPBool &res);
|
||||
bool terminateAllFail(const RPCError &error);
|
||||
|
@ -107,7 +107,7 @@ private:
|
|||
SessionsBox::List *_list;
|
||||
SessionsBox::Data *_current;
|
||||
|
||||
typedef QMap<uint64, Ui::IconButton*> TerminateButtons;
|
||||
typedef QMap<uint64_t, Ui::IconButton*> TerminateButtons;
|
||||
TerminateButtons _terminateButtons;
|
||||
|
||||
object_ptr<Ui::LinkButton> _terminateAll;
|
||||
|
|
|
@ -64,7 +64,7 @@ void ShareBox::prepare() {
|
|||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||
|
||||
_select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
|
||||
_select->setItemRemovedCallback([this](uint64 itemId) {
|
||||
_select->setItemRemovedCallback([this](uint64_t itemId) {
|
||||
if (auto peer = App::peerLoaded(itemId)) {
|
||||
_inner->peerUnselected(peer);
|
||||
onSelectedChanged();
|
||||
|
@ -481,7 +481,7 @@ ShareBox::Inner::Chat *ShareBox::Inner::getChat(Dialogs::Row *row) {
|
|||
|
||||
void ShareBox::Inner::setActive(int active) {
|
||||
if (active != _active) {
|
||||
auto changeNameFg = [this](int index, float64 from, float64 to) {
|
||||
auto changeNameFg = [this](int index, double from, double to) {
|
||||
if (auto chat = getChatAtIndex(index)) {
|
||||
chat->nameActive.start([this, peer = chat->peer] {
|
||||
repaintChat(peer);
|
||||
|
@ -620,7 +620,7 @@ void ShareBox::Inner::onSelectActive() {
|
|||
}
|
||||
|
||||
void ShareBox::Inner::resizeEvent(QResizeEvent *e) {
|
||||
_columnSkip = (width() - _columnCount * st::sharePhotoCheckbox.imageRadius * 2) / float64(_columnCount + 1);
|
||||
_columnSkip = (width() - _columnCount * st::sharePhotoCheckbox.imageRadius * 2) / double(_columnCount + 1);
|
||||
_rowWidthReal = st::sharePhotoCheckbox.imageRadius * 2 + _columnSkip;
|
||||
_rowsLeft = qFloor(_columnSkip / 2);
|
||||
_rowWidth = qFloor(_rowWidthReal);
|
||||
|
@ -743,7 +743,7 @@ void ShareBox::Inner::updateFilter(QString filter) {
|
|||
void ShareBox::Inner::peopleReceived(const QString &query, const QVector<MTPPeer> &people) {
|
||||
_lastQuery = query.toLower().trimmed();
|
||||
if (_lastQuery.at(0) == '@') _lastQuery = _lastQuery.mid(1);
|
||||
int32 already = _byUsernameFiltered.size();
|
||||
int32_t already = _byUsernameFiltered.size();
|
||||
_byUsernameFiltered.reserve(already + people.size());
|
||||
d_byUsernameFiltered.reserve(already + people.size());
|
||||
for_const (auto &mtpPeer, people) {
|
||||
|
@ -800,10 +800,10 @@ QVector<PeerData*> ShareBox::Inner::selected() const {
|
|||
|
||||
QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
||||
auto shareHashData = QByteArray(0x10, Qt::Uninitialized);
|
||||
auto shareHashDataInts = reinterpret_cast<int32*>(shareHashData.data());
|
||||
auto shareHashDataInts = reinterpret_cast<int32_t*>(shareHashData.data());
|
||||
auto channel = fullId.channel ? App::channelLoaded(fullId.channel) : static_cast<ChannelData*>(nullptr);
|
||||
auto channelAccessHash = channel ? channel->access : 0ULL;
|
||||
auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash);
|
||||
auto channelAccessHashInts = reinterpret_cast<int32_t*>(&channelAccessHash);
|
||||
shareHashDataInts[0] = Auth().userId();
|
||||
shareHashDataInts[1] = fullId.channel;
|
||||
shareHashDataInts[2] = fullId.msg;
|
||||
|
@ -815,7 +815,7 @@ QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
|
|||
hashSha1(shareHashData.constData(), shareHashData.size(), shareHashEncrypted.data());
|
||||
|
||||
// Mix in channel access hash to the first 64 bits of SHA1 of data.
|
||||
*reinterpret_cast<uint64*>(shareHashEncrypted.data()) ^= *reinterpret_cast<uint64*>(channelAccessHashInts);
|
||||
*reinterpret_cast<uint64_t*>(shareHashEncrypted.data()) ^= *reinterpret_cast<uint64_t*>(channelAccessHashInts);
|
||||
|
||||
// Encrypt data.
|
||||
if (!Local::encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(), shareHashEncrypted.constData())) {
|
||||
|
@ -861,7 +861,7 @@ void ShareGameScoreByHash(const QString &hash) {
|
|||
hashSha1(hashData.constData(), hashData.size(), dataSha1);
|
||||
|
||||
// Mix out channel access hash from the first 64 bits of SHA1 of data.
|
||||
auto channelAccessHash = *reinterpret_cast<uint64*>(hashEncrypted.data()) ^ *reinterpret_cast<uint64*>(dataSha1);
|
||||
auto channelAccessHash = *reinterpret_cast<uint64_t*>(hashEncrypted.data()) ^ *reinterpret_cast<uint64_t*>(dataSha1);
|
||||
|
||||
// Check next 64 bits of SHA1() of data.
|
||||
auto skipSha1Part = sizeof(channelAccessHash);
|
||||
|
@ -870,14 +870,14 @@ void ShareGameScoreByHash(const QString &hash) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto hashDataInts = reinterpret_cast<int32*>(hashData.data());
|
||||
auto hashDataInts = reinterpret_cast<int32_t*>(hashData.data());
|
||||
if (!AuthSession::Exists() || hashDataInts[0] != Auth().userId()) {
|
||||
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check first 32 bits of channel access hash.
|
||||
auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash);
|
||||
auto channelAccessHashInts = reinterpret_cast<int32_t*>(&channelAccessHash);
|
||||
if (channelAccessHashInts[0] != hashDataInts[3]) {
|
||||
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
|
||||
return;
|
||||
|
|
|
@ -182,8 +182,8 @@ private:
|
|||
|
||||
void refresh();
|
||||
|
||||
float64 _columnSkip = 0.;
|
||||
float64 _rowWidthReal = 0.;
|
||||
double _columnSkip = 0.;
|
||||
double _rowWidthReal = 0.;
|
||||
int _rowsLeft = 0;
|
||||
int _rowsTop = 0;
|
||||
int _rowWidth = 0;
|
||||
|
|
|
@ -56,10 +56,10 @@ void StickerSetBox::prepare() {
|
|||
onUpdateButtons();
|
||||
|
||||
connect(_inner, SIGNAL(updateButtons()), this, SLOT(onUpdateButtons()));
|
||||
connect(_inner, SIGNAL(installed(uint64)), this, SLOT(onInstalled(uint64)));
|
||||
connect(_inner, SIGNAL(installed(uint64_t)), this, SLOT(onInstalled(uint64_t)));
|
||||
}
|
||||
|
||||
void StickerSetBox::onInstalled(uint64 setId) {
|
||||
void StickerSetBox::onInstalled(uint64_t setId) {
|
||||
emit installed(setId);
|
||||
closeBox();
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
|||
if (_pack.isEmpty()) {
|
||||
Ui::show(Box<InformBox>(lang(lng_stickers_not_found)));
|
||||
} else {
|
||||
int32 rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
|
||||
int32_t rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
|
||||
resize(st::stickersPadding.left() + kStickersPanelPerRow * st::stickersSize.width(), st::stickersPadding.top() + rows * st::stickersSize.height() + st::stickersPadding.bottom());
|
||||
}
|
||||
_loaded = true;
|
||||
|
@ -315,7 +315,7 @@ void StickerSetBox::Inner::setSelected(int selected) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickerSetBox::Inner::startOverAnimation(int index, float64 from, float64 to) {
|
||||
void StickerSetBox::Inner::startOverAnimation(int index, double from, double to) {
|
||||
if (index >= 0 && index < _packOvers.size()) {
|
||||
_packOvers[index].start([this, index] {
|
||||
int row = index / kStickersPanelPerRow;
|
||||
|
@ -335,13 +335,13 @@ void StickerSetBox::Inner::onPreview() {
|
|||
}
|
||||
}
|
||||
|
||||
int32 StickerSetBox::Inner::stickerFromGlobalPos(const QPoint &p) const {
|
||||
int32_t StickerSetBox::Inner::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;
|
||||
int32_t row = (l.y() >= st::stickersPadding.top()) ? qFloor((l.y() - st::stickersPadding.top()) / st::stickersSize.height()) : -1;
|
||||
int32_t col = (l.x() >= st::stickersPadding.left()) ? qFloor((l.x() - st::stickersPadding.left()) / st::stickersSize.width()) : -1;
|
||||
if (row >= 0 && col >= 0 && col < kStickersPanelPerRow) {
|
||||
int32 result = row * kStickersPanelPerRow + col;
|
||||
int32_t result = row * kStickersPanelPerRow + col;
|
||||
return (result < _pack.size()) ? result : -1;
|
||||
}
|
||||
return -1;
|
||||
|
@ -354,12 +354,12 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
if (_pack.isEmpty()) return;
|
||||
|
||||
auto ms = getms();
|
||||
int32 rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
|
||||
int32 from = qFloor(e->rect().top() / st::stickersSize.height()), to = qFloor(e->rect().bottom() / st::stickersSize.height()) + 1;
|
||||
int32_t rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
|
||||
int32_t from = qFloor(e->rect().top() / st::stickersSize.height()), to = qFloor(e->rect().bottom() / st::stickersSize.height()) + 1;
|
||||
|
||||
for (int32 i = from; i < to; ++i) {
|
||||
for (int32 j = 0; j < kStickersPanelPerRow; ++j) {
|
||||
int32 index = i * kStickersPanelPerRow + j;
|
||||
for (int32_t i = from; i < to; ++i) {
|
||||
for (int32_t j = 0; j < kStickersPanelPerRow; ++j) {
|
||||
int32_t index = i * kStickersPanelPerRow + j;
|
||||
if (index >= _pack.size()) break;
|
||||
Assert(index < _packOvers.size());
|
||||
|
||||
|
@ -386,9 +386,9 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
float64 coef = qMin((st::stickersSize.width() - st::buttonRadius * 2) / float64(doc->dimensions.width()), (st::stickersSize.height() - st::buttonRadius * 2) / float64(doc->dimensions.height()));
|
||||
double coef = qMin((st::stickersSize.width() - st::buttonRadius * 2) / double(doc->dimensions.width()), (st::stickersSize.height() - st::buttonRadius * 2) / double(doc->dimensions.height()));
|
||||
if (coef > 1) coef = 1;
|
||||
int32 w = qRound(coef * doc->dimensions.width()), h = qRound(coef * doc->dimensions.height());
|
||||
int32_t w = qRound(coef * doc->dimensions.width()), h = qRound(coef * doc->dimensions.height());
|
||||
if (w < 1) w = 1;
|
||||
if (h < 1) h = 1;
|
||||
QPoint ppos = pos + QPoint((st::stickersSize.width() - w) / 2, (st::stickersSize.height() - h) / 2);
|
||||
|
@ -410,7 +410,7 @@ bool StickerSetBox::Inner::loaded() const {
|
|||
return _loaded && !_pack.isEmpty();
|
||||
}
|
||||
|
||||
int32 StickerSetBox::Inner::notInstalled() const {
|
||||
int32_t StickerSetBox::Inner::notInstalled() const {
|
||||
if (!_loaded) return 0;
|
||||
auto it = Global::StickerSets().constFind(_setId);
|
||||
if (it == Global::StickerSets().cend() || !(it->flags & MTPDstickerSet::Flag::f_installed) || (it->flags & MTPDstickerSet::Flag::f_archived)) return _pack.size();
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
StickerSetBox(QWidget*, const MTPInputStickerSet &set);
|
||||
|
||||
signals:
|
||||
void installed(uint64 id);
|
||||
void installed(uint64_t id);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -48,7 +48,7 @@ private slots:
|
|||
void onShareStickers();
|
||||
void onUpdateButtons();
|
||||
|
||||
void onInstalled(uint64 id);
|
||||
void onInstalled(uint64_t id);
|
||||
|
||||
private:
|
||||
void updateButtons();
|
||||
|
@ -68,7 +68,7 @@ public:
|
|||
Inner(QWidget *parent, const MTPInputStickerSet &set);
|
||||
|
||||
bool loaded() const;
|
||||
int32 notInstalled() const;
|
||||
int32_t notInstalled() const;
|
||||
bool official() const;
|
||||
base::lambda<TextWithEntities()> title() const;
|
||||
QString shortName() const;
|
||||
|
@ -90,12 +90,12 @@ private slots:
|
|||
|
||||
signals:
|
||||
void updateButtons();
|
||||
void installed(uint64 id);
|
||||
void installed(uint64_t id);
|
||||
|
||||
private:
|
||||
void updateSelected();
|
||||
void setSelected(int selected);
|
||||
void startOverAnimation(int index, float64 from, float64 to);
|
||||
void startOverAnimation(int index, double from, double to);
|
||||
int stickerFromGlobalPos(const QPoint &p) const;
|
||||
|
||||
void gotSet(const MTPmessages_StickerSet &set);
|
||||
|
@ -112,11 +112,11 @@ private:
|
|||
StickerPack _pack;
|
||||
StickersByEmojiMap _emoji;
|
||||
bool _loaded = false;
|
||||
uint64 _setId = 0;
|
||||
uint64 _setAccess = 0;
|
||||
uint64_t _setId = 0;
|
||||
uint64_t _setAccess = 0;
|
||||
QString _setTitle, _setShortName;
|
||||
int32 _setCount = 0;
|
||||
int32 _setHash = 0;
|
||||
int32_t _setCount = 0;
|
||||
int32_t _setHash = 0;
|
||||
MTPDstickerSet::Flags _setFlags = 0;
|
||||
|
||||
int _visibleTop = 0;
|
||||
|
|
|
@ -156,7 +156,7 @@ StickersBox::StickersBox(QWidget*, not_null<ChannelData*> megagroup)
|
|||
subscribe(_installed.widget()->scrollToY, [this](int y) { onScrollToY(y); });
|
||||
}
|
||||
|
||||
void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) {
|
||||
void StickersBox::getArchivedDone(uint64_t offsetId, const MTPmessages_ArchivedStickers &result) {
|
||||
_archivedRequestId = 0;
|
||||
_archivedLoaded = true;
|
||||
if (result.type() != mtpc_messages_archivedStickers) {
|
||||
|
@ -253,10 +253,10 @@ void StickersBox::prepare() {
|
|||
if (_archived.widget() && _section != Section::Archived) _archived.widget()->hide();
|
||||
|
||||
if (_featured.widget()) {
|
||||
_featured.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
|
||||
_featured.widget()->setInstallSetCallback([this](uint64_t setId) { installSet(setId); });
|
||||
}
|
||||
if (_archived.widget()) {
|
||||
_archived.widget()->setInstallSetCallback([this](uint64 setId) { installSet(setId); });
|
||||
_archived.widget()->setInstallSetCallback([this](uint64_t setId) { installSet(setId); });
|
||||
_archived.widget()->setLoadMoreCallback([this] { loadMoreArchived(); });
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ void StickersBox::loadMoreArchived() {
|
|||
return;
|
||||
}
|
||||
|
||||
uint64 lastId = 0;
|
||||
uint64_t lastId = 0;
|
||||
for (auto setIt = Global::ArchivedStickerSetsOrder().cend(), e = Global::ArchivedStickerSetsOrder().cbegin(); setIt != e;) {
|
||||
--setIt;
|
||||
auto it = Global::StickerSets().constFind(*setIt);
|
||||
|
@ -441,7 +441,7 @@ QPixmap StickersBox::grabContentCache() {
|
|||
return result;
|
||||
}
|
||||
|
||||
void StickersBox::installSet(uint64 setId) {
|
||||
void StickersBox::installSet(uint64_t setId) {
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend()) {
|
||||
|
@ -468,7 +468,7 @@ void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result)
|
|||
}
|
||||
}
|
||||
|
||||
bool StickersBox::installFail(uint64 setId, const RPCError &error) {
|
||||
bool StickersBox::installFail(uint64_t setId, const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
auto &sets = Global::RefStickerSets();
|
||||
|
@ -568,7 +568,7 @@ void StickersBox::setInnerFocus() {
|
|||
|
||||
StickersBox::~StickersBox() = default;
|
||||
|
||||
StickersBox::Inner::Row::Row(uint64 id, DocumentData *sticker, int32 count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, int32 pixw, int32 pixh) : id(id)
|
||||
StickersBox::Inner::Row::Row(uint64_t id, DocumentData *sticker, int32_t count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, int32_t pixw, int32_t pixh) : id(id)
|
||||
, sticker(sticker)
|
||||
, count(count)
|
||||
, title(title)
|
||||
|
@ -654,11 +654,11 @@ void StickersBox::Inner::paintEvent(QPaintEvent *e) {
|
|||
} else {
|
||||
p.translate(0, _itemsTop);
|
||||
|
||||
int32 yFrom = clip.y() - _itemsTop, yTo = clip.y() + clip.height() - _itemsTop;
|
||||
int32 from = floorclamp(yFrom - _rowHeight, _rowHeight, 0, _rows.size());
|
||||
int32 to = ceilclamp(yTo + _rowHeight, _rowHeight, 0, _rows.size());
|
||||
int32_t yFrom = clip.y() - _itemsTop, yTo = clip.y() + clip.height() - _itemsTop;
|
||||
int32_t from = floorclamp(yFrom - _rowHeight, _rowHeight, 0, _rows.size());
|
||||
int32_t to = ceilclamp(yTo + _rowHeight, _rowHeight, 0, _rows.size());
|
||||
p.translate(0, from * _rowHeight);
|
||||
for (int32 i = from; i < to; ++i) {
|
||||
for (int32_t i = from; i < to; ++i) {
|
||||
if (i != _above) {
|
||||
paintRow(p, _rows[i].get(), i, ms);
|
||||
}
|
||||
|
@ -957,14 +957,14 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
}
|
||||
if (_dragStart.y() > local.y() && _dragging > 0) {
|
||||
shift = -floorclamp(_dragStart.y() - local.y() + (_rowHeight / 2), _rowHeight, 0, _dragging - firstSetIndex);
|
||||
for (int32 from = _dragging, to = _dragging + shift; from > to; --from) {
|
||||
for (int32_t from = _dragging, to = _dragging + shift; from > to; --from) {
|
||||
qSwap(_rows[from], _rows[from - 1]);
|
||||
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() - _rowHeight, 0);
|
||||
_animStartTimes[from] = ms;
|
||||
}
|
||||
} else if (_dragStart.y() < local.y() && _dragging + 1 < _rows.size()) {
|
||||
shift = floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1);
|
||||
for (int32 from = _dragging, to = _dragging + shift; from < to; ++from) {
|
||||
for (int32_t from = _dragging, to = _dragging + shift; from < to; ++from) {
|
||||
qSwap(_rows[from], _rows[from + 1]);
|
||||
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() + _rowHeight, 0);
|
||||
_animStartTimes[from] = ms;
|
||||
|
@ -1033,7 +1033,7 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||
}
|
||||
}
|
||||
|
||||
float64 StickersBox::Inner::aboveShadowOpacity() const {
|
||||
double StickersBox::Inner::aboveShadowOpacity() const {
|
||||
if (_above < 0) return 0;
|
||||
|
||||
auto dx = 0;
|
||||
|
@ -1126,7 +1126,7 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
|
|||
if (updateMin < 0) updateMin = i;
|
||||
updateMax = i;
|
||||
if (start + st::stickersRowDuration > ms && ms >= start) {
|
||||
_rows[i]->yadd.update(float64(ms - start) / st::stickersRowDuration, anim::sineInOut);
|
||||
_rows[i]->yadd.update(double(ms - start) / st::stickersRowDuration, anim::sineInOut);
|
||||
animating = true;
|
||||
} else {
|
||||
_rows[i]->yadd.finish();
|
||||
|
@ -1138,7 +1138,7 @@ void StickersBox::Inner::step_shifting(TimeMs ms, bool timer) {
|
|||
if (updateMin < 0 || updateMin > _above) updateMin = _above;
|
||||
if (updateMax < _above) updateMin = _above;
|
||||
if (_aboveShadowFadeStart + st::stickersRowDuration > ms && ms > _aboveShadowFadeStart) {
|
||||
_aboveShadowFadeOpacity.update(float64(ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut);
|
||||
_aboveShadowFadeOpacity.update(double(ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut);
|
||||
animating = true;
|
||||
} else {
|
||||
_aboveShadowFadeOpacity.finish();
|
||||
|
@ -1179,7 +1179,7 @@ void StickersBox::Inner::clear() {
|
|||
update();
|
||||
}
|
||||
|
||||
void StickersBox::Inner::setActionSel(int32 actionSel) {
|
||||
void StickersBox::Inner::setActionSel(int32_t actionSel) {
|
||||
if (actionSel != _actionSel) {
|
||||
if (_actionSel >= 0) update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
|
||||
_actionSel = actionSel;
|
||||
|
@ -1502,7 +1502,7 @@ Stickers::Order StickersBox::Inner::getRemovedSets() const {
|
|||
});
|
||||
}
|
||||
|
||||
int StickersBox::Inner::getRowIndex(uint64 setId) const {
|
||||
int StickersBox::Inner::getRowIndex(uint64_t setId) const {
|
||||
for (auto i = 0, count = int(_rows.size()); i != count; ++i) {
|
||||
auto &row = _rows[i];
|
||||
if (row->id == setId) {
|
||||
|
|
|
@ -96,19 +96,19 @@ private:
|
|||
void rebuildList(Tab *tab = nullptr);
|
||||
void updateTabsGeometry();
|
||||
void switchTab();
|
||||
void installSet(uint64 setId);
|
||||
void installSet(uint64_t setId);
|
||||
int getTopSkip() const;
|
||||
void saveChanges();
|
||||
|
||||
QPixmap grabContentCache();
|
||||
|
||||
void installDone(const MTPmessages_StickerSetInstallResult &result);
|
||||
bool installFail(uint64 setId, const RPCError &error);
|
||||
bool installFail(uint64_t setId, const RPCError &error);
|
||||
|
||||
void preloadArchivedSets();
|
||||
void requestArchivedSets();
|
||||
void loadMoreArchived();
|
||||
void getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result);
|
||||
void getArchivedDone(uint64_t offsetId, const MTPmessages_ArchivedStickers &result);
|
||||
|
||||
object_ptr<Ui::SettingsSlider> _tabs = { nullptr };
|
||||
QList<Section> _tabIndices;
|
||||
|
@ -166,7 +166,7 @@ public:
|
|||
void setFullOrder(const Stickers::Order &order);
|
||||
void setRemovedSets(const Stickers::Order &removed);
|
||||
|
||||
void setInstallSetCallback(base::lambda<void(uint64 setId)> callback) {
|
||||
void setInstallSetCallback(base::lambda<void(uint64_t setId)> callback) {
|
||||
_installSetCallback = std::move(callback);
|
||||
}
|
||||
void setLoadMoreCallback(base::lambda<void()> callback) {
|
||||
|
@ -199,15 +199,15 @@ public slots:
|
|||
|
||||
private:
|
||||
struct Row {
|
||||
Row(uint64 id, DocumentData *sticker, int32 count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, int32 pixw, int32 pixh);
|
||||
Row(uint64_t id, DocumentData *sticker, int32_t count, const QString &title, int titleWidth, bool installed, bool official, bool unread, bool archived, bool removed, int32_t pixw, int32_t pixh);
|
||||
bool isRecentSet() const {
|
||||
return (id == Stickers::CloudRecentSetId);
|
||||
}
|
||||
~Row();
|
||||
|
||||
uint64 id = 0;
|
||||
uint64_t id = 0;
|
||||
DocumentData *sticker = nullptr;
|
||||
int32 count = 0;
|
||||
int32_t count = 0;
|
||||
QString title;
|
||||
int titleWidth = 0;
|
||||
bool installed = false;
|
||||
|
@ -215,8 +215,8 @@ private:
|
|||
bool unread = false;
|
||||
bool archived = false;
|
||||
bool removed = false;
|
||||
int32 pixw = 0;
|
||||
int32 pixh = 0;
|
||||
int32_t pixw = 0;
|
||||
int32_t pixh = 0;
|
||||
anim::value yadd;
|
||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
};
|
||||
|
@ -226,7 +226,7 @@ private:
|
|||
|
||||
void checkLoadMore();
|
||||
void updateScrollbarWidth();
|
||||
int getRowIndex(uint64 setId) const;
|
||||
int getRowIndex(uint64_t setId) const;
|
||||
void setRowRemoved(int index, bool removed);
|
||||
|
||||
void setSelected(int selected);
|
||||
|
@ -240,8 +240,8 @@ private:
|
|||
void paintRow(Painter &p, Row *set, int index, TimeMs ms);
|
||||
void paintFakeButton(Painter &p, Row *set, int index, TimeMs ms);
|
||||
void clear();
|
||||
void setActionSel(int32 actionSel);
|
||||
float64 aboveShadowOpacity() const;
|
||||
void setActionSel(int32_t actionSel);
|
||||
double aboveShadowOpacity() const;
|
||||
|
||||
void readVisibleSets();
|
||||
|
||||
|
@ -259,7 +259,7 @@ private:
|
|||
|
||||
Section _section;
|
||||
|
||||
int32 _rowHeight;
|
||||
int32_t _rowHeight;
|
||||
|
||||
std::vector<std::unique_ptr<Row>> _rows;
|
||||
QList<TimeMs> _animStartTimes;
|
||||
|
@ -267,7 +267,7 @@ private:
|
|||
anim::value _aboveShadowFadeOpacity;
|
||||
BasicAnimation _a_shifting;
|
||||
|
||||
base::lambda<void(uint64 setId)> _installSetCallback;
|
||||
base::lambda<void(uint64_t setId)> _installSetCallback;
|
||||
base::lambda<void()> _loadMoreCallback;
|
||||
|
||||
int _visibleTop = 0;
|
||||
|
|
|
@ -79,10 +79,10 @@ void UsernameBox::paintEvent(QPaintEvent *e) {
|
|||
p.drawTextLeft(st::usernamePadding.left(), _username->y() + _username->height() + ((st::usernameSkip - st::boxTextFont->height) / 2), width(), lang(lng_username_choose));
|
||||
}
|
||||
p.setPen(st::boxTextFg);
|
||||
int32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
|
||||
int32_t availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
|
||||
_about.drawLeft(p, st::usernamePadding.left(), _username->y() + _username->height() + st::usernameSkip, availw, width());
|
||||
|
||||
int32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
|
||||
int32_t linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
|
||||
if (_link->isHidden()) {
|
||||
p.drawTextLeft(st::usernamePadding.left(), linky, width(), lang(lng_username_link_willbe));
|
||||
p.setPen(st::usernameDefaultFg);
|
||||
|
@ -98,8 +98,8 @@ void UsernameBox::resizeEvent(QResizeEvent *e) {
|
|||
_username->resize(width() - st::usernamePadding.left() - st::usernamePadding.right(), _username->height());
|
||||
_username->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
|
||||
|
||||
int32 availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
|
||||
int32 linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
|
||||
int32_t availw = st::boxWidth - st::usernamePadding.left(), h = _about.countHeight(availw);
|
||||
int32_t linky = _username->y() + _username->height() + st::usernameSkip + h + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2);
|
||||
_link->moveToLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2));
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,8 @@ void UsernameBox::onChanged() {
|
|||
}
|
||||
_checkTimer->stop();
|
||||
} else {
|
||||
int32 len = name.size();
|
||||
for (int32 i = 0; i < len; ++i) {
|
||||
int32_t len = name.size();
|
||||
for (int32_t 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)) {
|
||||
if (_errorText != lang(lng_username_bad_symbols)) {
|
||||
|
@ -243,4 +243,4 @@ void UsernameBox::updateLinkText() {
|
|||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,16 +63,16 @@ void ConvertEndpoint(std::vector<tgvoip::Endpoint> &ep, const MTPDphoneConnectio
|
|||
}
|
||||
|
||||
constexpr auto kFingerprintDataSize = 256;
|
||||
uint64 ComputeFingerprint(const std::array<gsl::byte, kFingerprintDataSize> &authKey) {
|
||||
uint64_t ComputeFingerprint(const std::array<gsl::byte, kFingerprintDataSize> &authKey) {
|
||||
auto hash = openssl::Sha1(authKey);
|
||||
return (gsl::to_integer<uint64>(hash[19]) << 56)
|
||||
| (gsl::to_integer<uint64>(hash[18]) << 48)
|
||||
| (gsl::to_integer<uint64>(hash[17]) << 40)
|
||||
| (gsl::to_integer<uint64>(hash[16]) << 32)
|
||||
| (gsl::to_integer<uint64>(hash[15]) << 24)
|
||||
| (gsl::to_integer<uint64>(hash[14]) << 16)
|
||||
| (gsl::to_integer<uint64>(hash[13]) << 8)
|
||||
| (gsl::to_integer<uint64>(hash[12]));
|
||||
return (gsl::to_integer<uint64_t>(hash[19]) << 56)
|
||||
| (gsl::to_integer<uint64_t>(hash[18]) << 48)
|
||||
| (gsl::to_integer<uint64_t>(hash[17]) << 40)
|
||||
| (gsl::to_integer<uint64_t>(hash[16]) << 32)
|
||||
| (gsl::to_integer<uint64_t>(hash[15]) << 24)
|
||||
| (gsl::to_integer<uint64_t>(hash[14]) << 16)
|
||||
| (gsl::to_integer<uint64_t>(hash[13]) << 8)
|
||||
| (gsl::to_integer<uint64_t>(hash[12]));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -137,7 +137,7 @@ void Call::startOutgoing() {
|
|||
Expects(_type == Type::Outgoing);
|
||||
Expects(_state == State::Requesting);
|
||||
|
||||
request(MTPphone_RequestCall(_user->inputUser, MTP_int(rand_value<int32>()), MTP_bytes(_gaHash), MTP_phoneCallProtocol(MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), MTP_int(kMaxLayer)))).done([this](const MTPphone_PhoneCall &result) {
|
||||
request(MTPphone_RequestCall(_user->inputUser, MTP_int(rand_value<int32_t>()), MTP_bytes(_gaHash), MTP_phoneCallProtocol(MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), MTP_int(kMaxLayer)))).done([this](const MTPphone_PhoneCall &result) {
|
||||
Expects(result.type() == mtpc_phone_phoneCall);
|
||||
|
||||
setState(State::Waiting);
|
||||
|
@ -267,7 +267,7 @@ void Call::startWaitingTrack() {
|
|||
_waitingTrack->playInLoop();
|
||||
}
|
||||
|
||||
float64 Call::getWaitingSoundPeakValue() const {
|
||||
double Call::getWaitingSoundPeakValue() const {
|
||||
if (_waitingTrack) {
|
||||
auto when = getms() + kSoundSampleMs / 4;
|
||||
return _waitingTrack->getPeakValue(when);
|
||||
|
|
|
@ -38,8 +38,8 @@ class VoIPController;
|
|||
namespace Calls {
|
||||
|
||||
struct DhConfig {
|
||||
int32 version = 0;
|
||||
int32 g = 0;
|
||||
int32_t version = 0;
|
||||
int32_t g = 0;
|
||||
std::vector<gsl::byte> p;
|
||||
};
|
||||
|
||||
|
@ -115,7 +115,7 @@ public:
|
|||
}
|
||||
|
||||
TimeMs getDurationMs() const;
|
||||
float64 getWaitingSoundPeakValue() const;
|
||||
double getWaitingSoundPeakValue() const;
|
||||
|
||||
void answer();
|
||||
void hangup();
|
||||
|
@ -179,9 +179,9 @@ private:
|
|||
MTP::AuthKey::Data _authKey;
|
||||
MTPPhoneCallProtocol _protocol;
|
||||
|
||||
uint64 _id = 0;
|
||||
uint64 _accessHash = 0;
|
||||
uint64 _keyFingerprint = 0;
|
||||
uint64_t _id = 0;
|
||||
uint64_t _accessHash = 0;
|
||||
uint64_t _keyFingerprint = 0;
|
||||
|
||||
std::unique_ptr<tgvoip::VoIPController> _controller;
|
||||
|
||||
|
|
|
@ -112,16 +112,16 @@ ushort Offsets[] = {
|
|||
620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 641,
|
||||
642, 643, 644, 646, 648, 650, 652, 654, 656, 658 };
|
||||
|
||||
uint64 ComputeEmojiIndex(base::const_byte_span bytes) {
|
||||
uint64_t ComputeEmojiIndex(base::const_byte_span bytes) {
|
||||
Expects(bytes.size() == 8);
|
||||
return ((gsl::to_integer<uint64>(bytes[0]) & 0x7F) << 56)
|
||||
| (gsl::to_integer<uint64>(bytes[1]) << 48)
|
||||
| (gsl::to_integer<uint64>(bytes[2]) << 40)
|
||||
| (gsl::to_integer<uint64>(bytes[3]) << 32)
|
||||
| (gsl::to_integer<uint64>(bytes[4]) << 24)
|
||||
| (gsl::to_integer<uint64>(bytes[5]) << 16)
|
||||
| (gsl::to_integer<uint64>(bytes[6]) << 8)
|
||||
| (gsl::to_integer<uint64>(bytes[7]));
|
||||
return ((gsl::to_integer<uint64_t>(bytes[0]) & 0x7F) << 56)
|
||||
| (gsl::to_integer<uint64_t>(bytes[1]) << 48)
|
||||
| (gsl::to_integer<uint64_t>(bytes[2]) << 40)
|
||||
| (gsl::to_integer<uint64_t>(bytes[3]) << 32)
|
||||
| (gsl::to_integer<uint64_t>(bytes[4]) << 24)
|
||||
| (gsl::to_integer<uint64_t>(bytes[5]) << 16)
|
||||
| (gsl::to_integer<uint64_t>(bytes[6]) << 8)
|
||||
| (gsl::to_integer<uint64_t>(bytes[7]));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -49,8 +49,8 @@ class Panel::Button : public Ui::RippleButton {
|
|||
public:
|
||||
Button(QWidget *parent, const style::CallButton &stFrom, const style::CallButton *stTo = nullptr);
|
||||
|
||||
void setProgress(float64 progress);
|
||||
void setOuterValue(float64 value);
|
||||
void setProgress(double progress);
|
||||
void setOuterValue(double value);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
@ -66,13 +66,13 @@ private:
|
|||
|
||||
not_null<const style::CallButton*> _stFrom;
|
||||
const style::CallButton *_stTo = nullptr;
|
||||
float64 _progress = 0.;
|
||||
double _progress = 0.;
|
||||
|
||||
QImage _bgMask, _bg;
|
||||
QPixmap _bgFrom, _bgTo;
|
||||
QImage _iconMixedMask, _iconFrom, _iconTo, _iconMixed;
|
||||
|
||||
float64 _outerValue = 0.;
|
||||
double _outerValue = 0.;
|
||||
Animation _outerAnimation;
|
||||
|
||||
};
|
||||
|
@ -114,7 +114,7 @@ Panel::Button::Button(QWidget *parent, const style::CallButton &stFrom, const st
|
|||
}
|
||||
}
|
||||
|
||||
void Panel::Button::setOuterValue(float64 value) {
|
||||
void Panel::Button::setOuterValue(double value) {
|
||||
if (_outerValue != value) {
|
||||
_outerAnimation.start([this] {
|
||||
if (_progress == 0. || _progress == 1.) {
|
||||
|
@ -125,7 +125,7 @@ void Panel::Button::setOuterValue(float64 value) {
|
|||
}
|
||||
}
|
||||
|
||||
void Panel::Button::setProgress(float64 progress) {
|
||||
void Panel::Button::setProgress(double progress) {
|
||||
_progress = progress;
|
||||
update();
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ void Panel::Button::mixIconMasks() {
|
|||
|
||||
Painter p(&_iconMixedMask);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
auto paintIconMask = [this, &p](const QImage &mask, float64 angle) {
|
||||
auto paintIconMask = [this, &p](const QImage &mask, double angle) {
|
||||
auto skipFrom = _stFrom->button.rippleAreaSize / 2;
|
||||
p.translate(skipFrom, skipFrom);
|
||||
p.rotate(angle);
|
||||
|
|
|
@ -60,7 +60,7 @@ int BotKeyboard::Style::buttonRadius() const {
|
|||
return st::buttonRadius;
|
||||
}
|
||||
|
||||
void BotKeyboard::Style::paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const {
|
||||
void BotKeyboard::Style::paintButtonBg(Painter &p, const QRect &rect, double howMuchOver) const {
|
||||
App::roundRect(p, rect, st::botKbBg, BotKeyboardCorners);
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ private:
|
|||
void repaint(not_null<const HistoryItem*> item) const override;
|
||||
|
||||
protected:
|
||||
void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override;
|
||||
void paintButtonBg(Painter &p, const QRect &rect, double howMuchOver) const override;
|
||||
void paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const override;
|
||||
void paintButtonLoading(Painter &p, const QRect &rect) const override;
|
||||
int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const override;
|
||||
|
|
|
@ -186,7 +186,7 @@ void EmojiColorPicker::mouseReleaseEvent(QMouseEvent *e) {
|
|||
|
||||
void EmojiColorPicker::handleMouseRelease(QPoint globalPos) {
|
||||
_lastMousePos = globalPos;
|
||||
int32 pressed = _pressedSel;
|
||||
int32_t pressed = _pressedSel;
|
||||
_pressedSel = -1;
|
||||
|
||||
updateSelected();
|
||||
|
@ -492,7 +492,7 @@ void EmojiListWidget::mousePressEvent(QMouseEvent *e) {
|
|||
}
|
||||
|
||||
void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||
int32 pressed = _pressedSel;
|
||||
int32_t pressed = _pressedSel;
|
||||
_pressedSel = -1;
|
||||
|
||||
_lastMousePos = e->globalPos();
|
||||
|
@ -553,7 +553,7 @@ void EmojiListWidget::onShowPicker() {
|
|||
y += _picker->height() - st::buttonRadius + st::emojiPanSize.height() - st::buttonRadius;
|
||||
}
|
||||
auto xmax = width() - _picker->width();
|
||||
auto coef = float64(sel % kEmojiPanelPerRow) / float64(kEmojiPanelPerRow - 1);
|
||||
auto coef = double(sel % kEmojiPanelPerRow) / double(kEmojiPanelPerRow - 1);
|
||||
if (rtl()) coef = 1. - coef;
|
||||
_picker->move(qRound(xmax * coef), y);
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ private:
|
|||
int _counts[kEmojiSectionCount];
|
||||
QVector<EmojiPtr> _emoji[kEmojiSectionCount];
|
||||
|
||||
int32 _esize;
|
||||
int32_t _esize;
|
||||
|
||||
int _selected = -1;
|
||||
int _pressedSel = -1;
|
||||
|
|
|
@ -142,7 +142,7 @@ inline int indexOfInFirstN(const T &v, const U &elem, int last) {
|
|||
}
|
||||
|
||||
void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
||||
int32 now = unixtime(), recentInlineBots = 0;
|
||||
int32_t now = unixtime(), recentInlineBots = 0;
|
||||
internal::MentionRows mrows;
|
||||
internal::HashtagRows hrows;
|
||||
internal::BotCommandRows brows;
|
||||
|
@ -190,7 +190,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
}
|
||||
}
|
||||
if (_chat) {
|
||||
QMultiMap<int32, UserData*> ordered;
|
||||
QMultiMap<int32_t, UserData*> ordered;
|
||||
mrows.reserve(mrows.size() + (_chat->participants.isEmpty() ? _chat->lastAuthors.size() : _chat->participants.size()));
|
||||
if (_chat->noParticipantInfo()) {
|
||||
Auth().api().requestFullPeer(_chat);
|
||||
|
@ -219,7 +219,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
}
|
||||
}
|
||||
} else if (_channel && _channel->isMegagroup()) {
|
||||
QMultiMap<int32, UserData*> ordered;
|
||||
QMultiMap<int32_t, UserData*> ordered;
|
||||
if (_channel->mgInfo->lastParticipants.isEmpty() || _channel->lastParticipantsCountOutdated()) {
|
||||
Auth().api().requestLastParticipants(_channel);
|
||||
} else {
|
||||
|
@ -246,7 +246,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
bool listAllSuggestions = _filter.isEmpty();
|
||||
bool hasUsername = _filter.indexOf('@') > 0;
|
||||
QMap<UserData*, bool> bots;
|
||||
int32 cnt = 0;
|
||||
int32_t cnt = 0;
|
||||
if (_chat) {
|
||||
if (_chat->noParticipantInfo()) {
|
||||
Auth().api().requestFullPeer(_chat);
|
||||
|
@ -287,7 +287,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
}
|
||||
if (cnt) {
|
||||
brows.reserve(cnt);
|
||||
int32 botStatus = _chat ? _chat->botStatus : ((_channel && _channel->isMegagroup()) ? _channel->mgInfo->botStatus : -1);
|
||||
int32_t botStatus = _chat ? _chat->botStatus : ((_channel && _channel->isMegagroup()) ? _channel->mgInfo->botStatus : -1);
|
||||
if (_chat) {
|
||||
for (auto i = _chat->lastAuthors.cbegin(), e = _chat->lastAuthors.cend(); i != e; ++i) {
|
||||
auto user = *i;
|
||||
|
@ -314,7 +314,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
if (!bots.isEmpty()) {
|
||||
for (QMap<UserData*, bool>::const_iterator i = bots.cbegin(), e = bots.cend(); i != e; ++i) {
|
||||
UserData *user = i.key();
|
||||
for (int32 j = 0, l = user->botInfo->commands.size(); j < l; ++j) {
|
||||
for (int32_t j = 0, l = user->botInfo->commands.size(); j < l; ++j) {
|
||||
if (!listAllSuggestions) {
|
||||
QString toFilter = (hasUsername || botStatus == 0 || botStatus == 2) ? user->botInfo->commands.at(j).command + '@' + user->username : user->botInfo->commands.at(j).command;
|
||||
if (!toFilter.startsWith(_filter, Qt::CaseInsensitive)/* || toFilter.size() == _filter.size()*/) continue;
|
||||
|
@ -364,10 +364,10 @@ void FieldAutocomplete::setBoundings(QRect boundings) {
|
|||
}
|
||||
|
||||
void FieldAutocomplete::recount(bool resetScroll) {
|
||||
int32 h = 0, oldst = _scroll->scrollTop(), st = oldst, maxh = 4.5 * st::mentionHeight;
|
||||
int32_t h = 0, oldst = _scroll->scrollTop(), st = oldst, maxh = 4.5 * st::mentionHeight;
|
||||
if (!_srows.isEmpty()) {
|
||||
int32 stickersPerRow = qMax(1, int32(_boundings.width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()));
|
||||
int32 rows = rowscount(_srows.size(), stickersPerRow);
|
||||
int32_t stickersPerRow = qMax(1, int32_t(_boundings.width() - 2 * st::stickerPanPadding) / int32_t(st::stickerPanSize.width()));
|
||||
int32_t rows = rowscount(_srows.size(), stickersPerRow);
|
||||
h = st::stickerPanPadding + rows * st::stickerPanSize.height();
|
||||
} else if (!_mrows.isEmpty()) {
|
||||
h = _mrows.size() * st::mentionHeight;
|
||||
|
@ -465,11 +465,11 @@ UserData *FieldAutocomplete::user() const {
|
|||
return _user;
|
||||
}
|
||||
|
||||
int32 FieldAutocomplete::innerTop() {
|
||||
int32_t FieldAutocomplete::innerTop() {
|
||||
return _scroll->scrollTop();
|
||||
}
|
||||
|
||||
int32 FieldAutocomplete::innerBottom() {
|
||||
int32_t FieldAutocomplete::innerBottom() {
|
||||
return _scroll->scrollTop() + _scroll->height();
|
||||
}
|
||||
|
||||
|
@ -531,20 +531,20 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
QRect r(e->rect());
|
||||
if (r != rect()) p.setClipRect(r);
|
||||
|
||||
int32 atwidth = st::mentionFont->width('@'), hashwidth = st::mentionFont->width('#');
|
||||
int32 mentionleft = 2 * st::mentionPadding.left() + st::mentionPhotoSize;
|
||||
int32 mentionwidth = width() - mentionleft - 2 * st::mentionPadding.right();
|
||||
int32 htagleft = st::historyAttach.width + st::historyComposeField.textMrg.left() - st::lineWidth, htagwidth = width() - st::mentionPadding.right() - htagleft - st::mentionScroll.width;
|
||||
int32_t atwidth = st::mentionFont->width('@'), hashwidth = st::mentionFont->width('#');
|
||||
int32_t mentionleft = 2 * st::mentionPadding.left() + st::mentionPhotoSize;
|
||||
int32_t mentionwidth = width() - mentionleft - 2 * st::mentionPadding.right();
|
||||
int32_t htagleft = st::historyAttach.width + st::historyComposeField.textMrg.left() - st::lineWidth, htagwidth = width() - st::mentionPadding.right() - htagleft - st::mentionScroll.width;
|
||||
|
||||
if (!_srows->isEmpty()) {
|
||||
int32 rows = rowscount(_srows->size(), _stickersPerRow);
|
||||
int32 fromrow = floorclamp(r.y() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
|
||||
int32 torow = ceilclamp(r.y() + r.height() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
|
||||
int32 fromcol = floorclamp(r.x() - st::stickerPanPadding, st::stickerPanSize.width(), 0, _stickersPerRow);
|
||||
int32 tocol = ceilclamp(r.x() + r.width() - st::stickerPanPadding, st::stickerPanSize.width(), 0, _stickersPerRow);
|
||||
for (int32 row = fromrow; row < torow; ++row) {
|
||||
for (int32 col = fromcol; col < tocol; ++col) {
|
||||
int32 index = row * _stickersPerRow + col;
|
||||
int32_t rows = rowscount(_srows->size(), _stickersPerRow);
|
||||
int32_t fromrow = floorclamp(r.y() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
|
||||
int32_t torow = ceilclamp(r.y() + r.height() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
|
||||
int32_t fromcol = floorclamp(r.x() - st::stickerPanPadding, st::stickerPanSize.width(), 0, _stickersPerRow);
|
||||
int32_t tocol = ceilclamp(r.x() + r.width() - st::stickerPanPadding, st::stickerPanSize.width(), 0, _stickersPerRow);
|
||||
for (int32_t row = fromrow; row < torow; ++row) {
|
||||
for (int32_t col = fromcol; col < tocol; ++col) {
|
||||
int32_t index = row * _stickersPerRow + col;
|
||||
if (index >= _srows->size()) break;
|
||||
|
||||
DocumentData *sticker = _srows->at(index);
|
||||
|
@ -564,9 +564,9 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
sticker->checkSticker();
|
||||
}
|
||||
|
||||
float64 coef = qMin((st::stickerPanSize.width() - st::buttonRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::buttonRadius * 2) / float64(sticker->dimensions.height()));
|
||||
double coef = qMin((st::stickerPanSize.width() - st::buttonRadius * 2) / double(sticker->dimensions.width()), (st::stickerPanSize.height() - st::buttonRadius * 2) / double(sticker->dimensions.height()));
|
||||
if (coef > 1) coef = 1;
|
||||
int32 w = qRound(coef * sticker->dimensions.width()), h = qRound(coef * sticker->dimensions.height());
|
||||
int32_t w = qRound(coef * sticker->dimensions.width()), h = qRound(coef * sticker->dimensions.height());
|
||||
if (w < 1) w = 1;
|
||||
if (h < 1) h = 1;
|
||||
QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2);
|
||||
|
@ -578,13 +578,13 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
int32 from = qFloor(e->rect().top() / st::mentionHeight), to = qFloor(e->rect().bottom() / st::mentionHeight) + 1;
|
||||
int32 last = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size();
|
||||
int32_t from = qFloor(e->rect().top() / st::mentionHeight), to = qFloor(e->rect().bottom() / st::mentionHeight) + 1;
|
||||
int32_t last = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size();
|
||||
auto filter = _parent->filter();
|
||||
bool hasUsername = filter.indexOf('@') > 0;
|
||||
int filterSize = filter.size();
|
||||
bool filterIsEmpty = filter.isEmpty();
|
||||
for (int32 i = from; i < to; ++i) {
|
||||
for (int32_t i = from; i < to; ++i) {
|
||||
if (i >= last) break;
|
||||
|
||||
bool selected = (i == _sel);
|
||||
|
@ -599,7 +599,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
UserData *user = _mrows->at(i);
|
||||
QString first = (!filterIsEmpty && user->username.startsWith(filter, Qt::CaseInsensitive)) ? ('@' + user->username.mid(0, filterSize)) : QString();
|
||||
QString second = first.isEmpty() ? (user->username.isEmpty() ? QString() : ('@' + user->username)) : user->username.mid(filterSize);
|
||||
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth();
|
||||
int32_t firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth();
|
||||
if (mentionwidth < unamewidth + namewidth) {
|
||||
namewidth = (mentionwidth * namewidth) / (namewidth + unamewidth);
|
||||
unamewidth = mentionwidth - namewidth;
|
||||
|
@ -631,7 +631,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
QString hrow = _hrows->at(i);
|
||||
QString first = filterIsEmpty ? QString() : ('#' + hrow.mid(0, filterSize));
|
||||
QString second = filterIsEmpty ? ('#' + hrow) : hrow.mid(filterSize);
|
||||
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);
|
||||
int32_t firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);
|
||||
if (htagwidth < firstwidth + secondwidth) {
|
||||
if (htagwidth < firstwidth + st::mentionFont->elidew) {
|
||||
first = st::mentionFont->elided(first + second, htagwidth);
|
||||
|
@ -655,7 +655,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
|
||||
const BotCommand *command = _brows->at(i).second;
|
||||
QString toHighlight = command->command;
|
||||
int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1);
|
||||
int32_t botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1);
|
||||
if (hasUsername || botStatus == 0 || botStatus == 2) {
|
||||
toHighlight += '@' + user->username;
|
||||
}
|
||||
|
@ -684,7 +684,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
void FieldAutocompleteInner::resizeEvent(QResizeEvent *e) {
|
||||
_stickersPerRow = qMax(1, int32(width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()));
|
||||
_stickersPerRow = qMax(1, int32_t(width() - 2 * st::stickerPanPadding) / int32_t(st::stickerPanSize.width()));
|
||||
}
|
||||
|
||||
void FieldAutocompleteInner::mouseMoveEvent(QMouseEvent *e) {
|
||||
|
@ -704,8 +704,8 @@ void FieldAutocompleteInner::clearSel(bool hidden) {
|
|||
|
||||
bool FieldAutocompleteInner::moveSel(int key) {
|
||||
_mouseSel = false;
|
||||
int32 maxSel = (_mrows->isEmpty() ? (_hrows->isEmpty() ? (_brows->isEmpty() ? _srows->size() : _brows->size()) : _hrows->size()) : _mrows->size());
|
||||
int32 direction = (key == Qt::Key_Up) ? -1 : (key == Qt::Key_Down ? 1 : 0);
|
||||
int32_t maxSel = (_mrows->isEmpty() ? (_hrows->isEmpty() ? (_brows->isEmpty() ? _srows->size() : _brows->size()) : _hrows->size()) : _mrows->size());
|
||||
int32_t direction = (key == Qt::Key_Up) ? -1 : (key == Qt::Key_Down ? 1 : 0);
|
||||
if (!_srows->isEmpty()) {
|
||||
if (key == Qt::Key_Left) {
|
||||
direction = -1;
|
||||
|
@ -749,7 +749,7 @@ bool FieldAutocompleteInner::chooseSelected(FieldAutocomplete::ChooseMethod meth
|
|||
if (_sel >= 0 && _sel < _brows->size()) {
|
||||
UserData *user = _brows->at(_sel).first;
|
||||
const BotCommand *command(_brows->at(_sel).second);
|
||||
int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1);
|
||||
int32_t botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1);
|
||||
if (botStatus == 0 || botStatus == 2 || _parent->filter().indexOf('@') > 0) {
|
||||
emit botCommandChosen('/' + command->command + '@' + user->username, method);
|
||||
} else {
|
||||
|
@ -761,7 +761,7 @@ bool FieldAutocompleteInner::chooseSelected(FieldAutocomplete::ChooseMethod meth
|
|||
return false;
|
||||
}
|
||||
|
||||
void FieldAutocompleteInner::setRecentInlineBotsInRows(int32 bots) {
|
||||
void FieldAutocompleteInner::setRecentInlineBotsInRows(int32_t bots) {
|
||||
_recentInlineBotsInRows = bots;
|
||||
}
|
||||
|
||||
|
@ -787,7 +787,7 @@ void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) {
|
|||
} else {
|
||||
UserData *toRemove = _mrows->at(_sel);
|
||||
RecentInlineBots &recent(cRefRecentInlineBots());
|
||||
int32 index = recent.indexOf(toRemove);
|
||||
int32_t index = recent.indexOf(toRemove);
|
||||
if (index >= 0) {
|
||||
recent.remove(index);
|
||||
removed = true;
|
||||
|
@ -812,7 +812,7 @@ void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) {
|
|||
void FieldAutocompleteInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
_previewTimer.stop();
|
||||
|
||||
int32 pressed = _down;
|
||||
int32_t pressed = _down;
|
||||
_down = -1;
|
||||
|
||||
_mousePos = mapToGlobal(e->pos());
|
||||
|
@ -847,7 +847,7 @@ void FieldAutocompleteInner::updateSelectedRow() {
|
|||
if (_srows->isEmpty()) {
|
||||
update(0, _sel * st::mentionHeight, width(), st::mentionHeight);
|
||||
} else {
|
||||
int32 row = _sel / _stickersPerRow, col = _sel % _stickersPerRow;
|
||||
int32_t row = _sel / _stickersPerRow, col = _sel % _stickersPerRow;
|
||||
update(st::stickerPanPadding + col * st::stickerPanSize.width(), st::stickerPanPadding + row * st::stickerPanSize.height(), st::stickerPanSize.width(), st::stickerPanSize.height());
|
||||
}
|
||||
}
|
||||
|
@ -862,7 +862,7 @@ void FieldAutocompleteInner::setSel(int sel, bool scroll) {
|
|||
if (_srows->isEmpty()) {
|
||||
emit mustScrollTo(_sel * st::mentionHeight, (_sel + 1) * st::mentionHeight);
|
||||
} else {
|
||||
int32 row = _sel / _stickersPerRow;
|
||||
int32_t row = _sel / _stickersPerRow;
|
||||
emit mustScrollTo(st::stickerPanPadding + row * st::stickerPanSize.height(), st::stickerPanPadding + (row + 1) * st::stickerPanSize.height());
|
||||
}
|
||||
}
|
||||
|
@ -874,18 +874,18 @@ void FieldAutocompleteInner::onUpdateSelected(bool force) {
|
|||
|
||||
if (_down >= 0 && !_previewShown) return;
|
||||
|
||||
int32 sel = -1, maxSel = 0;
|
||||
int32_t sel = -1, maxSel = 0;
|
||||
if (!_srows->isEmpty()) {
|
||||
int32 rows = rowscount(_srows->size(), _stickersPerRow);
|
||||
int32 row = (mouse.y() >= st::stickerPanPadding) ? ((mouse.y() - st::stickerPanPadding) / st::stickerPanSize.height()) : -1;
|
||||
int32 col = (mouse.x() >= st::stickerPanPadding) ? ((mouse.x() - st::stickerPanPadding) / st::stickerPanSize.width()) : -1;
|
||||
int32_t rows = rowscount(_srows->size(), _stickersPerRow);
|
||||
int32_t row = (mouse.y() >= st::stickerPanPadding) ? ((mouse.y() - st::stickerPanPadding) / st::stickerPanSize.height()) : -1;
|
||||
int32_t col = (mouse.x() >= st::stickerPanPadding) ? ((mouse.x() - st::stickerPanPadding) / st::stickerPanSize.width()) : -1;
|
||||
if (row >= 0 && col >= 0) {
|
||||
sel = row * _stickersPerRow + col;
|
||||
}
|
||||
maxSel = _srows->size();
|
||||
_overDelete = false;
|
||||
} else {
|
||||
sel = mouse.y() / int32(st::mentionHeight);
|
||||
sel = mouse.y() / int32_t(st::mentionHeight);
|
||||
maxSel = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size();
|
||||
_overDelete = (!_hrows->isEmpty() || (!_mrows->isEmpty() && sel < _recentInlineBotsInRows)) ? (mouse.x() >= width() - st::mentionHeight) : false;
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ public:
|
|||
ChannelData *channel() const;
|
||||
UserData *user() const;
|
||||
|
||||
int32 innerTop();
|
||||
int32 innerBottom();
|
||||
int32_t innerTop();
|
||||
int32_t innerBottom();
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *e) override;
|
||||
|
||||
|
@ -126,7 +126,7 @@ private:
|
|||
QRect _boundings;
|
||||
bool _addInlineBots;
|
||||
|
||||
int32 _width, _height;
|
||||
int32_t _width, _height;
|
||||
bool _hiding = false;
|
||||
|
||||
Animation _a_opacity;
|
||||
|
@ -147,7 +147,7 @@ public:
|
|||
bool moveSel(int key);
|
||||
bool chooseSelected(FieldAutocomplete::ChooseMethod method) const;
|
||||
|
||||
void setRecentInlineBotsInRows(int32 bots);
|
||||
void setRecentInlineBotsInRows(int32_t bots);
|
||||
|
||||
signals:
|
||||
void mentionChosen(UserData *user, FieldAutocomplete::ChooseMethod method) const;
|
||||
|
@ -180,8 +180,8 @@ private:
|
|||
HashtagRows *_hrows;
|
||||
BotCommandRows *_brows;
|
||||
StickerPack *_srows;
|
||||
int32 _stickersPerRow, _recentInlineBotsInRows;
|
||||
int32 _sel, _down;
|
||||
int32_t _stickersPerRow, _recentInlineBotsInRows;
|
||||
int32_t _sel, _down;
|
||||
bool _mouseSel;
|
||||
QPoint _mousePos;
|
||||
|
||||
|
|
|
@ -418,7 +418,7 @@ void GifsListWidget::processPanelHideFinished() {
|
|||
}
|
||||
}
|
||||
|
||||
bool GifsListWidget::inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, Row &row, int32 &sumWidth) {
|
||||
bool GifsListWidget::inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, Row &row, int32_t &sumWidth) {
|
||||
LayoutItem *layout = nullptr;
|
||||
if (savedGif) {
|
||||
layout = layoutPrepareSavedGif(savedGif, (_rows.size() * MatrixRowShift) + row.items.size());
|
||||
|
@ -441,7 +441,7 @@ bool GifsListWidget::inlineRowsAddItem(DocumentData *savedGif, InlineResult *res
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GifsListWidget::inlineRowFinalize(Row &row, int32 &sumWidth, bool force) {
|
||||
bool GifsListWidget::inlineRowFinalize(Row &row, int32_t &sumWidth, bool force) {
|
||||
if (row.items.isEmpty()) return false;
|
||||
|
||||
auto full = (row.items.size() >= kInlineItemsMaxPerRow);
|
||||
|
@ -502,7 +502,7 @@ void GifsListWidget::clearInlineRows(bool resultsDeleted) {
|
|||
_rows.clear();
|
||||
}
|
||||
|
||||
GifsListWidget::LayoutItem *GifsListWidget::layoutPrepareSavedGif(DocumentData *doc, int32 position) {
|
||||
GifsListWidget::LayoutItem *GifsListWidget::layoutPrepareSavedGif(DocumentData *doc, int32_t position) {
|
||||
auto it = _gifLayouts.find(doc);
|
||||
if (it == _gifLayouts.cend()) {
|
||||
if (auto layout = LayoutItem::createLayoutGif(this, doc)) {
|
||||
|
@ -518,7 +518,7 @@ GifsListWidget::LayoutItem *GifsListWidget::layoutPrepareSavedGif(DocumentData *
|
|||
return it->second.get();
|
||||
}
|
||||
|
||||
GifsListWidget::LayoutItem *GifsListWidget::layoutPrepareInlineResult(InlineResult *result, int32 position) {
|
||||
GifsListWidget::LayoutItem *GifsListWidget::layoutPrepareInlineResult(InlineResult *result, int32_t position) {
|
||||
auto it = _inlineLayouts.find(result);
|
||||
if (it == _inlineLayouts.cend()) {
|
||||
if (auto layout = LayoutItem::createLayout(this, result, _inlineWithThumb)) {
|
||||
|
@ -562,7 +562,7 @@ void GifsListWidget::deleteUnusedInlineLayouts() {
|
|||
}
|
||||
}
|
||||
|
||||
GifsListWidget::Row &GifsListWidget::layoutInlineRow(Row &row, int32 sumWidth) {
|
||||
GifsListWidget::Row &GifsListWidget::layoutInlineRow(Row &row, int32_t sumWidth) {
|
||||
auto count = int(row.items.size());
|
||||
Assert(count <= kInlineItemsMaxPerRow);
|
||||
|
||||
|
@ -640,7 +640,7 @@ int GifsListWidget::refreshInlineRows(const InlineCacheEntry *entry, bool result
|
|||
inlineRowFinalize(row, sumWidth, true);
|
||||
}
|
||||
|
||||
int32 h = countHeight();
|
||||
int32_t h = countHeight();
|
||||
if (h != height()) resize(width(), h);
|
||||
update();
|
||||
|
||||
|
@ -763,7 +763,7 @@ void GifsListWidget::beforeHiding() {
|
|||
}
|
||||
}
|
||||
|
||||
bool GifsListWidget::refreshInlineRows(int32 *added) {
|
||||
bool GifsListWidget::refreshInlineRows(int32_t *added) {
|
||||
auto it = _inlineCache.find(_inlineQuery);
|
||||
const InlineCacheEntry *entry = nullptr;
|
||||
if (it != _inlineCache.cend()) {
|
||||
|
@ -775,7 +775,7 @@ bool GifsListWidget::refreshInlineRows(int32 *added) {
|
|||
return (entry != nullptr);
|
||||
}
|
||||
|
||||
int32 GifsListWidget::showInlineRows(bool newResults) {
|
||||
int32_t GifsListWidget::showInlineRows(bool newResults) {
|
||||
auto added = 0;
|
||||
auto clear = !refreshInlineRows(&added);
|
||||
if (newResults) {
|
||||
|
|
|
@ -117,8 +117,8 @@ private:
|
|||
int refreshInlineRows(const InlineCacheEntry *results, bool resultsDeleted);
|
||||
void checkLoadMore();
|
||||
|
||||
int32 showInlineRows(bool newResults);
|
||||
bool refreshInlineRows(int32 *added = 0);
|
||||
int32_t showInlineRows(bool newResults);
|
||||
bool refreshInlineRows(int32_t *added = 0);
|
||||
void inlineResultsDone(const MTPmessages_BotResults &result);
|
||||
|
||||
void updateSelected();
|
||||
|
@ -137,15 +137,15 @@ private:
|
|||
void clearInlineRows(bool resultsDeleted);
|
||||
|
||||
std::map<DocumentData*, std::unique_ptr<LayoutItem>> _gifLayouts;
|
||||
LayoutItem *layoutPrepareSavedGif(DocumentData *doc, int32 position);
|
||||
LayoutItem *layoutPrepareSavedGif(DocumentData *doc, int32_t position);
|
||||
|
||||
std::map<InlineResult*, std::unique_ptr<LayoutItem>> _inlineLayouts;
|
||||
LayoutItem *layoutPrepareInlineResult(InlineResult *result, int32 position);
|
||||
LayoutItem *layoutPrepareInlineResult(InlineResult *result, int32_t position);
|
||||
|
||||
bool inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, Row &row, int32 &sumWidth);
|
||||
bool inlineRowFinalize(Row &row, int32 &sumWidth, bool force = false);
|
||||
bool inlineRowsAddItem(DocumentData *savedGif, InlineResult *result, Row &row, int32_t &sumWidth);
|
||||
bool inlineRowFinalize(Row &row, int32_t &sumWidth, bool force = false);
|
||||
|
||||
Row &layoutInlineRow(Row &row, int32 sumWidth = 0);
|
||||
Row &layoutInlineRow(Row &row, int32_t sumWidth = 0);
|
||||
void deleteUnusedGifLayouts();
|
||||
|
||||
void deleteUnusedInlineLayouts();
|
||||
|
|
|
@ -144,8 +144,8 @@ void MessageField::dropEvent(QDropEvent *e) {
|
|||
|
||||
bool MessageField::canInsertFromMimeData(const QMimeData *source) const {
|
||||
if (source->hasUrls()) {
|
||||
int32 files = 0;
|
||||
for (int32 i = 0; i < source->urls().size(); ++i) {
|
||||
int32_t files = 0;
|
||||
for (int32_t i = 0; i < source->urls().size(); ++i) {
|
||||
if (source->urls().at(i).isLocalFile()) {
|
||||
++files;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
|
|||
auto &order = Global::RefStickerSetsOrder();
|
||||
Order archived;
|
||||
archived.reserve(v.size());
|
||||
QMap<uint64, uint64> setsToRequest;
|
||||
QMap<uint64_t, uint64_t> setsToRequest;
|
||||
for_const (auto &stickerSet, v) {
|
||||
const MTPDstickerSet *setData = nullptr;
|
||||
switch (stickerSet.type()) {
|
||||
|
@ -96,7 +96,7 @@ bool ApplyArchivedResultFake() {
|
|||
auto sets = QVector<MTPStickerSetCovered>();
|
||||
for (auto &set : Global::RefStickerSets()) {
|
||||
if ((set.flags & MTPDstickerSet::Flag::f_installed) && !(set.flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
if (rand_value<uint32>() % 128 < 64) {
|
||||
if (rand_value<uint32_t>() % 128 < 64) {
|
||||
auto data = MTP_stickerSet(MTP_flags(set.flags | MTPDstickerSet::Flag::f_archived), MTP_long(set.id), MTP_long(set.access), MTP_string(set.title), MTP_string(set.shortName), MTP_int(set.count), MTP_int(set.hash));
|
||||
sets.push_back(MTP_stickerSetCovered(data, MTP_documentEmpty(MTP_long(0))));
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ bool ApplyArchivedResultFake() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void InstallLocally(uint64 setId) {
|
||||
void InstallLocally(uint64_t setId) {
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.end()) {
|
||||
|
@ -151,7 +151,7 @@ void InstallLocally(uint64 setId) {
|
|||
Auth().data().stickersUpdated().notify(true);
|
||||
}
|
||||
|
||||
void UndoInstallLocally(uint64 setId) {
|
||||
void UndoInstallLocally(uint64_t setId) {
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.end()) {
|
||||
|
@ -172,7 +172,7 @@ void UndoInstallLocally(uint64 setId) {
|
|||
Ui::show(Box<InformBox>(lang(lng_stickers_not_found)), KeepOtherLayers);
|
||||
}
|
||||
|
||||
void MarkFeaturedAsRead(uint64 setId) {
|
||||
void MarkFeaturedAsRead(uint64_t setId) {
|
||||
if (!FeaturedReaderInstance) {
|
||||
if (auto main = App::main()) {
|
||||
FeaturedReaderInstance = object_ptr<internal::FeaturedReader>(main);
|
||||
|
@ -338,12 +338,12 @@ void SetFaved(not_null<DocumentData*> document, bool faved) {
|
|||
}
|
||||
}
|
||||
|
||||
void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
|
||||
void SetsReceived(const QVector<MTPStickerSet> &data, int32_t hash) {
|
||||
auto &setsOrder = Global::RefStickerSetsOrder();
|
||||
setsOrder.clear();
|
||||
|
||||
auto &sets = Global::RefStickerSets();
|
||||
QMap<uint64, uint64> setsToRequest;
|
||||
QMap<uint64_t, uint64_t> setsToRequest;
|
||||
for (auto &set : sets) {
|
||||
if (!(set.flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
set.flags &= ~MTPDstickerSet::Flag::f_installed; // mark for removing
|
||||
|
@ -425,7 +425,7 @@ void SetPackAndEmoji(Set &set, StickerPack &&pack, const QVector<MTPStickerPack>
|
|||
}
|
||||
}
|
||||
|
||||
void SpecialSetReceived(uint64 setId, const QString &setTitle, const QVector<MTPDocument> &items, int32 hash, const QVector<MTPStickerPack> &packs) {
|
||||
void SpecialSetReceived(uint64_t setId, const QString &setTitle, const QVector<MTPDocument> &items, int32_t hash, const QVector<MTPStickerPack> &packs) {
|
||||
auto &sets = Global::RefStickerSets();
|
||||
auto it = sets.find(setId);
|
||||
|
||||
|
@ -503,8 +503,8 @@ void SpecialSetReceived(uint64 setId, const QString &setTitle, const QVector<MTP
|
|||
Auth().data().stickersUpdated().notify(true);
|
||||
}
|
||||
|
||||
void FeaturedSetsReceived(const QVector<MTPStickerSetCovered> &data, const QVector<MTPlong> &unread, int32 hash) {
|
||||
OrderedSet<uint64> unreadMap;
|
||||
void FeaturedSetsReceived(const QVector<MTPStickerSetCovered> &data, const QVector<MTPlong> &unread, int32_t hash) {
|
||||
OrderedSet<uint64_t> unreadMap;
|
||||
for_const (auto &unreadSetId, unread) {
|
||||
unreadMap.insert(unreadSetId.v);
|
||||
}
|
||||
|
@ -513,7 +513,7 @@ void FeaturedSetsReceived(const QVector<MTPStickerSetCovered> &data, const QVect
|
|||
setsOrder.clear();
|
||||
|
||||
auto &sets = Global::RefStickerSets();
|
||||
QMap<uint64, uint64> setsToRequest;
|
||||
QMap<uint64_t, uint64_t> setsToRequest;
|
||||
for (auto &set : sets) {
|
||||
set.flags &= ~MTPDstickerSet_ClientFlag::f_featured; // mark for removing
|
||||
}
|
||||
|
@ -606,7 +606,7 @@ void FeaturedSetsReceived(const QVector<MTPStickerSetCovered> &data, const QVect
|
|||
Auth().data().stickersUpdated().notify(true);
|
||||
}
|
||||
|
||||
void GifsReceived(const QVector<MTPDocument> &items, int32 hash) {
|
||||
void GifsReceived(const QVector<MTPDocument> &items, int32_t hash) {
|
||||
auto &saved = cRefSavedGifs();
|
||||
saved.clear();
|
||||
|
||||
|
@ -632,7 +632,7 @@ void GifsReceived(const QVector<MTPDocument> &items, int32 hash) {
|
|||
StickerPack GetListByEmoji(not_null<EmojiPtr> emoji) {
|
||||
auto original = emoji->original();
|
||||
auto result = StickerPack();
|
||||
auto setsToRequest = QMap<uint64, uint64>();
|
||||
auto setsToRequest = QMap<uint64_t, uint64_t>();
|
||||
auto &sets = Global::RefStickerSets();
|
||||
|
||||
auto faved = StickerPack();
|
||||
|
@ -840,7 +840,7 @@ FeaturedReader::FeaturedReader(QObject *parent) : QObject(parent)
|
|||
_timer->setTimeoutHandler([this] { readSets(); });
|
||||
}
|
||||
|
||||
void FeaturedReader::scheduleRead(uint64 setId) {
|
||||
void FeaturedReader::scheduleRead(uint64_t setId) {
|
||||
if (!_setIds.contains(setId)) {
|
||||
_setIds.insert(setId);
|
||||
_timer->start(kReadFeaturedSetsTimeoutMs);
|
||||
|
|
|
@ -28,16 +28,16 @@ constexpr auto kPanelPerRow = 5;
|
|||
|
||||
void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d);
|
||||
bool ApplyArchivedResultFake(); // For testing.
|
||||
void InstallLocally(uint64 setId);
|
||||
void UndoInstallLocally(uint64 setId);
|
||||
void MarkFeaturedAsRead(uint64 setId);
|
||||
void InstallLocally(uint64_t setId);
|
||||
void UndoInstallLocally(uint64_t setId);
|
||||
void MarkFeaturedAsRead(uint64_t setId);
|
||||
bool IsFaved(not_null<DocumentData*> document);
|
||||
void SetFaved(not_null<DocumentData*> document, bool faved);
|
||||
|
||||
void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash);
|
||||
void SpecialSetReceived(uint64 setId, const QString &setTitle, const QVector<MTPDocument> &items, int32 hash, const QVector<MTPStickerPack> &packs = QVector<MTPStickerPack>());
|
||||
void FeaturedSetsReceived(const QVector<MTPStickerSetCovered> &data, const QVector<MTPlong> &unread, int32 hash);
|
||||
void GifsReceived(const QVector<MTPDocument> &items, int32 hash);
|
||||
void SetsReceived(const QVector<MTPStickerSet> &data, int32_t hash);
|
||||
void SpecialSetReceived(uint64_t setId, const QString &setTitle, const QVector<MTPDocument> &items, int32_t hash, const QVector<MTPStickerPack> &packs = QVector<MTPStickerPack>());
|
||||
void FeaturedSetsReceived(const QVector<MTPStickerSetCovered> &data, const QVector<MTPlong> &unread, int32_t hash);
|
||||
void GifsReceived(const QVector<MTPDocument> &items, int32_t hash);
|
||||
|
||||
StickerPack GetListByEmoji(not_null<EmojiPtr> emoji);
|
||||
base::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
|
||||
|
@ -53,13 +53,13 @@ namespace internal {
|
|||
class FeaturedReader : public QObject, private MTP::Sender {
|
||||
public:
|
||||
FeaturedReader(QObject *parent);
|
||||
void scheduleRead(uint64 setId);
|
||||
void scheduleRead(uint64_t setId);
|
||||
|
||||
private:
|
||||
void readSets();
|
||||
|
||||
object_ptr<SingleTimer> _timer;
|
||||
OrderedSet<uint64> _setIds;
|
||||
OrderedSet<uint64_t> _setIds;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -46,11 +46,11 @@ constexpr auto kInlineItemsMaxPerRow = 5;
|
|||
} // namespace
|
||||
|
||||
struct StickerIcon {
|
||||
StickerIcon(uint64 setId) : setId(setId) {
|
||||
StickerIcon(uint64_t setId) : setId(setId) {
|
||||
}
|
||||
StickerIcon(uint64 setId, DocumentData *sticker, int32 pixw, int32 pixh) : setId(setId), sticker(sticker), pixw(pixw), pixh(pixh) {
|
||||
StickerIcon(uint64_t setId, DocumentData *sticker, int32_t pixw, int32_t pixh) : setId(setId), sticker(sticker), pixw(pixw), pixh(pixh) {
|
||||
}
|
||||
uint64 setId = 0;
|
||||
uint64_t setId = 0;
|
||||
DocumentData *sticker = nullptr;
|
||||
ChannelData *megagroup = nullptr;
|
||||
int pixw = 0;
|
||||
|
@ -63,7 +63,7 @@ public:
|
|||
Footer(not_null<StickersListWidget*> parent);
|
||||
|
||||
void preloadImages();
|
||||
void validateSelectedIcon(uint64 setId, ValidateIconAnimations animations);
|
||||
void validateSelectedIcon(uint64_t setId, ValidateIconAnimations animations);
|
||||
void refreshIcons(ValidateIconAnimations animations);
|
||||
bool hasOnlyFeaturedSets() const;
|
||||
|
||||
|
@ -143,7 +143,7 @@ void StickersListWidget::Footer::preloadImages() {
|
|||
});
|
||||
}
|
||||
|
||||
void StickersListWidget::Footer::validateSelectedIcon(uint64 setId, ValidateIconAnimations animations) {
|
||||
void StickersListWidget::Footer::validateSelectedIcon(uint64_t setId, ValidateIconAnimations animations) {
|
||||
auto newSel = 0;
|
||||
for (auto i = 0, l = _icons.size(); i != l; ++i) {
|
||||
if (_icons[i].setId == setId) {
|
||||
|
@ -214,7 +214,7 @@ void StickersListWidget::Footer::paintEvent(QPaintEvent *e) {
|
|||
} else if (icon.megagroup) {
|
||||
icon.megagroup->paintUserpicLeft(p, x + (st::emojiCategory.width - st::stickerGroupCategorySize) / 2, _iconsTop + (st::emojiCategory.height - st::stickerGroupCategorySize) / 2, width(), st::stickerGroupCategorySize);
|
||||
} else {
|
||||
auto getSpecialSetIcon = [](uint64 setId) {
|
||||
auto getSpecialSetIcon = [](uint64_t setId) {
|
||||
if (setId == Stickers::FeaturedSetId) {
|
||||
return &st::stickersTrending;
|
||||
} else if (setId == Stickers::FavedSetId) {
|
||||
|
@ -344,7 +344,7 @@ void StickersListWidget::Footer::updateSelected() {
|
|||
}
|
||||
|
||||
auto p = mapFromGlobal(_iconsMousePos);
|
||||
int32 x = p.x(), y = p.y(), newOver = -1;
|
||||
int32_t x = p.x(), y = p.y(), newOver = -1;
|
||||
if (rtl()) x = width() - x;
|
||||
x -= _iconsLeft;
|
||||
if (x >= st::emojiCategory.width * (kVisibleIconsCount - 1) && x < st::emojiCategory.width * kVisibleIconsCount && y >= _iconsTop && y < _iconsTop + st::emojiCategory.height) {
|
||||
|
@ -416,7 +416,7 @@ void StickersListWidget::validateSelectedIcon(ValidateIconAnimations animations)
|
|||
|
||||
void StickersListWidget::Footer::step_icons(TimeMs ms, bool timer) {
|
||||
if (_iconsStartAnim) {
|
||||
auto dt = (ms - _iconsStartAnim) / float64(st::stickerIconMove);
|
||||
auto dt = (ms - _iconsStartAnim) / double(st::stickerIconMove);
|
||||
if (dt >= 1) {
|
||||
_iconsStartAnim = 0;
|
||||
_iconsX.finish();
|
||||
|
@ -575,11 +575,11 @@ int StickersListWidget::countHeight() {
|
|||
return qMax(minimalLastHeight, countResult()) + st::stickerPanPadding;
|
||||
}
|
||||
|
||||
void StickersListWidget::installedLocally(uint64 setId) {
|
||||
void StickersListWidget::installedLocally(uint64_t setId) {
|
||||
_installedLocallySets.insert(setId);
|
||||
}
|
||||
|
||||
void StickersListWidget::notInstalledLocally(uint64 setId) {
|
||||
void StickersListWidget::notInstalledLocally(uint64_t setId) {
|
||||
_installedLocallySets.remove(setId);
|
||||
}
|
||||
|
||||
|
@ -827,7 +827,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int index, bo
|
|||
sticker->checkSticker();
|
||||
}
|
||||
|
||||
auto coef = qMin((st::stickerPanSize.width() - st::buttonRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::buttonRadius * 2) / float64(sticker->dimensions.height()));
|
||||
auto coef = qMin((st::stickerPanSize.width() - st::buttonRadius * 2) / double(sticker->dimensions.width()), (st::stickerPanSize.height() - st::buttonRadius * 2) / double(sticker->dimensions.height()));
|
||||
if (coef > 1) coef = 1;
|
||||
auto w = qMax(qRound(coef * sticker->dimensions.width()), 1);
|
||||
auto h = qMax(qRound(coef * sticker->dimensions.height()), 1);
|
||||
|
@ -1041,7 +1041,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
|
|||
bool refresh = false;
|
||||
auto sticker = _mySets[section].pack[index];
|
||||
auto &recent = cGetRecentStickers();
|
||||
for (int32 i = 0, l = recent.size(); i < l; ++i) {
|
||||
for (int32_t i = 0, l = recent.size(); i < l; ++i) {
|
||||
if (recent.at(i).first == sticker) {
|
||||
recent.removeAt(i);
|
||||
Local::writeUserSettings();
|
||||
|
@ -1198,14 +1198,14 @@ void StickersListWidget::preloadImages() {
|
|||
}
|
||||
}
|
||||
|
||||
uint64 StickersListWidget::currentSet(int yOffset) const {
|
||||
uint64_t StickersListWidget::currentSet(int yOffset) const {
|
||||
if (_section == Section::Featured) {
|
||||
return Stickers::FeaturedSetId;
|
||||
}
|
||||
return _mySets.isEmpty() ? Stickers::RecentSetId : _mySets[sectionInfoByOffset(yOffset).section].id;
|
||||
}
|
||||
|
||||
void StickersListWidget::appendSet(Sets &to, uint64 setId, AppendSkip skip) {
|
||||
void StickersListWidget::appendSet(Sets &to, uint64_t setId, AppendSkip skip) {
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it == sets.cend() || it->stickers.isEmpty()) return;
|
||||
|
@ -1281,7 +1281,7 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
|
|||
}
|
||||
|
||||
if (performResize && (_section == Section::Stickers || _section == Section::Featured)) {
|
||||
int32 h = countHeight();
|
||||
int32_t h = countHeight();
|
||||
if (h != height()) {
|
||||
resize(width(), h);
|
||||
update();
|
||||
|
@ -1545,7 +1545,7 @@ void StickersListWidget::onPreview() {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::showStickerSet(uint64 setId) {
|
||||
void StickersListWidget::showStickerSet(uint64_t setId) {
|
||||
clearSelection();
|
||||
|
||||
if (setId == Stickers::FeaturedSetId) {
|
||||
|
@ -1615,7 +1615,7 @@ void StickersListWidget::showMegagroupSet(ChannelData *megagroup) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::displaySet(uint64 setId) {
|
||||
void StickersListWidget::displaySet(uint64_t setId) {
|
||||
if (setId == Stickers::MegagroupSetId) {
|
||||
if (_megagroupSet->canEditStickers()) {
|
||||
_displayingSetId = setId;
|
||||
|
@ -1643,7 +1643,7 @@ void StickersListWidget::displaySet(uint64 setId) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::installSet(uint64 setId) {
|
||||
void StickersListWidget::installSet(uint64_t setId) {
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend()) {
|
||||
|
@ -1683,7 +1683,7 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
|
|||
})));
|
||||
}
|
||||
|
||||
void StickersListWidget::removeSet(uint64 setId) {
|
||||
void StickersListWidget::removeSet(uint64_t setId) {
|
||||
auto &sets = Global::StickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend()) {
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
void clearSelection() override;
|
||||
object_ptr<TabbedSelector::InnerFooter> createFooter() override;
|
||||
|
||||
void showStickerSet(uint64 setId);
|
||||
void showStickerSet(uint64_t setId);
|
||||
void showMegagroupSet(ChannelData *megagroup);
|
||||
|
||||
void refreshStickers();
|
||||
|
@ -56,10 +56,10 @@ public:
|
|||
|
||||
void setVisibleTopBottom(int visibleTop, int visibleBottom) override;
|
||||
|
||||
uint64 currentSet(int yOffset) const;
|
||||
uint64_t currentSet(int yOffset) const;
|
||||
|
||||
void installedLocally(uint64 setId);
|
||||
void notInstalledLocally(uint64 setId);
|
||||
void installedLocally(uint64_t setId);
|
||||
void notInstalledLocally(uint64_t setId);
|
||||
void clearInstalledLocally();
|
||||
|
||||
~StickersListWidget();
|
||||
|
@ -133,9 +133,9 @@ private:
|
|||
};
|
||||
|
||||
struct Set {
|
||||
Set(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), pack(pack) {
|
||||
Set(uint64_t id, MTPDstickerSet::Flags flags, const QString &title, int32_t hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), pack(pack) {
|
||||
}
|
||||
uint64 id;
|
||||
uint64_t id;
|
||||
MTPDstickerSet::Flags flags;
|
||||
QString title;
|
||||
StickerPack pack;
|
||||
|
@ -148,10 +148,10 @@ private:
|
|||
SectionInfo sectionInfo(int section) const;
|
||||
SectionInfo sectionInfoByOffset(int yOffset) const;
|
||||
|
||||
void displaySet(uint64 setId);
|
||||
void installSet(uint64 setId);
|
||||
void displaySet(uint64_t setId);
|
||||
void installSet(uint64_t setId);
|
||||
void removeMegagroupSet(bool locally);
|
||||
void removeSet(uint64 setId);
|
||||
void removeSet(uint64_t setId);
|
||||
|
||||
bool setHasTitle(const Set &set) const;
|
||||
bool stickerHasDeleteButton(const Set &set, int index) const;
|
||||
|
@ -204,7 +204,7 @@ private:
|
|||
Archived,
|
||||
Installed,
|
||||
};
|
||||
void appendSet(Sets &to, uint64 setId, AppendSkip skip = AppendSkip::None);
|
||||
void appendSet(Sets &to, uint64_t setId, AppendSkip skip = AppendSkip::None);
|
||||
|
||||
void selectEmoji(EmojiPtr emoji);
|
||||
int stickersLeft() const;
|
||||
|
@ -216,14 +216,14 @@ private:
|
|||
ChannelData *_megagroupSet = nullptr;
|
||||
Sets _mySets;
|
||||
Sets _featuredSets;
|
||||
OrderedSet<uint64> _installedLocallySets;
|
||||
OrderedSet<uint64_t> _installedLocallySets;
|
||||
QList<bool> _custom;
|
||||
base::flat_set<not_null<DocumentData*>> _favedStickersMap;
|
||||
|
||||
Section _section = Section::Stickers;
|
||||
|
||||
uint64 _displayingSetId = 0;
|
||||
uint64 _removingSetId = 0;
|
||||
uint64_t _displayingSetId = 0;
|
||||
uint64_t _removingSetId = 0;
|
||||
|
||||
Footer *_footer = nullptr;
|
||||
|
||||
|
|
|
@ -376,7 +376,7 @@ bool TabbedPanel::eventFilter(QObject *obj, QEvent *e) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void TabbedPanel::stickersInstalled(uint64 setId) {
|
||||
void TabbedPanel::stickersInstalled(uint64_t setId) {
|
||||
if (isDestroying()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
return _hiding || _hideTimer.isActive();
|
||||
}
|
||||
|
||||
void stickersInstalled(uint64 setId);
|
||||
void stickersInstalled(uint64_t setId);
|
||||
|
||||
bool overlaps(const QRect &globalRect) const;
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ QPointer<TabbedSelector> TabbedSection::getSelector() const {
|
|||
return _selector.data();
|
||||
}
|
||||
|
||||
void TabbedSection::stickersInstalled(uint64 setId) {
|
||||
void TabbedSection::stickersInstalled(uint64_t setId) {
|
||||
_selector->stickersInstalled(setId);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
object_ptr<TabbedSelector> takeSelector();
|
||||
QPointer<TabbedSelector> getSelector() const;
|
||||
|
||||
void stickersInstalled(uint64 setId);
|
||||
void stickersInstalled(uint64_t setId);
|
||||
|
||||
// Float player interface.
|
||||
bool wheelEventFromFloatPlayer(QEvent *e, Window::Column myColumn, Window::Column playerColumn) override;
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
void setFinalImages(Direction direction, QImage &&left, QImage &&right, QRect inner, bool wasSectionIcons);
|
||||
|
||||
void start();
|
||||
void paintFrame(QPainter &p, float64 dt, float64 opacity);
|
||||
void paintFrame(QPainter &p, double dt, double opacity);
|
||||
|
||||
private:
|
||||
Direction _direction = Direction::LeftToRight;
|
||||
|
@ -133,7 +133,7 @@ void TabbedSelector::SlideAnimation::start() {
|
|||
_frameIntsPerLineAdd = (_width - _innerWidth) + _frameIntsPerLineAdded;
|
||||
}
|
||||
|
||||
void TabbedSelector::SlideAnimation::paintFrame(QPainter &p, float64 dt, float64 opacity) {
|
||||
void TabbedSelector::SlideAnimation::paintFrame(QPainter &p, double dt, double opacity) {
|
||||
Expects(started());
|
||||
Expects(dt >= 0.);
|
||||
|
||||
|
@ -219,15 +219,15 @@ void TabbedSelector::SlideAnimation::paintFrame(QPainter &p, float64 dt, float64
|
|||
if (opacity == 1.) {
|
||||
// Fill above the frame top with transparent.
|
||||
auto fillTopInts = (_frameInts + outerTop * _frameIntsPerLine + outerLeft);
|
||||
auto fillWidth = (outerRight - outerLeft) * sizeof(uint32);
|
||||
auto fillWidth = (outerRight - outerLeft) * sizeof(uint32_t);
|
||||
for (auto fillTop = _innerTop - outerTop; fillTop != 0; --fillTop) {
|
||||
memset(fillTopInts, 0, fillWidth);
|
||||
fillTopInts += _frameIntsPerLine;
|
||||
}
|
||||
|
||||
// Fill to the left and to the right of the frame with transparent.
|
||||
auto fillLeft = (_innerLeft - outerLeft) * sizeof(uint32);
|
||||
auto fillRight = (outerRight - _innerRight) * sizeof(uint32);
|
||||
auto fillLeft = (_innerLeft - outerLeft) * sizeof(uint32_t);
|
||||
auto fillRight = (outerRight - _innerRight) * sizeof(uint32_t);
|
||||
if (fillLeft || fillRight) {
|
||||
auto fillInts = _frameInts + _innerTop * _frameIntsPerLine;
|
||||
for (auto y = _innerTop; y != _innerBottom; ++y) {
|
||||
|
@ -250,7 +250,7 @@ void TabbedSelector::SlideAnimation::paintFrame(QPainter &p, float64 dt, float64
|
|||
|
||||
// Debug
|
||||
//frameInts = _frameInts;
|
||||
//auto pattern = anim::shifted((static_cast<uint32>(0xFF) << 24) | (static_cast<uint32>(0xFF) << 16) | (static_cast<uint32>(0xFF) << 8) | static_cast<uint32>(0xFF));
|
||||
//auto pattern = anim::shifted((static_cast<uint32_t>(0xFF) << 24) | (static_cast<uint32_t>(0xFF) << 16) | (static_cast<uint32_t>(0xFF) << 8) | static_cast<uint32_t>(0xFF));
|
||||
//for (auto y = 0; y != _finalHeight; ++y) {
|
||||
// for (auto x = 0; x != _finalWidth; ++x) {
|
||||
// auto source = *frameInts;
|
||||
|
@ -514,7 +514,7 @@ void TabbedSelector::afterShown() {
|
|||
}
|
||||
}
|
||||
|
||||
void TabbedSelector::stickersInstalled(uint64 setId) {
|
||||
void TabbedSelector::stickersInstalled(uint64_t setId) {
|
||||
_tabsSlider->setActiveSection(static_cast<int>(SelectorTab::Stickers));
|
||||
stickers()->showStickerSet(setId);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
|
||||
void setRoundRadius(int radius);
|
||||
void refreshStickers();
|
||||
void stickersInstalled(uint64 setId);
|
||||
void stickersInstalled(uint64_t setId);
|
||||
void showMegagroupSet(ChannelData *megagroup);
|
||||
void setCurrentPeer(PeerData *peer);
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
add_subdirectory(common)
|
||||
add_subdirectory(emoji)
|
||||
add_subdirectory(lang)
|
||||
add_subdirectory(numbers)
|
||||
add_subdirectory(style)
|
|
@ -0,0 +1,8 @@
|
|||
add_library(codegen_common STATIC
|
||||
basic_tokenized_file.cpp
|
||||
checked_utf8_string.cpp
|
||||
clean_file.cpp
|
||||
cpp_file.cpp
|
||||
logging.cpp
|
||||
)
|
||||
qt5_use_modules(codegen_common Core)
|
|
@ -290,6 +290,8 @@ LogStream operator<<(LogStream &&stream, BasicTokenizedFile::Token::Type type) {
|
|||
case Type::Plus: value = "'+'"; break;
|
||||
case Type::Minus: value = "'-'"; break;
|
||||
case Type::Equals: value = "'='"; break;
|
||||
case Type::And: value = "'and'"; break;
|
||||
case Type::Or: value = "'or'"; break;
|
||||
case Type::Name: value = "'identifier'"; break;
|
||||
}
|
||||
return std::forward<LogStream>(stream) << value;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
add_executable(codegen_emoji
|
||||
data.cpp
|
||||
generator.cpp
|
||||
main.cpp
|
||||
options.cpp
|
||||
replaces.cpp
|
||||
)
|
||||
target_link_libraries(codegen_emoji codegen_common Qt5::Core Qt5::Gui)
|
||||
qt5_use_modules(codegen_emoji Core)
|
|
@ -19,15 +19,12 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "codegen/emoji/data.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace codegen {
|
||||
namespace emoji {
|
||||
namespace {
|
||||
|
||||
using uint16 = quint16;
|
||||
using uint32 = quint32;
|
||||
using uint64 = quint64;
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::find;
|
||||
|
@ -36,7 +33,7 @@ using std::move;
|
|||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
using InputId = vector<uint32>;
|
||||
using InputId = vector<uint32_t>;
|
||||
using InputCategory = vector<InputId>;
|
||||
|
||||
// copied from emoji_box.cpp
|
||||
|
@ -83,7 +80,7 @@ Replace Replaces[] = {
|
|||
{ { 0xD83DDE08U }, "}:)" },
|
||||
};
|
||||
|
||||
using ColorId = uint32;
|
||||
using ColorId = uint32_t;
|
||||
ColorId Colors[] = {
|
||||
0xD83CDFFBU,
|
||||
0xD83CDFFCU,
|
||||
|
@ -1703,11 +1700,11 @@ InputCategory Category7 = {
|
|||
|
||||
constexpr auto kErrorBadData = 401;
|
||||
|
||||
void append(Id &id, uint32 code) {
|
||||
if (auto first = static_cast<uint16>((code >> 16) & 0xFFFFU)) {
|
||||
void append(Id &id, uint32_t code) {
|
||||
if (auto first = static_cast<uint16_t>((code >> 16) & 0xFFFFU)) {
|
||||
id.append(QChar(first));
|
||||
}
|
||||
id.append(QChar(static_cast<uint16>(code & 0xFFFFU)));
|
||||
id.append(QChar(static_cast<uint16_t>(code & 0xFFFFU)));
|
||||
}
|
||||
|
||||
using VariatedIds = map<Id, bool>;
|
||||
|
|
|
@ -123,11 +123,11 @@ QRect computeSourceRect(const QImage &image) {
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32 Crc32Table[256];
|
||||
uint32_t Crc32Table[256];
|
||||
class Crc32Initializer {
|
||||
public:
|
||||
Crc32Initializer() {
|
||||
uint32 poly = 0x04C11DB7U;
|
||||
uint32_t poly = 0x04C11DB7U;
|
||||
for (auto i = 0; i != 256; ++i) {
|
||||
Crc32Table[i] = reflect(i, 8) << 24;
|
||||
for (auto j = 0; j != 8; ++j) {
|
||||
|
@ -138,8 +138,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
uint32 reflect(uint32 val, char ch) {
|
||||
uint32 result = 0;
|
||||
uint32_t reflect(uint32_t val, char ch) {
|
||||
uint32_t result = 0;
|
||||
for (int i = 1; i < (ch + 1); ++i) {
|
||||
if (val & 1) {
|
||||
result |= 1 << (ch - i);
|
||||
|
@ -151,11 +151,11 @@ private:
|
|||
|
||||
};
|
||||
|
||||
uint32 countCrc32(const void *data, std::size_t size) {
|
||||
uint32_t countCrc32(const void *data, std::size_t size) {
|
||||
static Crc32Initializer InitTable;
|
||||
|
||||
auto buffer = static_cast<const unsigned char*>(data);
|
||||
auto result = uint32(0xFFFFFFFFU);
|
||||
auto result = uint32_t(0xFFFFFFFFU);
|
||||
for (auto i = std::size_t(0); i != size; ++i) {
|
||||
result = (result >> 8) ^ Crc32Table[(result & 0xFFU) ^ buffer[i]];
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ void Init() {\n\
|
|||
\n\
|
||||
Items.reserve(base::array_size(Data));\n\
|
||||
for (auto &data : Data) {\n\
|
||||
Items.emplace_back(takeString(data.idSize), uint16(data.column), uint16(data.row), bool(data.postfixed), bool(data.variated), data.original ? &Items[data.original - 1] : nullptr, One::CreationTag());\n\
|
||||
Items.emplace_back(takeString(data.idSize), uint16_t(data.column), uint16_t(data.row), bool(data.postfixed), bool(data.variated), data.original ? &Items[data.original - 1] : nullptr, One::CreationTag());\n\
|
||||
}\n\
|
||||
InitReplacements();\n\
|
||||
}\n\
|
||||
|
@ -806,9 +806,9 @@ bool Generator::writeReplacements() {
|
|||
QMap<QChar, QVector<int>> byCharIndices;
|
||||
suggestionsSource_->stream() << "\
|
||||
struct ReplacementStruct {\n\
|
||||
small emojiSize;\n\
|
||||
small replacementSize;\n\
|
||||
small wordsCount;\n\
|
||||
smallchar emojiSize;\n\
|
||||
smallchar replacementSize;\n\
|
||||
smallchar wordsCount;\n\
|
||||
};\n\
|
||||
\n\
|
||||
const utf16char ReplacementData[] = {";
|
||||
|
@ -833,7 +833,7 @@ const utf16char ReplacementData[] = {";
|
|||
}
|
||||
suggestionsSource_->stream() << " };\n\
|
||||
\n\
|
||||
const small ReplacementWordLengths[] = {";
|
||||
const smallchar ReplacementWordLengths[] = {";
|
||||
startBinary();
|
||||
for (auto &replace : replaces_.list) {
|
||||
auto wordLengths = QStringList();
|
||||
|
@ -846,7 +846,7 @@ const small ReplacementWordLengths[] = {";
|
|||
const ReplacementStruct ReplacementInitData[] = {\n";
|
||||
for (auto &replace : replaces_.list) {
|
||||
suggestionsSource_->stream() << "\
|
||||
{ small(" << replace.id.size() << "), small(" << replace.replacement.size() << "), small(" << replace.words.size() << ") },\n";
|
||||
{ smallchar(" << replace.id.size() << "), smallchar(" << replace.replacement.size() << "), smallchar(" << replace.words.size() << ") },\n";
|
||||
}
|
||||
suggestionsSource_->stream() << "};\n\
|
||||
\n\
|
||||
|
@ -984,7 +984,7 @@ void Generator::writeIntBinary(common::CppFile *source, int data) {
|
|||
++_binaryFullLength;
|
||||
}
|
||||
|
||||
void Generator::writeUintBinary(common::CppFile *source, uint32 data) {
|
||||
void Generator::writeUintBinary(common::CppFile *source, uint32_t data) {
|
||||
if (_binaryFullLength > 0) source->stream() << ",";
|
||||
if (!_binaryCount++) {
|
||||
source->stream() << "\n";
|
||||
|
|
|
@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QSet>
|
||||
|
@ -31,8 +32,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
namespace codegen {
|
||||
namespace emoji {
|
||||
|
||||
using uint32 = unsigned int;
|
||||
|
||||
class Generator {
|
||||
public:
|
||||
Generator(const Options &options);
|
||||
|
@ -66,7 +65,7 @@ private:
|
|||
void startBinary();
|
||||
bool writeStringBinary(common::CppFile *source, const QString &string);
|
||||
void writeIntBinary(common::CppFile *source, int data);
|
||||
void writeUintBinary(common::CppFile *source, uint32 data);
|
||||
void writeUintBinary(common::CppFile *source, uint32_t data);
|
||||
|
||||
const common::ProjectInfo &project_;
|
||||
int colorsCount_ = 0;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
add_executable(codegen_lang
|
||||
generator.cpp
|
||||
main.cpp
|
||||
options.cpp
|
||||
parsed_file.cpp
|
||||
processor.cpp
|
||||
)
|
||||
target_link_libraries(codegen_lang codegen_common Qt5::Core Qt5::Gui)
|
||||
qt5_use_modules(codegen_lang Core Gui)
|
|
@ -150,8 +150,8 @@ QString lang(LangKey key);\n\
|
|||
for (auto &tagData : entry.tags) {
|
||||
auto &tag = tagData.tag;
|
||||
auto isPluralTag = isPlural && (tag == kPluralTag);
|
||||
genericParams.push_back("lngtag_" + tag + ", " + (isPluralTag ? "float64 " : "const ResultString &") + tag + "__val");
|
||||
params.push_back("lngtag_" + tag + ", " + (isPluralTag ? "float64 " : "const QString &") + tag + "__val");
|
||||
genericParams.push_back("lngtag_" + tag + ", " + (isPluralTag ? "double " : "const ResultString &") + tag + "__val");
|
||||
params.push_back("lngtag_" + tag + ", " + (isPluralTag ? "double " : "const QString &") + tag + "__val");
|
||||
if (isPluralTag) {
|
||||
plural = "\tauto plural = Lang::Plural(" + key + ", " + kPluralTag + "__val);\n";
|
||||
applyTags.push_back("\tresult = Lang::ReplaceTag<ResultString>::Call(std::move(result), lt_" + tag + ", Lang::StartReplacements<ResultString>::Call(std::move(plural.replacement)));\n");
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
add_executable(codegen_numbers
|
||||
generator.cpp
|
||||
main.cpp
|
||||
options.cpp
|
||||
parsed_file.cpp
|
||||
processor.cpp
|
||||
)
|
||||
target_link_libraries(codegen_numbers codegen_common Qt5::Core)
|
||||
qt5_use_modules(codegen_numbers Core)
|
|
@ -51,7 +51,7 @@ bool Generator::writeSource() {
|
|||
QVector<int> phoneNumberParse(const QString &number) {\n\
|
||||
QVector<int> result;\n\
|
||||
\n\
|
||||
int32 len = number.size();\n\
|
||||
int32_t len = number.size();\n\
|
||||
if (len > 0) switch (number.at(0).unicode()) {\n";
|
||||
|
||||
QString already;
|
||||
|
|
|
@ -311,7 +311,7 @@ with open(input_file) as f:
|
|||
prmsInit = [];
|
||||
prmsNames = [];
|
||||
if (hasFlags != ''):
|
||||
funcsText += '\tenum class Flag : int32 {\n';
|
||||
funcsText += '\tenum class Flag : int32_t {\n';
|
||||
maxbit = 0;
|
||||
parentFlagsCheck['MTP' + name] = {};
|
||||
for paramName in conditionsList:
|
||||
|
@ -356,12 +356,12 @@ with open(input_file) as f:
|
|||
funcsText += '\tMTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n\t}\n';
|
||||
|
||||
funcsText += '\n';
|
||||
funcsText += '\tuint32 innerLength() const;\n'; # count size
|
||||
funcsText += '\tuint32_t innerLength() const;\n'; # count size
|
||||
if (isTemplate != ''):
|
||||
methodBodies += 'template <typename TQueryType>\n'
|
||||
methodBodies += 'uint32 MTP' + name + '<TQueryType>::innerLength() const {\n';
|
||||
methodBodies += 'uint32_t MTP' + name + '<TQueryType>::innerLength() const {\n';
|
||||
else:
|
||||
methodBodies += 'uint32 MTP' + name + '::innerLength() const {\n';
|
||||
methodBodies += 'uint32_t MTP' + name + '::innerLength() const {\n';
|
||||
size = [];
|
||||
for k in prmsList:
|
||||
v = prms[k];
|
||||
|
@ -453,7 +453,7 @@ def addTextSerialize(lst, dct, dataLetter):
|
|||
conditions = data[6];
|
||||
trivialConditions = data[7];
|
||||
|
||||
result += 'void Serialize_' + name + '(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {\n';
|
||||
result += 'void Serialize_' + name + '(MTPStringLogger &to, int32_t stage, int32_t lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32_t iflag) {\n';
|
||||
if (len(conditions)):
|
||||
result += '\tMTP' + dataLetter + name + '::Flags flag(iflag);\n\n';
|
||||
if (len(prms)):
|
||||
|
@ -592,7 +592,7 @@ for restype in typesList:
|
|||
writeText = '';
|
||||
|
||||
if (hasFlags != ''):
|
||||
dataText += '\tenum class Flag : int32 {\n';
|
||||
dataText += '\tenum class Flag : int32_t {\n';
|
||||
maxbit = 0;
|
||||
parentFlagsCheck['MTPD' + name] = {};
|
||||
for paramName in conditionsList:
|
||||
|
@ -752,8 +752,8 @@ for restype in typesList:
|
|||
if (withData):
|
||||
typesText += getters;
|
||||
|
||||
typesText += '\n\tuint32 innerLength() const;\n'; # size method
|
||||
methods += '\nuint32 MTP' + restype + '::innerLength() const {\n';
|
||||
typesText += '\n\tuint32_t innerLength() const;\n'; # size method
|
||||
methods += '\nuint32_t MTP' + restype + '::innerLength() const {\n';
|
||||
if (withType and sizeCases):
|
||||
methods += '\tswitch (_type) {\n';
|
||||
methods += sizeCases;
|
||||
|
@ -853,7 +853,7 @@ for childName in parentFlagsList:
|
|||
|
||||
# manual types added here
|
||||
textSerializeMethods += '\
|
||||
void _serialize_rpc_result(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {\n\
|
||||
void _serialize_rpc_result(MTPStringLogger &to, int32_t stage, int32_t lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32_t iflag) {\n\
|
||||
if (stage) {\n\
|
||||
to.add(",\\n").addSpaces(lev);\n\
|
||||
} else {\n\
|
||||
|
@ -867,7 +867,7 @@ void _serialize_rpc_result(MTPStringLogger &to, int32 stage, int32 lev, Types &t
|
|||
}\n\
|
||||
}\n\
|
||||
\n\
|
||||
void _serialize_msg_container(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {\n\
|
||||
void _serialize_msg_container(MTPStringLogger &to, int32_t stage, int32_t lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32_t iflag) {\n\
|
||||
if (stage) {\n\
|
||||
to.add(",\\n").addSpaces(lev);\n\
|
||||
} else {\n\
|
||||
|
@ -880,7 +880,7 @@ void _serialize_msg_container(MTPStringLogger &to, int32 stage, int32 lev, Types
|
|||
}\n\
|
||||
}\n\
|
||||
\n\
|
||||
void _serialize_core_message(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {\n\
|
||||
void _serialize_core_message(MTPStringLogger &to, int32_t stage, int32_t lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32_t iflag) {\n\
|
||||
if (stage) {\n\
|
||||
to.add(",\\n").addSpaces(lev);\n\
|
||||
} else {\n\
|
||||
|
@ -966,7 +966,7 @@ enum {\n\
|
|||
// Factory methods declaration\n\
|
||||
' + factories + '\n\
|
||||
// Human-readable text serialization\n\
|
||||
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons);\n'
|
||||
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32_t level, mtpPrime vcons);\n'
|
||||
|
||||
source = '\
|
||||
/*\n\
|
||||
|
@ -1007,12 +1007,12 @@ public:\n\
|
|||
' + methods + '\n\
|
||||
\n\
|
||||
using Types = QVector<mtpTypeId>;\n\
|
||||
using StagesFlags = QVector<int32>;\n\
|
||||
using StagesFlags = QVector<int32_t>;\n\
|
||||
\n\
|
||||
' + textSerializeMethods + '\n\
|
||||
namespace {\n\
|
||||
\n\
|
||||
using TextSerializer = void (*)(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag);\n\
|
||||
using TextSerializer = void (*)(MTPStringLogger &to, int32_t stage, int32_t lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32_t iflag);\n\
|
||||
using TextSerializers = QMap<mtpTypeId, TextSerializer>;\n\
|
||||
\n\
|
||||
QMap<mtpTypeId, TextSerializer> createTextSerializers() {\n\
|
||||
|
@ -1025,17 +1025,17 @@ QMap<mtpTypeId, TextSerializer> createTextSerializers() {\n\
|
|||
\n\
|
||||
} // namespace\n\
|
||||
\n\
|
||||
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons) {\n\
|
||||
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32_t level, mtpPrime vcons) {\n\
|
||||
static auto serializers = createTextSerializers();\n\
|
||||
\n\
|
||||
QVector<mtpTypeId> types, vtypes;\n\
|
||||
QVector<int32> stages, flags;\n\
|
||||
QVector<int32_t> stages, flags;\n\
|
||||
types.reserve(20); vtypes.reserve(20); stages.reserve(20); flags.reserve(20);\n\
|
||||
types.push_back(mtpTypeId(cons)); vtypes.push_back(mtpTypeId(vcons)); stages.push_back(0); flags.push_back(0);\n\
|
||||
\n\
|
||||
const mtpPrime *start = from;\n\
|
||||
mtpTypeId type = cons, vtype = vcons;\n\
|
||||
int32 stage = 0, flag = 0;\n\
|
||||
int32_t stage = 0, flag = 0;\n\
|
||||
\n\
|
||||
while (!types.isEmpty()) {\n\
|
||||
type = types.back();\n\
|
||||
|
@ -1052,7 +1052,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
|
|||
start = ++from;\n\
|
||||
}\n\
|
||||
\n\
|
||||
int32 lev = level + types.size() - 1;\n\
|
||||
int32_t lev = level + types.size() - 1;\n\
|
||||
auto it = serializers.constFind(type);\n\
|
||||
if (it != serializers.cend()) {\n\
|
||||
(*it.value())(to, stage, lev, types, vtypes, stages, flags, start, end, flag);\n\
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
add_executable(codegen_style
|
||||
generator.cpp
|
||||
main.cpp
|
||||
module.cpp
|
||||
options.cpp
|
||||
parsed_file.cpp
|
||||
processor.cpp
|
||||
structure_types.cpp
|
||||
)
|
||||
target_link_libraries(codegen_style codegen_common Qt5::Core Qt5::Gui)
|
||||
qt5_use_modules(codegen_style Core Gui)
|
|
@ -46,7 +46,7 @@ constexpr int kErrorBadIconFormat = 862;
|
|||
class Crc32Table {
|
||||
public:
|
||||
Crc32Table() {
|
||||
quint32 poly = 0x04c11db7;
|
||||
uint32_t poly = 0x04c11db7;
|
||||
for (auto i = 0; i != 256; ++i) {
|
||||
_data[i] = reflect(i, 8) << 24;
|
||||
for (auto j = 0; j != 8; ++j) {
|
||||
|
@ -56,13 +56,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
inline quint32 operator[](int index) const {
|
||||
inline uint32_t operator[](int index) const {
|
||||
return _data[index];
|
||||
}
|
||||
|
||||
private:
|
||||
quint32 reflect(quint32 val, char ch) {
|
||||
quint32 result = 0;
|
||||
uint32_t reflect(uint32_t val, char ch) {
|
||||
uint32_t result = 0;
|
||||
for (int i = 1; i < (ch + 1); ++i) {
|
||||
if (val & 1) {
|
||||
result |= 1 << (ch - i);
|
||||
|
@ -72,21 +72,21 @@ private:
|
|||
return result;
|
||||
}
|
||||
|
||||
quint32 _data[256];
|
||||
uint32_t _data[256];
|
||||
|
||||
};
|
||||
|
||||
qint32 hashCrc32(const void *data, int len) {
|
||||
int32_t hashCrc32(const void *data, int len) {
|
||||
static Crc32Table table;
|
||||
|
||||
const uchar *buffer = static_cast<const uchar *>(data);
|
||||
|
||||
quint32 crc = 0xffffffff;
|
||||
uint32_t crc = 0xffffffff;
|
||||
for (int i = 0; i != len; ++i) {
|
||||
crc = (crc >> 8) ^ table[(crc & 0xFF) ^ buffer[i]];
|
||||
}
|
||||
|
||||
return static_cast<qint32>(crc ^ 0xffffffff);
|
||||
return static_cast<int32_t>(crc ^ 0xffffffff);
|
||||
}
|
||||
|
||||
char hexChar(uchar ch) {
|
||||
|
@ -504,7 +504,7 @@ public:\n\
|
|||
return *this;\n\
|
||||
}\n\
|
||||
\n\
|
||||
static int32 Checksum();\n\
|
||||
static int32_t Checksum();\n\
|
||||
\n\
|
||||
~palette() {\n\
|
||||
clear();\n\
|
||||
|
@ -809,7 +809,7 @@ void palette::finalize() {\n\
|
|||
source_->stream() << "\
|
||||
}\n\
|
||||
\n\
|
||||
int32 palette::Checksum() {\n\
|
||||
int32_t palette::Checksum() {\n\
|
||||
return " << checksum << ";\n\
|
||||
}\n";
|
||||
|
||||
|
@ -1178,7 +1178,7 @@ QByteArray iconMaskValueSize(int width, int height) {
|
|||
{
|
||||
QDataStream stream(&result, QIODevice::Append);
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
stream << qint32(width) << qint32(height);
|
||||
stream << int32_t(width) << int32_t(height);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <QImage>
|
||||
#include <QtGui/QImage>
|
||||
#include "codegen/common/basic_tokenized_file.h"
|
||||
#include "codegen/style/options.h"
|
||||
#include "codegen/style/module.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue