From 96a68a619bf61ebc223685fec154add007c02e5d Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 21 Sep 2019 01:30:01 +0300 Subject: [PATCH] Wallet send & receive screens --- BUCK | 21 +- Telegram-iOS/Info.plist | 6 +- .../buck-project.meta.json | 2 +- .../contents.xcworkspacedata | 2 +- .../xcschemes/Telegram_Buck.xcscheme | 14 + submodules/Camera/BUCK | 18 + .../Camera/Camera.xcodeproj/project.pbxproj | 501 +++++++++++++ .../xcshareddata/xcschemes/Camera.xcscheme | 1 + submodules/Camera/Info.plist | 22 + submodules/Camera/Sources/Camera.h | 11 + submodules/Camera/Sources/Camera.swift | 183 +++++ submodules/Camera/Sources/CameraDevice.swift | 138 ++++ submodules/Camera/Sources/CameraInput.swift | 45 ++ submodules/Camera/Sources/CameraOutput.swift | 67 ++ .../Camera/Sources/CameraPreviewNode.swift | 50 ++ submodules/Camera/Sources/CameraUtils.swift | 43 ++ .../Sources/CreatePollController.swift | 2 +- .../Sources/HashtagSearchControllerNode.swift | 13 +- submodules/HexColor/BUCK | 3 + .../HexColor.xcodeproj/project.pbxproj | 206 ++++++ submodules/HexColor/Sources/HexColor.swift | 17 +- .../Items/ItemListMultilineInputItem.swift | 50 +- .../Items/ItemListMultilineTextItem.swift | 24 +- .../Items/ItemListSingleLineInputItem.swift | 14 +- .../Sources/PasscodeEntryInputFieldNode.swift | 22 +- .../PasscodeUI/Sources/PasscodeLayout.swift | 4 +- .../Sources/ChannelInfoController.swift | 2 - .../Sources/GroupInfoController.swift | 2 - .../Sources/PeerReportController.swift | 2 +- submodules/QrCode/BUCK | 14 +- .../QrCode/QrCode.xcodeproj/project.pbxproj | 158 +++- submodules/QrCode/Sources/BitBuffer.cpp | 41 ++ submodules/QrCode/Sources/BitBuffer.hpp | 52 ++ submodules/QrCode/Sources/QrCode.cpp | 660 +++++++++++++++++ submodules/QrCode/Sources/QrCode.hpp | 350 +++++++++ .../Sources/{QRCode.swift => QrCode.swift} | 72 +- submodules/QrCode/Sources/QrCodeInstance.h | 18 + submodules/QrCode/Sources/QrCodeInstance.mm | 28 + submodules/QrCode/Sources/QrSegment.cpp | 225 ++++++ submodules/QrCode/Sources/QrSegment.hpp | 216 ++++++ .../SettingsUI.xcodeproj/project.pbxproj | 22 + ...hareProxyServerActionSheetController.swift | 4 +- .../Sources/EditSettingsController.swift | 3 +- .../Sources/CallFeedbackController.swift | 2 +- .../Settings/Test.imageset/Contents.json | 21 + .../Settings/Test.imageset/Test.png | Bin 0 -> 109352 bytes .../PasscodeIcon.imageset/Contents.json | 12 + .../PasscodeIcon.imageset/PasscodeIcon.pdf | Bin 0 -> 50370 bytes .../Wallet/SendingIcon.imageset/Contents.json | 21 + .../SendingIcon.imageset/SendingIcon@3x.png | Bin 0 -> 103984 bytes .../TelegramUI/TelegramUI/AppDelegate.swift | 2 +- .../TelegramUI/CreateChannelController.swift | 2 - .../Sources/UpdateInfoController.swift | 2 +- .../TextFormat/Sources/StringPadding.swift | 17 + .../TextFormat.xcodeproj/project.pbxproj | 20 + submodules/WalletUI/BUCK | 12 +- .../WalletUI/Sources/WalletInfoScreen.swift | 11 +- .../Sources/WalletPasscodeScreen.swift | 250 +++++++ .../WalletUI/Sources/WalletQrCodeItem.swift | 209 ++++++ .../WalletUI/Sources/WalletQrScanScreen.swift | 184 +++++ .../Sources/WalletReceiveScreen.swift | 196 +++++ .../WalletUI/Sources/WalletSendScreen.swift | 425 +++++++++++ .../WalletUI/Sources/WalletSplashScreen.swift | 55 +- .../WalletUI.xcodeproj/project.pbxproj | 694 +++++++++++++++++- 64 files changed, 5366 insertions(+), 117 deletions(-) create mode 100644 submodules/Camera/BUCK create mode 100644 submodules/Camera/Camera.xcodeproj/project.pbxproj create mode 100644 submodules/Camera/Camera.xcodeproj/xcshareddata/xcschemes/Camera.xcscheme create mode 100644 submodules/Camera/Info.plist create mode 100644 submodules/Camera/Sources/Camera.h create mode 100644 submodules/Camera/Sources/Camera.swift create mode 100644 submodules/Camera/Sources/CameraDevice.swift create mode 100644 submodules/Camera/Sources/CameraInput.swift create mode 100644 submodules/Camera/Sources/CameraOutput.swift create mode 100644 submodules/Camera/Sources/CameraPreviewNode.swift create mode 100644 submodules/Camera/Sources/CameraUtils.swift create mode 100755 submodules/QrCode/Sources/BitBuffer.cpp create mode 100755 submodules/QrCode/Sources/BitBuffer.hpp create mode 100755 submodules/QrCode/Sources/QrCode.cpp create mode 100755 submodules/QrCode/Sources/QrCode.hpp rename submodules/QrCode/Sources/{QRCode.swift => QrCode.swift} (52%) create mode 100755 submodules/QrCode/Sources/QrCodeInstance.h create mode 100755 submodules/QrCode/Sources/QrCodeInstance.mm create mode 100755 submodules/QrCode/Sources/QrSegment.cpp create mode 100755 submodules/QrCode/Sources/QrSegment.hpp create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Test.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Test.imageset/Test.png create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Wallet/PasscodeIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Wallet/PasscodeIcon.imageset/PasscodeIcon.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Wallet/SendingIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Wallet/SendingIcon.imageset/SendingIcon@3x.png create mode 100644 submodules/TextFormat/Sources/StringPadding.swift create mode 100644 submodules/WalletUI/Sources/WalletPasscodeScreen.swift create mode 100644 submodules/WalletUI/Sources/WalletQrCodeItem.swift create mode 100644 submodules/WalletUI/Sources/WalletQrScanScreen.swift create mode 100644 submodules/WalletUI/Sources/WalletReceiveScreen.swift create mode 100644 submodules/WalletUI/Sources/WalletSendScreen.swift diff --git a/BUCK b/BUCK index 660f12f65b..83d0e06861 100644 --- a/BUCK +++ b/BUCK @@ -397,6 +397,15 @@ apple_bundle( # Watch +apple_resource( + name = "WatchAppStringResources", + files = [], + variants = glob([ + "Telegram-iOS/*.lproj/Localizable.strings", + ]), + visibility = ["PUBLIC"], +) + apple_binary( name = "WatchAppExtensionBinary", srcs = glob([ @@ -426,6 +435,9 @@ apple_binary( "$SDKROOT/System/Library/Frameworks/CoreLocation.framework", "$SDKROOT/System/Library/Frameworks/CoreGraphics.framework", ], + deps = [ + ":WatchAppStringResources", + ], ) apple_bundle( @@ -460,15 +472,6 @@ apple_resource( visibility = ["PUBLIC"], ) -apple_resource( - name = "WatchAppStringResources", - files = [], - variants = glob([ - "Telegram-iOS/*.lproj/Localizable.strings", - ]), - visibility = ["PUBLIC"], -) - apple_binary( name = "WatchAppBinary", configs = watch_binary_configs(), diff --git a/Telegram-iOS/Info.plist b/Telegram-iOS/Info.plist index 2dc4525f1d..ff93b6667c 100644 --- a/Telegram-iOS/Info.plist +++ b/Telegram-iOS/Info.plist @@ -202,7 +202,7 @@ CFBundleTypeRole - Editor + Viewer CFBundleURLName $(PRODUCT_BUNDLE_IDENTIFIER).compatibility CFBundleURLSchemes @@ -215,10 +215,10 @@ CFBundleTypeRole Viewer CFBundleURLName - $(PRODUCT_BUNDLE_IDENTIFIER).dropbox + $(PRODUCT_BUNDLE_IDENTIFIER).ton CFBundleURLSchemes - db-pa9wtoz9l514anx + ton diff --git a/Telegram_Buck.xcworkspace/buck-project.meta.json b/Telegram_Buck.xcworkspace/buck-project.meta.json index 573f189fa5..3e9789ef89 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/MtProtoKit:openssl_libs","//submodules/MtProtoKit:ton_libs","//submodules/Opus:opus_lib_file","//submodules/WebP:WebP_lib_file"],"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/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/MtProtoKit/openssl-Debug.xcconfig","buck-out/gen/submodules/MtProtoKit/openssl-Profile.xcconfig","buck-out/gen/submodules/MtProtoKit/openssl-Release.xcconfig","buck-out/gen/submodules/MtProtoKit/ton-Debug.xcconfig","buck-out/gen/submodules/MtProtoKit/ton-Profile.xcconfig","buck-out/gen/submodules/MtProtoKit/ton-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/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/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"],"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/MtProtoKit:openssl_libs","//submodules/MtProtoKit:ton_libs","//submodules/Opus:opus_lib_file","//submodules/WebP:WebP_lib_file"],"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/MtProtoKit/openssl-Debug.xcconfig","buck-out/gen/submodules/MtProtoKit/openssl-Profile.xcconfig","buck-out/gen/submodules/MtProtoKit/openssl-Release.xcconfig","buck-out/gen/submodules/MtProtoKit/ton-Debug.xcconfig","buck-out/gen/submodules/MtProtoKit/ton-Profile.xcconfig","buck-out/gen/submodules/MtProtoKit/ton-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/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/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"],"copy-in-xcode":[]} \ No newline at end of file diff --git a/Telegram_Buck.xcworkspace/contents.xcworkspacedata b/Telegram_Buck.xcworkspace/contents.xcworkspacedata index 3e61562224..f8d39baefe 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 3a3c953561..4598c4b8b6 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme @@ -2218,6 +2218,20 @@ ReferencedContainer = "container:submodules/UrlHandling/UrlHandling.xcodeproj"> + + + + + + + + archiveVersion + 1 + classes + + + objectVersion + 46 + objects + + 1DD70E29001F47FB00000000 + + isa + PBXFileReference + name + BUCK + path + BUCK + sourceTree + SOURCE_ROOT + explicitFileType + text.script.python + + 1DD70E2992F8922A00000000 + + isa + PBXFileReference + name + Camera.swift + path + Sources/Camera.swift + sourceTree + SOURCE_ROOT + + 1DD70E2908EBF46000000000 + + isa + PBXFileReference + name + CameraDevice.swift + path + Sources/CameraDevice.swift + sourceTree + SOURCE_ROOT + + 1DD70E29264D2E6A00000000 + + isa + PBXFileReference + name + CameraInput.swift + path + Sources/CameraInput.swift + sourceTree + SOURCE_ROOT + + 1DD70E29387802CB00000000 + + isa + PBXFileReference + name + CameraOutput.swift + path + Sources/CameraOutput.swift + sourceTree + SOURCE_ROOT + + 1DD70E29FFA2D84A00000000 + + isa + PBXFileReference + name + CameraPreviewNode.swift + path + Sources/CameraPreviewNode.swift + sourceTree + SOURCE_ROOT + + 1DD70E29F10E5E1100000000 + + isa + PBXFileReference + name + CameraUtils.swift + path + Sources/CameraUtils.swift + sourceTree + SOURCE_ROOT + + B401C979EAB5339800000000 + + isa + PBXGroup + name + Sources + sourceTree + ]]> + children + + 1DD70E2992F8922A00000000 + 1DD70E2908EBF46000000000 + 1DD70E29264D2E6A00000000 + 1DD70E29387802CB00000000 + 1DD70E29FFA2D84A00000000 + 1DD70E29F10E5E1100000000 + + + B401C97977DEAF4500000000 + + isa + PBXGroup + name + Camera + sourceTree + ]]> + children + + 1DD70E29001F47FB00000000 + B401C979EAB5339800000000 + + + 1DD70E2939BFF6D000000000 + + isa + PBXFileReference + name + Camera-Debug.xcconfig + path + ../../buck-out/gen/submodules/Camera/Camera-Debug.xcconfig + sourceTree + SOURCE_ROOT + explicitFileType + text.xcconfig + + 1DD70E29AEC01A3A00000000 + + isa + PBXFileReference + name + Camera-Profile.xcconfig + path + ../../buck-out/gen/submodules/Camera/Camera-Profile.xcconfig + sourceTree + SOURCE_ROOT + explicitFileType + text.xcconfig + + 1DD70E292256C59C00000000 + + isa + PBXFileReference + name + Camera-Release.xcconfig + path + ../../buck-out/gen/submodules/Camera/Camera-Release.xcconfig + sourceTree + SOURCE_ROOT + explicitFileType + text.xcconfig + + B401C9792F7F325000000000 + + isa + PBXGroup + name + Buck (Do Not Modify) + sourceTree + ]]> + children + + 1DD70E2939BFF6D000000000 + 1DD70E29AEC01A3A00000000 + 1DD70E292256C59C00000000 + + + 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 + + + 1DD70E29BFBD457D00000000 + + isa + PBXFileReference + name + libCamera.a + path + libCamera.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + B401C979C806358400000000 + + isa + PBXGroup + name + Products + sourceTree + ]]> + children + + 1DD70E29BFBD457D00000000 + + + B401C979EFB6AC4600000000 + + isa + PBXGroup + name + mainGroup + sourceTree + ]]> + children + + B401C97977DEAF4500000000 + B401C979B781F65D00000000 + B401C97968022A5500000000 + B401C979C806358400000000 + + + E7A30F0492F8922A00000000 + + isa + PBXBuildFile + fileRef + 1DD70E2992F8922A00000000 + + E7A30F0408EBF46000000000 + + isa + PBXBuildFile + fileRef + 1DD70E2908EBF46000000000 + + E7A30F04264D2E6A00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29264D2E6A00000000 + + E7A30F04387802CB00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29387802CB00000000 + + E7A30F04FFA2D84A00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29FFA2D84A00000000 + + E7A30F04F10E5E1100000000 + + isa + PBXBuildFile + fileRef + 1DD70E29F10E5E1100000000 + + 1870857F0000000000000000 + + isa + PBXSourcesBuildPhase + files + + E7A30F0492F8922A00000000 + E7A30F0408EBF46000000000 + E7A30F04264D2E6A00000000 + E7A30F04387802CB00000000 + E7A30F04FFA2D84A00000000 + E7A30F04F10E5E1100000000 + + + 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 + 1DD70E2939BFF6D000000000 + + 4952437350C7218900000000 + + isa + XCBuildConfiguration + name + Profile + buildSettings + + + baseConfigurationReference + 1DD70E29AEC01A3A00000000 + + 49524373A439BFE700000000 + + isa + XCBuildConfiguration + name + Release + buildSettings + + + baseConfigurationReference + 1DD70E292256C59C00000000 + + 218C37090000000000000000 + + isa + XCConfigurationList + buildConfigurations + + 4952437303EDA63300000000 + 4952437350C7218900000000 + 49524373A439BFE700000000 + + defaultConfigurationIsVisible + + + E66DC04E77DEAF4500000000 + + isa + PBXNativeTarget + name + Camera + productName + Camera + productReference + 1DD70E29BFBD457D00000000 + 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 + + + 96C8479377DEAF4500000000 + + isa + PBXProject + mainGroup + B401C979EFB6AC4600000000 + targets + + E66DC04E77DEAF4500000000 + + buildConfigurationList + 218C37090000000000000001 + compatibilityVersion + Xcode 3.2 + attributes + + LastUpgradeCheck + 9999 + + + + rootObject + 96C8479377DEAF4500000000 + + \ No newline at end of file diff --git a/submodules/Camera/Camera.xcodeproj/xcshareddata/xcschemes/Camera.xcscheme b/submodules/Camera/Camera.xcodeproj/xcshareddata/xcschemes/Camera.xcscheme new file mode 100644 index 0000000000..209bf1cfc3 --- /dev/null +++ b/submodules/Camera/Camera.xcodeproj/xcshareddata/xcschemes/Camera.xcscheme @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/submodules/Camera/Info.plist b/submodules/Camera/Info.plist new file mode 100644 index 0000000000..e1fe4cfb7b --- /dev/null +++ b/submodules/Camera/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/Camera/Sources/Camera.h b/submodules/Camera/Sources/Camera.h new file mode 100644 index 0000000000..f8d2a3b3ed --- /dev/null +++ b/submodules/Camera/Sources/Camera.h @@ -0,0 +1,11 @@ +#import + +//! Project version number for Camera. +FOUNDATION_EXPORT double CameraVersionNumber; + +//! Project version string for Camera. +FOUNDATION_EXPORT const unsigned char CameraVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/submodules/Camera/Sources/Camera.swift b/submodules/Camera/Sources/Camera.swift new file mode 100644 index 0000000000..0af6423ea2 --- /dev/null +++ b/submodules/Camera/Sources/Camera.swift @@ -0,0 +1,183 @@ +import Foundation +import SwiftSignalKit +import AVFoundation + +private final class CameraContext { + private let queue: Queue + private let session = AVCaptureSession() + private let device: CameraDevice + private let input = CameraInput() + private let output = CameraOutput() + + private let initialConfiguration: Camera.Configuration + + var previewNode: CameraPreviewNode? { + didSet { + self.previewNode?.prepare() + } + } + + var previousSampleBuffer: CMSampleBuffer? + var processSampleBuffer: ((CMSampleBuffer) -> Void)? + + private var invalidated = false + + init(queue: Queue, configuration: Camera.Configuration) { + self.queue = queue + self.initialConfiguration = configuration + + self.device = CameraDevice() + self.device.configure(for: self.session, position: configuration.position) + + self.session.beginConfiguration() + self.session.sessionPreset = configuration.preset + self.input.configure(for: self.session, device: self.device, audio: configuration.audio) + self.output.configure(for: self.session) + self.session.commitConfiguration() + + self.output.processSampleBuffer = { [weak self] sampleBuffer, connection in + if let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer), CMFormatDescriptionGetMediaType(formatDescription) == kCMMediaType_Video { + self?.previousSampleBuffer = sampleBuffer + self?.previewNode?.enqueue(sampleBuffer) + } + + self?.queue.async { + self?.processSampleBuffer?(sampleBuffer) + } + } + } + + func startCapture() { + guard !self.session.isRunning else { + return + } + + self.session.startRunning() + } + + func stopCapture() { + self.session.beginConfiguration() + self.input.invalidate(for: self.session) + self.output.invalidate(for: self.session) + self.session.commitConfiguration() + + self.session.stopRunning() + } + + func focus(at point: CGPoint) { + self.device.setFocusPoint(point, focusMode: .continuousAutoFocus, exposureMode: .continuousAutoExposure, monitorSubjectAreaChange: true) + } + + func setFPS(_ fps: Float64) { + self.device.fps = fps + } + + func togglePosition() { + self.session.beginConfiguration() + self.input.invalidate(for: self.session) + let targetPosition: Camera.Position + if case .back = self.device.position { + targetPosition = .front + } else { + targetPosition = .back + } + self.device.configure(for: self.session, position: targetPosition) + self.input.configure(for: self.session, device: self.device, audio: self.initialConfiguration.audio) + self.session.commitConfiguration() + } +} + +final class Camera { + typealias Preset = AVCaptureSession.Preset + typealias Position = AVCaptureDevice.Position + typealias FocusMode = AVCaptureDevice.FocusMode + typealias ExposureMode = AVCaptureDevice.ExposureMode + + struct Configuration { + let preset: Preset + let position: Position + let audio: Bool + } + + private let queue = Queue() + private var contextRef: Unmanaged? + + 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) + } + } + + deinit { + let contextRef = self.contextRef + self.queue.async { + contextRef?.release() + } + } + + func startCapture() { + self.queue.async { + if let context = self.contextRef?.takeUnretainedValue() { + context.startCapture() + } + } + } + + func stopCapture() { + self.queue.async { + if let context = self.contextRef?.takeUnretainedValue() { + context.stopCapture() + } + } + } + func togglePosition() { + self.queue.async { + if let context = self.contextRef?.takeUnretainedValue() { + context.togglePosition() + } + } + } + + func takePhoto() -> Signal { + return .never() + } + + func focus(at point: CGPoint) { + self.queue.async { + if let context = self.contextRef?.takeUnretainedValue() { + context.focus(at: point) + } + } + } + + func setFPS(_ fps: Double) { + self.queue.async { + if let context = self.contextRef?.takeUnretainedValue() { + context.setFPS(fps) + } + } + } + + func attachPreviewNode(_ node: CameraPreviewNode) { + let nodeRef: Unmanaged = Unmanaged.passRetained(node) + self.queue.async { + if let context = self.contextRef?.takeUnretainedValue() { + context.previewNode = nodeRef.takeUnretainedValue() + nodeRef.release() + } else { + Queue.mainQueue().async { + nodeRef.release() + } + } + } + } + + func setProcessSampleBuffer(_ block: ((CMSampleBuffer) -> Void)?) { + self.queue.async { + if let context = self.contextRef?.takeUnretainedValue() { + context.processSampleBuffer = block + } + } + } +} diff --git a/submodules/Camera/Sources/CameraDevice.swift b/submodules/Camera/Sources/CameraDevice.swift new file mode 100644 index 0000000000..90d110db6f --- /dev/null +++ b/submodules/Camera/Sources/CameraDevice.swift @@ -0,0 +1,138 @@ +import Foundation +import AVFoundation +import SwiftSignalKit + +private let defaultFPS: Double = 30.0 + +final class CameraDevice { + public private(set) var videoDevice: AVCaptureDevice? = nil + public private(set) var audioDevice: AVCaptureDevice? = nil + private var videoDevicePromise = Promise() + + init() { + } + + var position: Camera.Position = .back + + func configure(for session: AVCaptureSession, position: Camera.Position) { + self.position = position + if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { + self.videoDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDuoCamera, .builtInWideAngleCamera, .builtInTelephotoCamera], mediaType: .video, position: position).devices.first + } else { + self.videoDevice = AVCaptureDevice.devices(for: .video).filter { $0.position == position }.first + } + if let videoDevice = self.videoDevice { + self.videoDevicePromise.set(.single(videoDevice)) + } + self.audioDevice = AVCaptureDevice.default(for: .audio) + } + + func transaction(_ device: AVCaptureDevice, update: (AVCaptureDevice) -> Void) { + if let _ = try? device.lockForConfiguration() { + update(device) + device.unlockForConfiguration() + } + } + + private func subscribeForChanges() { + NotificationCenter.default.addObserver(self, selector: #selector(self.subjectAreaChanged), name: Notification.Name.AVCaptureDeviceSubjectAreaDidChange, object: self.videoDevice) + } + + private func unsubscribeFromChanges() { + NotificationCenter.default.removeObserver(self, name: Notification.Name.AVCaptureDeviceSubjectAreaDidChange, object: self.videoDevice) + } + + @objc private func subjectAreaChanged() { + + } + + var fps: Double = defaultFPS { + didSet { + guard let device = self.videoDevice, let targetFPS = device.actualFPS(Double(self.fps)) else { + return + } + + self.fps = targetFPS.fps + + self.transaction(device) { device in + device.activeVideoMinFrameDuration = targetFPS.duration + device.activeVideoMaxFrameDuration = targetFPS.duration + } + } + } + + var isFlashActive: Signal { + return self.videoDevicePromise.get() + |> mapToSignal { device -> Signal in + return Signal { subscriber in + subscriber.putNext(device.isFlashActive) + let observer = device.observe(\.isFlashActive, options: [.new], changeHandler: { device, _ in + subscriber.putNext(device.isFlashActive) + }) + return ActionDisposable { + observer.invalidate() + } + } + |> distinctUntilChanged + } + } + + var isFlashAvailable: Signal { + return self.videoDevicePromise.get() + |> mapToSignal { device -> Signal in + return Signal { subscriber in + subscriber.putNext(device.isFlashAvailable) + let observer = device.observe(\.isFlashAvailable, options: [.new], changeHandler: { device, _ in + subscriber.putNext(device.isFlashAvailable) + }) + return ActionDisposable { + observer.invalidate() + } + } + |> distinctUntilChanged + } + } + + var isAdjustingFocus: Signal { + return self.videoDevicePromise.get() + |> mapToSignal { device -> Signal in + return Signal { subscriber in + subscriber.putNext(device.isAdjustingFocus) + let observer = device.observe(\.isAdjustingFocus, options: [.new], changeHandler: { device, _ in + subscriber.putNext(device.isAdjustingFocus) + }) + return ActionDisposable { + observer.invalidate() + } + } + |> distinctUntilChanged + } + } + + func setFocusPoint(_ point: CGPoint, focusMode: Camera.FocusMode, exposureMode: Camera.ExposureMode, monitorSubjectAreaChange: Bool) { + guard let device = self.videoDevice else { + return + } + self.transaction(device) { device in + if device.isExposurePointOfInterestSupported && device.isExposureModeSupported(exposureMode) { + device.exposurePointOfInterest = point + device.exposureMode = exposureMode + } + if device.isFocusPointOfInterestSupported && device.isFocusModeSupported(focusMode) { + device.focusPointOfInterest = point + device.focusMode = focusMode + } + } + } + + func setExposureTargetBias(_ bias: Float) { + guard let device = self.videoDevice else { + return + } + self.transaction(device) { device in + let extremum = (bias >= 0) ? device.maxExposureTargetBias : device.minExposureTargetBias; + let value = abs(bias) * extremum * 0.85 + device.setExposureTargetBias(value, completionHandler: nil) + } + } +} diff --git a/submodules/Camera/Sources/CameraInput.swift b/submodules/Camera/Sources/CameraInput.swift new file mode 100644 index 0000000000..690e019ed6 --- /dev/null +++ b/submodules/Camera/Sources/CameraInput.swift @@ -0,0 +1,45 @@ +import AVFoundation + +class CameraInput { + private var videoInput: AVCaptureDeviceInput? + private var audioInput: AVCaptureDeviceInput? + + func configure(for session: AVCaptureSession, device: CameraDevice, audio: Bool) { + if let videoDevice = device.videoDevice { + self.configureVideoInput(for: session, device: videoDevice) + } + if audio, let audioDevice = device.audioDevice { + self.configureAudioInput(for: session, device: audioDevice) + } + } + + func invalidate(for session: AVCaptureSession) { + for input in session.inputs { + session.removeInput(input) + } + } + + private func configureVideoInput(for session: AVCaptureSession, device: AVCaptureDevice) { + if let videoInput = try? AVCaptureDeviceInput(device: device) { + if let currentVideoInput = self.videoInput { + session.removeInput(currentVideoInput) + } + self.videoInput = videoInput + if session.canAddInput(videoInput) { + session.addInput(videoInput) + } + } + } + + private func configureAudioInput(for session: AVCaptureSession, device: AVCaptureDevice) { + guard self.audioInput == nil else { + return + } + if let audioInput = try? AVCaptureDeviceInput(device: device) { + self.audioInput = audioInput + if session.canAddInput(audioInput) { + session.addInput(audioInput) + } + } + } +} diff --git a/submodules/Camera/Sources/CameraOutput.swift b/submodules/Camera/Sources/CameraOutput.swift new file mode 100644 index 0000000000..a7cb2258c5 --- /dev/null +++ b/submodules/Camera/Sources/CameraOutput.swift @@ -0,0 +1,67 @@ +import AVFoundation + +final class CameraOutput: NSObject { + //private let photoOutput = CameraPhotoOutput() + private let videoOutput = AVCaptureVideoDataOutput() + private let audioOutput = AVCaptureAudioDataOutput() + private let metadataOutput = AVCaptureMetadataOutput() + + private let queue = DispatchQueue(label: "") + + var processSampleBuffer: ((CMSampleBuffer, AVCaptureConnection) -> Void)? + var processQRCode: ((String, AVMetadataMachineReadableCodeObject) -> Void)? + + override init() { + super.init() + + self.videoOutput.alwaysDiscardsLateVideoFrames = true; + self.videoOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] as [String : Any] + } + + deinit { + self.videoOutput.setSampleBufferDelegate(nil, queue: nil) + self.audioOutput.setSampleBufferDelegate(nil, queue: nil) + } + + func configure(for session: AVCaptureSession) { + if session.canAddOutput(self.videoOutput) { + session.addOutput(self.videoOutput) + self.videoOutput.setSampleBufferDelegate(self, queue: self.queue) + } + if session.canAddOutput(self.audioOutput) { + session.addOutput(self.audioOutput) + self.audioOutput.setSampleBufferDelegate(self, queue: self.queue) + } + if session.canAddOutput(self.metadataOutput) { + session.addOutput(self.metadataOutput) + } + } + + func invalidate(for session: AVCaptureSession) { + for output in session.outputs { + session.removeOutput(output) + } + } +} + +extension CameraOutput: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate { + func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { + guard CMSampleBufferDataIsReady(sampleBuffer) else { + return + } + + self.processSampleBuffer?(sampleBuffer, connection) + } + + func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { + + } +} + +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) + } + } +} diff --git a/submodules/Camera/Sources/CameraPreviewNode.swift b/submodules/Camera/Sources/CameraPreviewNode.swift new file mode 100644 index 0000000000..9f18fa7e21 --- /dev/null +++ b/submodules/Camera/Sources/CameraPreviewNode.swift @@ -0,0 +1,50 @@ +import Foundation +import AsyncDisplayKit +import Display +import AVFoundation + +private final class CameraPreviewNodeLayerNullAction: NSObject, CAAction { + @objc func run(forKey event: String, object anObject: Any, arguments dict: [AnyHashable : Any]?) { + } +} + +private final class CameraPreviewNodeLayer: AVSampleBufferDisplayLayer { + override func action(forKey event: String) -> CAAction? { + return CameraPreviewNodeLayerNullAction() + } +} + +class CameraPreviewNode: ASDisplayNode { + private var displayLayer: AVSampleBufferDisplayLayer + + override init() { + self.displayLayer = AVSampleBufferDisplayLayer() + self.displayLayer.videoGravity = .resizeAspectFill + + super.init() + + self.clipsToBounds = true + + self.layer.addSublayer(self.displayLayer) + } + + func prepare() { + DispatchQueue.main.async { + self.displayLayer.flushAndRemoveImage() + } + } + + func enqueue(_ sampleBuffer: CMSampleBuffer) { + self.displayLayer.enqueue(sampleBuffer) + } + + override func layout() { + super.layout() + + var transform = CGAffineTransform(rotationAngle: CGFloat.pi / 2.0) + transform = transform.scaledBy(x: 1.0, y: -1.0) + self.displayLayer.setAffineTransform(transform) + + self.displayLayer.frame = self.bounds + } +} diff --git a/submodules/Camera/Sources/CameraUtils.swift b/submodules/Camera/Sources/CameraUtils.swift new file mode 100644 index 0000000000..7f83618271 --- /dev/null +++ b/submodules/Camera/Sources/CameraUtils.swift @@ -0,0 +1,43 @@ +import AVFoundation + +extension AVFrameRateRange { + func clamp(rate: Float64) -> Float64 { + return max(self.minFrameRate, min(self.maxFrameRate, rate)) + } + + func contains(rate: Float64) -> Bool { + return (self.minFrameRate...self.maxFrameRate) ~= rate + } +} + +extension AVCaptureDevice { + func actualFPS(_ fps: Double) -> (fps: Double, duration: CMTime)? { + var durations: [CMTime] = [] + var frameRates: [Double] = [] + + for range in self.activeFormat.videoSupportedFrameRateRanges { + if range.minFrameRate == range.maxFrameRate { + durations.append(range.minFrameDuration) + frameRates.append(range.maxFrameRate) + continue + } + + if range.contains(rate: fps) { + return (fps, CMTimeMake(value: 100, timescale: Int32(100 * fps))) + } + + let actualFPS: Double = range.clamp(rate: fps) + return (actualFPS, CMTimeMake(value: 100, timescale: Int32(100 * actualFPS))) + } + + let diff = frameRates.map { abs($0 - fps) } + + if let minElement: Float64 = diff.min() { + for i in 0..B401C9792F7F325000000000 + 1DD70E29FF334B1F00000000 + + isa + PBXFileReference + name + libDisplay.dylib + path + libDisplay.dylib + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + compiled.mach-o.dylib + + 1DD70E2936DE2CF900000000 + + isa + PBXFileReference + name + libMediaResources.a + path + libMediaResources.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29DB6520C800000000 + + isa + PBXFileReference + name + libPostbox.dylib + path + libPostbox.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 + + 1DD70E29119CDA0700000000 + + isa + PBXFileReference + name + libTelegramCore.dylib + path + libTelegramCore.dylib + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + compiled.mach-o.dylib + + 1DD70E2984A59C1D00000000 + + isa + PBXFileReference + name + libTelegramPresentationData.a + path + libTelegramPresentationData.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E292395015100000000 + + isa + PBXFileReference + name + libTelegramUIPreferences.a + path + libTelegramUIPreferences.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29F0C15F9C00000000 + + isa + PBXFileReference + name + libTextFormat.a + path + libTextFormat.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + B401C97968022A5500000000 + + isa + PBXGroup + name + Frameworks + sourceTree + ]]> + children + + 1DD70E29FF334B1F00000000 + 1DD70E2936DE2CF900000000 + 1DD70E29DB6520C800000000 + 1DD70E29D65BA68200000000 + 1DD70E29119CDA0700000000 + 1DD70E2984A59C1D00000000 + 1DD70E292395015100000000 + 1DD70E29F0C15F9C00000000 + + 1DD70E29001F47FB00000000 isa @@ -166,6 +290,7 @@ children B401C979B781F65D00000000 + B401C97968022A5500000000 B401C979E6D3C92800000000 B401C979C806358400000000 @@ -186,6 +311,86 @@ E7A30F049A1D75CD00000000 + E7A30F04FF334B1F00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29FF334B1F00000000 + + E7A30F04119CDA0700000000 + + isa + PBXBuildFile + fileRef + 1DD70E29119CDA0700000000 + + E7A30F04DB6520C800000000 + + isa + PBXBuildFile + fileRef + 1DD70E29DB6520C800000000 + + E7A30F04D65BA68200000000 + + isa + PBXBuildFile + fileRef + 1DD70E29D65BA68200000000 + + E7A30F0436DE2CF900000000 + + isa + PBXBuildFile + fileRef + 1DD70E2936DE2CF900000000 + + E7A30F042395015100000000 + + isa + PBXBuildFile + fileRef + 1DD70E292395015100000000 + + E7A30F0484A59C1D00000000 + + isa + PBXBuildFile + fileRef + 1DD70E2984A59C1D00000000 + + E7A30F04F0C15F9C00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29F0C15F9C00000000 + + FAF5FAC90000000000000000 + + isa + PBXCopyFilesBuildPhase + files + + E7A30F04FF334B1F00000000 + E7A30F04119CDA0700000000 + E7A30F04DB6520C800000000 + E7A30F04D65BA68200000000 + E7A30F0436DE2CF900000000 + E7A30F042395015100000000 + E7A30F0484A59C1D00000000 + E7A30F04F0C15F9C00000000 + + name + Fake Swift Dependencies (Copy Files Phase) + runOnlyForDeploymentPostprocessing + 1 + dstSubfolderSpec + 16 + dstPath + + 4952437303EDA63300000000 isa @@ -253,6 +458,7 @@ buildPhases 1870857F0000000000000000 + FAF5FAC90000000000000000 buildConfigurationList 218C37090000000000000000 diff --git a/submodules/HexColor/Sources/HexColor.swift b/submodules/HexColor/Sources/HexColor.swift index 24fa5263c8..181590c87e 100644 --- a/submodules/HexColor/Sources/HexColor.swift +++ b/submodules/HexColor/Sources/HexColor.swift @@ -1,21 +1,6 @@ import Foundation import UIKit - -private extension String { - func rightJustified(width: Int, pad: String = " ", truncate: Bool = false) -> String { - guard width > count else { - return truncate ? String(suffix(width)) : self - } - return String(repeating: pad, count: width - count) + self - } - - func leftJustified(width: Int, pad: String = " ", truncate: Bool = false) -> String { - guard width > count else { - return truncate ? String(prefix(width)) : self - } - return self + String(repeating: pad, count: width - count) - } -} +import TextFormat public extension UIColor { var hexString: String { diff --git a/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift b/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift index 28c7a274bc..3d131bfeac 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift @@ -21,19 +21,29 @@ public class ItemListMultilineInputItem: ListViewItem, ItemListItem { let placeholder: String public let sectionId: ItemListSectionId let style: ItemListStyle - let action: () -> Void + let capitalization: Bool + let autocorrection: Bool + let returnKeyType: UIReturnKeyType + let action: (() -> Void)? let textUpdated: (String) -> Void + let shouldUpdateText: (String) -> Bool public let tag: ItemListItemTag? let maxLength: ItemListMultilineInputItemTextLimit? + let minimalHeight: CGFloat? - public init(theme: PresentationTheme, text: String, placeholder: String, maxLength: ItemListMultilineInputItemTextLimit?, sectionId: ItemListSectionId, style: ItemListStyle, textUpdated: @escaping (String) -> Void, tag: ItemListItemTag? = nil, action: @escaping () -> Void) { + 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) { self.theme = theme self.text = text self.placeholder = placeholder self.maxLength = maxLength self.sectionId = sectionId self.style = style + self.capitalization = capitalization + self.autocorrection = autocorrection + self.returnKeyType = returnKeyType + self.minimalHeight = minimalHeight self.textUpdated = textUpdated + self.shouldUpdateText = shouldUpdateText self.tag = tag self.action = action } @@ -188,7 +198,12 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod let textTopInset: CGFloat = 11.0 let textBottomInset: CGFloat = 11.0 - let contentSize = CGSize(width: params.width, height: textLayout.size.height + textTopInset + textBottomInset) + var contentHeight: CGFloat = textLayout.size.height + textTopInset + textBottomInset + if let minimalHeight = item.minimalHeight { + contentHeight = max(minimalHeight, contentHeight) + } + + let contentSize = CGSize(width: params.width, height: contentHeight) let insets = itemListNeighborsGroupedInsets(neighbors) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) @@ -212,6 +227,19 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod } } + let capitalizationType: UITextAutocapitalizationType = item.capitalization ? .sentences : .none + let autocorrectionType: UITextAutocorrectionType = item.autocorrection ? .default : .no + + if strongSelf.textNode.textView.autocapitalizationType != capitalizationType { + strongSelf.textNode.textView.autocapitalizationType = capitalizationType + } + if strongSelf.textNode.textView.autocorrectionType != autocorrectionType { + strongSelf.textNode.textView.autocorrectionType = autocorrectionType + } + if strongSelf.textNode.textView.returnKeyType != item.returnKeyType { + strongSelf.textNode.textView.returnKeyType = item.returnKeyType + } + let _ = textApply() if let currentText = strongSelf.textNode.attributedText { if currentText.string != attributedText.string { @@ -299,6 +327,22 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod self.textClippingNode.frame = CGRect(origin: CGPoint(x: leftInset, y: textTopInset), size: CGSize(width: max(0.0, params.width - leftInset - params.rightInset), height: max(0.0, contentSize.height - textTopInset - textBottomInset))) } + public func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { + if let item = self.item { + if let action = item.action, text == "\n" { + action() + return false + } + + var newText: String = editableTextNode.textView.text + newText.replaceSubrange(newText.index(newText.startIndex, offsetBy: range.lowerBound) ..< newText.index(newText.startIndex, offsetBy: range.upperBound), with: text) + if !item.shouldUpdateText(newText) { + return false + } + } + return true + } + public func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) { if let item = self.item { if let text = self.textNode.attributedText { diff --git a/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift b/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift index 72f3e11cfb..3a2c18d0e2 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift @@ -7,10 +7,16 @@ import TelegramPresentationData import TextFormat import AccountContext +public enum ItemListMultilineTextBaseFont { + case `default` + case monospace +} + public class ItemListMultilineTextItem: ListViewItem, ItemListItem { let theme: PresentationTheme let text: String let enabledEntityTypes: EnabledEntityTypes + let font: ItemListMultilineTextBaseFont public let sectionId: ItemListSectionId let style: ItemListStyle let action: (() -> Void)? @@ -21,10 +27,11 @@ public class ItemListMultilineTextItem: ListViewItem, ItemListItem { public let selectable: Bool - public init(theme: PresentationTheme, text: String, enabledEntityTypes: EnabledEntityTypes, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) { + public init(theme: PresentationTheme, text: String, enabledEntityTypes: EnabledEntityTypes, font: ItemListMultilineTextBaseFont = .default, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) { self.theme = theme self.text = text self.enabledEntityTypes = enabledEntityTypes + self.font = font self.sectionId = sectionId self.style = style self.action = action @@ -175,8 +182,21 @@ public class ItemListMultilineTextItemNode: ListViewItemNode { leftInset = 16.0 + params.rightInset } + var baseFont = titleFont + var linkFont = titleFont + var boldFont = titleBoldFont + var italicFont = titleItalicFont + var boldItalicFont = titleBoldItalicFont + if case .monospace = item.font { + baseFont = Font.monospace(17.0) + linkFont = Font.monospace(17.0) + boldFont = Font.semiboldMonospace(17.0) + italicFont = Font.italicMonospace(17.0) + boldItalicFont = Font.semiboldItalicMonospace(17.0) + } + let entities = generateTextEntities(item.text, enabledTypes: item.enabledEntityTypes) - let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: textColor, linkColor: item.theme.list.itemAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleBoldFont, italicFont: titleItalicFont, boldItalicFont: titleBoldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: titleFont) + let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: textColor, linkColor: item.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: titleFont) let (titleLayout, titleApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) diff --git a/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift b/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift index 660d2fa35f..07c75821c4 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift @@ -10,6 +10,7 @@ public enum ItemListSingleLineInputItemType: Equatable { case password case email case number + case decimal case username } @@ -262,6 +263,11 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg } else { keyboardType = .numberPad } + case .decimal: + secureEntry = false + capitalizationType = .none + autocorrectionType = .no + keyboardType = .decimalPad case .username: secureEntry = false capitalizationType = .none @@ -393,8 +399,12 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg } @objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - if let item = self.item, !item.shouldUpdateText(string) { - return false + if let item = self.item { + var newText = textField.text ?? "" + newText.replaceSubrange(newText.index(newText.startIndex, offsetBy: range.lowerBound) ..< newText.index(newText.startIndex, offsetBy: range.upperBound), with: string) + if !item.shouldUpdateText(newText) { + return false + } } if string.count > 1, let item = self.item, let processPaste = item.processPaste { diff --git a/submodules/PasscodeUI/Sources/PasscodeEntryInputFieldNode.swift b/submodules/PasscodeUI/Sources/PasscodeEntryInputFieldNode.swift index 97fb1f56b7..119811902c 100644 --- a/submodules/PasscodeUI/Sources/PasscodeEntryInputFieldNode.swift +++ b/submodules/PasscodeUI/Sources/PasscodeEntryInputFieldNode.swift @@ -128,7 +128,7 @@ private class PasscodeEntryDotNode: ASImageNode { } } -final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { +public final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { private var background: PasscodeBackground? private var color: UIColor private var accentColor: UIColor @@ -141,19 +141,19 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { private var validLayout: PasscodeLayout? - var complete: ((String) -> Void)? + public var complete: ((String) -> Void)? - var text: String { + public var text: String { return self.textFieldNode.textField.text ?? "" } - var keyboardAppearance: UIKeyboardAppearance { + public var keyboardAppearance: UIKeyboardAppearance { didSet { self.textFieldNode.textField.keyboardAppearance = self.keyboardAppearance } } - init(color: UIColor, accentColor: UIColor, fieldType: PasscodeEntryFieldType, keyboardAppearance: UIKeyboardAppearance, useCustomNumpad: Bool = false) { + public init(color: UIColor, accentColor: UIColor, fieldType: PasscodeEntryFieldType, keyboardAppearance: UIKeyboardAppearance, useCustomNumpad: Bool = false) { self.color = color self.accentColor = accentColor self.fieldType = fieldType @@ -175,7 +175,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { self.addSubnode(self.borderNode) } - override func didLoad() { + override public func didLoad() { super.didLoad() self.textFieldNode.textField.isSecureTextEntry = true @@ -214,7 +214,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { } } - func activateInput() { + public func activateInput() { self.textFieldNode.textField.becomeFirstResponder() } @@ -245,7 +245,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { } } - func reset(animated: Bool = true) { + public func reset(animated: Bool = true) { var delay: Double = 0.0 for node in self.dotNodes.reversed() { if node.alpha < 1.0 { @@ -297,7 +297,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { } } - func update(fieldType: PasscodeEntryFieldType) { + public func update(fieldType: PasscodeEntryFieldType) { if fieldType != self.fieldType { self.textFieldNode.textField.text = "" } @@ -307,7 +307,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { } } - func updateLayout(layout: PasscodeLayout, transition: ContainedViewLayoutTransition) -> CGRect { + public func updateLayout(layout: PasscodeLayout, transition: ContainedViewLayoutTransition) -> CGRect { self.validLayout = layout let fieldAlpha: CGFloat @@ -353,7 +353,7 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { return fieldFrame } - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let currentText = textField.text ?? "" let text = (currentText as NSString).replacingCharacters(in: range, with: string) if let maxLength = self.fieldType.maxLength, text.count > maxLength { diff --git a/submodules/PasscodeUI/Sources/PasscodeLayout.swift b/submodules/PasscodeUI/Sources/PasscodeLayout.swift index 28ecd125be..90a8c918bf 100644 --- a/submodules/PasscodeUI/Sources/PasscodeLayout.swift +++ b/submodules/PasscodeUI/Sources/PasscodeLayout.swift @@ -108,7 +108,7 @@ struct PasscodeKeyboardLayout { } } -struct PasscodeLayout { +public struct PasscodeLayout { let layout: ContainerViewLayout let keyboard: PasscodeKeyboardLayout let titleOffset: CGFloat @@ -155,7 +155,7 @@ struct PasscodeLayout { } } - init(layout: ContainerViewLayout, titleOffset: CGFloat, subtitleOffset: CGFloat, inputFieldOffset: CGFloat) { + public init(layout: ContainerViewLayout, titleOffset: CGFloat, subtitleOffset: CGFloat, inputFieldOffset: CGFloat) { self.layout = layout self.keyboard = PasscodeKeyboardLayout(layout: layout) self.titleOffset = titleOffset diff --git a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift b/submodules/PeerInfoUI/Sources/ChannelInfoController.swift index 6d136daa9c..cc40e51e79 100644 --- a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelInfoController.swift @@ -355,8 +355,6 @@ private enum ChannelInfoEntry: ItemListNodeEntry { case let .channelDescriptionSetup(theme, placeholder, value): return ItemListMultilineInputItem(theme: theme, text: value, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .plain, textUpdated: { updatedText in arguments.updateEditingDescriptionText(updatedText) - }, action: { - }) case let .admins(theme, text, value): return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: { diff --git a/submodules/PeerInfoUI/Sources/GroupInfoController.swift b/submodules/PeerInfoUI/Sources/GroupInfoController.swift index 06c8beae09..af05be151b 100644 --- a/submodules/PeerInfoUI/Sources/GroupInfoController.swift +++ b/submodules/PeerInfoUI/Sources/GroupInfoController.swift @@ -541,8 +541,6 @@ private enum GroupInfoEntry: ItemListNodeEntry { case let .groupDescriptionSetup(theme, placeholder, text): return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in arguments.updateEditingDescriptionText(updatedText) - }, action: { - }) case let .permissions(theme, title, text): return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesChat.groupInfoPermissionsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: { diff --git a/submodules/PeerInfoUI/Sources/PeerReportController.swift b/submodules/PeerInfoUI/Sources/PeerReportController.swift index db0614a5bb..01261f203e 100644 --- a/submodules/PeerInfoUI/Sources/PeerReportController.swift +++ b/submodules/PeerInfoUI/Sources/PeerReportController.swift @@ -254,7 +254,7 @@ private enum PeerReportControllerEntry: ItemListNodeEntry { case let .text(theme, title, value): return ItemListMultilineInputItem(theme: theme, text: value, placeholder: title, maxLength: nil, sectionId: self.section, style: .blocks, textUpdated: { text in arguments.updateText(text) - }, tag: PeerReportControllerEntryTag.text, action: {}) + }, tag: PeerReportControllerEntryTag.text) } } } diff --git a/submodules/QrCode/BUCK b/submodules/QrCode/BUCK index 1661dd7beb..f1dd281d16 100644 --- a/submodules/QrCode/BUCK +++ b/submodules/QrCode/BUCK @@ -4,11 +4,23 @@ static_library( name = "QrCode", srcs = glob([ "Sources/**/*.swift", - ]), + "Sources/**/*.cpp", + ]) + [ + "Sources/QrCodeInstance.mm" + ], + has_cpp = True, deps = [ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit#shared", "//submodules/Display:Display#shared", ], + headers = glob([ + "Sources/**/*.hpp", + ]) + [ + "Sources/QrCodeInstance.h" + ], + exported_headers = [ + "Sources/QrCodeInstance.h" + ], frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework", diff --git a/submodules/QrCode/QrCode.xcodeproj/project.pbxproj b/submodules/QrCode/QrCode.xcodeproj/project.pbxproj index 6c5e1c3c2f..cd6b029c10 100644 --- a/submodules/QrCode/QrCode.xcodeproj/project.pbxproj +++ b/submodules/QrCode/QrCode.xcodeproj/project.pbxproj @@ -157,16 +157,120 @@ explicitFileType text.script.python - 1DD70E29213163D300000000 + 1DD70E2905A53BC200000000 isa PBXFileReference name - QRCode.swift + BitBuffer.cpp path - Sources/QRCode.swift + 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 @@ -178,7 +282,15 @@ ]]> children - 1DD70E29213163D300000000 + 1DD70E2905A53BC200000000 + 1DD70E2905A54E8700000000 + 1DD70E2921C2F78300000000 + 1DD70E2921C30A4800000000 + 1DD70E29BDC7BBF300000000 + 1DD70E2956ECDFBD00000000 + 1DD70E2986AF18EB00000000 + 1DD70E290F1C936700000000 + 1DD70E290F1CA62C00000000 B401C979909F23CE00000000 @@ -211,12 +323,40 @@ B401C979909F23CE00000000 - E7A30F04213163D300000000 + E7A30F0405A53BC200000000 isa PBXBuildFile fileRef - 1DD70E29213163D300000000 + 1DD70E2905A53BC200000000 + + E7A30F0421C2F78300000000 + + isa + PBXBuildFile + fileRef + 1DD70E2921C2F78300000000 + + E7A30F04BDC7BBF300000000 + + isa + PBXBuildFile + fileRef + 1DD70E29BDC7BBF300000000 + + E7A30F0486AF18EB00000000 + + isa + PBXBuildFile + fileRef + 1DD70E2986AF18EB00000000 + + E7A30F040F1C936700000000 + + isa + PBXBuildFile + fileRef + 1DD70E290F1C936700000000 1870857F0000000000000000 @@ -224,7 +364,11 @@ PBXSourcesBuildPhase files - E7A30F04213163D300000000 + E7A30F0405A53BC200000000 + E7A30F0421C2F78300000000 + E7A30F04BDC7BBF300000000 + E7A30F0486AF18EB00000000 + E7A30F040F1C936700000000 E7A30F04FF334B1F00000000 diff --git a/submodules/QrCode/Sources/BitBuffer.cpp b/submodules/QrCode/Sources/BitBuffer.cpp new file mode 100755 index 0000000000..e22e9d3381 --- /dev/null +++ b/submodules/QrCode/Sources/BitBuffer.cpp @@ -0,0 +1,41 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#include +#include "BitBuffer.hpp" + + +namespace qrcodegen { + +BitBuffer::BitBuffer() + : std::vector() {} + + +void BitBuffer::appendBits(std::uint32_t val, int len) { + if (len < 0 || len > 31 || val >> len != 0) + throw std::domain_error("Value out of range"); + for (int i = len - 1; i >= 0; i--) // Append bit by bit + this->push_back(((val >> i) & 1) != 0); +} + +} diff --git a/submodules/QrCode/Sources/BitBuffer.hpp b/submodules/QrCode/Sources/BitBuffer.hpp new file mode 100755 index 0000000000..f30913a891 --- /dev/null +++ b/submodules/QrCode/Sources/BitBuffer.hpp @@ -0,0 +1,52 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#pragma once + +#include +#include + + +namespace qrcodegen { + +/* + * An appendable sequence of bits (0s and 1s). Mainly used by QrSegment. + */ +class BitBuffer final : public std::vector { + + /*---- Constructor ----*/ + + // Creates an empty bit buffer (length 0). + public: BitBuffer(); + + + + /*---- Method ----*/ + + // Appends the given number of low-order bits of the given value + // to this buffer. Requires 0 <= len <= 31 and val < 2^len. + public: void appendBits(std::uint32_t val, int len); + +}; + +} diff --git a/submodules/QrCode/Sources/QrCode.cpp b/submodules/QrCode/Sources/QrCode.cpp new file mode 100755 index 0000000000..a6e25683c6 --- /dev/null +++ b/submodules/QrCode/Sources/QrCode.cpp @@ -0,0 +1,660 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#include +#include +#include +#include +#include +#include +#include "BitBuffer.hpp" +#include "QrCode.hpp" + +using std::int8_t; +using std::uint8_t; +using std::size_t; +using std::vector; + + +namespace qrcodegen { + +int QrCode::getFormatBits(Ecc ecl) { + switch (ecl) { + case Ecc::LOW : return 1; + case Ecc::MEDIUM : return 0; + case Ecc::QUARTILE: return 3; + case Ecc::HIGH : return 2; + default: throw std::logic_error("Assertion error"); + } +} + + +QrCode QrCode::encodeText(const char *text, Ecc ecl) { + vector segs = QrSegment::makeSegments(text); + return encodeSegments(segs, ecl); +} + + +QrCode QrCode::encodeBinary(const vector &data, Ecc ecl) { + vector segs{QrSegment::makeBytes(data)}; + return encodeSegments(segs, ecl); +} + + +QrCode QrCode::encodeSegments(const vector &segs, Ecc ecl, + int minVersion, int maxVersion, int mask, bool boostEcl) { + if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) + throw std::invalid_argument("Invalid value"); + + // Find the minimal version number to use + int version, dataUsedBits; + for (version = minVersion; ; version++) { + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available + dataUsedBits = QrSegment::getTotalBits(segs, version); + if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) + break; // This version number is found to be suitable + if (version >= maxVersion) { // All versions in the range could not fit the given data + std::ostringstream sb; + if (dataUsedBits == -1) + sb << "Segment too long"; + else { + sb << "Data length = " << dataUsedBits << " bits, "; + sb << "Max capacity = " << dataCapacityBits << " bits"; + } + throw data_too_long(sb.str()); + } + } + if (dataUsedBits == -1) + throw std::logic_error("Assertion error"); + + // Increase the error correction level while the data still fits in the current version number + for (Ecc newEcl : vector{Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) { // From low to high + if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8) + ecl = newEcl; + } + + // Concatenate all segments to create the data bit string + BitBuffer bb; + for (const QrSegment &seg : segs) { + bb.appendBits(static_cast(seg.getMode().getModeBits()), 4); + bb.appendBits(static_cast(seg.getNumChars()), seg.getMode().numCharCountBits(version)); + bb.insert(bb.end(), seg.getData().begin(), seg.getData().end()); + } + if (bb.size() != static_cast(dataUsedBits)) + throw std::logic_error("Assertion error"); + + // Add terminator and pad up to a byte if applicable + size_t dataCapacityBits = static_cast(getNumDataCodewords(version, ecl)) * 8; + if (bb.size() > dataCapacityBits) + throw std::logic_error("Assertion error"); + bb.appendBits(0, std::min(4, static_cast(dataCapacityBits - bb.size()))); + bb.appendBits(0, (8 - static_cast(bb.size() % 8)) % 8); + if (bb.size() % 8 != 0) + throw std::logic_error("Assertion error"); + + // Pad with alternating bytes until data capacity is reached + for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11) + bb.appendBits(padByte, 8); + + // Pack bits into bytes in big endian + vector dataCodewords(bb.size() / 8); + for (size_t i = 0; i < bb.size(); i++) + dataCodewords[i >> 3] |= (bb.at(i) ? 1 : 0) << (7 - (i & 7)); + + // Create the QR Code object + return QrCode(version, ecl, dataCodewords, mask); +} + + +QrCode::QrCode(int ver, Ecc ecl, const vector &dataCodewords, int mask) : + // Initialize fields and check arguments + version(ver), + errorCorrectionLevel(ecl) { + if (ver < MIN_VERSION || ver > MAX_VERSION) + throw std::domain_error("Version value out of range"); + if (mask < -1 || mask > 7) + throw std::domain_error("Mask value out of range"); + size = ver * 4 + 17; + size_t sz = static_cast(size); + modules = vector >(sz, vector(sz)); // Initially all white + isFunction = vector >(sz, vector(sz)); + + // Compute ECC, draw modules + drawFunctionPatterns(); + const vector allCodewords = addEccAndInterleave(dataCodewords); + drawCodewords(allCodewords); + + // Do masking + if (mask == -1) { // Automatically choose best mask + long minPenalty = LONG_MAX; + for (int i = 0; i < 8; i++) { + applyMask(i); + drawFormatBits(i); + long penalty = getPenaltyScore(); + if (penalty < minPenalty) { + mask = i; + minPenalty = penalty; + } + applyMask(i); // Undoes the mask due to XOR + } + } + if (mask < 0 || mask > 7) + throw std::logic_error("Assertion error"); + this->mask = mask; + applyMask(mask); // Apply the final choice of mask + drawFormatBits(mask); // Overwrite old format bits + + isFunction.clear(); + isFunction.shrink_to_fit(); +} + + +int QrCode::getVersion() const { + return version; +} + + +int QrCode::getSize() const { + return size; +} + + +QrCode::Ecc QrCode::getErrorCorrectionLevel() const { + return errorCorrectionLevel; +} + + +int QrCode::getMask() const { + return mask; +} + + +bool QrCode::getModule(int x, int y) const { + return 0 <= x && x < size && 0 <= y && y < size && module(x, y); +} + + +std::string QrCode::toSvgString(int border) const { + if (border < 0) + throw std::domain_error("Border must be non-negative"); + if (border > INT_MAX / 2 || border * 2 > INT_MAX - size) + throw std::overflow_error("Border too large"); + + std::ostringstream sb; + sb << "\n"; + sb << "\n"; + sb << "\n"; + sb << "\t\n"; + sb << "\t\n"; + sb << "\n"; + return sb.str(); +} + + +void QrCode::drawFunctionPatterns() { + // Draw horizontal and vertical timing patterns + for (int i = 0; i < size; i++) { + setFunctionModule(6, i, i % 2 == 0); + setFunctionModule(i, 6, i % 2 == 0); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + drawFinderPattern(3, 3); + drawFinderPattern(size - 4, 3); + drawFinderPattern(3, size - 4); + + // Draw numerous alignment patterns + const vector alignPatPos = getAlignmentPatternPositions(); + size_t numAlign = alignPatPos.size(); + for (size_t i = 0; i < numAlign; i++) { + for (size_t j = 0; j < numAlign; j++) { + // Don't draw on the three finder corners + if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) + drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j)); + } + } + + // Draw configuration data + drawFormatBits(0); // Dummy mask value; overwritten later in the constructor + drawVersion(); +} + + +void QrCode::drawFormatBits(int mask) { + // Calculate error correction code and pack bits + int data = getFormatBits(errorCorrectionLevel) << 3 | mask; // errCorrLvl is uint2, mask is uint3 + int rem = data; + for (int i = 0; i < 10; i++) + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + int bits = (data << 10 | rem) ^ 0x5412; // uint15 + if (bits >> 15 != 0) + throw std::logic_error("Assertion error"); + + // Draw first copy + for (int i = 0; i <= 5; i++) + setFunctionModule(8, i, getBit(bits, i)); + setFunctionModule(8, 7, getBit(bits, 6)); + setFunctionModule(8, 8, getBit(bits, 7)); + setFunctionModule(7, 8, getBit(bits, 8)); + for (int i = 9; i < 15; i++) + setFunctionModule(14 - i, 8, getBit(bits, i)); + + // Draw second copy + for (int i = 0; i < 8; i++) + setFunctionModule(size - 1 - i, 8, getBit(bits, i)); + for (int i = 8; i < 15; i++) + setFunctionModule(8, size - 15 + i, getBit(bits, i)); + setFunctionModule(8, size - 8, true); // Always black +} + + +void QrCode::drawVersion() { + if (version < 7) + return; + + // Calculate error correction code and pack bits + int rem = version; // version is uint6, in the range [7, 40] + for (int i = 0; i < 12; i++) + rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + long bits = static_cast(version) << 12 | rem; // uint18 + if (bits >> 18 != 0) + throw std::logic_error("Assertion error"); + + // Draw two copies + for (int i = 0; i < 18; i++) { + bool bit = getBit(bits, i); + int a = size - 11 + i % 3; + int b = i / 3; + setFunctionModule(a, b, bit); + setFunctionModule(b, a, bit); + } +} + + +void QrCode::drawFinderPattern(int x, int y) { + for (int dy = -4; dy <= 4; dy++) { + for (int dx = -4; dx <= 4; dx++) { + int dist = std::max(std::abs(dx), std::abs(dy)); // Chebyshev/infinity norm + int xx = x + dx, yy = y + dy; + if (0 <= xx && xx < size && 0 <= yy && yy < size) + setFunctionModule(xx, yy, dist != 2 && dist != 4); + } + } +} + + +void QrCode::drawAlignmentPattern(int x, int y) { + for (int dy = -2; dy <= 2; dy++) { + for (int dx = -2; dx <= 2; dx++) + setFunctionModule(x + dx, y + dy, std::max(std::abs(dx), std::abs(dy)) != 1); + } +} + + +void QrCode::setFunctionModule(int x, int y, bool isBlack) { + size_t ux = static_cast(x); + size_t uy = static_cast(y); + modules .at(uy).at(ux) = isBlack; + isFunction.at(uy).at(ux) = true; +} + + +bool QrCode::module(int x, int y) const { + return modules.at(static_cast(y)).at(static_cast(x)); +} + + +vector QrCode::addEccAndInterleave(const vector &data) const { + if (data.size() != static_cast(getNumDataCodewords(version, errorCorrectionLevel))) + throw std::invalid_argument("Invalid argument"); + + // Calculate parameter numbers + int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast(errorCorrectionLevel)][version]; + int blockEccLen = ECC_CODEWORDS_PER_BLOCK [static_cast(errorCorrectionLevel)][version]; + int rawCodewords = getNumRawDataModules(version) / 8; + int numShortBlocks = numBlocks - rawCodewords % numBlocks; + int shortBlockLen = rawCodewords / numBlocks; + + // Split data into blocks and append ECC to each block + vector > blocks; + const vector rsDiv = reedSolomonComputeDivisor(blockEccLen); + for (int i = 0, k = 0; i < numBlocks; i++) { + vector dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1))); + k += static_cast(dat.size()); + const vector ecc = reedSolomonComputeRemainder(dat, rsDiv); + if (i < numShortBlocks) + dat.push_back(0); + dat.insert(dat.end(), ecc.cbegin(), ecc.cend()); + blocks.push_back(std::move(dat)); + } + + // Interleave (not concatenate) the bytes from every block into a single sequence + vector result; + for (size_t i = 0; i < blocks.at(0).size(); i++) { + for (size_t j = 0; j < blocks.size(); j++) { + // Skip the padding byte in short blocks + if (i != static_cast(shortBlockLen - blockEccLen) || j >= static_cast(numShortBlocks)) + result.push_back(blocks.at(j).at(i)); + } + } + if (result.size() != static_cast(rawCodewords)) + throw std::logic_error("Assertion error"); + return result; +} + + +void QrCode::drawCodewords(const vector &data) { + if (data.size() != static_cast(getNumRawDataModules(version) / 8)) + throw std::invalid_argument("Invalid argument"); + + size_t i = 0; // Bit index into the data + // Do the funny zigzag scan + for (int right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair + if (right == 6) + right = 5; + for (int vert = 0; vert < size; vert++) { // Vertical counter + for (int j = 0; j < 2; j++) { + size_t x = static_cast(right - j); // Actual x coordinate + bool upward = ((right + 1) & 2) == 0; + size_t y = static_cast(upward ? size - 1 - vert : vert); // Actual y coordinate + if (!isFunction.at(y).at(x) && i < data.size() * 8) { + modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast(i & 7)); + i++; + } + // If this QR Code has any remainder bits (0 to 7), they were assigned as + // 0/false/white by the constructor and are left unchanged by this method + } + } + } + if (i != data.size() * 8) + throw std::logic_error("Assertion error"); +} + + +void QrCode::applyMask(int mask) { + if (mask < 0 || mask > 7) + throw std::domain_error("Mask value out of range"); + size_t sz = static_cast(size); + for (size_t y = 0; y < sz; y++) { + for (size_t x = 0; x < sz; x++) { + bool invert; + switch (mask) { + case 0: invert = (x + y) % 2 == 0; break; + case 1: invert = y % 2 == 0; break; + case 2: invert = x % 3 == 0; break; + case 3: invert = (x + y) % 3 == 0; break; + case 4: invert = (x / 3 + y / 2) % 2 == 0; break; + case 5: invert = x * y % 2 + x * y % 3 == 0; break; + case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; + case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; + default: throw std::logic_error("Assertion error"); + } + modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x)); + } + } +} + + +long QrCode::getPenaltyScore() const { + long result = 0; + + // Adjacent modules in row having same color, and finder-like patterns + for (int y = 0; y < size; y++) { + bool runColor = false; + int runX = 0; + std::array runHistory = {}; + int padRun = size; // Add white border to initial run + for (int x = 0; x < size; x++) { + if (module(x, y) == runColor) { + runX++; + if (runX == 5) + result += PENALTY_N1; + else if (runX > 5) + result++; + } else { + finderPenaltyAddHistory(runX + padRun, runHistory); + padRun = 0; + if (!runColor) + result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3; + runColor = module(x, y); + runX = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runX + padRun, runHistory) * PENALTY_N3; + } + // Adjacent modules in column having same color, and finder-like patterns + for (int x = 0; x < size; x++) { + bool runColor = false; + int runY = 0; + std::array runHistory = {}; + int padRun = size; // Add white border to initial run + for (int y = 0; y < size; y++) { + if (module(x, y) == runColor) { + runY++; + if (runY == 5) + result += PENALTY_N1; + else if (runY > 5) + result++; + } else { + finderPenaltyAddHistory(runY + padRun, runHistory); + padRun = 0; + if (!runColor) + result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3; + runColor = module(x, y); + runY = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runY + padRun, runHistory) * PENALTY_N3; + } + + // 2*2 blocks of modules having same color + for (int y = 0; y < size - 1; y++) { + for (int x = 0; x < size - 1; x++) { + bool color = module(x, y); + if ( color == module(x + 1, y) && + color == module(x, y + 1) && + color == module(x + 1, y + 1)) + result += PENALTY_N2; + } + } + + // Balance of black and white modules + int black = 0; + for (const vector &row : modules) { + for (bool color : row) { + if (color) + black++; + } + } + int total = size * size; // Note that size is odd, so black/total != 1/2 + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + int k = static_cast((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1; + result += k * PENALTY_N4; + return result; +} + + +vector QrCode::getAlignmentPatternPositions() const { + if (version == 1) + return vector(); + else { + int numAlign = version / 7 + 2; + int step = (version == 32) ? 26 : + (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; + vector result; + for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step) + result.insert(result.begin(), pos); + result.insert(result.begin(), 6); + return result; + } +} + + +int QrCode::getNumRawDataModules(int ver) { + if (ver < MIN_VERSION || ver > MAX_VERSION) + throw std::domain_error("Version number out of range"); + int result = (16 * ver + 128) * ver + 64; + if (ver >= 2) { + int numAlign = ver / 7 + 2; + result -= (25 * numAlign - 10) * numAlign - 55; + if (ver >= 7) + result -= 36; + } + if (!(208 <= result && result <= 29648)) + throw std::logic_error("Assertion error"); + return result; +} + + +int QrCode::getNumDataCodewords(int ver, Ecc ecl) { + return getNumRawDataModules(ver) / 8 + - ECC_CODEWORDS_PER_BLOCK [static_cast(ecl)][ver] + * NUM_ERROR_CORRECTION_BLOCKS[static_cast(ecl)][ver]; +} + + +vector QrCode::reedSolomonComputeDivisor(int degree) { + if (degree < 1 || degree > 255) + throw std::domain_error("Degree out of range"); + // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. + // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. + vector result(static_cast(degree)); + result.at(result.size() - 1) = 1; // Start off with the monomial x^0 + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // and drop the highest monomial term which is always 1x^degree. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint8_t root = 1; + for (int i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for (size_t j = 0; j < result.size(); j++) { + result.at(j) = reedSolomonMultiply(result.at(j), root); + if (j + 1 < result.size()) + result.at(j) ^= result.at(j + 1); + } + root = reedSolomonMultiply(root, 0x02); + } + return result; +} + + +vector QrCode::reedSolomonComputeRemainder(const vector &data, const vector &divisor) { + vector result(divisor.size()); + for (uint8_t b : data) { // Polynomial division + uint8_t factor = b ^ result.at(0); + result.erase(result.begin()); + result.push_back(0); + for (size_t i = 0; i < result.size(); i++) + result.at(i) ^= reedSolomonMultiply(divisor.at(i), factor); + } + return result; +} + + +uint8_t QrCode::reedSolomonMultiply(uint8_t x, uint8_t y) { + // Russian peasant multiplication + int z = 0; + for (int i = 7; i >= 0; i--) { + z = (z << 1) ^ ((z >> 7) * 0x11D); + z ^= ((y >> i) & 1) * x; + } + if (z >> 8 != 0) + throw std::logic_error("Assertion error"); + return static_cast(z); +} + + +int QrCode::finderPenaltyCountPatterns(const std::array &runHistory) const { + int n = runHistory.at(1); + if (n > size * 3) + throw std::logic_error("Assertion error"); + bool core = n > 0 && runHistory.at(2) == n && runHistory.at(3) == n * 3 && runHistory.at(4) == n && runHistory.at(5) == n; + return (core && runHistory.at(0) >= n * 4 && runHistory.at(6) >= n ? 1 : 0) + + (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0); +} + + +int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array &runHistory) const { + if (currentRunColor) { // Terminate black run + finderPenaltyAddHistory(currentRunLength, runHistory); + currentRunLength = 0; + } + currentRunLength += size; // Add white border to final run + finderPenaltyAddHistory(currentRunLength, runHistory); + return finderPenaltyCountPatterns(runHistory); +} + + +void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array &runHistory) { + std::copy_backward(runHistory.cbegin(), runHistory.cend() - 1, runHistory.end()); + runHistory.at(0) = currentRunLength; +} + + +bool QrCode::getBit(long x, int i) { + return ((x >> i) & 1) != 0; +} + + +/*---- Tables of constants ----*/ + +const int QrCode::PENALTY_N1 = 3; +const int QrCode::PENALTY_N2 = 3; +const int QrCode::PENALTY_N3 = 40; +const int QrCode::PENALTY_N4 = 10; + + +const int8_t QrCode::ECC_CODEWORDS_PER_BLOCK[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low + {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium + {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile + {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High +}; + +const int8_t QrCode::NUM_ERROR_CORRECTION_BLOCKS[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile + {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High +}; + + +data_too_long::data_too_long(const std::string &msg) : + std::length_error(msg) {} + +} diff --git a/submodules/QrCode/Sources/QrCode.hpp b/submodules/QrCode/Sources/QrCode.hpp new file mode 100755 index 0000000000..8ad519f3f4 --- /dev/null +++ b/submodules/QrCode/Sources/QrCode.hpp @@ -0,0 +1,350 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "QrSegment.hpp" + + +namespace qrcodegen { + +/* + * A QR Code symbol, which is a type of two-dimension barcode. + * Invented by Denso Wave and described in the ISO/IEC 18004 standard. + * Instances of this class represent an immutable square grid of black and white cells. + * The class provides static factory functions to create a QR Code from text or binary data. + * The class covers the QR Code Model 2 specification, supporting all versions (sizes) + * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. + * + * Ways to create a QR Code object: + * - High level: Take the payload data and call QrCode::encodeText() or QrCode::encodeBinary(). + * - Mid level: Custom-make the list of segments and call QrCode::encodeSegments(). + * - Low level: Custom-make the array of data codeword bytes (including + * segment headers and final padding, excluding error correction codewords), + * supply the appropriate version number, and call the QrCode() constructor. + * (Note that all ways require supplying the desired error correction level.) + */ +class QrCode final { + + /*---- Public helper enumeration ----*/ + + /* + * The error correction level in a QR Code symbol. + */ + public: enum class Ecc { + LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords + MEDIUM , // The QR Code can tolerate about 15% erroneous codewords + QUARTILE, // The QR Code can tolerate about 25% erroneous codewords + HIGH , // The QR Code can tolerate about 30% erroneous codewords + }; + + + // Returns a value in the range 0 to 3 (unsigned 2-bit integer). + private: static int getFormatBits(Ecc ecl); + + + + /*---- Static factory functions (high level) ----*/ + + /* + * Returns a QR Code representing the given Unicode text string at the given error correction level. + * As a conservative upper bound, this function is guaranteed to succeed for strings that have 2953 or fewer + * UTF-8 code units (not Unicode code points) if the low error correction level is used. The smallest possible + * QR Code version is automatically chosen for the output. The ECC level of the result may be higher than + * the ecl argument if it can be done without increasing the version. + */ + public: static QrCode encodeText(const char *text, Ecc ecl); + + + /* + * Returns a QR Code representing the given binary data at the given error correction level. + * This function always encodes using the binary segment mode, not any text mode. The maximum number of + * bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output. + * The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. + */ + public: static QrCode encodeBinary(const std::vector &data, Ecc ecl); + + + /*---- Static factory functions (mid level) ----*/ + + /* + * Returns a QR Code representing the given segments with the given encoding parameters. + * The smallest possible QR Code version within the given range is automatically + * chosen for the output. Iff boostEcl is true, then the ECC level of the result + * may be higher than the ecl argument if it can be done without increasing the + * version. The mask number is either between 0 to 7 (inclusive) to force that + * mask, or -1 to automatically choose an appropriate mask (which may be slow). + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a mid-level API; the high-level API is encodeText() and encodeBinary(). + */ + public: static QrCode encodeSegments(const std::vector &segs, Ecc ecl, + int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true); // All optional parameters + + + + /*---- Instance fields ----*/ + + // Immutable scalar parameters: + + /* The version number of this QR Code, which is between 1 and 40 (inclusive). + * This determines the size of this barcode. */ + private: int version; + + /* The width and height of this QR Code, measured in modules, between + * 21 and 177 (inclusive). This is equal to version * 4 + 17. */ + private: int size; + + /* The error correction level used in this QR Code. */ + private: Ecc errorCorrectionLevel; + + /* The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive). + * Even if a QR Code is created with automatic masking requested (mask = -1), + * the resulting object still has a mask value between 0 and 7. */ + private: int mask; + + // Private grids of modules/pixels, with dimensions of size*size: + + // The modules of this QR Code (false = white, true = black). + // Immutable after constructor finishes. Accessed through getModule(). + private: std::vector > modules; + + // Indicates function modules that are not subjected to masking. Discarded when constructor finishes. + private: std::vector > isFunction; + + + + /*---- Constructor (low level) ----*/ + + /* + * Creates a new QR Code with the given version number, + * error correction level, data codeword bytes, and mask number. + * This is a low-level API that most users should not use directly. + * A mid-level API is the encodeSegments() function. + */ + public: QrCode(int ver, Ecc ecl, const std::vector &dataCodewords, int mask); + + + + /*---- Public instance methods ----*/ + + /* + * Returns this QR Code's version, in the range [1, 40]. + */ + public: int getVersion() const; + + + /* + * Returns this QR Code's size, in the range [21, 177]. + */ + public: int getSize() const; + + + /* + * Returns this QR Code's error correction level. + */ + public: Ecc getErrorCorrectionLevel() const; + + + /* + * Returns this QR Code's mask, in the range [0, 7]. + */ + public: int getMask() const; + + + /* + * Returns the color of the module (pixel) at the given coordinates, which is false + * for white or true for black. The top left corner has the coordinates (x=0, y=0). + * If the given coordinates are out of bounds, then false (white) is returned. + */ + public: bool getModule(int x, int y) const; + + + /* + * Returns a string of SVG code for an image depicting this QR Code, with the given number + * of border modules. The string always uses Unix newlines (\n), regardless of the platform. + */ + public: std::string toSvgString(int border) const; + + + + /*---- Private helper methods for constructor: Drawing function modules ----*/ + + // Reads this object's version field, and draws and marks all function modules. + private: void drawFunctionPatterns(); + + + // Draws two copies of the format bits (with its own error correction code) + // based on the given mask and this object's error correction level field. + private: void drawFormatBits(int mask); + + + // Draws two copies of the version bits (with its own error correction code), + // based on this object's version field, iff 7 <= version <= 40. + private: void drawVersion(); + + + // Draws a 9*9 finder pattern including the border separator, + // with the center module at (x, y). Modules can be out of bounds. + private: void drawFinderPattern(int x, int y); + + + // Draws a 5*5 alignment pattern, with the center module + // at (x, y). All modules must be in bounds. + private: void drawAlignmentPattern(int x, int y); + + + // Sets the color of a module and marks it as a function module. + // Only used by the constructor. Coordinates must be in bounds. + private: void setFunctionModule(int x, int y, bool isBlack); + + + // Returns the color of the module at the given coordinates, which must be in range. + private: bool module(int x, int y) const; + + + /*---- Private helper methods for constructor: Codewords and masking ----*/ + + // Returns a new byte string representing the given data with the appropriate error correction + // codewords appended to it, based on this object's version and error correction level. + private: std::vector addEccAndInterleave(const std::vector &data) const; + + + // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire + // data area of this QR Code. Function modules need to be marked off before this is called. + private: void drawCodewords(const std::vector &data); + + + // XORs the codeword modules in this QR Code with the given mask pattern. + // The function modules must be marked and the codeword bits must be drawn + // before masking. Due to the arithmetic of XOR, calling applyMask() with + // the same mask value a second time will undo the mask. A final well-formed + // QR Code needs exactly one (not zero, two, etc.) mask applied. + private: void applyMask(int mask); + + + // Calculates and returns the penalty score based on state of this QR Code's current modules. + // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. + private: long getPenaltyScore() const; + + + + /*---- Private helper functions ----*/ + + // Returns an ascending list of positions of alignment patterns for this version number. + // Each position is in the range [0,177), and are used on both the x and y axes. + // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. + private: std::vector getAlignmentPatternPositions() const; + + + // Returns the number of data bits that can be stored in a QR Code of the given version number, after + // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. + // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. + private: static int getNumRawDataModules(int ver); + + + // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any + // QR Code of the given version number and error correction level, with remainder bits discarded. + // This stateless pure function could be implemented as a (40*4)-cell lookup table. + private: static int getNumDataCodewords(int ver, Ecc ecl); + + + // Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be + // implemented as a lookup table over all possible parameter values, instead of as an algorithm. + private: static std::vector reedSolomonComputeDivisor(int degree); + + + // Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials. + private: static std::vector reedSolomonComputeRemainder(const std::vector &data, const std::vector &divisor); + + + // Returns the product of the two given field elements modulo GF(2^8/0x11D). + // All inputs are valid. This could be implemented as a 256*256 lookup table. + private: static std::uint8_t reedSolomonMultiply(std::uint8_t x, std::uint8_t y); + + + // Can only be called immediately after a white run is added, and + // returns either 0, 1, or 2. A helper function for getPenaltyScore(). + private: int finderPenaltyCountPatterns(const std::array &runHistory) const; + + + // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). + private: int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array &runHistory) const; + + + // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). + private: static void finderPenaltyAddHistory(int currentRunLength, std::array &runHistory); + + + // Returns true iff the i'th bit of x is set to 1. + private: static bool getBit(long x, int i); + + + /*---- Constants and tables ----*/ + + // The minimum version number supported in the QR Code Model 2 standard. + public: static constexpr int MIN_VERSION = 1; + + // The maximum version number supported in the QR Code Model 2 standard. + public: static constexpr int MAX_VERSION = 40; + + + // For use in getPenaltyScore(), when evaluating which mask is best. + private: static const int PENALTY_N1; + private: static const int PENALTY_N2; + private: static const int PENALTY_N3; + private: static const int PENALTY_N4; + + + private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41]; + private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41]; + +}; + + + +/*---- Public exception class ----*/ + +/* + * Thrown when the supplied data does not fit any QR Code version. Ways to handle this exception include: + * - Decrease the error correction level if it was greater than Ecc::LOW. + * - If the encodeSegments() function was called with a maxVersion argument, then increase + * it if it was less than QrCode::MAX_VERSION. (This advice does not apply to the other + * factory functions because they search all versions up to QrCode::MAX_VERSION.) + * - Split the text data into better or optimal segments in order to reduce the number of bits required. + * - Change the text or binary data to be shorter. + * - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric). + * - Propagate the error upward to the caller/user. + */ +class data_too_long : public std::length_error { + + public: explicit data_too_long(const std::string &msg); + +}; + +} diff --git a/submodules/QrCode/Sources/QRCode.swift b/submodules/QrCode/Sources/QrCode.swift similarity index 52% rename from submodules/QrCode/Sources/QRCode.swift rename to submodules/QrCode/Sources/QrCode.swift index 9475cd4e44..521fc7fe88 100644 --- a/submodules/QrCode/Sources/QRCode.swift +++ b/submodules/QrCode/Sources/QrCode.swift @@ -4,11 +4,17 @@ import CoreImage import SwiftSignalKit import Display -public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, scale: CGFloat = 0.0) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { +public enum QrCodeIcon { + case none + case proxy + case custom(UIImage?) +} + +public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, icon: QrCodeIcon, ecl: String = "M", scale: CGFloat = 0.0) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return Signal { subscriber in if let data = string.data(using: .isoLatin1, allowLossyConversion: false), let filter = CIFilter(name: "CIQRCodeGenerator") { filter.setValue(data, forKey: "inputMessage") - filter.setValue("M", forKey: "inputCorrectionLevel") + filter.setValue(ecl, forKey: "inputCorrectionLevel") if let output = filter.outputImage { subscriber.putNext(output) @@ -67,28 +73,50 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n } let clipSide = 81.0 * fittedRect.width / 267.0 * codeScale - c.fill(CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide)) - c.setBlendMode(.normal) - - let iconScale = fittedRect.width / 308.0 * codeScale - let iconSize = CGSize(width: 65.0 * iconScale, height: 79.0 * iconScale) - let point = CGPoint(x: fittedRect.midX - iconSize.width / 2.0, y: fittedRect.midY - iconSize.height / 2.0) - c.translateBy(x: point.x, y: point.y) - c.scaleBy(x: iconScale, y: iconScale) - c.setFillColor(color.cgColor) - let _ = try? drawSvgPath(c, path: "M0.0,40 C0,20.3664202 20.1230605,0.0 32.5,0.0 C44.8769395,0.0 65,20.3664202 65,40 C65,47.217934 65,55.5505326 65,64.9977957 L32.5,79 L0.0,64.9977957 C0.0,55.0825772 0.0,46.7499786 0.0,40 Z") - - if let backgroundColor = backgroundColor { - c.setFillColor(backgroundColor.cgColor) - } else { - c.setBlendMode(.clear) - c.setFillColor(UIColor.clear.cgColor) + let clipRect = CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide) + switch icon { + case .proxy, .custom: + c.fill(clipRect) + default: + break } - let _ = try? drawSvgPath(c, path: "M7.03608247,43.556701 L18.9836689,32.8350515 L32.5,39.871134 L45.8888139,32.8350515 L57.9639175,43.556701 L57.9639175,60.0 L32.5,71.0 L7.03608247,60.0 Z") - + c.setBlendMode(.normal) - c.setFillColor(color.cgColor) - let _ = try? drawSvgPath(c, path: "M24.1237113,50.5927835 L40.8762887,50.5927835 L40.8762887,60.9793814 L32.5,64.0928525 L24.1237113,60.9793814 Z") + + switch icon { + case .proxy: + let iconScale = fittedRect.width / 308.0 * codeScale + let iconSize = CGSize(width: 65.0 * iconScale, height: 79.0 * iconScale) + let point = CGPoint(x: fittedRect.midX - iconSize.width / 2.0, y: fittedRect.midY - iconSize.height / 2.0) + c.translateBy(x: point.x, y: point.y) + c.scaleBy(x: iconScale, y: iconScale) + c.setFillColor(color.cgColor) + let _ = try? drawSvgPath(c, path: "M0.0,40 C0,20.3664202 20.1230605,0.0 32.5,0.0 C44.8769395,0.0 65,20.3664202 65,40 C65,47.217934 65,55.5505326 65,64.9977957 L32.5,79 L0.0,64.9977957 C0.0,55.0825772 0.0,46.7499786 0.0,40 Z") + + if let backgroundColor = backgroundColor { + c.setFillColor(backgroundColor.cgColor) + } else { + c.setBlendMode(.clear) + c.setFillColor(UIColor.clear.cgColor) + } + let _ = try? drawSvgPath(c, path: "M7.03608247,43.556701 L18.9836689,32.8350515 L32.5,39.871134 L45.8888139,32.8350515 L57.9639175,43.556701 L57.9639175,60.0 L32.5,71.0 L7.03608247,60.0 Z") + + c.setBlendMode(.normal) + c.setFillColor(color.cgColor) + let _ = try? drawSvgPath(c, path: "M24.1237113,50.5927835 L40.8762887,50.5927835 L40.8762887,60.9793814 L32.5,64.0928525 L24.1237113,60.9793814 Z") + case let .custom(image): + if let image = image { + let fittedSize = image.size.fitted(clipRect.size) + let fittedRect = CGRect(origin: CGPoint(x: fittedRect.midX - fittedSize.width / 2.0, y: fittedRect.midY - fittedSize.height / 2.0), size: fittedSize) + c.translateBy(x: fittedRect.midX, y: fittedRect.midY) + c.scaleBy(x: 1.0, y: -1.0) + c.translateBy(x: -fittedRect.midX, y: -fittedRect.midY) + c.draw(image.cgImage!, in: fittedRect) + } + break + default: + break + } } return context } diff --git a/submodules/QrCode/Sources/QrCodeInstance.h b/submodules/QrCode/Sources/QrCodeInstance.h new file mode 100755 index 0000000000..791ec4a5af --- /dev/null +++ b/submodules/QrCode/Sources/QrCodeInstance.h @@ -0,0 +1,18 @@ +#ifndef QrCodeInstance_h +#define QrCodeInstance_h + +#import +#import + +@interface QrCodeInstance : NSObject + +@property (nonatomic, readonly) NSString *string; +@property (nonatomic, readonly) int32_t size; + +- (instancetype _Nullable)initWithStirng:(NSString * _Nonnull)string; + +- (BOOL)getModuleAtX:(int32_t)x y:(int32_t)y; + +@end + +#endif /* QrCodeInstance_h */ diff --git a/submodules/QrCode/Sources/QrCodeInstance.mm b/submodules/QrCode/Sources/QrCodeInstance.mm new file mode 100755 index 0000000000..7c38129a48 --- /dev/null +++ b/submodules/QrCode/Sources/QrCodeInstance.mm @@ -0,0 +1,28 @@ +#import "QrCodeInstance.h" + +#include "QrCode.hpp" + +@interface QrCodeInstance () { + std::unique_ptr _qrCode; +} +@end + +@implementation QrCodeInstance + +- (instancetype _Nullable)initWithStirng:(NSString * _Nonnull)string { + self = [super init]; + if (self != nil) { + _qrCode = std::make_unique(qrcodegen::QrCode::encodeText(string.UTF8String, qrcodegen::QrCode::Ecc::MEDIUM)); + } + return self; +} + +- (int32_t)size { + return _qrCode->getSize() +} + +- (BOOL)getModuleAtX:(int32_t)x y:(int32_t)y { + return _qrCode->getModule(x, y); +} + +@end diff --git a/submodules/QrCode/Sources/QrSegment.cpp b/submodules/QrCode/Sources/QrSegment.cpp new file mode 100755 index 0000000000..45ea8433fa --- /dev/null +++ b/submodules/QrCode/Sources/QrSegment.cpp @@ -0,0 +1,225 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#include +#include +#include +#include +#include "QrSegment.hpp" + +using std::uint8_t; +using std::vector; + + +namespace qrcodegen { + +QrSegment::Mode::Mode(int mode, int cc0, int cc1, int cc2) : + modeBits(mode) { + numBitsCharCount[0] = cc0; + numBitsCharCount[1] = cc1; + numBitsCharCount[2] = cc2; +} + + +int QrSegment::Mode::getModeBits() const { + return modeBits; +} + + +int QrSegment::Mode::numCharCountBits(int ver) const { + return numBitsCharCount[(ver + 7) / 17]; +} + + +const QrSegment::Mode QrSegment::Mode::NUMERIC (0x1, 10, 12, 14); +const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13); +const QrSegment::Mode QrSegment::Mode::BYTE (0x4, 8, 16, 16); +const QrSegment::Mode QrSegment::Mode::KANJI (0x8, 8, 10, 12); +const QrSegment::Mode QrSegment::Mode::ECI (0x7, 0, 0, 0); + + + +QrSegment QrSegment::makeBytes(const vector &data) { + if (data.size() > static_cast(INT_MAX)) + throw std::length_error("Data too long"); + BitBuffer bb; + for (uint8_t b : data) + bb.appendBits(b, 8); + return QrSegment(Mode::BYTE, static_cast(data.size()), std::move(bb)); +} + + +QrSegment QrSegment::makeNumeric(const char *digits) { + BitBuffer bb; + int accumData = 0; + int accumCount = 0; + int charCount = 0; + for (; *digits != '\0'; digits++, charCount++) { + char c = *digits; + if (c < '0' || c > '9') + throw std::domain_error("String contains non-numeric characters"); + accumData = accumData * 10 + (c - '0'); + accumCount++; + if (accumCount == 3) { + bb.appendBits(static_cast(accumData), 10); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) // 1 or 2 digits remaining + bb.appendBits(static_cast(accumData), accumCount * 3 + 1); + return QrSegment(Mode::NUMERIC, charCount, std::move(bb)); +} + + +QrSegment QrSegment::makeAlphanumeric(const char *text) { + BitBuffer bb; + int accumData = 0; + int accumCount = 0; + int charCount = 0; + for (; *text != '\0'; text++, charCount++) { + const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text); + if (temp == nullptr) + throw std::domain_error("String contains unencodable characters in alphanumeric mode"); + accumData = accumData * 45 + static_cast(temp - ALPHANUMERIC_CHARSET); + accumCount++; + if (accumCount == 2) { + bb.appendBits(static_cast(accumData), 11); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) // 1 character remaining + bb.appendBits(static_cast(accumData), 6); + return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb)); +} + + +vector QrSegment::makeSegments(const char *text) { + // Select the most efficient segment encoding automatically + vector result; + if (*text == '\0'); // Leave result empty + else if (isNumeric(text)) + result.push_back(makeNumeric(text)); + else if (isAlphanumeric(text)) + result.push_back(makeAlphanumeric(text)); + else { + vector bytes; + for (; *text != '\0'; text++) + bytes.push_back(static_cast(*text)); + result.push_back(makeBytes(bytes)); + } + return result; +} + + +QrSegment QrSegment::makeEci(long assignVal) { + BitBuffer bb; + if (assignVal < 0) + throw std::domain_error("ECI assignment value out of range"); + else if (assignVal < (1 << 7)) + bb.appendBits(static_cast(assignVal), 8); + else if (assignVal < (1 << 14)) { + bb.appendBits(2, 2); + bb.appendBits(static_cast(assignVal), 14); + } else if (assignVal < 1000000L) { + bb.appendBits(6, 3); + bb.appendBits(static_cast(assignVal), 21); + } else + throw std::domain_error("ECI assignment value out of range"); + return QrSegment(Mode::ECI, 0, std::move(bb)); +} + + +QrSegment::QrSegment(Mode md, int numCh, const std::vector &dt) : + mode(md), + numChars(numCh), + data(dt) { + if (numCh < 0) + throw std::domain_error("Invalid value"); +} + + +QrSegment::QrSegment(Mode md, int numCh, std::vector &&dt) : + mode(md), + numChars(numCh), + data(std::move(dt)) { + if (numCh < 0) + throw std::domain_error("Invalid value"); +} + + +int QrSegment::getTotalBits(const vector &segs, int version) { + int result = 0; + for (const QrSegment &seg : segs) { + int ccbits = seg.mode.numCharCountBits(version); + if (seg.numChars >= (1L << ccbits)) + return -1; // The segment's length doesn't fit the field's bit width + if (4 + ccbits > INT_MAX - result) + return -1; // The sum will overflow an int type + result += 4 + ccbits; + if (seg.data.size() > static_cast(INT_MAX - result)) + return -1; // The sum will overflow an int type + result += static_cast(seg.data.size()); + } + return result; +} + + +bool QrSegment::isAlphanumeric(const char *text) { + for (; *text != '\0'; text++) { + if (std::strchr(ALPHANUMERIC_CHARSET, *text) == nullptr) + return false; + } + return true; +} + + +bool QrSegment::isNumeric(const char *text) { + for (; *text != '\0'; text++) { + char c = *text; + if (c < '0' || c > '9') + return false; + } + return true; +} + + +QrSegment::Mode QrSegment::getMode() const { + return mode; +} + + +int QrSegment::getNumChars() const { + return numChars; +} + + +const std::vector &QrSegment::getData() const { + return data; +} + + +const char *QrSegment::ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; + +} diff --git a/submodules/QrCode/Sources/QrSegment.hpp b/submodules/QrCode/Sources/QrSegment.hpp new file mode 100755 index 0000000000..663b8bba3a --- /dev/null +++ b/submodules/QrCode/Sources/QrSegment.hpp @@ -0,0 +1,216 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#pragma once + +#include +#include +#include "BitBuffer.hpp" + + +namespace qrcodegen { + +/* + * A segment of character/binary/control data in a QR Code symbol. + * Instances of this class are immutable. + * The mid-level way to create a segment is to take the payload data + * and call a static factory function such as QrSegment::makeNumeric(). + * The low-level way to create a segment is to custom-make the bit buffer + * and call the QrSegment() constructor with appropriate values. + * This segment class imposes no length restrictions, but QR Codes have restrictions. + * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. + * Any segment longer than this is meaningless for the purpose of generating QR Codes. + */ +class QrSegment final { + + /*---- Public helper enumeration ----*/ + + /* + * Describes how a segment's data bits are interpreted. Immutable. + */ + public: class Mode final { + + /*-- Constants --*/ + + public: static const Mode NUMERIC; + public: static const Mode ALPHANUMERIC; + public: static const Mode BYTE; + public: static const Mode KANJI; + public: static const Mode ECI; + + + /*-- Fields --*/ + + // The mode indicator bits, which is a uint4 value (range 0 to 15). + private: int modeBits; + + // Number of character count bits for three different version ranges. + private: int numBitsCharCount[3]; + + + /*-- Constructor --*/ + + private: Mode(int mode, int cc0, int cc1, int cc2); + + + /*-- Methods --*/ + + /* + * (Package-private) Returns the mode indicator bits, which is an unsigned 4-bit value (range 0 to 15). + */ + public: int getModeBits() const; + + /* + * (Package-private) Returns the bit width of the character count field for a segment in + * this mode in a QR Code at the given version number. The result is in the range [0, 16]. + */ + public: int numCharCountBits(int ver) const; + + }; + + + + /*---- Static factory functions (mid level) ----*/ + + /* + * Returns a segment representing the given binary data encoded in + * byte mode. All input byte vectors are acceptable. Any text string + * can be converted to UTF-8 bytes and encoded as a byte mode segment. + */ + public: static QrSegment makeBytes(const std::vector &data); + + + /* + * Returns a segment representing the given string of decimal digits encoded in numeric mode. + */ + public: static QrSegment makeNumeric(const char *digits); + + + /* + * Returns a segment representing the given text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ + public: static QrSegment makeAlphanumeric(const char *text); + + + /* + * Returns a list of zero or more segments to represent the given text string. The result + * may use various segment modes and switch modes to optimize the length of the bit stream. + */ + public: static std::vector makeSegments(const char *text); + + + /* + * Returns a segment representing an Extended Channel Interpretation + * (ECI) designator with the given assignment value. + */ + public: static QrSegment makeEci(long assignVal); + + + /*---- Public static helper functions ----*/ + + /* + * Tests whether the given string can be encoded as a segment in alphanumeric mode. + * A string is encodable iff each character is in the following set: 0 to 9, A to Z + * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ + public: static bool isAlphanumeric(const char *text); + + + /* + * Tests whether the given string can be encoded as a segment in numeric mode. + * A string is encodable iff each character is in the range 0 to 9. + */ + public: static bool isNumeric(const char *text); + + + + /*---- Instance fields ----*/ + + /* The mode indicator of this segment. Accessed through getMode(). */ + private: Mode mode; + + /* The length of this segment's unencoded data. Measured in characters for + * numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. + * Always zero or positive. Not the same as the data's bit length. + * Accessed through getNumChars(). */ + private: int numChars; + + /* The data bits of this segment. Accessed through getData(). */ + private: std::vector data; + + + /*---- Constructors (low level) ----*/ + + /* + * Creates a new QR Code segment with the given attributes and data. + * The character count (numCh) must agree with the mode and the bit buffer length, + * but the constraint isn't checked. The given bit buffer is copied and stored. + */ + public: QrSegment(Mode md, int numCh, const std::vector &dt); + + + /* + * Creates a new QR Code segment with the given parameters and data. + * The character count (numCh) must agree with the mode and the bit buffer length, + * but the constraint isn't checked. The given bit buffer is moved and stored. + */ + public: QrSegment(Mode md, int numCh, std::vector &&dt); + + + /*---- Methods ----*/ + + /* + * Returns the mode field of this segment. + */ + public: Mode getMode() const; + + + /* + * Returns the character count field of this segment. + */ + public: int getNumChars() const; + + + /* + * Returns the data bits of this segment. + */ + public: const std::vector &getData() const; + + + // (Package-private) Calculates the number of bits needed to encode the given segments at + // the given version. Returns a non-negative number if successful. Otherwise returns -1 if a + // segment has too many characters to fit its length field, or the total bits exceeds INT_MAX. + public: static int getTotalBits(const std::vector &segs, int version); + + + /*---- Private constant ----*/ + + /* The set of all legal characters in alphanumeric mode, where + * each character value maps to the index in the string. */ + private: static const char *ALPHANUMERIC_CHARSET; + +}; + +} diff --git a/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj b/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj index 6fc68ad753..dbbce2fb6b 100644 --- a/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj +++ b/submodules/SettingsUI/SettingsUI.xcodeproj/project.pbxproj @@ -182,6 +182,19 @@ explicitFileType archive.ar + 1DD70E29BFBD457D00000000 + + isa + PBXFileReference + name + libCamera.a + path + libCamera.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29FD72F45600000000 isa @@ -1539,6 +1552,7 @@ 1DD70E296A100F7B00000000 1DD70E29A54A195300000000 1DD70E2938C0E4C800000000 + 1DD70E29BFBD457D00000000 1DD70E29FD72F45600000000 1DD70E2907DC840B00000000 1DD70E297AB043C800000000 @@ -4754,6 +4768,13 @@ fileRef 1DD70E29D81471E200000000 + E7A30F04BFBD457D00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29BFBD457D00000000 + E7A30F04D097476500000000 isa @@ -4889,6 +4910,7 @@ E7A30F04F18DE1D900000000 E7A30F04DA3FBAD600000000 E7A30F04D81471E200000000 + E7A30F04BFBD457D00000000 E7A30F04D097476500000000 E7A30F04A7E1559B00000000 E7A30F04DF12291E00000000 diff --git a/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift b/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift index 29c12410f7..96ca2be9b0 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift @@ -38,7 +38,7 @@ public final class ShareProxyServerActionSheetController: ActionSheetController })) items.append(ActionSheetButtonItem(title: strings.SocksProxySetup_ShareQRCode, action: { [weak self] in self?.dismissAnimated() - let _ = (qrCode(string: link, color: .black, backgroundColor: .white, scale: 1.0) + let _ = (qrCode(string: link, color: .black, backgroundColor: .white, icon: .proxy, scale: 1.0) |> map { generator -> UIImage? in let imageSize = CGSize(width: 512.0, height: 512.0) let context = generator(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())) @@ -126,7 +126,7 @@ private final class ProxyServerQRCodeItemNode: ActionSheetItemNode { self.label.attributedText = NSAttributedString(string: strings.SocksProxySetup_ShareQRCodeInfo, font: ActionSheetTextNode.defaultFont, textColor: self.theme.secondaryTextColor, paragraphAlignment: .center) self.imageNode = TransformImageNode() - self.imageNode.setSignal(qrCode(string: link, color: .black, backgroundColor: .white), attemptSynchronously: true) + self.imageNode.setSignal(qrCode(string: link, color: .black, backgroundColor: .white, icon: .proxy), attemptSynchronously: true) super.init(theme: theme) diff --git a/submodules/SettingsUI/Sources/EditSettingsController.swift b/submodules/SettingsUI/Sources/EditSettingsController.swift index 3fd8ed5c3d..ee04356ba7 100644 --- a/submodules/SettingsUI/Sources/EditSettingsController.swift +++ b/submodules/SettingsUI/Sources/EditSettingsController.swift @@ -201,8 +201,7 @@ private enum SettingsEntry: ItemListNodeEntry { case let .bioText(theme, currentText, placeholder): return ItemListMultilineInputItem(theme: theme, text: currentText, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 70, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in arguments.updateBioText(currentText, updatedText) - }, tag: EditSettingsEntryTag.bio, action: { - }) + }, tag: EditSettingsEntryTag.bio) case let .bioInfo(theme, text): return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) case let .phoneNumber(theme, text, number): diff --git a/submodules/TelegramCallsUI/Sources/CallFeedbackController.swift b/submodules/TelegramCallsUI/Sources/CallFeedbackController.swift index e877128d18..7431144131 100644 --- a/submodules/TelegramCallsUI/Sources/CallFeedbackController.swift +++ b/submodules/TelegramCallsUI/Sources/CallFeedbackController.swift @@ -158,7 +158,7 @@ private enum CallFeedbackControllerEntry: ItemListNodeEntry { case let .comment(theme, text, placeholder): return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: nil, sectionId: self.section, style: .blocks, textUpdated: { updatedText in arguments.updateComment(updatedText) - }, action: {}) + }) case let .includeLogs(theme, title, value): return ItemListSwitchItem(theme: theme, title: title, value: value, sectionId: self.section, style: .blocks, updated: { value in arguments.toggleIncludeLogs(value) diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Test.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Test.imageset/Contents.json new file mode 100644 index 0000000000..77b88f3827 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Test.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Test.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Test.imageset/Test.png b/submodules/TelegramUI/Images.xcassets/Settings/Test.imageset/Test.png new file mode 100644 index 0000000000000000000000000000000000000000..ef1d2a37101335fdac15758ef41bd6669a7ac579 GIT binary patch literal 109352 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 Lx}%4b*b>N3s=+SLB<~<`@}ReKCi@SAn5nag zlcj@;rM(^TKa57k_O34cq<=mAuMlh<{+rg$`QK^!n=nQXBL_xi2Bv>P`j4W#{Qq0k z*7m=(on2H+|F^&YS7PVyo(`srDyGi%u1+R@3ui|5k0}QpQ72O)7kj7g_Vzaa$)b{l zy^FoGg}no@sOUdg<0ht-H!`ub`)85nUnqHb9%(yg7b80pQ)w}N(!V?mmX<&s77=by zF%eEyF;-DgW@d425oUIFQE^UYc2*HFF;NcA|6s-JO`yblr?*68z=IC*nt@}bde06BZ^ zzpQn{THba)&%aIC&shA+t3Q&6MV+U-Hi10ftaJYHHg<$--x~ebzr9oBnr{3559Z%7 z{NEE|PmuDJ6-V@ki!(7NE~hCXcfiBqhkAD4MuGplXt#>7;0@Q;u8&X7!6u29fZs4? z|H0BkiU>_Tf((wyVc2{44CWzx`ae;;qtb)iD_72Wk=iiDb~Po(f)bnc z%+hM(gAJkhx^a$7E7r2nD~qxocU_YMXF1-J*aZ2RHg=5eSs8r+TsRTR4?7fv5QbF~ zH3zekXf^FOR5qfCQ}^aS_4E@Ufv^c;w_UN|=TKXF+B!JSyIBA5D}kLQ2B5uW+lVD29|OSCqKT!j zV<2R>*_^t`{$(N~CGhb}%FGD+b)%)`y#4idf^p*G)3E_3R9G>X0E8KR1lL80k0gxf zHN`po9!%6epR2uHJHd7Ijt>5VEn*Ct4$~1mbYdy6n_=1db&F1`lo0mv*O zg74w08F_d446^;Prka-MoYzmecW|X#1kgnVM33_tY?pp8H?IhTT@MGU;bJ=iR zPlvDIq3Ek~x`DNXAxpXlkE9f}34VB;~xo~j4R2#FTrMS3;f_4N}3 zA|`iwP^o5N_&1S2MA|sAdMd4ixs@ejVI<5b$i3J~O{HL!LQiA~zhp<)AU~R7rVv6< zg+D>gRfjWClw2D?6z9YkrmTF-ioPQII^^-3m_VoL1KrtI({;e6dsUbvZp9Y8QP|GM zg5cbWMvVcQTWPr&E{XdVkihUAoR1iiMUy4%l^NB*g0vi&gaTih$3&Pbw zjpUMYX9KX(0jeGgKrT^XL1E(lodV)>aK9V(J8r`d8s6CF%i>Fz@%SzaXc0C-8ztcY z=se_$p?B|~W@QU!h!FwpJ5esm0=vRr^P$~>Or9~^m~9q>Ged_WA0$$?=dWim*^Oo&~7iYAy4I@uPz zHf!jYFr^peJgCgB04crE4}2T3IMN>5_wXrhnUin=aBxwS+H|A@XQy3}GUtp}Dkzdc za}Xf~)rBh)D*X0m`u3X?)ZIkvpD>H@4f$F)Sy zz_xiF`BR|;^614wzx3>UoEouh103s%Fli&1-%K$sWF>hubT|=t6wbYFLNhiv6Yk*) zDdzxT`hD0OXYrEoX+r#XzRYXZ26GF@KX;H?5CBS;s8Bx;h8UA+CV|Fxos+6ptR_?- z@jcU`=nlK<%kk2+d&h@{f$!Gh*0JLX(t(?XljTBi-q-sJ#nv<^4dgAYChUb8;ZTBU zqcnEVvIx8oia5*%1}c16`7mo_e;{965+BZpWy{*1@kl;FVi(~aZWczgy~v5!q@;c_ z{DfTc^B21WrC`xw3fTibMMg%fRICZ(1bWPLD!6ZSolFP=Y>JFGHPqY%5rVe#KR!g3 zyVgi5v7uqVQ7(L2Y>7cPgjQd7HhzbC%5 zASZ!gSp6~CEsVd1Hi|Tg8gHBaE*&H$u5OkaMz7;rN%r`SI!qy)gzGb0C_&1Eg@`BR z78<&oE8z!es$CX{6}K%z@6w6s9`_7c9;1E=CW>zn=jCf%wKof5mW=3np#J6^RIg@L zXdSE^T~9Rfa}7wZp8;Fn*m+qshv<$C(N44p)pxBN)=6N=*hB?c)ikfZ>I8>yD>LYF z0Hcx;foyKTud>(r15iQ%5wFKXN=K;VPY9I0eq>~_Ks*3iJ` zZG->U=flV4#>U25SeV|*Lx=4cSq*}nDL&+=gzRy~O&*cCOV4)^UYENadBTjbC>upM7)#0XkJB-6dPnd%fM& zZck6{Pe_@1TAcE{2^vVf3B~a_k0x1z*%fi#iG|Y*gV4&Tmi-(s2u_I2L?d)F`&^UG zk!%(w64Ln2GMh@z!bU^J3CH5cucB*5v+~6wFthU}KpD1SV}*M}pyPVBA!8o8t$8(~ z$SSv7(TVjnc#Cv=$ysQr-Pjg=@%OvP$b!{{pmgnBg35cqZ~N)`oVh`F$?RbAw{G9B zV@~-lsyjs_5-p)rK8QMsUD~BSCVa#kq$saY!3Ep&gs(j5Vj^us621|qKMDpTJndO; z6fY8OpM(^P2G!Xt;Hkz2;)FCOuIOG;R)f$|nEA~T2pz1-EC6ej;ZVafXbXR$-?_@Cq`+?b5Wfe(Y{PvXDO=L%8QDt?*Qkg2z z$OJLEZd6FMj%>YfU@T+UW;tkbQ>V|Ueh(UXc+?=PznO3=ib1TSOjrHG(8BdYWM%$I z3{B-(j5*4#oR8@bLKK4Ul7vkY)Ac3IT!1y+GEJmI=NY652|p;Db|A*EzZBnSY%?@n z9-`~_FY;?oFlO?jyaZh40A=*sSahf)^Ida<-y(tbKflkYA1DSUq4^TDr!bi=sM+c@ ztEv5T-MDWgQ7#Ddd`u7t@6XTeLND?}P2!g7w^T`r9qSsgp^Q%>Pe$ouw18E26#@iK zdZz3{(|{qdumfnHtJ3Llo}EJjkjv7@s!h4<$x+dz1cM!=ELbOu`*AH}fK=#yV}j-gsn|boDn9eo=bl8+ zg3l*z1B8wh`W0D)@XMhx&Db zgaEhCBUZ@_G^G80& zf-6DWecB4t9z^?N0MQi4T&AW8)EHDO%;7LM(r%!{39Zj3)C<$&dq5bwadInZa6^Er zb&!62S-VjhA*bmAd|cccsITd+-VjVV;ijHh8WLg}nnVDV4CZf)GhKD@#FMiHtQBcg zeL6TV*IOeX zxXxf3Pw=fx+37|BPW7Y$;}nyfVgt3B-u=`NaL<=#c;T#}j)lFm!Cymosl zuYC1m3nnx9P87+fm0z4TPXrRlbzIpjxTAmDcX(tQ{H;cWiC|G0qu&#Ij9(Tl-c=gX zbuf|YbbdT#D2^=?L*G@`B2~9c(lNLR{W^GW5dqEfSM$XU;t7;n#E#B;S z;V&y{{0ve$R%&*ZOh0ZkA3w+mvMNlwb&pq8qAo5>>w;qdtyTbmU&`Ci61p!`rStgp zD|hVdK8)aqawpWND8avy_DdC+{4;liVv?#e&G1Ls&y^tBG;_uIVlhrAUyAthPP9() zZM49(HoLt`GmLuZVYDVW3BD993|8JH^wEcfv2RCa=UXIhPR5cZ=oGUBw452pz*b4X zaVReyN`wJ)w-cku{s!9+ASB$N>ozWD4^o&|9ZN04wq*5#kG&yjEmRxk1H|#H@}YT! z9l6m24-Z6_Bm)vUc)22c04f}?z`z>*WGBNqm=5=jU4 zXetpXbWoFzI)4!oi9EBgE3|s_Y{#;-wP|g0loJjNgMITy#pO3h2*zp*b9}4C9&6(8 z4?mrsrfoYKuCf5*`3#X(YFNt+y3`*?QKVCePc|T|(m{i+a@herSvO^e4{Y7F7H5k*w zg?K*RP2OTUqi6ho8=>9GaPdikz@J|l5o2Itjlb8CC;bvdH#sVbcC9(1y|cj*-UX?2 zAXkP9wv3yFdRTFAiwllOW3SB5F*k$j#BRqI?ZFHEysX&aaD6zwq=&@1wr`==f)2bI z)}d=4kEyP~RJ2pSaP70hmj+a&*E3?`hc15Q#=8cNo}L6zlp4$O6XydnGa*QPllmhL zmbF|b4Ze+}<IwrPj;zLG3X2>k?<>BR;(zN4qo73t__0!13SdH50 zBowXMT!bN@VwwofONIv`e-LA4312a*QfDxSg>fL^P&y@{Yf?zRUl{O<@3|$scyx?D z9ptx$@6%1G3nPE36~MG0%uyy8c92?7knxnHn_a4KnYG#~;evVC3)?2DW>sWLjJ{9S zAG(l+BOQ{G8%#Zm5sYpV+I0$!l!v)3+GoN{@RPmockfB4Nig1h%U;%u+sB$;WzZb( zRB^K-_I2_bq}3|%fi2CJDiwoM3dvAR?n3e>AJhO+!ec%7D-4T#FE1&hkey?Dm~Gkk zsJ1@ea?{X2Sf>dcI{}JjQ+Q&YXk`>L8`-wAq3LZ2JCh<0#s0Wh?8}m=J%`xPvfsDn zv*d;04rLY1LWsYJ!z7-yKKb6{a5wnzBesfueeNy5l251=#hcva}(!kIi2k3_YTMLb_h;n2~bn-L5^dHVNLb}Y?OuDb~~m~t$UY#<$eq`M1@i7 zdG1rod&I>0=JDQ`GjkteEwndZXWG)Bnu6h z`tb80TRbRZDlkQKk>hWdVF44&v<6}+am~ite*!7Frcm(baR~3Yb+4fXr?D4V!Bh~* z(K0m z)9)7*RKIRMCz{K8p3f(WEq8qGn4;0NYttd5H6Dg0WN(XR4D=HNPQ&UhhMTW4+fBBE zNQg2A=Z=n?x1a;*9Ifeh`ML_#*keOi0P*U#5l=@(Yf>lCFY(Q6my8p9pwRmwnZhF6DN*Y zCqt&AJe-0fAcxSsBJcyV#n;RxGFcso#ftWyB~h$hvxEyrB~m%r1RkK~Rk{g_4T*iI zowR!R!zQ`=8N<=(4RZ=Z{k-uM3Wv3o-WmMI)!dZ?Yd(YT`=pkAC)M~<3nwhJC(`gO zt%-ud%R{_E22awJj)=2Pq6zP4hTd02=8}a_(nA5Qd!oA-S#vpt%M00QFzYA$FQ?5_ z8`TmT<{Rt;x%?ATa||Ii-&2NYgkkoS6q{KGxO!u;?FtNe@tGtoF?+MM5Y!3Mu-x_q zjA7)`#`7U0YsoQk!v9bzbxwt4gQSyjJ@PUTWavf9SE^56pfne7*T!xg((wV~$V6qFj2h#6Cb`%9zWtxc}(*{oO&u`(BUd z4n+QBJq;wPH%C?@`y)58FKTAGjj^)M@f1hLYx6rU0V_c6PjqYA{@W*vYO+C~BIO|( za72m_s+S`&_yBys!sDBep*entwwuQvsqd_$d#`thv$c}a8Tnnz+RsMlC9*jY!GgcU z2QIgRvfGQhYAS9YFFTrTyFZWBb`av?me|gWgf3e($x%Y~b9Ax9<^K3bL(x5FmRq@X z96#E5ySM06-9D5HWgGuG;f5rO5WI6d!viD3pvSFv5;Zq78)T6`wT||q@7hXM6$BNK z(TO*fo*)iS3TGg>SiiC7#*pK!&&Fu*hpB=3yY+Z5;5gi z$=UFtqMoMW*ii?iKDUMGV9=UUsDteOrS&~Rk`&@sXEwctn}I-^-2CaSl{|4&l9pdQ zy2~rp#fi%Sr2ZFsK8!Vt6GbBuyL;5S5J#l-a09gWVPYV)3;t~ggZo%Qr+3PdGwf^~ zlkbqU#SV>zR&nj>TJl{_vRGvxIl7Jq*Pu~yFeGf|yvreU7_p=%2g2Hr$+X_&&}efs zX6XYJc-vF;#cMaT)qZRNb)od2=sA-I`fQ0hWJa|b zltAfg1fY?}2+(b)r*oO%^!4nq!G-{k`q1R;5?{TZo1R=CpE-D-HNe!uhIYvIiH@I; zYzjcEzk{(q;|r1%@PN}|$v{ilV*5ED^yh57!|ann)Uy9!plkwylwwF7(HqIRPJrUcD%-CT z`4MHxDl#ws9o#@^m&egCr~QbPW`c9a+Y(##6V-a%qv6@*(=#zqo+6NT98lj2$S}gt z9!$19CvNQ?-@CB(?XH(&Bt0E-t>KP@AjRRF`U0fz-fT8gY|IMStVeG5;)!$|Z*8L% zc*&pN%zr60=p}_GejSn^#w27_munjXyr8(9T@#UoRdW{w3JL9EWlu|!MFYSV7bnd+ zd{=EYn#m3cBD0;Ti~cyY=^~41GGa;NGp5QCBXCJD^eMT3PqTnl2Q(W(+hY7OrTI7> zdWfQ%z?#52V|bCJ$IYX!JJn^se;C-}R8#BrdMGdB1%n*mYI3!2)s@eA8k&gWlhyBR z9ltBQm_<;ST>*FArNC z5oE?cCg&ddM8FwuzHW&-veQWTLpnG}0-I{94E6_#e|CY)jdT8s9hCG1D=ILsu7r^R z0IQ5Xfa_z4T%^^_5Gjiolm9pQj-%+5(h_Mum&29A1bB@m(!sqI>}Hs|gW-;K!VOpE z$|(qb#NzEKQIpuds+{(+Hs0G1bcm!yUf#jI+(L=8F3H8!DdpY7FM#dL3&Kct5gzGa z1oUvv{6wp8-~9ju2&L9kZ`4;lz9oJ-5E2~jb1BpZcPhls;RUu_5O|&{@$Soj{>Eth zIJIBbBs=BFkQ?J#JQQj0AvJi$`YnWZgdLP6vcTSPdDXnGfz*N|&-?q4;1(H*gC`2~ zSz{s)esD-U0qD3;V4<0R$V^$OLojGDL46BUjt4!|EpXV0hTB0v!?6bMD}#yAAk-lH z-uqw|xpgYS3~7>~(@h~O#fXn9{lp|UsDA&eHku8AS#$5c(4n0F!WSNIvF9@qKT+pd zDIf(6T}R3t-yMp!X*1w zL`y!n4EYpNQVRTp4*bY-E7%_1d!Zt_uH-}iV{gXf@#-zakM8OT_nL0f!-uH~cVDDv zkb=GcHds-v8FG%!gy1t3&7fbk;goHUX z)}&Ew)#SO1vu;}pQ7oYGham=KV^e6h+~ECZEJH>Fvm%+t>%KIuqz7yW9@O}&&43!Z zH%anyk<-x|0~B+jT2X265VGJPO2fCea1(Pux}cmi)Cxo)HF8?MwBU-0B`3XE$!RPc z;cWL7Jn(i%UGQGy0L1n`jk? z#*Qc>E>8_Tn5@EBQFgS{%+kwG@*Bo5JUW7zVQ3Z(iz$X|BsRK#e|uVt6cbb35UI^w z`7VBh?;={`2c>QdpWrN+P3Oyo0L1`u22_Een>vRIAbg7Izg=L^33bQDE$}Y_Ta19> zA>)dpRUxQWv#_yI`I>r_n4aC*3?ZS@)5unl{I*S&R_7@x2s@C@BnxB{d(i+y^*$~;+yRW;@a;^mfvLgxv^*?07T8vhj?v@= zad1J}$li1Mdi2nrEj~LFyGjZ;nhN~SmAcF=D6(e3L&QGvMup~MWvfK};<8S1r$6rN zMwJpP^6td^_8ld+Eg=LRh*KbE*kv&AF;T5F2#L|EirV2i@^t7eVZ>qjG+wz5Z2_Z{ zb3!=@o$9Y>(CB}kk`jr$JU!XBH^1IKeMuokZrqBVO&@MeUm%Lh&rHH^2Wbb(a=(q7 zGIO1^-fG44eESH6fVe9g;=8e*OBCbCyBJfQ+YoP@UN}5HN41oS#7I!Z-vtdF z8)cl6uFKaB6e|?z&l0_)1{7@zJ4&|ISk}#ct6ZrtZZa&!Y8DnW?4=+-%tM2B$w0@k z%~q?+tra*SB$@g-ObE9ll}MrBtj$pIFm-g~d<=vT><%DiTuDT!81HEJY3=Cn_F4U| zcK5h-z?M->02w#rD3!xFmEZI6PJl-Ra`9ZKNQp5`pPHxAZU-Z!pa01R17nSrzi z#YQTHbF6Il@nc>WH>Dd=#aacnBqFhLKBZ1)cBnz@1#~U=h@g0U&=Z7sse|_L1Sf(~ z4LY0n+59N6OM)}F#(Y&x8Yk=SoJ8lnXsC23FQZ*RT7*6WM0z>|KcaGW(I`-iIg!8+ zxvjqggL<%ld8|Tl0XuX%&XzJO93FsTyOR=3(wsT+7AC&||Ii&aBgsmh!3D#C6~#4^ zw1i5bII!m9bVC$2L zf?A*-J!1?<<#rmiUR6l}UaeMMsOB64vX=7JxE{JPu9ycN?FQf{WA;qw^&Wl3) z7LH+N?%InV3>k}Q4y|*w%20~7wpx0HorWZe$QCu2T)Q}d^t70PsN(kX>gw_H)32kd zStocYqXq}`0K0RHbmo9ck?|C)QQkmf>!W)9V3DoM%tX78`CB zJ*OWw^*EK3yJD%i;b?p766jbivoYs*4sCTNd?MCB0dy_g?mbpE{` z1MeTq_grkc9*Jz=L)mxucF}35$1_&S$>_Y>g6C%IHXQdhBEF4iA zctD%0)(TM4SV5sM3haPtwZBOZ?xi5F=7M0{RO=5}3R^T`sMRUQ#?;1J$BO-q?RIwo zl1MAq`a-`{v29lI+(L$=-Rl$XTFiOeXBEyg}u*G$XBw~4fY zR1N-!z~y)`cgjyBS9qB8F$fIZMo``1QY&M&+rpg0QEgjr6b;YR7!(>s9bQKz-rvIgZK9dRXjXL{GXz^u`%` zm`ahMK0j^L*L4b_ke2~7HP8Ez5l?<{IiGqN1*+zUzWk5;>PHp)d-L%F8ulbko(%V~ zv{MirCh>R7_xffsAXQp_$v;fmk()Uh{NvANObF+hX*3prDrT0_v-zGaFl0~NC?$KIMQg#@>**FaTVa^+Qoz=6JX^sU?STi(d{AhSA!H1J{p?^oGZG1=YQ zd~(`QHy*&&GYP&&S9{m<5%m4bhi9hd{`#)yg(&i%g8;WGoUT6eUnHP4( zEqA)siEl|9TWryyf_%xmfnhVF0VQ(}4;X!6`P8Jd(!T;hmtPCVlz*h~<|(H8p|m~2 zKnU}nw^z4h(%Uvoxw(7Rd3_#+{+>AU3K3S`L~Nv&<ImC#zuxZZ>ZrK7l3C@oQ@90<=%T)*@$q;$ zb4@5wtXT$e$`9{slp`Q= zVPgiNVBD|f4(W&aCfsE(Q@lpI;j?s(Fhw@i1@f!uXe#SQ5CJ&r1LM-0@2sQ!e)v9I zspP7rN}42O*sn$@=;DaY$mDPmeF18mE- zPq!}^Yo?Qfnbb-H_;lKo!8RmLcM}|FVH4Tp=`HQ~MT*P$RTa%uD6XW<&M|r-r9XMt z^Sx(Yt0fPJ-OGZ3A?6dw!j=%38&qP2IR)4=>4eu@h^K6Aup;PIirY?Iq;UQZhl%QY zHG;nBW@q)(Y4!?kM)gSvdt{TLfsg64agqwGxW{DfjYaIQyy_LEiN+ojo*G^&)p$Lg zAImwiE{DNqzn6(ohP9x;K^g8!p<_k=4tD&Yk*Bzg1y4_|HW9l6|1N3HucN1a9o9|T zf|NP3!ONzL439gxDSmV(mc$m7BdC+4Q?Mm#{<&1~GyojSniC%-(ZYk7_xptZl?x=B z=iBSY9PzjdJ%7+t5RDq1uiG6`P?q=&nc*hRN&Mc-w~p2zFc7sw8s0CxCXCdwVaDhQ=YRHcZ<$|MayrXB7?)0{?uK?RCIIYC;FId_ga`BZ)8N? z`MZ?r${aF)AJIg=k)z0C+(U0+OYln4RwF7}gu4RDjw_pxsLp-)f{HE$_1$UjOxA*qg4+KpXi+*`uBojc9`<$@)(#u-fTa-Y`gb3?UY=0+mNgG1{$bz%l-2p_5-!w zKqG{pc(FOIAgFday~&fj{J*4xp#{n~NJp{jOCu80jr7MnE5Q$IXD>ybvi2Fx0YXAy9r9aAc(IfJ+a$_&WY7)>`3^*Wu^eyyA?*MFIi2VJ<7xI#X1u}HGo=$y(fBk_?wBsk%pvPNz_?6yjJ z{1lc0vT=t04qp*&l5GceHr$fXGv3B{cq22y8%4Bl&#{bm+mkL#Inz(L`)YK1epHt~ zZqVa|r&P}`EuqT8UiMZ1pT=40R2ZiM-&x>{8B62rx(v*c#}-G(Irb3?g{ zviy?qpX$A|$BS{Bf$A};XClR~BL%no9=9eS124x`X!_e&wkE(83_Y3b#utJ}ftD1yj%-4$2@|j%P2`pOLpcOxL{P{@fBegk#L#Kb$>omul(7PfC!ucCAXG zUCnJ{-P4jV=1q>tlY$2(3TDUj?{yvX-$bo#>O`QfZjI%+z&MOq2)q&|sU-sZ-48#( zU`yt*A@WdCM(k#qx7IF<#lm;ReA?DMoM&zt@Gq?M1VR#Fxu_hXq`Ypi}+nrli71e|lR;``7 z`g#~01ff^b<@c{vFSkRkqlvUYUXCXzo90TK5v^^*uFpM2-VYatk+F*_6Gljj+q=_v6f`Mh;B4`PbgF;Q^pG+**itCYobQa4$%42bzGOeuMa$nRuN=X(?S;9^23Y=JrLNiTNWd+Tz zX16P?WM*C7b)k%7Mgq|i&QO54G3w2Fq>Q`#F~@3EOS&=WAN&P(#W93mE1l&9`N4=x z>o~|y_(^vrY0VB9#9QQFY|&IK4t@edPp(+UD(nw?oX6~w(He$f)ev6+QUjL^DneJu z|6;I#G6;)JETA!m{b1| z2K5%?fR@opx(MyV`8doYPYC8thHC{ZY!oI+Me@v#ci1V^DfFgVq&wgmF%`wq01zge zQ8o~TUCzq$tuCBc!pen1{s|G4E}OY!63)hl%ddpaUdp8kOh;*~vUs6Y=f~oU7GdT9oRuSgTKt`cFY2E~2;5Dz zqx9IZbVwz_=BrABJy%8fw-Wqin`49igF+s?|vV~hW@Sbos|yXn3P&-UB``5SP4bS~iQC1?(7dTpUYJc4uW3^Ib1xhUU=rC3L#N@MBzi<}r$@1n z`$2D!y3Kgn^xBtHPmadEGOBN^0mYuB*wR}v)t}4nknLI}!WwU84KzF5T}9$xM%!Gk z?{}%W@gQF3ZzJAyC^tB{c`p@9fqp-`6ZLG)o6AAJt=mG^BZk(Jfg^3dZ;^?Y<@i5l z2^e&a0Ez)$d|Y4??!*>5ZnoU;2vzotmjb`Lv5e{%$*7@ZL{ z7W>ppb&wR-*_K$g;jJ57h*}cEx z+mCoD!)V*EtlV>JF~Mw#9x!6UA6%~oystk5CY7WZFs@&=la6{lNH!HRd6j*%6L6LAZK#6f87BNdSEP{K5>#mi?SK*0*1+lZ`G z887p3*Ed&<+8ROOSQ~w$#|-5R$T4}WY)rk4gt@!6Syo&+q0rwd>K-Mz;Ycammb5{Lv^ypF#G*vF-P^&zx@FI|TS^{o@f3^4(isvroA1Bp zg9IxKPaC7BkzRCbqC@V5i<4NEM5w8S7+%zqxP0dFd1zcT_~~$KWMPl?unI}+}(RhzP%3- z>Ca93`|Hf>`##=B+TdeDbJ2x>|D6b*5%3O#ET6jk$j;wyz9RGhVZ;gM3e_qceOa4; zd!-b%uP|qt8?Qg@l)N#jUEo}*HlDIr$MbLK)<)eFA)M>6c5_F{^;f;=FGsUfFp^EE z!zE1=Lx5UEdU6$YH}A7qILr9^Db2JL5=P zptoE8kQ$fc2oTH7Q+;t2wbMh2Cy(@F);B5IRjpLow1j~=XfcQz zzHdopkd(QomPJ7u@Ii%}tsy=P^4}a)=}fncc2z#~-$=)x>Yy=;XCsLLOuf&=_z z!6``|!D(duGq`ND4kVl-cZd0w>ZuGY}j3Tw^(DS-f&^3pk+^ zBf%0U9wGvpV$HjwSZ zs!1;tFYKDMr(|45nEQ9yQ96B_xXpgHj&n(-rTjFZqzYg>L)iH#k|qShRqn}7qfVE= zaae4rS?}nS5a@D9eQU6MRyscqQ73#C313|^hD3#K9&dsoz+FWIu*?lC^DZ{ko*Ua0 zN}UvPR2GV(0$j9j*-cbmpN2$jcC`O}2A0~|RB92u#nkC}clELL;nhXl67uebjar-q z7VS!1fl!s*srmlR_RlDSUS`J*r~J#*O3hQp@g*+{&cR&?vRzeXc0Ll#^82}lqTfeF z=1{q2b^T>?es4?l`bYI~9v)eG=-+#^TNktEa|x}TN#s|?@LBvC9{196qI4iIP_b^9 zqWCBtFJv^Pp#xBpkG}QPH-x%q&vNMHpsEabOrVIdB|1`?lOwCGvR?dg?^l^{5%oR_ z7a6X0^gCVX)v3-;t8$FjoNqP@dd9o%i@EM9C^9rt#b?r( zhd^9fL^4-}6)i`OmOjO;ZuCxkZ)#MGA<%3}P(<2t!BK1%LGDlC-|hFppGju2?G;}) z?u-nKSjgWgYG#}F3jF;$ihAwj4*Y_zaJ1r)+Ygl&Tn@ielJm3UC`ZCt5`6AethhX! zHYDwJcj{a6+FW&$zV+_&pILnz&ZNx2`+uhfE#-PdXSk?C^EieJn17ot%X~b9(s5-8 zyqG;<{~F+xTQhPcPCsnM-^_jvNZAX#Mg%LuOoWQS!8HoL^fIN8`Y7?@lz%gP*xQlvM`bsDCbIznV zRHT`jHZfS2{jSQ#H9ohgWFftKC@!tcKRa`UO=BD=0xb%fJSv_&oA$%*kjtrWa77Y2 z)K#uF)Gy792AT+m?7JKr;l*P=$A z6hhrKkL$d`!eTjuF{2uAyq43_e^T<%_}sPvB2*Xo?8Vo`P6(Mx^oORTlI|bL47b(1 z?=9Fy>)z_D!-!<;OU=x=QyMMcxa{`!$vYM;e^~^IU@dO!W87(oRL;r}t2^ zMJrJozPw)xin18u<7i4W($0C?{U+*u_v+Z_@qMd4YoGaiT)BAQnPA;R3zh1r{U2oj9hsvYzY1 zWy&|M;LP`j^4z$d<_S{SGc1_ZT$aG^6aqSf zC6`S?{Dl(oJQn$<=RL<;UeEY#W@W1ueRhpH7~aWIK`gE1B*shr+C$G*Q@p2p+=)DTcDbK*Ujy#<~JVEZ9b3J!~GZM8tTM$!t(m9OC2u}Q>f}WkIIjq4IaFZ1I1>y7;QK# z$Oe8N42&QQw{*UrV`#8#SN1(B!ArRq5`PZZwbF7b(sxIFlNA7Gm!F8;ofhUDG<`(m zx#lq)T8P&=p66@z&Vv`+#*cY*n_N5sNNe1==!hA0Pi$%1WU2dnXyH+4T(pw_!XZ$W zE?!xU+uHeA%adYtldW>2Az)6C%c5f?@;WGtMn!CqhGYQK&0uj^MzJ0HlWF}v8ZX4f z?=1+;iV$2kZIDj}Q5#By`=IVc(WXpS_%soEZst{$sR0J$rKBT~C5L&slsUK$pF!~+wC@aU5yP^=OHrF^S#Y2qxL<11_|q-l5Q>QH!+mM{{WM-YFH zD-ayP*sbFPvLvTDWSu{-8=GyNn!!xP#K~k)I-poD;_@DkL3CrNEd?W^xGSxLg-tN5 zBaT4i8=^Ss-CT1eGDV!_03(3q3MN^x$kuRI5l{))Ni?t-u7-H@A_FZCx`9FPqxXG; zKMs^Ib@d39#r?y6cRR~a9r1#h6^GHDUC;}dDMN6yZ{SU)qO}@wh_;+ac`p4gXiL`bFKlQNL z(EVO5iuKiE4XtVf*R-VrU(sG|p!VK@yE90#%Kz@94|tOOyW4NtwtoH1>!z;1_~Mpa zv9#Zk^`Jnk+JoZs{Kc9=-0SPr)2Ek@kL9~pkFQ?ezIuJfVTEEwP_$m>|K=aA(SDPN zh@(F2vxz6U!hU+eGKjTr3F?FLG^nvhx2(UkN)x3Y z_RLJPCxc+^Nh5}Tl&*6!FQOh))(zAuAt{1REXY7?_vFSmo2o~B7@;x>!K~{kQ${2| z>WlJ-8Cl>A6VE>T?8U=F`M9s>jy*i=gD8Cd0fqE?pe=41(K=n$QzozrMpFnJnF*PhMOGp1r;O znmihvY);pEarxs38vQ6{Ldu^LE)(Ido{{rO;p31oI^YQh3gmlFa@OW!Ufe19-inN- zRI?8;hA7F;28bQdJXTbGsZo5h|yfePJc3L0|#Rj)-^08ZiK3b2dy70dtnVk$y$%6vKTtx0GUJ zq$+IqaomA)dTYn68M>i)1o^%0n}&0*la4X;1G_eXkk#r$ak-X%Qeq0rH-Bw_2aZVn0(TEVS%Tuf4oL4s~IJa>Z z>d^DaH)0USKKpVMBbjgsiQOU$7s#%J(h_4oAXBREs%3oqxQs-=c}yt4 zPXW5K$WFCnnE@px5xf!RNXVlW0f-WZ zQRM&b-~Yq))7rbbTtjUEISY@&gLx<=ultdQcS`@$2lt+$sHxJ` zm)-0Cv1>N>w{h78zxjRCj~=AIQ!fE&)w|#B=}J7M@V!W1zPMbnB7W126wqE>7FE40 z>rQ;^r=Q+DdvS$~V3t}GdZxqlJQnw$*Ov#+t_t=NZUyghVnP z0!Ub97?7;ZvQ)-=J3W4r@+SbS@Q0oZ%D)E#g69cYyXhc*KB8C{JSWc^Mo{iyy$?E# zUnNU4?I&@O$ecmn9wZ=K1{)-ZS@!nGt@Ms8OjI#ZujxQw>#ClcTYb8hkB?hv+@cp= zW_eM7ubbxyk_r)YcShsV=445Bn`+PqPspV_dv)H~N~# zP5IopuWsMn(?{qhy0FQwfBj4;eSiOou0}sJS-M=UuOq12`#)(j;j;cfqQJ~DuidJ- zQgNaeW=_5yix-|G2qdvCaFK70v8TbUqh0ZP9g?AH7QZ`84YD7mGbGHE$H=L|L4?v) zXqjXQ9T3(^3ndLf5kC*OJ+Qx(WGxX132&G&wWq1=RX8T7Nff)l! z6QYJb8ZDs+({Vy(WV$Si4C0;3hGyn>d}t#G26c9L^!i)V{Kj@$f4KC=*wdFv6M#-c zf@7}tVCDsMeF^LYJlufWIz8kdqC6FqJw;ETHBDFoYCo{B>d-tb%*(?q|2#g(MBq63Jf;+&lCGW%H5@tc zbX=a1`MC_E!tg+^0^=)=$q0^I7FISj2TJk8g*cG7t?hV18Z9=w5o{cq4@X{_)6B+! z79X=jjLe`hQ)og?jIe*SkZ8tSf?*O`67pGnM@Dy=R?JBWe{f6jLz)TA3Cp{OZf1zFV-I`Xg$8;KCYTdzgc-|}9(|C|mQtB^o6{VJL(hB3=glvCOv9Br zIys(i4RY6VMJC)5;&3BuIvr)i`j5%o-8tk2rsMsO3pgly-t1 zx@!NJ#EC5yb0U+;r2XsZtN%fl|H;4mpX1ScIe4x1+U0-OnTsy_50gzFcOamH(-W#s zKfPY93xJ?*5EBOF$Sk_KSx0d|4xc{$a+#vt1ygs#I2(UfSCBayPMA>|F8S-kKUm~Q zWKc8%0Z3@ok>Q0xAS`JQRSuyTg38UKJ3uiEJc%dh+ngdiV^?F2oDoZ&Ukxd)Iz{qf zc(Y!CUBO}>Z41D`BF1PBoJ70mv;puiQT|koZmxYfm3D?C*z}>FE%IO(o6Wvwu^jZR z2O*h-tLrr=`Ef$N`Z&7HdUW6S`)cBn3Y|Y#a%A^aLNEMyw+rL&>GgWLT#_+qn)Y|U zd({sh%h2^;^BZ>nOqvIZ*rCylo}y5j0_KuDNLjUy+x`7!M~Fsb{t1F5H&+JVpybpO zUJG@AG7;2+Xg6%`c6+)Glc8(!^u-lD{qgY)*`$8#k~qJt%Odw;Du9XdEaRjFA+L>&v`fSp+H zu(a03w3FpONM_Sjh#-;(u9SxYo=jvpbfaic6{osI%R><=+6*ky8j0sbC$(t2ST~o{ z3F`Q+JwdViqphOBi7-P9!8}_2!vsb4gN^v$BXFC%1{YW#Yd}^j-Fm~ubicL3|LqO5 zv(d(o_}(gdmssORb#F|hd~Q^BiU_=0QFju+lH$^9GzypM2r?5~@G~i*^ai@BkWMVX?hp zi;M*+LkWdJprzSJ0%jj&b*{&IZQX$5M@upcaCLy=TWFe(1J)f+EBT=;Mfd}T8=Je= zO|#!_A1UGpT;Gi=54ss#m{(v9d`iWYGfvp}mi1nc|D24SgX59cZRj5u*dH#6S%Y!r zX!9rquI4G18D)kdhp0&4aVNjq5?q=#EG)<4e4q>PxGTvKmfL+VTz%tBoS^GK^6xG$ z))$xSXE!&WfBq{9E@_*AJj38awAiq*Shj|n%7H3#6a)f%XivsmsbUEYxu$C9{R$sC zvGBh+8w?H)XiKdGYVk#oCY3b}+AB-;+n;-gb)b$1Y($2*~M~Cn&lRZ z096tvDMYTKW6lElxX9(ED3i?glrvhQfhZ>-?m&HjEGSr@byN#9WMz%jDyQ?i-^E1MEJK(S;*Ge7dAW^DTA?tWX>Er@pgICRropF^4jO|cO=O$k?- zaP)Xg5!MN3njvnKgaq7w|HW&%%w5~B){9?#_MD8=eshcHc$(5|v0Pp)S65DS{wHH5 zjMVVSo*C|%V?lS<$K`nP^F$VV6qbPwlt}XHIrKIkOkbIWLH-q=)XsibA4(^Oq$yLo z0^f;~a9Z6aBFuu(uLj;0MQV7o4winD21LxP!SJj?>B8rJjOaCyV(vPz4_7eX_#f-)!8HL>szS<4fAjB?dYnG5UB z?SE<(J)L7OmzuVJd|{|LM>0&P0tg3-b{9e3f#cAC2Nd%}fiM99j@vn9%(zU1bh_Fy zWCynnnkHPz^W2c+Kun(4CqHoY5%MmK(dML_C;F{&0VQh>r`U8u-J-Ul(dO^TKs*XA zJQ3kmG9*yz2k-OwjEI&G!pMsgdo#>lkX!ra3y4uMe z)4cJI?Af_za~|Bs4`3~fC`TP$hVG$%oY=|*k&LaC&PbTTyVuCz&&OCPGO6SY%KW2+!PQpxSiL$8#kap z_>Ozb2k%C*Ps8XTh1Hny{~P}B-|L<%h!@PCcw*DY$u93I^VZ4zI{TjnyPOJw>d(G< zd%5qzSMRo6KdqM2RX+tPw$~GPcCfq7{v05sQxX>QOL!lHmF8}J+FQC=<^pZd#T|g+$2goh&%ln`X zCrxHz$n$kxtiFHa`4567u=>YAw;1Noi;k*fzm9Vp)iGyjPvF5(v+_tRdOOu9wD6#T9OyqTig3nUuM z<$`%uDfx%xYH@M7y1BWMqP|8)2(uJu4`BW+PX-;)4@NPj&$P;rv)nT3!_K-}9F5BK zP?mBEgK1|dMjB0O=rABZ5!k(HZ^ugbdB6@Q>3hk0dMSM$c@$S^udKpX zt%pvUu8LdQdA*GT)kdlZ8%krAs~f9#B9f&%?~gZDx(W`b9ee@DT+}|D!zhUh8Igf; zBqp#tZ<;&fkQZheoIeb{FKWS_uYG)!kdqF+FJiO~n`nC+oS|k074vyN$m7p~11B9E zr#(YP4cr#obqIo3RLY{+L_i#!2v{=c7EzoOwAOgv;_Pr;E3h&+S<}tc+^XXX$p@qu z4o(M%br??NLL>qu3PN`V4H{@U$3#G7W($O#4G+VU7(%$oHA$8%7AXwe$W35|)rq3e z$^3!`jL#BdjB2o47ik2IcNzBb07zXW)ZCr8^El$#$lN7;U9!)g$zGPG)Iga&mRW-sAKt!?EzOZ7=k;Bgm0!pv%?(NI06OTvw*Q5 za#0DAQOH^&2NJp>sz4RGC47Pdhei~D(8B4nlzy~YQp_1PO+cp=B9G?3c>d&*PoCf0 zTt{Kh5A-QJJ%X7Na5pcvgd@HA{_cI8Brl&mUFK<;qrXG*z$qb5b6=sAVS?mq(199q zstn5o9+{pSF;EJeEV*w~++$MsSBbq}4gagD{xhbRLp|!lCdheH$nFXGPcZ#2x$*u+ zeSQ&KZOyZ3%$ohW=`N#mv0R%xRnl8%X9}#ibkPcv2RX@q9K$>J=}PG!5R-2m15&~O z=MZ=-6B%R`v%U;1Xc6X^2P07&Gz6of%S-nqhI|aYsg;4FPBVauJpsC{xW`xCD6pOz zd?Di(d^H<}Q!*Y;dGVx!itrlU>Z@@@v11RiJcfvH_`)^U92q1`L+=K(>{;v29IB7a zBflw^NJHx;%Ypi#2P61`Ym-nTKy@R5WDy!}J!WUHV1dkh8Cjs2W!Vr7#95T(F}Inp zN*@C&LXd=79&R^;So;n{``T}Xa7DlMPFyYVgIRAi0d!!~#r+9+ zQ4sLUnDT(R4gCJA{B2Le4)cHa{s^W{MBH>ZpgSx zo~KfI%4znpcqXR`EW1trG+X=;$EKc=i=IfvYeL$*6M*%n1ct|sA z%o^i4sX#6;5)mqn92IgP<=L4vVviqqUTHExid)6Nk)-X6+8$D^TBva$D{_WxLk)un z=vJT*Yxxd~K9bWn0rQSoyy8ctRx~m@c4&JEj(|8sZAIQZ2$n@2r}4$rl9t&bFX&P3 zyaN}3oe*}Q#6=~=|9b)yX&B}#WAhV8VG^(bxltQ(wk&$?pEQ13Umb#Ab!_FG#mo=Y z_!;lHu<$TdT7Ea+ek2KIMAXi5(N)~FzkU5L{Te+e@}0&F4il0wGKzmT1pUQtm}q#is~=F`i3mS)9b5? z)#AzXCvg;Gm7r9v(Wt{=2LLV4<5o^N*70h&sgkv@hAEW1rw8eT02FJbo8Pwe7oPb| z+Wki*GEBj-Q}$p_?MePeA9w`Td$#tjmtGP5A64&d#{XtBeqOALICxIc++ZVag3*r; z<#w~j322>V@w2B;zATF5P+pp5Q80f7|8s-8oom2{T(do~@A#L`LkF>e_%^U`gwfKl zhvqgzpd5tpiK8ekR&wOhqUOrA&i#m`WT?T}MPGA2&LYoQ zB{+u3=qB87RG56Oyc$=XPtanE;O$YZqE(>#&|O+S4@Kwuaj z?;gitYI^8pEYgf@fQYSpvo*aKID?|4$|`<3>)i^46o5_Wu}m>maHFHTdMhO)UMgO*icKP}%A_$kMD< zJ-1HBu1n=3nWy7AlZ28afe>XJK%;nj$$AL3iC8Y1zKpOHAiOEo$X0VGvWV3KxFHoYvCv*b-^r>h>$>mzZ3&T~u4|jN zjgy+tbk}#^voiVvm~qcLL``r`L#SiiFj>~K zvpj`Pb_`ePS-I2`OCw@!e@0ENiS_SyQ-?olHdbWhFBM%-|x%)zDCqack#)^zx}s=SL7M5 z4Twnr_wYXkneM{~Q$P;#4o*_hCIBTd@|t<7Uo8K(KKQzy{?My`=+xgnmce5c+}+iWn+B;; zo?uj!3%WoT7lq=o@uB`HdgVeLH;(ptcyD!R#+(~?9ghS};I5kqw=d36Dvf3QB5!%0 zId^iAMduc}a(LVjzBjWXnKMwQt)PMdogs2nXV>S=oLeL*LhMQI@>WP~gix9jA8wp* zqB^F{#Pl60I5R^FEK%I0K}*%f3?qwBqzO13F=DG`-p6mhRShG z#(h^dWEA%MJ-tKSb(41btaKF;WJxRwpduH}>c!z-&`c;~06dkXS=VQ3?@MJHgRobR&sc$a8{^BOzytL&j~LPmQa7zwyo4b|)rWV$(9ZIAt-uKmUq>q~>!M-j5nJYHlh&&jQMiXl>yj-nH)pAwBJo>8lPQ%>)+Hv8{;cYjZ{J z5-{16ansr*sRxI?nDtFH-4jna!<}n(ZMj;$Pmjp95;P38AkAC6WIjp|*aYQ{hcFc` zeynag`Kl1BogaNGo=x{v${}{o)*3v^Kx&Dlaj|HqqC^7yR^TKcmEF}UC4YB~2WNu2 z8pk|1^k+E>^fJYi7rzw^5ZYM`M9hW}vS=O~pv3O}{uJ_v+1>lmq;>?z`nZ&QdXagwp^@y*Xe^USosQ#+F>pkz)6HVNE{OX@kQjt0M{zJp;*;Ye zc&-ko2?VC7$axBOAhJksKJSF6TL9sd)o%I;dZ?3IFI{ zi{J-B{)MPNR2fs6TT8{>daFlsCc&TpBE~c7}c4y~`ID zNbQ838mZQSg(saP0$|5#Qb7s8+!rW3H#ev`x>~3B1eJj@(H9=+rjfKoMg3v;A0$RN zl0bw%_l;1;pk~t?y$K!R|yKu_~D zP0`dAo2Z%`X&l=Lv^#;IE4aieYz>ItdYDko!QsPtUM-hb0tx(Qa3y5Et_Ea`&f}SP zuF#Y(P<3hSD1tVt?8;v(`D*T`o3`5L6c*9Paj&kb;VUKWPsJdsk`_LE%iXv6U1yOeYBY-W_NLS62r^S-+>mN^V|a*;y$p0cscY1~DTKZk_m2HCKw&9XnBX+wYsekVq=+^vaqkeIufFt1W@DUDRAfZUNMU^!b3WQ3> z_N6-A7)tsOm})idOxv&+X0w)%L<^4hJc8q8M1zb3@oG4i@4%g=m8BT~!fhdK{TS@I z#4FQb5#4UpE6N~lk=H^Vt<2a5X3UJj>liW6}8=QnS z8t18TjJ8koBs*Jx4orqpfb1^T%27CyjJpxbOd76@w9!mOCiLTscmIG+!*g zA&;oAubfw88E>Nl5qX%Y#pVf8+#`cGaP+ZrF|O$OleqtWN0VRUUL|v2`nm8X5!g!i z3ofJ15er_Il=k9u)Qix1-olO%=+-J7MM*H8!s>`%B_~M~k3uS(U9!0pWLb%4$Yz@s zWwn8_qH1ndOL#x)%@zsMnmYIBv?Q!=o^rZAGP9=$&W&hJC@g~@`0a-Ye#}q-93DL^ z%e|t=Hm<*3iB+CaN6Mnj&{VfE?dU-?L$xF`$l^j(px>H+Zh0?I^VCmv~&ca$7>$;XGaxc_R2E!%uCjrbB1q)M}C> zF#>+c#va>|utvA*4HBpWL>R$8`&4n*^4SQ}D}jiD}t=f-=WtCx`RsPZ#Wy^s5cw!U${tn?5A0v*paXTF#RV&ebgIQmKH{%{>Xf~2`% zkq>GJp^K&5l^UePLbcfFZv3g6zPm(iPEDSu^mTTK+MWT1`;*k%gp`<41;t8P#u~g^ zz2n`@(V%BedE<+D_w=rqT^lpvJ=H$((YNC@DnLdr#v zp;{>p#T}VU!s&cGn~kQ^F$4s74RtFW{tO!tUKuJkJlG+4W1mqHADmf*W~d1>Oe%PAXG>^l8``3kLZLyh zZcEte&lb8Os4c>9G8!>eo{txYw6nbck{UGZf>%Oso}#!ozobSN7K)SU7&R$ysUW^v z-eR;VZniaK3*wWS2>H-Rc>PN9IHs-fapQI5DtBb$13mh0bhB`ftmP{|)}t94=GRk;V5&~>B8`&aXcE_vKU2uVyG5#cOdA8UVK zc?_OZHqT&HI0^@*Eh$;RhV?_*eq>7+>4LbWv)g_F{d3(i+*tlWOWw)&-iTq04>KeB z3%?p{xHt((*VC5>nd3S`ihDc1T=HtdkRZYWZNyoLla4)XD`Hq|#B#GOsnEDtuE`k5 zC9wdSDAhQ{tkG4qp&M|yM$rwqf>_j~pK@t(;2%l_niCs*grm9yd zCM?V4CM(hH1>R4Zr6`{#S(Ddg@R(%g9o^D)YS-ReX_GzzM6=_R`8I_KDiaS6AHd1F zUN1+Z$?1zvSBq=LuP{+lbQ5`d(wOcn5}m`}K$$|>J?T$JBNr12T!l6JWV8c?P9UqN zq4Kt(e1lIr$Lg{(X{<3V?vvc26+@mn40xMLqm)Y+g(C{a1$y39F6A6y9IzXhON_GZ zdb`?gpP!yNC}#w@WHcp@UC&1-GL8{;(bbw~whd|-IF5EK;0ks@twhOWG2~B}Ht#mX zU4%5&oj{~${9}m_omf`qviYA81y#3DZqox(?v->h19+?Fh|pz~#~)XXaEfAM4zAMg zrKNwhc91=8GU`F%25_YZYtJS0M;M{*26Ew$B2KtrD$x3Pt*PpeHdu71SF>^A%T5chH!N!BPw}N6b*?qVYK)5W^oeDrsMg198mL}o1J7DMsI**oG&jIX_mdbxF}IJF=ZGCyi)>J z;cTzFjy7i|J_8MdrRZs`9Zty3Y`#5VqQhLli$_sH?^OpuSmtoyn-Yq)y2RNpj)8c- zKoA!p+2T#JTOZBDiE54Eoc3f)s`%I+;x4>3(=ocuA$A2xgcu^mhidCqNT2dw&LDhZ z*K~Sw9eAj{76e!Op&ttqG(M@Dp-C5(k|bRR>n6?f(^nTzKPVI(iXNUEMGz-YLds>x z=eBZ`V+&M;v;A`D0jN-OT#J^R|lY{1Z)gRVthfUQ`lNQB4Xl(k;1whWnpA5=C7 z-^2ic;f$6r)@qNr8JxCwL; z&2v;pOYzdK7fZ-nvmA-1F5O1S-3Lc@Ihgge?6t(P0J>dcQu)GO0l#H<)oVdlI4?}# zGYI49?C|>P3_jCznQd#tQnB*|GVM{G1si8B4u5ph_Msu=3vmsOM~Op)29XYlPF}O? zs2L1U`qG6zrS9Y{L_hp$Z9MpQiV{>39r5e{!nUyN%MvFFw*~iwBR6Vl*!gX;M=Swn#rE&@=-j)IXxda9oNQ@mi8Exi-e! zQB#nuFCsO>(6U=c&oDFh4`jW-;95SHo4>{Cg9{M%E9#D}e<9lmVO$GWKiAE3ry89X ze_EHxcJr*(o}rp3aBA7wvoej2#*wgduulV-#dsV|rX#d}3?aU=o;e1#rnl;qW{6B^ z)5dm`-40CXr_`)EV?{2kkUFGcX__yWYel-|IIS!yEPT*4-k(lKsM!UpMY8nwPMtBV z;jLOC&6o%wjlfEhpK_>^i2TZIxq;08>S}@F`b@%bP=t;kxdmyF)QYJD=uSq4D5xHW zfs72F@Mq8Vk|gv`9vnmZIgUfeb$Xx>Z2?GL7V9+>7uPq-o7J));bj^YlWz>-o8{1n zqaz*I#<7+Cu;`FM=b8Z%4MCK?onc}(vp@yLC>~E{2!(QeB<`0v%D$8(4>;j=Rz+#s z<*<8w4+^`G_%Ym5B!w2%r4=^w>~aWmt8I5r5jN21Z_gMy3|+!>Tj;MP2%1*mMmpT2 zhm%w*6fITug(=-_iCdCgEL0rgaW^+LM5-HzBxXpQG(A{T+{YL1(DmHrf(0LYn}g^wcFRic6*|b8 zk;W3i;UBNiOxSdiF`R!P5OB*v4k(O#LpoXY;Rm;hU8+Qy0rgPI&V;(Bl4-VjL-Ya<4-IMh+xahgW#q+n zi>ExK9BjFS7$8`R><2@Q42G0LnQfyVL4<8P-|@Toa*XaB!86UaHGN?+H z%k657nM8$0VB@f`kLV1vJ0L{&tFdbFb}6V`lwx;aYSS?zh4@y72_F#-K^%_`j~iXSEB{br41H=YfGPSWrPh9kN98YzpCPeENBSg+|~dy_q8lKD_wZQNsON-)A!&wJkK|2 zz4yWL`)L)Pu40Y4TX+evPXIK!V>v$8I^AIV58)xMGnxqE!(pvEVMdIv3b{1~3<+S1KoSr!zIX-IA!4p_-GPX5$WhnfG4bEG{o^&;fW`zz!e90Rbfi%`ys_!qyNq$o>S4 zmEl{;EsCANn}V+#Ls}L1ClB{WaR_h8BP$p7wS>c?pgHSuxmqmO_=9e4pdg1&n}#DR zEo1;emqTh2)n@rB>%z-r$k43F&iL4UmRcT7VBP1MMS`@p=gM-o1l#TqG2Bz3@ga|hp(ci!({(xG>#tznleQvq3{h&p zML8vHM{+`ZZBP1k9wb>D&(~0ZDBnbX)VTYO_&XBn=@9F?uWIi3tu+p}Ei+sniT6`S zeP_>~1u|MXGuRzP<)YDANjjzuoplY3H?cVOI0$0zZIe=q$|R$xj>xzOJrt$6rTWso z!PeeUFxN&>v(wz8I)H+BfqqE5@M{ylGgve$Z;Cw~VN7D5^1QRe>i70gUXyR(#8%42IlnxkI0o zeYb*)N)dJiTQqoPLTSQBqF$TTznA5w&gw5^MWqR($%li{OWq`onOP36@Ad52ww!XgGlLu;NH}oHE%$e z*bNt=g-%i`B^uumP}JkZo3aVQPsmnH=&s2AP93H@c2}D|5OC920e@}FG|9>yjQ^*O z&`?8dAaz3;du`C^x(hbZ+o8T&KM0pdHaH_Etc$v%fOHr2#34_kU>WWL>|QFWr&{R} z*+C0B8Mm*QS&)vmQL%KD37!f_bjnkqK9Y6cfcVN}V5e!pUZ-rP z*su~ZF4Tt5qmsxwvLz278ZvM^2+=;$GQ4DhO)5AH71kN#4_e@yb%RvS;(D>n(tN$y zY*9F!M7FF_CI7$Gt3di&pbT zzFwJnz{q3F31m|6`NPL&b#wOC{`;Ha=ogniTx8=H3wK*M>&*)Gqwfl+)JLOaG(z0S zWHKrWBrm|hdG_ii2;H0IW;{urJ$)FUbb?Q&dsYbD2K|=0!6ks|A)clM?_p({sChi4#zSY^cuZOHk$~U?;Be>&lNmegS{~o$ow?Kn44l2oTtv9>)R6@@)@xV|ILudFyaP z0_PeIi4DkZ>LEIZp&lzi53I4TXSva`w*ndBGrNkhxAhbEq&-6*t?9A}o^E&^Y%QdX zbJkYn77)H+e-7EZX|~$@YnlI*l4VCQ{W_UN_o6Hc1$oangzb9% zaI{GL#z-eEgPRP3oWmQws&Qb+QwnXZ7!}KaK%Nh~cd=NagNYhbG?je^)jk*7w&f8i zwQ|X{z_1kvXB(tEh9a7%W(Wx=ws!6yOt`OAlr@A2hyw8L(oGK84HPWc4st!H7~r2^ z4=vYQ#6@5S7AdFLc_HhJhLA0kp;}7?Y`Zj+1sD{(bw*(n1d}mTJONIHJ(uY47@iPu z2Nh9OK?bo+Gsqy)EaT+ga0k+6s5XOW!Q*n5y>GF&gB2%x@$f#&7|uAlRos@-gYMj$ z7bcpf+H9_hd`s>bZ1|>YJ8m!*VQXa&g))7XO7Kg@pK6OqHMk+T!PGInta=LRk@^g> z^j$mmpvhJ1N!YuWGa;{Ue+&yH#h79%&9$SwZBOPwIN@()L%rcwQh+E(k^=jG=nSAD zkHj5lz;@61ZY(zQPUBCCf!n9(ODA3{1zj0EU;m*A9_jEcIr-;m`>&kzr!xHul`R-v zVVvEW=xczRj3MO$WFComEFMh%2Fm@j>|buHgOArwmU(ouX|9%ax?Nx0Tp?NvZH?#q z^Lc>&gHBb{H&^TBVzXGRCzIs6?>>POcsxP?9%SW~$RS(BL#2#t<;MHQouZi)J_&@n zA{-k&P^_$NXc)=o0Lgok=6k(fr?5k>FITW=qVOCtod?HrG}=jF>GPlX@1ke zg5&_u>_S9@B1k!JUYM}H#C3%&zIH*h=762&pBW-@x>(7sKe|I6_i{Hv4&+YTajE2C zxMPzu(W0jYo1A*o*1d2SvcRRD&F)@5P`u~l6+5sl>$xm#BTliyH)V_n7#G%AKnySD zcJ=X_BUdN~_mE@iPK`aK5_hXkK4^wzG;8=v3Pysp;`^Xy! zT++8zoV*a>w}!+4!o()awkU2%I>n~XER_@kt7N%TmkyA`1MNOD%qWK$?T%i{&LiyC z&utdnZ_rTuX0VIj@I#YXPMR*yPv37)J-U#Ln`}jtD=Q}6*z0VwD6RECIm) z6=9tO5)P|7JB%cW`3t*d838G{?xr)>#sb5WS8h!(h)NOm&XQQWD!T8PqWG(1C7Z6E z#KREP7VUCC;AHPR#HKOQ6jC;$#2|}JcP`4U(`pYfwm>`e`U79x+2VRon#tZqPg$B} zaq5&W6{HoL|6Rh(uLhA%y(SLcF=G?G=CMf4ywDGpau2HiXZ~ zcr=bm+6_v#Oi^0Nr8axv zs9vL-4WAGhwZ1{R)OwrMX#SehL*>Dcaee3QXAfbg-YixSs-9y%B8y{)Rvyy}Tk^Qg zW>CD7XRg#D^+JDtZ;~X@lSjva?}lhfY=1OOLn^cd%(72E`ywxj^>$OyBBY^>!^B3> zNvU;NQk#dG*3`1c#`PZcO7yl*)UDClbaW^S^y|b!?Ozk0x%uNi{L?@A!#|r%XS3P- zP0A+7-HQngs2(P5a%I_@T%vbV%*G;ZEPG>UHY{4#a%(Fi?N(^I)Izc0gCiUoDK)0= z4Tu))$B3f-AlvOaSeoum-=WVHdSQz}^|xa{)g?RHGCbS5k&afWY@cA@n>Ba`=9b9t zR~+;5bw@#4`J#gik;mppEvrvN@P|_Wcwq7VYs^6`{)MG(oEz6!Heymcv&uNN2;r%g zm8Z2+6aupNtSphG(Gau^K?J&jW8B9XB+dfHHG(eCy$m@HOq|7B1LsF*!RNGeJeEgi z^-#X^6e;X!2a5*sl(HzdXx>|)_%(u4NQ>0Hv}XFli$7`=O?c)nUnQYnVxH z5!hU$bfU8qkb@C`w%Qh~vgO)QJ^LCeUbXDdC0dJ3*>FH4y#UWR%F@fb^zoLa%P z3)#ArS?Jf`r8=UmJ%TigUP6y1ZT>2{(d& zox>L}QmV-E(^pq{3SY3OsG>uzl zAUM6o38;{V2h%y^5s>>F%&^WQ(men0lg}Y@IlDL~6EJ)}*k5f$<=H>A z>la817-2s&Ejp<$JF0d1651YZq`2K?npT8HbT-?n>*KTQUW?JL$)C3&@RxqW!UXQ) z3dJ&w7*fCOsoF}$bc|t}fyhAx!qr8O2(qT4v<2ydP9dro9c5%cPqewSY>n;+zGU^G zhBic0cypm4+aJ*y5sF<5D0Nu7d{WFLMLs85U1 z=@z-nGMxG4MNN8?2tHHf*@<4XBU*{dN&q>1yejEnQ9LhXH3w~l2TWBJi1)=8l-49eqpF`~yhQ6- z%QlXrpr`1(iAEz-sti$gQ?W(?LMn>_5(o$oYjl4@BNsTQ&@tGmbI6@G+kF$M`{J?5 zs}wJK-M*b>C+RaYj;u>@tpGLl$0b+A><&d&ubSX35xgavtxkR<%QNTZ|CIGlWOjRf zn){=K*onV%?Qrsr#otB#-yNCYf%~V+`Lh@E$*cA8a#Mfwd;w`>o_~?V@zaNxQ=n+L z)*pZL-19xy-0+^yuC7q1dRw4p_cnt>V4Iam5OedoUNBhUed#DQ#GP46`86}3K^o!H;)q3;A%TsJvZnxOaQbM7`p)JVNHPuHqUq*ZvLi}k@vDBVQqg?rfQ7Ug$mE`G9(Hx`z~;fR zE$U?3>f<}0DF`#&(}QqG`dE9Iu!he>;mGoDZ+9zRSBBgNV?l;Kc5sWxz0_tpi`+_k zvS~se_Xq4}&n@Xm5m*K@f(qWzCPO_$^iw0DfQCc`(0wy2T%}M&62B6q&Dkl3Nipyj z8R8q!&j!8*{V)uAhPjGWwj>1yO&0UI_iwUJlEx8SFgk{GS~0YfLkT=1$Rh$Yb3*xw zI3ghp56O8ASxjeHMt)9PNFt~cfxcj>xH8vdivndb(}QaXq1h@ zA{05)#7SV_1LktXo!Xm@9nT|?>ynoVZ$?s)^aNKFjV|)q@x9r6%)Bhv&)YO_$C;2g zc)O!S=@ZPGhq9Y(RCYPI>r$Dcy_aB*?o zu&oKnDA6I&qoLXi!nW;O242f9Y~_JP=Ooirh}OVFc0k*f!BG=WRPyQC(g$R#@Z8E5 z6G|Ok5X~}O??*rSlRy5^pCmElaPgawO|T0d^Yx9DW3YfR?z^bh#4Ua6=xS4ZaylV~ zIGj$j8c5#4wVlM)s>j?@RqJ7l9MT7z9t|fu+Tz{Lff@cz_CTQ5rBUs>Hrz`8njnlX zM=*3w7KZarD3!~sF7oYmoo~}E3Nhy#CVW3^!UB&KBE$QBBo%`ojfMW=p9n&P!^VA~ zOQRl3^@UC0zRtYmPP#!#6CzMojtt>NXJMV^GH`WS8`OlaJxCYGO#vsrqzZ%TKP;P1 ztDZ&;7|L;0;*kBOHH4FP3u4Mt4b)Gqyc>-_S~4}db-0pQBJEIHv{sCWfTdX{b2IUW zN=HIy2qBNa)~VlFFtH{-Hb)BVo?!ii9$&&!uKji%oqf$CdZ!2R+U~=BnWVXel^7s5 zJ7WYK0}^D2~^X->4t|wKi;gD ztLw9>$RH7CK|oGqB${Z>qS557@BP#7eD4oN<4GJ&G0P@)jA+U>JjTuF4`lN;0ypcG zTK$!*&*b(4R_*ObX=XU}xSbn!_;*%*fMD@rqF#J&`uT%kHgk@yw*Jqa2Xz&lzJ$ar zIM|zeo(!-QZK|@u8x`Sj!gG8kz`!cWHmM*crR4LUFohN?QIo$?jagNa#G&scp@&-d zWl882s;DZwg%Fn{5#tcjM$-gTRF%f7N}?}AXz<44WHue`?M>(NNdWhkXe5xQtk#?L zHeasRAAkBO%2nPhVEK7&&>|m%9@q$25@+itC9G>fN6%VWEyqYRayfW-m^EtvUC|>w z@0ot@{N9q;DQj%77{M5!9K!-E+Pdw2eeh#nzlzSAn_4X>)t+U`%d_qJ=KS=t&Ek5q zdR0|f(+qTa=s)3T6>VpSCr@j1Ib~13#yaeY#wI4PUY(h7AVCd;yD`-(QH@0YffPdg znlm-N`KslEjQulDoz-(MaKh)oIIZQT+>%)19C8C#(6D_AQ!2D3ql2E%)0luF#FIp$ z(74!@jIXCxuCzr~H&DqK2Sqr^?SO>0C2>C_PckUZHr@Epwvmh#o<`3;qGXIm$$UPY zOpw6FIU>Xe_$eFInA+T|mgiSD=oeYQs#C=N?oNffb}2^OnpVi+h-jD*NI4MtFgqF{ zx3rdTL9M#JnB3``aj)Il6v$!u^9F9Jtn6^;v68N;ajW7~rDWpK+ZUqwZvz@;)3yUum`7 z3d1h&@FH2d&eHUQpZv{cb^Yo4KPl1Sbd7gaHq^p(sJijsJL)Ed!aE3}@pOMOnT;oN z*Y~+esBf2dux~QFTqlt#($oJ|=uG+Vi2B-D|65t#uzJO7625!tDAQGcH5POaMn9bg zVjezN6_d{wo4kp$(ye9a_)|15FB)mBo~&hFLt-P_EnEUx{-JO(5+htPN^8&+CC#w$ zf)1RXABIqGK-h%h<>+vfWhGQAMPXp6z&nX$tO&%(%@~ZZWX=SyDqZ#X!G1D=WGkLb zQKk@{H7k`~Ufsaw+2zI6)m2eeP;8K7W+>Z!qOrEGt?^*{tCf}-ka`;3rVpZ%uIz!C z!n#^^ObuRBu4tXehCmq2ikM=6@UvVb*~T3e1<`aekHW;otmw_jCUAB8A$n|Gw%ueU zN$B^)3RLkJVrW93t$>?^=*&XCTh})W{9G)w-RFv+p=KAeB=3x+GJyY(X$}gwwDt~fNSN?EAIi(4qo<=}3dQsF;JQ5qu9rad>mGLK?2+E#f#6=ZT9lzSzhGh>0~yK4)*s>jt;2w^3iDl8~avX z*9EP;4GDz)TEnv2!$xVyJq>nF)8yM#y50QUkN>ar^7_+X{l~Ic!?n19&2E%**|C^r z^o2nmTGW(%@aTKr`N5BlA3hDDm?nzNppe;}eBunZ6r!ceMNfr!V7xuiY}EGWvN}`S zKbJKPO}iZHtNO956jV_L36Wx+-5$QQ?`=qPOMhs&ai-!=|@Rz7tFn7s>wbrHMKP0 zNKTTmAB5i|M*J4S1Pe%oA>@8e?rozYSIVu5%1$lXc8sCPHTJ8ByM^s}oNmIyYu0JD zPE%MS^ZglFC&lCGSPAxeVN#Ipkr+lQbt|RruqjgYvU7G*E7?0knLD%!+t=(#A?E&S z-0Xrec||HMNj8O=mf9HkHDiS0usOViD2PxO=_Xw-E?<4IT3l||*G(h*fUrb}!`YFt zv;BV@js>W0zJDB!CW;J1OjEx;CFrgkl?II)(;oMPP7RbKDmKN(!hA0EYmUz^jTD@M zc~S%s{!!^q3%%D=Ctgz}K?47@Az>iyX452+Jp(bZ_lZeCMw6H|5C{&T)6{K5Yo04;oQx5N9XJ${Aj{1ww8>bmHc)QdtX7+J zOFU4QvLAfft~@iXnc(nn4qnzxydXvg5;j$R3_O zdjy4s?*$GD!&48-?97O)Y^GE;-(}Pxw%wKLt+&vcRFP~MYoIdOr|qwrc5toQ;)MYC zgqUdOA+50r(nO?9?)Wj|fDd+94X+xwngwwvqwbMiM!p86#L!aeKGEK?unTm!%JRk4 zt6%-($IF|`7oYwd@(A>D#w+l7LTYwbFJvC@gU7Rn2PaQYp1ghd;4!42aKFjkU39uU z@|Kmkm5~&RWpc#PEo=MFDBb&1y?coT6@;Qx&Lg zvaC3L`3gR7Q2cs@20vb8``T@QXr~JUu!BWj8rz++Z3)TEiB1)5C*DhE0D}^}@huHz z+73nQ#34khG$HzK1t%u9bk^4M2-Q@OSBXNcG5SKt?%lsZVS*8XWTq1koDM;mMVJ$+ zf@DHz3dStqFdV}*k{|CDN0zWMB7Z!JCu21E9e_J;!6R%ZT*_TYJqx|d9Tb2an3E++ zzkQ9lhXh4=1PaKQ4$>!$?KX61YRMgtL9?P!+?DuRx%q7{XFoGjN~7I&nr>H@=U=RD zF7tE=d4%V?EW_EEmho*i9B--k3W8`d-A~5TD2kB+*EDzD#qeq^#jZcoZ18cBB8Qm; zTz@0$wJgs`t>x50UG>+>DMYI=#;F~T>O66#&6!b?xJoVq+-aL8tBkCgL=r&*@#ctx zav`a#pmb@pLjyl3zj20v04qo~lrP-5bn>Fg@(t`2*z>S9Agr)=IX+cXLp4yiK>9Ep zV@wGHoQ}}=7JH&;ny!|stE-!BmO^>!V#Czy=1j(Xog(qedlSQ!)vXPzMc*^&9Amm6 zhq{BL=&?bvGpr-oWmuxvph4`YE8i?m$DJC4g%8mn&;(&CQY);KC~aSONT`rnA-`ud z3itLV2L}fzh3q*4#fRR-q#GhJK0?|#M_YtoU!dV~gD9H~w-#?p?#uqarq}Ye0)sfN zHSD88^G;=f3EgVYY+Oq3%6C~xw`N*Lueh=chP~A{;n_@{XLVh`IT{2ZT1UFDLpCoz z`|#@Q6f%i)vyi=1uWAt-6}~rJ2`1Od2EF?HWI8`Qe)x1Wo{^G+?AxnD@ib{CXWUli zPB2qW=o)1UW2JhVTM6;~Mgv)LHV7&HOMPzV<_ z^>LocV%-wk5rKbrFoA3|j-mjKrWI^2f=iW`NE^Aly1GvDtU*-^k8K17*?vzf+Nt@? zE(@odPYrlT7BOvlWdhS#H4LLM3taXj#9f%-K*Q1WJx|lOLI|Y_pV-QwF~>LDr@!Se z!8h6=S#j6(zXZZa7Qgvu5;kxHwcK}~q<@5RU`L_C#}tac;xmy#q*%e#QjBHeDcD{R=! zj|BRbC^#aYfB5t3%hSu3A5|sxBb+uyhyfl%la-LB@rFB#!(=u)I5~OpPBNag`X_o9 zi$O?8B*J+1Wi*=}SVa%xARyea!Vjd}<4lYrjXOoWraM>VrOb|%{y(s{IhjAUg@Mj8i!joPFV{mL$=!-YERUCNFr93-)_@Q zmO)kpiRs=fdH7&o2R>o$4195xSKN%oh=BQN0IB%l(cW}E8k03Kjg1U?g>JLcmuH`R z{=6ji2%N)k7@OP7iQ)CALCEWi5u1ovj&mzQWA*iAJGST);q|aX(H43g_F4`GcG?oX zT5$JJ|56MRVP2__1SRpv^ZYkHOngn8PF?5l8AB3*-dn0^O}b2LCMt*g6tna6`i5is zF!1|ot{zPfYq5rdw%5$1WJ^yqy`-sS_2||uo#ryi&Q99YM%?Jo|q^o+hzJh?fSuLQr$+8R+3IsPn zo{q{+qshd@*B;@VEr5{iAeB)$COp>eM7ks6AIt1>RlFza3yc?LhYWHzm=B36yl-^7 zUpz+~C1wGw_|5>?H%bx>9D@;c56cz9l;QQaSQb549PQeSSa(A~3w!io$fn{1my zxvEhY8#@xAj}GG}5B4D&O;G37hsX$_B;BNCQGNEstJQjay|B-0j<9T}`^U-vc=C|&=>})^B5(sxuZmPxF334-%i1;wpj(9ei zjgpc7I}#?SC12{M9K})NNjB@!9gN@D`H;1?=@Mvr-1o893=+MXn*1JFMsn%jQ3B*Z zly---C&k_1qXi`kZP85n2;iNM9}QWk^E^S0#7PEP3&Ck688&3bwI*#{rI z_g9YR9Y6hk7>=g1!`1Tg?8W<4m65ETuv1Swz70D^VSeGLFq%QaspJxt;QsNG`Tp_V z;Yl)?K#U+yn$BKJIOHwPZ@t#_a&eVz*5@xi&GUS-Tv+XSAt5$kv^sj=NAb~vhjB9I zlbJS=qy2{(-i&`Dqj!}5zDcJleNQ$Y+VW5B;1BQVYz}q^MQ;R{K;p8WdHiNOfVB>wL3C&|TnpaqPptB6YKF0(`R);zE>! z4^H-AAtj@TBqz`rc!M<0?D>lqSBqs$*l!m{CvGc?*d8vlLO!%Yc`f!cDPtK)OqD~=S8jZ1c^E(hGxSfbn zJdyy2Qd+}sW7A(_VauG;_p_yLJGVVOniOD}sx|2y$}sSi1V&XxjaqNGaSO4 z`mPr)E>Fum)!26+ga_sk67KQ8Jmqu@5y1e8J(Pr}1bUk0-=| z>Op&az(RRaKt-NyFJ8Tb0PzX}M7CYuT;l90FN{@-$2kMssP)a2=lj>^FQa&T@)%!s zJllfZ(h3vl;E8b(;~nbo9a%h=#m{Ba))mU`j-gDRZ0Cc+o(0pgxWVZ=OL&{d z;ftvojGXbtkRU~L}`WdcC?T0Z_M_KtPc%bbL^(GLp5|eLy|iU3|r0`Ih0`R zM3h)S1c}QS2m-P&4v{411Yv|e-a#Pnbis=Xf&lHtsO@@kd=fi2hVDW}>$pyg4z%?;Z?K_gzDBE=q_*)A>S}R)_WYAyUY&oQZ&0xPrn8WXSbwAIpkozxSir{BSgz!;-3V93BM_vq)VQr$}^%6vGBkf5pRm zJ~%p#@@bk}Tkf&;9Yfe|%HF zyU^aMQp+kN!GH+eh8R4fP$PeX3KZ4NVy*FF@iD{Y!(KW**-MgmoWzPOTQqhqD35sg z>SnQoTfsWXE~*&sOqPd2-?HD`a@S(SYTghpR`uNncJUN_3$xF4MN5#jCU9N$z{eB| z*05kB#`Gji;N6WTW5{*plR4UGPNqQ^Oh!|9l*q+V5I)d{86JvHK-+JE(SDP{gl-t7 z&4(w(ey2HF$u}Mqpr)&@&yrvAI#KLk{z*Q ziv-8UFxtX#2AV_!AEgVd$amK}di*F(rr-M~|2!T|4^AEiaSW-4LTHT-w@*4AH_nj^ z%3yA?REK?@t(WI7pI@E5TrF=-KmBEa9-0;0QaGPzjOw(Y_I7STJ@_Kanx=aG>8~!& zPjy|6XY=ES&w@B%=?y!-NB8Apd?xO`EWR(Z&t-Ehs*hw>S*slYTk8^dONFRz+9n>y z{=nbP)lJZxPMR#$2V1?D%ULPLM)+F#oH=guJWUrR+JkGdl*UHN(a{V7#AF;>1uAW} zX!~2eczL#5LrQ_to2p~x4CUMVdg-oL(@-#Z=+MyC2tDp*7q@N&wEH%s>4FFX$DBBb z5Pk|F*!3U}bYPwOzUMeeGKQr*3S)?Rm`6Bn97kll98etLp}Es(Dg5W!gYFxUOK_VK zHMlFy9zLv6t?h~%C=KwSf&3Ucyfhm57_OqL3WX9^8?=@`m`~Alo`6;8Mc5x40||f@ zX2dGXxF>Oj9weiAoXpN&Jtrk4sC^5Zn_w}kqGS>T;b=S)rrunC)-(l6iHI+?;p?hh z{6U&ru`7raIZOMa39@3wtm$k+>~L0VNLvmcd}lg8{QeLB6n;9qJ?SVE^=rlR8d80u zp-{uuLcnb=T`!h5S6_Vc!SfG)wt+I^)#n%n{R9@9hg5w>?7)C~lXoPTWzA-}fXo(t z5F{_jXom8znCwc5iV)r+<4&bFZ}dAVd+7KlvOH6(kKn|WTHM#Mdkr4Juv5IJ3@X`2 zUX%D&6MfZaQHUR8^66HIjU1)g&vo43Bi1?EWaQk@gtvs{M(7?N?u|xJBw>d|61_N0 zbNI3^FppS49s#%ABT9(beJAZY7&Mu8Zpfg}kbSp83%y&I3{0j)J1%3ap8WxeD+?$b z0@oiyjt~TUvwbKT_V*4vG+xExVmuzfmqcO2X+k@|{xAOVZ4VP>(A2@DZUGRj9gna_ zzUXS(0T;$tOF-OU6+&yu^)^KqFA5nrXb0&!gXXo(K$Inm_D38lOeyO>M0Dd2LODhA zBuS>oKg866@m(rk`bilu!Sc$R5Be0L-(PaPl2`@yVgcp*Fb!%C} zLKUnFkFJ-l7brBQbF3+VZtb7?9$2f`A{AyURk>PRU!J{KFR!7*s47Hf2+=xT^u3zy z!|CCFP+Q=A!Uc)~IF7fxxrA4SOe&d-rRBen#UdAjPK0C-cnjgb63wNMzm$3xXEY?8 zwcMp0M1rU^>5%IIeOigk6AMp_LgNwtHK}X4*~-ltiY7`WaO~rTAxhLiUE&39O+Rx=rMxJN2&@kUB^?%NrUNl zhKQGBLjPoOe~Z~)t7 zJl;#UtMl{c5J%!<0-r}mPoU7Kva1>i$7|gbMtGFHn_FOkd-~?2{w%OB<-GOXADldX z`}2=~dHVSWaMC~j=&xz2=eFRShO!>m+6^2((sw#5R)kwV z-#>c%_IKa<-tXfG1|>+TBg1B(!NWRuB6Tj3-&4hfv-}%bpR4q5`_Z0r4@UF$?!)OP z>2%0IhzhbUUwjgXPvS;Y=J-5)QfHI(Hu~hnc%7=V3jq&zHj5x`pFG%yTI2BOAP9WO zkxZ@EX_{rl$DcmGSuR)W4P=9qM>uA8#wiDRgdLPyGM4USh`Gv=W(eYzJ&elEH5(qS zbs>VOH^@~8NNrc-Hm%mQO zs~i1Db^zS27I1f_^S$kA>5~MtXeBqS>=shPT?AG@1drYl^~f|gqWN4hW_-5*F#~D( zTRVataUtcvy9SAFXOW60Zq<0vL8yJBve=if4a0F1dT|oNe)LE)mS#PA4RIpPHW}0$ zrPf`$(B`MZ(Z-k1Qf`BF1{6^dHg<(;2-A|&d=eo|QBv3p0-STylwO)#bq;d@WxFiUn>`zzAqRdUFiNlC&>!^X# zohskH|C7J;gJgAcF`CTZ{{0`$=KINX4p~Ek{Ydhu5d^z&y>zoqH>*#6_1-Vv`|)OV zy}X7$(At@caIV8gvR| z?U~<7*6`*Q9b^HHs<_$$sYL5aY?=<+-plwH>f^f-Q#U`zWxiTK;f??5I%+b42NRL# zdyje*z2r>m97M0CTF49c&v7~(jj;jNE}-ry(mJ4K67>*e*u zE2uail0hj)-W_co@tZ_(%iBPUp0X~s+vUyGY;T_g@~O#U8U518j=X_tH)wk7A3%9! zn%@)6iD~{E9g2;(KeM3ZQ15aZs3`@P-zeE{YB+tz!40Hh$J0$|yxiS{QQ*rhwY8n5 zk?S?~u-9n2Q|LzD!Gzw%NbF)Izd|sWmEt+aB|}3=EpjKs!Gym*+Y5qV|L`z@6fuG1 zVH{v53w?^YkN)im3U6f5L0gUm%`AouR|lg7EbmL3R+1mSC5V$KPR66X(P(zFSbX~Y zs;C4M8uQus?YEvF)I=hi(0W*~NLia>vfKzJ5Dgyb>@ds)X&ldvj^A>T(z=t3vN4q1 z#7&-UPs?Hr+Z7^)B)NAva21rV9dh)mUlPx`uF5RiT)h13`A0unuP#MnHAo0jRZ|e@ zge_2CvnM8z3}n=-e{rP|P21u49}) zB=10RCgXQRle+#hSzn9Qzk$nCO{)$(2wt)c7CXjlodg&Uze&4)n&?SO zwSUqykuIj0c&n_%N1t7!S$2MP)6}&`vK2-c-5cM_!6Dw8NOiV->W&b$RmW$fU&H== zL~BkG$Q>R(dNztj4^B=JhzpYm+!Kfq+<+V=4&UYg@x~M#aFCnUP@a1f92ay8nb25X zxNNQg2YU#`XfjTc3H&C=ONN?E&;<;8mX-l=-}KGMA+XM7+8X)np67>N7@_O|1^)Zz zw)noPve?vBdOLgmbv|e+>NFKOsOucQCYkI_rZdlRv(0+Fyjd?UH_NNCOlhXUPJ%-d0?SjTE*%Yc7!j#RjfDz> z`&P8gmK%6C8JyJko*{g|TarPtdDO$yh;*$&}G$a zMjJPErL8`gA>RoX3i$}Ki1BPRo7OI$Qt{Z1h{uelY&5NuJ1=)5Tdd&YHj++dLq$5#3N%W zs$E}@Pl4%1Cbzb#+)=i(jSfUz&3 zS)_R6I6)APrtrR?l5q22v%ZvN+Uju;iOay7ak6yd`N3wj&~>v#%;*~3ec;xS%W(@g zR;)XR$2&#}+#-rxQ;Afr1_eet^iec9+0FX6pF$?sNC(kP^A*=PbWcHpLdYyo@ZR`) zxL@l7BQIrhPsjJ(oT5vIsBj=`7zY?r(S#Uk)+$P?nlF*l4$64#OQX#&gFLybAfqY?}DrbX{svMH{|nn*)mm$`?2U+%rqh$xQM6rLMRW(Sa<&GwHW60u*-`OD{M z#k5{w^mM$=fS_yZV7AxDrfN1&)m*+B&*x~{DYO_kavO8kKbdk3$}Eg`XuJb-NY|N8 ze<-UfXZ<&_`njy?j+WOBWCpc{*-0+6ycQxB@(41BO2=iLZ_5{Db(t?;){QuIg|t3YFEI1_hLbBo%)MtlJ?cFr8~1ch#|NIb@qHrQ6e}iNH|BnHb|gWZ`0H%s!o2hYvqn7sdbe_zJ-iJ znAWhtw$d=K@`E6VMo~PWB+Hxa9YTf?U+$MVC z8p}`(^qC{;T#oV5M2zr~MzIjPmUcAU@m4$Zq%_upUeWm!ctI4$v+;C1o=&H8C~YU> z2^*UJ!w3y;SeRg?$tW7ZDKQ$&*ll6xPRAd{nBn8$38jx%*93M;QEbQs%8{nEkR(2z z9eZo?-D#Maj&(^Cjyx~gKYAP|klTB=rW?18;Hq2~`OS87j+LrudG5C~SMIs4JGv&M zA63DLTovop&Eou3wpp72AqvxIH<-?jN0U7_@Eyo%5koZlqks9|Lrgh%^fu%apTGa! zdU2U$i>5AN&*O|E--ujT-871RJKaGX98trktm4t$qqo05-8+8wpZrl6jpFf`hB%Og z)mIni+x7Cjzy6EuX1TgPFU#B!fmFMlT6!$-Puuk>&r%33_R%nyV8F$fZG_OB&jH@z zjBXl~44#g^gLgK5BI~VMzbDIcC;baqXVxcOu`K#du;^kwq*17NSLbWUB+4yH&eS5U zP|2b~XK0bc6D6Cm_a0pJRen^|!A<_SFiGwnYZWB`TfUGw?YtmBZTSIg>+CPH& z;_dHzZ!{VmAD#q3NLqUi>t+7KixF>3Hqrj7zVgdHc{KO0wEmOplt&r zRN6s;RPpJ24;Jfqen7#lu8M6d)Yr5#BW2Bw`^&c8*0AmTU<4V&c)mZG?~NyO2taUJ zvNR^72IJ`rPSJQgg=^d{Zv+G$Ly=D1?(!HifF$IsR^r!jxV2pe?ihLmgqRu`nBWit zW%*qpK19Rx0iNRS7#H&yLwJCeKw`KJ)8Hi#g6j>sZrHitq3e$SNce~{7PO$rm=WY=N$F$fyWDlKN2 z;F~P*NSoZTGe1ppMc6Qqut0%x{OCJzGKs?2AzR}w2~16st!_T4$}OiSR#WITxwigN zHw$J1)peF{SKG~Ey}qpSt!wjYhX?#py1wVT*og6v#8pr;0yT^L?|$zO;SwG{eK*~# zfANzaFD}n6UVfBk3&#nFRN@G+)1ou&F$w=o#(PiR{=wei$q#|%;)q5<6-j(y zFq-f0PbQP%5C7R}agAj2b5olFE?H^5Kgy>2h=fB4TezFBJFzLKtmazRw}il=<*v%z zPOzxyGHV20DqkqyO#TcTNAdS%wNUwIGX0sXe#TBi!)k|PN25^!GcVGj+^kl0QHs?T zlZc9Lz3aZ^C{H>g3q8*Xe#%hgo&7HT#vfU-^6RMX2xMNY8bi zK7Q-u;lsV@-rH|~mwFH*>OrV)XwUhNVd7hohFGgEt4`X=Ew-E}LuogijKs2m48jj0 z9G!T9+EuK%bNDew6P-pHU7ByUSo#u*TnI>8qb6Gqp>|n_X6PSmFHDj#nh%L@Jedgx zmAD}XZq11}M>n_H_bs0Z#}=;ZC6j49p2x`;Y8iGO)B_zQWJb9nj>k|+_XK+H{>E1Py2O~qqH4HDnUXe z6shEhxWOL6KqYd0QQkpDaQOi$a_F$S7EP$@u+pA3e$)8UNtDE!nZyxxAf^aH8MhgP z_?`K1|6#`nL|cU;(SkKOPi^g939nU?SX5KNHW*D0q9{2$dIaBszGRN`<)f^o%Bw0x ztVFtMbR~@=d(&=tYo=yi!y=LcAw8Od$f_(M9mrFZ%tf~$NA~1t!jGn#WtOh%8e&r< zJsM|L)LbDgI;a)!l=FP!v;{@qu2o_OP1R^odn$IFAR6zVJp0~kwjYc}s0Nc|M6+#L zK$Kt=*~#7>9Kw^s!?MbX(-(D7C|{|z=V09;qIC4u_ERI(F2#^u_OKm{%rw7K?)&4qb{RL)n9yCGQ>P}4T4XbL=6 zS^m)ch6{)g3xXWPHIGh=9!jfnIm3p2sOnmiq8HiWDPzq|=!%f>UPC5AXQ;j%mb#wJ z&RsH&Y&~I!>ClK4f!15tY0fDKx8@4h#zeCNsc11Ntx?)HZeO=AiO<5JH%g1vo0)n8 zzsmBFF)yrXu;D>VNvwatzqY&$l-fag2PR|h>~aE+DU`@-knLka_+CfkQuz8JaH`OE zk~p5CcVG-5SpAL#h~JSgp}Zif>XL;It*Dr2jWnpA3B~8Z(Gy6dr}HCZB@*1?WY0Qrm{ zWRcP4b$+Yjb>!@RxY-UQv9c*!p%^K=2aS6mgQv|1GK4h4L~qk#y%v!tVtNSsxQLH}2iVkSF)9=?K@6pnK-wkh+*Az` zH^gPth@uvCDeBs$67YDX3<#L3x@4j=b0leA4KI%Mob*VXwsxI~sjrCksiMa7h(Tpw0~D^JC8sW;4VQIga}^yVgziN^hT6m;ZNh z_HQBAg@e<0V^RN)#y@J}9|%}&u#R!GR_+{*U%PdOhjK5>*>OwZ&Ed|K)%B z%P<-(E?#=X8mQ~))#=A&w!J)mQEbZFySJG{&YP-71 z)755uos4D|r=O2zdyk*J8%D`^zUPt@Cwy;Flp1AzGL*pRUSVh7YY4SboIrL)M32S_ zpWmbZcH0_fmw9RN6kSfC`ydCuEt!fb)I`U>SNTtC|3#DjSLOC%z5MrieZI}e${251 z6U<%!t18%k5d9z67L)&y>S9P^oUNxB)`N7yBopseT7tcPa z$}C-9LCA11Dd;9Lx~u56r=-dY>wtDsp*X~Zlcr_9Dzc5^`c+Ymrw2{j#G|n#QQVzV zf2C0QTTt^@+%n7~KUS1qvXRhj-8O)JNpR5{H{bF!(PC>AZv(DTj-#x&t=h`AYFk#; zQ4KdppVOEMTtkGENsJ2)fl8})TBq0LS>cw7K9GgAl=H12+w*+e3m*jWevlkmZulxp ze8tfOtl20Y9iP6{)>WD>(L}?GAbn0o2LK;vY}Eb|F@iLa%f%0iPyU-~`R^IlN;=-G ztN$Htr&WBcy$9{+_k^7&XNFr+l}5?;Zg_oj6XC$C9|8V>{YK|L1|geS4v|uAV`nqEWs= zk+^fv)YaLie|vrY^y>0i5G8Ma^Sj|_^v2u21-C0NG6*7@^?bdW!=~yv>|4DLh$vx@ zOs8HL@c0#LwcIut-YrDv8}~*H{v!2FC}t8IoUPzWuF4xHSF=iZ3-=GJU|A=RrK(+3 z+DL9kVyum0t!kK2LY6^)sv$;5Y^l^jZ{Qcv!$flYua4gSqsfCmu>IsKFuV0COnh;q zKwsu)1e*#@3dgej2wgVfBw+*2FV);4y_!no&ztqX$CRQk^0&fR?Arf_Q2&wi-_~%J zJENT`=r8JYa7~S*li}zi5mzJBwaw5a=MJJlf&e;b7Cn7{Q*YZ2**uYPgzjd%aK=F@ zoJSB=l#FMGC)f}{mH#YVEpeh0tNYj_M8Za~s;aE6n;?oO(}ScePwr*5>jBz;pV*XD zQYFBKrVG zSDR{f^7h{G{kOjP+Yi6_9g-JS&p&(f>g==Ca{ly__p2gLH`gfQ;ldHB>$+$*)i3_~ z&-^gjtgbx|mAfEJz!z6_ORwcBL+YUXPccsfUD7J*BcneD z=56Rl;=v_l9m{fFNS5qJ2xHA!=oo)1zXAwCSiPfbnoH)hu;`Y_qk&L zJDHNN(5 zQ!SbpbH;Xoe^x0rS#?fIBP*d-$W*gMJbCxvjsG;9Jv3gluRgwRVd7W%AW5@!^Qe6O zzclH^iyEBf_-SZ^HY;KO1K^!?s{TI>R`*>P4e5#2xrq*nCmy zZoP@you7euui6P2gJ#Eo=*hz-ZL6E61q@LXWl@%SMPk{cF6h`ST12|xC`2N(KS3v- z8d9Oc${P4xs5L}4TW3ONx?T3Iv3UR8!*~A3kN2hZ3QD{R6JI*r$lE$=(ogHv`>N_R zAQX*ncK%Q|>U74WBK;F#{|SyQJNqhpSGW^l$HbIsy7rzqExY+qJW3(KKSBM7#q#=D zUFEdZVc7>Scde2=EMX79C5~n%evq8L_V)cZ-`zhtbsPs15juETmH>Z1fWM#plEN^w z_6{F@>pR(M8HRD1F6QUY>bk7UoP4@H^CpeHbO)TsTMS*&Z7WX3@cIyU9JE1EN-Ocw z&CokB#ZLUyW?+x1y7&RvPl?uyC4>nqPdAvKk?Nd-2GT~qTA4-(+<)n6Zz6P}&|JEd z^;p)as?UVls0NKf#z(&$B(KGX-+~xnyV0vP|0+y;=?~SGZMmrPPpef&ne4^c<*l{e zyKut4Zg@WPe-Q3{A$=uY*LJL>PsNCqx+B{7pNme0R>*ifJ$mrw<@wX-Y?@^{UuQ@@ zH1=KENc0U)=7HK0z8amkO@laMJUM{;<@Akr-hTIczVAbrP~?xy-$#;dSiXVKKxC?e zY_o#IVSas4!$F;{t11Uv;o3B%abu1RwVV(#Ai#Isa5UaKx|fV+uIpl%plDgCKs{W~jvqfP!mdk5M*LNNvH7zMR{Obc_H2B}};+0ng+byY2|FFyU? z&#_oXn8LDsqFWjJjLrqaz>&7CC~wC)%1VY!4A_9-VG%&6q~=*_TS>y25+ilq^(F8B68ht8TL$dTo2Cny52MR~;n0?w}%OWsQz_#t_!Rci0=*@3^Z|~q35&?Kg>lV*zRBu7`Vn2u?$MbQw;$cpkQw=rC zUlv}7yU+yBi~zK$Ar=Bs0-UBd=2}I-7^V_*Xw?-O;9zg|+^7R`Ecp0sw^y-_}k-p1~dg3gctSm?DZt2dDQu z-`lMI*?M(-{`lv}r>-`wZe(lS=&!ImpXVoz9n6kSf_U`C+ut2c_s5ex+ePrxk`(=m zj%{fi7S+~O1HA<;MLb92TyXOPq5*|OtR|N8%d<~@{*%pWRb-hL;0FO7OPgVmmn*CE zf;9bQa4&`KON-&G-Kk16G<=6n3;-cey^cjcrMWG;VqIdOo7Gubq?NX>s*^|Q_oLR2njgHQMBw7D&^Jo1T!-vYxxPts zGQh)1;j>S)`nTHueQl3O%stXpAaSCJk9x)2ry!2w@ipS+sm_+90h=#}le~~;* zqs8sv3`H6kG?XrDh!gXR=lNy>F#^(ngQH{b@I>RR=+JEWc7VG18Fg3TLU*cNim2HY zHbEidz#a#nBe-T{o1rolO{U7;{`HP0ItWILp_FYqvy=B`dnZ8xVZwj4>|ce6FBc@L zDsP*zLE3VGM^|3r(IuT$PHX$UwfgD25U64z5K~BdaCoV$K%;eM#*MH7@{pff#k;yK zj6a2BH9FPxQ8aT6VY8yT+@#t+eJ$LK;Y)}uP-$(>ek2D-+YL|^dV&@k$$0N58P9BL zYLKO(xP6@KftBTMIR$6SYKV@DdAeC{HcLQKj4pQet`q~aW=@48;gzTJccOv=;E zglcvupbw*5-sMPjT`iZ3#pUx4e*72dYX11+pEY%b+;-%54e1hOAc&JvlG84-#%Ls* z>(cqgcmK&ZzVrS4!;`(k;|4CEsc%LpmVCI=gL$wz`>2c2!BDfSHNd-dmI1)a3Vs)! z=aR4p^+HiQhkVQEf5w)_+A4Okvj>D3`15Sw6D@LJPYiWkUEXNLl7`|(Ea9kC+>-%W4Q`HnEd`PO3**+YJ z@n{+Zp@ouG7Ks7hG0V>VikfCjyFH5=4DHM67G8XDdA6EgE*9rSx>gOph_%(cliN`* z8z6=w*wKil%qz#WJ3~cRqR9OhOIO{ACUhsL&$}BXGRT=80#04)8a>7Ex)6YoZL($Z zjE(%nCEVJ{A)%p2+ zvnp1r-1pqWgNV*1IbS-<`e0E$_$(Vw{L5PWa1w|IdzgSw<3SkOK-+cYc7d-sw`iYQ z^@rBxLlvE<o+$|}oq{FN3B-V==@FpkT*gtDKp(M)GC$%XFRNu<<$ZJL@v&dI&E_x4Z2X!5FZ z`6^7jY-@w`Xww#nJDax3vkk4u6uTU7csY*cy0-5-EqbHl0`<`|BeH_~fgR`0wIx2j zUPHPoM!vAEj;|=U)e143R2a@Eu#jYZW@SGU03|G6+Y{kTS%F@&t}j>KxU#6>^!M;` zE#gxfJtnFqnz(ScF&|4eVbp1x&3ZY%I0Hb@wiTfDG#a5&-fCH9DdaSD4cneY_XZXK z(va5SbDkSQVm~`Pg_LLIUlwInWb15=W4NQ~eiV<;-qo@@EzB230dX7dm=EsCaA|`I z5)_B(h6ICAtI)E#x`fyZR7C=bKAupmaiEF3aNSXXlV^ELO#Gp2d+r9>qcE27$L;We`6+4~};?3`fT&@6}atdH$_s z`s9-*|Kr3fzj-VoU+j&sT2WF9gg2Ts%m4<1Tc*623z`4ODt;vWhiddM+vIn(GlgV? zzO$khX-(4fQg(n^QfO#cA-vjJ=G+GN{BJht^gtlktQJo{`uY2R`Gcy;;TK>L*9&ld zq-n7-B3U^C4pt&R50DS7G91Vg$}IR%Ht3DlEma$kTP27wDBy z6p*a9SRtU}xdx;!@i#cGAYO#N7lz&_393Raym3?Q=km8?`}BN$5tUe{@EoyY3AEe( z+fj+@Xcss(CO?tIealX?e_y)|5{<1ui*9;^6A5eU!)^5D^e{}^h2uNx)e_GA#dVsl z$`YXy_B$=zG^mZMT6Q1fFSk16Zc=`Q+Ygb9go~T*P4*7s(Ig%vlf6B_RSHdg>&XFp za_sni2a>js;bqW-zWGm>Gyr^o)CiJ}x=}T;NVO5-vAD`>L_;MTld#}0aW1=eO_VFq zBIR5=Bn}=$<0PJuVyN|ZeF8C#W1ij(H*C4(o*7@J+l&_R_iau3Doh9}Se9*5tk+M= zV!fJQmU;2`)5~>QE*G1s!nVAFJ4hFRck>cbWS6p!lf&uB(aiNN$9MAF&Wgi@9h_bL zC+qy;>8F1gSQo!roR35C#t~L48d{32=7I5>y^pQ(B?N;KDVuir18emIHTpdjeP6pL zD*iSG3!4-v+nO5~VjysNV}sqs`Ca!D;+?*_JpbtDe|`1*Nm-=mtQ$t0v%?p;jyBK- zugBgEI2v#SY(6iH{2+ewoo^qUzP5jS5+QPrnzlJf-%dB{5dP{1w&zw5fYcpYxp(fQ zyQ`bzf?Q#$(H2=hZRU<*Nm$`+n!o=TcU!$e8 zw`^*f4XCTKsPm$(>IQOl0O0gY;ejdUAFvgk6hUoRBZd5C_YryIlMXiw4Q|Ues!jtV9X_|I8v=YB7slUaH?y+l7;TuL*Im0&saSmrM@oXoj}teHydXfDChAsU^H%|&2qKj5 zb&$%A_JHb_(Vgi>+gQ?9Gxbs#IwrGityt-=O~In&5Fzi_=DenjwgO}u>t|N_KM7aJ>|a>k>+R$Zg_UR=Mo_xFt;8$t zQmWxk5T(FzR`aXH_2siqKYH@XPa!7S4p#3tTai|4iYG=&OPWDVWMyiIn^-dRoFGiz z`mOKp9iG1S@a<$g(U7MV8S8bqa7V&G8$Oq@1e5ZYIRkm79t*{g##A`9k)|2xN&uo$ z=rjc3*>R+8=4>${DT+%h(JOE|PPvHi9o|ro{vnR5Aj>$u|8^WtBFH%0m*!k<-41#B zmTC3G@4`FP>h1%sSCHK#-Y&c@EO!$y!mqS@Q9=sLJ%dIW(P7PD#TW&k+5iR(EY)J# z1kVstB-f*Ux#e*p^Bag4U%N2TAw8lsD1Z!k(-cja!&=N>9p><>hF>+-&1hy@O0J2K z^rMDzD2lu=^n<_yR0wG@WF=Wq!LO>ql)|@B5mMToRr{8AELD){NVM?pxb{8D8}#QM zuzI%x!p%on{RBA*)s=Q?Vf(v5;Rb@xyN%Z!uv(Kuf01vhBBwOj?p%niZAnoLF2xi( z6wjOnK^UU#(R4JKcqsgDqhJ&=O-P25=nI7Z%zd*A=V(RBae zH{KgfW@eibEy6PUe`_u>)RoclM#Pd|fFq~~328=IV&@ZXa#2+C#gg5aG%~CaO-M7M z>qyJN`EW%2Xz~U)BaTswGjLss7Ua^wnH9RFTGQzseA#F;!IrIufgQ6)_AZg!O_e;( z(~IEnnrZ3HYP{Q+2ayX&L!g4M%UG}C-gQ{z+##_qi&*5_$ZbljvTIs(43DlN%K?)? z1_nkHUFD?FMto7!4MaT8i;P+vKt=O z!Y#}Du*K8z6S(8p1hD!us#_G|&IVxexvGKcFid)i*(ZeliDuh$gu@nlEAk2^?V_;ds?C2Gm_@!b5 z38U3@x>=vMb#Xoa3{u|D9-qTWb#}f1Ov`5i-xjLSYk&ieW6j3#-YnkVAMNdpaj_`< z{CshKeog0#hCr}h=R93Cio=HwPh2EZ;Cz8ir{a8r>M4&uc~s`>YWdf8_3W+5kH>*H zorusgCv8hu^X8D)jX}yTb}3ALgc$v2+C6GVe<pMD+Qh2rp?`(eY?DFjC zFMj%$AN=G`**y&X(C#v!(B^ooN&HHNqp2T_-uvF~$CKGR-})XBD|tS=*Sg$+3UUCa z#f_wclqz3{CU~nU!*av3d!43bRbO2$;Ra?IqCB)iw;eY4a~$772^`0!*-(H9fHA@( z^c=_vL-<7C2f`MpyJbn2Mn@$!M0pF-4aeizGRnecsI&`DotpEfRMzIgz0G=z(6f|6NXTcRjgK&J&__Zds6?~-)pcq#P_64jUz_ODc zP2p}Ao5R}DY4c-QiU~Sh&{D93)Z5ni-JP$&i6dDVuXqe6nvAYcPTtxVrfqg7tiabt z=f5IrssjEChb~zMBIo-B-AQr~bg*Xu5F&_2$?PB*;l!uyx=01rMA6iDCrURi4t%;68L|YL1~iJrQS%MBoi# zaBkb}k5y(EWH1NQpQ8HaEwcI;v1_QzlI6-$lDRfQu--S8UX^yqgG>*~Dce6$b;CHW zZUr~ELnd`UOHV+}%(HPNl+Hgy9c@Xa5Kf@vD>U&XA_M~Hw$6(=;)vBVIN7fj3pkyg ze0ot-&1R9~lGi)3ZE#oOIPhKf{)4?Z@uR?x<8ZZ3SL=+*>D1hm)_Rkz(+q;gD30){ z!I9;=d(#+Kt?NLNK&f$;@QxF==lySqE8aR3fGpsUa~v|C z8axf_R^?CLn&8q=q}^|*$-malRE4h#>Eh`HYXuc9O${85TR`m3A3u8X=z}L8zW?}x zA8Uj}tpV*!qoTb@fdluR9u zCLjT{DC>|s>|qK(lIiazoxr=!^L{AtOUQzKQ@R=Z?xWw)x?|ewj#+EU+$>Yva%O@} z8XT8V3XUVlWIc*pv%LwNB{Uf4@Qg06s0P2m2y_tv-J($d%uXQ;Qk223tLhSdjzf{p zb3J+i;>*?Cx_7m-C({$SEi^c5zd{o))zP5GhLs33$i;dDWEe!yf&Y|kUA7eBA-+5P z7G!3h3)nHRnP-Vh(8cM=s%)sTrX3H~sWc%TXRa&+!}#d!LAgrwFNl?P3>?x6M_%h_ zd)iuUre3qE$5kzA2ZGJ(f%|1F{)xk8ErHdRIj0H>S`Fj zJkO8YwrHD5^lm$*Rw{+D2!ah3_Vk=F&wN$2HsMm?j^h5Aw7@f)#Sih7GnHE{LQLvJo+?|v|X=BE3Z8ul1ySb50 zdq>J!I-M^FZKCfVbJWJ}8E*Uvwl!{kOqA-PY%$&FVok5|VIHMsP^YN-Cbtj1S2yC5 z2LInuciJ{_#O``CM%|E#pbk}4m92lBXyPjyCa46}LW)rq*L9t*SLa!lou6G4MSXF; zs_Hh)Dgt_2k|cnn0}r>lS!d;Zv00~OwkgKrXgm(9vepgG zNxGg3nZ35+voqab`mxDFSRpM!8fHd(l(s@o=_zf*o;?<5se+mu`i?T7Z{T}z7!J2tmo39m`ULGbJ1;tFEKCQVyX z$Y^mIrGgiE@Y-qMQw_zkIRa7_)n>qVY3n52f{rO?vb`gP*>W0yI+zfML^9zKMI2|2Hc)yn=D(?YDWDV z$92&GbTkRVWdHaS!o+0%0Ah#j(I{$F^_&6uGI{Ff2Zp<=5}GNO5EiNyg>34ksoJ)$ zE1RyaMJheE+gA~2FKo5Abl*Rc-E<03ASG$q5!I3J#?~-Qd{8m65W>fN3 ze1uh!mnHmKt=2tf6!tj;lcq5h@|H;yEi)(t3VhTx`YPJeL^dh-0&vL@gA29&6o(Sh zBIYk50Lr|w4ge{nal+Y9!|4UTFS(odgNUtt0v#fmf?6NHD z>t&`<+?7#;>3hLVkFoCP92`vI*grfR`8bczW<|bOKxB|XfSrrugUQ|`S+27AGR6G4 z(WAr*BS=5o*(8DZ0?%6;60xv{o5W_lY~nB>sMNDblq9X|zFy`hPoIQ&wm2)Eo<05W zIR43LA^?=^#YVPUX)^|*cPR(5gBaQ|npDW_Uj6`wIrE>1u`1{X zOC65JkVj1Rj_*B$w!`jQ?^+Y^9-$k{d!##@{A z32`o3W>8Ww$|i`9c|N{AgGy79G;Sb$JJ}Q%4ZDd;HmR zcpIw5n1CHx*DZ=N41%&K;pHlH4`>)ua8l$%NaDF7zvh*I08pyB^_rQ6Xo5;67LOtY5Cu{SsV>9-c5w0f}lY@+1(%Ay=D=5~kFT9ZVFnv!(8dEz+e%5Dvs~I|V?!A+l=eYnSAegV#Sy47mpI+uUVnuj(<220D z3M0LPnZ@zZgmMr?M;Q0TI_n3jL`WtmvG!!w>$HearMMYJ15{yXLG*d+jpMr9yIzd1 zu21sCYws@~J+D5R%|ARDW3|F{xnGVVR@>Jabl}Vevj%@g^~ZRS*1;!6FfwYZ^9#)I^$&gf_k$yu*+kCtADhr|u0|loK}u^#UuM9kAc+ zW5}HjCBI9hIxjZKM7yrt*p(l<_6YSj#B?%-QwQDyZf~+Ooe{AeZ~y>`k3W5iD~Ikd zz}vcPMx$ty#PIJ)617yMB-2QI;fAKjxD)T9!l+HN9u}q|Xz7L^5&I`Z|1g8cx==#31|%DYZ@lDt_$q&QrBr!uJe4kPM7OVx>}{M)z|BsJZTjhzMxP8H43Sq z;EaBx|_TbcakuESxhlVIc}8UsS%0v zS9($n9J38|2(`gL7899!`5D73kXr*XskentdMVtBtpQQmSg&;{kQi=XGbFudtyJqmELrNmt9WNlYa*nAUo-3h&`J> zm)W0->O<|GYX2=2z9X;+GLe{^V0ld_HQ2>QuYUVdJ2DpXa~jWbM>za*V$1eNm;`}B z6Ey@BWO+!EO-tmzmvvJs+#)ttZ0SHnZ*Nk-bl=~mkKTD7!VtEI7Sk1}}& zlPT;*8Cqo5ROO?$r(SaFnxNj6OT-(J2$S4V;ex2@ely%AqVOs>zL7u$CrTK;^X41y zvjC!6hybt=a=lojxt*O|uGWxWA~BbDKXuwv$@jl#tO4n6p%z;&srXXfuX& zhm*_FGE;(Gq>x?afBW3j1MYxjKBHN(fGZXjR?+}P>%g*n7hXA$mRpocuVt21>pTsd zxo@E+DCT8fA2O4oUgLg#aE@ zBy)+KMVt*sjU1f2S1jjev0^2S&tNfF8!eq~cW~~9g4?*U@a|Gyli5nNB_-E;WJizK z&feX;N_A(Xle?50o(k1WjzU!e+`TrH8Iu_Iyo+H1AsbwqmwB)tvB%N0B?*O|5RCHH3GpQ<`OZ`?b8V%2Zb6!erI1twzG>M!9LFn!6jXcke!Vq5V z>T=oC?fiOOLOz`4b;sKFh$^+eKZdmx$3ZfR087M?M=JGVPzB!}qqmh|%Btmk^Q@G>=el0J&-CrVV2i*|(ls(FD$&aFKusR^QJe5jrUP zVGuy;AE2Q7IWjReEZ7vk&!mDvyYru-wPVX}vjir;#go+ZsnvBgq zGBiOTkj1adboH#Ra)=J|`TTmG!mli?;1D+1tRWllAf5~ZCyv8=_xGaMKRTFNj)Y{e zEbEK&1tc1uoz3AuaEP2&(>z`r`moRrkEUS=PZ1|IT%7N4X+f(y-L<#ze5n80ebVAd z%C7Zq;szlLQnf%AOhBCgbG*Qv%|>U>Bjp~w4D0i%B4>;t4#%Va9Ej*SvQ3A9?%7a99Cixt|AGRX;gi;PpOwnPEQ`Q#K zDh6TNus`%2^5fc!Rv_flqN92mMuy(DMVaDVQz@k^OU_N;R|G4^CVrF@t$9c^{O&=< zY9AczCrMnv_f+*LiIY)G`Ifr6nqOWmuyiHuID$oB8>Xq0W|WjJpl(Q~2f~DufpkrV ztGCJ(-Q?PK%DJnpeAUr}A<$tj1JK%1)#Y+|SycJr>Jk#X)oQa^t+Tw^WHok@&24MR zPzFnn5FLWR+1raD%#TMQEU4$_b6A(lb%B*GAza^`BoRD-ysThF?(KyT@2BG=@ZH%o zhJVE|QPh~0h%7%xQik;dww68Jd8K)7LUsKP7L1eBKU1a{Ds1Eb1L)MlgJ^$$1c50D z^fC#X>TtdhMLE~cf1G&K0db5ax{?NVzW^TZ{2j4<`H@uTvi<|RdM^AE?VX}^kmdGj z)KaU@ty}6_#D^hO@g+G`x(_AXGeYuU%{>l+?^@YRB0}s$T~hcORiiJ6vij;z+tQFV zZ40&!)t&=S8{#=0>9(b%+};FvXMJ)jNl8F;P#^6Iy0Xi3`Y+~9*pTWTBnvoiPqD-g zeey8HKdZr991YSE_gw3MIeYX{o{!f_>59toBFxJ5dNa?~o6K{3Sb?L-WF&~AA+%BD zQaHP>*b%{Wf{n>Kp++O&wS^DZf2~T0WSvy+S2j$TXxz31&NyaQb+x&={4CA0vuBGe zEi=5iB};^G)aR&TqX8G3&;HTT7_x?wlL>o6t<&POv#TsGFD@4F^>4g!49hAR1xSWN z6T5aFB1967M({l0^C28Y%-`d?uWzOrH!oF*?Wxt-`ELF1dU}-R&uc~&Th%jINiK4x z9pABMkm*EzGTvJ*S0AmtMRB!QSCineZ|5Ulgdsuwv+bMw>PJ$G|DmJqEV^RE6 zCI3PTPr3)%iikv1@kINtWei!qFgWzgfbMWc=w3m(hXQsL8;on41Z5}@vKT@uELT|E z`bE(k!CU~TX`NRTDo%cAY3vqtZs|Lg;=h($uQ^ zoP#)&WmUrOMFqi2A`9EGA%mc4RSGME;MCz0oX(1a05OuyGsGP1kh~IQVHoC@*K>ds z5J(`Dz-M23aEh~Gs1Rgm5=hO)O{*yuS-s$viMg7gi5`^jFp$-h8rj4y|LTPaa&SQb znN{1=o6U7o7T4F8d68e7Ulo8WmN`5r<~|yrjnnp4fI%8b5K$b2zQ>3FZamy#WLo9s zt}z=5J_C1JeISp$w~4=iwI@idc} z_Ys{2b5|fmm`SPuSP8T2Cti1!0cySqy{W@BocmAvHo7gNm1HXujgcGz)-7?vU z^%(dJXLoj8D`8cD8nku*RoHfmtsJQw8V!w6evk6}FzCE_`U-;RDlbNnZdh`r(?xd! zWlg6TrG`vw<~r5fuvLQDlUZ58YeJ-k(lv-#p zz~|y5Ryf(N{UE?0E+wj>JU_qm{a`d2@t7ODGIDv~ZTTogV{0}4qo zB8!u0mZk7g0nzHdN@0S}Z#1MT(#yIoE-#)IS$1}|NYi3IhiBB#@N9pB@R-1i)Ug2z zOs3&<8c)VCM292}IJtyCyk6zl(qP*tdibkV8iwBMub&3K!%V&aPz08dY;p-zt=c;9 z?4)*jdr(_D-M($Hf~FGTRgq9_a}kV+CT4({0)q+uhNQ)0Ae4Zm!n`$3ta0R5bp%^r zwcgK~Fi)?4@!X2-%c}Ze;tTi{xW*Ds_1>7f8VLGE+Xb$yVM*TSvUo0|$0Gc$@b4*i zMq$FEyV>5k_lFG~c{|=80OHcwf}XrrAhTiE41$ zY2=$&+QzY7;vqRCH4#R^WHbR750Qc*=4~|$7Qkk{OV1KFn4weEq#iA9YGrrR71UwG zYiOwsp*pH)Sr*i@^lfCddURHIVWMwGbsAjok~GOK*)X6djB-yF@~AkDAi#O3?vdna zetwQKiqFq4;j=Dgy)-bUb(UqsG&9rIN4Yzee#tE z6BPfc)mg3KxB23{uFK`+1pvIOt82(z7mKv4+B7R$Zb1QPc2H&6_ZUG0apFS;5hZ{+ zy#O^`Evi58UY3wV(0U3XNQ@^q^#lkPo`UBRTb_ztHZgy(@!k%!kB6O$ZkOntvUxY) z%rhNypiv=A*W}vWR1Lj1(U;J83W1g*X-JXu0P}Qur$7D!gqcws*pBt^jpHnh&RwOe z#bxQQinTodo6r%bQvqR(s})V}?K>zN+&JV_Kc=i(RiZ)V?5d&ely)o^vki-wXBaU8-e;_mlABfqOo^!2>1qPSbSG{QwBT18QS4ckpgg0zSby~6>65Vvlq z+Xyh;h4_u4r^L%NlW`n!sCL;>#gT^qsmLIE>mVj@4DvAiAS!SKhzXhMO}$!e(oL48 z8BWIIkgnP+Q&=`9500ZKoFpUoBy%`4MpUa`ipJ@I5-Zp!S+-fsFCpBFMw71wnxIl; zTa~CHlV3gm2*TlKXP0HsT+egJ1FHh1fLa=w6I_*Xa4H5u!*mi&XYq8J_#rxR;Z{)0 zX{CB0EHF!q$EY{&xfqz?D`A0NFH?y$7>CS3J&VM$`2cCPus)ZYAO>TF{rSzP(j=&S zoK(aeLR%osd|oqN0m#v|BHO1Xr{=>5!xPozaU*eZtSme|#$nLu<_9+Oi%>iKbRX;)pDvmxgpybh%L+r98cH^IvM`>v3Ib9c5|dmgNS%_cp+yn?&Z zl;qWDJMfyz<&vETCX+-xxZlZR5>3V$LP--Hagx1liY#4NR~RE+a_s*fW|&}ps#0)E znyTEWre3b+RaLB(n-X>CFmc5>T&fAT)DWVs6wWmg<6ZbZmKy_9oN@@P%1$j^@74;W zS@T-huC1x@$-7!g9yv4yG}MIH(WSqGi#=pI3+6s^B?D-xqul2s&q&x@nT_k9HX#y(@vfRTOYbGPTzpWvz+C+URk+93f`7~(p2 zJ=x#5Aw~}T2N#*g^hjxN#2~lnQY8vE*vzu*f$i&-f~t31nV6}?F3GlwO^|UMLpqk~ ztnKFIvFTX#IqRz=QyMiRBQ7W<6Nn2GpEi%MGV**N#tk6V>aIV9$ z=>;Uc=yY7uq)7vR4Satxo8o9N`I})iwNt)gWp?bnk;aah&a(R%&E43n%?7W@0FhmZ z;EMq)BoXAz-X_n_&d%YC$@3D!MmK*W$?lS1+kxePZzZd@Na8l+|I%WjL7Eqq&a#rFmmm{iQyjFN*tT%UESEjV zup(*)o&Zb%?-4LX5xDdEfow;s_Gw*Q`Z;=_M;;;zX}tho-ZJ`8-3`D!-3Wp7id@=> z#16;_K^Zy7KJ=H6ow-$&;4MusqOGws(Xd3fg$~A)f#EMLw?cLJvl~V8qDneS1Ned* zJ_-ZkN7zCPfP@|%>Rll3DGXgyz^A|p8Z6}9vJ(du9V~R&l8Uev^S-tpq)5q;(W6?H z9iRCM zmd!ea18IbSTA(bZ+zPXEu^e$J>)+s2wAxq-{4yM?zb7<-*Z{MxEW6J0&Bghrd77O) zyMU~3ew`uHDMPJ+8i$2DLOON4xzrq?8jQPtfR$~C_GOiyKflUT6u*VX2=IvNqwgtJR4Dg-{L$PNgI9)>MZZ#_U(E)gOHd(1XO z-xe*;cv4FOF5hxGGR2LE$y8X1w1$#vS|2Rux97JDfOVoZ*}KAtvN`*@X!kagy@s;2;$~?del~-Dp!Sy z7Wt16!wPJFxOQhAd<$C1Tc7GD#}G$1PlR5{{B4{85rMFL2vA+!)_yT{`>u!IYYz$% zTWPvun)WA8c~hT{6o*Ocjlw#zPHc49zz!57MzAvxMNp!F$g3-M+^*9a6;go^%<7WH zKF{c9ACxH~v@ASFZSvX#Xh_0Hv5r%Z5}WWSJK{$XDs!SS2y#|Q%MgJ{&C$3~Ts37V zWba7AaBz@%&>Zg03repnVa7&{y8uFC*RsvrCp>x_GiyknRh6(+q`aCh;0j@_V2y?- zdZg;3D5_Q%3DaG5a7CnsZsZCx8YbJ}a%#kSlYji^3<4bFiu^tu;%-3Bb8L_)w3!o+=-Jb&G%eV~!SyY8QyIjXr_UkQk0&u%U|OaH-Z}Ofr6f8Ak^N=s$buwY z`wu-hX~)wT(wwJHPB-i2-z-k;_TugFkH)^ZHxm(YD>SL*aZ`2(E4FQne&&JoWODe- z$}azV4c9*XFSK)@NB;pd2gtu#4VR*SyiHoFls|M zE-Sc^mmf-y6JgM5DX4o84zxmvXkT&*zKfd^MX*MsaMB5ruZVe?VcPYfxjl z)#Btk9kdYL(q)#d=JV^-asiPJPGCe3SxHUvhRfN)oCBhxMr&iD24^D*;WOhvmqpgr zE`$bngf`z$q9L$&Avyr31;k@&r15ZoDetqkn)P`&;%*XSUk+mq9V8k>R;F2A7I@$= z^^GbiLd3$c93+8~=r)e@5V1;k_4i8HUf{H?Tc=!$MZDP{D-jngoCYM-ghz{#h7Ht7 z!f75yw+#6Ln|9=t3BfUT9XFlM9LL?LQ&svKaoJW+!dz4>I&yo?&32gnTx8LqHwqx- z$D-Y6_fXm+?d@Tt;3~ow%zzBr27*scW?rHxLd^=Hf=9h6E4OVknQ!+l8D!aGN1@;P zB1ur|3G+CkSa};laMnT9Ko%$`86Mrca&+|w_BP{*i$-_e?$|`cdI{+m=J+^>u#3Y2 zNSr`Tx}hFvCtpQ@fGVI3Rwa0p{Z7%FT@p8avn7qDe#gJw3iOL@#-w|L5XLF+%pupp zP%G-idQjutHnPE&XQ5Vx_c?U|Al-nmK{fm3vnr65e3X5>eRAZ=B(<@xgs z_t9FE4D~}4j>g6_>>1d37uUD1rGgmwM-XX*tHJe0Ot#~}$ ztkbh+$7MF3=YJNHkGKM%S0uPU-c4r*E%V%~g7F-lF)r!TBaE>DXsdgT;(|;94*>+S9B9~~V*hQ+0&L45C6@7%}M-IRk-y))$s{;rlgh%F@=>;uRkgEB2Rb|CU! zEf!Z-b54(V<5I4KbXnEkGJL_7WN}2#k^txd{}MW37x*l(H4zirCM*^X5Rc;fbg&>p zCOuZKn$7e~Q(o6*4uyS7AUT8k6^|15o-D&I#?LWo<$ z*W{J)Vd4c#1NfL0MkW-+{#2Z!g z=&^C5n4J&|vysp@M15OHhtk=eWN340fkg@`Qc*(`@OooYLr`@RfiHD;^sT9go3lg6 zbmXQbIxN&JflS7eNF1b;wXK@E#Q95vypV#K-=jUj#Hvn)zkH2&Vb0E+*Q$~9CoxuZ>s2}QJ?(Mlqto3XM zJuL3%ZS>{<#`9x~b9$ACjv#HoYX6C@RG~TF!ZH#*NrbL8O_NJH?OjKs^&=UXc2I&O z@L8dko+hzH@9014o6RsDUzYzph6x{gc|mm;SP zn-1r@mG;mG(mvRmqSF)|L4ZN3vSHFl6nSVW8wIEyMq6vOO0O>$9K7?qNz+Oq(Fk5S z+MkZe*@0^emXLb)+}u7=UYw@U(K|jEZ`@8|mh385oAvee>hf~EUgnalL$UShi%?qA z{Ruh`KD&Sou-xQv9DMs5uS52cjC>wafTdJHtSqau%N0NgWM|T;X_5c8#B3Hh$da4k z6eO*F@RY95gG>a=`xs#htlEnh5>6>As^Gf;93S4>53vY;bTENC|K!QN#b&uIo_ws3I94PQNs=mO#nh-2{t6XZ-?g{Y?sGg_>ovz`auBC@95|xh){{a zbMQ)G1zDZCm?2gf$0I@z1NmG|D@^C9Y5QU-H$+e~5W8EPU6lQxvHaAcnP8@4e+ zAF2u)0+?ZrnfgDTg79Cdk|g$!DQ?40U#>Sq6~#B=P*LBtZ7=jjqj)@yrhDTF0$WF^ zN|A{(sk+&}p)k=8+O{o+;*wBUuG>-}cLt&ZZ$8*6Q5--VMCCI;s(DSIivf#nRo8^3CbL7g+05kBja^lcy($~&IhJMW zVY+v0l{e}Uw@0Pqi|I(XrP}_qoPSt?~lLa(E~j zS1&$llyXC(TQ0Sw{4ETQfS~Y3GTO4$x|d!g@MH-@MU|hf{RI7 z2sc5r*C+>vo~uo+VL?4|YT?yL!Lo;qAL@o|4e#y*R8$Ti)GlQG1XjDO?_;~xwa{ct zv|UeSrxI*bs+2Zne+{j7E*VjoP7p)enE&lGRq^LJXgKa*M(GliFpO-fB}+M|H4G>@ zdfQwv(xKGLs9A>J;9kwcpsK?iEQLo>G**D6WdOU4Tf%2L^Vg$CAWGrWBWImbYRMjQ}<1lUc>fuWI^UHDZuf~22-Zh@)`~G z*2QL3u=gp-`vfjIwop%_DP2F9%_eZDo}H~=K&V}TrUma0*!0$(li-N@UUO^yzx&#&eemy0~d7h|pI)uY zKTF>a0{>g@yyl1gXcWO>!+9rizQ85#yR6+-WThVg=!oG2fTzo+hebWX0VNbO3HQx*^3Sz*DD0Vb_UWG+WTdc^i=dJO z=9hJWW`A{>=ZFPx{KbYXN3w2|$lEx}V0XH;g5COrg~z4`>pcP_fheHuij7)YR2g6; z2vba?Qe{i+Ev>f9r&<}xio*F(3|y^gg_0b$<61O!g?kIj1aL&dnymZQ6(%5jXV4xE zcXmtZGL0KIkXOUfU8NawC}Gi>6sF}%(0$ycSs`P89gG1i zz)#V7oFIXCHXfmo^>_kUA}b0weQeSVbw6)Y?M2o+&uU1N1natU z>MG*+2WV^K#s-0Di2?MQ@##t;>Zz@$aB5^FHSu@k9r zp+GFbx-@;QH2J*IS?E;qROjSHgPV$5uiBK!h6G6l9_^M4%2JmWX`R^&85}yzI$Jmz z8Y8Q%&KuF3{Vl6DlYlkPhE?RB=(Msch#9dfhF3;|jw2L{=!s5Rr>}_08@N{Y*V%S$ z5y?Yq_;Af$g3pJosNDv(54?M0ZH*RH9wLdr=Ox7`irA(cBIIufO*BpY=<%bg`PHBP z>HmFsb@A5gr;~Af|70JI!_g!fM-c?GciuQ%uJhG8n=jJEVw0s6u>DCJDp5Mdk6OZ;TSg9v!~YpRxamj>;_d$ zRiv|75=QQ5l)(F+&(rJ0S~ZpKEa6c!&K>mjdtHDoY;amA#h`GuD?&Bo#=vq6 z;d+OJASAw79C$~EOkI#O75d8EYKyo)aB~uwybOZ!T4Q;V^ zs1f~?qgB9H=Cb^^@S{}peHDF2`)}*u4J|!od%8s%SFH5XWCT3@ij47aXSzPQp9D0= zMg44hn6BXeIPNEY?D+u}hS|!s%Pv~6O*d%twpD!SVs_K;Bkt@-%&0}hUtZTn4MtjF z5}}wNKu#9}g+k4g77hOdA4#5bF;P58!pk zeMc%TmQsNo-aCowTBfbx46H`D1jZ4b>JhEz`?iS4FlnO5=V9grhmd3J1#l*ahLUK( zxb)hbC{ZujV#6`MOUMv`hayo<=jB@-zhcsX6(9(s%hmGg>SCIN@Rv9Y;CzSYANqi1 zAwolf$@YIpT((g3e)(WQh}H{ha*n|@&uqoQJn^I zX}Cdd4+`0P&{|Y!vT?>P@O-!zloSjV=x&1p%WMJb9V8;eBY+?eWN)&ol!Fd$OPymOYe3 zbGpQPRy+-8@)+h~A-w`AGe~ws)r_K`rz43LOm;-N_cZJ0Sp;ckYJ;C{EXW%*u}*!9 znIGIwAww!|yht`(HYF9o<|V?l84rqRl3|xVYYI za@TX;|6l^C(1X*%Q4;O%O^*&|(@}J=Ki%KM{@Hq+tyd`=!pl{*Sr=^shfMj&rS2>dGAp?b!#G&3W>;((KNKyHr zcO2}!{pS6*-n>tqY?!PyO5d2eu{y7MylXas4ZBtS5CZD;mK+yKs*V z_9i|=HQyy4Y7)t$Mkg$J$m^b^OE`wgRt2`bA0~lgc~t*%X(=>$32QRXYaE18IG$8y z2<7+p$8c|2iv@0!qjZAmE&g~EJa}+;eRXqPVr-E-PIcemis3fFZaE+TXhs`W; z0b_~UCQ(9?<#Dz=q+U$Wl3oxxu8*@#fY+$@O=wPcG|R3eN58ekWe5M>urj1-dYyh# z{U$k&AWquGgD@@e7dDAkB=bPQjjg-R!Z2&rbpnJinS}d3Jt&4VWS?aKg37 z3%V2$1^!~SMuA)uzjH{uYO9OGOc1vG6L)g>hC?4l2$U7Dn4>H_%D`+Q8ey^|5sTvA zaY0!OVfa;AqUuq4N3C6)Xlu%*bWkZe`VA!=QW#z-opLSlA+=*?kO(Z22&JWb53qOO zy9t(d0AW~w$I#9M8Eu%KL*mpD#T8iyfI+wm!X%S!{u?_2Qb5SCY%+twvBK8S_hc^? zq56_C9SjcVX1I$OD)uykejtB<9Xfv7%VH=d4Z@T5Lm!9!9Scuuybn}35N%Owt3|5_ z!;-O#1|~ya9(bjgZ;^HuU=t?@(0fYmG|N)fDt-SJ! zJlvb@jcn?(wzW{ZIKtt%BKkHI)P{XnrZ~zO_oU}alq=wx9&(BQjm zsAcC;MVw5+EH0)bz7Lm|VF|gpx>~~Z02o1CMjJ`{m8J=#p<4%C08+oT_Av{$?ZfeO z5-<0{_45Thv$S;)kLA(P^MUSBw+vm@1?GN-x6UL*3+^NZHj;CADhvQdj@0 zT>U^<->c;7MKvlL_(h&Y5)cG!Ph2iM56Nj~fS(M{K$46WAJ$ZhHWDwUY26w{Ny{{?%{xT59*i}1 zg~tH=Sxe7_n-1wVJz`|8pdh>C!@OnRjHb&$IM@(HM3}K|-SZ<%Xjh#8N^6wV(4L*& zRbL)vh=UoKZM=#AT}!TOn=uk1AJV1ckppXxePXzouC@5hBprQco2(CAHl!j3yav30 z=m^#EGfLjDazmXaYZU+gFCRQG?7(=P+WClUty5?vcx@aAOR$|;gC281}j2W<92gzB9 z4u};>SFvBFkl5d*%ePq~4UaO^Uqi172k(c6Dw3kM>rS7S&o8OW<&jmSEHVZlSN z{0^6vlV#$PbzD|$RxP$D%4#i31!)mlRdDB;@r*IpF%hRBRDc*iJfZm2iVmJ>nbas# z9`z)Gk6TEohm~biy~V-);_z^>w>J%ZZ#Is`VKkpk(=2=Z_(2?J zXJLs)~lm0S}RVj|G%?wU|l_2eHFUKlRcu1xr5Zb9n@@hmKlSW;Gq(*G!L9DHlkVa+R^xuk@xzz~Afx2@AuDLPeOT_z9@gRI0I*}%L4RYS+CPPtI{-2;+(8oTT?f{NeW-u6h#|l zeuiR}kl0s6HF}SSo5{JNOVY1nOy9 zV%v**tE!X(?Y7orbODrI@bFwXC7RMl#j~1a_9{cAfLJC`Mt~hvICfla46++AAA*R# zmJQq-?63=glMsz>LSbOb^ej8FeE0-~QNRblxiZ?FGWm$%0Mt*UM3WkXjQW{%t#P-(4ex`LB@5k4{vZ=9%RA_%ojyf9+BCo-3}B#cG3xXr;EYJix%#KQ58^p z8M1sO?ZU7hSlC>tIO*nxD>^M8)$h`(Q`kqWi9&;x9StjQi~itm)r_eZw-c11D?kK| z0U$012tl-c-$fw2X>00<9Ll5{1DzNJ(qhcbmbd7D6DN?E2XB`LKCO9++(S{7GejpL zR_&xQt!kS{;+HlW=h6<-he1NocUlCaJ6pwLPqd%OMnPo~5v6ZO7r*A(%mLThdZbt}Ltb%gd{qo3qy!pO1pcX!Oq8 zkEWC8$-@V*toIM5v)O2|7(+mL{_-l%iu3bZ><=Nl!0>S=3O=Rt3_IEEvE>-cCNI~BAtY}!WVfbb}{ z)3bI<-NsNt11yY0od^RZi%7uU-?ifTwq{wgFG?WrcIt4&qnT)U|Q+X)=^ z$PYuvUN@w?e1aPjMP0w+imA?{%RU=C-b&&w3W?<~FSY2c3lLSd0mHwU?f zEx<`sjTc*6*J-+e++`d%Ry!+>KCG+sqIhUmNqYKsp?&(!qV=?UkQ{X8M7!k_$h`mv zH$@G>%t+}M+-VertgrmynJp)Fl3Pw_i$lZmO@BhCwomb&Ck=IndWGvT>!L9W14)z~ zA^ORijbYD1?BbhMEnu>Eau`M?BGyREf^q{TTG=%c_5MMmKe0%S0fgGzVzu@3@s?(( z5n`a>%QuwjB5F^f@D$vpRwi)Uq{a3Q*Vtuh)4 zfHYN=wZx3op{kQc83NU)434sFy{xX-x>pHE_deTBcDR+@2mgTy#jhGBY(jAmh6D6mS*5&ETw`I>V4t3mdRr=CV`T`-Xdcrvjh;3pcWI1DLxMslX(myoNScTeyXFuaeXM*; z$ZN;8-=bDZj^a8JRi1I9Ab+P(EiDs*wGU6gqvzmKf3P7ymQ)lL(e>B$ktqh}wt@sh zxdeB>MvkcyM$@7Q)|Fi}sa0GT_2?k~xpa*>Fo>Vl%^C*c`dw6Qu>;pY9?@XwQPvnW z1eFxFT-t4GRbzOPW*yRv@TB1qSzQ?B5X?qfr$v|)N`P_O5=DFv~_Lw5HUq!6=T3yd zCsB$hB<)|&eE3%i6L60pV2|>AK3~jd^E^$fmd$IhN6P?sp^+dcD}c+ml{PNmw8--c zeI|l1c=77>Vlw{l{l`#1o*W$5j`jHQK~uMrSqL@A^B3n?Q6=jXZaD0Gtj>(UK$H>` z3#A3yzNsl%xsXs4MVhD8+3C&x;cR~~4Fhk!H=^j<@DuR@=jdp!L2@cJSsj<;stLG7 zvxXnWux*V#?^VqDGvXRKobBMQaP?MIzjXPx;E+GeWLD^Rwu;7q;)+(uPgg;W5LOgCs7l2i5)zr7w ztE|Y^>kZt}Q3z=!k~?d~mSl?!A!QdgaGu%_iK`;Gr$h_wW?dHWh!5R4#z9A8&~T%Z z?_fjg){ySxiXpQspH9Y*aL*>=POaYc8H%$qSAW`wE zVV$cMVQp~C)CkRnn4Km$`hYo5P`8sNq&tLHh7)*LO}>x9sFY`Ncbd~hmQLu{6k9?= zdU2_sAa_9pDhpw)O2YgNi5R#7DZ{O3@?W)R0fvJbL_s4umvhqh{j^)A-D;+5GB&aaaWM&CX*~G;+pnM5Ivoj9R-EHL8Jv_*4D%)LK$OF>g%Z*ad>ppAEKtnPuAlITtwu!8;^e%D543?@Sf}qXGGooh8#*%DBQYgm%!skB#Y4%R=??@gL8@~LTz6->6POWQC79Ftz<(4AxNuO zeIap$@NIY!<#Bpjw@<%*F_}bAl|)hS_M-;~pmd>xwH_TW;G4ed#%T$s2>S%1vKyWj z47wx7+JdP2w#fo^F$!bJD9%JH+`yjA#uiJ)NK9d2S9(5Hm4b$@LY3K);_}^$&D@sS zzEh8gKA3O~t9s-*Wrg5SkzQ1eA~wyc$f~w>EF`YN`o>U2n-_t@P)9XV)X4S7TH>l> z#tNsC&FnHbQeXw4G4d$F_n>hJzB3754P?1!?kl>!l{96CEEUWdw<&Jp&GI0d7|#xZVCLXVN$51 zu!&|HE~BNk$_;i3(_fkGp!6^K(POCdPan~dCIAfbbeHX8YsU|YkQ^=v)F0o#+=A*|b18>=ig)m4sS z6Yc9oXdIG#DG?7bSU?5=0Rn0b_*HOd#4K%Wqiwi{nm&Y1QUG3DAUP%m&9Ws|B+LoD z85ASJnj4mHxid>R5F_>v-tr(_MLL!jh9fB#2qA+oQ5IJhFKnyU%m$o+D#U@5TfGw{ zfj3CYr4p@ac`PD2o|x=}e$_&dTXrvEIFrz_;9|hgkb(_?j37Y%Z5ReEbDCN#^_1Hg zmW{Ycnc>Qm7uf^EC5=MMB*|XAdYwa|6(@o3fAs15xWXmN!?rZGP|Y;0L?KnFIXKKo z*#(m~c-(oGE;n%yw2MWC#@av3eE3(*CNNT%)^t8U$P>?TS*o}TWu2$9LLra@7|)s6 zn3<#kp`>(~hYk7F*~R5@y+(2BD1cE2M^eot)!s zxc4kVljjB9eTEO99@1uw?tJhtM`3VuxMw*iK!m*|Yx_DR)SR2fdGlayo!A?^@}%R*%#_=~0@K7`;{zFKWa zfEua^YttOpRrvJUiPoo2%6jY>k&nTmqP8Uj2q+MtlB`Lj25~fYWFvLLQgpAO2%H)# z(Qa;Y+@M8HY1p^Ya>ft;xj$Ki9^R^LS34e@rD?K;I^JTRZ+2E}x6RRY%Tl!4|5)od zFxi##qlCsra~jyw)s11>vzspx_LJn|C?z#Ss~mo{HUcvG9C(Y#IKoQNaUc+&>nY(u zAxxMGU8X%~5N}hn`vmKH-$1>cBv;qh7;Az6c7!E*RM~J{>d!+%4DA4@7y9@yW&ga`za+%)3;)dJqqpSno6xL94iD~LU zhU&N|;<8E1L?oMZini5067T~L1szI*wMiK2zdg=SJh7eT#7?PU8m!)_N<*8v0c<>1 zlWmNmFr!smbCGSzwz1K1!i4HMz=PFh2tLM3!n{=2g{afKKoPtgHge^o3@{0EHTVW7 zjfHU)F_ia_3;SYR%kcE4si{@+V8LWrxm<2mt2O-2u9(Qz9*xP~QMAPvIPbC z+~q|=buvEZxOtFQvsDa5=22V!-6AR;&W+GRltcjqM1jpq_%l=-whdX^+`^CRV7%aR zL-baHN}y5c^XEcBbh(mkEFl#!jp@68F`l6Q5+o6Ka{aa{vou*k*^VOj>OfarG1Z1K z?uT_K4N+AKYWP? z5G-A#f*8XwTMez^oT6=EX|2~WR6JRpSR{b(BWYohoy-)%U^E(eo=;N3g0bh^($ef; z&NCH&8WSz5**pJk>@G^oyy-+K;7t4ZSKmeD@$lIJ8xRP%D+L}LLLCKH z?qF18PSP%Uy47kst=7WM45P9fbWWb^zc)Vo*m8Fhfx7}e?*K@o4?BU{u;vJd>4@l%TiH!(2(qa&Y@3oDdhL# z$q)ud+5spbhpjDKs<0J^=Myz36;3p;7{`7Xa zv8l^C83kb&ky9bs!-c+Qd(L@Q{pkf#W6gF|Dgu)H(7AQKorDQ!I!nHQ}3^m3a@n~bKvfEWQ70s2`{M@b2Dpu)a zLlZNwEf3L;rZOJk@9P|g*R#}-f_Eww9S|cNZ#La~Z+iHN?L<3V-Xc#n>+5uLo26^2 zI4r3sxOe#2cUz8zR-s~mtTpiE>avi*A9g{wlC}I9%V6l*d5Eb|2v@-#)V2xrLMzo| z70FGcU6x{)FikddFeJo?cpcx~tZr9pNG7jtmb9z$D2kpOo=m6X?QHK@U z6(FKitpdS@?ieymBHODHi$wNXo-)>0OXhK$-mW*bG@lAic+tdXly8^opG*ZG7GD%`=sbW?sUDJWu@738=;JF52 z_4XHI0wdT$%OPp`do5MNdIgloOB8xmT}&Z+`4%ksn)3P8G06ZjF3pk zp69CqT8cU=5e!ivV}WPm@IsK?D9p9QF(d@I@!0WIDQk8(9F7BWFoQ9^&!w*`K3m33 z;5fsb&nHlS?eEW+APKQ*wTcNzXz5m%!AjGL>5Y%el%(5%!r#K&JD5YV1M$nYL>c={ zvCcQg+4758KC7x58*>rECWepA+A@}D3fS9Qe$Zz#7X zC@hDsE)GT5sSuoK7Z~T`Cz12wlR$t{?SDb#Fpy5gqt%z1p0eUoPPt znQSUpexUs!di=khq64)|g#lp#p8Ctv7u9-clSgtVkgh5u$!D7;+jpXYY_)=Jk8tB% zb~Hi=0FilLUtGWw-6ScV|BjRGEj-^Hx%Of{g%^coI-8E3zc^3O3LH;J2pqoW7Wh99 z*P9g?WEpU~ske_{jq}&ngc`NRQ81r|XxnG%k%Ypp?rLvqJgrcpHQ9|p1z&mDR2T84 z6|HZ<9x}Ps^{7U0$O3Z~AOebgp)V05R3te9wfQiDx&l53c~xTi4W~N9K3EwJF^D?w zB&(vJ%wC5Ud}D8QQ2q-o#HbB*Y}c71T5|?34(D4{6f2YqN|DJ%*g`?HnNsP_U~Ggf z56`L;sG#RT6!+{WZymy&ACD&x3a)P-q*;1-_8`gknsQN#{~VZ0*D4XpU@28GYS(p` z1Rm@+)IVtidFY}Up-drepm^W$pN|ed^Tx-fI~wK!u)p#=&eL_8tcYxC$$pm$qYG_= zxn^(E!tP!yAx?x3p*0~}A$OsRJKz}xg=&dCPD40E$)4BR+yAvHWkPU;t(y2m=(bhl zZBdUj%dwe^!heuE=UDEsNUFi$(a~tMm`yN`@VyAxjOba>peI0y!hF#Pouve6f~t8J zgXb(IRjd`r*c)ZFUZ0+w$4T0dvoh)2^s1oW-N^hkgb9U}FvMgs-P=3#y?_|jJ>yNw zk?#ce!9El{j9A%tD+B;8Pm74huyfM1xV*lFXEho75P~6>ARvV4dAP^s^Jx-iv5}F2 za1Hm%MptQguo(8srnXv>;S3gG4T`LUXADOu#FQ`$slLSKs@%Fpv85z0?u-V9;#46DUU0|Lxg}yb8?e(5e?$0kOqI#+77N(+p#@VyTBGWOO&}Z&KUAkzhiuF z-h<*8h{!M{ux0N;RQ2J`8%d|)bO}zdf{ULPr)FHwphpJNRJi|4!%do1nBmwD;4wp{ z<2l6Lk!;aZx1y3xBgVD)$TH`av9V=Pw%E|Xj=yM>7lQIXX?uMXMkq-P6OcMsuJ45V zZggN;&Xzt46pv8NWpUG#Vpq0aWf0rqPrax@D|_9Vd+hh#)WjGLk7S3iQ(to1z=+!} zqLUp!yrOrB8JVqe&-a(1=z_&>HU#M{bJ{>d!Y1$-?aeU%= zCaH%Am(%1l9)w3*#(>#TWvPB;fG$q1@PK)-XmT8LLcs9Xz9KzeDpZ@Wq zM{oV7zx|Kv^{PgF@|poFl(w2i-_q6Mqb#n2|L1g}8WsZHJDPyFWCUoUglr4x86;^? zK|qFMQWgRLMRSvgp_*w|B)ah#)eTZsF2 z;zn>c&n|A@?&Mh!M*b(CJc0DyMhjUBmLRREKAqQ`X))vw@FBtsWY=>1whe8&qH&yK zn)ASS&@~n{S6lRAGO{?M=^&gYGJ~~Vz^Ry{NQ4(yo;ixb#bVkhB}?S4k_4C4sd#Qp zzrH7rFm?@-Tb7^)Fs}E z5Roa)JMTOiPourPnTInbY|+@&n)#DYXD5F#KlyXpA9tS!!%$UjHdhy~pHa4NZnr~~7j&zq zOWGn(*;H1FPTDfI&oEWdp&Bs**Zclo4$cNO+8|)G_WTnAMhPdHW;Y$-4h2hiQae%T zJ{|HY5V-7nIf)w+KBC|qf`1ifDct{) zqeECc4xKT)i3GY>sA@>k!Ekwb`Qp{t>$3~^b+Es;2Pw*Q!U=Cprsu%%=8Fj|`|-$! zVnkR5Br)SL

9cvc}G+Xlf>NB8=H-Ntpuz1|-yiod>b7OVRVfxV_zYfj66sT)tl> zi=p%*F{3vN=#!%1*^V?VwEV=CfUpQ+{*wcqnvoV&O`4mMbrofR6K0aS=Lj(b2Vo4Mc#Lj|=mA=5dG|uxTZXxDER4uZK)uGA??t0C2 zJqj~H$U>aB0*Pc*r>?6vod7Pu7Vg(P>fJV+)X)YM zUo=u(3MJw7M)~<}&u^!cL*uSNg3wv*>`2{;`@5%xri9YlTgulDpFFz|3d#INgq=s2 zt$8@-@==w8(Nyrd4*Vokd{D@h2oZu!zFx(3RZk{k2gz3@mB@Fv zZJUm9&y)})Z;b*Fs54LPOwS-UT0~M;WnQH}{n;0AcW>7T#KpHCAHVm`Be<)OQan64 zI5?bNoZp_G-CSL*Zf-ZQB>c#SG}d!bS0YOaVM6uMK#DOM1@K^!O`2}dx-ba658rz< znT?}S1Sff0*M^om(VBNO2vPD8YDs8F2=X8vMpHft+NPy>XuZiwqFtbHZW1S`mw^=q zG1eU?B2B>gY!V=~)2`^Cvh>?<7I0q=VoNPYik;k{$0Q(|pk?B0Mmo<10acwK43QvP z)vr%4A^(cwG)W37qcQi-a_XPCs5eb+BL<`!CS*5(8+hJ_AHE%i-fT9pT~u3uZ29c! z2BOTfZ(gk8nADb9Z2LG)ZBC13lDEZmRRvAqnuTYUdv)yD_1tSLqw&pxBIpKA`UbHQ z=yPa?#)D7(yI}StoIWv$Io=hv$>xT-604>zO$2K(%Tc+7h|Vus*=1>-n=ac0!4-+? zK^`k=lBg%BqALvyrde-=8(pxN{8N@TY}hG9O~&bK39l`By`d6CN*KbP~f_neQ#Kta$nD3wW%{Wdc9*_~ZflU@jJjwRcJP z6uTS^qz|uNot~Xtz%Qt*7n2G6%;Di7#CjyXz#6SG)H`rI@ndBZ3VAl0&EX_I*gq^t zn!G?Lpwb)zEja&3tz>bE1jg3__8QSu2NuTUe z43*u~&TQzqZK49%P_`IGMhgkSbQL*YR=_!=IX_?ZlUq`6;$yP{ph^SnI-C*M`^DrYsyt_^?e;IC%34!}5jM zx@PJ5C*J79iypwS*B$r-%7eIu&{2qQ3T|n1(z&v)GWvc*ZwqKB3vngDs|X*`=zgdR ztYSwISQ`C7p%*C!^jK*>y;47N|`H85MG)C@{C*Jbww_Iy=Ak=Ed2^??3tI zgLkImXgmoa63^!oh{XH18>qLReSHcqZhI)uI*LZHYhZ`K85=hloO_Tx!{bEIV_H7@ z@&#OI_2J{`e7so9;a1X66>;5!UNr7nzN?W(r((tw~Ap9194v=xQ9xo-W3)a^HLRksmmV>4eimh$a_T z*PC_x_1DjrkVnW?3#^#RoC;YpXpi06X5H9H6Ty|OGL(zBurm1G#NPN;wHIZMS&pp+ z&PXRZ@g{H0PyWms9htT}9D+i0h}V}%yp)`g5s#O(q7~v^%HiHu%3lP^fC|(=u_?qy zSmd80MITwni38Uqp1^3Jp&fj5*}^cMz~x@*?`Y)+ZLUGzXALzDPdaVE z|K%g_k4x3A#}L$W3c zedKDxU%_FpP9Td-p{N~=qQ(B+g9ir(d-K_JjH}MZsvlX4)8#aEIo4k=2m5rdasFO-| zIlD}Oos`m`QKhAr!3G*yN%U)@%nm<^Lu@!WB226;vCwze_(=@UDr2CkcDKCk8R2Fp zh%-ohRS%ei(I}5-EK**UB>!LGUV{*srAbzi?G?9$*c?Ex4Nb&!_tP81N>sUa$GPJR&}tnm`rmaAmDLy0>qhphmcGr<4(>MwSg|GO z-z(4w6^MlnFYON{o6Ve00OVj^kvtT5dM$Z(h9mF3YUiw|~=W%&_xC6WYI#U@En%ziY27sP6=mEV4I3TJ*@Hj`O&a?sF=&TLi7O>fm_*dwjT^Mq)HrCT0v5vv z(lOSRei<6q)AXw%_BnhfqDCVQI;-|(y}7wrka0wzFiH5UtX`d6uGgEdo_)KDV@U=%!ZHW43_YFQAXK2G z)LpC=ZlScQ8guM*5sK;2{-=LEpH5Epr?$=NMUE59g=r1vpjirObK1bUCs~}c&HXIcyn6FbmM*~^NufB{cl z4TgVrvr#HHOs-i}Iw7!!fIN9P|ATX#LFsk4nPfem%^)O%o)5*? z#l>Zs7B{PPR;KG!O{o?+i9!uN_NUY7WHvd3qkDgk0DCSSin#uos;C9#_>?5R5k2wi z4-@=RSWYSoqv>=u9#6v{YKbe$@G6o4=LvM9CXPZM0(TIy13eM3(=%3^6ZNc76fcg` z^(OWMKPp2~-eX~9C&-~1^AXifgA%ovsWnu~M(s(#&yvacn9g~LQR!a;l{jAocHvV%6gC3XzWA>gEa*py?-#mN=QZ^GBNj zAxq=YXgnH!^!_^^e(>bzaPMGm%FcjLZr|Rn*Q@yRuU?{dP=S222nmr!o+3Z1Ht;*4 zAK;LZ(5sNa!NYm-pEU+CC0j#l4fP}|91DPJ`{5voVLB?BCZNZhr=Lz>(P@3M-TtmU;Xt6t@?U)d7nzK zRZml&e*4oHnV_Y?(7Uc4>B@`FvT4TVfapClIonr_hj;~58g#$h(m^)zJ1BJcM_ zt66bs|Mt>DvIFBvq5XdpT3d5EYHq6;%KAVWwpPRL)og^;wZJhwd0C(}G@^u>vhI;! z$Y#Wd)9Nmmwgs{jCZ?5HoWcWLE;j{AR3s#|i`xVTs(}v+cs`$ma8?Hav7Zo+Us0FZ zvfwZn9UQ)Gl1$)_S9A-35cH%{u$oD)3oi$UhtgA({FqrO zvyrl67SWQasTW77G^>>`Wzcr4wso{1inx1DlfMgU%Cb%QP(l`yw1yj*IBP0N?NWs^ zIiRelj-#Oj*9ht6xJV=!LA5c4Qr5>Dm{^SPGI>#KHV|17oY)v znuhGeY6*~LPbc&7c4~Ggl$EAr&1R&(tDRSct1h49`azby$ia%C@`J9rDj) z+6ehAph9fmk$(-UgQ75;lpbsWWDmN&%dlQ^CuI;)-j{*>h}lG!HoT8}%{PI6| z@9if~9`4PjAHMUD1ZrHkdGRJ$t>dr0IfeRs10ldLAOV5*FVK|CzzjmlfK;m4C$1J}H8|ug)f7BrJCNR{!;661Hd$*i!L;susapDZ+;SY(;m>%d zsx&LIG+#_dv)ROBfQ`|iy-e!eV_s0y6$}5e%pY9KC`3=Kyo3+hTwN^-v|LLd&7k~( z)h}d?f)NeR1@nps1qEgnaEG{6d3-pJM#15O1E`rDQr1fmFj{>6^ywzazW(+lHG??_ zYPo|U_-M<=Q*ODok|+_ba$B4{c=X@=oBwt+8qH_(HyvW|ud^(!s_fN^f6S6KVfGc2 znSHUuK&O|i+FQwf3zU>vG~7Xiifd_YB*-SLfmBVu^c!wcYZ+9bP|qZsOH6ZXV1O|c zN|$$<*(SRZQNy()4;B7fw1ZIPraEAVS#J(vlL|>_m0a@f;7D$X?pj4(%jhs+O66fB zp{9n@A+M@d?GS8ph8}ezT!&;z6yT!+G0|Bb?H#<0ijlVSCJvZw{D!}OS)K%8obbd5?%bT zqfs@Y*F__xGXxx%4QezH(TGV{TBlGF@t3rrYt|QH#Rpz`hbww4oEHG_wRfel%9dO-&wXv<332F(c9H@ z>3_%9+kJicCf3W=xVbxG(M_-8)##rYVrSlb2Frf1DiqX0=UGDY3xygf_4W{&WB&%q zi5MuMm|Gkk{0{{|X{^<1?HUj2NzWzsGxN=tN%A%SwAsX9tc72<%bT0qn-{NMUR<8t z++Kh6_2&>cVHx(8;YuF5!V4>@gQX;dlsOiQqxTBfG}G2%gt%XbnOk#g+FQ*2>?fb? zEvBD+^bT6ZyAD)5B^=jz`NikoWLa@_yMbH4IYmX>r?RZ!JLG(UNLtJ_hz+rrjpwuR z@$ugA@d3+;-L5w4O`K=>&CLdmX!rwtyPLrY!Xa6cY2-TAe6a@?02LxUw!niD(Il7P z>h$GVoRTmf4oPvl2B=f+^IPDg0WwKpwgfUN(f%6E5G4ts!8`d;$Y(4ZAU8K_NJf^o z2&Z99c%}r^bh=P*Y1ul^B9>7Khjp4#DJ90E@V)om3PTU_FVddH`N%4P5Rv`#XJ2g6 z^z7^m`K%UMn3{bAka7nAYIJP^#mevW4Uw*%&u4po@n?UvSnPfJ$!E$zd#MztJy z1r_ot*)jW|)1^?d-6DVJu{4gcXkF6pOz|bEm(tnbj-?nlPWF*e$-Fg8N$(^!rP#*U zsu|7JTlZi^y&W9-(!v%Rv&8+7M(IU)-e_^~mhHHn7yihTj{Dw;zQ&^o_398#2fO0> z<}%Mx_H@JgUot8}3olW(g4CCY2qCwEx7aRIWv5e1U#P5G)*CmyUM}H5Cu!EUet;X- zfaC)HZ7@QoDQA_iot)rSmBCWS4ULpq&ic3zge?j$0u=$a18F7UU}e3@vnoc5r&^Cu zdJoXariL)?%HGKPiO*6inscw7Gq!%FZN51f(FK~=(pdZfNqfKS z3?+W4a7vmax0?_2HCwCLfp5lQ{&?9$*LfolGb!d5#m&t%hD7nfJd<@(ESzJ-kA_IAx9lEG2D1CrR)wjUn$g19;G zIN&ZF9Uh-NIQf_V{BLNy;(yna7Z*zN^2N{cbd_gujT|3SYZ9;!y0+A%071Nb%0Nh~ zhJ{p7+(jxDkeWHjChoG=4W+|_1+#5h+7ySa@&pTfwR&GEufT?{ zzqMU|Ha~V8FN|iUY5fyt6WzF%w9?^fJUTNGRy&^(P$a313I+JJvRK?n`^Bq`AfP5sb^2Su41Y^mDPQg@0MFsvL)>MGbIgJqM3 zvX+DHSU$4mXsT}8><~fbj0Hit;VW;@vlDGS26yQfIT&>70PCqBaD9@gaNO_iXR*Ap zdACofaE%%wAqUw6_W`7`0yf3>Uzr$SDDGwzL#JUWwvd-t{x@?4(c;Odc~DR1d7>g`q?KR?C;G#dhZ=5 z_ya$HAKPTuBKY>}(=0ERw{cmOUKkKV6zdKIHB0G`vl&Nb_%T$TLVffK_m=BMQSkWW z(4-k;QP)t3w5@6gIh?oB+#97i+ZM9-mJS*?m<|pWaOgdHbQDGbwhtYL$pbV$F>9U% z!TCn~gcgziCS)S;(ijwqdbLR)HpI(>s&cZcCO`^WnUgI9*_=6qvBCa6CRgN$4H0iN z9Ze>q`D8Smj$DcnEPMbN&FLvTh0RyrK8FyPAgH7@8OUP}=791JI(hI|MMt@phH_h? zllJi7!N2_LznM%X4^JL_$B15yy-;JkeEH2kWa*l)RkFvRF=hvSF=2GWa8I zYs5x>ou`)^n6`CUNY{>3;@RPH(r z(;2CWYnm!Y?Fgw+pIWKRvQ5#mSH;eKR#Y^hr1}hUY3L9t7V0`Gc`nW=wg;aoNHmD% zcEZsD7T|bth$;j35jbLdz$weRClzl3Vlp7@l1V45q=GKB*r32h z34{r3mlOoT!#adyGH^W0tt!}~E{VO9{tP-RLi&OD9m|Y-Z#o%`Cee5taa3xl837jt zCB_PYCrcVJP{+ox$b_PIMZLFX-j-_U8=NR3Mu8Td@BZEaZQ$=e=v&1RY!!%WpyJi1 z{02L2>4_JOsD#-wW$u%-)bjOutl0F>H4Sqx)aFve^6h@uo2MFGuXZpHk#ADSx+@f- z`}DgPEw)Of-QJ28X3%(GI2_;G?q z(^oH&Bz^kz&*RPJ^QT`FC=>`MTca4nEG^s0E#RN7`Y0;5gC%7Wd8B50mFaX0*~Dxz z{*yobGz|Qa?;{p7$0FkO>+3kqE-r2$1VAc|_Scy0lg~=i^6)%PGbEVO`h9$I^x(k( z;e+f=l79X5D|QKoz;k#wg<>9?=XHB=wS;d@Mqe3kcS$Q5!ZK*j&OiN z@xsG#MnS|Dqs13@km}N+xmkmh?V?;QV@aU|!@T8^hh{@Jkb)#N?>yTi6Khy9cw<{E zuh7wCHk-`nV|Y{4m7($-D7eoLGmi@Y?@BSzxxS# zDy#?l-n;KVdHl{|vG>VGpOSyQ{k{0zvPi2cfBEe{q{*u9O6a7ZQ7)XVn*7lnfLl$| zRz%bJfj<~u_UN0PLP6>f!=D9%GGudHJ}PzmLH)m7@G=(`J(yZG-QdNEgjC2Thy*~V zxuG45_-GVL^tjKwgvMeTJmIEwjqA-Mu_DXt#naeAy2o^B#)?g?Wf~kyCTp0gF`?)o z1GKu{E=P@W|n$P17XH(p9)TJv&7?D9o98 z2qc&uw#5Wd?inV-5?W&AvCbI516uUpZrWA3foE}caRnPAjT89rsP|@>kQBHOK_(eI zlFRF5Lx-7`T{hUe4Iv1$?vblSUPO?qqY98IP*y1~(HF~*5MNqhLkZzI76P3J3JL!_ z#CT+TP+nNLgDVH6wJ~*yV>`nh0crstli8}tftn{3tbu~+wIqJM-r%NArjmKv^G5acScD$(mV^DH*=**L3Fr@L+qaZZ@qr+OF%YsGkUv%H zMHBKQJBe>)68E0t!%jpi?_Z5PX%KhGxjUSW?a!>M8!5VR-R_+d#*QrPR)*b;lQC7^ zfn6HgR>^}v*JmXx_ALj>7ji3(iynv5sYMBvG;F`)rv0{riQ(OXV7{2oXK?P1$54!X z_~A!!y!rf#pIzNtKYR9NlEgF!RM`Kv6&gFOIa~y`qtuIHJP|{11|ei1&{Fi-w=Z6! zcAyEx!e9K!XJHt?7KKf`jS7Kz2UC_7@IRhlzV$!&dI`BrC z;*=D2RTKp8zkfWNh3`Cuz-+?doTlY!1Akj?k_-ZVRn?Fmcs}Ci;b4cWPjiHsVXD81 z4-OVb2eW95jRSgeO_t=>*C`!j43+Rr!*>3GRDfmTWVwj<7N2tMD=+VE;bz( zA;~=UQpuz#x-kTwD%6whD4cwlH!ObL&ry}DUYG2Op=>fmf@VMh5j%kr$waJSqwGLL zr>$l5zU4#6iOMNBS7tV%*CKW`3 z(VP<9<0S{>w#(gqtHXrOEU*&}hY#wqd48P4%jF8T|Hb7QEWaFWa#}{pndIHrYW;!0h*19~u$+dqgV;{=e zB*kxKJd4o@j^Y+&1S*oR!BM4aPR9YNgigPSrLB6A{}46DUiRK zHaeD1qLA#1!pVd?5s%hmd7xxBc+Ix8=76Ysp=iOw1Wep@e>aHm4P7l^nN)!TD7+Z2zT7Q>@*_zCzDQTo^ zerFcC^|IP3P@~8O6TqFe#9a`p_9i3}_q}+{-^MU8{9&bb*b8h=dVloMqr9k|J-A z(~o~bULN)jj1jD?(_kbkY4l(a`={wn+E#yc&fV~S2%@L7Pcc?iSt@q%M|#r{=CZe> z<0%7S(9OZguSOCCJdp#`j(Y8u?Y1PFOES})yQ+dzvJ~z?t8vPHKMU5n=yiPwzfA(g zO24xg;#5R07DkoZIyu`IGqdYYcKM0u(H?C_ieM-reM4a-?@MoHifoLp4sE{NLLII_X4BQKk}E$XI(mzhk* z@Xhfw^2=s&6Q?=ODcY)4ns&6-aQ6z+Xyva>A!h_og#nWuMx3{-%{bJZno?2iw!L)q^VM3*HCOPp| zQei?*!ATm&6vKnP*-~l{J3I!d5>i30tZ-JGaSuKn1O0?GKtpJSe$gq~@E=-3^?@`R zOCciV7FSFyRQ9QE`Z!QAOYD#ge8Q#m`C_hdt-Pbm(FwbSV`~+GYg{;wiS*-CRt@9)k)S* zHt96uTCbW)*$_%HoI);{mR^8LzQF#A2O-BbgV6*MAIOPNkB3^b2GPw^sA{tO=5}=r znb>j(F#h38Ug& zXgEr=or7-M8akus6%$`I8!c+r3Z))q4rpE^rij(P zGLG$Z)`cN^M?3l{N&HufJv9bOxyC&=QR*Z@s}>5D_EZ#jW4nRT@y)h_oisYj+bu+d z7;w*|*plFr#_(Qf2uQ<`SDCPh-@T$^Sbf0ni^U$?o!M-j=Q$J!7nf&Wefh<5b%RT& zkwT0582y}7fo%!G*%Ahpn^YJk;9tR>fuq%NoY{0bnMRPZx(;R)=-McQs%qg#KRdg= zS#GdrX`&P|qzMi3P^-FblPrT}JB77t35W?rUR~a9$gxpEXn-IQMc#ZCLdZBcnj(eN zFp*|S%?y5$IU=m37ocQFQ`PG_iK~3G$)Exvqk2k!nwF)jn+ie1jt?b>iEu3TH$%VT z0)A{U_2JTwj}F3-Kb?&*&Y6h6M5Izxuj2IT>gM$I*~_!D4E2IChwuzanUV7dF}#7> zml5=_-OS4j$E;+Ws z1S!W5!AW~9_cJi5v?s(i0zfJ+JqipCH#JP{0y$_sVCzSkea}VLEdwF%MtfXxXR*UE zbdo}YLP0~%B=-8sbTPtydwS_e?ut(=0qFlDc)%sB-a zH!N?LMPB^;i)U9?%a1>NcRC%1A(A*Lr?BB+qbg|vRX|SQJkxdU@i-);Q&S>*JH=z! zvR%&@MLx+fO4BmnkcYRpxs5%~ftPe`dv9+%88@g8hvse>1dI*x$QuYh_%K{ZKmwGO zA{7~p3t+V_9FDt`0U>0Hu$YVsg6r8oSip52E@n{vOlBiSUc=Ld!~|ac{Q4G3nB{79 zeSN!*_(7B}8%AejH7Ib+?gZMdGVabhdR*+m!4YydP98ywa2)5C#LSh)(6p4Igl;Q)Hmcg*ELYZMgN}id@qCV^#3&r-ArLzt^OZ34 zUc9(i-NpjdMGSISa$+2JW=7F$lAHoTRGUzec;tJBkD;VK#m!CX`_6QNIfdh+Cv%lo zkf*%H_|TvzOkTM@@}NA&X~Pg{6m=m9=)vd#^dh#g31NG#0=c6gO+}m(2g1|A{w(yp z!{dE?3&#)%s?6%L@x75^8=df z1_F{o5JP(?OzaY*nm{LGzd|N$Sj5Y|nQj55mZEhJykLBP$mZ!45@6w+wVm_InW~h8P&% z4`4-p^wB4y(fIj`Z@zi{42K{$H+<9>9k)&z0}hUx zS%#o7)-e)Eu5Z=}R0}BzVH+fEEGSiBT?xms;hShXjK1auqanx}$za*d#bjhV)@*MI zxx?NZ?V(%}NGdC2KrEN*EHBS5FCo9e(J$gmYaTZ+Y-~`~3zc~q?VySns>+H%24)Nr zS*a5VM4iEBhm!DM@9?chZ~y8sB8(;w71K0^6fI9P1gO-NI#yehrn1oQ1gm*6#6j34 ziF=q@KyEiHP-!GJBpU_wmOAM-^=H)cfL_H~XhR*jH4W|6c{_Dm-M3Wq*&zg*SDeoA z<@WG}1mZPjLhsmJJp7KXx*U2ONcF*l?zE~$)9U#Q|86mZM4_)Fn_}yL$#NvMX;#Ac zeaR*U>&c8l^dA^S<0o&u!>jX)FF#){m&Au+V2ee!z3J|_MI_FKg|leazzGbuDM{i@ zEI)sW&J_EL84Ef=h2gvCi-#(^f%p97#d5h37FInD;k01|Z{h@wwXiH5@@Ry&E=bbS z)&}JUX~RI8TOt9yzP?^%S#@=@&U0)la)Ln49ac?tlJH}&`PU$wjG7X|1Ri^q z9 z5T7C`<)@A#aoQ|QiyRN1ghAAq?be)>TX|3im0*-EH7A7GD;f=yeY>+B=S#X_+U-dd zQ^|^<_YPDwoN8XmdwVWJl7&#lxHNVi_Cs|)#n@K6=oDlPJ^JY?kcO4Px?V+x&D3g) zLc5_`L<*29w17EO9nH3N+3!V|7&bUP&pSRop*h@iKHqzF`r_;i^7@8PU^T&R z`sE!hVlATlG-+Ny*H5~EUOQ)JkjK&X`=#$f;#ABIR0Mfz!$qbqlacIq|} zH%sb45RyzxMiCsH==bYknD7wWjyO>q3(FdnFU#`sdYPu#+4%*82dIkRh@d87Czr~i zU$SEv$U(Y%rxh;-9rYmrX^^%zs1|i}cpOF1qepK)cyK%#jeZ?ST(tI@E{?+SbUdD; z9}|hBGEtaS6ih~>(?%`xO_8s)m4Z5ChsHgvVg)LMgVYv47JH&;&AGuiKn%f8nhC}M zL^U5p4;oj54U2m{!Wf2}R%%(hj<>GLAY-VkWoVvgt99FljsbjiOnOz#5yg)swQ)*F z8crFu2fw|ugB}j)PN&X2=$hM}ZYPc3*D%4-SPxGg!BIA!FOD8O_>ceTKWsMZG)2t> zI@6t@eJsOiX@*sI#fa^=@RU+WD&qL_r(aLTDyJCB2!n)cIVe;wMq%*c`T2UeL9;l- zg`0tcLyAq3R^&a8)Faicqg`geYpvXyAI$ z3IP2&QICT~ZMhhLq$V0e;^dzk@57(NQHTO0WF`g?2e#48%_>Q=Z(qDvuH&2KZCRCU z%;1n0Ax+4kP# zi^5AQG4JqzfE>Krn!}_k4E@ zc?2X94#L2YR1aGShpTP6N%OM2zFneGJyacaB}m1{)R$o>(1lj_(vvyaD<{73eu_5@ zH|T7KJjij}*JzE3B5Ioz&WV)VAqLdz`+E!(dsVyXkGm27l} z%eW_Q#NErwSZt4!f3pwqxGuD|ews z7^6X%V zJj-@@!Z%Pilf-VaG>L(Sk0QfoA~uALS+;5?#Ti zIslbnY9Dijo9?=wvS*MBhKXzIk`B*^kjGwFd?+U&JL0|U{#xN0#6TgUYcH#pMx7&z zoSYg{s&BSv9LBXuM>J#eIXa+dkV880va3X-BA7E9-Qrtpyg^su_bN;bS5*+AOmI=` zJ$~zL*k|kY3K9ya*6-~g%RVpUDLNeUc=%>%4)^@(=JxgZ1^iFcn1Xb`MIlN*kWh`! z#&C95MFu&AY7*g4lckXxqbdqyk#Ia}c@0Tz(4gWsra6T`yhohE9!FmZ%kmuZ&O;n0 z)E0ga_)zI!)k8`RG)Qgp98J%!u9tb9->%j<>fKZ%LZPTnLaF_0*q}z54M^ErGxj?N z=}_d==+j@_YIBgmX3Zz_y~QEq5hNXG{^lO*n`#+`ZEr!L#a*+XPT_taqRF11M&Ff? z+tc0-&MEFoB$P(4Hbx)H;dc-yh5x>TT$T5xDBPIPjRUF2HQets2a^_IN@L(xNaA8f zt1ao}c56w+1u4H*fR~)p{{XUy;aA`XzUPldW2lzT&R;_%a(Q|2_y6#B4Y3IagHpOL zoKqlWS5ZGyPO;vs)@wMZU!Prk_Q{9vlM6UHr)UrBkv;cpK3cDmpMUiY98-3V%%j=f z1a@z{+7xA-X9a|D8|}%>0M)Nds25nS8J-&gD5X5Vynzjl9*XGGhtibc2#Tg?K1V~h zC<>wg$)m24pC zf#GPCVT9dGo)dP4_n6A)aCi=4W3R4Cf%u4rqtWEkPyXca;P971TmJe=O~h(SMG0o{ zfJXLxYwa!GN;R2KG;=hyAm1j0Gxe~$J5YtLN7+p*d4h=G&Btd$Wh|DWR!fhJ|f!fx57;b#29AVpSE+A>?qtqu#XbkUU$H zSZ!aSVV9a%*9?Jbzvp3scLl87AP6Vp>En~PJjcJfx`KpawO(y&84Ys^Q|A<>&M9y_ zx!J@wH@9c!7YObm@kkH$ylp`h0fokV9OY$|r{vTG>qZ)u>xiZ;E7ZIY)K;tP76mCS zTvct=va<#XE0F09nlFVuiAqJIX*5CkIm{#At!%We5)FwxlGAT-b+b;=>~;xxM3EIa z`3bW4ve}i{I(r?u+etk~lizWsC@`V82aiar3ImGkdFX*MTTCa5hR@R(Hv`ToAi*xf1)p}d@MRvlTQkz<{$h!(CgMn+$Ar;?oYVQ~pi-AKf(b3yo zyJoRPG-phdmg_V+$lmSz%aeKYKzv~AI@vgN)M=M>1QOcE&iU!7fk z_D3H>tq1$VrKBQsEXQ|T-(IbgFFyYkRcDjZ!al_q9sv4xv~^Rp?3qr~2|U0Wl(j|c z5OmNYNo|M=v)N>^n9di|Q3Od)NTVBzqZgDINuE84J<~ zm7_AOSt{2U(Gi%*L)p-p-5M)FElsO~;*mwQ*y>j3Au@JDs@$^d!~KWj@$^ss^e+$g z560v1FCrxIn>Y}3TWK(f;7Ls@O{J&VO47n&*B)7sa))JW_g9{98l9%4R>3#=JB23K z6xJJ(urb)mr7PY{WixDSpV+3@l@3+ig`uyg@~OuES5n`aiS3X*xR~py*HWEWI^HUa zdyr;VA(%ZCbzuLZ=zOwKF=6Oq+5<`@4Y5oXz%f~w#`;4kI<|-KXnGut#z#lTaGxJN zervN{UtXM(DxBQy4pUB{PE$o2!{=R`DPS5^+T3He1()zjIiD5^Zk z8&bKDC{&3*QV2vU^$ zh?2Uwy-ib;1ub#W8*D+;`Oau8fb7g2#1`=3-Xl)&1<2kAeK&EDz)<0#8xPJnnEXM?6yIajSXPHS-=B6jm4vlpN$FtGXvO3s8HxpG(qXXp! zWOpj?Sx?OBZ%W6XFm`0~cOQd>KPl&PIq0cw0f`Bb#Y*E_A~kY=j@_2XePjDcNd)rw zA{6B652-h?9Vtx5F&Fds_$U9xJ8!Q}j*l-dFaL-C>A#0y!Awodwz}=ajwWqeQ`>@y zKw?r>Rh6X4Puu$R{Ng8{ehjBL?Cl90`<699Jfs8Ld$o!`|M@o%ed08=gc*zi$RI-L z>zW@MmR$SUrm?p-VX@pO@O-Q|(18Zsz(|`HqEcDa*Gss@^(IcApPoU5v0klMe1ViW zU1bp?ly6f*1*lLONSYchS;0*b&D!dZTgognH&m?|(S3Y5G@ZaJFRK);?qvVTWHSBJ zzxXeY4vu`+x2)fS7(og|Qlp)fK?9w-^bBRA(rIE!H;7~}nilSx-Pr7yCtGu8|4=09 z^-%d^N-a@I2JWhf<(Pc0O`*s`y@zb?K*uqM$oi(S)m!Y|&|u4KyS26a4ks{5M?-~y z?J2G7?UKn&#;|*^wy_few~$(F7T1zMaKmjHEWhB^I7(wr{vn2mL9noW6sMiQcAbo; za7PjpkK6KD725~PPLsVxtD9_-Ca`xM2SS5u88}h1NwyodZs<8>B?=-z)5FHKW~!}> zMG!tt8--+oz{fPi^9V@gxMY@xf_>P@Lj9|}DAF{IlML0y%e*9INQ3x(hQjes&Y=2J zQgtDv7--1IVJq$4Ji-_%+u!G%$D7YWda5%Tk09p>-N17_Eg1dV(1el$7YaE*X7lwo zJPTnKSIc-rp$KhqO9TI&Da1g$eVcm8DnW|r)f)-lkq%a`(P$~k`x7BnyWJAvRo7@Vg5#rRyt{iE1U95&w;dJ(EnQH&Eoooa#JB+sDE#Vr)O1L4< zXEpVpe^rzjyyNlF$#^vR7yt5KL!b!!!2ZFabw5UPLfCXxOQ~HXE1GApS_J_nP``q_ zj`8;b^?1zCb=YFS6uQUPc3v5jS#bu@P{22p92O;oLioPQssTowzA;e*LLco$qsW6)0zujkm^g_* zou;NJ(K2I`K&p~#AV3gn3%=JXX-{4mTB*I=b4*u5l*7qhB8~`-!agd{U_h{ywMp- z%Q||)@xuT*-s|6QMc84kAP2I$Z?2wXA1pBV^%;a12;!*8%AL-N7`9K%t<}4myKL1X zT@wb9SWEul_9pIr!6E+P`yZEOxtQ-=Utj&(|K)#Nu5LH0&HvBdmG(wOZKy2rO?Zgfo$Di^~^Tml`I6)8~2x2=ijBIx77@A$;-c9!Qw%nzv z-s7fOGz+b%D`G@Z+@`DEtyA}&drrQ}T*MTP8YRR5B;0ONH&C%k;d-lO_Q~v%qR8*v zd$hhj`jfAH&`#6wS|7f$-A+PsGhWVDzxvHbd0w=W1R%ru<_InqolZ)cF(f@ncf@Rg zE*__+v*VN5{=v~cn`NAw5Qhpah{)qjk_C?HTF{-cEU?iE>*o?>5)ZJPdwr6X@LWfz zQUsap{OpBiYO5}r5T7aWV!;-)4V4aEBb1FF*^t#mqJN>(v2`hl=UI!QLGvyvRaX*CH4A3^ zoavvk7QARU2=N7~Ff#kBuu7vY8D3uVOI^y|&@=%7hq>#ykS5?|8LkcCMPH%~S1B4o zVDij?Ak0JoV~WLmF_9ChTuxvidz}{6C<4^5#?de7wBiUJ_9%%UHNYv%a~VE*dt>s+ z$Wm+pmy;|*1aSfg0^)Qwo1tPjtDY+F2&1=RoNe>~W2JlVl{jz3EH51%Fx9V%@*{?; ztdJ>cI(UAk-RX3CkRZ||y>2<8ahpWY!|DMIIVmMNg6AhrpNlF$52QFsQJ5zPUEdML zclKgoq81GnRkM0nRcB2(nv@H9QF6ASWFzDihkPaL^S`RA7@XGY+C=l~N~)5o)O3cI zaprGwuHJE;A#$$ABQA$K*To$0bp;v{X4!*>_xBI>KK#2M-o1bK@Zd08t%%g*RA=hS zG~+Au)Qxh!%aSuZl$AsA3NJ*`kIrly&IzVb>fFqG{=V!N!4Ysdw95* zFCRVHgTw%D)9Gne<{6q8@-!08eQ0u&)&d%TGtRqG?u11*nf0D3NkCCn5Csro$u-sSSmU*KcKvK$MjqTsgCBMZG7KDGH)cQpbaCJyMJK zOXXO~i%NwA@*reyVN<)P2j!ZRB>Gk+rPIhbMd7$!6m@(*9B$n5a2~<4Xrl4=M{1A* z`v%@04u&VE*jLcZdUKn^_UM@Vacoc%PVQjZo?qMiUcTXB%}uj*W=M2NFvM4#43*ITP1 zFKo}JmQcG5IHHwYUmT&9!-owX#&AvZy#Q_zxr47|fK_97oITj|Nt^~=khI`Q2$H0Q zceD&$X#rg1wO^pTl!no4Knl%qI_vx)^(2>Cn?g54T}`BLFC62l!PziBG=zG2PLW2H zI2)i+|ALO5Ai0PPtFw&I>QY?Uknv^$h`4P2>rGD++==LQ`)Shp!4LlG`1t6DAO7{- z2X`Modc0aJeBvf()c~}^p%cB}SC;D(aBe-`-9;(d#R4$JH@=3LVy)Z7Aw@-#L)C`U z)e^AB@zLpgvH19tPiC|E-q93C$BQLfX*)i^03VJuskLiKAE_+0qyTA{;bey^v|tgQ zY&rb^Pv~E?tS1u$lPPu1!*dZmzoe%-@I2*!YFOx1!QyXu5roljeLNbD|M2|}@UB6L z@7m@FUY#WEhEcj&E#suk;}-aeqPa6LYkX%6IqyVMI6go zR#w(%Lu(yi%@iK2C`n@g5pbi5uXBzN`h=whw)DIbFa?V+kpX>(mS|ywBQrs$I*8g> zw4qtiyo6tRgV)6%ZlF{b&g2Vh2JRur3&-|_x_}zrEP3p+I>UMpm!bgu&Ey$>LX|h% z%X>kWR4AHBmiT8Sn@i(6&Kow<@l1_UbRmr6@BZocj*gCg^ba3CeDvVa!$!ZQ@zyBW2fTt;Z(eY#gpy89*WS-|4%f>k_&Up|A!O>!edj3cUZ~n&imRevzY0@zPSkHcH zPp321P^BrH>%nT3Pxt{+R$9dV3VgrQ?hm?aqu~hEIQ`&Sjeb6H1*xp#K7A(@7U+sP zO)UynnaOebNU8rvgAH|M*{9OQ#;S%6m;W*)&vCLPiFWtldWCZ3(P9{taV0YIsCc-C%ks($(x@q*7NcvIp1!1# zS|(}h*7jSFAl|)w2Y&N*yK|jumM)JAdEwlNM4QJ2?A>m6H^%FW<$SeV9UdN3 zvdKtb0$;(HLTF4;q07z+1+VrG;@LdJDN+{@1Wk9)sFf0WrRBd!e`JqP9zj+)LNpW# zw5x>DRMXN48rEo^7$dw6-^#;;qXY(6kVZ;95W+gn#E)=;ARP49hW+7iG-6|c&vlNV zR{<#$uD0C098(}}*APO@(Ur;$${3xPYn{9VlE`z4q8C3!DNw4bWo?{6`gy$RWZgy8 z+pTKcTh6HD*8LVu_28zfo&l1Tp`23lh4@z*6l0P1@`j*I4OcWuy;iIB?QeeP=;-J_ z{___<{r8{j?eFdF?Xq4w^At%<*(0@*g71p(M210t<Y0*0A=?aC=HwCuvW9^KB@6nQ{IjE<~8U?l5i5g)b2$3^) zd2?fHJl<5_!Ncbu&lpewuWJkvpt~@ z%G}f_X_n@jo9?Ypv#ZS0;~OoCEoZrr-F5=cN9r(2r(7&d*fjBJy$^WK#^a4{x4(b5 zH@vqtpPe3@owU?hxU3I!T}!KINFzr*czRm#A6HRY&LU36w%l*vN<>2?LMbFF@4ki* zym5viJ==x{wVq})28qH{;+kd?$lpO3e#mHP(pu{c2ZOaBE_)gs{A?1M540BXX1uVr9b{&(T zD&ySl=;EZ*M-kI+36#3@Yp{!&w6%%n%M`tCFAAeaj~=cKKFU@(vMuFVJu@{kV8ycij>PaM;i!R}E=XX)LK#t*2&04J~S44()zS_}`3v zQF!Rs#S^C|JZCR;uDzKa2Yj3=6dv2j2-WrEuVSrjMc*#TUk?Yvq%$6@ z-?{zXXfz&=*Wa`Rac*(p_CQy32TPUQLoBFXnFH|8xpJAHHv8IOZN1+g20@ghEqD(}B!&m3asj^N*89PUhjG8uz zHghv_WTH8cBuLGK&nQK|a*Qht>v$oc3h|okvb~{A6Q3byWJvDZdK-4eFWdhOuO%Rg z)03035?bwt&IB6AEQykk=d0SLPD)cab68l2N)7eoIt$-O-3m1_jtl@$Hc8hPRBw*y zdaf|`e`i#69R0Zh-8V(WRekJwu8p>Dz6A*)O;e%!Wp8MbfMpFMSidyIx!&1gj#-}4 z24n-ch{4^$higXKZne5e(vITPlz6GJg_}ZTbBR9ERpr)}pxP5m`xKtPfM~(%ip6s1 zd_aFTG+J=Ia6nR{X{Wzh&5!nG*q11B%nuj3=td%^Vy@*GCsbi7~UP>z0%QIw)Fkdk{BD9XYLXP8uSHD@SPQIv)o5Ie(%!!U~D z^yb#i?RVZCV653SMeq11!D-l}1-HQkdbloFnmwo>eZPiTd+HTS|0k7KOJ&GRTN95LqsQ5bW&ov@ z&UP*|Ps~-OVeFyg8ntS-aUv>BS4@qviy(}HAeNWWv~8MrPD}wW`mI~H;AQXpvI9G8 zHa|Vs-^cr-BQJEvxXtMaHS@15f3=YYPlYIFa9Nw~s0^Zzho;k*sRA|mrz#PuEGdL3 zc{o(aDyZ#`WWIK*6Zj!yw;P)`*Tf*Am(qX&*Y!HxVHCGKKg#orTT4M0K?cEO z5domMya(jCUXpg;f1Mm3(qYl8VK!#CwOD`cGfX$kMnk1yH*f$D5l-ZGTWQxtvqcwf z9&y}poYUpWQWT}@QZJ*B+Tir^BB^XZjY|8n@GdgUFwzyl)5w)x7{q`z9eHI9+op+U z3$9bVwe$A+cmp!SB3th6?jG#zlh%vNw?j>XlkDQ_@PV)7SPSjhr${&GOs=>REZoW< zv}6P!6%NG1iaMp-3RTYOhOEsM3LG=n7VD&p#R@c{)oOQI-M4PN^X|KMV#p9SN1S`w z9kpZT!0F0gePJi{wgFm;Icore_+4gcjOCnl>7pse(wEa|Il8g$$$A zN7*E4)5MES7Jd|oTiZLZp+0{6a6X$MrZ_mDqO|5dl$uDb6b-0Ci4;kpK?Jj@RN1Rk zlZdR2>ozJBT(2xlYg0)ND55VB_}QSLVwO$8oeucKcDomb;TPZeV!yvO9F8GDyf&xL zYv1@lO^PUnt0Hp;qQDuxF9P{91H z_F8Xkeb65RkTH+H=X&i<57jLW+!Ym6X~4~u=e3mtt z7RCgZ&^6ls6g6MFX`UZb?A&^5V}0YngM0TMKiJ*dJJ>(Kn;*6(B&vlJtmUjE1WJ(; ztDEIdP(jb-$!@lfz{FBWz4>ZcI&7peJ}ucUugplT8#R7L7~;U=?FWe)#@KGm7RmrhTw#r3a(V4oTv4ezZ?)5I zf7I`f`-5?l;{>=SO?&V;9!lwC1*t-~u5)H;Lt_WrZ?bZg-y4cXR1Q!6QNKeQkd+M> z6$B|HM}QLUr#dRwH1Yi5lB8^$BpVx>uwy=c{AjscE*1+`FT}SZD+{NrJWa9`+-7fD z&T7w@N}BPl`a)Z2zNTt|=<}eg1^DzB0^yOmtdX|b0GikO0AhP&1$JX+C$^!*OsV2&#!4WJ{mXi}QHR}MysCs@)a#Fz%h}>|0tde1HaNGk zp+iTLWWi%#gmcT~Y881QfEUPdPaO8MY2q{O60TFEfD60b?X6p3 z5bf^ntybvEgEvkZ6w)A}KFn1sRNHN7*%)m)ukE??AciBFO%S5*8VRFHxdi7z=b?7H z8%5DzFzELONt&Y1fa}^E@e;QILiY%=zU#Sau1AWC`ZHBinx;gRD(QNW>&J1LB<&zb z9M=e`U&O60;0@etewa&QjH0(w4I;`5x_IVJq8g)2*JpJsDx66!(~_6nlW*B}nLqQ@ z!)>LlU~Bt3-~K*eiuq!(zrX*{N57@gb&gYaZh$)gYZE-2!Rhp{Sz^;ul1Qj{fu!3qqYj9Vd+y73{$PDH-r3%Pf!yl1kdlhopK$*6og3-L=7B3}A%heBG;mL;#03(QugThd*!qIt78iqcM+c7pK9S3-61biH=k zS-2kDJ{+WFmWChEbd*+OXtLHvHiK+}hKnJucxVp6RSEY~8XPuFy!a!f-EIeA@V)Q+ z<-PlNA=w`t9X@{ia0O8;eMe0hQrn_}UE-*D3sR;Ks&~#?#grS#tCqP~iio8S9Fk(r ztBhuja6`5Sy(CG$`u+#)c4za(RuU(d>qgsnN!JcX`av)p?ktzH2eWCO6_pgt8Uu;f zTH_f5|X;p9>j`My6|8@JMSw~NUlz~MsIF2}21{~!oa9fBGM zkPZa?{ex?as)YhZ7@V7=fV*G zQF2`~GArUrc*gX}2qtOoFG(#DLDT4%d04>}_RM&^(N5bReDKGlm*4j;^J1~_3Idim zPFjE|+T9^wis{jAQ51ZgWZ|g54*^B4ZQP3DR+_ZaR#%8;hI^>n?6{lTx3M!?7JwI8cBv2InR)FsM-nE0}C(zLz3y#op2{V#tdj$@Xe5|=qF*m#uz%etJ; z$-($8{7Kd=WfG;1=lA;KFie9mR=VoXo6vdiAHMDB$w{8A_V@2CW|PU}5TJs`g3P3j z&C+R17Z!@Xjq<$x!43FL0-S71p8+P@rF}`50ulh=I`%P!CCip89P2Pbc0x29?G?5V z#&o0kzjOzLKaSuwh+BvnyWMsd?ivxv{M!U^O&|pv^RRG15R+|+3kL?g@4=M=as<5N z`Ja&vs~1{^XnH84faXyAQ_0|k9Y&=pdr^bERE7(vJOfwgF(a#&E~jsu#;9~)8qZsV*c^&-6h;` z3qGiXxmK{yX}7oD>5t>26GhJ~YiQBLOTDZjnYYzy!@KZcLr$2_PSMn(mO-t~_&Ny9 zD#54ag7EQb&OaV}0dNTd#&;Dg^Z+GwDV6|G(MM25E zvqYux>|<$6nhj+>H*AG|Z_w-Y@7#V5lElsJZP#IAJDVfy?lLlH<>_>i=gX7R!)&!= z1q+-ecbp{cz$G<~@y%!jKhsaKXyO%NiZp4#1K;iR7t1B_DYD8)=xQM{BV)(DwhBZb zVJ-sr&~5i1M_|MCcgg|S#>?JaTGPS_qu9;8RknaVQ|7trtf(Y`&W}`&c>Zl;(Znmn z6lF0xoz3R6fBx5h+THzRZ|{@Ua!Jp;Vmcs#Kyf-Y{=*d>^Z`Wl`n}am_G=<3>>g@262bjY8K^^0}2(Hq;W^#IPU@ z_Am%hUnq%Mtu&6W6lJtwLtiCOw8nLtPRQc3UrsHWc%{JtsfUOAC#NU>_KTk#9PI7w zezIIHDd)3DLB;Z!H*Rd*+}s)s*9U9ED2n^N0b8Zp*U-jOBa0Wtqp@h>l?L~ydN|72 z9`%Pso*f-xIkO@MNp6S|!!GQ$`=jB;a5(Ds*GQi(u&qu@p|eMMX|rX zH=E7=>wkW6czkdO0OMdUjuLp=x`Fn;qv2>Y97A^CuBWY8+IWp&(Zp-2Q@C!g*N>BA zFc?)*uF%2wI1Hm!+8PW78|$0BZm-kn*w@O&wb-#1O}y4RMKL{{EEdb7qa(l*38alU z?RIPY}hpMrbk}nZ~-|vnNFvZD2k&njwtLaW5cEi8+Dz6OBH#ZJ0zB7XEbcs zG-1Prjo-1brS8#Zj%G-1Pr4Vxxx*sx*Kgbf=uY?`oP!-h>0Hf-2 String { + guard width > count else { + return truncate ? String(suffix(width)) : self + } + return String(repeating: pad, count: width - count) + self + } + + func leftJustified(width: Int, pad: String = " ", truncate: Bool = false) -> String { + guard width > count else { + return truncate ? String(prefix(width)) : self + } + return self + String(repeating: pad, count: width - count) + } +} diff --git a/submodules/TextFormat/TextFormat.xcodeproj/project.pbxproj b/submodules/TextFormat/TextFormat.xcodeproj/project.pbxproj index 5c70809e31..a8784728c0 100644 --- a/submodules/TextFormat/TextFormat.xcodeproj/project.pbxproj +++ b/submodules/TextFormat/TextFormat.xcodeproj/project.pbxproj @@ -271,6 +271,17 @@ sourceTree SOURCE_ROOT + 1DD70E29C71C514500000000 + + isa + PBXFileReference + name + StringPadding.swift + path + Sources/StringPadding.swift + sourceTree + SOURCE_ROOT + 1DD70E294ED72F2C00000000 isa @@ -307,6 +318,7 @@ 1DD70E29D54426E100000000 1DD70E294757B6A800000000 1DD70E29080E447400000000 + 1DD70E29C71C514500000000 1DD70E294ED72F2C00000000 1DD70E29E70765FD00000000 @@ -369,6 +381,13 @@ fileRef 1DD70E29080E447400000000 + E7A30F04C71C514500000000 + + isa + PBXBuildFile + fileRef + 1DD70E29C71C514500000000 + E7A30F044ED72F2C00000000 isa @@ -393,6 +412,7 @@ E7A30F04D54426E100000000 E7A30F044757B6A800000000 E7A30F04080E447400000000 + E7A30F04C71C514500000000 E7A30F044ED72F2C00000000 E7A30F04E70765FD00000000 diff --git a/submodules/WalletUI/BUCK b/submodules/WalletUI/BUCK index 72b2b7c1ac..9969005169 100644 --- a/submodules/WalletUI/BUCK +++ b/submodules/WalletUI/BUCK @@ -15,9 +15,15 @@ static_library( "//submodules/OverlayStatusController:OverlayStatusController", "//submodules/AppBundle:AppBundle", "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode", - "//submodules/AccountContext:AccountContext", - "//submodules/UndoUI:UndoUI", - "//submodules/AlertUI:AlertUI", + "//submodules/ItemListUI:ItemListUI", + "//submodules/AccountContext:AccountContext", + "//submodules/UndoUI:UndoUI", + "//submodules/AlertUI:AlertUI", + "//submodules/TextFormat:TextFormat", + "//submodules/Camera:Camera", + "//submodules/ShareController:ShareController", + "//submodules/PasscodeUI:PasscodeUI", + "//submodules/QrCode:QrCode", ], frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", diff --git a/submodules/WalletUI/Sources/WalletInfoScreen.swift b/submodules/WalletUI/Sources/WalletInfoScreen.swift index 9754906135..f2c7c3db97 100644 --- a/submodules/WalletUI/Sources/WalletInfoScreen.swift +++ b/submodules/WalletUI/Sources/WalletInfoScreen.swift @@ -36,6 +36,8 @@ public final class WalletInfoScreen: ViewController { self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.navigationBar?.intrinsicCanTransitionInline = false + self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Receive", style: .plain, target: self, action: #selector(receivePressed)) + self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) } @@ -47,6 +49,10 @@ public final class WalletInfoScreen: ViewController { self.dismiss() } + @objc private func receivePressed() { + self.push(walletReceiveScreen(context: self.context, tonContext: self.tonContext, walletInfo: self.walletInfo, address: self.address)) + } + override public func loadDisplayNode() { self.displayNode = WalletInfoScreenNode(account: self.context.account, tonContext: self.tonContext, presentationData: self.presentationData, walletInfo: self.walletInfo, address: self.address, exportAction: { [weak self] in guard let strongSelf = self else { @@ -57,7 +63,8 @@ public final class WalletInfoScreen: ViewController { guard let strongSelf = self else { return } - strongSelf.push(WalletWordDisplayScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: strongSelf.walletInfo, wordList: wordList)) + strongSelf.push(walletSendScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: strongSelf.walletInfo)) + //strongSelf.push(WalletWordDisplayScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: strongSelf.walletInfo, wordList: wordList)) }, error: { _ in guard let strongSelf = self else { return @@ -104,7 +111,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { let title: String = address let text: String = "..." - let buttonText: String = "Export" + let buttonText: String = "Send" self.titleNode = ImmediateTextNode() self.titleNode.displaysAsynchronously = false diff --git a/submodules/WalletUI/Sources/WalletPasscodeScreen.swift b/submodules/WalletUI/Sources/WalletPasscodeScreen.swift new file mode 100644 index 0000000000..903a6d6327 --- /dev/null +++ b/submodules/WalletUI/Sources/WalletPasscodeScreen.swift @@ -0,0 +1,250 @@ +import Foundation +import UIKit +import AppBundle +import AccountContext +import TelegramPresentationData +import AsyncDisplayKit +import Display +import Postbox +import TelegramCore +import AnimationUI +import SwiftSignalKit +import OverlayStatusController +import PasscodeUI + +public enum WalletPasscodeMode { + case setup + case authorizeTransfer(WalletInfo, String, Int64, String) +} + +public final class WalletPasscodeScreen: ViewController { + private let context: AccountContext + private let tonContext: TonContext + private var presentationData: PresentationData + private let mode: WalletPasscodeMode + + public init(context: AccountContext, tonContext: TonContext, mode: WalletPasscodeMode) { + self.context = context + self.tonContext = tonContext + self.mode = mode + + 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) + + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: defaultNavigationPresentationData.strings)) + + self.navigationPresentation = .modalInLargeLayout + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + self.navigationBar?.intrinsicCanTransitionInline = false + + self.navigationItem.setLeftBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.backPressed)), animated: false) + + self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func backPressed() { + self.view.endEditing(true) + self.dismiss() + } + + override public func loadDisplayNode() { + self.displayNode = WalletPasscodeScreenNode(account: self.context.account, presentationData: self.presentationData, mode: self.mode, proceed: { [weak self] in + guard let strongSelf = self else { + return + } + switch strongSelf.mode { + case .setup: + break + case let .authorizeTransfer(walletInfo, address, amount, comment): + if let navigationController = strongSelf.navigationController as? NavigationController { + var controllers = navigationController.viewControllers + controllers = controllers.filter { controller in + if controller is WalletSplashScreen { + return false + } + if controller is WalletSendScreen { + return false + } + if controller is WalletPasscodeScreen { + return false + } + return true + } + controllers.append(WalletSplashScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, mode: .sending(walletInfo, address, amount, comment))) + strongSelf.view.endEditing(true) + navigationController.setViewControllers(controllers, animated: true) + } + } + }, requestBiometrics: { + + }) + + self.displayNodeDidLoad() + } + + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + (self.displayNode as! WalletPasscodeScreenNode).activateInput() + } + + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + self.view.disablesInteractiveTransitionGestureRecognizer = true + + (self.displayNode as! WalletPasscodeScreenNode).activateInput() + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + (self.displayNode as! WalletPasscodeScreenNode).containerLayoutUpdated(layout: layout, navigationHeight: self.navigationHeight, transition: transition) + } +} + +private final class WalletPasscodeScreenNode: ViewControllerTracingNode { + private var presentationData: PresentationData + private let mode: WalletPasscodeMode + private let requestBiometrics: () -> Void + + private let iconNode: ASImageNode + private let animationNode: AnimatedStickerNode + private let titleNode: ImmediateTextNode + private let biometricsActionTitleNode: ImmediateTextNode + private let biometricsActionButtonNode: HighlightTrackingButtonNode + private let inputFieldNode: PasscodeEntryInputFieldNode + + private let hapticFeedback = HapticFeedback() + + init(account: Account, presentationData: PresentationData, mode: WalletPasscodeMode, proceed: @escaping () -> Void, requestBiometrics: @escaping () -> Void) { + self.presentationData = presentationData + self.mode = mode + self.requestBiometrics = requestBiometrics + + self.iconNode = ASImageNode() + self.iconNode.displayWithoutProcessing = true + self.iconNode.displaysAsynchronously = false + + self.animationNode = AnimatedStickerNode() + + let title: String + let biometricsActionText: String + + title = "Enter Passcode" + biometricsActionText = "Use Face ID" + + self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/PasscodeIcon") + + 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.maximumNumberOfLines = 0 + self.titleNode.textAlignment = .center + + self.biometricsActionTitleNode = ImmediateTextNode() + self.biometricsActionTitleNode.displaysAsynchronously = false + self.biometricsActionTitleNode.attributedText = NSAttributedString(string: biometricsActionText, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemAccentColor, paragraphAlignment: .center) + self.biometricsActionTitleNode.textAlignment = .center + + self.biometricsActionButtonNode = HighlightTrackingButtonNode() + + self.inputFieldNode = PasscodeEntryInputFieldNode(color: self.presentationData.theme.list.itemPrimaryTextColor, accentColor: self.presentationData.theme.list.itemAccentColor, fieldType: .digits4, keyboardAppearance: self.presentationData.theme.rootController.keyboardColor.keyboardAppearance) + + super.init() + + self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor + + self.addSubnode(self.iconNode) + self.addSubnode(self.animationNode) + self.addSubnode(self.titleNode) + self.addSubnode(self.biometricsActionTitleNode) + self.addSubnode(self.biometricsActionButtonNode) + self.addSubnode(self.inputFieldNode) + + self.biometricsActionButtonNode.highligthedChanged = { [weak self] highlighted in + guard let strongSelf = self else { + return + } + if highlighted { + strongSelf.biometricsActionTitleNode.layer.removeAnimation(forKey: "opacity") + strongSelf.biometricsActionTitleNode.alpha = 0.4 + } else { + strongSelf.biometricsActionTitleNode.alpha = 1.0 + strongSelf.biometricsActionTitleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + + self.biometricsActionButtonNode.addTarget(self, action: #selector(self.biometricsActionPressed), forControlEvents: .touchUpInside) + + self.inputFieldNode.complete = { [weak self] passcode in + if passcode == "1111" { + proceed() + } else { + self?.animateError() + } + } + } + + @objc private func biometricsActionPressed() { + self.requestBiometrics() + } + + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) { + let sideInset: CGFloat = 32.0 + let buttonSideInset: CGFloat = 48.0 + let iconSpacing: CGFloat = 21.0 + let titleSpacing: CGFloat = 60.0 + let biometricsSpacing: CGFloat = 44.0 + let buttonHeight: CGFloat = 50.0 + let inputFieldHeight: CGFloat = 34.0 + + let iconSize = self.iconNode.image?.size ?? CGSize(width: 140.0, height: 140.0) + var iconOffset = CGPoint() + + let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height)) + let biometricsActionSize = self.biometricsActionTitleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height)) + + let insets = layout.insets(options: [.input]) + let contentHeight = iconSize.height + iconSpacing + titleSize.height + titleSpacing + inputFieldHeight + let contentVerticalOrigin = floor((layout.size.height - contentHeight - iconSize.height / 2.0 - insets.bottom) / 2.0) + + let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y) + transition.updateFrameAdditive(node: self.iconNode, frame: iconFrame) + self.animationNode.updateLayout(size: iconFrame.size) + transition.updateFrameAdditive(node: self.animationNode, frame: iconFrame) + let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize) + transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame) + + let passcodeLayout = PasscodeLayout(layout: layout, titleOffset: 0.0, subtitleOffset: 0.0, inputFieldOffset: titleFrame.maxY + titleSpacing) + let inputFieldFrame = self.inputFieldNode.updateLayout(layout: passcodeLayout, transition: transition) + transition.updateFrame(node: self.inputFieldNode, frame: CGRect(origin: CGPoint(), size: layout.size)) + + let minimalBottomInset: CGFloat = 60.0 + let bottomInset = layout.intrinsicInsets.bottom + max(minimalBottomInset, biometricsActionSize.height + biometricsSpacing * 2.0) + + if !biometricsActionSize.width.isZero { + let biometricsActionFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - biometricsActionSize.width) / 2.0), y: inputFieldFrame.maxY + floor((layout.size.height - insets.bottom - inputFieldFrame.maxY - biometricsActionSize.height) / 2.0)), size: biometricsActionSize) + transition.updateFrameAdditive(node: self.biometricsActionTitleNode, frame: biometricsActionFrame) + transition.updateFrame(node: self.biometricsActionButtonNode, frame: biometricsActionFrame.insetBy(dx: -10.0, dy: -10.0)) + } + } + + func activateInput() { + self.inputFieldNode.activateInput() + + UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: self.titleNode.attributedText?.string) + } + + func animateError() { + self.inputFieldNode.reset() + self.inputFieldNode.layer.addShakeAnimation(amplitude: -30.0, duration: 0.5, count: 6, decay: true) + + self.hapticFeedback.error() + } +} diff --git a/submodules/WalletUI/Sources/WalletQrCodeItem.swift b/submodules/WalletUI/Sources/WalletQrCodeItem.swift new file mode 100644 index 0000000000..c2bc7e8e76 --- /dev/null +++ b/submodules/WalletUI/Sources/WalletQrCodeItem.swift @@ -0,0 +1,209 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import TelegramPresentationData +import ItemListUI +import QrCode + +class WalletQrCodeItem: ListViewItem, ItemListItem { + let theme: PresentationTheme + let address: String + let sectionId: ItemListSectionId + let style: ItemListStyle + + init(theme: PresentationTheme, address: String, sectionId: ItemListSectionId, style: ItemListStyle) { + self.theme = theme + self.address = address + self.sectionId = sectionId + self.style = style + } + + func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + async { + let node = WalletQrCodeItemNode() + let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + + node.contentSize = layout.contentSize + node.insets = layout.insets + + Queue.mainQueue().async { + completion(node, { + return (nil, { _ in apply() }) + }) + } + } + } + + func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) { + Queue.mainQueue().async { + if let nodeValue = node() as? WalletQrCodeItemNode { + 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 { + completion(layout, { _ in + apply() + }) + } + } + } + } + } +} + +class WalletQrCodeItemNode: ListViewItemNode { + private let backgroundNode: ASDisplayNode + private let topStripeNode: ASDisplayNode + private let bottomStripeNode: ASDisplayNode + + private let imageNode: TransformImageNode + + private var item: WalletQrCodeItem? + + var tag: Any? { + return self.item?.tag + } + + init() { + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + self.backgroundNode.backgroundColor = .white + + self.topStripeNode = ASDisplayNode() + self.topStripeNode.isLayerBacked = true + + self.bottomStripeNode = ASDisplayNode() + self.bottomStripeNode.isLayerBacked = true + + self.imageNode = TransformImageNode() + + super.init(layerBacked: false, dynamicBounce: false) + + self.addSubnode(self.imageNode) + } + + func asyncLayout() -> (_ item: WalletQrCodeItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { + let makeImageLayout = self.imageNode.asyncLayout() + + let currentItem = self.item + + return { item, params, neighbors in + var updatedTheme: PresentationTheme? + var updatedAddress: String? + + if currentItem?.theme !== item.theme { + updatedTheme = item.theme + } + + if currentItem?.address != item.address { + updatedAddress = item.address + } + + let contentSize: CGSize + let insets: UIEdgeInsets + let separatorHeight = UIScreenPixel + + let inset: CGFloat = 12.0 + var imageSize = CGSize(width: 256.0, height: 256.0) + let imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: nil)) + + let itemBackgroundColor: UIColor + let itemSeparatorColor: UIColor + switch item.style { + case .plain: + itemBackgroundColor = item.theme.list.plainBackgroundColor + itemSeparatorColor = item.theme.list.itemPlainSeparatorColor + contentSize = CGSize(width: params.width, height: imageSize.height + inset * 2.0) + insets = itemListNeighborsPlainInsets(neighbors) + case .blocks: + itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor + itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor + contentSize = CGSize(width: params.width, height: imageSize.height + inset * 2.0) + insets = itemListNeighborsGroupedInsets(neighbors) + } + + let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) + + return (layout, { [weak self] in + if let strongSelf = self { + strongSelf.item = item + + if let _ = updatedTheme { + strongSelf.topStripeNode.backgroundColor = itemSeparatorColor + strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor + strongSelf.backgroundNode.backgroundColor = itemBackgroundColor + } + + if let updatedAddress = updatedAddress { + strongSelf.imageNode.setSignal(qrCode(string: updatedAddress, color: .black, backgroundColor: .white, icon: .custom(UIImage(bundleImageName: "Settings/Wallet/IntroIcon")), ecl: "Q"), attemptSynchronously: true) + } + + let _ = imageApply() + + let leftInset: CGFloat + + switch item.style { + case .plain: + leftInset = 35.0 + params.leftInset + + if strongSelf.backgroundNode.supernode != nil { + strongSelf.backgroundNode.removeFromSupernode() + } + if strongSelf.topStripeNode.supernode != nil { + strongSelf.topStripeNode.removeFromSupernode() + } + if strongSelf.bottomStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 0) + } + + strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight)) + case .blocks: + leftInset = 16.0 + params.leftInset + + if strongSelf.backgroundNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) + } + if strongSelf.topStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1) + } + if strongSelf.bottomStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) + } + switch neighbors.top { + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + strongSelf.topStripeNode.isHidden = false + } + let bottomStripeInset: CGFloat + let bottomStripeOffset: CGFloat + switch neighbors.bottom { + case .sameSection(false): + bottomStripeInset = 16.0 + params.leftInset + bottomStripeOffset = -separatorHeight + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + } + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight)) + strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight)) + } + + strongSelf.imageNode.frame = CGRect(origin: CGPoint(x: (params.width - imageSize.width) / 2.0, y: 12.0), size: imageSize) + } + }) + } + } + + override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4) + } + + override func animateRemoved(_ currentTimestamp: Double, duration: Double) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) + } +} diff --git a/submodules/WalletUI/Sources/WalletQrScanScreen.swift b/submodules/WalletUI/Sources/WalletQrScanScreen.swift new file mode 100644 index 0000000000..e904b1f0f1 --- /dev/null +++ b/submodules/WalletUI/Sources/WalletQrScanScreen.swift @@ -0,0 +1,184 @@ +import Foundation +import UIKit +import AppBundle +import AccountContext +import TelegramPresentationData +import AsyncDisplayKit +import Display +import Postbox +import TelegramCore +import AlertUI + +public final class WalletQrScanScreen: ViewController { + private let context: AccountContext + private let tonContext: TonContext + private var presentationData: PresentationData + + public init(context: AccountContext, tonContext: TonContext) { + self.context = context + self.tonContext = tonContext + + 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) + + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: defaultNavigationPresentationData.strings)) + + self.navigationPresentation = .modalInLargeLayout + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + self.navigationBar?.intrinsicCanTransitionInline = false + + self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func backPressed() { + self.dismiss() + } + + override public func loadDisplayNode() { + self.displayNode = WalletQrScanScreenNode(presentationData: self.presentationData) + + self.displayNodeDidLoad() + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + (self.displayNode as! WalletQrScanScreenNode).containerLayoutUpdated(layout: layout, navigationHeight: self.navigationHeight, transition: transition) + } +} + +private final class WalletQrScanScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { + private var presentationData: PresentationData + + private let navigationBackgroundNode: ASDisplayNode + private let navigationSeparatorNode: ASDisplayNode + private let navigationTitleNode: ImmediateTextNode + private let scrollNode: ASScrollNode + private let iconNode: ASImageNode + private let titleNode: ImmediateTextNode + private let textNode: ImmediateTextNode + + private var navigationHeight: CGFloat? + + init(presentationData: PresentationData) { + self.presentationData = presentationData + + self.navigationBackgroundNode = ASDisplayNode() + self.navigationBackgroundNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.backgroundColor + self.navigationBackgroundNode.alpha = 0.0 + self.navigationSeparatorNode = ASDisplayNode() + self.navigationSeparatorNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor + + self.scrollNode = ASScrollNode() + + self.iconNode = ASImageNode() + self.iconNode.displayWithoutProcessing = true + self.iconNode.displaysAsynchronously = false + + let title: String = "24 Secret Words" + let text: String = "Write down these 24 words in the correct order and store them in a secret place.\n\nUse these secret words to restore access to your wallet if you lose your passcode or Telegram account." + let buttonText: String = "Done" + + self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/WordsDisplayIcon") + + 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.maximumNumberOfLines = 0 + self.titleNode.textAlignment = .center + + self.navigationTitleNode = ImmediateTextNode() + self.navigationTitleNode.displaysAsynchronously = false + self.navigationTitleNode.attributedText = NSAttributedString(string: title, font: Font.bold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) + self.navigationTitleNode.maximumNumberOfLines = 0 + self.navigationTitleNode.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 + + super.init() + + self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor + + self.addSubnode(self.scrollNode) + + self.scrollNode.addSubnode(self.iconNode) + self.scrollNode.addSubnode(self.titleNode) + self.scrollNode.addSubnode(self.textNode) + + self.navigationBackgroundNode.addSubnode(self.navigationSeparatorNode) + self.navigationBackgroundNode.addSubnode(self.navigationTitleNode) + self.addSubnode(self.navigationBackgroundNode) + } + + override func didLoad() { + super.didLoad() + + self.scrollNode.view.alwaysBounceVertical = false + self.scrollNode.view.showsVerticalScrollIndicator = false + self.scrollNode.view.showsHorizontalScrollIndicator = false + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.scrollNode.view.contentInsetAdjustmentBehavior = .never + } + self.scrollNode.view.delegate = self + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + let navigationHeight = self.navigationHeight ?? 0.0 + let alpha: CGFloat = scrollView.contentOffset.y >= (self.titleNode.frame.maxY - navigationHeight) ? 1.0 : 0.0 + if self.navigationBackgroundNode.alpha != alpha { + let transition: ContainedViewLayoutTransition = .animated(duration: 0.12, curve: .easeInOut) + transition.updateAlpha(node: self.navigationBackgroundNode, alpha: alpha, beginWithCurrentState: true) + } + } + + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) { + self.navigationHeight = navigationHeight + + let sideInset: CGFloat = 32.0 + let buttonSideInset: CGFloat = 48.0 + let iconSpacing: CGFloat = 5.0 + let titleSpacing: CGFloat = 19.0 + let textSpacing: CGFloat = 37.0 + let buttonHeight: CGFloat = 50.0 + let buttonSpacing: CGFloat = 45.0 + let wordSpacing: CGFloat = 12.0 + let indexSpacing: CGFloat = 4.0 + + transition.updateFrame(node: self.navigationBackgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: navigationHeight))) + transition.updateFrame(node: self.navigationSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel))) + + transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size)) + + let iconSize = self.iconNode.image?.size ?? CGSize(width: 50.0, height: 50.0) + + let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height)) + let navigationTitleSize = self.navigationTitleNode.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 iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize) + transition.updateFrameAdditive(node: self.iconNode, frame: iconFrame) + let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), 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) + + transition.updateFrameAdditive(node: self.navigationTitleNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - navigationTitleSize.width) / 2.0), y: navigationHeight - 44.0 + floor((44.0 - navigationTitleSize.height) / 2.0)), size: navigationTitleSize)) + + contentHeight = textFrame.maxY + textSpacing + } +} diff --git a/submodules/WalletUI/Sources/WalletReceiveScreen.swift b/submodules/WalletUI/Sources/WalletReceiveScreen.swift new file mode 100644 index 0000000000..7cd9494005 --- /dev/null +++ b/submodules/WalletUI/Sources/WalletReceiveScreen.swift @@ -0,0 +1,196 @@ +import Foundation +import UIKit +import AppBundle +import AccountContext +import TelegramPresentationData +import AsyncDisplayKit +import Display +import Postbox +import TelegramCore +import ItemListUI +import SwiftSignalKit +import OverlayStatusController +import ShareController + +private final class WalletReceiveScreenArguments { + let context: AccountContext + let copyAddress: () -> Void + let shareAddressLink: () -> Void + + init(context: AccountContext, copyAddress: @escaping () -> Void, shareAddressLink: @escaping () -> Void) { + self.context = context + self.copyAddress = copyAddress + self.shareAddressLink = shareAddressLink + } +} + +private enum WalletReceiveScreenSection: Int32 { + case address +} + +private enum WalletReceiveScreenEntry: ItemListNodeEntry { + case addressHeader(PresentationTheme, String) + case addressCode(PresentationTheme, String) + case address(PresentationTheme, String) + case copyAddress(PresentationTheme, String) + case shareAddressLink(PresentationTheme, String) + case addressInfo(PresentationTheme, String) + + var section: ItemListSectionId { + switch self { + case .addressHeader, .addressCode, .address, .copyAddress, .shareAddressLink, .addressInfo: + return WalletReceiveScreenSection.address.rawValue + } + } + + var stableId: Int32 { + switch self { + case .addressHeader: + return 0 + case .addressCode: + return 1 + case .address: + return 2 + case .copyAddress: + return 3 + case .shareAddressLink: + return 4 + case .addressInfo: + return 5 + } + } + + static func ==(lhs: WalletReceiveScreenEntry, rhs: WalletReceiveScreenEntry) -> Bool { + switch lhs { + case let .addressHeader(lhsTheme, lhsText): + if case let .addressHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + case let .addressCode(lhsTheme, lhsAddress): + if case let .addressCode(rhsTheme, rhsAddress) = rhs, lhsTheme === rhsTheme, lhsAddress == rhsAddress { + return true + } else { + return false + } + case let .address(lhsTheme, lhsAddress): + if case let .address(rhsTheme, rhsAddress) = rhs, lhsTheme === rhsTheme, lhsAddress == rhsAddress { + return true + } else { + return false + } + case let .copyAddress(lhsTheme, lhsText): + if case let .copyAddress(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + case let .shareAddressLink(lhsTheme, lhsText): + if case let .shareAddressLink(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + case let .addressInfo(lhsTheme, lhsText): + if case let .addressInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + } + } + + static func <(lhs: WalletReceiveScreenEntry, rhs: WalletReceiveScreenEntry) -> Bool { + return lhs.stableId < rhs.stableId + } + + func item(_ arguments: WalletReceiveScreenArguments) -> ListViewItem { + switch self { + case let .addressHeader(theme, text): + return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) + case let .addressCode(theme, address): + return WalletQrCodeItem(theme: theme, address: "ton://\(address)", sectionId: self.section, style: .blocks) + case let .address(theme, address): + return ItemListMultilineTextItem(theme: theme, text: address, enabledEntityTypes: [], font: .monospace, sectionId: self.section, style: .blocks) + case let .copyAddress(theme, text): + return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { + arguments.copyAddress() + }) + case let .shareAddressLink(theme, text): + return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { + arguments.shareAddressLink() + }) + case let .addressInfo(theme, text): + return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section) + } + } +} + +private func walletReceiveScreenEntries(presentationData: PresentationData, address: String) -> [WalletReceiveScreenEntry] { + var entries: [WalletReceiveScreenEntry] = [] + entries.append(.addressHeader(presentationData.theme, "YOUR WALLET ADDRESS")) + + let address = String(address[address.startIndex.., WalletSendScreen { + +} + +func walletReceiveScreen(context: AccountContext, tonContext: TonContext, walletInfo: WalletInfo, address: String) -> ViewController { + var presentControllerImpl: ((ViewController, Any?) -> Void)? + var presentInGlobalOverlayImpl: ((ViewController, Any?) -> Void)? + var dismissImpl: (() -> Void)? + + let arguments = WalletReceiveScreenArguments(context: context, copyAddress: { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + UIPasteboard.general.string = address + + presentInGlobalOverlayImpl?(OverlayStatusController(theme: presentationData.theme, strings: presentationData.strings, type: .genericSuccess("Address copied to clipboard.", false)), nil) + }, shareAddressLink: { + guard let address = address.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else { + return + } + let controller = ShareController(context: context, subject: .url("ton://\(address)"), preferredAction: .default) + presentControllerImpl?(controller, nil) + }) + + let address: Signal = .single(address) + + let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, address) + |> map { presentationData, address -> (ItemListControllerState, (ItemListNodeState, WalletReceiveScreenEntry.ItemGenerationArguments)) in + let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .regular, enabled: true, action: { + dismissImpl?() + }) + + let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text("Receive Grams"), leftNavigationButton: rightNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) + let listState = ItemListNodeState(entries: walletReceiveScreenEntries(presentationData: presentationData, address: address), style: .blocks, animateChanges: false) + + return (controllerState, (listState, arguments)) + } + + let controller = WalletReceiveScreenImpl(context: context, state: signal) + controller.navigationPresentation = .modal + presentControllerImpl = { [weak controller] c, a in + controller?.present(c, in: .window(.root), with: a) + } + presentInGlobalOverlayImpl = { [weak controller] c, a in + controller?.presentInGlobalOverlay(c, with: a) + } + dismissImpl = { [weak controller] in + let _ = controller?.dismiss() + } + return controller +} diff --git a/submodules/WalletUI/Sources/WalletSendScreen.swift b/submodules/WalletUI/Sources/WalletSendScreen.swift new file mode 100644 index 0000000000..dc173c92fe --- /dev/null +++ b/submodules/WalletUI/Sources/WalletSendScreen.swift @@ -0,0 +1,425 @@ +import Foundation +import UIKit +import AppBundle +import AccountContext +import TelegramPresentationData +import AsyncDisplayKit +import Display +import Postbox +import TelegramCore +import ItemListUI +import SwiftSignalKit +import AlertUI +import TextFormat + +private let walletAddressLength: Int = 48 + +private final class WalletSendScreenArguments { + let context: AccountContext + let updateState: ((WalletSendScreenState) -> WalletSendScreenState) -> Void + let selectNextInputItem: (WalletSendScreenEntryTag) -> Void + let proceed: () -> Void + + init(context: AccountContext, updateState: @escaping ((WalletSendScreenState) -> WalletSendScreenState) -> Void, selectNextInputItem: @escaping (WalletSendScreenEntryTag) -> Void, proceed: @escaping () -> Void) { + self.context = context + self.updateState = updateState + self.selectNextInputItem = selectNextInputItem + self.proceed = proceed + } +} + +private enum WalletSendScreenSection: Int32 { + case address + case amount + case comment +} + +private enum WalletSendScreenEntryTag: ItemListItemTag { + case address + case amount + case comment + + func isEqual(to other: ItemListItemTag) -> Bool { + if let other = other as? WalletSendScreenEntryTag { + return self == other + } else { + return false + } + } +} + +private let invalidAddressCharacters = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=").inverted +private func isValidAddress(_ address: String, exactLength: Bool = false) -> Bool { + if address.count > walletAddressLength || address.rangeOfCharacter(from: invalidAddressCharacters) != nil { + return false + } + if exactLength && address.count != walletAddressLength { + return false + } + return true +} + +private let invalidAmountCharacters = CharacterSet(charactersIn: "01234567890.,").inverted +private func isValidAmount(_ amount: String) -> Bool { + if amount.rangeOfCharacter(from: invalidAmountCharacters) != nil { + return false + } + var hasDecimalSeparator = false + var hasLeadingZero = false + var index = 0 + for c in amount { + if c == "." || c == "," { + if !hasDecimalSeparator { + hasDecimalSeparator = true + } else { + return false + } + } + index += 1 + } + + var decimalIndex: String.Index? + if let index = amount.firstIndex(of: ".") { + decimalIndex = index + } else if let index = amount.firstIndex(of: ",") { + decimalIndex = index + } + + if let decimalIndex = decimalIndex, amount.distance(from: decimalIndex, to: amount.endIndex) > 4 { + return false + } + + return true +} + +private func stringForGramsAmount(_ amount: Int64, decimalSeparator: String = ".") -> String { + if amount < 1000 { + return "0\(decimalSeparator)\(String(amount).rightJustified(width: 3, pad: "0"))" + } else { + var string = String(amount) + string.insert(contentsOf: decimalSeparator, at: string.index(string.endIndex, offsetBy: -3)) + return string + } +} + +private func amountValue(_ string: String) -> Int64 { + return Int64((Double(string) ?? 0.0) * 1000.0) +} + +private func normalizedStringForGramsString(_ string: String, decimalSeparator: String = ".") -> String { + return stringForGramsAmount(amountValue(string), decimalSeparator: decimalSeparator) +} + +private enum WalletSendScreenEntry: ItemListNodeEntry { + case addressHeader(PresentationTheme, String) + case address(PresentationTheme, String, String) + case addressInfo(PresentationTheme, String) + + case amountHeader(PresentationTheme, String, String, Bool) + case amount(PresentationTheme, PresentationStrings, String, String) + + case commentHeader(PresentationTheme, String) + case comment(PresentationTheme, String, String) + + var section: ItemListSectionId { + switch self { + case .addressHeader, .address, .addressInfo: + return WalletSendScreenSection.address.rawValue + case .amountHeader, .amount: + return WalletSendScreenSection.amount.rawValue + case .commentHeader, .comment: + return WalletSendScreenSection.comment.rawValue + } + } + + var stableId: Int32 { + switch self { + case .addressHeader: + return 0 + case .address: + return 1 + case .addressInfo: + return 2 + case .amountHeader: + return 3 + case .amount: + return 4 + case .commentHeader: + return 5 + case .comment: + return 6 + } + } + + static func ==(lhs: WalletSendScreenEntry, rhs: WalletSendScreenEntry) -> Bool { + switch lhs { + case let .addressHeader(lhsTheme, lhsText): + if case let .addressHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + case let .address(lhsTheme, lhsPlaceholder, lhsAddress): + if case let .address(rhsTheme, rhsPlaceholder, rhsAddress) = rhs, lhsTheme === rhsTheme, lhsPlaceholder == rhsPlaceholder, lhsAddress == rhsAddress { + return true + } else { + return false + } + case let .addressInfo(lhsTheme, lhsText): + if case let .addressInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + case let .amountHeader(lhsTheme, lhsText, lhsBalance, lhsInsufficient): + if case let .amountHeader(rhsTheme, rhsText, rhsBalance, rhsInsufficient) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsBalance == rhsBalance, lhsInsufficient == rhsInsufficient { + return true + } else { + return false + } + case let .amount(lhsTheme, lhsStrings, lhsPlaceholder, lhsBalance): + if case let .amount(rhsTheme, rhsStrings, rhsPlaceholder, rhsBalance) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsPlaceholder == rhsPlaceholder, lhsBalance == rhsBalance { + return true + } else { + return false + } + case let .commentHeader(lhsTheme, lhsText): + if case let .commentHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + case let .comment(lhsTheme, lhsPlaceholder, lhsText): + if case let .comment(rhsTheme, rhsPlaceholder, rhsText) = rhs, lhsTheme === rhsTheme, lhsPlaceholder == rhsPlaceholder, lhsText == rhsText { + return true + } else { + return false + } + } + } + + static func <(lhs: WalletSendScreenEntry, rhs: WalletSendScreenEntry) -> Bool { + return lhs.stableId < rhs.stableId + } + + func item(_ arguments: WalletSendScreenArguments) -> ListViewItem { + switch self { + 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 + arguments.updateState { state in + var state = state + state.address = address + return state + } + }, shouldUpdateText: { text in + return isValidAddress(text) + }, tag: WalletSendScreenEntryTag.address, action: { + arguments.selectNextInputItem(WalletSendScreenEntryTag.address) + }) + 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) + 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 + var state = state + state.amount = text + return state + } + }, shouldUpdateText: { text in + return isValidAmount(text) + }, processPaste: { pastedText in + if isValidAmount(pastedText) { + return normalizedStringForGramsString(pastedText) + } else { + return text + } + }, updatedFocus: { focus in + if !focus { + let presentationData = arguments.context.sharedContext.currentPresentationData.with { $0 } + arguments.updateState { state in + var state = state + if !state.amount.isEmpty { + state.amount = normalizedStringForGramsString(state.amount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) + } + return state + } + } + }, action: { + arguments.selectNextInputItem(WalletSendScreenEntryTag.amount) + }) + case let .commentHeader(theme, text): + return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) + case let .comment(theme, placeholder, value): + return ItemListMultilineInputItem(theme: theme, text: value, placeholder: placeholder, maxLength: nil, sectionId: self.section, style: .blocks, returnKeyType: .send, textUpdated: { comment in + arguments.updateState { state in + var state = state + state.comment = comment + return state + } + }, tag: WalletSendScreenEntryTag.comment, action: { + arguments.proceed() + }) + } + } +} + +private struct WalletSendScreenState: Equatable { + var address: String + var amount: String + var comment: String +} + +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: \(stringForGramsAmount(balance ?? 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")) + entries.append(.comment(presentationData.theme, "Optional description of the payment", state.comment)) + return entries +} + +protocol WalletSendScreen { + +} + +private final class WalletSendScreenImpl: ItemListController, WalletSendScreen { + +} + +func walletSendScreen(context: AccountContext, tonContext: TonContext, walletInfo: WalletInfo, address: String? = nil, amount: Int64? = nil) -> ViewController { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let initialState = WalletSendScreenState(address: address ?? "", amount: amount.flatMap { stringForGramsAmount($0, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } ?? "", comment: "") + + let statePromise = ValuePromise(initialState, ignoreRepeated: true) + let stateValue = Atomic(value: initialState) + let updateState: ((WalletSendScreenState) -> WalletSendScreenState) -> Void = { f in + statePromise.set(stateValue.modify { f($0) }) + } + + var presentControllerImpl: ((ViewController, Any?) -> Void)? + var presentInGlobalOverlayImpl: ((ViewController, Any?) -> Void)? + var pushImpl: ((ViewController) -> Void)? + var dismissImpl: (() -> Void)? + var selectNextInputItemImpl: ((WalletSendScreenEntryTag) -> Void)? + + let arguments = WalletSendScreenArguments(context: context, updateState: { f in + updateState(f) + }, selectNextInputItem: { tag in + selectNextInputItemImpl?(tag) + }, proceed: { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let state = stateValue.with { $0 } + let amount = amountValue(state.amount) + + updateState { state in + var state = state + state.amount = stringForGramsAmount(amount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) + return state + } + + let title = NSAttributedString(string: "Confirmation", font: Font.semibold(17.0), textColor: presentationData.theme.actionSheet.primaryTextColor) + + let address = state.address[state.address.startIndex.. Void)? + let controller = richTextAlertController(context: context, title: title, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { + dismissAlertImpl?(true) + }), TextAlertAction(type: .defaultAction, title: "Confirm", action: { + dismissAlertImpl?(false) + pushImpl?(WalletPasscodeScreen(context: context, tonContext: tonContext, mode: .authorizeTransfer(walletInfo, state.address, amount, state.comment))) + })], dismissAutomatically: false) + presentInGlobalOverlayImpl?(controller, nil) + + dismissAlertImpl = { [weak controller] animated in + if animated { + controller?.dismissAnimated() + } else { + controller?.dismiss() + } + } + }) + + let balance: Signal = Signal.single(WalletBalance(rawValue: 2500)) + + var focusItemTag: ItemListItemTag? + if address == nil { + focusItemTag = WalletSendScreenEntryTag.address + } else if amount == nil { + focusItemTag = WalletSendScreenEntryTag.amount + } + + let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, balance, statePromise.get()) + |> map { presentationData, balance, state -> (ItemListControllerState, (ItemListNodeState, WalletSendScreenEntry.ItemGenerationArguments)) in + let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { + dismissImpl?() + }) + + let amount = amountValue(state.amount) + var sendEnabled = false + if let balance = balance { + sendEnabled = isValidAddress(state.address, exactLength: true) && amount > 0 && amount <= balance.rawValue + } + 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) + + return (controllerState, (listState, arguments)) + } + + let controller = WalletSendScreenImpl(context: context, state: signal) + controller.navigationPresentation = .modalInLargeLayout + presentControllerImpl = { [weak controller] c, a in + controller?.present(c, in: .window(.root), with: a) + } + presentInGlobalOverlayImpl = { [weak controller] c, a in + controller?.presentInGlobalOverlay(c, with: a) + } + pushImpl = { [weak controller] c in + controller?.push(c) + } + dismissImpl = { [weak controller] in + controller?.view.endEditing(true) + let _ = controller?.dismiss() + } + selectNextInputItemImpl = { [weak controller] currentTag in + guard let controller = controller else { + return + } + var resultItemNode: ItemListItemFocusableNode? + var focusOnNext = false + let _ = controller.frameForItemNode({ itemNode in + if let itemNode = itemNode as? ItemListItemNode, let tag = itemNode.tag, let focusableItemNode = itemNode as? ItemListItemFocusableNode { + if focusOnNext && resultItemNode == nil { + resultItemNode = focusableItemNode + return true + } else if currentTag.isEqual(to: tag) { + focusOnNext = true + } + } + return false + }) + if let resultItemNode = resultItemNode { + resultItemNode.focus() + } + } + return controller +} diff --git a/submodules/WalletUI/Sources/WalletSplashScreen.swift b/submodules/WalletUI/Sources/WalletSplashScreen.swift index 60e960cdba..c64f38b7f0 100644 --- a/submodules/WalletUI/Sources/WalletSplashScreen.swift +++ b/submodules/WalletUI/Sources/WalletSplashScreen.swift @@ -11,12 +11,15 @@ import SolidRoundedButtonNode import AnimationUI import SwiftSignalKit import OverlayStatusController +import ItemListUI public enum WalletSplashMode { case intro case created(WalletInfo, [String]) case success(WalletInfo) case restoreFailed + case sending(WalletInfo, String, Int64, String) + case sent(WalletInfo, Int64) } public final class WalletSplashScreen: ViewController { @@ -45,6 +48,33 @@ 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): + self.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: ASDisplayNode())!, animated: false) + let _ = (Signal.complete() |> delay(3.0, queue: Queue.mainQueue())).start(completed: { [weak self] in + guard let strongSelf = self else { + return + } + if let navigationController = strongSelf.navigationController as? NavigationController { + var controllers = navigationController.viewControllers + controllers = controllers.filter { controller in + if controller is WalletSplashScreen { + return false + } + if controller is WalletSendScreen { + return false + } + if controller is WalletInfoScreen { + return false + } + return true + } + controllers.append(WalletSplashScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, mode: .sent(walletInfo, amount))) + strongSelf.view.endEditing(true) + navigationController.setViewControllers(controllers, animated: true) + } + }) + case .sent: + self.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: ASDisplayNode())!, animated: false) case .created, .success, .restoreFailed: break } @@ -83,7 +113,7 @@ public final class WalletSplashScreen: ViewController { }) case let .created(walletInfo, wordList): strongSelf.push(WalletWordDisplayScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: walletInfo, wordList: wordList)) - case let .success(walletInfo): + case let .success(walletInfo), let .sent(walletInfo, _): let _ = (walletAddress(publicKey: walletInfo.publicKey, tonInstance: strongSelf.tonContext.instance) |> deliverOnMainQueue).start(next: { address in guard let strongSelf = self else { @@ -127,6 +157,8 @@ public final class WalletSplashScreen: ViewController { strongSelf.view.endEditing(true) navigationController.setViewControllers(controllers, animated: true) } + case .sending: + break } }, secondaryAction: { [weak self] in guard let strongSelf = self else { @@ -182,7 +214,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode { let buttonText: String let termsText: String let secondaryActionText: String - + switch mode { case .intro: title = "Gram Wallet" @@ -220,6 +252,24 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode { self.animationNode.visibility = true } secondaryActionText = "Enter 24 words" + case .sending: + title = "Sending Grams" + text = "Please wait a few seconds for your transaction to be processed..." + buttonText = "" + termsText = "" + self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/SendingIcon") + secondaryActionText = "" + case let .sent(_, amount): + title = "Done!" + text = "\(amount) Grams have been sent." + buttonText = "View My Wallet" + termsText = "" + self.iconNode.image = nil + if let path = getAppBundle().path(forResource: "celebrate", ofType: "tgs") { + self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct) + self.animationNode.visibility = true + } + secondaryActionText = "" } self.titleNode = ImmediateTextNode() @@ -248,6 +298,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode { self.secondaryActionButtonNode = HighlightTrackingButtonNode() self.buttonNode = SolidRoundedButtonNode(title: buttonText, theme: self.presentationData.theme, height: 50.0, cornerRadius: 10.0, gloss: true) + self.buttonNode.isHidden = buttonText.isEmpty super.init() diff --git a/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj b/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj index e86b59dcee..1942d162a1 100644 --- a/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj +++ b/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj @@ -91,6 +91,32 @@ explicitFileType archive.ar + 1DD70E291E16CC6C00000000 + + isa + PBXFileReference + name + libActionSheetPeerItem.a + path + libActionSheetPeerItem.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29BF0846EE00000000 + + isa + PBXFileReference + name + libActivityIndicator.a + path + libActivityIndicator.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29F523B9DE00000000 isa @@ -117,6 +143,84 @@ explicitFileType archive.ar + 1DD70E29A54A195300000000 + + isa + PBXFileReference + name + libAvatarNode.a + path + libAvatarNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29BFBD457D00000000 + + isa + PBXFileReference + name + libCamera.a + path + libCamera.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E297AB043C800000000 + + isa + PBXFileReference + name + libChatListSearchRecentPeersNode.a + path + libChatListSearchRecentPeersNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E2997B4D6D800000000 + + isa + PBXFileReference + name + libCheckNode.a + path + libCheckNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E296C9831F100000000 + + isa + PBXFileReference + name + libContextUI.a + path + libContextUI.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E292417E0B200000000 + + isa + PBXFileReference + name + libDeviceAccess.a + path + libDeviceAccess.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E295915423000000000 isa @@ -143,6 +247,19 @@ explicitFileType compiled.mach-o.dylib + 1DD70E2971ED41B100000000 + + isa + PBXFileReference + name + libHorizontalPeerItem.a + path + libHorizontalPeerItem.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29D6F14E1000000000 isa @@ -156,6 +273,45 @@ explicitFileType archive.ar + 1DD70E295A26607D00000000 + + isa + PBXFileReference + name + libItemListUI.a + path + libItemListUI.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29AC43662400000000 + + isa + PBXFileReference + name + libListSectionHeaderNode.a + path + libListSectionHeaderNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29A889192100000000 + + isa + PBXFileReference + name + libLocalAuth.a + path + libLocalAuth.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29CE34063500000000 isa @@ -182,6 +338,19 @@ explicitFileType archive.ar + 1DD70E29C37F741500000000 + + isa + PBXFileReference + name + libMergeLists.a + path + libMergeLists.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29BBAF750C00000000 isa @@ -195,6 +364,45 @@ explicitFileType archive.ar + 1DD70E29D0DBC52A00000000 + + isa + PBXFileReference + name + libPasscodeUI.a + path + libPasscodeUI.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29928D142900000000 + + isa + PBXFileReference + name + libPeerOnlineMarkerNode.a + path + libPeerOnlineMarkerNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29D233F68C00000000 + + isa + PBXFileReference + name + libPeerPresenceStatusManager.a + path + libPeerPresenceStatusManager.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E290F1A3C6400000000 isa @@ -221,6 +429,32 @@ explicitFileType compiled.mach-o.dylib + 1DD70E29CBE117ED00000000 + + isa + PBXFileReference + name + libProgressNavigationButtonNode.a + path + libProgressNavigationButtonNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29AA32BBC600000000 + + isa + PBXFileReference + name + libQrCode.a + path + libQrCode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E293E4DE92B00000000 isa @@ -234,6 +468,71 @@ explicitFileType archive.ar + 1DD70E29AD66967300000000 + + isa + PBXFileReference + name + libReactionSelectionNode.a + path + libReactionSelectionNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E291D58331200000000 + + isa + PBXFileReference + name + libSaveToCameraRoll.a + path + libSaveToCameraRoll.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E2957B5522500000000 + + isa + PBXFileReference + name + libSegmentedControlNode.a + path + libSegmentedControlNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E29097DBE9200000000 + + isa + PBXFileReference + name + libSelectablePeerNode.a + path + libSelectablePeerNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + + 1DD70E2981AE180900000000 + + isa + PBXFileReference + name + libShareController.a + path + libShareController.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29524F478E00000000 isa @@ -273,6 +572,19 @@ explicitFileType compiled.mach-o.dylib + 1DD70E2925BBFEEE00000000 + + isa + PBXFileReference + name + libSwitchNode.a + path + libSwitchNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29F33FDAC300000000 isa @@ -364,6 +676,19 @@ explicitFileType archive.ar + 1DD70E29F40A586F00000000 + + isa + PBXFileReference + name + libTextSelectionNode.a + path + libTextSelectionNode.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + 1DD70E29CD296A8300000000 isa @@ -403,6 +728,19 @@ explicitFileType archive.ar + 1DD70E29597BAFBB00000000 + + isa + PBXFileReference + name + libUrlEscaping.a + path + libUrlEscaping.a + sourceTree + BUILT_PRODUCTS_DIR + explicitFileType + archive.ar + B401C97968022A5500000000 isa @@ -414,20 +752,44 @@ children 1DD70E299D2580DA00000000 + 1DD70E291E16CC6C00000000 + 1DD70E29BF0846EE00000000 1DD70E29F523B9DE00000000 1DD70E292420028600000000 + 1DD70E29A54A195300000000 + 1DD70E29BFBD457D00000000 + 1DD70E297AB043C800000000 + 1DD70E2997B4D6D800000000 + 1DD70E296C9831F100000000 + 1DD70E292417E0B200000000 1DD70E295915423000000000 1DD70E29FF334B1F00000000 + 1DD70E2971ED41B100000000 1DD70E29D6F14E1000000000 + 1DD70E295A26607D00000000 + 1DD70E29AC43662400000000 + 1DD70E29A889192100000000 1DD70E29CE34063500000000 1DD70E2936DE2CF900000000 + 1DD70E29C37F741500000000 1DD70E29BBAF750C00000000 + 1DD70E29D0DBC52A00000000 + 1DD70E29928D142900000000 + 1DD70E29D233F68C00000000 1DD70E290F1A3C6400000000 1DD70E29DB6520C800000000 + 1DD70E29CBE117ED00000000 + 1DD70E29AA32BBC600000000 1DD70E293E4DE92B00000000 + 1DD70E29AD66967300000000 + 1DD70E291D58331200000000 + 1DD70E2957B5522500000000 + 1DD70E29097DBE9200000000 + 1DD70E2981AE180900000000 1DD70E29524F478E00000000 1DD70E293594DCC000000000 1DD70E29D65BA68200000000 + 1DD70E2925BBFEEE00000000 1DD70E29F33FDAC300000000 1DD70E29119CDA0700000000 1DD70E2984A59C1D00000000 @@ -435,9 +797,11 @@ 1DD70E292395015100000000 1DD70E29BA06E3A600000000 1DD70E29F0C15F9C00000000 + 1DD70E29F40A586F00000000 1DD70E29CD296A8300000000 1DD70E29AE67341000000000 1DD70E2951398CF200000000 + 1DD70E29597BAFBB00000000 1DD70E29D097476500000000 @@ -490,6 +854,61 @@ sourceTree SOURCE_ROOT + 1DD70E29E336006800000000 + + isa + PBXFileReference + name + WalletPasscodeScreen.swift + path + Sources/WalletPasscodeScreen.swift + sourceTree + SOURCE_ROOT + + 1DD70E296D49CFFF00000000 + + isa + PBXFileReference + name + WalletQrCodeItem.swift + path + Sources/WalletQrCodeItem.swift + sourceTree + SOURCE_ROOT + + 1DD70E29DE28A96800000000 + + isa + PBXFileReference + name + WalletQrScanScreen.swift + path + Sources/WalletQrScanScreen.swift + sourceTree + SOURCE_ROOT + + 1DD70E2979DDEBBB00000000 + + isa + PBXFileReference + name + WalletReceiveScreen.swift + path + Sources/WalletReceiveScreen.swift + sourceTree + SOURCE_ROOT + + 1DD70E2948FA33F200000000 + + isa + PBXFileReference + name + WalletSendScreen.swift + path + Sources/WalletSendScreen.swift + sourceTree + SOURCE_ROOT + 1DD70E2964068E1100000000 isa @@ -534,6 +953,11 @@ children 1DD70E29D2B1401800000000 + 1DD70E29E336006800000000 + 1DD70E296D49CFFF00000000 + 1DD70E29DE28A96800000000 + 1DD70E2979DDEBBB00000000 + 1DD70E2948FA33F200000000 1DD70E2964068E1100000000 1DD70E2936794EB600000000 1DD70E290678D03000000000 @@ -576,6 +1000,41 @@ fileRef 1DD70E29D2B1401800000000 + E7A30F04E336006800000000 + + isa + PBXBuildFile + fileRef + 1DD70E29E336006800000000 + + E7A30F046D49CFFF00000000 + + isa + PBXBuildFile + fileRef + 1DD70E296D49CFFF00000000 + + E7A30F04DE28A96800000000 + + isa + PBXBuildFile + fileRef + 1DD70E29DE28A96800000000 + + E7A30F0479DDEBBB00000000 + + isa + PBXBuildFile + fileRef + 1DD70E2979DDEBBB00000000 + + E7A30F0448FA33F200000000 + + isa + PBXBuildFile + fileRef + 1DD70E2948FA33F200000000 + E7A30F0464068E1100000000 isa @@ -604,6 +1063,11 @@ files E7A30F04D2B1401800000000 + E7A30F04E336006800000000 + E7A30F046D49CFFF00000000 + E7A30F04DE28A96800000000 + E7A30F0479DDEBBB00000000 + E7A30F0448FA33F200000000 E7A30F0464068E1100000000 E7A30F0436794EB600000000 E7A30F040678D03000000000 @@ -728,19 +1192,12 @@ fileRef 1DD70E29F523B9DE00000000 - E7A30F04BBAF750C00000000 + E7A30F04BFBD457D00000000 isa PBXBuildFile fileRef - 1DD70E29BBAF750C00000000 - - E7A30F04524F478E00000000 - - isa - PBXBuildFile - fileRef - 1DD70E29524F478E00000000 + 1DD70E29BFBD457D00000000 E7A30F04D6F14E1000000000 @@ -770,6 +1227,160 @@ fileRef 1DD70E292420028600000000 + E7A30F0497B4D6D800000000 + + isa + PBXBuildFile + fileRef + 1DD70E2997B4D6D800000000 + + E7A30F04C37F741500000000 + + isa + PBXBuildFile + fileRef + 1DD70E29C37F741500000000 + + E7A30F04BF0846EE00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29BF0846EE00000000 + + E7A30F04CBE117ED00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29CBE117ED00000000 + + E7A30F0457B5522500000000 + + isa + PBXBuildFile + fileRef + 1DD70E2957B5522500000000 + + E7A30F0425BBFEEE00000000 + + isa + PBXBuildFile + fileRef + 1DD70E2925BBFEEE00000000 + + E7A30F045A26607D00000000 + + isa + PBXBuildFile + fileRef + 1DD70E295A26607D00000000 + + E7A30F04BBAF750C00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29BBAF750C00000000 + + E7A30F04A889192100000000 + + isa + PBXBuildFile + fileRef + 1DD70E29A889192100000000 + + E7A30F04D0DBC52A00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29D0DBC52A00000000 + + E7A30F04AA32BBC600000000 + + isa + PBXBuildFile + fileRef + 1DD70E29AA32BBC600000000 + + E7A30F04A54A195300000000 + + isa + PBXBuildFile + fileRef + 1DD70E29A54A195300000000 + + E7A30F041E16CC6C00000000 + + isa + PBXBuildFile + fileRef + 1DD70E291E16CC6C00000000 + + E7A30F04AD66967300000000 + + isa + PBXBuildFile + fileRef + 1DD70E29AD66967300000000 + + E7A30F04F40A586F00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29F40A586F00000000 + + E7A30F046C9831F100000000 + + isa + PBXBuildFile + fileRef + 1DD70E296C9831F100000000 + + E7A30F04928D142900000000 + + isa + PBXBuildFile + fileRef + 1DD70E29928D142900000000 + + E7A30F04097DBE9200000000 + + isa + PBXBuildFile + fileRef + 1DD70E29097DBE9200000000 + + E7A30F0471ED41B100000000 + + isa + PBXBuildFile + fileRef + 1DD70E2971ED41B100000000 + + E7A30F04AC43662400000000 + + isa + PBXBuildFile + fileRef + 1DD70E29AC43662400000000 + + E7A30F047AB043C800000000 + + isa + PBXBuildFile + fileRef + 1DD70E297AB043C800000000 + + E7A30F04D233F68C00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29D233F68C00000000 + E7A30F043E4DE92B00000000 isa @@ -777,6 +1388,41 @@ fileRef 1DD70E293E4DE92B00000000 + E7A30F042417E0B200000000 + + isa + PBXBuildFile + fileRef + 1DD70E292417E0B200000000 + + E7A30F041D58331200000000 + + isa + PBXBuildFile + fileRef + 1DD70E291D58331200000000 + + E7A30F04597BAFBB00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29597BAFBB00000000 + + E7A30F0481AE180900000000 + + isa + PBXBuildFile + fileRef + 1DD70E2981AE180900000000 + + E7A30F04524F478E00000000 + + isa + PBXBuildFile + fileRef + 1DD70E29524F478E00000000 + E7A30F04AE67341000000000 isa @@ -807,13 +1453,39 @@ E7A30F04BA06E3A600000000 E7A30F049D2580DA00000000 E7A30F04F523B9DE00000000 - E7A30F04BBAF750C00000000 - E7A30F04524F478E00000000 + E7A30F04BFBD457D00000000 E7A30F04D6F14E1000000000 E7A30F04CD296A8300000000 E7A30F043594DCC000000000 E7A30F042420028600000000 + E7A30F0497B4D6D800000000 + E7A30F04C37F741500000000 + E7A30F04BF0846EE00000000 + E7A30F04CBE117ED00000000 + E7A30F0457B5522500000000 + E7A30F0425BBFEEE00000000 + E7A30F045A26607D00000000 + E7A30F04BBAF750C00000000 + E7A30F04A889192100000000 + E7A30F04D0DBC52A00000000 + E7A30F04AA32BBC600000000 + E7A30F04A54A195300000000 + E7A30F041E16CC6C00000000 + E7A30F04AD66967300000000 + E7A30F04F40A586F00000000 + E7A30F046C9831F100000000 + E7A30F04928D142900000000 + E7A30F04097DBE9200000000 + E7A30F0471ED41B100000000 + E7A30F04AC43662400000000 + E7A30F047AB043C800000000 + E7A30F04D233F68C00000000 E7A30F043E4DE92B00000000 + E7A30F042417E0B200000000 + E7A30F041D58331200000000 + E7A30F04597BAFBB00000000 + E7A30F0481AE180900000000 + E7A30F04524F478E00000000 E7A30F04AE67341000000000 name