diff --git a/Telegram_Buck.xcworkspace/buck-project.meta.json b/Telegram_Buck.xcworkspace/buck-project.meta.json
index ea47a3d535..19305fd247 100644
--- a/Telegram_Buck.xcworkspace/buck-project.meta.json
+++ b/Telegram_Buck.xcworkspace/buck-project.meta.json
@@ -1 +1 @@
-{"required-targets":["//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_ac3_parser.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_adts_parser.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_avcodec.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_avdct.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_avfft.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_d3d11va.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_dirac.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_dv_profile.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_dxva2.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_jni.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_mediacodec.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_qsv.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_vaapi.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_vdpau.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_version.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_videotoolbox.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_vorbis_parser.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_xvmc.h","//submodules/FFMpeg:ffmpeg_header_libavformat_sub_avformat.h","//submodules/FFMpeg:ffmpeg_header_libavformat_sub_avio.h","//submodules/FFMpeg:ffmpeg_header_libavformat_sub_version.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_adler32.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_aes.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_aes_ctr.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_attributes.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_audio_fifo.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avassert.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avconfig.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avstring.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avutil.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_base64.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_blowfish.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_bprint.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_bswap.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_buffer.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_camellia.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_cast5.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_channel_layout.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_common.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_cpu.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_crc.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_des.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_dict.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_display.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_downmix_info.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_encryption_info.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_error.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_eval.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_ffversion.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_fifo.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_file.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_frame.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hash.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hmac.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_cuda.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_d3d11va.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_drm.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_dxva2.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_mediacodec.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_qsv.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_vaapi.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_vdpau.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_videotoolbox.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_imgutils.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_intfloat.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_intreadwrite.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_lfg.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_log.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_lzo.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_macros.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_mastering_display_metadata.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_mathematics.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_md5.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_mem.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_motion_vector.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_murmur3.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_opt.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_parseutils.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_pixdesc.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_pixelutils.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_pixfmt.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_random_seed.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_rational.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_rc4.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_replaygain.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_ripemd.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_samplefmt.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_sha.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_sha512.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_spherical.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_stereo3d.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_tea.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_threadmessage.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_time.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_timecode.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_timestamp.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_tree.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_twofish.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_version.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_xtea.h","//submodules/FFMpeg:ffmpeg_header_libswresample_sub_swresample.h","//submodules/FFMpeg:ffmpeg_header_libswresample_sub_version.h","//submodules/FFMpeg:libffmpeg_build","//submodules/Opus:opus_lib_file","//submodules/WebP:WebP_lib_file","//submodules/openssl:openssl_build_merged","//submodules/openssl:openssl_header_openssl_sub_aes.h","//submodules/openssl:openssl_header_openssl_sub_asn1.h","//submodules/openssl:openssl_header_openssl_sub_asn1_mac.h","//submodules/openssl:openssl_header_openssl_sub_asn1err.h","//submodules/openssl:openssl_header_openssl_sub_asn1t.h","//submodules/openssl:openssl_header_openssl_sub_async.h","//submodules/openssl:openssl_header_openssl_sub_asyncerr.h","//submodules/openssl:openssl_header_openssl_sub_bio.h","//submodules/openssl:openssl_header_openssl_sub_bioerr.h","//submodules/openssl:openssl_header_openssl_sub_blowfish.h","//submodules/openssl:openssl_header_openssl_sub_bn.h","//submodules/openssl:openssl_header_openssl_sub_bnerr.h","//submodules/openssl:openssl_header_openssl_sub_buffer.h","//submodules/openssl:openssl_header_openssl_sub_buffererr.h","//submodules/openssl:openssl_header_openssl_sub_camellia.h","//submodules/openssl:openssl_header_openssl_sub_cast.h","//submodules/openssl:openssl_header_openssl_sub_cmac.h","//submodules/openssl:openssl_header_openssl_sub_cms.h","//submodules/openssl:openssl_header_openssl_sub_cmserr.h","//submodules/openssl:openssl_header_openssl_sub_comp.h","//submodules/openssl:openssl_header_openssl_sub_comperr.h","//submodules/openssl:openssl_header_openssl_sub_conf.h","//submodules/openssl:openssl_header_openssl_sub_conf_api.h","//submodules/openssl:openssl_header_openssl_sub_conferr.h","//submodules/openssl:openssl_header_openssl_sub_crypto.h","//submodules/openssl:openssl_header_openssl_sub_cryptoerr.h","//submodules/openssl:openssl_header_openssl_sub_ct.h","//submodules/openssl:openssl_header_openssl_sub_cterr.h","//submodules/openssl:openssl_header_openssl_sub_des.h","//submodules/openssl:openssl_header_openssl_sub_dh.h","//submodules/openssl:openssl_header_openssl_sub_dherr.h","//submodules/openssl:openssl_header_openssl_sub_dsa.h","//submodules/openssl:openssl_header_openssl_sub_dsaerr.h","//submodules/openssl:openssl_header_openssl_sub_dtls1.h","//submodules/openssl:openssl_header_openssl_sub_e_os2.h","//submodules/openssl:openssl_header_openssl_sub_ebcdic.h","//submodules/openssl:openssl_header_openssl_sub_ec.h","//submodules/openssl:openssl_header_openssl_sub_ecdh.h","//submodules/openssl:openssl_header_openssl_sub_ecdsa.h","//submodules/openssl:openssl_header_openssl_sub_ecerr.h","//submodules/openssl:openssl_header_openssl_sub_engine.h","//submodules/openssl:openssl_header_openssl_sub_engineerr.h","//submodules/openssl:openssl_header_openssl_sub_err.h","//submodules/openssl:openssl_header_openssl_sub_evp.h","//submodules/openssl:openssl_header_openssl_sub_evperr.h","//submodules/openssl:openssl_header_openssl_sub_hmac.h","//submodules/openssl:openssl_header_openssl_sub_idea.h","//submodules/openssl:openssl_header_openssl_sub_kdf.h","//submodules/openssl:openssl_header_openssl_sub_kdferr.h","//submodules/openssl:openssl_header_openssl_sub_lhash.h","//submodules/openssl:openssl_header_openssl_sub_md2.h","//submodules/openssl:openssl_header_openssl_sub_md4.h","//submodules/openssl:openssl_header_openssl_sub_md5.h","//submodules/openssl:openssl_header_openssl_sub_mdc2.h","//submodules/openssl:openssl_header_openssl_sub_modes.h","//submodules/openssl:openssl_header_openssl_sub_obj_mac.h","//submodules/openssl:openssl_header_openssl_sub_objects.h","//submodules/openssl:openssl_header_openssl_sub_objectserr.h","//submodules/openssl:openssl_header_openssl_sub_ocsp.h","//submodules/openssl:openssl_header_openssl_sub_ocsperr.h","//submodules/openssl:openssl_header_openssl_sub_opensslconf.h","//submodules/openssl:openssl_header_openssl_sub_opensslv.h","//submodules/openssl:openssl_header_openssl_sub_ossl_typ.h","//submodules/openssl:openssl_header_openssl_sub_pem.h","//submodules/openssl:openssl_header_openssl_sub_pem2.h","//submodules/openssl:openssl_header_openssl_sub_pemerr.h","//submodules/openssl:openssl_header_openssl_sub_pkcs12.h","//submodules/openssl:openssl_header_openssl_sub_pkcs12err.h","//submodules/openssl:openssl_header_openssl_sub_pkcs7.h","//submodules/openssl:openssl_header_openssl_sub_pkcs7err.h","//submodules/openssl:openssl_header_openssl_sub_rand.h","//submodules/openssl:openssl_header_openssl_sub_rand_drbg.h","//submodules/openssl:openssl_header_openssl_sub_randerr.h","//submodules/openssl:openssl_header_openssl_sub_rc2.h","//submodules/openssl:openssl_header_openssl_sub_rc4.h","//submodules/openssl:openssl_header_openssl_sub_rc5.h","//submodules/openssl:openssl_header_openssl_sub_ripemd.h","//submodules/openssl:openssl_header_openssl_sub_rsa.h","//submodules/openssl:openssl_header_openssl_sub_rsaerr.h","//submodules/openssl:openssl_header_openssl_sub_safestack.h","//submodules/openssl:openssl_header_openssl_sub_seed.h","//submodules/openssl:openssl_header_openssl_sub_sha.h","//submodules/openssl:openssl_header_openssl_sub_srp.h","//submodules/openssl:openssl_header_openssl_sub_srtp.h","//submodules/openssl:openssl_header_openssl_sub_ssl.h","//submodules/openssl:openssl_header_openssl_sub_ssl2.h","//submodules/openssl:openssl_header_openssl_sub_ssl3.h","//submodules/openssl:openssl_header_openssl_sub_sslerr.h","//submodules/openssl:openssl_header_openssl_sub_stack.h","//submodules/openssl:openssl_header_openssl_sub_store.h","//submodules/openssl:openssl_header_openssl_sub_storeerr.h","//submodules/openssl:openssl_header_openssl_sub_symhacks.h","//submodules/openssl:openssl_header_openssl_sub_tls1.h","//submodules/openssl:openssl_header_openssl_sub_ts.h","//submodules/openssl:openssl_header_openssl_sub_tserr.h","//submodules/openssl:openssl_header_openssl_sub_txt_db.h","//submodules/openssl:openssl_header_openssl_sub_ui.h","//submodules/openssl:openssl_header_openssl_sub_uierr.h","//submodules/openssl:openssl_header_openssl_sub_whrlpool.h","//submodules/openssl:openssl_header_openssl_sub_x509.h","//submodules/openssl:openssl_header_openssl_sub_x509_vfy.h","//submodules/openssl:openssl_header_openssl_sub_x509err.h","//submodules/openssl:openssl_header_openssl_sub_x509v3.h","//submodules/openssl:openssl_header_openssl_sub_x509v3err.h","//submodules/ton:ton_build","//submodules/ton:ton_header_auto_sub_tl_sub_tonlib_api.h","//submodules/ton:ton_header_td_sub_utils_sub_SharedSlice.h","//submodules/ton:ton_header_td_sub_utils_sub_Slice-decl.h","//submodules/ton:ton_header_td_sub_utils_sub_Slice.h","//submodules/ton:ton_header_td_sub_utils_sub_check.h","//submodules/ton:ton_header_td_sub_utils_sub_common.h","//submodules/ton:ton_header_td_sub_utils_sub_config.h","//submodules/ton:ton_header_td_sub_utils_sub_int_types.h","//submodules/ton:ton_header_td_sub_utils_sub_port_sub_platform.h","//submodules/ton:ton_header_td_sub_utils_sub_unique_ptr.h","//submodules/ton:ton_header_tl_sub_TlObject.h","//submodules/ton:ton_header_tonlib_sub_Client.h","//submodules/ton:ton_header_tonlib_sub_tonlib_client_json.h","//submodules/ton:ton_header_tonlib_sub_tonlibjson_export.h"],"xcconfig-paths":["buck-out/gen/AppLibrary-Debug.xcconfig","buck-out/gen/AppLibrary-Profile.xcconfig","buck-out/gen/AppLibrary-Release.xcconfig","buck-out/gen/IntentsExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/IntentsExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/IntentsExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/NotificationContentExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/NotificationContentExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/NotificationContentExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/NotificationServiceExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/NotificationServiceExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/NotificationServiceExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/ShareExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/ShareExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/ShareExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/Telegram-Debug.xcconfig","buck-out/gen/Telegram-Profile.xcconfig","buck-out/gen/Telegram-Release.xcconfig","buck-out/gen/WatchApp#watchsimulator-i386-Debug.xcconfig","buck-out/gen/WatchApp#watchsimulator-i386-Profile.xcconfig","buck-out/gen/WatchApp#watchsimulator-i386-Release.xcconfig","buck-out/gen/WatchAppExtension#watchsimulator-i386-Debug.xcconfig","buck-out/gen/WatchAppExtension#watchsimulator-i386-Profile.xcconfig","buck-out/gen/WatchAppExtension#watchsimulator-i386-Release.xcconfig","buck-out/gen/WidgetExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/WidgetExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/WidgetExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/submodules/AccountContext/AccountContext-Debug.xcconfig","buck-out/gen/submodules/AccountContext/AccountContext-Profile.xcconfig","buck-out/gen/submodules/AccountContext/AccountContext-Release.xcconfig","buck-out/gen/submodules/ActionSheetPeerItem/ActionSheetPeerItem-Debug.xcconfig","buck-out/gen/submodules/ActionSheetPeerItem/ActionSheetPeerItem-Profile.xcconfig","buck-out/gen/submodules/ActionSheetPeerItem/ActionSheetPeerItem-Release.xcconfig","buck-out/gen/submodules/ActivityIndicator/ActivityIndicator-Debug.xcconfig","buck-out/gen/submodules/ActivityIndicator/ActivityIndicator-Profile.xcconfig","buck-out/gen/submodules/ActivityIndicator/ActivityIndicator-Release.xcconfig","buck-out/gen/submodules/AlertUI/AlertUI-Debug.xcconfig","buck-out/gen/submodules/AlertUI/AlertUI-Profile.xcconfig","buck-out/gen/submodules/AlertUI/AlertUI-Release.xcconfig","buck-out/gen/submodules/AnimationUI/AnimationUI-Debug.xcconfig","buck-out/gen/submodules/AnimationUI/AnimationUI-Profile.xcconfig","buck-out/gen/submodules/AnimationUI/AnimationUI-Release.xcconfig","buck-out/gen/submodules/AppBundle/AppBundle-Debug.xcconfig","buck-out/gen/submodules/AppBundle/AppBundle-Profile.xcconfig","buck-out/gen/submodules/AppBundle/AppBundle-Release.xcconfig","buck-out/gen/submodules/AsyncDisplayKit/AsyncDisplayKit#shared-Debug.xcconfig","buck-out/gen/submodules/AsyncDisplayKit/AsyncDisplayKit#shared-Profile.xcconfig","buck-out/gen/submodules/AsyncDisplayKit/AsyncDisplayKit#shared-Release.xcconfig","buck-out/gen/submodules/AuthorizationUI/AuthorizationUI-Debug.xcconfig","buck-out/gen/submodules/AuthorizationUI/AuthorizationUI-Profile.xcconfig","buck-out/gen/submodules/AuthorizationUI/AuthorizationUI-Release.xcconfig","buck-out/gen/submodules/AvatarNode/AvatarNode-Debug.xcconfig","buck-out/gen/submodules/AvatarNode/AvatarNode-Profile.xcconfig","buck-out/gen/submodules/AvatarNode/AvatarNode-Release.xcconfig","buck-out/gen/submodules/BotPaymentsUI/BotPaymentsUI-Debug.xcconfig","buck-out/gen/submodules/BotPaymentsUI/BotPaymentsUI-Profile.xcconfig","buck-out/gen/submodules/BotPaymentsUI/BotPaymentsUI-Release.xcconfig","buck-out/gen/submodules/BuildConfig/BuildConfig-Debug.xcconfig","buck-out/gen/submodules/BuildConfig/BuildConfig-Profile.xcconfig","buck-out/gen/submodules/BuildConfig/BuildConfig-Release.xcconfig","buck-out/gen/submodules/CallListUI/CallListUI-Debug.xcconfig","buck-out/gen/submodules/CallListUI/CallListUI-Profile.xcconfig","buck-out/gen/submodules/CallListUI/CallListUI-Release.xcconfig","buck-out/gen/submodules/Camera/Camera-Debug.xcconfig","buck-out/gen/submodules/Camera/Camera-Profile.xcconfig","buck-out/gen/submodules/Camera/Camera-Release.xcconfig","buck-out/gen/submodules/ChatListSearchItemHeader/ChatListSearchItemHeader-Debug.xcconfig","buck-out/gen/submodules/ChatListSearchItemHeader/ChatListSearchItemHeader-Profile.xcconfig","buck-out/gen/submodules/ChatListSearchItemHeader/ChatListSearchItemHeader-Release.xcconfig","buck-out/gen/submodules/ChatListSearchItemNode/ChatListSearchItemNode-Debug.xcconfig","buck-out/gen/submodules/ChatListSearchItemNode/ChatListSearchItemNode-Profile.xcconfig","buck-out/gen/submodules/ChatListSearchItemNode/ChatListSearchItemNode-Release.xcconfig","buck-out/gen/submodules/ChatListSearchRecentPeersNode/ChatListSearchRecentPeersNode-Debug.xcconfig","buck-out/gen/submodules/ChatListSearchRecentPeersNode/ChatListSearchRecentPeersNode-Profile.xcconfig","buck-out/gen/submodules/ChatListSearchRecentPeersNode/ChatListSearchRecentPeersNode-Release.xcconfig","buck-out/gen/submodules/ChatListUI/ChatListUI-Debug.xcconfig","buck-out/gen/submodules/ChatListUI/ChatListUI-Profile.xcconfig","buck-out/gen/submodules/ChatListUI/ChatListUI-Release.xcconfig","buck-out/gen/submodules/ChatTitleActivityNode/ChatTitleActivityNode-Debug.xcconfig","buck-out/gen/submodules/ChatTitleActivityNode/ChatTitleActivityNode-Profile.xcconfig","buck-out/gen/submodules/ChatTitleActivityNode/ChatTitleActivityNode-Release.xcconfig","buck-out/gen/submodules/CheckNode/CheckNode-Debug.xcconfig","buck-out/gen/submodules/CheckNode/CheckNode-Profile.xcconfig","buck-out/gen/submodules/CheckNode/CheckNode-Release.xcconfig","buck-out/gen/submodules/ComposePollUI/ComposePollUI-Debug.xcconfig","buck-out/gen/submodules/ComposePollUI/ComposePollUI-Profile.xcconfig","buck-out/gen/submodules/ComposePollUI/ComposePollUI-Release.xcconfig","buck-out/gen/submodules/ContactListUI/ContactListUI-Debug.xcconfig","buck-out/gen/submodules/ContactListUI/ContactListUI-Profile.xcconfig","buck-out/gen/submodules/ContactListUI/ContactListUI-Release.xcconfig","buck-out/gen/submodules/ContactsPeerItem/ContactsPeerItem-Debug.xcconfig","buck-out/gen/submodules/ContactsPeerItem/ContactsPeerItem-Profile.xcconfig","buck-out/gen/submodules/ContactsPeerItem/ContactsPeerItem-Release.xcconfig","buck-out/gen/submodules/ContextUI/ContextUI-Debug.xcconfig","buck-out/gen/submodules/ContextUI/ContextUI-Profile.xcconfig","buck-out/gen/submodules/ContextUI/ContextUI-Release.xcconfig","buck-out/gen/submodules/CounterContollerTitleView/CounterContollerTitleView-Debug.xcconfig","buck-out/gen/submodules/CounterContollerTitleView/CounterContollerTitleView-Profile.xcconfig","buck-out/gen/submodules/CounterContollerTitleView/CounterContollerTitleView-Release.xcconfig","buck-out/gen/submodules/CountrySelectionUI/CountrySelectionUI-Debug.xcconfig","buck-out/gen/submodules/CountrySelectionUI/CountrySelectionUI-Profile.xcconfig","buck-out/gen/submodules/CountrySelectionUI/CountrySelectionUI-Release.xcconfig","buck-out/gen/submodules/Crc32/Crc32-Debug.xcconfig","buck-out/gen/submodules/Crc32/Crc32-Profile.xcconfig","buck-out/gen/submodules/Crc32/Crc32-Release.xcconfig","buck-out/gen/submodules/DateSelectionUI/DateSelectionUI-Debug.xcconfig","buck-out/gen/submodules/DateSelectionUI/DateSelectionUI-Profile.xcconfig","buck-out/gen/submodules/DateSelectionUI/DateSelectionUI-Release.xcconfig","buck-out/gen/submodules/DeleteChatPeerActionSheetItem/DeleteChatPeerActionSheetItem-Debug.xcconfig","buck-out/gen/submodules/DeleteChatPeerActionSheetItem/DeleteChatPeerActionSheetItem-Profile.xcconfig","buck-out/gen/submodules/DeleteChatPeerActionSheetItem/DeleteChatPeerActionSheetItem-Release.xcconfig","buck-out/gen/submodules/DeviceAccess/DeviceAccess-Debug.xcconfig","buck-out/gen/submodules/DeviceAccess/DeviceAccess-Profile.xcconfig","buck-out/gen/submodules/DeviceAccess/DeviceAccess-Release.xcconfig","buck-out/gen/submodules/DeviceLocationManager/DeviceLocationManager-Debug.xcconfig","buck-out/gen/submodules/DeviceLocationManager/DeviceLocationManager-Profile.xcconfig","buck-out/gen/submodules/DeviceLocationManager/DeviceLocationManager-Release.xcconfig","buck-out/gen/submodules/DeviceProximity/DeviceProximity-Debug.xcconfig","buck-out/gen/submodules/DeviceProximity/DeviceProximity-Profile.xcconfig","buck-out/gen/submodules/DeviceProximity/DeviceProximity-Release.xcconfig","buck-out/gen/submodules/DirectionalPanGesture/DirectionalPanGesture-Debug.xcconfig","buck-out/gen/submodules/DirectionalPanGesture/DirectionalPanGesture-Profile.xcconfig","buck-out/gen/submodules/DirectionalPanGesture/DirectionalPanGesture-Release.xcconfig","buck-out/gen/submodules/Display/Display#shared-Debug.xcconfig","buck-out/gen/submodules/Display/Display#shared-Profile.xcconfig","buck-out/gen/submodules/Display/Display#shared-Release.xcconfig","buck-out/gen/submodules/Emoji/Emoji-Debug.xcconfig","buck-out/gen/submodules/Emoji/Emoji-Profile.xcconfig","buck-out/gen/submodules/Emoji/Emoji-Release.xcconfig","buck-out/gen/submodules/EncryptionKeyVisualization/EncryptionKeyVisualization-Debug.xcconfig","buck-out/gen/submodules/EncryptionKeyVisualization/EncryptionKeyVisualization-Profile.xcconfig","buck-out/gen/submodules/EncryptionKeyVisualization/EncryptionKeyVisualization-Release.xcconfig","buck-out/gen/submodules/FFMpeg/FFMpeg-Debug.xcconfig","buck-out/gen/submodules/FFMpeg/FFMpeg-Profile.xcconfig","buck-out/gen/submodules/FFMpeg/FFMpeg-Release.xcconfig","buck-out/gen/submodules/FFMpeg/libffmpeg-Debug.xcconfig","buck-out/gen/submodules/FFMpeg/libffmpeg-Profile.xcconfig","buck-out/gen/submodules/FFMpeg/libffmpeg-Release.xcconfig","buck-out/gen/submodules/GZip/GZip-Debug.xcconfig","buck-out/gen/submodules/GZip/GZip-Profile.xcconfig","buck-out/gen/submodules/GZip/GZip-Release.xcconfig","buck-out/gen/submodules/GalleryUI/GalleryUI-Debug.xcconfig","buck-out/gen/submodules/GalleryUI/GalleryUI-Profile.xcconfig","buck-out/gen/submodules/GalleryUI/GalleryUI-Release.xcconfig","buck-out/gen/submodules/GameUI/GameUI-Debug.xcconfig","buck-out/gen/submodules/GameUI/GameUI-Profile.xcconfig","buck-out/gen/submodules/GameUI/GameUI-Release.xcconfig","buck-out/gen/submodules/Geocoding/Geocoding-Debug.xcconfig","buck-out/gen/submodules/Geocoding/Geocoding-Profile.xcconfig","buck-out/gen/submodules/Geocoding/Geocoding-Release.xcconfig","buck-out/gen/submodules/GridMessageSelectionNode/GridMessageSelectionNode-Debug.xcconfig","buck-out/gen/submodules/GridMessageSelectionNode/GridMessageSelectionNode-Profile.xcconfig","buck-out/gen/submodules/GridMessageSelectionNode/GridMessageSelectionNode-Release.xcconfig","buck-out/gen/submodules/HashtagSearchUI/HashtagSearchUI-Debug.xcconfig","buck-out/gen/submodules/HashtagSearchUI/HashtagSearchUI-Profile.xcconfig","buck-out/gen/submodules/HashtagSearchUI/HashtagSearchUI-Release.xcconfig","buck-out/gen/submodules/HexColor/HexColor-Debug.xcconfig","buck-out/gen/submodules/HexColor/HexColor-Profile.xcconfig","buck-out/gen/submodules/HexColor/HexColor-Release.xcconfig","buck-out/gen/submodules/HockeySDK-iOS/HockeySDK-Debug.xcconfig","buck-out/gen/submodules/HockeySDK-iOS/HockeySDK-Profile.xcconfig","buck-out/gen/submodules/HockeySDK-iOS/HockeySDK-Release.xcconfig","buck-out/gen/submodules/HorizontalPeerItem/HorizontalPeerItem-Debug.xcconfig","buck-out/gen/submodules/HorizontalPeerItem/HorizontalPeerItem-Profile.xcconfig","buck-out/gen/submodules/HorizontalPeerItem/HorizontalPeerItem-Release.xcconfig","buck-out/gen/submodules/ImageBlur/ImageBlur-Debug.xcconfig","buck-out/gen/submodules/ImageBlur/ImageBlur-Profile.xcconfig","buck-out/gen/submodules/ImageBlur/ImageBlur-Release.xcconfig","buck-out/gen/submodules/ImageCompression/ImageCompression-Debug.xcconfig","buck-out/gen/submodules/ImageCompression/ImageCompression-Profile.xcconfig","buck-out/gen/submodules/ImageCompression/ImageCompression-Release.xcconfig","buck-out/gen/submodules/ImageTransparency/ImageTransparency-Debug.xcconfig","buck-out/gen/submodules/ImageTransparency/ImageTransparency-Profile.xcconfig","buck-out/gen/submodules/ImageTransparency/ImageTransparency-Release.xcconfig","buck-out/gen/submodules/InstantPageCache/InstantPageCache-Debug.xcconfig","buck-out/gen/submodules/InstantPageCache/InstantPageCache-Profile.xcconfig","buck-out/gen/submodules/InstantPageCache/InstantPageCache-Release.xcconfig","buck-out/gen/submodules/InstantPageUI/InstantPageUI-Debug.xcconfig","buck-out/gen/submodules/InstantPageUI/InstantPageUI-Profile.xcconfig","buck-out/gen/submodules/InstantPageUI/InstantPageUI-Release.xcconfig","buck-out/gen/submodules/ItemListAddressItem/ItemListAddressItem-Debug.xcconfig","buck-out/gen/submodules/ItemListAddressItem/ItemListAddressItem-Profile.xcconfig","buck-out/gen/submodules/ItemListAddressItem/ItemListAddressItem-Release.xcconfig","buck-out/gen/submodules/ItemListAvatarAndNameInfoItem/ItemListAvatarAndNameInfoItem-Debug.xcconfig","buck-out/gen/submodules/ItemListAvatarAndNameInfoItem/ItemListAvatarAndNameInfoItem-Profile.xcconfig","buck-out/gen/submodules/ItemListAvatarAndNameInfoItem/ItemListAvatarAndNameInfoItem-Release.xcconfig","buck-out/gen/submodules/ItemListPeerActionItem/ItemListPeerActionItem-Debug.xcconfig","buck-out/gen/submodules/ItemListPeerActionItem/ItemListPeerActionItem-Profile.xcconfig","buck-out/gen/submodules/ItemListPeerActionItem/ItemListPeerActionItem-Release.xcconfig","buck-out/gen/submodules/ItemListPeerItem/ItemListPeerItem-Debug.xcconfig","buck-out/gen/submodules/ItemListPeerItem/ItemListPeerItem-Profile.xcconfig","buck-out/gen/submodules/ItemListPeerItem/ItemListPeerItem-Release.xcconfig","buck-out/gen/submodules/ItemListStickerPackItem/ItemListStickerPackItem-Debug.xcconfig","buck-out/gen/submodules/ItemListStickerPackItem/ItemListStickerPackItem-Profile.xcconfig","buck-out/gen/submodules/ItemListStickerPackItem/ItemListStickerPackItem-Release.xcconfig","buck-out/gen/submodules/ItemListUI/ItemListUI-Debug.xcconfig","buck-out/gen/submodules/ItemListUI/ItemListUI-Profile.xcconfig","buck-out/gen/submodules/ItemListUI/ItemListUI-Release.xcconfig","buck-out/gen/submodules/JoinLinkPreviewUI/JoinLinkPreviewUI-Debug.xcconfig","buck-out/gen/submodules/JoinLinkPreviewUI/JoinLinkPreviewUI-Profile.xcconfig","buck-out/gen/submodules/JoinLinkPreviewUI/JoinLinkPreviewUI-Release.xcconfig","buck-out/gen/submodules/LanguageLinkPreviewUI/LanguageLinkPreviewUI-Debug.xcconfig","buck-out/gen/submodules/LanguageLinkPreviewUI/LanguageLinkPreviewUI-Profile.xcconfig","buck-out/gen/submodules/LanguageLinkPreviewUI/LanguageLinkPreviewUI-Release.xcconfig","buck-out/gen/submodules/LanguageSuggestionUI/LanguageSuggestionUI-Debug.xcconfig","buck-out/gen/submodules/LanguageSuggestionUI/LanguageSuggestionUI-Profile.xcconfig","buck-out/gen/submodules/LanguageSuggestionUI/LanguageSuggestionUI-Release.xcconfig","buck-out/gen/submodules/LegacyComponents/LegacyComponents-Debug.xcconfig","buck-out/gen/submodules/LegacyComponents/LegacyComponents-Profile.xcconfig","buck-out/gen/submodules/LegacyComponents/LegacyComponents-Release.xcconfig","buck-out/gen/submodules/LegacyDataImport/LegacyDataImport-Debug.xcconfig","buck-out/gen/submodules/LegacyDataImport/LegacyDataImport-Profile.xcconfig","buck-out/gen/submodules/LegacyDataImport/LegacyDataImport-Release.xcconfig","buck-out/gen/submodules/LegacyMediaPickerUI/LegacyMediaPickerUI-Debug.xcconfig","buck-out/gen/submodules/LegacyMediaPickerUI/LegacyMediaPickerUI-Profile.xcconfig","buck-out/gen/submodules/LegacyMediaPickerUI/LegacyMediaPickerUI-Release.xcconfig","buck-out/gen/submodules/LegacyUI/LegacyUI-Debug.xcconfig","buck-out/gen/submodules/LegacyUI/LegacyUI-Profile.xcconfig","buck-out/gen/submodules/LegacyUI/LegacyUI-Release.xcconfig","buck-out/gen/submodules/LightweightAccountData/LightweightAccountData-Debug.xcconfig","buck-out/gen/submodules/LightweightAccountData/LightweightAccountData-Profile.xcconfig","buck-out/gen/submodules/LightweightAccountData/LightweightAccountData-Release.xcconfig","buck-out/gen/submodules/ListSectionHeaderNode/ListSectionHeaderNode-Debug.xcconfig","buck-out/gen/submodules/ListSectionHeaderNode/ListSectionHeaderNode-Profile.xcconfig","buck-out/gen/submodules/ListSectionHeaderNode/ListSectionHeaderNode-Release.xcconfig","buck-out/gen/submodules/LiveLocationManager/LiveLocationManager-Debug.xcconfig","buck-out/gen/submodules/LiveLocationManager/LiveLocationManager-Profile.xcconfig","buck-out/gen/submodules/LiveLocationManager/LiveLocationManager-Release.xcconfig","buck-out/gen/submodules/LiveLocationPositionNode/LiveLocationPositionNode-Debug.xcconfig","buck-out/gen/submodules/LiveLocationPositionNode/LiveLocationPositionNode-Profile.xcconfig","buck-out/gen/submodules/LiveLocationPositionNode/LiveLocationPositionNode-Release.xcconfig","buck-out/gen/submodules/LiveLocationTimerNode/LiveLocationTimerNode-Debug.xcconfig","buck-out/gen/submodules/LiveLocationTimerNode/LiveLocationTimerNode-Profile.xcconfig","buck-out/gen/submodules/LiveLocationTimerNode/LiveLocationTimerNode-Release.xcconfig","buck-out/gen/submodules/LocalAuth/LocalAuth-Debug.xcconfig","buck-out/gen/submodules/LocalAuth/LocalAuth-Profile.xcconfig","buck-out/gen/submodules/LocalAuth/LocalAuth-Release.xcconfig","buck-out/gen/submodules/LocalMediaResources/LocalMediaResources-Debug.xcconfig","buck-out/gen/submodules/LocalMediaResources/LocalMediaResources-Profile.xcconfig","buck-out/gen/submodules/LocalMediaResources/LocalMediaResources-Release.xcconfig","buck-out/gen/submodules/LocalizedPeerData/LocalizedPeerData-Debug.xcconfig","buck-out/gen/submodules/LocalizedPeerData/LocalizedPeerData-Profile.xcconfig","buck-out/gen/submodules/LocalizedPeerData/LocalizedPeerData-Release.xcconfig","buck-out/gen/submodules/LocationUI/LocationUI-Debug.xcconfig","buck-out/gen/submodules/LocationUI/LocationUI-Profile.xcconfig","buck-out/gen/submodules/LocationUI/LocationUI-Release.xcconfig","buck-out/gen/submodules/MapResourceToAvatarSizes/MapResourceToAvatarSizes-Debug.xcconfig","buck-out/gen/submodules/MapResourceToAvatarSizes/MapResourceToAvatarSizes-Profile.xcconfig","buck-out/gen/submodules/MapResourceToAvatarSizes/MapResourceToAvatarSizes-Release.xcconfig","buck-out/gen/submodules/MediaPlayer/UniversalMediaPlayer-Debug.xcconfig","buck-out/gen/submodules/MediaPlayer/UniversalMediaPlayer-Profile.xcconfig","buck-out/gen/submodules/MediaPlayer/UniversalMediaPlayer-Release.xcconfig","buck-out/gen/submodules/MediaResources/MediaResources-Debug.xcconfig","buck-out/gen/submodules/MediaResources/MediaResources-Profile.xcconfig","buck-out/gen/submodules/MediaResources/MediaResources-Release.xcconfig","buck-out/gen/submodules/MergeLists/MergeLists-Debug.xcconfig","buck-out/gen/submodules/MergeLists/MergeLists-Profile.xcconfig","buck-out/gen/submodules/MergeLists/MergeLists-Release.xcconfig","buck-out/gen/submodules/MessageReactionListUI/MessageReactionListUI-Debug.xcconfig","buck-out/gen/submodules/MessageReactionListUI/MessageReactionListUI-Profile.xcconfig","buck-out/gen/submodules/MessageReactionListUI/MessageReactionListUI-Release.xcconfig","buck-out/gen/submodules/MimeTypes/MimeTypes-Debug.xcconfig","buck-out/gen/submodules/MimeTypes/MimeTypes-Profile.xcconfig","buck-out/gen/submodules/MimeTypes/MimeTypes-Release.xcconfig","buck-out/gen/submodules/MosaicLayout/MosaicLayout-Debug.xcconfig","buck-out/gen/submodules/MosaicLayout/MosaicLayout-Profile.xcconfig","buck-out/gen/submodules/MosaicLayout/MosaicLayout-Release.xcconfig","buck-out/gen/submodules/MtProtoKit/MtProtoKit#shared-Debug.xcconfig","buck-out/gen/submodules/MtProtoKit/MtProtoKit#shared-Profile.xcconfig","buck-out/gen/submodules/MtProtoKit/MtProtoKit#shared-Release.xcconfig","buck-out/gen/submodules/MusicAlbumArtResources/MusicAlbumArtResources-Debug.xcconfig","buck-out/gen/submodules/MusicAlbumArtResources/MusicAlbumArtResources-Profile.xcconfig","buck-out/gen/submodules/MusicAlbumArtResources/MusicAlbumArtResources-Release.xcconfig","buck-out/gen/submodules/NotificationMuteSettingsUI/NotificationMuteSettingsUI-Debug.xcconfig","buck-out/gen/submodules/NotificationMuteSettingsUI/NotificationMuteSettingsUI-Profile.xcconfig","buck-out/gen/submodules/NotificationMuteSettingsUI/NotificationMuteSettingsUI-Release.xcconfig","buck-out/gen/submodules/NotificationSoundSelectionUI/NotificationSoundSelectionUI-Debug.xcconfig","buck-out/gen/submodules/NotificationSoundSelectionUI/NotificationSoundSelectionUI-Profile.xcconfig","buck-out/gen/submodules/NotificationSoundSelectionUI/NotificationSoundSelectionUI-Release.xcconfig","buck-out/gen/submodules/OpenInExternalAppUI/OpenInExternalAppUI-Debug.xcconfig","buck-out/gen/submodules/OpenInExternalAppUI/OpenInExternalAppUI-Profile.xcconfig","buck-out/gen/submodules/OpenInExternalAppUI/OpenInExternalAppUI-Release.xcconfig","buck-out/gen/submodules/Opus/opus-Debug.xcconfig","buck-out/gen/submodules/Opus/opus-Profile.xcconfig","buck-out/gen/submodules/Opus/opus-Release.xcconfig","buck-out/gen/submodules/Opus/opus_lib-Debug.xcconfig","buck-out/gen/submodules/Opus/opus_lib-Profile.xcconfig","buck-out/gen/submodules/Opus/opus_lib-Release.xcconfig","buck-out/gen/submodules/OpusBinding/OpusBinding-Debug.xcconfig","buck-out/gen/submodules/OpusBinding/OpusBinding-Profile.xcconfig","buck-out/gen/submodules/OpusBinding/OpusBinding-Release.xcconfig","buck-out/gen/submodules/OverlayStatusController/OverlayStatusController-Debug.xcconfig","buck-out/gen/submodules/OverlayStatusController/OverlayStatusController-Profile.xcconfig","buck-out/gen/submodules/OverlayStatusController/OverlayStatusController-Release.xcconfig","buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Debug.xcconfig","buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Profile.xcconfig","buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Release.xcconfig","buck-out/gen/submodules/PasscodeUI/PasscodeUI-Debug.xcconfig","buck-out/gen/submodules/PasscodeUI/PasscodeUI-Profile.xcconfig","buck-out/gen/submodules/PasscodeUI/PasscodeUI-Release.xcconfig","buck-out/gen/submodules/PassportUI/PassportUI-Debug.xcconfig","buck-out/gen/submodules/PassportUI/PassportUI-Profile.xcconfig","buck-out/gen/submodules/PassportUI/PassportUI-Release.xcconfig","buck-out/gen/submodules/PasswordSetupUI/PasswordSetupUI-Debug.xcconfig","buck-out/gen/submodules/PasswordSetupUI/PasswordSetupUI-Profile.xcconfig","buck-out/gen/submodules/PasswordSetupUI/PasswordSetupUI-Release.xcconfig","buck-out/gen/submodules/Pdf/Pdf-Debug.xcconfig","buck-out/gen/submodules/Pdf/Pdf-Profile.xcconfig","buck-out/gen/submodules/Pdf/Pdf-Release.xcconfig","buck-out/gen/submodules/PeerAvatarGalleryUI/PeerAvatarGalleryUI-Debug.xcconfig","buck-out/gen/submodules/PeerAvatarGalleryUI/PeerAvatarGalleryUI-Profile.xcconfig","buck-out/gen/submodules/PeerAvatarGalleryUI/PeerAvatarGalleryUI-Release.xcconfig","buck-out/gen/submodules/PeerInfoUI/PeerInfoUI-Debug.xcconfig","buck-out/gen/submodules/PeerInfoUI/PeerInfoUI-Profile.xcconfig","buck-out/gen/submodules/PeerInfoUI/PeerInfoUI-Release.xcconfig","buck-out/gen/submodules/PeerOnlineMarkerNode/PeerOnlineMarkerNode-Debug.xcconfig","buck-out/gen/submodules/PeerOnlineMarkerNode/PeerOnlineMarkerNode-Profile.xcconfig","buck-out/gen/submodules/PeerOnlineMarkerNode/PeerOnlineMarkerNode-Release.xcconfig","buck-out/gen/submodules/PeerPresenceStatusManager/PeerPresenceStatusManager-Debug.xcconfig","buck-out/gen/submodules/PeerPresenceStatusManager/PeerPresenceStatusManager-Profile.xcconfig","buck-out/gen/submodules/PeerPresenceStatusManager/PeerPresenceStatusManager-Release.xcconfig","buck-out/gen/submodules/PeersNearbyIconNode/PeersNearbyIconNode-Debug.xcconfig","buck-out/gen/submodules/PeersNearbyIconNode/PeersNearbyIconNode-Profile.xcconfig","buck-out/gen/submodules/PeersNearbyIconNode/PeersNearbyIconNode-Release.xcconfig","buck-out/gen/submodules/PeersNearbyUI/PeersNearbyUI-Debug.xcconfig","buck-out/gen/submodules/PeersNearbyUI/PeersNearbyUI-Profile.xcconfig","buck-out/gen/submodules/PeersNearbyUI/PeersNearbyUI-Release.xcconfig","buck-out/gen/submodules/PersistentStringHash/PersistentStringHash-Debug.xcconfig","buck-out/gen/submodules/PersistentStringHash/PersistentStringHash-Profile.xcconfig","buck-out/gen/submodules/PersistentStringHash/PersistentStringHash-Release.xcconfig","buck-out/gen/submodules/PhoneInputNode/PhoneInputNode-Debug.xcconfig","buck-out/gen/submodules/PhoneInputNode/PhoneInputNode-Profile.xcconfig","buck-out/gen/submodules/PhoneInputNode/PhoneInputNode-Release.xcconfig","buck-out/gen/submodules/PhotoResources/PhotoResources-Debug.xcconfig","buck-out/gen/submodules/PhotoResources/PhotoResources-Profile.xcconfig","buck-out/gen/submodules/PhotoResources/PhotoResources-Release.xcconfig","buck-out/gen/submodules/PlatformRestrictionMatching/PlatformRestrictionMatching-Debug.xcconfig","buck-out/gen/submodules/PlatformRestrictionMatching/PlatformRestrictionMatching-Profile.xcconfig","buck-out/gen/submodules/PlatformRestrictionMatching/PlatformRestrictionMatching-Release.xcconfig","buck-out/gen/submodules/Postbox/Postbox#shared-Debug.xcconfig","buck-out/gen/submodules/Postbox/Postbox#shared-Profile.xcconfig","buck-out/gen/submodules/Postbox/Postbox#shared-Release.xcconfig","buck-out/gen/submodules/ProgressNavigationButtonNode/ProgressNavigationButtonNode-Debug.xcconfig","buck-out/gen/submodules/ProgressNavigationButtonNode/ProgressNavigationButtonNode-Profile.xcconfig","buck-out/gen/submodules/ProgressNavigationButtonNode/ProgressNavigationButtonNode-Release.xcconfig","buck-out/gen/submodules/QrCode/QrCode-Debug.xcconfig","buck-out/gen/submodules/QrCode/QrCode-Profile.xcconfig","buck-out/gen/submodules/QrCode/QrCode-Release.xcconfig","buck-out/gen/submodules/RMIntro/RMIntro-Debug.xcconfig","buck-out/gen/submodules/RMIntro/RMIntro-Profile.xcconfig","buck-out/gen/submodules/RMIntro/RMIntro-Release.xcconfig","buck-out/gen/submodules/RadialStatusNode/RadialStatusNode-Debug.xcconfig","buck-out/gen/submodules/RadialStatusNode/RadialStatusNode-Profile.xcconfig","buck-out/gen/submodules/RadialStatusNode/RadialStatusNode-Release.xcconfig","buck-out/gen/submodules/RaiseToListen/RaiseToListen-Debug.xcconfig","buck-out/gen/submodules/RaiseToListen/RaiseToListen-Profile.xcconfig","buck-out/gen/submodules/RaiseToListen/RaiseToListen-Release.xcconfig","buck-out/gen/submodules/ReactionSelectionNode/ReactionSelectionNode-Debug.xcconfig","buck-out/gen/submodules/ReactionSelectionNode/ReactionSelectionNode-Profile.xcconfig","buck-out/gen/submodules/ReactionSelectionNode/ReactionSelectionNode-Release.xcconfig","buck-out/gen/submodules/SSignalKit/SSignalKit/SSignalKit-Debug.xcconfig","buck-out/gen/submodules/SSignalKit/SSignalKit/SSignalKit-Profile.xcconfig","buck-out/gen/submodules/SSignalKit/SSignalKit/SSignalKit-Release.xcconfig","buck-out/gen/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit#shared-Debug.xcconfig","buck-out/gen/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit#shared-Profile.xcconfig","buck-out/gen/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit#shared-Release.xcconfig","buck-out/gen/submodules/SaveToCameraRoll/SaveToCameraRoll-Debug.xcconfig","buck-out/gen/submodules/SaveToCameraRoll/SaveToCameraRoll-Profile.xcconfig","buck-out/gen/submodules/SaveToCameraRoll/SaveToCameraRoll-Release.xcconfig","buck-out/gen/submodules/ScreenCaptureDetection/ScreenCaptureDetection-Debug.xcconfig","buck-out/gen/submodules/ScreenCaptureDetection/ScreenCaptureDetection-Profile.xcconfig","buck-out/gen/submodules/ScreenCaptureDetection/ScreenCaptureDetection-Release.xcconfig","buck-out/gen/submodules/SearchBarNode/SearchBarNode-Debug.xcconfig","buck-out/gen/submodules/SearchBarNode/SearchBarNode-Profile.xcconfig","buck-out/gen/submodules/SearchBarNode/SearchBarNode-Release.xcconfig","buck-out/gen/submodules/SearchUI/SearchUI-Debug.xcconfig","buck-out/gen/submodules/SearchUI/SearchUI-Profile.xcconfig","buck-out/gen/submodules/SearchUI/SearchUI-Release.xcconfig","buck-out/gen/submodules/SegmentedControlNode/SegmentedControlNode-Debug.xcconfig","buck-out/gen/submodules/SegmentedControlNode/SegmentedControlNode-Profile.xcconfig","buck-out/gen/submodules/SegmentedControlNode/SegmentedControlNode-Release.xcconfig","buck-out/gen/submodules/SelectablePeerNode/SelectablePeerNode-Debug.xcconfig","buck-out/gen/submodules/SelectablePeerNode/SelectablePeerNode-Profile.xcconfig","buck-out/gen/submodules/SelectablePeerNode/SelectablePeerNode-Release.xcconfig","buck-out/gen/submodules/SettingsUI/SettingsUI-Debug.xcconfig","buck-out/gen/submodules/SettingsUI/SettingsUI-Profile.xcconfig","buck-out/gen/submodules/SettingsUI/SettingsUI-Release.xcconfig","buck-out/gen/submodules/ShareController/ShareController-Debug.xcconfig","buck-out/gen/submodules/ShareController/ShareController-Profile.xcconfig","buck-out/gen/submodules/ShareController/ShareController-Release.xcconfig","buck-out/gen/submodules/ShareItems/ShareItems-Debug.xcconfig","buck-out/gen/submodules/ShareItems/ShareItems-Profile.xcconfig","buck-out/gen/submodules/ShareItems/ShareItems-Release.xcconfig","buck-out/gen/submodules/SinglePhoneInputNode/SinglePhoneInputNode-Debug.xcconfig","buck-out/gen/submodules/SinglePhoneInputNode/SinglePhoneInputNode-Profile.xcconfig","buck-out/gen/submodules/SinglePhoneInputNode/SinglePhoneInputNode-Release.xcconfig","buck-out/gen/submodules/SolidRoundedButtonNode/SolidRoundedButtonNode-Debug.xcconfig","buck-out/gen/submodules/SolidRoundedButtonNode/SolidRoundedButtonNode-Profile.xcconfig","buck-out/gen/submodules/SolidRoundedButtonNode/SolidRoundedButtonNode-Release.xcconfig","buck-out/gen/submodules/StickerPackPreviewUI/StickerPackPreviewUI-Debug.xcconfig","buck-out/gen/submodules/StickerPackPreviewUI/StickerPackPreviewUI-Profile.xcconfig","buck-out/gen/submodules/StickerPackPreviewUI/StickerPackPreviewUI-Release.xcconfig","buck-out/gen/submodules/StickerResources/StickerResources-Debug.xcconfig","buck-out/gen/submodules/StickerResources/StickerResources-Profile.xcconfig","buck-out/gen/submodules/StickerResources/StickerResources-Release.xcconfig","buck-out/gen/submodules/Stripe/Stripe-Debug.xcconfig","buck-out/gen/submodules/Stripe/Stripe-Profile.xcconfig","buck-out/gen/submodules/Stripe/Stripe-Release.xcconfig","buck-out/gen/submodules/SwipeToDismissGesture/SwipeToDismissGesture-Debug.xcconfig","buck-out/gen/submodules/SwipeToDismissGesture/SwipeToDismissGesture-Profile.xcconfig","buck-out/gen/submodules/SwipeToDismissGesture/SwipeToDismissGesture-Release.xcconfig","buck-out/gen/submodules/SwitchNode/SwitchNode-Debug.xcconfig","buck-out/gen/submodules/SwitchNode/SwitchNode-Profile.xcconfig","buck-out/gen/submodules/SwitchNode/SwitchNode-Release.xcconfig","buck-out/gen/submodules/TelegramApi/TelegramApi-Debug.xcconfig","buck-out/gen/submodules/TelegramApi/TelegramApi-Profile.xcconfig","buck-out/gen/submodules/TelegramApi/TelegramApi-Release.xcconfig","buck-out/gen/submodules/TelegramAudio/TelegramAudio-Debug.xcconfig","buck-out/gen/submodules/TelegramAudio/TelegramAudio-Profile.xcconfig","buck-out/gen/submodules/TelegramAudio/TelegramAudio-Release.xcconfig","buck-out/gen/submodules/TelegramBaseController/TelegramBaseController-Debug.xcconfig","buck-out/gen/submodules/TelegramBaseController/TelegramBaseController-Profile.xcconfig","buck-out/gen/submodules/TelegramBaseController/TelegramBaseController-Release.xcconfig","buck-out/gen/submodules/TelegramCallsUI/TelegramCallsUI-Debug.xcconfig","buck-out/gen/submodules/TelegramCallsUI/TelegramCallsUI-Profile.xcconfig","buck-out/gen/submodules/TelegramCallsUI/TelegramCallsUI-Release.xcconfig","buck-out/gen/submodules/TelegramCore/TelegramCore#shared-Debug.xcconfig","buck-out/gen/submodules/TelegramCore/TelegramCore#shared-Profile.xcconfig","buck-out/gen/submodules/TelegramCore/TelegramCore#shared-Release.xcconfig","buck-out/gen/submodules/TelegramNotices/TelegramNotices-Debug.xcconfig","buck-out/gen/submodules/TelegramNotices/TelegramNotices-Profile.xcconfig","buck-out/gen/submodules/TelegramNotices/TelegramNotices-Release.xcconfig","buck-out/gen/submodules/TelegramPermissions/TelegramPermissions-Debug.xcconfig","buck-out/gen/submodules/TelegramPermissions/TelegramPermissions-Profile.xcconfig","buck-out/gen/submodules/TelegramPermissions/TelegramPermissions-Release.xcconfig","buck-out/gen/submodules/TelegramPermissionsUI/TelegramPermissionsUI-Debug.xcconfig","buck-out/gen/submodules/TelegramPermissionsUI/TelegramPermissionsUI-Profile.xcconfig","buck-out/gen/submodules/TelegramPermissionsUI/TelegramPermissionsUI-Release.xcconfig","buck-out/gen/submodules/TelegramPresentationData/TelegramPresentationData-Debug.xcconfig","buck-out/gen/submodules/TelegramPresentationData/TelegramPresentationData-Profile.xcconfig","buck-out/gen/submodules/TelegramPresentationData/TelegramPresentationData-Release.xcconfig","buck-out/gen/submodules/TelegramStringFormatting/TelegramStringFormatting-Debug.xcconfig","buck-out/gen/submodules/TelegramStringFormatting/TelegramStringFormatting-Profile.xcconfig","buck-out/gen/submodules/TelegramStringFormatting/TelegramStringFormatting-Release.xcconfig","buck-out/gen/submodules/TelegramUI/TelegramUI#shared-Debug.xcconfig","buck-out/gen/submodules/TelegramUI/TelegramUI#shared-Profile.xcconfig","buck-out/gen/submodules/TelegramUI/TelegramUI#shared-Release.xcconfig","buck-out/gen/submodules/TelegramUIPreferences/TelegramUIPreferences-Debug.xcconfig","buck-out/gen/submodules/TelegramUIPreferences/TelegramUIPreferences-Profile.xcconfig","buck-out/gen/submodules/TelegramUIPreferences/TelegramUIPreferences-Release.xcconfig","buck-out/gen/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent-Debug.xcconfig","buck-out/gen/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent-Profile.xcconfig","buck-out/gen/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent-Release.xcconfig","buck-out/gen/submodules/TelegramUpdateUI/TelegramUpdateUI-Debug.xcconfig","buck-out/gen/submodules/TelegramUpdateUI/TelegramUpdateUI-Profile.xcconfig","buck-out/gen/submodules/TelegramUpdateUI/TelegramUpdateUI-Release.xcconfig","buck-out/gen/submodules/TelegramVoip/TelegramVoip-Debug.xcconfig","buck-out/gen/submodules/TelegramVoip/TelegramVoip-Profile.xcconfig","buck-out/gen/submodules/TelegramVoip/TelegramVoip-Release.xcconfig","buck-out/gen/submodules/TemporaryCachedPeerDataManager/TemporaryCachedPeerDataManager-Debug.xcconfig","buck-out/gen/submodules/TemporaryCachedPeerDataManager/TemporaryCachedPeerDataManager-Profile.xcconfig","buck-out/gen/submodules/TemporaryCachedPeerDataManager/TemporaryCachedPeerDataManager-Release.xcconfig","buck-out/gen/submodules/TextFormat/TextFormat-Debug.xcconfig","buck-out/gen/submodules/TextFormat/TextFormat-Profile.xcconfig","buck-out/gen/submodules/TextFormat/TextFormat-Release.xcconfig","buck-out/gen/submodules/TextSelectionNode/TextSelectionNode-Debug.xcconfig","buck-out/gen/submodules/TextSelectionNode/TextSelectionNode-Profile.xcconfig","buck-out/gen/submodules/TextSelectionNode/TextSelectionNode-Release.xcconfig","buck-out/gen/submodules/TinyThumbnail/TinyThumbnail-Debug.xcconfig","buck-out/gen/submodules/TinyThumbnail/TinyThumbnail-Profile.xcconfig","buck-out/gen/submodules/TinyThumbnail/TinyThumbnail-Release.xcconfig","buck-out/gen/submodules/TouchDownGesture/TouchDownGesture-Debug.xcconfig","buck-out/gen/submodules/TouchDownGesture/TouchDownGesture-Profile.xcconfig","buck-out/gen/submodules/TouchDownGesture/TouchDownGesture-Release.xcconfig","buck-out/gen/submodules/Tuples/Tuples-Debug.xcconfig","buck-out/gen/submodules/Tuples/Tuples-Profile.xcconfig","buck-out/gen/submodules/Tuples/Tuples-Release.xcconfig","buck-out/gen/submodules/UndoUI/UndoUI-Debug.xcconfig","buck-out/gen/submodules/UndoUI/UndoUI-Profile.xcconfig","buck-out/gen/submodules/UndoUI/UndoUI-Release.xcconfig","buck-out/gen/submodules/UrlEscaping/UrlEscaping-Debug.xcconfig","buck-out/gen/submodules/UrlEscaping/UrlEscaping-Profile.xcconfig","buck-out/gen/submodules/UrlEscaping/UrlEscaping-Release.xcconfig","buck-out/gen/submodules/UrlHandling/UrlHandling-Debug.xcconfig","buck-out/gen/submodules/UrlHandling/UrlHandling-Profile.xcconfig","buck-out/gen/submodules/UrlHandling/UrlHandling-Release.xcconfig","buck-out/gen/submodules/WalletUI/WalletUI-Debug.xcconfig","buck-out/gen/submodules/WalletUI/WalletUI-Profile.xcconfig","buck-out/gen/submodules/WalletUI/WalletUI-Release.xcconfig","buck-out/gen/submodules/WallpaperResources/WallpaperResources-Debug.xcconfig","buck-out/gen/submodules/WallpaperResources/WallpaperResources-Profile.xcconfig","buck-out/gen/submodules/WallpaperResources/WallpaperResources-Release.xcconfig","buck-out/gen/submodules/WatchBridge/WatchBridge-Debug.xcconfig","buck-out/gen/submodules/WatchBridge/WatchBridge-Profile.xcconfig","buck-out/gen/submodules/WatchBridge/WatchBridge-Release.xcconfig","buck-out/gen/submodules/WatchBridgeAudio/WatchBridgeAudio-Debug.xcconfig","buck-out/gen/submodules/WatchBridgeAudio/WatchBridgeAudio-Profile.xcconfig","buck-out/gen/submodules/WatchBridgeAudio/WatchBridgeAudio-Release.xcconfig","buck-out/gen/submodules/WatchCommon/Host/WatchCommon-Debug.xcconfig","buck-out/gen/submodules/WatchCommon/Host/WatchCommon-Profile.xcconfig","buck-out/gen/submodules/WatchCommon/Host/WatchCommon-Release.xcconfig","buck-out/gen/submodules/WebP/WebPImage-Debug.xcconfig","buck-out/gen/submodules/WebP/WebPImage-Profile.xcconfig","buck-out/gen/submodules/WebP/WebPImage-Release.xcconfig","buck-out/gen/submodules/WebP/WebP_lib-Debug.xcconfig","buck-out/gen/submodules/WebP/WebP_lib-Profile.xcconfig","buck-out/gen/submodules/WebP/WebP_lib-Release.xcconfig","buck-out/gen/submodules/WebSearchUI/WebSearchUI-Debug.xcconfig","buck-out/gen/submodules/WebSearchUI/WebSearchUI-Profile.xcconfig","buck-out/gen/submodules/WebSearchUI/WebSearchUI-Release.xcconfig","buck-out/gen/submodules/WebUI/WebUI-Debug.xcconfig","buck-out/gen/submodules/WebUI/WebUI-Profile.xcconfig","buck-out/gen/submodules/WebUI/WebUI-Release.xcconfig","buck-out/gen/submodules/WebsiteType/WebsiteType-Debug.xcconfig","buck-out/gen/submodules/WebsiteType/WebsiteType-Profile.xcconfig","buck-out/gen/submodules/WebsiteType/WebsiteType-Release.xcconfig","buck-out/gen/submodules/YuvConversion/YuvConversion-Debug.xcconfig","buck-out/gen/submodules/YuvConversion/YuvConversion-Profile.xcconfig","buck-out/gen/submodules/YuvConversion/YuvConversion-Release.xcconfig","buck-out/gen/submodules/libphonenumber/libphonenumber-Debug.xcconfig","buck-out/gen/submodules/libphonenumber/libphonenumber-Profile.xcconfig","buck-out/gen/submodules/libphonenumber/libphonenumber-Release.xcconfig","buck-out/gen/submodules/libtgvoip/libtgvoip-Debug.xcconfig","buck-out/gen/submodules/libtgvoip/libtgvoip-Profile.xcconfig","buck-out/gen/submodules/libtgvoip/libtgvoip-Release.xcconfig","buck-out/gen/submodules/lottie-ios/Lottie-Debug.xcconfig","buck-out/gen/submodules/lottie-ios/Lottie-Profile.xcconfig","buck-out/gen/submodules/lottie-ios/Lottie-Release.xcconfig","buck-out/gen/submodules/openssl/openssl-Debug.xcconfig","buck-out/gen/submodules/openssl/openssl-Profile.xcconfig","buck-out/gen/submodules/openssl/openssl-Release.xcconfig","buck-out/gen/submodules/rlottie/RLottieBinding-Debug.xcconfig","buck-out/gen/submodules/rlottie/RLottieBinding-Profile.xcconfig","buck-out/gen/submodules/rlottie/RLottieBinding-Release.xcconfig","buck-out/gen/submodules/sqlcipher/sqlcipher-Debug.xcconfig","buck-out/gen/submodules/sqlcipher/sqlcipher-Profile.xcconfig","buck-out/gen/submodules/sqlcipher/sqlcipher-Release.xcconfig","buck-out/gen/submodules/ton/ton-Debug.xcconfig","buck-out/gen/submodules/ton/ton-Profile.xcconfig","buck-out/gen/submodules/ton/ton-Release.xcconfig"],"copy-in-xcode":[]}
\ No newline at end of file
+{"required-targets":["//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_ac3_parser.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_adts_parser.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_avcodec.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_avdct.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_avfft.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_d3d11va.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_dirac.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_dv_profile.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_dxva2.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_jni.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_mediacodec.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_qsv.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_vaapi.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_vdpau.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_version.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_videotoolbox.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_vorbis_parser.h","//submodules/FFMpeg:ffmpeg_header_libavcodec_sub_xvmc.h","//submodules/FFMpeg:ffmpeg_header_libavformat_sub_avformat.h","//submodules/FFMpeg:ffmpeg_header_libavformat_sub_avio.h","//submodules/FFMpeg:ffmpeg_header_libavformat_sub_version.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_adler32.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_aes.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_aes_ctr.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_attributes.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_audio_fifo.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avassert.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avconfig.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avstring.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_avutil.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_base64.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_blowfish.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_bprint.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_bswap.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_buffer.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_camellia.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_cast5.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_channel_layout.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_common.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_cpu.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_crc.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_des.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_dict.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_display.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_downmix_info.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_encryption_info.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_error.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_eval.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_ffversion.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_fifo.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_file.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_frame.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hash.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hmac.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_cuda.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_d3d11va.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_drm.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_dxva2.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_mediacodec.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_qsv.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_vaapi.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_vdpau.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_hwcontext_videotoolbox.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_imgutils.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_intfloat.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_intreadwrite.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_lfg.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_log.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_lzo.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_macros.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_mastering_display_metadata.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_mathematics.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_md5.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_mem.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_motion_vector.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_murmur3.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_opt.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_parseutils.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_pixdesc.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_pixelutils.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_pixfmt.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_random_seed.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_rational.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_rc4.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_replaygain.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_ripemd.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_samplefmt.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_sha.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_sha512.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_spherical.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_stereo3d.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_tea.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_threadmessage.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_time.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_timecode.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_timestamp.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_tree.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_twofish.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_version.h","//submodules/FFMpeg:ffmpeg_header_libavutil_sub_xtea.h","//submodules/FFMpeg:ffmpeg_header_libswresample_sub_swresample.h","//submodules/FFMpeg:ffmpeg_header_libswresample_sub_version.h","//submodules/FFMpeg:libffmpeg_build","//submodules/Opus:opus_lib_file","//submodules/WebP:WebP_lib_file","//submodules/openssl:openssl_build_merged","//submodules/openssl:openssl_header_openssl_sub_aes.h","//submodules/openssl:openssl_header_openssl_sub_asn1.h","//submodules/openssl:openssl_header_openssl_sub_asn1_mac.h","//submodules/openssl:openssl_header_openssl_sub_asn1err.h","//submodules/openssl:openssl_header_openssl_sub_asn1t.h","//submodules/openssl:openssl_header_openssl_sub_async.h","//submodules/openssl:openssl_header_openssl_sub_asyncerr.h","//submodules/openssl:openssl_header_openssl_sub_bio.h","//submodules/openssl:openssl_header_openssl_sub_bioerr.h","//submodules/openssl:openssl_header_openssl_sub_blowfish.h","//submodules/openssl:openssl_header_openssl_sub_bn.h","//submodules/openssl:openssl_header_openssl_sub_bnerr.h","//submodules/openssl:openssl_header_openssl_sub_buffer.h","//submodules/openssl:openssl_header_openssl_sub_buffererr.h","//submodules/openssl:openssl_header_openssl_sub_camellia.h","//submodules/openssl:openssl_header_openssl_sub_cast.h","//submodules/openssl:openssl_header_openssl_sub_cmac.h","//submodules/openssl:openssl_header_openssl_sub_cms.h","//submodules/openssl:openssl_header_openssl_sub_cmserr.h","//submodules/openssl:openssl_header_openssl_sub_comp.h","//submodules/openssl:openssl_header_openssl_sub_comperr.h","//submodules/openssl:openssl_header_openssl_sub_conf.h","//submodules/openssl:openssl_header_openssl_sub_conf_api.h","//submodules/openssl:openssl_header_openssl_sub_conferr.h","//submodules/openssl:openssl_header_openssl_sub_crypto.h","//submodules/openssl:openssl_header_openssl_sub_cryptoerr.h","//submodules/openssl:openssl_header_openssl_sub_ct.h","//submodules/openssl:openssl_header_openssl_sub_cterr.h","//submodules/openssl:openssl_header_openssl_sub_des.h","//submodules/openssl:openssl_header_openssl_sub_dh.h","//submodules/openssl:openssl_header_openssl_sub_dherr.h","//submodules/openssl:openssl_header_openssl_sub_dsa.h","//submodules/openssl:openssl_header_openssl_sub_dsaerr.h","//submodules/openssl:openssl_header_openssl_sub_dtls1.h","//submodules/openssl:openssl_header_openssl_sub_e_os2.h","//submodules/openssl:openssl_header_openssl_sub_ebcdic.h","//submodules/openssl:openssl_header_openssl_sub_ec.h","//submodules/openssl:openssl_header_openssl_sub_ecdh.h","//submodules/openssl:openssl_header_openssl_sub_ecdsa.h","//submodules/openssl:openssl_header_openssl_sub_ecerr.h","//submodules/openssl:openssl_header_openssl_sub_engine.h","//submodules/openssl:openssl_header_openssl_sub_engineerr.h","//submodules/openssl:openssl_header_openssl_sub_err.h","//submodules/openssl:openssl_header_openssl_sub_evp.h","//submodules/openssl:openssl_header_openssl_sub_evperr.h","//submodules/openssl:openssl_header_openssl_sub_hmac.h","//submodules/openssl:openssl_header_openssl_sub_idea.h","//submodules/openssl:openssl_header_openssl_sub_kdf.h","//submodules/openssl:openssl_header_openssl_sub_kdferr.h","//submodules/openssl:openssl_header_openssl_sub_lhash.h","//submodules/openssl:openssl_header_openssl_sub_md2.h","//submodules/openssl:openssl_header_openssl_sub_md4.h","//submodules/openssl:openssl_header_openssl_sub_md5.h","//submodules/openssl:openssl_header_openssl_sub_mdc2.h","//submodules/openssl:openssl_header_openssl_sub_modes.h","//submodules/openssl:openssl_header_openssl_sub_obj_mac.h","//submodules/openssl:openssl_header_openssl_sub_objects.h","//submodules/openssl:openssl_header_openssl_sub_objectserr.h","//submodules/openssl:openssl_header_openssl_sub_ocsp.h","//submodules/openssl:openssl_header_openssl_sub_ocsperr.h","//submodules/openssl:openssl_header_openssl_sub_opensslconf.h","//submodules/openssl:openssl_header_openssl_sub_opensslv.h","//submodules/openssl:openssl_header_openssl_sub_ossl_typ.h","//submodules/openssl:openssl_header_openssl_sub_pem.h","//submodules/openssl:openssl_header_openssl_sub_pem2.h","//submodules/openssl:openssl_header_openssl_sub_pemerr.h","//submodules/openssl:openssl_header_openssl_sub_pkcs12.h","//submodules/openssl:openssl_header_openssl_sub_pkcs12err.h","//submodules/openssl:openssl_header_openssl_sub_pkcs7.h","//submodules/openssl:openssl_header_openssl_sub_pkcs7err.h","//submodules/openssl:openssl_header_openssl_sub_rand.h","//submodules/openssl:openssl_header_openssl_sub_rand_drbg.h","//submodules/openssl:openssl_header_openssl_sub_randerr.h","//submodules/openssl:openssl_header_openssl_sub_rc2.h","//submodules/openssl:openssl_header_openssl_sub_rc4.h","//submodules/openssl:openssl_header_openssl_sub_rc5.h","//submodules/openssl:openssl_header_openssl_sub_ripemd.h","//submodules/openssl:openssl_header_openssl_sub_rsa.h","//submodules/openssl:openssl_header_openssl_sub_rsaerr.h","//submodules/openssl:openssl_header_openssl_sub_safestack.h","//submodules/openssl:openssl_header_openssl_sub_seed.h","//submodules/openssl:openssl_header_openssl_sub_sha.h","//submodules/openssl:openssl_header_openssl_sub_srp.h","//submodules/openssl:openssl_header_openssl_sub_srtp.h","//submodules/openssl:openssl_header_openssl_sub_ssl.h","//submodules/openssl:openssl_header_openssl_sub_ssl2.h","//submodules/openssl:openssl_header_openssl_sub_ssl3.h","//submodules/openssl:openssl_header_openssl_sub_sslerr.h","//submodules/openssl:openssl_header_openssl_sub_stack.h","//submodules/openssl:openssl_header_openssl_sub_store.h","//submodules/openssl:openssl_header_openssl_sub_storeerr.h","//submodules/openssl:openssl_header_openssl_sub_symhacks.h","//submodules/openssl:openssl_header_openssl_sub_tls1.h","//submodules/openssl:openssl_header_openssl_sub_ts.h","//submodules/openssl:openssl_header_openssl_sub_tserr.h","//submodules/openssl:openssl_header_openssl_sub_txt_db.h","//submodules/openssl:openssl_header_openssl_sub_ui.h","//submodules/openssl:openssl_header_openssl_sub_uierr.h","//submodules/openssl:openssl_header_openssl_sub_whrlpool.h","//submodules/openssl:openssl_header_openssl_sub_x509.h","//submodules/openssl:openssl_header_openssl_sub_x509_vfy.h","//submodules/openssl:openssl_header_openssl_sub_x509err.h","//submodules/openssl:openssl_header_openssl_sub_x509v3.h","//submodules/openssl:openssl_header_openssl_sub_x509v3err.h","//submodules/ton:ton_build","//submodules/ton:ton_header_auto_sub_tl_sub_tonlib_api.h","//submodules/ton:ton_header_td_sub_utils_sub_SharedSlice.h","//submodules/ton:ton_header_td_sub_utils_sub_Slice-decl.h","//submodules/ton:ton_header_td_sub_utils_sub_Slice.h","//submodules/ton:ton_header_td_sub_utils_sub_check.h","//submodules/ton:ton_header_td_sub_utils_sub_common.h","//submodules/ton:ton_header_td_sub_utils_sub_config.h","//submodules/ton:ton_header_td_sub_utils_sub_int_types.h","//submodules/ton:ton_header_td_sub_utils_sub_port_sub_platform.h","//submodules/ton:ton_header_td_sub_utils_sub_unique_ptr.h","//submodules/ton:ton_header_tl_sub_TlObject.h","//submodules/ton:ton_header_tonlib_sub_Client.h","//submodules/ton:ton_header_tonlib_sub_tonlib_client_json.h","//submodules/ton:ton_header_tonlib_sub_tonlibjson_export.h"],"xcconfig-paths":["buck-out/gen/AppLibrary-Debug.xcconfig","buck-out/gen/AppLibrary-Profile.xcconfig","buck-out/gen/AppLibrary-Release.xcconfig","buck-out/gen/IntentsExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/IntentsExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/IntentsExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/NotificationContentExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/NotificationContentExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/NotificationContentExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/NotificationServiceExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/NotificationServiceExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/NotificationServiceExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/ShareExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/ShareExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/ShareExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/Telegram-Debug.xcconfig","buck-out/gen/Telegram-Profile.xcconfig","buck-out/gen/Telegram-Release.xcconfig","buck-out/gen/WatchApp#watchsimulator-i386-Debug.xcconfig","buck-out/gen/WatchApp#watchsimulator-i386-Profile.xcconfig","buck-out/gen/WatchApp#watchsimulator-i386-Release.xcconfig","buck-out/gen/WatchAppExtension#watchsimulator-i386-Debug.xcconfig","buck-out/gen/WatchAppExtension#watchsimulator-i386-Profile.xcconfig","buck-out/gen/WatchAppExtension#watchsimulator-i386-Release.xcconfig","buck-out/gen/WidgetExtension#iphonesimulator-x86_64-Debug.xcconfig","buck-out/gen/WidgetExtension#iphonesimulator-x86_64-Profile.xcconfig","buck-out/gen/WidgetExtension#iphonesimulator-x86_64-Release.xcconfig","buck-out/gen/submodules/AccountContext/AccountContext-Debug.xcconfig","buck-out/gen/submodules/AccountContext/AccountContext-Profile.xcconfig","buck-out/gen/submodules/AccountContext/AccountContext-Release.xcconfig","buck-out/gen/submodules/ActionSheetPeerItem/ActionSheetPeerItem-Debug.xcconfig","buck-out/gen/submodules/ActionSheetPeerItem/ActionSheetPeerItem-Profile.xcconfig","buck-out/gen/submodules/ActionSheetPeerItem/ActionSheetPeerItem-Release.xcconfig","buck-out/gen/submodules/ActivityIndicator/ActivityIndicator-Debug.xcconfig","buck-out/gen/submodules/ActivityIndicator/ActivityIndicator-Profile.xcconfig","buck-out/gen/submodules/ActivityIndicator/ActivityIndicator-Release.xcconfig","buck-out/gen/submodules/AlertUI/AlertUI-Debug.xcconfig","buck-out/gen/submodules/AlertUI/AlertUI-Profile.xcconfig","buck-out/gen/submodules/AlertUI/AlertUI-Release.xcconfig","buck-out/gen/submodules/AnimationUI/AnimationUI-Debug.xcconfig","buck-out/gen/submodules/AnimationUI/AnimationUI-Profile.xcconfig","buck-out/gen/submodules/AnimationUI/AnimationUI-Release.xcconfig","buck-out/gen/submodules/AppBundle/AppBundle-Debug.xcconfig","buck-out/gen/submodules/AppBundle/AppBundle-Profile.xcconfig","buck-out/gen/submodules/AppBundle/AppBundle-Release.xcconfig","buck-out/gen/submodules/AsyncDisplayKit/AsyncDisplayKit#shared-Debug.xcconfig","buck-out/gen/submodules/AsyncDisplayKit/AsyncDisplayKit#shared-Profile.xcconfig","buck-out/gen/submodules/AsyncDisplayKit/AsyncDisplayKit#shared-Release.xcconfig","buck-out/gen/submodules/AuthorizationUI/AuthorizationUI-Debug.xcconfig","buck-out/gen/submodules/AuthorizationUI/AuthorizationUI-Profile.xcconfig","buck-out/gen/submodules/AuthorizationUI/AuthorizationUI-Release.xcconfig","buck-out/gen/submodules/AvatarNode/AvatarNode-Debug.xcconfig","buck-out/gen/submodules/AvatarNode/AvatarNode-Profile.xcconfig","buck-out/gen/submodules/AvatarNode/AvatarNode-Release.xcconfig","buck-out/gen/submodules/BotPaymentsUI/BotPaymentsUI-Debug.xcconfig","buck-out/gen/submodules/BotPaymentsUI/BotPaymentsUI-Profile.xcconfig","buck-out/gen/submodules/BotPaymentsUI/BotPaymentsUI-Release.xcconfig","buck-out/gen/submodules/BuildConfig/BuildConfig-Debug.xcconfig","buck-out/gen/submodules/BuildConfig/BuildConfig-Profile.xcconfig","buck-out/gen/submodules/BuildConfig/BuildConfig-Release.xcconfig","buck-out/gen/submodules/CallListUI/CallListUI-Debug.xcconfig","buck-out/gen/submodules/CallListUI/CallListUI-Profile.xcconfig","buck-out/gen/submodules/CallListUI/CallListUI-Release.xcconfig","buck-out/gen/submodules/Camera/Camera-Debug.xcconfig","buck-out/gen/submodules/Camera/Camera-Profile.xcconfig","buck-out/gen/submodules/Camera/Camera-Release.xcconfig","buck-out/gen/submodules/ChatListSearchItemHeader/ChatListSearchItemHeader-Debug.xcconfig","buck-out/gen/submodules/ChatListSearchItemHeader/ChatListSearchItemHeader-Profile.xcconfig","buck-out/gen/submodules/ChatListSearchItemHeader/ChatListSearchItemHeader-Release.xcconfig","buck-out/gen/submodules/ChatListSearchItemNode/ChatListSearchItemNode-Debug.xcconfig","buck-out/gen/submodules/ChatListSearchItemNode/ChatListSearchItemNode-Profile.xcconfig","buck-out/gen/submodules/ChatListSearchItemNode/ChatListSearchItemNode-Release.xcconfig","buck-out/gen/submodules/ChatListSearchRecentPeersNode/ChatListSearchRecentPeersNode-Debug.xcconfig","buck-out/gen/submodules/ChatListSearchRecentPeersNode/ChatListSearchRecentPeersNode-Profile.xcconfig","buck-out/gen/submodules/ChatListSearchRecentPeersNode/ChatListSearchRecentPeersNode-Release.xcconfig","buck-out/gen/submodules/ChatListUI/ChatListUI-Debug.xcconfig","buck-out/gen/submodules/ChatListUI/ChatListUI-Profile.xcconfig","buck-out/gen/submodules/ChatListUI/ChatListUI-Release.xcconfig","buck-out/gen/submodules/ChatTitleActivityNode/ChatTitleActivityNode-Debug.xcconfig","buck-out/gen/submodules/ChatTitleActivityNode/ChatTitleActivityNode-Profile.xcconfig","buck-out/gen/submodules/ChatTitleActivityNode/ChatTitleActivityNode-Release.xcconfig","buck-out/gen/submodules/CheckNode/CheckNode-Debug.xcconfig","buck-out/gen/submodules/CheckNode/CheckNode-Profile.xcconfig","buck-out/gen/submodules/CheckNode/CheckNode-Release.xcconfig","buck-out/gen/submodules/ComposePollUI/ComposePollUI-Debug.xcconfig","buck-out/gen/submodules/ComposePollUI/ComposePollUI-Profile.xcconfig","buck-out/gen/submodules/ComposePollUI/ComposePollUI-Release.xcconfig","buck-out/gen/submodules/ContactListUI/ContactListUI-Debug.xcconfig","buck-out/gen/submodules/ContactListUI/ContactListUI-Profile.xcconfig","buck-out/gen/submodules/ContactListUI/ContactListUI-Release.xcconfig","buck-out/gen/submodules/ContactsPeerItem/ContactsPeerItem-Debug.xcconfig","buck-out/gen/submodules/ContactsPeerItem/ContactsPeerItem-Profile.xcconfig","buck-out/gen/submodules/ContactsPeerItem/ContactsPeerItem-Release.xcconfig","buck-out/gen/submodules/ContextUI/ContextUI-Debug.xcconfig","buck-out/gen/submodules/ContextUI/ContextUI-Profile.xcconfig","buck-out/gen/submodules/ContextUI/ContextUI-Release.xcconfig","buck-out/gen/submodules/CounterContollerTitleView/CounterContollerTitleView-Debug.xcconfig","buck-out/gen/submodules/CounterContollerTitleView/CounterContollerTitleView-Profile.xcconfig","buck-out/gen/submodules/CounterContollerTitleView/CounterContollerTitleView-Release.xcconfig","buck-out/gen/submodules/CountrySelectionUI/CountrySelectionUI-Debug.xcconfig","buck-out/gen/submodules/CountrySelectionUI/CountrySelectionUI-Profile.xcconfig","buck-out/gen/submodules/CountrySelectionUI/CountrySelectionUI-Release.xcconfig","buck-out/gen/submodules/Crc32/Crc32-Debug.xcconfig","buck-out/gen/submodules/Crc32/Crc32-Profile.xcconfig","buck-out/gen/submodules/Crc32/Crc32-Release.xcconfig","buck-out/gen/submodules/DateSelectionUI/DateSelectionUI-Debug.xcconfig","buck-out/gen/submodules/DateSelectionUI/DateSelectionUI-Profile.xcconfig","buck-out/gen/submodules/DateSelectionUI/DateSelectionUI-Release.xcconfig","buck-out/gen/submodules/DeleteChatPeerActionSheetItem/DeleteChatPeerActionSheetItem-Debug.xcconfig","buck-out/gen/submodules/DeleteChatPeerActionSheetItem/DeleteChatPeerActionSheetItem-Profile.xcconfig","buck-out/gen/submodules/DeleteChatPeerActionSheetItem/DeleteChatPeerActionSheetItem-Release.xcconfig","buck-out/gen/submodules/DeviceAccess/DeviceAccess-Debug.xcconfig","buck-out/gen/submodules/DeviceAccess/DeviceAccess-Profile.xcconfig","buck-out/gen/submodules/DeviceAccess/DeviceAccess-Release.xcconfig","buck-out/gen/submodules/DeviceLocationManager/DeviceLocationManager-Debug.xcconfig","buck-out/gen/submodules/DeviceLocationManager/DeviceLocationManager-Profile.xcconfig","buck-out/gen/submodules/DeviceLocationManager/DeviceLocationManager-Release.xcconfig","buck-out/gen/submodules/DeviceProximity/DeviceProximity-Debug.xcconfig","buck-out/gen/submodules/DeviceProximity/DeviceProximity-Profile.xcconfig","buck-out/gen/submodules/DeviceProximity/DeviceProximity-Release.xcconfig","buck-out/gen/submodules/DirectionalPanGesture/DirectionalPanGesture-Debug.xcconfig","buck-out/gen/submodules/DirectionalPanGesture/DirectionalPanGesture-Profile.xcconfig","buck-out/gen/submodules/DirectionalPanGesture/DirectionalPanGesture-Release.xcconfig","buck-out/gen/submodules/Display/Display#shared-Debug.xcconfig","buck-out/gen/submodules/Display/Display#shared-Profile.xcconfig","buck-out/gen/submodules/Display/Display#shared-Release.xcconfig","buck-out/gen/submodules/Emoji/Emoji-Debug.xcconfig","buck-out/gen/submodules/Emoji/Emoji-Profile.xcconfig","buck-out/gen/submodules/Emoji/Emoji-Release.xcconfig","buck-out/gen/submodules/EncryptionKeyVisualization/EncryptionKeyVisualization-Debug.xcconfig","buck-out/gen/submodules/EncryptionKeyVisualization/EncryptionKeyVisualization-Profile.xcconfig","buck-out/gen/submodules/EncryptionKeyVisualization/EncryptionKeyVisualization-Release.xcconfig","buck-out/gen/submodules/FFMpeg/FFMpeg-Debug.xcconfig","buck-out/gen/submodules/FFMpeg/FFMpeg-Profile.xcconfig","buck-out/gen/submodules/FFMpeg/FFMpeg-Release.xcconfig","buck-out/gen/submodules/FFMpeg/libffmpeg-Debug.xcconfig","buck-out/gen/submodules/FFMpeg/libffmpeg-Profile.xcconfig","buck-out/gen/submodules/FFMpeg/libffmpeg-Release.xcconfig","buck-out/gen/submodules/GZip/GZip-Debug.xcconfig","buck-out/gen/submodules/GZip/GZip-Profile.xcconfig","buck-out/gen/submodules/GZip/GZip-Release.xcconfig","buck-out/gen/submodules/GalleryUI/GalleryUI-Debug.xcconfig","buck-out/gen/submodules/GalleryUI/GalleryUI-Profile.xcconfig","buck-out/gen/submodules/GalleryUI/GalleryUI-Release.xcconfig","buck-out/gen/submodules/GameUI/GameUI-Debug.xcconfig","buck-out/gen/submodules/GameUI/GameUI-Profile.xcconfig","buck-out/gen/submodules/GameUI/GameUI-Release.xcconfig","buck-out/gen/submodules/Geocoding/Geocoding-Debug.xcconfig","buck-out/gen/submodules/Geocoding/Geocoding-Profile.xcconfig","buck-out/gen/submodules/Geocoding/Geocoding-Release.xcconfig","buck-out/gen/submodules/GlassButtonNode/GlassButtonNode-Debug.xcconfig","buck-out/gen/submodules/GlassButtonNode/GlassButtonNode-Profile.xcconfig","buck-out/gen/submodules/GlassButtonNode/GlassButtonNode-Release.xcconfig","buck-out/gen/submodules/GridMessageSelectionNode/GridMessageSelectionNode-Debug.xcconfig","buck-out/gen/submodules/GridMessageSelectionNode/GridMessageSelectionNode-Profile.xcconfig","buck-out/gen/submodules/GridMessageSelectionNode/GridMessageSelectionNode-Release.xcconfig","buck-out/gen/submodules/HashtagSearchUI/HashtagSearchUI-Debug.xcconfig","buck-out/gen/submodules/HashtagSearchUI/HashtagSearchUI-Profile.xcconfig","buck-out/gen/submodules/HashtagSearchUI/HashtagSearchUI-Release.xcconfig","buck-out/gen/submodules/HexColor/HexColor-Debug.xcconfig","buck-out/gen/submodules/HexColor/HexColor-Profile.xcconfig","buck-out/gen/submodules/HexColor/HexColor-Release.xcconfig","buck-out/gen/submodules/HockeySDK-iOS/HockeySDK-Debug.xcconfig","buck-out/gen/submodules/HockeySDK-iOS/HockeySDK-Profile.xcconfig","buck-out/gen/submodules/HockeySDK-iOS/HockeySDK-Release.xcconfig","buck-out/gen/submodules/HorizontalPeerItem/HorizontalPeerItem-Debug.xcconfig","buck-out/gen/submodules/HorizontalPeerItem/HorizontalPeerItem-Profile.xcconfig","buck-out/gen/submodules/HorizontalPeerItem/HorizontalPeerItem-Release.xcconfig","buck-out/gen/submodules/ImageBlur/ImageBlur-Debug.xcconfig","buck-out/gen/submodules/ImageBlur/ImageBlur-Profile.xcconfig","buck-out/gen/submodules/ImageBlur/ImageBlur-Release.xcconfig","buck-out/gen/submodules/ImageCompression/ImageCompression-Debug.xcconfig","buck-out/gen/submodules/ImageCompression/ImageCompression-Profile.xcconfig","buck-out/gen/submodules/ImageCompression/ImageCompression-Release.xcconfig","buck-out/gen/submodules/ImageTransparency/ImageTransparency-Debug.xcconfig","buck-out/gen/submodules/ImageTransparency/ImageTransparency-Profile.xcconfig","buck-out/gen/submodules/ImageTransparency/ImageTransparency-Release.xcconfig","buck-out/gen/submodules/InstantPageCache/InstantPageCache-Debug.xcconfig","buck-out/gen/submodules/InstantPageCache/InstantPageCache-Profile.xcconfig","buck-out/gen/submodules/InstantPageCache/InstantPageCache-Release.xcconfig","buck-out/gen/submodules/InstantPageUI/InstantPageUI-Debug.xcconfig","buck-out/gen/submodules/InstantPageUI/InstantPageUI-Profile.xcconfig","buck-out/gen/submodules/InstantPageUI/InstantPageUI-Release.xcconfig","buck-out/gen/submodules/ItemListAddressItem/ItemListAddressItem-Debug.xcconfig","buck-out/gen/submodules/ItemListAddressItem/ItemListAddressItem-Profile.xcconfig","buck-out/gen/submodules/ItemListAddressItem/ItemListAddressItem-Release.xcconfig","buck-out/gen/submodules/ItemListAvatarAndNameInfoItem/ItemListAvatarAndNameInfoItem-Debug.xcconfig","buck-out/gen/submodules/ItemListAvatarAndNameInfoItem/ItemListAvatarAndNameInfoItem-Profile.xcconfig","buck-out/gen/submodules/ItemListAvatarAndNameInfoItem/ItemListAvatarAndNameInfoItem-Release.xcconfig","buck-out/gen/submodules/ItemListPeerActionItem/ItemListPeerActionItem-Debug.xcconfig","buck-out/gen/submodules/ItemListPeerActionItem/ItemListPeerActionItem-Profile.xcconfig","buck-out/gen/submodules/ItemListPeerActionItem/ItemListPeerActionItem-Release.xcconfig","buck-out/gen/submodules/ItemListPeerItem/ItemListPeerItem-Debug.xcconfig","buck-out/gen/submodules/ItemListPeerItem/ItemListPeerItem-Profile.xcconfig","buck-out/gen/submodules/ItemListPeerItem/ItemListPeerItem-Release.xcconfig","buck-out/gen/submodules/ItemListStickerPackItem/ItemListStickerPackItem-Debug.xcconfig","buck-out/gen/submodules/ItemListStickerPackItem/ItemListStickerPackItem-Profile.xcconfig","buck-out/gen/submodules/ItemListStickerPackItem/ItemListStickerPackItem-Release.xcconfig","buck-out/gen/submodules/ItemListUI/ItemListUI-Debug.xcconfig","buck-out/gen/submodules/ItemListUI/ItemListUI-Profile.xcconfig","buck-out/gen/submodules/ItemListUI/ItemListUI-Release.xcconfig","buck-out/gen/submodules/JoinLinkPreviewUI/JoinLinkPreviewUI-Debug.xcconfig","buck-out/gen/submodules/JoinLinkPreviewUI/JoinLinkPreviewUI-Profile.xcconfig","buck-out/gen/submodules/JoinLinkPreviewUI/JoinLinkPreviewUI-Release.xcconfig","buck-out/gen/submodules/LanguageLinkPreviewUI/LanguageLinkPreviewUI-Debug.xcconfig","buck-out/gen/submodules/LanguageLinkPreviewUI/LanguageLinkPreviewUI-Profile.xcconfig","buck-out/gen/submodules/LanguageLinkPreviewUI/LanguageLinkPreviewUI-Release.xcconfig","buck-out/gen/submodules/LanguageSuggestionUI/LanguageSuggestionUI-Debug.xcconfig","buck-out/gen/submodules/LanguageSuggestionUI/LanguageSuggestionUI-Profile.xcconfig","buck-out/gen/submodules/LanguageSuggestionUI/LanguageSuggestionUI-Release.xcconfig","buck-out/gen/submodules/LegacyComponents/LegacyComponents-Debug.xcconfig","buck-out/gen/submodules/LegacyComponents/LegacyComponents-Profile.xcconfig","buck-out/gen/submodules/LegacyComponents/LegacyComponents-Release.xcconfig","buck-out/gen/submodules/LegacyDataImport/LegacyDataImport-Debug.xcconfig","buck-out/gen/submodules/LegacyDataImport/LegacyDataImport-Profile.xcconfig","buck-out/gen/submodules/LegacyDataImport/LegacyDataImport-Release.xcconfig","buck-out/gen/submodules/LegacyMediaPickerUI/LegacyMediaPickerUI-Debug.xcconfig","buck-out/gen/submodules/LegacyMediaPickerUI/LegacyMediaPickerUI-Profile.xcconfig","buck-out/gen/submodules/LegacyMediaPickerUI/LegacyMediaPickerUI-Release.xcconfig","buck-out/gen/submodules/LegacyUI/LegacyUI-Debug.xcconfig","buck-out/gen/submodules/LegacyUI/LegacyUI-Profile.xcconfig","buck-out/gen/submodules/LegacyUI/LegacyUI-Release.xcconfig","buck-out/gen/submodules/LightweightAccountData/LightweightAccountData-Debug.xcconfig","buck-out/gen/submodules/LightweightAccountData/LightweightAccountData-Profile.xcconfig","buck-out/gen/submodules/LightweightAccountData/LightweightAccountData-Release.xcconfig","buck-out/gen/submodules/ListSectionHeaderNode/ListSectionHeaderNode-Debug.xcconfig","buck-out/gen/submodules/ListSectionHeaderNode/ListSectionHeaderNode-Profile.xcconfig","buck-out/gen/submodules/ListSectionHeaderNode/ListSectionHeaderNode-Release.xcconfig","buck-out/gen/submodules/LiveLocationManager/LiveLocationManager-Debug.xcconfig","buck-out/gen/submodules/LiveLocationManager/LiveLocationManager-Profile.xcconfig","buck-out/gen/submodules/LiveLocationManager/LiveLocationManager-Release.xcconfig","buck-out/gen/submodules/LiveLocationPositionNode/LiveLocationPositionNode-Debug.xcconfig","buck-out/gen/submodules/LiveLocationPositionNode/LiveLocationPositionNode-Profile.xcconfig","buck-out/gen/submodules/LiveLocationPositionNode/LiveLocationPositionNode-Release.xcconfig","buck-out/gen/submodules/LiveLocationTimerNode/LiveLocationTimerNode-Debug.xcconfig","buck-out/gen/submodules/LiveLocationTimerNode/LiveLocationTimerNode-Profile.xcconfig","buck-out/gen/submodules/LiveLocationTimerNode/LiveLocationTimerNode-Release.xcconfig","buck-out/gen/submodules/LocalAuth/LocalAuth-Debug.xcconfig","buck-out/gen/submodules/LocalAuth/LocalAuth-Profile.xcconfig","buck-out/gen/submodules/LocalAuth/LocalAuth-Release.xcconfig","buck-out/gen/submodules/LocalMediaResources/LocalMediaResources-Debug.xcconfig","buck-out/gen/submodules/LocalMediaResources/LocalMediaResources-Profile.xcconfig","buck-out/gen/submodules/LocalMediaResources/LocalMediaResources-Release.xcconfig","buck-out/gen/submodules/LocalizedPeerData/LocalizedPeerData-Debug.xcconfig","buck-out/gen/submodules/LocalizedPeerData/LocalizedPeerData-Profile.xcconfig","buck-out/gen/submodules/LocalizedPeerData/LocalizedPeerData-Release.xcconfig","buck-out/gen/submodules/LocationUI/LocationUI-Debug.xcconfig","buck-out/gen/submodules/LocationUI/LocationUI-Profile.xcconfig","buck-out/gen/submodules/LocationUI/LocationUI-Release.xcconfig","buck-out/gen/submodules/MapResourceToAvatarSizes/MapResourceToAvatarSizes-Debug.xcconfig","buck-out/gen/submodules/MapResourceToAvatarSizes/MapResourceToAvatarSizes-Profile.xcconfig","buck-out/gen/submodules/MapResourceToAvatarSizes/MapResourceToAvatarSizes-Release.xcconfig","buck-out/gen/submodules/MediaPlayer/UniversalMediaPlayer-Debug.xcconfig","buck-out/gen/submodules/MediaPlayer/UniversalMediaPlayer-Profile.xcconfig","buck-out/gen/submodules/MediaPlayer/UniversalMediaPlayer-Release.xcconfig","buck-out/gen/submodules/MediaResources/MediaResources-Debug.xcconfig","buck-out/gen/submodules/MediaResources/MediaResources-Profile.xcconfig","buck-out/gen/submodules/MediaResources/MediaResources-Release.xcconfig","buck-out/gen/submodules/MergeLists/MergeLists-Debug.xcconfig","buck-out/gen/submodules/MergeLists/MergeLists-Profile.xcconfig","buck-out/gen/submodules/MergeLists/MergeLists-Release.xcconfig","buck-out/gen/submodules/MessageReactionListUI/MessageReactionListUI-Debug.xcconfig","buck-out/gen/submodules/MessageReactionListUI/MessageReactionListUI-Profile.xcconfig","buck-out/gen/submodules/MessageReactionListUI/MessageReactionListUI-Release.xcconfig","buck-out/gen/submodules/MimeTypes/MimeTypes-Debug.xcconfig","buck-out/gen/submodules/MimeTypes/MimeTypes-Profile.xcconfig","buck-out/gen/submodules/MimeTypes/MimeTypes-Release.xcconfig","buck-out/gen/submodules/MosaicLayout/MosaicLayout-Debug.xcconfig","buck-out/gen/submodules/MosaicLayout/MosaicLayout-Profile.xcconfig","buck-out/gen/submodules/MosaicLayout/MosaicLayout-Release.xcconfig","buck-out/gen/submodules/MtProtoKit/MtProtoKit#shared-Debug.xcconfig","buck-out/gen/submodules/MtProtoKit/MtProtoKit#shared-Profile.xcconfig","buck-out/gen/submodules/MtProtoKit/MtProtoKit#shared-Release.xcconfig","buck-out/gen/submodules/MusicAlbumArtResources/MusicAlbumArtResources-Debug.xcconfig","buck-out/gen/submodules/MusicAlbumArtResources/MusicAlbumArtResources-Profile.xcconfig","buck-out/gen/submodules/MusicAlbumArtResources/MusicAlbumArtResources-Release.xcconfig","buck-out/gen/submodules/NotificationMuteSettingsUI/NotificationMuteSettingsUI-Debug.xcconfig","buck-out/gen/submodules/NotificationMuteSettingsUI/NotificationMuteSettingsUI-Profile.xcconfig","buck-out/gen/submodules/NotificationMuteSettingsUI/NotificationMuteSettingsUI-Release.xcconfig","buck-out/gen/submodules/NotificationSoundSelectionUI/NotificationSoundSelectionUI-Debug.xcconfig","buck-out/gen/submodules/NotificationSoundSelectionUI/NotificationSoundSelectionUI-Profile.xcconfig","buck-out/gen/submodules/NotificationSoundSelectionUI/NotificationSoundSelectionUI-Release.xcconfig","buck-out/gen/submodules/OpenInExternalAppUI/OpenInExternalAppUI-Debug.xcconfig","buck-out/gen/submodules/OpenInExternalAppUI/OpenInExternalAppUI-Profile.xcconfig","buck-out/gen/submodules/OpenInExternalAppUI/OpenInExternalAppUI-Release.xcconfig","buck-out/gen/submodules/Opus/opus-Debug.xcconfig","buck-out/gen/submodules/Opus/opus-Profile.xcconfig","buck-out/gen/submodules/Opus/opus-Release.xcconfig","buck-out/gen/submodules/Opus/opus_lib-Debug.xcconfig","buck-out/gen/submodules/Opus/opus_lib-Profile.xcconfig","buck-out/gen/submodules/Opus/opus_lib-Release.xcconfig","buck-out/gen/submodules/OpusBinding/OpusBinding-Debug.xcconfig","buck-out/gen/submodules/OpusBinding/OpusBinding-Profile.xcconfig","buck-out/gen/submodules/OpusBinding/OpusBinding-Release.xcconfig","buck-out/gen/submodules/OverlayStatusController/OverlayStatusController-Debug.xcconfig","buck-out/gen/submodules/OverlayStatusController/OverlayStatusController-Profile.xcconfig","buck-out/gen/submodules/OverlayStatusController/OverlayStatusController-Release.xcconfig","buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Debug.xcconfig","buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Profile.xcconfig","buck-out/gen/submodules/PasscodeInputFieldNode/PasscodeInputFieldNode-Release.xcconfig","buck-out/gen/submodules/PasscodeUI/PasscodeUI-Debug.xcconfig","buck-out/gen/submodules/PasscodeUI/PasscodeUI-Profile.xcconfig","buck-out/gen/submodules/PasscodeUI/PasscodeUI-Release.xcconfig","buck-out/gen/submodules/PassportUI/PassportUI-Debug.xcconfig","buck-out/gen/submodules/PassportUI/PassportUI-Profile.xcconfig","buck-out/gen/submodules/PassportUI/PassportUI-Release.xcconfig","buck-out/gen/submodules/PasswordSetupUI/PasswordSetupUI-Debug.xcconfig","buck-out/gen/submodules/PasswordSetupUI/PasswordSetupUI-Profile.xcconfig","buck-out/gen/submodules/PasswordSetupUI/PasswordSetupUI-Release.xcconfig","buck-out/gen/submodules/Pdf/Pdf-Debug.xcconfig","buck-out/gen/submodules/Pdf/Pdf-Profile.xcconfig","buck-out/gen/submodules/Pdf/Pdf-Release.xcconfig","buck-out/gen/submodules/PeerAvatarGalleryUI/PeerAvatarGalleryUI-Debug.xcconfig","buck-out/gen/submodules/PeerAvatarGalleryUI/PeerAvatarGalleryUI-Profile.xcconfig","buck-out/gen/submodules/PeerAvatarGalleryUI/PeerAvatarGalleryUI-Release.xcconfig","buck-out/gen/submodules/PeerInfoUI/PeerInfoUI-Debug.xcconfig","buck-out/gen/submodules/PeerInfoUI/PeerInfoUI-Profile.xcconfig","buck-out/gen/submodules/PeerInfoUI/PeerInfoUI-Release.xcconfig","buck-out/gen/submodules/PeerOnlineMarkerNode/PeerOnlineMarkerNode-Debug.xcconfig","buck-out/gen/submodules/PeerOnlineMarkerNode/PeerOnlineMarkerNode-Profile.xcconfig","buck-out/gen/submodules/PeerOnlineMarkerNode/PeerOnlineMarkerNode-Release.xcconfig","buck-out/gen/submodules/PeerPresenceStatusManager/PeerPresenceStatusManager-Debug.xcconfig","buck-out/gen/submodules/PeerPresenceStatusManager/PeerPresenceStatusManager-Profile.xcconfig","buck-out/gen/submodules/PeerPresenceStatusManager/PeerPresenceStatusManager-Release.xcconfig","buck-out/gen/submodules/PeersNearbyIconNode/PeersNearbyIconNode-Debug.xcconfig","buck-out/gen/submodules/PeersNearbyIconNode/PeersNearbyIconNode-Profile.xcconfig","buck-out/gen/submodules/PeersNearbyIconNode/PeersNearbyIconNode-Release.xcconfig","buck-out/gen/submodules/PeersNearbyUI/PeersNearbyUI-Debug.xcconfig","buck-out/gen/submodules/PeersNearbyUI/PeersNearbyUI-Profile.xcconfig","buck-out/gen/submodules/PeersNearbyUI/PeersNearbyUI-Release.xcconfig","buck-out/gen/submodules/PersistentStringHash/PersistentStringHash-Debug.xcconfig","buck-out/gen/submodules/PersistentStringHash/PersistentStringHash-Profile.xcconfig","buck-out/gen/submodules/PersistentStringHash/PersistentStringHash-Release.xcconfig","buck-out/gen/submodules/PhoneInputNode/PhoneInputNode-Debug.xcconfig","buck-out/gen/submodules/PhoneInputNode/PhoneInputNode-Profile.xcconfig","buck-out/gen/submodules/PhoneInputNode/PhoneInputNode-Release.xcconfig","buck-out/gen/submodules/PhotoResources/PhotoResources-Debug.xcconfig","buck-out/gen/submodules/PhotoResources/PhotoResources-Profile.xcconfig","buck-out/gen/submodules/PhotoResources/PhotoResources-Release.xcconfig","buck-out/gen/submodules/PlatformRestrictionMatching/PlatformRestrictionMatching-Debug.xcconfig","buck-out/gen/submodules/PlatformRestrictionMatching/PlatformRestrictionMatching-Profile.xcconfig","buck-out/gen/submodules/PlatformRestrictionMatching/PlatformRestrictionMatching-Release.xcconfig","buck-out/gen/submodules/Postbox/Postbox#shared-Debug.xcconfig","buck-out/gen/submodules/Postbox/Postbox#shared-Profile.xcconfig","buck-out/gen/submodules/Postbox/Postbox#shared-Release.xcconfig","buck-out/gen/submodules/ProgressNavigationButtonNode/ProgressNavigationButtonNode-Debug.xcconfig","buck-out/gen/submodules/ProgressNavigationButtonNode/ProgressNavigationButtonNode-Profile.xcconfig","buck-out/gen/submodules/ProgressNavigationButtonNode/ProgressNavigationButtonNode-Release.xcconfig","buck-out/gen/submodules/QrCode/QrCode-Debug.xcconfig","buck-out/gen/submodules/QrCode/QrCode-Profile.xcconfig","buck-out/gen/submodules/QrCode/QrCode-Release.xcconfig","buck-out/gen/submodules/RMIntro/RMIntro-Debug.xcconfig","buck-out/gen/submodules/RMIntro/RMIntro-Profile.xcconfig","buck-out/gen/submodules/RMIntro/RMIntro-Release.xcconfig","buck-out/gen/submodules/RadialStatusNode/RadialStatusNode-Debug.xcconfig","buck-out/gen/submodules/RadialStatusNode/RadialStatusNode-Profile.xcconfig","buck-out/gen/submodules/RadialStatusNode/RadialStatusNode-Release.xcconfig","buck-out/gen/submodules/RaiseToListen/RaiseToListen-Debug.xcconfig","buck-out/gen/submodules/RaiseToListen/RaiseToListen-Profile.xcconfig","buck-out/gen/submodules/RaiseToListen/RaiseToListen-Release.xcconfig","buck-out/gen/submodules/ReactionSelectionNode/ReactionSelectionNode-Debug.xcconfig","buck-out/gen/submodules/ReactionSelectionNode/ReactionSelectionNode-Profile.xcconfig","buck-out/gen/submodules/ReactionSelectionNode/ReactionSelectionNode-Release.xcconfig","buck-out/gen/submodules/SSignalKit/SSignalKit/SSignalKit-Debug.xcconfig","buck-out/gen/submodules/SSignalKit/SSignalKit/SSignalKit-Profile.xcconfig","buck-out/gen/submodules/SSignalKit/SSignalKit/SSignalKit-Release.xcconfig","buck-out/gen/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit#shared-Debug.xcconfig","buck-out/gen/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit#shared-Profile.xcconfig","buck-out/gen/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit#shared-Release.xcconfig","buck-out/gen/submodules/SaveToCameraRoll/SaveToCameraRoll-Debug.xcconfig","buck-out/gen/submodules/SaveToCameraRoll/SaveToCameraRoll-Profile.xcconfig","buck-out/gen/submodules/SaveToCameraRoll/SaveToCameraRoll-Release.xcconfig","buck-out/gen/submodules/ScreenCaptureDetection/ScreenCaptureDetection-Debug.xcconfig","buck-out/gen/submodules/ScreenCaptureDetection/ScreenCaptureDetection-Profile.xcconfig","buck-out/gen/submodules/ScreenCaptureDetection/ScreenCaptureDetection-Release.xcconfig","buck-out/gen/submodules/SearchBarNode/SearchBarNode-Debug.xcconfig","buck-out/gen/submodules/SearchBarNode/SearchBarNode-Profile.xcconfig","buck-out/gen/submodules/SearchBarNode/SearchBarNode-Release.xcconfig","buck-out/gen/submodules/SearchUI/SearchUI-Debug.xcconfig","buck-out/gen/submodules/SearchUI/SearchUI-Profile.xcconfig","buck-out/gen/submodules/SearchUI/SearchUI-Release.xcconfig","buck-out/gen/submodules/SegmentedControlNode/SegmentedControlNode-Debug.xcconfig","buck-out/gen/submodules/SegmentedControlNode/SegmentedControlNode-Profile.xcconfig","buck-out/gen/submodules/SegmentedControlNode/SegmentedControlNode-Release.xcconfig","buck-out/gen/submodules/SelectablePeerNode/SelectablePeerNode-Debug.xcconfig","buck-out/gen/submodules/SelectablePeerNode/SelectablePeerNode-Profile.xcconfig","buck-out/gen/submodules/SelectablePeerNode/SelectablePeerNode-Release.xcconfig","buck-out/gen/submodules/SettingsUI/SettingsUI-Debug.xcconfig","buck-out/gen/submodules/SettingsUI/SettingsUI-Profile.xcconfig","buck-out/gen/submodules/SettingsUI/SettingsUI-Release.xcconfig","buck-out/gen/submodules/ShareController/ShareController-Debug.xcconfig","buck-out/gen/submodules/ShareController/ShareController-Profile.xcconfig","buck-out/gen/submodules/ShareController/ShareController-Release.xcconfig","buck-out/gen/submodules/ShareItems/ShareItems-Debug.xcconfig","buck-out/gen/submodules/ShareItems/ShareItems-Profile.xcconfig","buck-out/gen/submodules/ShareItems/ShareItems-Release.xcconfig","buck-out/gen/submodules/SinglePhoneInputNode/SinglePhoneInputNode-Debug.xcconfig","buck-out/gen/submodules/SinglePhoneInputNode/SinglePhoneInputNode-Profile.xcconfig","buck-out/gen/submodules/SinglePhoneInputNode/SinglePhoneInputNode-Release.xcconfig","buck-out/gen/submodules/SolidRoundedButtonNode/SolidRoundedButtonNode-Debug.xcconfig","buck-out/gen/submodules/SolidRoundedButtonNode/SolidRoundedButtonNode-Profile.xcconfig","buck-out/gen/submodules/SolidRoundedButtonNode/SolidRoundedButtonNode-Release.xcconfig","buck-out/gen/submodules/StickerPackPreviewUI/StickerPackPreviewUI-Debug.xcconfig","buck-out/gen/submodules/StickerPackPreviewUI/StickerPackPreviewUI-Profile.xcconfig","buck-out/gen/submodules/StickerPackPreviewUI/StickerPackPreviewUI-Release.xcconfig","buck-out/gen/submodules/StickerResources/StickerResources-Debug.xcconfig","buck-out/gen/submodules/StickerResources/StickerResources-Profile.xcconfig","buck-out/gen/submodules/StickerResources/StickerResources-Release.xcconfig","buck-out/gen/submodules/Stripe/Stripe-Debug.xcconfig","buck-out/gen/submodules/Stripe/Stripe-Profile.xcconfig","buck-out/gen/submodules/Stripe/Stripe-Release.xcconfig","buck-out/gen/submodules/SwipeToDismissGesture/SwipeToDismissGesture-Debug.xcconfig","buck-out/gen/submodules/SwipeToDismissGesture/SwipeToDismissGesture-Profile.xcconfig","buck-out/gen/submodules/SwipeToDismissGesture/SwipeToDismissGesture-Release.xcconfig","buck-out/gen/submodules/SwitchNode/SwitchNode-Debug.xcconfig","buck-out/gen/submodules/SwitchNode/SwitchNode-Profile.xcconfig","buck-out/gen/submodules/SwitchNode/SwitchNode-Release.xcconfig","buck-out/gen/submodules/TelegramApi/TelegramApi-Debug.xcconfig","buck-out/gen/submodules/TelegramApi/TelegramApi-Profile.xcconfig","buck-out/gen/submodules/TelegramApi/TelegramApi-Release.xcconfig","buck-out/gen/submodules/TelegramAudio/TelegramAudio-Debug.xcconfig","buck-out/gen/submodules/TelegramAudio/TelegramAudio-Profile.xcconfig","buck-out/gen/submodules/TelegramAudio/TelegramAudio-Release.xcconfig","buck-out/gen/submodules/TelegramBaseController/TelegramBaseController-Debug.xcconfig","buck-out/gen/submodules/TelegramBaseController/TelegramBaseController-Profile.xcconfig","buck-out/gen/submodules/TelegramBaseController/TelegramBaseController-Release.xcconfig","buck-out/gen/submodules/TelegramCallsUI/TelegramCallsUI-Debug.xcconfig","buck-out/gen/submodules/TelegramCallsUI/TelegramCallsUI-Profile.xcconfig","buck-out/gen/submodules/TelegramCallsUI/TelegramCallsUI-Release.xcconfig","buck-out/gen/submodules/TelegramCore/TelegramCore#shared-Debug.xcconfig","buck-out/gen/submodules/TelegramCore/TelegramCore#shared-Profile.xcconfig","buck-out/gen/submodules/TelegramCore/TelegramCore#shared-Release.xcconfig","buck-out/gen/submodules/TelegramNotices/TelegramNotices-Debug.xcconfig","buck-out/gen/submodules/TelegramNotices/TelegramNotices-Profile.xcconfig","buck-out/gen/submodules/TelegramNotices/TelegramNotices-Release.xcconfig","buck-out/gen/submodules/TelegramPermissions/TelegramPermissions-Debug.xcconfig","buck-out/gen/submodules/TelegramPermissions/TelegramPermissions-Profile.xcconfig","buck-out/gen/submodules/TelegramPermissions/TelegramPermissions-Release.xcconfig","buck-out/gen/submodules/TelegramPermissionsUI/TelegramPermissionsUI-Debug.xcconfig","buck-out/gen/submodules/TelegramPermissionsUI/TelegramPermissionsUI-Profile.xcconfig","buck-out/gen/submodules/TelegramPermissionsUI/TelegramPermissionsUI-Release.xcconfig","buck-out/gen/submodules/TelegramPresentationData/TelegramPresentationData-Debug.xcconfig","buck-out/gen/submodules/TelegramPresentationData/TelegramPresentationData-Profile.xcconfig","buck-out/gen/submodules/TelegramPresentationData/TelegramPresentationData-Release.xcconfig","buck-out/gen/submodules/TelegramStringFormatting/TelegramStringFormatting-Debug.xcconfig","buck-out/gen/submodules/TelegramStringFormatting/TelegramStringFormatting-Profile.xcconfig","buck-out/gen/submodules/TelegramStringFormatting/TelegramStringFormatting-Release.xcconfig","buck-out/gen/submodules/TelegramUI/TelegramUI#shared-Debug.xcconfig","buck-out/gen/submodules/TelegramUI/TelegramUI#shared-Profile.xcconfig","buck-out/gen/submodules/TelegramUI/TelegramUI#shared-Release.xcconfig","buck-out/gen/submodules/TelegramUIPreferences/TelegramUIPreferences-Debug.xcconfig","buck-out/gen/submodules/TelegramUIPreferences/TelegramUIPreferences-Profile.xcconfig","buck-out/gen/submodules/TelegramUIPreferences/TelegramUIPreferences-Release.xcconfig","buck-out/gen/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent-Debug.xcconfig","buck-out/gen/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent-Profile.xcconfig","buck-out/gen/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent-Release.xcconfig","buck-out/gen/submodules/TelegramUpdateUI/TelegramUpdateUI-Debug.xcconfig","buck-out/gen/submodules/TelegramUpdateUI/TelegramUpdateUI-Profile.xcconfig","buck-out/gen/submodules/TelegramUpdateUI/TelegramUpdateUI-Release.xcconfig","buck-out/gen/submodules/TelegramVoip/TelegramVoip-Debug.xcconfig","buck-out/gen/submodules/TelegramVoip/TelegramVoip-Profile.xcconfig","buck-out/gen/submodules/TelegramVoip/TelegramVoip-Release.xcconfig","buck-out/gen/submodules/TemporaryCachedPeerDataManager/TemporaryCachedPeerDataManager-Debug.xcconfig","buck-out/gen/submodules/TemporaryCachedPeerDataManager/TemporaryCachedPeerDataManager-Profile.xcconfig","buck-out/gen/submodules/TemporaryCachedPeerDataManager/TemporaryCachedPeerDataManager-Release.xcconfig","buck-out/gen/submodules/TextFormat/TextFormat-Debug.xcconfig","buck-out/gen/submodules/TextFormat/TextFormat-Profile.xcconfig","buck-out/gen/submodules/TextFormat/TextFormat-Release.xcconfig","buck-out/gen/submodules/TextSelectionNode/TextSelectionNode-Debug.xcconfig","buck-out/gen/submodules/TextSelectionNode/TextSelectionNode-Profile.xcconfig","buck-out/gen/submodules/TextSelectionNode/TextSelectionNode-Release.xcconfig","buck-out/gen/submodules/TinyThumbnail/TinyThumbnail-Debug.xcconfig","buck-out/gen/submodules/TinyThumbnail/TinyThumbnail-Profile.xcconfig","buck-out/gen/submodules/TinyThumbnail/TinyThumbnail-Release.xcconfig","buck-out/gen/submodules/TouchDownGesture/TouchDownGesture-Debug.xcconfig","buck-out/gen/submodules/TouchDownGesture/TouchDownGesture-Profile.xcconfig","buck-out/gen/submodules/TouchDownGesture/TouchDownGesture-Release.xcconfig","buck-out/gen/submodules/Tuples/Tuples-Debug.xcconfig","buck-out/gen/submodules/Tuples/Tuples-Profile.xcconfig","buck-out/gen/submodules/Tuples/Tuples-Release.xcconfig","buck-out/gen/submodules/UndoUI/UndoUI-Debug.xcconfig","buck-out/gen/submodules/UndoUI/UndoUI-Profile.xcconfig","buck-out/gen/submodules/UndoUI/UndoUI-Release.xcconfig","buck-out/gen/submodules/UrlEscaping/UrlEscaping-Debug.xcconfig","buck-out/gen/submodules/UrlEscaping/UrlEscaping-Profile.xcconfig","buck-out/gen/submodules/UrlEscaping/UrlEscaping-Release.xcconfig","buck-out/gen/submodules/UrlHandling/UrlHandling-Debug.xcconfig","buck-out/gen/submodules/UrlHandling/UrlHandling-Profile.xcconfig","buck-out/gen/submodules/UrlHandling/UrlHandling-Release.xcconfig","buck-out/gen/submodules/WalletUI/WalletUI-Debug.xcconfig","buck-out/gen/submodules/WalletUI/WalletUI-Profile.xcconfig","buck-out/gen/submodules/WalletUI/WalletUI-Release.xcconfig","buck-out/gen/submodules/WallpaperResources/WallpaperResources-Debug.xcconfig","buck-out/gen/submodules/WallpaperResources/WallpaperResources-Profile.xcconfig","buck-out/gen/submodules/WallpaperResources/WallpaperResources-Release.xcconfig","buck-out/gen/submodules/WatchBridge/WatchBridge-Debug.xcconfig","buck-out/gen/submodules/WatchBridge/WatchBridge-Profile.xcconfig","buck-out/gen/submodules/WatchBridge/WatchBridge-Release.xcconfig","buck-out/gen/submodules/WatchBridgeAudio/WatchBridgeAudio-Debug.xcconfig","buck-out/gen/submodules/WatchBridgeAudio/WatchBridgeAudio-Profile.xcconfig","buck-out/gen/submodules/WatchBridgeAudio/WatchBridgeAudio-Release.xcconfig","buck-out/gen/submodules/WatchCommon/Host/WatchCommon-Debug.xcconfig","buck-out/gen/submodules/WatchCommon/Host/WatchCommon-Profile.xcconfig","buck-out/gen/submodules/WatchCommon/Host/WatchCommon-Release.xcconfig","buck-out/gen/submodules/WebP/WebPImage-Debug.xcconfig","buck-out/gen/submodules/WebP/WebPImage-Profile.xcconfig","buck-out/gen/submodules/WebP/WebPImage-Release.xcconfig","buck-out/gen/submodules/WebP/WebP_lib-Debug.xcconfig","buck-out/gen/submodules/WebP/WebP_lib-Profile.xcconfig","buck-out/gen/submodules/WebP/WebP_lib-Release.xcconfig","buck-out/gen/submodules/WebSearchUI/WebSearchUI-Debug.xcconfig","buck-out/gen/submodules/WebSearchUI/WebSearchUI-Profile.xcconfig","buck-out/gen/submodules/WebSearchUI/WebSearchUI-Release.xcconfig","buck-out/gen/submodules/WebUI/WebUI-Debug.xcconfig","buck-out/gen/submodules/WebUI/WebUI-Profile.xcconfig","buck-out/gen/submodules/WebUI/WebUI-Release.xcconfig","buck-out/gen/submodules/WebsiteType/WebsiteType-Debug.xcconfig","buck-out/gen/submodules/WebsiteType/WebsiteType-Profile.xcconfig","buck-out/gen/submodules/WebsiteType/WebsiteType-Release.xcconfig","buck-out/gen/submodules/YuvConversion/YuvConversion-Debug.xcconfig","buck-out/gen/submodules/YuvConversion/YuvConversion-Profile.xcconfig","buck-out/gen/submodules/YuvConversion/YuvConversion-Release.xcconfig","buck-out/gen/submodules/libphonenumber/libphonenumber-Debug.xcconfig","buck-out/gen/submodules/libphonenumber/libphonenumber-Profile.xcconfig","buck-out/gen/submodules/libphonenumber/libphonenumber-Release.xcconfig","buck-out/gen/submodules/libtgvoip/libtgvoip-Debug.xcconfig","buck-out/gen/submodules/libtgvoip/libtgvoip-Profile.xcconfig","buck-out/gen/submodules/libtgvoip/libtgvoip-Release.xcconfig","buck-out/gen/submodules/lottie-ios/Lottie-Debug.xcconfig","buck-out/gen/submodules/lottie-ios/Lottie-Profile.xcconfig","buck-out/gen/submodules/lottie-ios/Lottie-Release.xcconfig","buck-out/gen/submodules/openssl/openssl-Debug.xcconfig","buck-out/gen/submodules/openssl/openssl-Profile.xcconfig","buck-out/gen/submodules/openssl/openssl-Release.xcconfig","buck-out/gen/submodules/rlottie/RLottieBinding-Debug.xcconfig","buck-out/gen/submodules/rlottie/RLottieBinding-Profile.xcconfig","buck-out/gen/submodules/rlottie/RLottieBinding-Release.xcconfig","buck-out/gen/submodules/sqlcipher/sqlcipher-Debug.xcconfig","buck-out/gen/submodules/sqlcipher/sqlcipher-Profile.xcconfig","buck-out/gen/submodules/sqlcipher/sqlcipher-Release.xcconfig","buck-out/gen/submodules/ton/ton-Debug.xcconfig","buck-out/gen/submodules/ton/ton-Profile.xcconfig","buck-out/gen/submodules/ton/ton-Release.xcconfig"],"copy-in-xcode":[]}
\ No newline at end of file
diff --git a/Telegram_Buck.xcworkspace/contents.xcworkspacedata b/Telegram_Buck.xcworkspace/contents.xcworkspacedata
index 149ca31975..a3f93af764 100644
--- a/Telegram_Buck.xcworkspace/contents.xcworkspacedata
+++ b/Telegram_Buck.xcworkspace/contents.xcworkspacedata
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme
index 4a01a62522..e009a59b64 100644
--- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme
+++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme
@@ -2246,6 +2246,20 @@
ReferencedContainer = "container:submodules/Camera/Camera.xcodeproj">
+
+
+
+
Void)?
+
+ private let detectedCodesPipe = ValuePipe<[CameraCode]>()
var previewNode: CameraPreviewNode? {
didSet {
@@ -17,11 +23,6 @@ private final class CameraContext {
}
}
- var previousSampleBuffer: CMSampleBuffer?
- var processSampleBuffer: ((CMSampleBuffer) -> Void)?
-
- private var invalidated = false
-
init(queue: Queue, configuration: Camera.Configuration) {
self.queue = queue
self.initialConfiguration = configuration
@@ -45,6 +46,10 @@ private final class CameraContext {
self?.processSampleBuffer?(sampleBuffer)
}
}
+
+ self.output.processCodes = { [weak self] codes in
+ self?.detectedCodesPipe.putNext(codes)
+ }
}
func startCapture() {
@@ -85,24 +90,38 @@ private final class CameraContext {
self.input.configure(for: self.session, device: self.device, audio: self.initialConfiguration.audio)
self.session.commitConfiguration()
}
+
+ func setTorchActive(_ active: Bool) {
+ self.device.setTorchActive(active)
+ }
+
+ var detectedCodes: Signal<[CameraCode], NoError> {
+ return self.detectedCodesPipe.signal()
+ }
}
-final class Camera {
- typealias Preset = AVCaptureSession.Preset
- typealias Position = AVCaptureDevice.Position
- typealias FocusMode = AVCaptureDevice.FocusMode
- typealias ExposureMode = AVCaptureDevice.ExposureMode
+public final class Camera {
+ public typealias Preset = AVCaptureSession.Preset
+ public typealias Position = AVCaptureDevice.Position
+ public typealias FocusMode = AVCaptureDevice.FocusMode
+ public typealias ExposureMode = AVCaptureDevice.ExposureMode
- struct Configuration {
+ public struct Configuration {
let preset: Preset
let position: Position
let audio: Bool
+
+ public init(preset: Preset, position: Position, audio: Bool) {
+ self.preset = preset
+ self.position = position
+ self.audio = audio
+ }
}
private let queue = Queue()
private var contextRef: Unmanaged?
- init(configuration: Camera.Configuration = Configuration(preset: .hd1920x1080, position: .back, audio: true)) {
+ public init(configuration: Camera.Configuration = Configuration(preset: .hd1920x1080, position: .back, audio: true)) {
self.queue.async {
let context = CameraContext(queue: self.queue, configuration: configuration)
self.contextRef = Unmanaged.passRetained(context)
@@ -116,7 +135,7 @@ final class Camera {
}
}
- func startCapture() {
+ public func startCapture() {
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
context.startCapture()
@@ -124,14 +143,15 @@ final class Camera {
}
}
- func stopCapture() {
+ public func stopCapture() {
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
context.stopCapture()
}
}
}
- func togglePosition() {
+
+ public func togglePosition() {
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
context.togglePosition()
@@ -139,11 +159,11 @@ final class Camera {
}
}
- func takePhoto() -> Signal {
+ public func takePhoto() -> Signal {
return .never()
}
- func focus(at point: CGPoint) {
+ public func focus(at point: CGPoint) {
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
context.focus(at: point)
@@ -151,7 +171,7 @@ final class Camera {
}
}
- func setFPS(_ fps: Double) {
+ public func setFPS(_ fps: Double) {
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
context.setFPS(fps)
@@ -159,7 +179,15 @@ final class Camera {
}
}
- func attachPreviewNode(_ node: CameraPreviewNode) {
+ public func setTorchActive(_ active: Bool) {
+ self.queue.async {
+ if let context = self.contextRef?.takeUnretainedValue() {
+ context.setTorchActive(active)
+ }
+ }
+ }
+
+ public func attachPreviewNode(_ node: CameraPreviewNode) {
let nodeRef: Unmanaged = Unmanaged.passRetained(node)
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
@@ -173,11 +201,25 @@ final class Camera {
}
}
- func setProcessSampleBuffer(_ block: ((CMSampleBuffer) -> Void)?) {
+ public func setProcessSampleBuffer(_ block: ((CMSampleBuffer) -> Void)?) {
self.queue.async {
if let context = self.contextRef?.takeUnretainedValue() {
context.processSampleBuffer = block
}
}
}
+
+ public var detectedCodes: Signal<[CameraCode], NoError> {
+ return Signal { subscriber in
+ let disposable = MetaDisposable()
+ self.queue.async {
+ if let context = self.contextRef?.takeUnretainedValue() {
+ disposable.set(context.detectedCodes.start(next: { codes in
+ subscriber.putNext(codes)
+ }))
+ }
+ }
+ return disposable
+ }
+ }
}
diff --git a/submodules/Camera/Sources/CameraDevice.swift b/submodules/Camera/Sources/CameraDevice.swift
index 90d110db6f..5cbf8ff7e1 100644
--- a/submodules/Camera/Sources/CameraDevice.swift
+++ b/submodules/Camera/Sources/CameraDevice.swift
@@ -135,4 +135,13 @@ final class CameraDevice {
device.setExposureTargetBias(value, completionHandler: nil)
}
}
+
+ func setTorchActive(_ active: Bool) {
+ guard let device = self.videoDevice else {
+ return
+ }
+ self.transaction(device) { device in
+ device.torchMode = active ? .on : .off
+ }
+ }
}
diff --git a/submodules/Camera/Sources/CameraOutput.swift b/submodules/Camera/Sources/CameraOutput.swift
index a7cb2258c5..d2c4203b6a 100644
--- a/submodules/Camera/Sources/CameraOutput.swift
+++ b/submodules/Camera/Sources/CameraOutput.swift
@@ -1,5 +1,43 @@
import AVFoundation
+public struct CameraCode: Equatable {
+ public enum CodeType {
+ case qr
+ }
+
+ public let type: CodeType
+ public let message: String
+ public let corners: [CGPoint]
+
+ public init(type: CameraCode.CodeType, message: String, corners: [CGPoint]) {
+ self.type = type
+ self.message = message
+ self.corners = corners
+ }
+
+ public var boundingBox: CGRect {
+ let x = self.corners.map { $0.x }
+ let y = self.corners.map { $0.y }
+ if let minX = x.min(), let minY = y.min(), let maxX = x.max(), let maxY = y.max() {
+ return CGRect(x: minX, y: minY, width: abs(maxX - minX), height: abs(maxY - minY))
+ }
+ return CGRect.null
+ }
+
+ public static func == (lhs: CameraCode, rhs: CameraCode) -> Bool {
+ if lhs.type != rhs.type {
+ return false
+ }
+ if lhs.message != rhs.message {
+ return false
+ }
+ if lhs.corners != rhs.corners {
+ return false
+ }
+ return true
+ }
+}
+
final class CameraOutput: NSObject {
//private let photoOutput = CameraPhotoOutput()
private let videoOutput = AVCaptureVideoDataOutput()
@@ -7,9 +45,10 @@ final class CameraOutput: NSObject {
private let metadataOutput = AVCaptureMetadataOutput()
private let queue = DispatchQueue(label: "")
+ private let metadataQueue = DispatchQueue(label: "")
var processSampleBuffer: ((CMSampleBuffer, AVCaptureConnection) -> Void)?
- var processQRCode: ((String, AVMetadataMachineReadableCodeObject) -> Void)?
+ var processCodes: (([CameraCode]) -> Void)?
override init() {
super.init()
@@ -34,6 +73,11 @@ final class CameraOutput: NSObject {
}
if session.canAddOutput(self.metadataOutput) {
session.addOutput(self.metadataOutput)
+
+ self.metadataOutput.setMetadataObjectsDelegate(self, queue: self.metadataQueue)
+ if self.metadataOutput.availableMetadataObjectTypes.contains(.qr) {
+ self.metadataOutput.metadataObjectTypes = [.qr]
+ }
}
}
@@ -60,8 +104,13 @@ extension CameraOutput: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureA
extension CameraOutput: AVCaptureMetadataOutputObjectsDelegate {
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
- if let object = metadataObjects.first as? AVMetadataMachineReadableCodeObject, object.type == .qr, let stringValue = object.stringValue, !stringValue.isEmpty {
- self.processQRCode?(stringValue, object)
+ let codes: [CameraCode] = metadataObjects.filter { $0.type == .qr }.compactMap { object in
+ if let object = object as? AVMetadataMachineReadableCodeObject, let stringValue = object.stringValue, !stringValue.isEmpty {
+ return CameraCode(type: .qr, message: stringValue, corners: object.corners)
+ } else {
+ return nil
+ }
}
+ self.processCodes?(codes)
}
}
diff --git a/submodules/Camera/Sources/CameraPreviewNode.swift b/submodules/Camera/Sources/CameraPreviewNode.swift
index 9f18fa7e21..9e88730a71 100644
--- a/submodules/Camera/Sources/CameraPreviewNode.swift
+++ b/submodules/Camera/Sources/CameraPreviewNode.swift
@@ -14,10 +14,10 @@ private final class CameraPreviewNodeLayer: AVSampleBufferDisplayLayer {
}
}
-class CameraPreviewNode: ASDisplayNode {
+public final class CameraPreviewNode: ASDisplayNode {
private var displayLayer: AVSampleBufferDisplayLayer
- override init() {
+ public override init() {
self.displayLayer = AVSampleBufferDisplayLayer()
self.displayLayer.videoGravity = .resizeAspectFill
@@ -38,11 +38,11 @@ class CameraPreviewNode: ASDisplayNode {
self.displayLayer.enqueue(sampleBuffer)
}
- override func layout() {
+ override public func layout() {
super.layout()
var transform = CGAffineTransform(rotationAngle: CGFloat.pi / 2.0)
- transform = transform.scaledBy(x: 1.0, y: -1.0)
+ transform = transform.scaledBy(x: 1.0, y: 1.0)
self.displayLayer.setAffineTransform(transform)
self.displayLayer.frame = self.bounds
diff --git a/submodules/GlassButtonNode/BUCK b/submodules/GlassButtonNode/BUCK
new file mode 100644
index 0000000000..4127cf308e
--- /dev/null
+++ b/submodules/GlassButtonNode/BUCK
@@ -0,0 +1,16 @@
+load("//Config:buck_rule_macros.bzl", "static_library")
+
+static_library(
+ name = "GlassButtonNode",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit#shared",
+ "//submodules/Display:Display#shared",
+ ],
+ frameworks = [
+ "$SDKROOT/System/Library/Frameworks/Foundation.framework",
+ "$SDKROOT/System/Library/Frameworks/UIKit.framework",
+ ],
+)
diff --git a/submodules/GlassButtonNode/GlassButtonNode.xcodeproj/project.pbxproj b/submodules/GlassButtonNode/GlassButtonNode.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..19233389ae
--- /dev/null
+++ b/submodules/GlassButtonNode/GlassButtonNode.xcodeproj/project.pbxproj
@@ -0,0 +1,379 @@
+
+
+
+
+ archiveVersion
+ 1
+ classes
+
+
+ objectVersion
+ 46
+ objects
+
+ 1DD70E294F632DE500000000
+
+ isa
+ PBXFileReference
+ name
+ GlassButtonNode-Debug.xcconfig
+ path
+ ../../buck-out/gen/submodules/GlassButtonNode/GlassButtonNode-Debug.xcconfig
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.xcconfig
+
+ 1DD70E29E871E00F00000000
+
+ isa
+ PBXFileReference
+ name
+ GlassButtonNode-Profile.xcconfig
+ path
+ ../../buck-out/gen/submodules/GlassButtonNode/GlassButtonNode-Profile.xcconfig
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.xcconfig
+
+ 1DD70E295C088B7100000000
+
+ isa
+ PBXFileReference
+ name
+ GlassButtonNode-Release.xcconfig
+ path
+ ../../buck-out/gen/submodules/GlassButtonNode/GlassButtonNode-Release.xcconfig
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.xcconfig
+
+ B401C9792F7F325000000000
+
+ isa
+ PBXGroup
+ name
+ Buck (Do Not Modify)
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E294F632DE500000000
+ 1DD70E29E871E00F00000000
+ 1DD70E295C088B7100000000
+
+
+ B401C979B781F65D00000000
+
+ isa
+ PBXGroup
+ name
+ Configurations
+ sourceTree
+ ]]>
+ children
+
+ B401C9792F7F325000000000
+
+
+ 1DD70E29FF334B1F00000000
+
+ isa
+ PBXFileReference
+ name
+ libDisplay.dylib
+ path
+ libDisplay.dylib
+ sourceTree
+ BUILT_PRODUCTS_DIR
+ explicitFileType
+ compiled.mach-o.dylib
+
+ B401C97968022A5500000000
+
+ isa
+ PBXGroup
+ name
+ Frameworks
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E29FF334B1F00000000
+
+
+ 1DD70E29001F47FB00000000
+
+ isa
+ PBXFileReference
+ name
+ BUCK
+ path
+ BUCK
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.script.python
+
+ 1DD70E2923081F7500000000
+
+ isa
+ PBXFileReference
+ name
+ GlassButtonNode.swift
+ path
+ Sources/GlassButtonNode.swift
+ sourceTree
+ SOURCE_ROOT
+
+ B401C979EAB5339800000000
+
+ isa
+ PBXGroup
+ name
+ Sources
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E2923081F7500000000
+
+
+ B401C97978C8D0D000000000
+
+ isa
+ PBXGroup
+ name
+ GlassButtonNode
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E29001F47FB00000000
+ B401C979EAB5339800000000
+
+
+ 1DD70E29BCD8FADE00000000
+
+ isa
+ PBXFileReference
+ name
+ libGlassButtonNode.a
+ path
+ libGlassButtonNode.a
+ sourceTree
+ BUILT_PRODUCTS_DIR
+ explicitFileType
+ archive.ar
+
+ B401C979C806358400000000
+
+ isa
+ PBXGroup
+ name
+ Products
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E29BCD8FADE00000000
+
+
+ B401C979EFB6AC4600000000
+
+ isa
+ PBXGroup
+ name
+ mainGroup
+ sourceTree
+ ]]>
+ children
+
+ B401C979B781F65D00000000
+ B401C97968022A5500000000
+ B401C97978C8D0D000000000
+ B401C979C806358400000000
+
+
+ E7A30F0423081F7500000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E2923081F7500000000
+
+ 1870857F0000000000000000
+
+ isa
+ PBXSourcesBuildPhase
+ files
+
+ E7A30F0423081F7500000000
+
+
+ E7A30F04FF334B1F00000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E29FF334B1F00000000
+
+ FAF5FAC90000000000000000
+
+ isa
+ PBXCopyFilesBuildPhase
+ files
+
+ E7A30F04FF334B1F00000000
+
+ name
+ Fake Swift Dependencies (Copy Files Phase)
+ runOnlyForDeploymentPostprocessing
+ 1
+ dstSubfolderSpec
+ 16
+ dstPath
+
+
+ 4952437303EDA63300000000
+
+ isa
+ XCBuildConfiguration
+ name
+ Debug
+ buildSettings
+
+
+ baseConfigurationReference
+ 1DD70E294F632DE500000000
+
+ 4952437350C7218900000000
+
+ isa
+ XCBuildConfiguration
+ name
+ Profile
+ buildSettings
+
+
+ baseConfigurationReference
+ 1DD70E29E871E00F00000000
+
+ 49524373A439BFE700000000
+
+ isa
+ XCBuildConfiguration
+ name
+ Release
+ buildSettings
+
+
+ baseConfigurationReference
+ 1DD70E295C088B7100000000
+
+ 218C37090000000000000000
+
+ isa
+ XCConfigurationList
+ buildConfigurations
+
+ 4952437303EDA63300000000
+ 4952437350C7218900000000
+ 49524373A439BFE700000000
+
+ defaultConfigurationIsVisible
+
+
+ E66DC04E78C8D0D000000000
+
+ isa
+ PBXNativeTarget
+ name
+ GlassButtonNode
+ productName
+ GlassButtonNode
+ productReference
+ 1DD70E29BCD8FADE00000000
+ productType
+ com.apple.product-type.library.static
+ dependencies
+
+
+ buildPhases
+
+ 1870857F0000000000000000
+ FAF5FAC90000000000000000
+
+ buildConfigurationList
+ 218C37090000000000000000
+
+ 4952437303EDA63300000001
+
+ isa
+ XCBuildConfiguration
+ name
+ Debug
+ buildSettings
+
+
+
+ 4952437350C7218900000001
+
+ isa
+ XCBuildConfiguration
+ name
+ Profile
+ buildSettings
+
+
+
+ 49524373A439BFE700000001
+
+ isa
+ XCBuildConfiguration
+ name
+ Release
+ buildSettings
+
+
+
+ 218C37090000000000000001
+
+ isa
+ XCConfigurationList
+ buildConfigurations
+
+ 4952437303EDA63300000001
+ 4952437350C7218900000001
+ 49524373A439BFE700000001
+
+ defaultConfigurationIsVisible
+
+
+ 96C8479378C8D0D000000000
+
+ isa
+ PBXProject
+ mainGroup
+ B401C979EFB6AC4600000000
+ targets
+
+ E66DC04E78C8D0D000000000
+
+ buildConfigurationList
+ 218C37090000000000000001
+ compatibilityVersion
+ Xcode 3.2
+ attributes
+
+ LastUpgradeCheck
+ 9999
+
+
+
+ rootObject
+ 96C8479378C8D0D000000000
+
+
\ No newline at end of file
diff --git a/submodules/GlassButtonNode/GlassButtonNode.xcodeproj/xcshareddata/xcschemes/GlassButtonNode.xcscheme b/submodules/GlassButtonNode/GlassButtonNode.xcodeproj/xcshareddata/xcschemes/GlassButtonNode.xcscheme
new file mode 100644
index 0000000000..3a6a3325bb
--- /dev/null
+++ b/submodules/GlassButtonNode/GlassButtonNode.xcodeproj/xcshareddata/xcschemes/GlassButtonNode.xcscheme
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/submodules/GlassButtonNode/Info.plist b/submodules/GlassButtonNode/Info.plist
new file mode 100644
index 0000000000..e1fe4cfb7b
--- /dev/null
+++ b/submodules/GlassButtonNode/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ $(CURRENT_PROJECT_VERSION)
+
+
diff --git a/submodules/GlassButtonNode/QrCode.xcodeproj/project.pbxproj b/submodules/GlassButtonNode/QrCode.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..cd6b029c10
--- /dev/null
+++ b/submodules/GlassButtonNode/QrCode.xcodeproj/project.pbxproj
@@ -0,0 +1,545 @@
+
+
+
+
+ archiveVersion
+ 1
+ classes
+
+
+ objectVersion
+ 46
+ objects
+
+ 1DD70E295898BF2700000000
+
+ isa
+ PBXFileReference
+ name
+ QrCode-Debug.xcconfig
+ path
+ ../../buck-out/gen/submodules/QrCode/QrCode-Debug.xcconfig
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.xcconfig
+
+ 1DD70E297A8828D100000000
+
+ isa
+ PBXFileReference
+ name
+ QrCode-Profile.xcconfig
+ path
+ ../../buck-out/gen/submodules/QrCode/QrCode-Profile.xcconfig
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.xcconfig
+
+ 1DD70E29EE1ED43300000000
+
+ isa
+ PBXFileReference
+ name
+ QrCode-Release.xcconfig
+ path
+ ../../buck-out/gen/submodules/QrCode/QrCode-Release.xcconfig
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.xcconfig
+
+ B401C9792F7F325000000000
+
+ isa
+ PBXGroup
+ name
+ Buck (Do Not Modify)
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E295898BF2700000000
+ 1DD70E297A8828D100000000
+ 1DD70E29EE1ED43300000000
+
+
+ B401C979B781F65D00000000
+
+ isa
+ PBXGroup
+ name
+ Configurations
+ sourceTree
+ ]]>
+ children
+
+ B401C9792F7F325000000000
+
+
+ 1DD70E29FF334B1F00000000
+
+ isa
+ PBXFileReference
+ name
+ libDisplay.dylib
+ path
+ libDisplay.dylib
+ sourceTree
+ BUILT_PRODUCTS_DIR
+ explicitFileType
+ compiled.mach-o.dylib
+
+ 1DD70E29D65BA68200000000
+
+ isa
+ PBXFileReference
+ name
+ libSwiftSignalKit.dylib
+ path
+ libSwiftSignalKit.dylib
+ sourceTree
+ BUILT_PRODUCTS_DIR
+ explicitFileType
+ compiled.mach-o.dylib
+
+ B401C97968022A5500000000
+
+ isa
+ PBXGroup
+ name
+ Frameworks
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E29FF334B1F00000000
+ 1DD70E29D65BA68200000000
+
+
+ 1DD70E29AA32BBC600000000
+
+ isa
+ PBXFileReference
+ name
+ libQrCode.a
+ path
+ libQrCode.a
+ sourceTree
+ BUILT_PRODUCTS_DIR
+ explicitFileType
+ archive.ar
+
+ B401C979C806358400000000
+
+ isa
+ PBXGroup
+ name
+ Products
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E29AA32BBC600000000
+
+
+ 1DD70E29001F47FB00000000
+
+ isa
+ PBXFileReference
+ name
+ BUCK
+ path
+ BUCK
+ sourceTree
+ SOURCE_ROOT
+ explicitFileType
+ text.script.python
+
+ 1DD70E2905A53BC200000000
+
+ isa
+ PBXFileReference
+ name
+ BitBuffer.cpp
+ path
+ Sources/BitBuffer.cpp
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.cpp.cpp
+
+ 1DD70E2905A54E8700000000
+
+ isa
+ PBXFileReference
+ name
+ BitBuffer.hpp
+ path
+ Sources/BitBuffer.hpp
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.cpp.h
+
+ 1DD70E2921C2F78300000000
+
+ isa
+ PBXFileReference
+ name
+ QrCode.cpp
+ path
+ Sources/QrCode.cpp
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.cpp.cpp
+
+ 1DD70E2921C30A4800000000
+
+ isa
+ PBXFileReference
+ name
+ QrCode.hpp
+ path
+ Sources/QrCode.hpp
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.cpp.h
+
+ 1DD70E29BDC7BBF300000000
+
+ isa
+ PBXFileReference
+ name
+ QrCode.swift
+ path
+ Sources/QrCode.swift
+ sourceTree
+ SOURCE_ROOT
+
+ 1DD70E2956ECDFBD00000000
+
+ isa
+ PBXFileReference
+ name
+ QrCodeInstance.h
+ path
+ Sources/QrCodeInstance.h
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.c.h
+
+ 1DD70E2986AF18EB00000000
+
+ isa
+ PBXFileReference
+ name
+ QrCodeInstance.mm
+ path
+ Sources/QrCodeInstance.mm
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.cpp.objcpp
+
+ 1DD70E290F1C936700000000
+
+ isa
+ PBXFileReference
+ name
+ QrSegment.cpp
+ path
+ Sources/QrSegment.cpp
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.cpp.cpp
+
+ 1DD70E290F1CA62C00000000
+
+ isa
+ PBXFileReference
+ name
+ QrSegment.hpp
+ path
+ Sources/QrSegment.hpp
+ sourceTree
+ SOURCE_ROOT
+ lastKnownFileType
+ sourcecode.cpp.h
+
+ B401C979EAB5339800000000
+
+ isa
+ PBXGroup
+ name
+ Sources
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E2905A53BC200000000
+ 1DD70E2905A54E8700000000
+ 1DD70E2921C2F78300000000
+ 1DD70E2921C30A4800000000
+ 1DD70E29BDC7BBF300000000
+ 1DD70E2956ECDFBD00000000
+ 1DD70E2986AF18EB00000000
+ 1DD70E290F1C936700000000
+ 1DD70E290F1CA62C00000000
+
+
+ B401C979909F23CE00000000
+
+ isa
+ PBXGroup
+ name
+ QrCode
+ sourceTree
+ ]]>
+ children
+
+ 1DD70E29001F47FB00000000
+ B401C979EAB5339800000000
+
+
+ B401C979EFB6AC4600000000
+
+ isa
+ PBXGroup
+ name
+ mainGroup
+ sourceTree
+ ]]>
+ children
+
+ B401C979B781F65D00000000
+ B401C97968022A5500000000
+ B401C979C806358400000000
+ B401C979909F23CE00000000
+
+
+ E7A30F0405A53BC200000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E2905A53BC200000000
+
+ E7A30F0421C2F78300000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E2921C2F78300000000
+
+ E7A30F04BDC7BBF300000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E29BDC7BBF300000000
+
+ E7A30F0486AF18EB00000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E2986AF18EB00000000
+
+ E7A30F040F1C936700000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E290F1C936700000000
+
+ 1870857F0000000000000000
+
+ isa
+ PBXSourcesBuildPhase
+ files
+
+ E7A30F0405A53BC200000000
+ E7A30F0421C2F78300000000
+ E7A30F04BDC7BBF300000000
+ E7A30F0486AF18EB00000000
+ E7A30F040F1C936700000000
+
+
+ E7A30F04FF334B1F00000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E29FF334B1F00000000
+
+ E7A30F04D65BA68200000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E29D65BA68200000000
+
+ FAF5FAC90000000000000000
+
+ isa
+ PBXCopyFilesBuildPhase
+ files
+
+ E7A30F04FF334B1F00000000
+ E7A30F04D65BA68200000000
+
+ name
+ Fake Swift Dependencies (Copy Files Phase)
+ runOnlyForDeploymentPostprocessing
+ 1
+ dstSubfolderSpec
+ 16
+ dstPath
+
+
+ 4952437303EDA63300000000
+
+ isa
+ XCBuildConfiguration
+ name
+ Debug
+ buildSettings
+
+
+ baseConfigurationReference
+ 1DD70E295898BF2700000000
+
+ 4952437350C7218900000000
+
+ isa
+ XCBuildConfiguration
+ name
+ Profile
+ buildSettings
+
+
+ baseConfigurationReference
+ 1DD70E297A8828D100000000
+
+ 49524373A439BFE700000000
+
+ isa
+ XCBuildConfiguration
+ name
+ Release
+ buildSettings
+
+
+ baseConfigurationReference
+ 1DD70E29EE1ED43300000000
+
+ 218C37090000000000000000
+
+ isa
+ XCConfigurationList
+ buildConfigurations
+
+ 4952437303EDA63300000000
+ 4952437350C7218900000000
+ 49524373A439BFE700000000
+
+ defaultConfigurationIsVisible
+
+
+ E66DC04E909F23CE00000000
+
+ isa
+ PBXNativeTarget
+ name
+ QrCode
+ productName
+ QrCode
+ productReference
+ 1DD70E29AA32BBC600000000
+ productType
+ com.apple.product-type.library.static
+ dependencies
+
+
+ buildPhases
+
+ 1870857F0000000000000000
+ FAF5FAC90000000000000000
+
+ buildConfigurationList
+ 218C37090000000000000000
+
+ 4952437303EDA63300000001
+
+ isa
+ XCBuildConfiguration
+ name
+ Debug
+ buildSettings
+
+
+
+ 4952437350C7218900000001
+
+ isa
+ XCBuildConfiguration
+ name
+ Profile
+ buildSettings
+
+
+
+ 49524373A439BFE700000001
+
+ isa
+ XCBuildConfiguration
+ name
+ Release
+ buildSettings
+
+
+
+ 218C37090000000000000001
+
+ isa
+ XCConfigurationList
+ buildConfigurations
+
+ 4952437303EDA63300000001
+ 4952437350C7218900000001
+ 49524373A439BFE700000001
+
+ defaultConfigurationIsVisible
+
+
+ 96C84793909F23CE00000000
+
+ isa
+ PBXProject
+ mainGroup
+ B401C979EFB6AC4600000000
+ targets
+
+ E66DC04E909F23CE00000000
+
+ buildConfigurationList
+ 218C37090000000000000001
+ compatibilityVersion
+ Xcode 3.2
+ attributes
+
+ LastUpgradeCheck
+ 9999
+
+
+
+ rootObject
+ 96C84793909F23CE00000000
+
+
\ No newline at end of file
diff --git a/submodules/GlassButtonNode/QrCode.xcodeproj/xcshareddata/xcschemes/QrCode.xcscheme b/submodules/GlassButtonNode/QrCode.xcodeproj/xcshareddata/xcschemes/QrCode.xcscheme
new file mode 100644
index 0000000000..9365080e82
--- /dev/null
+++ b/submodules/GlassButtonNode/QrCode.xcodeproj/xcshareddata/xcschemes/QrCode.xcscheme
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/submodules/GlassButtonNode/Sources/GlassButtonNode.swift b/submodules/GlassButtonNode/Sources/GlassButtonNode.swift
new file mode 100644
index 0000000000..f9fd932c6a
--- /dev/null
+++ b/submodules/GlassButtonNode/Sources/GlassButtonNode.swift
@@ -0,0 +1,178 @@
+import Foundation
+import Display
+import AsyncDisplayKit
+import SwiftSignalKit
+
+private let largeButtonSize = CGSize(width: 72.0, height: 72.0)
+private let smallButtonSize = CGSize(width: 60.0, height: 60.0)
+
+private func generateEmptyButtonImage(icon: UIImage?, strokeColor: UIColor?, fillColor: UIColor, knockout: Bool = false, angle: CGFloat = 0.0, buttonSize: CGSize = smallButtonSize) -> UIImage? {
+ return generateImage(buttonSize, contextGenerator: { size, context in
+ context.clear(CGRect(origin: CGPoint(), size: size))
+ context.setBlendMode(.copy)
+ if let strokeColor = strokeColor {
+ context.setFillColor(strokeColor.cgColor)
+ context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
+ context.setFillColor(fillColor.cgColor)
+ context.fillEllipse(in: CGRect(origin: CGPoint(x: 1.5, y: 1.5), size: CGSize(width: size.width - 3.0, height: size.height - 3.0)))
+ } else {
+ context.setFillColor(fillColor.cgColor)
+ context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height)))
+ }
+
+ if let icon = icon {
+ if !angle.isZero {
+ context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
+ context.rotate(by: angle)
+ context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
+ }
+ let imageSize = icon.size
+ let imageRect = CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.width - imageSize.height) / 2.0)), size: imageSize)
+ if knockout {
+ context.setBlendMode(.copy)
+ context.clip(to: imageRect, mask: icon.cgImage!)
+ context.setFillColor(UIColor.clear.cgColor)
+ context.fill(imageRect)
+ } else {
+ context.setBlendMode(.normal)
+ context.draw(icon.cgImage!, in: imageRect)
+ }
+ }
+ })
+}
+
+private func generateFilledButtonImage(color: UIColor, icon: UIImage?, angle: CGFloat = 0.0, buttonSize: CGSize = smallButtonSize) -> UIImage? {
+ return generateImage(buttonSize, contextGenerator: { size, context in
+ context.clear(CGRect(origin: CGPoint(), size: size))
+ context.setBlendMode(.normal)
+ context.setFillColor(color.cgColor)
+ context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
+
+ if let icon = icon {
+ if !angle.isZero {
+ context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
+ context.rotate(by: angle)
+ context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
+ }
+ context.draw(icon.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - icon.size.width) / 2.0), y: floor((size.height - icon.size.height) / 2.0)), size: icon.size))
+ }
+ })
+}
+
+private let emptyHighlightedFill = UIColor(white: 1.0, alpha: 0.3)
+private let invertedFill = UIColor(white: 1.0, alpha: 1.0)
+
+private let largeLabelFont = Font.regular(14.5)
+private let smallLabelFont = Font.regular(11.5)
+
+public final class GlassButtonNode: HighlightTrackingButtonNode {
+ private var regularImage: UIImage?
+ private var highlightedImage: UIImage?
+ private var filledImage: UIImage?
+
+ private let blurView: UIVisualEffectView
+ private let iconNode: ASImageNode
+ private var labelNode: ASTextNode?
+
+ public init(icon: UIImage, label: String?) {
+ let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
+ blurView.clipsToBounds = true
+ blurView.isUserInteractionEnabled = false
+ self.blurView = blurView
+
+ self.iconNode = ASImageNode()
+ self.iconNode.isLayerBacked = true
+ self.iconNode.displayWithoutProcessing = false
+ self.iconNode.displaysAsynchronously = false
+
+ self.regularImage = generateEmptyButtonImage(icon: icon, strokeColor: nil, fillColor: .clear, buttonSize: largeButtonSize)
+ self.highlightedImage = generateEmptyButtonImage(icon: icon, strokeColor: nil, fillColor: emptyHighlightedFill, buttonSize: largeButtonSize)
+ self.filledImage = generateEmptyButtonImage(icon: icon, strokeColor: nil, fillColor: invertedFill, knockout: true, buttonSize: largeButtonSize)
+
+ if let label = label {
+ let labelNode = ASTextNode()
+ let labelFont: UIFont
+ if let image = regularImage, image.size.width < 70.0 {
+ labelFont = smallLabelFont
+ } else {
+ labelFont = largeLabelFont
+ }
+ labelNode.attributedText = NSAttributedString(string: label, font: labelFont, textColor: .white)
+ self.labelNode = labelNode
+ } else {
+ self.labelNode = nil
+ }
+
+ super.init()
+
+ self.view.addSubview(blurView)
+ self.addSubnode(self.iconNode)
+ if let labelNode = self.labelNode {
+ self.addSubnode(labelNode)
+ }
+ self.iconNode.image = regularImage
+ self.currentImage = regularImage
+
+ self.highligthedChanged = { [weak self] highlighted in
+ if let strongSelf = self {
+ strongSelf.internalHighlighted = highlighted
+ strongSelf.updateState(highlighted: highlighted, selected: strongSelf.isSelected)
+ }
+ }
+ }
+
+ private var internalHighlighted = false
+
+ override public var isSelected: Bool {
+ didSet {
+ self.updateState(highlighted: self.internalHighlighted, selected: self.isSelected)
+ }
+ }
+
+ private var currentImage: UIImage?
+
+ private func updateState(highlighted: Bool, selected: Bool) {
+ let image: UIImage?
+ if selected {
+ image = self.filledImage
+ } else if highlighted {
+ image = self.highlightedImage
+ } else {
+ image = self.regularImage
+ }
+
+ if self.currentImage !== image {
+ let currentContents = self.iconNode.layer.contents
+ self.iconNode.layer.removeAnimation(forKey: "contents")
+ if let currentContents = currentContents, let image = image {
+ self.iconNode.image = image
+ self.iconNode.layer.animate(from: currentContents as AnyObject, to: image.cgImage!, keyPath: "contents", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: image === self.currentImage || image === self.filledImage ? 0.25 : 0.15)
+ } else {
+ self.iconNode.image = image
+ }
+ self.currentImage = image
+ }
+ }
+
+ override public func layout() {
+ super.layout()
+
+ let size = self.bounds.size
+
+ self.blurView.layer.cornerRadius = size.width / 2.0
+ blurView.frame = self.bounds
+
+ self.iconNode.frame = self.bounds
+
+ if let labelNode = self.labelNode {
+ let labelSize = labelNode.measure(CGSize(width: 200.0, height: 100.0))
+ let offset: CGFloat
+ if size.width < 70.0 {
+ offset = 65.0
+ } else {
+ offset = 81.0
+ }
+ labelNode.frame = CGRect(origin: CGPoint(x: floor((size.width - labelSize.width) / 2.0), y: offset), size: labelSize)
+ }
+ }
+}
diff --git a/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift b/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift
index 3d131bfeac..742e363123 100644
--- a/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift
+++ b/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift
@@ -15,6 +15,16 @@ public struct ItemListMultilineInputItemTextLimit {
}
}
+public struct ItemListMultilineInputInlineAction {
+ public let icon: UIImage
+ public let action: (() -> Void)?
+
+ public init(icon: UIImage, action: (() -> Void)?) {
+ self.icon = icon
+ self.action = action
+ }
+}
+
public class ItemListMultilineInputItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let text: String
@@ -27,11 +37,12 @@ public class ItemListMultilineInputItem: ListViewItem, ItemListItem {
let action: (() -> Void)?
let textUpdated: (String) -> Void
let shouldUpdateText: (String) -> Bool
- public let tag: ItemListItemTag?
let maxLength: ItemListMultilineInputItemTextLimit?
let minimalHeight: CGFloat?
+ let inlineAction: ItemListMultilineInputInlineAction?
+ public let tag: ItemListItemTag?
- public init(theme: PresentationTheme, text: String, placeholder: String, maxLength: ItemListMultilineInputItemTextLimit?, sectionId: ItemListSectionId, style: ItemListStyle, capitalization: Bool = true, autocorrection: Bool = true, returnKeyType: UIReturnKeyType = .default, minimalHeight: CGFloat? = nil, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, tag: ItemListItemTag? = nil, action: (() -> Void)? = nil) {
+ public init(theme: PresentationTheme, text: String, placeholder: String, maxLength: ItemListMultilineInputItemTextLimit?, sectionId: ItemListSectionId, style: ItemListStyle, capitalization: Bool = true, autocorrection: Bool = true, returnKeyType: UIReturnKeyType = .default, minimalHeight: CGFloat? = nil, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, tag: ItemListItemTag? = nil, action: (() -> Void)? = nil, inlineAction: ItemListMultilineInputInlineAction? = nil) {
self.theme = theme
self.text = text
self.placeholder = placeholder
@@ -46,6 +57,7 @@ public class ItemListMultilineInputItem: ListViewItem, ItemListItem {
self.shouldUpdateText = shouldUpdateText
self.tag = tag
self.action = action
+ self.inlineAction = inlineAction
}
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) {
@@ -94,6 +106,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
private let measureTextNode: TextNode
private let limitTextNode: TextNode
+ private var inlineActionButtonNode: HighlightableButtonNode?
private var item: ItemListMultilineInputItem?
private var layoutParams: ListViewItemLayoutParams?
@@ -185,6 +198,10 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
rightInset += 30.0
}
+ if let inlineAction = item.inlineAction {
+ rightInset += inlineAction.icon.size.width + 8.0
+ }
+
var measureText = item.text
if measureText.hasSuffix("\n") || measureText.isEmpty {
measureText += "|"
@@ -225,6 +242,10 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor]
strongSelf.textNode.tintColor = item.theme.list.itemAccentColor
}
+
+ if let inlineAction = item.inlineAction {
+ strongSelf.inlineActionButtonNode?.setImage(generateTintedImage(image: inlineAction.icon, color: item.theme.list.itemAccentColor), for: .normal)
+ }
}
let capitalizationType: UITextAutocapitalizationType = item.capitalization ? .sentences : .none
@@ -293,6 +314,23 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
} else if strongSelf.limitTextNode.supernode != nil {
strongSelf.limitTextNode.removeFromSupernode()
}
+
+ if let inlineAction = item.inlineAction {
+ let inlineActionButtonNode: HighlightableButtonNode
+ if let currentInlineActionButtonNode = strongSelf.inlineActionButtonNode {
+ inlineActionButtonNode = currentInlineActionButtonNode
+ } else {
+ inlineActionButtonNode = HighlightableButtonNode()
+ inlineActionButtonNode.setImage(generateTintedImage(image: inlineAction.icon, color: item.theme.list.itemAccentColor), for: .normal)
+ inlineActionButtonNode.addTarget(strongSelf, action: #selector(strongSelf.inlineActionPressed), forControlEvents: .touchUpInside)
+ strongSelf.addSubnode(inlineActionButtonNode)
+ strongSelf.inlineActionButtonNode = inlineActionButtonNode
+ }
+ inlineActionButtonNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - inlineAction.icon.size.width - 11.0, y: 7.0), size: inlineAction.icon.size)
+ } else if let inlineActionButtonNode = strongSelf.inlineActionButtonNode {
+ inlineActionButtonNode.removeFromSupernode()
+ strongSelf.inlineActionButtonNode = nil
+ }
}
})
}
@@ -377,4 +415,10 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
public func animateError() {
self.textNode.layer.addShakeAnimation()
}
+
+ @objc private func inlineActionPressed() {
+ if let action = self.item?.inlineAction?.action {
+ action()
+ }
+ }
}
diff --git a/submodules/ItemListUI/Sources/Items/ItemListSectionHeaderItem.swift b/submodules/ItemListUI/Sources/Items/ItemListSectionHeaderItem.swift
index 452182202f..18d396b2b8 100644
--- a/submodules/ItemListUI/Sources/Items/ItemListSectionHeaderItem.swift
+++ b/submodules/ItemListUI/Sources/Items/ItemListSectionHeaderItem.swift
@@ -14,10 +14,27 @@ public enum ItemListSectionHeaderAccessoryTextColor {
public struct ItemListSectionHeaderAccessoryText: Equatable {
public let value: String
public let color: ItemListSectionHeaderAccessoryTextColor
+ public let icon: UIImage?
- public init(value: String, color: ItemListSectionHeaderAccessoryTextColor) {
+ public init(value: String, color: ItemListSectionHeaderAccessoryTextColor, icon: UIImage? = nil) {
self.value = value
self.color = color
+ self.icon = icon
+ }
+}
+
+public enum ItemListSectionHeaderActivityIndicator {
+ case none
+ case left
+ case right
+
+ fileprivate var hasActivity: Bool {
+ switch self {
+ case .left, .right:
+ return true
+ default:
+ return false
+ }
}
}
@@ -25,13 +42,13 @@ public class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let text: String
let multiline: Bool
- let activityIndicator: Bool
+ let activityIndicator: ItemListSectionHeaderActivityIndicator
let accessoryText: ItemListSectionHeaderAccessoryText?
public let sectionId: ItemListSectionId
public let isAlwaysPlain: Bool = true
- public init(theme: PresentationTheme, text: String, multiline: Bool = false, activityIndicator: Bool = false, accessoryText: ItemListSectionHeaderAccessoryText? = nil, sectionId: ItemListSectionId) {
+ public init(theme: PresentationTheme, text: String, multiline: Bool = false, activityIndicator: ItemListSectionHeaderActivityIndicator = .none, accessoryText: ItemListSectionHeaderAccessoryText? = nil, sectionId: ItemListSectionId) {
self.theme = theme
self.text = text
self.multiline = multiline
@@ -64,7 +81,6 @@ public class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
}
let makeLayout = nodeValue.asyncLayout()
-
async {
let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
Queue.mainQueue().async {
@@ -84,8 +100,9 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
private let titleNode: TextNode
private let accessoryTextNode: TextNode
+ private var accessoryImageNode: ASImageNode?
private var activityIndicator: ActivityIndicator?
-
+
private let activateArea: AccessibilityAreaNode
public init() {
@@ -120,6 +137,7 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.text, font: titleFont, textColor: item.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: item.multiline ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var accessoryTextString: NSAttributedString?
+ var accessoryIcon: UIImage?
if let accessoryText = item.accessoryText {
let color: UIColor
switch accessoryText.color {
@@ -129,6 +147,7 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
color = item.theme.list.freeTextErrorColor
}
accessoryTextString = NSAttributedString(string: accessoryText.value, font: titleFont, textColor: color)
+ accessoryIcon = accessoryText.icon
}
let (accessoryLayout, accessoryApply) = makeAccessoryTextLayout(TextNodeLayoutArguments(attributedString: accessoryTextString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@@ -158,10 +177,33 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
strongSelf.activateArea.accessibilityLabel = item.text
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 7.0), size: titleLayout.size)
- strongSelf.accessoryTextNode.frame = CGRect(origin: CGPoint(x: params.width - leftInset - accessoryLayout.size.width, y: 7.0), size: accessoryLayout.size)
+
+ var accessoryTextOffset: CGFloat = 0.0
+ if let accessoryIcon = accessoryIcon {
+ accessoryTextOffset += accessoryIcon.size.width + 3.0
+ }
+ strongSelf.accessoryTextNode.frame = CGRect(origin: CGPoint(x: params.width - leftInset - accessoryLayout.size.width - accessoryTextOffset, y: 7.0), size: accessoryLayout.size)
+
+ if let accessoryIcon = accessoryIcon {
+ let accessoryImageNode: ASImageNode
+ if let currentAccessoryImageNode = strongSelf.accessoryImageNode {
+ accessoryImageNode = currentAccessoryImageNode
+ } else {
+ accessoryImageNode = ASImageNode()
+ accessoryImageNode.displaysAsynchronously = false
+ accessoryImageNode.displayWithoutProcessing = true
+ strongSelf.addSubnode(accessoryImageNode)
+ strongSelf.accessoryImageNode = accessoryImageNode
+ }
+ accessoryImageNode.image = accessoryIcon
+ accessoryImageNode.frame = CGRect(origin: CGPoint(x: params.width - leftInset - accessoryIcon.size.width, y: 7.0), size: accessoryIcon.size)
+ } else if let accessoryImageNode = strongSelf.accessoryImageNode {
+ accessoryImageNode.removeFromSupernode()
+ strongSelf.accessoryImageNode = nil
+ }
if previousItem?.activityIndicator != item.activityIndicator {
- if item.activityIndicator {
+ if item.activityIndicator.hasActivity {
let activityIndicator: ActivityIndicator
if let currentActivityIndicator = strongSelf.activityIndicator {
activityIndicator = currentActivityIndicator
@@ -183,7 +225,18 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
}
}
- strongSelf.activityIndicator?.frame = CGRect(origin: CGPoint(x: strongSelf.titleNode.frame.maxX + 6.0, y: 7.0 - UIScreenPixel), size: CGSize(width: 18.0, height: 18.0))
+ var activityIndicatorOrigin: CGPoint?
+ switch item.activityIndicator {
+ case .left:
+ activityIndicatorOrigin = CGPoint(x: strongSelf.titleNode.frame.maxX + 6.0, y: 7.0 - UIScreenPixel)
+ case .right:
+ activityIndicatorOrigin = CGPoint(x: params.width - leftInset - 18.0, y: 7.0 - UIScreenPixel)
+ default:
+ break
+ }
+ if let activityIndicatorOrigin = activityIndicatorOrigin {
+ strongSelf.activityIndicator?.frame = CGRect(origin: activityIndicatorOrigin, size: CGSize(width: 18.0, height: 18.0))
+ }
}
})
}
diff --git a/submodules/MtProtoKit/TON/TON.h b/submodules/MtProtoKit/TON/TON.h
index 21051e8dee..17c500e573 100644
--- a/submodules/MtProtoKit/TON/TON.h
+++ b/submodules/MtProtoKit/TON/TON.h
@@ -43,8 +43,9 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) int64_t value;
@property (nonatomic, strong, readonly) NSString * _Nonnull source;
@property (nonatomic, strong, readonly) NSString * _Nonnull destination;
+@property (nonatomic, strong, readonly) NSString * _Nonnull textMessage;
-- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination;
+- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination textMessage:(NSString * _Nonnull)textMessage;
@end
@@ -80,7 +81,7 @@ NS_ASSUME_NONNULL_BEGIN
- (MTSignal *)getTestGiverAddress;
- (MTSignal *)testGiverSendGramsWithAccountState:(TONAccountState *)accountState accountAddress:(NSString *)accountAddress amount:(int64_t)amount;
- (MTSignal *)getAccountStateWithAddress:(NSString *)accountAddress;
-- (MTSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount;
+- (MTSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSString *)textMessage;
- (MTSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword;
- (MTSignal *)importKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword wordList:(NSArray *)wordList;
- (MTSignal *)deleteKeyWithPublicKey:(NSString *)publicKey;
diff --git a/submodules/MtProtoKit/TON/TON.mm b/submodules/MtProtoKit/TON/TON.mm
index a1d75df6eb..a1da48eb10 100644
--- a/submodules/MtProtoKit/TON/TON.mm
+++ b/submodules/MtProtoKit/TON/TON.mm
@@ -42,11 +42,15 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
return nil;
}
NSString *source = readString(message->source_);
- NSString *destination = readString(message->source_);
+ NSString *destination = readString(message->destination_);
+ NSString *textMessage = readString(message->message_);
if (source == nil || destination == nil) {
return nil;
}
- return [[TONTransactionMessage alloc] initWithValue:message->value_ source:source destination:destination];
+ if (textMessage == nil) {
+ textMessage = @"";
+ }
+ return [[TONTransactionMessage alloc] initWithValue:message->value_ source:source destination:destination textMessage:textMessage];
}
@implementation TONKey
@@ -91,12 +95,13 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
@implementation TONTransactionMessage
-- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination {
+- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination textMessage:(NSString * _Nonnull)textMessage {
self = [super init];
if (self != nil) {
_value = value;
_source = source;
_destination = destination;
+ _textMessage = textMessage;
}
return self;
}
@@ -449,7 +454,12 @@ typedef enum {
}
}];
- auto query = make_object(make_object(accountAddress.UTF8String), accountState.seqno, amount);
+ auto query = make_object(make_object(
+ accountAddress.UTF8String),
+ accountState.seqno,
+ amount,
+ std::string()
+ );
_client->send({ requestId, std::move(query) });
return [[MTBlockDisposable alloc] initWithBlock:^{
@@ -493,13 +503,18 @@ typedef enum {
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
-- (MTSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount {
+- (MTSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSString * _Nonnull)textMessage {
return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) {
NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding];
if (publicKeyData == nil) {
[subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in sendGramsFromKey"]];
return [[MTBlockDisposable alloc] initWithBlock:^{}];
}
+ NSData *textMessageData = [textMessage dataUsingEncoding:NSUTF8StringEncoding];
+ if (textMessageData == nil) {
+ [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in sendGramsFromKey"]];
+ return [[MTBlockDisposable alloc] initWithBlock:^{}];
+ }
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
@@ -523,7 +538,8 @@ typedef enum {
),
make_object(fromAddress.UTF8String),
make_object(address.UTF8String),
- amount
+ amount,
+ makeString(textMessageData)
);
_client->send({ requestId, std::move(query) });
diff --git a/submodules/PeerInfoUI/Sources/SecretChatKeyController.swift b/submodules/PeerInfoUI/Sources/SecretChatKeyController.swift
index 40dc5a7f67..6a10c006f6 100644
--- a/submodules/PeerInfoUI/Sources/SecretChatKeyController.swift
+++ b/submodules/PeerInfoUI/Sources/SecretChatKeyController.swift
@@ -27,6 +27,8 @@ final class SecretChatKeyController: ViewController {
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
+ self.navigationPresentation = .modal
+
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.title = self.presentationData.strings.EncryptionKey_Title
}
diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift
index cd5c41fe47..2080e27999 100644
--- a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift
+++ b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift
@@ -192,7 +192,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
case let .header(theme, text):
return PeersNearbyHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .usersHeader(theme, text, loading):
- return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading, sectionId: self.section)
+ return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
case let .empty(theme, text):
return ItemListPlaceholderItem(theme: theme, text: text, sectionId: self.section, style: .blocks)
case let .user(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
@@ -200,7 +200,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
arguments.openChat(peer.peer.0)
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, hasTopGroupInset: false, tag: nil)
case let .groupsHeader(theme, text, loading):
- return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading, sectionId: self.section)
+ return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
case let .createGroup(theme, title, latitude, longitude, address):
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.createGroupIcon(theme), title: title, alwaysPlain: false, sectionId: self.section, editing: false, action: {
if let latitude = latitude, let longitude = longitude {
diff --git a/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj b/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj
index 4a3bb76ff3..cf28f35d43 100644
--- a/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj
+++ b/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj
@@ -429,6 +429,19 @@
explicitFileType
archive.ar
+ 1DD70E29BCD8FADE00000000
+
+ isa
+ PBXFileReference
+ name
+ libGlassButtonNode.a
+ path
+ libGlassButtonNode.a
+ sourceTree
+ BUILT_PRODUCTS_DIR
+ explicitFileType
+ archive.ar
+
1DD70E29F8FF5A6500000000
isa
@@ -1584,6 +1597,7 @@
1DD70E29FF334B1F00000000
1DD70E29F29DEA1400000000
1DD70E29D1EB356900000000
+ 1DD70E29BCD8FADE00000000
1DD70E29F8FF5A6500000000
1DD70E2947B6256000000000
1DD70E2971ED41B100000000
@@ -4796,6 +4810,13 @@
fileRef
1DD70E29BFBD457D00000000
+ E7A30F04BCD8FADE00000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E29BCD8FADE00000000
+
E7A30F04D097476500000000
isa
@@ -4933,6 +4954,7 @@
E7A30F04DA3FBAD600000000
E7A30F04D81471E200000000
E7A30F04BFBD457D00000000
+ E7A30F04BCD8FADE00000000
E7A30F04D097476500000000
E7A30F04A7E1559B00000000
E7A30F04DF12291E00000000
diff --git a/submodules/SettingsUI/Sources/DebugController.swift b/submodules/SettingsUI/Sources/DebugController.swift
index bba8987083..aa7b247e47 100644
--- a/submodules/SettingsUI/Sources/DebugController.swift
+++ b/submodules/SettingsUI/Sources/DebugController.swift
@@ -479,6 +479,8 @@ private enum DebugControllerEntry: ItemListNodeEntry {
guard let context = arguments.context else {
return
}
+ let _ = debugDeleteWallets(postbox: context.account.postbox).start()
+ return
let _ = (availableWallets(postbox: context.account.postbox)
|> deliverOnMainQueue).start(next: { wallets in
if let tonContext = context.tonContext {
diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift
index 2bae821282..96802ba9f2 100644
--- a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift
+++ b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift
@@ -808,8 +808,17 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
}
}
- return combineLatest(watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings)
- |> map { watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings in
+ let hasWallet = context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
+ |> take(1)
+ |> map { view -> Bool in
+ let appConfiguration = view.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? .defaultValue
+ let configuration = WalletConfiguration.with(appConfiguration: appConfiguration)
+ return configuration.enabled
+ }
+
+
+ return combineLatest(watchAppInstalled, hasWallet, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings)
+ |> map { watchAppInstalled, hasWallet, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings in
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
var allItems: [SettingsSearchableItem] = []
@@ -858,12 +867,14 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
})
allItems.append(passport)
- let wallet = SettingsSearchableItem(id: .wallet(0), title: "Wallet", alternate: synonyms("Wallet"), icon: .passport, breadcrumbs: [], present: { context, _, present in
- openWallet(context: context, push: { c in
- present(.push, c)
+ if hasWallet {
+ let wallet = SettingsSearchableItem(id: .wallet(0), title: "Wallet", alternate: synonyms("Wallet"), icon: .passport, breadcrumbs: [], present: { context, _, present in
+ openWallet(context: context, push: { c in
+ present(.push, c)
+ })
})
- })
- allItems.append(wallet)
+ allItems.append(wallet)
+ }
let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: synonyms(strings.SettingsSearch_Synonyms_Support), icon: .support, breadcrumbs: [], present: { context, _, present in
let _ = (supportPeerId(account: context.account)
diff --git a/submodules/SettingsUI/Sources/SettingsController.swift b/submodules/SettingsUI/Sources/SettingsController.swift
index fa38b0f10b..cf7b3e3846 100644
--- a/submodules/SettingsUI/Sources/SettingsController.swift
+++ b/submodules/SettingsUI/Sources/SettingsController.swift
@@ -453,7 +453,7 @@ private enum SettingsEntry: ItemListNodeEntry {
case let .proxy(theme, image, text, value):
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
arguments.openProxy()
- }, clearHighlightAutomatically: false)
+ })
case let .savedMessages(theme, image, text):
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
arguments.openSavedMessages()
@@ -516,7 +516,7 @@ private struct SettingsState: Equatable {
var isSearching: Bool
}
-private func settingsEntries(account: Account, presentationData: PresentationData, state: SettingsState, view: PeerView, proxySettings: ProxySettings, notifyExceptions: NotificationExceptionsList?, notificationsAuthorizationStatus: AccessType, notificationsWarningSuppressed: Bool, unreadTrendingStickerPacks: Int, archivedPacks: [ArchivedStickerPackItem]?, privacySettings: AccountPrivacySettings?, hasPassport: Bool, hasWatchApp: Bool, accountsAndPeers: [(Account, Peer, Int32)], inAppNotificationSettings: InAppNotificationSettings, experimentalUISettings: ExperimentalUISettings, displayPhoneNumberConfirmation: Bool) -> [SettingsEntry] {
+private func settingsEntries(account: Account, presentationData: PresentationData, state: SettingsState, view: PeerView, proxySettings: ProxySettings, notifyExceptions: NotificationExceptionsList?, notificationsAuthorizationStatus: AccessType, notificationsWarningSuppressed: Bool, unreadTrendingStickerPacks: Int, archivedPacks: [ArchivedStickerPackItem]?, privacySettings: AccountPrivacySettings?, hasWallet: Bool, hasPassport: Bool, hasWatchApp: Bool, accountsAndPeers: [(Account, Peer, Int32)], inAppNotificationSettings: InAppNotificationSettings, experimentalUISettings: ExperimentalUISettings, displayPhoneNumberConfirmation: Bool) -> [SettingsEntry] {
var entries: [SettingsEntry] = []
if let peer = peerViewMainPeer(view) as? TelegramUser {
@@ -577,7 +577,7 @@ private func settingsEntries(account: Account, presentationData: PresentationDat
if hasPassport {
entries.append(.passport(presentationData.theme, PresentationResourcesSettings.passport, presentationData.strings.Settings_Passport, ""))
}
- if experimentalUISettings.wallets {
+ if hasWallet || experimentalUISettings.wallets {
entries.append(.wallet(presentationData.theme, PresentationResourcesSettings.passport, "Wallet", ""))
}
@@ -1098,6 +1098,17 @@ public func settingsController(context: AccountContext, accountManager: AccountM
)
)
+ let hasWallet = .single(false)
+ |> then(contextValue.get()
+ |> mapToSignal { context in
+ return context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
+ |> map { view -> Bool in
+ let appConfiguration = view.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? .defaultValue
+ let configuration = WalletConfiguration.with(appConfiguration: appConfiguration)
+ return configuration.enabled
+ }
+ })
+
let hasPassport = ValuePromise(false)
let updatePassport: () -> Void = {
updatePassportDisposable.set((
@@ -1206,8 +1217,8 @@ public func settingsController(context: AccountContext, accountManager: AccountM
return context.account.viewTracker.featuredStickerPacks()
}
- let signal = combineLatest(queue: Queue.mainQueue(), contextValue.get(), updatedPresentationData, statePromise.get(), peerView, combineLatest(queue: Queue.mainQueue(), preferences, notifyExceptions.get(), notificationsAuthorizationStatus.get(), notificationsWarningSuppressed.get(), privacySettings.get(), displayPhoneNumberConfirmation.get()), combineLatest(featuredStickerPacks, archivedPacks.get()), combineLatest(hasPassport.get(), hasWatchApp.get()), accountsAndPeers.get())
- |> map { context, presentationData, state, view, preferencesAndExceptions, featuredAndArchived, hasPassportAndWatch, accountsAndPeers -> (ItemListControllerState, (ItemListNodeState, SettingsEntry.ItemGenerationArguments)) in
+ let signal = combineLatest(queue: Queue.mainQueue(), contextValue.get(), updatedPresentationData, statePromise.get(), peerView, combineLatest(queue: Queue.mainQueue(), preferences, notifyExceptions.get(), notificationsAuthorizationStatus.get(), notificationsWarningSuppressed.get(), privacySettings.get(), displayPhoneNumberConfirmation.get()), combineLatest(featuredStickerPacks, archivedPacks.get()), combineLatest(hasWallet, hasPassport.get(), hasWatchApp.get()), accountsAndPeers.get())
+ |> map { context, presentationData, state, view, preferencesAndExceptions, featuredAndArchived, hasWalletPassportAndWatch, accountsAndPeers -> (ItemListControllerState, (ItemListNodeState, SettingsEntry.ItemGenerationArguments)) in
let proxySettings: ProxySettings = preferencesAndExceptions.0.entries[SharedDataKeys.proxySettings] as? ProxySettings ?? ProxySettings.defaultSettings
let inAppNotificationSettings: InAppNotificationSettings = preferencesAndExceptions.0.entries[ApplicationSpecificSharedDataKeys.inAppNotificationSettings] as? InAppNotificationSettings ?? InAppNotificationSettings.defaultSettings
let experimentalUISettings: ExperimentalUISettings = preferencesAndExceptions.0.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings] as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
@@ -1244,8 +1255,8 @@ public func settingsController(context: AccountContext, accountManager: AccountM
pushControllerImpl?(c)
}, getNavigationController: getNavigationControllerImpl, exceptionsList: notifyExceptions.get(), archivedStickerPacks: archivedPacks.get(), privacySettings: privacySettings.get())
- let (hasPassport, hasWatchApp) = hasPassportAndWatch
- let listState = ItemListNodeState(entries: settingsEntries(account: context.account, presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, notifyExceptions: preferencesAndExceptions.1, notificationsAuthorizationStatus: preferencesAndExceptions.2, notificationsWarningSuppressed: preferencesAndExceptions.3, unreadTrendingStickerPacks: unreadTrendingStickerPacks, archivedPacks: featuredAndArchived.1, privacySettings: preferencesAndExceptions.4, hasPassport: hasPassport, hasWatchApp: hasWatchApp, accountsAndPeers: accountsAndPeers.1, inAppNotificationSettings: inAppNotificationSettings, experimentalUISettings: experimentalUISettings, displayPhoneNumberConfirmation: preferencesAndExceptions.5), style: .blocks, searchItem: searchItem, initialScrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up))
+ let (hasWallet, hasPassport, hasWatchApp) = hasWalletPassportAndWatch
+ let listState = ItemListNodeState(entries: settingsEntries(account: context.account, presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, notifyExceptions: preferencesAndExceptions.1, notificationsAuthorizationStatus: preferencesAndExceptions.2, notificationsWarningSuppressed: preferencesAndExceptions.3, unreadTrendingStickerPacks: unreadTrendingStickerPacks, archivedPacks: featuredAndArchived.1, privacySettings: preferencesAndExceptions.4, hasWallet: hasWallet, hasPassport: hasPassport, hasWatchApp: hasWatchApp, accountsAndPeers: accountsAndPeers.1, inAppNotificationSettings: inAppNotificationSettings, experimentalUISettings: experimentalUISettings, displayPhoneNumberConfirmation: preferencesAndExceptions.5), style: .blocks, searchItem: searchItem, initialScrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up))
return (controllerState, (listState, arguments))
}
diff --git a/submodules/TelegramCore/TelegramCore/Wallets.swift b/submodules/TelegramCore/TelegramCore/Wallets.swift
index d299929367..4a112da79f 100644
--- a/submodules/TelegramCore/TelegramCore/Wallets.swift
+++ b/submodules/TelegramCore/TelegramCore/Wallets.swift
@@ -69,10 +69,33 @@ public final class TonInstance {
})
}
- fileprivate func createWallet(keychain: TonKeychain, serverSalt: Data) -> Signal<(WalletInfo, [String]), NoError> {
+ fileprivate func exportKey(key: TONKey, serverSalt: Data) -> Signal<[String], NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
+ self.impl.with { impl in
+ impl.withInstance { ton in
+ let cancel = ton.export(key, localPassword: serverSalt).start(next: { wordList in
+ guard let wordList = wordList as? [String] else {
+ assertionFailure()
+ return
+ }
+ subscriber.putNext(wordList)
+ subscriber.putCompletion()
+ })
+ disposable.set(ActionDisposable {
+ cancel?.dispose()
+ })
+ }
+ }
+
+ return disposable
+ }
+ }
+
+ fileprivate func createWallet(keychain: TonKeychain, serverSalt: Data) -> Signal<(WalletInfo, [String]), NoError> {
+ return Signal { subscriber in
+ let disposable = MetaDisposable()
self.impl.with { impl in
impl.withInstance { ton in
let cancel = ton.createKey(withLocalPassword: serverSalt, mnemonicPassword: Data()).start(next: { key in
@@ -85,13 +108,11 @@ public final class TonInstance {
assertionFailure()
return
}
- let cancel = ton.export(key, localPassword: serverSalt).start(next: { wordList in
- guard let wordList = wordList as? [String] else {
- assertionFailure()
- return
- }
+ let _ = self.exportKey(key: key, serverSalt: serverSalt).start(next: { wordList in
subscriber.putNext((WalletInfo(publicKey: WalletPublicKey(rawValue: key.publicKey), encryptedSecret: EncryptedWalletSecret(rawValue: encryptedSecretData)), wordList))
subscriber.putCompletion()
+ }, error: { _ in
+ preconditionFailure()
})
}, error: { _ in
}, completed: {
@@ -195,30 +216,20 @@ public final class TonInstance {
}
}
- fileprivate func walletBalance(publicKey: WalletPublicKey) -> Signal {
+ fileprivate func getWalletState(address: String) -> Signal {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
impl.withInstance { ton in
- let cancel = ton.getTestWalletAccountAddress(withPublicKey: publicKey.rawValue).start(next: { address in
- guard let address = address as? String else {
+ let cancel = ton.getAccountState(withAddress: address).start(next: { state in
+ guard let state = state as? TONAccountState else {
return
}
- let cancel = ton.getAccountState(withAddress: address).start(next: { state in
- guard let state = state as? TONAccountState else {
- return
- }
- subscriber.putNext(WalletBalance(rawValue: state.balance))
- }, error: { _ in
- }, completed: {
- subscriber.putCompletion()
- })
- disposable.set(ActionDisposable {
- cancel?.dispose()
- })
+ subscriber.putNext(WalletState(balance: state.balance, lastTransactionId: state.lastTransactionId.flatMap(WalletTransactionId.init(tonTransactionId:))))
}, error: { _ in
}, completed: {
+ subscriber.putCompletion()
})
disposable.set(ActionDisposable {
cancel?.dispose()
@@ -282,17 +293,39 @@ public final class TonInstance {
}
}
- fileprivate func getGramsFromTestGiver(address: String, amount: Int64) -> Signal {
+ fileprivate func getTestGiverAccountState() -> Signal {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
impl.withInstance { ton in
let cancel = ton.getTestGiverAccountState().start(next: { state in
- guard let state = state as? TONAccountState else {
- subscriber.putError(.generic)
- return
- }
+ subscriber.putNext(state as? TONAccountState)
+ subscriber.putCompletion()
+ }, error: { _ in
+ subscriber.putNext(nil)
+ subscriber.putCompletion()
+ }, completed: {
+ })
+ }
+ }
+
+ return disposable
+ }
+ }
+
+ fileprivate func getGramsFromTestGiver(address: String, amount: Int64) -> Signal {
+ return self.getTestGiverAccountState()
+ |> introduceError(GetGramsFromTestGiverError.self)
+ |> mapToSignal { state in
+ guard let state = state else {
+ return .fail(.generic)
+ }
+ return Signal { subscriber in
+ let disposable = MetaDisposable()
+
+ self.impl.with { impl in
+ impl.withInstance { ton in
let cancel = ton.testGiverSendGrams(with: state, accountAddress: address, amount: amount).start(next: { _ in
}, error: { _ in
subscriber.putError(.generic)
@@ -302,17 +335,11 @@ public final class TonInstance {
disposable.set(ActionDisposable {
cancel?.dispose()
})
- }, error: { _ in
- subscriber.putError(.generic)
- }, completed: {
- })
- disposable.set(ActionDisposable {
- cancel?.dispose()
- })
+ }
}
+
+ return disposable
}
-
- return disposable
}
}
@@ -368,7 +395,7 @@ public final class TonInstance {
}
}
- fileprivate func sendGramsFromWallet(keychain: TonKeychain, serverSalt: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64) -> Signal {
+ fileprivate func sendGramsFromWallet(keychain: TonKeychain, serverSalt: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: String) -> Signal {
return keychain.decrypt(walletInfo.encryptedSecret.rawValue)
|> introduceError(SendGramsFromWalletError.self)
|> mapToSignal { decryptedSecret -> Signal in
@@ -380,9 +407,9 @@ public final class TonInstance {
self.impl.with { impl in
impl.withInstance { ton in
- let cancel = ton.sendGrams(from: TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret), localPassword: serverSalt, fromAddress: fromAddress, toAddress: toAddress, amount: amount).start(next: { _ in
+ let cancel = ton.sendGrams(from: TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret), localPassword: serverSalt, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage).start(next: { _ in
preconditionFailure()
- }, error: { _ in
+ }, error: { error in
subscriber.putError(.generic)
}, completed: {
subscriber.putCompletion()
@@ -578,11 +605,13 @@ public func walletRestoreWords(network: Network, walletInfo: WalletInfo, tonInst
}
}
-public struct WalletBalance: Hashable {
- public var rawValue: Int64
+public struct WalletState: Equatable {
+ public let balance: Int64
+ public let lastTransactionId: WalletTransactionId?
- public init(rawValue: Int64) {
- self.rawValue = rawValue
+ public init(balance: Int64, lastTransactionId: WalletTransactionId?) {
+ self.balance = balance
+ self.lastTransactionId = lastTransactionId
}
}
@@ -594,8 +623,8 @@ public func testGiverWalletAddress(tonInstance: TonInstance) -> Signal Signal {
- return tonInstance.walletBalance(publicKey: publicKey)
+public func getWalletState(address: String, tonInstance: TonInstance) -> Signal {
+ return tonInstance.getWalletState(address: address)
}
public enum GetGramsFromTestGiverError {
@@ -611,7 +640,7 @@ public enum SendGramsFromWalletError {
case secretDecryptionFailed
}
-public func sendGramsFromWallet(network: Network, tonInstance: TonInstance, keychain: TonKeychain, walletInfo: WalletInfo, toAddress: String, amount: Int64) -> Signal {
+public func sendGramsFromWallet(network: Network, tonInstance: TonInstance, keychain: TonKeychain, walletInfo: WalletInfo, toAddress: String, amount: Int64, textMessage: String) -> Signal {
return getServerWalletSalt(network: network)
|> mapError { _ -> SendGramsFromWalletError in
return .generic
@@ -620,7 +649,7 @@ public func sendGramsFromWallet(network: Network, tonInstance: TonInstance, keyc
return walletAddress(publicKey: walletInfo.publicKey, tonInstance: tonInstance)
|> introduceError(SendGramsFromWalletError.self)
|> mapToSignal { fromAddress in
- return tonInstance.sendGramsFromWallet(keychain: keychain, serverSalt: serverSalt, walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount)
+ return tonInstance.sendGramsFromWallet(keychain: keychain, serverSalt: serverSalt, walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage)
}
}
}
@@ -655,11 +684,13 @@ public final class WalletTransactionMessage: Equatable {
public let value: Int64
public let source: String
public let destination: String
+ public let textMessage: String
- init(value: Int64, source: String, destination: String) {
+ init(value: Int64, source: String, destination: String, textMessage: String) {
self.value = value
self.source = source
self.destination = destination
+ self.textMessage = textMessage
}
public static func ==(lhs: WalletTransactionMessage, rhs: WalletTransactionMessage) -> Bool {
@@ -670,7 +701,10 @@ public final class WalletTransactionMessage: Equatable {
return false
}
if lhs.destination != rhs.destination {
- return false;
+ return false
+ }
+ if lhs.textMessage != rhs.textMessage {
+ return false
}
return true
}
@@ -678,7 +712,7 @@ public final class WalletTransactionMessage: Equatable {
private extension WalletTransactionMessage {
convenience init(tonTransactionMessage: TONTransactionMessage) {
- self.init(value: tonTransactionMessage.value, source: tonTransactionMessage.source, destination: tonTransactionMessage.destination)
+ self.init(value: tonTransactionMessage.value, source: tonTransactionMessage.source, destination: tonTransactionMessage.destination, textMessage: tonTransactionMessage.textMessage)
}
}
diff --git a/submodules/TelegramUI/Images.xcassets/Wallet/CameraFlashIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Wallet/CameraFlashIcon.imageset/Contents.json
new file mode 100644
index 0000000000..39f252e34f
--- /dev/null
+++ b/submodules/TelegramUI/Images.xcassets/Wallet/CameraFlashIcon.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_flash.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/submodules/TelegramUI/Images.xcassets/Wallet/CameraFlashIcon.imageset/ic_flash.pdf b/submodules/TelegramUI/Images.xcassets/Wallet/CameraFlashIcon.imageset/ic_flash.pdf
new file mode 100644
index 0000000000..68f60cae43
Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Wallet/CameraFlashIcon.imageset/ic_flash.pdf differ
diff --git a/submodules/TelegramUI/Images.xcassets/Wallet/QrIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Wallet/QrIcon.imageset/Contents.json
new file mode 100644
index 0000000000..9bead22d1f
--- /dev/null
+++ b/submodules/TelegramUI/Images.xcassets/Wallet/QrIcon.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "ic_qrcode.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/submodules/TelegramUI/Images.xcassets/Wallet/QrIcon.imageset/ic_qrcode.pdf b/submodules/TelegramUI/Images.xcassets/Wallet/QrIcon.imageset/ic_qrcode.pdf
new file mode 100644
index 0000000000..cf234b8223
Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Wallet/QrIcon.imageset/ic_qrcode.pdf differ
diff --git a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift
index f5188ec19f..908a150212 100644
--- a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift
+++ b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift
@@ -400,47 +400,55 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
if !messages[0].text.isEmpty || resourceAvailable {
let message = messages[0]
- actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopy, icon: { theme in
- return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.actionSheet.primaryTextColor)
- }, action: { _, f in
- if resourceAvailable {
- for media in message.media {
- if let image = media as? TelegramMediaImage, let largest = largestImageRepresentation(image.representations) {
- let _ = (context.account.postbox.mediaBox.resourceData(largest.resource, option: .incremental(waitUntilFetchStatus: false))
- |> take(1)
- |> deliverOnMainQueue).start(next: { data in
- if data.complete, let imageData = try? Data(contentsOf: URL(fileURLWithPath: data.path)) {
- if let image = UIImage(data: imageData) {
- if !message.text.isEmpty {
- UIPasteboard.general.string = message.text
- /*UIPasteboard.general.items = [
- [kUTTypeUTF8PlainText as String: message.text],
- [kUTTypePNG as String: image]
- ]*/
+ var isExpired = false
+ for media in message.media {
+ if let _ = media as? TelegramMediaExpiredContent {
+ isExpired = true
+ }
+ }
+ if !isExpired {
+ actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopy, icon: { theme in
+ return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.actionSheet.primaryTextColor)
+ }, action: { _, f in
+ if resourceAvailable {
+ for media in message.media {
+ if let image = media as? TelegramMediaImage, let largest = largestImageRepresentation(image.representations) {
+ let _ = (context.account.postbox.mediaBox.resourceData(largest.resource, option: .incremental(waitUntilFetchStatus: false))
+ |> take(1)
+ |> deliverOnMainQueue).start(next: { data in
+ if data.complete, let imageData = try? Data(contentsOf: URL(fileURLWithPath: data.path)) {
+ if let image = UIImage(data: imageData) {
+ if !message.text.isEmpty {
+ UIPasteboard.general.string = message.text
+ /*UIPasteboard.general.items = [
+ [kUTTypeUTF8PlainText as String: message.text],
+ [kUTTypePNG as String: image]
+ ]*/
+ } else {
+ UIPasteboard.general.image = image
+ }
} else {
- UIPasteboard.general.image = image
+ UIPasteboard.general.string = message.text
}
} else {
UIPasteboard.general.string = message.text
}
- } else {
- UIPasteboard.general.string = message.text
- }
- })
+ })
+ }
}
- }
- } else {
- var messageEntities: [MessageTextEntity]?
- for attribute in message.attributes {
- if let attribute = attribute as? TextEntitiesMessageAttribute {
- messageEntities = attribute.entities
- break
+ } else {
+ var messageEntities: [MessageTextEntity]?
+ for attribute in message.attributes {
+ if let attribute = attribute as? TextEntitiesMessageAttribute {
+ messageEntities = attribute.entities
+ break
+ }
}
+ storeMessageTextInPasteboard(message.text, entities: messageEntities)
}
- storeMessageTextInPasteboard(message.text, entities: messageEntities)
- }
- f(.default)
- })))
+ f(.default)
+ })))
+ }
if resourceAvailable, !message.containsSecretMedia {
var mediaReference: AnyMediaReference?
for media in message.media {
diff --git a/submodules/TelegramUI/TelegramUI/OpenChatMessage.swift b/submodules/TelegramUI/TelegramUI/OpenChatMessage.swift
index a280fae0b8..ccd3d27004 100644
--- a/submodules/TelegramUI/TelegramUI/OpenChatMessage.swift
+++ b/submodules/TelegramUI/TelegramUI/OpenChatMessage.swift
@@ -328,6 +328,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
}))
return true
case let .other(otherMedia):
+ params.dismissInput()
if let contact = otherMedia as? TelegramMediaContact {
let _ = (params.context.account.postbox.transaction { transaction -> (Peer?, Bool?) in
if let peerId = contact.peerId {
diff --git a/submodules/TelegramUI/TelegramUI/OpenUrl.swift b/submodules/TelegramUI/TelegramUI/OpenUrl.swift
index 43ed376890..03aaf8d49d 100644
--- a/submodules/TelegramUI/TelegramUI/OpenUrl.swift
+++ b/submodules/TelegramUI/TelegramUI/OpenUrl.swift
@@ -139,6 +139,10 @@ func formattedConfirmationCode(_ code: Int) -> String {
}
func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, url: String, forceExternal: Bool, presentationData: PresentationData, navigationController: NavigationController?, dismissInput: @escaping () -> Void) {
+ if url.hasPrefix("ton://") {
+ return
+ }
+
if forceExternal || url.lowercased().hasPrefix("tel:") || url.lowercased().hasPrefix("calshow:") {
context.sharedContext.applicationBindings.openUrl(url)
return
diff --git a/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift b/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift
index c9b216e987..b29f5fae37 100644
--- a/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift
+++ b/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift
@@ -159,7 +159,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
var toolbarHeight: CGFloat = cleanInsets.bottom
if let segmentedControlNode = self.segmentedControlNode, let toolbarBackgroundNode = self.toolbarBackgroundNode, let toolbarSeparatorNode = self.toolbarSeparatorNode {
- toolbarHeight += 44
+ toolbarHeight += 44.0
transition.updateFrame(node: toolbarBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), size: CGSize(width: layout.size.width, height: toolbarHeight)))
transition.updateFrame(node: toolbarSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
@@ -169,7 +169,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
var insets = layout.insets(options: [.input])
insets.top += navigationBarHeight
- insets.bottom = max(insets.bottom, cleanInsets.bottom)
+ insets.bottom = max(insets.bottom, cleanInsets.bottom + 44.0)
insets.left += layout.safeInsets.left
insets.right += layout.safeInsets.right
diff --git a/submodules/WalletUI/BUCK b/submodules/WalletUI/BUCK
index e4ba0f4f53..b9422a5863 100644
--- a/submodules/WalletUI/BUCK
+++ b/submodules/WalletUI/BUCK
@@ -26,6 +26,7 @@ static_library(
"//submodules/QrCode:QrCode",
"//submodules/MergeLists:MergeLists",
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
+ "//submodules/GlassButtonNode:GlassButtonNode",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
diff --git a/submodules/WalletUI/Sources/WalletConfiguration.swift b/submodules/WalletUI/Sources/WalletConfiguration.swift
new file mode 100644
index 0000000000..5dc047a74b
--- /dev/null
+++ b/submodules/WalletUI/Sources/WalletConfiguration.swift
@@ -0,0 +1,22 @@
+import Foundation
+import TelegramCore
+
+public struct WalletConfiguration {
+ static var defaultValue: WalletConfiguration {
+ return WalletConfiguration(enabled: false)
+ }
+
+ public let enabled: Bool
+
+ fileprivate init(enabled: Bool) {
+ self.enabled = enabled
+ }
+
+ public static func with(appConfiguration: AppConfiguration) -> WalletConfiguration {
+ if let data = appConfiguration.data, let enabled = data["wallet_enabled"] as? Bool {
+ return WalletConfiguration(enabled: enabled)
+ } else {
+ return .defaultValue
+ }
+ }
+}
diff --git a/submodules/WalletUI/Sources/WalletInfoScreen.swift b/submodules/WalletUI/Sources/WalletInfoScreen.swift
index ebb092dcb5..b6698ec221 100644
--- a/submodules/WalletUI/Sources/WalletInfoScreen.swift
+++ b/submodules/WalletUI/Sources/WalletInfoScreen.swift
@@ -17,6 +17,7 @@ public final class WalletInfoScreen: ViewController {
private let tonContext: TonContext
private let walletInfo: WalletInfo
private let address: String
+ private let walletState = Promise()
private var presentationData: PresentationData
@@ -44,6 +45,8 @@ public final class WalletInfoScreen: ViewController {
self.scrollToTop = { [weak self] in
(self?.displayNode as? WalletInfoScreenNode)?.scrollToTop()
}
+
+ self.walletState.set(Signal.single(nil) |> then(getWalletState(address: address, tonInstance: tonContext.instance) |> map(Optional.init)))
}
required init(coder aDecoder: NSCoder) {
@@ -59,11 +62,18 @@ public final class WalletInfoScreen: ViewController {
}
override public func loadDisplayNode() {
- self.displayNode = WalletInfoScreenNode(account: self.context.account, tonContext: self.tonContext, presentationData: self.presentationData, walletInfo: self.walletInfo, address: self.address, sendAction: { [weak self] in
+ self.displayNode = WalletInfoScreenNode(account: self.context.account, tonContext: self.tonContext, presentationData: self.presentationData, walletInfo: self.walletInfo, address: self.address, walletState: self.walletState.get(), sendAction: { [weak self] in
guard let strongSelf = self else {
return
}
- strongSelf.push(walletSendScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: strongSelf.walletInfo))
+ let _ = (strongSelf.walletState.get()
+ |> take(1)
+ |> deliverOnMainQueue).start(next: { [weak self] walletState in
+ guard let strongSelf = self else {
+ return
+ }
+ strongSelf.push(walletSendScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: strongSelf.walletInfo, walletState: walletState))
+ })
}, receiveAction: { [weak self] in
guard let strongSelf = self else {
return
@@ -87,8 +97,8 @@ public final class WalletInfoScreen: ViewController {
}
private final class WalletInfoBalanceNode: ASDisplayNode {
- private let balanceTextNode: ImmediateTextNode
- private let balanceIconNode: ASImageNode
+ let balanceTextNode: ImmediateTextNode
+ let balanceIconNode: ASImageNode
var balance: String = " " {
didSet {
@@ -96,6 +106,8 @@ private final class WalletInfoBalanceNode: ASDisplayNode {
}
}
+ var isLoading: Bool = true
+
init(theme: PresentationTheme) {
self.balanceTextNode = ImmediateTextNode()
self.balanceTextNode.displaysAsynchronously = false
@@ -123,9 +135,14 @@ private final class WalletInfoBalanceNode: ASDisplayNode {
let balanceOrigin = CGPoint(x: floor((width - balanceTextSize.width - balanceIconSpacing - balanceIconSize.width / 2.0) / 2.0), y: 0.0)
let balanceTextFrame = CGRect(origin: balanceOrigin, size: balanceTextSize)
- let balanceIconFrame = CGRect(origin: CGPoint(x: balanceTextFrame.maxX + balanceIconSpacing, y: balanceTextFrame.minY + floor((balanceTextFrame.height - balanceIconSize.height) / 2.0)), size: balanceIconSize)
+ let balanceIconFrame: CGRect
+ if self.isLoading {
+ balanceIconFrame = CGRect(origin: CGPoint(x: floor((width - balanceIconSize.width) / 2.0), y: balanceTextFrame.minY + floor((balanceTextFrame.height - balanceIconSize.height) / 2.0)), size: balanceIconSize)
+ } else {
+ balanceIconFrame = CGRect(origin: CGPoint(x: balanceTextFrame.maxX + balanceIconSpacing, y: balanceTextFrame.minY + floor((balanceTextFrame.height - balanceIconSize.height) / 2.0)), size: balanceIconSize)
+ }
transition.updateFrameAdditive(node: self.balanceTextNode, frame: balanceTextFrame)
- transition.updateFrameAdditive(node: self.balanceIconNode, frame: balanceIconFrame)
+ transition.updateFrame(node: self.balanceIconNode, frame: balanceIconFrame)
return balanceTextSize.height
}
@@ -245,10 +262,10 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
}
}
if self.balance == nil {
- self.balanceNode.isHidden = true
+ self.balanceNode.balanceTextNode.isHidden = true
self.balanceSubtitleNode.isHidden = true
} else {
- self.balanceNode.isHidden = false
+ self.balanceNode.balanceTextNode.isHidden = false
self.balanceSubtitleNode.isHidden = false
}
transition.updateFrame(node: self.receiveButtonNode, frame: receiveButtonFrame)
@@ -272,7 +289,8 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
func animateIn() {
self.sendButtonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.receiveButtonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
- self.balanceNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
+ self.balanceNode.isLoading = false
+ self.balanceNode.balanceTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.balanceSubtitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
@@ -348,6 +366,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
private var presentationData: PresentationData
private let walletInfo: WalletInfo
private let address: String
+
private let openTransaction: (WalletTransaction) -> Void
private let headerNode: WalletInfoHeaderNode
@@ -366,7 +385,9 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
private var currentEntries: [WalletInfoListEntry]?
- init(account: Account, tonContext: TonContext, presentationData: PresentationData, walletInfo: WalletInfo, address: String, sendAction: @escaping () -> Void, receiveAction: @escaping () -> Void, openTransaction: @escaping (WalletTransaction) -> Void) {
+ private var isReady: Bool = false
+
+ init(account: Account, tonContext: TonContext, presentationData: PresentationData, walletInfo: WalletInfo, address: String, walletState: Signal, sendAction: @escaping () -> Void, receiveAction: @escaping () -> Void, openTransaction: @escaping (WalletTransaction) -> Void) {
self.account = account
self.tonContext = tonContext
self.presentationData = presentationData
@@ -379,24 +400,29 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.listNode = ListView()
self.listNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
+ self.listNode.isHidden = true
super.init()
self.backgroundColor = .white
- self.balanceDisposable.set((currentWalletBalance(publicKey: walletInfo.publicKey, tonInstance: tonContext.instance)
+ self.balanceDisposable.set((walletState
|> deliverOnMainQueue).start(next: { [weak self] value in
- guard let strongSelf = self else {
+ guard let strongSelf = self, let value = value else {
return
}
- let firstTime = strongSelf.headerNode.balance == nil
- strongSelf.headerNode.balanceNode.balance = formatBalanceText(max(0, value.rawValue), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator)
- strongSelf.headerNode.balance = max(0, value.rawValue)
+
+ strongSelf.headerNode.balanceNode.balance = formatBalanceText(max(0, value.balance), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator)
+ strongSelf.headerNode.balance = max(0, value.balance)
+
if let (layout, navigationHeight) = strongSelf.validLayout {
strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
}
- if firstTime {
- strongSelf.headerNode.animateIn()
+
+ let wasReady = strongSelf.isReady
+ strongSelf.isReady = strongSelf.headerNode.balance != nil && strongSelf.currentEntries != nil
+ if strongSelf.isReady && !wasReady {
+ strongSelf.animateReadyIn()
}
}))
@@ -412,7 +438,9 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
strongSelf.listOffset = offset
- strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: offset, transition: listTransition)
+ if strongSelf.isReady {
+ strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: offset, transition: listTransition)
+ }
}
self.listNode.visibleBottomContentOffsetChanged = { [weak self] offset in
@@ -448,6 +476,11 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.refreshTransactions()
}
+ deinit {
+ self.balanceDisposable.dispose()
+ self.transactionListDisposable.dispose()
+ }
+
func scrollToHideHeader() {
guard let (_, navigationHeight) = self.validLayout else {
return
@@ -466,11 +499,22 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
let headerHeight: CGFloat = navigationHeight + 260.0
let topInset: CGFloat = headerHeight
- let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: headerHeight))
- transition.updateFrame(node: self.headerNode, frame: headerFrame)
- self.headerNode.update(size: headerFrame.size, navigationHeight: navigationHeight, offset: self.listOffset ?? 0.0, transition: transition)
+ let visualHeaderHeight: CGFloat
+ let visualHeaderOffset: CGFloat
+ if !self.isReady {
+ visualHeaderHeight = layout.size.height
+ visualHeaderOffset = visualHeaderHeight
+ } else {
+ visualHeaderHeight = headerHeight
+ visualHeaderOffset = self.listOffset ?? 0.0
+ }
+ let visualListOffset = visualHeaderHeight - headerHeight
- transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: layout.size))
+ let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: visualHeaderHeight))
+ transition.updateFrame(node: self.headerNode, frame: headerFrame)
+ self.headerNode.update(size: headerFrame.size, navigationHeight: navigationHeight, offset: visualHeaderOffset, transition: transition)
+
+ transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(x: 0.0, y: visualListOffset), size: layout.size))
var duration: Double = 0.0
var curve: UInt = 0
@@ -601,8 +645,11 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.enqueuedTransactions.append(transaction)
self.dequeueTransaction()
- if isFirst {
- self.listNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
+ let wasReady = self.isReady
+ self.isReady = self.headerNode.balance != nil && self.currentEntries != nil
+
+ if self.isReady && !wasReady {
+ self.animateReadyIn()
}
}
@@ -621,6 +668,14 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.listNode.transaction(deleteIndices: transaction.deletions, insertIndicesAndItems: transaction.insertions, updateIndicesAndItems: transaction.updates, options: options, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { _ in
})
}
+
+ private func animateReadyIn() {
+ self.listNode.isHidden = false
+ self.headerNode.animateIn()
+ if let (layout, navigationHeight) = self.validLayout {
+ self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.5, curve: .spring))
+ }
+ }
}
func formatBalanceText(_ value: Int64, decimalSeparator: String) -> String {
diff --git a/submodules/WalletUI/Sources/WalletQrScanScreen.swift b/submodules/WalletUI/Sources/WalletQrScanScreen.swift
index 54522f7c85..acab010687 100644
--- a/submodules/WalletUI/Sources/WalletQrScanScreen.swift
+++ b/submodules/WalletUI/Sources/WalletQrScanScreen.swift
@@ -5,26 +5,66 @@ import AccountContext
import TelegramPresentationData
import AsyncDisplayKit
import Display
-import Postbox
+import SwiftSignalKit
import TelegramCore
-import AlertUI
+import Camera
+import GlassButtonNode
+
+private func generateFrameImage() -> UIImage? {
+ return generateImage(CGSize(width: 64.0, height: 64.0), contextGenerator: { size, context in
+ let bounds = CGRect(origin: CGPoint(), size: size)
+ context.clear(bounds)
+ context.setStrokeColor(UIColor.white.cgColor)
+ context.setLineWidth(4.0)
+ context.setLineCap(.round)
+
+ var path = CGMutablePath();
+ path.move(to: CGPoint(x: 2.0, y: 2.0 + 26.0))
+ path.addArc(tangent1End: CGPoint(x: 2.0, y: 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: 2.0), radius: 6.0)
+ path.addLine(to: CGPoint(x: 2.0 + 26.0, y: 2.0))
+ context.addPath(path)
+ context.strokePath()
+
+ path.move(to: CGPoint(x: size.width - 2.0, y: 2.0 + 26.0))
+ path.addArc(tangent1End: CGPoint(x: size.width - 2.0, y: 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: 2.0), radius: 6.0)
+ path.addLine(to: CGPoint(x: size.width - 2.0 - 26.0, y: 2.0))
+ context.addPath(path)
+ context.strokePath()
+
+ path.move(to: CGPoint(x: 2.0, y: size.height - 2.0 - 26.0))
+ path.addArc(tangent1End: CGPoint(x: 2.0, y: size.height - 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: size.height - 2.0), radius: 6.0)
+ path.addLine(to: CGPoint(x: 2.0 + 26.0, y: size.height - 2.0))
+ context.addPath(path)
+ context.strokePath()
+
+ path.move(to: CGPoint(x: size.width - 2.0, y: size.height - 2.0 - 26.0))
+ path.addArc(tangent1End: CGPoint(x: size.width - 2.0, y: size.height - 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: size.height - 2.0), radius: 6.0)
+ path.addLine(to: CGPoint(x: size.width - 2.0 - 26.0, y: size.height - 2.0))
+ context.addPath(path)
+ context.strokePath()
+ })?.stretchableImage(withLeftCapWidth: 32, topCapHeight: 32)
+}
public final class WalletQrScanScreen: ViewController {
private let context: AccountContext
- private let tonContext: TonContext
+ private let completion: (String, Int64?, String?) -> Void
private var presentationData: PresentationData
- public init(context: AccountContext, tonContext: TonContext) {
+ private var disposable: Disposable?
+
+ public init(context: AccountContext, completion: @escaping (String, Int64?, String?) -> Void) {
self.context = context
- self.tonContext = tonContext
+ self.completion = completion
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
let defaultNavigationPresentationData = NavigationBarPresentationData(presentationTheme: self.presentationData.theme, presentationStrings: self.presentationData.strings)
- let navigationBarTheme = NavigationBarTheme(buttonColor: defaultNavigationPresentationData.theme.buttonColor, disabledButtonColor: defaultNavigationPresentationData.theme.disabledButtonColor, primaryTextColor: defaultNavigationPresentationData.theme.primaryTextColor, backgroundColor: .clear, separatorColor: .clear, badgeBackgroundColor: defaultNavigationPresentationData.theme.badgeBackgroundColor, badgeStrokeColor: defaultNavigationPresentationData.theme.badgeStrokeColor, badgeTextColor: defaultNavigationPresentationData.theme.badgeTextColor)
+ let navigationBarTheme = NavigationBarTheme(buttonColor: .white, disabledButtonColor: .white, primaryTextColor: .white, backgroundColor: .clear, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: defaultNavigationPresentationData.strings))
+ self.statusBar.statusBarStyle = .White
+
self.navigationPresentation = .modalInLargeLayout
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
self.navigationBar?.intrinsicCanTransitionInline = false
@@ -36,6 +76,10 @@ public final class WalletQrScanScreen: ViewController {
fatalError("init(coder:) has not been implemented")
}
+ deinit {
+ self.disposable?.dispose()
+ }
+
@objc private func backPressed() {
self.dismiss()
}
@@ -44,6 +88,27 @@ public final class WalletQrScanScreen: ViewController {
self.displayNode = WalletQrScanScreenNode(presentationData: self.presentationData)
self.displayNodeDidLoad()
+
+// (self.displayNode as! WalletQrScanScreenNode).focusedCode.get()
+// |> map { code -> String? in
+// return code?.message
+// } |> distinctUntilChanged
+
+ self.disposable = (((self.displayNode as! WalletQrScanScreenNode).focusedCode.get()
+ |> map { code -> String? in
+ return code?.message
+ }
+ |> distinctUntilChanged
+ |> delay(2.5, queue: Queue.mainQueue()))
+ |> mapToSignal { code -> Signal in
+ return .single(code)
+ }).start(next: { [weak self] code in
+ guard let strongSelf = self, let code = code else {
+ return
+ }
+ let cleanString = code.replacingOccurrences(of: "ton://", with: "")
+ strongSelf.completion(cleanString, nil, nil)
+ })
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
@@ -55,59 +120,168 @@ public final class WalletQrScanScreen: ViewController {
private final class WalletQrScanScreenNode: ViewControllerTracingNode, UIScrollViewDelegate {
private var presentationData: PresentationData
-
+
+ private let previewNode: CameraPreviewNode
+ private let fadeNode: ASDisplayNode
+ private let topDimNode: ASDisplayNode
+ private let bottomDimNode: ASDisplayNode
+ private let leftDimNode: ASDisplayNode
+ private let rightDimNode: ASDisplayNode
+ private let frameNode: ASImageNode
+ private let torchButtonNode: GlassButtonNode
private let titleNode: ImmediateTextNode
- private let textNode: ImmediateTextNode
- private var navigationHeight: CGFloat?
+ private let camera: Camera
+ private let codeDisposable = MetaDisposable()
+
+ fileprivate let focusedCode = ValuePromise(ignoreRepeated: true)
+ private var focusedRect: CGRect?
+
+ private var validLayout: (ContainerViewLayout, CGFloat)?
init(presentationData: PresentationData) {
self.presentationData = presentationData
-
- let title: String = ""
- let text: String = ""
+ self.previewNode = CameraPreviewNode()
+ self.previewNode.backgroundColor = .black
+
+ self.fadeNode = ASDisplayNode()
+ self.fadeNode.alpha = 0.0
+ self.fadeNode.backgroundColor = .black
+
+ self.topDimNode = ASDisplayNode()
+ self.topDimNode.alpha = 0.625
+ self.topDimNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.8)
+
+ self.bottomDimNode = ASDisplayNode()
+ self.bottomDimNode.alpha = 0.625
+ self.bottomDimNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.8)
+
+ self.leftDimNode = ASDisplayNode()
+ self.leftDimNode.alpha = 0.625
+ self.leftDimNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.8)
+
+ self.rightDimNode = ASDisplayNode()
+ self.rightDimNode.alpha = 0.625
+ self.rightDimNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.8)
+
+ self.frameNode = ASImageNode()
+ self.frameNode.image = generateFrameImage()
+
+ self.torchButtonNode = GlassButtonNode(icon: UIImage(bundleImageName: "Wallet/CameraFlashIcon")!, label: nil)
self.titleNode = ImmediateTextNode()
self.titleNode.displaysAsynchronously = false
- self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(32.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
+ self.titleNode.attributedText = NSAttributedString(string: "Scan QR Code", font: Font.bold(32.0), textColor: .white)
self.titleNode.maximumNumberOfLines = 0
self.titleNode.textAlignment = .center
- self.textNode = ImmediateTextNode()
- self.textNode.displaysAsynchronously = false
- self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
- self.textNode.maximumNumberOfLines = 0
- self.textNode.lineSpacing = 0.1
- self.textNode.textAlignment = .center
+ self.camera = Camera(configuration: .init(preset: .hd1920x1080, position: .back, audio: false))
super.init()
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
+ self.addSubnode(self.previewNode)
+ self.addSubnode(self.fadeNode)
+ self.addSubnode(self.topDimNode)
+ self.addSubnode(self.bottomDimNode)
+ self.addSubnode(self.leftDimNode)
+ self.addSubnode(self.rightDimNode)
+ self.addSubnode(self.frameNode)
+ self.addSubnode(self.torchButtonNode)
self.addSubnode(self.titleNode)
- self.addSubnode(self.textNode)
+
+ self.torchButtonNode.addTarget(self, action: #selector(self.torchPressed), forControlEvents: .touchUpInside)
+ }
+
+ deinit {
+ self.codeDisposable.dispose()
+ }
+
+ override func didLoad() {
+ super.didLoad()
+
+ self.camera.attachPreviewNode(self.previewNode)
+ self.camera.startCapture()
+
+ let throttledSignal = self.camera.detectedCodes
+ |> mapToThrottled { next -> Signal<[CameraCode], NoError> in
+ return .single(next) |> then(.complete() |> delay(0.3, queue: Queue.concurrentDefaultQueue()))
+ }
+
+ self.codeDisposable.set((throttledSignal
+ |> deliverOnMainQueue).start(next: { [weak self] codes in
+ guard let strongSelf = self else {
+ return
+ }
+ let filteredCodes = codes.filter { $0.message.hasPrefix("ton://") }
+ if let code = filteredCodes.first, CGRect(x: 0.3, y: 0.3, width: 0.4, height: 0.4).contains(code.boundingBox.center) {
+ strongSelf.focusedCode.set(code)
+ strongSelf.updateFocusedRect(code.boundingBox)
+ } else {
+ strongSelf.focusedCode.set(nil)
+ strongSelf.updateFocusedRect(nil)
+ }
+ }))
+ }
+
+ private func updateFocusedRect(_ rect: CGRect?) {
+ self.focusedRect = rect
+ if let (layout, navigationHeight) = self.validLayout {
+ self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring))
+ }
}
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
- self.navigationHeight = navigationHeight
+ self.validLayout = (layout, navigationHeight)
- let sideInset: CGFloat = 32.0
- let titleSpacing: CGFloat = 19.0
- let textSpacing: CGFloat = 37.0
+ let sideInset: CGFloat = 66.0
+ let titleSpacing: CGFloat = 48.0
+
+ let bounds = CGRect(origin: CGPoint(), size: layout.size)
+
+ transition.updateFrame(node: self.previewNode, frame: bounds)
+ transition.updateFrame(node: self.fadeNode, frame: bounds)
+
+ let frameSide = max(240.0, layout.size.width - sideInset * 2.0)
+ let dimHeight = ceil((layout.size.height - frameSide) / 2.0)
+ let dimInset = (layout.size.width - frameSide) / 2.0
+
+ let dimAlpha: CGFloat
+ let dimRect: CGRect
+ if let focusedRect = self.focusedRect {
+ dimAlpha = 1.0
+ let side = max(bounds.width * focusedRect.width, bounds.height * focusedRect.height) * 0.6
+ let center = CGPoint(x: (1.0 - focusedRect.center.y) * bounds.width, y: focusedRect.center.x * bounds.height)
+ dimRect = CGRect(x: center.x - side / 2.0, y: center.y - side / 2.0, width: side, height: side)
+ } else {
+ dimAlpha = 0.625
+ dimRect = CGRect(x: dimInset, y: dimHeight, width: layout.size.width - dimInset * 2.0, height: layout.size.height - dimHeight * 2.0)
+ }
+
+ transition.updateFrame(node: self.topDimNode, frame: CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: dimRect.minY))
+ transition.updateFrame(node: self.bottomDimNode, frame: CGRect(x: 0.0, y: dimRect.maxY, width: layout.size.width, height: max(0.0, layout.size.height - dimRect.maxY)))
+ transition.updateFrame(node: self.leftDimNode, frame: CGRect(x: 0.0, y: dimRect.minY, width: max(0.0, dimRect.minX), height: dimRect.height))
+ transition.updateFrame(node: self.rightDimNode, frame: CGRect(x: dimRect.maxX, y: dimRect.minY, width: max(0.0, layout.size.width - dimRect.maxX), height: dimRect.height))
+
+ transition.updateAlpha(node: self.topDimNode, alpha: dimAlpha)
+ transition.updateAlpha(node: self.bottomDimNode, alpha: dimAlpha)
+ transition.updateAlpha(node: self.leftDimNode, alpha: dimAlpha)
+ transition.updateAlpha(node: self.rightDimNode, alpha: dimAlpha)
+
+ transition.updateFrame(node: self.frameNode, frame: dimRect.insetBy(dx: -2.0, dy: -2.0))
+
+ let torchButtonSize = CGSize(width: 72.0, height: 72.0)
+ transition.updateFrame(node: self.torchButtonNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - torchButtonSize.width) / 2.0), y: dimHeight + frameSide + 50.0), size: torchButtonSize))
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
- let textSize = self.textNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
-
- var contentHeight: CGFloat = 0.0
-
- let contentVerticalOrigin = navigationHeight + 10.0
-
- let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: contentVerticalOrigin), size: titleSize)
+ let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: dimHeight - titleSize.height - titleSpacing), size: titleSize)
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
- let textFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize)
- transition.updateFrameAdditive(node: self.textNode, frame: textFrame)
-
- contentHeight = textFrame.maxY + textSpacing
+ }
+
+ @objc private func torchPressed() {
+ self.torchButtonNode.isSelected = !self.torchButtonNode.isSelected
+ self.camera.setTorchActive(self.torchButtonNode.isSelected)
}
}
diff --git a/submodules/WalletUI/Sources/WalletReceiveScreen.swift b/submodules/WalletUI/Sources/WalletReceiveScreen.swift
index 1c2ceb6b88..cb93773439 100644
--- a/submodules/WalletUI/Sources/WalletReceiveScreen.swift
+++ b/submodules/WalletUI/Sources/WalletReceiveScreen.swift
@@ -131,9 +131,9 @@ private func walletReceiveScreenEntries(presentationData: PresentationData, addr
var entries: [WalletReceiveScreenEntry] = []
entries.append(.addressHeader(presentationData.theme, "YOUR WALLET ADDRESS"))
- let address = String(address[address.startIndex.. WalletSendScreenState) -> Void
let selectNextInputItem: (WalletSendScreenEntryTag) -> Void
+ let openQrScanner: () -> Void
let proceed: () -> Void
- init(context: AccountContext, updateState: @escaping ((WalletSendScreenState) -> WalletSendScreenState) -> Void, selectNextInputItem: @escaping (WalletSendScreenEntryTag) -> Void, proceed: @escaping () -> Void) {
+ init(context: AccountContext, updateState: @escaping ((WalletSendScreenState) -> WalletSendScreenState) -> Void, selectNextInputItem: @escaping (WalletSendScreenEntryTag) -> Void, openQrScanner: @escaping () -> Void, proceed: @escaping () -> Void) {
self.context = context
self.updateState = updateState
self.selectNextInputItem = selectNextInputItem
+ self.openQrScanner = openQrScanner
self.proceed = proceed
}
}
@@ -93,8 +96,8 @@ private func isValidAmount(_ amount: String) -> Bool {
}
private func formatAmountText(_ amount: Int64, decimalSeparator: String = ".") -> String {
- if amount < 10000000000 {
- return "0\(decimalSeparator)\(String(amount).rightJustified(width: 10, pad: "0"))"
+ if amount < 1000000000 {
+ return "0\(decimalSeparator)\(String(amount).rightJustified(width: 9, pad: "0"))"
} else {
var string = String(amount)
string.insert(contentsOf: decimalSeparator, at: string.index(string.endIndex, offsetBy: -9))
@@ -103,7 +106,7 @@ private func formatAmountText(_ amount: Int64, decimalSeparator: String = ".") -
}
private func amountValue(_ string: String) -> Int64 {
- return Int64((Double(string) ?? 0.0) * 1000.0)
+ return Int64((Double(string.replacingOccurrences(of: ",", with: ".")) ?? 0.0) * 1000000000.0)
}
private func normalizedStringForGramsString(_ string: String, decimalSeparator: String = ".") -> String {
@@ -115,7 +118,7 @@ private enum WalletSendScreenEntry: ItemListNodeEntry {
case address(PresentationTheme, String, String)
case addressInfo(PresentationTheme, String)
- case amountHeader(PresentationTheme, String, String, Bool)
+ case amountHeader(PresentationTheme, String, String?, Bool)
case amount(PresentationTheme, PresentationStrings, String, String)
case commentHeader(PresentationTheme, String)
@@ -207,21 +210,23 @@ private enum WalletSendScreenEntry: ItemListNodeEntry {
case let .addressHeader(theme, text):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .address(theme, placeholder, address):
- return ItemListMultilineInputItem(theme: theme, text: address, placeholder: "Enter wallet address...", maxLength: .init(value: walletAddressLength, display: false), sectionId: self.section, style: .blocks, capitalization: false, autocorrection: false, returnKeyType: .next, minimalHeight: 68.0, textUpdated: { address in
+ return ItemListMultilineInputItem(theme: theme, text: address, placeholder: placeholder, maxLength: .init(value: walletAddressLength, display: false), sectionId: self.section, style: .blocks, capitalization: false, autocorrection: false, returnKeyType: .next, minimalHeight: 68.0, textUpdated: { address in
arguments.updateState { state in
var state = state
- state.address = address
+ state.address = address.replacingOccurrences(of: "\n", with: "")
return state
}
}, shouldUpdateText: { text in
return isValidAddress(text)
}, tag: WalletSendScreenEntryTag.address, action: {
arguments.selectNextInputItem(WalletSendScreenEntryTag.address)
- })
+ }, inlineAction: ItemListMultilineInputInlineAction(icon: UIImage(bundleImageName: "Wallet/QrIcon")!, action: {
+ arguments.openQrScanner()
+ }))
case let .addressInfo(theme, text):
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
case let .amountHeader(theme, text, balance, insufficient):
- return ItemListSectionHeaderItem(theme: theme, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: balance, color: insufficient ? .destructive : .generic), sectionId: self.section)
+ return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: balance == nil ? .right : .none, accessoryText: balance.flatMap { ItemListSectionHeaderAccessoryText(value: $0, color: insufficient ? .destructive : .generic, icon: balanceIcon) }, sectionId: self.section)
case let .amount(theme, strings, placeholder, text):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: ""), text: text, placeholder: placeholder, type: .decimal, returnKeyType: .next, tag: WalletSendScreenEntryTag.amount, sectionId: self.section, textUpdated: { text in
arguments.updateState { state in
@@ -271,16 +276,18 @@ private struct WalletSendScreenState: Equatable {
var address: String
var amount: String
var comment: String
+ var qrScanAvailable: Bool
}
private func walletSendScreenEntries(presentationData: PresentationData, balance: Int64?, state: WalletSendScreenState) -> [WalletSendScreenEntry] {
var entries: [WalletSendScreenEntry] = []
+
entries.append(.addressHeader(presentationData.theme, "RECIPIENT WALLET ADDRESS"))
entries.append(.address(presentationData.theme, "Enter wallet address...", state.address))
entries.append(.addressInfo(presentationData.theme, "Copy the 48-letter address of the recipient here or ask them to send you a ton:// link."))
let amount = amountValue(state.amount)
- entries.append(.amountHeader(presentationData.theme, "AMOUNT", "BALANCE: \(formatBalanceText(balance ?? 0, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))💎", amount > 0 && (balance ?? 0) < amount))
+ entries.append(.amountHeader(presentationData.theme, "AMOUNT", balance.flatMap { "BALANCE: \(formatBalanceText($0, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))" }, amount > 0 && (balance ?? 0) < amount))
entries.append(.amount(presentationData.theme, presentationData.strings, "Grams to send", state.amount ?? ""))
entries.append(.commentHeader(presentationData.theme, "COMMENT"))
@@ -296,9 +303,9 @@ private final class WalletSendScreenImpl: ItemListController ViewController {
+func walletSendScreen(context: AccountContext, tonContext: TonContext, walletInfo: WalletInfo, walletState: WalletState? = nil, address: String? = nil, amount: Int64? = nil) -> ViewController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
- let initialState = WalletSendScreenState(address: address ?? "", amount: amount.flatMap { formatAmountText($0, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } ?? "", comment: "")
+ let initialState = WalletSendScreenState(address: address ?? "", amount: amount.flatMap { formatAmountText($0, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } ?? "", comment: "", qrScanAvailable: address == nil)
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState)
@@ -309,13 +316,41 @@ func walletSendScreen(context: AccountContext, tonContext: TonContext, walletInf
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var presentInGlobalOverlayImpl: ((ViewController, Any?) -> Void)?
var pushImpl: ((ViewController) -> Void)?
+ var popImpl: (() -> Void)?
var dismissImpl: (() -> Void)?
+ var dismissInputImpl: (() -> Void)?
var selectNextInputItemImpl: ((WalletSendScreenEntryTag) -> Void)?
let arguments = WalletSendScreenArguments(context: context, updateState: { f in
updateState(f)
}, selectNextInputItem: { tag in
selectNextInputItemImpl?(tag)
+ }, openQrScanner: {
+ dismissInputImpl?()
+ pushImpl?(WalletQrScanScreen(context: context, completion: { address, amount, comment in
+ var updatedState: WalletSendScreenState?
+ updateState { state in
+ var state = state
+ state.address = address
+ if let amount = amount {
+ state.amount = formatAmountText(amount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator)
+ }
+ if let comment = comment {
+ state.comment = comment
+ }
+ state.qrScanAvailable = false
+ updatedState = state
+ return state
+ }
+ popImpl?()
+ if let updatedState = updatedState {
+ if updatedState.amount.isEmpty {
+ selectNextInputItemImpl?(WalletSendScreenEntryTag.address)
+ } else if updatedState.comment.isEmpty {
+ selectNextInputItemImpl?(WalletSendScreenEntryTag.amount)
+ }
+ }
+ }))
}, proceed: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let state = stateValue.with { $0 }
@@ -331,7 +366,7 @@ func walletSendScreen(context: AccountContext, tonContext: TonContext, walletInf
let address = state.address[state.address.startIndex.. = Signal.single(WalletBalance(rawValue: 2500))
-
+ let balance: Signal = .single(walletState)
+ |> then(walletAddress(publicKey: walletInfo.publicKey, tonInstance: tonContext.instance)
+ |> mapToSignal { address in
+ return getWalletState(address: address, tonInstance: tonContext.instance)
+ |> map(Optional.init)
+ })
+
var focusItemTag: ItemListItemTag?
if address == nil {
focusItemTag = WalletSendScreenEntryTag.address
@@ -373,14 +413,14 @@ func walletSendScreen(context: AccountContext, tonContext: TonContext, walletInf
let amount = amountValue(state.amount)
var sendEnabled = false
if let balance = balance {
- sendEnabled = isValidAddress(state.address, exactLength: true) && amount > 0 && amount <= balance.rawValue
+ sendEnabled = isValidAddress(state.address, exactLength: true) && amount > 0 && amount <= balance.balance
}
let rightNavigationButton = ItemListNavigationButton(content: .text("Send"), style: .bold, enabled: sendEnabled, action: {
arguments.proceed()
})
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text("Send Grams"), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
- let listState = ItemListNodeState(entries: walletSendScreenEntries(presentationData: presentationData, balance: balance?.rawValue, state: state), style: .blocks, focusItemTag: focusItemTag, animateChanges: false)
+ let listState = ItemListNodeState(entries: walletSendScreenEntries(presentationData: presentationData, balance: balance?.balance, state: state), style: .blocks, focusItemTag: focusItemTag, animateChanges: false)
return (controllerState, (listState, arguments))
}
@@ -396,10 +436,16 @@ func walletSendScreen(context: AccountContext, tonContext: TonContext, walletInf
pushImpl = { [weak controller] c in
controller?.push(c)
}
+ popImpl = { [weak controller] in
+ (controller?.navigationController as? NavigationController)?.popViewController(animated: true)
+ }
dismissImpl = { [weak controller] in
controller?.view.endEditing(true)
let _ = controller?.dismiss()
}
+ dismissInputImpl = { [weak controller] in
+ controller?.view.endEditing(true)
+ }
selectNextInputItemImpl = { [weak controller] currentTag in
guard let controller = controller else {
return
diff --git a/submodules/WalletUI/Sources/WalletSplashScreen.swift b/submodules/WalletUI/Sources/WalletSplashScreen.swift
index 3e79e1c96a..d2239588ae 100644
--- a/submodules/WalletUI/Sources/WalletSplashScreen.swift
+++ b/submodules/WalletUI/Sources/WalletSplashScreen.swift
@@ -13,6 +13,7 @@ import SwiftSignalKit
import OverlayStatusController
import ItemListUI
import AlertUI
+import TextFormat
public enum WalletSplashMode {
case intro
@@ -49,10 +50,10 @@ public final class WalletSplashScreen: ViewController {
case .intro:
self.navigationItem.setLeftBarButton(UIBarButtonItem(title: "Not Now", style: .plain, target: self, action: #selector(self.backPressed)), animated: false)
self.navigationItem.setRightBarButton(UIBarButtonItem(title: "Import existing wallet", style: .plain, target: self, action: #selector(self.importPressed)), animated: false)
- case let .sending(walletInfo, address, amount, comment):
+ case let .sending(walletInfo, address, amount, textMessage):
self.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: ASDisplayNode())!, animated: false)
- let _ = (sendGramsFromWallet(network: self.context.account.network, tonInstance: self.tonContext.instance, keychain: self.tonContext.keychain, walletInfo: walletInfo, toAddress: address, amount: amount)
+ let _ = (sendGramsFromWallet(network: self.context.account.network, tonInstance: self.tonContext.instance, keychain: self.tonContext.keychain, walletInfo: walletInfo, toAddress: address, amount: amount, textMessage: textMessage)
|> deliverOnMainQueue).start(error: { [weak self] error in
guard let strongSelf = self else {
return
@@ -223,29 +224,32 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
self.animationNode = AnimatedStickerNode()
let title: String
- let text: String
+ let text: NSAttributedString
let buttonText: String
let termsText: String
let secondaryActionText: String
-
+
+ let textFont = Font.regular(16.0)
+ let textColor = self.presentationData.theme.list.itemPrimaryTextColor
+
switch mode {
case .intro:
title = "Gram Wallet"
- text = "Gram wallet allows you to make fast and secure blockchain-based payments without intermediaries."
+ text = NSAttributedString(string: "Gram wallet allows you to make fast and secure blockchain-based payments without intermediaries.", font: textFont, textColor: textColor)
buttonText = "Create My Wallet"
termsText = "By creating the wallet you accept\nTerms of Conditions."
self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/IntroIcon")
secondaryActionText = ""
case .created:
title = "Congratulations"
- text = "Your Gram wallet has just been created. Only you control it.\n\nTo be able to always have access to it, please write down secret words and\nset up a secure passcode."
+ text = NSAttributedString(string: "Your Gram wallet has just been created. Only you control it.\n\nTo be able to always have access to it, please write down secret words and\nset up a secure passcode.", font: textFont, textColor: textColor)
buttonText = "Proceed"
termsText = ""
self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/CreatedIcon")
secondaryActionText = ""
case .success:
title = "Ready to go!"
- text = "You’re all set. Now you have a wallet that only you control - directly, without middlemen or bankers. "
+ text = NSAttributedString(string: "You’re all set. Now you have a wallet that only you control - directly, without middlemen or bankers. ", font: textFont, textColor: textColor)
buttonText = "View My Wallet"
termsText = ""
self.iconNode.image = nil
@@ -256,7 +260,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
secondaryActionText = ""
case .restoreFailed:
title = "Too Bad"
- text = "Without the secret words, you can't'nrestore access to the wallet."
+ text = NSAttributedString(string: "Without the secret words, you can't'nrestore access to the wallet.", font: textFont, textColor: textColor)
buttonText = "Create a New Wallet"
termsText = ""
self.iconNode.image = nil
@@ -267,14 +271,16 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
secondaryActionText = "Enter 24 words"
case .sending:
title = "Sending Grams"
- text = "Please wait a few seconds for your transaction to be processed..."
+ text = NSAttributedString(string: "Please wait a few seconds for your transaction to be processed...", font: textFont, textColor: textColor)
buttonText = ""
termsText = ""
self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/SendingIcon")
secondaryActionText = ""
case let .sent(_, amount):
title = "Done!"
- text = "\(amount) Grams have been sent."
+ let bodyAttributes = MarkdownAttributeSet(font: textFont, textColor: textColor)
+ let boldAttributes = MarkdownAttributeSet(font: Font.semibold(16.0), textColor: textColor)
+ text = parseMarkdownIntoAttributedString("**\(formatBalanceText(amount, decimalSeparator: self.presentationData.dateTimeFormat.decimalSeparator)) Grams** have been sent.", attributes: MarkdownAttributes(body: bodyAttributes, bold: boldAttributes, link: bodyAttributes, linkAttribute: { _ in return nil }), textAlignment: .center)
buttonText = "View My Wallet"
termsText = ""
self.iconNode.image = nil
@@ -293,7 +299,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
self.textNode = ImmediateTextNode()
self.textNode.displaysAsynchronously = false
- self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
+ self.textNode.attributedText = text
self.textNode.maximumNumberOfLines = 0
self.textNode.lineSpacing = 0.1
self.textNode.textAlignment = .center
diff --git a/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift b/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift
index 65300e0fbc..15689dc300 100644
--- a/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift
+++ b/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift
@@ -142,7 +142,7 @@ private func walletTransactionInfoControllerEntries(presentationData: Presentati
}
entries.append(.infoAddress(presentationData.theme, text))
if case .list = address {
- entries.append(.infoCopyAddress(presentationData.theme, "Copy Address"))
+ entries.append(.infoCopyAddress(presentationData.theme, "Copy Wallet Address"))
entries.append(.infoSendGrams(presentationData.theme, "Send Grams"))
}
@@ -170,6 +170,7 @@ func walletTransactionInfoController(context: AccountContext, tonContext: TonCon
}, sendGrams: {
let address = extractAddress(walletTransaction)
if case let .list(addresses) = address, let address = addresses.first {
+ dismissImpl?()
pushImpl?(walletSendScreen(context: context, tonContext: tonContext, walletInfo: walletInfo, address: address))
}
})
diff --git a/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj b/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj
index 0bc91d1cfb..66750110b2 100644
--- a/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj
+++ b/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj
@@ -247,6 +247,19 @@
explicitFileType
compiled.mach-o.dylib
+ 1DD70E29BCD8FADE00000000
+
+ isa
+ PBXFileReference
+ name
+ libGlassButtonNode.a
+ path
+ libGlassButtonNode.a
+ sourceTree
+ BUILT_PRODUCTS_DIR
+ explicitFileType
+ archive.ar
+
1DD70E2971ED41B100000000
isa
@@ -751,6 +764,7 @@
1DD70E292417E0B200000000
1DD70E295915423000000000
1DD70E29FF334B1F00000000
+ 1DD70E29BCD8FADE00000000
1DD70E2971ED41B100000000
1DD70E29D6F14E1000000000
1DD70E295A26607D00000000
@@ -829,6 +843,17 @@
explicitFileType
text.script.python
+ 1DD70E292CCF064200000000
+
+ isa
+ PBXFileReference
+ name
+ WalletConfiguration.swift
+ path
+ Sources/WalletConfiguration.swift
+ sourceTree
+ SOURCE_ROOT
+
1DD70E298B98CCED00000000
isa
@@ -982,6 +1007,7 @@
]]>
children
+ 1DD70E292CCF064200000000
1DD70E298B98CCED00000000
1DD70E29D2B1401800000000
1DD70E2900657ECF00000000
@@ -1027,6 +1053,13 @@
B401C979172FA86D00000000
+ E7A30F042CCF064200000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E292CCF064200000000
+
E7A30F048B98CCED00000000
isa
@@ -1124,6 +1157,7 @@
PBXSourcesBuildPhase
files
+ E7A30F042CCF064200000000
E7A30F048B98CCED00000000
E7A30F04D2B1401800000000
E7A30F0400657ECF00000000
@@ -1265,6 +1299,13 @@
fileRef
1DD70E29BFBD457D00000000
+ E7A30F04BCD8FADE00000000
+
+ isa
+ PBXBuildFile
+ fileRef
+ 1DD70E29BCD8FADE00000000
+
E7A30F04D6F14E1000000000
isa
@@ -1513,6 +1554,7 @@
E7A30F049D2580DA00000000
E7A30F04F523B9DE00000000
E7A30F04BFBD457D00000000
+ E7A30F04BCD8FADE00000000
E7A30F04D6F14E1000000000
E7A30F04CD296A8300000000
E7A30F043594DCC000000000
diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp b/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp
index efc71e6f27..d7a39d417e 100644
--- a/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp
+++ b/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp
@@ -176,6 +176,113 @@ td::Status AdnlOutboundConnection::process_packet(td::BufferSlice data) {
return td::Status::OK();
}
+void AdnlExtMultiClientImpl::start_up() {
+ for (auto &id : ids_) {
+ add_server(id.first, id.second, [](td::Result R) {});
+ }
+ ids_.clear();
+}
+
+void AdnlExtMultiClientImpl::add_server(AdnlNodeIdFull dst, td::IPAddress dst_addr, td::Promise promise) {
+ for (auto &c : clients_) {
+ if (c.second->addr == dst_addr) {
+ promise.set_error(td::Status::Error(ErrorCode::error, "duplicate ip"));
+ return;
+ }
+ }
+
+ auto g = ++generation_;
+ auto cli = std::make_unique(AdnlExtClient::create(dst, dst_addr, make_callback(g)), dst, dst_addr, g);
+ clients_[g] = std::move(cli);
+}
+
+void AdnlExtMultiClientImpl::del_server(td::IPAddress dst_addr, td::Promise promise) {
+ for (auto &c : clients_) {
+ if (c.second->addr == dst_addr) {
+ if (c.second->ready) {
+ total_ready_--;
+ if (!total_ready_) {
+ callback_->on_stop_ready();
+ }
+ }
+ clients_.erase(c.first);
+ promise.set_value(td::Unit());
+ return;
+ }
+ }
+ promise.set_error(td::Status::Error(ErrorCode::error, "ip not found"));
+}
+
+void AdnlExtMultiClientImpl::send_query(std::string name, td::BufferSlice data, td::Timestamp timeout,
+ td::Promise promise) {
+ if (total_ready_ == 0) {
+ promise.set_error(td::Status::Error(ErrorCode::notready, "conn not ready"));
+ return;
+ }
+
+ std::vector vec;
+ for (auto &c : clients_) {
+ if (c.second->ready) {
+ vec.push_back(c.first);
+ }
+ }
+ CHECK(vec.size() == total_ready_);
+
+ auto &c = clients_[vec[td::Random::fast(0, td::narrow_cast(vec.size() - 1))]];
+
+ td::actor::send_closure(c->client, &AdnlExtClient::send_query, std::move(name), std::move(data), timeout,
+ std::move(promise));
+}
+
+void AdnlExtMultiClientImpl::client_ready(td::uint32 idx, bool value) {
+ auto it = clients_.find(idx);
+ if (it == clients_.end()) {
+ return;
+ }
+ auto &c = it->second;
+ if (c->ready == value) {
+ return;
+ }
+ c->ready = value;
+ if (value) {
+ total_ready_++;
+ if (total_ready_ == 1) {
+ callback_->on_ready();
+ }
+ } else {
+ total_ready_--;
+ if (total_ready_ == 0) {
+ callback_->on_stop_ready();
+ }
+ }
+}
+
+std::unique_ptr AdnlExtMultiClientImpl::make_callback(td::uint32 g) {
+ class Cb : public Callback {
+ public:
+ Cb(td::actor::ActorId id, td::uint32 idx) : id_(id), idx_(idx) {
+ }
+
+ void on_ready() override {
+ td::actor::send_closure(id_, &AdnlExtMultiClientImpl::client_ready, idx_, true);
+ }
+
+ void on_stop_ready() override {
+ td::actor::send_closure(id_, &AdnlExtMultiClientImpl::client_ready, idx_, false);
+ }
+
+ private:
+ td::actor::ActorId id_;
+ td::uint32 idx_;
+ };
+ return std::make_unique(actor_id(this), g);
+}
+
+td::actor::ActorOwn AdnlExtMultiClient::create(
+ std::vector> ids, std::unique_ptr callback) {
+ return td::actor::create_actor("extmulticlient", std::move(ids), std::move(callback));
+}
+
} // namespace adnl
} // namespace ton
diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-client.h b/submodules/ton/tonlib-src/adnl/adnl-ext-client.h
index babccced5e..bd60f202d6 100644
--- a/submodules/ton/tonlib-src/adnl/adnl-ext-client.h
+++ b/submodules/ton/tonlib-src/adnl/adnl-ext-client.h
@@ -43,6 +43,14 @@ class AdnlExtClient : public td::actor::Actor {
std::unique_ptr callback);
};
+class AdnlExtMultiClient : public AdnlExtClient {
+ public:
+ virtual void add_server(AdnlNodeIdFull dst, td::IPAddress dst_addr, td::Promise promise) = 0;
+ virtual void del_server(td::IPAddress dst_addr, td::Promise promise) = 0;
+ static td::actor::ActorOwn create(std::vector> ids,
+ std::unique_ptr callback);
+};
+
} // namespace adnl
} // namespace ton
diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-client.hpp b/submodules/ton/tonlib-src/adnl/adnl-ext-client.hpp
index 95348135ca..d58247fcc4 100644
--- a/submodules/ton/tonlib-src/adnl/adnl-ext-client.hpp
+++ b/submodules/ton/tonlib-src/adnl/adnl-ext-client.hpp
@@ -140,6 +140,52 @@ class AdnlExtClientImpl : public AdnlExtClient {
void try_stop();
};
+class AdnlExtMultiClientImpl : public AdnlExtMultiClient {
+ public:
+ AdnlExtMultiClientImpl(std::vector> ids,
+ std::unique_ptr callback)
+ : ids_(std::move(ids)), callback_(std::move(callback)) {
+ }
+
+ void start_up() override;
+
+ void add_server(AdnlNodeIdFull dst, td::IPAddress dst_addr, td::Promise promise) override;
+ void del_server(td::IPAddress dst_addr, td::Promise promise) override;
+
+ void check_ready(td::Promise promise) override {
+ if (total_ready_ > 0) {
+ promise.set_value(td::Unit());
+ } else {
+ promise.set_error(td::Status::Error(ErrorCode::notready, "conn not ready"));
+ }
+ }
+ void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout,
+ td::Promise promise) override;
+
+ void client_ready(td::uint32 idx, bool value);
+
+ private:
+ std::unique_ptr make_callback(td::uint32 g);
+
+ struct Client {
+ Client(td::actor::ActorOwn client, AdnlNodeIdFull pubkey, td::IPAddress addr, td::uint32 generation)
+ : client(std::move(client)), pubkey(std::move(pubkey)), addr(addr), generation(generation), ready(false) {
+ }
+ td::actor::ActorOwn client;
+ AdnlNodeIdFull pubkey;
+ td::IPAddress addr;
+ td::uint32 generation;
+ bool ready = false;
+ };
+ td::uint32 total_ready_ = 0;
+
+ td::uint32 generation_ = 0;
+ std::map> clients_;
+
+ std::vector> ids_;
+ std::unique_ptr callback_;
+};
+
} // namespace adnl
} // namespace ton
diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Timer.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/Timer.cpp
index 27e5d985ce..dd2a3a618a 100644
--- a/submodules/ton/tonlib-src/tdutils/td/utils/Timer.cpp
+++ b/submodules/ton/tonlib-src/tdutils/td/utils/Timer.cpp
@@ -25,15 +25,40 @@
namespace td {
-Timer::Timer() : start_time_(Time::now()) {
+Timer::Timer(bool is_paused) : is_paused_(is_paused) {
+ if (is_paused_) {
+ start_time_ = 0;
+ } else {
+ start_time_ = Time::now();
+ }
+}
+
+void Timer::pause() {
+ if (is_paused_) {
+ return;
+ }
+ elapsed_ += Time::now() - start_time_;
+ is_paused_ = true;
+}
+
+void Timer::resume() {
+ if (!is_paused_) {
+ return;
+ }
+ start_time_ = Time::now();
+ is_paused_ = false;
}
double Timer::elapsed() const {
- return Time::now() - start_time_;
+ double res = elapsed_;
+ if (!is_paused_) {
+ res += Time::now() - start_time_;
+ }
+ return res;
}
StringBuilder &operator<<(StringBuilder &string_builder, const Timer &timer) {
- return string_builder << "in " << Time::now() - timer.start_time_;
+ return string_builder << format::as_time(timer.elapsed());
}
PerfWarningTimer::PerfWarningTimer(string name, double max_duration)
diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Timer.h b/submodules/ton/tonlib-src/tdutils/td/utils/Timer.h
index 1b84b7daba..ed5afa7468 100644
--- a/submodules/ton/tonlib-src/tdutils/td/utils/Timer.h
+++ b/submodules/ton/tonlib-src/tdutils/td/utils/Timer.h
@@ -24,14 +24,22 @@ namespace td {
class Timer {
public:
- Timer();
+ Timer() : Timer(false) {
+ }
+ explicit Timer(bool is_paused);
+ Timer(const Timer &other) = default;
+ Timer &operator=(const Timer &other) = default;
double elapsed() const;
+ void pause();
+ void resume();
private:
friend StringBuilder &operator<<(StringBuilder &string_builder, const Timer &timer);
+ double elapsed_{0};
double start_time_;
+ bool is_paused_{false};
};
class PerfWarningTimer {
diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/filesystem.cpp b/submodules/ton/tonlib-src/tdutils/td/utils/filesystem.cpp
index 9ee0cf615f..0d6a21a832 100644
--- a/submodules/ton/tonlib-src/tdutils/td/utils/filesystem.cpp
+++ b/submodules/ton/tonlib-src/tdutils/td/utils/filesystem.cpp
@@ -53,17 +53,20 @@ SecureString create_empty(size_t size) {
template
Result read_file_impl(CSlice path, int64 size, int64 offset) {
TRY_RESULT(from_file, FileFd::open(path, FileFd::Read));
+ TRY_RESULT(file_size, from_file.get_size());
+ if (offset < 0 || offset > file_size) {
+ return Status::Error("Failed to read file: invalid offset");
+ }
if (size == -1) {
- TRY_RESULT(file_size, from_file.get_size());
- size = file_size;
+ size = file_size - offset;
+ } else if (size >= 0) {
+ if (size + offset > file_size) {
+ size = file_size - offset;
+ }
}
if (size < 0) {
return Status::Error("Failed to read file: invalid size");
}
- if (offset < 0 || offset > size) {
- return Status::Error("Failed to read file: invalid offset");
- }
- size -= offset;
auto content = create_empty(narrow_cast(size));
TRY_RESULT(got_size, from_file.pread(as_mutable_slice(content), offset));
if (got_size != static_cast(size)) {
diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp
index 8d4a3f1c23..bfbdee4ed8 100644
--- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp
+++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp
@@ -7643,21 +7643,21 @@ engine_validator_config::engine_validator_config()
, dht_()
, validators_()
, fullnode_()
- , fullnodeslave_()
+ , fullnodeslaves_()
, fullnodemasters_()
, liteservers_()
, control_()
, gc_()
{}
-engine_validator_config::engine_validator_config(std::int32_t out_port_, std::vector> &&addrs_, std::vector> &&adnl_, std::vector> &&dht_, std::vector> &&validators_, td::Bits256 const &fullnode_, object_ptr &&fullnodeslave_, std::vector> &&fullnodemasters_, std::vector> &&liteservers_, std::vector> &&control_, object_ptr &&gc_)
+engine_validator_config::engine_validator_config(std::int32_t out_port_, std::vector> &&addrs_, std::vector> &&adnl_, std::vector> &&dht_, std::vector> &&validators_, td::Bits256 const &fullnode_, std::vector> &&fullnodeslaves_, std::vector> &&fullnodemasters_, std::vector> &&liteservers_, std::vector> &&control_, object_ptr &&gc_)
: out_port_(out_port_)
, addrs_(std::move(addrs_))
, adnl_(std::move(adnl_))
, dht_(std::move(dht_))
, validators_(std::move(validators_))
, fullnode_(fullnode_)
- , fullnodeslave_(std::move(fullnodeslave_))
+ , fullnodeslaves_(std::move(fullnodeslaves_))
, fullnodemasters_(std::move(fullnodemasters_))
, liteservers_(std::move(liteservers_))
, control_(std::move(control_))
@@ -7678,7 +7678,7 @@ engine_validator_config::engine_validator_config(td::TlParser &p)
, dht_(TlFetchVector>::parse(p))
, validators_(TlFetchVector>::parse(p))
, fullnode_(TlFetchInt256::parse(p))
- , fullnodeslave_(TlFetchObject::parse(p))
+ , fullnodeslaves_(TlFetchVector>::parse(p))
, fullnodemasters_(TlFetchVector>::parse(p))
, liteservers_(TlFetchVector>::parse(p))
, control_(TlFetchVector>::parse(p))
@@ -7694,7 +7694,7 @@ void engine_validator_config::store(td::TlStorerCalcLength &s) const {
TlStoreVector::store(dht_, s);
TlStoreVector::store(validators_, s);
TlStoreBinary::store(fullnode_, s);
- TlStoreObject::store(fullnodeslave_, s);
+ TlStoreVector::store(fullnodeslaves_, s);
TlStoreVector::store(fullnodemasters_, s);
TlStoreVector::store(liteservers_, s);
TlStoreVector::store(control_, s);
@@ -7709,7 +7709,7 @@ void engine_validator_config::store(td::TlStorerUnsafe &s) const {
TlStoreVector::store(dht_, s);
TlStoreVector::store(validators_, s);
TlStoreBinary::store(fullnode_, s);
- TlStoreObject::store(fullnodeslave_, s);
+ TlStoreVector::store(fullnodeslaves_, s);
TlStoreVector::store(fullnodemasters_, s);
TlStoreVector::store(liteservers_, s);
TlStoreVector::store(control_, s);
@@ -7725,7 +7725,7 @@ void engine_validator_config::store(td::TlStorerToString &s, const char *field_n
{ const std::vector> &v = dht_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("dht", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
{ const std::vector> &v = validators_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("validators", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
s.store_field("fullnode", fullnode_);
- if (fullnodeslave_ == nullptr) { s.store_field("fullnodeslave", "null"); } else { fullnodeslave_->store(s, "fullnodeslave"); }
+ { const std::vector> &v = fullnodeslaves_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("fullnodeslaves", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
{ const std::vector> &v = fullnodemasters_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("fullnodemasters", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
{ const std::vector> &v = liteservers_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("liteservers", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
{ const std::vector> &v = control_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("control", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h
index 3387d77f77..41eec24536 100644
--- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h
+++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h
@@ -4214,7 +4214,7 @@ class engine_validator_config final : public Object {
std::vector> dht_;
std::vector> validators_;
td::Bits256 fullnode_;
- object_ptr fullnodeslave_;
+ std::vector> fullnodeslaves_;
std::vector> fullnodemasters_;
std::vector> liteservers_;
std::vector> control_;
@@ -4222,9 +4222,9 @@ class engine_validator_config final : public Object {
engine_validator_config();
- engine_validator_config(std::int32_t out_port_, std::vector> &&addrs_, std::vector> &&adnl_, std::vector> &&dht_, std::vector> &&validators_, td::Bits256 const &fullnode_, object_ptr &&fullnodeslave_, std::vector> &&fullnodemasters_, std::vector> &&liteservers_, std::vector> &&control_, object_ptr &&gc_);
+ engine_validator_config(std::int32_t out_port_, std::vector> &&addrs_, std::vector> &&adnl_, std::vector> &&dht_, std::vector> &&validators_, td::Bits256 const &fullnode_, std::vector> &&fullnodeslaves_, std::vector> &&fullnodemasters_, std::vector> &&liteservers_, std::vector> &&control_, object_ptr &&gc_);
- static const std::int32_t ID = 17126390;
+ static const std::int32_t ID = -826140252;
std::int32_t get_id() const final {
return ID;
}
diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp
index 58e145707d..d08d906c9d 100644
--- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp
+++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp
@@ -625,7 +625,7 @@ Result tl_constructor_from_string(ton_api::Object *object, const std::str
{"engine.adnlProxy.config", 1848000769},
{"engine.adnlProxy.port", -117344950},
{"engine.dht.config", -197295930},
- {"engine.validator.config", 17126390},
+ {"engine.validator.config", -826140252},
{"engine.validator.controlQueryError", 1999018527},
{"engine.validator.dhtServerStatus", -1323440290},
{"engine.validator.dhtServersStatus", 725155112},
@@ -3099,9 +3099,9 @@ Status from_json(ton_api::engine_validator_config &to, JsonObject &from) {
}
}
{
- TRY_RESULT(value, get_json_object_field(from, "fullnodeslave", JsonValue::Type::Null, true));
+ TRY_RESULT(value, get_json_object_field(from, "fullnodeslaves", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
- TRY_STATUS(from_json(to.fullnodeslave_, value));
+ TRY_STATUS(from_json(to.fullnodeslaves_, value));
}
}
{
@@ -6711,9 +6711,7 @@ void to_json(JsonValueScope &jv, const ton_api::engine_validator_config &object)
jo << ctie("dht", ToJson(object.dht_));
jo << ctie("validators", ToJson(object.validators_));
jo << ctie("fullnode", ToJson(object.fullnode_));
- if (object.fullnodeslave_) {
- jo << ctie("fullnodeslave", ToJson(object.fullnodeslave_));
- }
+ jo << ctie("fullnodeslaves", ToJson(object.fullnodeslaves_));
jo << ctie("fullnodemasters", ToJson(object.fullnodemasters_));
jo << ctie("liteservers", ToJson(object.liteservers_));
jo << ctie("control", ToJson(object.control_));
diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp
index 8deb110d68..0a6d3b95d8 100644
--- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp
+++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp
@@ -413,12 +413,14 @@ raw_message::raw_message()
: source_()
, destination_()
, value_()
+ , message_()
{}
-raw_message::raw_message(std::string const &source_, std::string const &destination_, std::int64_t value_)
+raw_message::raw_message(std::string const &source_, std::string const &destination_, std::int64_t value_, std::string const &message_)
: source_(std::move(source_))
, destination_(std::move(destination_))
, value_(value_)
+ , message_(std::move(message_))
{}
const std::int32_t raw_message::ID;
@@ -429,6 +431,7 @@ void raw_message::store(td::TlStorerToString &s, const char *field_name) const {
s.store_field("source", source_);
s.store_field("destination", destination_);
s.store_field("value", value_);
+ s.store_bytes_field("message", message_);
s.store_class_end();
}
}
@@ -741,13 +744,15 @@ generic_sendGrams::generic_sendGrams()
, source_()
, destination_()
, amount_()
+ , message_()
{}
-generic_sendGrams::generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_)
+generic_sendGrams::generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::string const &message_)
: private_key_(std::move(private_key_))
, source_(std::move(source_))
, destination_(std::move(destination_))
, amount_(amount_)
+ , message_(std::move(message_))
{}
const std::int32_t generic_sendGrams::ID;
@@ -759,6 +764,7 @@ void generic_sendGrams::store(td::TlStorerToString &s, const char *field_name) c
if (source_ == nullptr) { s.store_field("source", "null"); } else { source_->store(s, "source"); }
if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); }
s.store_field("amount", amount_);
+ s.store_bytes_field("message", message_);
s.store_class_end();
}
}
@@ -1058,12 +1064,14 @@ testGiver_sendGrams::testGiver_sendGrams()
: destination_()
, seqno_()
, amount_()
+ , message_()
{}
-testGiver_sendGrams::testGiver_sendGrams(object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_)
+testGiver_sendGrams::testGiver_sendGrams(object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_)
: destination_(std::move(destination_))
, seqno_(seqno_)
, amount_(amount_)
+ , message_(std::move(message_))
{}
const std::int32_t testGiver_sendGrams::ID;
@@ -1074,6 +1082,7 @@ void testGiver_sendGrams::store(td::TlStorerToString &s, const char *field_name)
if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); }
s.store_field("seqno", seqno_);
s.store_field("amount", amount_);
+ s.store_bytes_field("message", message_);
s.store_class_end();
}
}
@@ -1137,13 +1146,15 @@ testWallet_sendGrams::testWallet_sendGrams()
, destination_()
, seqno_()
, amount_()
+ , message_()
{}
-testWallet_sendGrams::testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_)
+testWallet_sendGrams::testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_)
: private_key_(std::move(private_key_))
, destination_(std::move(destination_))
, seqno_(seqno_)
, amount_(amount_)
+ , message_(std::move(message_))
{}
const std::int32_t testWallet_sendGrams::ID;
@@ -1155,6 +1166,7 @@ void testWallet_sendGrams::store(td::TlStorerToString &s, const char *field_name
if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); }
s.store_field("seqno", seqno_);
s.store_field("amount", amount_);
+ s.store_bytes_field("message", message_);
s.store_class_end();
}
}
diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h
index bbca471746..36277cd3a0 100644
--- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h
+++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h
@@ -442,12 +442,13 @@ class raw_message final : public Object {
std::string source_;
std::string destination_;
std::int64_t value_;
+ std::string message_;
raw_message();
- raw_message(std::string const &source_, std::string const &destination_, std::int64_t value_);
+ raw_message(std::string const &source_, std::string const &destination_, std::int64_t value_, std::string const &message_);
- static const std::int32_t ID = -1131081640;
+ static const std::int32_t ID = -259956097;
std::int32_t get_id() const final {
return ID;
}
@@ -717,12 +718,13 @@ class generic_sendGrams final : public Function {
object_ptr source_;
object_ptr destination_;
std::int64_t amount_;
+ std::string message_;
generic_sendGrams();
- generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_);
+ generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::string const &message_);
- static const std::int32_t ID = 799772985;
+ static const std::int32_t ID = 1523427648;
std::int32_t get_id() const final {
return ID;
}
@@ -1012,12 +1014,13 @@ class testGiver_sendGrams final : public Function {
object_ptr destination_;
std::int32_t seqno_;
std::int64_t amount_;
+ std::string message_;
testGiver_sendGrams();
- testGiver_sendGrams(object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_);
+ testGiver_sendGrams(object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_);
- static const std::int32_t ID = -178493799;
+ static const std::int32_t ID = -1361914347;
std::int32_t get_id() const final {
return ID;
}
@@ -1087,12 +1090,13 @@ class testWallet_sendGrams final : public Function {
object_ptr destination_;
std::int32_t seqno_;
std::int64_t amount_;
+ std::string message_;
testWallet_sendGrams();
- testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_);
+ testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_);
- static const std::int32_t ID = -1716705044;
+ static const std::int32_t ID = 43200674;
std::int32_t get_id() const final {
return ID;
}
diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp
index 1b35ee3e61..3c1402d996 100644
--- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp
+++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp
@@ -60,7 +60,7 @@ Result tl_constructor_from_string(tonlib_api::Object *object, const std::
{"internal.transactionId", -989527262},
{"raw.accountState", 461615898},
{"raw.initialAccountState", 777456197},
- {"raw.message", -1131081640},
+ {"raw.message", -259956097},
{"raw.transaction", -1159530820},
{"raw.transactions", 240548986},
{"testGiver.accountState", 860930426},
@@ -84,7 +84,7 @@ Result tl_constructor_from_string(tonlib_api::Function *object, const std
{"exportKey", 399723440},
{"exportPemKey", -2047752448},
{"generic.getAccountState", -657000446},
- {"generic.sendGrams", 799772985},
+ {"generic.sendGrams", 1523427648},
{"getBip39Hints", -1889640982},
{"importEncryptedKey", 656724958},
{"importKey", -1607900903},
@@ -100,11 +100,11 @@ Result tl_constructor_from_string(tonlib_api::Function *object, const std
{"runTests", -2039925427},
{"testGiver.getAccountAddress", -540100768},
{"testGiver.getAccountState", 267738275},
- {"testGiver.sendGrams", -178493799},
+ {"testGiver.sendGrams", -1361914347},
{"testWallet.getAccountAddress", -1557748223},
{"testWallet.getAccountState", 654082364},
{"testWallet.init", 419055225},
- {"testWallet.sendGrams", -1716705044}
+ {"testWallet.sendGrams", 43200674}
};
auto it = m.find(str);
if (it == m.end()) {
@@ -377,6 +377,12 @@ Status from_json(tonlib_api::raw_message &to, JsonObject &from) {
TRY_STATUS(from_json(to.value_, value));
}
}
+ {
+ TRY_RESULT(value, get_json_object_field(from, "message", JsonValue::Type::Null, true));
+ if (value.type() != JsonValue::Type::Null) {
+ TRY_STATUS(from_json_bytes(to.message_, value));
+ }
+ }
return Status::OK();
}
Status from_json(tonlib_api::raw_transaction &to, JsonObject &from) {
@@ -638,6 +644,12 @@ Status from_json(tonlib_api::generic_sendGrams &to, JsonObject &from) {
TRY_STATUS(from_json(to.amount_, value));
}
}
+ {
+ TRY_RESULT(value, get_json_object_field(from, "message", JsonValue::Type::Null, true));
+ if (value.type() != JsonValue::Type::Null) {
+ TRY_STATUS(from_json_bytes(to.message_, value));
+ }
+ }
return Status::OK();
}
Status from_json(tonlib_api::getBip39Hints &to, JsonObject &from) {
@@ -848,6 +860,12 @@ Status from_json(tonlib_api::testGiver_sendGrams &to, JsonObject &from) {
TRY_STATUS(from_json(to.amount_, value));
}
}
+ {
+ TRY_RESULT(value, get_json_object_field(from, "message", JsonValue::Type::Null, true));
+ if (value.type() != JsonValue::Type::Null) {
+ TRY_STATUS(from_json_bytes(to.message_, value));
+ }
+ }
return Status::OK();
}
Status from_json(tonlib_api::testWallet_getAccountAddress &to, JsonObject &from) {
@@ -902,6 +920,12 @@ Status from_json(tonlib_api::testWallet_sendGrams &to, JsonObject &from) {
TRY_STATUS(from_json(to.amount_, value));
}
}
+ {
+ TRY_RESULT(value, get_json_object_field(from, "message", JsonValue::Type::Null, true));
+ if (value.type() != JsonValue::Type::Null) {
+ TRY_STATUS(from_json_bytes(to.message_, value));
+ }
+ }
return Status::OK();
}
void to_json(JsonValueScope &jv, const tonlib_api::accountAddress &object) {
@@ -1043,6 +1067,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::raw_message &object) {
jo << ctie("source", ToJson(object.source_));
jo << ctie("destination", ToJson(object.destination_));
jo << ctie("value", ToJson(JsonInt64{object.value_}));
+ jo << ctie("message", ToJson(JsonBytes{object.message_}));
}
void to_json(JsonValueScope &jv, const tonlib_api::raw_transaction &object) {
auto jo = jv.enter_object();
@@ -1167,6 +1192,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::generic_sendGrams &object) {
jo << ctie("destination", ToJson(object.destination_));
}
jo << ctie("amount", ToJson(JsonInt64{object.amount_}));
+ jo << ctie("message", ToJson(JsonBytes{object.message_}));
}
void to_json(JsonValueScope &jv, const tonlib_api::getBip39Hints &object) {
auto jo = jv.enter_object();
@@ -1280,6 +1306,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::testGiver_sendGrams &object)
}
jo << ctie("seqno", ToJson(object.seqno_));
jo << ctie("amount", ToJson(JsonInt64{object.amount_}));
+ jo << ctie("message", ToJson(JsonBytes{object.message_}));
}
void to_json(JsonValueScope &jv, const tonlib_api::testWallet_getAccountAddress &object) {
auto jo = jv.enter_object();
@@ -1313,6 +1340,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::testWallet_sendGrams &object)
}
jo << ctie("seqno", ToJson(object.seqno_));
jo << ctie("amount", ToJson(JsonInt64{object.amount_}));
+ jo << ctie("message", ToJson(JsonBytes{object.message_}));
}
} // namespace tonlib_api
} // namespace ton
diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl
index 073595ce56..860ffd5d37 100644
--- a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl
+++ b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl
@@ -490,7 +490,7 @@ engine.validator.fullNodeMaster port:int adnl:int256 = engine.validator.FullNode
engine.validator.fullNodeSlave ip:int port:int adnl:PublicKey = engine.validator.FullNodeSlave;
engine.validator.config out_port:int addrs:(vector engine.Addr) adnl:(vector engine.adnl)
dht:(vector engine.dht)
- validators:(vector engine.validator) fullnode:int256 fullnodeslave:engine.validator.fullNodeSlave
+ validators:(vector engine.validator) fullnode:int256 fullnodeslaves:(vector engine.validator.fullNodeSlave)
fullnodemasters:(vector engine.validator.fullNodeMaster)
liteservers:(vector engine.liteServer) control:(vector engine.controlInterface)
gc:engine.gc = engine.validator.Config;
diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo
index 00dc97c4e0..7ad04d37e5 100644
Binary files a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo and b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo differ
diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl
index 9535f056fc..356f263c2d 100644
--- a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl
+++ b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl
@@ -32,7 +32,7 @@ internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
raw.initialAccountState code:bytes data:bytes = raw.InitialAccountState;
raw.accountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId sync_utime:int53 = raw.AccountState;
-raw.message source:string destination:string value:int64 = raw.Message;
+raw.message source:string destination:string value:int64 message:bytes = raw.Message;
raw.transaction utime:int53 data:bytes transaction_id:internal.transactionId fee:int64 in_msg:raw.message out_msgs:vector = raw.Transaction;
raw.transactions transactions:vector previous_transaction_id:internal.transactionId = raw.Transactions;
@@ -81,15 +81,15 @@ raw.getTransactions account_address:accountAddress from_transaction_id:internal.
testWallet.init private_key:inputKey = Ok;
testWallet.getAccountAddress initital_account_state:testWallet.initialAccountState = AccountAddress;
testWallet.getAccountState account_address:accountAddress = testWallet.AccountState;
-testWallet.sendGrams private_key:inputKey destination:accountAddress seqno:int32 amount:int64 = Ok;
+testWallet.sendGrams private_key:inputKey destination:accountAddress seqno:int32 amount:int64 message:bytes = Ok;
testGiver.getAccountState = testGiver.AccountState;
testGiver.getAccountAddress = AccountAddress;
-testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 = Ok;
+testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 message:bytes = Ok;
//generic.getAccountAddress initital_account_state:generic.InitialAccountState = AccountAddress;
generic.getAccountState account_address:accountAddress = generic.AccountState;
-generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 = Ok;
+generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 message:bytes = Ok;
onLiteServerQueryResult id:int64 bytes:bytes = Ok;
onLiteServerQueryError id:int64 error:error = Ok;
diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo
index 7d87ccac80..40a4ccdce4 100644
Binary files a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo and b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo differ
diff --git a/submodules/ton/tonlib-src/tonlib/CMakeLists.txt b/submodules/ton/tonlib-src/tonlib/CMakeLists.txt
index 6c2f11a423..9b9b81da08 100644
--- a/submodules/ton/tonlib-src/tonlib/CMakeLists.txt
+++ b/submodules/ton/tonlib-src/tonlib/CMakeLists.txt
@@ -13,6 +13,7 @@ set(TONLIB_SOURCE
tonlib/GenericAccount.cpp
tonlib/KeyStorage.cpp
tonlib/LastBlock.cpp
+ tonlib/LastBlockStorage.cpp
tonlib/TestGiver.cpp
tonlib/TestWallet.cpp
tonlib/TonlibClient.cpp
@@ -26,6 +27,7 @@ set(TONLIB_SOURCE
tonlib/GenericAccount.h
tonlib/KeyStorage.h
tonlib/LastBlock.h
+ tonlib/LastBlockStorage.h
tonlib/TestGiver.h
tonlib/TestWallet.h
tonlib/TonlibCallback.h
diff --git a/submodules/ton/tonlib-src/tonlib/test/.online.cpp.swp b/submodules/ton/tonlib-src/tonlib/test/.online.cpp.swp
deleted file mode 100644
index f03547aa93..0000000000
Binary files a/submodules/ton/tonlib-src/tonlib/test/.online.cpp.swp and /dev/null differ
diff --git a/submodules/ton/tonlib-src/tonlib/test/offline.cpp b/submodules/ton/tonlib-src/tonlib/test/offline.cpp
index d5d86dba24..e009adf7c7 100644
--- a/submodules/ton/tonlib-src/tonlib/test/offline.cpp
+++ b/submodules/ton/tonlib-src/tonlib/test/offline.cpp
@@ -127,8 +127,8 @@ TEST(Tonlib, TestGiver) {
auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data;
- auto res = GenericAccount::create_ext_message(TestGiver::address(), {},
- TestGiver::make_a_gift_message(0, 1000000000ll * 6666 / 1000, address));
+ auto res = GenericAccount::create_ext_message(
+ TestGiver::address(), {}, TestGiver::make_a_gift_message(0, 1000000000ll * 6666 / 1000, "GIFT", address));
vm::CellSlice(vm::NoVm(), res).print_rec(std::cerr);
CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == res->get_hash());
}
diff --git a/submodules/ton/tonlib-src/tonlib/test/online.cpp b/submodules/ton/tonlib-src/tonlib/test/online.cpp
index 8f5a73e9a0..716f9153bc 100644
--- a/submodules/ton/tonlib-src/tonlib/test/online.cpp
+++ b/submodules/ton/tonlib-src/tonlib/test/online.cpp
@@ -118,7 +118,7 @@ void transfer_grams(Client& client, std::string from, std::string to, td::int64
auto balance = get_balance(client, to);
sync_send(client, tonlib_api::make_object(
std::move(input_key), tonlib_api::make_object(from),
- tonlib_api::make_object(to), amount))
+ tonlib_api::make_object(to), amount, "GIFT"))
.ensure();
while (balance == get_balance(client, to)) {
client.receive(1);
@@ -270,7 +270,7 @@ int main(int argc, char* argv[]) {
{
sync_send(client, make_object(
make_object(wallet_addr.rserialize()), seqno,
- 1000000000ll * 6666 / 1000))
+ 1000000000ll * 6666 / 1000, "GIFT"))
.ensure();
}
@@ -307,9 +307,10 @@ int main(int argc, char* argv[]) {
}
{
- sync_send(client, make_object(
- create_input_key(), make_object(wallet_addr.rserialize()),
- make_object(test_giver_address), 1000000000ll * 3333 / 1000))
+ sync_send(client,
+ make_object(
+ create_input_key(), make_object(wallet_addr.rserialize()),
+ make_object(test_giver_address), 1000000000ll * 3333 / 1000, "GIFT"))
.ensure();
}
while (true) {
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/BlockchainInfoStorage.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/BlockchainInfoStorage.cpp
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/BlockchainInfoStorage.h b/submodules/ton/tonlib-src/tonlib/tonlib/BlockchainInfoStorage.h
deleted file mode 100644
index 4a249cffa2..0000000000
--- a/submodules/ton/tonlib-src/tonlib/tonlib/BlockchainInfoStorage.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include "tonlib/LastBlock.h"
-
-namespace tonlib {
-class BlockchainInfoStorage {
- td::Status set_directory(std::string directory);
- td::Result get_state(ZeroStateIdExt);
- void save_state(LastBlock::State state);
-};
-} // namespace tonlib
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp
index 5633363dab..0ec942ed90 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp
@@ -21,10 +21,10 @@
#include "tonlib/LastBlock.h"
namespace tonlib {
-void ExtClient::with_last_block(td::Promise promise) {
+void ExtClient::with_last_block(td::Promise promise) {
auto query_id = last_block_queries_.create(std::move(promise));
- td::Promise P = [query_id, self = this,
- actor_id = td::actor::actor_id()](td::Result result) {
+ td::Promise P = [query_id, self = this,
+ actor_id = td::actor::actor_id()](td::Result result) {
send_lambda(actor_id, [self, query_id, result = std::move(result)]() mutable {
self->last_block_queries_.extract(query_id).set_result(std::move(result));
});
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h
index 8f92ea9e1b..dca5cdfdd4 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h
@@ -29,7 +29,7 @@
namespace tonlib {
class LastBlock;
-struct LastBlockInfo;
+struct LastBlockState;
struct ExtClientRef {
td::actor::ActorId andl_ext_client_;
td::actor::ActorId last_block_actor_;
@@ -50,7 +50,7 @@ class ExtClient {
return client_;
}
- void with_last_block(td::Promise promise);
+ void with_last_block(td::Promise promise);
template
void send_query(QueryT query, td::Promise promise) {
@@ -75,7 +75,7 @@ class ExtClient {
private:
ExtClientRef client_;
td::Container> queries_;
- td::Container> last_block_queries_;
+ td::Container> last_block_queries_;
void send_raw_query(td::BufferSlice query, td::Promise promise);
};
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp
index ca02099400..330393c0e7 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp
@@ -28,7 +28,7 @@ td::Ref GenericAccount::get_init_state(td::Ref code, td::Ref
.finalize();
}
block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id, const td::Ref& init_state) {
- return block::StdAddress(workchain_id, init_state->get_hash().bits());
+ return block::StdAddress(workchain_id, init_state->get_hash().bits(), false);
}
td::Ref GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref new_state,
td::Ref body) {
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp
index f4754023c9..3593adc5ec 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp
@@ -23,13 +23,23 @@
#include "lite-client/lite-client-common.h"
namespace tonlib {
-LastBlock::LastBlock(ExtClientRef client, State state, td::unique_ptr callback)
+
+td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state) {
+ return sb << td::tag("last_block", state.last_block_id.to_str())
+ << td::tag("last_key_block", state.last_key_block_id.to_str()) << td::tag("utime", state.utime);
+}
+
+LastBlock::LastBlock(ExtClientRef client, LastBlockState state, td::unique_ptr callback)
: state_(std::move(state)), callback_(std::move(callback)) {
client_.set_client(client);
}
-void LastBlock::get_last_block(td::Promise promise) {
+void LastBlock::get_last_block(td::Promise promise) {
if (promises_.empty()) {
+ total_sync_ = td::Timer();
+ validate_ = td::Timer(true);
+ queries_ = 0;
+ LOG(INFO) << "Begin last block synchronization " << state_;
do_get_last_block();
}
promises_.push_back(std::move(promise));
@@ -41,6 +51,7 @@ void LastBlock::do_get_last_block() {
//return;
//liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof;
+ queries_++;
client_.send_query(
ton::lite_api::liteServer_getBlockProof(0, create_tl_lite_block_id(state_.last_key_block_id), nullptr),
[this, from = state_.last_key_block_id](auto r_block_proof) {
@@ -51,21 +62,30 @@ void LastBlock::do_get_last_block() {
td::Result LastBlock::process_block_proof(
ton::BlockIdExt from,
td::Result> r_block_proof) {
+ validate_.resume();
+ SCOPE_EXIT {
+ validate_.pause();
+ };
+
TRY_RESULT(block_proof, std::move(r_block_proof));
- LOG(ERROR) << to_string(block_proof);
+ LOG(DEBUG) << "Got proof FROM\n" << to_string(block_proof->from_) << "TO\n" << to_string(block_proof->to_);
TRY_RESULT(chain, liteclient::deserialize_proof_chain(std::move(block_proof)));
if (chain->from != from) {
return td::Status::Error(PSLICE() << "block proof chain starts from block " << chain->from.to_str()
<< ", not from requested block " << from.to_str());
}
TRY_STATUS(chain->validate());
- update_mc_last_block(chain->to);
+ bool is_changed = false;
+ is_changed |= update_mc_last_block(chain->to);
if (chain->has_key_block) {
- update_mc_last_key_block(chain->key_blkid);
+ is_changed |= update_mc_last_key_block(chain->key_blkid);
}
if (chain->has_utime) {
update_utime(chain->last_utime);
}
+ if (is_changed) {
+ callback_->on_state_changed(state_);
+ }
return chain->complete;
}
@@ -73,17 +93,20 @@ void LastBlock::on_block_proof(
ton::BlockIdExt from,
td::Result> r_block_proof) {
auto r_is_ready = process_block_proof(from, std::move(r_block_proof));
+ bool is_ready;
if (r_is_ready.is_error()) {
- LOG(WARNING) << "Failed liteServer_getBlockProof " << r_is_ready.error();
- return;
+ LOG(WARNING) << "Error during last block synchronization " << r_is_ready.error();
+ is_ready = true;
+ } else {
+ is_ready = r_is_ready.move_as_ok();
}
- auto is_ready = r_is_ready.move_as_ok();
if (is_ready) {
+ LOG(INFO) << "End last block synchronization " << state_ << "\n"
+ << " net queries: " << queries_ << "\n"
+ << " total: " << total_sync_ << " validation: " << validate_;
for (auto& promise : promises_) {
- LastBlockInfo res;
- res.id = state_.last_block_id;
- res.utime = state_.utime;
- promise.set_value(std::move(res));
+ auto state = state_;
+ promise.set_value(std::move(state));
}
promises_.clear();
} else {
@@ -101,10 +124,8 @@ void LastBlock::on_masterchain_info(
LOG(WARNING) << "Failed liteServer_getMasterchainInfo " << r_info.error();
}
for (auto& promise : promises_) {
- LastBlockInfo res;
- res.id = state_.last_block_id;
- res.utime = state_.utime;
- promise.set_value(std::move(res));
+ auto state = state_;
+ promise.set_value(std::move(state));
}
promises_.clear();
}
@@ -131,25 +152,30 @@ void LastBlock::update_zero_state(ton::ZeroStateIdExt zero_state_id) {
// One will have to restart ton client
}
-void LastBlock::update_mc_last_block(ton::BlockIdExt mc_block_id) {
+bool LastBlock::update_mc_last_block(ton::BlockIdExt mc_block_id) {
if (!mc_block_id.is_valid()) {
LOG(ERROR) << "Ignore invalid masterchain block";
- return;
+ return false;
}
if (!state_.last_block_id.is_valid() || state_.last_block_id.id.seqno < mc_block_id.id.seqno) {
state_.last_block_id = mc_block_id;
LOG(INFO) << "Update masterchain block id: " << state_.last_block_id.to_str();
+ return true;
}
+ return false;
}
-void LastBlock::update_mc_last_key_block(ton::BlockIdExt mc_key_block_id) {
+
+bool LastBlock::update_mc_last_key_block(ton::BlockIdExt mc_key_block_id) {
if (!mc_key_block_id.is_valid()) {
LOG(ERROR) << "Ignore invalid masterchain block";
- return;
+ return false;
}
if (!state_.last_key_block_id.is_valid() || state_.last_key_block_id.id.seqno < mc_key_block_id.id.seqno) {
state_.last_key_block_id = mc_key_block_id;
LOG(INFO) << "Update masterchain key block id: " << state_.last_key_block_id.to_str();
+ return true;
}
+ return false;
}
void LastBlock::update_utime(td::int64 utime) {
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h
index 968f21bddb..bb250d749e 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h
@@ -22,35 +22,114 @@
#include "tonlib/ExtClient.h"
namespace tonlib {
-struct LastBlockInfo {
- ton::BlockIdExt id;
+td::StringBuilder &operator<<(td::StringBuilder &sb, const LastBlockState &state);
+template
+void store(const td::BitArray &arr, StorerT &storer) {
+ storer.store_binary(arr);
+}
+template
+void parse(td::BitArray &arr, ParserT &parser) {
+ arr = parser.template fetch_binary>();
+}
+
+template
+void store(const ton::ZeroStateIdExt &zero_state_id, StorerT &storer) {
+ using td::store;
+ using tonlib::store;
+ store(zero_state_id.workchain, storer);
+ store(zero_state_id.root_hash, storer);
+ store(zero_state_id.file_hash, storer);
+}
+template
+void parse(ton::ZeroStateIdExt &zero_state_id, ParserT &parser) {
+ using td::parse;
+ using tonlib::parse;
+ parse(zero_state_id.workchain, parser);
+ parse(zero_state_id.root_hash, parser);
+ parse(zero_state_id.file_hash, parser);
+}
+template
+void store(const ton::BlockId &block_id, StorerT &storer) {
+ using td::store;
+ using tonlib::store;
+ store(block_id.workchain, storer);
+ store(block_id.shard, storer);
+ store(block_id.seqno, storer);
+}
+template
+void parse(ton::BlockId &block_id, ParserT &parser) {
+ using td::parse;
+ using tonlib::parse;
+ parse(block_id.workchain, parser);
+ parse(block_id.shard, parser);
+ parse(block_id.seqno, parser);
+}
+template
+void store(const ton::BlockIdExt &block_id, StorerT &storer) {
+ using td::store;
+ using tonlib::store;
+ store(block_id.id, storer);
+ store(block_id.root_hash, storer);
+ store(block_id.file_hash, storer);
+}
+template
+void parse(ton::BlockIdExt &block_id, ParserT &parser) {
+ using td::parse;
+ using tonlib::parse;
+ parse(block_id.id, parser);
+ parse(block_id.root_hash, parser);
+ parse(block_id.file_hash, parser);
+}
+struct LastBlockState {
+ ton::ZeroStateIdExt zero_state_id;
+ ton::BlockIdExt last_key_block_id;
+ ton::BlockIdExt last_block_id;
td::int64 utime{0};
+
+ template
+ void store(StorerT &storer) const {
+ using td::store;
+ using tonlib::store;
+ store(zero_state_id, storer);
+ store(last_key_block_id, storer);
+ store(last_block_id, storer);
+ store(utime, storer);
+ }
+
+ template
+ void parse(ParserT &parser) {
+ using td::parse;
+ using tonlib::parse;
+ parse(zero_state_id, parser);
+ parse(last_key_block_id, parser);
+ parse(last_block_id, parser);
+ parse(utime, parser);
+ }
};
+
class LastBlock : public td::actor::Actor {
public:
- struct State {
- ton::ZeroStateIdExt zero_state_id;
- ton::BlockIdExt last_key_block_id;
- ton::BlockIdExt last_block_id;
- td::int64 utime{0};
- };
-
class Callback {
public:
virtual ~Callback() {
}
- virtual void on_state_changes(State state) = 0;
+ virtual void on_state_changed(LastBlockState state) = 0;
};
- explicit LastBlock(ExtClientRef client, State state, td::unique_ptr callback);
- void get_last_block(td::Promise promise);
+ explicit LastBlock(ExtClientRef client, LastBlockState state, td::unique_ptr callback);
+ void get_last_block(td::Promise promise);
private:
ExtClient client_;
- State state_;
+ LastBlockState state_;
td::unique_ptr callback_;
- std::vector> promises_;
+ // stats
+ td::Timer total_sync_;
+ td::Timer validate_;
+ td::uint32 queries_;
+
+ std::vector> promises_;
void do_get_last_block();
void on_masterchain_info(td::Result> r_info);
@@ -62,8 +141,8 @@ class LastBlock : public td::actor::Actor {
void update_zero_state(ton::ZeroStateIdExt zero_state_id);
- void update_mc_last_block(ton::BlockIdExt mc_block_id);
- void update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
+ bool update_mc_last_block(ton::BlockIdExt mc_block_id);
+ bool update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
void update_utime(td::int64 utime);
};
} // namespace tonlib
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.cpp
new file mode 100644
index 0000000000..fa979a3ca3
--- /dev/null
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.cpp
@@ -0,0 +1,44 @@
+#include "LastBlockStorage.h"
+
+#include "td/utils/as.h"
+#include "td/utils/filesystem.h"
+#include "td/utils/port/path.h"
+#include "td/utils/tl_helpers.h"
+
+namespace tonlib {
+
+td::Status LastBlockStorage::set_directory(std::string directory) {
+ TRY_RESULT(path, td::realpath(directory));
+ TRY_RESULT(stat, td::stat(path));
+ if (!stat.is_dir_) {
+ return td::Status::Error("not a directory");
+ }
+ directory_ = std::move(path);
+ return td::Status::OK();
+}
+
+std::string LastBlockStorage::get_file_name(td::Slice name) {
+ return directory_ + TD_DIR_SLASH + td::buffer_to_hex(name) + ".blkstate";
+}
+
+td::Result LastBlockStorage::get_state(td::Slice name) {
+ TRY_RESULT(data, td::read_file(get_file_name(name)));
+ if (data.size() < 8) {
+ return td::Status::Error("too short");
+ }
+ if (td::as(data.data()) != td::crc64(td::Slice(data).substr(8))) {
+ return td::Status::Error("crc64 mismatch");
+ }
+ LastBlockState res;
+ TRY_STATUS(td::unserialize(res, td::Slice(data).substr(8)));
+ return res;
+}
+
+void LastBlockStorage::save_state(td::Slice name, LastBlockState state) {
+ auto x = td::serialize(state);
+ std::string y(x.size() + 8, 0);
+ td::MutableSlice(y).substr(8).copy_from(x);
+ td::as(td::MutableSlice(y).data()) = td::crc64(x);
+ td::atomic_write_file(get_file_name(name), y);
+}
+} // namespace tonlib
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.h b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.h
new file mode 100644
index 0000000000..fa920ef6ed
--- /dev/null
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "tonlib/LastBlock.h"
+
+namespace tonlib {
+class LastBlockStorage {
+ public:
+ td::Status set_directory(std::string directory);
+ td::Result get_state(td::Slice name);
+ void save_state(td::Slice name, LastBlockState state);
+
+ private:
+ std::string directory_;
+ std::string get_file_name(td::Slice name);
+};
+} // namespace tonlib
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp
index c9ebbcc9df..9ea58e54e2 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp
@@ -32,8 +32,9 @@ vm::CellHash TestGiver::get_init_code_hash() {
return vm::CellHash::from_slice(td::base64_decode("wDkZp0yR4xo+9+BnuAPfGVjBzK6FPzqdv2DwRq3z3KE=").move_as_ok());
}
-td::Ref TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gramms,
+td::Ref TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message,
const block::StdAddress& dest_address) {
+ CHECK(message.size() <= 128);
td::BigInt256 dest_addr;
dest_addr.import_bits(dest_address.addr.as_bitslice());
vm::CellBuilder cb;
@@ -44,7 +45,7 @@ td::Ref TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gr
.store_int256(dest_addr, 256);
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
- auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("GIFT").finalize();
+ auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes(message).finalize();
return vm::CellBuilder().store_long(seqno, 32).store_long(1, 8).store_ref(message_inner).finalize();
}
} // namespace tonlib
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.h b/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.h
index 88ccd1b772..6859be8ff0 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.h
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.h
@@ -23,7 +23,7 @@ class TestGiver {
public:
static const block::StdAddress& address();
static vm::CellHash get_init_code_hash();
- static td::Ref make_a_gift_message(td::uint32 seqno, td::uint64 gramms,
+ static td::Ref make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message,
const block::StdAddress& dest_address);
};
} // namespace tonlib
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp
index bda32c1752..c092bac29c 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp
@@ -38,7 +38,9 @@ td::Ref TestWallet::get_init_message(const td::Ed25519::PrivateKey& pr
}
td::Ref TestWallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno,
- td::int64 gramms, const block::StdAddress& dest_address) {
+ td::int64 gramms, td::Slice message,
+ const block::StdAddress& dest_address) {
+ CHECK(message.size() <= 128);
td::BigInt256 dest_addr;
dest_addr.import_bits(dest_address.addr.as_bitslice());
vm::CellBuilder cb;
@@ -46,11 +48,11 @@ td::Ref TestWallet::make_a_gift_message(const td::Ed25519::PrivateKey&
.store_long(dest_address.workchain, 8)
.store_int256(dest_addr, 256);
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
- auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("GIFT").finalize();
- auto message = vm::CellBuilder().store_long(seqno, 32).store_long(1, 8).store_ref(message_inner).finalize();
+ auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes(message).finalize();
+ auto message_outer = vm::CellBuilder().store_long(seqno, 32).store_long(1, 8).store_ref(message_inner).finalize();
std::string seq_no(4, 0);
- auto signature = private_key.sign(message->get_hash().as_slice()).move_as_ok();
- return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message)).finalize();
+ auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok();
+ return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize();
}
td::Ref TestWallet::get_init_code() {
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.h b/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.h
index f4de1f6ae6..921e3b3afe 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.h
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.h
@@ -28,7 +28,8 @@ class TestWallet {
static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key);
static td::Ref get_init_message(const td::Ed25519::PrivateKey& private_key);
static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno,
- td::int64 gramms, const block::StdAddress& dest_address);
+ td::int64 gramms, td::Slice message,
+ const block::StdAddress& dest_address);
static td::Ref get_init_code();
static vm::CellHash get_init_code_hash();
diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp
index 7b48876f93..ea0c6c81e9 100644
--- a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp
+++ b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp
@@ -41,8 +41,6 @@
#include "td/utils/tests.h"
#include "td/utils/port/path.h"
-namespace ton {} // namespace ton
-
namespace tonlib {
template
@@ -152,6 +150,11 @@ class GetTransactionHistory : public td::actor::Actor {
}
void start_up() override {
+ if (lt_ == 0) {
+ promise_.set_value(block::TransactionList::Info());
+ stop();
+ return;
+ }
client_.send_query(
ton::lite_api::liteServer_getTransactions(
count_, ton::create_tl_object(address_.workchain, address_.addr), lt_,
@@ -171,7 +174,7 @@ class GetRawAccountState : public td::actor::Actor {
block::StdAddress address_;
td::Promise promise_;
ExtClient client_;
- LastBlockInfo last_block_;
+ LastBlockState last_block_;
void with_account_state(td::Result> r_account_state) {
promise_.set_result(TRY_VM(do_with_account_state(std::move(r_account_state))));
@@ -182,7 +185,7 @@ class GetRawAccountState : public td::actor::Actor {
td::Result> r_account_state) {
TRY_RESULT(raw_account_state, std::move(r_account_state));
auto account_state = create_account_state(std::move(raw_account_state));
- TRY_RESULT(info, account_state.validate(last_block_.id, address_));
+ TRY_RESULT(info, account_state.validate(last_block_.last_block_id, address_));
auto serialized_state = account_state.state.clone();
RawAccountState res;
res.info = std::move(info);
@@ -225,14 +228,14 @@ class GetRawAccountState : public td::actor::Actor {
}
void start_up() override {
- client_.with_last_block([self = this](td::Result r_last_block) {
+ client_.with_last_block([self = this](td::Result r_last_block) {
if (r_last_block.is_error()) {
return self->check(r_last_block.move_as_error());
}
self->last_block_ = r_last_block.move_as_ok();
self->client_.send_query(
- ton::lite_api::liteServer_getAccountState(ton::create_tl_lite_block_id(self->last_block_.id),
+ ton::lite_api::liteServer_getAccountState(ton::create_tl_lite_block_id(self->last_block_.last_block_id),
ton::create_tl_object(
self->address_.workchain, self->address_.addr)),
[self](auto r_state) { self->with_account_state(std::move(r_state)); });
@@ -307,24 +310,36 @@ void TonlibClient::init_ext_client() {
td::make_unique(td::actor::actor_shared()));
}
}
+
+void TonlibClient::update_last_block_state(LastBlockState state) {
+ last_block_storage_.save_state("none", state);
+}
+
void TonlibClient::init_last_block() {
ref_cnt_++;
class Callback : public LastBlock::Callback {
public:
Callback(td::actor::ActorShared client) : client_(std::move(client)) {
}
- void on_state_changes(LastBlock::State state) override {
- //TODO
+ void on_state_changed(LastBlockState state) override {
+ send_closure(client_, &TonlibClient::update_last_block_state, std::move(state));
}
private:
td::actor::ActorShared client_;
};
- LastBlock::State state;
- //state.zero_state_id = ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash,
- //config_.zero_state_id.file_hash),
- state.last_block_id = config_.zero_state_id;
- state.last_key_block_id = config_.zero_state_id;
+ LastBlockState state;
+
+ auto r_state = last_block_storage_.get_state("none");
+ if (r_state.is_error()) {
+ LOG(WARNING) << "Unknown LastBlockState: " << r_state.error();
+ state.zero_state_id = ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash,
+ config_.zero_state_id.file_hash),
+ state.last_block_id = config_.zero_state_id;
+ state.last_key_block_id = config_.zero_state_id;
+ } else {
+ state = r_state.move_as_ok();
+ }
raw_last_block_ = td::actor::create_actor("LastBlock", get_client_ref(), std::move(state),
td::make_unique